Using GPy with IPv6



  • Has anyone prior experience with using GPy over IPv6 NB-IoT networks? Our local MNO supports only IPV6 and I am able to attach to the network using the following code snippet:

    from network import LTE
    lte = LTE()
    lte.init()
    lte.send_at_cmd('AT+CFUN=0')
    lte.send_at_cmd('AT+CGDCONT=1,"IPV6","iot"')
    lte.send_at_cmd('AT+CFUN?')
    lte.send_at_cmd('AT+CFUN=1')
    lte.send_at_cmd('AT+CFUN?')
    lte.send_at_cmd('AT+CREG?')
    

    However I am not sure how I can establish UDP socket communication. I checked the Sequans modem manual for IPv6 data transmission support. When creating a new socket through the AT+SQNSD command the remote IP address should be configured as follows:

    IPaddr
    String type. Address of the remote host.
    Any valid IP address in the format “xxx.xxx.xxx.xxx” or any host
    name solved with a DNS query.
    

    So this means that only IPv4 addresses are supported?

    Is also anyone aware of native IPv6 support for the WLAN/LTE classes of pycom? I guess not?

    Thanks!



  • Just an update of the latest changes. The API of the microATsocket has changed to be closer to the typical usocket API. Also a custom version of getaddrinfo info has been implemented, so the code now looks somehting like:

    import microATsocket as socket
    from network import LTE
    import binascii
    
    lte = LTE()
    
    # attach to network
    # ...
    
    #message as bytes
    data = bytearray('{data:"testmessage"}')
    
    # create socket instance providing the instance of the LTE modem
    sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    sock.setModemInstance(lte)
    
    # getaddrinfo needs to be called on the instance of socket
    resolvedIPs = sock.getaddrinfo("google.com", 5683)
    
    # send data to specific IP (dummy IP and port used as example)
    sock.sendto(data, resolvedIPs[0][-1])
    
    # receive data from the previously used IP.
    # socket is still open from the 'sendto' operation
    (resp, address) = sock.recvfrom(1024)
    print("Response: from ip:" + address[0] + ", port: " + str(address[1]) + ", data: " + str(binascii.hexlify(bytearray(resp))))
    


  • @kjm you are correct, a URL can resolve to multiple IPs and yes, a getaddrinfo lookup is needed.

    Since getaddrinfo lookup is a DNS request, I have created an example code on how to do it over the UDP socket.
    The example uses https://github.com/insighio/DNS-Client to form and decode the DNS request/response along with the custom MicroATSocket socket.

    socket = MicroATSocket(lte)
    
    url='google.com'
    dns_server="2001:4860:4860::8888"
    ipv6_only = True
    
    resolvedIPs = dns_query.dns_resolve(socket, url, dns_server, ipv6_only)
    
    print("Resolved IP list: " + str(resolvedIPs))
    
    data = bytearray('{data:"testmessage"}')
    socket.sendto(data, (resolvedIPs[0], 8888))
    
    (resp, address) = socket.recvfrom()
    
    print("Response: from ip:" + address[0] + ", port: " + str(address[1]) + ", data: " + str(binascii.hexlify(bytearray(resp))))
    
    socket.close()
    

    Since Google's DNS server IP is fixed, it can be used directly. If DNS resolve is successful, a list of IPs will be returned. Pick any of the returned IPs and you are ready to transfer your data.

    Full source code can be found: here



  • @nftylitak thnx heaps for doing that. I seem to be confused re IPV6. I thought is was a scheme that would allow each iot mote to have its own unique address & free us from the tyranny of dns lookups. But when I check the IPv6 address of a random website, say detectportal.firefox.com, I find it has more than one IPv6 address. Which makes me think IPv6 addresses are going to be just as fluid as IPV4, which means some sort of getaddrinfo style lookup will still be required?

    
    nslookup detectportal.firefox.com
    Non-authoritative answer:
    Name:    a1089.dscd.akamai.net
    Addresses:  2407:8800:bf00:145::cb57:7a19
              2407:8800:bf00:145::cb57:7a2b
              23.212.98.59
              202.7.177.35
    Aliases:  detectportal.firefox.com
              detectportal.prod.mozaws.net
              detectportal.firefox.com-v2.edgesuite.net
    


  • @kjm I have added the socket implementation to a separate repo to be easier to use.

    You can find the report in GitHub: microATsocket for more examples and special features.

    A quick example would be the following:

    from microATsocket import MicroATSocket
    from network import LTE
    import binascii
    
    lte = LTE()
    
    # attach to network
    # ...
    
    #message as bytes
    data = bytearray('{data:"testmessage"}')
    
    # create socket instance providing the instance of the LTE modem
    socket = MicroATSocket(lte)
    
    # send data to specific IP (dummy IP and port used as example)
    socket.sendto(data, ("2001:4860:4860::8888", 8888))
    
    # receive data from the previously used IP.
    # socket is still open from the 'sendto' operation
    (resp, address) = socket.recvfrom()
    print("Response: from ip:" + address[0] + ", port: " + str(address[1]) + ", data: " + str(binascii.hexlify(bytearray(resp))))
    
    # close socket
    socket.close()
    

    The feedback is always welcomed.



  • @kjm today I will create some examples and get back to you within the day.



  • @nftylitak Are you able to post an example of how to use that wrapper socket?



  • Greetings,

    @agotsis your example indeed works for IPv6, so based on your code I have made a wrapper "socket" based on AT commands for GPy. The tricky part was that through AT+SQNSSEND, I could not send bytes, so it needed special care.

    The socket can be found through this link in the hope that it will save time to others: https://github.com/insighio/microCoAPy/blob/master/examples/pycom/nbiot/pycom_at_socket.py



  • I'm salivating in anticipation! It would be so nice to ditch that useless, untimeoutable, getaddrinfo dns lookup with a move to IPV6.



  • A small update: It seems that the AT+SQNSD is also accepting IPv6 target addresses. I managed to send a UDP message from GPy to an IPv6 address, using the following snippet:

    lte.send_at_cmd('AT+SQNSD=1,1,<targetPort>,"XXXX:XXX:XXXX:XX:XXXX:XXX:XXX:XXXX",0,0,1')
    lte.send_at_cmd('AT+SQNSSEND=1')
    lte.send_at_cmd('hello\x1A')
    lte.send_at_cmd('AT+SQNSH=1')
    

    However usocket is not able to handle IPv6 (see for example in [1] and [2]), so native support is yet available.


Log in to reply
 

Pycom on Twitter