Hardened (dis)connections
Added support fot multiple sessions (Currently 5 max. Each connection costs RAM!) Each session can send data to the gateway. Data from the gateway will be broadcasted to all connected clients. Added serial logging of client (dis)connections. Inspect serial terminal in case of problems.
This commit is contained in:
@@ -123,24 +123,34 @@ MySensor gw(transport, hw
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
#define IP_PORT 5003 // The port you want to open
|
#define IP_PORT 5003 // The port you want to open
|
||||||
|
#define MAX_SRV_CLIENTS 5 // how many clients should be able to telnet to this ESP8266
|
||||||
|
|
||||||
// a R/W server on the port
|
// a R/W server on the port
|
||||||
WiFiServer server(IP_PORT);
|
static WiFiServer server(IP_PORT);
|
||||||
// handle to open connection
|
static WiFiClient clients[MAX_SRV_CLIENTS];
|
||||||
WiFiClient client;
|
static bool clientsConnected[MAX_SRV_CLIENTS];
|
||||||
|
static inputBuffer inputString[MAX_SRV_CLIENTS];
|
||||||
|
|
||||||
char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface
|
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||||
int inputPos = 0;
|
|
||||||
bool sentReady = false;
|
|
||||||
|
|
||||||
void output(const char *fmt, ... ) {
|
|
||||||
va_list args;
|
void output(const char *fmt, ... )
|
||||||
va_start (args, fmt );
|
{
|
||||||
vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args);
|
char serialBuffer[MAX_SEND_LENGTH];
|
||||||
va_end (args);
|
va_list args;
|
||||||
Serial.print(serialBuffer);
|
va_start (args, fmt );
|
||||||
server.write(serialBuffer);
|
vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args);
|
||||||
|
va_end (args);
|
||||||
|
Serial.print(serialBuffer);
|
||||||
|
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++)
|
||||||
|
{
|
||||||
|
if (clients[i] && clients[i].connected())
|
||||||
|
{
|
||||||
|
// Serial.print("Client "); Serial.print(i); Serial.println(" write");
|
||||||
|
clients[i].write((uint8_t*)serialBuffer, strlen(serialBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
@@ -153,7 +163,8 @@ void setup()
|
|||||||
Serial.print("Connecting to "); Serial.println(ssid);
|
Serial.print("Connecting to "); Serial.println(ssid);
|
||||||
|
|
||||||
(void)WiFi.begin(ssid, pass);
|
(void)WiFi.begin(ssid, pass);
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.print(".");
|
Serial.print(".");
|
||||||
}
|
}
|
||||||
@@ -168,6 +179,7 @@ void setup()
|
|||||||
|
|
||||||
// start listening for clients
|
// start listening for clients
|
||||||
server.begin();
|
server.begin();
|
||||||
|
server.setNoDelay(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -177,46 +189,73 @@ void loop() {
|
|||||||
checkButtonTriggeredInclusion();
|
checkButtonTriggeredInclusion();
|
||||||
checkInclusionFinished();
|
checkInclusionFinished();
|
||||||
|
|
||||||
//check if there are any new clients
|
// Go over list of clients and stop any that are no longer connected.
|
||||||
if (server.hasClient())
|
// If the server has a new client connection it will be assigned to a free slot.
|
||||||
|
bool allSlotsOccupied = true;
|
||||||
|
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++)
|
||||||
{
|
{
|
||||||
if (client)
|
if (!clients[i].connected())
|
||||||
{
|
{
|
||||||
client.stop();
|
if (clientsConnected[i])
|
||||||
|
{
|
||||||
|
Serial.print("Client "); Serial.print(i); Serial.println(" disconnected");
|
||||||
|
clients[i].stop();
|
||||||
|
}
|
||||||
|
//check if there are any new clients
|
||||||
|
if (server.hasClient())
|
||||||
|
{
|
||||||
|
clients[i] = server.available();
|
||||||
|
inputString[i].idx = 0;
|
||||||
|
Serial.print("Client "); Serial.print(i); Serial.println(" connected");
|
||||||
|
output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client = server.available();
|
bool connected = clients[i].connected();
|
||||||
output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY);
|
clientsConnected[i] = connected;
|
||||||
|
allSlotsOccupied &= connected;
|
||||||
|
}
|
||||||
|
if (allSlotsOccupied && server.hasClient())
|
||||||
|
{
|
||||||
|
//no free/disconnected spot so reject
|
||||||
|
Serial.println("No free slot available");
|
||||||
|
WiFiClient c = server.available();
|
||||||
|
c.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client) {
|
// Loop over clients connect and read available data
|
||||||
if (!client.connected()) {
|
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++)
|
||||||
client.stop();
|
{
|
||||||
} else if (client.available()) {
|
while(clients[i].connected() && clients[i].available())
|
||||||
// read the bytes incoming from the client
|
{
|
||||||
char inChar = client.read();
|
char inChar = clients[i].read();
|
||||||
if (inputPos<MAX_RECEIVE_LENGTH-1) {
|
if ( inputString[i].idx < MAX_RECEIVE_LENGTH - 1 )
|
||||||
// if newline then command is complete
|
{
|
||||||
if (inChar == '\n') {
|
// if newline then command is complete
|
||||||
Serial.println("Finished");
|
if (inChar == '\n')
|
||||||
// a command was issued by the client
|
{
|
||||||
// we will now try to send it to the actuator
|
// a command was issued by the client
|
||||||
inputString[inputPos] = 0;
|
// we will now try to send it to the actuator
|
||||||
|
inputString[i].string[inputString[i].idx] = 0;
|
||||||
|
|
||||||
// echo the string to the serial port
|
// echo the string to the serial port
|
||||||
Serial.print(inputString);
|
Serial.print("Client "); Serial.print(i); Serial.print(": "); Serial.println(inputString[i].string);
|
||||||
|
|
||||||
parseAndSend(gw, inputString);
|
parseAndSend(gw, inputString[i].string);
|
||||||
|
|
||||||
// clear the string:
|
// clear the string:
|
||||||
inputPos = 0;
|
inputString[i].idx = 0;
|
||||||
} else {
|
// Finished with this client's message. Next loop() we'll see if there's more to read.
|
||||||
// add it to the inputString:
|
break;
|
||||||
inputString[inputPos] = inChar;
|
} else {
|
||||||
inputPos++;
|
// add it to the inputString:
|
||||||
}
|
inputString[i].string[inputString[i].idx++] = inChar;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Incoming message too long. Throw away
|
// Incoming message too long. Throw away
|
||||||
inputPos = 0;
|
Serial.print("Client "); Serial.print(i); Serial.println(": Message too long");
|
||||||
|
inputString[i].idx = 0;
|
||||||
|
// Finished with this client's message. Next loop() we'll see if there's more to read.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,19 @@
|
|||||||
|
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
|
|
||||||
|
|
||||||
static uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled
|
static uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled
|
||||||
static uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode
|
static uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode
|
||||||
|
|
||||||
#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller
|
#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller
|
||||||
#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller
|
#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char string[MAX_RECEIVE_LENGTH];
|
||||||
|
uint8_t idx;
|
||||||
|
} inputBuffer;
|
||||||
|
|
||||||
static volatile boolean buttonTriggeredInclusion;
|
static volatile boolean buttonTriggeredInclusion;
|
||||||
static boolean inclusionMode; // Keeps track on inclusion mode
|
static boolean inclusionMode; // Keeps track on inclusion mode
|
||||||
bool inclusionButtonSupported = false;
|
bool inclusionButtonSupported = false;
|
||||||
@@ -20,7 +26,6 @@ MyParserSerial parser;
|
|||||||
void setInclusionMode(boolean newMode);
|
void setInclusionMode(boolean newMode);
|
||||||
|
|
||||||
char convBuf[MAX_PAYLOAD*2+1];
|
char convBuf[MAX_PAYLOAD*2+1];
|
||||||
char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera
|
|
||||||
unsigned long inclusionStartTime;
|
unsigned long inclusionStartTime;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user