Skip to content

Commit

Permalink
ONME-3433 ESP8266 driver support for UDP get - modified ESP8266 drive…
Browse files Browse the repository at this point in the history
…r to support UDP connection in server mode (get)
  • Loading branch information
Marcin Tomczyk committed Jan 31, 2020
1 parent f469f71 commit 46718d0
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 21 deletions.
41 changes: 35 additions & 6 deletions components/wifi/esp8266-driver/ESP8266/ESP8266.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,17 @@ bool ESP8266::disconnect(void)
return done;
}

bool ESP8266::ip_info_print(int enable)
{
_smutex.lock();
_disconnect = true;
bool done = _parser.send("AT+CIPDINFO=%d", enable) && _parser.recv("OK\n");
_smutex.unlock();

return done;
}


const char *ESP8266::ip_addr(void)
{
_smutex.lock();
Expand Down Expand Up @@ -508,11 +519,13 @@ int ESP8266::scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned
return cnt;
}

nsapi_error_t ESP8266::open_udp(int id, const char *addr, int port, int local_port)
nsapi_error_t ESP8266::open_udp(int id, const char *addr, int port, int local_port, int udp_mode)
{
static const char *type = "UDP";
bool done = false;

ip_info_print(1);

_smutex.lock();

// process OOB so that _sock_i reflects the correct state of the socket
Expand All @@ -533,7 +546,7 @@ nsapi_error_t ESP8266::open_udp(int id, const char *addr, int port, int local_po

for (int i = 0; i < 2; i++) {
if (local_port) {
done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d", id, type, addr, port, local_port);
done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d,%d", id, type, addr, port, local_port, udp_mode);
} else {
done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port);
}
Expand Down Expand Up @@ -572,6 +585,8 @@ nsapi_error_t ESP8266::open_tcp(int id, const char *addr, int port, int keepaliv
static const char *type = "TCP";
bool done = false;

ip_info_print(1);

if (!addr) {
return NSAPI_ERROR_PARAMETER;
}
Expand Down Expand Up @@ -754,6 +769,7 @@ nsapi_size_or_error_t ESP8266::send(int id, const void *data, uint32_t amount)
void ESP8266::_oob_packet_hdlr()
{
int id;
int port;
int amount;
int pdu_len;

Expand All @@ -763,6 +779,8 @@ void ESP8266::_oob_packet_hdlr()
}

if (_tcp_passive && _sock_i[id].open == true && _sock_i[id].proto == NSAPI_TCP) {
//For TCP +IPD return only id and amount and it is independent on AT+CIPDINFO settings
//Unfortunately no information about that in ESP manual but it has sense.
if (_parser.recv("%d\n", &amount)) {
_sock_i[id].tcp_data_avbl = amount;

Expand All @@ -772,8 +790,12 @@ void ESP8266::_oob_packet_hdlr()
}
}
return;
} else if (!_parser.scanf("%d:", &amount)) {
return;
} else {
if (!(_parser.scanf("%d,", &amount)
&& _parser.scanf("%15[^,],", _ip_buffer)
&& _parser.scanf("%d:", &port))) {
return;
}
}

pdu_len = sizeof(struct packet) + amount;
Expand All @@ -791,6 +813,10 @@ void ESP8266::_oob_packet_hdlr()
_heap_usage += pdu_len;

packet->id = id;
if (_sock_i[id].proto == NSAPI_UDP) {
packet->remote_port = port;
memcpy(packet->remote_ip, _ip_buffer, 16);
}
packet->len = amount;
packet->alloc_len = amount;
packet->next = 0;
Expand Down Expand Up @@ -943,7 +969,7 @@ int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout)
return NSAPI_ERROR_WOULD_BLOCK;
}

int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount, uint32_t timeout)
int32_t ESP8266::recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, uint32_t timeout)
{
_smutex.lock();
set_timeout(timeout);
Expand All @@ -956,9 +982,12 @@ int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount, uint32_t timeout)

// check if any packets are ready for us
for (struct packet **p = &_packets; *p; p = &(*p)->next) {
if ((*p)->id == id) {
if ((*p)->id == socket->id) {
struct packet *q = *p;

socket->addr.set_ip_address((*p)->remote_ip);
socket->addr.set_port((*p)->remote_port);

// Return and remove packet (truncated if necessary)
uint32_t len = q->len < amount ? q->len : amount;
memcpy(data, q + 1, len);
Expand Down
25 changes: 23 additions & 2 deletions components/wifi/esp8266-driver/ESP8266/ESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "platform/mbed_error.h"
#include "rtos/Mutex.h"
#include "rtos/ThisThread.h"
#include "features/netsocket/SocketAddress.h"

// Various timeouts for different ESP8266 operations
#ifndef ESP8266_CONNECT_TIMEOUT
Expand Down Expand Up @@ -64,6 +65,15 @@
#define FW_AT_LEAST_VERSION(MAJOR,MINOR,PATCH,NUSED/*Not used*/,REF) \
(((MAJOR)*1000000+(MINOR)*10000+(PATCH)*100) >= REF ? true : false)

struct esp8266_socket {
int id;
nsapi_protocol_t proto;
bool connected;
bool bound;
SocketAddress addr;
int keepalive; // TCP
};

/** ESP8266Interface class.
This is an interface to a ESP8266 radio.
*/
Expand Down Expand Up @@ -167,6 +177,14 @@ class ESP8266 {
*/
bool disconnect(void);

/**
* Enable or disable Remote IP and Port printing with +IPD
*
* @param enable, 1 on, 0 off
* @return true only if ESP8266 is disconnected successfully
*/
bool ip_info_print(int enable);

/**
* Get the IP address of ESP8266
*
Expand Down Expand Up @@ -236,9 +254,10 @@ class ESP8266 {
* @param addr the IP address of the destination
* @param port the port on the destination
* @param local_port UDP socket's local port, zero means any
* @param udp_mode UDP socket's mode, zero means can't change remote, 1 can change once, 2 can change multiple times
* @return NSAPI_ERROR_OK in success, negative error code in failure
*/
nsapi_error_t open_udp(int id, const char *addr, int port, int local_port = 0);
nsapi_error_t open_udp(int id, const char *addr, int port, int local_port = 0, int udp_mode = 0);

/**
* Open a socketed connection
Expand Down Expand Up @@ -271,7 +290,7 @@ class ESP8266 {
* @param amount number of bytes to be received
* @return the number of bytes received
*/
int32_t recv_udp(int id, void *data, uint32_t amount, uint32_t timeout = ESP8266_RECV_TIMEOUT);
int32_t recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, uint32_t timeout = ESP8266_RECV_TIMEOUT);

/**
* Receives stream data from an open TCP socket
Expand Down Expand Up @@ -442,6 +461,8 @@ class ESP8266 {
struct packet {
struct packet *next;
int id;
char remote_ip[16];
int remote_port;
uint32_t len; // Remaining length
uint32_t alloc_len; // Original length
// data follows
Expand Down
35 changes: 22 additions & 13 deletions components/wifi/esp8266-driver/ESP8266Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@

#define ESP8266_WIFI_IF_NAME "es0"

#define LOCAL_ADDR "127.0.0.1"

using namespace mbed;
using namespace rtos;

Expand Down Expand Up @@ -750,14 +752,6 @@ nsapi_error_t ESP8266Interface::_reset()
return _esp.at_available() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
}

struct esp8266_socket {
int id;
nsapi_protocol_t proto;
bool connected;
SocketAddress addr;
int keepalive; // TCP
};

int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
{
// Look for an unused socket
Expand All @@ -783,6 +777,7 @@ int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
socket->id = id;
socket->proto = proto;
socket->connected = false;
socket->bound = false;
socket->keepalive = 0;
*handle = socket;
return 0;
Expand All @@ -801,11 +796,16 @@ int ESP8266Interface::socket_close(void *handle)
err = NSAPI_ERROR_DEVICE_ERROR;
}

if (socket->bound && !_esp.close(socket->id)) {
err = NSAPI_ERROR_DEVICE_ERROR;
}

_cbs[socket->id].callback = NULL;
_cbs[socket->id].data = NULL;
core_util_atomic_store_u8(&_cbs[socket->id].deferred, false);

socket->connected = false;
socket->bound = false;
_sock_i[socket->id].open = false;
_sock_i[socket->id].sport = 0;
delete socket;
Expand All @@ -828,12 +828,17 @@ int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
for (int id = 0; id < ESP8266_SOCKET_COUNT; id++) {
if (_sock_i[id].sport == address.get_port() && id != socket->id) { // Port already reserved by another socket
return NSAPI_ERROR_PARAMETER;
} else if (id == socket->id && socket->connected) {
} else if (id == socket->id && (socket->connected || socket->bound)) {
return NSAPI_ERROR_PARAMETER;
}
}
_sock_i[socket->id].sport = address.get_port();
return 0;

int ret = _esp.open_udp(socket->id, LOCAL_ADDR, address.get_port(), _sock_i[socket->id].sport, 2);

socket->bound = (ret == NSAPI_ERROR_OK) ? true : false;

return ret;
}

return NSAPI_ERROR_UNSUPPORTED;
Expand All @@ -854,7 +859,7 @@ int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
}

if (socket->proto == NSAPI_UDP) {
ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _sock_i[socket->id].sport);
ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _sock_i[socket->id].sport, 0);
} else {
ret = _esp.open_tcp(socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive);
}
Expand Down Expand Up @@ -925,7 +930,7 @@ int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
socket->connected = false;
}
} else {
recv = _esp.recv_udp(socket->id, data, size);
recv = _esp.recv_udp(socket, data, size);
}

return recv;
Expand All @@ -950,14 +955,18 @@ int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, con
socket->connected = false;
}

if (!socket->connected) {
if (!socket->connected && !socket->bound) {
int err = socket_connect(socket, addr);
if (err < 0) {
return err;
}
socket->addr = addr;
}

if (socket->bound) {
socket->addr = addr;
}

return socket_send(socket, data, size);
}

Expand Down

0 comments on commit 46718d0

Please sign in to comment.