LwESP branch-7c00ef1 documentation¶
Welcome to the documentation for version branch-7c00ef1.
LwESP is generic, platform independent, ESP-AT parser library to communicate with ESP8266 or ESP32 WiFi-based microcontrollers from Espressif systems using official AT Commands set running on ESP device. Its objective is to run on master system, while Espressif device runs official AT commands firmware developed and maintained by Espressif systems.
Download library Getting started Open Github Donate
Features¶
Supports latest ESP32, ESP32-C3 & ESP8266 AT software from Espressif system
Platform independent and easy to port, written in C99
Library is developed under Win32 platform
Provided examples for ARM Cortex-M or Win32 platforms
Allows different configurations to optimize user requirements
Optimized for systems with operating systems (or RTOS)
Currently only OS mode is supported
2
different threads to process user inputs and received dataProducer thread to collect user commands from application threads and to start command execution
Process thread to process received data from ESP device
Allows sequential API for connections in client and server mode
Includes several applications built on top of library
HTTP server with dynamic files (file system) support
MQTT client for MQTT connection
MQTT client Cayenne API for Cayenne MQTT server
Embeds other AT features, such as WPS
User friendly MIT license
Requirements¶
C compiler
ESP8266 or ESP32 device with running AT-Commands firmware
Contribute¶
Fresh contributions are always welcome. Simple instructions to proceed:
Fork Github repository
Respect C style & coding rules used by the library
Create a pull request to
develop
branch with new features or bug fixes
Alternatively you may:
Report a bug
Ask for a feature request
License¶
MIT License
Copyright (c) 2020 Tilen MAJERLE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Table of contents¶
Getting started¶
Getting started may be the most challenging part of every new library. This guide is describing how to start with the library quickly and effectively
Download library¶
Library is primarly hosted on Github.
You can get it with:
Downloading latest release from releases area on Github
Clone
master
branch for latest stable versionClone
develop
branch for latest development
Download from releases¶
All releases are available on Github releases area.
Clone from Github¶
First-time clone¶
This is used when you do not have yet local copy on your machine.
Make sure
git
is installed.Open console and navigate to path in the system to clone repository to. Use command
cd your_path
Clone repository with one of available
3
optionsRun
git clone --recurse-submodules https://github.com/MaJerle/lwesp
command to clone entire repository, including submodulesRun
git clone --recurse-submodules --branch develop https://github.com/MaJerle/lwesp
to clone development branch, including submodulesRun
git clone --recurse-submodules --branch master https://github.com/MaJerle/lwesp
to clone latest stable branch, including submodules
Navigate to
examples
directory and run favourite example
Update cloned to latest version¶
Open console and navigate to path in the system where your repository is located. Use command
cd your_path
Run
git pull origin master
command to get latest changes onmaster
branchRun
git pull origin develop
command to get latest changes ondevelop
branchRun
git submodule update --init --remote
to update submodules to latest version
Note
This is preferred option to use when you want to evaluate library and run prepared examples. Repository consists of multiple submodules which can be automatically downloaded when cloning and pulling changes from root repository.
Add library to project¶
At this point it is assumed that you have successfully download library, either cloned it or from releases page. Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path
Copy
lwesp
folder to your project, it contains library filesAdd
lwesp/src/include
folder to include path of your toolchain. This is where C/C++ compiler can find the files during compilation process. Usually using-I
flagAdd source files from
lwesp/src/
folder to toolchain build. These files are built by C/C++ compilerCopy
lwesp/src/include/lwesp/lwesp_opts_template.h
to project folder and rename it tolwesp_opts.h
Build the project
Configuration file¶
Configuration file is used to overwrite default settings defined for the essential use case.
Library comes with template config file, which can be modified according to needs.
and it should be copied (or simply renamed in-place) and named lwesp_opts.h
Note
Default configuration template file location: lwesp/src/include/lwesp/lwesp_opts_template.h
.
File must be renamed to lwesp_opts.h
first and then copied to the project directory where compiler
include paths have access to it by using #include "lwesp_opts.h"
.
List of configuration options are available in the Configuration section. If any option is about to be modified, it should be done in configuration file
1/**
2 * \file lwesp_opts_template.h
3 * \brief Template config file
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#ifndef LWESP_HDR_OPTS_H
35#define LWESP_HDR_OPTS_H
36
37/* Rename this file to "lwesp_opts.h" for your application */
38
39/*
40 * Open "include/lwesp/lwesp_opt.h" and
41 * copy & replace here settings you want to change values
42 */
43
44#endif /* LWESP_HDR_OPTS_H */
Note
If you prefer to avoid using configuration file, application must define
a global symbol LWESP_IGNORE_USER_OPTS
, visible across entire application.
This can be achieved with -D
compiler option.
User manual¶
Overview¶
WiFi devices (focus on ESP8266 and ESP32) from Espressif Systems are low-cost and very useful for embedded projects. These are classic microcontrollers without embedded flash memory. Application needs to assure external Quad-SPI flash to execute code from it directly.
Espressif offers SDK to program these microcontrollers directly and run code from there.
It is called RTOS-based SDK, written in C language, and allows customers to program MCU starting with main
function.
These devices have some basic peripherals, such as GPIO, ADC, SPI, I2C, UART, etc. Pretty basic though.
Wifi connectivity is often part of bigger system with more powerful MCU. There is usually bigger MCU + Wifi transceiver (usually module) aside with UART/SPI communication. MCU handles application, such as display & graphics, runs operating systems, drives motor and has additional external memories.
Typical application example with access to WiFi¶
Espressif is not only developing RTOS SDK firmware, it also develops AT Slave firmware based on RTOS-SDK. This is a special application, which is running on ESP device and allows host MCU to send AT commands and get response for it. Now it is time to use LwESP you are reading this manual for.
LwESP has been developed to allow customers to:
Develop on single (host MCU) architecture at the same time and do not care about Espressif arch
Shorten time to market
Customers using LwESP do not need to take care about proper command for specific task,
they can call API functions, such as lwesp_sta_join()
to join WiFi network instead.
Library will take the necessary steps in order to send right command to device via low-level driver (usually UART) and
process incoming response from device before it will notify application layer if it was successfuly or not.
Note
LwESP offers efficient communication between host MCU at one side and Espressif wifi transceiver on another side.
To summarize:
ESP device runs official AT firmware, provided by Espressif systems
Host MCU runs custom application, together with LwESP library
Host MCU communicates with ESP device with UART or similar interface.
Architecture¶
Architecture of the library consists of 4
layers.
ESP-AT layer architecture overview¶
Application layer¶
User layer is the highest layer of the final application. This is the part where API functions are called to execute some command.
Middleware layer¶
Middleware part is actively developed and shall not be modified by customer by any means. If there is a necessity to do it, often it means that developer of the application uses it wrongly. This part is platform independent and does not use any specific compiler features for proper operation.
Note
There is no compiler specific features implemented in this layer.
System & low-level layer¶
Application needs to fully implement this part and resolve it with care. Functions are related to actual implementation with ESP device and are highly architecture oriented. Some examples for WIN32 and ARM Cortex-M are included with library.
Tip
Check Porting guide for detailed instructions and examples.
System functions¶
System functions are bridge between operating system running on embedded system and ESP-AT middleware. Functions need to provide:
Thread management
Binary semaphore management
Recursive mutex management
Message queue management
Current time status information
Tip
System function prototypes are available in System functions section.
Low-level implementation¶
Low-Level, or LWESP_LL, is part, dedicated for communication between ESP-AT middleware and ESP physical device. Application needs to implement output function to send necessary AT command instruction aswell as implement input module to send received data from ESP device to ESP-AT middleware.
Application must also assure memory assignment for Memory manager when default allocation is used.
Tip
Low level, input module & memory function prototypes are available in Low-Level functions, Input module and Memory manager respectfully.
ESP physical device¶
Inter thread communication¶
ESP-AT middleware is only available with operating system.
For successful resources management, it uses 2
threads within library and allows multiple application threads to post new command to be processed.
Inter-thread architecture block diagram¶
Producing and Processing threads are part of library, its implementation is in lwesp_threads.c
file.
Processing thread¶
Processing thread is in charge of processing each and every received character from ESP device. It can process URC messages which are received from ESP device without any command request. Some of them are:
+IPD indicating new data packet received from remote side on active connection
WIFI CONNECTED indicating ESP has been just connected to access point
and more others
Note
Received messages without any command (URC messages) are sent to application layer using events, where they can be processed and used in further steps
This thread also checks and processes specific received messages based on active command.
As an example, when application tries to make a new connection to remote server, it starts command with AT+CIPSTART
message.
Thread understands that active command is to connect to remote side and will wait for potential +LINK_CONN:<...>
message,
indicating connection status. it will also wait for OK
or ERROR
,
indicating command finished status before it unlocks sync_sem to unblock producing thread.
Tip
When thread tries to unlock sync_sem, it first checks if it has been locked by producing thread.
Producing thread¶
Producing thread waits for command messages posted from application thread. When new message has been received, it sends initial AT message over AT port.
It checks if command is valid and if it has corresponding initial AT sequence, such as
AT+CIPSTART
It locks sync_sem semaphore and waits for processing thread to unlock it
Processing thread is in charge to read respone from ESP and react accordingly. See previous section for details.
If application uses blocking mode, it unlocks command sem semaphore and returns response
If application uses non-blocking mode, it frees memory for message and sends event with response message
Application thread¶
Application thread is considered any thread which calls API functions and therefore writes new messages to producing message queue, later processed by producing thread.
A new message memory is allocated in this thread and type of command is assigned to it, together with required input data for command. It also sets blocking or non-blocking mode, how command shall be executed.
When application tries to execute command in blocking mode, it creates new sync semaphore sem, locks it, writes message to producing queue and waits for sem to get unlocked. This effectively puts thread to blocked state by operating system and removes it from scheduler until semaphore is unlocked again. Semaphore sem gets unlocked in producing thread when response has been received for specific command.
Tip
sem semaphore is unlocked in producing thread after sync_sem is unlocked in processing thread
Note
Every command message uses its own sem semaphore to sync multiple application threads at the same time.
If message is to be executed in non-blocking mode, sem is not created as there is no need to block application thread. When this is the case, application thread will only write message command to producing queue and return status of writing to application.
Events and callback functions¶
Library uses events to notify application layer for (possible, but not limited to) unexpected events. This concept is used aswell for commands with longer executing time, such as scanning access points or when application starts new connection as client mode.
There are 3
types of events/callbacks available:
Global event callback function, assigned when initializing library
Connection specific event callback function, to process only events related to connection, such as connection error, data send, data receive, connection closed
API function call based event callback function
Every callback is always called from protected area of middleware (when exclusing access is granted to single thread only),
and it can be called from one of these 3
threads:
Producing thread
Processing thread
Input thread, when
LWESP_CFG_INPUT_USE_PROCESS
is enabled andlwesp_input_process()
function is called
Tip
Check Inter thread communication for more details about Producing and Processing thread.
Global event callback¶
Global event callback function is assigned at library initialization. It is used by the application to receive any kind of event, except the one related to connection:
ESP station successfully connected to access point
ESP physical device reset has been detected
Restore operation finished
New station has connected to access point
and many more..
Tip
Check Event management section for different kind of events
By default, global event function is single function.
If the application tries to split different events with different callback functions,
it is possible to do so by using lwesp_evt_register()
function to register a new,
custom, event function.
Tip
Implementation of Netconn API leverages lwesp_evt_register()
to
receive event when station disconnected from wifi access point.
Check its source file for actual implementation.
1/**
2 * \file lwesp_netconn.c
3 * \brief API functions for sequential calls
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#include "lwesp/lwesp_netconn.h"
35#include "lwesp/lwesp_private.h"
36#include "lwesp/lwesp_conn.h"
37#include "lwesp/lwesp_mem.h"
38
39#if LWESP_CFG_NETCONN || __DOXYGEN__
40
41/* Check conditions */
42#if LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN < 2
43#error "LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN must be greater or equal to 2"
44#endif /* LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN < 2 */
45
46#if LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN < 2
47#error "LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN must be greater or equal to 2"
48#endif /* LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN < 2 */
49
50/* Check for IP status */
51#if LWESP_CFG_IPV6
52#define NETCONN_IS_TCP(nc) (nc->type == LWESP_NETCONN_TYPE_TCP || nc->type == LWESP_NETCONN_TYPE_TCPV6)
53#define NETCONN_IS_SSL(nc) (nc->type == LWESP_NETCONN_TYPE_SSL || nc->type == LWESP_NETCONN_TYPE_SSLV6)
54#else
55#define NETCONN_IS_TCP(nc) (nc->type == LWESP_NETCONN_TYPE_TCP)
56#define NETCONN_IS_SSL(nc) (nc->type == LWESP_NETCONN_TYPE_SSL)
57#endif /* LWESP_CFG_IPV6 */
58
59/**
60 * \brief Sequential API structure
61 */
62typedef struct lwesp_netconn {
63 struct lwesp_netconn* next; /*!< Linked list entry */
64
65 lwesp_netconn_type_t type; /*!< Netconn type */
66 lwesp_port_t listen_port; /*!< Port on which we are listening */
67
68 size_t rcv_packets; /*!< Number of received packets so far on this connection */
69 lwesp_conn_p conn; /*!< Pointer to actual connection */
70
71 lwesp_sys_mbox_t mbox_accept; /*!< List of active connections waiting to be processed */
72 lwesp_sys_mbox_t mbox_receive; /*!< Message queue for receive mbox */
73 size_t mbox_receive_entries; /*!< Number of entries written to receive mbox */
74
75 lwesp_linbuff_t buff; /*!< Linear buffer structure */
76
77 uint16_t conn_timeout; /*!< Connection timeout in units of seconds when
78 netconn is in server (listen) mode.
79 Connection will be automatically closed if there is no
80 data exchange in time. Set to `0` when timeout feature is disabled. */
81
82#if LWESP_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__
83 uint32_t rcv_timeout; /*!< Receive timeout in unit of milliseconds */
84#endif
85} lwesp_netconn_t;
86
87static uint8_t recv_closed = 0xFF, recv_not_present = 0xFF;
88static lwesp_netconn_t* listen_api; /*!< Main connection in listening mode */
89static lwesp_netconn_t* netconn_list; /*!< Linked list of netconn entries */
90
91/**
92 * \brief Flush all mboxes and clear possible used memories
93 * \param[in] nc: Pointer to netconn to flush
94 * \param[in] protect: Set to 1 to protect against multi-thread access
95 */
96static void
97flush_mboxes(lwesp_netconn_t* nc, uint8_t protect) {
98 lwesp_pbuf_p pbuf;
99 lwesp_netconn_t* new_nc;
100 if (protect) {
101 lwesp_core_lock();
102 }
103 if (lwesp_sys_mbox_isvalid(&nc->mbox_receive)) {
104 while (lwesp_sys_mbox_getnow(&nc->mbox_receive, (void**)&pbuf)) {
105 if (nc->mbox_receive_entries > 0) {
106 --nc->mbox_receive_entries;
107 }
108 if (pbuf != NULL && (uint8_t*)pbuf != (uint8_t*)&recv_closed) {
109 lwesp_pbuf_free(pbuf); /* Free received data buffers */
110 }
111 }
112 lwesp_sys_mbox_delete(&nc->mbox_receive); /* Delete message queue */
113 lwesp_sys_mbox_invalid(&nc->mbox_receive); /* Invalid handle */
114 }
115 if (lwesp_sys_mbox_isvalid(&nc->mbox_accept)) {
116 while (lwesp_sys_mbox_getnow(&nc->mbox_accept, (void**)&new_nc)) {
117 if (new_nc != NULL
118 && (uint8_t*)new_nc != (uint8_t*)&recv_closed
119 && (uint8_t*)new_nc != (uint8_t*)&recv_not_present) {
120 lwesp_netconn_close(new_nc); /* Close netconn connection */
121 }
122 }
123 lwesp_sys_mbox_delete(&nc->mbox_accept);/* Delete message queue */
124 lwesp_sys_mbox_invalid(&nc->mbox_accept); /* Invalid handle */
125 }
126 if (protect) {
127 lwesp_core_unlock();
128 }
129}
130
131/**
132 * \brief Callback function for every server connection
133 * \param[in] evt: Pointer to callback structure
134 * \return Member of \ref lwespr_t enumeration
135 */
136static lwespr_t
137netconn_evt(lwesp_evt_t* evt) {
138 lwesp_conn_p conn;
139 lwesp_netconn_t* nc = NULL;
140 uint8_t close = 0;
141
142 conn = lwesp_conn_get_from_evt(evt); /* Get connection from event */
143 switch (lwesp_evt_get_type(evt)) {
144 /*
145 * A new connection has been active
146 * and should be handled by netconn API
147 */
148 case LWESP_EVT_CONN_ACTIVE: { /* A new connection active is active */
149 if (lwesp_conn_is_client(conn)) { /* Was connection started by us? */
150 nc = lwesp_conn_get_arg(conn); /* Argument should be already set */
151 if (nc != NULL) {
152 nc->conn = conn; /* Save actual connection */
153 } else {
154 close = 1; /* Close this connection, invalid netconn */
155 }
156
157 /* Is the connection server type and we have known listening API? */
158 } else if (lwesp_conn_is_server(conn) && listen_api != NULL) {
159 /*
160 * Create a new netconn structure
161 * and set it as connection argument.
162 */
163 nc = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP); /* Create new API */
164 LWESP_DEBUGW(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_WARNING,
165 nc == NULL, "[NETCONN] Cannot create new structure for incoming server connection!\r\n");
166
167 if (nc != NULL) {
168 nc->conn = conn; /* Set connection handle */
169 lwesp_conn_set_arg(conn, nc); /* Set argument for connection */
170
171 /*
172 * In case there is no listening connection,
173 * simply close the connection
174 */
175 if (!lwesp_sys_mbox_isvalid(&listen_api->mbox_accept)
176 || !lwesp_sys_mbox_putnow(&listen_api->mbox_accept, nc)) {
177 close = 1;
178 }
179 } else {
180 close = 1;
181 }
182 } else {
183 LWESP_DEBUGW(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_WARNING, listen_api == NULL,
184 "[NETCONN] Closing connection as there is no listening API in netconn!\r\n");
185 close = 1; /* Close the connection at this point */
186 }
187
188 /* Decide if some events want to close the connection */
189 if (close) {
190 if (nc != NULL) {
191 lwesp_conn_set_arg(conn, NULL); /* Reset argument */
192 lwesp_netconn_delete(nc); /* Free memory for API */
193 }
194 lwesp_conn_close(conn, 0); /* Close the connection */
195 close = 0;
196 }
197 break;
198 }
199
200 /*
201 * We have a new data received which
202 * should have netconn structure as argument
203 */
204 case LWESP_EVT_CONN_RECV: {
205 lwesp_pbuf_p pbuf;
206
207 nc = lwesp_conn_get_arg(conn); /* Get API from connection */
208 pbuf = lwesp_evt_conn_recv_get_buff(evt); /* Get received buff */
209
210#if !LWESP_CFG_CONN_MANUAL_TCP_RECEIVE
211 lwesp_conn_recved(conn, pbuf); /* Notify stack about received data */
212#endif /* !LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */
213
214 lwesp_pbuf_ref(pbuf); /* Increase reference counter */
215 if (nc == NULL || !lwesp_sys_mbox_isvalid(&nc->mbox_receive)
216 || !lwesp_sys_mbox_putnow(&nc->mbox_receive, pbuf)) {
217 LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN,
218 "[NETCONN] Ignoring more data for receive!\r\n");
219 lwesp_pbuf_free(pbuf); /* Free pbuf */
220 return lwespOKIGNOREMORE; /* Return OK to free the memory and ignore further data */
221 }
222 ++nc->mbox_receive_entries; /* Increase number of packets in receive mbox */
223#if LWESP_CFG_CONN_MANUAL_TCP_RECEIVE
224 /* Check against 1 less to still allow potential close event to be written to queue */
225 if (nc->mbox_receive_entries >= (LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN - 1)) {
226 conn->status.f.receive_blocked = 1; /* Block reading more data */
227 }
228#endif /* LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */
229
230 ++nc->rcv_packets; /* Increase number of packets received */
231 LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE,
232 "[NETCONN] Received pbuf contains %d bytes. Handle written to receive mbox\r\n",
233 (int)lwesp_pbuf_length(pbuf, 0));
234 break;
235 }
236
237 /* Connection was just closed */
238 case LWESP_EVT_CONN_CLOSE: {
239 nc = lwesp_conn_get_arg(conn); /* Get API from connection */
240
241 /*
242 * In case we have a netconn available,
243 * simply write pointer to received variable to indicate closed state
244 */
245 if (nc != NULL && lwesp_sys_mbox_isvalid(&nc->mbox_receive)) {
246 if (lwesp_sys_mbox_putnow(&nc->mbox_receive, (void*)&recv_closed)) {
247 ++nc->mbox_receive_entries;
248 }
249 }
250
251 break;
252 }
253 default:
254 return lwespERR;
255 }
256 return lwespOK;
257}
258
259/**
260 * \brief Global event callback function
261 * \param[in] evt: Callback information and data
262 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
263 */
264static lwespr_t
265lwesp_evt(lwesp_evt_t* evt) {
266 switch (lwesp_evt_get_type(evt)) {
267 case LWESP_EVT_WIFI_DISCONNECTED: { /* Wifi disconnected event */
268 if (listen_api != NULL) { /* Check if listen API active */
269 lwesp_sys_mbox_putnow(&listen_api->mbox_accept, &recv_closed);
270 }
271 break;
272 }
273 case LWESP_EVT_DEVICE_PRESENT: { /* Device present event */
274 if (listen_api != NULL && !lwesp_device_is_present()) { /* Check if device present */
275 lwesp_sys_mbox_putnow(&listen_api->mbox_accept, &recv_not_present);
276 }
277 }
278 default:
279 break;
280 }
281 return lwespOK;
282}
283
284/**
285 * \brief Create new netconn connection
286 * \param[in] type: Netconn connection type
287 * \return New netconn connection on success, `NULL` otherwise
288 */
289lwesp_netconn_p
290lwesp_netconn_new(lwesp_netconn_type_t type) {
291 lwesp_netconn_t* a;
292 static uint8_t first = 1;
293
294 /* Register only once! */
295 lwesp_core_lock();
296 if (first) {
297 first = 0;
298 lwesp_evt_register(lwesp_evt); /* Register global event function */
299 }
300 lwesp_core_unlock();
301 a = lwesp_mem_calloc(1, sizeof(*a)); /* Allocate memory for core object */
302 if (a != NULL) {
303 a->type = type; /* Save netconn type */
304 a->conn_timeout = 0; /* Default connection timeout */
305 if (!lwesp_sys_mbox_create(&a->mbox_accept, LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN)) { /* Allocate memory for accepting message box */
306 LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_DANGER,
307 "[NETCONN] Cannot create accept MBOX\r\n");
308 goto free_ret;
309 }
310 if (!lwesp_sys_mbox_create(&a->mbox_receive, LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN)) {/* Allocate memory for receiving message box */
311 LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_DANGER,
312 "[NETCONN] Cannot create receive MBOX\r\n");
313 goto free_ret;
314 }
315 lwesp_core_lock();
316 if (netconn_list == NULL) { /* Add new netconn to the existing list */
317 netconn_list = a;
318 } else {
319 a->next = netconn_list; /* Add it to beginning of the list */
320 netconn_list = a;
321 }
322 lwesp_core_unlock();
323 }
324 return a;
325free_ret:
326 if (lwesp_sys_mbox_isvalid(&a->mbox_accept)) {
327 lwesp_sys_mbox_delete(&a->mbox_accept);
328 lwesp_sys_mbox_invalid(&a->mbox_accept);
329 }
330 if (lwesp_sys_mbox_isvalid(&a->mbox_receive)) {
331 lwesp_sys_mbox_delete(&a->mbox_receive);
332 lwesp_sys_mbox_invalid(&a->mbox_receive);
333 }
334 if (a != NULL) {
335 lwesp_mem_free_s((void**)&a);
336 }
337 return NULL;
338}
339
340/**
341 * \brief Delete netconn connection
342 * \param[in] nc: Netconn handle
343 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
344 */
345lwespr_t
346lwesp_netconn_delete(lwesp_netconn_p nc) {
347 LWESP_ASSERT("netconn != NULL", nc != NULL);
348
349 lwesp_core_lock();
350 flush_mboxes(nc, 0); /* Clear mboxes */
351
352 /* Stop listening on netconn */
353 if (nc == listen_api) {
354 listen_api = NULL;
355 lwesp_core_unlock();
356 lwesp_set_server(0, nc->listen_port, 0, 0, NULL, NULL, NULL, 1);
357 lwesp_core_lock();
358 }
359
360 /* Remove netconn from linkedlist */
361 if (nc == netconn_list) {
362 netconn_list = netconn_list->next; /* Remove first from linked list */
363 } else if (netconn_list != NULL) {
364 lwesp_netconn_p tmp, prev;
365 /* Find element on the list */
366 for (prev = netconn_list, tmp = netconn_list->next;
367 tmp != NULL; prev = tmp, tmp = tmp->next) {
368 if (nc == tmp) {
369 prev->next = tmp->next; /* Remove tmp from linked list */
370 break;
371 }
372 }
373 }
374 lwesp_core_unlock();
375
376 lwesp_mem_free_s((void**)&nc);
377 return lwespOK;
378}
379
380/**
381 * \brief Connect to server as client
382 * \param[in] nc: Netconn handle
383 * \param[in] host: Pointer to host, such as domain name or IP address in string format
384 * \param[in] port: Target port to use
385 * \return \ref lwespOK if successfully connected, member of \ref lwespr_t otherwise
386 */
387lwespr_t
388lwesp_netconn_connect(lwesp_netconn_p nc, const char* host, lwesp_port_t port) {
389 lwespr_t res;
390
391 LWESP_ASSERT("nc != NULL", nc != NULL);
392 LWESP_ASSERT("host != NULL", host != NULL);
393 LWESP_ASSERT("port > 0", port > 0);
394
395 /*
396 * Start a new connection as client and:
397 *
398 * - Set current netconn structure as argument
399 * - Set netconn callback function for connection management
400 * - Start connection in blocking mode
401 */
402 res = lwesp_conn_start(NULL, (lwesp_conn_type_t)nc->type, host, port, nc, netconn_evt, 1);
403 return res;
404}
405
406/**
407 * \brief Connect to server as client, allow keep-alive option
408 * \param[in] nc: Netconn handle
409 * \param[in] host: Pointer to host, such as domain name or IP address in string format
410 * \param[in] port: Target port to use
411 * \param[in] keep_alive: Keep alive period seconds
412 * \param[in] local_ip: Local ip in connected command
413 * \param[in] local_port: Local port address
414 * \param[in] mode: UDP mode
415 * \return \ref lwespOK if successfully connected, member of \ref lwespr_t otherwise
416 */
417lwespr_t
418lwesp_netconn_connect_ex(lwesp_netconn_p nc, const char* host, lwesp_port_t port,
419 uint16_t keep_alive, const char* local_ip, lwesp_port_t local_port, uint8_t mode) {
420 lwesp_conn_start_t cs = {0};
421 lwespr_t res;
422
423 LWESP_ASSERT("nc != NULL", nc != NULL);
424 LWESP_ASSERT("host != NULL", host != NULL);
425 LWESP_ASSERT("port > 0", port > 0);
426
427 /*
428 * Start a new connection as client and:
429 *
430 * - Set current netconn structure as argument
431 * - Set netconn callback function for connection management
432 * - Start connection in blocking mode
433 */
434 cs.type = nc->type;
435 cs.remote_host = host;
436 cs.remote_port = port;
437 cs.local_ip = local_ip;
438 if (NETCONN_IS_TCP(nc) || NETCONN_IS_SSL(nc)) {
439 cs.ext.tcp_ssl.keep_alive = keep_alive;
440 } else {
441 cs.ext.udp.local_port = local_port;
442 cs.ext.udp.mode = mode;
443 }
444 res = lwesp_conn_startex(NULL, &cs, nc, netconn_evt, 1);
445 return res;
446}
447
448/**
449 * \brief Bind a connection to specific port, can be only used for server connections
450 * \param[in] nc: Netconn handle
451 * \param[in] port: Port used to bind a connection to
452 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
453 */
454lwespr_t
455lwesp_netconn_bind(lwesp_netconn_p nc, lwesp_port_t port) {
456 lwespr_t res = lwespOK;
457
458 LWESP_ASSERT("nc != NULL", nc != NULL);
459
460 /*
461 * Protection is not needed as it is expected
462 * that this function is called only from single
463 * thread for single netconn connection,
464 * thus it is considered reentrant
465 */
466
467 nc->listen_port = port;
468
469 return res;
470}
471
472/**
473 * \brief Set timeout value in units of seconds when connection is in listening mode
474 * If new connection is accepted, it will be automatically closed after `seconds` elapsed
475 * without any data exchange.
476 * \note Call this function before you put connection to listen mode with \ref lwesp_netconn_listen
477 * \param[in] nc: Netconn handle used for listen mode
478 * \param[in] timeout: Time in units of seconds. Set to `0` to disable timeout feature
479 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
480 */
481lwespr_t
482lwesp_netconn_set_listen_conn_timeout(lwesp_netconn_p nc, uint16_t timeout) {
483 lwespr_t res = lwespOK;
484 LWESP_ASSERT("nc != NULL", nc != NULL);
485
486 /*
487 * Protection is not needed as it is expected
488 * that this function is called only from single
489 * thread for single netconn connection,
490 * thus it is reentrant in this case
491 */
492
493 nc->conn_timeout = timeout;
494
495 return res;
496}
497
498/**
499 * \brief Listen on previously binded connection
500 * \param[in] nc: Netconn handle used to listen for new connections
501 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
502 */
503lwespr_t
504lwesp_netconn_listen(lwesp_netconn_p nc) {
505 return lwesp_netconn_listen_with_max_conn(nc, LWESP_CFG_MAX_CONNS);
506}
507
508/**
509 * \brief Listen on previously binded connection with max allowed connections at a time
510 * \param[in] nc: Netconn handle used to listen for new connections
511 * \param[in] max_connections: Maximal number of connections server can accept at a time
512 * This parameter may not be larger than \ref LWESP_CFG_MAX_CONNS
513 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
514 */
515lwespr_t
516lwesp_netconn_listen_with_max_conn(lwesp_netconn_p nc, uint16_t max_connections) {
517 lwespr_t res;
518
519 LWESP_ASSERT("nc != NULL", nc != NULL);
520 LWESP_ASSERT("nc->type must be TCP", NETCONN_IS_TCP(nc));
521
522 /* Enable server on port and set default netconn callback */
523 if ((res = lwesp_set_server(1, nc->listen_port,
524 LWESP_U16(LWESP_MIN(max_connections, LWESP_CFG_MAX_CONNS)),
525 nc->conn_timeout, netconn_evt, NULL, NULL, 1)) == lwespOK) {
526 lwesp_core_lock();
527 listen_api = nc; /* Set current main API in listening state */
528 lwesp_core_unlock();
529 }
530 return res;
531}
532
533/**
534 * \brief Accept a new connection
535 * \param[in] nc: Netconn handle used as base connection to accept new clients
536 * \param[out] client: Pointer to netconn handle to save new connection to
537 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
538 */
539lwespr_t
540lwesp_netconn_accept(lwesp_netconn_p nc, lwesp_netconn_p* client) {
541 lwesp_netconn_t* tmp;
542 uint32_t time;
543
544 LWESP_ASSERT("nc != NULL", nc != NULL);
545 LWESP_ASSERT("client != NULL", client != NULL);
546 LWESP_ASSERT("nc->type must be TCP", NETCONN_IS_TCP(nc));
547 LWESP_ASSERT("nc == listen_api", nc == listen_api);
548
549 *client = NULL;
550 time = lwesp_sys_mbox_get(&nc->mbox_accept, (void**)&tmp, 0);
551 if (time == LWESP_SYS_TIMEOUT) {
552 return lwespTIMEOUT;
553 }
554 if ((uint8_t*)tmp == (uint8_t*)&recv_closed) {
555 lwesp_core_lock();
556 listen_api = NULL; /* Disable listening at this point */
557 lwesp_core_unlock();
558 return lwespERRWIFINOTCONNECTED; /* Wifi disconnected */
559 } else if ((uint8_t*)tmp == (uint8_t*)&recv_not_present) {
560 lwesp_core_lock();
561 listen_api = NULL; /* Disable listening at this point */
562 lwesp_core_unlock();
563 return lwespERRNODEVICE; /* Device not present */
564 }
565 *client = tmp; /* Set new pointer */
566 return lwespOK; /* We have a new connection */
567}
568
569/**
570 * \brief Write data to connection output buffers
571 * \note This function may only be used on TCP or SSL connections
572 * \param[in] nc: Netconn handle used to write data to
573 * \param[in] data: Pointer to data to write
574 * \param[in] btw: Number of bytes to write
575 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
576 */
577lwespr_t
578lwesp_netconn_write(lwesp_netconn_p nc, const void* data, size_t btw) {
579 size_t len, sent;
580 const uint8_t* d = data;
581 lwespr_t res;
582
583 LWESP_ASSERT("nc != NULL", nc != NULL);
584 LWESP_ASSERT("nc->type must be TCP or SSL", NETCONN_IS_TCP(nc) || NETCONN_IS_SSL(nc));
585 LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
586
587 /*
588 * Several steps are done in write process
589 *
590 * 1. Check if buffer is set and check if there is something to write to it.
591 * 1. In case buffer will be full after copy, send it and free memory.
592 * 2. Check how many bytes we can write directly without need to copy
593 * 3. Try to allocate a new buffer and copy remaining input data to it
594 * 4. In case buffer allocation fails, send data directly (may have impact on speed and effectivenes)
595 */
596
597 /* Step 1 */
598 if (nc->buff.buff != NULL) { /* Is there a write buffer ready to accept more data? */
599 len = LWESP_MIN(nc->buff.len - nc->buff.ptr, btw); /* Get number of bytes we can write to buffer */
600 if (len > 0) {
601 LWESP_MEMCPY(&nc->buff.buff[nc->buff.ptr], data, len); /* Copy memory to temporary write buffer */
602 d += len;
603 nc->buff.ptr += len;
604 btw -= len;
605 }
606
607 /* Step 1.1 */
608 if (nc->buff.ptr == nc->buff.len) {
609 res = lwesp_conn_send(nc->conn, nc->buff.buff, nc->buff.len, &sent, 1);
610
611 lwesp_mem_free_s((void**)&nc->buff.buff);
612 if (res != lwespOK) {
613 return res;
614 }
615 } else {
616 return lwespOK; /* Buffer is not full yet */
617 }
618 }
619
620 /* Step 2 */
621 if (btw >= LWESP_CFG_CONN_MAX_DATA_LEN) {
622 size_t rem;
623 rem = btw % LWESP_CFG_CONN_MAX_DATA_LEN;/* Get remaining bytes for max data length */
624 res = lwesp_conn_send(nc->conn, d, btw - rem, &sent, 1);/* Write data directly */
625 if (res != lwespOK) {
626 return res;
627 }
628 d += sent; /* Advance in data pointer */
629 btw -= sent; /* Decrease remaining data to send */
630 }
631
632 if (btw == 0) { /* Sent everything? */
633 return lwespOK;
634 }
635
636 /* Step 3 */
637 if (nc->buff.buff == NULL) { /* Check if we should allocate a new buffer */
638 nc->buff.buff = lwesp_mem_malloc(sizeof(*nc->buff.buff) * LWESP_CFG_CONN_MAX_DATA_LEN);
639 nc->buff.len = LWESP_CFG_CONN_MAX_DATA_LEN; /* Save buffer length */
640 nc->buff.ptr = 0; /* Save buffer pointer */
641 }
642
643 /* Step 4 */
644 if (nc->buff.buff != NULL) { /* Memory available? */
645 LWESP_MEMCPY(&nc->buff.buff[nc->buff.ptr], d, btw); /* Copy data to buffer */
646 nc->buff.ptr += btw;
647 } else { /* Still no memory available? */
648 return lwesp_conn_send(nc->conn, data, btw, NULL, 1); /* Simply send directly blocking */
649 }
650 return lwespOK;
651}
652
653/**
654 * \brief Flush buffered data on netconn TCP/SSL connection
655 * \note This function may only be used on TCP/SSL connection
656 * \param[in] nc: Netconn handle to flush data
657 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
658 */
659lwespr_t
660lwesp_netconn_flush(lwesp_netconn_p nc) {
661 LWESP_ASSERT("nc != NULL", nc != NULL);
662 LWESP_ASSERT("nc->type must be TCP or SSL", NETCONN_IS_TCP(nc) || NETCONN_IS_SSL(nc));
663 LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
664
665 /*
666 * In case we have data in write buffer,
667 * flush them out to network
668 */
669 if (nc->buff.buff != NULL) { /* Check remaining data */
670 if (nc->buff.ptr > 0) { /* Do we have data in current buffer? */
671 lwesp_conn_send(nc->conn, nc->buff.buff, nc->buff.ptr, NULL, 1);/* Send data */
672 }
673 lwesp_mem_free_s((void**)&nc->buff.buff);
674 }
675 return lwespOK;
676}
677
678/**
679 * \brief Send data on UDP connection to default IP and port
680 * \param[in] nc: Netconn handle used to send
681 * \param[in] data: Pointer to data to write
682 * \param[in] btw: Number of bytes to write
683 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
684 */
685lwespr_t
686lwesp_netconn_send(lwesp_netconn_p nc, const void* data, size_t btw) {
687 LWESP_ASSERT("nc != NULL", nc != NULL);
688 LWESP_ASSERT("nc->type must be UDP", nc->type == LWESP_NETCONN_TYPE_UDP);
689 LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
690
691 return lwesp_conn_send(nc->conn, data, btw, NULL, 1);
692}
693
694/**
695 * \brief Send data on UDP connection to specific IP and port
696 * \note Use this function in case of UDP type netconn
697 * \param[in] nc: Netconn handle used to send
698 * \param[in] ip: Pointer to IP address
699 * \param[in] port: Port number used to send data
700 * \param[in] data: Pointer to data to write
701 * \param[in] btw: Number of bytes to write
702 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
703 */
704lwespr_t
705lwesp_netconn_sendto(lwesp_netconn_p nc, const lwesp_ip_t* ip, lwesp_port_t port, const void* data, size_t btw) {
706 LWESP_ASSERT("nc != NULL", nc != NULL);
707 LWESP_ASSERT("nc->type must be UDP", nc->type == LWESP_NETCONN_TYPE_UDP);
708 LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
709
710 return lwesp_conn_sendto(nc->conn, ip, port, data, btw, NULL, 1);
711}
712
713/**
714 * \brief Receive data from connection
715 * \param[in] nc: Netconn handle used to receive from
716 * \param[in] pbuf: Pointer to pointer to save new receive buffer to.
717 * When function returns, user must check for valid pbuf value `pbuf != NULL`
718 * \return \ref lwespOK when new data ready
719 * \return \ref lwespCLOSED when connection closed by remote side
720 * \return \ref lwespTIMEOUT when receive timeout occurs
721 * \return Any other member of \ref lwespr_t otherwise
722 */
723lwespr_t
724lwesp_netconn_receive(lwesp_netconn_p nc, lwesp_pbuf_p* pbuf) {
725 LWESP_ASSERT("nc != NULL", nc != NULL);
726 LWESP_ASSERT("pbuf != NULL", pbuf != NULL);
727
728 *pbuf = NULL;
729#if LWESP_CFG_NETCONN_RECEIVE_TIMEOUT
730 /*
731 * Wait for new received data for up to specific timeout
732 * or throw error for timeout notification
733 */
734 if (nc->rcv_timeout == LWESP_NETCONN_RECEIVE_NO_WAIT) {
735 if (!lwesp_sys_mbox_getnow(&nc->mbox_receive, (void**)pbuf)) {
736 return lwespTIMEOUT;
737 }
738 } else if (lwesp_sys_mbox_get(&nc->mbox_receive, (void**)pbuf, nc->rcv_timeout) == LWESP_SYS_TIMEOUT) {
739 return lwespTIMEOUT;
740 }
741#else /* LWESP_CFG_NETCONN_RECEIVE_TIMEOUT */
742 /* Forever wait for new receive packet */
743 lwesp_sys_mbox_get(&nc->mbox_receive, (void**)pbuf, 0);
744#endif /* !LWESP_CFG_NETCONN_RECEIVE_TIMEOUT */
745
746 lwesp_core_lock();
747 if (nc->mbox_receive_entries > 0) {
748 --nc->mbox_receive_entries;
749 }
750 lwesp_core_unlock();
751
752 /* Check if connection closed */
753 if ((uint8_t*)(*pbuf) == (uint8_t*)&recv_closed) {
754 *pbuf = NULL; /* Reset pbuf */
755 return lwespCLOSED;
756 }
757#if LWESP_CFG_CONN_MANUAL_TCP_RECEIVE
758 else {
759 lwesp_core_lock();
760 nc->conn->status.f.receive_blocked = 0; /* Resume reading more data */
761 lwesp_conn_recved(nc->conn, *pbuf); /* Notify stack about received data */
762 lwesp_core_unlock();
763 }
764#endif /* LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */
765 return lwespOK; /* We have data available */
766}
767
768/**
769 * \brief Close a netconn connection
770 * \param[in] nc: Netconn handle to close
771 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
772 */
773lwespr_t
774lwesp_netconn_close(lwesp_netconn_p nc) {
775 lwesp_conn_p conn;
776
777 LWESP_ASSERT("nc != NULL", nc != NULL);
778 LWESP_ASSERT("nc->conn != NULL", nc->conn != NULL);
779 LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
780
781 lwesp_netconn_flush(nc); /* Flush data and ignore result */
782 conn = nc->conn;
783 nc->conn = NULL;
784
785 lwesp_conn_set_arg(conn, NULL); /* Reset argument */
786 lwesp_conn_close(conn, 1); /* Close the connection */
787 flush_mboxes(nc, 1); /* Flush message queues */
788 return lwespOK;
789}
790
791/**
792 * \brief Get connection number used for netconn
793 * \param[in] nc: Netconn handle
794 * \return `-1` on failure, connection number between `0` and \ref LWESP_CFG_MAX_CONNS otherwise
795 */
796int8_t
797lwesp_netconn_get_connnum(lwesp_netconn_p nc) {
798 if (nc != NULL && nc->conn != NULL) {
799 return lwesp_conn_getnum(nc->conn);
800 }
801 return -1;
802}
803
804#if LWESP_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__
805
806/**
807 * \brief Set timeout value for receiving data.
808 *
809 * When enabled, \ref lwesp_netconn_receive will only block for up to
810 * `timeout` value and will return if no new data within this time
811 *
812 * \param[in] nc: Netconn handle
813 * \param[in] timeout: Timeout in units of milliseconds.
814 * Set to `0` to disable timeout feature
815 * Set to `> 0` to set maximum milliseconds to wait before timeout
816 * Set to \ref LWESP_NETCONN_RECEIVE_NO_WAIT to enable non-blocking receive
817 */
818void
819lwesp_netconn_set_receive_timeout(lwesp_netconn_p nc, uint32_t timeout) {
820 nc->rcv_timeout = timeout;
821}
822
823/**
824 * \brief Get netconn receive timeout value
825 * \param[in] nc: Netconn handle
826 * \return Timeout in units of milliseconds.
827 * If value is `0`, timeout is disabled (wait forever)
828 */
829uint32_t
830lwesp_netconn_get_receive_timeout(lwesp_netconn_p nc) {
831 return nc->rcv_timeout;
832}
833
834#endif /* LWESP_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ */
835
836/**
837 * \brief Get netconn connection handle
838 * \param[in] nc: Netconn handle
839 * \return ESP connection handle
840 */
841lwesp_conn_p
842lwesp_netconn_get_conn(lwesp_netconn_p nc) {
843 return nc->conn;
844}
845
846/**
847 * \brief Get netconn connection type
848 * \param[in] nc: Netconn handle
849 * \return ESP connection type
850 */
851lwesp_netconn_type_t
852lwesp_netconn_get_type(lwesp_netconn_p nc) {
853 return nc->type;
854}
855
856#endif /* LWESP_CFG_NETCONN || __DOXYGEN__ */
Connection specific event¶
This events are subset of global event callback. They work exactly the same way as global, but only receive events related to connections.
Tip
Connection related events start with LWESP_EVT_CONN_*
, such as LWESP_EVT_CONN_RECV
.
Check Event management for list of all connection events.
Connection events callback function is set for 2
cases:
Each client (when application starts connection) sets event callback function when trying to connect with
lwesp_conn_start()
functionApplication sets global event callback function when enabling server mode with
lwesp_set_server()
function
1#include "client.h"
2#include "lwesp/lwesp.h"
3
4/* Host parameter */
5#define CONN_HOST "example.com"
6#define CONN_PORT 80
7
8static lwespr_t conn_callback_func(lwesp_evt_t* evt);
9
10/**
11 * \brief Request data for connection
12 */
13static const
14uint8_t req_data[] = ""
15 "GET / HTTP/1.1\r\n"
16 "Host: " CONN_HOST "\r\n"
17 "Connection: close\r\n"
18 "\r\n";
19
20/**
21 * \brief Start a new connection(s) as client
22 */
23void
24client_connect(void) {
25 lwespr_t res;
26
27 /* Start a new connection as client in non-blocking mode */
28 if ((res = lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, "example.com", 80, NULL, conn_callback_func, 0)) == lwespOK) {
29 printf("Connection to " CONN_HOST " started...\r\n");
30 } else {
31 printf("Cannot start connection to " CONN_HOST "!\r\n");
32 }
33
34 /* Start 2 more */
35 lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, CONN_PORT, NULL, conn_callback_func, 0);
36
37 /*
38 * An example of connection which should fail in connecting.
39 * When this is the case, \ref LWESP_EVT_CONN_ERROR event should be triggered
40 * in callback function processing
41 */
42 lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, 10, NULL, conn_callback_func, 0);
43}
44
45/**
46 * \brief Event callback function for connection-only
47 * \param[in] evt: Event information with data
48 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
49 */
50static lwespr_t
51conn_callback_func(lwesp_evt_t* evt) {
52 lwesp_conn_p conn;
53 lwespr_t res;
54 uint8_t conn_num;
55
56 conn = lwesp_conn_get_from_evt(evt); /* Get connection handle from event */
57 if (conn == NULL) {
58 return lwespERR;
59 }
60 conn_num = lwesp_conn_getnum(conn); /* Get connection number for identification */
61 switch (lwesp_evt_get_type(evt)) {
62 case LWESP_EVT_CONN_ACTIVE: { /* Connection just active */
63 printf("Connection %d active!\r\n", (int)conn_num);
64 res = lwesp_conn_send(conn, req_data, sizeof(req_data) - 1, NULL, 0); /* Start sending data in non-blocking mode */
65 if (res == lwespOK) {
66 printf("Sending request data to server...\r\n");
67 } else {
68 printf("Cannot send request data to server. Closing connection manually...\r\n");
69 lwesp_conn_close(conn, 0); /* Close the connection */
70 }
71 break;
72 }
73 case LWESP_EVT_CONN_CLOSE: { /* Connection closed */
74 if (lwesp_evt_conn_close_is_forced(evt)) {
75 printf("Connection %d closed by client!\r\n", (int)conn_num);
76 } else {
77 printf("Connection %d closed by remote side!\r\n", (int)conn_num);
78 }
79 break;
80 }
81 case LWESP_EVT_CONN_SEND: { /* Data send event */
82 lwespr_t res = lwesp_evt_conn_send_get_result(evt);
83 if (res == lwespOK) {
84 printf("Data sent successfully on connection %d...waiting to receive data from remote side...\r\n", (int)conn_num);
85 } else {
86 printf("Error while sending data on connection %d!\r\n", (int)conn_num);
87 }
88 break;
89 }
90 case LWESP_EVT_CONN_RECV: { /* Data received from remote side */
91 lwesp_pbuf_p pbuf = lwesp_evt_conn_recv_get_buff(evt);
92 lwesp_conn_recved(conn, pbuf); /* Notify stack about received pbuf */
93 printf("Received %d bytes on connection %d..\r\n", (int)lwesp_pbuf_length(pbuf, 1), (int)conn_num);
94 break;
95 }
96 case LWESP_EVT_CONN_ERROR: { /* Error connecting to server */
97 const char* host = lwesp_evt_conn_error_get_host(evt);
98 lwesp_port_t port = lwesp_evt_conn_error_get_port(evt);
99 printf("Error connecting to %s:%d\r\n", host, (int)port);
100 break;
101 }
102 default:
103 break;
104 }
105 return lwespOK;
106}
API call event¶
API function call event function is special type of event and is linked to command execution. It is especially useful when dealing with non-blocking commands to understand when specific command execution finished and when next operation could start.
Every API function, which directly operates with AT command on physical device layer,
has optional 2
parameters for API call event:
Callback function, called when command finished
Custom user parameter for callback function
Below is an example code for DNS resolver. It uses custom API callback function with custom argument, used to distinguis domain name (when multiple domains are to be resolved).
1#include "dns.h"
2#include "lwesp/lwesp.h"
3
4/* Host to resolve */
5#define DNS_HOST1 "example.com"
6#define DNS_HOST2 "example.net"
7
8/**
9 * \brief Variable to hold result of DNS resolver
10 */
11static lwesp_ip_t ip;
12
13/**
14 * \brief Function to print actual resolved IP address
15 */
16static void
17prv_print_ip(void) {
18 if (0) {
19#if LWESP_CFG_IPV6
20 } else if (ip.type == LWESP_IPTYPE_V6) {
21 printf("IPv6: %04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X\r\n",
22 (unsigned)ip.addr.ip6.addr[0], (unsigned)ip.addr.ip6.addr[1], (unsigned)ip.addr.ip6.addr[2],
23 (unsigned)ip.addr.ip6.addr[3], (unsigned)ip.addr.ip6.addr[4], (unsigned)ip.addr.ip6.addr[5],
24 (unsigned)ip.addr.ip6.addr[6], (unsigned)ip.addr.ip6.addr[7]);
25#endif /* LWESP_CFG_IPV6 */
26 } else {
27 printf("IPv4: %d.%d.%d.%d\r\n",
28 (int)ip.addr.ip4.addr[0], (int)ip.addr.ip4.addr[1], (int)ip.addr.ip4.addr[2], (int)ip.addr.ip4.addr[3]);
29 }
30}
31
32/**
33 * \brief Event callback function for API call,
34 * called when API command finished with execution
35 */
36static void
37prv_dns_resolve_evt(lwespr_t res, void* arg) {
38 /* Check result of command */
39 if (res == lwespOK) {
40 /* Print actual resolved IP */
41 prv_print_ip();
42 }
43}
44
45/**
46 * \brief Start DNS resolver
47 */
48void
49dns_start(void) {
50 /* Use DNS protocol to get IP address of domain name */
51
52 /* Get IP with non-blocking mode */
53 if (lwesp_dns_gethostbyname(DNS_HOST2, &ip, prv_dns_resolve_evt, DNS_HOST2, 0) == lwespOK) {
54 printf("Request for DNS record for " DNS_HOST2 " has started\r\n");
55 } else {
56 printf("Could not start command for DNS\r\n");
57 }
58
59 /* Get IP with blocking mode */
60 if (lwesp_dns_gethostbyname(DNS_HOST1, &ip, prv_dns_resolve_evt, DNS_HOST1, 1) == lwespOK) {
61 /* Print actual resolved IP */
62 prv_print_ip();
63 } else {
64 printf("Could not retrieve IP address for " DNS_HOST1 "\r\n");
65 }
66}
Blocking or non-blocking API calls¶
API functions often allow application to set blocking
parameter indicating if function shall be blocking or non-blocking.
Blocking mode¶
When the function is called in blocking mode blocking = 1
, application thread gets suspended until response from ESP device is received.
If there is a queue of multiple commands, thread may wait a while before receiving data.
When API function returns, application has valid response data and can react immediately.
Linear programming model may be used
Application may use multiple threads for real-time execution to prevent system stalling when running function call
Warning
Due to internal architecture, it is not allowed to call API functions in blocking mode from events or callbacks. Any attempt to do so will result in function returning error.
Example code:
1char hostname[20];
2
3/* Somewhere in thread function */
4
5/* Get device hostname in blocking mode */
6/* Function returns actual result */
7if (lwesp_hostname_get(hostname, sizeof(hostname), NULL, NULL, 1 /* 1 means blocking call */) == lwespOK) {
8 /* At this point we have valid result and parameters from API function */
9 printf("ESP hostname is %s\r\n", hostname);
10} else {
11 printf("Error reading ESP hostname..\r\n");
12}
Non-blocking mode¶
If the API function is called in non-blocking mode, function will return immediately with status indicating if command request has been successfully sent to internal command queue. Response has to be processed in event callback function.
Warning
Due to internal architecture, it is only allowed to call API functions in non-blocking mode from events or callbacks. Any attempt not to do so will result in function returning error.
Example code:
1char hostname[20];
2
3/* Hostname event function, called when lwesp_hostname_get() function finishes */
4void
5hostname_fn(lwespr_t res, void* arg) {
6 /* Check actual result from device */
7 if (res == lwespOK) {
8 printf("ESP hostname is %s\r\n", hostname);
9 } else {
10 printf("Error reading ESP hostname...\r\n");
11 }
12}
13
14/* Somewhere in thread and/or other ESP event function */
15
16/* Get device hostname in non-blocking mode */
17/* Function now returns if command has been sent to internal message queue */
18if (lwesp_hostname_get(hostname, sizeof(hostname), hostname_fn, NULL, 0 /* 0 means non-blocking call */) == lwespOK) {
19 /* At this point application knows that command has been sent to queue */
20 /* But it does not have yet valid data in "hostname" variable */
21 printf("ESP hostname get command sent to queue.\r\n");
22} else {
23 /* Error writing message to queue */
24 printf("Cannot send hostname get command to queue.\r\n");
25}
Warning
When using non-blocking API calls, do not use local variables as parameter. This may introduce undefined behavior and memory corruption if application function returns before command is executed.
Example of a bad code:
1char hostname[20];
2
3/* Hostname event function, called when lwesp_hostname_get() function finishes */
4void
5hostname_fn(lwespr_t res, void* arg) {
6 /* Check actual result from device */
7 if (res == lwespOK) {
8 printf("ESP hostname is %s\r\n", hostname);
9 } else {
10 printf("Error reading ESP hostname...\r\n");
11 }
12}
13
14/* Check hostname */
15void
16check_hostname(void) {
17 char hostname[20];
18
19 /* Somewhere in thread and/or other ESP event function */
20
21 /* Get device hostname in non-blocking mode */
22 /* Function now returns if command has been sent to internal message queue */
23 /* Function will use local "hostname" variable and will write to undefined memory */
24 if (lwesp_hostname_get(hostname, sizeof(hostname), hostname_fn, NULL, 0 /* 0 means non-blocking call */) == lwespOK) {
25 /* At this point application knows that command has been sent to queue */
26 /* But it does not have yet valid data in "hostname" variable */
27 printf("ESP hostname get command sent to queue.\r\n");
28 } else {
29 /* Error writing message to queue */
30 printf("Cannot send hostname get command to queue.\r\n");
31 }
32}
Porting guide¶
High level of ESP-AT library is platform independent, written in ANSI C99, however there is an important part where middleware needs to communicate with target ESP device and it must work under different optional operating systems selected by final customer.
Porting consists of:
Implementation of low-level part, for actual communication between host device and ESP device
Implementation of system functions, link between target operating system and middleware functions
Assignment of memory for allocation manager
Implement low-level driver¶
To successfully prepare all parts of low-level driver, application must take care of:
Implementing
lwesp_ll_init()
andlwesp_ll_deinit()
callback functionsImplement and assign send data and optional hardware reset function callbacks
Assign memory for allocation manager when using default allocator or use custom allocator
Process received data from ESP device and send it to input module for further processing
Tip
Port examples are available for STM32 and WIN32 architectures. Both actual working and up-to-date implementations are available within the library.
Note
Check Input module for more information about direct & indirect input processing.
Implement system functions¶
System functions are bridge between operating system calls and ESP middleware. ESP library relies on stable operating system features and its implementation and does not require any special features which do not normally come with operating systems.
Operating system must support:
Thread management functions
Mutex management functions
Binary semaphores only, no need for counting semaphores
Message queue management functions
Warning
If any of the features are not available within targeted operating system, customer needs to resolve it with care. As an example, message queue is not available in WIN32 OS API therefore custom message queue has been implemented using binary semaphores
Application needs to implement all system call functions, starting with lwesp_sys_
.
It must also prepare header file for standard types in order to support OS types within ESP middleware.
An example code is provided latter section of this page for WIN32 and STM32.
Steps to follow¶
Copy
lwesp/src/system/lwesp_sys_template.c
to the same folder and rename it to application port, eg.lwesp_sys_win32.c
Open newly created file and implement all system functions
Copy folder
lwesp/src/include/system/port/template/*
to the same folder and rename folder name to application port, eg.cmsis_os
Open
lwesp_sys_port.h
file from newly created folder and implement all typedefs and macros for specific targetAdd source file to compiler sources and add path to header file to include paths in compiler options
Note
Check System functions for function prototypes.
Example: Low-level driver for WIN32¶
Example code for low-level porting on WIN32 platform. It uses native Windows features to open COM port and read/write from/to it.
Notes:
It uses separate thread for received data processing. It uses
lwesp_input_process()
orlwesp_input()
functions, based on application configuration ofLWESP_CFG_INPUT_USE_PROCESS
parameter.When
LWESP_CFG_INPUT_USE_PROCESS
is disabled, dedicated receive buffer is created by ESP-AT library andlwesp_input()
function just writes data to it and does not process received characters immediately. This is handled by Processing thread at later stage instead.When
LWESP_CFG_INPUT_USE_PROCESS
is enabled,lwesp_input_process()
is used, which directly processes input data and sends potential callback/event functions to application layer.
Memory manager has been assigned to
1
region ofLWESP_MEM_SIZE
sizeIt sets send and reset callback functions for ESP-AT library
1/**
2 * \file lwesp_ll_win32.c
3 * \brief Low-level communication with ESP device for WIN32
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#include "system/lwesp_ll.h"
35#include "lwesp/lwesp.h"
36#include "lwesp/lwesp_mem.h"
37#include "lwesp/lwesp_input.h"
38
39#if !__DOXYGEN__
40
41volatile uint8_t lwesp_ll_win32_driver_ignore_data;
42static uint8_t initialized = 0;
43static HANDLE thread_handle;
44static volatile HANDLE com_port; /*!< COM port handle */
45static uint8_t data_buffer[0x1000]; /*!< Received data array */
46
47static void uart_thread(void* param);
48
49/**
50 * \brief Send data to ESP device, function called from ESP stack when we have data to send
51 */
52static size_t
53send_data(const void* data, size_t len) {
54 DWORD written;
55 if (com_port != NULL) {
56#if !LWESP_CFG_AT_ECHO
57 const uint8_t* d = data;
58 HANDLE hConsole;
59
60 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
61 SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
62 for (DWORD i = 0; i < len; ++i) {
63 printf("%c", d[i]);
64 }
65 SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
66#endif /* !LWESP_CFG_AT_ECHO */
67
68 WriteFile(com_port, data, len, &written, NULL);
69 FlushFileBuffers(com_port);
70 return written;
71 }
72 return 0;
73}
74
75/**
76 * \brief Configure UART (USB to UART)
77 */
78static uint8_t
79configure_uart(uint32_t baudrate) {
80 DCB dcb = { 0 };
81 dcb.DCBlength = sizeof(dcb);
82 size_t i;
83
84 /* List of COM ports to probe */
85 static const char* com_port_names[] = {
86 "\\\\.\\COM16",
87 "\\\\.\\COM4"
88 };
89
90 /* TODO: Needs proper work to run for loop only if not initialized */
91
92 for (i = 0; i < LWESP_ARRAYSIZE(com_port_names); ++i) {
93 /*
94 * On first call,
95 * create virtual file on selected COM port and open it
96 * as generic read and write
97 */
98 if (!initialized) {
99 printf("Probing COM port %s\r\n", com_port_names[i]);
100 com_port = CreateFileA(com_port_names[i], GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
101 }
102
103 /* Configure COM port parameters */
104 if (GetCommState(com_port, &dcb)) {
105 COMMTIMEOUTS timeouts;
106
107 dcb.BaudRate = baudrate;
108 dcb.ByteSize = 8;
109 dcb.Parity = NOPARITY;
110 dcb.StopBits = ONESTOPBIT;
111
112 if (!SetCommState(com_port, &dcb)) {
113 printf("Cannot set COM PORT info for port: %s\r\n", com_port_names[i]);
114 continue;
115 }
116 if (GetCommTimeouts(com_port, &timeouts)) {
117 /* Set timeout to return immediately from ReadFile function */
118 timeouts.ReadIntervalTimeout = MAXDWORD;
119 timeouts.ReadTotalTimeoutConstant = 0;
120 timeouts.ReadTotalTimeoutMultiplier = 0;
121 if (!SetCommTimeouts(com_port, &timeouts)) {
122 printf("Cannot set COM PORT timeouts: %s\r\n", com_port_names[i]);
123 }
124 GetCommTimeouts(com_port, &timeouts);
125 break;
126 } else {
127 printf("Cannot get COM PORT timeouts: %s\r\n", com_port_names[i]);
128 }
129 } else {
130 printf("Cannot get COM PORT info: %s\r\n", com_port_names[i]);
131 }
132 }
133 if (i == LWESP_ARRAYSIZE(com_port_names)) {
134 printf("Failed to open any COM port\r\n");
135 return 0;
136 }
137
138 /* On first function call, create a thread to read data from COM port */
139 if (!initialized) {
140 lwesp_sys_thread_create(&thread_handle, "lwesp_ll_thread", uart_thread, NULL, 0, 0);
141 }
142 return 1;
143}
144
145/**
146 * \brief UART thread
147 */
148static void
149uart_thread(void* param) {
150 DWORD bytes_read;
151 lwesp_sys_sem_t sem;
152 FILE* file = NULL;
153
154 lwesp_sys_sem_create(&sem, 0); /* Create semaphore for delay functions */
155
156 while (com_port == NULL) {
157 lwesp_sys_sem_wait(&sem, 1); /* Add some delay with yield */
158 }
159
160 fopen_s(&file, "log_file.txt", "w+"); /* Open debug file in write mode */
161 while (1) {
162 /*
163 * Try to read data from COM port
164 * and send it to upper layer for processing
165 */
166 do {
167 ReadFile(com_port, data_buffer, sizeof(data_buffer), &bytes_read, NULL);
168 if (bytes_read > 0) {
169 HANDLE hConsole;
170 hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
171 SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
172 for (DWORD i = 0; i < bytes_read; ++i) {
173 printf("%c", data_buffer[i]);
174 }
175 SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
176
177 if (lwesp_ll_win32_driver_ignore_data) {
178 printf("IGNORING..\r\n");
179 continue;
180 }
181
182 /* Send received data to input processing module */
183#if LWESP_CFG_INPUT_USE_PROCESS
184 lwesp_input_process(data_buffer, (size_t)bytes_read);
185#else /* LWESP_CFG_INPUT_USE_PROCESS */
186 lwesp_input(data_buffer, (size_t)bytes_read);
187#endif /* !LWESP_CFG_INPUT_USE_PROCESS */
188
189 /* Write received data to output debug file */
190 if (file != NULL) {
191 fwrite(data_buffer, 1, bytes_read, file);
192 fflush(file);
193 }
194 }
195 } while (bytes_read == (DWORD)sizeof(data_buffer));
196
197 /* Implement delay to allow other tasks processing */
198 lwesp_sys_sem_wait(&sem, 1);
199 }
200}
201
202/**
203 * \brief Reset device GPIO management
204 */
205static uint8_t
206reset_device(uint8_t state) {
207 return 0; /* Hardware reset was not successful */
208}
209
210/**
211 * \brief Callback function called from initialization process
212 */
213lwespr_t
214lwesp_ll_init(lwesp_ll_t* ll) {
215#if !LWESP_CFG_MEM_CUSTOM
216 /* Step 1: Configure memory for dynamic allocations */
217 static uint8_t memory[0x10000]; /* Create memory for dynamic allocations with specific size */
218
219 /*
220 * Create memory region(s) of memory.
221 * If device has internal/external memory available,
222 * multiple memories may be used
223 */
224 lwesp_mem_region_t mem_regions[] = {
225 { memory, sizeof(memory) }
226 };
227 if (!initialized) {
228 lwesp_mem_assignmemory(mem_regions, LWESP_ARRAYSIZE(mem_regions)); /* Assign memory for allocations to ESP library */
229 }
230#endif /* !LWESP_CFG_MEM_CUSTOM */
231
232 /* Step 2: Set AT port send function to use when we have data to transmit */
233 if (!initialized) {
234 ll->send_fn = send_data; /* Set callback function to send data */
235 ll->reset_fn = reset_device;
236 }
237
238 /* Step 3: Configure AT port to be able to send/receive data to/from ESP device */
239 if (!configure_uart(ll->uart.baudrate)) { /* Initialize UART for communication */
240 return lwespERR;
241 }
242 initialized = 1;
243 return lwespOK;
244}
245
246/**
247 * \brief Callback function to de-init low-level communication part
248 */
249lwespr_t
250lwesp_ll_deinit(lwesp_ll_t* ll) {
251 if (thread_handle != NULL) {
252 lwesp_sys_thread_terminate(&thread_handle);
253 thread_handle = NULL;
254 }
255 initialized = 0; /* Clear initialized flag */
256 return lwespOK;
257}
258
259#endif /* !__DOXYGEN__ */
Example: Low-level driver for STM32¶
Example code for low-level porting on STM32 platform. It uses CMSIS-OS based application layer functions for implementing threads & other OS dependent features.
Notes:
It uses separate thread for received data processing. It uses
lwesp_input_process()
function to directly process received data without using intermediate receive bufferMemory manager has been assigned to
1
region ofLWESP_MEM_SIZE
sizeIt sets send and reset callback functions for ESP-AT library
1/**
2 * \file lwesp_ll_stm32.c
3 * \brief Generic STM32 driver, included in various STM32 driver variants
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34
35/*
36 * How it works
37 *
38 * On first call to \ref lwesp_ll_init, new thread is created and processed in usart_ll_thread function.
39 * USART is configured in RX DMA mode and any incoming bytes are processed inside thread function.
40 * DMA and USART implement interrupt handlers to notify main thread about new data ready to send to upper layer.
41 *
42 * More about UART + RX DMA: https://github.com/MaJerle/stm32-usart-dma-rx-tx
43 *
44 * \ref LWESP_CFG_INPUT_USE_PROCESS must be enabled in `lwesp_config.h` to use this driver.
45 */
46#include "lwesp/lwesp.h"
47#include "lwesp/lwesp_mem.h"
48#include "lwesp/lwesp_input.h"
49#include "system/lwesp_ll.h"
50
51#if !__DOXYGEN__
52
53#if !LWESP_CFG_INPUT_USE_PROCESS
54#error "LWESP_CFG_INPUT_USE_PROCESS must be enabled in `lwesp_config.h` to use this driver."
55#endif /* LWESP_CFG_INPUT_USE_PROCESS */
56
57#if !defined(LWESP_USART_DMA_RX_BUFF_SIZE)
58#define LWESP_USART_DMA_RX_BUFF_SIZE 0x1000
59#endif /* !defined(LWESP_USART_DMA_RX_BUFF_SIZE) */
60
61#if !defined(LWESP_MEM_SIZE)
62#define LWESP_MEM_SIZE 0x1000
63#endif /* !defined(LWESP_MEM_SIZE) */
64
65#if !defined(LWESP_USART_RDR_NAME)
66#define LWESP_USART_RDR_NAME RDR
67#endif /* !defined(LWESP_USART_RDR_NAME) */
68
69/* USART memory */
70static uint8_t usart_mem[LWESP_USART_DMA_RX_BUFF_SIZE];
71static uint8_t is_running, initialized;
72static size_t old_pos;
73
74/* USART thread */
75static void usart_ll_thread(void* arg);
76static osThreadId_t usart_ll_thread_id;
77
78/* Message queue */
79static osMessageQueueId_t usart_ll_mbox_id;
80
81/**
82 * \brief USART data processing
83 */
84static void
85usart_ll_thread(void* arg) {
86 size_t pos;
87
88 LWESP_UNUSED(arg);
89
90 while (1) {
91 void* d;
92 /* Wait for the event message from DMA or USART */
93 osMessageQueueGet(usart_ll_mbox_id, &d, NULL, osWaitForever);
94
95 /* Read data */
96#if defined(LWESP_USART_DMA_RX_STREAM)
97 pos = sizeof(usart_mem) - LL_DMA_GetDataLength(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
98#else
99 pos = sizeof(usart_mem) - LL_DMA_GetDataLength(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
100#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
101 if (pos != old_pos && is_running) {
102 if (pos > old_pos) {
103 lwesp_input_process(&usart_mem[old_pos], pos - old_pos);
104 } else {
105 lwesp_input_process(&usart_mem[old_pos], sizeof(usart_mem) - old_pos);
106 if (pos > 0) {
107 lwesp_input_process(&usart_mem[0], pos);
108 }
109 }
110 old_pos = pos;
111 if (old_pos == sizeof(usart_mem)) {
112 old_pos = 0;
113 }
114 }
115 }
116}
117
118/**
119 * \brief Configure UART using DMA for receive in double buffer mode and IDLE line detection
120 */
121static void
122configure_uart(uint32_t baudrate) {
123 static LL_USART_InitTypeDef usart_init;
124 static LL_DMA_InitTypeDef dma_init;
125 LL_GPIO_InitTypeDef gpio_init;
126
127 if (!initialized) {
128 /* Enable peripheral clocks */
129 LWESP_USART_CLK;
130 LWESP_USART_DMA_CLK;
131 LWESP_USART_TX_PORT_CLK;
132 LWESP_USART_RX_PORT_CLK;
133
134#if defined(LWESP_RESET_PIN)
135 LWESP_RESET_PORT_CLK;
136#endif /* defined(LWESP_RESET_PIN) */
137
138#if defined(LWESP_GPIO0_PIN)
139 LWESP_GPIO0_PORT_CLK;
140#endif /* defined(LWESP_GPIO0_PIN) */
141
142#if defined(LWESP_GPIO2_PIN)
143 LWESP_GPIO2_PORT_CLK;
144#endif /* defined(LWESP_GPIO2_PIN) */
145
146#if defined(LWESP_CH_PD_PIN)
147 LWESP_CH_PD_PORT_CLK;
148#endif /* defined(LWESP_CH_PD_PIN) */
149
150 /* Global pin configuration */
151 LL_GPIO_StructInit(&gpio_init);
152 gpio_init.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
153 gpio_init.Pull = LL_GPIO_PULL_UP;
154 gpio_init.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
155 gpio_init.Mode = LL_GPIO_MODE_OUTPUT;
156
157#if defined(LWESP_RESET_PIN)
158 /* Configure RESET pin */
159 gpio_init.Pin = LWESP_RESET_PIN;
160 LL_GPIO_Init(LWESP_RESET_PORT, &gpio_init);
161#endif /* defined(LWESP_RESET_PIN) */
162
163#if defined(LWESP_GPIO0_PIN)
164 /* Configure GPIO0 pin */
165 gpio_init.Pin = LWESP_GPIO0_PIN;
166 LL_GPIO_Init(LWESP_GPIO0_PORT, &gpio_init);
167 LL_GPIO_SetOutputPin(LWESP_GPIO0_PORT, LWESP_GPIO0_PIN);
168#endif /* defined(LWESP_GPIO0_PIN) */
169
170#if defined(LWESP_GPIO2_PIN)
171 /* Configure GPIO2 pin */
172 gpio_init.Pin = LWESP_GPIO2_PIN;
173 LL_GPIO_Init(LWESP_GPIO2_PORT, &gpio_init);
174 LL_GPIO_SetOutputPin(LWESP_GPIO2_PORT, LWESP_GPIO2_PIN);
175#endif /* defined(LWESP_GPIO2_PIN) */
176
177#if defined(LWESP_CH_PD_PIN)
178 /* Configure CH_PD pin */
179 gpio_init.Pin = LWESP_CH_PD_PIN;
180 LL_GPIO_Init(LWESP_CH_PD_PORT, &gpio_init);
181 LL_GPIO_SetOutputPin(LWESP_CH_PD_PORT, LWESP_CH_PD_PIN);
182#endif /* defined(LWESP_CH_PD_PIN) */
183
184 /* Configure USART pins */
185 gpio_init.Mode = LL_GPIO_MODE_ALTERNATE;
186
187 /* TX PIN */
188 gpio_init.Alternate = LWESP_USART_TX_PIN_AF;
189 gpio_init.Pin = LWESP_USART_TX_PIN;
190 LL_GPIO_Init(LWESP_USART_TX_PORT, &gpio_init);
191
192 /* RX PIN */
193 gpio_init.Alternate = LWESP_USART_RX_PIN_AF;
194 gpio_init.Pin = LWESP_USART_RX_PIN;
195 LL_GPIO_Init(LWESP_USART_RX_PORT, &gpio_init);
196
197 /* Configure UART */
198 LL_USART_DeInit(LWESP_USART);
199 LL_USART_StructInit(&usart_init);
200 usart_init.BaudRate = baudrate;
201 usart_init.DataWidth = LL_USART_DATAWIDTH_8B;
202 usart_init.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
203 usart_init.OverSampling = LL_USART_OVERSAMPLING_16;
204 usart_init.Parity = LL_USART_PARITY_NONE;
205 usart_init.StopBits = LL_USART_STOPBITS_1;
206 usart_init.TransferDirection = LL_USART_DIRECTION_TX_RX;
207 LL_USART_Init(LWESP_USART, &usart_init);
208
209 /* Enable USART interrupts and DMA request */
210 LL_USART_EnableIT_IDLE(LWESP_USART);
211 LL_USART_EnableIT_PE(LWESP_USART);
212 LL_USART_EnableIT_ERROR(LWESP_USART);
213 LL_USART_EnableDMAReq_RX(LWESP_USART);
214
215 /* Enable USART interrupts */
216 NVIC_SetPriority(LWESP_USART_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00));
217 NVIC_EnableIRQ(LWESP_USART_IRQ);
218
219 /* Configure DMA */
220 is_running = 0;
221#if defined(LWESP_USART_DMA_RX_STREAM)
222 LL_DMA_DeInit(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
223 dma_init.Channel = LWESP_USART_DMA_RX_CH;
224#else
225 LL_DMA_DeInit(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
226 dma_init.PeriphRequest = LWESP_USART_DMA_RX_REQ_NUM;
227#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
228 dma_init.PeriphOrM2MSrcAddress = (uint32_t)&LWESP_USART->LWESP_USART_RDR_NAME;
229 dma_init.MemoryOrM2MDstAddress = (uint32_t)usart_mem;
230 dma_init.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
231 dma_init.Mode = LL_DMA_MODE_CIRCULAR;
232 dma_init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
233 dma_init.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
234 dma_init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
235 dma_init.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
236 dma_init.NbData = sizeof(usart_mem);
237 dma_init.Priority = LL_DMA_PRIORITY_MEDIUM;
238#if defined(LWESP_USART_DMA_RX_STREAM)
239 LL_DMA_Init(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM, &dma_init);
240#else
241 LL_DMA_Init(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH, &dma_init);
242#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
243
244 /* Enable DMA interrupts */
245#if defined(LWESP_USART_DMA_RX_STREAM)
246 LL_DMA_EnableIT_HT(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
247 LL_DMA_EnableIT_TC(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
248 LL_DMA_EnableIT_TE(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
249 LL_DMA_EnableIT_FE(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
250 LL_DMA_EnableIT_DME(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
251#else
252 LL_DMA_EnableIT_HT(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
253 LL_DMA_EnableIT_TC(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
254 LL_DMA_EnableIT_TE(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
255#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
256
257 /* Enable DMA interrupts */
258 NVIC_SetPriority(LWESP_USART_DMA_RX_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00));
259 NVIC_EnableIRQ(LWESP_USART_DMA_RX_IRQ);
260
261 old_pos = 0;
262 is_running = 1;
263
264 /* Start DMA and USART */
265#if defined(LWESP_USART_DMA_RX_STREAM)
266 LL_DMA_EnableStream(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
267#else
268 LL_DMA_EnableChannel(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
269#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
270 LL_USART_Enable(LWESP_USART);
271 } else {
272 osDelay(10);
273 LL_USART_Disable(LWESP_USART);
274 usart_init.BaudRate = baudrate;
275 LL_USART_Init(LWESP_USART, &usart_init);
276 LL_USART_Enable(LWESP_USART);
277 }
278
279 /* Create mbox and start thread */
280 if (usart_ll_mbox_id == NULL) {
281 usart_ll_mbox_id = osMessageQueueNew(10, sizeof(void*), NULL);
282 }
283 if (usart_ll_thread_id == NULL) {
284 const osThreadAttr_t attr = {
285 .stack_size = 1024
286 };
287 usart_ll_thread_id = osThreadNew(usart_ll_thread, usart_ll_mbox_id, &attr);
288 }
289}
290
291#if defined(LWESP_RESET_PIN)
292/**
293 * \brief Hardware reset callback
294 */
295static uint8_t
296reset_device(uint8_t state) {
297 if (state) { /* Activate reset line */
298 LL_GPIO_ResetOutputPin(LWESP_RESET_PORT, LWESP_RESET_PIN);
299 } else {
300 LL_GPIO_SetOutputPin(LWESP_RESET_PORT, LWESP_RESET_PIN);
301 }
302 return 1;
303}
304#endif /* defined(LWESP_RESET_PIN) */
305
306/**
307 * \brief Send data to ESP device
308 * \param[in] data: Pointer to data to send
309 * \param[in] len: Number of bytes to send
310 * \return Number of bytes sent
311 */
312static size_t
313send_data(const void* data, size_t len) {
314 const uint8_t* d = data;
315
316 for (size_t i = 0; i < len; ++i, ++d) {
317 LL_USART_TransmitData8(LWESP_USART, *d);
318 while (!LL_USART_IsActiveFlag_TXE(LWESP_USART)) {}
319 }
320 return len;
321}
322
323/**
324 * \brief Callback function called from initialization process
325 */
326lwespr_t
327lwesp_ll_init(lwesp_ll_t* ll) {
328#if !LWESP_CFG_MEM_CUSTOM
329 static uint8_t memory[LWESP_MEM_SIZE];
330 lwesp_mem_region_t mem_regions[] = {
331 { memory, sizeof(memory) }
332 };
333
334 if (!initialized) {
335 lwesp_mem_assignmemory(mem_regions, LWESP_ARRAYSIZE(mem_regions)); /* Assign memory for allocations */
336 }
337#endif /* !LWESP_CFG_MEM_CUSTOM */
338
339 if (!initialized) {
340 ll->send_fn = send_data; /* Set callback function to send data */
341#if defined(LWESP_RESET_PIN)
342 ll->reset_fn = reset_device; /* Set callback for hardware reset */
343#endif /* defined(LWESP_RESET_PIN) */
344 }
345
346 configure_uart(ll->uart.baudrate); /* Initialize UART for communication */
347 initialized = 1;
348 return lwespOK;
349}
350
351/**
352 * \brief Callback function to de-init low-level communication part
353 */
354lwespr_t
355lwesp_ll_deinit(lwesp_ll_t* ll) {
356 if (usart_ll_mbox_id != NULL) {
357 osMessageQueueId_t tmp = usart_ll_mbox_id;
358 usart_ll_mbox_id = NULL;
359 osMessageQueueDelete(tmp);
360 }
361 if (usart_ll_thread_id != NULL) {
362 osThreadId_t tmp = usart_ll_thread_id;
363 usart_ll_thread_id = NULL;
364 osThreadTerminate(tmp);
365 }
366 initialized = 0;
367 LWESP_UNUSED(ll);
368 return lwespOK;
369}
370
371/**
372 * \brief UART global interrupt handler
373 */
374void
375LWESP_USART_IRQHANDLER(void) {
376 LL_USART_ClearFlag_IDLE(LWESP_USART);
377 LL_USART_ClearFlag_PE(LWESP_USART);
378 LL_USART_ClearFlag_FE(LWESP_USART);
379 LL_USART_ClearFlag_ORE(LWESP_USART);
380 LL_USART_ClearFlag_NE(LWESP_USART);
381
382 if (usart_ll_mbox_id != NULL) {
383 void* d = (void*)1;
384 osMessageQueuePut(usart_ll_mbox_id, &d, 0, 0);
385 }
386}
387
388/**
389 * \brief UART DMA stream/channel handler
390 */
391void
392LWESP_USART_DMA_RX_IRQHANDLER(void) {
393 LWESP_USART_DMA_RX_CLEAR_TC;
394 LWESP_USART_DMA_RX_CLEAR_HT;
395
396 if (usart_ll_mbox_id != NULL) {
397 void* d = (void*)1;
398 osMessageQueuePut(usart_ll_mbox_id, &d, 0, 0);
399 }
400}
401
402#endif /* !__DOXYGEN__ */
Example: System functions for WIN32¶
1/**
2 * \file lwesp_sys_port.h
3 * \brief WIN32 based system file implementation
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#ifndef LWESP_HDR_SYSTEM_PORT_H
35#define LWESP_HDR_SYSTEM_PORT_H
36
37#include <stdint.h>
38#include <stdlib.h>
39#include "lwesp/lwesp_opt.h"
40#include "windows.h"
41
42#ifdef __cplusplus
43extern "C" {
44#endif /* __cplusplus */
45
46#if LWESP_CFG_OS && !__DOXYGEN__
47
48typedef HANDLE lwesp_sys_mutex_t;
49typedef HANDLE lwesp_sys_sem_t;
50typedef HANDLE lwesp_sys_mbox_t;
51typedef HANDLE lwesp_sys_thread_t;
52typedef int lwesp_sys_thread_prio_t;
53
54#define LWESP_SYS_MBOX_NULL ((HANDLE)0)
55#define LWESP_SYS_SEM_NULL ((HANDLE)0)
56#define LWESP_SYS_MUTEX_NULL ((HANDLE)0)
57#define LWESP_SYS_TIMEOUT (INFINITE)
58#define LWESP_SYS_THREAD_PRIO (0)
59#define LWESP_SYS_THREAD_SS (1024)
60
61#endif /* LWESP_CFG_OS && !__DOXYGEN__ */
62
63#ifdef __cplusplus
64}
65#endif /* __cplusplus */
66
67#endif /* LWESP_HDR_SYSTEM_PORT_H */
1/**
2 * \file lwesp_sys_win32.c
3 * \brief System dependant functions for WIN32
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#include <string.h>
35#include <stdlib.h>
36#include "system/lwesp_sys.h"
37#include "windows.h"
38
39#if !__DOXYGEN__
40
41/**
42 * \brief Custom message queue implementation for WIN32
43 */
44typedef struct {
45 lwesp_sys_sem_t sem_not_empty; /*!< Semaphore indicates not empty */
46 lwesp_sys_sem_t sem_not_full; /*!< Semaphore indicates not full */
47 lwesp_sys_sem_t sem; /*!< Semaphore to lock access */
48 size_t in, out, size;
49 void* entries[1];
50} win32_mbox_t;
51
52static LARGE_INTEGER freq, sys_start_time;
53static lwesp_sys_mutex_t sys_mutex; /* Mutex ID for main protection */
54
55/**
56 * \brief Check if message box is full
57 * \param[in] m: Message box handle
58 * \return 1 if full, 0 otherwise
59 */
60static uint8_t
61mbox_is_full(win32_mbox_t* m) {
62 size_t size = 0;
63 if (m->in > m->out) {
64 size = (m->in - m->out);
65 } else if (m->out > m->in) {
66 size = m->size - m->out + m->in;
67 }
68 return size == m->size - 1;
69}
70
71/**
72 * \brief Check if message box is empty
73 * \param[in] m: Message box handle
74 * \return 1 if empty, 0 otherwise
75 */
76static uint8_t
77mbox_is_empty(win32_mbox_t* m) {
78 return m->in == m->out;
79}
80
81/**
82 * \brief Get current kernel time in units of milliseconds
83 */
84static uint32_t
85osKernelSysTick(void) {
86 LONGLONG ret;
87 LARGE_INTEGER now;
88
89 QueryPerformanceFrequency(&freq); /* Get frequency */
90 QueryPerformanceCounter(&now); /* Get current time */
91 ret = now.QuadPart - sys_start_time.QuadPart;
92 return (uint32_t)(((ret) * 1000) / freq.QuadPart);
93}
94
95uint8_t
96lwesp_sys_init(void) {
97 QueryPerformanceFrequency(&freq);
98 QueryPerformanceCounter(&sys_start_time);
99
100 lwesp_sys_mutex_create(&sys_mutex);
101 return 1;
102}
103
104uint32_t
105lwesp_sys_now(void) {
106 return osKernelSysTick();
107}
108
109#if LWESP_CFG_OS
110uint8_t
111lwesp_sys_protect(void) {
112 lwesp_sys_mutex_lock(&sys_mutex);
113 return 1;
114}
115
116uint8_t
117lwesp_sys_unprotect(void) {
118 lwesp_sys_mutex_unlock(&sys_mutex);
119 return 1;
120}
121
122uint8_t
123lwesp_sys_mutex_create(lwesp_sys_mutex_t* p) {
124 *p = CreateMutex(NULL, FALSE, NULL);
125 return *p != NULL;
126}
127
128uint8_t
129lwesp_sys_mutex_delete(lwesp_sys_mutex_t* p) {
130 return CloseHandle(*p);
131}
132
133uint8_t
134lwesp_sys_mutex_lock(lwesp_sys_mutex_t* p) {
135 DWORD ret;
136 ret = WaitForSingleObject(*p, INFINITE);
137 if (ret != WAIT_OBJECT_0) {
138 return 0;
139 }
140 return 1;
141}
142
143uint8_t
144lwesp_sys_mutex_unlock(lwesp_sys_mutex_t* p) {
145 return ReleaseMutex(*p);
146}
147
148uint8_t
149lwesp_sys_mutex_isvalid(lwesp_sys_mutex_t* p) {
150 return p != NULL && *p != NULL;
151}
152
153uint8_t
154lwesp_sys_mutex_invalid(lwesp_sys_mutex_t* p) {
155 *p = LWESP_SYS_MUTEX_NULL;
156 return 1;
157}
158
159uint8_t
160lwesp_sys_sem_create(lwesp_sys_sem_t* p, uint8_t cnt) {
161 HANDLE h;
162 h = CreateSemaphore(NULL, !!cnt, 1, NULL);
163 *p = h;
164 return *p != NULL;
165}
166
167uint8_t
168lwesp_sys_sem_delete(lwesp_sys_sem_t* p) {
169 return CloseHandle(*p);
170}
171
172uint32_t
173lwesp_sys_sem_wait(lwesp_sys_sem_t* p, uint32_t timeout) {
174 DWORD ret;
175 uint32_t tick = osKernelSysTick();
176
177 if (timeout == 0) {
178 ret = WaitForSingleObject(*p, INFINITE);
179 return 1;
180 } else {
181 ret = WaitForSingleObject(*p, timeout);
182 if (ret == WAIT_OBJECT_0) {
183 return 1;
184 } else {
185 return LWESP_SYS_TIMEOUT;
186 }
187 }
188}
189
190uint8_t
191lwesp_sys_sem_release(lwesp_sys_sem_t* p) {
192 return ReleaseSemaphore(*p, 1, NULL);
193}
194
195uint8_t
196lwesp_sys_sem_isvalid(lwesp_sys_sem_t* p) {
197 return p != NULL && *p != NULL;
198}
199
200uint8_t
201lwesp_sys_sem_invalid(lwesp_sys_sem_t* p) {
202 *p = LWESP_SYS_SEM_NULL;
203 return 1;
204}
205
206uint8_t
207lwesp_sys_mbox_create(lwesp_sys_mbox_t* b, size_t size) {
208 win32_mbox_t* mbox;
209
210 *b = 0;
211
212 mbox = malloc(sizeof(*mbox) + size * sizeof(void*));
213 if (mbox != NULL) {
214 memset(mbox, 0x00, sizeof(*mbox));
215 mbox->size = size + 1; /* Set it to 1 more as cyclic buffer has only one less than size */
216 lwesp_sys_sem_create(&mbox->sem, 1);
217 lwesp_sys_sem_create(&mbox->sem_not_empty, 0);
218 lwesp_sys_sem_create(&mbox->sem_not_full, 0);
219 *b = mbox;
220 }
221 return *b != NULL;
222}
223
224uint8_t
225lwesp_sys_mbox_delete(lwesp_sys_mbox_t* b) {
226 win32_mbox_t* mbox = *b;
227 lwesp_sys_sem_delete(&mbox->sem);
228 lwesp_sys_sem_delete(&mbox->sem_not_full);
229 lwesp_sys_sem_delete(&mbox->sem_not_empty);
230 free(mbox);
231 return 1;
232}
233
234uint32_t
235lwesp_sys_mbox_put(lwesp_sys_mbox_t* b, void* m) {
236 win32_mbox_t* mbox = *b;
237 uint32_t time = osKernelSysTick(); /* Get start time */
238
239 lwesp_sys_sem_wait(&mbox->sem, 0); /* Wait for access */
240
241 /*
242 * Since function is blocking until ready to write something to queue,
243 * wait and release the semaphores to allow other threads
244 * to process the queue before we can write new value.
245 */
246 while (mbox_is_full(mbox)) {
247 lwesp_sys_sem_release(&mbox->sem); /* Release semaphore */
248 lwesp_sys_sem_wait(&mbox->sem_not_full, 0); /* Wait for semaphore indicating not full */
249 lwesp_sys_sem_wait(&mbox->sem, 0); /* Wait availability again */
250 }
251 mbox->entries[mbox->in] = m;
252 if (++mbox->in >= mbox->size) {
253 mbox->in = 0;
254 }
255 lwesp_sys_sem_release(&mbox->sem_not_empty);/* Signal non-empty state */
256 lwesp_sys_sem_release(&mbox->sem); /* Release access for other threads */
257 return osKernelSysTick() - time;
258}
259
260uint32_t
261lwesp_sys_mbox_get(lwesp_sys_mbox_t* b, void** m, uint32_t timeout) {
262 win32_mbox_t* mbox = *b;
263 uint32_t time;
264
265 time = osKernelSysTick();
266
267 /* Get exclusive access to message queue */
268 if (lwesp_sys_sem_wait(&mbox->sem, timeout) == LWESP_SYS_TIMEOUT) {
269 return LWESP_SYS_TIMEOUT;
270 }
271 while (mbox_is_empty(mbox)) {
272 lwesp_sys_sem_release(&mbox->sem);
273 if (lwesp_sys_sem_wait(&mbox->sem_not_empty, timeout) == LWESP_SYS_TIMEOUT) {
274 return LWESP_SYS_TIMEOUT;
275 }
276 lwesp_sys_sem_wait(&mbox->sem, timeout);
277 }
278 *m = mbox->entries[mbox->out];
279 if (++mbox->out >= mbox->size) {
280 mbox->out = 0;
281 }
282 lwesp_sys_sem_release(&mbox->sem_not_full);
283 lwesp_sys_sem_release(&mbox->sem);
284
285 return osKernelSysTick() - time;
286}
287
288uint8_t
289lwesp_sys_mbox_putnow(lwesp_sys_mbox_t* b, void* m) {
290 win32_mbox_t* mbox = *b;
291
292 lwesp_sys_sem_wait(&mbox->sem, 0);
293 if (mbox_is_full(mbox)) {
294 lwesp_sys_sem_release(&mbox->sem);
295 return 0;
296 }
297 mbox->entries[mbox->in] = m;
298 if (mbox->in == mbox->out) {
299 lwesp_sys_sem_release(&mbox->sem_not_empty);
300 }
301 if (++mbox->in >= mbox->size) {
302 mbox->in = 0;
303 }
304 lwesp_sys_sem_release(&mbox->sem);
305 return 1;
306}
307
308uint8_t
309lwesp_sys_mbox_getnow(lwesp_sys_mbox_t* b, void** m) {
310 win32_mbox_t* mbox = *b;
311
312 lwesp_sys_sem_wait(&mbox->sem, 0); /* Wait exclusive access */
313 if (mbox->in == mbox->out) {
314 lwesp_sys_sem_release(&mbox->sem); /* Release access */
315 return 0;
316 }
317
318 *m = mbox->entries[mbox->out];
319 if (++mbox->out >= mbox->size) {
320 mbox->out = 0;
321 }
322 lwesp_sys_sem_release(&mbox->sem_not_full); /* Queue not full anymore */
323 lwesp_sys_sem_release(&mbox->sem); /* Release semaphore */
324 return 1;
325}
326
327uint8_t
328lwesp_sys_mbox_isvalid(lwesp_sys_mbox_t* b) {
329 return b != NULL && *b != NULL;
330}
331
332uint8_t
333lwesp_sys_mbox_invalid(lwesp_sys_mbox_t* b) {
334 *b = LWESP_SYS_MBOX_NULL;
335 return 1;
336}
337
338uint8_t
339lwesp_sys_thread_create(lwesp_sys_thread_t* t, const char* name, lwesp_sys_thread_fn thread_func, void* const arg, size_t stack_size, lwesp_sys_thread_prio_t prio) {
340 HANDLE h;
341 DWORD id;
342 h = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_func, arg, 0, &id);
343 if (t != NULL) {
344 *t = h;
345 }
346 return h != NULL;
347}
348
349uint8_t
350lwesp_sys_thread_terminate(lwesp_sys_thread_t* t) {
351 if (t == NULL) { /* Shall we terminate ourself? */
352 ExitThread(0);
353 } else {
354 /* We have known thread, find handle by looking at ID */
355 TerminateThread(*t, 0);
356 }
357 return 1;
358}
359
360uint8_t
361lwesp_sys_thread_yield(void) {
362 /* Not implemented */
363 return 1;
364}
365
366#endif /* LWESP_CFG_OS */
367#endif /* !__DOXYGEN__ */
Example: System functions for CMSIS-OS¶
1/**
2 * \file lwesp_sys_port.h
3 * \brief CMSIS-OS based system file
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#ifndef LWESP_HDR_SYSTEM_PORT_H
35#define LWESP_HDR_SYSTEM_PORT_H
36
37#include <stdint.h>
38#include <stdlib.h>
39#include "lwesp/lwesp_opt.h"
40#include "cmsis_os.h"
41
42#ifdef __cplusplus
43extern "C" {
44#endif /* __cplusplus */
45
46#if LWESP_CFG_OS && !__DOXYGEN__
47
48typedef osMutexId_t lwesp_sys_mutex_t;
49typedef osSemaphoreId_t lwesp_sys_sem_t;
50typedef osMessageQueueId_t lwesp_sys_mbox_t;
51typedef osThreadId_t lwesp_sys_thread_t;
52typedef osPriority_t lwesp_sys_thread_prio_t;
53
54#define LWESP_SYS_MUTEX_NULL ((lwesp_sys_mutex_t)0)
55#define LWESP_SYS_SEM_NULL ((lwesp_sys_sem_t)0)
56#define LWESP_SYS_MBOX_NULL ((lwesp_sys_mbox_t)0)
57#define LWESP_SYS_TIMEOUT ((uint32_t)osWaitForever)
58#define LWESP_SYS_THREAD_PRIO (osPriorityNormal)
59#define LWESP_SYS_THREAD_SS (512)
60
61#endif /* LWESP_CFG_OS && !__DOXYGEN__ */
62
63#ifdef __cplusplus
64}
65#endif /* __cplusplus */
66
67#endif /* LWESP_HDR_SYSTEM_PORT_H */
1/**
2 * \file lwesp_sys_cmsis_os.c
3 * \brief System dependent functions for CMSIS based operating system
4 */
5
6/*
7 * Copyright (c) 2020 Tilen MAJERLE
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LwESP - Lightweight ESP-AT parser library.
30 *
31 * Author: Tilen MAJERLE <tilen@majerle.eu>
32 * Version: v1.1.2-dev
33 */
34#include "system/lwesp_sys.h"
35#include "cmsis_os.h"
36
37#if !__DOXYGEN__
38
39static osMutexId_t sys_mutex;
40
41uint8_t
42lwesp_sys_init(void) {
43 lwesp_sys_mutex_create(&sys_mutex);
44 return 1;
45}
46
47uint32_t
48lwesp_sys_now(void) {
49 return osKernelSysTick();
50}
51
52uint8_t
53lwesp_sys_protect(void) {
54 lwesp_sys_mutex_lock(&sys_mutex);
55 return 1;
56}
57
58uint8_t
59lwesp_sys_unprotect(void) {
60 lwesp_sys_mutex_unlock(&sys_mutex);
61 return 1;
62}
63
64uint8_t
65lwesp_sys_mutex_create(lwesp_sys_mutex_t* p) {
66 const osMutexAttr_t attr = {
67 .attr_bits = osMutexRecursive,
68 .name = "lwesp_mutex",
69 };
70 return (*p = osMutexNew(&attr)) != NULL;
71}
72
73uint8_t
74lwesp_sys_mutex_delete(lwesp_sys_mutex_t* p) {
75 return osMutexDelete(*p) == osOK;
76}
77
78uint8_t
79lwesp_sys_mutex_lock(lwesp_sys_mutex_t* p) {
80 return osMutexAcquire(*p, osWaitForever) == osOK;
81}
82
83uint8_t
84lwesp_sys_mutex_unlock(lwesp_sys_mutex_t* p) {
85 return osMutexRelease(*p) == osOK;
86}
87
88uint8_t
89lwesp_sys_mutex_isvalid(lwesp_sys_mutex_t* p) {
90 return p != NULL && *p != NULL;
91}
92
93uint8_t
94lwesp_sys_mutex_invalid(lwesp_sys_mutex_t* p) {
95 *p = LWESP_SYS_MUTEX_NULL;
96 return 1;
97}
98
99uint8_t
100lwesp_sys_sem_create(lwesp_sys_sem_t* p, uint8_t cnt) {
101 const osSemaphoreAttr_t attr = {
102 .name = "lwesp_sem",
103 };
104 return (*p = osSemaphoreNew(1, cnt > 0 ? 1 : 0, &attr)) != NULL;
105}
106
107uint8_t
108lwesp_sys_sem_delete(lwesp_sys_sem_t* p) {
109 return osSemaphoreDelete(*p) == osOK;
110}
111
112uint32_t
113lwesp_sys_sem_wait(lwesp_sys_sem_t* p, uint32_t timeout) {
114 uint32_t tick = osKernelSysTick();
115 return (osSemaphoreAcquire(*p, timeout == 0 ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : LWESP_SYS_TIMEOUT;
116}
117
118uint8_t
119lwesp_sys_sem_release(lwesp_sys_sem_t* p) {
120 return osSemaphoreRelease(*p) == osOK;
121}
122
123uint8_t
124lwesp_sys_sem_isvalid(lwesp_sys_sem_t* p) {
125 return p != NULL && *p != NULL;
126}
127
128uint8_t
129lwesp_sys_sem_invalid(lwesp_sys_sem_t* p) {
130 *p = LWESP_SYS_SEM_NULL;
131 return 1;
132}
133
134uint8_t
135lwesp_sys_mbox_create(lwesp_sys_mbox_t* b, size_t size) {
136 const osMessageQueueAttr_t attr = {
137 .name = "lwesp_mbox",
138 };
139 return (*b = osMessageQueueNew(size, sizeof(void*), &attr)) != NULL;
140}
141
142uint8_t
143lwesp_sys_mbox_delete(lwesp_sys_mbox_t* b) {
144 if (osMessageQueueGetCount(*b) > 0) {
145 return 0;
146 }
147 return osMessageQueueDelete(*b) == osOK;
148}
149
150uint32_t
151lwesp_sys_mbox_put(lwesp_sys_mbox_t* b, void* m) {
152 uint32_t tick = osKernelSysTick();
153 return osMessageQueuePut(*b, &m, 0, osWaitForever) == osOK ? (osKernelSysTick() - tick) : LWESP_SYS_TIMEOUT;
154}
155
156uint32_t
157lwesp_sys_mbox_get(lwesp_sys_mbox_t* b, void** m, uint32_t timeout) {
158 uint32_t tick = osKernelSysTick();
159 return (osMessageQueueGet(*b, m, NULL, timeout == 0 ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : LWESP_SYS_TIMEOUT;
160}
161
162uint8_t
163lwesp_sys_mbox_putnow(lwesp_sys_mbox_t* b, void* m) {
164 return osMessageQueuePut(*b, &m, 0, 0) == osOK;
165}
166
167uint8_t
168lwesp_sys_mbox_getnow(lwesp_sys_mbox_t* b, void** m) {
169 return osMessageQueueGet(*b, m, NULL, 0) == osOK;
170}
171
172uint8_t
173lwesp_sys_mbox_isvalid(lwesp_sys_mbox_t* b) {
174 return b != NULL && *b != NULL;
175}
176
177uint8_t
178lwesp_sys_mbox_invalid(lwesp_sys_mbox_t* b) {
179 *b = LWESP_SYS_MBOX_NULL;
180 return 1;
181}
182
183uint8_t
184lwesp_sys_thread_create(lwesp_sys_thread_t* t, const char* name, lwesp_sys_thread_fn thread_func, void* const arg, size_t stack_size, lwesp_sys_thread_prio_t prio) {
185 lwesp_sys_thread_t id;
186 const osThreadAttr_t thread_attr = {
187 .name = (char*)name,
188 .priority = (osPriority)prio,
189 .stack_size = stack_size > 0 ? stack_size : LWESP_SYS_THREAD_SS
190 };
191
192 id = osThreadNew(thread_func, arg, &thread_attr);
193 if (t != NULL) {
194 *t = id;
195 }
196 return id != NULL;
197}
198
199uint8_t
200lwesp_sys_thread_terminate(lwesp_sys_thread_t* t) {
201 if (t != NULL) {
202 osThreadTerminate(*t);
203 } else {
204 osThreadExit();
205 }
206 return 1;
207}
208
209uint8_t
210lwesp_sys_thread_yield(void) {
211 osThreadYield();
212 return 1;
213}
214
215#endif /* !__DOXYGEN__ */
API reference¶
List of all the modules:
LwESP¶
Access point¶
- group LWESP_AP
Access point.
Functions to manage access point (AP) on ESP device.
In order to be able to use AP feature, LWESP_CFG_MODE_ACCESS_POINT must be enabled.
Functions
-
lwespr_t lwesp_ap_getip(lwesp_ip_t *ip, lwesp_ip_t *gw, lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get IP of access point.
- Parameters
ip – [out] Pointer to variable to write IP address
gw – [out] Pointer to variable to write gateway address
nm – [out] Pointer to variable to write netmask address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_setip(const lwesp_ip_t *ip, const lwesp_ip_t *gw, const lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set IP of access point.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
ip – [in] Pointer to IP address
gw – [in] Pointer to gateway address. Set to
NULL
to use default gatewaynm – [in] Pointer to netmask address. Set to
NULL
to use default netmaskevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_getmac(lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get MAC of access point.
- Parameters
mac – [out] Pointer to output variable to save MAC address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_setmac(const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set MAC of access point.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
mac – [in] Pointer to variable with MAC address. Memory of at least 6 bytes is required
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_get_config(lwesp_ap_conf_t *ap_conf, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get configuration of Soft Access Point.
Note
Before you can get configuration access point, ESP device must be in AP mode. Check lwesp_set_wifi_mode for more information
- Parameters
ap_conf – [out] soft access point configuration
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_set_config(const char *ssid, const char *pwd, uint8_t ch, lwesp_ecn_t ecn, uint8_t max_sta, uint8_t hid, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure access point.
Configuration changes will be saved in the NVS area of ESP device.
Note
Before you can configure access point, ESP device must be in AP mode. Check lwesp_set_wifi_mode for more information
- Parameters
ssid – [in] SSID name of access point
pwd – [in] Password for network. Either set it to
NULL
or less than64
charactersch – [in] Wifi RF channel
ecn – [in] Encryption type. Valid options are
OPEN
,WPA_PSK
,WPA2_PSK
andWPA_WPA2_PSK
max_sta – [in] Maximal number of stations access point can accept. Valid between 1 and 10 stations
hid – [in] Set to
1
to hide access point from public accessevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_list_sta(lwesp_sta_t *sta, size_t stal, size_t *staf, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
List stations connected to access point.
- Parameters
sta – [in] Pointer to array of lwesp_sta_t structure to fill with stations
stal – [in] Number of array entries of sta parameter
staf – [out] Number of stations connected to access point
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ap_disconn_sta(const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Disconnects connected station from SoftAP access point.
- Parameters
mac – [in] Device MAC address to disconnect. Application may use lwesp_ap_list_sta to obtain list of connected stations to SoftAP. Set to
NULL
to disconnect all stations.evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
struct lwesp_ap_t¶
- #include <lwesp_typedefs.h>
Access point data structure.
Public Members
-
lwesp_ecn_t ecn¶
Encryption mode
-
char ssid[LWESP_CFG_MAX_SSID_LENGTH]¶
Access point name
-
int16_t rssi¶
Received signal strength indicator
-
lwesp_mac_t mac¶
MAC physical address
-
uint8_t ch¶
WiFi channel used on access point
-
uint8_t scan_type¶
Scan type, 0 = active, 1 = passive
-
uint16_t scan_time_min¶
Minimum active scan time per channel in units of milliseconds
-
uint16_t scan_time_max¶
maximum active scan time per channel in units of milliseconds
-
int16_t freq_offset¶
Frequency offset
-
int16_t freq_cal¶
Frequency calibration
-
lwesp_ap_cipher_t pairwise_cipher¶
Pairwise cipher mode
-
lwesp_ap_cipher_t group_cipher¶
Group cipher mode
-
uint8_t bgn¶
Information about 802.11[b|g|n] support
-
uint8_t wps¶
Status if WPS function is supported
-
lwesp_ecn_t ecn¶
-
struct lwesp_sta_info_ap_t¶
- #include <lwesp_typedefs.h>
Access point information on which station is connected to.
Public Members
-
char ssid[LWESP_CFG_MAX_SSID_LENGTH]¶
Access point name
-
int16_t rssi¶
RSSI
-
lwesp_mac_t mac¶
MAC address
-
uint8_t ch¶
Channel information
-
char ssid[LWESP_CFG_MAX_SSID_LENGTH]¶
-
struct lwesp_ap_conf_t¶
- #include <lwesp_typedefs.h>
Soft access point data structure.
Public Members
-
char ssid[LWESP_CFG_MAX_SSID_LENGTH]¶
Access point name
-
char pwd[LWESP_CFG_MAX_PWD_LENGTH]¶
Access point password/passphrase
-
uint8_t ch¶
WiFi channel used on access point
-
lwesp_ecn_t ecn¶
Encryption mode
-
uint8_t max_cons¶
Maximum number of stations allowed connected to this AP
broadcast the SSID, 0 No, 1 Yes
-
char ssid[LWESP_CFG_MAX_SSID_LENGTH]¶
-
lwespr_t lwesp_ap_getip(lwesp_ip_t *ip, lwesp_ip_t *gw, lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Ring buffer¶
- group LWESP_BUFF
Generic ring buffer.
Defines
-
BUF_PREF(x)¶
Buffer function/typedef prefix string.
It is used to change function names in zero time to easily re-use same library between applications. Use
#define BUF_PREF(x) my_prefix_ ## x
to change all function names to (for example)my_prefix_buff_init
Note
Modification of this macro must be done in header and source file aswell
Functions
-
uint8_t lwesp_buff_init(lwesp_buff_t *buff, size_t size)¶
Initialize buffer.
- Parameters
buff – [in] Pointer to buffer structure
size – [in] Size of buffer in units of bytes
- Returns
1
on success,0
otherwise
-
void lwesp_buff_free(lwesp_buff_t *buff)¶
Free dynamic allocation if used on memory.
- Parameters
buff – [in] Pointer to buffer structure
-
void lwesp_buff_reset(lwesp_buff_t *buff)¶
Resets buffer to default values. Buffer size is not modified.
- Parameters
buff – [in] Buffer handle
-
size_t lwesp_buff_write(lwesp_buff_t *buff, const void *data, size_t btw)¶
Write data to buffer Copies data from
data
array to buffer and marks buffer as full for maximumcount
number of bytes.- Parameters
buff – [in] Buffer handle
data – [in] Pointer to data to write into buffer
btw – [in] Number of bytes to write
- Returns
Number of bytes written to buffer. When returned value is less than
btw
, there was no enough memory available to copy full data array
-
size_t lwesp_buff_read(lwesp_buff_t *buff, void *data, size_t btr)¶
Read data from buffer Copies data from buffer to
data
array and marks buffer as free for maximumbtr
number of bytes.- Parameters
buff – [in] Buffer handle
data – [out] Pointer to output memory to copy buffer data to
btr – [in] Number of bytes to read
- Returns
Number of bytes read and copied to data array
-
size_t lwesp_buff_peek(lwesp_buff_t *buff, size_t skip_count, void *data, size_t btp)¶
Read from buffer without changing read pointer (peek only)
- Parameters
buff – [in] Buffer handle
skip_count – [in] Number of bytes to skip before reading data
data – [out] Pointer to output memory to copy buffer data to
btp – [in] Number of bytes to peek
- Returns
Number of bytes peeked and written to output array
-
size_t lwesp_buff_get_free(lwesp_buff_t *buff)¶
Get number of bytes in buffer available to write.
- Parameters
buff – [in] Buffer handle
- Returns
Number of free bytes in memory
-
size_t lwesp_buff_get_full(lwesp_buff_t *buff)¶
Get number of bytes in buffer available to read.
- Parameters
buff – [in] Buffer handle
- Returns
Number of bytes ready to be read
-
void *lwesp_buff_get_linear_block_read_address(lwesp_buff_t *buff)¶
Get linear address for buffer for fast read.
- Parameters
buff – [in] Buffer handle
- Returns
Linear buffer start address
-
size_t lwesp_buff_get_linear_block_read_length(lwesp_buff_t *buff)¶
Get length of linear block address before it overflows for read operation.
- Parameters
buff – [in] Buffer handle
- Returns
Linear buffer size in units of bytes for read operation
-
size_t lwesp_buff_skip(lwesp_buff_t *buff, size_t len)¶
Skip (ignore; advance read pointer) buffer data Marks data as read in the buffer and increases free memory for up to
len
bytes.Note
Useful at the end of streaming transfer such as DMA
- Parameters
buff – [in] Buffer handle
len – [in] Number of bytes to skip and mark as read
- Returns
Number of bytes skipped
-
void *lwesp_buff_get_linear_block_write_address(lwesp_buff_t *buff)¶
Get linear address for buffer for fast read.
- Parameters
buff – [in] Buffer handle
- Returns
Linear buffer start address
-
size_t lwesp_buff_get_linear_block_write_length(lwesp_buff_t *buff)¶
Get length of linear block address before it overflows for write operation.
- Parameters
buff – [in] Buffer handle
- Returns
Linear buffer size in units of bytes for write operation
-
size_t lwesp_buff_advance(lwesp_buff_t *buff, size_t len)¶
Advance write pointer in the buffer. Similar to skip function but modifies write pointer instead of read.
Note
Useful when hardware is writing to buffer and application needs to increase number of bytes written to buffer by hardware
- Parameters
buff – [in] Buffer handle
len – [in] Number of bytes to advance
- Returns
Number of bytes advanced for write operation
-
struct lwesp_buff_t¶
- #include <lwesp_typedefs.h>
Buffer structure.
Public Members
-
uint8_t *buff¶
Pointer to buffer data. Buffer is considered initialized when
buff != NULL
-
size_t size¶
Size of buffer data. Size of actual buffer is
1
byte less than this value
-
size_t r¶
Next read pointer. Buffer is considered empty when
r == w
and full whenw == r - 1
-
size_t w¶
Next write pointer. Buffer is considered empty when
r == w
and full whenw == r - 1
-
uint8_t *buff¶
-
BUF_PREF(x)¶
Connections¶
Connections are essential feature of WiFi device and middleware. It is developed with strong focus on its performance and since it may interact with huge amount of data, it tries to use zero-copy (when available) feature, to decrease processing time.
ESP AT Firmware by default supports up to 5
connections being active at the same time and supports:
Up to
5
TCP connections active at the same timeUp to
5
UDP connections active at the same timeUp to
1
SSL connection active at a time
Note
Client or server connections are available. Same API function call are used to send/receive data or close connection.
Architecture of the connection API is using callback event functions. This allows maximal optimization in terms of responsiveness on different kind of events.
Example below shows bare minimum implementation to:
Start a new connection to remote host
Send HTTP GET request to remote host
Process received data in event and print number of received bytes
1#include "client.h"
2#include "lwesp/lwesp.h"
3
4/* Host parameter */
5#define CONN_HOST "example.com"
6#define CONN_PORT 80
7
8static lwespr_t conn_callback_func(lwesp_evt_t* evt);
9
10/**
11 * \brief Request data for connection
12 */
13static const
14uint8_t req_data[] = ""
15 "GET / HTTP/1.1\r\n"
16 "Host: " CONN_HOST "\r\n"
17 "Connection: close\r\n"
18 "\r\n";
19
20/**
21 * \brief Start a new connection(s) as client
22 */
23void
24client_connect(void) {
25 lwespr_t res;
26
27 /* Start a new connection as client in non-blocking mode */
28 if ((res = lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, "example.com", 80, NULL, conn_callback_func, 0)) == lwespOK) {
29 printf("Connection to " CONN_HOST " started...\r\n");
30 } else {
31 printf("Cannot start connection to " CONN_HOST "!\r\n");
32 }
33
34 /* Start 2 more */
35 lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, CONN_PORT, NULL, conn_callback_func, 0);
36
37 /*
38 * An example of connection which should fail in connecting.
39 * When this is the case, \ref LWESP_EVT_CONN_ERROR event should be triggered
40 * in callback function processing
41 */
42 lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, 10, NULL, conn_callback_func, 0);
43}
44
45/**
46 * \brief Event callback function for connection-only
47 * \param[in] evt: Event information with data
48 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
49 */
50static lwespr_t
51conn_callback_func(lwesp_evt_t* evt) {
52 lwesp_conn_p conn;
53 lwespr_t res;
54 uint8_t conn_num;
55
56 conn = lwesp_conn_get_from_evt(evt); /* Get connection handle from event */
57 if (conn == NULL) {
58 return lwespERR;
59 }
60 conn_num = lwesp_conn_getnum(conn); /* Get connection number for identification */
61 switch (lwesp_evt_get_type(evt)) {
62 case LWESP_EVT_CONN_ACTIVE: { /* Connection just active */
63 printf("Connection %d active!\r\n", (int)conn_num);
64 res = lwesp_conn_send(conn, req_data, sizeof(req_data) - 1, NULL, 0); /* Start sending data in non-blocking mode */
65 if (res == lwespOK) {
66 printf("Sending request data to server...\r\n");
67 } else {
68 printf("Cannot send request data to server. Closing connection manually...\r\n");
69 lwesp_conn_close(conn, 0); /* Close the connection */
70 }
71 break;
72 }
73 case LWESP_EVT_CONN_CLOSE: { /* Connection closed */
74 if (lwesp_evt_conn_close_is_forced(evt)) {
75 printf("Connection %d closed by client!\r\n", (int)conn_num);
76 } else {
77 printf("Connection %d closed by remote side!\r\n", (int)conn_num);
78 }
79 break;
80 }
81 case LWESP_EVT_CONN_SEND: { /* Data send event */
82 lwespr_t res = lwesp_evt_conn_send_get_result(evt);
83 if (res == lwespOK) {
84 printf("Data sent successfully on connection %d...waiting to receive data from remote side...\r\n", (int)conn_num);
85 } else {
86 printf("Error while sending data on connection %d!\r\n", (int)conn_num);
87 }
88 break;
89 }
90 case LWESP_EVT_CONN_RECV: { /* Data received from remote side */
91 lwesp_pbuf_p pbuf = lwesp_evt_conn_recv_get_buff(evt);
92 lwesp_conn_recved(conn, pbuf); /* Notify stack about received pbuf */
93 printf("Received %d bytes on connection %d..\r\n", (int)lwesp_pbuf_length(pbuf, 1), (int)conn_num);
94 break;
95 }
96 case LWESP_EVT_CONN_ERROR: { /* Error connecting to server */
97 const char* host = lwesp_evt_conn_error_get_host(evt);
98 lwesp_port_t port = lwesp_evt_conn_error_get_port(evt);
99 printf("Error connecting to %s:%d\r\n", host, (int)port);
100 break;
101 }
102 default:
103 break;
104 }
105 return lwespOK;
106}
Sending data¶
Receiving data flow is always the same. Whenever new data packet arrives, corresponding event is called to notify application layer.
When it comes to sending data, application may decide between 2
options (*this is valid only for non-UDP connections):
Write data to temporary transmit buffer
Execute send command for every API function call
By calling lwesp_conn_write()
on active connection, temporary buffer is allocated and input data are copied to it.
There is always up to 1
internal buffer active. When it is full (or if input data length is longer than maximal size),
data are immediately send out and are not written to buffer.
ESP AT Firmware allows (current revision) to transmit up to 2048
bytes at a time with single command.
When trying to send more than this, application would need to issue multiple send commands on AT commands level.
Write option is used mostly when application needs to write many different small chunks of data. Temporary buffer hence prevents many send command instructions as it is faster to send single command with big buffer, than many of them with smaller chunks of bytes.
1size_t rem_len;
2lwesp_conn_p conn;
3lwespr_t res;
4
5/* ... other tasks to make sure connection is established */
6
7/* We are connected to server at this point! */
8/*
9 * Call write function to write data to memory
10 * and do not send immediately unless buffer is full after this write
11 *
12 * rem_len will give us response how much bytes
13 * is available in memory after write
14 */
15res = lwesp_conn_write(conn, "My string", 9, 0, &rem_len);
16if (rem_len == 0) {
17 printf("No more memory available for next write!\r\n");
18}
19res = lwesp_conn_write(conn, "example.com", 11, 0, &rem_len);
20
21/*
22 * Data will stay in buffer until buffer is full,
23 * except if user wants to force send,
24 * call write function with flush mode enabled
25 *
26 * It will send out together 20 bytes
27 */
28lwesp_conn_write(conn, NULL, 0, 1, NULL);
In some cases it is not possible to use temporary buffers,
mostly because of memory constraints.
Application can directly start send data instructions on AT level by using lwesp_conn_send()
or lwesp_conn_sendto()
functions.
- group LWESP_CONN
Connection API functions.
Typedefs
-
typedef struct lwesp_conn *lwesp_conn_p¶
Pointer to lwesp_conn_t structure.
Enums
-
enum lwesp_conn_type_t¶
List of possible connection types.
Values:
-
enumerator LWESP_CONN_TYPE_TCP¶
Connection type is TCP
-
enumerator LWESP_CONN_TYPE_UDP¶
Connection type is UDP
-
enumerator LWESP_CONN_TYPE_SSL¶
Connection type is SSL
-
enumerator LWESP_CONN_TYPE_TCPV6¶
Connection type is TCP over IPV6
-
enumerator LWESP_CONN_TYPE_SSLV6¶
Connection type is SSL over IPV6
-
enumerator LWESP_CONN_TYPE_TCP¶
Functions
-
lwespr_t lwesp_conn_start(lwesp_conn_p *conn, lwesp_conn_type_t type, const char *const remote_host, lwesp_port_t remote_port, void *const arg, lwesp_evt_fn conn_evt_fn, const uint32_t blocking)¶
Start a new connection of specific type.
- Parameters
conn – [out] Pointer to connection handle to set new connection reference in case of successfully connected
type – [in] Connection type. This parameter can be a value of lwesp_conn_type_t enumeration
remote_host – [in] Connection host. In case of IP, write it as string, ex. “192.168.1.1”
remote_port – [in] Connection port
arg – [in] Pointer to user argument passed to connection if successfully connected
conn_evt_fn – [in] Callback function for this connection
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_conn_startex(lwesp_conn_p *conn, lwesp_conn_start_t *start_struct, void *const arg, lwesp_evt_fn conn_evt_fn, const uint32_t blocking)¶
Start a new connection of specific type in extended mode.
- Parameters
conn – [out] Pointer to connection handle to set new connection reference in case of successfully connected
start_struct – [in] Connection information are handled by one giant structure
arg – [in] Pointer to user argument passed to connection if successfully connected
conn_evt_fn – [in] Callback function for this connection
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_conn_close(lwesp_conn_p conn, const uint32_t blocking)¶
Close specific or all connections.
-
lwespr_t lwesp_conn_send(lwesp_conn_p conn, const void *data, size_t btw, size_t *const bw, const uint32_t blocking)¶
Send data on already active connection either as client or server.
- Parameters
conn – [in] Connection handle to send data
data – [in] Data to send
btw – [in] Number of bytes to send
bw – [out] Pointer to output variable to save number of sent data when successfully sent. Parameter value might not be accurate if you combine lwesp_conn_write and lwesp_conn_send functions
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_conn_sendto(lwesp_conn_p conn, const lwesp_ip_t *const ip, lwesp_port_t port, const void *data, size_t btw, size_t *bw, const uint32_t blocking)¶
Send data on active connection of type UDP to specific remote IP and port.
Note
In case IP and port values are not set, it will behave as normal send function (suitable for TCP too)
- Parameters
conn – [in] Connection handle to send data
ip – [in] Remote IP address for UDP connection
port – [in] Remote port connection
data – [in] Pointer to data to send
btw – [in] Number of bytes to send
bw – [out] Pointer to output variable to save number of sent data when successfully sent
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_conn_set_arg(lwesp_conn_p conn, void *const arg)¶
Set argument variable for connection.
-
void *lwesp_conn_get_arg(lwesp_conn_p conn)¶
Get user defined connection argument.
- Parameters
conn – [in] Connection handle to get argument
- Returns
User argument
-
uint8_t lwesp_conn_is_client(lwesp_conn_p conn)¶
Check if connection type is client.
- Parameters
conn – [in] Pointer to connection to check for status
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_conn_is_server(lwesp_conn_p conn)¶
Check if connection type is server.
- Parameters
conn – [in] Pointer to connection to check for status
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_conn_is_active(lwesp_conn_p conn)¶
Check if connection is active.
- Parameters
conn – [in] Pointer to connection to check for status
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_conn_is_closed(lwesp_conn_p conn)¶
Check if connection is closed.
- Parameters
conn – [in] Pointer to connection to check for status
- Returns
1
on success,0
otherwise
-
int8_t lwesp_conn_getnum(lwesp_conn_p conn)¶
Get the number from connection.
- Parameters
conn – [in] Connection pointer
- Returns
Connection number in case of success or -1 on failure
-
lwespr_t lwesp_conn_set_ssl_buffersize(size_t size, const uint32_t blocking)¶
Set internal buffer size for SSL connection on ESP device.
Note
Use this function before you start first SSL connection
-
lwesp_conn_p lwesp_conn_get_from_evt(lwesp_evt_t *evt)¶
Get connection from connection based event.
- Parameters
evt – [in] Event which happened for connection
- Returns
Connection pointer on success,
NULL
otherwise
-
lwespr_t lwesp_conn_write(lwesp_conn_p conn, const void *data, size_t btw, uint8_t flush, size_t *const mem_available)¶
Write data to connection buffer and if it is full, send it non-blocking way.
Note
This function may only be called from core (connection callbacks)
- Parameters
conn – [in] Connection to write
data – [in] Data to copy to write buffer
btw – [in] Number of bytes to write
flush – [in] Flush flag. Set to
1
if you want to send data immediately after copyingmem_available – [out] Available memory size available in current write buffer. When the buffer length is reached, current one is sent and a new one is automatically created. If function returns lwespOK and
*mem_available = 0
, there was a problem allocating a new buffer for next operation
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_conn_recved(lwesp_conn_p conn, lwesp_pbuf_p pbuf)¶
Notify connection about received data which means connection is ready to accept more data.
Once data reception is confirmed, stack will try to send more data to user.
Note
Since this feature is not supported yet by AT commands, function is only prototype and should be used in connection callback when data are received
Note
Function is not thread safe and may only be called from connection event function
-
size_t lwesp_conn_get_total_recved_count(lwesp_conn_p conn)¶
Get total number of bytes ever received on connection and sent to user.
- Parameters
conn – [in] Connection handle
- Returns
Total number of received bytes on connection
-
uint8_t lwesp_conn_get_remote_ip(lwesp_conn_p conn, lwesp_ip_t *ip)¶
Get connection remote IP address.
- Parameters
conn – [in] Connection handle
ip – [out] Pointer to IP output handle
- Returns
1
on success,0
otherwise
-
lwesp_port_t lwesp_conn_get_remote_port(lwesp_conn_p conn)¶
Get connection remote port number.
- Parameters
conn – [in] Connection handle
- Returns
Port number on success,
0
otherwise
-
lwesp_port_t lwesp_conn_get_local_port(lwesp_conn_p conn)¶
Get connection local port number.
- Parameters
conn – [in] Connection handle
- Returns
Port number on success,
0
otherwise
-
lwespr_t lwesp_conn_ssl_set_config(uint8_t link_id, uint8_t auth_mode, uint8_t pki_number, uint8_t ca_number, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure SSL parameters.
- Parameters
link_id – [in] ID of the connection (0~max), for multiple connections, if the value is max, it means all connections. By default, max is LWESP_CFG_MAX_CONNS.
auth_mode – [in] Authentication mode
0
: no authorization1
: load cert and private key for server authorization2
: load CA for client authorize server cert and private key3
: both authorizationpki_number – [in] The index of cert and private key, if only one cert and private key, the value should be
0
.ca_number – [in] The index of CA, if only one CA, the value should be 0.
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
struct lwesp_conn_start_t¶
- #include <lwesp_typedefs.h>
Connection start structure, used to start the connection in extended mode.
Public Members
-
lwesp_conn_type_t type¶
Connection type
-
const char *remote_host¶
Host name or IP address in string format
-
lwesp_port_t remote_port¶
Remote server port
-
const char *local_ip¶
Local IP. Optional parameter, set to NULL if not used (most cases)
-
uint16_t keep_alive¶
Keep alive parameter for TCP/SSL connection in units of seconds. Value can be between
0 - 7200
where0
means no keep alive
-
struct lwesp_conn_start_t::[anonymous]::[anonymous] tcp_ssl¶
TCP/SSL specific features
-
lwesp_port_t local_port¶
Custom local port for UDP
-
uint8_t mode¶
UDP mode. Set to
0
by default. Check ESP AT commands instruction set for more info when needed
-
struct lwesp_conn_start_t::[anonymous]::[anonymous] udp¶
UDP specific features
-
union lwesp_conn_start_t::[anonymous] ext¶
Extended support union
-
lwesp_conn_type_t type¶
-
typedef struct lwesp_conn *lwesp_conn_p¶
Debug support¶
Middleware has extended debugging capabilities. These consist of different debugging levels and types of debug messages, allowing to track and catch different types of warnings, severe problems or simply output messages program flow messages (trace messages).
Module is highly configurable using library configuration methods. Application must enable some options to decide what type of messages and for which modules it would like to output messages.
With default configuration, printf
is used as output function.
This behavior can be changed with LWESP_CFG_DBG_OUT
configuration.
For successful debugging, application must:
Enable global debugging by setting
LWESP_CFG_DBG
toLWESP_DBG_ON
Configure which types of messages to output
Configure debugging level, from all messages to severe only
Enable specific modules to debug, by setting its configuration value to
LWESP_DBG_ON
Tip
Check Configuration for all modules with debug implementation.
An example code with config and latter usage:
1/* Modifications of lwesp_opts.h file for configuration */
2
3/* Enable global debug */
4#define LWESP_CFG_DBG LWESP_DBG_ON
5
6/*
7 * Enable debug types.
8 * Application may use bitwise OR | to use multiple types:
9 * LWESP_DBG_TYPE_TRACE | LWESP_DBG_TYPE_STATE
10 */
11#define LWESP_CFG_DBG_TYPES_ON LWESP_DBG_TYPE_TRACE
12
13/* Enable debug on custom module */
14#define MY_DBG_MODULE LWESP_DBG_ON
1#include "lwesp/lwesp_debug.h"
2
3/*
4 * Print debug message to the screen
5 * Trace message will be printed as it is enabled in types
6 * while state message will not be printed.
7 */
8LWESP_DEBUGF(MY_DBG_MODULE | LWESP_DBG_TYPE_TRACE, "This is trace message on my program\r\n");
9LWESP_DEBUGF(MY_DBG_MODULE | LWESP_DBG_TYPE_STATE, "This is state message on my program\r\n");
- group LWESP_DEBUG
Debug support module to track library flow.
Debug levels
List of debug levels
-
LWESP_DBG_LVL_ALL¶
Print all messages of all types
-
LWESP_DBG_LVL_WARNING¶
Print warning and upper messages
-
LWESP_DBG_LVL_DANGER¶
Print danger errors
-
LWESP_DBG_LVL_SEVERE¶
Print severe problems affecting program flow
-
LWESP_DBG_LVL_MASK¶
Mask for getting debug level
Debug types
List of debug types
-
LWESP_DBG_TYPE_TRACE¶
Debug trace messages for program flow
-
LWESP_DBG_TYPE_STATE¶
Debug state messages (such as state machines)
-
LWESP_DBG_TYPE_ALL¶
All debug types
Defines
-
LWESP_DBG_ON¶
Indicates debug is enabled
-
LWESP_DBG_OFF¶
Indicates debug is disabled
-
LWESP_DEBUGF(c, fmt, ...)¶
Print message to the debug “window” if enabled.
- Parameters
c – [in] Condition if debug of specific type is enabled
fmt – [in] Formatted string for debug
... – [in] Variable parameters for formatted string
-
LWESP_DEBUGW(c, cond, fmt, ...)¶
Print message to the debug “window” if enabled when specific condition is met.
- Parameters
c – [in] Condition if debug of specific type is enabled
cond – [in] Debug only if this condition is true
fmt – [in] Formatted string for debug
... – [in] Variable parameters for formatted string
-
LWESP_DBG_LVL_ALL¶
Dynamic Host Configuration Protocol¶
- group LWESP_DHCP
DHCP config.
Functions
-
lwespr_t lwesp_dhcp_set_config(uint8_t sta, uint8_t ap, uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure DHCP settings for station or access point (or both)
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
sta – [in] Set to
1
to affect station DHCP configuration, set to0
to keep current setupap – [in] Set to
1
to affect access point DHCP configuration, set to0
to keep current setupen – [in] Set to
1
to enable DHCP, or0
to disable (static IP)evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_dhcp_set_config(uint8_t sta, uint8_t ap, uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Domain Name System¶
- group LWESP_DNS
Domain name server.
Functions
-
lwespr_t lwesp_dns_gethostbyname(const char *host, lwesp_ip_t *const ip, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get IP address from host name.
- Parameters
host – [in] Pointer to host name to get IP for
ip – [out] Pointer to lwesp_ip_t variable to save IP
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_dns_get_config(lwesp_ip_t *s1, lwesp_ip_t *s2, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get the DNS server configuration.
Retrive configuration saved in the NVS area of ESP device.
- Parameters
s1 – [out] First server IP address in lwesp_ip_t format, set to 0.0.0.0 if not used
s2 – [out] Second server IP address in lwesp_ip_t format, set to to 0.0.0.0 if not used. Address
s1
cannot be the same ass2
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_dns_set_config(uint8_t en, const char *s1, const char *s2, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Enable or disable custom DNS server configuration.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
en – [in] Set to
1
to enable,0
to disable custom DNS configuration. When disabled, default DNS servers are used as proposed by ESP AT commands firmwares1 – [in] First server IP address in string format, set to
NULL
if not useds2 – [in] Second server IP address in string format, set to
NULL
if not used. Addresss1
cannot be the same ass2
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_dns_gethostbyname(const char *host, lwesp_ip_t *const ip, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Event management¶
- group LWESP_EVT
Event helper functions.
Reset detected
Event helper functions for LWESP_EVT_RESET_DETECTED event
-
uint8_t lwesp_evt_reset_detected_is_forced(lwesp_evt_t *cc)¶
Check if detected reset was forced by user.
- Parameters
cc – [in] Event handle
- Returns
1
if forced by user,0
otherwise
Reset event
Event helper functions for LWESP_EVT_RESET event
-
lwespr_t lwesp_evt_reset_get_result(lwesp_evt_t *cc)¶
Get reset sequence operation status.
- Parameters
cc – [in] Event data
- Returns
Member of lwespr_t enumeration
Restore event
Event helper functions for LWESP_EVT_RESTORE event
-
lwespr_t lwesp_evt_restore_get_result(lwesp_evt_t *cc)¶
Get restore sequence operation status.
- Parameters
cc – [in] Event data
- Returns
Member of lwespr_t enumeration
Access point or station IP or MAC
Event helper functions for LWESP_EVT_AP_IP_STA event
-
lwesp_mac_t *lwesp_evt_ap_ip_sta_get_mac(lwesp_evt_t *cc)¶
Get MAC address from station.
- Parameters
cc – [in] Event handle
- Returns
MAC address
-
lwesp_ip_t *lwesp_evt_ap_ip_sta_get_ip(lwesp_evt_t *cc)¶
Get IP address from station.
- Parameters
cc – [in] Event handle
- Returns
IP address
Connected station to access point
Event helper functions for LWESP_EVT_AP_CONNECTED_STA event
-
lwesp_mac_t *lwesp_evt_ap_connected_sta_get_mac(lwesp_evt_t *cc)¶
Get MAC address from connected station.
- Parameters
cc – [in] Event handle
- Returns
MAC address
Disconnected station from access point
Event helper functions for LWESP_EVT_AP_DISCONNECTED_STA event
-
lwesp_mac_t *lwesp_evt_ap_disconnected_sta_get_mac(lwesp_evt_t *cc)¶
Get MAC address from disconnected station.
- Parameters
cc – [in] Event handle
- Returns
MAC address
Connection data received
Event helper functions for LWESP_EVT_CONN_RECV event
-
lwesp_pbuf_p lwesp_evt_conn_recv_get_buff(lwesp_evt_t *cc)¶
Get buffer from received data.
- Parameters
cc – [in] Event handle
- Returns
Buffer handle
-
lwesp_conn_p lwesp_evt_conn_recv_get_conn(lwesp_evt_t *cc)¶
Get connection handle for receive.
- Parameters
cc – [in] Event handle
- Returns
Connection handle
Connection data send
Event helper functions for LWESP_EVT_CONN_SEND event
-
lwesp_conn_p lwesp_evt_conn_send_get_conn(lwesp_evt_t *cc)¶
Get connection handle for data sent event.
- Parameters
cc – [in] Event handle
- Returns
Connection handle
-
size_t lwesp_evt_conn_send_get_length(lwesp_evt_t *cc)¶
Get number of bytes sent on connection.
- Parameters
cc – [in] Event handle
- Returns
Number of bytes sent
-
lwespr_t lwesp_evt_conn_send_get_result(lwesp_evt_t *cc)¶
Check if connection send was successful.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
Connection active
Event helper functions for LWESP_EVT_CONN_ACTIVE event
-
lwesp_conn_p lwesp_evt_conn_active_get_conn(lwesp_evt_t *cc)¶
Get connection handle.
- Parameters
cc – [in] Event handle
- Returns
Connection handle
-
uint8_t lwesp_evt_conn_active_is_client(lwesp_evt_t *cc)¶
Check if new connection is client.
- Parameters
cc – [in] Event handle
- Returns
1
if client,0
otherwise
Connection close event
Event helper functions for LWESP_EVT_CONN_CLOSE event
-
lwesp_conn_p lwesp_evt_conn_close_get_conn(lwesp_evt_t *cc)¶
Get connection handle.
- Parameters
cc – [in] Event handle
- Returns
Connection handle
-
uint8_t lwesp_evt_conn_close_is_client(lwesp_evt_t *cc)¶
Check if just closed connection was client.
- Parameters
cc – [in] Event handle
- Returns
1
if client,0
otherwise
-
uint8_t lwesp_evt_conn_close_is_forced(lwesp_evt_t *cc)¶
Check if connection close even was forced by user.
- Parameters
cc – [in] Event handle
- Returns
1
if forced,0
otherwise
-
lwespr_t lwesp_evt_conn_close_get_result(lwesp_evt_t *cc)¶
Get connection close event result.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
Connection poll
Event helper functions for LWESP_EVT_CONN_POLL event
-
lwesp_conn_p lwesp_evt_conn_poll_get_conn(lwesp_evt_t *cc)¶
Get connection handle.
- Parameters
cc – [in] Event handle
- Returns
Connection handle
Connection error
Event helper functions for LWESP_EVT_CONN_ERROR event
-
lwespr_t lwesp_evt_conn_error_get_error(lwesp_evt_t *cc)¶
Get connection error type.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
lwesp_conn_type_t lwesp_evt_conn_error_get_type(lwesp_evt_t *cc)¶
Get connection type.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
const char *lwesp_evt_conn_error_get_host(lwesp_evt_t *cc)¶
Get connection host.
- Parameters
cc – [in] Event handle
- Returns
Host name for connection
-
lwesp_port_t lwesp_evt_conn_error_get_port(lwesp_evt_t *cc)¶
Get connection port.
- Parameters
cc – [in] Event handle
- Returns
Host port number
-
void *lwesp_evt_conn_error_get_arg(lwesp_evt_t *cc)¶
Get user argument.
- Parameters
cc – [in] Event handle
- Returns
User argument
List access points
Event helper functions for LWESP_EVT_STA_LIST_AP event
-
lwespr_t lwesp_evt_sta_list_ap_get_result(lwesp_evt_t *cc)¶
Get command success result.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
lwesp_ap_t *lwesp_evt_sta_list_ap_get_aps(lwesp_evt_t *cc)¶
Get access points.
- Parameters
cc – [in] Event handle
- Returns
Pointer to lwesp_ap_t with first access point description
-
size_t lwesp_evt_sta_list_ap_get_length(lwesp_evt_t *cc)¶
Get number of access points found.
- Parameters
cc – [in] Event handle
- Returns
Number of access points found
Join access point
Event helper functions for LWESP_EVT_STA_JOIN_AP event
-
lwespr_t lwesp_evt_sta_join_ap_get_result(lwesp_evt_t *cc)¶
Get command success result.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
Get access point info
Event helper functions for LWESP_EVT_STA_INFO_AP event
-
lwespr_t lwesp_evt_sta_info_ap_get_result(lwesp_evt_t *cc)¶
Get command result.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
const char *lwesp_evt_sta_info_ap_get_ssid(lwesp_evt_t *cc)¶
Get current AP name.
- Parameters
cc – [in] Event handle
- Returns
AP name
-
lwesp_mac_t lwesp_evt_sta_info_ap_get_mac(lwesp_evt_t *cc)¶
Get current AP MAC address.
- Parameters
cc – [in] Event handle
- Returns
AP MAC address
-
uint8_t lwesp_evt_sta_info_ap_get_channel(lwesp_evt_t *cc)¶
Get current AP channel.
- Parameters
cc – [in] Event handle
- Returns
AP channel
-
int16_t lwesp_evt_sta_info_ap_get_rssi(lwesp_evt_t *cc)¶
Get current AP rssi.
- Parameters
cc – [in] Event handle
- Returns
AP rssi
Get host address by name
Event helper functions for LWESP_EVT_DNS_HOSTBYNAME event
-
lwespr_t lwesp_evt_dns_hostbyname_get_result(lwesp_evt_t *cc)¶
Get resolve result.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
const char *lwesp_evt_dns_hostbyname_get_host(lwesp_evt_t *cc)¶
Get hostname used to resolve IP address.
- Parameters
cc – [in] Event handle
- Returns
Hostname
-
lwesp_ip_t *lwesp_evt_dns_hostbyname_get_ip(lwesp_evt_t *cc)¶
Get IP address from DNS function.
- Parameters
cc – [in] Event handle
- Returns
IP address
Ping
Event helper functions for LWESP_EVT_PING event
-
lwespr_t lwesp_evt_ping_get_result(lwesp_evt_t *cc)¶
Get ping status.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
const char *lwesp_evt_ping_get_host(lwesp_evt_t *cc)¶
Get hostname used to ping.
- Parameters
cc – [in] Event handle
- Returns
Hostname
-
uint32_t lwesp_evt_ping_get_time(lwesp_evt_t *cc)¶
Get time required for ping.
- Parameters
cc – [in] Event handle
- Returns
Ping time
Web Server
Event helper functions for LWESP_EVT_WEBSERVER event
-
uint8_t lwesp_evt_webserver_get_status(lwesp_evt_t *cc)¶
Get web server status.
- Parameters
cc – [in] Event handle
- Returns
Web server status code
Server
Event helper functions for LWESP_EVT_SERVER event
-
lwespr_t lwesp_evt_server_get_result(lwesp_evt_t *cc)¶
Get server command result.
- Parameters
cc – [in] Event handle
- Returns
Member of lwespr_t enumeration
-
lwesp_port_t lwesp_evt_server_get_port(lwesp_evt_t *cc)¶
Get port for server operation.
- Parameters
cc – [in] Event handle
- Returns
Server port
-
uint8_t lwesp_evt_server_is_enable(lwesp_evt_t *cc)¶
Check if operation was to enable or disable server.
- Parameters
cc – [in] Event handle
- Returns
1
if enable,0
otherwise
Typedefs
Enums
-
enum lwesp_evt_type_t¶
List of possible callback types received to user.
Values:
-
enumerator LWESP_EVT_INIT_FINISH¶
Initialization has been finished at this point
-
enumerator LWESP_EVT_RESET_DETECTED¶
Device reset detected
-
enumerator LWESP_EVT_RESET¶
Device reset operation finished
-
enumerator LWESP_EVT_RESTORE¶
Device restore operation finished
-
enumerator LWESP_EVT_CMD_TIMEOUT¶
Timeout on command. When application receives this event, it may reset system as there was (maybe) a problem in device
-
enumerator LWESP_EVT_DEVICE_PRESENT¶
Notification when device present status changes
-
enumerator LWESP_EVT_AT_VERSION_NOT_SUPPORTED¶
Library does not support firmware version on ESP device.
-
enumerator LWESP_EVT_CONN_RECV¶
Connection data received
-
enumerator LWESP_EVT_CONN_SEND¶
Connection data send
-
enumerator LWESP_EVT_CONN_ACTIVE¶
Connection just became active
-
enumerator LWESP_EVT_CONN_ERROR¶
Client connection start was not successful
-
enumerator LWESP_EVT_CONN_CLOSE¶
Connection close event. Check status if successful
-
enumerator LWESP_EVT_CONN_POLL¶
Poll for connection if there are any changes
-
enumerator LWESP_EVT_SERVER¶
Server status changed
-
enumerator LWESP_EVT_KEEP_ALIVE¶
Generic keep-alive event type, used as periodic timeout. Optionally enabled with LWESP_CFG_KEEP_ALIVE
-
enumerator LWESP_EVT_WIFI_CONNECTED¶
Station just connected to AP
-
enumerator LWESP_EVT_WIFI_GOT_IP¶
Station has valid IP. When this event is received to application, no IP has been read from device. Stack will proceed with IP read from device and will later send LWESP_EVT_WIFI_IP_ACQUIRED event
-
enumerator LWESP_EVT_WIFI_DISCONNECTED¶
Station just disconnected from AP
-
enumerator LWESP_EVT_WIFI_IP_ACQUIRED¶
Station IP address acquired. At this point, valid IP address has been received from device. Application may use lwesp_sta_copy_ip function to read it
-
enumerator LWESP_EVT_STA_LIST_AP¶
Station listed APs event
-
enumerator LWESP_EVT_STA_JOIN_AP¶
Join to access point
-
enumerator LWESP_EVT_STA_INFO_AP¶
Station AP info (name, mac, channel, rssi)
-
enumerator LWESP_EVT_AP_CONNECTED_STA¶
New station just connected to ESP’s access point
-
enumerator LWESP_EVT_AP_DISCONNECTED_STA¶
New station just disconnected from ESP’s access point
-
enumerator LWESP_EVT_AP_IP_STA¶
New station just received IP from ESP’s access point
-
enumerator LWESP_EVT_DNS_HOSTBYNAME¶
DNS domain service finished
-
enumerator LWESP_EVT_PING¶
PING service finished
-
enumerator LWESP_EVT_WEBSERVER¶
Web server events
-
enumerator LWESP_EVT_INIT_FINISH¶
Functions
-
lwespr_t lwesp_evt_register(lwesp_evt_fn fn)¶
Register event function for global (non-connection based) events.
-
lwespr_t lwesp_evt_unregister(lwesp_evt_fn fn)¶
Unregister callback function for global (non-connection based) events.
Note
Function must be first registered using lwesp_evt_register
-
lwesp_evt_type_t lwesp_evt_get_type(lwesp_evt_t *cc)¶
Get event type.
- Parameters
cc – [in] Event handle
- Returns
Event type. Member of lwesp_evt_type_t enumeration
-
struct lwesp_evt_t¶
- #include <lwesp_typedefs.h>
Global callback structure to pass as parameter to callback function.
Public Members
-
lwesp_evt_type_t type¶
Callback type
-
uint8_t forced¶
Set to
1
if reset forced by userSet to 1 if connection action was forced when active: 1 = CLIENT, 0 = SERVER when closed, 1 = CMD, 0 = REMOTE
-
struct lwesp_evt_t::[anonymous]::[anonymous] reset_detected¶
Reset occurred. Use with LWESP_EVT_RESET_DETECTED event
-
lwespr_t res¶
Reset operation result
Restore operation result
Send data result
Result of close event. Set to lwespOK on success
Status of command
Result of command
-
struct lwesp_evt_t::[anonymous]::[anonymous] reset¶
Reset sequence finish. Use with LWESP_EVT_RESET event
-
struct lwesp_evt_t::[anonymous]::[anonymous] restore¶
Restore sequence finish. Use with LWESP_EVT_RESTORE event
-
lwesp_conn_p conn¶
Connection where data were received
Connection where data were sent
Pointer to connection
Set connection pointer
-
lwesp_pbuf_p buff¶
Pointer to received data
-
struct lwesp_evt_t::[anonymous]::[anonymous] conn_data_recv¶
Network data received. Use with LWESP_EVT_CONN_RECV event
-
size_t sent¶
Number of bytes sent on connection
-
struct lwesp_evt_t::[anonymous]::[anonymous] conn_data_send¶
Data send. Use with LWESP_EVT_CONN_SEND event
-
const char *host¶
Host to use for connection
Host name for DNS lookup
Host name for ping
-
lwesp_port_t port¶
Remote port used for connection
Server port number
-
lwesp_conn_type_t type
Connection type
-
void *arg¶
Connection user argument
-
struct lwesp_evt_t::[anonymous]::[anonymous] conn_error¶
Client connection start error. Use with LWESP_EVT_CONN_ERROR event
-
uint8_t client¶
Set to 1 if connection is/was client mode
-
struct lwesp_evt_t::[anonymous]::[anonymous] conn_active_close¶
Process active and closed statuses at the same time. Use with LWESP_EVT_CONN_ACTIVE or LWESP_EVT_CONN_CLOSE events
-
struct lwesp_evt_t::[anonymous]::[anonymous] conn_poll¶
Polling active connection to check for timeouts. Use with LWESP_EVT_CONN_POLL event
-
uint8_t en¶
Status to enable/disable server
-
struct lwesp_evt_t::[anonymous]::[anonymous] server¶
Server change event. Use with LWESP_EVT_SERVER event
-
lwesp_ap_t *aps¶
Pointer to access points
-
size_t len¶
Number of access points found
-
struct lwesp_evt_t::[anonymous]::[anonymous] sta_list_ap¶
Station list access points. Use with LWESP_EVT_STA_LIST_AP event
-
struct lwesp_evt_t::[anonymous]::[anonymous] sta_join_ap¶
Join to access point. Use with LWESP_EVT_STA_JOIN_AP event
-
lwesp_sta_info_ap_t *info¶
AP info of current station
-
struct lwesp_evt_t::[anonymous]::[anonymous] sta_info_ap¶
Current AP informations. Use with LWESP_EVT_STA_INFO_AP event
-
lwesp_mac_t *mac¶
Station MAC address
-
struct lwesp_evt_t::[anonymous]::[anonymous] ap_conn_disconn_sta¶
A new station connected or disconnected to ESP’s access point. Use with LWESP_EVT_AP_CONNECTED_STA or LWESP_EVT_AP_DISCONNECTED_STA events
-
lwesp_ip_t *ip¶
Station IP address
Pointer to IP result
-
struct lwesp_evt_t::[anonymous]::[anonymous] ap_ip_sta¶
Station got IP address from ESP’s access point. Use with LWESP_EVT_AP_IP_STA event
-
struct lwesp_evt_t::[anonymous]::[anonymous] dns_hostbyname¶
DNS domain service finished. Use with LWESP_EVT_DNS_HOSTBYNAME event
-
uint32_t time¶
Time required for ping. Valid only if operation succedded
-
struct lwesp_evt_t::[anonymous]::[anonymous] ping¶
Ping finished. Use with LWESP_EVT_PING event
-
uint8_t code¶
Result of command
-
struct lwesp_evt_t::[anonymous]::[anonymous] ws_status¶
Ping finished. Use with LWESP_EVT_PING event
-
union lwesp_evt_t::[anonymous] evt¶
Callback event union
-
lwesp_evt_type_t type¶
-
uint8_t lwesp_evt_reset_detected_is_forced(lwesp_evt_t *cc)¶
Hostname¶
- group LWESP_HOSTNAME
Hostname API.
Functions
-
lwespr_t lwesp_hostname_set(const char *hostname, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set hostname of WiFi station.
- Parameters
hostname – [in] Name of ESP host
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_hostname_get(char *hostname, size_t size, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get hostname of WiFi station.
- Parameters
hostname – [in] Pointer to output variable holding memory to save hostname
size – [in] Size of buffer for hostname. Size includes memory for
NULL
terminationevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_hostname_set(const char *hostname, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Input module¶
Input module is used to input received data from ESP device to LwESP middleware part.
2
processing options are possible:
Indirect processing with
lwesp_input()
(default mode)Direct processing with
lwesp_input_process()
Tip
Direct or indirect processing mode is select by setting LWESP_CFG_INPUT_USE_PROCESS
configuration value.
Indirect processing¶
With indirect processing mode, every received character from ESP physical device is written to intermediate buffer between low-level driver and processing thread.
Function lwesp_input()
is used to write data to buffer, which is later processed
by processing thread.
Indirect processing mode allows embedded systems to write received data to buffer from interrupt context (outside threads). As a drawback, its performance is decreased as it involves copying every receive character to intermediate buffer, and may also introduce RAM memory footprint increase.
Direct processing¶
Direct processing is targeting more advanced host controllers, like STM32 or WIN32 implementation use. It is developed with DMA support in mind, allowing low-level drivers to skip intermediate data buffer and process input bytes directly.
Note
When using this mode, function lwesp_input_process()
must be used and it may
only be called from thread context. Processing of input bytes is done in low-level
input thread, started by application.
Tip
Check Porting guide for implementation examples.
- group LWESP_INPUT
Input function for received data.
Functions
-
lwespr_t lwesp_input(const void *data, size_t len)¶
Write data to input buffer.
Note
LWESP_CFG_INPUT_USE_PROCESS must be disabled to use this function
-
lwespr_t lwesp_input_process(const void *data, size_t len)¶
Process input data directly without writing it to input buffer.
Note
This function may only be used when in OS mode, where single thread is dedicated for input read of AT receive
Note
LWESP_CFG_INPUT_USE_PROCESS must be enabled to use this function
-
lwespr_t lwesp_input(const void *data, size_t len)¶
Multicast DNS¶
- group LWESP_MDNS
mDNS function
Functions
-
lwespr_t lwesp_mdns_set_config(uint8_t en, const char *host, const char *server, lwesp_port_t port, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure mDNS parameters with hostname and server.
- Parameters
en – [in] Status to enable
1
or disable0
mDNS functionhost – [in] mDNS host name
server – [in] mDNS server name
port – [in] mDNS server port number
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_mdns_set_config(uint8_t en, const char *host, const char *server, lwesp_port_t port, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Memory manager¶
- group LWESP_MEM
Dynamic memory manager.
Functions
-
uint8_t lwesp_mem_assignmemory(const lwesp_mem_region_t *regions, size_t size)¶
Assign memory region(s) for allocation functions.
Note
You can allocate multiple regions by assigning start address and region size in units of bytes
Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
- Parameters
regions – [in] Pointer to list of regions to use for allocations
len – [in] Number of regions to use
- Returns
1
on success,0
otherwise
-
void *lwesp_mem_malloc(size_t size)¶
Allocate memory of specific size.
Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
size – [in] Number of bytes to allocate
- Returns
Memory address on success,
NULL
otherwise
-
void *lwesp_mem_realloc(void *ptr, size_t size)¶
Reallocate memory to specific size.
Note
After new memory is allocated, content of old one is copied to new memory
Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
ptr – [in] Pointer to current allocated memory to resize, returned using lwesp_mem_malloc, lwesp_mem_calloc or lwesp_mem_realloc functions
size – [in] Number of bytes to allocate on new memory
- Returns
Memory address on success,
NULL
otherwise
-
void *lwesp_mem_calloc(size_t num, size_t size)¶
Allocate memory of specific size and set memory to zero.
Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
num – [in] Number of elements to allocate
size – [in] Size of each element
- Returns
Memory address on success,
NULL
otherwise
-
void lwesp_mem_free(void *ptr)¶
Free memory.
Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
ptr – [in] Pointer to memory previously returned using lwesp_mem_malloc, lwesp_mem_calloc or lwesp_mem_realloc functions
-
uint8_t lwesp_mem_free_s(void **ptr)¶
Free memory in safe way by invalidating pointer after freeing.
- Parameters
ptr – [in] Pointer to pointer to allocated memory to free
- Returns
1
on success,0
otherwise
-
struct lwesp_mem_region_t¶
- #include <lwesp_mem.h>
Single memory region descriptor.
-
uint8_t lwesp_mem_assignmemory(const lwesp_mem_region_t *regions, size_t size)¶
Packet buffer¶
Packet buffer (or pbuf) is buffer manager to handle received data from any connection. It is optimized to construct big buffer of smaller chunks of fragmented data as received bytes are not always coming as single packet.
Pbuf block diagram¶
Block diagram of pbuf chain¶
Image above shows structure of pbuf chain. Each pbuf consists of:
Pointer to next pbuf, or
NULL
when it is last in chainLength of current packet length
Length of current packet and all next in chain
If pbuf is last in chain, total length is the same as current packet length
Reference counter, indicating how many pointers point to current pbuf
Actual buffer data
Top image shows 3
pbufs connected to single chain.
There are 2
custom pointer variables to point at different pbuf structures. Second pbuf has reference counter set to 2
, as 2
variables point to it:
next of pbuf 1 is the first one
User variable 2 is the second one
Block number |
Next pbuf |
Block size |
Total size in chain |
Reference counter |
---|---|---|---|---|
Block 1 |
Block 2 |
|
|
|
Block 2 |
Block 3 |
|
|
|
Block 3 |
|
|
|
|
Reference counter¶
Reference counter holds number of references (or variables) pointing to this block. It is used to properly handle memory free operation, especially when pbuf is used by lib core and application layer.
Note
If there would be no reference counter information and application would free memory while another part of library still uses its reference, application would invoke undefined behavior and system could crash instantly.
When application tries to free pbuf chain as on first image, it would normally call lwesp_pbuf_free()
function. That would:
Decrease reference counter by
1
If reference counter
== 0
, it removes it from chain list and frees packet buffer memoryIf reference counter
!= 0
after decrease, it stops free procedureGo to next pbuf in chain and repeat steps
As per first example, result of freeing from user variable 1 would look similar to image and table below.
First block (blue) had reference counter set to 1
prior freeing operation.
It was successfully removed as user variable 1 was the only one pointing to it,
while second (green) block had reference counter set to 2
, preventing free operation.
Block diagram of pbuf chain after free from user variable 1¶
Block number |
Next pbuf |
Block size |
Total size in chain |
Reference counter |
---|---|---|---|---|
Block 2 |
Block 3 |
|
|
|
Block 3 |
|
|
|
|
Note
Block 1 has been successfully freed, but since block 2 had reference counter set to 2
before, it was only decreased by 1
to a new value 1
and free operation stopped instead.
User variable 2 is still using pbuf starting at block 2 and must manually call lwesp_pbuf_free()
to free it.
Concatenating vs chaining¶
This section will explain difference between concat and chain operations.
Both operations link 2
pbufs together in a chain of pbufs,
difference is that chain operation increases reference counter to linked pbuf,
while concat keeps reference counter at its current status.
Different pbufs, each pointed to by its own variable¶
Concat operation shall be used when 2
pbufs are linked together and reference to second is no longer used.
Structure after pbuf concat¶
After concating 2 pbufs together, reference counter of second is still set to 1
, however we can see that 2
pointers point to second pbuf.
Note
After application calls lwesp_pbuf_cat()
, it must not use pointer which points to second pbuf.
This would invoke undefined behavior if one pointer tries to free memory while second still points to it.
An example code showing proper usage of concat operation:
1lwesp_pbuf_p a, b;
2
3/* Create 2 pbufs of different sizes */
4a = lwesp_pbuf_new(10);
5b = lwesp_pbuf_new(20);
6
7/* Link them together with concat operation */
8/* Reference on b will stay as is, won't be increased */
9lwesp_pbuf_cat(a, b);
10
11/*
12 * Operating with b variable has from now on undefined behavior,
13 * application shall stop using variable b to access pbuf.
14 *
15 * The best way would be to set b reference to NULL
16 */
17b = NULL;
18
19/*
20 * When application doesn't need pbufs anymore,
21 * free a and it will also free b
22 */
23lwesp_pbuf_free(a);
Chain operation shall be used when 2
pbufs are linked together and reference to second is still required.
Structure after pbuf chain¶
After chainin 2 pbufs together, reference counter of second is increased by 1
, which allows application to reference second pbuf separatelly.
Note
After application calls lwesp_pbuf_chain()
,
it also has to manually free its reference using lwesp_pbuf_free()
function.
Forgetting to free pbuf invokes memory leak
An example code showing proper usage of chain operation:
1lwesp_pbuf_p a, b;
2
3/* Create 2 pbufs of different sizes */
4a = lwesp_pbuf_new(10);
5b = lwesp_pbuf_new(20);
6
7/* Chain both pbufs together */
8/* This will increase reference on b as 2 variables now point to it */
9lwesp_pbuf_chain(a, b);
10
11/*
12 * When application does not need a anymore, it may free it
13
14 * This will free only pbuf a, as pbuf b has now 2 references:
15 * - one from pbuf a
16 * - one from variable b
17 */
18
19/* If application calls this, it will free only first pbuf */
20/* As there is link to b pbuf somewhere */
21lwesp_pbuf_free(a);
22
23/* Reset a variable, not used anymore */
24a = NULL;
25
26/*
27 * At this point, b is still valid memory block,
28 * but when application doesn't need it anymore,
29 * it should free it, otherwise memory leak appears
30 */
31lwesp_pbuf_free(b);
32
33/* Reset b variable */
34b = NULL;
Each pbuf holds some amount of data bytes. When multiple pbufs are linked together (either chained or concated), blocks of raw data are not linked to contiguous memory block. It is necessary to process block by block manually.
An example code showing proper reading of any pbuf:
1const void* data;
2size_t pos, len;
3lwesp_pbuf_p a, b, c;
4
5const char str_a[] = "This is one long";
6const char str_a[] = "string. We want to save";
7const char str_a[] = "chain of pbufs to file";
8
9/* Create pbufs to hold these strings */
10a = lwesp_pbuf_new(strlen(str_a));
11b = lwesp_pbuf_new(strlen(str_b));
12c = lwesp_pbuf_new(strlen(str_c));
13
14/* Write data to pbufs */
15lwesp_pbuf_take(a, str_a, strlen(str_a), 0);
16lwesp_pbuf_take(b, str_b, strlen(str_b), 0);
17lwesp_pbuf_take(c, str_c, strlen(str_c), 0);
18
19/* Connect pbufs together */
20lwesp_pbuf_chain(a, b);
21lwesp_pbuf_chain(a, c);
22
23/*
24 * pbuf a now contains chain of b and c together
25 * and at this point application wants to print (or save) data from chained pbuf
26 *
27 * Process pbuf by pbuf with code below
28 */
29
30/*
31 * Get linear address of current pbuf at specific offset
32 * Function will return pointer to memory address at specific position
33 * and `len` will hold length of data block
34 */
35pos = 0;
36while ((data = lwesp_pbuf_get_linear_addr(a, pos, &len)) != NULL) {
37 /* Custom process function... */
38 /* Process data with data pointer and block length */
39 process_data(data, len);
40 printf("Str: %.*s", len, data);
41
42 /* Increase offset position for next block */
43 pos += len;
44}
45
46/* Call free only on a pbuf. Since it is chained, b and c will be freed too */
47lwesp_pbuf_free(a);
- group LWESP_PBUF
Packet buffer manager.
Typedefs
-
typedef struct lwesp_pbuf *lwesp_pbuf_p¶
Pointer to lwesp_pbuf_t structure.
Functions
-
lwesp_pbuf_p lwesp_pbuf_new(size_t len)¶
Allocate packet buffer for network data of specific size.
- Parameters
len – [in] Length of payload memory to allocate
- Returns
Pointer to allocated memory,
NULL
otherwise
-
size_t lwesp_pbuf_free(lwesp_pbuf_p pbuf)¶
Free previously allocated packet buffer.
- Parameters
pbuf – [in] Packet buffer to free
- Returns
Number of freed pbufs from head
-
void *lwesp_pbuf_data(const lwesp_pbuf_p pbuf)¶
Get data pointer from packet buffer.
- Parameters
pbuf – [in] Packet buffer
- Returns
Pointer to data buffer on success,
NULL
otherwise
-
size_t lwesp_pbuf_length(const lwesp_pbuf_p pbuf, uint8_t tot)¶
Get length of packet buffer.
- Parameters
pbuf – [in] Packet buffer to get length for
tot – [in] Set to
1
to return total packet chain length or0
to get only first packet length
- Returns
Length of data in units of bytes
-
uint8_t lwesp_pbuf_set_length(lwesp_pbuf_p pbuf, size_t new_len)¶
Set new length of pbuf.
Note
New length can only be smaller than existing one. It has no effect when greater than existing one
Note
This function can be used on single-chain pbufs only, without
next
pbuf in chain- Parameters
pbuf – [in] Pbuf to make it smaller
new_len – [in] New length in units of bytes
- Returns
1
on success,0
otherwise
-
lwespr_t lwesp_pbuf_take(lwesp_pbuf_p pbuf, const void *data, size_t len, size_t offset)¶
Copy user data to chain of pbufs.
-
size_t lwesp_pbuf_copy(lwesp_pbuf_p pbuf, void *data, size_t len, size_t offset)¶
Copy memory from pbuf to user linear memory.
- Parameters
pbuf – [in] Pbuf to copy from
data – [out] User linear memory to copy to
len – [in] Length of data in units of bytes
offset – [in] Possible start offset in pbuf
- Returns
Number of bytes copied
-
lwespr_t lwesp_pbuf_cat(lwesp_pbuf_p head, const lwesp_pbuf_p tail)¶
Concatenate
2
packet buffers together to one big packet.Note
After
tail
pbuf has been added tohead
pbuf chain, it must not be referenced by user anymore as it is now completely controlled byhead
pbuf. In simple words, when user calls this function, it should not call lwesp_pbuf_free function anymore, as it might make memory undefined forhead
pbuf.
-
lwespr_t lwesp_pbuf_chain(lwesp_pbuf_p head, lwesp_pbuf_p tail)¶
Chain 2 pbufs together. Similar to lwesp_pbuf_cat but now new reference is done from head pbuf to tail pbuf.
Note
After this function call, user must call lwesp_pbuf_free to remove its reference to tail pbuf and allow control to head pbuf:
lwesp_pbuf_free(tail)
-
lwesp_pbuf_p lwesp_pbuf_unchain(lwesp_pbuf_p head)¶
Unchain first pbuf from list and return second one.
tot_len
andlen
fields are adjusted to reflect new values and reference counter isas is
Note
After unchain, user must take care of both pbufs (
head
andnew returned one
)- Parameters
head – [in] First pbuf in chain to remove from chain
- Returns
Next pbuf after
head
-
lwespr_t lwesp_pbuf_ref(lwesp_pbuf_p pbuf)¶
Increment reference count on pbuf.
-
uint8_t lwesp_pbuf_get_at(const lwesp_pbuf_p pbuf, size_t pos, uint8_t *el)¶
Get value from pbuf at specific position.
- Parameters
pbuf – [in] Pbuf used to get data from
pos – [in] Position at which to get element
el – [out] Output variable to save element value at desired position
- Returns
1
on success,0
otherwise
-
size_t lwesp_pbuf_memcmp(const lwesp_pbuf_p pbuf, const void *data, size_t len, size_t offset)¶
Compare pbuf memory with memory from data.
Note
Compare is done on entire pbuf chain
- Parameters
pbuf – [in] Pbuf used to compare with data memory
data – [in] Actual data to compare with
len – [in] Length of input data in units of bytes
offset – [in] Start offset to use when comparing data
- Returns
0
if equal,LWESP_SIZET_MAX
if memory/offset too big or anything between if not equal
-
size_t lwesp_pbuf_strcmp(const lwesp_pbuf_p pbuf, const char *str, size_t offset)¶
Compare pbuf memory with input string.
Note
Compare is done on entire pbuf chain
- Parameters
pbuf – [in] Pbuf used to compare with data memory
str – [in] String to be compared with pbuf
offset – [in] Start memory offset in pbuf
- Returns
0
if equal,LWESP_SIZET_MAX
if memory/offset too big or anything between if not equal
-
size_t lwesp_pbuf_memfind(const lwesp_pbuf_p pbuf, const void *data, size_t len, size_t off)¶
Find desired needle in a haystack.
- Parameters
pbuf – [in] Pbuf used as haystack
needle – [in] Data memory used as needle
len – [in] Length of needle memory
off – [in] Starting offset in pbuf memory
- Returns
LWESP_SIZET_MAX
if no match or position where in pbuf we have a match
-
size_t lwesp_pbuf_strfind(const lwesp_pbuf_p pbuf, const char *str, size_t off)¶
Find desired needle (str) in a haystack (pbuf)
- Parameters
pbuf – [in] Pbuf used as haystack
str – [in] String to search for in pbuf
off – [in] Starting offset in pbuf memory
- Returns
LWESP_SIZET_MAX
if no match or position where in pbuf we have a match
-
uint8_t lwesp_pbuf_advance(lwesp_pbuf_p pbuf, int len)¶
Advance pbuf payload pointer by number of len bytes. It can only advance single pbuf in a chain.
Note
When other pbufs are referencing current one, they are not adjusted in length and total length
- Parameters
pbuf – [in] Pbuf to advance
len – [in] Number of bytes to advance. when negative is used, buffer size is increased only if it was decreased before
- Returns
1
on success,0
otherwise
-
lwesp_pbuf_p lwesp_pbuf_skip(lwesp_pbuf_p pbuf, size_t offset, size_t *new_offset)¶
Skip a list of pbufs for desired offset.
Note
Reference is not changed after return and user must not free the memory of new pbuf directly
- Parameters
pbuf – [in] Start of pbuf chain
offset – [in] Offset in units of bytes to skip
new_offset – [out] Pointer to output variable to save new offset in returned pbuf
- Returns
New pbuf on success,
NULL
otherwise
-
void *lwesp_pbuf_get_linear_addr(const lwesp_pbuf_p pbuf, size_t offset, size_t *new_len)¶
Get linear offset address for pbuf from specific offset.
Note
Since pbuf memory can be fragmented in chain, you may need to call function multiple times to get memory for entire pbuf chain
- Parameters
pbuf – [in] Pbuf to get linear address
offset – [in] Start offset from where to start
new_len – [out] Length of memory returned by function
- Returns
Pointer to memory on success,
NULL
otherwise
-
void lwesp_pbuf_set_ip(lwesp_pbuf_p pbuf, const lwesp_ip_t *ip, lwesp_port_t port)¶
Set IP address and port number for received data.
- Parameters
pbuf – [in] Packet buffer
ip – [in] IP to assing to packet buffer
port – [in] Port number to assign to packet buffer
-
void lwesp_pbuf_dump(lwesp_pbuf_p p, uint8_t seq)¶
Dump and debug pbuf chain.
- Parameters
p – [in] Head pbuf to dump
seq – [in] Set to
1
to dump allpbufs
in linked list or0
to dump first one only
-
struct lwesp_pbuf_t¶
- #include <lwesp_private.h>
Packet buffer structure.
Public Members
-
struct lwesp_pbuf *next¶
Next pbuf in chain list
-
size_t tot_len¶
Total length of pbuf chain
-
size_t len¶
Length of payload
-
size_t ref¶
Number of references to this structure
-
uint8_t *payload¶
Pointer to payload memory
-
lwesp_ip_t ip¶
Remote address for received IPD data
-
lwesp_port_t port¶
Remote port for received IPD data
-
struct lwesp_pbuf *next¶
-
typedef struct lwesp_pbuf *lwesp_pbuf_p¶
Ping support¶
- group LWESP_PING
Ping server and get response time.
Functions
-
lwespr_t lwesp_ping(const char *host, uint32_t *time, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Ping server and get response time from it.
- Parameters
host – [in] Host name to ping
time – [out] Pointer to output variable to save ping time in units of milliseconds
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ping(const char *host, uint32_t *time, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Server¶
- group LWESP_SERVER
Server mode.
Functions
-
lwespr_t lwesp_set_server(uint8_t en, lwesp_port_t port, uint16_t max_conn, uint16_t timeout, lwesp_evt_fn cb, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Enables or disables server mode.
- Parameters
en – [in] Set to
1
to enable server,0
otherwiseport – [in] Port number used to listen on. Must also be used when disabling server mode
max_conn – [in] Number of maximal connections populated by server
timeout – [in] Time used to automatically close the connection in units of seconds. Set to
0
to disable timeout feature (not recommended)server_evt_fn – [in] Connection callback function for new connections started as server
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_set_server(uint8_t en, lwesp_port_t port, uint16_t max_conn, uint16_t timeout, lwesp_evt_fn cb, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Smart config¶
- group LWESP_SMART
SMART function on ESP device.
Functions
-
lwespr_t lwesp_smart_set_config(uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure SMART function on ESP device.
- Parameters
en – [in] Set to
1
to start SMART or0
to stop SMARTevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_smart_set_config(uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Simple Network Time Protocol¶
ESP has built-in support for Simple Network Time Protocol (SNTP). It is support through middleware API calls for configuring servers and reading actual date and time.
1#include "sntp.h"
2#include "lwesp/lwesp.h"
3
4/**
5 * \brief Run SNTP
6 */
7void
8sntp_gettime(void) {
9 lwesp_datetime_t dt;
10
11 /* Enable SNTP with default configuration for NTP servers */
12 if (lwesp_sntp_set_config(1, 1, NULL, NULL, NULL, NULL, NULL, 1) == lwespOK) {
13 lwesp_delay(5000);
14
15 /* Get actual time and print it */
16 if (lwesp_sntp_gettime(&dt, NULL, NULL, 1) == lwespOK) {
17 printf("Date & time: %d.%d.%d, %d:%d:%d\r\n",
18 (int)dt.date, (int)dt.month, (int)dt.year,
19 (int)dt.hours, (int)dt.minutes, (int)dt.seconds);
20 }
21 }
22}
- group LWESP_SNTP
Simple network time protocol supported by AT commands.
Functions
-
lwespr_t lwesp_sntp_set_config(uint8_t en, int8_t tz, const char *h1, const char *h2, const char *h3, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure SNTP mode parameters.
- Parameters
en – [in] Status whether SNTP mode is enabled or disabled on ESP device
tz – [in] Timezone to use when SNTP acquires time, between
-11
and13
h1 – [in] Optional first SNTP server for time. Set to
NULL
if not usedh2 – [in] Optional second SNTP server for time. Set to
NULL
if not usedh3 – [in] Optional third SNTP server for time. Set to
NULL
if not usedevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sntp_gettime(lwesp_datetime_t *dt, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get time from SNTP servers.
- Parameters
dt – [out] Pointer to lwesp_datetime_t structure to fill with date and time values
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sntp_set_config(uint8_t en, int8_t tz, const char *h1, const char *h2, const char *h3, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Station API¶
Station API is used to work with ESP acting in station mode. It allows to join other access point, scan for available access points or simply disconnect from it.
An example below is showing how all examples (coming with this library) scan for access point and then try to connect to AP from list of preferred one.
1#include "station_manager.h"
2#include "utils.h"
3#include "lwesp/lwesp.h"
4
5/**
6 * \brief Private access-point and station management system
7 *
8 * This is used for asynchronous connection to access point
9 */
10typedef struct {
11 size_t index_preferred_list; /*!< Current index position of preferred array */
12 size_t index_scanned_list; /*!< Current index position in array of scanned APs */
13
14 uint8_t command_is_running; /*!< Indicating if command is currently in progress */
15} prv_ap_data_t;
16
17/* Arguments for callback function */
18#define ARG_SCAN (void*)1
19#define ARG_CONNECT (void*)2
20
21/* Function declaration */
22static void prv_cmd_event_fn(lwespr_t status, void* arg);
23static void prv_try_next_access_point(void);
24
25/*
26 * List of preferred access points for ESP device
27 * SSID and password
28 *
29 * ESP will try to scan for access points
30 * and then compare them with the one on the list below
31 */
32static const ap_entry_t ap_list_preferred[] = {
33 //{ .ssid = "SSID name", .pass = "SSID password" },
34 { .ssid = "TilenM_ST", .pass = "its private" },
35 { .ssid = "Kaja", .pass = "kajagin2021" },
36 { .ssid = "Majerle WIFI", .pass = "majerle_internet_private" },
37 { .ssid = "Majerle AMIS", .pass = "majerle_internet_private" },
38};
39static lwesp_ap_t ap_list_scanned[100]; /* Scanned access points information */
40static size_t ap_list_scanned_len = 0; /* Number of scanned access points */
41static prv_ap_data_t ap_async_data; /* Asynchronous data structure */
42
43/* Command to execute to start scanning access points */
44#define prv_scan_ap_command_ex(blocking) lwesp_sta_list_ap(NULL, ap_list_scanned, LWESP_ARRAYSIZE(ap_list_scanned), &ap_list_scanned_len, NULL, NULL, (blocking))
45#define prv_scan_ap_command() do {\
46 if (!ap_async_data.command_is_running) { \
47 printf("Starting scan command on line %d\r\n", __LINE__);\
48 ap_async_data.command_is_running = lwesp_sta_list_ap(NULL, ap_list_scanned, LWESP_ARRAYSIZE(ap_list_scanned), &ap_list_scanned_len, prv_cmd_event_fn, ARG_SCAN, 0) == lwespOK; \
49 } \
50} while (0)
51
52/**
53 * \brief Every internal command execution callback
54 * \param[in] status: Execution status result
55 * \param[in] arg: Custom user argument
56 */
57static void
58prv_cmd_event_fn(lwespr_t status, void* arg) {
59 /*
60 * Command has now successfully finish
61 * and callbacks have been properly processed
62 */
63 ap_async_data.command_is_running = 0;
64
65 if (arg == ARG_SCAN) {
66 /* Immediately try to connect to access point after successful scan*/
67 prv_try_next_access_point();
68 }
69}
70
71/**
72 * \brief Try to connect to next access point on a list
73 */
74static void
75prv_try_next_access_point(void) {
76 uint8_t tried = 0;
77
78 /* No action to be done if command is currently in progress or already connected to network */
79 if (ap_async_data.command_is_running
80 || lwesp_sta_has_ip()) {
81 return;
82 }
83
84 /*
85 * Process complete list and try to find suitable match
86 *
87 * Use global variable for indexes to be able to call function multiple times
88 * and continue where it finished previously
89 */
90
91 /* List all preferred access points */
92 for (; ap_async_data.index_preferred_list < LWESP_ARRAYSIZE(ap_list_preferred);
93 ap_async_data.index_preferred_list++, ap_async_data.index_scanned_list = 0) {
94
95 /* List all scanned access points */
96 for (; ap_async_data.index_scanned_list < ap_list_scanned_len; ap_async_data.index_scanned_list++) {
97
98 /* Find a match if available */
99 if (strncmp(ap_list_scanned[ap_async_data.index_scanned_list].ssid,
100 ap_list_preferred[ap_async_data.index_preferred_list].ssid,
101 strlen(ap_list_preferred[ap_async_data.index_preferred_list].ssid)) == 0) {
102
103 /* Try to connect to the network */
104 if (!ap_async_data.command_is_running
105 && lwesp_sta_join(ap_list_preferred[ap_async_data.index_preferred_list].ssid,
106 ap_list_preferred[ap_async_data.index_preferred_list].pass,
107 NULL, prv_cmd_event_fn, ARG_CONNECT, 0) == lwespOK) {
108 ap_async_data.command_is_running = 1;
109
110 /* Go to next index for sub-for loop and exit */
111 ap_async_data.index_scanned_list++;
112 tried = 1;
113 goto stp;
114 } else {
115 /* We have a problem, needs to resume action in next run */
116 }
117 }
118 }
119 }
120
121 /* Restart scan operation if there was no try to connect and station has no IP */
122 if (!tried && !lwesp_sta_has_ip()) {
123 prv_scan_ap_command();
124 }
125stp:
126 return;
127}
128
129/**
130 * \brief Private event function for asynchronous scanning
131 * \param[in] evt: Event information
132 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
133 */
134static lwespr_t
135prv_evt_fn(lwesp_evt_t* evt) {
136 switch (evt->type) {
137 case LWESP_EVT_KEEP_ALIVE:
138 case LWESP_EVT_WIFI_DISCONNECTED: {
139 /* Try to connect to next access point */
140 prv_try_next_access_point();
141 break;
142 }
143 case LWESP_EVT_STA_LIST_AP: {
144 /*
145 * After scanning gets completed
146 * manually reset all indexes for comparison purposes
147 */
148 ap_async_data.index_scanned_list = 0;
149 ap_async_data.index_preferred_list = 0;
150
151 /* Actual connection try is done in function callback */
152 break;
153 }
154 default: break;
155 }
156 return lwespOK;
157}
158
159/**
160 * \brief Initialize asynchronous mode to connect to preferred access point
161 *
162 * Asynchronous mode relies on system events received by the application,
163 * to determine current device status if station is being, or not, connected to access point.
164 *
165 * When used, async acts only upon station connection change through callbacks,
166 * therefore it does not require additional system thread or user code,
167 * to be able to properly handle preferred access points.
168 * This certainly decreases memory consumption of the complete system.
169 *
170 * \ref LWESP_CFG_KEEP_ALIVE feature must be enable to properly handle all events
171 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
172 */
173lwespr_t
174station_manager_connect_to_access_point_async_init(void) {
175 /* Register system event function */
176 lwesp_evt_register(prv_evt_fn);
177
178 /*
179 * Start scanning process in non-blocking mode
180 *
181 * This is the only command being executed from non-callback mode,
182 * therefore it must be protected against other threads trying to access the same core
183 */
184 lwesp_core_lock();
185 prv_scan_ap_command();
186 lwesp_core_unlock();
187
188 /* Return all good, things will progress (from now-on) asynchronously */
189 return lwespOK;
190}
191
192/**
193 * \brief Connect to preferred access point in blocking mode
194 *
195 * This functionality can only be used if non-blocking approach is not used
196 *
197 * \note List of access points should be set by user in \ref ap_list structure
198 * \param[in] unlimited: When set to 1, function will block until SSID is found and connected
199 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
200 */
201lwespr_t
202connect_to_preferred_access_point(uint8_t unlimited) {
203 lwespr_t eres;
204 uint8_t tried;
205
206 /*
207 * Scan for network access points
208 * In case we have access point,
209 * try to connect to known AP
210 */
211 do {
212 if (lwesp_sta_has_ip()) {
213 return lwespOK;
214 }
215
216 /* Scan for access points visible to ESP device */
217 printf("Scanning access points...\r\n");
218 if ((eres = prv_scan_ap_command_ex(1)) == lwespOK) {
219 tried = 0;
220
221 /* Print all access points found by ESP */
222 for (size_t i = 0; i < ap_list_scanned_len; i++) {
223 printf("AP found: %s, CH: %d, RSSI: %d\r\n", ap_list_scanned[i].ssid, ap_list_scanned[i].ch, ap_list_scanned[i].rssi);
224 }
225
226 /* Process array of preferred access points with array of found points */
227 for (size_t j = 0; j < LWESP_ARRAYSIZE(ap_list_preferred); j++) {
228
229 /* Go through all scanned list */
230 for (size_t i = 0; i < ap_list_scanned_len; i++) {
231
232 /* Try to find a match between preferred and scanned */
233 if (strncmp(ap_list_scanned[i].ssid, ap_list_preferred[j].ssid, strlen(ap_list_scanned[i].ssid)) == 0) {
234 tried = 1;
235 printf("Connecting to \"%s\" network...\r\n", ap_list_preferred[j].ssid);
236
237 /* Try to join to access point */
238 if ((eres = lwesp_sta_join(ap_list_preferred[j].ssid, ap_list_preferred[j].pass, NULL, NULL, NULL, 1)) == lwespOK) {
239 lwesp_ip_t ip;
240 uint8_t is_dhcp;
241
242 printf("Connected to %s network!\r\n", ap_list_preferred[j].ssid);
243
244 lwesp_sta_copy_ip(&ip, NULL, NULL, &is_dhcp);
245 utils_print_ip("Station IP address: ", &ip, "\r\n");
246 printf("; Is DHCP: %d\r\n", (int)is_dhcp);
247 return lwespOK;
248 } else {
249 printf("Connection error: %d\r\n", (int)eres);
250 }
251 }
252 }
253 }
254 if (!tried) {
255 printf("No access points available with preferred SSID!\r\nPlease check station_manager.c file and edit preferred SSID access points!\r\n");
256 }
257 } else if (eres == lwespERRNODEVICE) {
258 printf("Device is not present!\r\n");
259 break;
260 } else {
261 printf("Error on WIFI scan procedure!\r\n");
262 }
263 if (!unlimited) {
264 break;
265 }
266 } while (1);
267 return lwespERR;
268}
- group LWESP_STA
Station API.
Functions
-
lwespr_t lwesp_sta_join(const char *name, const char *pass, const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Join as station to access point.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
name – [in] SSID of access point to connect to
pass – [in] Password of access point. Use
NULL
if AP does not have passwordmac – [in] Pointer to MAC address of AP. If multiple APs with same name exist, MAC may help to select proper one. Set to
NULL
if not neededevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_quit(const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Quit (disconnect) from access point.
-
lwespr_t lwesp_sta_autojoin(uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure auto join to access point on startup.
Note
For auto join feature, you need to do a join to access point with default mode. Check lwesp_sta_join for more information
- Parameters
en – [in] Set to
1
to enable or0
to disableevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_reconnect_set_config(uint16_t interval, uint16_t rep_cnt, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set reconnect interval and maximum tries when connection drops.
- Parameters
interval – [in] Interval in units of seconds. Valid numbers are
1-7200
or0
to disable reconnect featurerep_cnt – [in] Repeat counter. Number of maximum tries for reconnect. Valid entries are
1-1000
or0
to always try. This parameter is only valid if interval is not0
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_getip(lwesp_ip_t *ip, lwesp_ip_t *gw, lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get station IP address.
- Parameters
ip – [out] Pointer to variable to save IP address
gw – [out] Pointer to output variable to save gateway address
nm – [out] Pointer to output variable to save netmask address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_setip(const lwesp_ip_t *ip, const lwesp_ip_t *gw, const lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set station IP address.
Application may manually set IP address. When this happens, stack will check for DHCP settings and will read actual IP address from device. Once procedure is finished, LWESP_EVT_WIFI_IP_ACQUIRED event will be sent to application where user may read the actual new IP and DHCP settings.
Configuration changes will be saved in the NVS area of ESP device.
Note
DHCP is automatically disabled when using static IP address
- Parameters
ip – [in] Pointer to IP address
gw – [in] Pointer to gateway address. Set to
NULL
to use default gatewaynm – [in] Pointer to netmask address. Set to
NULL
to use default netmaskevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_getmac(lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get station MAC address.
- Parameters
mac – [out] Pointer to output variable to save MAC address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_setmac(const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set station MAC address.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
mac – [in] Pointer to variable with MAC address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
uint8_t lwesp_sta_has_ip(void)¶
Check if ESP got IP from access point.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_is_joined(void)¶
Check if station is connected to WiFi network.
- Returns
1
on success,0
otherwise
-
lwespr_t lwesp_sta_copy_ip(lwesp_ip_t *ip, lwesp_ip_t *gw, lwesp_ip_t *nm, uint8_t *is_dhcp)¶
Copy IP address from internal value to user variable.
Note
Use lwesp_sta_getip to refresh actual IP value from device
- Parameters
ip – [out] Pointer to output IP variable. Set to
NULL
if not interested in IP addressgw – [out] Pointer to output gateway variable. Set to
NULL
if not interested in gateway addressnm – [out] Pointer to output netmask variable. Set to
NULL
if not interested in netmask addressis_dhcp – [out] Pointer to output DHCP status variable. Set to
NULL
if not interested
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_list_ap(const char *ssid, lwesp_ap_t *aps, size_t apsl, size_t *apf, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
List for available access points ESP can connect to.
- Parameters
ssid – [in] Optional SSID name to search for. Set to
NULL
to disable filteraps – [in] Pointer to array of available access point parameters
apsl – [in] Length of aps array
apf – [out] Pointer to output variable to save number of access points found
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_get_ap_info(lwesp_sta_info_ap_t *info, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get current access point information (name, mac, channel, rssi)
Note
Access point station is currently connected to
- Parameters
info – [in] Pointer to connected access point information
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
uint8_t lwesp_sta_is_ap_802_11b(lwesp_ap_t *ap)¶
Check if access point is
802.11b
compatible.- Parameters
ap – [in] Access point detailes acquired by lwesp_sta_list_ap
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_is_ap_802_11g(lwesp_ap_t *ap)¶
Check if access point is
802.11g
compatible.- Parameters
ap – [in] Access point detailes acquired by lwesp_sta_list_ap
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_is_ap_802_11n(lwesp_ap_t *ap)¶
Check if access point is
802.11n
compatible.- Parameters
ap – [in] Access point detailes acquired by lwesp_sta_list_ap
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_has_ipv6_local(void)¶
Check if station has local IPV6 IP Local IP is used between station and router.
Note
Defined as macro with
0
constant if LWESP_CFG_IPV6 is disabled- Returns
1
if local IPv6 is available,0
otherwise
-
uint8_t lwesp_sta_has_ipv6_global(void)¶
Check if station has global IPV6 IP Global IP is used router and outside network.
Note
Defined as macro with
0
constant if LWESP_CFG_IPV6 is disabled- Returns
1
if global IPv6 is available,0
otherwise
-
struct lwesp_sta_t¶
- #include <lwesp_typedefs.h>
Station data structure.
Public Members
-
lwesp_ip_t ip¶
IP address of connected station
-
lwesp_mac_t mac¶
MAC address of connected station
-
lwesp_ip_t ip¶
-
lwespr_t lwesp_sta_join(const char *name, const char *pass, const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Timeout manager¶
Timeout manager allows application to call specific function at desired time. It is used in middleware (and can be used by application too) to poll active connections.
Note
Callback function is called from processing thread. It is not allowed to call any blocking API function from it.
When application registers timeout, it needs to set timeout, callback function and optional user argument. When timeout elapses, ESP middleware will call timeout callback.
This feature can be considered as single-shot software timer.
- group LWESP_TIMEOUT
Timeout manager.
Typedefs
-
typedef void (*lwesp_timeout_fn)(void *arg)¶
Timeout callback function prototype.
- Param arg
[in] Custom user argument
Functions
-
lwespr_t lwesp_timeout_add(uint32_t time, lwesp_timeout_fn fn, void *arg)¶
Add new timeout to processing list.
-
lwespr_t lwesp_timeout_remove(lwesp_timeout_fn fn)¶
Remove callback from timeout list.
-
typedef void (*lwesp_timeout_fn)(void *arg)¶
Structures and enumerations¶
- group LWESP_TYPEDEFS
List of core structures and enumerations.
Typedefs
-
typedef uint16_t lwesp_port_t¶
Port variable.
Enums
-
enum lwesp_cmd_t¶
List of possible messages.
Values:
-
enumerator LWESP_CMD_IDLE¶
IDLE mode
-
enumerator LWESP_CMD_RESET¶
Reset device
-
enumerator LWESP_CMD_ATE0¶
Disable ECHO mode on AT commands
-
enumerator LWESP_CMD_ATE1¶
Enable ECHO mode on AT commands
-
enumerator LWESP_CMD_GMR¶
Get AT commands version
-
enumerator LWESP_CMD_GSLP¶
Set ESP to sleep mode
-
enumerator LWESP_CMD_RESTORE¶
Restore ESP internal settings to default values
-
enumerator LWESP_CMD_UART¶
-
enumerator LWESP_CMD_SLEEP¶
-
enumerator LWESP_CMD_WAKEUPGPIO¶
-
enumerator LWESP_CMD_RFPOWER¶
-
enumerator LWESP_CMD_RFVDD¶
-
enumerator LWESP_CMD_RFAUTOTRACE¶
-
enumerator LWESP_CMD_SYSRAM¶
-
enumerator LWESP_CMD_SYSADC¶
-
enumerator LWESP_CMD_SYSMSG¶
-
enumerator LWESP_CMD_SYSLOG¶
-
enumerator LWESP_CMD_WIFI_CWMODE¶
Set wifi mode
-
enumerator LWESP_CMD_WIFI_CWMODE_GET¶
Get wifi mode
-
enumerator LWESP_CMD_WIFI_CWLAPOPT¶
Configure what is visible on CWLAP response
-
enumerator LWESP_CMD_WIFI_IPV6¶
Configure IPv6 support
-
enumerator LWESP_CMD_WIFI_CWJAP¶
Connect to access point
-
enumerator LWESP_CMD_WIFI_CWRECONNCFG¶
Setup reconnect interval and maximum tries
-
enumerator LWESP_CMD_WIFI_CWJAP_GET¶
Info of the connected access point
-
enumerator LWESP_CMD_WIFI_CWQAP¶
Disconnect from access point
-
enumerator LWESP_CMD_WIFI_CWLAP¶
List available access points
-
enumerator LWESP_CMD_WIFI_CIPSTAMAC_GET¶
Get MAC address of ESP station
-
enumerator LWESP_CMD_WIFI_CIPSTAMAC_SET¶
Set MAC address of ESP station
-
enumerator LWESP_CMD_WIFI_CIPSTA_GET¶
Get IP address of ESP station
-
enumerator LWESP_CMD_WIFI_CIPSTA_SET¶
Set IP address of ESP station
-
enumerator LWESP_CMD_WIFI_CWAUTOCONN¶
Configure auto connection to access point
-
enumerator LWESP_CMD_WIFI_CWDHCP_SET¶
Set DHCP config
-
enumerator LWESP_CMD_WIFI_CWDHCP_GET¶
Get DHCP config
-
enumerator LWESP_CMD_WIFI_CWDHCPS_SET¶
Set DHCP SoftAP IP config
-
enumerator LWESP_CMD_WIFI_CWDHCPS_GET¶
Get DHCP SoftAP IP config
-
enumerator LWESP_CMD_WIFI_CWSAP_GET¶
Get software access point configuration
-
enumerator LWESP_CMD_WIFI_CWSAP_SET¶
Set software access point configuration
-
enumerator LWESP_CMD_WIFI_CIPAPMAC_GET¶
Get MAC address of ESP access point
-
enumerator LWESP_CMD_WIFI_CIPAPMAC_SET¶
Set MAC address of ESP access point
-
enumerator LWESP_CMD_WIFI_CIPAP_GET¶
Get IP address of ESP access point
-
enumerator LWESP_CMD_WIFI_CIPAP_SET¶
Set IP address of ESP access point
-
enumerator LWESP_CMD_WIFI_CWLIF¶
Get connected stations on access point
-
enumerator LWESP_CMD_WIFI_CWQIF¶
Discnnect station from SoftAP
-
enumerator LWESP_CMD_WIFI_WPS¶
Set WPS option
-
enumerator LWESP_CMD_WIFI_MDNS¶
Configure MDNS function
-
enumerator LWESP_CMD_WIFI_CWHOSTNAME_SET¶
Set device hostname
-
enumerator LWESP_CMD_WIFI_CWHOSTNAME_GET¶
Get device hostname
-
enumerator LWESP_CMD_TCPIP_CIPDOMAIN¶
Get IP address from domain name = DNS function
-
enumerator LWESP_CMD_TCPIP_CIPDNS_SET¶
Configure user specific DNS servers
-
enumerator LWESP_CMD_TCPIP_CIPDNS_GET¶
Get DNS configuration
-
enumerator LWESP_CMD_TCPIP_CIPSTATUS¶
Get status of connections (deprecated, used on ESP8266 devices)
-
enumerator LWESP_CMD_TCPIP_CIPSTATE¶
Obtain connection state and information
-
enumerator LWESP_CMD_TCPIP_CIPSTART¶
Start client connection
-
enumerator LWESP_CMD_TCPIP_CIPSEND¶
Send network data
-
enumerator LWESP_CMD_TCPIP_CIPCLOSE¶
Close active connection
-
enumerator LWESP_CMD_TCPIP_CIPSSLSIZE¶
Set SSL buffer size for SSL connection
-
enumerator LWESP_CMD_TCPIP_CIPSSLCCONF¶
Set the SSL configuration
-
enumerator LWESP_CMD_TCPIP_CIFSR¶
Get local IP
-
enumerator LWESP_CMD_TCPIP_CIPMUX¶
Set single or multiple connections
-
enumerator LWESP_CMD_TCPIP_CIPSERVER¶
Enables/Disables server mode
-
enumerator LWESP_CMD_TCPIP_CIPSERVERMAXCONN¶
Sets maximal number of connections allowed for server population
-
enumerator LWESP_CMD_TCPIP_CIPMODE¶
Transmission mode, either transparent or normal one
-
enumerator LWESP_CMD_TCPIP_CIPSTO¶
Sets connection timeout
-
enumerator LWESP_CMD_TCPIP_CIPRECVMODE¶
Sets mode for TCP data receive (manual or automatic)
-
enumerator LWESP_CMD_TCPIP_CIPRECVDATA¶
Manually reads TCP data from device
-
enumerator LWESP_CMD_TCPIP_CIPRECVLEN¶
Gets number of available bytes in connection to be read
-
enumerator LWESP_CMD_TCPIP_CIUPDATE¶
Perform self-update
-
enumerator LWESP_CMD_TCPIP_CIPSNTPCFG¶
Configure SNTP servers
-
enumerator LWESP_CMD_TCPIP_CIPSNTPTIME¶
Get current time using SNTP
-
enumerator LWESP_CMD_TCPIP_CIPDINFO¶
Configure what data are received on +IPD statement
-
enumerator LWESP_CMD_TCPIP_PING¶
Ping domain
-
enumerator LWESP_CMD_WIFI_SMART_START¶
Start smart config
-
enumerator LWESP_CMD_WIFI_SMART_STOP¶
Stop smart config
-
enumerator LWESP_CMD_WEBSERVER¶
Start or Stop Web Server
-
enumerator LWESP_CMD_BLEINIT_GET¶
Get BLE status
-
enumerator LWESP_CMD_IDLE¶
-
enum lwespr_t¶
Result enumeration used across application functions.
Values:
-
enumerator lwespOK¶
Function succeeded
-
enumerator lwespOKIGNOREMORE¶
Function succedded, should continue as lwespOK but ignore sending more data. This result is possible on connection data receive callback
-
enumerator lwespERR¶
General error
-
enumerator lwespPARERR¶
Wrong parameters on function call
-
enumerator lwespERRMEM¶
Memory error occurred
-
enumerator lwespTIMEOUT¶
Timeout occurred on command
-
enumerator lwespCONT¶
There is still some command to be processed in current command
-
enumerator lwespCLOSED¶
Connection just closed
-
enumerator lwespINPROG¶
Operation is in progress
-
enumerator lwespERRNOIP¶
Station does not have IP address
-
enumerator lwespERRNOFREECONN¶
There is no free connection available to start
-
enumerator lwespERRCONNTIMEOUT¶
Timeout received when connection to access point
-
enumerator lwespERRPASS¶
Invalid password for access point
-
enumerator lwespERRNOAP¶
No access point found with specific SSID and MAC address
-
enumerator lwespERRCONNFAIL¶
Connection failed to access point
-
enumerator lwespERRWIFINOTCONNECTED¶
Wifi not connected to access point
-
enumerator lwespERRNODEVICE¶
Device is not present
-
enumerator lwespERRBLOCKING¶
Blocking mode command is not allowed
-
enumerator lwespOK¶
-
enum lwesp_device_t¶
List of support ESP devices by firmware.
Values:
-
enumerator LWESP_DEVICE_ESP8266¶
Device is ESP8266
-
enumerator LWESP_DEVICE_ESP32¶
Device is ESP32
-
enumerator LWESP_DEVICE_ESP32_C3¶
Device is ESP32-C3
-
enumerator LWESP_DEVICE_UNKNOWN¶
Unknown device
-
enumerator LWESP_DEVICE_ESP8266¶
-
enum lwesp_ecn_t¶
List of encryptions of access point.
Values:
-
enumerator LWESP_ECN_OPEN¶
No encryption on access point
-
enumerator LWESP_ECN_WEP¶
WEP (Wired Equivalent Privacy) encryption
-
enumerator LWESP_ECN_WPA_PSK¶
WPA (Wifi Protected Access) encryption
-
enumerator LWESP_ECN_WPA2_PSK¶
WPA2 (Wifi Protected Access 2) encryption
-
enumerator LWESP_ECN_WPA_WPA2_PSK¶
WPA/2 (Wifi Protected Access 1/2) encryption
-
enumerator LWESP_ECN_WPA2_Enterprise¶
Enterprise encryption.
Note
ESP8266 is not able to connect to such device
-
enumerator LWESP_ECN_WPA3_PSK¶
WPA3 (Wifi Protected Access 3) encryption
-
enumerator LWESP_ECN_WPA2_WPA3_PSK¶
WPA2/3 (Wifi Protected Access 2/3) encryption, ESP32-C3 only mode
-
enumerator LWESP_ECN_END¶
-
enumerator LWESP_ECN_OPEN¶
-
enum lwesp_iptype_t¶
IP type.
Values:
-
enumerator LWESP_IPTYPE_V4¶
IP type is V4
-
enumerator LWESP_IPTYPE_V6¶
IP type is V6
-
enumerator LWESP_IPTYPE_V4¶
-
enum lwesp_mode_t¶
List of possible WiFi modes.
Values:
-
enumerator LWESP_MODE_STA¶
Set WiFi mode to station only
-
enumerator LWESP_MODE_AP¶
Set WiFi mode to access point only
-
enumerator LWESP_MODE_STA_AP¶
Set WiFi mode to station and access point
-
enumerator LWESP_MODE_STA¶
-
enum lwesp_http_method_t¶
List of possible HTTP methods.
Values:
-
enumerator LWESP_HTTP_METHOD_GET¶
HTTP method GET
-
enumerator LWESP_HTTP_METHOD_HEAD¶
HTTP method HEAD
-
enumerator LWESP_HTTP_METHOD_POST¶
HTTP method POST
-
enumerator LWESP_HTTP_METHOD_PUT¶
HTTP method PUT
-
enumerator LWESP_HTTP_METHOD_DELETE¶
HTTP method DELETE
-
enumerator LWESP_HTTP_METHOD_CONNECT¶
HTTP method CONNECT
-
enumerator LWESP_HTTP_METHOD_OPTIONS¶
HTTP method OPTIONS
-
enumerator LWESP_HTTP_METHOD_TRACE¶
HTTP method TRACE
-
enumerator LWESP_HTTP_METHOD_PATCH¶
HTTP method PATCH
-
enumerator LWESP_HTTP_METHOD_GET¶
-
struct lwesp_conn_t¶
- #include <lwesp_private.h>
Connection structure.
Public Members
-
lwesp_conn_type_t type¶
Connection type
-
uint8_t num¶
Connection number
-
lwesp_ip_t remote_ip¶
Remote IP address
-
lwesp_port_t remote_port¶
Remote port number
-
lwesp_port_t local_port¶
Local IP address
-
lwesp_evt_fn evt_func¶
Callback function for connection
-
void *arg¶
User custom argument
-
uint8_t val_id¶
Validation ID number. It is increased each time a new connection is established. It protects sending data to wrong connection in case we have data in send queue, and connection was closed and active again in between.
-
lwesp_linbuff_t buff¶
Linear buffer structure
-
size_t total_recved¶
Total number of bytes received
-
size_t tcp_available_bytes¶
Number of bytes in ESP ready to be read on connection. This variable always holds last known info from ESP device and is not decremented (or incremented) by application
-
size_t tcp_not_ack_bytes¶
Number of bytes not acknowledge by application done with processing This variable is increased everytime new packet is read to be sent to application and decreased when application acknowledges it
-
uint8_t active¶
Status whether connection is active
-
uint8_t client¶
Status whether connection is in client mode
-
uint8_t data_received¶
Status whether first data were received on connection
-
uint8_t in_closing¶
Status if connection is in closing mode. When in closing mode, ignore any possible received data from function
-
uint8_t receive_blocked¶
Status whether we should block manual receive for some time
-
uint8_t receive_is_command_queued¶
Status whether manual read command is in the queue already
-
struct lwesp_conn_t::[anonymous]::[anonymous] f¶
Connection flags
-
union lwesp_conn_t::[anonymous] status¶
Connection status union with flag bits
-
lwesp_conn_type_t type¶
-
struct lwesp_pbuf_t
- #include <lwesp_private.h>
Packet buffer structure.
Public Members
-
struct lwesp_pbuf *next
Next pbuf in chain list
-
size_t tot_len
Total length of pbuf chain
-
size_t len
Length of payload
-
size_t ref
Number of references to this structure
-
uint8_t *payload
Pointer to payload memory
-
lwesp_ip_t ip
Remote address for received IPD data
-
lwesp_port_t port
Remote port for received IPD data
-
struct lwesp_pbuf *next
-
struct lwesp_ipd_t¶
- #include <lwesp_private.h>
Incoming network data read structure.
Public Members
-
uint8_t read¶
Set to 1 when we should process input data as connection data
-
size_t tot_len¶
Total length of packet
-
size_t rem_len¶
Remaining bytes to read in current +IPD statement
-
lwesp_conn_p conn¶
Pointer to connection for network data
-
lwesp_ip_t ip¶
Remote IP address on from IPD data
-
lwesp_port_t port¶
Remote port on IPD data
-
size_t buff_ptr¶
Buffer pointer to save data to. When set to
NULL
whileread = 1
, reading should ignore incoming data
-
lwesp_pbuf_p buff¶
Pointer to data buffer used for receiving data
-
uint8_t read¶
-
struct lwesp_msg_t¶
- #include <lwesp_private.h>
Message queue structure to share between threads.
Public Members
-
lwesp_cmd_t cmd_def¶
Default message type received from queue
-
lwesp_cmd_t cmd¶
Since some commands can have different subcommands, sub command is used here
-
uint8_t i¶
Variable to indicate order number of subcommands
-
lwesp_sys_sem_t sem¶
Semaphore for the message
-
uint8_t is_blocking¶
Status if command is blocking
-
uint32_t block_time¶
Maximal blocking time in units of milliseconds. Use
0
to for non-blocking call
-
uint32_t delay¶
Delay in units of milliseconds before executing first RESET command
-
struct lwesp_msg_t::[anonymous]::[anonymous] reset¶
Reset device
-
uint32_t baudrate¶
Baudrate for AT port
-
struct lwesp_msg_t::[anonymous]::[anonymous] uart¶
UART configuration
-
lwesp_mode_t mode¶
Mode of operation
-
lwesp_mode_t *mode_get¶
Get mode
-
struct lwesp_msg_t::[anonymous]::[anonymous] wifi_mode¶
When message type LWESP_CMD_WIFI_CWMODE is used
-
const char *name¶
AP name
-
const char *pass¶
AP password
-
const lwesp_mac_t *mac¶
Specific MAC address to use when connecting to AP
-
uint8_t error_num¶
Error number on connecting
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_join¶
Message for joining to access point
-
uint16_t interval¶
Interval in units of seconds
-
uint16_t rep_cnt¶
Repetition counter
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_reconn_set¶
Reconnect setup
-
uint8_t en¶
Status to enable/disable auto join feature
Enable/disable DHCP settings
Enable/Disable server status
Status if SNTP is enabled or not
Status if WPS is enabled or not
Set to 1 to enable or 0 to disable
Enable/Disable web server status
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_autojoin¶
Message for auto join procedure
-
lwesp_sta_info_ap_t *info¶
Information structure
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_info_ap¶
Message for reading the AP information
-
const char *ssid¶
Pointer to optional filter SSID name to search
Name of access point
-
lwesp_ap_t *aps¶
Pointer to array to save access points
-
size_t apsl¶
Length of input array of access points
-
size_t apsi¶
Current access point array
-
size_t *apf¶
Pointer to output variable holding number of access points found
-
struct lwesp_msg_t::[anonymous]::[anonymous] ap_list¶
List for available access points to connect to
-
const char *pwd¶
Password of access point
-
lwesp_ecn_t ecn¶
Ecryption used
-
uint8_t ch¶
RF Channel used
-
uint8_t max_sta¶
Max allowed connected stations
-
uint8_t hid¶
Configuration if network is hidden or visible
-
struct lwesp_msg_t::[anonymous]::[anonymous] ap_conf¶
Parameters to configure access point
-
lwesp_ap_conf_t *ap_conf
AP configuration
-
struct lwesp_msg_t::[anonymous]::[anonymous] ap_conf_get¶
Get the soft AP configuration
-
lwesp_sta_t *stas¶
Pointer to array to save access points
-
size_t stal¶
Length of input array of access points
-
size_t stai¶
Current access point array
-
size_t *staf¶
Pointer to output variable holding number of access points found
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_list¶
List for stations connected to SoftAP
-
uint8_t use_mac¶
Status if specific MAC is to be used
-
lwesp_mac_t mac
MAC address to disconnect from access point
Pointer to MAC variable
-
struct lwesp_msg_t::[anonymous]::[anonymous] ap_disconn_sta¶
Disconnect station from access point
-
lwesp_ip_t *ip¶
Pointer to IP variable
-
lwesp_ip_t *gw¶
Pointer to gateway variable
-
lwesp_ip_t *nm¶
Pointer to netmask variable
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_ap_getip¶
Message for reading station or access point IP
-
lwesp_mac_t *mac
Pointer to MAC variable
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_ap_getmac¶
Message for reading station or access point MAC address
-
lwesp_ip_t ip
IP variable
-
lwesp_ip_t gw
Gateway variable
-
lwesp_ip_t nm
Netmask variable
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_ap_setip¶
Message for setting station or access point IP
-
struct lwesp_msg_t::[anonymous]::[anonymous] sta_ap_setmac¶
Message for setting station or access point MAC address
-
uint8_t sta¶
Set station DHCP settings
-
uint8_t ap¶
Set access point DHCP settings
-
struct lwesp_msg_t::[anonymous]::[anonymous] wifi_cwdhcp¶
Set DHCP settings
-
const char *hostname_set¶
Hostname set value
-
char *hostname_get¶
Hostname get value
-
size_t length¶
Length of buffer when reading hostname
-
struct lwesp_msg_t::[anonymous]::[anonymous] wifi_hostname¶
Set or get hostname structure
-
lwesp_conn_t **conn¶
Pointer to pointer to save connection used
-
const char *remote_host¶
Host to use for connection
-
lwesp_port_t remote_port¶
Remote port used for connection
Remote port address for UDP connection
-
lwesp_conn_type_t type¶
Connection type
-
const char *local_ip¶
Local IP address. Normally set to NULL
-
uint16_t tcp_ssl_keep_alive¶
Keep alive parameter for TCP
-
uint8_t udp_mode¶
UDP mode
-
lwesp_port_t udp_local_port¶
UDP local port
-
void *arg¶
Connection custom argument
-
lwesp_evt_fn evt_func¶
Callback function to use on connection
-
uint8_t success¶
Status if connection AT+CIPSTART succedded
-
struct lwesp_msg_t::[anonymous]::[anonymous] conn_start¶
Structure for starting new connection
-
lwesp_conn_t *conn
Pointer to connection to close
Pointer to connection to send data
-
uint8_t val_id¶
Connection current validation ID when command was sent to queue
-
struct lwesp_msg_t::[anonymous]::[anonymous] conn_close¶
Close connection
-
size_t btw¶
Number of remaining bytes to write
-
size_t ptr¶
Current write pointer for data
-
const uint8_t *data¶
Data to send
-
size_t sent¶
Number of bytes sent in last packet
-
size_t sent_all¶
Number of bytes sent all together
-
uint8_t tries¶
Number of tries used for last packet
-
uint8_t wait_send_ok_err¶
Set to 1 when we wait for SEND OK or SEND ERROR
-
const lwesp_ip_t *remote_ip¶
Remote IP address for UDP connection
-
uint8_t fau¶
Free after use flag to free memory after data are sent (or not)
-
size_t *bw¶
Number of bytes written so far
-
struct lwesp_msg_t::[anonymous]::[anonymous] conn_send¶
Structure to send data on connection
-
lwesp_port_t port¶
Server port number
mDNS server port
-
uint16_t max_conn¶
Maximal number of connections available for server
-
uint16_t timeout¶
Connection timeout
-
lwesp_evt_fn cb¶
Server default callback function
-
struct lwesp_msg_t::[anonymous]::[anonymous] tcpip_server¶
Server configuration
-
size_t size¶
Size for SSL in uints of bytes
-
struct lwesp_msg_t::[anonymous]::[anonymous] tcpip_sslsize¶
TCP SSL size for SSL connections
-
const char *host¶
Hostname to ping
mDNS host name
-
uint32_t time¶
Time used for ping
-
uint32_t *time_out¶
Pointer to time output variable
-
struct lwesp_msg_t::[anonymous]::[anonymous] tcpip_ping¶
Pinging structure
-
int8_t tz¶
Timezone setup
-
const char *h1¶
Optional server 1
-
const char *h2¶
Optional server 2
-
const char *h3¶
Optional server 3
-
struct lwesp_msg_t::[anonymous]::[anonymous] tcpip_sntp_cfg¶
SNTP configuration
-
lwesp_datetime_t *dt¶
Pointer to datetime structure
-
struct lwesp_msg_t::[anonymous]::[anonymous] tcpip_sntp_time¶
SNTP get time
-
struct lwesp_msg_t::[anonymous]::[anonymous] wps_cfg¶
WPS configuration
-
const char *server¶
mDNS server
-
struct lwesp_msg_t::[anonymous]::[anonymous] mdns¶
mDNS configuration
-
uint8_t timeout
Connection timeout
-
struct lwesp_msg_t::[anonymous]::[anonymous] web_server¶
Web Server configuration
-
uint8_t link_id¶
Link ID of connection to set SSL configuration for
-
uint8_t auth_mode¶
Timezone setup
-
uint8_t pki_number¶
The index of cert and private key, if only one cert and private key, the value should be 0.
-
uint8_t ca_number¶
The index of CA, if only one CA, the value should be 0.
-
struct lwesp_msg_t::[anonymous]::[anonymous] tcpip_ssl_cfg¶
SSl configuration for connection
-
union lwesp_msg_t::[anonymous] msg¶
Group of different message contents
-
lwesp_cmd_t cmd_def¶
-
struct lwesp_ip_mac_t¶
- #include <lwesp_private.h>
IP and MAC structure with netmask and gateway addresses.
Public Members
-
lwesp_ip_t ip¶
IP address
-
lwesp_ip_t gw¶
Gateway address
-
lwesp_ip_t nm¶
Netmask address
-
lwesp_mac_t mac¶
MAC address
-
uint8_t dhcp¶
Flag indicating DHCP is enabled
-
uint8_t has_ip¶
Flag indicating IP is available
-
uint8_t is_connected¶
Flag indicating ESP is connected to wifi
-
struct lwesp_ip_mac_t::[anonymous] f¶
Flags structure
-
lwesp_ip_t ip¶
-
struct lwesp_link_conn_t¶
- #include <lwesp_private.h>
Link connection active info.
Public Members
-
uint8_t failed¶
Status if connection successful
-
uint8_t num¶
Connection number
-
uint8_t is_server¶
Status if connection is client or server
-
lwesp_conn_type_t type¶
Connection type
-
lwesp_ip_t remote_ip¶
Remote IP address
-
lwesp_port_t remote_port¶
Remote port
-
lwesp_port_t local_port¶
Local port number
-
uint8_t failed¶
-
struct lwesp_evt_func_t¶
- #include <lwesp_private.h>
Callback function linked list prototype.
Public Members
-
struct lwesp_evt_func *next¶
Next function in the list
-
lwesp_evt_fn fn¶
Function pointer itself
-
struct lwesp_evt_func *next¶
-
struct lwesp_modules_t¶
- #include <lwesp_private.h>
ESP modules structure.
Public Members
-
lwesp_device_t device¶
ESP device type
-
lwesp_sw_version_t version_at¶
Version of AT command software on ESP device
-
lwesp_sw_version_t version_sdk¶
Version of SDK used to build AT software
-
uint32_t active_conns¶
Bit field of currently active connections,
- Todo:
: In case user has more than 32 connections, single variable is not enough
-
uint32_t active_conns_last¶
The same as previous but status before last check
-
lwesp_link_conn_t link_conn¶
Link connection handle
-
lwesp_ipd_t ipd¶
Connection incoming data structure
-
lwesp_conn_t conns[LWESP_CFG_MAX_CONNS]¶
Array of all connection structures
-
lwesp_ip_mac_t sta¶
Station IP and MAC addressed
-
lwesp_ip_mac_t ap¶
Access point IP and MAC addressed
-
lwesp_device_t device¶
-
struct lwesp_t¶
- #include <lwesp_private.h>
ESP global structure.
Public Members
-
size_t locked_cnt¶
Counter how many times (recursive) stack is currently locked
-
lwesp_sys_sem_t sem_sync¶
Synchronization semaphore between threads
-
lwesp_sys_mbox_t mbox_producer¶
Producer message queue handle
-
lwesp_sys_mbox_t mbox_process¶
Consumer message queue handle
-
lwesp_sys_thread_t thread_produce¶
Producer thread handle
-
lwesp_sys_thread_t thread_process¶
Processing thread handle
-
lwesp_buff_t buff¶
Input processing buffer
-
lwesp_ll_t ll¶
Low level functions
-
lwesp_msg_t *msg¶
Pointer to current user message being executed
-
lwesp_evt_t evt¶
Callback processing structure
-
lwesp_evt_func_t *evt_func¶
Callback function linked list
-
lwesp_evt_fn evt_server¶
Default callback function for server connections
-
lwesp_modules_t m¶
All modules. When resetting, reset structure
-
uint8_t initialized¶
Flag indicating ESP library is initialized
-
uint8_t dev_present¶
Flag indicating if physical device is connected to host device
-
uint8_t conn_val_id¶
Validation ID increased each time device connects to wifi network or on reset. It is used for connections
-
size_t locked_cnt¶
-
struct lwesp_unicode_t¶
- #include <lwesp_private.h>
Unicode support structure.
-
struct lwesp_ip4_addr_t¶
- #include <lwesp_typedefs.h>
IPv4 address structure.
Public Members
-
uint8_t addr[4]¶
IP address data
-
uint8_t addr[4]¶
-
struct lwesp_ip6_addr_t¶
- #include <lwesp_typedefs.h>
IPv6 address structure.
Public Members
-
uint16_t addr[8]¶
IP address data
-
uint16_t addr[8]¶
-
struct lwesp_ip_t¶
- #include <lwesp_typedefs.h>
IP structure.
Public Members
-
lwesp_ip4_addr_t ip4¶
IPv4 address
-
union lwesp_ip_t::[anonymous] addr¶
Actual IP address
-
lwesp_iptype_t type¶
IP type, either V4 or V6
-
lwesp_ip4_addr_t ip4¶
-
struct lwesp_mac_t¶
- #include <lwesp_typedefs.h>
MAC address.
Public Members
-
uint8_t mac[6]¶
MAC address
-
uint8_t mac[6]¶
-
struct lwesp_sw_version_t¶
- #include <lwesp_typedefs.h>
SW version in semantic versioning format.
-
struct lwesp_datetime_t¶
- #include <lwesp_typedefs.h>
Date and time structure.
Public Members
-
uint8_t date¶
Day in a month, from 1 to up to 31
-
uint8_t month¶
Month in a year, from 1 to 12
-
uint16_t year¶
Year
-
uint8_t day¶
Day in a week, from 1 to 7
-
uint8_t hours¶
Hours in a day, from 0 to 23
-
uint8_t minutes¶
Minutes in a hour, from 0 to 59
-
uint8_t seconds¶
Seconds in a minute, from 0 to 59
-
uint8_t date¶
-
struct lwesp_linbuff_t¶
- #include <lwesp_typedefs.h>
Linear buffer structure.
-
typedef uint16_t lwesp_port_t¶
Unicode¶
Unicode decoder block. It can decode sequence of UTF-8 characters,
between 1
and 4
bytes long.
Note
This is simple implementation and does not support string encoding.
- group LWESP_UNICODE
Unicode support manager.
Functions
-
lwespr_t lwespi_unicode_decode(lwesp_unicode_t *uni, uint8_t ch)¶
Decode single character for unicode (UTF-8 only) format.
- Parameters
s – [inout] Pointer to unicode decode control structure
c – [in] UTF-8 character sequence to test for device
- Returns
lwespOK Function succedded, there is a valid UTF-8 sequence
- Returns
lwespINPROG Function continues well but expects some more data to finish sequence
- Returns
lwespERR Error in UTF-8 sequence
-
struct lwesp_unicode_t
- #include <lwesp_private.h>
Unicode support structure.
Public Members
-
uint8_t ch[4]
UTF-8 max characters
-
uint8_t t
Total expected length in UTF-8 sequence
-
uint8_t r
Remaining bytes in UTF-8 sequence
-
lwespr_t res
Current result of processing
-
uint8_t ch[4]
-
lwespr_t lwespi_unicode_decode(lwesp_unicode_t *uni, uint8_t ch)¶
Utilities¶
Utility functions for various cases. These function are used across entire middleware and can also be used by application.
- group LWESP_UTILS
Utilities.
Defines
-
LWESP_ASSERT(msg, c)¶
Assert an input parameter if in valid range.
Note
Since this is a macro, it may only be used on a functions where return status is of type lwespr_t enumeration
- Parameters
msg – [in] message to print to debug if test fails
c – [in] Condition to test
-
LWESP_MEM_ALIGN(x)¶
Align
x
value to specific number of bytes, provided by LWESP_CFG_MEM_ALIGNMENT configuration.- Parameters
x – [in] Input value to align
- Returns
Input value aligned to specific number of bytes
-
LWESP_MIN(x, y)¶
Get minimal value between
x
andy
inputs.- Parameters
x – [in] First input to test
y – [in] Second input to test
- Returns
Minimal value between
x
andy
parameters
-
LWESP_MAX(x, y)¶
Get maximal value between
x
andy
inputs.- Parameters
x – [in] First input to test
y – [in] Second input to test
- Returns
Maximal value between
x
andy
parameters
-
LWESP_ARRAYSIZE(x)¶
Get size of statically declared array.
- Parameters
x – [in] Input array
- Returns
Number of array elements
-
LWESP_UNUSED(x)¶
Unused argument in a function call.
Note
Use this on all parameters in a function which are not used to prevent compiler warnings complaining about “unused variables”
- Parameters
x – [in] Variable which is not used
-
LWESP_U32(x)¶
Get input value casted to
unsigned 32-bit
value.- Parameters
x – [in] Input value
-
LWESP_U16(x)¶
Get input value casted to
unsigned 16-bit
value.- Parameters
x – [in] Input value
-
LWESP_U8(x)¶
Get input value casted to
unsigned 8-bit
value.- Parameters
x – [in] Input value
-
LWESP_I32(x)¶
Get input value casted to
signed 32-bit
value.- Parameters
x – [in] Input value
-
LWESP_I16(x)¶
Get input value casted to
signed 16-bit
value.- Parameters
x – [in] Input value
-
LWESP_I8(x)¶
Get input value casted to
signed 8-bit
value.- Parameters
x – [in] Input value
-
LWESP_SZ(x)¶
Get input value casted to
size_t
value.- Parameters
x – [in] Input value
-
lwesp_u32_to_str(num, out)¶
Convert
unsigned 32-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
-
lwesp_u32_to_hex_str(num, out, w)¶
Convert
unsigned 32-bit
number to HEX string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
w – [in] Width of output string. When number is shorter than width, leading
0
characters will apply
- Returns
Pointer to output variable
-
lwesp_i32_to_str(num, out)¶
Convert
signed 32-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
-
lwesp_u16_to_str(num, out)¶
Convert
unsigned 16-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
-
lwesp_u16_to_hex_str(num, out, w)¶
Convert
unsigned 16-bit
number to HEX string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
w – [in] Width of output string. When number is shorter than width, leading
0
characters will apply.
- Returns
Pointer to output variable
-
lwesp_i16_to_str(num, out)¶
Convert
signed 16-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
-
lwesp_u8_to_str(num, out)¶
Convert
unsigned 8-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
-
lwesp_u8_to_hex_str(num, out, w)¶
Convert
unsigned 16-bit
number to HEX string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
w – [in] Width of output string. When number is shorter than width, leading
0
characters will apply.
- Returns
Pointer to output variable
-
lwesp_i8_to_str(num, out)¶
Convert
signed 8-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
Functions
-
char *lwesp_u32_to_gen_str(uint32_t num, char *out, uint8_t is_hex, uint8_t padding)¶
Convert
unsigned 32-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
is_hex – [in] Set to
1
to output hex, 0 otherwisewidth – [in] Width of output string. When number is shorter than width, leading
0
characters will apply. This parameter is valid only when formatting hex numbers
- Returns
Pointer to output variable
-
char *lwesp_i32_to_gen_str(int32_t num, char *out)¶
Convert
signed 32-bit
number to string.- Parameters
num – [in] Number to convert
out – [out] Output variable to save string
- Returns
Pointer to output variable
-
LWESP_ASSERT(msg, c)¶
Web Server¶
Use ESP-AT’s built-in web server feature to help WiFi provisioning and/or Firmware Over-the-Air update.
Note
Web Server is not enabled in ESP-AT by default. Refer to ESP-AT User Guide to build a custom image from source.
- group LWESP_WEBSERVER
Web Server function.
Functions
-
lwespr_t lwesp_set_webserver(uint8_t en, lwesp_port_t port, uint16_t timeout, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Enables or disables Web Server.
- Parameters
en – [in] Set to
1
to enable web server,0
to disable web server.port – [in] The web server port number.
timeout – [in] The timeout for the every connection. Unit: second. Range:[21,60].
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_set_webserver(uint8_t en, lwesp_port_t port, uint16_t timeout, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Wi-Fi Protected Setup¶
- group LWESP_WPS
WPS function on ESP device.
Functions
-
lwespr_t lwesp_wps_set_config(uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure WPS function on ESP device.
- Parameters
en – [in] Set to
1
to enable WPS or0
to disable WPSevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_wps_set_config(uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
- group LWESP
Lightweight ESP-AT parser.
Defines
-
lwesp_set_fw_version(v, major_, minor_, patch_)¶
Set and format major, minor and patch values to firmware version.
- Parameters
v – [in] Version output, pointer to lwesp_sw_version_t structure
major_ – [in] Major version
minor_ – [in] Minor version
patch_ – [in] Patch version
-
lwesp_get_min_at_fw_version(v)¶
Get minimal AT version supported by library.
- Todo:
Convert to function and take care of different Espressif devices
- Parameters
v – [out] Version output, pointer to lwesp_sw_version_t structure
Functions
-
lwespr_t lwesp_init(lwesp_evt_fn cb_func, const uint32_t blocking)¶
Init and prepare ESP stack for device operation.
Note
Function must be called from operating system thread context. It creates necessary threads and waits them to start, thus running operating system is important.
When LWESP_CFG_RESET_ON_INIT is enabled, reset sequence will be sent to device otherwise manual call to lwesp_reset is required to setup device
When LWESP_CFG_RESTORE_ON_INIT is enabled, restore sequence will be sent to device.
- Parameters
evt_func – [in] Global event callback function for all major events
blocking – [in] Status whether command should be blocking or not. Used when LWESP_CFG_RESET_ON_INIT or LWESP_CFG_RESTORE_ON_INIT are enabled.
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_reset(const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Execute reset and send default commands.
-
lwespr_t lwesp_reset_with_delay(uint32_t delay, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Execute reset and send default commands with delay before first command.
- Parameters
delay – [in] Number of milliseconds to wait before initiating first command to device
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_restore(const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Execute restore command and set module to default values.
-
lwespr_t lwesp_set_at_baudrate(uint32_t baud, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Sets baudrate of AT port (usually UART)
- Parameters
baud – [in] Baudrate in units of bits per second
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_set_wifi_mode(lwesp_mode_t mode, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Sets WiFi mode to either station only, access point only or both.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
mode – [in] Mode of operation. This parameter can be a value of lwesp_mode_t enumeration
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_get_wifi_mode(lwesp_mode_t *mode, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Gets WiFi mode of either station only, access point only or both.
- Parameters
mode – [in] point to space of Mode to get. This parameter can be a pointer of lwesp_mode_t enumeration
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_update_sw(const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Update ESP software remotely.
Note
ESP must be connected to access point to use this feature
-
lwespr_t lwesp_core_lock(void)¶
Lock stack from multi-thread access, enable atomic access to core.
If lock was
0
prior function call, lock is enabled and increasedNote
Function may be called multiple times to increase locks. Application must take care to call lwesp_core_unlock the same amount of time to make sure lock gets back to
0
-
lwespr_t lwesp_core_unlock(void)¶
Unlock stack for multi-thread access.
Used in conjunction with lwesp_core_lock function
If lock was non-zero before function call, lock is decreased. When
lock == 0
, protection is disabled and other threads may access to core
-
lwespr_t lwesp_device_set_present(uint8_t present, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Notify stack if device is present or not.
Use this function to notify stack that device is not physically connected and not ready to communicate with host device
- Parameters
present – [in] Flag indicating device is present
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
uint8_t lwesp_device_is_present(void)¶
Check if device is present.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_device_is_esp8266(void)¶
Check if modem device is ESP8266.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_device_is_esp32(void)¶
Check if modem device is ESP32.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_device_is_esp32_c3(void)¶
Check if modem device is ESP32-C3.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_delay(const uint32_t ms)¶
Delay for amount of milliseconds.
Delay is based on operating system semaphores. It locks semaphore and waits for timeout in
ms
time. Based on operating system, thread may be put to blocked list during delay and may improve execution speed- Parameters
ms – [in] Milliseconds to delay
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_get_current_at_fw_version(lwesp_sw_version_t *const version)¶
Get current AT firmware version of connected device.
- Parameters
version – [out] Output version variable
- Returns
1
on success,0
otherwise
-
lwesp_set_fw_version(v, major_, minor_, patch_)¶
Configuration¶
This is the default configuration of the middleware.
When any of the settings shall be modified, it shall be done in dedicated application config lwesp_opts.h
file.
Note
Check Getting started for guidelines on how to create and use configuration file.
- group LWESP_OPT
ESP-AT options.
Defines
-
LWESP_CFG_ESP8266¶
Enables
1
or disables0
support for ESP8266 AT commands.
-
LWESP_CFG_ESP32¶
Enables
1
or disables0
support for ESP32 AT commands.
-
LWESP_CFG_ESP32_C3¶
Enables
1
or disables0
support for ESP32-C3 AT commands.
-
LWESP_CFG_OS¶
Enables
1
or disables0
operating system support for ESP library.Note
Value must be set to
1
in the current revisionNote
Check OS configuration group for more configuration related to operating system
-
LWESP_CFG_MEM_CUSTOM¶
Enables
1
or disables0
custom memory management functions.When set to
1
, Memory manager block must be provided manually. This includes implementation of functions lwesp_mem_malloc, lwesp_mem_calloc, lwesp_mem_realloc and lwesp_mem_freeNote
Function declaration follows standard C functions
malloc, calloc, realloc, free
. Declaration is available inlwesp/lwesp_mem.h
file. Include this file to final implementation fileNote
When implementing custom memory allocation, it is necessary to take care of multiple threads accessing same resource for custom allocator
-
LWESP_CFG_MEM_ALIGNMENT¶
Memory alignment for dynamic memory allocations.
Note
Some CPUs can work faster if memory is aligned, usually to
4
or8
bytes. To speed up this possibilities, you can set memory alignment and library will try to allocate memory on aligned boundaries.Note
Some CPUs such ARM Cortex-M0 dont’t support unaligned memory access.
Note
This value must be power of
2
-
LWESP_CFG_USE_API_FUNC_EVT¶
Enables
1
or disables0
callback function and custom parameter for API functions.When enabled,
2
additional parameters are available in API functions. When command is executed, callback function with its parameter could be called when not set toNULL
.
-
LWESP_CFG_MAX_SEND_RETRIES¶
Set number of retries for send data command.
Sometimes it may happen that
AT+SEND
command fails due to different problems. Trying to send the same data multiple times can raise chances for success.
-
LWESP_CFG_AT_PORT_BAUDRATE¶
Default baudrate used for AT port.
Note
User may call API function to change to desired baudrate if necessary
-
LWESP_CFG_MODE_STATION¶
Enables
1
or disables0
ESP acting as station.Note
When device is in station mode, it can connect to other access points
-
LWESP_CFG_MODE_ACCESS_POINT¶
Enables
1
or disables0
ESP acting as access point.Note
When device is in access point mode, it can accept connections from other stations
-
LWESP_CFG_ACCESS_POINT_STRUCT_FULL_FIELDS¶
Enables
1
or disables0
full data info in lwesp_ap_t structure.When enabled, advanced information is stored, and as a consequence, structure size is increased. Information such as scan type, min scan time, max scan time, frequency offset, frequency calibration are added
-
LWESP_CFG_KEEP_ALIVE¶
Enables
1
or disables0
periodic keep-alive events to registered callbacks.
-
LWESP_CFG_KEEP_ALIVE_TIMEOUT¶
Timeout periodic time to trigger keep alive events to registered callbacks.
Feature must be enabled with LWESP_CFG_KEEP_ALIVE
-
LWESP_CFG_RCV_BUFF_SIZE¶
Buffer size for received data waiting to be processed.
Note
When server mode is active and a lot of connections are in queue this should be set high otherwise your buffer may overflow
Note
Buffer size also depends on TX user driver if it uses DMA or blocking mode. In case of DMA (CPU can work other tasks), buffer may be smaller as CPU will have more time to process all the incoming bytes
Note
This parameter has no meaning when LWESP_CFG_INPUT_USE_PROCESS is enabled
-
LWESP_CFG_RESET_ON_INIT¶
Enables
1
or disables0
reset sequence after lwesp_init call.Note
When this functionality is disabled, user must manually call lwesp_reset to send reset sequence to ESP device.
-
LWESP_CFG_RESTORE_ON_INIT¶
Enables
1
or disables0
device restore after lwesp_init call.Note
When this feature is enabled, it will automatically restore and clear any settings stored as default in ESP device
-
LWESP_CFG_RESET_ON_DEVICE_PRESENT¶
Enables
1
or disables0
reset sequence after lwesp_device_set_present call.Note
When this functionality is disabled, user must manually call lwesp_reset to send reset sequence to ESP device.
-
LWESP_CFG_RESET_DELAY_DEFAULT¶
Default delay (milliseconds unit) before sending first AT command on reset sequence.
-
LWESP_CFG_MAX_SSID_LENGTH¶
Maximum length of SSID for access point scan.
Note
This parameter must include trailling zero
-
LWESP_CFG_MAX_PWD_LENGTH¶
Maximum length of PWD for access point.
Note
This parameter must include trailling zero
-
LWESP_CFG_CONN_POLL_INTERVAL¶
Poll interval for connections in units of milliseconds.
Value indicates interval time to call poll event on active connections.
Note
Single poll interval applies for all connections
-
LWESP_CFG_CONN_MANUAL_TCP_RECEIVE¶
Enables
1
or disables0
manualTCP
data receive from ESP device.Normally ESP automatically sends received TCP data to host device in async mode. When host device is slow or if there is memory constrain, it may happen that processing cannot handle all received data.
When feature is enabled, ESP will notify host device about new data available for read and then user may start read process
Note
This feature is only available for
TCP
connections.
-
LWESP_CFG_ESP8266¶
- group LWESP_OPT_DBG
Debugging configurations.
Defines
-
LWESP_CFG_DBG¶
Set global debug support.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
Note
Set to LWESP_DBG_OFF to globally disable all debugs
-
LWESP_CFG_DBG_OUT(fmt, ...)¶
Debugging output function.
Called with format and optional parameters for printf-like debug
-
LWESP_CFG_DBG_LVL_MIN¶
Minimal debug level.
Check LWESP_DBG_LVL for possible values
-
LWESP_CFG_DBG_TYPES_ON¶
Enabled debug types.
When debug is globally enabled with LWESP_CFG_DBG parameter, user must enable debug types such as TRACE or STATE messages.
Check LWESP_DBG_TYPE for possible options. Separate values with
bitwise OR
operator
-
LWESP_CFG_DBG_INIT¶
Set debug level for init function.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_MEM¶
Set debug level for memory manager.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_INPUT¶
Set debug level for input module.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_THREAD¶
Set debug level for ESP threads.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_ASSERT¶
Set debug level for asserting of input variables.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_IPD¶
Set debug level for incoming data received from device.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_NETCONN¶
Set debug level for netconn sequential API.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_PBUF¶
Set debug level for packet buffer manager.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_CONN¶
Set debug level for connections.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_VAR¶
Set debug level for dynamic variable allocations.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_AT_ECHO¶
Enables
1
or disables0
echo mode on AT commands sent to ESP device.Note
This mode is useful when debugging ESP communication
-
LWESP_CFG_DBG¶
- group LWESP_OPT_OS
Operating system dependant configuration.
Defines
-
LWESP_CFG_THREAD_PRODUCER_MBOX_SIZE¶
Set number of message queue entries for procuder thread.
Message queue is used for storing memory address to command data
-
LWESP_CFG_THREAD_PROCESS_MBOX_SIZE¶
Set number of message queue entries for processing thread.
Message queue is used to notify processing thread about new received data on AT port
-
LWESP_CFG_INPUT_USE_PROCESS¶
Enables
1
or disables0
direct support for processing input data.When this mode is enabled, no overhead is included for copying data to receive buffer because bytes are processed directly by lwesp_input_process function
If this mode is not enabled, then user have to send every received byte via lwesp_input function to the internal buffer for future processing. This may introduce additional overhead with data copy and may decrease library performance
Note
This mode can only be used when LWESP_CFG_OS is enabled
Note
When using this mode, separate thread must be dedicated only for reading data on AT port. It is usually implemented in LL driver
Note
Best case for using this mode is if DMA receive is supported by host device
-
LWESP_THREAD_PRODUCER_HOOK()¶
Producer thread hook, called each time thread wakes-up and does the processing.
It can be used to check if thread is alive.
-
LWESP_THREAD_PROCESS_HOOK()¶
Process thread hook, called each time thread wakes-up and does the processing.
It can be used to check if thread is alive.
-
LWESP_CFG_THREAD_PRODUCER_MBOX_SIZE¶
- group LWESP_OPT_STD_LIB
Standard C library configuration.
Configuration allows you to overwrite default C language function in case of better implementation with hardware (for example DMA for data copy).
Defines
-
LWESP_MEMCPY(dst, src, len)¶
Memory copy function declaration.
User is able to change the memory function, in case hardware supports copy operation, it may implement its own
Function prototype must be similar to:
void * my_memcpy(void* dst, const void* src, size_t len);
- Parameters
dst – [in] Destination memory start address
src – [in] Source memory start address
len – [in] Number of bytes to copy
- Returns
Destination memory start address
-
LWESP_MEMSET(dst, b, len)¶
Memory set function declaration.
Function prototype must be similar to:
void * my_memset(void* dst, int b, size_t len);
- Parameters
dst – [in] Destination memory start address
b – [in] Value (byte) to set in memory
len – [in] Number of bytes to set
- Returns
Destination memory start address
-
LWESP_MEMCPY(dst, src, len)¶
- group LWESP_OPT_MODULES
Configuration of specific modules.
Defines
-
LWESP_CFG_DNS¶
Enables
1
or disables0
support for DNS functions.
-
LWESP_CFG_WPS¶
Enables
1
or disables0
support for WPS functions.
-
LWESP_CFG_SNTP¶
Enables
1
or disables0
support for SNTP protocol with AT commands.
-
LWESP_CFG_HOSTNAME¶
Enables
1
or disables0
support for hostname with AT commands.
-
LWESP_CFG_PING¶
Enables
1
or disables0
support for ping functions.
-
LWESP_CFG_MDNS¶
Enables
1
or disables0
support for mDNS.
-
LWESP_CFG_SMART¶
Enables
1
or disables0
support for SMART config.
-
LWESP_CFG_WEBSERVER¶
Enables
1
or disables0
support for Web Server feature.
-
LWESP_CFG_DNS¶
- group LWESP_OPT_MODULES_NETCONN
Configuration of netconn API module.
Defines
-
LWESP_CFG_NETCONN¶
Enables
1
or disables0
NETCONN sequential API support for OS systems.- See
Note
To use this feature, OS support is mandatory.
-
LWESP_CFG_NETCONN_RECEIVE_TIMEOUT¶
Enables
1
or disables0
receive timeout feature.When this option is enabled, user will get an option to set timeout value for receive data on netconn, before function returns timeout error.
Note
Even if this option is enabled, user must still manually set timeout, by default time will be set to 0 which means no timeout.
-
LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN¶
Accept queue length for new client when netconn server is used.
Defines number of maximal clients waiting in accept queue of server connection
-
LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN¶
Receive queue length for pbuf entries.
Defines maximal number of pbuf data packet references for receive
-
LWESP_CFG_NETCONN¶
- group LWESP_OPT_MODULES_MQTT
Configuration of MQTT and MQTT API client modules.
Defines
-
LWESP_CFG_MQTT_MAX_REQUESTS¶
Maximal number of open MQTT requests at a time.
-
LWESP_CFG_DBG_MQTT¶
Set debug level for MQTT client module.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_MQTT_API¶
Set debug level for MQTT API client module.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_MQTT_MAX_REQUESTS¶
- group LWESP_OPT_MODULES_CAYENNE
Configuration of Cayenne MQTT client.
Defines
-
LWESP_CFG_DBG_CAYENNE¶
Set debug level for Cayenne MQTT client module.
Possible values are LWESP_DBG_ON or LWESP_DBG_OFF
-
LWESP_CFG_DBG_CAYENNE¶
- group LWESP_OPT_APP_HTTP
Configuration of HTTP server app.
Defines
-
LWESP_CFG_DBG_SERVER¶
Server debug default setting.
-
HTTP_SSI_TAG_START¶
SSI tag start string
-
HTTP_SSI_TAG_START_LEN¶
SSI tag start length
-
HTTP_SSI_TAG_END¶
SSI tag end string
-
HTTP_SSI_TAG_END_LEN¶
SSI tag end length
-
HTTP_SSI_TAG_MAX_LEN¶
Maximal length of tag name excluding start and end parts of tag.
-
HTTP_SUPPORT_POST¶
Enables
1
or disables0
support for POST request.
-
HTTP_MAX_URI_LEN¶
Maximal length of allowed uri length including parameters in format
/uri/sub/path?param=value
-
HTTP_MAX_PARAMS¶
Maximal number of parameters in URI.
-
HTTP_USE_METHOD_NOTALLOWED_RESP¶
Enables
1
or disables0
method not allowed response.Response is used in case user makes HTTP request with method which is not on the list of allowed methods. See http_req_method_t
Note
When disabled, connection will be closed without response
-
HTTP_USE_DEFAULT_STATIC_FILES¶
Enables
1
or disables1
default static files.To allow fast startup of server development, several static files are included by default:
/index.html
/index.shtml
/js/style.css
/js/js.js
-
HTTP_DYNAMIC_HEADERS¶
Enables
1
or disables0
dynamic headers support.With dynamic headers enabled, script will try to detect most common file extensions and will try to response with:
HTTP response code as first line
Server name as second line
Content type as third line including end of headers (empty line)
-
HTTP_DYNAMIC_HEADERS_CONTENT_LEN¶
Enables
1
or disables0
content length header for response.If response has fixed length without SSI tags, dynamic headers will try to include “Content-Length” header as part of response message sent to client
Note
In order to use this, HTTP_DYNAMIC_HEADERS must be enabled
-
HTTP_SERVER_NAME¶
Default server name for
Server: x
response dynamic header.
-
LWESP_CFG_DBG_SERVER¶
Platform specific¶
List of all the modules:
Low-Level functions¶
Low-level module consists of callback-only functions, which are called by middleware and must be implemented by final application.
Tip
Check Porting guide for actual implementation
- group LWESP_LL
Low-level communication functions.
Typedefs
-
typedef size_t (*lwesp_ll_send_fn)(const void *data, size_t len)¶
Function prototype for AT output data.
- Param data
[in] Pointer to data to send. This parameter can be set to
NULL
- Param len
[in] Number of bytes to send. This parameter can be set to
0
to indicate that internal buffer can be flushed to stream. This is implementation defined and feature might be ignored- Return
Number of bytes sent
-
typedef uint8_t (*lwesp_ll_reset_fn)(uint8_t state)¶
Function prototype for hardware reset of ESP device.
- Param state
[in] State indicating reset. When set to
1
, reset must be active (usually pin active low), or set to0
when reset is cleared- Return
1
on successful action,0
otherwise
Functions
-
lwespr_t lwesp_ll_init(lwesp_ll_t *ll)¶
Callback function called from initialization process.
Note
This function may be called multiple times if AT baudrate is changed from application. It is important that every configuration except AT baudrate is configured only once!
Note
This function may be called from different threads in ESP stack when using OS. When LWESP_CFG_INPUT_USE_PROCESS is set to
1
, this function may be called from user UART thread.- Parameters
ll – [inout] Pointer to lwesp_ll_t structure to fill data for communication functions
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_ll_deinit(lwesp_ll_t *ll)¶
Callback function to de-init low-level communication part.
- Parameters
ll – [inout] Pointer to lwesp_ll_t structure to fill data for communication functions
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
struct lwesp_ll_t¶
- #include <lwesp_typedefs.h>
Low level user specific functions.
Public Members
-
lwesp_ll_send_fn send_fn¶
Callback function to transmit data
-
lwesp_ll_reset_fn reset_fn¶
Reset callback function
-
uint32_t baudrate¶
UART baudrate value
-
struct lwesp_ll_t::[anonymous] uart¶
UART communication parameters
-
lwesp_ll_send_fn send_fn¶
-
typedef size_t (*lwesp_ll_send_fn)(const void *data, size_t len)¶
System functions¶
System functions are bridge between operating system system calls and middleware system calls. Middleware is tightly coupled with operating system features hence it is important to include OS features directly.
It includes support for:
Thread management, to start/stop threads
Mutex management for recursive mutexes
Semaphore management for binary-only semaphores
Message queues for thread-safe data exchange between threads
Core system protection for mutual exclusion to access shared resources
Tip
Check Porting guide for actual implementation guidelines.
- group LWESP_SYS
System based function for OS management, timings, etc.
Main
-
uint8_t lwesp_sys_init(void)¶
Init system dependant parameters.
After this function is called, all other system functions must be fully ready.
- Returns
1
on success,0
otherwise
-
uint32_t lwesp_sys_now(void)¶
Get current time in units of milliseconds.
- Returns
Current time in units of milliseconds
-
uint8_t lwesp_sys_protect(void)¶
Protect middleware core.
Stack protection must support recursive mode. This function may be called multiple times, even if access has been granted before.
Note
Most operating systems support recursive mutexes.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_unprotect(void)¶
Unprotect middleware core.
This function must follow number of calls of lwesp_sys_protect and unlock access only when counter reached back zero.
Note
Most operating systems support recursive mutexes.
- Returns
1
on success,0
otherwise
Mutex
-
uint8_t lwesp_sys_mutex_create(lwesp_sys_mutex_t *p)¶
Create new recursive mutex.
Note
Recursive mutex has to be created as it may be locked multiple times before unlocked
- Parameters
p – [out] Pointer to mutex structure to allocate
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mutex_delete(lwesp_sys_mutex_t *p)¶
Delete recursive mutex from system.
- Parameters
p – [in] Pointer to mutex structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mutex_lock(lwesp_sys_mutex_t *p)¶
Lock recursive mutex, wait forever to lock.
- Parameters
p – [in] Pointer to mutex structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mutex_unlock(lwesp_sys_mutex_t *p)¶
Unlock recursive mutex.
- Parameters
p – [in] Pointer to mutex structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mutex_isvalid(lwesp_sys_mutex_t *p)¶
Check if mutex structure is valid system.
- Parameters
p – [in] Pointer to mutex structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mutex_invalid(lwesp_sys_mutex_t *p)¶
Set recursive mutex structure as invalid.
- Parameters
p – [in] Pointer to mutex structure
- Returns
1
on success,0
otherwise
Semaphores
-
uint8_t lwesp_sys_sem_create(lwesp_sys_sem_t *p, uint8_t cnt)¶
Create a new binary semaphore and set initial state.
Note
Semaphore may only have
1
token available- Parameters
p – [out] Pointer to semaphore structure to fill with result
cnt – [in] Count indicating default semaphore state:
0
: Take semaphore token immediately1
: Keep token available
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_sem_delete(lwesp_sys_sem_t *p)¶
Delete binary semaphore.
- Parameters
p – [in] Pointer to semaphore structure
- Returns
1
on success,0
otherwise
-
uint32_t lwesp_sys_sem_wait(lwesp_sys_sem_t *p, uint32_t timeout)¶
Wait for semaphore to be available.
- Parameters
p – [in] Pointer to semaphore structure
timeout – [in] Timeout to wait in milliseconds. When
0
is applied, wait forever
- Returns
Number of milliseconds waited for semaphore to become available or LWESP_SYS_TIMEOUT if not available within given time
-
uint8_t lwesp_sys_sem_release(lwesp_sys_sem_t *p)¶
Release semaphore.
- Parameters
p – [in] Pointer to semaphore structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_sem_isvalid(lwesp_sys_sem_t *p)¶
Check if semaphore is valid.
- Parameters
p – [in] Pointer to semaphore structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_sem_invalid(lwesp_sys_sem_t *p)¶
Invalid semaphore.
- Parameters
p – [in] Pointer to semaphore structure
- Returns
1
on success,0
otherwise
Message queues
-
uint8_t lwesp_sys_mbox_create(lwesp_sys_mbox_t *b, size_t size)¶
Create a new message queue with entry type of
void *
- Parameters
b – [out] Pointer to message queue structure
size – [in] Number of entries for message queue to hold
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mbox_delete(lwesp_sys_mbox_t *b)¶
Delete message queue.
- Parameters
b – [in] Pointer to message queue structure
- Returns
1
on success,0
otherwise
-
uint32_t lwesp_sys_mbox_put(lwesp_sys_mbox_t *b, void *m)¶
Put a new entry to message queue and wait until memory available.
- Parameters
b – [in] Pointer to message queue structure
m – [in] Pointer to entry to insert to message queue
- Returns
Time in units of milliseconds needed to put a message to queue
-
uint32_t lwesp_sys_mbox_get(lwesp_sys_mbox_t *b, void **m, uint32_t timeout)¶
Get a new entry from message queue with timeout.
- Parameters
b – [in] Pointer to message queue structure
m – [in] Pointer to pointer to result to save value from message queue to
timeout – [in] Maximal timeout to wait for new message. When
0
is applied, wait for unlimited time
- Returns
Time in units of milliseconds needed to put a message to queue or LWESP_SYS_TIMEOUT if it was not successful
-
uint8_t lwesp_sys_mbox_putnow(lwesp_sys_mbox_t *b, void *m)¶
Put a new entry to message queue without timeout (now or fail)
- Parameters
b – [in] Pointer to message queue structure
m – [in] Pointer to message to save to queue
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mbox_getnow(lwesp_sys_mbox_t *b, void **m)¶
Get an entry from message queue immediately.
- Parameters
b – [in] Pointer to message queue structure
m – [in] Pointer to pointer to result to save value from message queue to
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mbox_isvalid(lwesp_sys_mbox_t *b)¶
Check if message queue is valid.
- Parameters
b – [in] Pointer to message queue structure
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_mbox_invalid(lwesp_sys_mbox_t *b)¶
Invalid message queue.
- Parameters
b – [in] Pointer to message queue structure
- Returns
1
on success,0
otherwise
Threads
-
uint8_t lwesp_sys_thread_create(lwesp_sys_thread_t *t, const char *name, lwesp_sys_thread_fn thread_func, void *const arg, size_t stack_size, lwesp_sys_thread_prio_t prio)¶
Create a new thread.
- Parameters
t – [out] Pointer to thread identifier if create was successful. It may be set to
NULL
name – [in] Name of a new thread
thread_func – [in] Thread function to use as thread body
arg – [in] Thread function argument
stack_size – [in] Size of thread stack in uints of bytes. If set to 0, reserve default stack size
prio – [in] Thread priority
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_thread_terminate(lwesp_sys_thread_t *t)¶
Terminate thread (shut it down and remove)
- Parameters
t – [in] Pointer to thread handle to terminate. If set to
NULL
, terminate current thread (thread from where function is called)- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sys_thread_yield(void)¶
Yield current thread.
- Returns
1
on success,0
otherwise
Defines
-
LWESP_SYS_MUTEX_NULL¶
Mutex invalid value.
Value assigned to lwesp_sys_mutex_t type when it is not valid.
-
LWESP_SYS_SEM_NULL¶
Semaphore invalid value.
Value assigned to lwesp_sys_sem_t type when it is not valid.
-
LWESP_SYS_MBOX_NULL¶
Message box invalid value.
Value assigned to lwesp_sys_mbox_t type when it is not valid.
-
LWESP_SYS_TIMEOUT¶
OS timeout value.
Value returned by operating system functions (mutex wait, sem wait, mbox wait) when it returns timeout and does not give valid value to application
-
LWESP_SYS_THREAD_PRIO¶
Default thread priority value used by middleware to start built-in threads.
Threads can well operate with normal (default) priority and do not require any special feature in terms of priority for proper operation.
-
LWESP_SYS_THREAD_SS¶
Stack size in units of bytes for system threads.
It is used as default stack size for all built-in threads.
Typedefs
-
typedef void (*lwesp_sys_thread_fn)(void*)¶
Thread function prototype.
-
typedef void *lwesp_sys_mutex_t¶
System mutex type.
It is used by middleware as base type of mutex.
-
typedef void *lwesp_sys_sem_t¶
System semaphore type.
It is used by middleware as base type of mutex.
-
typedef void *lwesp_sys_mbox_t¶
System message queue type.
It is used by middleware as base type of mutex.
-
typedef void *lwesp_sys_thread_t¶
System thread ID type.
-
typedef int lwesp_sys_thread_prio_t¶
System thread priority type.
It is used as priority type for system function, to start new threads by middleware.
-
uint8_t lwesp_sys_init(void)¶
Applications¶
Cayenne MQTT API¶
- group LWESP_APP_CAYENNE_API
MQTT client API for Cayenne.
Defines
-
LWESP_CAYENNE_API_VERSION¶
Cayenne API version in string.
-
LWESP_CAYENNE_HOST¶
Cayenne host server.
-
LWESP_CAYENNE_PORT¶
Cayenne port number.
-
LWESP_CAYENNE_NO_CHANNEL¶
No channel macro
-
LWESP_CAYENNE_ALL_CHANNELS¶
All channels macro
Typedefs
-
typedef lwespr_t (*lwesp_cayenne_evt_fn)(struct lwesp_cayenne *c, lwesp_cayenne_evt_t *evt)¶
Cayenne event callback function.
Enums
-
enum lwesp_cayenne_topic_t¶
List of possible cayenne topics.
Values:
-
enumerator LWESP_CAYENNE_TOPIC_DATA¶
Data topic
-
enumerator LWESP_CAYENNE_TOPIC_COMMAND¶
Command topic
-
enumerator LWESP_CAYENNE_TOPIC_CONFIG¶
-
enumerator LWESP_CAYENNE_TOPIC_RESPONSE¶
-
enumerator LWESP_CAYENNE_TOPIC_SYS_MODEL¶
-
enumerator LWESP_CAYENNE_TOPIC_SYS_VERSION¶
-
enumerator LWESP_CAYENNE_TOPIC_SYS_CPU_MODEL¶
-
enumerator LWESP_CAYENNE_TOPIC_SYS_CPU_SPEED¶
-
enumerator LWESP_CAYENNE_TOPIC_DIGITAL¶
-
enumerator LWESP_CAYENNE_TOPIC_DIGITAL_COMMAND¶
-
enumerator LWESP_CAYENNE_TOPIC_DIGITAL_CONFIG¶
-
enumerator LWESP_CAYENNE_TOPIC_ANALOG¶
-
enumerator LWESP_CAYENNE_TOPIC_ANALOG_COMMAND¶
-
enumerator LWESP_CAYENNE_TOPIC_ANALOG_CONFIG¶
-
enumerator LWESP_CAYENNE_TOPIC_END¶
Last entry
-
enumerator LWESP_CAYENNE_TOPIC_DATA¶
Functions
-
lwespr_t lwesp_cayenne_create(lwesp_cayenne_t *c, const lwesp_mqtt_client_info_t *client_info, lwesp_cayenne_evt_fn evt_fn)¶
Create new instance of cayenne MQTT connection.
Note
Each call to this functions starts new thread for async receive processing. Function will block until thread is created and successfully started
-
lwespr_t lwesp_cayenne_subscribe(lwesp_cayenne_t *c, lwesp_cayenne_topic_t topic, uint16_t channel)¶
Subscribe to cayenne based topics and channels.
- Parameters
c – [in] Cayenne handle
topic – [in] Cayenne topic
channel – [in] Optional channel number. Use LWESP_CAYENNE_NO_CHANNEL when channel is not needed or LWESP_CAYENNE_ALL_CHANNELS to subscribe to all channels
- Returns
-
lwespr_t lwesp_cayenne_publish_data(lwesp_cayenne_t *c, lwesp_cayenne_topic_t topic, uint16_t channel, const char *type, const char *unit, const char *data)¶
Publish data to cayenne cloud.
- Parameters
c – [in] Cayenne handle
topic – [in] Cayenne specific topic to publish on
channel – [in] Device channel to publish on
type – [in] Data type, string format, for example
temp
for temperature. Set toNULL
if not usedunit – [in] Data unit, string format, for example
c
for celcius. Set toNULL
if not useddata – [in] Actual data, for example
127
for127
degrees
- Returns
-
lwespr_t lwesp_cayenne_publish_float(lwesp_cayenne_t *c, lwesp_cayenne_topic_t topic, uint16_t channel, const char *type, const char *unit, float f)¶
-
lwespr_t lwesp_cayenne_publish_response(lwesp_cayenne_t *c, lwesp_cayenne_msg_t *msg, lwesp_cayenne_rlwesp_t resp, const char *message)¶
Publish response message to command.
-
struct lwesp_cayenne_key_value_t¶
- #include <lwesp_cayenne.h>
Key/Value pair structure.
-
struct lwesp_cayenne_msg_t¶
- #include <lwesp_cayenne.h>
Cayenne message.
Public Members
-
lwesp_cayenne_topic_t topic¶
Message topic
-
uint16_t channel¶
Message channel, optional, based on topic type
-
const char *seq¶
Sequence string on command
-
lwesp_cayenne_key_value_t values[2]¶
Key/Value pair of values
-
size_t values_count¶
Count of valid pairs in values member
-
lwesp_cayenne_topic_t topic¶
-
struct lwesp_cayenne_evt_t¶
- #include <lwesp_cayenne.h>
Cayenne event.
Public Members
-
lwesp_cayenne_evt_type_t type¶
Event type
-
lwesp_cayenne_msg_t *msg¶
Pointer to data message
-
struct lwesp_cayenne_evt_t::[anonymous]::[anonymous] data¶
Data event, used with LWESP_CAYENNE_EVT_DATA event
-
union lwesp_cayenne_evt_t::[anonymous] evt¶
Event union
-
lwesp_cayenne_evt_type_t type¶
-
struct lwesp_cayenne_t¶
- #include <lwesp_cayenne.h>
Cayenne handle.
Public Members
-
lwesp_mqtt_client_api_p api_c¶
MQTT API client
-
const lwesp_mqtt_client_info_t *info_c¶
MQTT Client info structure
-
lwesp_cayenne_msg_t msg¶
Received data message
-
lwesp_cayenne_evt_t evt¶
Event handle
-
lwesp_cayenne_evt_fn evt_fn¶
Event callback function
-
lwesp_sys_thread_t thread¶
Cayenne thread handle
-
lwesp_sys_sem_t sem¶
Sync semaphore handle
-
lwesp_mqtt_client_api_p api_c¶
-
LWESP_CAYENNE_API_VERSION¶
HTTP Server¶
- group LWESP_APP_HTTP_SERVER
HTTP server based on callback API.
Defines
-
HTTP_MAX_HEADERS¶
Maximal number of headers we can control.
-
lwesp_http_server_write_string(hs, str)¶
Write string to HTTP server output.
Note
May only be called from SSI callback function
- Parameters
hs – [in] HTTP handle
str – [in] String to write
- Returns
Number of bytes written to output
Typedefs
-
typedef char *(*http_cgi_fn)(http_param_t *params, size_t params_len)¶
CGI callback function.
- Param params
[in] Pointer to list of parameteres and their values
- Param params_len
[in] Number of parameters
- Return
Function must return a new URI which is used later as response string, such as “/index.html” or similar
-
typedef lwespr_t (*http_post_start_fn)(struct http_state *hs, const char *uri, uint32_t content_length)¶
Post request started with non-zero content length function prototype.
-
typedef lwespr_t (*http_post_data_fn)(struct http_state *hs, lwesp_pbuf_p pbuf)¶
Post data received on request function prototype.
Note
This function may be called multiple time until content_length from http_post_start_fn callback is not reached
-
typedef lwespr_t (*http_post_end_fn)(struct http_state *hs)¶
End of POST data request function prototype.
-
typedef size_t (*http_ssi_fn)(struct http_state *hs, const char *tag_name, size_t tag_len)¶
SSI (Server Side Includes) callback function prototype.
Note
User can use server write functions to directly write to connection output
- Param hs
[in] HTTP state
- Param tag_name
[in] Name of TAG to replace with user content
- Param tag_len
[in] Length of TAG
- Returns
1 – Everything was written on this tag
0 – There are still data to write to output which means callback will be called again for user to process all the data
-
typedef uint8_t (*http_fs_open_fn)(struct http_fs_file *file, const char *path)¶
File system open file function Function is called when user file system (FAT or similar) should be invoked to open a file from specific path.
- Param file
[in] Pointer to file where user has to set length of file if opening was successful
- Param path
[in] Path of file to open
- Return
1 if file is opened, 0 otherwise
-
typedef uint32_t (*http_fs_read_fn)(struct http_fs_file *file, void *buff, size_t btr)¶
File system read file function Function may be called for
2
purposes. First is to read data and second to get remaining length of file to read.- Param file
[in] File pointer to read content
- Param buff
[in] Buffer to read data to. When parameter is set to NULL, number of remaining bytes available to read should be returned
- Param btr
[in] Number of bytes to read from file. This parameter has no meaning when buff is NULL
- Return
Number of bytes read or number of bytes available to read
-
typedef uint8_t (*http_fs_close_fn)(struct http_fs_file *file)¶
Close file callback function.
- Param file
[in] File to close
- Return
1
on success,0
otherwise
Enums
Functions
-
lwespr_t lwesp_http_server_init(const http_init_t *init, lwesp_port_t port)¶
Initialize HTTP server at specific port.
-
size_t lwesp_http_server_write(http_state_t *hs, const void *data, size_t len)¶
Write data directly to connection from callback.
Note
This function may only be called from SSI callback function for HTTP server
- Parameters
hs – [in] HTTP state
data – [in] Data to write
len – [in] Length of bytes to write
- Returns
Number of bytes written
-
struct http_param_t¶
- #include <lwesp_http_server.h>
HTTP parameters on http URI in format
?param1=value1¶m2=value2&...
-
struct http_cgi_t¶
- #include <lwesp_http_server.h>
CGI structure to register handlers on URI paths.
Public Members
-
const char *uri¶
URI path for CGI handler
-
http_cgi_fn fn¶
Callback function to call when we have a CGI match
-
const char *uri¶
-
struct http_init_t¶
- #include <lwesp_http_server.h>
HTTP server initialization structure.
Public Members
-
http_post_start_fn post_start_fn¶
Callback function for post start
-
http_post_data_fn post_data_fn¶
Callback functon for post data
-
http_post_end_fn post_end_fn¶
Callback functon for post end
-
const http_cgi_t *cgi¶
Pointer to array of CGI entries. Set to NULL if not used
-
size_t cgi_count¶
Length of CGI array. Set to 0 if not used
-
http_ssi_fn ssi_fn¶
SSI callback function
-
http_fs_open_fn fs_open¶
Open file function callback
-
http_fs_read_fn fs_read¶
Read file function callback
-
http_fs_close_fn fs_close¶
Close file function callback
-
http_post_start_fn post_start_fn¶
-
struct http_fs_file_table_t¶
- #include <lwesp_http_server.h>
HTTP file system table structure of static files in device memory.
-
struct http_fs_file_t¶
- #include <lwesp_http_server.h>
HTTP response file structure.
Public Members
-
const uint8_t *data¶
Pointer to data array in case file is static
-
uint8_t is_static¶
Flag indicating file is static and no dynamic read is required
-
uint32_t size¶
Total length of file
-
uint32_t fptr¶
File pointer to indicate next read position
-
const uint16_t *rem_open_files¶
Pointer to number of remaining open files. User can use value on this pointer to get number of other opened files
-
void *arg¶
User custom argument, may be used for user specific file system object
-
const uint8_t *data¶
-
struct http_state_t¶
- #include <lwesp_http_server.h>
HTTP state structure.
Public Members
-
lwesp_conn_p conn¶
Connection handle
-
lwesp_pbuf_p p¶
Header received pbuf chain
-
size_t conn_mem_available¶
Available memory in connection send queue
-
uint32_t written_total¶
Total number of bytes written into send buffer
-
uint32_t sent_total¶
Number of bytes we already sent
-
http_req_method_t req_method¶
Used request method
-
uint8_t headers_received¶
Did we fully received a headers?
-
uint8_t process_resp¶
Process with response flag
-
uint32_t content_length¶
Total expected content length for request (on POST) (without headers)
-
uint32_t content_received¶
Content length received so far (POST request, without headers)
-
http_fs_file_t rlwesp_file¶
Response file structure
-
uint8_t rlwesp_file_opened¶
Status if response file is opened and ready
-
const uint8_t *buff¶
Buffer pointer with data
-
uint32_t buff_len¶
Total length of buffer
-
uint32_t buff_ptr¶
Current buffer pointer
-
void *arg¶
User optional argument
-
const char *dyn_hdr_strs[4]¶
Pointer to constant strings for dynamic header outputs
-
size_t dyn_hdr_idx¶
Current header for processing on output
-
size_t dyn_hdr_pos¶
Current position in current index for output
-
char dyn_hdr_cnt_len[30]¶
Content length header response: “Content-Length: 0123456789\r\n”
-
uint8_t is_ssi¶
Flag if current request is SSI enabled
-
http_ssi_state_t ssi_state¶
Current SSI state when parsing SSI tags
-
char ssi_tag_buff[5 + 3 + 10 + 1]¶
Temporary buffer for SSI tag storing
-
size_t ssi_tag_buff_ptr¶
Current write pointer
-
size_t ssi_tag_buff_written¶
Number of bytes written so far to output buffer in case tag is not valid
-
size_t ssi_tag_len¶
Length of SSI tag
-
size_t ssi_tag_process_more¶
Set to
1
when we have to process tag multiple times
-
lwesp_conn_p conn¶
-
HTTP_MAX_HEADERS¶
- group LWESP_APP_HTTP_SERVER_FS_FAT
FATFS file system implementation for dynamic files.
Functions
-
uint8_t http_fs_open(http_fs_file_t *file, const char *path)¶
Open a file of specific path.
- Parameters
file – [in] File structure to fill if file is successfully open
path – [in] File path to open in format “/js/scripts.js” or “/index.html”
- Returns
1
on success,0
otherwise
-
uint32_t http_fs_read(http_fs_file_t *file, void *buff, size_t btr)¶
Read a file content.
- Parameters
file – [in] File handle to read
buff – [out] Buffer to read data to. When set to NULL, function should return remaining available data to read
btr – [in] Number of bytes to read. Has no meaning when buff = NULL
- Returns
Number of bytes read or number of bytes available to read
-
uint8_t http_fs_close(http_fs_file_t *file)¶
Close a file handle.
- Parameters
file – [in] File handle
- Returns
1
on success,0
otherwise
-
uint8_t http_fs_open(http_fs_file_t *file, const char *path)¶
MQTT Client¶
MQTT client v3.1.1 implementation, based on callback (non-netconn) connection API.
1/*
2 * MQTT client example with ESP device.
3 *
4 * Once device is connected to network,
5 * it will try to connect to mosquitto test server and start the MQTT.
6 *
7 * If successfully connected, it will publish data to "esp8266_mqtt_topic" topic every x seconds.
8 *
9 * To check if data are sent, you can use mqtt-spy PC software to inspect
10 * test.mosquitto.org server and subscribe to publishing topic
11 */
12
13#include "lwesp/apps/lwesp_mqtt_client.h"
14#include "lwesp/lwesp.h"
15#include "lwesp/lwesp_timeout.h"
16#include "mqtt_client.h"
17
18/**
19 * \brief MQTT client structure
20 */
21static lwesp_mqtt_client_p
22mqtt_client;
23
24/**
25 * \brief Client ID is structured from ESP station MAC address
26 */
27static char
28mqtt_client_id[13];
29
30/**
31 * \brief Connection information for MQTT CONNECT packet
32 */
33static const lwesp_mqtt_client_info_t
34mqtt_client_info = {
35 .id = mqtt_client_id, /* The only required field for connection! */
36
37 .keep_alive = 10,
38 // .user = "test_username",
39 // .pass = "test_password",
40};
41
42static void mqtt_cb(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t* evt);
43static void example_do_connect(lwesp_mqtt_client_p client);
44static uint32_t retries = 0;
45
46/**
47 * \brief Custom callback function for ESP events
48 */
49static lwespr_t
50mqtt_lwesp_cb(lwesp_evt_t* evt) {
51 switch (lwesp_evt_get_type(evt)) {
52#if LWESP_CFG_MODE_STATION
53 case LWESP_EVT_WIFI_GOT_IP: {
54 example_do_connect(mqtt_client); /* Start connection after we have a connection to network client */
55 break;
56 }
57#endif /* LWESP_CFG_MODE_STATION */
58 default:
59 break;
60 }
61 return lwespOK;
62}
63
64/**
65 * \brief MQTT client thread
66 * \param[in] arg: User argument
67 */
68void
69mqtt_client_thread(void const* arg) {
70 lwesp_mac_t mac;
71
72 lwesp_evt_register(mqtt_lwesp_cb); /* Register new callback for general events from ESP stack */
73
74 /* Get station MAC to format client ID */
75 if (lwesp_sta_getmac(&mac, NULL, NULL, 1) == lwespOK) {
76 snprintf(mqtt_client_id, sizeof(mqtt_client_id), "%02X%02X%02X%02X%02X%02X",
77 (unsigned)mac.mac[0], (unsigned)mac.mac[1], (unsigned)mac.mac[2],
78 (unsigned)mac.mac[3], (unsigned)mac.mac[4], (unsigned)mac.mac[5]
79 );
80 } else {
81 strcpy(mqtt_client_id, "unknown");
82 }
83 printf("MQTT Client ID: %s\r\n", mqtt_client_id);
84
85 /*
86 * Create a new client with 256 bytes of RAW TX data
87 * and 128 bytes of RAW incoming data
88 */
89 mqtt_client = lwesp_mqtt_client_new(256, 128);/* Create new MQTT client */
90 if (lwesp_sta_is_joined()) { /* If ESP is already joined to network */
91 example_do_connect(mqtt_client); /* Start connection to MQTT server */
92 }
93
94 /* Make dummy delay of thread */
95 while (1) {
96 lwesp_delay(1000);
97 }
98}
99
100/**
101 * \brief Timeout callback for MQTT events
102 * \param[in] arg: User argument
103 */
104void
105mqtt_timeout_cb(void* arg) {
106 static uint32_t num = 10;
107 lwesp_mqtt_client_p client = arg;
108 lwespr_t res;
109
110 static char tx_data[20];
111
112 if (lwesp_mqtt_client_is_connected(client)) {
113 sprintf(tx_data, "R: %u, N: %u", (unsigned)retries, (unsigned)num);
114 if ((res = lwesp_mqtt_client_publish(client, "esp8266_mqtt_topic", tx_data, LWESP_U16(strlen(tx_data)), LWESP_MQTT_QOS_EXACTLY_ONCE, 0, (void*)((uintptr_t)num))) == lwespOK) {
115 printf("Publishing %d...\r\n", (int)num);
116 num++;
117 } else {
118 printf("Cannot publish...: %d\r\n", (int)res);
119 }
120 }
121 lwesp_timeout_add(10000, mqtt_timeout_cb, client);
122}
123
124/**
125 * \brief MQTT event callback function
126 * \param[in] client: MQTT client where event occurred
127 * \param[in] evt: Event type and data
128 */
129static void
130mqtt_cb(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t* evt) {
131 switch (lwesp_mqtt_client_evt_get_type(client, evt)) {
132 /*
133 * Connect event
134 * Called if user successfully connected to MQTT server
135 * or even if connection failed for some reason
136 */
137 case LWESP_MQTT_EVT_CONNECT: { /* MQTT connect event occurred */
138 lwesp_mqtt_conn_status_t status = lwesp_mqtt_client_evt_connect_get_status(client, evt);
139
140 if (status == LWESP_MQTT_CONN_STATUS_ACCEPTED) {
141 printf("MQTT accepted!\r\n");
142 /*
143 * Once we are accepted by server,
144 * it is time to subscribe to different topics
145 * We will subscrive to "mqtt_lwesp_example_topic" topic,
146 * and will also set the same name as subscribe argument for callback later
147 */
148 lwesp_mqtt_client_subscribe(client, "esp8266_mqtt_topic", LWESP_MQTT_QOS_EXACTLY_ONCE, "esp8266_mqtt_topic");
149
150 /* Start timeout timer after 5000ms and call mqtt_timeout_cb function */
151 lwesp_timeout_add(5000, mqtt_timeout_cb, client);
152 } else {
153 printf("MQTT server connection was not successful: %d\r\n", (int)status);
154
155 /* Try to connect all over again */
156 example_do_connect(client);
157 }
158 break;
159 }
160
161 /*
162 * Subscribe event just happened.
163 * Here it is time to check if it was successful or failed attempt
164 */
165 case LWESP_MQTT_EVT_SUBSCRIBE: {
166 const char* arg = lwesp_mqtt_client_evt_subscribe_get_argument(client, evt); /* Get user argument */
167 lwespr_t res = lwesp_mqtt_client_evt_subscribe_get_result(client, evt); /* Get result of subscribe event */
168
169 if (res == lwespOK) {
170 printf("Successfully subscribed to %s topic\r\n", arg);
171 if (!strcmp(arg, "esp8266_mqtt_topic")) { /* Check topic name we were subscribed */
172 /* Subscribed to "esp8266_mqtt_topic" topic */
173
174 /*
175 * Now publish an even on example topic
176 * and set QoS to minimal value which does not guarantee message delivery to received
177 */
178 lwesp_mqtt_client_publish(client, "esp8266_mqtt_topic", "test_data", 9, LWESP_MQTT_QOS_AT_MOST_ONCE, 0, (void*)1);
179 }
180 }
181 break;
182 }
183
184 /* Message published event occurred */
185 case LWESP_MQTT_EVT_PUBLISH: {
186 uint32_t val = (uint32_t)(uintptr_t)lwesp_mqtt_client_evt_publish_get_argument(client, evt);/* Get user argument, which is in fact our custom number */
187
188 printf("Publish event, user argument on message was: %d\r\n", (int)val);
189 break;
190 }
191
192 /*
193 * A new message was published to us
194 * and now it is time to read the data
195 */
196 case LWESP_MQTT_EVT_PUBLISH_RECV: {
197 const char* topic = lwesp_mqtt_client_evt_publish_recv_get_topic(client, evt);
198 size_t topic_len = lwesp_mqtt_client_evt_publish_recv_get_topic_len(client, evt);
199 const uint8_t* payload = lwesp_mqtt_client_evt_publish_recv_get_payload(client, evt);
200 size_t payload_len = lwesp_mqtt_client_evt_publish_recv_get_payload_len(client, evt);
201
202 LWESP_UNUSED(payload);
203 LWESP_UNUSED(payload_len);
204 LWESP_UNUSED(topic);
205 LWESP_UNUSED(topic_len);
206 break;
207 }
208
209 /* Client is fully disconnected from MQTT server */
210 case LWESP_MQTT_EVT_DISCONNECT: {
211 printf("MQTT client disconnected!\r\n");
212 example_do_connect(client); /* Connect to server all over again */
213 break;
214 }
215
216 default:
217 break;
218 }
219}
220
221/** Make a connection to MQTT server in non-blocking mode */
222static void
223example_do_connect(lwesp_mqtt_client_p client) {
224 if (client == NULL) {
225 return;
226 }
227
228 /*
229 * Start a simple connection to open source
230 * MQTT server on mosquitto.org
231 */
232 retries++;
233 lwesp_timeout_remove(mqtt_timeout_cb);
234 lwesp_mqtt_client_connect(mqtt_client, "test.mosquitto.org", 1883, mqtt_cb, &mqtt_client_info);
235}
- group LWESP_APP_MQTT_CLIENT
MQTT client.
Typedefs
-
typedef struct lwesp_mqtt_client *lwesp_mqtt_client_p¶
Pointer to lwesp_mqtt_client_t structure.
-
typedef void (*lwesp_mqtt_evt_fn)(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t *evt)¶
MQTT event callback function.
- Param client
[in] MQTT client
- Param evt
[in] MQTT event with type and related data
Enums
-
enum lwesp_mqtt_qos_t¶
Quality of service enumeration.
Values:
-
enumerator LWESP_MQTT_QOS_AT_MOST_ONCE¶
Delivery is not guaranteed to arrive, but can arrive
up to 1 time
= non-critical packets where losses are allowed
-
enumerator LWESP_MQTT_QOS_AT_LEAST_ONCE¶
Delivery is quaranteed
at least once
, but it may be delivered multiple times with the same content
-
enumerator LWESP_MQTT_QOS_EXACTLY_ONCE¶
Delivery is quaranteed
exactly once
= very critical packets such as billing informations or similar
-
enumerator LWESP_MQTT_QOS_AT_MOST_ONCE¶
-
enum lwesp_mqtt_state_t¶
State of MQTT client.
Values:
-
enumerator LWESP_MQTT_CONN_DISCONNECTED¶
Connection with server is not established
-
enumerator LWESP_MQTT_CONN_CONNECTING¶
Client is connecting to server
-
enumerator LWESP_MQTT_CONN_DISCONNECTING¶
Client connection is disconnecting from server
-
enumerator LWESP_MQTT_CONNECTING¶
MQTT client is connecting… CONNECT command has been sent to server
-
enumerator LWESP_MQTT_CONNECTED¶
MQTT is fully connected and ready to send data on topics
-
enumerator LWESP_MQTT_CONN_DISCONNECTED¶
-
enum lwesp_mqtt_evt_type_t¶
MQTT event types.
Values:
-
enumerator LWESP_MQTT_EVT_CONNECT¶
MQTT client connect event
-
enumerator LWESP_MQTT_EVT_SUBSCRIBE¶
MQTT client subscribed to specific topic
-
enumerator LWESP_MQTT_EVT_UNSUBSCRIBE¶
MQTT client unsubscribed from specific topic
-
enumerator LWESP_MQTT_EVT_PUBLISH¶
MQTT client publish message to server event.
Note
When publishing packet with quality of service LWESP_MQTT_QOS_AT_MOST_ONCE, you may not receive event, even if packet was successfully sent, thus do not rely on this event for packet with
qos = LWESP_MQTT_QOS_AT_MOST_ONCE
-
enumerator LWESP_MQTT_EVT_PUBLISH_RECV¶
MQTT client received a publish message from server
-
enumerator LWESP_MQTT_EVT_DISCONNECT¶
MQTT client disconnected from MQTT server
-
enumerator LWESP_MQTT_EVT_KEEP_ALIVE¶
MQTT keep-alive sent to server and reply received
-
enumerator LWESP_MQTT_EVT_CONNECT¶
-
enum lwesp_mqtt_conn_status_t¶
List of possible results from MQTT server when executing connect command.
Values:
-
enumerator LWESP_MQTT_CONN_STATUS_ACCEPTED¶
Connection accepted and ready to use
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_PROTOCOL_VERSION¶
Connection Refused, unacceptable protocol version
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_ID¶
Connection refused, identifier rejected
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_SERVER¶
Connection refused, server unavailable
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_USER_PASS¶
Connection refused, bad user name or password
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_NOT_AUTHORIZED¶
Connection refused, not authorized
-
enumerator LWESP_MQTT_CONN_STATUS_TCP_FAILED¶
TCP connection to server was not successful
-
enumerator LWESP_MQTT_CONN_STATUS_ACCEPTED¶
Functions
-
lwesp_mqtt_client_p lwesp_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len)¶
Allocate a new MQTT client structure.
- Parameters
tx_buff_len – [in] Length of raw data output buffer
rx_buff_len – [in] Length of raw data input buffer
- Returns
Pointer to new allocated MQTT client structure or
NULL
on failure
-
void lwesp_mqtt_client_delete(lwesp_mqtt_client_p client)¶
Delete MQTT client structure.
Note
MQTT client must be disconnected first
- Parameters
client – [in] MQTT client
-
lwespr_t lwesp_mqtt_client_connect(lwesp_mqtt_client_p client, const char *host, lwesp_port_t port, lwesp_mqtt_evt_fn evt_fn, const lwesp_mqtt_client_info_t *info)¶
Connect to MQTT server.
Note
After TCP connection is established, CONNECT packet is automatically sent to server
-
lwespr_t lwesp_mqtt_client_disconnect(lwesp_mqtt_client_p client)¶
Disconnect from MQTT server.
-
uint8_t lwesp_mqtt_client_is_connected(lwesp_mqtt_client_p client)¶
Test if client is connected to server and accepted to MQTT protocol.
Note
Function will return error if TCP is connected but MQTT not accepted
- Parameters
client – [in] MQTT client
- Returns
1
on success,0
otherwise
-
lwespr_t lwesp_mqtt_client_subscribe(lwesp_mqtt_client_p client, const char *topic, lwesp_mqtt_qos_t qos, void *arg)¶
Subscribe to MQTT topic.
- Parameters
client – [in] MQTT client
topic – [in] Topic name to subscribe to
qos – [in] Quality of service. This parameter can be a value of lwesp_mqtt_qos_t
arg – [in] User custom argument used in callback
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_mqtt_client_unsubscribe(lwesp_mqtt_client_p client, const char *topic, void *arg)¶
Unsubscribe from MQTT topic.
-
lwespr_t lwesp_mqtt_client_publish(lwesp_mqtt_client_p client, const char *topic, const void *payload, uint16_t len, lwesp_mqtt_qos_t qos, uint8_t retain, void *arg)¶
Publish a new message on specific topic.
- Parameters
client – [in] MQTT client
topic – [in] Topic to send message to
payload – [in] Message data
payload_len – [in] Length of payload data
qos – [in] Quality of service. This parameter can be a value of lwesp_mqtt_qos_t enumeration
retain – [in] Retian parameter value
arg – [in] User custom argument used in callback
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
void *lwesp_mqtt_client_get_arg(lwesp_mqtt_client_p client)¶
Get user argument on client.
- Parameters
client – [in] MQTT client handle
- Returns
User argument
-
void lwesp_mqtt_client_set_arg(lwesp_mqtt_client_p client, void *arg)¶
Set user argument on client.
- Parameters
client – [in] MQTT client handle
arg – [in] User argument
-
struct lwesp_mqtt_client_info_t¶
- #include <lwesp_mqtt_client.h>
MQTT client information structure.
Public Members
-
const char *id¶
Client unique identifier. It is required and must be set by user
-
const char *user¶
Authentication username. Set to
NULL
if not required
-
const char *pass¶
Authentication password, set to
NULL
if not required
-
uint16_t keep_alive¶
Keep-alive parameter in units of seconds. When set to
0
, functionality is disabled (not recommended)
-
const char *will_topic¶
Will topic
-
const char *will_message¶
Will message
-
lwesp_mqtt_qos_t will_qos¶
Will topic quality of service
-
const char *id¶
-
struct lwesp_mqtt_request_t¶
- #include <lwesp_mqtt_client.h>
MQTT request object.
Public Members
-
uint8_t status¶
Entry status flag for in use or pending bit
-
uint16_t packet_id¶
Packet ID generated by client on publish
-
void *arg¶
User defined argument
-
uint32_t expected_sent_len¶
Number of total bytes which must be sent on connection before we can say “packet was sent”.
-
uint32_t timeout_start_time¶
Timeout start time in units of milliseconds
-
uint8_t status¶
-
struct lwesp_mqtt_evt_t¶
- #include <lwesp_mqtt_client.h>
MQTT event structure for callback function.
Public Members
-
lwesp_mqtt_evt_type_t type¶
Event type
-
lwesp_mqtt_conn_status_t status¶
Connection status with MQTT
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] connect¶
Event for connecting to server
-
uint8_t is_accepted¶
Status if client was accepted to MQTT prior disconnect event
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] disconnect¶
Event for disconnecting from server
-
void *arg¶
User argument for callback function
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] sub_unsub_scribed¶
Event for (un)subscribe to/from topics
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] publish¶
Published event
-
const uint8_t *topic¶
Pointer to topic identifier
-
size_t topic_len¶
Length of topic
-
const void *payload¶
Topic payload
-
size_t payload_len¶
Length of topic payload
-
uint8_t dup¶
Duplicate flag if message was sent again
-
lwesp_mqtt_qos_t qos¶
Received packet quality of service
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] publish_recv¶
Publish received event
-
union lwesp_mqtt_evt_t::[anonymous] evt¶
Event data parameters
-
lwesp_mqtt_evt_type_t type¶
-
typedef struct lwesp_mqtt_client *lwesp_mqtt_client_p¶
- group LWESP_APP_MQTT_CLIENT_EVT
Event helper functions.
Connect event
Note
Use these functions on LWESP_MQTT_EVT_CONNECT event
-
lwesp_mqtt_client_evt_connect_get_status(client, evt)¶
Get connection status.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Connection status. Member of lwesp_mqtt_conn_status_t
Disconnect event
Note
Use these functions on LWESP_MQTT_EVT_DISCONNECT event
-
lwesp_mqtt_client_evt_disconnect_is_accepted(client, evt)¶
Check if MQTT client was accepted by server when disconnect event occurred.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
1
on success,0
otherwise
Subscribe/unsubscribe event
Note
Use these functions on LWESP_MQTT_EVT_SUBSCRIBE or LWESP_MQTT_EVT_UNSUBSCRIBE events
-
lwesp_mqtt_client_evt_subscribe_get_argument(client, evt)¶
Get user argument used on lwesp_mqtt_client_subscribe.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
User argument
-
lwesp_mqtt_client_evt_subscribe_get_result(client, evt)¶
Get result of subscribe event.
-
lwesp_mqtt_client_evt_unsubscribe_get_argument(client, evt)¶
Get user argument used on lwesp_mqtt_client_unsubscribe.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
User argument
Publish receive event
Note
Use these functions on LWESP_MQTT_EVT_PUBLISH_RECV event
-
lwesp_mqtt_client_evt_publish_recv_get_topic(client, evt)¶
Get topic from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Topic name
-
lwesp_mqtt_client_evt_publish_recv_get_topic_len(client, evt)¶
Get topic length from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Topic length
-
lwesp_mqtt_client_evt_publish_recv_get_payload(client, evt)¶
Get payload from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Packet payload
-
lwesp_mqtt_client_evt_publish_recv_get_payload_len(client, evt)¶
Get payload length from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Payload length
-
lwesp_mqtt_client_evt_publish_recv_is_duplicate(client, evt)¶
Check if packet is duplicated.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
1
if duplicated,0
otherwise
-
lwesp_mqtt_client_evt_publish_recv_get_qos(client, evt)¶
Get received quality of service.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Member of lwesp_mqtt_qos_t enumeration
Publish event
Note
Use these functions on LWESP_MQTT_EVT_PUBLISH event
-
lwesp_mqtt_client_evt_publish_get_argument(client, evt)¶
Get user argument used on lwesp_mqtt_client_publish.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
User argument
Defines
-
lwesp_mqtt_client_evt_get_type(client, evt)¶
Get MQTT event type.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
MQTT Event type, value of lwesp_mqtt_evt_type_t enumeration
-
lwesp_mqtt_client_evt_connect_get_status(client, evt)¶
MQTT Client API¶
MQTT Client API provides sequential API built on top of MQTT Client.
1/*
2 * MQTT client API example with ESP device.
3 *
4 * Once device is connected to network,
5 * it will try to connect to mosquitto test server and start the MQTT.
6 *
7 * If successfully connected, it will publish data to "lwesp_mqtt_topic" topic every x seconds.
8 *
9 * To check if data are sent, you can use mqtt-spy PC software to inspect
10 * test.mosquitto.org server and subscribe to publishing topic
11 */
12
13#include "lwesp/apps/lwesp_mqtt_client_api.h"
14#include "mqtt_client_api.h"
15#include "lwesp/lwesp_mem.h"
16
17/**
18 * \brief Connection information for MQTT CONNECT packet
19 */
20static const lwesp_mqtt_client_info_t
21mqtt_client_info = {
22 .keep_alive = 10,
23
24 /* Server login data */
25 .user = "8a215f70-a644-11e8-ac49-e932ed599553",
26 .pass = "26aa943f702e5e780f015cd048a91e8fb54cca28",
27
28 /* Device identifier address */
29 .id = "869f5a20-af9c-11e9-b01f-db5cf74e7fb7",
30};
31
32/**
33 * \brief Memory for topic
34 */
35static char
36mqtt_topic_str[256];
37
38/**
39 * \brief Memory for data
40 */
41static char
42mqtt_topic_data[256];
43
44/**
45 * \brief Generate random number and write it to string
46 * \param[out] str: Output string with new number
47 */
48void
49generate_random(char* str) {
50 static uint32_t random_beg = 0x8916;
51 random_beg = random_beg * 0x00123455 + 0x85654321;
52 sprintf(str, "%u", (unsigned)((random_beg >> 8) & 0xFFFF));
53}
54
55/**
56 * \brief MQTT client API thread
57 */
58void
59mqtt_client_api_thread(void const* arg) {
60 lwesp_mqtt_client_api_p client;
61 lwesp_mqtt_conn_status_t conn_status;
62 lwesp_mqtt_client_api_buf_p buf;
63 lwespr_t res;
64 char random_str[10];
65
66 /* Create new MQTT API */
67 client = lwesp_mqtt_client_api_new(256, 128);
68 if (client == NULL) {
69 goto terminate;
70 }
71
72 while (1) {
73 /* Make a connection */
74 printf("Joining MQTT server\r\n");
75
76 /* Try to join */
77 conn_status = lwesp_mqtt_client_api_connect(client, "mqtt.mydevices.com", 1883, &mqtt_client_info);
78 if (conn_status == LWESP_MQTT_CONN_STATUS_ACCEPTED) {
79 printf("Connected and accepted!\r\n");
80 printf("Client is ready to subscribe and publish to new messages\r\n");
81 } else {
82 printf("Connect API response: %d\r\n", (int)conn_status);
83 lwesp_delay(5000);
84 continue;
85 }
86
87 /* Subscribe to topics */
88 sprintf(mqtt_topic_str, "v1/%s/things/%s/cmd/#", mqtt_client_info.user, mqtt_client_info.id);
89 if (lwesp_mqtt_client_api_subscribe(client, mqtt_topic_str, LWESP_MQTT_QOS_AT_LEAST_ONCE) == lwespOK) {
90 printf("Subscribed to topic\r\n");
91 } else {
92 printf("Problem subscribing to topic!\r\n");
93 }
94
95 while (1) {
96 /* Receive MQTT packet with 1000ms timeout */
97 res = lwesp_mqtt_client_api_receive(client, &buf, 5000);
98 if (res == lwespOK) {
99 if (buf != NULL) {
100 printf("Publish received!\r\n");
101 printf("Topic: %s, payload: %s\r\n", buf->topic, buf->payload);
102 lwesp_mqtt_client_api_buf_free(buf);
103 buf = NULL;
104 }
105 } else if (res == lwespCLOSED) {
106 printf("MQTT connection closed!\r\n");
107 break;
108 } else if (res == lwespTIMEOUT) {
109 printf("Timeout on MQTT receive function. Manually publishing.\r\n");
110
111 /* Publish data on channel 1 */
112 generate_random(random_str);
113 sprintf(mqtt_topic_str, "v1/%s/things/%s/data/1", mqtt_client_info.user, mqtt_client_info.id);
114 sprintf(mqtt_topic_data, "temp,c=%s", random_str);
115 lwesp_mqtt_client_api_publish(client, mqtt_topic_str, mqtt_topic_data, strlen(mqtt_topic_data), LWESP_MQTT_QOS_AT_LEAST_ONCE, 0);
116 }
117 }
118 //goto terminate;
119 }
120
121terminate:
122 lwesp_mqtt_client_api_delete(client);
123 printf("MQTT client thread terminate\r\n");
124 lwesp_sys_thread_terminate(NULL);
125}
- group LWESP_APP_MQTT_CLIENT_API
Sequential, single thread MQTT client API.
Typedefs
-
typedef struct lwesp_mqtt_client_api_buf *lwesp_mqtt_client_api_buf_p¶
Pointer to lwesp_mqtt_client_api_buf_t structure.
Functions
-
lwesp_mqtt_client_api_p lwesp_mqtt_client_api_new(size_t tx_buff_len, size_t rx_buff_len)¶
Create new MQTT client API.
- Parameters
tx_buff_len – [in] Maximal TX buffer for maximal packet length
rx_buff_len – [in] Maximal RX buffer
- Returns
Client handle on success,
NULL
otherwise
-
void lwesp_mqtt_client_api_delete(lwesp_mqtt_client_api_p client)¶
Delete client from memory.
- Parameters
client – [in] MQTT API client handle
-
lwesp_mqtt_conn_status_t lwesp_mqtt_client_api_connect(lwesp_mqtt_client_api_p client, const char *host, lwesp_port_t port, const lwesp_mqtt_client_info_t *info)¶
Connect to MQTT broker.
- Parameters
client – [in] MQTT API client handle
host – [in] TCP host
port – [in] TCP port
info – [in] MQTT client info
- Returns
LWESP_MQTT_CONN_STATUS_ACCEPTED on success, member of lwesp_mqtt_conn_status_t otherwise
-
lwespr_t lwesp_mqtt_client_api_subscribe(lwesp_mqtt_client_api_p client, const char *topic, lwesp_mqtt_qos_t qos)¶
Subscribe to topic.
- Parameters
client – [in] MQTT API client handle
topic – [in] Topic to subscribe on
qos – [in] Quality of service. This parameter can be a value of lwesp_mqtt_qos_t
- Returns
-
lwespr_t lwesp_mqtt_client_api_unsubscribe(lwesp_mqtt_client_api_p client, const char *topic)¶
Unsubscribe from topic.
-
lwespr_t lwesp_mqtt_client_api_publish(lwesp_mqtt_client_api_p client, const char *topic, const void *data, size_t btw, lwesp_mqtt_qos_t qos, uint8_t retain)¶
Publish new packet to MQTT network.
- Parameters
client – [in] MQTT API client handle
topic – [in] Topic to publish on
data – [in] Data to send
btw – [in] Number of bytes to send for data parameter
qos – [in] Quality of service. This parameter can be a value of lwesp_mqtt_qos_t
retain – [in] Set to
1
for retain flag,0
otherwise
- Returns
-
uint8_t lwesp_mqtt_client_api_is_connected(lwesp_mqtt_client_api_p client)¶
Check if client MQTT connection is active.
- Parameters
client – [in] MQTT API client handle
- Returns
1
on success,0
otherwise
-
lwespr_t lwesp_mqtt_client_api_receive(lwesp_mqtt_client_api_p client, lwesp_mqtt_client_api_buf_p *p, uint32_t timeout)¶
Receive next packet in specific timeout time.
Note
This function can be called from separate thread than the rest of API function, which allows you to handle receive data separated with custom timeout
- Parameters
client – [in] MQTT API client handle
p – [in] Pointer to output buffer
timeout – [in] Maximal time to wait before function returns timeout
- Returns
lwespOK on success, lwespCLOSED if MQTT is closed, lwespTIMEOUT on timeout
-
void lwesp_mqtt_client_api_buf_free(lwesp_mqtt_client_api_buf_p p)¶
Free buffer memory after usage.
- Parameters
p – [in] Buffer to free
-
struct lwesp_mqtt_client_api_buf_t¶
- #include <lwesp_mqtt_client_api.h>
MQTT API RX buffer.
-
typedef struct lwesp_mqtt_client_api_buf *lwesp_mqtt_client_api_buf_p¶
Netconn API¶
Netconn API is addon on top of existing connection module and allows sending and receiving data with sequential API calls, similar to POSIX socket API.
It can operate in client or server mode and uses operating system features, such as message queues and semaphore to link non-blocking callback API for connections with sequential API for application thread.
Note
Connection API does not directly allow receiving data with sequential and linear code execution. All is based on connection event system. Netconn adds this functionality as it is implemented on top of regular connection API.
Warning
Netconn API are designed to be called from application threads ONLY. It is not allowed to call any of netconn API functions from within interrupt or callback event functions.
Netconn client¶
Netconn API client block diagram¶
Above block diagram shows basic architecture of netconn client application. There is always one application thread (in green) which calls netconn API functions to interact with connection API in synchronous mode.
Every netconn connection uses dedicated structure to handle message queue for data received packet buffers. Each time new packet is received (red block, data received event), reference to it is written to message queue of netconn structure, while application thread reads new entries from the same queue to get packets.
1#include "netconn_client.h"
2#include "lwesp/lwesp.h"
3
4/**
5 * \brief Host and port settings
6 */
7#define NETCONN_HOST "example.com"
8#define NETCONN_PORT 80
9
10/**
11 * \brief Request header to send on successful connection
12 */
13static const char
14request_header[] = ""
15 "GET / HTTP/1.1\r\n"
16 "Host: " NETCONN_HOST "\r\n"
17 "Connection: close\r\n"
18 "\r\n";
19
20/**
21 * \brief Netconn client thread implementation
22 * \param[in] arg: User argument
23 */
24void
25netconn_client_thread(void const* arg) {
26 lwespr_t res;
27 lwesp_pbuf_p pbuf;
28 lwesp_netconn_p client;
29 lwesp_sys_sem_t* sem = (void*)arg;
30
31 /*
32 * First create a new instance of netconn
33 * connection and initialize system message boxes
34 * to accept received packet buffers
35 */
36 client = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP);
37 if (client != NULL) {
38 /*
39 * Connect to external server as client
40 * with custom NETCONN_CONN_HOST and CONN_PORT values
41 *
42 * Function will block thread until we are successfully connected (or not) to server
43 */
44 res = lwesp_netconn_connect(client, NETCONN_HOST, NETCONN_PORT);
45 if (res == lwespOK) { /* Are we successfully connected? */
46 printf("Connected to " NETCONN_HOST "\r\n");
47 res = lwesp_netconn_write(client, request_header, sizeof(request_header) - 1); /* Send data to server */
48 if (res == lwespOK) {
49 res = lwesp_netconn_flush(client); /* Flush data to output */
50 }
51 if (res == lwespOK) { /* Were data sent? */
52 printf("Data were successfully sent to server\r\n");
53
54 /*
55 * Since we sent HTTP request,
56 * we are expecting some data from server
57 * or at least forced connection close from remote side
58 */
59 do {
60 /*
61 * Receive single packet of data
62 *
63 * Function will block thread until new packet
64 * is ready to be read from remote side
65 *
66 * After function returns, don't forgot the check value.
67 * Returned status will give you info in case connection
68 * was closed too early from remote side
69 */
70 res = lwesp_netconn_receive(client, &pbuf);
71 if (res == lwespCLOSED) { /* Was the connection closed? This can be checked by return status of receive function */
72 printf("Connection closed by remote side...\r\n");
73 break;
74 } else if (res == lwespTIMEOUT) {
75 printf("Netconn timeout while receiving data. You may try multiple readings before deciding to close manually\r\n");
76 }
77
78 if (res == lwespOK && pbuf != NULL) { /* Make sure we have valid packet buffer */
79 /*
80 * At this point read and manipulate
81 * with received buffer and check if you expect more data
82 *
83 * After you are done using it, it is important
84 * you free the memory otherwise memory leaks will appear
85 */
86 printf("Received new data packet of %d bytes\r\n", (int)lwesp_pbuf_length(pbuf, 1));
87 lwesp_pbuf_free(pbuf); /* Free the memory after usage */
88 pbuf = NULL;
89 }
90 } while (1);
91 } else {
92 printf("Error writing data to remote host!\r\n");
93 }
94
95 /*
96 * Check if connection was closed by remote server
97 * and in case it wasn't, close it manually
98 */
99 if (res != lwespCLOSED) {
100 lwesp_netconn_close(client);
101 }
102 } else {
103 printf("Cannot connect to remote host %s:%d!\r\n", NETCONN_HOST, NETCONN_PORT);
104 }
105 lwesp_netconn_delete(client); /* Delete netconn structure */
106 }
107
108 printf("Terminating thread\r\n");
109 if (lwesp_sys_sem_isvalid(sem)) {
110 lwesp_sys_sem_release(sem);
111 }
112 lwesp_sys_thread_terminate(NULL); /* Terminate current thread */
113}
Netconn server¶
Netconn API server block diagram¶
When netconn is configured in server mode, it is possible to accept new clients from remote side. Application creates netconn server connection, which can only accept clients and cannot send/receive any data. It configures server on dedicated port (selected by application) and listens on it.
When new client connects, server callback function is called with new active connection event. Newly accepted connection is then written to server structure netconn which is later read by application thread. At the same time, netconn connection structure (blue) is created to allow standard send/receive operation on active connection.
Note
Each connected client has its own netconn connection structure. When multiple clients connect to server at the same time, multiple entries are written to connection accept message queue and are ready to be processed by application thread.
From this point, program flow is the same as in case of netconn client.
This is basic example for netconn thread. It waits for client and processes it in blocking mode.
Warning
When multiple clients connect at the same time to netconn server, they are processed one-by-one, sequentially. This may introduce delay in response for other clients. Check netconn concurrency option to process multiple clients at the same time
1/*
2 * Netconn server example is based on single thread
3 * and it listens for single client only on port 23
4 */
5#include "netconn_server_1thread.h"
6#include "lwesp/lwesp.h"
7
8/**
9 * \brief Basic thread for netconn server to test connections
10 * \param[in] arg: User argument
11 */
12void
13netconn_server_1thread_thread(void* arg) {
14 lwespr_t res;
15 lwesp_netconn_p server, client;
16 lwesp_pbuf_p p;
17
18 /* Create netconn for server */
19 server = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP);
20 if (server == NULL) {
21 printf("Cannot create server netconn!\r\n");
22 }
23
24 /* Bind it to port 23 */
25 res = lwesp_netconn_bind(server, 23);
26 if (res != lwespOK) {
27 printf("Cannot bind server\r\n");
28 goto out;
29 }
30
31 /* Start listening for incoming connections with maximal 1 client */
32 res = lwesp_netconn_listen_with_max_conn(server, 1);
33 if (res != lwespOK) {
34 goto out;
35 }
36
37 /* Unlimited loop */
38 while (1) {
39 /* Accept new client */
40 res = lwesp_netconn_accept(server, &client);
41 if (res != lwespOK) {
42 break;
43 }
44 printf("New client accepted!\r\n");
45 while (1) {
46 /* Receive data */
47 res = lwesp_netconn_receive(client, &p);
48 if (res == lwespOK) {
49 printf("Data received!\r\n");
50 lwesp_pbuf_free(p);
51 } else {
52 printf("Netconn receive returned: %d\r\n", (int)res);
53 if (res == lwespCLOSED) {
54 printf("Connection closed by client\r\n");
55 break;
56 }
57 }
58 }
59 /* Delete client */
60 if (client != NULL) {
61 lwesp_netconn_delete(client);
62 client = NULL;
63 }
64 }
65 /* Delete client */
66 if (client != NULL) {
67 lwesp_netconn_delete(client);
68 client = NULL;
69 }
70
71out:
72 printf("Terminating netconn thread!\r\n");
73 if (server != NULL) {
74 lwesp_netconn_delete(server);
75 }
76 lwesp_sys_thread_terminate(NULL);
77}
Netconn server concurrency¶
Netconn API server concurrency block diagram¶
When compared to classic netconn server, concurrent netconn server mode allows multiple clients to be processed at the same time. This can drastically improve performance and response time on clients side, especially when many clients are connected to server at the same time.
Every time server application thread (green block) gets new client to process, it starts a new processing thread instead of doing it in accept thread.
Server thread is only dedicated to accept clients and start threads
Multiple processing thread can run in parallel to send/receive data from multiple clients
No delay when multi clients are active at the same time
Higher memory footprint is necessary as there are multiple threads active
1/*
2 * Netconn server example is based on single "user" thread
3 * which listens for new connections and accepts them.
4 *
5 * When a new client is accepted by server,
6 * separate thread for client is created where
7 * data is read, processed and send back to user
8 */
9#include "netconn_server.h"
10#include "lwesp/lwesp.h"
11
12static void netconn_server_processing_thread(void* const arg);
13
14/**
15 * \brief Main page response file
16 */
17static const uint8_t
18rlwesp_data_mainpage_top[] = ""
19 "HTTP/1.1 200 OK\r\n"
20 "Content-Type: text/html\r\n"
21 "\r\n"
22 "<html>"
23 " <head>"
24 " <link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\" />"
25 " <meta http-equiv=\"refresh\" content=\"1\" />"
26 " </head>"
27 " <body>"
28 " <p>Netconn driven website!</p>"
29 " <p>Total system up time: <b>";
30
31/**
32 * \brief Bottom part of main page
33 */
34static const uint8_t
35rlwesp_data_mainpage_bottom[] = ""
36 " </b></p>"
37 " </body>"
38 "</html>";
39
40/**
41 * \brief Style file response
42 */
43static const uint8_t
44rlwesp_data_style[] = ""
45 "HTTP/1.1 200 OK\r\n"
46 "Content-Type: text/css\r\n"
47 "\r\n"
48 "body { color: red; font-family: Tahoma, Arial; };";
49
50/**
51 * \brief 404 error response
52 */
53static const uint8_t
54rlwesp_error_404[] = ""
55 "HTTP/1.1 404 Not Found\r\n"
56 "\r\n"
57 "Error 404";
58
59/**
60 * \brief Netconn server thread implementation
61 * \param[in] arg: User argument
62 */
63void
64netconn_server_thread(void const* arg) {
65 lwespr_t res;
66 lwesp_netconn_p server, client;
67
68 /*
69 * First create a new instance of netconn
70 * connection and initialize system message boxes
71 * to accept clients and packet buffers
72 */
73 server = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP);
74 if (server != NULL) {
75 printf("Server netconn created\r\n");
76
77 /* Bind network connection to port 80 */
78 res = lwesp_netconn_bind(server, 80);
79 if (res == lwespOK) {
80 printf("Server netconn listens on port 80\r\n");
81 /*
82 * Start listening for incoming connections
83 * on previously binded port
84 */
85 res = lwesp_netconn_listen(server);
86
87 while (1) {
88 /*
89 * Wait and accept new client connection
90 *
91 * Function will block thread until
92 * new client is connected to server
93 */
94 res = lwesp_netconn_accept(server, &client);
95 if (res == lwespOK) {
96 printf("Netconn new client connected. Starting new thread...\r\n");
97 /*
98 * Start new thread for this request.
99 *
100 * Read and write back data to user in separated thread
101 * to allow processing of multiple requests at the same time
102 */
103 if (lwesp_sys_thread_create(NULL, "client", (lwesp_sys_thread_fn)netconn_server_processing_thread, client, 512, LWESP_SYS_THREAD_PRIO)) {
104 printf("Netconn client thread created\r\n");
105 } else {
106 printf("Netconn client thread creation failed!\r\n");
107
108 /* Force close & delete */
109 lwesp_netconn_close(client);
110 lwesp_netconn_delete(client);
111 }
112 } else {
113 printf("Netconn connection accept error!\r\n");
114 break;
115 }
116 }
117 } else {
118 printf("Netconn server cannot bind to port\r\n");
119 }
120 } else {
121 printf("Cannot create server netconn\r\n");
122 }
123
124 printf("Terminating thread\r\n");
125 lwesp_netconn_delete(server); /* Delete netconn structure */
126 lwesp_sys_thread_terminate(NULL); /* Terminate current thread */
127}
128
129/**
130 * \brief Thread to process single active connection
131 * \param[in] arg: Thread argument
132 */
133static void
134netconn_server_processing_thread(void* const arg) {
135 lwesp_netconn_p client;
136 lwesp_pbuf_p pbuf, p = NULL;
137 lwespr_t res;
138 char strt[20];
139
140 client = arg; /* Client handle is passed to argument */
141
142 printf("A new connection accepted!\r\n"); /* Print simple message */
143
144 do {
145 /*
146 * Client was accepted, we are now
147 * expecting client will send to us some data
148 *
149 * Wait for data and block thread for that time
150 */
151 res = lwesp_netconn_receive(client, &pbuf);
152
153 if (res == lwespOK) {
154 printf("Netconn data received, %d bytes\r\n", (int)lwesp_pbuf_length(pbuf, 1));
155 /* Check reception of all header bytes */
156 if (p == NULL) {
157 p = pbuf; /* Set as first buffer */
158 } else {
159 lwesp_pbuf_cat(p, pbuf); /* Concatenate buffers together */
160 }
161 if (lwesp_pbuf_strfind(pbuf, "\r\n\r\n", 0) != LWESP_SIZET_MAX) {
162 if (lwesp_pbuf_strfind(pbuf, "GET / ", 0) != LWESP_SIZET_MAX) {
163 uint32_t now;
164 printf("Main page request\r\n");
165 now = lwesp_sys_now(); /* Get current time */
166 sprintf(strt, "%u ms; %d s", (unsigned)now, (unsigned)(now / 1000));
167 lwesp_netconn_write(client, rlwesp_data_mainpage_top, sizeof(rlwesp_data_mainpage_top) - 1);
168 lwesp_netconn_write(client, strt, strlen(strt));
169 lwesp_netconn_write(client, rlwesp_data_mainpage_bottom, sizeof(rlwesp_data_mainpage_bottom) - 1);
170 } else if (lwesp_pbuf_strfind(pbuf, "GET /style.css ", 0) != LWESP_SIZET_MAX) {
171 printf("Style page request\r\n");
172 lwesp_netconn_write(client, rlwesp_data_style, sizeof(rlwesp_data_style) - 1);
173 } else {
174 printf("404 error not found\r\n");
175 lwesp_netconn_write(client, rlwesp_error_404, sizeof(rlwesp_error_404) - 1);
176 }
177 lwesp_netconn_close(client); /* Close netconn connection */
178 lwesp_pbuf_free(p); /* Do not forget to free memory after usage! */
179 p = NULL;
180 break;
181 }
182 }
183 } while (res == lwespOK);
184
185 if (p != NULL) { /* Free received data */
186 lwesp_pbuf_free(p);
187 p = NULL;
188 }
189 lwesp_netconn_delete(client); /* Destroy client memory */
190 lwesp_sys_thread_terminate(NULL); /* Terminate this thread */
191}
Non-blocking receive¶
By default, netconn API is written to only work in separate application thread, dedicated for network connection processing. Because of that, by default every function is fully blocking. It will wait until result is ready to be used by application.
It is, however, possible to enable timeout feature for receiving data only.
When this feature is enabled, lwesp_netconn_receive()
will block for maximal timeout set with
lwesp_netconn_set_receive_timeout()
function.
When enabled, if there is no received data for timeout amount of time, function will return with timeout status and application needs to process it accordingly.
Tip
LWESP_CFG_NETCONN_RECEIVE_TIMEOUT
must be set to 1
to use this feature.
- group LWESP_NETCONN
Network connection.
Defines
-
LWESP_NETCONN_RECEIVE_NO_WAIT¶
Receive data with no timeout.
Note
Used with lwesp_netconn_set_receive_timeout function
Typedefs
-
typedef struct lwesp_netconn *lwesp_netconn_p¶
Netconn object structure.
Enums
-
enum lwesp_netconn_type_t¶
Netconn connection type.
Values:
-
enumerator LWESP_NETCONN_TYPE_TCP¶
TCP connection
-
enumerator LWESP_NETCONN_TYPE_SSL¶
SSL connection
-
enumerator LWESP_NETCONN_TYPE_UDP¶
UDP connection
-
enumerator LWESP_NETCONN_TYPE_TCPV6¶
TCP connection over IPv6
-
enumerator LWESP_NETCONN_TYPE_SSLV6¶
SSL connection over IPv6
-
enumerator LWESP_NETCONN_TYPE_TCP¶
Functions
-
lwesp_netconn_p lwesp_netconn_new(lwesp_netconn_type_t type)¶
Create new netconn connection.
- Parameters
type – [in] Netconn connection type
- Returns
New netconn connection on success,
NULL
otherwise
-
lwespr_t lwesp_netconn_delete(lwesp_netconn_p nc)¶
Delete netconn connection.
-
lwespr_t lwesp_netconn_bind(lwesp_netconn_p nc, lwesp_port_t port)¶
Bind a connection to specific port, can be only used for server connections.
-
lwespr_t lwesp_netconn_connect(lwesp_netconn_p nc, const char *host, lwesp_port_t port)¶
Connect to server as client.
-
lwespr_t lwesp_netconn_receive(lwesp_netconn_p nc, lwesp_pbuf_p *pbuf)¶
Receive data from connection.
- Parameters
nc – [in] Netconn handle used to receive from
pbuf – [in] Pointer to pointer to save new receive buffer to. When function returns, user must check for valid pbuf value
pbuf != NULL
- Returns
lwespOK when new data ready
- Returns
lwespCLOSED when connection closed by remote side
- Returns
lwespTIMEOUT when receive timeout occurs
- Returns
Any other member of lwespr_t otherwise
-
lwespr_t lwesp_netconn_close(lwesp_netconn_p nc)¶
Close a netconn connection.
-
int8_t lwesp_netconn_get_connnum(lwesp_netconn_p nc)¶
Get connection number used for netconn.
- Parameters
nc – [in] Netconn handle
- Returns
-1
on failure, connection number between0
and LWESP_CFG_MAX_CONNS otherwise
-
lwesp_conn_p lwesp_netconn_get_conn(lwesp_netconn_p nc)¶
Get netconn connection handle.
- Parameters
nc – [in] Netconn handle
- Returns
ESP connection handle
-
lwesp_netconn_type_t lwesp_netconn_get_type(lwesp_netconn_p nc)¶
Get netconn connection type.
- Parameters
nc – [in] Netconn handle
- Returns
ESP connection type
-
void lwesp_netconn_set_receive_timeout(lwesp_netconn_p nc, uint32_t timeout)¶
Set timeout value for receiving data.
When enabled, lwesp_netconn_receive will only block for up to
timeout
value and will return if no new data within this time- Parameters
nc – [in] Netconn handle
timeout – [in] Timeout in units of milliseconds. Set to
0
to disable timeout feature Set to> 0
to set maximum milliseconds to wait before timeout Set to LWESP_NETCONN_RECEIVE_NO_WAIT to enable non-blocking receive
-
uint32_t lwesp_netconn_get_receive_timeout(lwesp_netconn_p nc)¶
Get netconn receive timeout value.
- Parameters
nc – [in] Netconn handle
- Returns
Timeout in units of milliseconds. If value is
0
, timeout is disabled (wait forever)
-
lwespr_t lwesp_netconn_connect_ex(lwesp_netconn_p nc, const char *host, lwesp_port_t port, uint16_t keep_alive, const char *local_ip, lwesp_port_t local_port, uint8_t mode)¶
Connect to server as client, allow keep-alive option.
- Parameters
nc – [in] Netconn handle
host – [in] Pointer to host, such as domain name or IP address in string format
port – [in] Target port to use
keep_alive – [in] Keep alive period seconds
local_ip – [in] Local ip in connected command
local_port – [in] Local port address
mode – [in] UDP mode
- Returns
lwespOK if successfully connected, member of lwespr_t otherwise
-
lwespr_t lwesp_netconn_listen(lwesp_netconn_p nc)¶
Listen on previously binded connection.
-
lwespr_t lwesp_netconn_listen_with_max_conn(lwesp_netconn_p nc, uint16_t max_connections)¶
Listen on previously binded connection with max allowed connections at a time.
-
lwespr_t lwesp_netconn_set_listen_conn_timeout(lwesp_netconn_p nc, uint16_t timeout)¶
Set timeout value in units of seconds when connection is in listening mode If new connection is accepted, it will be automatically closed after
seconds
elapsed without any data exchange.Note
Call this function before you put connection to listen mode with lwesp_netconn_listen
-
lwespr_t lwesp_netconn_accept(lwesp_netconn_p nc, lwesp_netconn_p *client)¶
Accept a new connection.
-
lwespr_t lwesp_netconn_write(lwesp_netconn_p nc, const void *data, size_t btw)¶
Write data to connection output buffers.
Note
This function may only be used on TCP or SSL connections
-
lwespr_t lwesp_netconn_flush(lwesp_netconn_p nc)¶
Flush buffered data on netconn TCP/SSL connection.
Note
This function may only be used on TCP/SSL connection
-
lwespr_t lwesp_netconn_send(lwesp_netconn_p nc, const void *data, size_t btw)¶
Send data on UDP connection to default IP and port.
-
lwespr_t lwesp_netconn_sendto(lwesp_netconn_p nc, const lwesp_ip_t *ip, lwesp_port_t port, const void *data, size_t btw)¶
Send data on UDP connection to specific IP and port.
Note
Use this function in case of UDP type netconn
-
LWESP_NETCONN_RECEIVE_NO_WAIT¶
Command line interface¶
CLI Input module¶
- group CLI_INPUT
Command line interface helper funcions for paring input data.
Functions to parse incoming data for command line interface (CLI).
Functions
-
void cli_in_data(cli_printf cliprintf, char ch)¶
parse new characters to the CLI
- Parameters
cliprintf – [in] Pointer to CLI printf function
ch – [in] new character to CLI
-
void cli_in_data(cli_printf cliprintf, char ch)¶
CLI Configuration¶
- group CLI_CONFIG
Default CLI configuration.
Configuration for command line interface (CLI).
- group CLI
Command line interface.
Functions to initialize everything needed for command line interface (CLI).
Typedefs
-
typedef void cli_printf(const char *format, ...)¶
Printf handle for CLI.
- Param format
[in] string format
-
typedef void cli_function(cli_printf cliprintf, int argc, char **argv)¶
CLI entriy function.
- Param cliprintf
[in] Printf handle callback
- Param argc
[in] Number of arguments
- Param argv
[in] Pointer to pointer to arguments
Functions
-
const cli_command_t *cli_lookup_command(char *command)¶
Find the CLI command that matches the input string.
- Parameters
command – [in] pointer to command string for which we are searching
- Returns
pointer of the command if we found a match, else NULL
-
void cli_tab_auto_complete(cli_printf cliprintf, char *cmd_buffer, uint32_t *cmd_pos, bool print_options)¶
CLI auto completion function.
- Parameters
cliprintf – [in] Pointer to CLI printf function
cmd_buffer – [in] CLI command buffer
cmd_pos – [in] pointer to current courser postion in command buffer
print_options – [in] additional prints in case of double tab
-
bool cli_register_commands(const cli_command_t *commands, size_t num_of_commands)¶
Register new CLI commands.
- Parameters
commands – [in] Pointer to commands table
num_of_commands – [in] Number of new commands
- Returns
true when new commands where succesfully added, else false
-
void cli_init(void)¶
CLI Init function for adding basic CLI commands.
-
struct cli_command_t¶
- #include <cli.h>
CLI command structure.
Public Members
-
const char *name¶
Command name
-
const char *help¶
Command help
-
cli_function *func¶
Command function
-
const char *name¶
-
struct cli_commands_t¶
- #include <cli.h>
List of commands.
Public Members
-
const cli_command_t *commands¶
Pointer to commands
-
size_t num_of_commands¶
Total number of commands
-
const cli_command_t *commands¶
-
typedef void cli_printf(const char *format, ...)¶
Examples and demos¶
Various examples are provided for fast library evaluation on embedded systems. These are prepared and maintained for 2
platforms, but could be easily extended to more platforms:
WIN32 examples, prepared as Visual Studio Community projects
ARM Cortex-M examples for STM32, prepared as STM32CubeIDE GCC projects
Warning
Library is platform independent and can be used on any platform.
Example architectures¶
There are many platforms available today on a market, however supporting them all would be tough task for single person.
Therefore it has been decided to support (for purpose of examples) 2
platforms only, WIN32 and STM32.
WIN32¶
Examples for WIN32 are prepared as Visual Studio Community projects. You can directly open project in the IDE, compile & debug.
Application opens COM port, set in the low-level driver. External USB to UART converter (FTDI-like device) is necessary in order to connect to ESP device.
Note
ESP device is connected with USB to UART converter only by RX and TX pins.
Device driver is located in /lwesp/src/system/lwesp_ll_win32.c
STM32¶
Embedded market is supported by many vendors and STMicroelectronics is, with their STM32 series of microcontrollers, one of the most important players. There are numerous amount of examples and topics related to this architecture.
Examples for STM32 are natively supported with STM32CubeIDE, an official development IDE from STMicroelectronics.
You can run examples on one of official development boards, available in repository examples.
Board name |
ESP settings |
Debug settings |
||||||||
---|---|---|---|---|---|---|---|---|---|---|
UART |
MTX |
MRX |
RST |
GP0 |
GP2 |
CHPD |
UART |
MDTX |
MDRX |
|
STM32F769I-Discovery |
UART5 |
PC12 |
PD2 |
PJ14 |
USART1 |
PA9 |
PA10 |
|||
STM32F723E-Discovery |
UART5 |
PC12 |
PD2 |
PG14 |
PD6 |
PD3 |
USART6 |
PC6 |
PC7 |
|
STM32L496G-Discovery |
USART1 |
PB6 |
PG10 |
PB2 |
PH2 |
PA0 |
PA4 |
USART2 |
PA2 |
PD6 |
STM32L432KC-Nucleo |
USART1 |
PA9 |
PA10 |
PA12 |
PA7 |
PA6 |
PB0 |
USART2 |
PA2 |
PA3 |
STM32F429ZI-Nucleo |
USART2 |
PD5 |
PD6 |
PD1 |
PD4 |
PD7 |
PD3 |
USART3 |
PD8 |
PD9 |
Pins to connect with ESP device:
MTX: MCU TX pin, connected to ESP RX pin
MRX: MCU RX pin, connected to ESP TX pin
RST: MCU output pin to control reset state of ESP device
GP0: GPIO0 pin of ESP8266, connected to MCU, configured as output at MCU side
GP2: GPIO2 pin of ESP8266, connected to MCU, configured as output at MCU side
CHPD: CH_PD pin of ESP8266, connected to MCU, configured as output at MCU side
Note
GP0, GP2, CH_PD pins are not always necessary for ESP device to work properly. When not used, these pins must be tied to fixed values as explained in ESP datasheet.
Other pins are for your information and are used for debugging purposes on board.
MDTX: MCU Debug TX pin, connected via on-board ST-Link to PC
MDRX: MCU Debug RX pin, connected via on-board ST-Link to PC
Baudrate is always set to
921600
bauds
Examples list¶
Here is a list of all examples coming with this library.
Tip
Examples are located in /examples/
folder in downloaded package.
Check Download library section to get your package.
Warning
Several examples need to connect to access point first, then they may start client connection or pinging server.
Application needs to modify file /snippets/station_manager.c
and update ap_list
variable with preferred access points,
in order to allow ESP to connect to home/local network
Ex. Access point¶
ESP device is configured as software access point, allowing stations to connect to it. When station connects to access point, it will output its MAC and IP addresses.
Ex. Client¶
Application tries to connect to custom server with classic, event-based API. It starts concurrent connections and processes data in its event callback function.
Ex. Server¶
It starts server on port 80
in event based connection mode.
Every client is processed in callback function.
When ESP is successfully connected to access point, it is possible to connect to it using its assigned IP address.
Ex. Domain name server¶
ESP tries to get domain name from specific domain name, example.com
as an example.
It needs to be connected to access point to have access to global internet.
Ex. MQTT Client¶
This example demonstrates raw MQTT connection to mosquitto test server. A new application thread is started after ESP successfully connects to access point. MQTT application starts by initiating a new TCP connection.
This is event-based example as there is no linear code.
Ex. MQTT Client API¶
Similar to MQTT Client examples, but it uses separate thread to process events in blocking mode. Application does not use events to process data, rather it uses blocking API to receive packets
Ex. Netconn client¶
Netconn client is based on sequential API. It starts connection to server, sends initial request and then waits to receive data.
Processing is in separate thread and fully sequential, no callbacks or events.
Ex. Netconn server¶
Netconn server is based on sequential API. It starts server on specific port (see example details) and it waits for new client in separate threads. Once new client has been accepted, it waits for client request and processes data accordingly by sending reply message back.
Tip
Server may accept multiple clients at the same time