Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: WNC14A2AInterface
esp8266-driver/ESP8266/ESP8266.cpp
- Committer:
- JMF
- Date:
- 2017-04-19
- Revision:
- 4:daf182af022b
- Parent:
- 0:2563b0415d1f
File content as of revision 4:daf182af022b:
/* ESP8266 Example
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ESP8266.h"
ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
: _serial(tx, rx, 1024), _parser(_serial)
, _packets(0), _packets_end(&_packets)
{
_serial.baud(115200);
_parser.debugOn(debug);
}
bool ESP8266::startup(int mode)
{
//only 3 valid modes
if(mode < 1 || mode > 3) {
return false;
}
bool success = reset()
&& _parser.send("AT+CWMODE=%d", mode)
&& _parser.recv("OK")
&& _parser.send("AT+CIPMUX=1")
&& _parser.recv("OK");
_parser.oob("+IPD", this, &ESP8266::_packet_handler);
return success;
}
bool ESP8266::reset(void)
{
for (int i = 0; i < 2; i++) {
if (_parser.send("AT+RST")
&& _parser.recv("OK\r\nready")) {
return true;
}
}
return false;
}
bool ESP8266::dhcp(bool enabled, int mode)
{
//only 3 valid modes
if(mode < 0 || mode > 2) {
return false;
}
return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
&& _parser.recv("OK");
}
bool ESP8266::connect(const char *ap, const char *passPhrase)
{
return _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
&& _parser.recv("OK");
}
bool ESP8266::disconnect(void)
{
return _parser.send("AT+CWQAP") && _parser.recv("OK");
}
const char *ESP8266::getIPAddress(void)
{
if (!(_parser.send("AT+CIFSR")
&& _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
&& _parser.recv("OK"))) {
return 0;
}
return _ip_buffer;
}
const char *ESP8266::getMACAddress(void)
{
if (!(_parser.send("AT+CIFSR")
&& _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
&& _parser.recv("OK"))) {
return 0;
}
return _mac_buffer;
}
const char *ESP8266::getGateway()
{
if (!(_parser.send("AT+CIPSTA?")
&& _parser.recv("+CIPSTA:gateway:\"%15[^\"]\"", _gateway_buffer)
&& _parser.recv("OK"))) {
return 0;
}
return _gateway_buffer;
}
const char *ESP8266::getNetmask()
{
if (!(_parser.send("AT+CIPSTA?")
&& _parser.recv("+CIPSTA:netmask:\"%15[^\"]\"", _netmask_buffer)
&& _parser.recv("OK"))) {
return 0;
}
return _netmask_buffer;
}
int8_t ESP8266::getRSSI()
{
int8_t rssi;
char bssid[18];
if (!(_parser.send("AT+CWJAP?")
&& _parser.recv("+CWJAP:\"%*[^\"]\",\"%17[^\"]\"", bssid)
&& _parser.recv("OK"))) {
return 0;
}
if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid)
&& _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
&& _parser.recv("OK"))) {
return 0;
}
return rssi;
}
bool ESP8266::isConnected(void)
{
return getIPAddress() != 0;
}
int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
{
unsigned cnt = 0;
nsapi_wifi_ap_t ap;
if (!_parser.send("AT+CWLAP")) {
return NSAPI_ERROR_DEVICE_ERROR;
}
while (recv_ap(&ap)) {
if (cnt < limit) {
res[cnt] = WiFiAccessPoint(ap);
}
cnt++;
if (limit != 0 && cnt >= limit) {
break;
}
}
return cnt;
}
bool ESP8266::open(const char *type, int id, const char* addr, int port)
{
//IDs only 0-4
if(id > 4) {
return false;
}
return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
&& _parser.recv("OK");
}
bool ESP8266::send(int id, const void *data, uint32_t amount)
{
//May take a second try if device is busy
for (unsigned i = 0; i < 2; i++) {
if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
&& _parser.recv(">")
&& _parser.write((char*)data, (int)amount) >= 0) {
return true;
}
}
return false;
}
void ESP8266::_packet_handler()
{
int id;
uint32_t amount;
// parse out the packet
if (!_parser.recv(",%d,%d:", &id, &amount)) {
return;
}
struct packet *packet = (struct packet*)malloc(
sizeof(struct packet) + amount);
if (!packet) {
return;
}
packet->id = id;
packet->len = amount;
packet->next = 0;
if (!(_parser.read((char*)(packet + 1), amount))) {
free(packet);
return;
}
// append to packet list
*_packets_end = packet;
_packets_end = &packet->next;
}
int32_t ESP8266::recv(int id, void *data, uint32_t amount)
{
while (true) {
// check if any packets are ready for us
for (struct packet **p = &_packets; *p; p = &(*p)->next) {
if ((*p)->id == id) {
struct packet *q = *p;
if (q->len <= amount) { // Return and remove full packet
memcpy(data, q+1, q->len);
if (_packets_end == &(*p)->next) {
_packets_end = p;
}
*p = (*p)->next;
uint32_t len = q->len;
free(q);
return len;
} else { // return only partial packet
memcpy(data, q+1, amount);
q->len -= amount;
memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
return amount;
}
}
}
// Wait for inbound packet
if (!_parser.recv("OK")) {
return -1;
}
}
}
bool ESP8266::close(int id)
{
//May take a second try if device is busy
for (unsigned i = 0; i < 2; i++) {
if (_parser.send("AT+CIPCLOSE=%d", id)
&& _parser.recv("OK")) {
return true;
}
}
return false;
}
void ESP8266::setTimeout(uint32_t timeout_ms)
{
_parser.setTimeout(timeout_ms);
}
bool ESP8266::readable()
{
return _serial.readable();
}
bool ESP8266::writeable()
{
return _serial.writeable();
}
void ESP8266::attach(Callback<void()> func)
{
_serial.attach(func);
}
bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
{
int sec;
bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%d", &sec, ap->ssid,
&ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
&ap->bssid[5], &ap->channel);
ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
return ret;
}