diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index 47551b2..de4e8bf 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -22,51 +22,10 @@
DCCEXParser * CommandDistributor::parser=0;
-bool CommandDistributor::parse(byte clientId,byte * buffer, Print * streamer) {
-
-
- // SIDE EFFECT WARNING:::
- // We know that parser will read the entire buffer before starting to write to it.
- // Otherwise we would have to copy the buffer elsewhere and RAM is in short supply.
-
-
- bool closeAfter=false;
- // Intercept HTTP requests
- if (isHTTP(buffer)) {
- if (httpCallback) httpCallback(streamer, buffer);
- closeAfter = true;
- }
- else if (buffer[0] == '<') {
+void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * streamer) {
+ if (buffer[0] == '<') {
if (!parser) parser = new DCCEXParser();
parser->parse(streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async
}
- else WiThrottle::getThrottle(clientId)->parse(*streamer, buffer);
-
- return closeAfter;
+ else WiThrottle::getThrottle(clientId)->parse(streamer, buffer);
}
-
-bool CommandDistributor::isHTTP(byte * buffer) {
-
- // POST GET PUT PATCH DELETE
- // You may think a simple strstr() is better... but not when ram & time is in short supply
- switch (buffer[0]) {
- case 'P':
- if (buffer[1] == 'U' && buffer[2] == 'T' && buffer[3] == ' ' ) return true;
- if (buffer[1] == 'O' && buffer[2] == 'S' && buffer[3] == 'T' && buffer[4] == ' ') return true;
- if (buffer[1] == 'A' && buffer[2] == 'T' && buffer[3] == 'C' && buffer[4] == 'H' && buffer[5] == ' ') return true;
- return false;
- case 'G':
- if (buffer[1] == 'E' && buffer[2] == 'T' && buffer[3] == ' ' ) return true;
- return false;
- case 'D':
- if (buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'E' && buffer[4] == 'T' && buffer[5] == 'E' && buffer[6] == ' ') return true;
- return false;
- default:
- return false;
- }
-}
-
-void CommandDistributor::setHTTPCallback(HTTP_CALLBACK callback) {
- httpCallback = callback;
-}
-HTTP_CALLBACK CommandDistributor::httpCallback=0;
diff --git a/CommandDistributor.h b/CommandDistributor.h
index 93e4d7c..155ada0 100644
--- a/CommandDistributor.h
+++ b/CommandDistributor.h
@@ -19,19 +19,13 @@
#ifndef CommandDistributor_h
#define CommandDistributor_h
#include "DCCEXParser.h"
-
-typedef void (*HTTP_CALLBACK)(Print *stream, byte *cmd);
+#include "RingStream.h"
class CommandDistributor {
public :
- static void setHTTPCallback(HTTP_CALLBACK callback);
- static bool parse(byte clientId,byte* buffer, Print * streamer);
-
-
+ static void parse(byte clientId,byte* buffer, RingStream * streamer);
private:
- static HTTP_CALLBACK httpCallback;
- static bool isHTTP(byte * buffer);
static DCCEXParser * parser;
};
diff --git a/DCC.cpp b/DCC.cpp
index 401f545..96868ca 100644
--- a/DCC.cpp
+++ b/DCC.cpp
@@ -155,6 +155,15 @@ int DCC::changeFn( int cab, byte functionNumber, bool pressed) {
return funcstate;
}
+int DCC::getFn( int cab, byte functionNumber) {
+ if (cab<=0 || functionNumber>28) return -1; // unknown
+ int reg = lookupSpeedTable(cab);
+ if (reg<0) return -1;
+
+ unsigned long funcmask = (1UL<.
+ */
+
+#include "RingStream.h"
+#include "DIAG.h"
+
+RingStream::RingStream( const uint16_t len)
+{
+ _len=len;
+ _buffer=new byte[len];
+ _pos_write=0;
+ _pos_read=0;
+ _buffer[0]=0;
+ _overflow=false;
+ _mark=0;
+ _count=0;
+}
+
+size_t RingStream::write(uint8_t b) {
+ if (_overflow) return 0;
+ _buffer[_pos_write] = b;
+ ++_pos_write;
+ if (_pos_write==_len) _pos_write=0;
+ if (_pos_write==_pos_read) {
+ _overflow=true;
+ return 0;
+ }
+ _count++;
+ return 1;
+}
+
+int RingStream::read() {
+ if ((_pos_read==_pos_write) && !_overflow) return -1; // empty
+ byte b=_buffer[_pos_read];
+ _pos_read++;
+ if (_pos_read==_len) _pos_read=0;
+ _overflow=false;
+ return b;
+}
+
+
+int RingStream::count() {
+ return (read()<<8) | read();
+ }
+
+int RingStream::freeSpace() {
+ // allow space for client flag and length bytes
+ if (_pos_read>_pos_write) return _pos_read-_pos_write-3;
+ else return _len - _pos_write + _pos_read-3;
+}
+
+
+// mark start of message with client id (0...9)
+void RingStream::mark(uint8_t b) {
+ _mark=_pos_write;
+ write(b); // client id
+ write((uint8_t)0); // count MSB placemarker
+ write((uint8_t)0); // count LSB placemarker
+ _count=0;
+}
+
+bool RingStream::commit() {
+ if (_overflow) {
+ DIAG(F("\nRingStream(%d) commit(%d) OVERFLOW\n"),_len, _count);
+ // just throw it away
+ _pos_write=_mark;
+ _overflow=false;
+ return false; // commit failed
+ }
+ if (_count==0) {
+ // ignore empty response
+ _pos_write=_mark;
+ return true; // true=commit ok
+ }
+ // Go back to the _mark and inject the count 1 byte later
+ _mark++;
+ if (_mark==_len) _mark=0;
+ _buffer[_mark]=highByte(_count);
+ _mark++;
+ if (_mark==_len) _mark=0;
+ _buffer[_mark]=lowByte(_count);
+ return true; // commit worked
+}
diff --git a/RingStream.h b/RingStream.h
new file mode 100644
index 0000000..b32e062
--- /dev/null
+++ b/RingStream.h
@@ -0,0 +1,47 @@
+#ifndef RingStream_h
+#define RingStream_h
+/*
+ * © 2020, Chris Harlow. All rights reserved.
+ *
+ * This file is part of DCC-EX CommandStation-EX
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * It is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CommandStation. If not, see .
+ */
+
+#include
+
+class RingStream : public Print {
+
+ public:
+ RingStream( const uint16_t len);
+
+ virtual size_t write(uint8_t b);
+ using Print::write;
+ int read();
+ int count();
+ int freeSpace();
+ void mark(uint8_t b);
+ bool commit();
+
+ private:
+ int _len;
+ int _pos_write;
+ int _pos_read;
+ bool _overflow;
+ int _mark;
+ int _count;
+ byte * _buffer;
+};
+
+#endif
diff --git a/StringFormatter.cpp b/StringFormatter.cpp
index 3b90b2c..9c81b88 100644
--- a/StringFormatter.cpp
+++ b/StringFormatter.cpp
@@ -47,9 +47,16 @@ void StringFormatter::diag( const __FlashStringHelper* input...) {
}
void StringFormatter::lcd(byte row, const __FlashStringHelper* input...) {
+ va_list args;
+
+ // Issue the LCD as a diag first
+ diag(F("\nLCD%d:"),row);
+ va_start(args, input);
+ send2(diagSerial,input,args);
+ diag(F("\n"));
+
if (!LCDDisplay::lcdDisplay) return;
LCDDisplay::lcdDisplay->setRow(row);
- va_list args;
va_start(args, input);
send2(LCDDisplay::lcdDisplay,input,args);
}
diff --git a/WiThrottle.cpp b/WiThrottle.cpp
index 5c536b5..61f7f92 100644
--- a/WiThrottle.cpp
+++ b/WiThrottle.cpp
@@ -99,17 +99,9 @@ WiThrottle::~WiThrottle() {
}
}
-void WiThrottle::parse(Print & stream, byte * cmdx) {
+void WiThrottle::parse(RingStream * stream, byte * cmdx) {
- // we have to take a copy of the cmd buffer as the reply will get built into the cmdx
- byte local[150];
- for (byte i=0;i\n"), throttleChar, cmd[3] ,locoid); //tell client to add loco
- // TODO... get known Fn states from DCC (need memoryStream improvements to handle data length)
- // for(fKey=0; fKey<29; fKey++)StringFormatter::send(stream,F("M%cA%c<;>F0&s\n"),throttleChar,cmd[3],fkey);
+ //Get known Fn states from DCC
+ for(int fKey=0; fKey<=28; fKey++) {
+ int fstate=DCC::getFn(locoid,fKey);
+ if (fstate>=0) StringFormatter::send(stream,F("M%cA%c<;>F%d%d\n"),throttleChar,cmd[3],fstate,fKey);
+ }
StringFormatter::send(stream, F("M%cA%c%d<;>V%d\n"), throttleChar, cmd[3], locoid, DCCToWiTSpeed(DCC::getThrottleSpeed(locoid)));
StringFormatter::send(stream, F("M%cA%c%d<;>R%d\n"), throttleChar, cmd[3], locoid, DCC::getThrottleDirection(locoid));
StringFormatter::send(stream, F("M%cA%c%d<;>s1\n"), throttleChar, cmd[3], locoid); //default speed step 128
@@ -261,7 +256,7 @@ void WiThrottle::multithrottle(Print & stream, byte * cmd){
}
}
-void WiThrottle::locoAction(Print & stream, byte* aval, char throttleChar, int cab){
+void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, int cab){
// Note cab=-1 for all cabs in the consist called throttleChar.
// DIAG(F("\nLoco Action aval=%c%c throttleChar=%c, cab=%d"), aval[0],aval[1],throttleChar, cab);
switch (aval[0]) {
@@ -339,10 +334,19 @@ int WiThrottle::WiTToDCCSpeed(int WiTSpeed) {
return WiTSpeed + 1; //offset others by 1
}
-void WiThrottle::loop() {
+void WiThrottle::loop(RingStream * stream) {
// for each WiThrottle, check the heartbeat
for (WiThrottle* wt=firstThrottle; wt!=NULL ; wt=wt->nextThrottle)
wt->checkHeartbeat();
+
+ // TODO... any broadcasts to be done
+ (void)stream;
+ /* MUST follow this model in this loop.
+ * stream->mark();
+ * send 1 digit client id, and any data
+ * stream->commit()
+ */
+
}
void WiThrottle::checkHeartbeat() {
diff --git a/WiThrottle.h b/WiThrottle.h
index c1b5bba..161020d 100644
--- a/WiThrottle.h
+++ b/WiThrottle.h
@@ -19,6 +19,7 @@
#ifndef WiThrottle_h
#define WiThrottle_h
+#include "RingStream.h"
struct MYLOCO {
char throttle; //indicates which throttle letter on client, often '0','1' or '2'
@@ -27,8 +28,8 @@ struct MYLOCO {
class WiThrottle {
public:
- static void loop();
- void parse(Print & stream, byte * cmd);
+ static void loop(RingStream * stream);
+ void parse(RingStream * stream, byte * cmd);
static WiThrottle* getThrottle( int wifiClient);
static bool annotateLeftRight;
private:
@@ -56,9 +57,9 @@ class WiThrottle {
bool lastPowerState; // last power state sent to this client
int DCCToWiTSpeed(int DCCSpeed);
int WiTToDCCSpeed(int WiTSpeed);
- void multithrottle(Print & stream, byte * cmd);
- void locoAction(Print & stream, byte* aval, char throttleChar, int cab);
- void accessory(Print & stream, byte* cmd);
+ void multithrottle(RingStream * stream, byte * cmd);
+ void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab);
+ void accessory(RingStream *, byte* cmd);
void checkHeartbeat();
};
#endif
diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp
index 691728c..2463921 100644
--- a/WifiInboundHandler.cpp
+++ b/WifiInboundHandler.cpp
@@ -1,5 +1,6 @@
#include
#include "WifiInboundHandler.h"
+#include "RingStream.h"
#include "CommandDistributor.h"
#include "DIAG.h"
@@ -16,14 +17,10 @@ void WifiInboundHandler::loop() {
WifiInboundHandler::WifiInboundHandler(Stream * ESStream) {
wifiStream=ESStream;
- for (int clientId=0;clientIdavailable()
- clientBuffer[clientId]=new byte[MAX_WIFI_BUFFER+1];
- clientStream[clientId]=new MemStream(clientBuffer[clientId], MAX_WIFI_BUFFER);
- }
clientPendingCIPSEND=-1;
+ inboundRing=new RingStream(INBOUND_RING);
+ outboundRing=new RingStream(OUTBOUND_RING);
+ pendingCipsend=false;
}
@@ -31,38 +28,48 @@ WifiInboundHandler::WifiInboundHandler(Stream * ESStream) {
// +IPD,x,lll:data is stored in streamer[x]
// Other input returns
void WifiInboundHandler::loop1() {
-
- // First handle all inbound traffic events
- if (loop2()!=INBOUND_IDLE) return;
+ // First handle all inbound traffic events because they will block the sending
+ if (loop2()!=INBOUND_IDLE) return;
+ WiThrottle::loop(outboundRing);
+
// if nothing is already CIPSEND pending, we can CIPSEND one reply
if (clientPendingCIPSEND<0) {
- for (int clientId=0;clientIdavailable());
- StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), clientId, clientStream[clientId]->available());
- clientStatus[clientId]=CIPSEND_PENDING;
- return;
- }
- }
- }
+ clientPendingCIPSEND=outboundRing->read();
+ if (clientPendingCIPSEND>=0) {
+ currentReplySize=outboundRing->count();
+ pendingCipsend=true;
+ }
+ }
- // if something waiting to close we can call one of them
-
- for (int clientId=0;clientIdread();
+ if (clientId>=0) {
+ int count=inboundRing->count();
+ if (Diag::WIFI) DIAG(F("\nWifi EXEC: %d %d:"),clientId,count);
+ byte cmd[count+1];
+ for (int i=0;iread();
+ cmd[count]=0;
+ if (Diag::WIFI) DIAG(F("%e\n"),cmd);
+
+ outboundRing->mark(clientId); // remember start of outbound data
+ CommandDistributor::parse(clientId,cmd,outboundRing);
+ // The commit call will either write the lenbgth bytes
+ // OR rollback to the mark because the reply is empty or commend generated more than fits the buffer
+ outboundRing->commit();
return;
}
}
-}
+
// This is a Finite State Automation (FSA) handling the inbound bytes from an ES AT command processor
@@ -78,7 +85,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
}
switch (loopState) {
- case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED
+ case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED, ERROR, SEND OK
if (ch == '+') {
loopState = IPD;
@@ -86,10 +93,14 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
}
if (ch=='>') {
- if (Diag::WIFI) DIAG(F("[[XMIT %d]]"),clientStream[clientPendingCIPSEND]->available());
- wifiStream->write(clientBuffer[clientPendingCIPSEND], clientStream[clientPendingCIPSEND]->available());
- clientStatus[clientPendingCIPSEND]=clientCloseAfterReply[clientPendingCIPSEND]? CLOSE_AFTER_SEND: UNUSED;
+ if (Diag::WIFI) DIAG(F("[XMIT %d]"),currentReplySize);
+ for (int i=0;iread();
+ wifiStream->write(cout);
+ if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise
+ }
clientPendingCIPSEND=-1;
+ pendingCipsend=false;
loopState=SKIPTOEND;
break;
}
@@ -98,21 +109,32 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
loopState=SKIPTOEND;
break;
}
+
+ if (ch=='S') { // SEND OK probably
+ loopState=SKIPTOEND;
+ break;
+ }
if (ch=='b') { // This is a busy indicator... probabaly must restart a CIPSEND
- if (clientPendingCIPSEND>=0) {
- clientStatus[clientPendingCIPSEND]=REPLY_PENDING;
- clientPendingCIPSEND=-1;
- }
+ pendingCipsend=(clientPendingCIPSEND>=0);
loopState=SKIPTOEND;
break;
}
- if (ch>='0' && ch<=('0'+MAX_CLIENTS)) {
+ if (ch>='0' && ch<='9') {
runningClientId=ch-'0';
loopState=GOT_CLIENT_ID;
break;
}
+
+ if (ch=='E' || ch=='l') { // ERROR or "link is not valid"
+ if (clientPendingCIPSEND>=0) {
+ // A CIPSEND was errored... just toss it away
+ purgeCurrentCIPSEND();
+ }
+ loopState=SKIPTOEND;
+ break;
+ }
break;
@@ -133,7 +155,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
break;
case IPD4_CLIENT: // reading connection id
- if (ch >= '0' || ch <('0'+MAX_CLIENTS)){
+ if (ch >= '0' || ch <='9'){
runningClientId=ch-'0';
loopState=IPD5;
}
@@ -151,8 +173,14 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
loopState=ANYTHING;
break;
}
- clientStream[runningClientId]->flush(); // prepare streamer for input
- clientStatus[runningClientId]=INBOUND_ARRIVING;
+ if (Diag::WIFI) DIAG(F("\nWifi inbound data(%d:%d):"),runningClientId,dataLength);
+ if (inboundRing->freeSpace()<=(dataLength+1)) {
+ // This input would overflow the inbound ring, ignore it
+ loopState=IPD_IGNORE_DATA;
+ if (Diag::WIFI) DIAG(F("\nWifi OVERFLOW IGNORING:"));
+ break;
+ }
+ inboundRing->mark(runningClientId);
loopState=IPD_DATA;
break;
}
@@ -160,32 +188,30 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
break;
case IPD_DATA: // reading data
- clientStream[runningClientId]->write(ch); // NOTE: The MemStream will throw away bytes that do not fit in the buffer.
- // This protects against buffer overflows even with things as innocent
- // as a browser which send massive, irrlevent HTTP headers.
+ inboundRing->write(ch);
dataLength--;
if (dataLength == 0) {
- clientStatus[runningClientId]=READY_TO_PROCESS;
+ inboundRing->commit();
loopState = ANYTHING;
}
break;
+ case IPD_IGNORE_DATA: // ignoring data that would not fit in inbound ring
+ dataLength--;
+ if (dataLength == 0) loopState = ANYTHING;
+ break;
+
case GOT_CLIENT_ID: // got x before CLOSE or CONNECTED
loopState=(ch==',') ? GOT_CLIENT_ID2: SKIPTOEND;
break;
- case GOT_CLIENT_ID2: // got "x," before CLOSE or CONNECTED
- loopState=(ch=='C') ? GOT_CLIENT_ID3: SKIPTOEND;
+ case GOT_CLIENT_ID2: // got "x,"
+ if (ch=='C') {
+ // got "x C" before CLOSE or CONNECTED, or CONNECT FAILED
+ if (runningClientId==clientPendingCIPSEND) purgeCurrentCIPSEND();
+ }
+ loopState=SKIPTOEND;
break;
-
- case GOT_CLIENT_ID3: // got "x C" before CLOSE or CONNECTED (which is ignored)
- if(ch=='L') {
- // CLOSE
- clientStatus[runningClientId]=UNUSED;
- if (runningClientId==clientPendingCIPSEND) clientPendingCIPSEND=-1;
- }
- loopState=SKIPTOEND;
- break;
case SKIPTOEND: // skipping for /n
if (ch=='\n') loopState=ANYTHING;
@@ -195,24 +221,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
return (loopState==ANYTHING) ? INBOUND_IDLE: INBOUND_BUSY;
}
-
-void WifiInboundHandler::processCommand(byte clientId) {
- clientStatus[clientId]=PROCESSING;
- byte * buffer=clientBuffer[clientId];
- MemStream * streamer=clientStream[clientId];
- buffer[streamer->available()]='\0';
-
- if (Diag::WIFI) DIAG(F("\n%l Wifi(%d)<-[%e]\n"), millis(),clientId, buffer);
- streamer->setBufferContentPosition(0, 0); // reset write position to start of buffer
-
- clientCloseAfterReply[clientId]=CommandDistributor::parse(clientId,buffer,streamer);
-
- if (streamer->available() == 0) {
- clientStatus[clientId]=UNUSED;
- }
- else {
- buffer[streamer->available()]='\0'; // mark end of buffer, so it can be used as a string later
- if (Diag::WIFI) DIAG(F("%l WiFi(%d)->[%e] l(%d)\n"), millis(), clientId, buffer, streamer->available());
- clientStatus[clientId]=REPLY_PENDING;
- }
+void WifiInboundHandler::purgeCurrentCIPSEND() {
+ // A CIPSEND was sent but errored... or the client closed just toss it away
+ if (Diag::WIFI) DIAG(F("Wifi: DROPPING CIPSEND=%d,%d\n"),clientPendingCIPSEND,currentReplySize);
+ for (int i=0;i<=currentReplySize;i++) outboundRing->read();
+ pendingCipsend=false;
+ clientPendingCIPSEND=-1;
}
diff --git a/WifiInboundHandler.h b/WifiInboundHandler.h
index 87ac89a..1979565 100644
--- a/WifiInboundHandler.h
+++ b/WifiInboundHandler.h
@@ -1,8 +1,8 @@
#ifndef WifiInboundHandler_h
#define WifiInboundHandler_h
-#include "MemStream.h"
-#include "DCCEXParser.h"
+#include "RingStream.h"
+#include "WiThrottle.h"
#include "DIAG.h"
class WifiInboundHandler {
@@ -14,9 +14,7 @@ class WifiInboundHandler {
static WifiInboundHandler * singleton;
- static const byte MAX_CLIENTS=5;
- static const byte MAX_WIFI_BUFFER=255;
-
+
enum INBOUND_STATE {
INBOUND_BUSY, // keep calling in loop()
INBOUND_IDLE // Nothing happening, outbound may xcall CIPSEND
@@ -35,38 +33,31 @@ class WifiInboundHandler {
IPD5, // got +IPD,c
IPD6_LENGTH, // got +IPD,c, reading length
IPD_DATA, // got +IPD,c,ll,: collecting data
+ IPD_IGNORE_DATA, // got +IPD,c,ll,: ignoring the data that won't fit inblound Ring
GOT_CLIENT_ID, // clientid prefix to CONNECTED / CLOSED
GOT_CLIENT_ID2, // clientid prefix to CONNECTED / CLOSED
GOT_CLIENT_ID3 // clientid prefix to CONNECTED / CLOSED
};
- enum CLIENT_STATUS {
- UNUSED, // client slot not in use
- INBOUND_ARRIVING, // data is arriving
- READY_TO_PROCESS, // data has arrived, may call parser now
- PROCESSING, // command in progress
- REPLY_PENDING, // reply is ready to CIPSEND
- CIPSEND_PENDING, // CIPSEND waiting for >
- CLOSE_PENDING, // CLOSE received
- CLOSE_AFTER_SEND // Send CLOSE after CIPSEND completed
- };
WifiInboundHandler(Stream * ESStream);
void loop1();
INBOUND_STATE loop2();
- void processCommand(byte clientId);
+ void purgeCurrentCIPSEND();
Stream * wifiStream;
- DCCEXParser *parser;
-
+ static const int INBOUND_RING = 512;
+ static const int OUTBOUND_RING = 2048;
+
+ RingStream * inboundRing;
+ RingStream * outboundRing;
+
LOOP_STATE loopState=ANYTHING;
int runningClientId; // latest client inbound processing data or CLOSE
int dataLength; // dataLength of +IPD
- byte * clientBuffer[MAX_CLIENTS];
- MemStream * clientStream[MAX_CLIENTS];
- CLIENT_STATUS clientStatus[MAX_CLIENTS];
- bool clientCloseAfterReply[MAX_CLIENTS];
int clientPendingCIPSEND=-1;
+ int currentReplySize;
+ bool pendingCipsend;
};
#endif
diff --git a/WifiInterface.cpp b/WifiInterface.cpp
index c751cab..be17b02 100644
--- a/WifiInterface.cpp
+++ b/WifiInterface.cpp
@@ -22,7 +22,7 @@
#include
#include "DIAG.h"
#include "StringFormatter.h"
-#include "WiThrottle.h"
+
#include "WifiInboundHandler.h"
const char PROGMEM READY_SEARCH[] = "\r\nready\r\n";
@@ -90,6 +90,11 @@ bool WifiInterface::setup(long serial_link_speed,
}
#endif
+DCCEXParser::setAtCommandCallback(ATCommand);
+
+// CAUTION... ONLY CALL THIS ONCE
+WifiInboundHandler::setup(wifiStream);
+
return wifiUp;
}
@@ -109,8 +114,6 @@ bool WifiInterface::setup(Stream & setupStream, const __FlashStringHelper* SSid
checkForOK(200, OK_SEARCH, true);
}
- DCCEXParser::setAtCommandCallback(ATCommand);
- WifiInboundHandler::setup(wifiStream);
DIAG(F("\n++ Wifi Setup %S ++\n"), connected ? F("OK") : F("FAILED"));
return connected;
@@ -233,6 +236,8 @@ bool WifiInterface::setup2(const __FlashStringHelper* SSid, const __FlashStringH
}
}
+ StringFormatter::send(wifiStream, F("AT+CIPSERVER=0\r\n")); // turn off tcp server (to clean connections before CIPMUX=1)
+ checkForOK(10000, OK_SEARCH, true); // ignore result in case it already was off
StringFormatter::send(wifiStream, F("AT+CIPMUX=1\r\n")); // configure for multiple connections
if (!checkForOK(10000, OK_SEARCH, true)) return false;
@@ -295,7 +300,6 @@ bool WifiInterface::checkForOK( const unsigned int timeout, const char * waitfor
void WifiInterface::loop() {
if (connected) {
- WiThrottle::loop();
WifiInboundHandler::loop();
}
}
diff --git a/WifiInterface.h b/WifiInterface.h
index b2bdd20..57dd469 100644
--- a/WifiInterface.h
+++ b/WifiInterface.h
@@ -20,7 +20,6 @@
#ifndef WifiInterface_h
#define WifiInterface_h
#include "DCCEXParser.h"
-#include "MemStream.h"
#include
#include
@@ -50,8 +49,5 @@ private:
static int datalength;
static int connectionId;
static unsigned long loopTimeoutStart;
- static const byte MAX_WIFI_BUFFER = 250;
- static byte buffer[MAX_WIFI_BUFFER + 1];
- static MemStream * streamer;
};
#endif
diff --git a/version.h b/version.h
index 6e45e70..d0c09b9 100644
--- a/version.h
+++ b/version.h
@@ -4,7 +4,7 @@
#include "StringFormatter.h"
// const char VERSION[] PROGMEM ="0.2.0";
-#define VERSION "0.2.0"
+#define VERSION "3.0.0"
-#endif
\ No newline at end of file
+#endif