Station API¶
Station API is used to work with ESP acting in station mode. It allows to join other access point, scan for available access points or simply disconnect from it.
An example below is showing how all examples (coming with this library) scan for access point and then try to connect to AP from list of preferred one.
1#include "station_manager.h"
2#include "utils.h"
3#include "lwesp/lwesp.h"
4
5/**
6 * \brief Private access-point and station management system
7 *
8 * This is used for asynchronous connection to access point
9 */
10typedef struct {
11 size_t index_preferred_list; /*!< Current index position of preferred array */
12 size_t index_scanned_list; /*!< Current index position in array of scanned APs */
13
14 uint8_t command_is_running; /*!< Indicating if command is currently in progress */
15} prv_ap_data_t;
16
17/* Arguments for callback function */
18#define ARG_SCAN (void*)1
19#define ARG_CONNECT (void*)2
20
21/* Function declaration */
22static void prv_cmd_event_fn(lwespr_t status, void* arg);
23static void prv_try_next_access_point(void);
24
25/*
26 * List of preferred access points for ESP device
27 * SSID and password
28 *
29 * ESP will try to scan for access points
30 * and then compare them with the one on the list below
31 */
32static const ap_entry_t ap_list_preferred[] = {
33 //{ .ssid = "SSID name", .pass = "SSID password" },
34 { .ssid = "TilenM_ST", .pass = "its private" },
35 { .ssid = "Kaja", .pass = "kajagin2021" },
36 { .ssid = "Majerle WIFI", .pass = "majerle_internet_private" },
37 { .ssid = "Majerle AMIS", .pass = "majerle_internet_private" },
38};
39static lwesp_ap_t ap_list_scanned[100]; /* Scanned access points information */
40static size_t ap_list_scanned_len = 0; /* Number of scanned access points */
41static prv_ap_data_t ap_async_data; /* Asynchronous data structure */
42
43/* Command to execute to start scanning access points */
44#define prv_scan_ap_command_ex(blocking) lwesp_sta_list_ap(NULL, ap_list_scanned, LWESP_ARRAYSIZE(ap_list_scanned), &ap_list_scanned_len, NULL, NULL, (blocking))
45#define prv_scan_ap_command() do {\
46 if (!ap_async_data.command_is_running) { \
47 printf("Starting scan command on line %d\r\n", __LINE__);\
48 ap_async_data.command_is_running = lwesp_sta_list_ap(NULL, ap_list_scanned, LWESP_ARRAYSIZE(ap_list_scanned), &ap_list_scanned_len, prv_cmd_event_fn, ARG_SCAN, 0) == lwespOK; \
49 } \
50} while (0)
51
52/**
53 * \brief Every internal command execution callback
54 * \param[in] status: Execution status result
55 * \param[in] arg: Custom user argument
56 */
57static void
58prv_cmd_event_fn(lwespr_t status, void* arg) {
59 /*
60 * Command has now successfully finish
61 * and callbacks have been properly processed
62 */
63 ap_async_data.command_is_running = 0;
64
65 if (arg == ARG_SCAN) {
66 /* Immediately try to connect to access point after successful scan*/
67 prv_try_next_access_point();
68 }
69}
70
71/**
72 * \brief Try to connect to next access point on a list
73 */
74static void
75prv_try_next_access_point(void) {
76 uint8_t tried = 0;
77
78 /* No action to be done if command is currently in progress or already connected to network */
79 if (ap_async_data.command_is_running
80 || lwesp_sta_has_ip()) {
81 return;
82 }
83
84 /*
85 * Process complete list and try to find suitable match
86 *
87 * Use global variable for indexes to be able to call function multiple times
88 * and continue where it finished previously
89 */
90
91 /* List all preferred access points */
92 for (; ap_async_data.index_preferred_list < LWESP_ARRAYSIZE(ap_list_preferred);
93 ap_async_data.index_preferred_list++, ap_async_data.index_scanned_list = 0) {
94
95 /* List all scanned access points */
96 for (; ap_async_data.index_scanned_list < ap_list_scanned_len; ap_async_data.index_scanned_list++) {
97
98 /* Find a match if available */
99 if (strncmp(ap_list_scanned[ap_async_data.index_scanned_list].ssid,
100 ap_list_preferred[ap_async_data.index_preferred_list].ssid,
101 strlen(ap_list_preferred[ap_async_data.index_preferred_list].ssid)) == 0) {
102
103 /* Try to connect to the network */
104 if (!ap_async_data.command_is_running
105 && lwesp_sta_join(ap_list_preferred[ap_async_data.index_preferred_list].ssid,
106 ap_list_preferred[ap_async_data.index_preferred_list].pass,
107 NULL, prv_cmd_event_fn, ARG_CONNECT, 0) == lwespOK) {
108 ap_async_data.command_is_running = 1;
109
110 /* Go to next index for sub-for loop and exit */
111 ap_async_data.index_scanned_list++;
112 tried = 1;
113 goto stp;
114 } else {
115 /* We have a problem, needs to resume action in next run */
116 }
117 }
118 }
119 }
120
121 /* Restart scan operation if there was no try to connect and station has no IP */
122 if (!tried && !lwesp_sta_has_ip()) {
123 prv_scan_ap_command();
124 }
125stp:
126 return;
127}
128
129/**
130 * \brief Private event function for asynchronous scanning
131 * \param[in] evt: Event information
132 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
133 */
134static lwespr_t
135prv_evt_fn(lwesp_evt_t* evt) {
136 switch (evt->type) {
137 case LWESP_EVT_KEEP_ALIVE:
138 case LWESP_EVT_WIFI_DISCONNECTED: {
139 /* Try to connect to next access point */
140 prv_try_next_access_point();
141 break;
142 }
143 case LWESP_EVT_STA_LIST_AP: {
144 /*
145 * After scanning gets completed
146 * manually reset all indexes for comparison purposes
147 */
148 ap_async_data.index_scanned_list = 0;
149 ap_async_data.index_preferred_list = 0;
150
151 /* Actual connection try is done in function callback */
152 break;
153 }
154 default: break;
155 }
156 return lwespOK;
157}
158
159/**
160 * \brief Initialize asynchronous mode to connect to preferred access point
161 *
162 * Asynchronous mode relies on system events received by the application,
163 * to determine current device status if station is being, or not, connected to access point.
164 *
165 * When used, async acts only upon station connection change through callbacks,
166 * therefore it does not require additional system thread or user code,
167 * to be able to properly handle preferred access points.
168 * This certainly decreases memory consumption of the complete system.
169 *
170 * \ref LWESP_CFG_KEEP_ALIVE feature must be enable to properly handle all events
171 * \return \ref lwespOK on success, member of \ref lwespr_t otherwise
172 */
173lwespr_t
174station_manager_connect_to_access_point_async_init(void) {
175 /* Register system event function */
176 lwesp_evt_register(prv_evt_fn);
177
178 /*
179 * Start scanning process in non-blocking mode
180 *
181 * This is the only command being executed from non-callback mode,
182 * therefore it must be protected against other threads trying to access the same core
183 */
184 lwesp_core_lock();
185 prv_scan_ap_command();
186 lwesp_core_unlock();
187
188 /* Return all good, things will progress (from now-on) asynchronously */
189 return lwespOK;
190}
191
192/**
193 * \brief Connect to preferred access point in blocking mode
194 *
195 * This functionality can only be used if non-blocking approach is not used
196 *
197 * \note List of access points should be set by user in \ref ap_list structure
198 * \param[in] unlimited: When set to 1, function will block until SSID is found and connected
199 * \return \ref lwespOK on success, member of \ref lwespr_t enumeration otherwise
200 */
201lwespr_t
202connect_to_preferred_access_point(uint8_t unlimited) {
203 lwespr_t eres;
204 uint8_t tried;
205
206 /*
207 * Scan for network access points
208 * In case we have access point,
209 * try to connect to known AP
210 */
211 do {
212 if (lwesp_sta_has_ip()) {
213 return lwespOK;
214 }
215
216 /* Scan for access points visible to ESP device */
217 printf("Scanning access points...\r\n");
218 if ((eres = prv_scan_ap_command_ex(1)) == lwespOK) {
219 tried = 0;
220
221 /* Print all access points found by ESP */
222 for (size_t i = 0; i < ap_list_scanned_len; i++) {
223 printf("AP found: %s, CH: %d, RSSI: %d\r\n", ap_list_scanned[i].ssid, ap_list_scanned[i].ch, ap_list_scanned[i].rssi);
224 }
225
226 /* Process array of preferred access points with array of found points */
227 for (size_t j = 0; j < LWESP_ARRAYSIZE(ap_list_preferred); j++) {
228
229 /* Go through all scanned list */
230 for (size_t i = 0; i < ap_list_scanned_len; i++) {
231
232 /* Try to find a match between preferred and scanned */
233 if (strncmp(ap_list_scanned[i].ssid, ap_list_preferred[j].ssid, strlen(ap_list_scanned[i].ssid)) == 0) {
234 tried = 1;
235 printf("Connecting to \"%s\" network...\r\n", ap_list_preferred[j].ssid);
236
237 /* Try to join to access point */
238 if ((eres = lwesp_sta_join(ap_list_preferred[j].ssid, ap_list_preferred[j].pass, NULL, NULL, NULL, 1)) == lwespOK) {
239 lwesp_ip_t ip;
240 uint8_t is_dhcp;
241
242 printf("Connected to %s network!\r\n", ap_list_preferred[j].ssid);
243
244 lwesp_sta_copy_ip(&ip, NULL, NULL, &is_dhcp);
245 utils_print_ip("Station IP address: ", &ip, "\r\n");
246 printf("; Is DHCP: %d\r\n", (int)is_dhcp);
247 return lwespOK;
248 } else {
249 printf("Connection error: %d\r\n", (int)eres);
250 }
251 }
252 }
253 }
254 if (!tried) {
255 printf("No access points available with preferred SSID!\r\nPlease check station_manager.c file and edit preferred SSID access points!\r\n");
256 }
257 } else if (eres == lwespERRNODEVICE) {
258 printf("Device is not present!\r\n");
259 break;
260 } else {
261 printf("Error on WIFI scan procedure!\r\n");
262 }
263 if (!unlimited) {
264 break;
265 }
266 } while (1);
267 return lwespERR;
268}
- group LWESP_STA
Station API.
Functions
-
lwespr_t lwesp_sta_join(const char *name, const char *pass, const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Join as station to access point.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
name – [in] SSID of access point to connect to
pass – [in] Password of access point. Use
NULL
if AP does not have passwordmac – [in] Pointer to MAC address of AP. If multiple APs with same name exist, MAC may help to select proper one. Set to
NULL
if not neededevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_quit(const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Quit (disconnect) from access point.
-
lwespr_t lwesp_sta_autojoin(uint8_t en, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Configure auto join to access point on startup.
Note
For auto join feature, you need to do a join to access point with default mode. Check lwesp_sta_join for more information
- Parameters
en – [in] Set to
1
to enable or0
to disableevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_reconnect_set_config(uint16_t interval, uint16_t rep_cnt, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set reconnect interval and maximum tries when connection drops.
- Parameters
interval – [in] Interval in units of seconds. Valid numbers are
1-7200
or0
to disable reconnect featurerep_cnt – [in] Repeat counter. Number of maximum tries for reconnect. Valid entries are
1-1000
or0
to always try. This parameter is only valid if interval is not0
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_getip(lwesp_ip_t *ip, lwesp_ip_t *gw, lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get station IP address.
- Parameters
ip – [out] Pointer to variable to save IP address
gw – [out] Pointer to output variable to save gateway address
nm – [out] Pointer to output variable to save netmask address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_setip(const lwesp_ip_t *ip, const lwesp_ip_t *gw, const lwesp_ip_t *nm, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set station IP address.
Application may manually set IP address. When this happens, stack will check for DHCP settings and will read actual IP address from device. Once procedure is finished, LWESP_EVT_WIFI_IP_ACQUIRED event will be sent to application where user may read the actual new IP and DHCP settings.
Configuration changes will be saved in the NVS area of ESP device.
Note
DHCP is automatically disabled when using static IP address
- Parameters
ip – [in] Pointer to IP address
gw – [in] Pointer to gateway address. Set to
NULL
to use default gatewaynm – [in] Pointer to netmask address. Set to
NULL
to use default netmaskevt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_getmac(lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get station MAC address.
- Parameters
mac – [out] Pointer to output variable to save MAC address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_setmac(const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Set station MAC address.
Configuration changes will be saved in the NVS area of ESP device.
- Parameters
mac – [in] Pointer to variable with MAC address
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
uint8_t lwesp_sta_has_ip(void)¶
Check if ESP got IP from access point.
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_is_joined(void)¶
Check if station is connected to WiFi network.
- Returns
1
on success,0
otherwise
-
lwespr_t lwesp_sta_copy_ip(lwesp_ip_t *ip, lwesp_ip_t *gw, lwesp_ip_t *nm, uint8_t *is_dhcp)¶
Copy IP address from internal value to user variable.
Note
Use lwesp_sta_getip to refresh actual IP value from device
- Parameters
ip – [out] Pointer to output IP variable. Set to
NULL
if not interested in IP addressgw – [out] Pointer to output gateway variable. Set to
NULL
if not interested in gateway addressnm – [out] Pointer to output netmask variable. Set to
NULL
if not interested in netmask addressis_dhcp – [out] Pointer to output DHCP status variable. Set to
NULL
if not interested
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_list_ap(const char *ssid, lwesp_ap_t *aps, size_t apsl, size_t *apf, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
List for available access points ESP can connect to.
- Parameters
ssid – [in] Optional SSID name to search for. Set to
NULL
to disable filteraps – [in] Pointer to array of available access point parameters
apsl – [in] Length of aps array
apf – [out] Pointer to output variable to save number of access points found
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_sta_get_ap_info(lwesp_sta_info_ap_t *info, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶
Get current access point information (name, mac, channel, rssi)
Note
Access point station is currently connected to
- Parameters
info – [in] Pointer to connected access point information
evt_fn – [in] Callback function called when command has finished. Set to
NULL
when not usedevt_arg – [in] Custom argument for event callback function
blocking – [in] Status whether command should be blocking or not
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
uint8_t lwesp_sta_is_ap_802_11b(lwesp_ap_t *ap)¶
Check if access point is
802.11b
compatible.- Parameters
ap – [in] Access point detailes acquired by lwesp_sta_list_ap
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_is_ap_802_11g(lwesp_ap_t *ap)¶
Check if access point is
802.11g
compatible.- Parameters
ap – [in] Access point detailes acquired by lwesp_sta_list_ap
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_is_ap_802_11n(lwesp_ap_t *ap)¶
Check if access point is
802.11n
compatible.- Parameters
ap – [in] Access point detailes acquired by lwesp_sta_list_ap
- Returns
1
on success,0
otherwise
-
uint8_t lwesp_sta_has_ipv6_local(void)¶
Check if station has local IPV6 IP Local IP is used between station and router.
Note
Defined as macro with
0
constant if LWESP_CFG_IPV6 is disabled- Returns
1
if local IPv6 is available,0
otherwise
-
uint8_t lwesp_sta_has_ipv6_global(void)¶
Check if station has global IPV6 IP Global IP is used router and outside network.
Note
Defined as macro with
0
constant if LWESP_CFG_IPV6 is disabled- Returns
1
if global IPv6 is available,0
otherwise
-
struct lwesp_sta_t¶
- #include <lwesp_typedefs.h>
Station data structure.
Public Members
-
lwesp_ip_t ip¶
IP address of connected station
-
lwesp_mac_t mac¶
MAC address of connected station
-
lwesp_ip_t ip¶
-
lwespr_t lwesp_sta_join(const char *name, const char *pass, const lwesp_mac_t *mac, const lwesp_api_cmd_evt_fn evt_fn, void *const evt_arg, const uint32_t blocking)¶