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