Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ESP8266Interface.h Source File

ESP8266Interface.h

00001 /* ESP8266 implementation of NetworkInterfaceAPI
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef ESP8266_INTERFACE_H
00018 #define ESP8266_INTERFACE_H
00019 
00020 #if DEVICE_SERIAL && DEVICE_INTERRUPTIN && defined(MBED_CONF_EVENTS_PRESENT) && defined(MBED_CONF_NSAPI_PRESENT) && defined(MBED_CONF_RTOS_API_PRESENT)
00021 #include "drivers/DigitalOut.h"
00022 #include "drivers/Timer.h"
00023 #include "ESP8266/ESP8266.h"
00024 #include "events/EventQueue.h"
00025 #include "events/mbed_shared_queues.h"
00026 #include "features/netsocket/NetworkInterface.h"
00027 #include "features/netsocket/NetworkStack.h"
00028 #include "features/netsocket/nsapi_types.h"
00029 #include "features/netsocket/SocketAddress.h"
00030 #include "features/netsocket/WiFiAccessPoint.h"
00031 #include "features/netsocket/WiFiInterface.h"
00032 #include "platform/Callback.h"
00033 #if MBED_CONF_RTOS_PRESENT
00034 #include "rtos/ConditionVariable.h"
00035 #endif
00036 #include "rtos/Mutex.h"
00037 
00038 #define ESP8266_SOCKET_COUNT 5
00039 
00040 #define ESP8266_INTERFACE_CONNECT_INTERVAL_MS (5000)
00041 #define ESP8266_INTERFACE_CONNECT_TIMEOUT_MS (2 * ESP8266_CONNECT_TIMEOUT + ESP8266_INTERFACE_CONNECT_INTERVAL_MS)
00042 
00043 #ifdef TARGET_FF_ARDUINO
00044 #ifndef MBED_CONF_ESP8266_TX
00045 #define MBED_CONF_ESP8266_TX D1
00046 #endif
00047 
00048 #ifndef MBED_CONF_ESP8266_RX
00049 #define MBED_CONF_ESP8266_RX D0
00050 #endif
00051 #endif /* TARGET_FF_ARDUINO */
00052 
00053 #ifndef MBED_CONF_ESP8266_COUNTRY_CODE
00054 #define MBED_CONF_ESP8266_COUNTRY_CODE "CN"
00055 #endif
00056 
00057 #ifndef MBED_CONF_ESP8266_CHANNEL_START
00058 #define MBED_CONF_ESP8266_CHANNEL_START 1
00059 #endif
00060 
00061 #ifndef MBED_CONF_ESP8266_CHANNELS
00062 #define MBED_CONF_ESP8266_CHANNELS 13
00063 #endif
00064 
00065 /** ESP8266Interface class
00066  *  Implementation of the NetworkStack for the ESP8266
00067  */
00068 class ESP8266Interface : public NetworkStack, public WiFiInterface {
00069 public:
00070 #if defined MBED_CONF_ESP8266_TX && defined MBED_CONF_ESP8266_RX
00071     /**
00072      * @brief ESP8266Interface default constructor
00073      *        Will use values defined in mbed_lib.json
00074      */
00075     ESP8266Interface();
00076 #endif
00077 
00078     /** ESP8266Interface lifetime
00079      * @param tx        TX pin
00080      * @param rx        RX pin
00081      * @param debug     Enable debugging
00082      */
00083     ESP8266Interface(PinName tx, PinName rx, bool debug = false, PinName rts = NC, PinName cts = NC, PinName rst = NC, PinName pwr = NC);
00084 
00085     /**
00086      * @brief ESP8266Interface default destructor
00087      */
00088     virtual ~ESP8266Interface();
00089 
00090     /** Start the interface
00091      *
00092      *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
00093      *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
00094      *
00095      *  @return         0 on success, negative error code on failure
00096      */
00097     virtual int connect();
00098 
00099     /** Start the interface
00100      *
00101      *  Attempts to connect to a WiFi network.
00102      *
00103      *  If interface is configured blocking it will timeout after up to
00104      *  ESP8266_INTERFACE_CONNECT_TIMEOUT_MS + ESP8266_CONNECT_TIMEOUT ms.
00105      *
00106      *  @param ssid      Name of the network to connect to
00107      *  @param pass      Security passphrase to connect to the network
00108      *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
00109      *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
00110      *  @return          0 on success, or error code on failure
00111      */
00112     virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE ,
00113                         uint8_t channel = 0);
00114 
00115     /** Set the WiFi network credentials
00116      *
00117      *  @param ssid      Name of the network to connect to
00118      *  @param pass      Security passphrase to connect to the network
00119      *  @param security  Type of encryption for connection
00120      *                   (defaults to NSAPI_SECURITY_NONE)
00121      *  @return          0 on success, or error code on failure
00122      */
00123     virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE );
00124 
00125     /** Set the WiFi network channel - NOT SUPPORTED
00126      *
00127      * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
00128      *
00129      *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
00130      *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
00131      */
00132     virtual int set_channel(uint8_t channel);
00133 
00134     /** Stop the interface
00135      *  @return             0 on success, negative on failure
00136      */
00137     virtual int disconnect();
00138 
00139     /** Get the internally stored IP address
00140      *  @return             IP address of the interface or null if not yet connected
00141      */
00142     virtual nsapi_error_t get_ip_address(SocketAddress *address);
00143 
00144     MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated")
00145     virtual const char *get_ip_address();
00146 
00147     /** Get the internally stored MAC address
00148      *  @return             MAC address of the interface
00149      */
00150     virtual const char *get_mac_address();
00151 
00152     /** Get the local gateway
00153     *
00154     *  @return         Null-terminated representation of the local gateway
00155     *                  or null if no network mask has been recieved
00156     */
00157     virtual nsapi_error_t get_gateway(SocketAddress *address);
00158 
00159     MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated")
00160     virtual const char *get_gateway();
00161 
00162     /** Get the local network mask
00163      *
00164      *  @return         Null-terminated representation of the local network mask
00165      *                  or null if no network mask has been recieved
00166      */
00167     virtual nsapi_error_t get_netmask(SocketAddress *address);
00168 
00169     MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated")
00170     virtual const char *get_netmask();
00171 
00172     /** Get the network interface name
00173      *
00174      *  @return         Null-terminated representation of the network interface name
00175      *                  or null if interface not exists
00176      */
00177     virtual char *get_interface_name(char *interface_name);
00178 
00179     /** Gets the current radio signal strength for active connection
00180      *
00181      * @return          Connection strength in dBm (negative value)
00182      */
00183     virtual int8_t get_rssi();
00184 
00185     /** Scan mode
00186      */
00187     enum scan_mode {
00188         SCANMODE_ACTIVE , /*!< active mode */
00189         SCANMODE_PASSIVE  /*!< passive mode */
00190     };
00191 
00192     /** Scan for available networks
00193      *
00194      * This function will block.
00195      *
00196      * @param  ap    Pointer to allocated array to store discovered AP
00197      * @param  count Size of allocated @a res array, or 0 to only count available AP
00198      * @return       Number of entries in @a, or if @a count was 0 number of available networks, negative on error
00199      *               see @a nsapi_error
00200      */
00201     virtual int scan(WiFiAccessPoint *res, unsigned count);
00202 
00203     /** Scan for available networks
00204      *
00205      * This function will block.
00206      *
00207      * @param  ap    Pointer to allocated array to store discovered AP
00208      * @param  count Size of allocated @a res array, or 0 to only count available AP
00209      * @param  t_max Scan time for each channel - 0-1500ms. If 0 - uses default value
00210      * @param  t_min Minimum for each channel in active mode - 0-1500ms. If 0 - uses default value. Omit in passive mode
00211      * @return       Number of entries in @a, or if @a count was 0 number of available networks, negative on error
00212      *               see @a nsapi_error
00213      */
00214     virtual int scan(WiFiAccessPoint *res, unsigned count, scan_mode mode = SCANMODE_PASSIVE ,
00215                      unsigned t_max = 0, unsigned t_min = 0);
00216 
00217     /** Translates a hostname to an IP address with specific version
00218      *
00219      *  The hostname may be either a domain name or an IP address. If the
00220      *  hostname is an IP address, no network transactions will be performed.
00221      *
00222      *  If no stack-specific DNS resolution is provided, the hostname
00223      *  will be resolve using a UDP socket on the stack.
00224      *
00225      *  @param address  Destination for the host SocketAddress
00226      *  @param host     Hostname to resolve
00227      *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
00228      *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
00229      *  @return         0 on success, negative error code on failure
00230      */
00231     using NetworkInterface::gethostbyname;
00232 
00233     /** Add a domain name server to list of servers to query
00234      *
00235      *  @param addr     Destination for the host address
00236      *  @return         0 on success, negative error code on failure
00237      */
00238     using NetworkInterface::add_dns_server;
00239 
00240     /** @copydoc NetworkStack::setsockopt
00241      */
00242     virtual nsapi_error_t setsockopt (nsapi_socket_t handle, int level,
00243                                      int optname, const void *optval, unsigned optlen);
00244 
00245     /** @copydoc NetworkStack::getsockopt
00246      */
00247     virtual nsapi_error_t getsockopt (nsapi_socket_t handle, int level, int optname,
00248                                      void *optval, unsigned *optlen);
00249 
00250     /** Register callback for status reporting
00251      *
00252      *  The specified status callback function will be called on status changes
00253      *  on the network. The parameters on the callback are the event type and
00254      *  event-type dependent reason parameter.
00255      *
00256      *  In ESP8266 the callback will be called when processing OOB-messages via
00257      *  AT-parser. Do NOT call any ESP8266Interface -functions or do extensive
00258      *  processing in the callback.
00259      *
00260      *  @param status_cb The callback for status changes
00261      */
00262     virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
00263 
00264     /** Get the connection status
00265      *
00266      *  @return         The connection status according to ConnectionStatusType
00267      */
00268     virtual nsapi_connection_status_t get_connection_status() const;
00269 
00270 protected:
00271     /** Open a socket
00272      *  @param handle       Handle in which to store new socket
00273      *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
00274      *  @return             0 on success, negative on failure
00275      */
00276     virtual int socket_open(void **handle, nsapi_protocol_t proto);
00277 
00278     /** Close the socket
00279      *  @param handle       Socket handle
00280      *  @return             0 on success, negative on failure
00281      *  @note On failure, any memory associated with the socket must still
00282      *        be cleaned up
00283      */
00284     virtual int socket_close(void *handle);
00285 
00286     /** Bind a server socket to a specific port
00287      *  @param handle       Socket handle
00288      *  @param address      Local address to listen for incoming connections on
00289      *  @return             0 on success, negative on failure.
00290      */
00291     virtual int socket_bind(void *handle, const SocketAddress &address);
00292 
00293     /** Start listening for incoming connections
00294      *  @param handle       Socket handle
00295      *  @param backlog      Number of pending connections that can be queued up at any
00296      *                      one time [Default: 1]
00297      *  @return             0 on success, negative on failure
00298      */
00299     virtual int socket_listen(void *handle, int backlog);
00300 
00301     /** Connects this TCP socket to the server
00302      *  @param handle       Socket handle
00303      *  @param address      SocketAddress to connect to
00304      *  @return             0 on success, negative on failure
00305      */
00306     virtual int socket_connect(void *handle, const SocketAddress &address);
00307 
00308     /** Accept a new connection.
00309      *  @param handle       Handle in which to store new socket
00310      *  @param server       Socket handle to server to accept from
00311      *  @return             0 on success, negative on failure
00312      *  @note This call is not-blocking, if this call would block, must
00313      *        immediately return NSAPI_ERROR_WOULD_WAIT
00314      */
00315     virtual int socket_accept(void *handle, void **socket, SocketAddress *address);
00316 
00317     /** Send data to the remote host
00318      *  @param handle       Socket handle
00319      *  @param data         The buffer to send to the host
00320      *  @param size         The length of the buffer to send
00321      *  @return             Number of written bytes on success, negative on failure
00322      *  @note This call is not-blocking, if this call would block, must
00323      *        immediately return NSAPI_ERROR_WOULD_WAIT
00324      */
00325     virtual int socket_send(void *handle, const void *data, unsigned size);
00326 
00327     /** Receive data from the remote host
00328      *  @param handle       Socket handle
00329      *  @param data         The buffer in which to store the data received from the host
00330      *  @param size         The maximum length of the buffer
00331      *  @return             Number of received bytes on success, negative on failure
00332      *  @note This call is not-blocking, if this call would block, must
00333      *        immediately return NSAPI_ERROR_WOULD_WAIT
00334      */
00335     virtual int socket_recv(void *handle, void *data, unsigned size);
00336 
00337     /** Send a packet to a remote endpoint
00338      *  @param handle       Socket handle
00339      *  @param address      The remote SocketAddress
00340      *  @param data         The packet to be sent
00341      *  @param size         The length of the packet to be sent
00342      *  @return             The number of written bytes on success, negative on failure
00343      *  @note This call is not-blocking, if this call would block, must
00344      *        immediately return NSAPI_ERROR_WOULD_WAIT
00345      */
00346     virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
00347 
00348     /** Receive a packet from a remote endpoint
00349      *  @param handle       Socket handle
00350      *  @param address      Destination for the remote SocketAddress or null
00351      *  @param buffer       The buffer for storing the incoming packet data
00352      *                      If a packet is too long to fit in the supplied buffer,
00353      *                      excess bytes are discarded
00354      *  @param size         The length of the buffer
00355      *  @return             The number of received bytes on success, negative on failure
00356      *  @note This call is not-blocking, if this call would block, must
00357      *        immediately return NSAPI_ERROR_WOULD_WAIT
00358      */
00359     virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
00360 
00361     /** Register a callback on state change of the socket
00362      *  @param handle       Socket handle
00363      *  @param callback     Function to call on state change
00364      *  @param data         Argument to pass to callback
00365      *  @note Callback may be called in an interrupt context.
00366      */
00367     virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
00368 
00369     /** Provide access to the NetworkStack object
00370      *
00371      *  @return The underlying NetworkStack object
00372      */
00373     virtual NetworkStack *get_stack()
00374     {
00375         return this;
00376     }
00377 
00378     /** Set blocking status of connect() which by default should be blocking.
00379      *
00380      *  @param blocking Use true to make connect() blocking.
00381      *  @return         NSAPI_ERROR_OK on success, negative error code on failure.
00382      */
00383     virtual nsapi_error_t set_blocking(bool blocking);
00384 
00385     /** Set country code
00386      *
00387      *  @param track_ap      if TRUE, use country code used by the AP ESP is connected to,
00388      *                       otherwise uses country_code always
00389      *  @param country_code  ISO 3166-1 coded, 2 character alphanumeric country code assumed
00390      *  @param len           Length of the country code
00391      *  @param channel_start The channel number to start at
00392      *  @param channel       Number of channels
00393      *  @return              NSAPI_ERROR_OK on success, negative error code on failure.
00394      */
00395     nsapi_error_t set_country_code(bool track_ap, const char *country_code, int len, int channel_start, int channels);
00396 
00397 private:
00398     // AT layer
00399     ESP8266 _esp;
00400     void refresh_conn_state_cb();
00401 
00402     /** Status of software connection
00403      */
00404     typedef enum esp_connection_software_status {
00405         IFACE_STATUS_DISCONNECTED = 0,
00406         IFACE_STATUS_CONNECTING = 1,
00407         IFACE_STATUS_CONNECTED = 2,
00408         IFACE_STATUS_DISCONNECTING = 3
00409     } esp_connection_software_status_t;
00410 
00411     // HW reset pin
00412     class ResetPin {
00413     public:
00414         ResetPin(PinName rst_pin);
00415         void rst_assert();
00416         void rst_deassert();
00417         bool is_connected();
00418     private:
00419         mbed::DigitalOut  _rst_pin;
00420     } _rst_pin;
00421 
00422     // HW power pin
00423     class PowerPin {
00424     public:
00425         PowerPin(PinName pwr_pin);
00426         void power_on();
00427         void power_off();
00428         bool is_connected();
00429     private:
00430         mbed::DigitalOut  _pwr_pin;
00431     } _pwr_pin;
00432 
00433     /** Assert the reset and power pins
00434      *  ESP8266 has two pins serving similar purpose and this function asserts them both
00435      *  if they are configured in mbed_app.json.
00436      */
00437     void _power_off();
00438 
00439     // Credentials
00440     static const int ESP8266_SSID_MAX_LENGTH = 32; /* 32 is what 802.11 defines as longest possible name */
00441     char ap_ssid[ESP8266_SSID_MAX_LENGTH + 1]; /* The longest possible name; +1 for the \0 */
00442     static const int ESP8266_PASSPHRASE_MAX_LENGTH = 63; /* The longest allowed passphrase */
00443     static const int ESP8266_PASSPHRASE_MIN_LENGTH = 8; /* The shortest allowed passphrase */
00444     char ap_pass[ESP8266_PASSPHRASE_MAX_LENGTH + 1]; /* The longest possible passphrase; +1 for the \0 */
00445     nsapi_security_t _ap_sec;
00446 
00447     // Country code
00448     struct _channel_info {
00449         bool track_ap; // Set country code based on the AP ESP is connected to
00450         char country_code[4]; // ISO 3166-1 coded, 2-3 character alphanumeric country code - +1 for the '\0' - assumed. Documentation doesn't tell.
00451         int channel_start;
00452         int channels;
00453     };
00454     struct _channel_info _ch_info;
00455 
00456     bool _if_blocking; // NetworkInterface, blocking or not
00457 #if MBED_CONF_RTOS_PRESENT
00458     rtos::ConditionVariable _if_connected;
00459 #endif
00460 
00461     // connect status reporting
00462     nsapi_error_t _conn_status_to_error();
00463     mbed::Timer _conn_timer;
00464 
00465     // Drivers's socket info
00466     struct _sock_info {
00467         bool open;
00468         uint16_t sport;
00469     };
00470     struct _sock_info _sock_i[ESP8266_SOCKET_COUNT];
00471 
00472     // Driver's state
00473     int _initialized;
00474     nsapi_error_t _connect_retval;
00475     nsapi_error_t _disconnect_retval;
00476     bool _get_firmware_ok();
00477     nsapi_error_t _init(void);
00478     nsapi_error_t _reset();
00479 
00480     //sigio
00481     struct {
00482         void (*callback)(void *);
00483         void *data;
00484         uint8_t deferred;
00485     } _cbs[ESP8266_SOCKET_COUNT];
00486     void event();
00487     void event_deferred();
00488 
00489     // Connection state reporting to application
00490     nsapi_connection_status_t _conn_stat;
00491     mbed::Callback<void(nsapi_event_t, intptr_t)> _conn_stat_cb;
00492 
00493     // Background OOB processing
00494     // Use global EventQueue
00495     events::EventQueue *_global_event_queue;
00496     int _oob_event_id;
00497     int _connect_event_id;
00498     int _disconnect_event_id;
00499     void proc_oob_evnt();
00500     void _connect_async();
00501     void _disconnect_async();
00502     rtos::Mutex _cmutex; // Protect asynchronous connection logic
00503     esp_connection_software_status_t _software_conn_stat ;
00504 
00505 };
00506 #endif
00507 #endif