diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h new file mode 100644 index 0000000..8d852a0 --- /dev/null +++ b/lib/api/GwApi.h @@ -0,0 +1,17 @@ +#ifndef _GWAPI_H +#define _GWAPI_H +#include "GwMessage.h" +#include "N2kMessages.h" +#include "NMEA0183Messages.h" +#include "GWConfig.h" +//API to be used for additional tasks +class GwApi{ + public: + virtual GwRequestQueue *getQueue()=0; + virtual void sendN2kMessage(const tN2kMsg &msg)=0; + virtual void sendNMEA0183Message(const tNMEA0183Msg &msg, int sourceId)=0; + virtual int getSourceId()=0; + virtual GwConfigHandler *getConfig()=0; + virtual GwLog *getLogger()=0; +}; +#endif \ No newline at end of file diff --git a/lib/buttons/GwButtons.cpp b/lib/buttons/GwButtons.cpp new file mode 100644 index 0000000..24f3751 --- /dev/null +++ b/lib/buttons/GwButtons.cpp @@ -0,0 +1,86 @@ +#include "GwButtons.h" +#include "GwHardware.h" +#include "GwApi.h" + +class FactoryResetRequest: public GwMessage{ + private: + GwApi *api; + public: + FactoryResetRequest(GwApi *api):GwMessage(F("reset button")){ + this->api=api; + } + virtual ~FactoryResetRequest(){} + protected: + virtual void processImpl(){ + api->getLogger()->logDebug(GwLog::LOG,"reset request processing"); + api->getConfig()->reset(true); + xTaskCreate([](void *p){ + delay(500); + ESP.restart(); + vTaskDelete(NULL); + },"reset",1000,NULL,0,NULL); + }; +}; +void handleButtons(void *param){ + GwApi *api=(GwApi*)param; + GwLog *logger=api->getLogger(); + #ifndef GWBUTTON_PIN + LOG_DEBUG(GwLog::LOG,"no button pin defined, do not watch"); + vTaskDelete(NULL); + return; + #else + #ifndef GWBUTTON_ACTIVE + int activeState=0; + #else + int activeState=GWBUTTON_ACTIVE; + #endif + #ifdef GWBUTTON_PULLUPDOWN + bool pullUpDown=true; + #else + bool pullUpDown=false; + #endif + uint8_t mode=INPUT; + if (pullUpDown){ + mode=activeState?INPUT_PULLDOWN:INPUT_PULLUP; + } + pinMode(GWBUTTON_PIN,mode); + unsigned long lastPressed=0; + unsigned long firstPressed=0; + unsigned long lastReport=0; + const unsigned long OFF_TIME=20; + const unsigned long REPORT_TIME=1000; + const unsigned long HARD_REST_TIME=10000; + while(true){ + delay(10); + int current=digitalRead(GWBUTTON_PIN); + unsigned long now=millis(); + if (current != activeState){ + if (lastPressed != 0 && (lastPressed+OFF_TIME) < now){ + lastPressed=0; //finally off + firstPressed=0; + LOG_DEBUG(GwLog::LOG,"Button press stopped"); + } + continue; + } + lastPressed=now; + if (firstPressed == 0) { + firstPressed=now; + LOG_DEBUG(GwLog::LOG,"Button press started"); + lastReport=now; + } + if (lastReport != 0 && (lastReport + REPORT_TIME) < now ){ + LOG_DEBUG(GwLog::LOG,"Button active for %ld",(now-firstPressed)); + lastReport=now; + } + if (now > (firstPressed+HARD_REST_TIME)){ + LOG_DEBUG(GwLog::ERROR,"Factory reset by button"); + GwMessage *r=new FactoryResetRequest(api); + api->getQueue()->sendAndForget(r); + r->unref(); + firstPressed=0; + lastPressed=0; + } + } + vTaskDelete(NULL); + #endif +} \ No newline at end of file diff --git a/lib/buttons/GwButtons.h b/lib/buttons/GwButtons.h new file mode 100644 index 0000000..6218e5d --- /dev/null +++ b/lib/buttons/GwButtons.h @@ -0,0 +1,5 @@ +#ifndef _GWBUTTONS_H +#define _GWBUTTONS_H +//task function +void handleButtons(void *param); +#endif \ No newline at end of file diff --git a/src/GwHardware.h b/lib/hardware/GwHardware.h similarity index 90% rename from src/GwHardware.h rename to lib/hardware/GwHardware.h index ed3c813..3471a73 100644 --- a/src/GwHardware.h +++ b/lib/hardware/GwHardware.h @@ -36,6 +36,11 @@ #define GWSERIAL_RX 16 #define GWSERIAL_MODE "RX" +#define GWBUTTON_PIN GPIO_NUM_0 +#define GWBUTTON_ACTIVE LOW +//if GWBUTTON_PULLUPDOWN we enable a pulup/pulldown +#define GWBUTTON_PULLUPDOWN + #else #endif diff --git a/src/main.cpp b/src/main.cpp index a4c7de1..89f9d48 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define VERSION "0.5.4" +#define VERSION "0.5.6" // #define GW_MESSAGE_DEBUG_ENABLED // #define FALLBACK_SERIAL @@ -43,6 +43,8 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting #include "GwSerial.h" #include "GwWebServer.h" #include "NMEA0183DataToN2K.h" +#include "GwApi.h" +#include "GwButtons.h" //NMEA message channels @@ -126,6 +128,41 @@ class GwSerialLog : public GwLogWriter{ }; +class ApiImpl : public GwApi +{ +private: + int sourceId = -1; + +public: + ApiImpl(int sourceId) + { + this->sourceId = sourceId; + } + virtual GwRequestQueue *getQueue() + { + return &mainQueue; + } + virtual void sendN2kMessage(const tN2kMsg &msg) + { + NMEA2000.SendMsg(msg); + } + virtual void sendNMEA0183Message(const tNMEA0183Msg &msg, int sourceId) + { + SendNMEA0183Message(msg, sourceId); + } + virtual int getSourceId() + { + return sourceId; + }; + virtual GwConfigHandler *getConfig() + { + return &config; + } + virtual GwLog* getLogger(){ + return &logger; + } +}; + void delayedRestart(){ xTaskCreate([](void *p){ delay(500); @@ -134,6 +171,12 @@ void delayedRestart(){ },"reset",1000,NULL,0,NULL); } + +void startAddOnTask(TaskFunction_t task,int sourceId){ + ApiImpl* api=new ApiImpl(sourceId); + xTaskCreate(task,"user",1000,api,3,NULL); +} + #define JSON_OK "{\"status\":\"OK\"}" //WebServer requests that should @@ -451,6 +494,7 @@ void setup() { nmea0183Converter->HandleMsg(n2kMsg); }); NMEA2000.Open(); + startAddOnTask(handleButtons,100); } //*****************************************************************************