Description
Currently, there isn't a way to throttle TCP data since +IPD packets are sent by the ESP8266 as soon as TCP data is received.
The master branch of the ESP8266 SDK now has support for commands to allow true TCP flow control. These were added on this commit but have not been released yet. A summary of the commands are:
- Enable no IPD data mode:
AT+CIPRECVMODE=<1=No +IPD data, 0=Old behavior>
- Read data directly:
AT+CIPRECVDATA=<link_id>,<len>
Further details on these commands can be found on the commit which adds them.
To experiment with these new commands I build the lastest version of the NONOS SDK at the time of this post - espressif/ESP8266_NONOS_SDK@89920dc. The steps I used to build this firmware are below:
- Install build tools by following instructions here: https://github.com/pfalcon/esp-open-sdk
- Clone NONOS SDK: https://github.com/espressif/ESP8266_NONOS_SDK
- Copy the AT example to the SDK root directory
ESP8266_NONOS_SDK/examples/at
toESP8266_NONOS_SDK/at
and switch your working directory to it - run
gen_misc.sh
using below settings OR runmake COMPILE=gcc BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=QIO SPI_SIZE_MAP=2
Step 1: 1=boot_v1.2+
Step 2: 1=user1.bin
Step 3: 2=40MHz
Step 4: 0=QIO
Step 5: 2=1024KB( 512KB+ 512KB) - New binary will be created -
ESP8266_NONOS_SDK/bin/upgrade/user1.1024.new.2.bin
For ease of access I attahed the firmware I built:
flow_control-NONOS_SDK-89920dcc.zip. ESP8266 firmware update instructions can be found here. All files in this zip are identical to the existing update package except user1.1024.new.2.bin
which is what I built.
Finally, below is a script which can be used to demonstrate the new commands. To use this script first load the board use are using with the SerialPassthrough program. Then in the below script replace <FILL IN>
with appropriate values and run the script. It will create a local TCP server and then have the ESP8266 connect to it and use the new commands to limit TCP data via flow control.
from serial import Serial
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
# Host IP address to use for listening and for device to connect to
HOST = <FILL IN>
# Host port to listen on and for device to connect to
PORT = <FILL IN>
# Serial port of the device
SERIAL = <FILL IN>
# SSID of wifi for device to use
SSID= <FILL IN>
# Password of wifi for device to use
PASS= <FILL IN>
def main():
server_start()
s = Serial(SERIAL, baudrate=115200)
s.timeout = 1
s.write("AT+RST\r\n") # reset device
print s.read(1024)
s.write("AT+GMR\r\n") # print version info
print s.read(1024)
s.write("AT+CWMODE_CUR=1\r\n") # station mode
print s.read(1024)
s.write("AT+CIPMUX=1\r\n") # enable multiple connections
print s.read(1024)
s.write("AT+CWDHCP_CUR=1,1\r\n") # enable DHCP
print s.read(1024)
s.timeout = 10
s.write('AT+CWJAP_CUR="%s","%s"\r\n' % (SSID, PASS)) # Connect to wifi
print s.read(1024)
s.timeout = 1
# New command to change +IPD behavior
s.write("AT+CIPRECVMODE=1\r\n") # disable +IPD data
print s.read(1024)
s.write("AT+CIFSR\r\n") # get IP
print s.read(1024)
s.write('AT+CIPSTART=0,"TCP","%s",%s\r\n' % (HOST, PORT)) # Connect socket
print s.read(1024)
while True:
# New command to read data
s.write("AT+CIPRECVDATA=0,32\r\n") # Read data
print s.read(1024)
def server_start():
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(1)
thread = Thread(target=server_main, args=(server_socket,))
thread.daemon = True
thread.start()
def server_main(server_socket):
conn, addr = server_socket.accept()
print 'Connected by', addr
count = 1
while True:
# Send an incrementing count with no delay in between packets to test flow control
msg = "count: %s\r\n" % count
print("HOST sending count %i" % count)
conn.sendall(bytearray(msg))
count = count + 1
conn.close()
if __name__ == "__main__":
main()