Added support for WNC M14A2A Cellular LTE Data Module.

Dependencies:   WNC14A2AInterface

Dependents:   http-example-wnc http-example-wnc-modified

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