0

I use Raspberry Pi Pico with ESP8266 WiFi module, and I am trying to write a TCP client. Rasp Pi Pico is able to send AT commands and receive responses and send data through UART. Also the TCP client is able to send data to the TCP server, which runs in my laptop. However the problem is that the client is not able to connect to the server after some point.

Let me first show the server-side code. In server, I am trying to receive data basically. ConnectionResetError was a problem for me so I wrote the following except block. I am not sure it is buggy or not, since I'm kind of a noob in this area.

import socket

HOST = ""
PORT = 8080

mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

mysocket.bind((HOST, PORT))
mysocket.listen(1)

while True:
    print("Waiting...")
    conn, addr = mysocket.accept()
    print('[SERVER] - Connected from: %s' % str(addr))
    while True:
        try:
            request = conn.recv(1024)
            if not request:
                break
            conn.sendall(request.upper())
            print('[SERVER] - Received Data: %s' % str(request))

        except ConnectionResetError as cr_err:
            break
        
    conn.close()
    print("[SERVER] - Disconnected")

Here is my client-side code. In client, I wrote two helper classes called ESP8266 and Sensor, in which I control the WiFi module and read analog value from a sensor. Pico first tries to start WiFi module, afterwards it tries to connect to TCP server and send data. After some point it does not connect to the TCP server, so it restart the WiFi module and reconnects.

class EndDevice:
    def __init__(self, sensor_id):
        self.__wifi_module = ESP8266(UART_PIN, BAUDRATE)
        self.__sensor = Sensor(sensor_id, SENSOR_PIN)
        
    def start(self):
        self.__wifi_module.start()
        self.__wifi_module.set_mode(STATION_MODE)
        self.__wifi_module.join_access_point(AP_NAME, AP_PWD)
    
    def reconnect(self):
        self.__wifi_module.restart()
        self.__wifi_module.set_mode(STATION_MODE)
        self.__wifi_module.join_access_point(AP_NAME, AP_PWD)
    
    def run(self):
        retry_count = 0
        while True:
            if self.__wifi_module.start_connection("TCP", SERVER_HOST, SERVER_PORT):
                self.__wifi_module.send_data(
                    str(self.__sensor.generate_package()))
                self.__wifi_module.close_connection()
            else:
                retry_count += 1
                if retry_count == MAX_RETRY:
                    break

if __name__ == "__main__":
    pico = EndDevice("SM-0")
    pico.start()
    while True:
        pico.run()
        pico.reconnect()

Finally I will share some of the methods in classes ESP8266 and UARTHandler (which is used in ESP8266), so you can see if I do anything non-sense.

start_connection method in ESP8266 is as follows. In this method, I tried to send the corresponding AT command to connect to a TCP server. In the method self.__uart_handler.send_receive_cmd timeout duration is 2000ms, and other parameters are AT command, connection_type (TCP), server IP address and server port, in order.

def start_connection(self, conn_type, remote_ip, remote_port):
    conn_type, remote_ip = "\"{}\"".format(conn_type), "\"{}\"".format(remote_ip)
    response = self.__uart_handler.send_receive_cmd(2000, CONN_START, conn_type, remote_ip, str(remote_port))
    if "OK" in response:
        self.__log("Connected to {} at port {}.".format(remote_ip, remote_port))
        return True
    else:
        self.__log("Failed to create a connection with {} at port {}.".format(remote_ip, remote_port))
            return False

send_receive_cmd method in UARTHandler is as follows. In this method I use lots of helper methods as you can see, however they are just formatting and writing to UART or reading from UART. I also insert a timeout between UART-read and UART-write

def __generate_cmd(self, cmd, *args):
    if len(args) != 0:
       cmd += "="
       for idx, each in enumerate(args):
            cmd += str(each)
            if idx != len(args)-1:
                cmd += ","
    cmd += "\r\n"
    return cmd

def __send_cmd(self, cmd, *args):
    sent_cmd = self.__generate_cmd(cmd, *args)
    self.__uart.write(sent_cmd)

def __receive_response(self, cmd):
    response = self.__uart.read()
    try: return response.decode('utf-8')
    except: return response

def send_receive_cmd(self, timeout, cmd, *args):
    self.__send_cmd(cmd, *args)
    utime.sleep_ms(timeout)
    return self.__receive_response(self.__generate_cmd(cmd, *args))

Let me ask my question again. This codes are working properly in starting-restarting and sending data for (let me say) 3 connections. However, after some connect-disconnect later, TCP client is not able to make a connection with TCP server. Again after some failed connection attempt, WiFi module is restarted and TCP connection is made and working properly again.

batuhancan
  • 37
  • 5
  • can you see the AT commands communication on serial? what version of AT firmware do you use? why do you connect and disconnect so frequently? let the connection open. now I guess the 5 links available in AT firmware are busy processing. – Juraj Jul 28 '22 at 16:06
  • Your server doesn't close connections so probably after a while you run into a maximum limit of connections. – user253751 Jul 28 '22 at 16:44
  • @Juraj sorry for the delay :) Yes, I can see the AT commands, also AT version is 2.3.0.0 and SDK version is v3.4-22-g967752e2. Also when I let the connection open, TCP connection stays alive for 2 data-send operations, then again disconnects. – batuhancan Jul 28 '22 at 16:58
  • @user253751 I changed the server-side in a way that it serves the current TCP client until there is no data sent. However after some iteration, server disconnects the client, even though the client still sends data. My extra question is that is 2000ms timeout long for sending commands or data? – batuhancan Jul 28 '22 at 17:01
  • 1
    The server side shown in the question does not loop until there is no data sent – user253751 Jul 28 '22 at 17:11
  • @user253751 I changed it according to your advise, updated version is now in the question :) – batuhancan Jul 28 '22 at 17:14
  • 1
    The server still doesn't close connections and now it closes the whole server if the client doesn't send anything – user253751 Jul 28 '22 at 17:18

0 Answers0