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