version 1.6

Dependents:   iot_water_monitor_v2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ESP8266Interface.cpp Source File

ESP8266Interface.cpp

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 #include <string.h>
00018 #include "ESP8266Interface.h"
00019 #include "mbed_debug.h"
00020 
00021 // Various timeouts for different ESP8266 operations
00022 #ifndef ESP8266_CONNECT_TIMEOUT
00023 #define ESP8266_CONNECT_TIMEOUT 15000
00024 #endif
00025 #ifndef ESP8266_SEND_TIMEOUT
00026 #define ESP8266_SEND_TIMEOUT    500
00027 #endif
00028 #ifndef ESP8266_RECV_TIMEOUT
00029 #define ESP8266_RECV_TIMEOUT    500
00030 #endif
00031 #ifndef ESP8266_MISC_TIMEOUT
00032 #define ESP8266_MISC_TIMEOUT    500
00033 #endif
00034 
00035 // Firmware version
00036 #define ESP8266_VERSION 2
00037 
00038 // ESP8266Interface implementation
00039 ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug)
00040     : _esp(tx, rx, debug)
00041 {
00042     memset(_ids, 0, sizeof(_ids));
00043     memset(_cbs, 0, sizeof(_cbs));
00044 
00045     _esp.attach(this, &ESP8266Interface::event);
00046 }
00047 
00048 int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
00049                                         uint8_t channel)
00050 {
00051     if (channel != 0) {
00052         return NSAPI_ERROR_UNSUPPORTED;
00053     }
00054 
00055     set_credentials(ssid, pass, security);
00056     return connect();
00057 }
00058 
00059 int ESP8266Interface::connect()
00060 {
00061     _esp.setTimeout(ESP8266_CONNECT_TIMEOUT);
00062     
00063     if (!_esp.reset()) {
00064         return NSAPI_ERROR_DEVICE_ERROR;
00065     }   
00066  
00067     _esp.setTimeout(ESP8266_MISC_TIMEOUT);
00068     
00069     if (_esp.get_firmware_version() != ESP8266_VERSION) {
00070         debug("ESP8266: ERROR: Firmware incompatible with this driver.\
00071                \r\nUpdate to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\r\n",ESP8266_VERSION); 
00072         return NSAPI_ERROR_DEVICE_ERROR;
00073     }
00074     
00075     _esp.setTimeout(ESP8266_CONNECT_TIMEOUT);
00076 
00077     if (!_esp.startup(3)) {
00078         return NSAPI_ERROR_DEVICE_ERROR;
00079     }
00080 
00081     if (!_esp.dhcp(true, 1)) {
00082         return NSAPI_ERROR_DHCP_FAILURE;
00083     }
00084 
00085     if (!_esp.connect(ap_ssid, ap_pass)) {
00086         return NSAPI_ERROR_NO_CONNECTION;
00087     }
00088 
00089     if (!_esp.getIPAddress()) {
00090         return NSAPI_ERROR_DHCP_FAILURE;
00091     }
00092 
00093     return NSAPI_ERROR_OK;
00094 }
00095 
00096 int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
00097 {
00098     memset(ap_ssid, 0, sizeof(ap_ssid));
00099     strncpy(ap_ssid, ssid, sizeof(ap_ssid));
00100 
00101     memset(ap_pass, 0, sizeof(ap_pass));
00102     strncpy(ap_pass, pass, sizeof(ap_pass));
00103 
00104     ap_sec = security;
00105 
00106     return 0;
00107 }
00108 
00109 int ESP8266Interface::set_channel(uint8_t channel)
00110 {
00111     return NSAPI_ERROR_UNSUPPORTED;
00112 }
00113 
00114 
00115 int ESP8266Interface::disconnect()
00116 {
00117     _esp.setTimeout(ESP8266_MISC_TIMEOUT);
00118 
00119     if (!_esp.disconnect()) {
00120         return NSAPI_ERROR_DEVICE_ERROR;
00121     }
00122 
00123     return NSAPI_ERROR_OK;
00124 }
00125 
00126 const char *ESP8266Interface::get_ip_address()
00127 {
00128     return _esp.getIPAddress();
00129 }
00130 
00131 const char *ESP8266Interface::get_mac_address()
00132 {
00133     return _esp.getMACAddress();
00134 }
00135 
00136 const char *ESP8266Interface::get_gateway()
00137 {
00138     return _esp.getGateway();
00139 }
00140 
00141 const char *ESP8266Interface::get_netmask()
00142 {
00143     return _esp.getNetmask();
00144 }
00145 
00146 int8_t ESP8266Interface::get_rssi()
00147 {
00148     return _esp.getRSSI();
00149 }
00150 
00151 int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count)
00152 {
00153     return _esp.scan(res, count);
00154 }
00155 
00156 struct esp8266_socket {
00157     int id;
00158     nsapi_protocol_t proto;
00159     bool connected;
00160     SocketAddress addr;
00161 };
00162 
00163 int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
00164 {
00165     // Look for an unused socket
00166     int id = -1;
00167  
00168     for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
00169         if (!_ids[i]) {
00170             id = i;
00171             _ids[i] = true;
00172             break;
00173         }
00174     }
00175  
00176     if (id == -1) {
00177         return NSAPI_ERROR_NO_SOCKET;
00178     }
00179     
00180     struct esp8266_socket *socket = new struct esp8266_socket;
00181     if (!socket) {
00182         return NSAPI_ERROR_NO_SOCKET;
00183     }
00184     
00185     socket->id = id;
00186     socket->proto = proto;
00187     socket->connected = false;
00188     *handle = socket;
00189     return 0;
00190 }
00191 
00192 int ESP8266Interface::socket_close(void *handle)
00193 {
00194     struct esp8266_socket *socket = (struct esp8266_socket *)handle;
00195     int err = 0;
00196     _esp.setTimeout(ESP8266_MISC_TIMEOUT);
00197  
00198     if (socket->connected && !_esp.close(socket->id)) {
00199         err = NSAPI_ERROR_DEVICE_ERROR;
00200     }
00201 
00202     socket->connected = false;
00203     _ids[socket->id] = false;
00204     delete socket;
00205     return err;
00206 }
00207 
00208 int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
00209 {
00210     return NSAPI_ERROR_UNSUPPORTED;
00211 }
00212 
00213 int ESP8266Interface::socket_listen(void *handle, int backlog)
00214 {
00215     return NSAPI_ERROR_UNSUPPORTED;
00216 }
00217 
00218 int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
00219 {
00220     struct esp8266_socket *socket = (struct esp8266_socket *)handle;
00221     _esp.setTimeout(ESP8266_MISC_TIMEOUT);
00222 
00223     const char *proto = (socket->proto == NSAPI_UDP) ? "UDP" : "TCP";
00224     if (!_esp.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
00225         return NSAPI_ERROR_DEVICE_ERROR;
00226     }
00227     
00228     socket->connected = true;
00229     return 0;
00230 }
00231     
00232 int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
00233 {
00234     return NSAPI_ERROR_UNSUPPORTED;
00235 }
00236 
00237 int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
00238 {
00239     struct esp8266_socket *socket = (struct esp8266_socket *)handle;
00240     _esp.setTimeout(ESP8266_SEND_TIMEOUT);
00241  
00242     if (!_esp.send(socket->id, data, size)) {
00243         return NSAPI_ERROR_DEVICE_ERROR;
00244     }
00245  
00246     return size;
00247 }
00248 
00249 int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
00250 {
00251     struct esp8266_socket *socket = (struct esp8266_socket *)handle;
00252     _esp.setTimeout(ESP8266_RECV_TIMEOUT);
00253  
00254     int32_t recv = _esp.recv(socket->id, data, size);
00255     if (recv < 0) {
00256         return NSAPI_ERROR_WOULD_BLOCK;
00257     }
00258  
00259     return recv;
00260 }
00261 
00262 int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
00263 {
00264     struct esp8266_socket *socket = (struct esp8266_socket *)handle;
00265 
00266     if (socket->connected && socket->addr != addr) {
00267         _esp.setTimeout(ESP8266_MISC_TIMEOUT);
00268         if (!_esp.close(socket->id)) {
00269             return NSAPI_ERROR_DEVICE_ERROR;
00270         }
00271         socket->connected = false;
00272     }
00273 
00274     if (!socket->connected) {
00275         int err = socket_connect(socket, addr);
00276         if (err < 0) {
00277             return err;
00278         }
00279         socket->addr = addr;
00280     }
00281     
00282     return socket_send(socket, data, size);
00283 }
00284 
00285 int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
00286 {
00287     struct esp8266_socket *socket = (struct esp8266_socket *)handle;
00288     int ret = socket_recv(socket, data, size);
00289     if (ret >= 0 && addr) {
00290         *addr = socket->addr;
00291     }
00292 
00293     return ret;
00294 }
00295 
00296 void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
00297 {
00298     struct esp8266_socket *socket = (struct esp8266_socket *)handle;    
00299     _cbs[socket->id].callback = callback;
00300     _cbs[socket->id].data = data;
00301 }
00302 
00303 void ESP8266Interface::event() {
00304     for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
00305         if (_cbs[i].callback) {
00306             _cbs[i].callback(_cbs[i].data);
00307         }
00308     }
00309 }