diff --git a/utility/EthernetClientStream.h b/utility/EthernetClientStream.h index 73ed5ca4..5ca2d126 100644 --- a/utility/EthernetClientStream.h +++ b/utility/EthernetClientStream.h @@ -31,6 +31,17 @@ #define HOST_CONNECTION_DISCONNECTED 0 #define HOST_CONNECTION_CONNECTED 1 +// If defined and set to a value higher than 1 all single bytes writes +// will be buffered until one of the following conditions is met: +// 1) write buffer full +// 2) any call to read(), available(), maintain(), peek() or flush() +// By combining the buffered bytes into a single TCP frame this feature will significantly +// reduce the network and receiver load by the factor 1/(1/20 + 1/bufferedSize). +// Buffer sizes up to 80 have been tested successfully. Note that higher buffer values +// may cause slight delays between an event and the network transmission. +#define WRITE_BUFFER_SIZE 40 + + extern "C" { // callback function types typedef void (*hostConnectionCallbackFunction)(byte); @@ -56,6 +67,10 @@ class EthernetClientStream : public Stream uint16_t port; bool connected; uint32_t time_connect; +#ifdef WRITE_BUFFER_SIZE + uint8_t writeBuffer[WRITE_BUFFER_SIZE]; + uint8_t writeBufferLength; +#endif hostConnectionCallbackFunction currentHostConnectionCallback; bool maintain(); void stop(); @@ -73,8 +88,11 @@ EthernetClientStream::EthernetClientStream(Client &client, IPAddress localip, IP ip(ip), host(host), port(port), - connected(false) - , currentHostConnectionCallback(nullptr) + connected(false), +#ifdef WRITE_BUFFER_SIZE + writeBufferLength(0), +#endif + currentHostConnectionCallback(nullptr) { } @@ -105,7 +123,20 @@ void EthernetClientStream::flush() size_t EthernetClientStream::write(uint8_t c) { +#ifdef WRITE_BUFFER_SIZE + if (connected) { + // buffer new byte and send buffer when full + writeBuffer[writeBufferLength++] = c; + if (writeBufferLength >= WRITE_BUFFER_SIZE) { + return maintain()? 1 : 0; + } + return 1; + } else { + return 0; + } +#else return maintain() ? client.write(c) : 0; +#endif } void @@ -128,6 +159,9 @@ EthernetClientStream::stop() (*currentHostConnectionCallback)(HOST_CONNECTION_DISCONNECTED); } connected = false; +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif time_connect = millis(); } @@ -140,8 +174,16 @@ EthernetClientStream::attach(hostConnectionCallbackFunction newFunction) bool EthernetClientStream::maintain() { - if (client && client.connected()) + if (client && client.connected()) { +#ifdef WRITE_BUFFER_SIZE + // send buffered bytes + if (writeBufferLength) { + client.write(writeBuffer, writeBufferLength); + writeBufferLength = 0; + } +#endif return true; + } if (connected) { stop(); @@ -153,6 +195,9 @@ EthernetClientStream::maintain() time_connect = millis(); DEBUG_PRINTLN("Connection failed. Attempting to reconnect..."); } else { +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif DEBUG_PRINTLN("Connected"); if (currentHostConnectionCallback) { diff --git a/utility/EthernetServerStream.h b/utility/EthernetServerStream.h index 56f541e9..c1300c48 100644 --- a/utility/EthernetServerStream.h +++ b/utility/EthernetServerStream.h @@ -10,7 +10,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated July 10th, 2017 + Last updated March 21st 2020 */ #ifndef ETHERNETSERVERSTREAM_H @@ -23,6 +23,17 @@ //#define SERIAL_DEBUG #include "firmataDebug.h" +// If defined and set to a value higher than 1 all single bytes writes +// will be buffered until one of the following conditions is met: +// 1) write buffer full +// 2) any call to read(), available(), maintain(), peek() or flush() +// By combining the buffered bytes into a single TCP frame this feature will significantly +// reduce the network and receiver load by the factor 1/(1/20 + 1/bufferedSize). +// Buffer sizes up to 80 have been tested successfully. Note that higher buffer values +// may cause slight delays between an event and the network transmission. +#define WRITE_BUFFER_SIZE 40 + + class EthernetServerStream : public Stream { public: @@ -39,6 +50,10 @@ class EthernetServerStream : public Stream IPAddress localip; uint16_t port; bool connected; +#ifdef WRITE_BUFFER_SIZE + uint8_t writeBuffer[WRITE_BUFFER_SIZE]; + uint8_t writeBufferLength; +#endif bool maintain(); void stop(); @@ -58,6 +73,9 @@ EthernetServerStream::EthernetServerStream(IPAddress localip, uint16_t port) : localip(localip), port(port), connected(false) +#ifdef WRITE_BUFFER_SIZE + , writeBufferLength(0) +#endif { } @@ -65,7 +83,17 @@ bool EthernetServerStream::connect_client() { if ( connected ) { - if ( client && client.connected() ) return true; + if ( client && client.connected() ) + { +#ifdef WRITE_BUFFER_SIZE + // send buffered bytes + if (writeBufferLength) { + client.write(writeBuffer, writeBufferLength); + writeBufferLength = 0; + } +#endif + return true; + } stop(); } @@ -73,6 +101,9 @@ bool EthernetServerStream::connect_client() if ( !newClient ) return false; client = newClient; connected = true; +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif DEBUG_PRINTLN("Connected"); return true; } @@ -126,6 +157,9 @@ EthernetServerStream::stop() client.stop(); } connected = false; +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif } bool diff --git a/utility/WiFiClientStream.h b/utility/WiFiClientStream.h index 7fd30af6..387ddab2 100644 --- a/utility/WiFiClientStream.h +++ b/utility/WiFiClientStream.h @@ -20,7 +20,7 @@ published under the same license. - Last updated April 23rd, 2016 + Last updated March 21st, 2020 */ #ifndef WIFI_CLIENT_STREAM_H @@ -43,7 +43,17 @@ class WiFiClientStream : public WiFiStream { if ( _connected ) { - if ( _client && _client.connected() ) return true; + if ( _client && _client.connected() ) + { +#ifdef WRITE_BUFFER_SIZE + // send buffered bytes + if (writeBufferLength) { + _client.write(writeBuffer, writeBufferLength); + writeBufferLength = 0; + } +#endif + return true; + } stop(); } @@ -58,9 +68,15 @@ class WiFiClientStream : public WiFiStream { _time_connect = millis(); } - else if ( _currentHostConnectionCallback ) + else { - (*_currentHostConnectionCallback)(HOST_CONNECTION_CONNECTED); +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif + if ( _currentHostConnectionCallback ) + { + (*_currentHostConnectionCallback)(HOST_CONNECTION_CONNECTED); + } } } } @@ -97,6 +113,9 @@ class WiFiClientStream : public WiFiStream } } _connected = false; +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif _time_connect = millis(); } diff --git a/utility/WiFiServerStream.h b/utility/WiFiServerStream.h index 1404b056..6bcbab7e 100644 --- a/utility/WiFiServerStream.h +++ b/utility/WiFiServerStream.h @@ -42,7 +42,17 @@ class WiFiServerStream : public WiFiStream { if ( _connected ) { - if ( _client && _client.connected() ) return true; + if ( _client && _client.connected() ) + { +#ifdef WRITE_BUFFER_SIZE + // send buffered bytes + if (writeBufferLength) { + _client.write(writeBuffer, writeBufferLength); + writeBufferLength = 0; + } +#endif + return true; + } stop(); } @@ -51,6 +61,9 @@ class WiFiServerStream : public WiFiStream if ( !newClient ) return false; _client = newClient; _connected = true; +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif if ( _currentHostConnectionCallback ) { (*_currentHostConnectionCallback)(HOST_CONNECTION_CONNECTED); @@ -100,6 +113,9 @@ class WiFiServerStream : public WiFiStream } } _connected = false; +#ifdef WRITE_BUFFER_SIZE + writeBufferLength = 0; +#endif } }; diff --git a/utility/WiFiStream.h b/utility/WiFiStream.h index 1ad44bbb..0c54ff6d 100644 --- a/utility/WiFiStream.h +++ b/utility/WiFiStream.h @@ -15,7 +15,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated April 23rd, 2016 + Last updated March 21st, 2020 */ #ifndef WIFI_STREAM_H @@ -27,6 +27,17 @@ #define HOST_CONNECTION_DISCONNECTED 0 #define HOST_CONNECTION_CONNECTED 1 +// If defined and set to a value higher than 1 all single bytes writes +// will be buffered until one of the following conditions is met: +// 1) write buffer full +// 2) any call to read(), available(), maintain(), peek() or flush() +// By combining the buffered bytes into a single TCP frame this feature will significantly +// reduce the network and receiver load by the factor 1/(1/20 + 1/bufferedSize). +// Buffer sizes up to 80 have been tested successfully. Note that higher buffer values +// may cause slight delays between an event and the network transmission. +#define WRITE_BUFFER_SIZE 40 + + extern "C" { // callback function types typedef void (*hostConnectionCallbackFunction)(byte); @@ -38,6 +49,10 @@ class WiFiStream : public Stream WiFiClient _client; bool _connected = false; hostConnectionCallbackFunction _currentHostConnectionCallback; +#ifdef WRITE_BUFFER_SIZE + uint8_t writeBuffer[WRITE_BUFFER_SIZE]; + uint8_t writeBufferLength; +#endif //configuration members IPAddress _local_ip; // DHCP @@ -58,7 +73,11 @@ class WiFiStream : public Stream public: /** constructor for TCP server */ - WiFiStream(uint16_t server_port) : _port(server_port) {} + WiFiStream(uint16_t server_port) : +#ifdef WRITE_BUFFER_SIZE + writeBufferLength(0), +#endif + _port(server_port) {} /** constructor for TCP client */ WiFiStream(IPAddress server_ip, uint16_t server_port) : _remote_ip(server_ip), _port(server_port) {} @@ -218,7 +237,20 @@ class WiFiStream : public Stream inline size_t write(uint8_t byte) { +#ifdef WRITE_BUFFER_SIZE + if (connect_client()) { + // buffer new byte and send buffer when full + writeBuffer[writeBufferLength++] = byte; + if (writeBufferLength >= WRITE_BUFFER_SIZE) { + return maintain()? 1 : 0; + } + return 1; + } else { + return 0; + } +#else return connect_client() ? _client.write( byte ) : 0; +#endif } };