Commit 9a3ddca1 authored by Wouter Klop's avatar Wouter Klop

Updated AsyncTCP and arduinoWebsockets libraries. Also, moved wireless tasks...

Updated AsyncTCP and arduinoWebsockets libraries. Also, moved wireless tasks (IBus and wsServer) back to the main loop (core 1). While running on core 0, i2c issues were created due to the i2c bus being accessed by two different threads.
parent b590e9d2
......@@ -157,7 +157,7 @@
Gyro gain (not saved to EEPROM): <input id="j" type="range" min="0.5" max="1.5" step="0.01" oninput=sendData(this);><input type="text" id="j_value" readonly value="" style="width:40px"><br />
Gyro filter constant (not saved to EEPROM): <input id="n" type="range" min="0.9" max="1" step="0.001" oninput=sendData(this);><input type="text" id="n_value" readonly value="" style="width:40px"><br /><br />
Calibration<br />
<button type="button" onclick="sendCommand('k', 1)">Calibrate Gyro and save to EEPROM</button> (Put the robot without any movement to the ground and press the button. It is very buggy, if it is going crazy than power cycle and ignore this button.)<br />
<button type="button" onclick="sendCommand('k', 1)">Calibrate Gyro and save to EEPROM</button> (Put the robot without any movement to the ground and press the button.<br />
<button type="button" onclick="sendCommand('k', 2)">Calibrate ACC (Angle) and save to EEPROM</button> (Put the robot upright on its wheels and push the button ~10 times. For first calibration hold it by hand. When it is self balancing, repeat the calibration a few times without holding it.)<br />
</fieldset><br />
<fieldset>
......
......@@ -12,7 +12,7 @@
"type": "git",
"url": "https://github.com/me-no-dev/AsyncTCP.git"
},
"version": "1.0.1",
"version": "1.0.3",
"license": "LGPL-3.0",
"frameworks": "arduino",
"platforms": "espressif32",
......
name=AsyncTCP
version=1.0.0
version=1.0.3
author=Me-No-Dev
maintainer=Me-No-Dev
sentence=Async TCP Library for ESP32
......
......@@ -256,7 +256,7 @@ static void _tcp_error(void * arg, int8_t err) {
#include "lwip/priv/tcpip_priv.h"
typedef struct {
struct tcpip_api_call call;
struct tcpip_api_call_data call;
tcp_pcb * pcb;
int8_t err;
union {
......@@ -279,20 +279,24 @@ typedef struct {
};
} tcp_api_call_t;
static err_t _tcp_output_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = tcp_output(msg->pcb);
if(msg->pcb){
msg->err = tcp_output(msg->pcb);
} else {
msg->err = 0;
}
return msg->err;
}
static esp_err_t _tcp_output(tcp_pcb * pcb) {
tcp_api_call_t msg;
msg.pcb = pcb;
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_write_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags);
return msg->err;
......@@ -304,11 +308,11 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_
msg.write.data = data;
msg.write.size = size;
msg.write.apiflags = apiflags;
tcpip_api_call(_tcp_write_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_recved_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = 0;
tcp_recved(msg->pcb, msg->received);
......@@ -319,11 +323,11 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) {
tcp_api_call_t msg;
msg.pcb = pcb;
msg.received = len;
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_connect_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb);
return msg->err;
......@@ -335,11 +339,11 @@ static esp_err_t _tcp_connect(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port, tc
msg.connect.addr = addr;
msg.connect.port = port;
msg.connect.cb = cb;
tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_close_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = tcp_close(msg->pcb);
return msg->err;
......@@ -349,11 +353,11 @@ static esp_err_t _tcp_close(tcp_pcb * pcb) {
tcp_api_call_t msg;
msg.pcb = pcb;
//ets_printf("close 0x%08x\n", (uint32_t)pcb);
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_abort_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = 0;
tcp_abort(msg->pcb);
......@@ -364,11 +368,11 @@ static esp_err_t _tcp_abort(tcp_pcb * pcb) {
tcp_api_call_t msg;
msg.pcb = pcb;
//ets_printf("abort 0x%08x\n", (uint32_t)pcb);
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_bind_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port);
return msg->err;
......@@ -379,11 +383,11 @@ static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) {
msg.pcb = pcb;
msg.bind.addr = addr;
msg.bind.port = port;
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
static err_t _tcp_listen_api(struct tcpip_api_call *api_call_msg){
static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = 0;
msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog);
......@@ -394,7 +398,7 @@ static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) {
tcp_api_call_t msg;
msg.pcb = pcb;
msg.backlog = backlog?backlog:0xFF;
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call*)&msg);
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg);
return msg.pcb;
}
#define _tcp_listen(p) _tcp_listen_with_backlog(p, 0xFF);
......@@ -432,6 +436,8 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
, next(NULL)
, _in_lwip_thread(false)
{
//ets_printf("+: 0x%08x\n", (uint32_t)this);
_pcb = pcb;
if(_pcb){
_rx_last_packet = millis();
......@@ -447,6 +453,8 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
AsyncClient::~AsyncClient(){
if(_pcb)
_close();
//ets_printf("-: 0x%08x\n", (uint32_t)this);
}
bool AsyncClient::connect(IPAddress ip, uint16_t port){
......@@ -512,6 +520,7 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){
}
int8_t AsyncClient::_close(){
//ets_printf("X: 0x%08x\n", (uint32_t)this);
int8_t err = ERR_OK;
if(_pcb) {
//log_i("");
......@@ -520,6 +529,7 @@ int8_t AsyncClient::_close(){
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
_tcp_clear_events(this);
if(_in_lwip_thread){
err = tcp_close(_pcb);
} else {
......@@ -529,7 +539,6 @@ int8_t AsyncClient::_close(){
err = abort();
}
_pcb = NULL;
_tcp_clear_events(this);
if(_discard_cb)
_discard_cb(_discard_cb_arg, this);
}
......@@ -562,6 +571,13 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) {
}
int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
if(!_pcb || pcb != _pcb){
log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
if(pb){
pbuf_free(pb);
}
return ERR_OK;
}
_in_lwip_thread = false;
if(pb == NULL){
return _close();
......@@ -621,7 +637,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){
return ERR_OK;
}
void AsyncClient::_dns_found(ip_addr_t *ipaddr){
void AsyncClient::_dns_found(struct ip_addr *ipaddr){
_in_lwip_thread = true;
if(ipaddr){
connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port);
......@@ -943,31 +959,58 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){
}
void AsyncClient::_s_dns_found(const char * name, ip_addr_t * ipaddr, void * arg){
reinterpret_cast<AsyncClient*>(arg)->_dns_found(ipaddr);
void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){
if(arg){
reinterpret_cast<AsyncClient*>(arg)->_dns_found(ipaddr);
} else {
log_e("Bad Arg: 0x%08x", arg);
}
}
int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) {
reinterpret_cast<AsyncClient*>(arg)->_poll(pcb);
if(arg && pcb){
reinterpret_cast<AsyncClient*>(arg)->_poll(pcb);
} else {
log_e("Bad Args: 0x%08x 0x%08x", arg, pcb);
}
return ERR_OK;
}
int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) {
reinterpret_cast<AsyncClient*>(arg)->_recv(pcb, pb, err);
if(arg && pcb){
reinterpret_cast<AsyncClient*>(arg)->_recv(pcb, pb, err);
} else {
if(pb){
pbuf_free(pb);
}
log_e("Bad Args: 0x%08x 0x%08x", arg, pcb);
}
return ERR_OK;
}
int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) {
reinterpret_cast<AsyncClient*>(arg)->_sent(pcb, len);
if(arg && pcb){
reinterpret_cast<AsyncClient*>(arg)->_sent(pcb, len);
} else {
log_e("Bad Args: 0x%08x 0x%08x", arg, pcb);
}
return ERR_OK;
}
void AsyncClient::_s_error(void * arg, int8_t err) {
reinterpret_cast<AsyncClient*>(arg)->_error(err);
if(arg){
reinterpret_cast<AsyncClient*>(arg)->_error(err);
} else {
log_e("Bad Arg: 0x%08x", arg);
}
}
int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){
reinterpret_cast<AsyncClient*>(arg)->_connected(pcb, err);
if(arg && pcb){
reinterpret_cast<AsyncClient*>(arg)->_connected(pcb, err);
} else {
log_e("Bad Args: 0x%08x 0x%08x", arg, pcb);
}
return ERR_OK;
}
......@@ -1122,9 +1165,9 @@ void AsyncServer::end(){
tcp_arg(_pcb, NULL);
tcp_accept(_pcb, NULL);
if(_in_lwip_thread){
tcp_abort(_pcb);
tcp_close(_pcb);
} else {
_tcp_abort(_pcb);
_tcp_close(_pcb);
}
_pcb = NULL;
}
......
......@@ -43,7 +43,7 @@ typedef std::function<void(void*, AsyncClient*, struct pbuf *pb)> AcPacketHandle
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
struct tcp_pcb;
struct _ip_addr;
struct ip_addr;
class AsyncClient {
protected:
......@@ -81,7 +81,7 @@ class AsyncClient {
void _error(int8_t err);
int8_t _poll(tcp_pcb* pcb);
int8_t _sent(tcp_pcb* pcb, uint16_t len);
void _dns_found(struct _ip_addr *ipaddr);
void _dns_found(struct ip_addr *ipaddr);
public:
......@@ -108,13 +108,13 @@ class AsyncClient {
bool canSend();//ack is not pending
size_t space();
size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending
size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending
bool send();//send all data added with the method above
size_t ack(size_t len); //ack data that you have not acked using the method below
void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData
size_t write(const char* data);
size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true
size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true
uint8_t state();
bool connecting();
......@@ -161,7 +161,7 @@ class AsyncClient {
static void _s_error(void *arg, int8_t err);
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
static void _s_dns_found(const char *name, struct _ip_addr *ipaddr, void *arg);
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
bool _in_lwip_thread;
};
......
......@@ -84,6 +84,12 @@ void setup() {
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
// start heartbeat (optional)
// ping server every 15000 ms
// expect pong from server within 3000 ms
// consider connection disconnected if pong is not received 2 times
webSocket.enableHeartbeat(15000, 3000, 2);
}
......
......@@ -13,7 +13,7 @@
"type": "git",
"url": "https://github.com/Links2004/arduinoWebSockets.git"
},
"version": "2.1.2",
"version": "2.1.3",
"license": "LGPL-2.1",
"export": {
"exclude": [
......
name=WebSockets
version=2.1.2
version=2.1.3
author=Markus Sattler
maintainer=Markus Sattler
sentence=WebSockets for Arduino (Server + Client)
......
......@@ -77,12 +77,11 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea
* @param opcode WSopcode_t
* @param payload uint8_t * ptr to the payload
* @param length size_t length of the payload
* @param mask bool add dummy mask to the frame (needed for web browser)
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
* @param headerToPayload bool set true if the payload has reserved 14 Byte at the beginning to dynamically add the Header (payload neet to be in RAM!)
* @return true if ok
*/
bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool mask, bool fin, bool headerToPayload) {
bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin, bool headerToPayload) {
if(client->tcp && !client->tcp->connected()) {
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] not Connected!?\n", client->num);
......@@ -95,7 +94,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
}
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send message frame -------\n", client->num);
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u headerToPayload: %u\n", client->num, fin, opcode, mask, length, headerToPayload);
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u headerToPayload: %u\n", client->num, fin, opcode, client->cIsClient, length, headerToPayload);
if(opcode == WSop_text) {
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0)));
......@@ -119,7 +118,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
headerSize = 10;
}
if(mask) {
if(client->cIsClient) {
headerSize += 4;
}
......@@ -158,7 +157,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
// byte 1
*headerPtr = 0x00;
if(mask) {
if(client->cIsClient) {
*headerPtr |= bit(7); ///< set mask
}
......@@ -194,7 +193,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
headerPtr++;
}
if(mask) {
if(client->cIsClient) {
if(useInternBuffer) {
// if we use a Intern Buffer we can modify the data
// by this fact its possible the do the masking
......@@ -434,10 +433,12 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
break;
case WSop_ping:
// send pong back
sendFrame(client, WSop_pong, payload, header->payloadLen, true);
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] ping received (%s)\n", client->num, payload ? (const char*)payload : "");
sendFrame(client, WSop_pong, payload, header->payloadLen);
break;
case WSop_pong:
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get pong (%s)\n", client->num, payload ? (const char*)payload : "");
client->pongReceived = true;
break;
case WSop_close: {
#ifndef NODEBUG_WEBSOCKETS
......@@ -653,3 +654,46 @@ size_t WebSockets::write(WSclient_t * client, const char *out) {
if(out == NULL) return 0;
return write(client, (uint8_t*)out, strlen(out));
}
/**
* enable ping/pong heartbeat process
* @param client WSclient_t *
* @param pingInterval uint32_t how often ping will be sent
* @param pongTimeout uint32_t millis after which pong should timout if not received
* @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect
*/
void WebSockets::enableHeartbeat(WSclient_t * client, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount){
if(client == NULL) return;
client->pingInterval = pingInterval;
client->pongTimeout = pongTimeout;
client->disconnectTimeoutCount = disconnectTimeoutCount;
}
/**
* handle ping/pong heartbeat timeout process
* @param client WSclient_t *
*/
void WebSockets::handleHBTimeout(WSclient_t * client){
if (client->pingInterval) { // if heartbeat is enabled
uint32_t pi = millis() - client->lastPing;
if (client->pongReceived) {
client->pongTimeoutCount = 0;
} else {
if (pi > client->pongTimeout){ // pong not received in time
client->pongTimeoutCount++;
client->lastPing = millis() - client->pingInterval - 500; // force ping on the next run
DEBUG_WEBSOCKETS("[HBtimeout] pong TIMEOUT! lp=%d millis=%d pi=%d count=%d\n", client->lastPing, millis(), pi, client->pongTimeoutCount);
if (client->disconnectTimeoutCount && client->pongTimeoutCount >= client->disconnectTimeoutCount){
DEBUG_WEBSOCKETS("[HBtimeout] count=%d, DISCONNECTING\n", client->pongTimeoutCount);
clientDisconnect(client);
}
}
}
}
}
\ No newline at end of file
......@@ -241,6 +241,7 @@ typedef struct {
String cUrl; ///< http url
uint16_t cCode; ///< http code
bool cIsClient = false; ///< will be used for masking
bool cIsUpgrade; ///< Connection == Upgrade
bool cIsWebsocket; ///< Upgrade == websocket
......@@ -263,6 +264,13 @@ typedef struct {
bool cHttpHeadersValid; ///< non-websocket http header validity indicator
size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count
bool pongReceived;
uint32_t pingInterval; // how often ping will be sent, 0 means "heartbeat is not active"
uint32_t lastPing; // millis when last pong has been received
uint32_t pongTimeout; // interval in millis after which pong is considered to timeout
uint8_t disconnectTimeoutCount; // after how many subsequent pong timeouts discconnect will happen, 0 means "do not disconnect"
uint8_t pongTimeoutCount; // current pong timeout count
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
String cHttpLine; ///< HTTP header lines
#endif
......@@ -285,7 +293,7 @@ class WebSockets {
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) = 0;
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false);
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool fin = true, bool headerToPayload = false);
void headerDone(WSclient_t * client);
......@@ -302,6 +310,9 @@ class WebSockets {
virtual size_t write(WSclient_t * client, uint8_t *out, size_t n);
size_t write(WSclient_t * client, const char *out);
void enableHeartbeat(WSclient_t * client, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
void handleHBTimeout(WSclient_t * client);
};
......
......@@ -28,6 +28,7 @@
WebSocketsClient::WebSocketsClient() {
_cbEvent = NULL;
_client.num = 0;
_client.cIsClient = true;
_client.extraHeaders = WEBSOCKETS_STRING("Origin: file://");
}
......@@ -65,6 +66,10 @@ void WebSocketsClient::begin(const char *host, uint16_t port, const char * url,
_client.plainAuthorization = "";
_client.isSocketIO = false;
_client.lastPing = 0;
_client.pongReceived = false;
_client.pongTimeoutCount = 0;
#ifdef ESP8266
randomSeed(RANDOM_REG32);
#else
......@@ -169,6 +174,12 @@ void WebSocketsClient::loop(void) {
}
} else {
handleClientData();
if (_client.status == WSC_CONNECTED){
handleHBPing();
handleHBTimeout(&_client);
}
}
}
#endif
......@@ -194,7 +205,7 @@ bool WebSocketsClient::sendTXT(uint8_t * payload, size_t length, bool headerToPa
length = strlen((const char *) payload);
}
if(clientIsConnected(&_client)) {
return sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload);
return sendFrame(&_client, WSop_text, payload, length, true, headerToPayload);
}
return false;
}
......@@ -225,7 +236,7 @@ bool WebSocketsClient::sendTXT(String & payload) {
*/
bool WebSocketsClient::sendBIN(uint8_t * payload, size_t length, bool headerToPayload) {
if(clientIsConnected(&_client)) {
return sendFrame(&_client, WSop_binary, payload, length, true, true, headerToPayload);
return sendFrame(&_client, WSop_binary, payload, length, true, headerToPayload);
}
return false;
}
......@@ -242,7 +253,10 @@ bool WebSocketsClient::sendBIN(const uint8_t * payload, size_t length) {
*/
bool WebSocketsClient::sendPing(uint8_t * payload, size_t length) {
if(clientIsConnected(&_client)) {
return sendFrame(&_client, WSop_ping, payload, length, true);
bool sent = sendFrame(&_client, WSop_ping, payload, length);
if (sent)
_client.lastPing = millis();
return sent;
}
return false;
}
......@@ -714,7 +728,7 @@ void WebSocketsClient::connectedCb() {
}
void WebSocketsClient::connectFailedCb() {
DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Faild\n", _host.c_str(), _port);
DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Failed\n", _host.c_str(), _port);
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
......@@ -760,3 +774,36 @@ void WebSocketsClient::asyncConnect() {
}
#endif
/**
* send heartbeat ping to server in set intervals
*/
void WebSocketsClient::handleHBPing(){
if (_client.pingInterval == 0) return;
uint32_t pi = millis() - _client.lastPing;
if (pi > _client.pingInterval){
DEBUG_WEBSOCKETS("[WS-Client] sending HB ping\n");
if (sendPing()) {
_client.lastPing = millis();
_client.pongReceived = false;
}
}
}
/**
* enable ping/pong heartbeat process
* @param pingInterval uint32_t how often ping will be sent
* @param pongTimeout uint32_t millis after which pong should timout if not received
* @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect
*/
void WebSocketsClient::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount){
WebSockets::enableHeartbeat(&_client, pingInterval, pongTimeout, disconnectTimeoutCount);
}
/**
* disable ping/pong heartbeat process
*/
void WebSocketsClient::disableHeartbeat(){
_client.pingInterval = 0;
}
\ No newline at end of file
......@@ -86,6 +86,9 @@ class WebSocketsClient: private WebSockets {
void setReconnectInterval(unsigned long time);
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
void disableHeartbeat();
protected:
String _host;
uint16_t _port;
......@@ -115,6 +118,8 @@ class WebSocketsClient: private WebSockets {
void connectedCb();
void connectFailedCb();
void handleHBPing(); // send ping in specified intervals
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
void asyncConnect();
#endif
......
......@@ -184,7 +184,7 @@ bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bo
}
WSclient_t * client = &_clients[num];
if(clientIsConnected(client)) {
return sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
return sendFrame(client, WSop_text, payload, length, true, headerToPayload);
}
return false;
}
......@@ -222,7 +222,7 @@ bool WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool heade
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
client = &_clients[i];
if(clientIsConnected(client)) {
if(!sendFrame(client, WSop_text, payload, length, false, true, headerToPayload)) {
if(!sendFrame(client, WSop_text, payload, length, true, headerToPayload)) {
ret = false;
}
}
......@@ -263,7 +263,7 @@ bool WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bo
}
WSclient_t * client = &_clients[num];
if(clientIsConnected(client)) {
return sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload);
return sendFrame(client, WSop_binary, payload, length, true, headerToPayload);
}
return false;
}
......@@ -285,7 +285,7 @@ bool WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool heade
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
client = &_clients[i];
if(clientIsConnected(client)) {
if(!sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload)) {
if(!sendFrame(client, WSop_binary, payload, length, true, headerToPayload)) {
ret = false;
}
}
......@@ -868,3 +868,6 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
}
}
}
......@@ -17,3 +17,4 @@ monitor_speed = 115200
; upload_port = COM3
; upload_port = balancingrobot.local
upload_port = 192.168.178.33
; upload_port = 192.168.4.1
......@@ -30,7 +30,7 @@ Also, you have to publish all modifications.
#include <SPIFFS.h>
#include <SPIFFSEditor.h>
#include <fastStepper.h>
#include <par.h>
// #include <par.h>
#include <Preferences.h> // for storing settings
// ----- Type definitions
......@@ -127,16 +127,16 @@ float speedFilterConstant = 0.9;
const char host[] = "balancingrobot";
// ----- Parameter definitions -----
void updatePIDParameters() {
pidAngle.updateParameters();
pidSpe