LwESP 1.0.0 documentation¶
Welcome to the documentation for version 1.0.0.
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
Features¶
Supports latest ESP8266 and ESP32 RTOS-SDK AT commands firmware
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¶
Download library¶
Library is primarly hosted on Github.
Download latest release from releases area on Github
Clone develop branch for latest development
Download from releases¶
All releases are available on Github releases area.
Clone from Github¶
First-time clone¶
Download and install
git
if not alreadyOpen 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 resources repository is. Use command
cd your_path
Run
git pull origin master --recurse-submodules
command to pull latest changes and to fetch latest changes from submodulesRun
git submodule foreach git pull origin master
to update & merge all submodules
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.
Copy
lwesp
folder to your projectAdd
lwesp/src/include
folder to include path of your toolchainAdd port architecture
lwesp/src/include/system/port/_arch_
folder to include path of your toolchainAdd source files from
lwesp/src/
folder to toolchain buildAdd source files from
lwesp/src/system/
folder to toolchain build for arch portCopy
lwesp/src/include/lwesp/lwesp_opts_template.h
to project folder and rename it tolwesp_opts.h
Build the project
Configuration file¶
Library comes with template config file, which can be modified according to needs.
This file shall be named lwesp_opts.h
and its default template looks like the one below.
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 (or simply renamed in-place) where compiler
include paths have access to it by using #include "lwesp_opts.h"
.
Tip
Check Configuration section for possible configuration settings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /**
* \file lwesp_opts_template.h
* \brief Template config file
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#ifndef LWESP_HDR_OPTS_H
#define LWESP_HDR_OPTS_H
/* Rename this file to "lwesp_opts.h" for your application */
/*
* Open "include/lwesp/lwesp_opt.h" and
* copy & replace here settings you want to change values
*/
#endif /* LWESP_HDR_OPTS_H */
|
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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 | /**
* \file lwesp_netconn.c
* \brief API functions for sequential calls
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#include "lwesp/lwesp_netconn.h"
#include "lwesp/lwesp_private.h"
#include "lwesp/lwesp_conn.h"
#include "lwesp/lwesp_mem.h"
#if LWESP_CFG_NETCONN || __DOXYGEN__
/* Check conditions */
#if LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN < 2
#error "LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN must be greater or equal to 2"
#endif /* LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN < 2 */
#if LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN < 2
#error "LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN must be greater or equal to 2"
#endif /* LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN < 2 */
/**
* \brief Sequential API structure
*/
typedef struct lwesp_netconn {
struct lwesp_netconn* next; /*!< Linked list entry */
lwesp_netconn_type_t type; /*!< Netconn type */
lwesp_port_t listen_port; /*!< Port on which we are listening */
size_t rcv_packets; /*!< Number of received packets so far on this connection */
lwesp_conn_p conn; /*!< Pointer to actual connection */
lwesp_sys_mbox_t mbox_accept; /*!< List of active connections waiting to be processed */
lwesp_sys_mbox_t mbox_receive; /*!< Message queue for receive mbox */
size_t mbox_receive_entries; /*!< Number of entries written to receive mbox */
lwesp_linbuff_t buff; /*!< Linear buffer structure */
uint16_t conn_timeout; /*!< Connection timeout in units of seconds when
netconn is in server (listen) mode.
Connection will be automatically closed if there is no
data exchange in time. Set to `0` when timeout feature is disabled. */
#if LWESP_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__
uint32_t rcv_timeout; /*!< Receive timeout in unit of milliseconds */
#endif
} lwesp_netconn_t;
static uint8_t recv_closed = 0xFF, recv_not_present = 0xFF;
static lwesp_netconn_t* listen_api; /*!< Main connection in listening mode */
static lwesp_netconn_t* netconn_list; /*!< Linked list of netconn entries */
/**
* \brief Flush all mboxes and clear possible used memories
* \param[in] nc: Pointer to netconn to flush
* \param[in] protect: Set to 1 to protect against multi-thread access
*/
static void
flush_mboxes(lwesp_netconn_t* nc, uint8_t protect) {
lwesp_pbuf_p pbuf;
lwesp_netconn_t* new_nc;
if (protect) {
lwesp_core_lock();
}
if (lwesp_sys_mbox_isvalid(&nc->mbox_receive)) {
while (lwesp_sys_mbox_getnow(&nc->mbox_receive, (void**)&pbuf)) {
if (nc->mbox_receive_entries > 0) {
--nc->mbox_receive_entries;
}
if (pbuf != NULL && (uint8_t*)pbuf != (uint8_t*)&recv_closed) {
lwesp_pbuf_free(pbuf); /* Free received data buffers */
}
}
lwesp_sys_mbox_delete(&nc->mbox_receive); /* Delete message queue */
lwesp_sys_mbox_invalid(&nc->mbox_receive); /* Invalid handle */
}
if (lwesp_sys_mbox_isvalid(&nc->mbox_accept)) {
while (lwesp_sys_mbox_getnow(&nc->mbox_accept, (void**)&new_nc)) {
if (new_nc != NULL
&& (uint8_t*)new_nc != (uint8_t*)&recv_closed
&& (uint8_t*)new_nc != (uint8_t*)&recv_not_present) {
lwesp_netconn_close(new_nc); /* Close netconn connection */
}
}
lwesp_sys_mbox_delete(&nc->mbox_accept);/* Delete message queue */
lwesp_sys_mbox_invalid(&nc->mbox_accept); /* Invalid handle */
}
if (protect) {
lwesp_core_unlock();
}
}
/**
* \brief Callback function for every server connection
* \param[in] evt: Pointer to callback structure
* \return Member of \ref lwespr_t enumeration
*/
static lwespr_t
netconn_evt(lwesp_evt_t* evt) {
lwesp_conn_p conn;
lwesp_netconn_t* nc = NULL;
uint8_t close = 0;
conn = lwesp_conn_get_from_evt(evt); /* Get connection from event */
switch (lwesp_evt_get_type(evt)) {
/*
* A new connection has been active
* and should be handled by netconn API
*/
case LWESP_EVT_CONN_ACTIVE: { /* A new connection active is active */
if (lwesp_conn_is_client(conn)) { /* Was connection started by us? */
nc = lwesp_conn_get_arg(conn); /* Argument should be already set */
if (nc != NULL) {
nc->conn = conn; /* Save actual connection */
} else {
close = 1; /* Close this connection, invalid netconn */
}
/* Is the connection server type and we have known listening API? */
} else if (lwesp_conn_is_server(conn) && listen_api != NULL) {
/*
* Create a new netconn structure
* and set it as connection argument.
*/
nc = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP); /* Create new API */
LWESP_DEBUGW(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_WARNING,
nc == NULL, "[NETCONN] Cannot create new structure for incoming server connection!\r\n");
if (nc != NULL) {
nc->conn = conn; /* Set connection handle */
lwesp_conn_set_arg(conn, nc); /* Set argument for connection */
/*
* In case there is no listening connection,
* simply close the connection
*/
if (!lwesp_sys_mbox_isvalid(&listen_api->mbox_accept)
|| !lwesp_sys_mbox_putnow(&listen_api->mbox_accept, nc)) {
close = 1;
}
} else {
close = 1;
}
} else {
LWESP_DEBUGW(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_WARNING, listen_api == NULL,
"[NETCONN] Closing connection as there is no listening API in netconn!\r\n");
close = 1; /* Close the connection at this point */
}
/* Decide if some events want to close the connection */
if (close) {
if (nc != NULL) {
lwesp_conn_set_arg(conn, NULL); /* Reset argument */
lwesp_netconn_delete(nc); /* Free memory for API */
}
lwesp_conn_close(conn, 0); /* Close the connection */
close = 0;
}
break;
}
/*
* We have a new data received which
* should have netconn structure as argument
*/
case LWESP_EVT_CONN_RECV: {
lwesp_pbuf_p pbuf;
nc = lwesp_conn_get_arg(conn); /* Get API from connection */
pbuf = lwesp_evt_conn_recv_get_buff(evt); /* Get received buff */
#if !LWESP_CFG_CONN_MANUAL_TCP_RECEIVE
lwesp_conn_recved(conn, pbuf); /* Notify stack about received data */
#endif /* !LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */
lwesp_pbuf_ref(pbuf); /* Increase reference counter */
if (nc == NULL || !lwesp_sys_mbox_isvalid(&nc->mbox_receive)
|| !lwesp_sys_mbox_putnow(&nc->mbox_receive, pbuf)) {
LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN,
"[NETCONN] Ignoring more data for receive!\r\n");
lwesp_pbuf_free(pbuf); /* Free pbuf */
return lwespOKIGNOREMORE; /* Return OK to free the memory and ignore further data */
}
++nc->mbox_receive_entries; /* Increase number of packets in receive mbox */
#if LWESP_CFG_CONN_MANUAL_TCP_RECEIVE
/* Check against 1 less to still allow potential close event to be written to queue */
if (nc->mbox_receive_entries >= (LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN - 1)) {
conn->status.f.receive_blocked = 1; /* Block reading more data */
}
#endif /* LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */
++nc->rcv_packets; /* Increase number of packets received */
LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE,
"[NETCONN] Received pbuf contains %d bytes. Handle written to receive mbox\r\n",
(int)lwesp_pbuf_length(pbuf, 0));
break;
}
/* Connection was just closed */
case LWESP_EVT_CONN_CLOSE: {
nc = lwesp_conn_get_arg(conn); /* Get API from connection */
/*
* In case we have a netconn available,
* simply write pointer to received variable to indicate closed state
*/
if (nc != NULL && lwesp_sys_mbox_isvalid(&nc->mbox_receive)) {
if (lwesp_sys_mbox_putnow(&nc->mbox_receive, (void*)&recv_closed)) {
++nc->mbox_receive_entries;
}
}
break;
}
default:
return lwespERR;
}
return lwespOK;
}
/**
* \brief Global event callback function
* \param[in] evt: Callback information and data
* \return \ref lwespOK on success, member of \ref lwespr_t otherwise
*/
static lwespr_t
lwesp_evt(lwesp_evt_t* evt) {
switch (lwesp_evt_get_type(evt)) {
case LWESP_EVT_WIFI_DISCONNECTED: { /* Wifi disconnected event */
if (listen_api != NULL) { /* Check if listen API active */
lwesp_sys_mbox_putnow(&listen_api->mbox_accept, &recv_closed);
}
break;
}
case LWESP_EVT_DEVICE_PRESENT: { /* Device present event */
if (listen_api != NULL && !lwesp_device_is_present()) { /* Check if device present */
lwesp_sys_mbox_putnow(&listen_api->mbox_accept, &recv_not_present);
}
}
default:
break;
}
return lwespOK;
}
/**
* \brief Create new netconn connection
* \param[in] type: Netconn connection type
* \return New netconn connection on success, `NULL` otherwise
*/
lwesp_netconn_p
lwesp_netconn_new(lwesp_netconn_type_t type) {
lwesp_netconn_t* a;
static uint8_t first = 1;
/* Register only once! */
lwesp_core_lock();
if (first) {
first = 0;
lwesp_evt_register(lwesp_evt); /* Register global event function */
}
lwesp_core_unlock();
a = lwesp_mem_calloc(1, sizeof(*a)); /* Allocate memory for core object */
if (a != NULL) {
a->type = type; /* Save netconn type */
a->conn_timeout = 0; /* Default connection timeout */
if (!lwesp_sys_mbox_create(&a->mbox_accept, LWESP_CFG_NETCONN_ACCEPT_QUEUE_LEN)) { /* Allocate memory for accepting message box */
LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_DANGER,
"[NETCONN] Cannot create accept MBOX\r\n");
goto free_ret;
}
if (!lwesp_sys_mbox_create(&a->mbox_receive, LWESP_CFG_NETCONN_RECEIVE_QUEUE_LEN)) {/* Allocate memory for receiving message box */
LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN | LWESP_DBG_TYPE_TRACE | LWESP_DBG_LVL_DANGER,
"[NETCONN] Cannot create receive MBOX\r\n");
goto free_ret;
}
lwesp_core_lock();
if (netconn_list == NULL) { /* Add new netconn to the existing list */
netconn_list = a;
} else {
a->next = netconn_list; /* Add it to beginning of the list */
netconn_list = a;
}
lwesp_core_unlock();
}
return a;
free_ret:
if (lwesp_sys_mbox_isvalid(&a->mbox_accept)) {
lwesp_sys_mbox_delete(&a->mbox_accept);
lwesp_sys_mbox_invalid(&a->mbox_accept);
}
if (lwesp_sys_mbox_isvalid(&a->mbox_receive)) {
lwesp_sys_mbox_delete(&a->mbox_receive);
lwesp_sys_mbox_invalid(&a->mbox_receive);
}
if (a != NULL) {
lwesp_mem_free_s((void**)&a);
}
return NULL;
}
/**
* \brief Delete netconn connection
* \param[in] nc: Netconn handle
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_delete(lwesp_netconn_p nc) {
LWESP_ASSERT("netconn != NULL", nc != NULL);
lwesp_core_lock();
flush_mboxes(nc, 0); /* Clear mboxes */
/* Stop listening on netconn */
if (nc == listen_api) {
listen_api = NULL;
lwesp_core_unlock();
lwesp_set_server(0, nc->listen_port, 0, 0, NULL, NULL, NULL, 1);
lwesp_core_lock();
}
/* Remove netconn from linkedlist */
if (nc == netconn_list) {
netconn_list = netconn_list->next; /* Remove first from linked list */
} else if (netconn_list != NULL) {
lwesp_netconn_p tmp, prev;
/* Find element on the list */
for (prev = netconn_list, tmp = netconn_list->next;
tmp != NULL; prev = tmp, tmp = tmp->next) {
if (nc == tmp) {
prev->next = tmp->next; /* Remove tmp from linked list */
break;
}
}
}
lwesp_core_unlock();
lwesp_mem_free_s((void**)&nc);
return lwespOK;
}
/**
* \brief Connect to server as client
* \param[in] nc: Netconn handle
* \param[in] host: Pointer to host, such as domain name or IP address in string format
* \param[in] port: Target port to use
* \return \ref lwespOK if successfully connected, member of \ref lwespr_t otherwise
*/
lwespr_t
lwesp_netconn_connect(lwesp_netconn_p nc, const char* host, lwesp_port_t port) {
lwespr_t res;
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("host != NULL", host != NULL);
LWESP_ASSERT("port > 0", port > 0);
/*
* Start a new connection as client and:
*
* - Set current netconn structure as argument
* - Set netconn callback function for connection management
* - Start connection in blocking mode
*/
res = lwesp_conn_start(NULL, (lwesp_conn_type_t)nc->type, host, port, nc, netconn_evt, 1);
return res;
}
/**
* \brief Connect to server as client, allow keep-alive option
* \param[in] nc: Netconn handle
* \param[in] host: Pointer to host, such as domain name or IP address in string format
* \param[in] port: Target port to use
* \param[in] keep_alive: Keep alive period seconds
* \param[in] local_ip: Local ip in connected command
* \param[in] local_port: Local port address
* \param[in] mode: UDP mode
* \return \ref lwespOK if successfully connected, member of \ref lwespr_t otherwise
*/
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) {
lwesp_conn_start_t cs = {0};
lwespr_t res;
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("host != NULL", host != NULL);
LWESP_ASSERT("port > 0", port > 0);
/*
* Start a new connection as client and:
*
* - Set current netconn structure as argument
* - Set netconn callback function for connection management
* - Start connection in blocking mode
*/
cs.type = nc->type;
cs.remote_host = host;
cs.remote_port = port;
cs.local_ip = local_ip;
if (nc->type == LWESP_NETCONN_TYPE_TCP || nc->type == LWESP_NETCONN_TYPE_SSL) {
cs.ext.tcp_ssl.keep_alive = keep_alive;
} else {
cs.ext.udp.local_port = local_port;
cs.ext.udp.mode = mode;
}
res = lwesp_conn_startex(NULL, &cs, nc, netconn_evt, 1);
return res;
}
/**
* \brief Bind a connection to specific port, can be only used for server connections
* \param[in] nc: Netconn handle
* \param[in] port: Port used to bind a connection to
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_bind(lwesp_netconn_p nc, lwesp_port_t port) {
lwespr_t res = lwespOK;
LWESP_ASSERT("nc != NULL", nc != NULL);
/*
* Protection is not needed as it is expected
* that this function is called only from single
* thread for single netconn connection,
* thus it is considered reentrant
*/
nc->listen_port = port;
return res;
}
/**
* \brief 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 \ref lwesp_netconn_listen
* \param[in] nc: Netconn handle used for listen mode
* \param[in] timeout: Time in units of seconds. Set to `0` to disable timeout feature
* \return \ref lwespOK on success, member of \ref lwespr_t otherwise
*/
lwespr_t
lwesp_netconn_set_listen_conn_timeout(lwesp_netconn_p nc, uint16_t timeout) {
lwespr_t res = lwespOK;
LWESP_ASSERT("nc != NULL", nc != NULL);
/*
* Protection is not needed as it is expected
* that this function is called only from single
* thread for single netconn connection,
* thus it is reentrant in this case
*/
nc->conn_timeout = timeout;
return res;
}
/**
* \brief Listen on previously binded connection
* \param[in] nc: Netconn handle used to listen for new connections
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_listen(lwesp_netconn_p nc) {
return lwesp_netconn_listen_with_max_conn(nc, LWESP_CFG_MAX_CONNS);
}
/**
* \brief Listen on previously binded connection with max allowed connections at a time
* \param[in] nc: Netconn handle used to listen for new connections
* \param[in] max_connections: Maximal number of connections server can accept at a time
* This parameter may not be larger than \ref LWESP_CFG_MAX_CONNS
* \return \ref lwespOK on success, member of \ref lwespr_t otherwise
*/
lwespr_t
lwesp_netconn_listen_with_max_conn(lwesp_netconn_p nc, uint16_t max_connections) {
lwespr_t res;
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("nc->type must be TCP", nc->type == LWESP_NETCONN_TYPE_TCP);
/* Enable server on port and set default netconn callback */
if ((res = lwesp_set_server(1, nc->listen_port,
LWESP_U16(LWESP_MIN(max_connections, LWESP_CFG_MAX_CONNS)),
nc->conn_timeout, netconn_evt, NULL, NULL, 1)) == lwespOK) {
lwesp_core_lock();
listen_api = nc; /* Set current main API in listening state */
lwesp_core_unlock();
}
return res;
}
/**
* \brief Accept a new connection
* \param[in] nc: Netconn handle used as base connection to accept new clients
* \param[out] client: Pointer to netconn handle to save new connection to
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_accept(lwesp_netconn_p nc, lwesp_netconn_p* client) {
lwesp_netconn_t* tmp;
uint32_t time;
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("client != NULL", client != NULL);
LWESP_ASSERT("nc->type must be TCP", nc->type == LWESP_NETCONN_TYPE_TCP);
LWESP_ASSERT("nc == listen_api", nc == listen_api);
*client = NULL;
time = lwesp_sys_mbox_get(&nc->mbox_accept, (void**)&tmp, 0);
if (time == LWESP_SYS_TIMEOUT) {
return lwespTIMEOUT;
}
if ((uint8_t*)tmp == (uint8_t*)&recv_closed) {
lwesp_core_lock();
listen_api = NULL; /* Disable listening at this point */
lwesp_core_unlock();
return lwespERRWIFINOTCONNECTED; /* Wifi disconnected */
} else if ((uint8_t*)tmp == (uint8_t*)&recv_not_present) {
lwesp_core_lock();
listen_api = NULL; /* Disable listening at this point */
lwesp_core_unlock();
return lwespERRNODEVICE; /* Device not present */
}
*client = tmp; /* Set new pointer */
return lwespOK; /* We have a new connection */
}
/**
* \brief Write data to connection output buffers
* \note This function may only be used on TCP or SSL connections
* \param[in] nc: Netconn handle used to write data to
* \param[in] data: Pointer to data to write
* \param[in] btw: Number of bytes to write
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_write(lwesp_netconn_p nc, const void* data, size_t btw) {
size_t len, sent;
const uint8_t* d = data;
lwespr_t res;
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("nc->type must be TCP or SSL", nc->type == LWESP_NETCONN_TYPE_TCP || nc->type == LWESP_NETCONN_TYPE_SSL);
LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
/*
* Several steps are done in write process
*
* 1. Check if buffer is set and check if there is something to write to it.
* 1. In case buffer will be full after copy, send it and free memory.
* 2. Check how many bytes we can write directly without need to copy
* 3. Try to allocate a new buffer and copy remaining input data to it
* 4. In case buffer allocation fails, send data directly (may have impact on speed and effectivenes)
*/
/* Step 1 */
if (nc->buff.buff != NULL) { /* Is there a write buffer ready to accept more data? */
len = LWESP_MIN(nc->buff.len - nc->buff.ptr, btw); /* Get number of bytes we can write to buffer */
if (len > 0) {
LWESP_MEMCPY(&nc->buff.buff[nc->buff.ptr], data, len); /* Copy memory to temporary write buffer */
d += len;
nc->buff.ptr += len;
btw -= len;
}
/* Step 1.1 */
if (nc->buff.ptr == nc->buff.len) {
res = lwesp_conn_send(nc->conn, nc->buff.buff, nc->buff.len, &sent, 1);
lwesp_mem_free_s((void**)&nc->buff.buff);
if (res != lwespOK) {
return res;
}
} else {
return lwespOK; /* Buffer is not full yet */
}
}
/* Step 2 */
if (btw >= LWESP_CFG_CONN_MAX_DATA_LEN) {
size_t rem;
rem = btw % LWESP_CFG_CONN_MAX_DATA_LEN;/* Get remaining bytes for max data length */
res = lwesp_conn_send(nc->conn, d, btw - rem, &sent, 1);/* Write data directly */
if (res != lwespOK) {
return res;
}
d += sent; /* Advance in data pointer */
btw -= sent; /* Decrease remaining data to send */
}
if (btw == 0) { /* Sent everything? */
return lwespOK;
}
/* Step 3 */
if (nc->buff.buff == NULL) { /* Check if we should allocate a new buffer */
nc->buff.buff = lwesp_mem_malloc(sizeof(*nc->buff.buff) * LWESP_CFG_CONN_MAX_DATA_LEN);
nc->buff.len = LWESP_CFG_CONN_MAX_DATA_LEN; /* Save buffer length */
nc->buff.ptr = 0; /* Save buffer pointer */
}
/* Step 4 */
if (nc->buff.buff != NULL) { /* Memory available? */
LWESP_MEMCPY(&nc->buff.buff[nc->buff.ptr], d, btw); /* Copy data to buffer */
nc->buff.ptr += btw;
} else { /* Still no memory available? */
return lwesp_conn_send(nc->conn, data, btw, NULL, 1); /* Simply send directly blocking */
}
return lwespOK;
}
/**
* \brief Flush buffered data on netconn TCP/SSL connection
* \note This function may only be used on TCP/SSL connection
* \param[in] nc: Netconn handle to flush data
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_flush(lwesp_netconn_p nc) {
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("nc->type must be TCP or SSL", nc->type == LWESP_NETCONN_TYPE_TCP || nc->type == LWESP_NETCONN_TYPE_SSL);
LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
/*
* In case we have data in write buffer,
* flush them out to network
*/
if (nc->buff.buff != NULL) { /* Check remaining data */
if (nc->buff.ptr > 0) { /* Do we have data in current buffer? */
lwesp_conn_send(nc->conn, nc->buff.buff, nc->buff.ptr, NULL, 1);/* Send data */
}
lwesp_mem_free_s((void**)&nc->buff.buff);
}
return lwespOK;
}
/**
* \brief Send data on UDP connection to default IP and port
* \param[in] nc: Netconn handle used to send
* \param[in] data: Pointer to data to write
* \param[in] btw: Number of bytes to write
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_send(lwesp_netconn_p nc, const void* data, size_t btw) {
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("nc->type must be UDP", nc->type == LWESP_NETCONN_TYPE_UDP);
LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
return lwesp_conn_send(nc->conn, data, btw, NULL, 1);
}
/**
* \brief Send data on UDP connection to specific IP and port
* \note Use this function in case of UDP type netconn
* \param[in] nc: Netconn handle used to send
* \param[in] ip: Pointer to IP address
* \param[in] port: Port number used to send data
* \param[in] data: Pointer to data to write
* \param[in] btw: Number of bytes to write
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_sendto(lwesp_netconn_p nc, const lwesp_ip_t* ip, lwesp_port_t port, const void* data, size_t btw) {
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("nc->type must be UDP", nc->type == LWESP_NETCONN_TYPE_UDP);
LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
return lwesp_conn_sendto(nc->conn, ip, port, data, btw, NULL, 1);
}
/**
* \brief Receive data from connection
* \param[in] nc: Netconn handle used to receive from
* \param[in] pbuf: Pointer to pointer to save new receive buffer to.
* When function returns, user must check for valid pbuf value `pbuf != NULL`
* \return \ref lwespOK when new data ready
* \return \ref lwespCLOSED when connection closed by remote side
* \return \ref lwespTIMEOUT when receive timeout occurs
* \return Any other member of \ref lwespr_t otherwise
*/
lwespr_t
lwesp_netconn_receive(lwesp_netconn_p nc, lwesp_pbuf_p* pbuf) {
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("pbuf != NULL", pbuf != NULL);
*pbuf = NULL;
#if LWESP_CFG_NETCONN_RECEIVE_TIMEOUT
/*
* Wait for new received data for up to specific timeout
* or throw error for timeout notification
*/
if (nc->rcv_timeout == LWESP_NETCONN_RECEIVE_NO_WAIT) {
if (!lwesp_sys_mbox_getnow(&nc->mbox_receive, (void**)pbuf)) {
return lwespTIMEOUT;
}
} else if (lwesp_sys_mbox_get(&nc->mbox_receive, (void**)pbuf, nc->rcv_timeout) == LWESP_SYS_TIMEOUT) {
return lwespTIMEOUT;
}
#else /* LWESP_CFG_NETCONN_RECEIVE_TIMEOUT */
/* Forever wait for new receive packet */
lwesp_sys_mbox_get(&nc->mbox_receive, (void**)pbuf, 0);
#endif /* !LWESP_CFG_NETCONN_RECEIVE_TIMEOUT */
lwesp_core_lock();
if (nc->mbox_receive_entries > 0) {
--nc->mbox_receive_entries;
}
lwesp_core_unlock();
/* Check if connection closed */
if ((uint8_t*)(*pbuf) == (uint8_t*)&recv_closed) {
*pbuf = NULL; /* Reset pbuf */
return lwespCLOSED;
}
#if LWESP_CFG_CONN_MANUAL_TCP_RECEIVE
else {
lwesp_core_lock();
nc->conn->status.f.receive_blocked = 0; /* Resume reading more data */
lwesp_conn_recved(nc->conn, *pbuf); /* Notify stack about received data */
lwesp_core_unlock();
}
#endif /* LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */
return lwespOK; /* We have data available */
}
/**
* \brief Close a netconn connection
* \param[in] nc: Netconn handle to close
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
lwesp_netconn_close(lwesp_netconn_p nc) {
lwesp_conn_p conn;
LWESP_ASSERT("nc != NULL", nc != NULL);
LWESP_ASSERT("nc->conn != NULL", nc->conn != NULL);
LWESP_ASSERT("nc->conn must be active", lwesp_conn_is_active(nc->conn));
lwesp_netconn_flush(nc); /* Flush data and ignore result */
conn = nc->conn;
nc->conn = NULL;
lwesp_conn_set_arg(conn, NULL); /* Reset argument */
lwesp_conn_close(conn, 1); /* Close the connection */
flush_mboxes(nc, 1); /* Flush message queues */
return lwespOK;
}
/**
* \brief Get connection number used for netconn
* \param[in] nc: Netconn handle
* \return `-1` on failure, connection number between `0` and \ref LWESP_CFG_MAX_CONNS otherwise
*/
int8_t
lwesp_netconn_get_connnum(lwesp_netconn_p nc) {
if (nc != NULL && nc->conn != NULL) {
return lwesp_conn_getnum(nc->conn);
}
return -1;
}
#if LWESP_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__
/**
* \brief Set timeout value for receiving data.
*
* When enabled, \ref lwesp_netconn_receive will only block for up to
* `timeout` value and will return if no new data within this time
*
* \param[in] nc: Netconn handle
* \param[in] timeout: 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 \ref LWESP_NETCONN_RECEIVE_NO_WAIT to enable non-blocking receive
*/
void
lwesp_netconn_set_receive_timeout(lwesp_netconn_p nc, uint32_t timeout) {
nc->rcv_timeout = timeout;
}
/**
* \brief Get netconn receive timeout value
* \param[in] nc: Netconn handle
* \return Timeout in units of milliseconds.
* If value is `0`, timeout is disabled (wait forever)
*/
uint32_t
lwesp_netconn_get_receive_timeout(lwesp_netconn_p nc) {
return nc->rcv_timeout;
}
#endif /* LWESP_CFG_NETCONN_RECEIVE_TIMEOUT || __DOXYGEN__ */
/**
* \brief Get netconn connection handle
* \param[in] nc: Netconn handle
* \return ESP connection handle
*/
lwesp_conn_p
lwesp_netconn_get_conn(lwesp_netconn_p nc) {
return nc->conn;
}
#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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #include "client.h"
#include "lwesp/lwesp.h"
/* Host parameter */
#define CONN_HOST "example.com"
#define CONN_PORT 80
static lwespr_t conn_callback_func(lwesp_evt_t* evt);
/**
* \brief Request data for connection
*/
static const
uint8_t req_data[] = ""
"GET / HTTP/1.1\r\n"
"Host: " CONN_HOST "\r\n"
"Connection: close\r\n"
"\r\n";
/**
* \brief Start a new connection(s) as client
*/
void
client_connect(void) {
lwespr_t res;
/* Start a new connection as client in non-blocking mode */
if ((res = lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, "example.com", 80, NULL, conn_callback_func, 0)) == lwespOK) {
printf("Connection to " CONN_HOST " started...\r\n");
} else {
printf("Cannot start connection to " CONN_HOST "!\r\n");
}
/* Start 2 more */
lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, CONN_PORT, NULL, conn_callback_func, 0);
/*
* An example of connection which should fail in connecting.
* When this is the case, \ref LWESP_EVT_CONN_ERROR event should be triggered
* in callback function processing
*/
lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, 10, NULL, conn_callback_func, 0);
}
/**
* \brief Event callback function for connection-only
* \param[in] evt: Event information with data
* \return \ref lwespOK on success, member of \ref lwespr_t otherwise
*/
static lwespr_t
conn_callback_func(lwesp_evt_t* evt) {
lwesp_conn_p conn;
lwespr_t res;
uint8_t conn_num;
conn = lwesp_conn_get_from_evt(evt); /* Get connection handle from event */
if (conn == NULL) {
return lwespERR;
}
conn_num = lwesp_conn_getnum(conn); /* Get connection number for identification */
switch (lwesp_evt_get_type(evt)) {
case LWESP_EVT_CONN_ACTIVE: { /* Connection just active */
printf("Connection %d active!\r\n", (int)conn_num);
res = lwesp_conn_send(conn, req_data, sizeof(req_data) - 1, NULL, 0); /* Start sending data in non-blocking mode */
if (res == lwespOK) {
printf("Sending request data to server...\r\n");
} else {
printf("Cannot send request data to server. Closing connection manually...\r\n");
lwesp_conn_close(conn, 0); /* Close the connection */
}
break;
}
case LWESP_EVT_CONN_CLOSE: { /* Connection closed */
if (lwesp_evt_conn_close_is_forced(evt)) {
printf("Connection %d closed by client!\r\n", (int)conn_num);
} else {
printf("Connection %d closed by remote side!\r\n", (int)conn_num);
}
break;
}
case LWESP_EVT_CONN_SEND: { /* Data send event */
lwespr_t res = lwesp_evt_conn_send_get_result(evt);
if (res == lwespOK) {
printf("Data sent successfully on connection %d...waiting to receive data from remote side...\r\n", (int)conn_num);
} else {
printf("Error while sending data on connection %d!\r\n", (int)conn_num);
}
break;
}
case LWESP_EVT_CONN_RECV: { /* Data received from remote side */
lwesp_pbuf_p pbuf = lwesp_evt_conn_recv_get_buff(evt);
lwesp_conn_recved(conn, pbuf); /* Notify stack about received pbuf */
printf("Received %d bytes on connection %d..\r\n", (int)lwesp_pbuf_length(pbuf, 1), (int)conn_num);
break;
}
case LWESP_EVT_CONN_ERROR: { /* Error connecting to server */
const char* host = lwesp_evt_conn_error_get_host(evt);
lwesp_port_t port = lwesp_evt_conn_error_get_port(evt);
printf("Error connecting to %s:%d\r\n", host, (int)port);
break;
}
default:
break;
}
return lwespOK;
}
|
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include "dns.h"
#include "lwesp/lwesp.h"
/* Host to resolve */
#define DNS_HOST1 "example.com"
#define DNS_HOST2 "example.net"
/**
* \brief Variable to hold result of DNS resolver
*/
static lwesp_ip_t ip;
/**
* \brief Event callback function for API call,
* called when API command finished with execution
*/
static void
dns_resolve_evt(lwespr_t res, void* arg) {
/* Check result of command */
if (res == lwespOK) {
/* DNS resolver has IP address */
printf("DNS record for %s (from API callback): %d.%d.%d.%d\r\n",
(const char*)arg, (int)ip.ip[0], (int)ip.ip[1], (int)ip.ip[2], (int)ip.ip[3]);
}
}
/**
* \brief Start DNS resolver
*/
void
dns_start(void) {
/* Use DNS protocol to get IP address of domain name */
/* Get IP with non-blocking mode */
if (lwesp_dns_gethostbyname(DNS_HOST2, &ip, dns_resolve_evt, DNS_HOST2, 0) == lwespOK) {
printf("Request for DNS record for " DNS_HOST2 " has started\r\n");
} else {
printf("Could not start command for DNS\r\n");
}
/* Get IP with blocking mode */
if (lwesp_dns_gethostbyname(DNS_HOST1, &ip, dns_resolve_evt, DNS_HOST1, 1) == lwespOK) {
printf("DNS record for " DNS_HOST1 " (from lin code): %d.%d.%d.%d\r\n",
(int)ip.ip[0], (int)ip.ip[1], (int)ip.ip[2], (int)ip.ip[3]);
} else {
printf("Could not retrieve IP address for " DNS_HOST1 "\r\n");
}
}
|
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:
1 2 3 4 5 6 7 8 9 10 11 12 | char hostname[20];
/* Somewhere in thread function */
/* Get device hostname in blocking mode */
/* Function returns actual result */
if (lwesp_hostname_get(hostname, sizeof(hostname), NULL, NULL, 1 /* 1 means blocking call */) == lwespOK) {
/* At this point we have valid result and parameters from API function */
printf("ESP hostname is %s\r\n", hostname);
} else {
printf("Error reading ESP hostname..\r\n");
}
|
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 to do so will result in function returning error.
Example code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | char hostname[20];
/* Hostname event function, called when lwesp_hostname_get() function finishes */
void
hostname_fn(lwespr_t res, void* arg) {
/* Check actual result from device */
if (res == lwespOK) {
printf("ESP hostname is %s\r\n", hostname);
} else {
printf("Error reading ESP hostname...\r\n");
}
}
/* Somewhere in thread and/or other ESP event function */
/* Get device hostname in non-blocking mode */
/* Function now returns if command has been sent to internal message queue */
if (lwesp_hostname_get(hostname, sizeof(hostname), hostname_fn, NULL, 0 /* 0 means non-blocking call */) == lwespOK) {
/* At this point application knows that command has been sent to queue */
/* But it does not have yet valid data in "hostname" variable */
printf("ESP hostname get command sent to queue.\r\n");
} else {
/* Error writing message to queue */
printf("Cannot send hostname get command to queue.\r\n");
}
|
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | char hostname[20];
/* Hostname event function, called when lwesp_hostname_get() function finishes */
void
hostname_fn(lwespr_t res, void* arg) {
/* Check actual result from device */
if (res == lwespOK) {
printf("ESP hostname is %s\r\n", hostname);
} else {
printf("Error reading ESP hostname...\r\n");
}
}
/* Check hostname */
void
check_hostname(void) {
char hostname[20];
/* Somewhere in thread and/or other ESP event function */
/* Get device hostname in non-blocking mode */
/* Function now returns if command has been sent to internal message queue */
/* Function will use local "hostname" variable and will write to undefined memory */
if (lwesp_hostname_get(hostname, sizeof(hostname), hostname_fn, NULL, 0 /* 0 means non-blocking call */) == lwespOK) {
/* At this point application knows that command has been sent to queue */
/* But it does not have yet valid data in "hostname" variable */
printf("ESP hostname get command sent to queue.\r\n");
} else {
/* Error writing message to queue */
printf("Cannot send hostname get command to queue.\r\n");
}
}
|
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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | /**
* \file lwesp_ll_win32.c
* \brief Low-level communication with ESP device for WIN32
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#include "system/lwesp_ll.h"
#include "lwesp/lwesp.h"
#include "lwesp/lwesp_mem.h"
#include "lwesp/lwesp_input.h"
#if !__DOXYGEN__
volatile uint8_t lwesp_ll_win32_driver_ignore_data;
static uint8_t initialized = 0;
static HANDLE thread_handle;
static volatile HANDLE com_port; /*!< COM port handle */
static uint8_t data_buffer[0x1000]; /*!< Received data array */
static void uart_thread(void* param);
/**
* \brief Send data to ESP device, function called from ESP stack when we have data to send
*/
static size_t
send_data(const void* data, size_t len) {
DWORD written;
if (com_port != NULL) {
#if !LWESP_CFG_AT_ECHO
const uint8_t* d = data;
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
for (DWORD i = 0; i < len; ++i) {
printf("%c", d[i]);
}
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif /* !LWESP_CFG_AT_ECHO */
WriteFile(com_port, data, len, &written, NULL);
FlushFileBuffers(com_port);
return written;
}
return 0;
}
/**
* \brief Configure UART (USB to UART)
*/
static void
configure_uart(uint32_t baudrate) {
DCB dcb = { 0 };
dcb.DCBlength = sizeof(dcb);
/*
* On first call,
* create virtual file on selected COM port and open it
* as generic read and write
*/
if (!initialized) {
com_port = CreateFile(L"\\\\.\\COM4",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
NULL
);
}
/* Configure COM port parameters */
if (GetCommState(com_port, &dcb)) {
COMMTIMEOUTS timeouts;
dcb.BaudRate = baudrate;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if (!SetCommState(com_port, &dcb)) {
printf("Cannot set COM PORT info\r\n");
}
if (GetCommTimeouts(com_port, &timeouts)) {
/* Set timeout to return immediately from ReadFile function */
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
if (!SetCommTimeouts(com_port, &timeouts)) {
printf("Cannot set COM PORT timeouts\r\n");
}
GetCommTimeouts(com_port, &timeouts);
} else {
printf("Cannot get COM PORT timeouts\r\n");
}
} else {
printf("Cannot get COM PORT info\r\n");
}
/* On first function call, create a thread to read data from COM port */
if (!initialized) {
lwesp_sys_thread_create(&thread_handle, "lwesp_ll_thread", uart_thread, NULL, 0, 0);
}
}
/**
* \brief UART thread
*/
static void
uart_thread(void* param) {
DWORD bytes_read;
lwesp_sys_sem_t sem;
FILE* file = NULL;
lwesp_sys_sem_create(&sem, 0); /* Create semaphore for delay functions */
while (com_port == NULL) {
lwesp_sys_sem_wait(&sem, 1); /* Add some delay with yield */
}
fopen_s(&file, "log_file.txt", "w+"); /* Open debug file in write mode */
while (1) {
/*
* Try to read data from COM port
* and send it to upper layer for processing
*/
do {
ReadFile(com_port, data_buffer, sizeof(data_buffer), &bytes_read, NULL);
if (bytes_read > 0) {
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
for (DWORD i = 0; i < bytes_read; ++i) {
printf("%c", data_buffer[i]);
}
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
if (lwesp_ll_win32_driver_ignore_data) {
printf("IGNORING..\r\n");
continue;
}
/* Send received data to input processing module */
#if LWESP_CFG_INPUT_USE_PROCESS
lwesp_input_process(data_buffer, (size_t)bytes_read);
#else /* LWESP_CFG_INPUT_USE_PROCESS */
lwesp_input(data_buffer, (size_t)bytes_read);
#endif /* !LWESP_CFG_INPUT_USE_PROCESS */
/* Write received data to output debug file */
if (file != NULL) {
fwrite(data_buffer, 1, bytes_read, file);
fflush(file);
}
}
} while (bytes_read == (DWORD)sizeof(data_buffer));
/* Implement delay to allow other tasks processing */
lwesp_sys_sem_wait(&sem, 1);
}
}
/**
* \brief Reset device GPIO management
*/
static uint8_t
reset_device(uint8_t state) {
return 0; /* Hardware reset was not successful */
}
/**
* \brief Callback function called from initialization process
*/
lwespr_t
lwesp_ll_init(lwesp_ll_t* ll) {
#if !LWESP_CFG_MEM_CUSTOM
/* Step 1: Configure memory for dynamic allocations */
static uint8_t memory[0x10000]; /* Create memory for dynamic allocations with specific size */
/*
* Create memory region(s) of memory.
* If device has internal/external memory available,
* multiple memories may be used
*/
lwesp_mem_region_t mem_regions[] = {
{ memory, sizeof(memory) }
};
if (!initialized) {
lwesp_mem_assignmemory(mem_regions, LWESP_ARRAYSIZE(mem_regions)); /* Assign memory for allocations to ESP library */
}
#endif /* !LWESP_CFG_MEM_CUSTOM */
/* Step 2: Set AT port send function to use when we have data to transmit */
if (!initialized) {
ll->send_fn = send_data; /* Set callback function to send data */
ll->reset_fn = reset_device;
}
/* Step 3: Configure AT port to be able to send/receive data to/from ESP device */
configure_uart(ll->uart.baudrate); /* Initialize UART for communication */
initialized = 1;
return lwespOK;
}
/**
* \brief Callback function to de-init low-level communication part
*/
lwespr_t
lwesp_ll_deinit(lwesp_ll_t* ll) {
if (thread_handle != NULL) {
lwesp_sys_thread_terminate(&thread_handle);
thread_handle = NULL;
}
initialized = 0; /* Clear initialized flag */
return lwespOK;
}
#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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 | /**
* \file lwesp_ll_stm32.c
* \brief Generic STM32 driver, included in various STM32 driver variants
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
/*
* How it works
*
* On first call to \ref lwesp_ll_init, new thread is created and processed in usart_ll_thread function.
* USART is configured in RX DMA mode and any incoming bytes are processed inside thread function.
* DMA and USART implement interrupt handlers to notify main thread about new data ready to send to upper layer.
*
* More about UART + RX DMA: https://github.com/MaJerle/stm32-usart-dma-rx-tx
*
* \ref LWESP_CFG_INPUT_USE_PROCESS must be enabled in `lwesp_config.h` to use this driver.
*/
#include "lwesp/lwesp.h"
#include "lwesp/lwesp_mem.h"
#include "lwesp/lwesp_input.h"
#include "system/lwesp_ll.h"
#if !__DOXYGEN__
#if !LWESP_CFG_INPUT_USE_PROCESS
#error "LWESP_CFG_INPUT_USE_PROCESS must be enabled in `lwesp_config.h` to use this driver."
#endif /* LWESP_CFG_INPUT_USE_PROCESS */
#if !defined(LWESP_USART_DMA_RX_BUFF_SIZE)
#define LWESP_USART_DMA_RX_BUFF_SIZE 0x1000
#endif /* !defined(LWESP_USART_DMA_RX_BUFF_SIZE) */
#if !defined(LWESP_MEM_SIZE)
#define LWESP_MEM_SIZE 0x1000
#endif /* !defined(LWESP_MEM_SIZE) */
#if !defined(LWESP_USART_RDR_NAME)
#define LWESP_USART_RDR_NAME RDR
#endif /* !defined(LWESP_USART_RDR_NAME) */
/* USART memory */
static uint8_t usart_mem[LWESP_USART_DMA_RX_BUFF_SIZE];
static uint8_t is_running, initialized;
static size_t old_pos;
/* USART thread */
static void usart_ll_thread(void* arg);
static osThreadId_t usart_ll_thread_id;
/* Message queue */
static osMessageQueueId_t usart_ll_mbox_id;
/**
* \brief USART data processing
*/
static void
usart_ll_thread(void* arg) {
size_t pos;
LWESP_UNUSED(arg);
while (1) {
void* d;
/* Wait for the event message from DMA or USART */
osMessageQueueGet(usart_ll_mbox_id, &d, NULL, osWaitForever);
/* Read data */
#if defined(LWESP_USART_DMA_RX_STREAM)
pos = sizeof(usart_mem) - LL_DMA_GetDataLength(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
#else
pos = sizeof(usart_mem) - LL_DMA_GetDataLength(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
if (pos != old_pos && is_running) {
if (pos > old_pos) {
lwesp_input_process(&usart_mem[old_pos], pos - old_pos);
} else {
lwesp_input_process(&usart_mem[old_pos], sizeof(usart_mem) - old_pos);
if (pos > 0) {
lwesp_input_process(&usart_mem[0], pos);
}
}
old_pos = pos;
if (old_pos == sizeof(usart_mem)) {
old_pos = 0;
}
}
}
}
/**
* \brief Configure UART using DMA for receive in double buffer mode and IDLE line detection
*/
static void
configure_uart(uint32_t baudrate) {
static LL_USART_InitTypeDef usart_init;
static LL_DMA_InitTypeDef dma_init;
LL_GPIO_InitTypeDef gpio_init;
if (!initialized) {
/* Enable peripheral clocks */
LWESP_USART_CLK;
LWESP_USART_DMA_CLK;
LWESP_USART_TX_PORT_CLK;
LWESP_USART_RX_PORT_CLK;
#if defined(LWESP_RESET_PIN)
LWESP_RESET_PORT_CLK;
#endif /* defined(LWESP_RESET_PIN) */
#if defined(LWESP_GPIO0_PIN)
LWESP_GPIO0_PORT_CLK;
#endif /* defined(LWESP_GPIO0_PIN) */
#if defined(LWESP_GPIO2_PIN)
LWESP_GPIO2_PORT_CLK;
#endif /* defined(LWESP_GPIO2_PIN) */
#if defined(LWESP_CH_PD_PIN)
LWESP_CH_PD_PORT_CLK;
#endif /* defined(LWESP_CH_PD_PIN) */
/* Global pin configuration */
LL_GPIO_StructInit(&gpio_init);
gpio_init.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
gpio_init.Pull = LL_GPIO_PULL_UP;
gpio_init.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpio_init.Mode = LL_GPIO_MODE_OUTPUT;
#if defined(LWESP_RESET_PIN)
/* Configure RESET pin */
gpio_init.Pin = LWESP_RESET_PIN;
LL_GPIO_Init(LWESP_RESET_PORT, &gpio_init);
#endif /* defined(LWESP_RESET_PIN) */
#if defined(LWESP_GPIO0_PIN)
/* Configure GPIO0 pin */
gpio_init.Pin = LWESP_GPIO0_PIN;
LL_GPIO_Init(LWESP_GPIO0_PORT, &gpio_init);
LL_GPIO_SetOutputPin(LWESP_GPIO0_PORT, LWESP_GPIO0_PIN);
#endif /* defined(LWESP_GPIO0_PIN) */
#if defined(LWESP_GPIO2_PIN)
/* Configure GPIO2 pin */
gpio_init.Pin = LWESP_GPIO2_PIN;
LL_GPIO_Init(LWESP_GPIO2_PORT, &gpio_init);
LL_GPIO_SetOutputPin(LWESP_GPIO2_PORT, LWESP_GPIO2_PIN);
#endif /* defined(LWESP_GPIO2_PIN) */
#if defined(LWESP_CH_PD_PIN)
/* Configure CH_PD pin */
gpio_init.Pin = LWESP_CH_PD_PIN;
LL_GPIO_Init(LWESP_CH_PD_PORT, &gpio_init);
LL_GPIO_SetOutputPin(LWESP_CH_PD_PORT, LWESP_CH_PD_PIN);
#endif /* defined(LWESP_CH_PD_PIN) */
/* Configure USART pins */
gpio_init.Mode = LL_GPIO_MODE_ALTERNATE;
/* TX PIN */
gpio_init.Alternate = LWESP_USART_TX_PIN_AF;
gpio_init.Pin = LWESP_USART_TX_PIN;
LL_GPIO_Init(LWESP_USART_TX_PORT, &gpio_init);
/* RX PIN */
gpio_init.Alternate = LWESP_USART_RX_PIN_AF;
gpio_init.Pin = LWESP_USART_RX_PIN;
LL_GPIO_Init(LWESP_USART_RX_PORT, &gpio_init);
/* Configure UART */
LL_USART_DeInit(LWESP_USART);
LL_USART_StructInit(&usart_init);
usart_init.BaudRate = baudrate;
usart_init.DataWidth = LL_USART_DATAWIDTH_8B;
usart_init.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
usart_init.OverSampling = LL_USART_OVERSAMPLING_16;
usart_init.Parity = LL_USART_PARITY_NONE;
usart_init.StopBits = LL_USART_STOPBITS_1;
usart_init.TransferDirection = LL_USART_DIRECTION_TX_RX;
LL_USART_Init(LWESP_USART, &usart_init);
/* Enable USART interrupts and DMA request */
LL_USART_EnableIT_IDLE(LWESP_USART);
LL_USART_EnableIT_PE(LWESP_USART);
LL_USART_EnableIT_ERROR(LWESP_USART);
LL_USART_EnableDMAReq_RX(LWESP_USART);
/* Enable USART interrupts */
NVIC_SetPriority(LWESP_USART_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00));
NVIC_EnableIRQ(LWESP_USART_IRQ);
/* Configure DMA */
is_running = 0;
#if defined(LWESP_USART_DMA_RX_STREAM)
LL_DMA_DeInit(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
dma_init.Channel = LWESP_USART_DMA_RX_CH;
#else
LL_DMA_DeInit(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
dma_init.PeriphRequest = LWESP_USART_DMA_RX_REQ_NUM;
#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
dma_init.PeriphOrM2MSrcAddress = (uint32_t)&LWESP_USART->LWESP_USART_RDR_NAME;
dma_init.MemoryOrM2MDstAddress = (uint32_t)usart_mem;
dma_init.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
dma_init.Mode = LL_DMA_MODE_CIRCULAR;
dma_init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
dma_init.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
dma_init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
dma_init.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
dma_init.NbData = sizeof(usart_mem);
dma_init.Priority = LL_DMA_PRIORITY_MEDIUM;
#if defined(LWESP_USART_DMA_RX_STREAM)
LL_DMA_Init(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM, &dma_init);
#else
LL_DMA_Init(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH, &dma_init);
#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
/* Enable DMA interrupts */
#if defined(LWESP_USART_DMA_RX_STREAM)
LL_DMA_EnableIT_HT(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
LL_DMA_EnableIT_TC(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
LL_DMA_EnableIT_TE(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
LL_DMA_EnableIT_FE(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
LL_DMA_EnableIT_DME(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
#else
LL_DMA_EnableIT_HT(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
LL_DMA_EnableIT_TC(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
LL_DMA_EnableIT_TE(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
/* Enable DMA interrupts */
NVIC_SetPriority(LWESP_USART_DMA_RX_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x07, 0x00));
NVIC_EnableIRQ(LWESP_USART_DMA_RX_IRQ);
old_pos = 0;
is_running = 1;
/* Start DMA and USART */
#if defined(LWESP_USART_DMA_RX_STREAM)
LL_DMA_EnableStream(LWESP_USART_DMA, LWESP_USART_DMA_RX_STREAM);
#else
LL_DMA_EnableChannel(LWESP_USART_DMA, LWESP_USART_DMA_RX_CH);
#endif /* defined(LWESP_USART_DMA_RX_STREAM) */
LL_USART_Enable(LWESP_USART);
} else {
osDelay(10);
LL_USART_Disable(LWESP_USART);
usart_init.BaudRate = baudrate;
LL_USART_Init(LWESP_USART, &usart_init);
LL_USART_Enable(LWESP_USART);
}
/* Create mbox and start thread */
if (usart_ll_mbox_id == NULL) {
usart_ll_mbox_id = osMessageQueueNew(10, sizeof(void*), NULL);
}
if (usart_ll_thread_id == NULL) {
const osThreadAttr_t attr = {
.stack_size = 1024
};
usart_ll_thread_id = osThreadNew(usart_ll_thread, usart_ll_mbox_id, &attr);
}
}
#if defined(LWESP_RESET_PIN)
/**
* \brief Hardware reset callback
*/
static uint8_t
reset_device(uint8_t state) {
if (state) { /* Activate reset line */
LL_GPIO_ResetOutputPin(LWESP_RESET_PORT, LWESP_RESET_PIN);
} else {
LL_GPIO_SetOutputPin(LWESP_RESET_PORT, LWESP_RESET_PIN);
}
return 1;
}
#endif /* defined(LWESP_RESET_PIN) */
/**
* \brief Send data to ESP device
* \param[in] data: Pointer to data to send
* \param[in] len: Number of bytes to send
* \return Number of bytes sent
*/
static size_t
send_data(const void* data, size_t len) {
const uint8_t* d = data;
for (size_t i = 0; i < len; ++i, ++d) {
LL_USART_TransmitData8(LWESP_USART, *d);
while (!LL_USART_IsActiveFlag_TXE(LWESP_USART)) {}
}
return len;
}
/**
* \brief Callback function called from initialization process
*/
lwespr_t
lwesp_ll_init(lwesp_ll_t* ll) {
#if !LWESP_CFG_MEM_CUSTOM
static uint8_t memory[LWESP_MEM_SIZE];
lwesp_mem_region_t mem_regions[] = {
{ memory, sizeof(memory) }
};
if (!initialized) {
lwesp_mem_assignmemory(mem_regions, LWESP_ARRAYSIZE(mem_regions)); /* Assign memory for allocations */
}
#endif /* !LWESP_CFG_MEM_CUSTOM */
if (!initialized) {
ll->send_fn = send_data; /* Set callback function to send data */
#if defined(LWESP_RESET_PIN)
ll->reset_fn = reset_device; /* Set callback for hardware reset */
#endif /* defined(LWESP_RESET_PIN) */
}
configure_uart(ll->uart.baudrate); /* Initialize UART for communication */
initialized = 1;
return lwespOK;
}
/**
* \brief Callback function to de-init low-level communication part
*/
lwespr_t
lwesp_ll_deinit(lwesp_ll_t* ll) {
if (usart_ll_mbox_id != NULL) {
osMessageQueueId_t tmp = usart_ll_mbox_id;
usart_ll_mbox_id = NULL;
osMessageQueueDelete(tmp);
}
if (usart_ll_thread_id != NULL) {
osThreadId_t tmp = usart_ll_thread_id;
usart_ll_thread_id = NULL;
osThreadTerminate(tmp);
}
initialized = 0;
LWESP_UNUSED(ll);
return lwespOK;
}
/**
* \brief UART global interrupt handler
*/
void
LWESP_USART_IRQHANDLER(void) {
LL_USART_ClearFlag_IDLE(LWESP_USART);
LL_USART_ClearFlag_PE(LWESP_USART);
LL_USART_ClearFlag_FE(LWESP_USART);
LL_USART_ClearFlag_ORE(LWESP_USART);
LL_USART_ClearFlag_NE(LWESP_USART);
if (usart_ll_mbox_id != NULL) {
void* d = (void*)1;
osMessageQueuePut(usart_ll_mbox_id, &d, 0, 0);
}
}
/**
* \brief UART DMA stream/channel handler
*/
void
LWESP_USART_DMA_RX_IRQHANDLER(void) {
LWESP_USART_DMA_RX_CLEAR_TC;
LWESP_USART_DMA_RX_CLEAR_HT;
if (usart_ll_mbox_id != NULL) {
void* d = (void*)1;
osMessageQueuePut(usart_ll_mbox_id, &d, 0, 0);
}
}
#endif /* !__DOXYGEN__ */
|
Example: System functions for WIN32¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | /**
* \file lwesp_sys_port.h
* \brief WIN32 based system file implementation
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#ifndef LWESP_HDR_SYSTEM_PORT_H
#define LWESP_HDR_SYSTEM_PORT_H
#include <stdint.h>
#include <stdlib.h>
#include "lwesp/lwesp_opt.h"
#include "windows.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#if LWESP_CFG_OS && !__DOXYGEN__
typedef HANDLE lwesp_sys_mutex_t;
typedef HANDLE lwesp_sys_sem_t;
typedef HANDLE lwesp_sys_mbox_t;
typedef HANDLE lwesp_sys_thread_t;
typedef int lwesp_sys_thread_prio_t;
#define LWESP_SYS_MBOX_NULL ((HANDLE)0)
#define LWESP_SYS_SEM_NULL ((HANDLE)0)
#define LWESP_SYS_MUTEX_NULL ((HANDLE)0)
#define LWESP_SYS_TIMEOUT (INFINITE)
#define LWESP_SYS_THREAD_PRIO (0)
#define LWESP_SYS_THREAD_SS (1024)
#endif /* LWESP_CFG_OS && !__DOXYGEN__ */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWESP_HDR_SYSTEM_PORT_H */
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | /**
* \file lwesp_sys_win32.c
* \brief System dependant functions for WIN32
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#include <string.h>
#include <stdlib.h>
#include "system/lwesp_sys.h"
#include "windows.h"
#if !__DOXYGEN__
/**
* \brief Custom message queue implementation for WIN32
*/
typedef struct {
lwesp_sys_sem_t sem_not_empty; /*!< Semaphore indicates not empty */
lwesp_sys_sem_t sem_not_full; /*!< Semaphore indicates not full */
lwesp_sys_sem_t sem; /*!< Semaphore to lock access */
size_t in, out, size;
void* entries[1];
} win32_mbox_t;
static LARGE_INTEGER freq, sys_start_time;
static lwesp_sys_mutex_t sys_mutex; /* Mutex ID for main protection */
/**
* \brief Check if message box is full
* \param[in] m: Message box handle
* \return 1 if full, 0 otherwise
*/
static uint8_t
mbox_is_full(win32_mbox_t* m) {
size_t size = 0;
if (m->in > m->out) {
size = (m->in - m->out);
} else if (m->out > m->in) {
size = m->size - m->out + m->in;
}
return size == m->size - 1;
}
/**
* \brief Check if message box is empty
* \param[in] m: Message box handle
* \return 1 if empty, 0 otherwise
*/
static uint8_t
mbox_is_empty(win32_mbox_t* m) {
return m->in == m->out;
}
/**
* \brief Get current kernel time in units of milliseconds
*/
static uint32_t
osKernelSysTick(void) {
LONGLONG ret;
LARGE_INTEGER now;
QueryPerformanceFrequency(&freq); /* Get frequency */
QueryPerformanceCounter(&now); /* Get current time */
ret = now.QuadPart - sys_start_time.QuadPart;
return (uint32_t)(((ret) * 1000) / freq.QuadPart);
}
uint8_t
lwesp_sys_init(void) {
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&sys_start_time);
lwesp_sys_mutex_create(&sys_mutex);
return 1;
}
uint32_t
lwesp_sys_now(void) {
return osKernelSysTick();
}
#if LWESP_CFG_OS
uint8_t
lwesp_sys_protect(void) {
lwesp_sys_mutex_lock(&sys_mutex);
return 1;
}
uint8_t
lwesp_sys_unprotect(void) {
lwesp_sys_mutex_unlock(&sys_mutex);
return 1;
}
uint8_t
lwesp_sys_mutex_create(lwesp_sys_mutex_t* p) {
*p = CreateMutex(NULL, FALSE, NULL);
return *p != NULL;
}
uint8_t
lwesp_sys_mutex_delete(lwesp_sys_mutex_t* p) {
return CloseHandle(*p);
}
uint8_t
lwesp_sys_mutex_lock(lwesp_sys_mutex_t* p) {
DWORD ret;
ret = WaitForSingleObject(*p, INFINITE);
if (ret != WAIT_OBJECT_0) {
return 0;
}
return 1;
}
uint8_t
lwesp_sys_mutex_unlock(lwesp_sys_mutex_t* p) {
return ReleaseMutex(*p);
}
uint8_t
lwesp_sys_mutex_isvalid(lwesp_sys_mutex_t* p) {
return p != NULL && *p != NULL;
}
uint8_t
lwesp_sys_mutex_invalid(lwesp_sys_mutex_t* p) {
*p = LWESP_SYS_MUTEX_NULL;
return 1;
}
uint8_t
lwesp_sys_sem_create(lwesp_sys_sem_t* p, uint8_t cnt) {
HANDLE h;
h = CreateSemaphore(NULL, !!cnt, 1, NULL);
*p = h;
return *p != NULL;
}
uint8_t
lwesp_sys_sem_delete(lwesp_sys_sem_t* p) {
return CloseHandle(*p);
}
uint32_t
lwesp_sys_sem_wait(lwesp_sys_sem_t* p, uint32_t timeout) {
DWORD ret;
uint32_t tick = osKernelSysTick();
if (timeout == 0) {
ret = WaitForSingleObject(*p, INFINITE);
return 1;
} else {
ret = WaitForSingleObject(*p, timeout);
if (ret == WAIT_OBJECT_0) {
return 1;
} else {
return LWESP_SYS_TIMEOUT;
}
}
}
uint8_t
lwesp_sys_sem_release(lwesp_sys_sem_t* p) {
return ReleaseSemaphore(*p, 1, NULL);
}
uint8_t
lwesp_sys_sem_isvalid(lwesp_sys_sem_t* p) {
return p != NULL && *p != NULL;
}
uint8_t
lwesp_sys_sem_invalid(lwesp_sys_sem_t* p) {
*p = LWESP_SYS_SEM_NULL;
return 1;
}
uint8_t
lwesp_sys_mbox_create(lwesp_sys_mbox_t* b, size_t size) {
win32_mbox_t* mbox;
*b = 0;
mbox = malloc(sizeof(*mbox) + size * sizeof(void*));
if (mbox != NULL) {
memset(mbox, 0x00, sizeof(*mbox));
mbox->size = size + 1; /* Set it to 1 more as cyclic buffer has only one less than size */
lwesp_sys_sem_create(&mbox->sem, 1);
lwesp_sys_sem_create(&mbox->sem_not_empty, 0);
lwesp_sys_sem_create(&mbox->sem_not_full, 0);
*b = mbox;
}
return *b != NULL;
}
uint8_t
lwesp_sys_mbox_delete(lwesp_sys_mbox_t* b) {
win32_mbox_t* mbox = *b;
lwesp_sys_sem_delete(&mbox->sem);
lwesp_sys_sem_delete(&mbox->sem_not_full);
lwesp_sys_sem_delete(&mbox->sem_not_empty);
free(mbox);
return 1;
}
uint32_t
lwesp_sys_mbox_put(lwesp_sys_mbox_t* b, void* m) {
win32_mbox_t* mbox = *b;
uint32_t time = osKernelSysTick(); /* Get start time */
lwesp_sys_sem_wait(&mbox->sem, 0); /* Wait for access */
/*
* Since function is blocking until ready to write something to queue,
* wait and release the semaphores to allow other threads
* to process the queue before we can write new value.
*/
while (mbox_is_full(mbox)) {
lwesp_sys_sem_release(&mbox->sem); /* Release semaphore */
lwesp_sys_sem_wait(&mbox->sem_not_full, 0); /* Wait for semaphore indicating not full */
lwesp_sys_sem_wait(&mbox->sem, 0); /* Wait availability again */
}
mbox->entries[mbox->in] = m;
if (++mbox->in >= mbox->size) {
mbox->in = 0;
}
lwesp_sys_sem_release(&mbox->sem_not_empty);/* Signal non-empty state */
lwesp_sys_sem_release(&mbox->sem); /* Release access for other threads */
return osKernelSysTick() - time;
}
uint32_t
lwesp_sys_mbox_get(lwesp_sys_mbox_t* b, void** m, uint32_t timeout) {
win32_mbox_t* mbox = *b;
uint32_t time;
time = osKernelSysTick();
/* Get exclusive access to message queue */
if (lwesp_sys_sem_wait(&mbox->sem, timeout) == LWESP_SYS_TIMEOUT) {
return LWESP_SYS_TIMEOUT;
}
while (mbox_is_empty(mbox)) {
lwesp_sys_sem_release(&mbox->sem);
if (lwesp_sys_sem_wait(&mbox->sem_not_empty, timeout) == LWESP_SYS_TIMEOUT) {
return LWESP_SYS_TIMEOUT;
}
lwesp_sys_sem_wait(&mbox->sem, timeout);
}
*m = mbox->entries[mbox->out];
if (++mbox->out >= mbox->size) {
mbox->out = 0;
}
lwesp_sys_sem_release(&mbox->sem_not_full);
lwesp_sys_sem_release(&mbox->sem);
return osKernelSysTick() - time;
}
uint8_t
lwesp_sys_mbox_putnow(lwesp_sys_mbox_t* b, void* m) {
win32_mbox_t* mbox = *b;
lwesp_sys_sem_wait(&mbox->sem, 0);
if (mbox_is_full(mbox)) {
lwesp_sys_sem_release(&mbox->sem);
return 0;
}
mbox->entries[mbox->in] = m;
if (mbox->in == mbox->out) {
lwesp_sys_sem_release(&mbox->sem_not_empty);
}
if (++mbox->in >= mbox->size) {
mbox->in = 0;
}
lwesp_sys_sem_release(&mbox->sem);
return 1;
}
uint8_t
lwesp_sys_mbox_getnow(lwesp_sys_mbox_t* b, void** m) {
win32_mbox_t* mbox = *b;
lwesp_sys_sem_wait(&mbox->sem, 0); /* Wait exclusive access */
if (mbox->in == mbox->out) {
lwesp_sys_sem_release(&mbox->sem); /* Release access */
return 0;
}
*m = mbox->entries[mbox->out];
if (++mbox->out >= mbox->size) {
mbox->out = 0;
}
lwesp_sys_sem_release(&mbox->sem_not_full); /* Queue not full anymore */
lwesp_sys_sem_release(&mbox->sem); /* Release semaphore */
return 1;
}
uint8_t
lwesp_sys_mbox_isvalid(lwesp_sys_mbox_t* b) {
return b != NULL && *b != NULL;
}
uint8_t
lwesp_sys_mbox_invalid(lwesp_sys_mbox_t* b) {
*b = LWESP_SYS_MBOX_NULL;
return 1;
}
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) {
HANDLE h;
DWORD id;
h = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_func, arg, 0, &id);
if (t != NULL) {
*t = h;
}
return h != NULL;
}
uint8_t
lwesp_sys_thread_terminate(lwesp_sys_thread_t* t) {
HANDLE h = NULL;
if (t == NULL) { /* Shall we terminate ourself? */
h = GetCurrentThread(); /* Get current thread handle */
} else { /* We have known thread, find handle by looking at ID */
h = *t;
}
TerminateThread(h, 0);
return 1;
}
uint8_t
lwesp_sys_thread_yield(void) {
/* Not implemented */
return 1;
}
#endif /* LWESP_CFG_OS */
#endif /* !__DOXYGEN__ */
|
Example: System functions for CMSIS-OS¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | /**
* \file lwesp_sys_port.h
* \brief CMSIS-OS based system file
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#ifndef LWESP_HDR_SYSTEM_PORT_H
#define LWESP_HDR_SYSTEM_PORT_H
#include <stdint.h>
#include <stdlib.h>
#include "lwesp/lwesp_opt.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#if LWESP_CFG_OS && !__DOXYGEN__
typedef osMutexId_t lwesp_sys_mutex_t;
typedef osSemaphoreId_t lwesp_sys_sem_t;
typedef osMessageQueueId_t lwesp_sys_mbox_t;
typedef osThreadId_t lwesp_sys_thread_t;
typedef osPriority_t lwesp_sys_thread_prio_t;
#define LWESP_SYS_MUTEX_NULL ((lwesp_sys_mutex_t)0)
#define LWESP_SYS_SEM_NULL ((lwesp_sys_sem_t)0)
#define LWESP_SYS_MBOX_NULL ((lwesp_sys_mbox_t)0)
#define LWESP_SYS_TIMEOUT ((uint32_t)osWaitForever)
#define LWESP_SYS_THREAD_PRIO (osPriorityNormal)
#define LWESP_SYS_THREAD_SS (512)
#endif /* LWESP_CFG_OS && !__DOXYGEN__ */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWESP_HDR_SYSTEM_PORT_H */
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | /**
* \file lwesp_sys_cmsis_os.c
* \brief System dependent functions for CMSIS based operating system
*/
/*
* 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.
*
* This file is part of LwESP - Lightweight ESP-AT parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v1.0.0
*/
#include "system/lwesp_sys.h"
#include "cmsis_os.h"
#if !__DOXYGEN__
static osMutexId_t sys_mutex;
uint8_t
lwesp_sys_init(void) {
lwesp_sys_mutex_create(&sys_mutex);
return 1;
}
uint32_t
lwesp_sys_now(void) {
return osKernelSysTick();
}
uint8_t
lwesp_sys_protect(void) {
lwesp_sys_mutex_lock(&sys_mutex);
return 1;
}
uint8_t
lwesp_sys_unprotect(void) {
lwesp_sys_mutex_unlock(&sys_mutex);
return 1;
}
uint8_t
lwesp_sys_mutex_create(lwesp_sys_mutex_t* p) {
const osMutexAttr_t attr = {
.attr_bits = osMutexRecursive
};
*p = osMutexNew(&attr);
return *p != NULL;
}
uint8_t
lwesp_sys_mutex_delete(lwesp_sys_mutex_t* p) {
return osMutexDelete(*p) == osOK;
}
uint8_t
lwesp_sys_mutex_lock(lwesp_sys_mutex_t* p) {
return osMutexAcquire(*p, osWaitForever) == osOK;
}
uint8_t
lwesp_sys_mutex_unlock(lwesp_sys_mutex_t* p) {
return osMutexRelease(*p) == osOK;
}
uint8_t
lwesp_sys_mutex_isvalid(lwesp_sys_mutex_t* p) {
return p != NULL && *p != NULL;
}
uint8_t
lwesp_sys_mutex_invalid(lwesp_sys_mutex_t* p) {
*p = LWESP_SYS_MUTEX_NULL;
return 1;
}
uint8_t
lwesp_sys_sem_create(lwesp_sys_sem_t* p, uint8_t cnt) {
return (*p = osSemaphoreNew(1, cnt > 0 ? 1 : 0, NULL)) != NULL;
}
uint8_t
lwesp_sys_sem_delete(lwesp_sys_sem_t* p) {
return osSemaphoreDelete(*p) == osOK;
}
uint32_t
lwesp_sys_sem_wait(lwesp_sys_sem_t* p, uint32_t timeout) {
uint32_t tick = osKernelSysTick();
return (osSemaphoreAcquire(*p, timeout == 0 ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : LWESP_SYS_TIMEOUT;
}
uint8_t
lwesp_sys_sem_release(lwesp_sys_sem_t* p) {
return osSemaphoreRelease(*p) == osOK;
}
uint8_t
lwesp_sys_sem_isvalid(lwesp_sys_sem_t* p) {
return p != NULL && *p != NULL;
}
uint8_t
lwesp_sys_sem_invalid(lwesp_sys_sem_t* p) {
*p = LWESP_SYS_SEM_NULL;
return 1;
}
uint8_t
lwesp_sys_mbox_create(lwesp_sys_mbox_t* b, size_t size) {
return (*b = osMessageQueueNew(size, sizeof(void*), NULL)) != NULL;
}
uint8_t
lwesp_sys_mbox_delete(lwesp_sys_mbox_t* b) {
if (osMessageQueueGetCount(*b) > 0) {
return 0;
}
return osMessageQueueDelete(*b) == osOK;
}
uint32_t
lwesp_sys_mbox_put(lwesp_sys_mbox_t* b, void* m) {
uint32_t tick = osKernelSysTick();
return osMessageQueuePut(*b, &m, 0, osWaitForever) == osOK ? (osKernelSysTick() - tick) : LWESP_SYS_TIMEOUT;
}
uint32_t
lwesp_sys_mbox_get(lwesp_sys_mbox_t* b, void** m, uint32_t timeout) {
uint32_t tick = osKernelSysTick();
return (osMessageQueueGet(*b, m, NULL, timeout == 0 ? osWaitForever : timeout) == osOK) ? (osKernelSysTick() - tick) : LWESP_SYS_TIMEOUT;
}
uint8_t
lwesp_sys_mbox_putnow(lwesp_sys_mbox_t* b, void* m) {
return osMessageQueuePut(*b, &m, 0, 0) == osOK;
}
uint8_t
lwesp_sys_mbox_getnow(lwesp_sys_mbox_t* b, void** m) {
return osMessageQueueGet(*b, m, NULL, 0) == osOK;
}
uint8_t
lwesp_sys_mbox_isvalid(lwesp_sys_mbox_t* b) {
return b != NULL && *b != NULL;
}
uint8_t
lwesp_sys_mbox_invalid(lwesp_sys_mbox_t* b) {
*b = LWESP_SYS_MBOX_NULL;
return 1;
}
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) {
lwesp_sys_thread_t id;
const osThreadAttr_t thread_attr = {
.name = (char*)name,
.priority = (osPriority)prio,
.stack_size = stack_size > 0 ? stack_size : LWESP_SYS_THREAD_SS
};
id = osThreadNew(thread_func, arg, &thread_attr);
if (t != NULL) {
*t = id;
}
return id != NULL;
}
uint8_t
lwesp_sys_thread_terminate(lwesp_sys_thread_t* t) {
if (t != NULL) {
osThreadTerminate(*t);
} else {
osThreadExit();
}
return 1;
}
uint8_t
lwesp_sys_thread_yield(void) {
osThreadYield();
return 1;
}
#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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] ip
: Pointer to variable to write IP address[out] gw
: Pointer to variable to write gateway address[out] nm
: Pointer to variable to write netmask address[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] ip
: Pointer to IP address[in] gw
: Pointer to gateway address. Set toNULL
to use default gateway[in] nm
: Pointer to netmask address. Set toNULL
to use default netmask[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] mac
: Pointer to output variable to save MAC address[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] mac
: Pointer to variable with MAC address. Memory of at least 6 bytes is required[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] ap_conf
: soft access point configuration[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] ssid
: SSID name of access point[in] pwd
: Password for network. Either set it toNULL
or less than64
characters[in] ch
: Wifi RF channel[in] ecn
: Encryption type. Valid options areOPEN
,WPA_PSK
,WPA2_PSK
andWPA_WPA2_PSK
[in] max_sta
: Maximal number of stations access point can accept. Valid between 1 and 10 stations[in] hid
: Set to1
to hide access point from public access[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] sta
: Pointer to array of lwesp_sta_t structure to fill with stations[in] stal
: Number of array entries of sta parameter[out] staf
: Number of stations connected to access point[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] mac
: Device MAC address to disconnect. Application may use lwesp_ap_list_sta to obtain list of connected stations to SoftAP.[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
bgn
¶ Information about 802.11[b|g|n] support
-
lwesp_ecn_t
-
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
-
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
-
lwespr_t
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.
- Return
1
on success,0
otherwise- Parameters
[in] buff
: Pointer to buffer structure[in] size
: Size of buffer in units of bytes
-
void
lwesp_buff_free
(lwesp_buff_t *buff)¶ Free dynamic allocation if used on memory.
- Parameters
[in] buff
: Pointer to buffer structure
-
void
lwesp_buff_reset
(lwesp_buff_t *buff)¶ Resets buffer to default values. Buffer size is not modified.
- Parameters
[in] buff
: 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.- Return
Number of bytes written to buffer. When returned value is less than
btw
, there was no enough memory available to copy full data array- Parameters
[in] buff
: Buffer handle[in] data
: Pointer to data to write into buffer[in] btw
: Number of bytes to write
-
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.- Return
Number of bytes read and copied to data array
- Parameters
[in] buff
: Buffer handle[out] data
: Pointer to output memory to copy buffer data to[in] btr
: Number of bytes to read
-
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)
- Return
Number of bytes peeked and written to output array
- Parameters
[in] buff
: Buffer handle[in] skip_count
: Number of bytes to skip before reading data[out] data
: Pointer to output memory to copy buffer data to[in] btp
: Number of bytes to peek
-
size_t
lwesp_buff_get_free
(lwesp_buff_t *buff)¶ Get number of bytes in buffer available to write.
- Return
Number of free bytes in memory
- Parameters
[in] buff
: Buffer handle
-
size_t
lwesp_buff_get_full
(lwesp_buff_t *buff)¶ Get number of bytes in buffer available to read.
- Return
Number of bytes ready to be read
- Parameters
[in] buff
: Buffer handle
-
void *
lwesp_buff_get_linear_block_read_address
(lwesp_buff_t *buff)¶ Get linear address for buffer for fast read.
- Return
Linear buffer start address
- Parameters
[in] buff
: Buffer handle
-
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.
- Return
Linear buffer size in units of bytes for read operation
- Parameters
[in] buff
: Buffer handle
-
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
- Return
Number of bytes skipped
- Parameters
[in] buff
: Buffer handle[in] len
: Number of bytes to skip and mark as read
-
void *
lwesp_buff_get_linear_block_write_address
(lwesp_buff_t *buff)¶ Get linear address for buffer for fast read.
- Return
Linear buffer start address
- Parameters
[in] buff
: Buffer handle
-
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.
- Return
Linear buffer size in units of bytes for write operation
- Parameters
[in] buff
: Buffer handle
-
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
- Return
Number of bytes advanced for write operation
- Parameters
[in] buff
: Buffer handle[in] len
: Number of bytes to advance
-
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 *
-
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #include "client.h"
#include "lwesp/lwesp.h"
/* Host parameter */
#define CONN_HOST "example.com"
#define CONN_PORT 80
static lwespr_t conn_callback_func(lwesp_evt_t* evt);
/**
* \brief Request data for connection
*/
static const
uint8_t req_data[] = ""
"GET / HTTP/1.1\r\n"
"Host: " CONN_HOST "\r\n"
"Connection: close\r\n"
"\r\n";
/**
* \brief Start a new connection(s) as client
*/
void
client_connect(void) {
lwespr_t res;
/* Start a new connection as client in non-blocking mode */
if ((res = lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, "example.com", 80, NULL, conn_callback_func, 0)) == lwespOK) {
printf("Connection to " CONN_HOST " started...\r\n");
} else {
printf("Cannot start connection to " CONN_HOST "!\r\n");
}
/* Start 2 more */
lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, CONN_PORT, NULL, conn_callback_func, 0);
/*
* An example of connection which should fail in connecting.
* When this is the case, \ref LWESP_EVT_CONN_ERROR event should be triggered
* in callback function processing
*/
lwesp_conn_start(NULL, LWESP_CONN_TYPE_TCP, CONN_HOST, 10, NULL, conn_callback_func, 0);
}
/**
* \brief Event callback function for connection-only
* \param[in] evt: Event information with data
* \return \ref lwespOK on success, member of \ref lwespr_t otherwise
*/
static lwespr_t
conn_callback_func(lwesp_evt_t* evt) {
lwesp_conn_p conn;
lwespr_t res;
uint8_t conn_num;
conn = lwesp_conn_get_from_evt(evt); /* Get connection handle from event */
if (conn == NULL) {
return lwespERR;
}
conn_num = lwesp_conn_getnum(conn); /* Get connection number for identification */
switch (lwesp_evt_get_type(evt)) {
case LWESP_EVT_CONN_ACTIVE: { /* Connection just active */
printf("Connection %d active!\r\n", (int)conn_num);
res = lwesp_conn_send(conn, req_data, sizeof(req_data) - 1, NULL, 0); /* Start sending data in non-blocking mode */
if (res == lwespOK) {
printf("Sending request data to server...\r\n");
} else {
printf("Cannot send request data to server. Closing connection manually...\r\n");
lwesp_conn_close(conn, 0); /* Close the connection */
}
break;
}
case LWESP_EVT_CONN_CLOSE: { /* Connection closed */
if (lwesp_evt_conn_close_is_forced(evt)) {
printf("Connection %d closed by client!\r\n", (int)conn_num);
} else {
printf("Connection %d closed by remote side!\r\n", (int)conn_num);
}
break;
}
case LWESP_EVT_CONN_SEND: { /* Data send event */
lwespr_t res = lwesp_evt_conn_send_get_result(evt);
if (res == lwespOK) {
printf("Data sent successfully on connection %d...waiting to receive data from remote side...\r\n", (int)conn_num);
} else {
printf("Error while sending data on connection %d!\r\n", (int)conn_num);
}
break;
}
case LWESP_EVT_CONN_RECV: { /* Data received from remote side */
lwesp_pbuf_p pbuf = lwesp_evt_conn_recv_get_buff(evt);
lwesp_conn_recved(conn, pbuf); /* Notify stack about received pbuf */
printf("Received %d bytes on connection %d..\r\n", (int)lwesp_pbuf_length(pbuf, 1), (int)conn_num);
break;
}
case LWESP_EVT_CONN_ERROR: { /* Error connecting to server */
const char* host = lwesp_evt_conn_error_get_host(evt);
lwesp_port_t port = lwesp_evt_conn_error_get_port(evt);
printf("Error connecting to %s:%d\r\n", host, (int)port);
break;
}
default:
break;
}
return lwespOK;
}
|
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | size_t rem_len;
lwesp_conn_p conn;
lwespr_t res;
/* ... other tasks to make sure connection is established */
/* We are connected to server at this point! */
/*
* Call write function to write data to memory
* and do not send immediately unless buffer is full after this write
*
* rem_len will give us response how much bytes
* is available in memory after write
*/
res = lwesp_conn_write(conn, "My string", 9, 0, &rem_len);
if (rem_len == 0) {
printf("No more memory available for next write!\r\n");
}
res = lwesp_conn_write(conn, "example.com", 11, 0, &rem_len);
/*
* Data will stay in buffer until buffer is full,
* except if user wants to force send,
* call write function with flush mode enabled
*
* It will send out together 20 bytes
*/
lwesp_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
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] conn
: Pointer to connection handle to set new connection reference in case of successfully connected[in] type
: Connection type. This parameter can be a value of lwesp_conn_type_t enumeration[in] remote_host
: Connection host. In case of IP, write it as string, ex. “192.168.1.1”[in] remote_port
: Connection port[in] arg
: Pointer to user argument passed to connection if successfully connected[in] conn_evt_fn
: Callback function for this connection[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] conn
: Pointer to connection handle to set new connection reference in case of successfully connected[in] start_struct
: Connection information are handled by one giant structure[in] arg
: Pointer to user argument passed to connection if successfully connected[in] conn_evt_fn
: Callback function for this connection[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] conn
: Connection handle to send data[in] data
: Data to send[in] btw
: Number of bytes to send[out] bw
: 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[in] blocking
: Status whether command should be blocking or not
-
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)
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] conn
: Connection handle to send data[in] ip
: Remote IP address for UDP connection[in] port
: Remote port connection[in] data
: Pointer to data to send[in] btw
: Number of bytes to send[out] bw
: Pointer to output variable to save number of sent data when successfully sent[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
User argument
- See
- Parameters
[in] conn
: Connection handle to get argument
-
uint8_t
lwesp_conn_is_client
(lwesp_conn_p conn)¶ Check if connection type is client.
- Return
1
on success,0
otherwise- Parameters
[in] conn
: Pointer to connection to check for status
-
uint8_t
lwesp_conn_is_server
(lwesp_conn_p conn)¶ Check if connection type is server.
- Return
1
on success,0
otherwise- Parameters
[in] conn
: Pointer to connection to check for status
-
uint8_t
lwesp_conn_is_active
(lwesp_conn_p conn)¶ Check if connection is active.
- Return
1
on success,0
otherwise- Parameters
[in] conn
: Pointer to connection to check for status
-
uint8_t
lwesp_conn_is_closed
(lwesp_conn_p conn)¶ Check if connection is closed.
- Return
1
on success,0
otherwise- Parameters
[in] conn
: Pointer to connection to check for status
-
int8_t
lwesp_conn_getnum
(lwesp_conn_p conn)¶ Get the number from connection.
- Return
Connection number in case of success or -1 on failure
- Parameters
[in] conn
: Connection pointer
-
lwespr_t
lwesp_conn_set_ssl_buffersize
(size_t size, const uint32_t blocking)¶ Set internal buffer size for SSL connection on ESP device.
-
lwesp_conn_p
lwesp_conn_get_from_evt
(lwesp_evt_t *evt)¶ Get connection from connection based event.
- Return
Connection pointer on success,
NULL
otherwise- Parameters
[in] evt
: Event which happened for connection
-
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)
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] conn
: Connection to write[in] data
: Data to copy to write buffer[in] btw
: Number of bytes to write[in] flush
: Flush flag. Set to1
if you want to send data immediately after copying[out] mem_available
: 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
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] conn
: Connection handle[in] pbuf
: Packet buffer received on connection
-
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.
- Return
Total number of received bytes on connection
- Parameters
[in] conn
: Connection handle
-
uint8_t
lwesp_conn_get_remote_ip
(lwesp_conn_p conn, lwesp_ip_t *ip)¶ Get connection remote IP address.
- Return
1
on success,0
otherwise- Parameters
[in] conn
: Connection handle[out] ip
: Pointer to IP output handle
-
lwesp_port_t
lwesp_conn_get_remote_port
(lwesp_conn_p conn)¶ Get connection remote port number.
- Return
Port number on success,
0
otherwise- Parameters
[in] conn
: Connection handle
-
lwesp_port_t
lwesp_conn_get_local_port
(lwesp_conn_p conn)¶ Get connection local port number.
- Return
Port number on success,
0
otherwise- Parameters
[in] conn
: Connection handle
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] link_id
: 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.[in] auth_mode
: Authentication mode0
: no authorization1
: load cert and private key for server authorization2
: load CA for client authorize server cert and private key3
: both authorization[in] pki_number
: The index of cert and private key, if only one cert and private key, the value should be0
.[in] ca_number
: The index of CA, if only one CA, the value should be 0.[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
-
typedef struct lwesp_conn *
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 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* Modifications of lwesp_opts.h file for configuration */
/* Enable global debug */
#define LWESP_CFG_DBG LWESP_DBG_ON
/*
* Enable debug types.
* Application may use bitwise OR | to use multiple types:
* LWESP_DBG_TYPE_TRACE | LWESP_DBG_TYPE_STATE
*/
#define LWESP_CFG_DBG_TYPES_ON LWESP_DBG_TYPE_TRACE
/* Enable debug on custom module */
#define MY_DBG_MODULE LWESP_DBG_ON
|
1 2 3 4 5 6 7 8 9 | #include "lwesp/lwesp_debug.h"
/*
* Print debug message to the screen
* Trace message will be printed as it is enabled in types
* while state message will not be printed.
*/
LWESP_DEBUGF(MY_DBG_MODULE | LWESP_DBG_TYPE_TRACE, "This is trace message on my program\r\n");
LWESP_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
[in] c
: Condition if debug of specific type is enabled[in] fmt
: 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
[in] c
: Condition if debug of specific type is enabled[in] cond
: Debug only if this condition is true[in] fmt
: Formatted string for debug[in] ...
: Variable parameters for formatted string
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] sta
: Set to1
to affect station DHCP configuration, set to0
to keep current setup[in] ap
: Set to1
to affect access point DHCP configuration, set to0
to keep current setup[in] en
: Set to1
to enable DHCP, or0
to disable (static IP)[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] host
: Pointer to host name to get IP for[out] ip
: Pointer to lwesp_ip_t variable to save IP[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] s1
: First server IP address in lwesp_ip_t format, set to 0.0.0.0 if not used[out] s2
: Second server IP address in lwesp_ip_t format, set to to 0.0.0.0 if not used. Addresss1
cannot be the same ass2
[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Set to1
to enable,0
to disable custom DNS configuration. When disabled, default DNS servers are used as proposed by ESP AT commands firmware[in] s1
: First server IP address in string format, set toNULL
if not used[in] s2
: Second server IP address in string format, set toNULL
if not used. Addresss1
cannot be the same ass2
[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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.
- Return
1
if forced by user,0
otherwise- Parameters
[in] cc
: Event handle
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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event data
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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event data
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.
- Return
MAC address
- Parameters
[in] cc
: Event handle
-
lwesp_ip_t *
lwesp_evt_ap_ip_sta_get_ip
(lwesp_evt_t *cc)¶ Get IP address from station.
- Return
IP address
- Parameters
[in] cc
: Event handle
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.
- Return
MAC address
- Parameters
[in] cc
: Event handle
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.
- Return
MAC address
- Parameters
[in] cc
: Event handle
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.
- Return
Buffer handle
- Parameters
[in] cc
: Event handle
-
lwesp_conn_p
lwesp_evt_conn_recv_get_conn
(lwesp_evt_t *cc)¶ Get connection handle for receive.
- Return
Connection handle
- Parameters
[in] cc
: Event 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.
- Return
Connection handle
- Parameters
[in] cc
: Event handle
-
size_t
lwesp_evt_conn_send_get_length
(lwesp_evt_t *cc)¶ Get number of bytes sent on connection.
- Return
Number of bytes sent
- Parameters
[in] cc
: Event handle
-
lwespr_t
lwesp_evt_conn_send_get_result
(lwesp_evt_t *cc)¶ Check if connection send was successful.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
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.
- Return
Connection handle
- Parameters
[in] cc
: Event handle
-
uint8_t
lwesp_evt_conn_active_is_client
(lwesp_evt_t *cc)¶ Check if new connection is client.
- Return
1
if client,0
otherwise- Parameters
[in] cc
: Event handle
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.
- Return
Connection handle
- Parameters
[in] cc
: Event handle
-
uint8_t
lwesp_evt_conn_close_is_client
(lwesp_evt_t *cc)¶ Check if just closed connection was client.
- Return
1
if client,0
otherwise- Parameters
[in] cc
: Event handle
-
uint8_t
lwesp_evt_conn_close_is_forced
(lwesp_evt_t *cc)¶ Check if connection close even was forced by user.
- Return
1
if forced,0
otherwise- Parameters
[in] cc
: Event handle
-
lwespr_t
lwesp_evt_conn_close_get_result
(lwesp_evt_t *cc)¶ Get connection close event result.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
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.
- Return
Connection handle
- Parameters
[in] cc
: Event 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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
lwesp_conn_type_t
lwesp_evt_conn_error_get_type
(lwesp_evt_t *cc)¶ Get connection type.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
const char *
lwesp_evt_conn_error_get_host
(lwesp_evt_t *cc)¶ Get connection host.
- Return
Host name for connection
- Parameters
[in] cc
: Event handle
-
lwesp_port_t
lwesp_evt_conn_error_get_port
(lwesp_evt_t *cc)¶ Get connection port.
- Return
Host port number
- Parameters
[in] cc
: Event handle
-
void *
lwesp_evt_conn_error_get_arg
(lwesp_evt_t *cc)¶ Get user argument.
- Return
User argument
- Parameters
[in] cc
: Event handle
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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
lwesp_ap_t *
lwesp_evt_sta_list_ap_get_aps
(lwesp_evt_t *cc)¶ Get access points.
- Return
Pointer to lwesp_ap_t with first access point description
- Parameters
[in] cc
: Event handle
-
size_t
lwesp_evt_sta_list_ap_get_length
(lwesp_evt_t *cc)¶ Get number of access points found.
- Return
Number of access points found
- Parameters
[in] cc
: Event handle
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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
const char *
lwesp_evt_sta_info_ap_get_ssid
(lwesp_evt_t *cc)¶ Get current AP name.
- Return
AP name
- Parameters
[in] cc
: Event handle
-
lwesp_mac_t
lwesp_evt_sta_info_ap_get_mac
(lwesp_evt_t *cc)¶ Get current AP MAC address.
- Return
AP MAC address
- Parameters
[in] cc
: Event handle
-
uint8_t
lwesp_evt_sta_info_ap_get_channel
(lwesp_evt_t *cc)¶ Get current AP channel.
- Return
AP channel
- Parameters
[in] cc
: Event handle
-
int16_t
lwesp_evt_sta_info_ap_get_rssi
(lwesp_evt_t *cc)¶ Get current AP rssi.
- Return
AP rssi
- Parameters
[in] cc
: Event handle
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.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
const char *
lwesp_evt_dns_hostbyname_get_host
(lwesp_evt_t *cc)¶ Get hostname used to resolve IP address.
- Return
Hostname
- Parameters
[in] cc
: Event handle
-
lwesp_ip_t *
lwesp_evt_dns_hostbyname_get_ip
(lwesp_evt_t *cc)¶ Get IP address from DNS function.
- Return
IP address
- Parameters
[in] cc
: Event handle
Ping
Event helper functions for LWESP_EVT_PING event
-
lwespr_t
lwesp_evt_ping_get_result
(lwesp_evt_t *cc)¶ Get ping status.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
const char *
lwesp_evt_ping_get_host
(lwesp_evt_t *cc)¶ Get hostname used to ping.
- Return
Hostname
- Parameters
[in] cc
: Event handle
-
uint32_t
lwesp_evt_ping_get_time
(lwesp_evt_t *cc)¶ Get time required for ping.
- Return
Ping time
- Parameters
[in] cc
: Event handle
Server
Event helper functions for LWESP_EVT_SERVER event
-
lwespr_t
lwesp_evt_server_get_result
(lwesp_evt_t *cc)¶ Get server command result.
- Return
Member of lwespr_t enumeration
- Parameters
[in] cc
: Event handle
-
lwesp_port_t
lwesp_evt_server_get_port
(lwesp_evt_t *cc)¶ Get port for server operation.
- Return
Server port
- Parameters
[in] cc
: Event handle
-
uint8_t
lwesp_evt_server_is_enable
(lwesp_evt_t *cc)¶ Check if operation was to enable or disable server.
- Return
1
if enable,0
otherwise- Parameters
[in] cc
: Event handle
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_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
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] fn
: Callback function to remove from event list
-
lwesp_evt_type_t
lwesp_evt_get_type
(lwesp_evt_t *cc)¶ Get event type.
- Return
Event type. Member of lwesp_evt_type_t enumeration
- Parameters
[in] cc
: Event handle
-
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
-
union lwesp_evt_t::[anonymous]
evt
¶ Callback event union
-
lwesp_evt_type_t
-
uint8_t
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] hostname
: Name of ESP host[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] hostname
: Pointer to output variable holding memory to save hostname[in] size
: Size of buffer for hostname. Size includes memory forNULL
termination[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] data
: Pointer to data to write[in] len
: Number of data elements in units of bytes
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] data
: Pointer to received data to be processed[in] len
: Length of data to process in units of bytes
-
lwespr_t
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Status to enable1
or disable0
mDNS function[in] host
: mDNS host name[in] server
: mDNS server name[in] port
: mDNS server port number[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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
- Return
1
on success,0
otherwise- Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
- Parameters
[in] regions
: Pointer to list of regions to use for allocations[in] len
: Number of regions to use
-
void *
lwesp_mem_malloc
(size_t size)¶ Allocate memory of specific size.
- Return
Memory address on success,
NULL
otherwise- Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
[in] size
: Number of bytes to allocate
-
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
- Return
Memory address on success,
NULL
otherwise- Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
[in] ptr
: Pointer to current allocated memory to resize, returned using lwesp_mem_malloc, lwesp_mem_calloc or lwesp_mem_realloc functions[in] size
: Number of bytes to allocate on new memory
-
void *
lwesp_mem_calloc
(size_t num, size_t size)¶ Allocate memory of specific size and set memory to zero.
- Return
Memory address on success,
NULL
otherwise- Note
Function is not available when LWESP_CFG_MEM_CUSTOM is
1
and must be implemented by user- Parameters
[in] num
: Number of elements to allocate[in] size
: Size of each element
-
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
[in] ptr
: 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.
- Return
1
on success,0
otherwise- Parameters
[in] ptr
: Pointer to pointer to allocated memory to free
-
struct
lwesp_mem_region_t
¶ - #include <lwesp_mem.h>
Single memory region descriptor.
-
uint8_t
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | lwesp_pbuf_p a, b;
/* Create 2 pbufs of different sizes */
a = lwesp_pbuf_new(10);
b = lwesp_pbuf_new(20);
/* Link them together with concat operation */
/* Reference on b will stay as is, won't be increased */
lwesp_pbuf_cat(a, b);
/*
* Operating with b variable has from now on undefined behavior,
* application shall stop using variable b to access pbuf.
*
* The best way would be to set b reference to NULL
*/
b = NULL;
/*
* When application doesn't need pbufs anymore,
* free a and it will also free b
*/
lwesp_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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | lwesp_pbuf_p a, b;
/* Create 2 pbufs of different sizes */
a = lwesp_pbuf_new(10);
b = lwesp_pbuf_new(20);
/* Chain both pbufs together */
/* This will increase reference on b as 2 variables now point to it */
lwesp_pbuf_chain(a, b);
/*
* When application does not need a anymore, it may free it
* This will free only pbuf a, as pbuf b has now 2 references:
* - one from pbuf a
* - one from variable b
*/
/* If application calls this, it will free only first pbuf */
/* As there is link to b pbuf somewhere */
lwesp_pbuf_free(a);
/* Reset a variable, not used anymore */
a = NULL;
/*
* At this point, b is still valid memory block,
* but when application doesn't need it anymore,
* it should free it, otherwise memory leak appears
*/
lwesp_pbuf_free(b);
/* Reset b variable */
b = 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | const void* data;
size_t pos, len;
lwesp_pbuf_p a, b, c;
const char str_a[] = "This is one long";
const char str_a[] = "string. We want to save";
const char str_a[] = "chain of pbufs to file";
/* Create pbufs to hold these strings */
a = lwesp_pbuf_new(strlen(str_a));
b = lwesp_pbuf_new(strlen(str_b));
c = lwesp_pbuf_new(strlen(str_c));
/* Write data to pbufs */
lwesp_pbuf_take(a, str_a, strlen(str_a), 0);
lwesp_pbuf_take(b, str_b, strlen(str_b), 0);
lwesp_pbuf_take(c, str_c, strlen(str_c), 0);
/* Connect pbufs together */
lwesp_pbuf_chain(a, b);
lwesp_pbuf_chain(a, c);
/*
* pbuf a now contains chain of b and c together
* and at this point application wants to print (or save) data from chained pbuf
*
* Process pbuf by pbuf with code below
*/
/*
* Get linear address of current pbuf at specific offset
* Function will return pointer to memory address at specific position
* and `len` will hold length of data block
*/
pos = 0;
while ((data = lwesp_pbuf_get_linear_addr(a, pos, &len)) != NULL) {
/* Custom process function... */
/* Process data with data pointer and block length */
process_data(data, len);
printf("Str: %.*s", len, data);
/* Increase offset position for next block */
pos += len;
}
/* Call free only on a pbuf. Since it is chained, b and c will be freed too */
lwesp_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.
- Return
Pointer to allocated memory,
NULL
otherwise- Parameters
[in] len
: Length of payload memory to allocate
-
size_t
lwesp_pbuf_free
(lwesp_pbuf_p pbuf)¶ Free previously allocated packet buffer.
- Return
Number of freed pbufs from head
- Parameters
[in] pbuf
: Packet buffer to free
-
void *
lwesp_pbuf_data
(const lwesp_pbuf_p pbuf)¶ Get data pointer from packet buffer.
- Return
Pointer to data buffer on success,
NULL
otherwise- Parameters
[in] pbuf
: Packet buffer
-
size_t
lwesp_pbuf_length
(const lwesp_pbuf_p pbuf, uint8_t tot)¶ Get length of packet buffer.
- Return
Length of data in units of bytes
- Parameters
[in] pbuf
: Packet buffer to get length for[in] tot
: Set to1
to return total packet chain length or0
to get only first packet length
-
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- Return
1
on success,0
otherwise- Parameters
[in] pbuf
: Pbuf to make it smaller[in] new_len
: New length in units of bytes
-
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.
- Return
Number of bytes copied
- Parameters
[in] pbuf
: Pbuf to copy from[out] data
: User linear memory to copy to[in] len
: Length of data in units of bytes[in] offset
: Possible start offset in pbuf
-
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.- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- See
- Parameters
[in] head
: Head packet buffer to append new pbuf to[in] tail
: Tail packet buffer to append to head 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)
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- See
- Parameters
[in] head
: Head packet buffer to append new pbuf to[in] tail
: Tail packet buffer to append to head pbuf
-
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
)- Return
Next pbuf after
head
- Parameters
[in] head
: First pbuf in chain to remove from chain
-
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.
- Return
1
on success,0
otherwise- Parameters
[in] pbuf
: Pbuf used to get data from[in] pos
: Position at which to get element[out] el
: Output variable to save element value at desired position
-
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
- Return
0
if equal,LWESP_SIZET_MAX
if memory/offset too big or anything between if not equal- See
- Parameters
[in] pbuf
: Pbuf used to compare with data memory[in] data
: Actual data to compare with[in] len
: Length of input data in units of bytes[in] offset
: Start offset to use when comparing data
-
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
- Return
0
if equal,LWESP_SIZET_MAX
if memory/offset too big or anything between if not equal- See
- Parameters
[in] pbuf
: Pbuf used to compare with data memory[in] str
: String to be compared with pbuf[in] offset
: Start memory offset in pbuf
-
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.
- Return
LWESP_SIZET_MAX
if no match or position where in pbuf we have a match- See
- Parameters
[in] pbuf
: Pbuf used as haystack[in] needle
: Data memory used as needle[in] len
: Length of needle memory[in] off
: Starting offset in pbuf memory
-
size_t
lwesp_pbuf_strfind
(const lwesp_pbuf_p pbuf, const char *str, size_t off)¶ Find desired needle (str) in a haystack (pbuf)
- Return
LWESP_SIZET_MAX
if no match or position where in pbuf we have a match- See
- Parameters
[in] pbuf
: Pbuf used as haystack[in] str
: String to search for in pbuf[in] off
: Starting offset in pbuf memory
-
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
- Return
1
on success,0
otherwise- Parameters
[in] pbuf
: Pbuf to advance[in] len
: Number of bytes to advance. when negative is used, buffer size is increased only if it was decreased before
-
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
- Return
New pbuf on success,
NULL
otherwise- Parameters
[in] pbuf
: Start of pbuf chain[in] offset
: Offset in units of bytes to skip[out] new_offset
: Pointer to output variable to save new offset in returned pbuf
-
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
- Return
Pointer to memory on success,
NULL
otherwise- Parameters
[in] pbuf
: Pbuf to get linear address[in] offset
: Start offset from where to start[out] new_len
: Length of memory returned by function
-
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
[in] pbuf
: Packet buffer[in] ip
: IP to assing to packet buffer[in] port
: Port number to assign to packet buffer
-
void
lwesp_pbuf_dump
(lwesp_pbuf_p p, uint8_t seq)¶ Dump and debug pbuf chain.
- Parameters
[in] p
: Head pbuf to dump[in] seq
: Set to1
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 *
-
typedef struct lwesp_pbuf *
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] host
: Host name to ping[out] time
: Pointer to output variable to save ping time in units of milliseconds[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Set to1
to start SMART or0
to stop SMART[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include "sntp.h"
#include "lwesp/lwesp.h"
/**
* \brief Run SNTP
*/
void
sntp_gettime(void) {
lwesp_datetime_t dt;
/* Enable SNTP with default configuration for NTP servers */
if (lwesp_sntp_set_config(1, 1, NULL, NULL, NULL, NULL, NULL, 1) == lwespOK) {
lwesp_delay(5000);
/* Get actual time and print it */
if (lwesp_sntp_gettime(&dt, NULL, NULL, 1) == lwespOK) {
printf("Date & time: %d.%d.%d, %d:%d:%d\r\n",
(int)dt.date, (int)dt.month, (int)dt.year,
(int)dt.hours, (int)dt.minutes, (int)dt.seconds);
}
}
}
|
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Status whether SNTP mode is enabled or disabled on ESP device[in] tz
: Timezone to use when SNTP acquires time, between-11
and13
[in] h1
: Optional first SNTP server for time. Set toNULL
if not used[in] h2
: Optional second SNTP server for time. Set toNULL
if not used[in] h3
: Optional third SNTP server for time. Set toNULL
if not used[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] dt
: Pointer to lwesp_datetime_t structure to fill with date and time values[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #include "station_manager.h"
#include "lwesp/lwesp.h"
/*
* List of preferred access points for ESP device
* SSID and password
*
* ESP will try to scan for access points
* and then compare them with the one on the list below
*/
ap_entry_t
ap_list[] = {
//{ "SSID name", "SSID password" },
{ "TilenM_ST", "its private" },
{ "Majerle WIFI", "majerle_internet_private" },
{ "Majerle AMIS", "majerle_internet_private" },
};
/**
* \brief List of access points found by ESP device
*/
static
lwesp_ap_t aps[100];
/**
* \brief Number of valid access points in \ref aps array
*/
static
size_t apf;
/**
* \brief Connect to preferred access point
*
* \note List of access points should be set by user in \ref ap_list structure
* \param[in] unlimited: When set to 1, function will block until SSID is found and connected
* \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
*/
lwespr_t
connect_to_preferred_access_point(uint8_t unlimited) {
lwespr_t eres;
uint8_t tried;
/*
* Scan for network access points
* In case we have access point,
* try to connect to known AP
*/
do {
if (lwesp_sta_has_ip()) {
return lwespOK;
}
/* Scan for access points visible to ESP device */
printf("Scanning access points...\r\n");
if ((eres = lwesp_sta_list_ap(NULL, aps, LWESP_ARRAYSIZE(aps), &apf, NULL, NULL, 1)) == lwespOK) {
tried = 0;
/* Print all access points found by ESP */
for (size_t i = 0; i < apf; i++) {
printf("AP found: %s, CH: %d, RSSI: %d\r\n", aps[i].ssid, aps[i].ch, aps[i].rssi);
}
/* Process array of preferred access points with array of found points */
for (size_t j = 0; j < LWESP_ARRAYSIZE(ap_list); j++) {
for (size_t i = 0; i < apf; i++) {
if (!strcmp(aps[i].ssid, ap_list[j].ssid)) {
tried = 1;
printf("Connecting to \"%s\" network...\r\n", ap_list[j].ssid);
/* Try to join to access point */
if ((eres = lwesp_sta_join(ap_list[j].ssid, ap_list[j].pass, NULL, NULL, NULL, 1)) == lwespOK) {
lwesp_ip_t ip;
uint8_t is_dhcp;
lwesp_sta_copy_ip(&ip, NULL, NULL, &is_dhcp);
printf("Connected to %s network!\r\n", ap_list[j].ssid);
printf("Station IP address: %d.%d.%d.%d; Is DHCP: %d\r\n",
(int)ip.ip[0], (int)ip.ip[1], (int)ip.ip[2], (int)ip.ip[3], (int)is_dhcp);
return lwespOK;
} else {
printf("Connection error: %d\r\n", (int)eres);
}
}
}
}
if (!tried) {
printf("No access points available with preferred SSID!\r\nPlease check station_manager.c file and edit preferred SSID access points!\r\n");
}
} else if (eres == lwespERRNODEVICE) {
printf("Device is not present!\r\n");
break;
} else {
printf("Error on WIFI scan procedure!\r\n");
}
if (!unlimited) {
break;
}
} while (1);
return lwespERR;
}
|
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] name
: SSID of access point to connect to[in] pass
: Password of access point. UseNULL
if AP does not have password[in] mac
: Pointer to MAC address of AP. If multiple APs with same name exist, MAC may help to select proper one. Set toNULL
if not needed[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Set to1
to enable or0
to disable[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] interval
: Interval in units of seconds. Valid numbers are1-7200
or0
to disable reconnect feature[in] rep_cnt
: Repeat counter. Number of maximum tries for reconnect. Valid entries are1-1000
or0
to always try. This parameter is only valid if interval is not0
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] ip
: Pointer to variable to save IP address[out] gw
: Pointer to output variable to save gateway address[out] nm
: Pointer to output variable to save netmask address[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] ip
: Pointer to IP address[in] gw
: Pointer to gateway address. Set toNULL
to use default gateway[in] nm
: Pointer to netmask address. Set toNULL
to use default netmask[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] mac
: Pointer to output variable to save MAC address[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] mac
: Pointer to variable with MAC address[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
uint8_t
lwesp_sta_has_ip
(void)¶ Check if ESP got IP from access point.
- Return
1
on success,0
otherwise
-
uint8_t
lwesp_sta_is_joined
(void)¶ Check if station is connected to WiFi network.
- Return
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[out] ip
: Pointer to output IP variable. Set toNULL
if not interested in IP address[out] gw
: Pointer to output gateway variable. Set toNULL
if not interested in gateway address[out] nm
: Pointer to output netmask variable. Set toNULL
if not interested in netmask address[out] is_dhcp
: Pointer to output DHCP status variable. Set toNULL
if not interested
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] ssid
: Optional SSID name to search for. Set toNULL
to disable filter[in] aps
: Pointer to array of available access point parameters[in] apsl
: Length of aps array[out] apf
: Pointer to output variable to save number of access points found[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] info
: Pointer to connected access point information[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
uint8_t
lwesp_sta_is_ap_802_11b
(lwesp_ap_t *ap)¶ Check if access point is
802.11b
compatible.- Return
1
on success,0
otherwise- Parameters
[in] ap
: Access point detailes acquired by lwesp_sta_list_ap
-
uint8_t
lwesp_sta_is_ap_802_11g
(lwesp_ap_t *ap)¶ Check if access point is
802.11g
compatible.- Return
1
on success,0
otherwise- Parameters
[in] ap
: Access point detailes acquired by lwesp_sta_list_ap
-
uint8_t
lwesp_sta_is_ap_802_11n
(lwesp_ap_t *ap)¶ Check if access point is
802.11n
compatible.- Return
1
on success,0
otherwise- Parameters
[in] ap
: Access point detailes acquired by lwesp_sta_list_ap
-
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
-
lwespr_t
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.
- Parameters
[in] arg
: 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 (*
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_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
-
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_BLEINIT_GET
¶ Get BLE status
-
enumerator
-
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
¶
-
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
-
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_UNKNOWN
¶ Unknown device
-
enumerator
-
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
ESP is currently not able to connect to access point of this encryption type
-
enumerator
-
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
-
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
-
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
-
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 *
-
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
-
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
-
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
-
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
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_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
num
¶ Connection number used for start
-
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
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
-
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 ESP has IP
-
uint8_t
is_connected
¶ Flag indicating ESP is connected to wifi
-
lwesp_ip_t
-
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
-
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 *
-
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
-
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
-
struct
lwesp_unicode_t
¶ - #include <lwesp_private.h>
Unicode support structure.
-
struct
lwesp_ip_t
¶ - #include <lwesp_typedefs.h>
IP structure.
Public Members
-
uint8_t
ip
[4]¶ IPv4 address
-
uint8_t
-
struct
lwesp_mac_t
¶ - #include <lwesp_typedefs.h>
MAC address.
Public Members
-
uint8_t
mac
[6]¶ MAC address
-
uint8_t
-
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
-
struct
lwesp_linbuff_t
¶ - #include <lwesp_typedefs.h>
Linear buffer structure.
-
typedef uint16_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.
- Return
lwespOK Function succedded, there is a valid UTF-8 sequence
- Return
lwespINPROG Function continues well but expects some more data to finish sequence
- Return
lwespERR Error in UTF-8 sequence
- Parameters
[inout] s
: Pointer to unicode decode control structure[in] c
: UTF-8 character sequence to test for device
-
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
-
lwespr_t
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
[in] msg
: message to print to debug if test fails[in] c
: Condition to test
-
LWESP_MEM_ALIGN
(x)¶ Align
x
value to specific number of bytes, provided by LWESP_CFG_MEM_ALIGNMENT configuration.- Return
Input value aligned to specific number of bytes
- Parameters
[in] x
: Input value to align
-
LWESP_MIN
(x, y)¶ Get minimal value between
x
andy
inputs.- Return
Minimal value between
x
andy
parameters- Parameters
[in] x
: First input to test[in] y
: Second input to test
-
LWESP_MAX
(x, y)¶ Get maximal value between
x
andy
inputs.- Return
Maximal value between
x
andy
parameters- Parameters
[in] x
: First input to test[in] y
: Second input to test
-
LWESP_ARRAYSIZE
(x)¶ Get size of statically declared array.
- Return
Number of array elements
- Parameters
[in] x
: Input array
-
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
[in] x
: Variable which is not used
-
LWESP_U32
(x)¶ Get input value casted to
unsigned 32-bit
value.- Parameters
[in] x
: Input value
-
LWESP_U16
(x)¶ Get input value casted to
unsigned 16-bit
value.- Parameters
[in] x
: Input value
-
LWESP_U8
(x)¶ Get input value casted to
unsigned 8-bit
value.- Parameters
[in] x
: Input value
-
LWESP_I32
(x)¶ Get input value casted to
signed 32-bit
value.- Parameters
[in] x
: Input value
-
LWESP_I16
(x)¶ Get input value casted to
signed 16-bit
value.- Parameters
[in] x
: Input value
-
LWESP_I8
(x)¶ Get input value casted to
signed 8-bit
value.- Parameters
[in] x
: Input value
-
LWESP_SZ
(x)¶ Get input value casted to
size_t
value.- Parameters
[in] x
: Input value
-
lwesp_u32_to_str
(num, out)¶ Convert
unsigned 32-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
-
lwesp_u32_to_hex_str
(num, out, w)¶ Convert
unsigned 32-bit
number to HEX string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string[in] w
: Width of output string. When number is shorter than width, leading0
characters will apply
-
lwesp_i32_to_str
(num, out)¶ Convert
signed 32-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
-
lwesp_u16_to_str
(num, out)¶ Convert
unsigned 16-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
-
lwesp_u16_to_hex_str
(num, out, w)¶ Convert
unsigned 16-bit
number to HEX string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string[in] w
: Width of output string. When number is shorter than width, leading0
characters will apply.
-
lwesp_i16_to_str
(num, out)¶ Convert
signed 16-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
-
lwesp_u8_to_str
(num, out)¶ Convert
unsigned 8-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
-
lwesp_u8_to_hex_str
(num, out, w)¶ Convert
unsigned 16-bit
number to HEX string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string[in] w
: Width of output string. When number is shorter than width, leading0
characters will apply.
-
lwesp_i8_to_str
(num, out)¶ Convert
signed 8-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
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.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string[in] is_hex
: Set to1
to output hex, 0 otherwise[in] width
: Width of output string. When number is shorter than width, leading0
characters will apply. This parameter is valid only when formatting hex numbers
-
char *
lwesp_i32_to_gen_str
(int32_t num, char *out)¶ Convert
signed 32-bit
number to string.- Return
Pointer to output variable
- Parameters
[in] num
: Number to convert[out] out
: Output variable to save string
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Set to1
to enable WPS or0
to disable WPS[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
lwespr_t
-
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
[in] v
: Version output, pointer to lwesp_sw_version_t structure[in] major_
: Major version[in] minor_
: Minor version[in] patch_
: Patch version
-
lwesp_get_min_at_fw_version
(v)¶ Get minimal AT version supported by library.
- Parameters
[out] v
: 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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] evt_func
: Global event callback function for all major events[in] blocking
: Status whether command should be blocking or not. Used when LWESP_CFG_RESET_ON_INIT or LWESP_CFG_RESTORE_ON_INIT are enabled.
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] delay
: Number of milliseconds to wait before initiating first command to device[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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)
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] baud
: Baudrate in units of bits per second[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] mode
: Mode of operation. This parameter can be a value of lwesp_mode_t enumeration[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] mode
: point to space of Mode to get. This parameter can be a pointer of lwesp_mode_t enumeration[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] en
: Set to1
to enable server,0
otherwise[in] port
: Port number used to listen on. Must also be used when disabling server mode[in] max_conn
: Number of maximal connections populated by server[in] timeout
: Time used to automatically close the connection in units of seconds. Set to0
to disable timeout feature (not recommended)[in] server_evt_fn
: Connection callback function for new connections started as server[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
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 increased- Note
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
-
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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] present
: Flag indicating device is present[in] evt_fn
: Callback function called when command has finished. Set toNULL
when not used[in] evt_arg
: Custom argument for event callback function[in] blocking
: Status whether command should be blocking or not
-
uint8_t
lwesp_device_is_present
(void)¶ Check if device is present.
- Return
1
on success,0
otherwise
-
uint8_t
lwesp_device_is_esp8266
(void)¶ Check if modem device is ESP8266.
- Return
1
on success,0
otherwise
-
uint8_t
lwesp_device_is_esp32
(void)¶ Check if modem device is ESP32.
- Return
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- Return
1
on success,0
otherwise- Parameters
[in] ms
: Milliseconds to delay
-
uint8_t
lwesp_get_current_at_fw_version
(lwesp_sw_version_t *const version)¶ Get current AT firmware version of connected device.
- Return
1
on success,0
otherwise- Parameters
[out] version
: Output version variable
-
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_OS
¶ Enables
1
or disables0
operating system support for ESP library.- Note
Value must be set to
1
in the current revision- Note
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_free- Note
Function declaration follows standard C functions
malloc, calloc, realloc, free
. Declaration is available inlwesp/lwesp_mem.h
file. Include this file to final implementation file- Note
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_CONNS
¶ Maximal number of connections AT software can support on ESP device.
- Note
In case of official AT software, leave this on default value (
5
)
-
LWESP_CFG_CONN_MAX_DATA_LEN
¶ Maximal number of bytes we can send at single command to ESP.
When manual TCP read mode is enabled, this parameter defines number of bytes to be read at a time
- Note
Value can not exceed
2048
bytes or no data will be send at all (ESP8266 AT SW limitation)
- Note
This is limitation of ESP AT commands and on systems where RAM is not an issue, it should be set to maximal value (
2048
) to optimize data transfer speed performance
-
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_CONN_MAX_RECV_BUFF_SIZE
¶ Maximum single buffer size for network receive data on active connection.
- Note
When ESP sends buffer bigger than maximal, multiple buffers are created
-
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_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_MIN_AT_VERSION_MAJOR_ESP8266
¶ Minimal major version for ESP8266
-
LWESP_MIN_AT_VERSION_MINOR_ESP8266
¶ Minimal minor version for ESP8266
-
LWESP_MIN_AT_VERSION_PATCH_ESP8266
¶ Minimal patch version for ESP8266
-
LWESP_MIN_AT_VERSION_MAJOR_ESP32
¶ Minimal major version for ESP32
-
LWESP_MIN_AT_VERSION_MINOR_ESP32
¶ Minimal minor version for ESP32
-
LWESP_MIN_AT_VERSION_PATCH_ESP32
¶ Minimal patch version for ESP32
-
-
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
-
-
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.
-
-
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);
- Return
Destination memory start address
- Parameters
[in] dst
: Destination memory start address[in] src
: Source memory start address[in] len
: Number of bytes to copy
-
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);
- Return
Destination memory start address
- Parameters
[in] dst
: Destination memory start address[in] b
: Value (byte) to set in memory[in] len
: Number of bytes to set
-
-
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.
-
-
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.- Note
To use this feature, OS support is mandatory.
- See
-
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
-
-
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
-
-
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
-
-
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.
-
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.
- Return
Number of bytes sent
- Parameters
[in] data
: Pointer to data to send. This parameter can be set toNULL
[in] len
: Number of bytes to send. This parameter can be set to0
to indicate that internal buffer can be flushed to stream. This is implementation defined and feature might be ignored
-
typedef uint8_t (*
lwesp_ll_reset_fn
)(uint8_t state)¶ Function prototype for hardware reset of ESP device.
- Return
1
on successful action,0
otherwise- Parameters
[in] state
: State indicating reset. When set to1
, reset must be active (usually pin active low), or set to0
when reset is cleared
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.- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[inout] ll
: Pointer to lwesp_ll_t structure to fill data for communication functions
-
lwespr_t
lwesp_ll_deinit
(lwesp_ll_t *ll)¶ Callback function to de-init low-level communication part.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[inout] ll
: Pointer to lwesp_ll_t structure to fill data for communication functions
-
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
-
typedef size_t (*
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.
- Return
1
on success,0
otherwise
-
uint32_t
lwesp_sys_now
(void)¶ Get current time in units of milliseconds.
- Return
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.
- Return
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.
- Return
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
- Return
1
on success,0
otherwise- Parameters
[out] p
: Pointer to mutex structure to allocate
-
uint8_t
lwesp_sys_mutex_delete
(lwesp_sys_mutex_t *p)¶ Delete recursive mutex from system.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to mutex structure
-
uint8_t
lwesp_sys_mutex_lock
(lwesp_sys_mutex_t *p)¶ Lock recursive mutex, wait forever to lock.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to mutex structure
-
uint8_t
lwesp_sys_mutex_unlock
(lwesp_sys_mutex_t *p)¶ Unlock recursive mutex.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to mutex structure
-
uint8_t
lwesp_sys_mutex_isvalid
(lwesp_sys_mutex_t *p)¶ Check if mutex structure is valid system.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to mutex structure
-
uint8_t
lwesp_sys_mutex_invalid
(lwesp_sys_mutex_t *p)¶ Set recursive mutex structure as invalid.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to mutex structure
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- Return
1
on success,0
otherwise- Parameters
[out] p
: Pointer to semaphore structure to fill with result[in] cnt
: Count indicating default semaphore state:0
: Take semaphore token immediately1
: Keep token available
-
uint8_t
lwesp_sys_sem_delete
(lwesp_sys_sem_t *p)¶ Delete binary semaphore.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to semaphore structure
-
uint32_t
lwesp_sys_sem_wait
(lwesp_sys_sem_t *p, uint32_t timeout)¶ Wait for semaphore to be available.
- Return
Number of milliseconds waited for semaphore to become available or LWESP_SYS_TIMEOUT if not available within given time
- Parameters
[in] p
: Pointer to semaphore structure[in] timeout
: Timeout to wait in milliseconds. When0
is applied, wait forever
-
uint8_t
lwesp_sys_sem_release
(lwesp_sys_sem_t *p)¶ Release semaphore.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to semaphore structure
-
uint8_t
lwesp_sys_sem_isvalid
(lwesp_sys_sem_t *p)¶ Check if semaphore is valid.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to semaphore structure
-
uint8_t
lwesp_sys_sem_invalid
(lwesp_sys_sem_t *p)¶ Invalid semaphore.
- Return
1
on success,0
otherwise- Parameters
[in] p
: Pointer to semaphore structure
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 *
- Return
1
on success,0
otherwise- Parameters
[out] b
: Pointer to message queue structure[in] size
: Number of entries for message queue to hold
-
uint8_t
lwesp_sys_mbox_delete
(lwesp_sys_mbox_t *b)¶ Delete message queue.
- Return
1
on success,0
otherwise- Parameters
[in] b
: Pointer to message queue structure
-
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.
- Return
Time in units of milliseconds needed to put a message to queue
- Parameters
[in] b
: Pointer to message queue structure[in] m
: Pointer to entry to insert to message 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.
- Return
Time in units of milliseconds needed to put a message to queue or LWESP_SYS_TIMEOUT if it was not successful
- Parameters
[in] b
: Pointer to message queue structure[in] m
: Pointer to pointer to result to save value from message queue to[in] timeout
: Maximal timeout to wait for new message. When0
is applied, wait for unlimited time
-
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)
- Return
1
on success,0
otherwise- Parameters
[in] b
: Pointer to message queue structure[in] m
: Pointer to message to save to queue
-
uint8_t
lwesp_sys_mbox_getnow
(lwesp_sys_mbox_t *b, void **m)¶ Get an entry from message queue immediately.
- Return
1
on success,0
otherwise- Parameters
[in] b
: Pointer to message queue structure[in] m
: Pointer to pointer to result to save value from message queue to
-
uint8_t
lwesp_sys_mbox_isvalid
(lwesp_sys_mbox_t *b)¶ Check if message queue is valid.
- Return
1
on success,0
otherwise- Parameters
[in] b
: Pointer to message queue structure
-
uint8_t
lwesp_sys_mbox_invalid
(lwesp_sys_mbox_t *b)¶ Invalid message queue.
- Return
1
on success,0
otherwise- Parameters
[in] b
: Pointer to message queue structure
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.
- Return
1
on success,0
otherwise- Parameters
[out] t
: Pointer to thread identifier if create was successful. It may be set toNULL
[in] name
: Name of a new thread[in] thread_func
: Thread function to use as thread body[in] arg
: Thread function argument[in] stack_size
: Size of thread stack in uints of bytes. If set to 0, reserve default stack size[in] prio
: Thread priority
-
uint8_t
lwesp_sys_thread_terminate
(lwesp_sys_thread_t *t)¶ Terminate thread (shut it down and remove)
- Return
1
on success,0
otherwise- Parameters
[in] t
: Pointer to thread handle to terminate. If set toNULL
, terminate current thread (thread from where function is called)
-
uint8_t
lwesp_sys_thread_yield
(void)¶ Yield current thread.
- Return
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 prioer 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 osMutexId_t
lwesp_sys_mutex_t
¶ System mutex type.
It is used by middleware as base type of mutex.
-
typedef osSemaphoreId_t
lwesp_sys_sem_t
¶ System semaphore type.
It is used by middleware as base type of mutex.
-
typedef osMessageQueueId_t
lwesp_sys_mbox_t
¶ System message queue type.
It is used by middleware as base type of mutex.
-
typedef osThreadId_t
lwesp_sys_thread_t
¶ System thread ID type.
-
typedef osPriority
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
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
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
- Return
- Parameters
[in] c
: Cayenne empty handle[in] client_info
: MQTT client info with username, password and id[in] evt_fn
: Event function
-
lwespr_t
lwesp_cayenne_subscribe
(lwesp_cayenne_t *c, lwesp_cayenne_topic_t topic, uint16_t channel)¶ Subscribe to cayenne based topics and channels.
- Return
- Parameters
[in] c
: Cayenne handle[in] topic
: Cayenne topic[in] channel
: Optional channel number. Use LWESP_CAYENNE_NO_CHANNEL when channel is not needed or LWESP_CAYENNE_ALL_CHANNELS to subscribe to all channels
-
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)¶
-
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
-
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
-
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
-
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
- Return
Number of bytes written to output
- See
- Parameters
[in] hs
: HTTP handle[in] str
: String to write
Typedefs
-
typedef char *(*
http_cgi_fn
)(http_param_t *params, size_t params_len)¶ CGI callback function.
- Return
Function must return a new URI which is used later as response string, such as “/index.html” or similar
- Parameters
[in] params
: Pointer to list of parameteres and their values[in] params_len
: Number of parameters
-
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
- Return
- Parameters
[in] hs
: HTTP state[in] pbuf
: Packet buffer wit reciveed data
-
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
- Parameters
[in] hs
: HTTP state[in] tag_name
: Name of TAG to replace with user content[in] tag_len
: Length of TAG
- Return Value
1
: Everything was written on this tag0
: 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.
- Return
1 if file is opened, 0 otherwise
- Parameters
[in] file
: Pointer to file where user has to set length of file if opening was successful[in] path
: Path of file to open
-
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.- Return
Number of bytes read or number of bytes available to read
- Parameters
[in] file
: File pointer to read content[in] buff
: Buffer to read data to. When parameter is set to NULL, number of remaining bytes available to read should be returned[in] btr
: Number of bytes to read from file. This parameter has no meaning when buff is NULL
-
typedef uint8_t (*
http_fs_close_fn
)(struct http_fs_file *file)¶ Close file callback function.
- Return
1
on success,0
otherwise- Parameters
[in] file
: File to close
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
- Return
Number of bytes written
- Parameters
[in] hs
: HTTP state[in] data
: Data to write[in] len
: Length of bytes to write
-
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 *
-
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
-
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 *
-
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
-
-
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.
- Return
1
on success,0
otherwise- Parameters
[in] file
: File structure to fill if file is successfully open[in] path
: File path to open in format “/js/scripts.js” or “/index.html”
-
uint32_t
http_fs_read
(http_fs_file_t *file, void *buff, size_t btr)¶ Read a file content.
- Return
Number of bytes read or number of bytes available to read
- Parameters
[in] file
: File handle to read[out] buff
: Buffer to read data to. When set to NULL, function should return remaining available data to read[in] btr
: Number of bytes to read. Has no meaning when buff = NULL
-
uint8_t
http_fs_close
(http_fs_file_t *file)¶ Close a file handle.
- Return
1
on success,0
otherwise- Parameters
[in] file
: File handle
-
uint8_t
MQTT Client¶
MQTT client v3.1.1 implementation, based on callback (non-netconn) connection API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | /*
* MQTT client example with ESP device.
*
* Once device is connected to network,
* it will try to connect to mosquitto test server and start the MQTT.
*
* If successfully connected, it will publish data to "esp8266_mqtt_topic" topic every x seconds.
*
* To check if data are sent, you can use mqtt-spy PC software to inspect
* test.mosquitto.org server and subscribe to publishing topic
*/
#include "lwesp/apps/lwesp_mqtt_client.h"
#include "lwesp/lwesp.h"
#include "lwesp/lwesp_timeout.h"
#include "mqtt_client.h"
/**
* \brief MQTT client structure
*/
static lwesp_mqtt_client_p
mqtt_client;
/**
* \brief Client ID is structured from ESP station MAC address
*/
static char
mqtt_client_id[13];
/**
* \brief Connection information for MQTT CONNECT packet
*/
static const lwesp_mqtt_client_info_t
mqtt_client_info = {
.id = mqtt_client_id, /* The only required field for connection! */
.keep_alive = 10,
// .user = "test_username",
// .pass = "test_password",
};
static void mqtt_cb(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t* evt);
static void example_do_connect(lwesp_mqtt_client_p client);
static uint32_t retries = 0;
/**
* \brief Custom callback function for ESP events
*/
static lwespr_t
mqtt_lwesp_cb(lwesp_evt_t* evt) {
switch (lwesp_evt_get_type(evt)) {
#if LWESP_CFG_MODE_STATION
case LWESP_EVT_WIFI_GOT_IP: {
example_do_connect(mqtt_client); /* Start connection after we have a connection to network client */
break;
}
#endif /* LWESP_CFG_MODE_STATION */
default:
break;
}
return lwespOK;
}
/**
* \brief MQTT client thread
* \param[in] arg: User argument
*/
void
mqtt_client_thread(void const* arg) {
lwesp_mac_t mac;
lwesp_evt_register(mqtt_lwesp_cb); /* Register new callback for general events from ESP stack */
/* Get station MAC to format client ID */
if (lwesp_sta_getmac(&mac, NULL, NULL, 1) == lwespOK) {
snprintf(mqtt_client_id, sizeof(mqtt_client_id), "%02X%02X%02X%02X%02X%02X",
(unsigned)mac.mac[0], (unsigned)mac.mac[1], (unsigned)mac.mac[2],
(unsigned)mac.mac[3], (unsigned)mac.mac[4], (unsigned)mac.mac[5]
);
} else {
strcpy(mqtt_client_id, "unknown");
}
printf("MQTT Client ID: %s\r\n", mqtt_client_id);
/*
* Create a new client with 256 bytes of RAW TX data
* and 128 bytes of RAW incoming data
*/
mqtt_client = lwesp_mqtt_client_new(256, 128);/* Create new MQTT client */
if (lwesp_sta_is_joined()) { /* If ESP is already joined to network */
example_do_connect(mqtt_client); /* Start connection to MQTT server */
}
/* Make dummy delay of thread */
while (1) {
lwesp_delay(1000);
}
}
/**
* \brief Timeout callback for MQTT events
* \param[in] arg: User argument
*/
void
mqtt_timeout_cb(void* arg) {
static uint32_t num = 10;
lwesp_mqtt_client_p client = arg;
lwespr_t res;
static char tx_data[20];
if (lwesp_mqtt_client_is_connected(client)) {
sprintf(tx_data, "R: %u, N: %u", (unsigned)retries, (unsigned)num);
if ((res = lwesp_mqtt_client_publish(client, "esp8266_mqtt_topic", tx_data, LWESP_U16(strlen(tx_data)), LWESP_MQTT_QOS_EXACTLY_ONCE, 0, (void*)num)) == lwespOK) {
printf("Publishing %d...\r\n", (int)num);
num++;
} else {
printf("Cannot publish...: %d\r\n", (int)res);
}
}
lwesp_timeout_add(10000, mqtt_timeout_cb, client);
}
/**
* \brief MQTT event callback function
* \param[in] client: MQTT client where event occurred
* \param[in] evt: Event type and data
*/
static void
mqtt_cb(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t* evt) {
switch (lwesp_mqtt_client_evt_get_type(client, evt)) {
/*
* Connect event
* Called if user successfully connected to MQTT server
* or even if connection failed for some reason
*/
case LWESP_MQTT_EVT_CONNECT: { /* MQTT connect event occurred */
lwesp_mqtt_conn_status_t status = lwesp_mqtt_client_evt_connect_get_status(client, evt);
if (status == LWESP_MQTT_CONN_STATUS_ACCEPTED) {
printf("MQTT accepted!\r\n");
/*
* Once we are accepted by server,
* it is time to subscribe to different topics
* We will subscrive to "mqtt_lwesp_example_topic" topic,
* and will also set the same name as subscribe argument for callback later
*/
lwesp_mqtt_client_subscribe(client, "esp8266_mqtt_topic", LWESP_MQTT_QOS_EXACTLY_ONCE, "esp8266_mqtt_topic");
/* Start timeout timer after 5000ms and call mqtt_timeout_cb function */
lwesp_timeout_add(5000, mqtt_timeout_cb, client);
} else {
printf("MQTT server connection was not successful: %d\r\n", (int)status);
/* Try to connect all over again */
example_do_connect(client);
}
break;
}
/*
* Subscribe event just happened.
* Here it is time to check if it was successful or failed attempt
*/
case LWESP_MQTT_EVT_SUBSCRIBE: {
const char* arg = lwesp_mqtt_client_evt_subscribe_get_argument(client, evt); /* Get user argument */
lwespr_t res = lwesp_mqtt_client_evt_subscribe_get_result(client, evt); /* Get result of subscribe event */
if (res == lwespOK) {
printf("Successfully subscribed to %s topic\r\n", arg);
if (!strcmp(arg, "esp8266_mqtt_topic")) { /* Check topic name we were subscribed */
/* Subscribed to "esp8266_mqtt_topic" topic */
/*
* Now publish an even on example topic
* and set QoS to minimal value which does not guarantee message delivery to received
*/
lwesp_mqtt_client_publish(client, "esp8266_mqtt_topic", "test_data", 9, LWESP_MQTT_QOS_AT_MOST_ONCE, 0, (void*)1);
}
}
break;
}
/* Message published event occurred */
case LWESP_MQTT_EVT_PUBLISH: {
uint32_t val = (uint32_t)lwesp_mqtt_client_evt_publish_get_argument(client, evt); /* Get user argument, which is in fact our custom number */
printf("Publish event, user argument on message was: %d\r\n", (int)val);
break;
}
/*
* A new message was published to us
* and now it is time to read the data
*/
case LWESP_MQTT_EVT_PUBLISH_RECV: {
const char* topic = lwesp_mqtt_client_evt_publish_recv_get_topic(client, evt);
size_t topic_len = lwesp_mqtt_client_evt_publish_recv_get_topic_len(client, evt);
const uint8_t* payload = lwesp_mqtt_client_evt_publish_recv_get_payload(client, evt);
size_t payload_len = lwesp_mqtt_client_evt_publish_recv_get_payload_len(client, evt);
LWESP_UNUSED(payload);
LWESP_UNUSED(payload_len);
LWESP_UNUSED(topic);
LWESP_UNUSED(topic_len);
break;
}
/* Client is fully disconnected from MQTT server */
case LWESP_MQTT_EVT_DISCONNECT: {
printf("MQTT client disconnected!\r\n");
example_do_connect(client); /* Connect to server all over again */
break;
}
default:
break;
}
}
/** Make a connection to MQTT server in non-blocking mode */
static void
example_do_connect(lwesp_mqtt_client_p client) {
if (client == NULL) {
return;
}
/*
* Start a simple connection to open source
* MQTT server on mosquitto.org
*/
retries++;
lwesp_timeout_remove(mqtt_timeout_cb);
lwesp_mqtt_client_connect(mqtt_client, "test.mosquitto.org", 1883, mqtt_cb, &mqtt_client_info);
}
|
-
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.
- Parameters
[in] client
: MQTT client[in] evt
: 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
-
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
-
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
-
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
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.
- Return
Pointer to new allocated MQTT client structure or
NULL
on failure- Parameters
[in] tx_buff_len
: Length of raw data output buffer[in] rx_buff_len
: Length of raw data input buffer
-
void
lwesp_mqtt_client_delete
(lwesp_mqtt_client_p client)¶ Delete MQTT client structure.
- Note
MQTT client must be disconnected first
- Parameters
[in] client
: 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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] client
: MQTT client[in] host
: Host address for server[in] port
: Host port number[in] evt_fn
: Callback function for all events on this MQTT client[in] info
: Information structure for connection
-
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
- Return
1
on success,0
otherwise- Parameters
[in] client
: MQTT client
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] client
: MQTT client[in] topic
: Topic name to subscribe to[in] qos
: Quality of service. This parameter can be a value of lwesp_mqtt_qos_t[in] arg
: User custom argument used in callback
-
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.
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] client
: MQTT client[in] topic
: Topic to send message to[in] payload
: Message data[in] payload_len
: Length of payload data[in] qos
: Quality of service. This parameter can be a value of lwesp_mqtt_qos_t enumeration[in] retain
: Retian parameter value[in] arg
: User custom argument used in callback
-
void *
lwesp_mqtt_client_get_arg
(lwesp_mqtt_client_p client)¶ Get user argument on client.
- Return
User argument
- Parameters
[in] client
: MQTT client handle
-
void
lwesp_mqtt_client_set_arg
(lwesp_mqtt_client_p client, void *arg)¶ Set user argument on client.
- Parameters
[in] client
: MQTT client handle[in] arg
: 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 *
-
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
-
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
-
typedef struct lwesp_mqtt_client *
-
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.
- Return
Connection status. Member of lwesp_mqtt_conn_status_t
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
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.
- Return
1
on success,0
otherwise- Parameters
[in] client
: MQTT client[in] evt
: Event handle
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.
- Return
User argument
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
-
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.
- Return
User argument
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
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.
- Return
Topic name
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
-
lwesp_mqtt_client_evt_publish_recv_get_topic_len
(client, evt)¶ Get topic length from received publish packet.
- Return
Topic length
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
-
lwesp_mqtt_client_evt_publish_recv_get_payload
(client, evt)¶ Get payload from received publish packet.
- Return
Packet payload
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
-
lwesp_mqtt_client_evt_publish_recv_get_payload_len
(client, evt)¶ Get payload length from received publish packet.
- Return
Payload length
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
-
lwesp_mqtt_client_evt_publish_recv_is_duplicate
(client, evt)¶ Check if packet is duplicated.
- Return
1
if duplicated,0
otherwise- Parameters
[in] client
: MQTT client[in] evt
: Event handle
-
lwesp_mqtt_client_evt_publish_recv_get_qos
(client, evt)¶ Get received quality of service.
- Return
Member of lwesp_mqtt_qos_t enumeration
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
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.
- Return
User argument
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
Defines
-
lwesp_mqtt_client_evt_get_type
(client, evt)¶ Get MQTT event type.
- Return
MQTT Event type, value of lwesp_mqtt_evt_type_t enumeration
- Parameters
[in] client
: MQTT client[in] evt
: Event handle
MQTT Client API¶
MQTT Client API provides sequential API built on top of MQTT Client.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | /*
* MQTT client API example with ESP device.
*
* Once device is connected to network,
* it will try to connect to mosquitto test server and start the MQTT.
*
* If successfully connected, it will publish data to "lwesp_mqtt_topic" topic every x seconds.
*
* To check if data are sent, you can use mqtt-spy PC software to inspect
* test.mosquitto.org server and subscribe to publishing topic
*/
#include "lwesp/apps/lwesp_mqtt_client_api.h"
#include "mqtt_client_api.h"
#include "lwesp/lwesp_mem.h"
/**
* \brief Connection information for MQTT CONNECT packet
*/
static const lwesp_mqtt_client_info_t
mqtt_client_info = {
.keep_alive = 10,
/* Server login data */
.user = "8a215f70-a644-11e8-ac49-e932ed599553",
.pass = "26aa943f702e5e780f015cd048a91e8fb54cca28",
/* Device identifier address */
.id = "869f5a20-af9c-11e9-b01f-db5cf74e7fb7",
};
/**
* \brief Memory for temporary topic
*/
static char
mqtt_topic_str[256];
/**
* \brief Generate random number and write it to string
* \param[out] str: Output string with new number
*/
void
generate_random(char* str) {
static uint32_t random_beg = 0x8916;
random_beg = random_beg * 0x00123455 + 0x85654321;
sprintf(str, "%u", (unsigned)((random_beg >> 8) & 0xFFFF));
}
/**
* \brief MQTT client API thread
*/
void
mqtt_client_api_thread(void const* arg) {
lwesp_mqtt_client_api_p client;
lwesp_mqtt_conn_status_t conn_status;
lwesp_mqtt_client_api_buf_p buf;
lwespr_t res;
char random_str[10];
/* Create new MQTT API */
client = lwesp_mqtt_client_api_new(256, 128);
if (client == NULL) {
goto terminate;
}
while (1) {
/* Make a connection */
printf("Joining MQTT server\r\n");
/* Try to join */
conn_status = lwesp_mqtt_client_api_connect(client, "mqtt.mydevices.com", 1883, &mqtt_client_info);
if (conn_status == LWESP_MQTT_CONN_STATUS_ACCEPTED) {
printf("Connected and accepted!\r\n");
printf("Client is ready to subscribe and publish to new messages\r\n");
} else {
printf("Connect API response: %d\r\n", (int)conn_status);
lwesp_delay(5000);
continue;
}
/* Subscribe to topics */
sprintf(mqtt_topic_str, "v1/%s/things/%s/cmd/#", mqtt_client_info.user, mqtt_client_info.id);
if (lwesp_mqtt_client_api_subscribe(client, mqtt_topic_str, LWESP_MQTT_QOS_AT_LEAST_ONCE) == lwespOK) {
printf("Subscribed to topic\r\n");
} else {
printf("Problem subscribing to topic!\r\n");
}
while (1) {
/* Receive MQTT packet with 1000ms timeout */
res = lwesp_mqtt_client_api_receive(client, &buf, 5000);
if (res == lwespOK) {
if (buf != NULL) {
printf("Publish received!\r\n");
printf("Topic: %s, payload: %s\r\n", buf->topic, buf->payload);
lwesp_mqtt_client_api_buf_free(buf);
buf = NULL;
}
} else if (res == lwespCLOSED) {
printf("MQTT connection closed!\r\n");
break;
} else if (res == lwespTIMEOUT) {
printf("Timeout on MQTT receive function. Manually publishing.\r\n");
/* Publish data on channel 1 */
generate_random(random_str);
sprintf(mqtt_topic_str, "v1/%s/things/%s/data/1", mqtt_client_info.user, mqtt_client_info.id);
lwesp_mqtt_client_api_publish(client, mqtt_topic_str, random_str, strlen(random_str), LWESP_MQTT_QOS_AT_LEAST_ONCE, 0);
}
}
//goto terminate;
}
terminate:
lwesp_mqtt_client_api_delete(client);
printf("MQTT client thread terminate\r\n");
lwesp_sys_thread_terminate(NULL);
}
|
-
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.
- Return
Client handle on success,
NULL
otherwise- Parameters
[in] tx_buff_len
: Maximal TX buffer for maximal packet length[in] rx_buff_len
: Maximal RX buffer
-
void
lwesp_mqtt_client_api_delete
(lwesp_mqtt_client_api_p client)¶ Delete client from memory.
- Parameters
[in] client
: 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.
- Return
LWESP_MQTT_CONN_STATUS_ACCEPTED on success, member of lwesp_mqtt_conn_status_t otherwise
- Parameters
[in] client
: MQTT API client handle[in] host
: TCP host[in] port
: TCP port[in] info
: MQTT client info
-
lwespr_t
lwesp_mqtt_client_api_subscribe
(lwesp_mqtt_client_api_p client, const char *topic, lwesp_mqtt_qos_t qos)¶ Subscribe to topic.
- Return
- Parameters
[in] client
: MQTT API client handle[in] topic
: Topic to subscribe on[in] qos
: Quality of service. This parameter can be a value of lwesp_mqtt_qos_t
-
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.
- Return
- Parameters
[in] client
: MQTT API client handle[in] topic
: Topic to publish on[in] data
: Data to send[in] btw
: Number of bytes to send for data parameter[in] qos
: Quality of service. This parameter can be a value of lwesp_mqtt_qos_t[in] retain
: Set to1
for retain flag,0
otherwise
-
uint8_t
lwesp_mqtt_client_api_is_connected
(lwesp_mqtt_client_api_p client)¶ Check if client MQTT connection is active.
- Return
1
on success,0
otherwise- Parameters
[in] client
: MQTT API client handle
-
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
- Return
lwespOK on success, lwespCLOSED if MQTT is closed, lwespTIMEOUT on timeout
- Parameters
[in] client
: MQTT API client handle[in] p
: Pointer to output buffer[in] timeout
: Maximal time to wait before function returns timeout
-
void
lwesp_mqtt_client_api_buf_free
(lwesp_mqtt_client_api_buf_p p)¶ Free buffer memory after usage.
- Parameters
[in] p
: 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 *
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include "netconn_client.h"
#include "lwesp/lwesp.h"
/**
* \brief Host and port settings
*/
#define NETCONN_HOST "example.com"
#define NETCONN_PORT 80
/**
* \brief Request header to send on successful connection
*/
static const char
request_header[] = ""
"GET / HTTP/1.1\r\n"
"Host: " NETCONN_HOST "\r\n"
"Connection: close\r\n"
"\r\n";
/**
* \brief Netconn client thread implementation
* \param[in] arg: User argument
*/
void
netconn_client_thread(void const* arg) {
lwespr_t res;
lwesp_pbuf_p pbuf;
lwesp_netconn_p client;
lwesp_sys_sem_t* sem = (void*)arg;
/*
* First create a new instance of netconn
* connection and initialize system message boxes
* to accept received packet buffers
*/
client = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP);
if (client != NULL) {
/*
* Connect to external server as client
* with custom NETCONN_CONN_HOST and CONN_PORT values
*
* Function will block thread until we are successfully connected (or not) to server
*/
res = lwesp_netconn_connect(client, NETCONN_HOST, NETCONN_PORT);
if (res == lwespOK) { /* Are we successfully connected? */
printf("Connected to " NETCONN_HOST "\r\n");
res = lwesp_netconn_write(client, request_header, sizeof(request_header) - 1); /* Send data to server */
if (res == lwespOK) {
res = lwesp_netconn_flush(client); /* Flush data to output */
}
if (res == lwespOK) { /* Were data sent? */
printf("Data were successfully sent to server\r\n");
/*
* Since we sent HTTP request,
* we are expecting some data from server
* or at least forced connection close from remote side
*/
do {
/*
* Receive single packet of data
*
* Function will block thread until new packet
* is ready to be read from remote side
*
* After function returns, don't forgot the check value.
* Returned status will give you info in case connection
* was closed too early from remote side
*/
res = lwesp_netconn_receive(client, &pbuf);
if (res == lwespCLOSED) { /* Was the connection closed? This can be checked by return status of receive function */
printf("Connection closed by remote side...\r\n");
break;
} else if (res == lwespTIMEOUT) {
printf("Netconn timeout while receiving data. You may try multiple readings before deciding to close manually\r\n");
}
if (res == lwespOK && pbuf != NULL) { /* Make sure we have valid packet buffer */
/*
* At this point read and manipulate
* with received buffer and check if you expect more data
*
* After you are done using it, it is important
* you free the memory otherwise memory leaks will appear
*/
printf("Received new data packet of %d bytes\r\n", (int)lwesp_pbuf_length(pbuf, 1));
lwesp_pbuf_free(pbuf); /* Free the memory after usage */
pbuf = NULL;
}
} while (1);
} else {
printf("Error writing data to remote host!\r\n");
}
/*
* Check if connection was closed by remote server
* and in case it wasn't, close it manually
*/
if (res != lwespCLOSED) {
lwesp_netconn_close(client);
}
} else {
printf("Cannot connect to remote host %s:%d!\r\n", NETCONN_HOST, NETCONN_PORT);
}
lwesp_netconn_delete(client); /* Delete netconn structure */
}
if (lwesp_sys_sem_isvalid(sem)) {
lwesp_sys_sem_release(sem);
}
lwesp_sys_thread_terminate(NULL); /* Terminate current thread */
}
|
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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | /*
* Netconn server example is based on single thread
* and it listens for single client only on port 23
*/
#include "netconn_server_1thread.h"
#include "lwesp/lwesp.h"
/**
* \brief Basic thread for netconn server to test connections
* \param[in] arg: User argument
*/
void
netconn_server_1thread_thread(void* arg) {
lwespr_t res;
lwesp_netconn_p server, client;
lwesp_pbuf_p p;
/* Create netconn for server */
server = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP);
if (server == NULL) {
printf("Cannot create server netconn!\r\n");
}
/* Bind it to port 23 */
res = lwesp_netconn_bind(server, 23);
if (res != lwespOK) {
printf("Cannot bind server\r\n");
goto out;
}
/* Start listening for incoming connections with maximal 1 client */
res = lwesp_netconn_listen_with_max_conn(server, 1);
if (res != lwespOK) {
goto out;
}
/* Unlimited loop */
while (1) {
/* Accept new client */
res = lwesp_netconn_accept(server, &client);
if (res != lwespOK) {
break;
}
printf("New client accepted!\r\n");
while (1) {
/* Receive data */
res = lwesp_netconn_receive(client, &p);
if (res == lwespOK) {
printf("Data received!\r\n");
lwesp_pbuf_free(p);
} else {
printf("Netconn receive returned: %d\r\n", (int)res);
if (res == lwespCLOSED) {
printf("Connection closed by client\r\n");
break;
}
}
}
/* Delete client */
if (client != NULL) {
lwesp_netconn_delete(client);
client = NULL;
}
}
/* Delete client */
if (client != NULL) {
lwesp_netconn_delete(client);
client = NULL;
}
out:
printf("Terminating netconn thread!\r\n");
if (server != NULL) {
lwesp_netconn_delete(server);
}
lwesp_sys_thread_terminate(NULL);
}
|
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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | /*
* Netconn server example is based on single "user" thread
* which listens for new connections and accepts them.
*
* When a new client is accepted by server,
* separate thread for client is created where
* data is read, processed and send back to user
*/
#include "netconn_server.h"
#include "lwesp/lwesp.h"
static void netconn_server_processing_thread(void* const arg);
/**
* \brief Main page response file
*/
static const uint8_t
rlwesp_data_mainpage_top[] = ""
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<html>"
" <head>"
" <link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\" />"
" <meta http-equiv=\"refresh\" content=\"1\" />"
" </head>"
" <body>"
" <p>Netconn driven website!</p>"
" <p>Total system up time: <b>";
/**
* \brief Bottom part of main page
*/
static const uint8_t
rlwesp_data_mainpage_bottom[] = ""
" </b></p>"
" </body>"
"</html>";
/**
* \brief Style file response
*/
static const uint8_t
rlwesp_data_style[] = ""
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/css\r\n"
"\r\n"
"body { color: red; font-family: Tahoma, Arial; };";
/**
* \brief 404 error response
*/
static const uint8_t
rlwesp_error_404[] = ""
"HTTP/1.1 404 Not Found\r\n"
"\r\n"
"Error 404";
/**
* \brief Netconn server thread implementation
* \param[in] arg: User argument
*/
void
netconn_server_thread(void const* arg) {
lwespr_t res;
lwesp_netconn_p server, client;
/*
* First create a new instance of netconn
* connection and initialize system message boxes
* to accept clients and packet buffers
*/
server = lwesp_netconn_new(LWESP_NETCONN_TYPE_TCP);
if (server != NULL) {
printf("Server netconn created\r\n");
/* Bind network connection to port 80 */
res = lwesp_netconn_bind(server, 80);
if (res == lwespOK) {
printf("Server netconn listens on port 80\r\n");
/*
* Start listening for incoming connections
* on previously binded port
*/
res = lwesp_netconn_listen(server);
while (1) {
/*
* Wait and accept new client connection
*
* Function will block thread until
* new client is connected to server
*/
res = lwesp_netconn_accept(server, &client);
if (res == lwespOK) {
printf("Netconn new client connected. Starting new thread...\r\n");
/*
* Start new thread for this request.
*
* Read and write back data to user in separated thread
* to allow processing of multiple requests at the same time
*/
if (lwesp_sys_thread_create(NULL, "client", (lwesp_sys_thread_fn)netconn_server_processing_thread, client, 512, LWESP_SYS_THREAD_PRIO)) {
printf("Netconn client thread created\r\n");
} else {
printf("Netconn client thread creation failed!\r\n");
/* Force close & delete */
lwesp_netconn_close(client);
lwesp_netconn_delete(client);
}
} else {
printf("Netconn connection accept error!\r\n");
break;
}
}
} else {
printf("Netconn server cannot bind to port\r\n");
}
} else {
printf("Cannot create server netconn\r\n");
}
lwesp_netconn_delete(server); /* Delete netconn structure */
lwesp_sys_thread_terminate(NULL); /* Terminate current thread */
}
/**
* \brief Thread to process single active connection
* \param[in] arg: Thread argument
*/
static void
netconn_server_processing_thread(void* const arg) {
lwesp_netconn_p client;
lwesp_pbuf_p pbuf, p = NULL;
lwespr_t res;
char strt[20];
client = arg; /* Client handle is passed to argument */
printf("A new connection accepted!\r\n"); /* Print simple message */
do {
/*
* Client was accepted, we are now
* expecting client will send to us some data
*
* Wait for data and block thread for that time
*/
res = lwesp_netconn_receive(client, &pbuf);
if (res == lwespOK) {
printf("Netconn data received, %d bytes\r\n", (int)lwesp_pbuf_length(pbuf, 1));
/* Check reception of all header bytes */
if (p == NULL) {
p = pbuf; /* Set as first buffer */
} else {
lwesp_pbuf_cat(p, pbuf); /* Concatenate buffers together */
}
if (lwesp_pbuf_strfind(pbuf, "\r\n\r\n", 0) != LWESP_SIZET_MAX) {
if (lwesp_pbuf_strfind(pbuf, "GET / ", 0) != LWESP_SIZET_MAX) {
uint32_t now;
printf("Main page request\r\n");
now = lwesp_sys_now(); /* Get current time */
sprintf(strt, "%u ms; %d s", (unsigned)now, (unsigned)(now / 1000));
lwesp_netconn_write(client, rlwesp_data_mainpage_top, sizeof(rlwesp_data_mainpage_top) - 1);
lwesp_netconn_write(client, strt, strlen(strt));
lwesp_netconn_write(client, rlwesp_data_mainpage_bottom, sizeof(rlwesp_data_mainpage_bottom) - 1);
} else if (lwesp_pbuf_strfind(pbuf, "GET /style.css ", 0) != LWESP_SIZET_MAX) {
printf("Style page request\r\n");
lwesp_netconn_write(client, rlwesp_data_style, sizeof(rlwesp_data_style) - 1);
} else {
printf("404 error not found\r\n");
lwesp_netconn_write(client, rlwesp_error_404, sizeof(rlwesp_error_404) - 1);
}
lwesp_netconn_close(client); /* Close netconn connection */
lwesp_pbuf_free(p); /* Do not forget to free memory after usage! */
p = NULL;
break;
}
}
} while (res == lwespOK);
if (p != NULL) { /* Free received data */
lwesp_pbuf_free(p);
p = NULL;
}
lwesp_netconn_delete(client); /* Destroy client memory */
lwesp_sys_thread_terminate(NULL); /* Terminate this thread */
}
|
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
Functions
-
lwesp_netconn_p
lwesp_netconn_new
(lwesp_netconn_type_t type)¶ Create new netconn connection.
- Return
New netconn connection on success,
NULL
otherwise- Parameters
[in] type
: Netconn connection type
-
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.
- Return
lwespOK when new data ready
- Return
lwespCLOSED when connection closed by remote side
- Return
lwespTIMEOUT when receive timeout occurs
- Return
Any other member of lwespr_t otherwise
- Parameters
[in] nc
: Netconn handle used to receive from[in] pbuf
: Pointer to pointer to save new receive buffer to. When function returns, user must check for valid pbuf valuepbuf != NULL
-
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.
- Return
-1
on failure, connection number between0
and LWESP_CFG_MAX_CONNS otherwise- Parameters
[in] nc
: Netconn handle
-
lwesp_conn_p
lwesp_netconn_get_conn
(lwesp_netconn_p nc)¶ Get netconn connection handle.
- Return
ESP connection handle
- Parameters
[in] nc
: Netconn handle
-
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
[in] nc
: Netconn handle[in] timeout
: Timeout in units of milliseconds. Set to0
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.
- Return
Timeout in units of milliseconds. If value is
0
, timeout is disabled (wait forever)- Parameters
[in] nc
: Netconn handle
-
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.
- Return
lwespOK if successfully connected, member of lwespr_t otherwise
- Parameters
[in] nc
: Netconn handle[in] host
: Pointer to host, such as domain name or IP address in string format[in] port
: Target port to use[in] keep_alive
: Keep alive period seconds[in] local_ip
: Local ip in connected command[in] local_port
: Local port address[in] mode
: UDP mode
-
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.
- Return
- Parameters
[in] nc
: Netconn handle used to listen for new connections[in] max_connections
: Maximal number of connections server can accept at a time This parameter may not be larger than LWESP_CFG_MAX_CONNS
-
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
- Return
- Parameters
[in] nc
: Netconn handle used for listen mode[in] timeout
: Time in units of seconds. Set to0
to disable timeout feature
-
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.
-
lwespr_t
lwesp_netconn_flush
(lwesp_netconn_p nc)¶ Flush buffered data on netconn 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
- Return
lwespOK on success, member of lwespr_t enumeration otherwise
- Parameters
[in] nc
: Netconn handle used to send[in] ip
: Pointer to IP address[in] port
: Port number used to send data[in] data
: Pointer to data to write[in] btw
: Number of bytes to write
-
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
[in] cliprintf
: Pointer to CLI printf function[in] ch
: new character to CLI
-
void
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.
- Parameters
[in] format
: string format
-
typedef void
cli_function
(cli_printf cliprintf, int argc, char **argv)¶ CLI entriy function.
- Parameters
[in] cliprintf
: Printf handle callback[in] argc
: Number of arguments[in] argv
: Pointer to pointer to arguments
Functions
-
const cli_command_t *
cli_lookup_command
(char *command)¶ Find the CLI command that matches the input string.
- Return
pointer of the command if we found a match, else NULL
- Parameters
[in] command
: pointer to command string for which we are searching
-
void
cli_tab_auto_complete
(cli_printf cliprintf, char *cmd_buffer, uint32_t *cmd_pos, bool print_options)¶ CLI auto completion function.
- Parameters
[in] cliprintf
: Pointer to CLI printf function[in] cmd_buffer
: CLI command buffer[in] cmd_pos
: pointer to current courser postion in command buffer[in] print_options
: 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.
- Return
true when new commands where succesfully added, else false
- Parameters
[in] commands
: Pointer to commands table[in] num_of_commands
: Number of new commands
-
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 *
-
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 *
-
typedef void
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
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.
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.
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.
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.
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.
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
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.
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