ESP-IDF: ESP32 as TCP Client
|We have seen how to connect to a AP in the previous post, in this post we will hose to open a TCP connection with a server.
Why TCP?
Though we can use HTTP , that approach consumes lot of resources like hosting a presentation layer, for a quick recap, given below is the OSI layer. In case of embedded systems, with constrained environment, using TCP , two layers below the 7 layers will make us power efficient and controlled way of programming the chipset.
We will see how TCP connection can be made using ESP 32. For development we will use IoT development platform built on top of eclipse platform.
ESP-IDF uses lwIP (lightweight IP) to provide support many protocols .
- Protocols supported by lwIP
- ARP (Address Resolution Protocol)
- IP (Internet Protocol) v4 and v6
- TCP (Transmission Control Protocol)
- UDP (User Datagram Protocol)
- DNS (Domain Name Server)
- SNMP (Simple Network Management Protocol)
- DHCP (Dynamic Host Configuration Protocol)
- ICMP (Internet Control Message Protocol) for network maintenance and debugging
- IGMP (Internet Group Management Protocol) for multicast traffic management
- PPP (Point to Point Protocol)
- PPPoE (Point to Point Protocol over Ethernet)
lwIP provides three types of APIs
- Raw API
- netcon API
- BSD Socket API
the first one is aimed at performance and code size , the remaining two are aimed at usability and portability . Raw API doesn’t need a OS while the other two requires a OS
We will use Socket API for this blog , list of methods available in socket API
How to send data remote host
In order to send some data to remote site, we will simulate a TCP server, running on a remote host and receive data sent by TCP client. Our TCP client runs on ESP-32 and TCP server runs on windows machine (the server is Nodejs based,it can run on any platform with nodejs support) . ESP32 sends a text message (“HelloTCPServer” ) to server, in response server sends “Hello TCP Client”
Program :
All the code is available on this github repo. First we connect ESP32 to a WLAN, you can see more about it here. Then on a separate task we will start the TCP client. Sending a message to server involves following steps
open a socket
socket(domain, type, protocol)
The first parameter is communication domain for which we are creating the domain. Second parameter is socket type it can be SOCK_STREAM/SOCK_DGRAM/SOCK_SEQPACKET. Third parameter specifies the protocol (if we pass 0, lib will select the appropriate protocol)
Connect to remote host
connect(socket,address,address_lenght)
to connect to a remote host, you pass the socket to be used, the address and length of the sockaddr structure to connect method
write to socket
write(socket,message,message_len)
write method accepts socket, message and length of the message (in the same order). It writes the given message to the socket
read from the socket
read(socket,buffer,size_of_buffer)
read function, read available data from the socket and returns the number bytes written to buffer
close the socket
close(socket)
closed the given socket
How to run :
In the tcp_client.c , put your network settings and your machine address where you will be running the TCP server program.
To start the server run the following command
node nodejs_tcp_server.js
you should see the following on your consoles
On serial monitor, you can see the following..It prints the message received from server
Note : Seems ESP IDF doesn’t support use of lwip RAW API. Please refer this forum post for more details. So that means we can only use the BSD Socket API and netcon API
Hi,
I want to run a Server on ESP32, to read sensor values on browser.Could you let me know how to do that
There are multiple ways to do this. In stead of making esp32 as webserver, use esp32 as node and publish data to cloudmqtt, then run the server on other environment which has better power/performance. (I shall be writing one blog shortly)
However if you still want to use webserver, one can do it using many languages.
If you prefer micropython, install picoweb and run server (I prefer Python as code is simple and clean)
you can check this blog on how to build end to end IoT app within 10-steps
http://icircuit.net/building-iot-application-using-esp32-micropython-10-steps/2077
Why do we need to use TCP when we have http ?
you can use esp32 as http client, actually that is recommended way as most of the content and APIs are HTTP based. http it self works on TCP, you just need some extra text handling specific to HTTP and you need to follow HTTP protocol when making the request. IF both the server and client are under your control, with TCP you can design your own set of protocols.note that it is better to follow standard protocols such as HTTP than inventing our own. This blog is an example for how you can access the socket api on esp32…their might be cases when you need to the last bit of performance you can get from the ESP where you can’t provide enough memory for generic protocol like HTTP, such scenarios are very rare
thanks so much for the charts
I am using the ESP-WROVER-Kit developer kit and have downloaded your excellent tcp_client example from your github repo: esp_idf_esp32_posts.
Make Flash runs and flashes with no problem; however there is a runtime error regarding the following monitor output (any suggestions?):
>>>>>>>>>>>>>>>>>>>
Rebooting…
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x3e (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5576
load:0x40078000,len:0
ho 12 tail 0 room 4
load:0x40078000,len:13716
entry 0x40078fb4
I (30) boot: ESP-IDF v3.1-dev-137-g4f44d16e 2nd stage bootloader
I (30) boot: compile time 14:49:26
I (40) boot: Enabling RNG early entropy source…
I (40) boot: SPI Speed : 40MHz
I (41) boot: SPI Mode : DIO
I (45) boot: SPI Flash Size : 4MB
I (49) boot: Partition Table:
I (52) boot: ## Label Usage Type ST Offset Length
I (60) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (67) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (75) boot: 2 factory factory app 00 00 00010000 00100000
I (82) boot: End of partition table
I (86) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x0f498 ( 62616) map
I (117) esp_image: segment 1: paddr=0x0001f4c0 vaddr=0x3ffb0000 size=0x00b50 ( 2896) load
I (118) esp_image: segment 2: paddr=0x00020018 vaddr=0x400d0018 size=0x513d8 (332760) map
0x400d0018: _stext at ??:?
I (239) esp_image: segment 3: paddr=0x000713f8 vaddr=0x3ffb0b50 size=0x025fc ( 9724) load
I (243) esp_image: segment 4: paddr=0x000739fc vaddr=0x40080000 size=0x00400 ( 1024) load
0x40080000: _iram_start at C:/msys32/home/robert/esp/esp-idf/components/freertos/xtensa_vectors.S:1685
I (246) esp_image: segment 5: paddr=0x00073e04 vaddr=0x40080400 size=0x103d4 ( 66516) load
I (282) esp_image: segment 6: paddr=0x000841e0 vaddr=0x400c0000 size=0x00000 ( 0) load
I (292) boot: Loaded app from partition at offset 0x10000
I (292) boot: Disabling RNG early entropy source…
I (294) cpu_start: Pro cpu up.
I (297) cpu_start: Starting app cpu, entry point is 0x40080f2c
0x40080f2c: call_start_cpu1 at C:/msys32/home/robert/esp/esp-idf/components/esp32/cpu_start.c:215
I (289) cpu_start: App cpu up.
I (308) heap_init: Initializing. RAM available for dynamic allocation:
I (315) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (321) heap_init: At 3FFB8E10 len 000271F0 (156 KiB): DRAM
I (327) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (334) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (340) heap_init: At 400907D4 len 0000F82C (62 KiB): IRAM
I (346) cpu_start: Pro cpu start user code
I (29) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
ESP_ERROR_CHECK failed: esp_err_t 0x1101 at 0x40107ff8
0x40107ff8: initialise_wifi at C:/msys32/home/robert/esp/tcp_client/main/tcp_client.c:61 (discriminator 1)
file: “C:/msys32/home/robert/esp/tcp_client/main/tcp_client.c” line 61
func: initialise_wifi
expression: esp_wifi_init(&cfg)
Backtrace: 0x40087b90:0x3ffbaaa0 0x40087efd:0x3ffbaac0 0x40107ff8:0x3ffbaae0 0x40108129:0x3ffbab50 0x400d0f82:0x3ffbab80
0x40087b90: invoke_abort at C:/msys32/home/robert/esp/esp-idf/components/esp32/panic.c:572
0x40087efd: _esp_error_check_failed at C:/msys32/home/robert/esp/esp-idf/components/esp32/panic.c:584
0x40107ff8: initialise_wifi at C:/msys32/home/robert/esp/tcp_client/main/tcp_client.c:61 (discriminator 1)
0x40108129: app_main at C:/msys32/home/robert/esp/tcp_client/main/tcp_client.c:117
0x400d0f82: main_task at C:/msys32/home/robert/esp/esp-idf/components/esp32/cpu_start.c:449
Hi Robert,
seems the crash is due to change in v3.0 of IDF
https://github.com/espressif/esp-idf/releases
“WiFi initialization function, esp_wifi_init, no longer calls nvs_flash_init internally. Applications need to call nvs_flash_init before calling esp_wifi_init”
please add a call to nvs_flash_init(). I have updated the code (not tested yet), please let me know how it goes
Hi Sankar,
Thanks for doing this .. Ur tutorials are so helpful. And while running client and server code together i was having an error in socket connection since the ports used in two codes are different. (ie 3000 for server and 3010 for client). Please correct it.
Thank you again.
Hi Jithesh,
Esp 32 code is tested with nodejs process running on host machine,the esp32 client and server are not intended for communicating with each other. I will add new post on that.
Hello Shankar,
I’ve been reading your blog posts and I find it very fresh and interesting.
Is it possible to configure esp32 as a Wi-Fi AP with TCP client program running on it? Also is it possible to configure an esp32 as a station and have TCP server running inside that? If so my intention is to get data from multiple esp32s ( configured in station mode ) which are connected to a central esp32 ( AP ). The TCP client running inside the AP should initiate a request to one of its stations and get the data. Please note that the stations contain sensor data and station esp32s are to be configured as TCP servers.
Please share your thoughts regarding the possibility of this method, if you find this method as non standard or non -working model, please suggest some other model where i can get data from multiple esp32 to a central esp32. I dont need Http abstraction here.
Regards,
Rakesh
Hi Rakesh,
I think you should be able to initiate connection from ESP32(AP) to other ESP32s (station mode) but I never tried it .I am not sure exactly why the server has to be running on stations , is there any specific reason for that ?
You can also try running a TCP server on AP and configure your station ESP32s to push data to your server. You can refer
this post on how to run TCP server on ESP32 AP
http://icircuit.net/esp-idf-tcp-server-esp32/2042
Hi,
I just found this, you might be interested. You can implement a mesh topology based on esp32 or use this lib
https://gitlab.com/painlessMesh/painlessMesh
Hi
How to download the program to ESP32-WROVER Module alone with Arduino IDE. I m using serial Converter from arduion UNO board.
First i Connect 3.3V and Gud pins from UNO to ESP module
Second i Connect RX(UNO) to TX (ESP) and TX(UNO) to RX(ESP)
Third ESP-EN Pin Connect to button with Pull-up resistor (3.3V) as datasheet
Fourth IO0(GPIO 0) pin to button with respect to ground
I start programming with IDE, i hold the IO0 button, then press the ESP-EN button to move the ESP module to programming mode, i still hold IO0 button upto fully downloaded.
But I start to programming the ESP module with IDE
It Show the Connecting *****——–*******——-******———- like this
Please help me to come out from problem
UNO data lines are 5v and ESP32 data lines are 3v3, so you should not directly connect UNO and ESP32
I want to read data on esp32 using udp protocol from my laptop. How can i do it it would be helpful if anyone could guide me.
Hello, I have integrated the ESP32 TCP Client in station mode example above to connect it with the TCP Server in SoftAP mode to get a running connection between two ESP devices (ESP32 TCP Server ESP32 TCP Client). The TCP Server is working as expected with Packet Sender on PC.
But if I am trying to get the TCP Client running in STA mode, I am always getting a periodically event SYSTEM_EVENT_STA_DISCONNECTED=5 from the event handler.
Terminal output:
I (254) tcpServer: tcp_client task started
I (2654) wifi: … eventHandler – handle=1073471956, eventID=5
I (5064) wifi: … eventHandler – handle=1073471956, eventID=5
Do you have an idea why? Is it possible that the device hasn`t received an IP address from the ESP32 SoftAP ? Is the DHCP Server not running?
Thank you for your work. This post is very interesting and to help me.
Hi somebody pls help to get this,
My ESP32 being as wifi station and HTTP server running on it using TCP.
Now I am able to control led pin. I want to run a Server on ESP32, to read sensor values on browser. webserver written in HTML code and the main application is using ESP-IDF written in C.
Could you let me know how to do that
i want to send data to esp32 by using tcp/ip protocol .can anyone please suggest me how to program this.
https://icircuit.net/esp-idf-tcp-server-esp32/2042