From 814494c154b7d559a8c44b2abc5990d345c769ae Mon Sep 17 00:00:00 2001 From: Phil Bowles Date: Thu, 20 Feb 2020 19:02:59 +0100 Subject: [PATCH] vn0.3.5 --- README.md | 8 +-- changelog.txt | 19 ++++-- docs/h43fnb.md | 2 + docs/h4gm.md | 26 ++++++++ docs/things.md | 17 ++--- .../H4GM_AnalogThreshold.ino | 64 +++++++++++++++++++ .../H4GM_AnalogThresholdThing.ino | 15 +++++ examples/H4GM_Polled/H4GM_Polled.ino | 9 ++- .../H4GM_PolledThing/H4GM_PolledThing.ino | 2 +- .../youtube/SoundAndMotion/SoundAndMotion.ino | 31 +++++++++ keywords.txt | 9 ++- src/H4P_GPIOManager.cpp | 24 ++++++- src/H4P_GPIOManager.h | 33 +++++++--- src/H4P_WiFi.cpp | 2 +- src/H4Plugins.cpp | 4 +- 15 files changed, 222 insertions(+), 43 deletions(-) create mode 100644 examples/H4GM_AnalogThreshold/H4GM_AnalogThreshold.ino create mode 100644 examples/H4GM_AnalogThresholdThing/H4GM_AnalogThresholdThing.ino create mode 100644 examples/youtube/SoundAndMotion/SoundAndMotion.ino diff --git a/README.md b/README.md index c6ecbc5a..0b05c20a 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Version **0.3.5** [Release Notes](changelog.txt) **MUST UPGRADE TO [H4 library]( ![H4PluginsFF](/assets/h4plugins.jpg) -Think of this as "IOT Lego" for [**H4**](https://github.com/philbowles/H4) - and if you are not already using H4's advanced scheduling and timing features, why not? Get it now from the link above, as you will need it to use the H4Plugins system. +Think of this as "IOT Lego" or an "IOT Swiss Army Knife" (or both) for [**H4**](https://github.com/philbowles/H4) - and if you are not already using H4's advanced scheduling and timing features, why not? Get it now from the link above, as you will need it to use the H4Plugins system. -H4Plugins includes modules for WiFi + OTA, Webserver, MQTT, 14 different types of GPIO handling, voice control and diagnostics. By "plugging " together only the required modules, you can rapidly build your own custom firmware or IOT app. Everything you build will be stable and responsive: the plugins work together to allow multiple simultaneous processes to run, so ***no more WDT resets***! As your experience grows you can extend your app / firmware with H4Plugins' well-documented API and runtime command system. Let's see H4Plugins being used as replacement firmware for a SONOFF Basic switch. +H4Plugins includes modules for WiFi + OTA, Webserver, MQTT, 15 different types of GPIO handling, voice control and diagnostics. By "plugging " together only the required modules, you can rapidly build your own custom firmware or IOT app. Everything you build will be stable and responsive: the plugins work together to allow multiple simultaneous processes to run, so ***no more WDT resets***! As your experience grows you can extend your app / firmware with H4Plugins' well-documented API and runtime command system. Let's see H4Plugins being used as replacement firmware for a SONOFF Basic switch. What follows is the *entire H4Plugins code* - despite the fact it might look like there is something missing, there is not. The code as shown compiles to produce firmware that can be uploaded directly to any / all of your SONOFF devices and provides: @@ -49,7 +49,7 @@ As you can see, all you need to do is list the modules you want (in the right or The modular design of H4's plugin architecture minimises scarce resources in low-memory MCU targets: You only compile in what you need with a simple `#include`. Detailed diagnostics can be easily included and controlled at runtime via the serial console, HTTP REST or MQTT depending on which options you choose. It is built on top of the very stable [H4](https://github.com/philbowles/H4) timer/scheduler which traces its ancestry back to "Esparto" - of which one user recently said: *"and now have Esparto modules with months of uptime without an issue"*. -There are 40 example sketches demonstrating all the features and the API of all of the plugins. They should be used both as a template for your own sketches and as a learning resource. +There are 44 example sketches demonstrating all the features and the API of all of the plugins. They should be used both as a template for your own sketches and as a learning resource. Users are strongly recommended to work through them in the order [listed below](readme.md#current-plugins-februrary-2020) @@ -160,7 +160,7 @@ Or: * [ESP32 AsyncUDP Library](https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP) * [ESP32 AsyncTCP Library](https://github.com/me-no-dev/AsyncTCP) -Depending on what target you are compiling for +Depending on what target you are compiling for (if both, then downlaod all libraries above) And: * [ESPAsyncWebServer](https://github.com/philbowles/ESPAsyncWebServer) * See note diff --git a/changelog.txt b/changelog.txt index 5c12716e..30470d43 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,17 @@ + +2020/02/19 0.3.6 + bugfix + Polled not getting value on fake event when in analog mode + new + GPIO types + AnalogThreshold + new example + AnalogThresholdThing + new example + 2020/02/19 0.3.5 breaking changes: h4/factory moved to serialcmd from wifi // update docs! changed - persistentStorage plugin + persistentStorage plugin + new example 2020/02/18 0.3.4 breaking changes: 1. _hasName removed from H4: MUST upgrade to 0.4.1 @@ -39,19 +48,15 @@ than a ground-up rewrite :) TODO: -H4 - rebootChain->forward_list? (watch size!) LONGTERM - heaplogger remote client get sql logger rf bridge signal on no spiffs template for hooking? proper condl diags - + diag out all dumps in GPIO fix switch.ps1 to use soap etc (revert a la esparto) take always ignore out of TS -SOONER lots of const string& - find easy way to get FS space etc on ESP32 +SOONER diff --git a/docs/h43fnb.md b/docs/h43fnb.md index 15e01d58..406ba669 100644 --- a/docs/h43fnb.md +++ b/docs/h43fnb.md @@ -29,6 +29,8 @@ A "long" press - anything over 5 seconds** - starts the LED flashing extremely r # Usage +H4P_ThreeFunctionButton is a specialised example of an IOT "Thing" - you should read ["Things vs Switches"](things.md) before continuing + ```cpp #include H4_USE_PLUGINS diff --git a/docs/h4gm.md b/docs/h4gm.md index e85a4711..92f8061f 100644 --- a/docs/h4gm.md +++ b/docs/h4gm.md @@ -50,6 +50,7 @@ Let's face it: there are only so many things you can do with a GPIO pin! Yes, th GPIOManager currently provides behaviours for: +* AnalogThreshold - send 0 or 1 depending on raw analog value > or < user-defined limit * Circular - Counts 1 - N, 1 - N etc * Debounced - Eliminates switch bounce * Encoder - Standard quadrature rotary encoder @@ -67,6 +68,7 @@ GPIOManager currently provides behaviours for: You should also read [Things vs Switches](things.md) which explains how some of the above strategies can be autmatically tied/bound/linked to predefined output actions. In it you will find how to use these variants of the above, each of which send an ON or OFF command to a linked output handler +* AnalogThresholdThing - binds a AnalogThreshold input to a BinarySwitch or UPNPSwitch output * DebouncedThing - binds a Debounced input to a BinarySwitch or UPNPSwitch output * EncoderThing - binds a Encoder input to a BinarySwitch or UPNPSwitch output * LatchingThing - binds a Latching input to a BinarySwitch or UPNPSwitch output @@ -270,6 +272,25 @@ This strategy can also do an `analogRead` if required: `state` will hold the raw --- +### **AnalogThreshold** + +**AnalogThreshold** is a specialised version of **Polled**. As with **Polled** it has its state checked periodically but it then converts the raw analog value to a 0 or a 1 and compares it with a threshhold value. It will only execute the callback function if the > or < test against the threshold succeeds. + +#### Additional fields for AnalogThreshold + +`uint32_t limit; // The threshold value` + +The constructor has a `compare` parameter which can be either `H4GM_LESS` or `H4GM_GREATER` + +* If the raw value of the encoder is 77 and you specify a limit of 100 and use `H4GM_LESS` then the callback will receive 1 as 77 is less than 100 +* If the raw value of the encoder is 77 and you specify a limit of 100 and use `H4GM_GREATER` then the callback will receive 0 as 77 is NOT greater than 100 +* If the raw value of the encoder is 100 and you specify a limit of 512 and use `H4GM_LESS` then the callback will receive 1 as 100 is less than 512 +* If the raw value of the encoder is 100 and you specify a limit of 512 and use `H4GM_GREATER` then the callback will receive 0 as 100 is NOT greater than 512 + +[Example Code](../examples/H4GM_AnalogThreshold/H4GM_AnalogThreshold.ino) + +--- + ### **Encoder** Manages a rotary encoder, including all necessary debouncing and decoding. You get called with additional field `encoderValue` of -1 for every anti-clockwise click or +1 for clockwise. It's that simple. Obviously it requires two physical pins but one single call does everything for you. @@ -279,6 +300,7 @@ It also has a variant that takes the name of an `int` variable instead of a call #### Additional fields for Encoder `int encoderValue; // +1 clockwise click. -1 anti-clockwise` + [Example Code](../examples/H4GM_Encoder/H4GM_Encoder.ino) --- @@ -315,6 +337,7 @@ setPercent // manually set value to % of max - min setCenter // manully set the value to the mid-point (max - min / 2) ``` + [Example Code](../examples/H4GM_EncoderAuto/H4GM_EncoderAuto.ino) --- @@ -375,6 +398,7 @@ For simplicity the code calls another plugin [H4P_FlasherController](../h4fc) to `int stage; // current table entry not exceeding held time` `uint32_t held; // Number of microseconds GPIO was held ON` + [Example Code](../examples/H4GM_Multistage/H4GM_Multistage.ino) --- @@ -411,6 +435,8 @@ void toggle(uint8_t p); // reverse current logical state // // Strategies // +AnalogThresholdPin* AnalogThreshold(uint8_t p,uint32_t freq,uint32_t threshold,H4GM_COMPARE compare,H4GM_FN_EVENT callback);// +AnalogThresholdPin* AnalogThresholdThing(uint8_t p,uint32_t freq,uint32_t threshold,H4GM_COMPARE compare,H4P_BinaryThing* btp);// CircularPin* Circular(uint8_t p,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,uint32_t nStages,H4GM_FN_EVENT callback);// DebouncedPin* Debounced(uint8_t p,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,H4GM_FN_EVENT callback);// DebouncedPin* DebouncedThing(uint8_t p,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,H4P_BinaryThing* btp);// diff --git a/docs/things.md b/docs/things.md index 2bb3ace0..8009c2d6 100644 --- a/docs/things.md +++ b/docs/things.md @@ -109,13 +109,14 @@ Your app can contain exactly one of these And as many GPIO input connectors as you need, to make your app do whatever it needs to do -* DebouncedThing -* EncoderThing -* LatchingThing -* PolledThing -* RawThing -* RetriggeringThing -* [H4P_ThreeFunctionButton](h43fnb.md) +* AnalogThresholdThing [Example Code](../examples/H4GM_AnalogThresholdThing/H4GM_AnalogThresholdThing.ino) +* DebouncedThing [Example Code](../examples/H4GM_DebouncedThing/H4GM_DebouncedThing.ino) +* EncoderThing [Example Code](../examples/H4GM_EncoderThing/H4GM_EncoderThing.ino) +* LatchingThing [Example Code](../examples/H4GM_LatchingThing/H4GM_LatchingThing.ino) +* PolledThing [Example Code](../examples/H4GM_PolledThing/H4GM_PolledThing.ino) +* RawThing [Example Code](../examples/H4GM_RawThing/H4GM_RawThing.ino) +* RetriggeringThing [Example Code](../examples/H4GM_RetriggeringThing/H4GM_RetriggeringThing.ino) +* [H4P_ThreeFunctionButton](h43fnb.md) [Example Code](../examples/H4P_SONOFF_Basic/H4P_SONOFF_Basic.ino) --- @@ -197,6 +198,7 @@ void friendlyName(const string& name); // sets UPNP friendly name. Causes a rebo You need to read the [H4P_GPIOManager](h4gm.md) documentation before using these +[Example Sketch - AnalogThresholdThing](../examples/H4GM_DebouncedThing/H4GM_DebouncedThing.ino) [Example Sketch - DebouncedThing](../examples/H4GM_DebouncedThing/H4GM_DebouncedThing.ino) [Example Sketch - EncoderThing](../examples/H4GM_EncoderThing/H4GM_EncoderThing.ino) [Example Sketch - LatchingThing](../examples/H4GM_LatchingThing/H4GM_LatchingThing.ino) @@ -262,7 +264,6 @@ The integer number of repeat UDP messages sent on each occasion to prevent packe --- - (c) 2020 Phil Bowles h4plugins@gmail.com * [Youtube channel (instructional videos)](https://www.youtube.com/channel/UCYi-Ko76_3p9hBUtleZRY6g) diff --git a/examples/H4GM_AnalogThreshold/H4GM_AnalogThreshold.ino b/examples/H4GM_AnalogThreshold/H4GM_AnalogThreshold.ino new file mode 100644 index 00000000..42be150a --- /dev/null +++ b/examples/H4GM_AnalogThreshold/H4GM_AnalogThreshold.ino @@ -0,0 +1,64 @@ +#include +H4_USE_PLUGINS +/* +My major testing devices were nodeMCU which has builtin button on GPIO0 which is ACTIVE_LOW +and STM32NUCLEO-F429ZI whuch has a user button that is ACTIVE_HIGH + +You will probably need to adjust these values for you own device +*/ +#ifdef ARDUINO_ARCH_STM32 + #define UB_ACTIVE ACTIVE_HIGH + #define UL_ACTIVE ACTIVE_HIGH +#else + #define USER_BTN 0 + #define UB_ACTIVE ACTIVE_LOW + #define UL_ACTIVE ACTIVE_LOW +#endif +/* + ALL GPIO strategies are derived from H4GPIOPin: the following members are available + inside ALL GPIO pin callbacks, once you have a valid pointer for the pin type using + H4GM_PIN( type ) with specific underlying type Raw needs H4GM_PIN(Raw); + + uint8_t pin=0; // GPIO hardware pin number + uint8_t gpioType=0; // INPUT, INPUT_PULLUP, OUTPUT etc + H4GM_STYLE style; // Strategy: Raw, debounced, retriggering etc + uint8_t sense=0; // active HIGH or LOW + unsigned long Tevt=0; // uS time of last event + int state=0; // 32 wide as it holds analog value as well as digital 0/1 + // and not uint because encoder returns -1 or +1 + uint32_t delta=0; // uS since last change + uint32_t rate=0; // instantaenous rate cps + uint32_t Rpeak=0; // peak rate + uint32_t cps=0; // sigma changes/sec (used internally, frequently re-set) + uint32_t cMax=UINT_MAX; // max permitted cps (see "throttling"); + uint32_t nEvents=UINT_MAX; // sigma "Events" (meaning depends on inheriting strategy) + + Additional members for AnalogThreshold: + + limit the threshold value: below this figure = 0, above it = 1 + + AnalogThreshold has its state checked periodically, usually with a large value, e.g. minutes. It is used + when you do *not* want to react quickly. A good example is a light sensor at dusk: you want lights + to come on when it is "dark". As the light fades the sensor will "flutter" rapidly for quite a long + time before settling to its "dark" value. Only *then* do you want to switch the lights. + + Each time it is polled, it will compare the raw analog value with limit and return 1 ig greater, else 0 + analog value. +*/ + +H4 h4(115200); //auto-start Serial @ 115200, Q size=20 +H4P_GPIOManager h4gm; + +#define U_POLL_FREQ 5000 +#define U_LIMIT 100 + +void h4setup() { // H4 constructor starts Serial + Serial.println("H4P_GPIOManager AnalogThreshold Example v"H4P_VERSION); + + h4gm.AnalogThreshold(A0,U_POLL_FREQ,U_LIMIT,[](H4GPIOPin* ptr){ + H4GM_PIN(AnalogThreshold); // Create the correct pointer type in 'pin' + Serial.print("T=");Serial.print(millis()); + Serial.print(" AnalogThreshold ");Serial.print(pin->pin); + Serial.print(" AnalogThreshold IS ");Serial.println(pin->logicalRead()); + }); +} diff --git a/examples/H4GM_AnalogThresholdThing/H4GM_AnalogThresholdThing.ino b/examples/H4GM_AnalogThresholdThing/H4GM_AnalogThresholdThing.ino new file mode 100644 index 00000000..a75e97f4 --- /dev/null +++ b/examples/H4GM_AnalogThresholdThing/H4GM_AnalogThresholdThing.ino @@ -0,0 +1,15 @@ +#include +H4_USE_PLUGINS + +#define F_POLL 5000 + +H4 h4(115200); +H4P_SerialCmd h4sc; +H4P_GPIOManager h4gm; + +H4P_BinarySwitch h4onof(LED_BUILTIN,ACTIVE_LOW,OFF); + +void h4setup(){ + h4gm.AnalogThresholdThing(LIGHT,F_POLL,100,H4GM_GREATER,&h4onof); // On if A0 > 100 + //h4gm.AnalogThresholdThing(LIGHT,F_POLL,100,H4GM_LESS,&h4onof); // On if A0 < 100 +} diff --git a/examples/H4GM_Polled/H4GM_Polled.ino b/examples/H4GM_Polled/H4GM_Polled.ino index 3b51c278..ef42c39b 100644 --- a/examples/H4GM_Polled/H4GM_Polled.ino +++ b/examples/H4GM_Polled/H4GM_Polled.ino @@ -1,10 +1,5 @@ #include H4_USE_PLUGINS - -H4 h4(115200,20); //auto-start Serial @ 115200, Q size=20 - -H4P_GPIOManager h4gm; -H4P_FlasherController h4fc; /* My major testing devices were nodeMCU which has builtin button on GPIO0 which is ACTIVE_LOW and STM32NUCLEO-F429ZI whuch has a user button that is ACTIVE_HIGH @@ -50,6 +45,10 @@ You will probably need to adjust these values for you own device It can be used for both digital and analog values: when isAnalog == true; 'state' will contain raw analog value. */ + +H4 h4(115200); //auto-start Serial @ 115200, Q size=20 +H4P_GPIOManager h4gm; + #define U_POLL_FREQ 5000 void h4setup() { // H4 constructor starts Serial diff --git a/examples/H4GM_PolledThing/H4GM_PolledThing.ino b/examples/H4GM_PolledThing/H4GM_PolledThing.ino index 38cafb77..7f49bd03 100644 --- a/examples/H4GM_PolledThing/H4GM_PolledThing.ino +++ b/examples/H4GM_PolledThing/H4GM_PolledThing.ino @@ -61,5 +61,5 @@ void h4setup() { // H4 constructor starts Serial Serial.println("H4P_GPIOManager Polled Example v"H4P_VERSION); Serial.print("GPIO ");Serial.print(USER_BTN);Serial.print(" ACTIVE ");Serial.println(UB_ACTIVE ? "HIGH":"LOW"); - h4gm.PolledThing(USER_BTN,INPUT,UB_ACTIVE,U_POLL_FREQ,true,&h4bt); + h4gm.PolledThing(USER_BTN,INPUT,UB_ACTIVE,U_POLL_FREQ,false,&h4bt); } diff --git a/examples/youtube/SoundAndMotion/SoundAndMotion.ino b/examples/youtube/SoundAndMotion/SoundAndMotion.ino new file mode 100644 index 00000000..40de38e8 --- /dev/null +++ b/examples/youtube/SoundAndMotion/SoundAndMotion.ino @@ -0,0 +1,31 @@ +#include +H4_USE_PLUGINS + +#define LED_RED D6 +#define LED_YELLOW D7 +#define LED_GREEN D8 + +#define MOTION D1 +#define LIGHT A0 + +#define F_POLL 5000 + +H4 h4(115200); +H4P_SerialCmd h4sc; +H4P_GPIOManager h4gm; +//H4P_WiFi h4wifi("XXXXXXXX","XXXXXXXX","h4plugins"); +//H4P_MQTT h4mqtt("192.168.1.4",1883); +//H4P_AsyncWebServer h4asws("admin","admin"); +//H4P_UPNPSwitch h4upnp("Demo Switch",RELAY_BUILTIN,ACTIVE_HIGH,OFF); +H4P_BinarySwitch h4onof(LED_RED,ACTIVE_HIGH,OFF); +H4P_FlasherController h4fc; +H4P_ThreeFunctionButton h43fb(&h4onof,15,BUTTON_BUILTIN,INPUT,ACTIVE_LOW,LED_BUILTIN,ACTIVE_LOW); + +void h4setup(){ + h4gm.RetriggeringThing(MOTION,INPUT,ACTIVE_HIGH,10000,&h4onof); // 10sec motion timeout + h4gm.Polled(LIGHT,INPUT,ACTIVE_HIGH,F_POLL,true,[](H4GPIOPin* ptr){ + H4GM_PIN(Polled); + Serial.printf("POLLED = %d\n",pin->state); + h4onof.turn(pin->state < 60 ? 1:0); + }); // door alarm +} diff --git a/keywords.txt b/keywords.txt index c89e503e..ebd17725 100644 --- a/keywords.txt +++ b/keywords.txt @@ -65,7 +65,6 @@ EncoderAuto KEYWORD2 Filtered KEYWORD2 Latching KEYWORD2 logEvent KEYWORD2 -logicalRead KEYWORD2 logicalWrite KEYWORD2 Latching KEYWORD2 Multistage KEYWORD2 @@ -113,7 +112,8 @@ exclude KEYWORD2 friendlyName KEYWORD2 host KEYWORD2 showSPIFFS KEYWORD2 - +AnalogThreshold KEYWORD2 +AnalogThresholdThing KEYWORD2 DebouncedThing KEYWORD2 EncoderThing KEYWORD2 LatchingThing KEYWORD2 @@ -134,4 +134,7 @@ H4_CMD_NAME_UNKNOWN LITERAL1 H4_CMD_PAYLOAD_FORMAT LITERAL1 H4_CMD_PROHIBITED LITERAL1 -H4P_FN_PSCHANGE LITERAL1 \ No newline at end of file +H4P_FN_PSCHANGE LITERAL1 +H4GM_COMPARE LITERAL1 +H4GM_LESS LITERAL1 +H4GM_GREATER LITERAL1 \ No newline at end of file diff --git a/src/H4P_GPIOManager.cpp b/src/H4P_GPIOManager.cpp index 6a10481d..d3bd2913 100644 --- a/src/H4P_GPIOManager.cpp +++ b/src/H4P_GPIOManager.cpp @@ -216,7 +216,8 @@ void MultistagePin::sendEvent(){ } PolledPin::PolledPin(uint8_t _p,uint8_t _g,H4GM_STYLE _s,uint8_t _a,uint32_t _f,uint32_t _v,H4GM_FN_EVENT _c): H4GPIOPin(_p,_g,_s,_a,_c),frequency(_f),isAnalog(_v){ - h4.every(frequency,[this](){ read(); },nullptr,H4P_TRID_POLL); + h4.every(frequency,[this](){ read(); },nullptr,H4P_TRID_POLL); + if(isAnalog) state=analogRead(pin); } void PolledPin::read(){ if(isAnalog){ // integrate with ::run? abstratc readAny ? @@ -228,6 +229,17 @@ void PolledPin::read(){ } else H4GPIOPin::run(); } +AnalogThresholdPin::AnalogThresholdPin(uint8_t _p,uint32_t _f,uint32_t _l,H4GM_COMPARE _cf,H4GM_FN_EVENT _c): limit(_l), fCompare(_cf), PolledPin(_p,INPUT,H4GM_PS_THRESHA,ACTIVE_HIGH,_f,true,_c) { + state=fCompare(analogRead(pin),limit); // refakta +} +void AnalogThresholdPin::read(){ + uint32_t inst=fCompare(analogRead(pin),limit); + if(inst!=state){ + stampEvent(); + _setState(inst); + } +} + SequencedPin::SequencedPin(uint8_t _p,uint8_t _g,H4GM_STYLE _s,uint8_t _a,uint32_t _t,H4GM_FN_EVENT _c): DebouncedPin(_p,_g,_s,_a,_t,_c){} void SequencedPin::sendEvent() { if(state){ @@ -238,7 +250,6 @@ void SequencedPin::sendEvent() { RetriggeringPin::RetriggeringPin(uint8_t _p,uint8_t _g,H4GM_STYLE _s,uint8_t _a,uint32_t _t,H4GM_FN_EVENT _c): H4GPIOPin(_p,_g,_s,_a,_c),timeout(_t){} void RetriggeringPin::stateChange(){ - // Serial.print("SC ");Serial.println(state); if(state){ if(timer) timer=h4.cancel(timer); else sendEvent(); @@ -302,11 +313,18 @@ void H4P_GPIOManager::toggle(uint8_t p){ if(isManaged(p)) reinterpret_cast(nullptr,pin,freq,threshold,compare,callback); +} +AnalogThresholdPin* H4P_GPIOManager::AnalogThresholdThing(uint8_t pin,uint32_t freq,uint32_t threshold,H4GM_COMPARE compare,H4P_BinaryThing* btp){ + return thingFactory(btp,pin,freq,threshold,compare,nullptr); +} + CircularPin* H4P_GPIOManager::Circular(uint8_t pin,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,uint32_t nStages,H4GM_FN_EVENT callback){ return thingFactory(nullptr,pin,mode,H4GM_PS_CIRCULAR,sense,dbTimeMs,nStages,callback); } - DebouncedPin* H4P_GPIOManager::Debounced(uint8_t pin,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,H4GM_FN_EVENT callback){ return thingFactory(nullptr,pin, mode, H4GM_PS_DEBOUNCED, sense, dbTimeMs, callback); } diff --git a/src/H4P_GPIOManager.h b/src/H4P_GPIOManager.h index 0a9b5f52..a42178df 100644 --- a/src/H4P_GPIOManager.h +++ b/src/H4P_GPIOManager.h @@ -52,6 +52,7 @@ enum H4GM_STYLE:uint8_t { H4GM_PS_RAW, H4GM_PS_REPEATING, H4GM_PS_SEQUENCED, + H4GM_PS_THRESHA, H4GM_PS_TIMED }; @@ -99,10 +100,10 @@ class H4GPIOPin{ virtual void stateChange(){ sendEvent(); }; - virtual uint32_t logicalRead(){ return state; } void _factoryCommon(H4P_BinaryThing* btp); public: + virtual uint32_t logicalRead(){ return state; } uint8_t pin=0; // GPIO hardware pin number uint8_t gpioType=0; // INPUT, INOUT_PULLUP, OUTPUT etc H4GM_STYLE style; // Strategy: Raw, debounced, retriggering etc @@ -185,11 +186,11 @@ class PolledPin: public H4GPIOPin { uint32_t frequency; bool isAnalog; - void read(); - - void run() override {} - + void run() override {} + protected: + virtual void read(); public: + // uint32_t logicalRead() override { return isAnalog ? } virtual void dump(){ H4GPIOPin::dump(); Serial.print(" frequency=");Serial.println(frequency); @@ -198,6 +199,22 @@ class PolledPin: public H4GPIOPin { PolledPin(uint8_t _p,uint8_t _g,H4GM_STYLE _s,uint8_t _a,uint32_t _f,uint32_t _v,H4GM_FN_EVENT _c); virtual ~PolledPin(){} }; +using H4GM_COMPARE=function; +#define H4GM_LESS std::less() +#define H4GM_GREATER std::greater() + +class AnalogThresholdPin: public PolledPin { + H4GM_COMPARE fCompare; + void read() override; + public: + uint32_t limit; + virtual void dump(){ + PolledPin::dump(); + Serial.print(" limit=");Serial.println(limit); + } + AnalogThresholdPin(uint8_t _p,uint32_t _f,uint32_t _l,H4GM_COMPARE _cf,H4GM_FN_EVENT _c); + virtual ~AnalogThresholdPin(){} +}; class RetriggeringPin: public H4GPIOPin { H4_TIMER timer=nullptr; @@ -224,7 +241,6 @@ class RepeatingPin: public DebouncedPin { held=t; H4GPIOPin::sendEvent(); } - void sendEvent() override; public: uint32_t held=0; @@ -303,12 +319,10 @@ class LatchingPin: public CircularPin { class OutputPin: public H4GPIOPin { void run(){} - public: void logicalWrite(uint8_t); void toggle(){ logicalWrite(!state); } - OutputPin(uint8_t _p,H4GM_STYLE _s,uint8_t _a,uint32_t _i,H4GM_FN_EVENT _c); virtual ~OutputPin(){} }; @@ -340,7 +354,6 @@ class EncoderPin: public H4GPIOPin{ EncoderPin(uint8_t _pA,uint8_t _g,H4GM_STYLE _s,uint8_t _a,H4GM_FN_EVENT _c); virtual ~EncoderPin(){} - }; class EncoderAutoPin: public EncoderPin{ @@ -398,6 +411,8 @@ class H4P_GPIOManager: public H4Plugin{// // // Strategies // + AnalogThresholdPin* AnalogThreshold(uint8_t p,uint32_t freq,uint32_t threshold,H4GM_COMPARE compare,H4GM_FN_EVENT callback);// + AnalogThresholdPin* AnalogThresholdThing(uint8_t p,uint32_t freq,uint32_t threshold,H4GM_COMPARE compare,H4P_BinaryThing* btp);// CircularPin* Circular(uint8_t p,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,uint32_t nStages,H4GM_FN_EVENT callback);// DebouncedPin* Debounced(uint8_t p,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,H4GM_FN_EVENT callback);// DebouncedPin* DebouncedThing(uint8_t p,uint8_t mode,H4GM_SENSE sense,uint32_t dbTimeMs,H4P_BinaryThing* btp);// diff --git a/src/H4P_WiFi.cpp b/src/H4P_WiFi.cpp index 201cd4ed..14e17fc2 100644 --- a/src/H4P_WiFi.cpp +++ b/src/H4P_WiFi.cpp @@ -184,7 +184,7 @@ void H4P_WiFi::_gotIP(){ ArduinoOTA.setHostname(CSTR(host)); ArduinoOTA.setRebootOnSuccess(false); ArduinoOTA.begin(); - EVENT("IP=%s\n",CSTR(_cb["ip"])); + EVENT("IP=%s",CSTR(_cb["ip"])); h4pcConnected(); } diff --git a/src/H4Plugins.cpp b/src/H4Plugins.cpp index db4366f9..ae47fff5 100644 --- a/src/H4Plugins.cpp +++ b/src/H4Plugins.cpp @@ -149,8 +149,8 @@ void H4PluginService::svc(const string& uid,H4P_LOG_TYPE ud) { #ifdef H4P_LOG_EVENTS if(H4Plugin::isLoaded(scmdTag())) { h4sc._logEvent(uid,ud,"h4","",0); - Serial.print("SVC ");Serial.print(CSTR(uid)); - Serial.print(" ");Serial.println(ud==H4P_LOG_SVC_UP ? "UP":"DOWN"); +// Serial.print("SVC ");Serial.print(CSTR(uid)); +// Serial.print(" ");Serial.println(ud==H4P_LOG_SVC_UP ? "UP":"DOWN"); } #endif }