Send a file from one Lopy to another Lopy



  • Hi, nice to see you again.

    I'm trying to send a .txt file from one lopy to another via WIFI and I do not know how to do it.

    I have been testing with 'socket.socket' but it gives me an error and I am not so sure that it is the correct method. It is also that the Lopy where the file will be received can not be left listening while waiting because it is executing another code.

    issuer code:

    from network import WLAN
    
    import socket
    import sys
    
    
    def buscarWifi(ssid):
        #Ponemos el wifi en modo estacion:
        wlan = WLAN(mode=WLAN.STA)
    
        #Buscamos wifi:
        redes = wlan.scan()
        print('Redes disponibles: ',len(redes))
        #for c in range(len(redes)):
            #print(c,'->',redes[c])
    
            #if ssid in redes[c]: //Otra opción de encontrar el ssid
            #print("Encontrado en:",redes[c])
            #return True
        for red in redes:
            if red.ssid == ssid:
                wlan.connect(red.ssid, auth=(red.sec,'witeklab@2018'), timeout=5000)
                while not wlan.isconnected():
                    machine.idle() # save power while waiting
                print('WLAN connection succeeded!')
                return True,wlan
                break
            else:
                return False,wlan
    ok,w = buscarWifi('Gateway1')
    if ok:
        print('ok')
        ip = w.ifconfig()
        print('ip destino = ',ip[0])
        print(w.ifconfig())
    
        #Creamos el fichero:
        #f = open ('prueba.txt', 'w')#MOdo 'a' Para añadir no sobre escribir
        #texto = ip[0]+"\nPrueba1"
        #f.write(texto)
        #f.close()
    
        import socket
    
        HOST = 'localhost'
        PORT = 9876
        ADDR = (ip[0],PORT)
        BUFSIZE = 4096
        videofile = "prueba.txt"
    
        bytes = open(videofile).read()
    
        print (len(bytes))
    
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.connect(ADDR) ## <-- Failure
        client.send(bytes)
        client.close()
        #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #s.connect((ip[0],9999))
        #l = f.read()
        #s.send(l)
        #s.close()
        #Intentamos el envío del fichero:
        #s = socket.socket()
    
    else:
        print('no')
    
    #Pag de interes:
    # + info : https://docs.pycom.io/chapter/firmwareapi/micropython/usocket.html
    # http://help.ubidots.com/connect-your-devices/connect-your-pycom-devices-over-wi-fi
    

    The code what it does is look for a wifi network in particular that is what generates the Lopy server and connects correctly and I want to send a .txt file generated in the Lopy and send via Wi-Fi to the connected Lopy.

    Is there a better way to do it?

    By the way I have already looked at the following documents documents:
    https://docs.pycom.io/chapter/tutorials/all/wlan.html
    https://docs.pycom.io/chapter/firmwareapi/pycom/network/wlan.html
    https://docs.pycom.io/chapter/firmwareapi/pycom/network/server.html

    And I have not managed to figure out how to make it sorry.



  • Good again.

    I return to post, because I would need the LoPy that receives the txt file is the one that starts the wifi as

    wlan = WLAN (mode = WLAN.AP,
    ssid = 'Gateway1',
    auth = (WLAN.WPA2, 'password'),
    antenna = WLAN.INT_ANT)

    I have tried to modify the code as I have the partner that works so that it is but I get error everywhere.

    Once trying once more, if I do not restart the board and try to execute the code, I always get the error:

    Traceback (most recent call last):
    File "<stdin>", line 17, in <module>
    OSError: [Errno 12] ENOMEM

    Because it is ? If someone can give me a hand code please!

    Capture Errors:
    0_1528129558524_f1.PNG

    0_1528129566385_f2.PNG

    used code:
    Server And Wifi AP:

    from network import WLAN
    import socket
    import select
    import time
    
    #Setup WiFi AP
    wlan = WLAN(mode=WLAN.AP,
                ssid='Gateway1',
                auth=(WLAN.WPA2,'password'),
                antenna=WLAN.INT_ANT)
    
    port = 12345
    s = socket.socket()
    s.bind(socket.getaddrinfo("0.0.0.0", port)[0][4])
    s.listen(1)
    
    print("Running server")
    while True:
        cl, remote_addr = s.accept()
        cl.setblocking(True)
        print("Client connection from:", remote_addr)
    
        file = "/flash/registro2.txt"
        with open(file, 'wb') as f:
            try:
                data = s.recv(1024)
                print(data)
                f.write(data)
            except TimeoutError:
                break
    

    Client and Lopy and in charge to send file:

    from network import WLAN
    import socket
    import select
    import machine
    import time
    
    # Abrimos wifi
    wlan = WLAN(mode=WLAN.STA)
    nets = wlan.scan()
    for net in nets:
        if net.ssid == 'Gateway1':
            print('Network found!')
            wlan.connect(net.ssid, auth=(net.sec, 'password'), timeout=5000)
            while not wlan.isconnected():
                machine.idle() # save power while waiting
            print('WLAN connection succeeded!')
            break
    else:
        raise Exception("WiFi network not found")
    
    # sleep just to make sure the wifi is connected
    time.sleep(1)
    
    ip, subnet, gateway, dns = wlan.ifconfig()
    
    # Connect to server
    # Bind to the port
    port = 12345
    s = socket.socket()
    s.connect((gateway, port))
    s.setblocking(True)
    s.settimeout(2)
    
    while True:
        readable, writable, errored = select.select([s], [], [])
        
        for s in readable:
            cl, remote_addr = s.accept()
            cl.setblocking(True)
            print("Client connection from:", remote_addr)
    
            file = "/flash/registro.txt"
            print("Sending: ", file)
    
            with open(file, 'rb') as f:
                data = f.read(1024)
                while(data):
                    print("sending", data)
                    cl.sendall(data)
                    data = f.read(1024)
            print("Done Sending")
            cl.close()
    


  • @zceld

    The docs are the best place to look at what these functions do: https://docs.pycom.io/chapter/firmwareapi/micropython/usocket.html

    Here is a basic run down, s.setblocking(True) will make any sending or recieving functions block, this means the lopy will get stuck at that line of code until it receives the amount of bytes asked for (or it timesout, if a timeout is set) or until all data is send. When it is False calls to any sending or receiving functions will return immediately. In the case of a send, it will place the data in a queue and it will be send in the background in a different thread. In the case of a recieve, if there is less data than expected available it simply returns that and doesnt wait for the full expected amount.

    You can change the WLAN modes but this will become messy because you will need to make sure the threads have proper locks and that they are aware of what state the WLAN is in before trying to use it. You might be better off just using the WLAN.STA_AP mode which is both modes at once.



  • @seb said in Send a file from one Lopy to another Lopy:

    You can cancel it by using setblocking(False)

    you can find out what s.listen(1) means here: https://docs.pycom.io/chapter/firmwareapi/micropython/usocket.html#socketlistenbacklog its basically how many unaccepted connections you can queue up

    Yeah that should be fine, the underlying drivers for wifi/lora will handle multiplexing access to them

    Would you know to tell me that I failed in all the previous examples??

    On the other hand I already ask you in your day for the same thing of s.setblocking (True / False) you know where I could find an exhaustive explanation about that?

    Finally on the _treads, to confirm. It would be possible to put in a Lopy a _tread that established the wifi in WLAN.AP mode and in turn in the same Lopy through another _tread the wifi was put in WLAN.STA mode at the same time?



  • @zceld

    1. You can cancel it by using setblocking(False)

    2. you can find out what s.listen(1) means here: https://docs.pycom.io/chapter/firmwareapi/micropython/usocket.html#socketlistenbacklog its basically how many unaccepted connections you can queue up

    3. Yeah that should be fine, the underlying drivers for wifi/lora will handle multiplexing access to them



  • @zceld

    I still do not know what that error means but it must be related to the socket and the listener method.

    But I have reset the plates and it has worked :) I still do not believe it ...
    0_1524149875255_Captura de pantalla 2018-04-19 16.48.22.png
    hehe thank you very much at least I know that something works now I need many things to know but already with the base is much.

    By the way when you put the socket = cl.setblocking (True)
    Is there a way to cancel or interrupt this?
    another question. this 's.listen (1)' which means you will be listening once?

    I have more questions ... If I use for example Wi-Fi or Lora with _threads, can I send and listen to the same chip at the same time?



  • @zceld

    How big of a file are you trying to copy?



  • @seb said in Send a file from one Lopy to another Lopy:

    Did you create a test.txt file on your device too? the server reads the file test.txt and client writes to a file called test.txt

    I had not realized that it was the other way around, that is, as my idea was to send the client to the server, I had not noticed sorry. Anyway now I have changed it to a file that is in the Lopy but now it tells me this error:

    0_1524148256070_d4c119a9-7b2b-4f3f-adb3-340e720e3c95-image.png Captura de pantalla 2018-04-19 16.30.23



  • @zceld

    Did you create a test.txt file on your device too? the server reads the file test.txt and client writes to a file called test.txt



  • @seb said in Send a file from one Lopy to another Lopy:

    from network import WLAN
    import socket
    import select
    import time
    
    #Setup WiFi AP
    wlan = WLAN(mode=WLAN.AP,
                ssid='Gateway1',
                auth=(WLAN.WPA2,'password'),
                antenna=WLAN.INT_ANT)
    
    
    # Bind to the port
    port = 12345
    s = socket.socket()
    s.bind(socket.getaddrinfo("0.0.0.0", port)[0][4])
    s.listen(1)
    
    print("Running server")
    while True:
        readable, writable, errored = select.select([s], [], [])
    
        for s in readable:
            cl, remote_addr = s.accept()
            cl.setblocking(True)
            print("Client connection from:", remote_addr)
    
            file = "/flash/test.txt"
            print("Sending: ", file)
    
            with open(file, 'rb') as f:
                data = f.read(1024)
                while(data):
                    print("sending", data)
                    cl.sendall(data)
                    data = f.read(1024)
            print("Done Sending")
            cl.close()
    

    hi, forgive me for the delay, yesterday I could not look at it, today was the first thing I've done and has given a failure on the server.
    0_1524143974181_Captura de pantalla 2018-04-19 15.12.08.png



  • Hi,

    Please excuse the delay. I have gone ahead and written some code for you to demonstrate sending a file between devices. Be aware that this does no error checking/retries etc. but the basic functionality is there.

    Client

    from network import WLAN
    import socket
    import select
    import machine
    import time
    
    # Connect to server AP
    wlan = WLAN(mode=WLAN.STA)
    nets = wlan.scan()
    for net in nets:
        if net.ssid == 'Gateway1':
            print('Network found!')
            wlan.connect(net.ssid, auth=(net.sec, 'password'), timeout=5000)
            while not wlan.isconnected():
                machine.idle() # save power while waiting
            print('WLAN connection succeeded!')
            break
    else:
        raise Exception("WiFi network not found")
    
    # sleep just to make sure the wifi is connected
    time.sleep(1)
    
    ip, subnet, gateway, dns = wlan.ifconfig()
    
    # Connect to server
    port = 12345
    s = socket.socket()
    print("Connecting to: ", gateway, port)
    s.connect((gateway, port))
    s.setblocking(True)
    s.settimeout(2)
    
    file = "/flash/test.txt"
    with open(file, 'wb') as f:
        while True:
            try:
                data = s.recv(1024)
                print(data)
                f.write(data)
            except TimeoutError:
                break
    

    Server

    from network import WLAN
    import socket
    import select
    import time
    
    #Setup WiFi AP
    wlan = WLAN(mode=WLAN.AP,
                ssid='Gateway1',
                auth=(WLAN.WPA2,'password'),
                antenna=WLAN.INT_ANT)
    
    
    # Bind to the port
    port = 12345
    s = socket.socket()
    s.bind(socket.getaddrinfo("0.0.0.0", port)[0][4])
    s.listen(1)
    
    print("Running server")
    while True:
        readable, writable, errored = select.select([s], [], [])
    
        for s in readable:
            cl, remote_addr = s.accept()
            cl.setblocking(True)
            print("Client connection from:", remote_addr)
    
            file = "/flash/test.txt"
            print("Sending: ", file)
    
            with open(file, 'rb') as f:
                data = f.read(1024)
                while(data):
                    print("sending", data)
                    cl.sendall(data)
                    data = f.read(1024)
            print("Done Sending")
            cl.close()
    


  • @seb
    This is the result that the server connected to Wi-Fi has given me, and to which it has begun to receive data from the client, it has failed:
    0_1523973201644_24ef8daf-4e91-4368-bb5f-bd71c763b827-imagen.png

    code used in the superior test:

    def buscarWifi(ssid):
        #Ponemos el wifi en modo estacion:
        wlan = WLAN(mode=WLAN.STA)
    
        #Buscamos wifi:
        redes = wlan.scan()
        print('Redes disponibles: ',len(redes))
        for red in redes:
            if red.ssid == ssid:
                wlan.connect(red.ssid, auth=(red.sec,'hszh6539'), timeout=5000)
                while not wlan.isconnected():
                    machine.idle() # save power while waiting
                print('WLAN connection succeeded!')
                return True,wlan
                break
            else:
                return False,wlan
    
    iniciarFTP()
    ok,w = buscarWifi('S9+ Wifi')
    if ok:
        print('ok')
        ip = w.ifconfig()
        host = ip[0]
        print('my ip = ',ip[0])
        port = 60000                     # Reserve a port for your service.
        s = socket.socket()             # Create a socket object
        gc.collect()
        s.bind((host, port))            # Bind to the port
        s.listen(5)                     # Now wait for client connection.
    
        print ('Server listening....')
    
        while True:
            conn, addr = s.accept()     # Establish connection with client.
            print ('Got connection from', addr)
            data = conn.recv(256)
            print('Server received', repr(data))
    
            with open('received_file.txt', 'wb') as f:
                print ('file opened')
                while True:
                    print('receiving data...')
                    s.setblocking(True)
                    print('Memoria->',str(gc.mem_free()))
                    data = s.recv(256)
                    print('M despues->',str(gc.mem_free()))
                    print('data=%s', (data))
                    if not data:
                        break
                    # write data to a file
                    f.write(data)
    
                f.close()
                print('Successfully get the file')
                s.close()
                print('connection closed')
    
                conn.send('Thank you for connecting')
            conn.close()
            gc.collect()
    

    Result of the Lopy that sends the file:
    0_1523973361916_fc3edc10-b727-4cfa-ae6c-5435e555f637-imagen.png

    code used in the superior test:

    from network import WLAN
    
    import socket
    import sys
    
    
    def buscarWifi(ssid):
        #Ponemos el wifi en modo estacion:
        wlan = WLAN(mode=WLAN.STA)
    
        #Buscamos wifi:
        redes = wlan.scan()
        print('Redes disponibles: ',len(redes))
        #for c in range(len(redes)):
            #print(c,'->',redes[c])
    
            #if ssid in redes[c]: //Otra opción de encontrar el ssid
            #print("Encontrado en:",redes[c])
            #return True
        for red in redes:
            if red.ssid == ssid:
                wlan.connect(red.ssid, auth=(red.sec,'hszh6539'), timeout=5000)
                while not wlan.isconnected():
                    machine.idle() # save power while waiting
                print('WLAN connection succeeded!')
                return True,wlan
                break
            else:
                return False,wlan
    
    ok,w = buscarWifi('S9+ Wifi')
    if ok:
        print('ok')
        s = socket.socket()
        print('ip destino = 192.168.43.26')
        print('Configuracion de red:',w.ifconfig())
        print('Estoy conectado=',w.isconnected())
        #host = ip[]
        #print(type(HOST),'--->>',HOST)
        port = 60000
        s.connect(('192.168.43.26', port))
        s.send("Hello server!")
        filename='prueba.txt'
        f = open(filename,'rb')
        l = f.read(256)
        while (l):
           conn.send(l)
           print('Sent ',repr(l))
           l = f.read(256)
        f.close()
        s.close()
    
    


  • @seb said in Send a file from one Lopy to another Lopy:

    @zceld
    The return of ifconfig is in the following format.
    (ip, subnet, gateway, dns)
    I see now from your code that you are using one of the modules as a wifi AP, can you first try connecting them to an existing network to see if this works, then we can narrow down if the issue lies with the networking or your logic

    Now I will try to reduce where the problem may be, but the need to connect and send data is to be used without a router, if you do not communicate with each other.

    Regardless of the Wi-Fi, do you think that you could send two messages simultaneously with LoRa using thread?



  • @zceld
    The return of ifconfig is in the following format.
    (ip, subnet, gateway, dns)

    I see now from your code that you are using one of the modules as a wifi AP, can you first try connecting them to an existing network to see if this works, then we can narrow down if the issue lies with the networking or your logic



  • @seb said in Send a file from one Lopy to another Lopy:

    host = ip[2]

    Hi, thanks again for checking it out!

    In theory the server returns these values of WLAN.ifconfig ():
    0_1523970875462_4.PNG

    Of the data that ifconfig returns are:?

    ('ip assigned', 'subnet mask', 'ip server'?, 'and this last one I do not know' /0.0.0.0).

    Capture of the client, this time trying to connect to the ip '192.168.4.1' that is supposed to be the server's Wi-Fi therefore the Lopy server does not?
    0_1523971525214_929fb555-6284-459b-a7ff-a0acf8bd5dbf-imagen.png



  • @zceld said in Send a file from one Lopy to another Lopy:

    from network import WLAN
    import socket
    import sys

    def buscarWifi(ssid):
    wlan = WLAN(mode=WLAN.STA)
    redes = wlan.scan()
    print('Redes disponibles: ',len(redes))
    for red in redes:
    if red.ssid == ssid:
    wlan.connect(red.ssid, auth=(red.sec,'witeklab@2018'), timeout=5000)
    while not wlan.isconnected():
    machine.idle() # save power while waiting
    print('WLAN connection succeeded!')
    return True,wlan
    break
    else:
    return False,wlan

    ok,w = buscarWifi('Gateway1')
    if ok:
    print('ok')
    s = socket.socket()
    ip = w.ifconfig()
    print('ip destino = ',ip[0])
    print('Configuracion de red:',w.ifconfig())
    print('Estoy conectado=',w.isconnected())
    ip = w.ifconfig()
    host = ip[2]
    #print(type(HOST),'--->>',HOST)
    port = 8206
    s.connect((host, port))
    s.send("Hello server!")
    filename='prueba.txt'
    f = open(filename,'rb')
    l = f.read(1024)
    while (l):
    conn.send(l)
    print('Sent ',repr(l))
    l = f.read(1024)
    f.close()
    s.close()

    Looking at your second block of code it looks like you are trying to connect the device to itself? You are getting host from ifconfig() but then trying to connect to that address



  • @seb said in Send a file from one Lopy to another Lopy:

    can you post your complete code and I will have a look

    Thank you very much for looking at it. This is the full code of the Lopy Server:

    import socket                   # Import socket module
    
    def iniciarFTP():
        try:
            import network
            from network import WLAN
            wlan = network.WLAN(mode=network.WLAN.STA)
            wlan.init(mode=WLAN.AP, ssid='Gateway1', auth=(WLAN.WPA2,'witeklab@2018'), channel=7, antenna=WLAN.INT_ANT)
            from network import Server
            server = Server(login=('micro', 'python'), timeout=600)
            server.timeout(300)
            server.timeout()
            print(server.isrunning())
            return True
        except:
            return False
    
    #Iniciamos servidor:
    iniciarFTP()
    host = ''
    port = 8206                     # Reserve a port for your service.
    s = socket.socket()             # Create a socket object
    
    s.bind((host, port))            # Bind to the port
    s.listen(5)                     # Now wait for client connection.
    
    print ('Server listening....')
    
    while True:
        conn, addr = s.accept()     # Establish connection with client.
        print ('Got connection from', addr)
        data = conn.recv(1024)
        print('Server received', repr(data))
    
        with open('received_file.txt', 'wb') as f:
            print ('file opened')
            while True:
                print('receiving data...')
                data = s.recv(1024)
                print('data=%s', (data))
                if not data:
                    break
                # write data to a file
                f.write(data)
    
            f.close()
            print('Successfully get the file')
            s.close()
            print('connection closed')
    
            conn.send('Thank you for connecting')
        conn.close()
    

    No more, now I give you a screenshot of what you do when you run it, but I already told you that it stops when you print ('Server listening ....')
    As the programming indicates waiting for some connection. But the one that receives a connection from the client fails with the error 'OSError: 128':

    0_1523540907912_2.PNG

    Now we go to the client Lopy code:

     from network import WLAN
    import socket
    import sys
    
    def buscarWifi(ssid):
        wlan = WLAN(mode=WLAN.STA)
        redes = wlan.scan()
        print('Redes disponibles: ',len(redes))
        for red in redes:
            if red.ssid == ssid:
                wlan.connect(red.ssid, auth=(red.sec,'witeklab@2018'), timeout=5000)
                while not wlan.isconnected():
                    machine.idle() # save power while waiting
                print('WLAN connection succeeded!')
                return True,wlan
                break
            else:
                return False,wlan
    
    ok,w = buscarWifi('Gateway1')
    if ok:
        print('ok')
        s = socket.socket() 
        ip = w.ifconfig()
        print('ip destino = ',ip[0])
        print('Configuracion de red:',w.ifconfig())
        print('Estoy conectado=',w.isconnected())
        ip = w.ifconfig()
        host = ip[2]
        #print(type(HOST),'--->>',HOST)
        port = 8206
        s.connect((host, port))
        s.send("Hello server!")
        filename='prueba.txt'
        f = open(filename,'rb')
        l = f.read(1024)
        while (l):
           conn.send(l)
           print('Sent ',repr(l))
           l = f.read(1024)
        f.close()
        s.close()
    

    and the error that appears to me in this case is:
    0_1523541847144_1.PNG

    I do not know what that error means, nor do I know if I'm doing things right. The only thing I know is that at least now they connect to Lopy client and Lopy server, which is already a lot, having to study how the socket system works.

    That's why in some comment I said, I was requesting some exemplary code of how the system should connect between a client and server and transfer a file.

    I have taken the code example from here:
    http://www.bogotobogo.com/python/python_network_programming_server_client_file_transfer.php

    Although I would like to be able to use the last one with Thread but I have not known how to adapt it to mircro python:
    http://www.bogotobogo.com/python/python_network_programming_server_client_file_transfer.php#ec2



  • can you post your complete code and I will have a look



  • @seb said in Send a file from one Lopy to another Lopy:

    error host unreachable - this means the lopy could not find a route to the destination

    If you do not find it as it is on the print server ('connected') when I run the client code? What am I missing?



  • @zceld

    error host unreachable - this means the lopy could not find a route to the destination



Pycom on Twitter