Skip to content

Host stream write buffer for message oriented transmits #447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions utility/EthernetClientStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand All @@ -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)
{
}

Expand Down Expand Up @@ -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
Expand All @@ -128,6 +159,9 @@ EthernetClientStream::stop()
(*currentHostConnectionCallback)(HOST_CONNECTION_DISCONNECTED);
}
connected = false;
#ifdef WRITE_BUFFER_SIZE
writeBufferLength = 0;
#endif
time_connect = millis();
}

Expand All @@ -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();
Expand All @@ -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)
{
Expand Down
38 changes: 36 additions & 2 deletions utility/EthernetServerStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand All @@ -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();

Expand All @@ -58,21 +73,37 @@ EthernetServerStream::EthernetServerStream(IPAddress localip, uint16_t port)
: localip(localip),
port(port),
connected(false)
#ifdef WRITE_BUFFER_SIZE
, writeBufferLength(0)
#endif
{
}

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();
}

EthernetClient newClient = server.available();
if ( !newClient ) return false;
client = newClient;
connected = true;
#ifdef WRITE_BUFFER_SIZE
writeBufferLength = 0;
#endif
DEBUG_PRINTLN("Connected");
return true;
}
Expand Down Expand Up @@ -126,6 +157,9 @@ EthernetServerStream::stop()
client.stop();
}
connected = false;
#ifdef WRITE_BUFFER_SIZE
writeBufferLength = 0;
#endif
}

bool
Expand Down
27 changes: 23 additions & 4 deletions utility/WiFiClientStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

published under the same license.

Last updated April 23rd, 2016
Last updated March 21st, 2020
*/

#ifndef WIFI_CLIENT_STREAM_H
Expand All @@ -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();
}

Expand All @@ -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);
}
}
}
}
Expand Down Expand Up @@ -97,6 +113,9 @@ class WiFiClientStream : public WiFiStream
}
}
_connected = false;
#ifdef WRITE_BUFFER_SIZE
writeBufferLength = 0;
#endif
_time_connect = millis();
}

Expand Down
18 changes: 17 additions & 1 deletion utility/WiFiServerStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand All @@ -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);
Expand Down Expand Up @@ -100,6 +113,9 @@ class WiFiServerStream : public WiFiStream
}
}
_connected = false;
#ifdef WRITE_BUFFER_SIZE
writeBufferLength = 0;
#endif
}

};
Expand Down
36 changes: 34 additions & 2 deletions utility/WiFiStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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) {}
Expand Down Expand Up @@ -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
}

};
Expand Down