#include "GwButtonTask.h" #include "GwHardware.h" #include "GwApi.h" #include "GwLedTask.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(); xTaskCreate([](void *p){ delay(500); ESP.restart(); vTaskDelete(NULL); },"reset",1000,NULL,0,NULL); }; }; void handleButtons(GwApi *api){ GwLog *logger=api->getLogger(); GwApi::TaskInterfaces *interfaces=api->taskInterfaces(); IButtonTask state; if (!interfaces->set(state)){ LOG_DEBUG(GwLog::ERROR,"unable to set button state"); } #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 PRESS_5_TIME=5000; const unsigned long PRESS_10_TIME=10000; const unsigned long PRESS_RESET_TIME=12000; LOG_DEBUG(GwLog::LOG,"button task started"); while(true){ delay(10); int current=digitalRead(GWBUTTON_PIN); unsigned long now=millis(); IButtonTask::ButtonState lastState=state.state; if (current != activeState){ if (lastPressed != 0 && (lastPressed+OFF_TIME) < now){ lastPressed=0; //finally off firstPressed=0; state.state=IButtonTask::OFF; LOG_DEBUG(GwLog::LOG,"Button press stopped"); } if (state.state != lastState){ interfaces->set(state); } continue; } lastPressed=now; if (firstPressed == 0) { firstPressed=now; LOG_DEBUG(GwLog::LOG,"Button press started"); state.pressCount++; state.state=IButtonTask::PRESSED; interfaces->set(state); lastReport=now; continue; } if (lastReport != 0 && (lastReport + REPORT_TIME) < now ){ LOG_DEBUG(GwLog::LOG,"Button active for %ld",(now-firstPressed)); lastReport=now; } if (now > (firstPressed+PRESS_5_TIME)){ state.state=IButtonTask::PRESSED_5; } if (now > (firstPressed+PRESS_10_TIME)){ state.state=IButtonTask::PRESSED_10; } if (lastState != state.state){ interfaces->set(state); } if (now > (firstPressed+PRESS_RESET_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 } void initButtons(GwApi *api){ #ifndef GWBUTTON_PIN api->getLogger()->logDebug(GwLog::LOG,"no buttons defined, no button task"); return; #endif const String taskname("buttonTask"); api->addUserTask(handleButtons,taskname); api->taskInterfaces()->claim(taskname); }