Skip to content

Add support for TCP flow control #77

Closed
@c1728p9

Description

@c1728p9

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 to ESP8266_NONOS_SDK/at and switch your working directory to it
  • run gen_misc.sh using below settings OR run make 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()

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions