I'm trying to implement a full-duplex communication between my ESP8266 and a socketserver running on my laptop. In concrete I need each of the devices to initiate communication whenever it needs to. The ESP is measuring temperature all the time and when the temperature changes, I want the ESP to transmit the new temperature to my laptop. On the other side I want to transmit a command from my laptop whenever I want to know the actual temperature (even if the temperature has not changed).
Therefore I have a python server-script and a python client-script both running on my laptop (see scipts below).
In the loop function on my ESP I'm also running a server and a client (script below).
Sending commands from laptop-client to ESP-server works perfectly. Even at high rates and for days without any problem.
Communicating the other way around (that is sending from ESP-client to laptop-server) seems to work in general, but after numerous packages (usually a few hundreds) have been sent from ESP-client to laptop-server the communication fails and the laptop-server only receives empty byte-strings. After that has happened, also sending commands from laptop-client to ESP-server does not work any more temporarily. When I shutdown the laptop-server, the ESP needs some time to "calm down" and will then continue working as usual.
Can anyone imagine what causes this behaviour? To me it looks like a buffer overflow or something like that. I appreciate any help and hints about how to implement the desired functionality (do I actually need to run a server on both my laptop and the ESP?).
Laptop-Server:
import socket
import time
# create a socket object
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
host = "0.0.0.0"
port=1992
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
try:
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
try:
data = clientsocket.recv(1024)
print(str(addr),": ",data)
clientsocket.send("hi there, "+str(addr)+"\n")
clientsocket.close()
except:
pass
except:
print(" !!! an exception occured !!!")
serversocket.shutdown(socket.SHUT_RDWR)
serversocket.close()
Laptop-Client:
import os,sys,re,time,socket,threading,readline
timeout=2
HOST, PORT = "ESP-IP", 1991
response=""
def s_client(data):
global response
try:
response='Error: received no response'
# Connect to server and send data
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
sock.connect((HOST, PORT))
sock.sendall(bytes(data + "\n", "utf-8"))
# Receive data from the server and shut down
response=str(sock.recv(1024), "utf-8")
except ConnectionRefusedError:
response='Error: connection refused by remote host'
except socket.timeout:
response='Error: connection timed out'
finally:
sock.close()
return 1
while True:
try:
print(' --> '+s_client(input('_$ ')))
except KeyboardInterrupt:
break
ESP-script (containing server and client):
#include <WiFiClient.h>
#include <ESP8266WiFi.h>
IPAddress laptop_ip=(0,0,0,0);
uint16_t TCP_port=1991;
uint16_t TCP_remote_port=1992;
WiFiServer TCPserver(TCP_port);
WiFiClient client;
void ESP_server(void){
if (!client.connected()) {
client=TCPserver.available();
}
else {
laptop_ip=client.remoteIP();
Serial.println("received request");
int query_l=client.available();
if(query_l>0){
String query="";
for (int nb = 0; nb < query_l-1; nb++){
query+=(char) client.read();
}client.read();
Serial.print("received from laptop: ");Serial.println(query);
// Do something with query and return the result
// For simplicity I'm just returning a constant value
client.write("command transmitted");
}
}
}
void ESP_client(String message){
WiFiClient TCPclient;
if (TCPclient.connect(laptop_ip, TCP_remote_port)){
TCPclient.print(message);
}
}
void setup() {
Serial.begin(115200);
WiFi.begin("MYSSID","MYPASS");
Serial.print("connecting with WiFi ");
while(WiFi.status()!=WL_CONNECTED){
Serial.print(".");
delay(500);
}Serial.println();
TCPserver.begin();
// wait until a command has been received from the laptop
// ESP_server stores the remote (laptop) ip in laptop_ip
while(laptop_ip==(0,0,0,0)){
ESP_server();
}
}
int temp=0;
void loop() {
// handle commands sent from my laptop
ESP_server();
// here is a temperature meaurement returning the current temperature
// I've replaced it with a temperature generator
if(temp<30){temp++;}
else{temp=0;}
// temperature has changed and needs to be transmitted by this function
ESP_client((String) temp);
}
The above code differes from the code I'm actually running but it reproduces my problem. I hope that somebody can figure out a misstake or give my some advice about how I could implement things in a better way. Actually I'm not sure whether the misstake is on laptop- or ESP-side but as the ESP crashes sometimes I think it's the ESP...
I'm using the arduino IDE for flashing, btw.