Mbed OS Reference
Loading...
Searching...
No Matches
ESP8266.h
1/* ESP8266Interface Example
2 * Copyright (c) 2015 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef ESP8266_H
19#define ESP8266_H
20
21#if DEVICE_SERIAL && DEVICE_INTERRUPTIN && defined(MBED_CONF_EVENTS_PRESENT) && defined(MBED_CONF_NSAPI_PRESENT) && defined(MBED_CONF_RTOS_API_PRESENT)
22#include <stdint.h>
23#include <ctime>
24
25#include "drivers/BufferedSerial.h"
26#include "netsocket/nsapi_types.h"
27#include "netsocket/WiFiAccessPoint.h"
28#include "PinNames.h"
29#include "platform/ATCmdParser.h"
30#include "platform/Callback.h"
31#include "platform/mbed_chrono.h"
32#include "platform/mbed_error.h"
33#include "rtos/Mutex.h"
34#include "rtos/ThisThread.h"
36
37// Various timeouts for different ESP8266 operations
38// (some of these can't use literal form as they're needed for defaults in this header, where
39// we shouldn't add a using directive for them. Defines only used in the C++ file can use literals).
40#ifndef ESP8266_CONNECT_TIMEOUT
41#define ESP8266_CONNECT_TIMEOUT 15s
42#endif
43#ifndef ESP8266_SEND_TIMEOUT
44#define ESP8266_SEND_TIMEOUT 2s
45#endif
46#ifndef ESP8266_RECV_TIMEOUT
47#define ESP8266_RECV_TIMEOUT std::chrono::seconds(2)
48#endif
49#ifndef ESP8266_MISC_TIMEOUT
50#define ESP8266_MISC_TIMEOUT std::chrono::seconds(2)
51#endif
52#ifndef ESP8266_DNS_TIMEOUT
53#define ESP8266_DNS_TIMEOUT 15s
54#endif
55
56#define ESP8266_SCAN_TIME_MIN 0ms
57#define ESP8266_SCAN_TIME_MAX 1500ms
58#define ESP8266_SCAN_TIME_MIN_DEFAULT 120ms
59#define ESP8266_SCAN_TIME_MAX_DEFAULT 360ms
60
61// Firmware version
62#define ESP8266_SDK_VERSION 2000000
63#define ESP8266_SDK_VERSION_MAJOR ESP8266_SDK_VERSION/1000000
64
65#define ESP8266_AT_VERSION 1000000
66#define ESP8266_AT_VERSION_MAJOR ESP8266_AT_VERSION/1000000
67#define ESP8266_AT_VERSION_TCP_PASSIVE_MODE 1070000
68#define ESP8266_AT_VERSION_WIFI_SCAN_CHANGE 1060000
69
70#define FW_AT_LEAST_VERSION(MAJOR,MINOR,PATCH,NUSED/*Not used*/,REF) \
71 (((MAJOR)*1000000+(MINOR)*10000+(PATCH)*100) >= REF ? true : false)
72
73struct esp8266_socket {
74 int id;
75 nsapi_protocol_t proto;
76 bool connected;
77 bool bound;
78 SocketAddress addr;
79 int keepalive; // TCP
80};
81
82/** ESP8266Interface class.
83 This is an interface to a ESP8266 radio.
84 */
85class ESP8266 {
86public:
87 ESP8266(PinName tx, PinName rx, bool debug = false, PinName rts = NC, PinName cts = NC);
88
89 /**
90 * ESP8266 firmware SDK version
91 *
92 * @param major Major version number
93 * @param minor Minor version number
94 * @param patch Patch version number
95 */
96 struct fw_sdk_version {
97 int major;
98 int minor;
99 int patch;
100 fw_sdk_version(int major, int minor, int patch) : major(major), minor(minor), patch(patch) {}
101 };
102
103 /**
104 * ESP8266 firmware AT version
105 *
106 * @param major Major version number
107 * @param minor Minor version number
108 * @param patch Patch version number
109 */
110 struct fw_at_version {
111 int major;
112 int minor;
113 int patch;
114 fw_at_version(int major, int minor, int patch) : major(major), minor(minor), patch(patch) {}
115 };
116
117 /**
118 * Check AT command interface of ESP8266
119 *
120 * @return true if ready to respond on AT commands
121 */
122 bool at_available(void);
123
124 /**
125 * Disable echo - required for OOB processing to work
126 *
127 * @return true if echo was successfully disabled
128 */
129 bool echo_off(void);
130
131 /**
132 * Check sdk version from which firmware is created
133 *
134 * @return fw_sdk_version which tells major, minor and patch version
135 */
136 struct fw_sdk_version sdk_version(void);
137
138 /**
139 * Check AT instruction set version from which firmware is created
140 *
141 * @return fw_at_version which tells major, minor and patch version
142 */
143 struct fw_at_version at_version(void);
144
145 /**
146 * Startup the ESP8266
147 *
148 * @param mode mode of WIFI 1-client, 2-host, 3-both
149 * @return true only if ESP8266 was setup correctly
150 */
151 bool startup(int mode);
152
153 /**
154 * Reset ESP8266
155 *
156 * @return true only if ESP8266 resets successfully
157 */
158 bool reset(void);
159
160 /**
161 * Enable/Disable DHCP
162 *
163 * @param enabled DHCP enabled when true
164 * @param mode mode of DHCP 0-softAP, 1-station, 2-both
165 * @return true only if ESP8266 enables/disables DHCP successfully
166 */
167 bool dhcp(bool enabled, int mode);
168
169 /**
170 * Connect ESP8266 to AP
171 *
172 * @param ap the name of the AP
173 * @param passPhrase the password of AP
174 * @return NSAPI_ERROR_OK in success, negative error code in failure
175 */
176 nsapi_error_t connect(const char *ap, const char *passPhrase);
177
178 /**
179 * Disconnect ESP8266 from AP
180 *
181 * @return true only if ESP8266 is disconnected successfully
182 */
183 bool disconnect(void);
184
185 /**
186 * Enable or disable Remote IP and Port printing with +IPD
187 *
188 * @param enable, 1 on, 0 off
189 * @return true only if ESP8266 is disconnected successfully
190 */
191 bool ip_info_print(int enable);
192
193 /**
194 * Get the IP address of ESP8266
195 *
196 * @return null-teriminated IP address or null if no IP address is assigned
197 */
198 const char *ip_addr(void);
199
200 /**
201 * Set static IP address, gateway and netmask
202 *
203 * @param ip IP address to set
204 * @param gateway (optional) gateway to set
205 * @param netmask (optional) netmask to set
206 *
207 * @return true if operation was successful and flase otherwise
208 */
209 bool set_ip_addr(const char *ip, const char *gateway, const char *netmask);
210
211 /**
212 * Get the MAC address of ESP8266
213 *
214 * @return null-terminated MAC address or null if no MAC address is assigned
215 */
216 const char *mac_addr(void);
217
218 /** Get the local gateway
219 *
220 * @return Null-terminated representation of the local gateway
221 * or null if no network mask has been recieved
222 */
223 const char *gateway();
224
225 /** Get the local network mask
226 *
227 * @return Null-terminated representation of the local network mask
228 * or null if no network mask has been recieved
229 */
230 const char *netmask();
231
232 /* Return RSSI for active connection
233 *
234 * @return Measured RSSI
235 */
236 int8_t rssi();
237
238 /** Scan mode
239 */
240 enum scan_mode {
241 SCANMODE_ACTIVE = 0, /*!< active mode */
242 SCANMODE_PASSIVE = 1 /*!< passive mode */
243 };
244
245 /** Scan for available networks
246 *
247 * @param ap Pointer to allocated array to store discovered AP
248 * @param limit Size of allocated @a res array, or 0 to only count available AP
249 * @param t_max Maximum scan time per channel
250 * @param t_min Minimum scan time per channel in active mode, can be omitted in passive mode
251 * @return Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
252 * see @a nsapi_error
253 */
254 int scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode,
255 std::chrono::duration<unsigned, std::milli> t_max,
256 std::chrono::duration<unsigned, std::milli> t_min);
257
258 /**Perform a dns query
259 *
260 * @param name Hostname to resolve
261 * @param ip Buffer to store IP address
262 * @return 0 true on success, false on failure
263 */
264 bool dns_lookup(const char *name, char *ip);
265
266 /**
267 * Open a socketed connection
268 *
269 * @param type the type of socket to open "UDP" or "TCP"
270 * @param id id to give the new socket, valid 0-4
271 * @param port port to open connection with
272 * @param addr the IP address of the destination
273 * @param port the port on the destination
274 * @param local_port UDP socket's local port, zero means any
275 * @param udp_mode UDP socket's mode, zero means can't change remote, 1 can change once, 2 can change multiple times
276 * @return NSAPI_ERROR_OK in success, negative error code in failure
277 */
278 nsapi_error_t open_udp(int id, const char *addr, int port, int local_port = 0, int udp_mode = 0);
279
280 /**
281 * Open a socketed connection
282 *
283 * @param type the type of socket to open "UDP" or "TCP"
284 * @param id id to give the new socket, valid 0-4
285 * @param port port to open connection with
286 * @param addr the IP address of the destination
287 * @param port the port on the destination
288 * @param tcp_keepalive TCP connection's keep alive time, zero means disabled
289 * @return NSAPI_ERROR_OK in success, negative error code in failure
290 */
291 nsapi_error_t open_tcp(int id, const char *addr, int port, int keepalive = 0);
292
293 /**
294 * Sends data to an open socket
295 *
296 * @param id id of socket to send to
297 * @param data data to be sent
298 * @param amount amount of data to be sent - max 2048
299 * @return number of bytes on success, negative error code in failure
300 */
301 nsapi_size_or_error_t send(int id, const void *data, uint32_t amount);
302
303 /**
304 * Receives datagram from an open UDP socket
305 *
306 * @param id id to receive from
307 * @param data placeholder for returned information
308 * @param amount number of bytes to be received
309 * @return the number of bytes received
310 */
311 int32_t recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, mbed::chrono::milliseconds_u32 timeout = ESP8266_RECV_TIMEOUT);
312
313 /**
314 * Receives stream data from an open TCP socket
315 *
316 * @param id id to receive from
317 * @param data placeholder for returned information
318 * @param amount number of bytes to be received
319 * @return the number of bytes received
320 */
321 int32_t recv_tcp(int id, void *data, uint32_t amount, mbed::chrono::milliseconds_u32 timeout = ESP8266_RECV_TIMEOUT);
322
323 /**
324 * Closes a socket
325 *
326 * @param id id of socket to close, valid only 0-4
327 * @return true only if socket is closed successfully
328 */
329 bool close(int id);
330
331 /**
332 * Allows timeout to be changed between commands
333 *
334 * @param timeout_ms timeout of the connection
335 */
336 void set_timeout(mbed::chrono::milliseconds_u32 timeout = ESP8266_MISC_TIMEOUT);
337
338 /**
339 * Checks if data is available
340 */
341 bool readable();
342
343 /**
344 * Checks if data can be written
345 */
346 bool writeable();
347
348 /**
349 * Attach a function to call whenever sigio happens in the serial
350 *
351 * @param func A pointer to a void function, or 0 to set as none
352 */
353 void sigio(mbed::Callback<void()> func);
354
355 /**
356 * Attach a function to call whenever sigio happens in the serial
357 *
358 * @param obj pointer to the object to call the member function on
359 * @param method pointer to the member function to call
360 */
361 template <typename T, typename M>
362 void sigio(T *obj, M method)
363 {
364 sigio(mbed::Callback<void()>(obj, method));
365 }
366
367 /**
368 * Attach a function to call whenever network state has changed.
369 *
370 * @param func A pointer to a void function, or 0 to set as none
371 */
372 void attach(mbed::Callback<void()> status_cb);
373
374 /**
375 * Configure SNTP (Simple Network Time Protocol)
376 *
377 * @param enable true to enable SNTP or false to disable it
378 * @param timezone timezone offset [-11,13] (0 by default)
379 * @param server0 optional parameter indicating the first SNTP server ("cn.ntp.org.cn" by default)
380 * @param server1 optional parameter indicating the second SNTP server ("ntp.sjtu.edu.cn" by default)
381 * @param server2 optional parameter indicating the third SNTP server ("us.pool.ntp.org" by default)
382 *
383 * @retval true if successful, false otherwise
384 */
385 bool set_sntp_config(bool enable, int timezone = 0, const char *server0 = nullptr,
386 const char *server1 = nullptr, const char *server2 = nullptr);
387
388 /**
389 * Read out the configuration of SNTP (Simple Network Time Protocol)
390 *
391 * @param enable true if SNTP is enabled
392 * @param timezone timezone offset [-11,13]
393 * @param server0 name of the first SNTP server
394 * @param server1 name of the second SNTP server (optional, nullptr if not set)
395 * @param server2 name of the third SNTP server (optional, nullptr if not set)
396 *
397 * @retval true if successful, false otherwise
398 */
399 bool get_sntp_config(bool *enable, int *timezone, char *server0,
400 char *server1, char *server2);
401
402 /**
403 * Read out SNTP time from ESP8266.
404 *
405 * @param t std::tm structure to be filled in
406 * @retval true on success, false otherwise
407 *
408 * @note ESP8266 must be connected and needs a couple of seconds
409 * before returning correct time. It may return 1 Jan 1970 if it is not ready.
410 *
411 * @note esp8266.sntp-enable must be set to true in mbed_app.json file.
412 */
413 bool get_sntp_time(std::tm *t);
414
415 template <typename T, typename M>
416 void attach(T *obj, M method)
417 {
418 attach(mbed::Callback<void()>(obj, method));
419 }
420
421 /**
422 * Read default Wifi mode from flash
423 *
424 * return Station, SoftAP or SoftAP+Station - 0 on failure
425 */
426 int8_t default_wifi_mode();
427
428 /**
429 * Default Wifi mode written to flash only if changes
430 */
431 bool set_default_wifi_mode(const int8_t mode);
432
433 /**
434 * @param track_ap if TRUE, sets the county code to be the same as the AP's that ESP is connected to,
435 * if FALSE the code will not change
436 * @param country_code ISO 3166-1 Alpha-2 coded country code
437 * @param channel_start the channel number to start at
438 * @param channels number of channels
439 */
440 bool set_country_code_policy(bool track_ap, const char *country_code, int channel_start, int channels);
441
442 /** Get the connection status
443 *
444 * @return The connection status according to ConnectionStatusType
445 */
446 nsapi_connection_status_t connection_status() const;
447
448 /**
449 * Start board's and ESP8266's UART flow control
450 *
451 * @return true if started
452 */
453 bool start_uart_hw_flow_ctrl();
454
455 /**
456 * Stop board's and ESP8266's UART flow control
457 *
458 * @param board_only true to apply to board only, false to apply both
459 * @return true if started
460 */
461 bool stop_uart_hw_flow_ctrl(bool board_only = false);
462
463 /*
464 * From AT firmware v1.7.0.0 onwards enables TCP passive mode
465 */
466 bool cond_enable_tcp_passive_mode();
467
468 /**
469 * For executing OOB processing on background
470 *
471 * @param timeout AT parser receive timeout
472 * @param if TRUE, process all OOBs instead of only one
473 */
474 void bg_process_oob(std::chrono::duration<uint32_t, std::milli> timeout, bool all);
475
476 /**
477 * Flush the serial port input buffers.
478 *
479 * If you do HW reset for ESP module, you should
480 * flush the input buffers from existing responses
481 * from the device.
482 */
483 void flush();
484
485 static const int8_t WIFIMODE_STATION = 1;
486 static const int8_t WIFIMODE_SOFTAP = 2;
487 static const int8_t WIFIMODE_STATION_SOFTAP = 3;
488 static const int8_t SOCKET_COUNT = 5;
489
490 /**
491 * Enables or disables uart input and deep sleep
492 *
493 * @param lock if TRUE, uart input is enabled and deep sleep is locked
494 * if FALSE, uart input is disabled and deep sleep is unlocked
495 */
496 int uart_enable_input(bool lock);
497
498private:
499 // FW version
500 struct fw_sdk_version _sdk_v;
501 struct fw_at_version _at_v;
502
503 // FW version specific settings and functionalities
504 bool _tcp_passive;
505 int32_t _recv_tcp_passive(int id, void *data, uint32_t amount, std::chrono::duration<uint32_t, std::milli> timeout);
506 mbed::Callback<void()> _callback;
507
508 // UART settings
509 mbed::BufferedSerial _serial;
510 PinName _serial_rts;
511 PinName _serial_cts;
512 rtos::Mutex _smutex; // Protect serial port access
513
514 // AT Command Parser
515 mbed::ATCmdParser _parser;
516
517 // Wifi scan result handling
518 bool _recv_ap(nsapi_wifi_ap_t *ap);
519
520 // Socket data buffer
521 struct packet {
522 struct packet *next;
523 int id;
524 char remote_ip[16];
525 int remote_port;
526 uint32_t len; // Remaining length
527 uint32_t alloc_len; // Original length
528 // data follows
529 } *_packets, * *_packets_end;
530 void _clear_socket_packets(int id);
531 void _clear_socket_sending(int id);
532 int _sock_active_id;
533
534 // Memory statistics
535 size_t _heap_usage; // (Socket data buffer usage)
536
537 // OOB processing
538 void _process_oob(std::chrono::duration<uint32_t, std::milli> timeout, bool all);
539
540 // OOB message handlers
541 void _oob_packet_hdlr();
542 void _oob_connect_err();
543 void _oob_conn_already();
544 void _oob_err();
545 void _oob_socket0_closed();
546 void _oob_socket1_closed();
547 void _oob_socket2_closed();
548 void _oob_socket3_closed();
549 void _oob_socket4_closed();
550 void _oob_connection_status();
551 void _oob_socket_close_err();
552 void _oob_watchdog_reset();
553 void _oob_busy();
554 void _oob_tcp_data_hdlr();
555 void _oob_ready();
556 void _oob_scan_results();
557 void _oob_send_ok_received();
558 void _oob_send_fail_received();
559
560 // OOB state variables
561 int _connect_error;
562 bool _disconnect;
563 bool _fail;
564 bool _sock_already;
565 bool _closed;
566 bool _error;
567 bool _busy;
568 bool _reset_done;
569 int _sock_sending_id;
570
571 // Modem's address info
572 char _ip_buffer[16];
573 char _gateway_buffer[16];
574 char _netmask_buffer[16];
575 char _mac_buffer[18];
576
577 // Modem's socket info
578 struct _sock_info {
579 bool open;
580 nsapi_protocol_t proto;
581 char *tcp_data;
582 int32_t tcp_data_avbl; // Data waiting on modem
583 int32_t tcp_data_rcvd;
584 bool send_fail; // Received 'SEND FAIL'. Expect user will close the socket.
585 };
586 struct _sock_info _sock_i[SOCKET_COUNT];
587
588 // Scan results
589 struct _scan_results {
590 WiFiAccessPoint *res;
591 unsigned limit;
592 unsigned cnt;
593 };
594 struct _scan_results _scan_r;
595
596 // Connection state reporting
597 nsapi_connection_status_t _conn_status;
598 mbed::Callback<void()> _conn_stat_cb; // ESP8266Interface registered
599};
600#endif
601#endif
SocketAddress class.
SocketAddress class.
Definition: SocketAddress.h:37
WiFiAccessPoint class.
Parser class for parsing AT commands.
Definition: ATCmdParser.h:56
Class providing buffered UART communication functionality using separate circular buffer for send and...
Callback class based on template specialization.
Definition: Callback.h:53
The Mutex class is used to synchronize the execution of threads.
Definition: Mutex.h:70
signed int nsapi_size_or_error_t
Type used to represent either a size or error passed through sockets.
Definition: nsapi_types.h:153
signed int nsapi_error_t
Type used to represent error codes.
Definition: nsapi_types.h:142
nsapi_wifi_ap structure
Definition: nsapi_types.h:368