|
| 1 | +#include "wled.h" |
| 2 | + |
| 3 | +/* |
| 4 | + * Usermods allow you to add own functionality to WLED more easily |
| 5 | + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality |
| 6 | + * |
| 7 | + * This is Stairway-Wipe as a v2 usermod. |
| 8 | + * |
| 9 | + * Using this usermod: |
| 10 | + * 1. Copy the usermod into the sketch folder (same folder as wled00.ino) |
| 11 | + * 2. Register the usermod by adding #include "stairway-wipe-usermod-v2.h" in the top and registerUsermod(new StairwayWipeUsermod()) in the bottom of usermods_list.cpp |
| 12 | + */ |
| 13 | + |
| 14 | +class StairwayWipeUsermod : public Usermod { |
| 15 | + private: |
| 16 | + //Private class members. You can declare variables and functions only accessible to your usermod here |
| 17 | + unsigned long lastTime = 0; |
| 18 | + byte wipeState = 0; //0: inactive 1: wiping 2: solid |
| 19 | + unsigned long timeStaticStart = 0; |
| 20 | + uint16_t previousUserVar0 = 0; |
| 21 | + |
| 22 | +//comment this out if you want the turn off effect to be just fading out instead of reverse wipe |
| 23 | +#define STAIRCASE_WIPE_OFF |
| 24 | + public: |
| 25 | + |
| 26 | + void loop() { |
| 27 | + //userVar0 (U0 in HTTP API): |
| 28 | + //has to be set to 1 if movement is detected on the PIR that is the same side of the staircase as the ESP8266 |
| 29 | + //has to be set to 2 if movement is detected on the PIR that is the opposite side |
| 30 | + //can be set to 0 if no movement is detected. Otherwise LEDs will turn off after a configurable timeout (userVar1 seconds) |
| 31 | + |
| 32 | + if (userVar0 > 0) |
| 33 | + { |
| 34 | + if ((previousUserVar0 == 1 && userVar0 == 2) || (previousUserVar0 == 2 && userVar0 == 1)) wipeState = 3; //turn off if other PIR triggered |
| 35 | + previousUserVar0 = userVar0; |
| 36 | + |
| 37 | + if (wipeState == 0) { |
| 38 | + startWipe(); |
| 39 | + wipeState = 1; |
| 40 | + } else if (wipeState == 1) { //wiping |
| 41 | + uint32_t cycleTime = 360 + (255 - effectSpeed)*75; //this is how long one wipe takes (minus 25 ms to make sure we switch in time) |
| 42 | + if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete |
| 43 | + effectCurrent = FX_MODE_STATIC; |
| 44 | + timeStaticStart = millis(); |
| 45 | + colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); |
| 46 | + wipeState = 2; |
| 47 | + } |
| 48 | + } else if (wipeState == 2) { //static |
| 49 | + if (userVar1 > 0) //if U1 is not set, the light will stay on until second PIR or external command is triggered |
| 50 | + { |
| 51 | + if (millis() - timeStaticStart > userVar1*1000) wipeState = 3; |
| 52 | + } |
| 53 | + } else if (wipeState == 3) { //switch to wipe off |
| 54 | + #ifdef STAIRCASE_WIPE_OFF |
| 55 | + effectCurrent = FX_MODE_COLOR_WIPE; |
| 56 | + strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit |
| 57 | + colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); |
| 58 | + wipeState = 4; |
| 59 | + #else |
| 60 | + turnOff(); |
| 61 | + #endif |
| 62 | + } else { //wiping off |
| 63 | + if (millis() + strip.timebase > (725 + (255 - effectSpeed)*150)) turnOff(); //wipe complete |
| 64 | + } |
| 65 | + } else { |
| 66 | + wipeState = 0; //reset for next time |
| 67 | + if (previousUserVar0) { |
| 68 | + #ifdef STAIRCASE_WIPE_OFF |
| 69 | + userVar0 = previousUserVar0; |
| 70 | + wipeState = 3; |
| 71 | + #else |
| 72 | + turnOff(); |
| 73 | + #endif |
| 74 | + } |
| 75 | + previousUserVar0 = 0; |
| 76 | + } |
| 77 | +} |
| 78 | + |
| 79 | + void readFromJsonState(JsonObject& root) |
| 80 | + { |
| 81 | + userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value |
| 82 | + //if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!")); |
| 83 | + } |
| 84 | + |
| 85 | + void addToConfig(JsonObject& root) |
| 86 | + { |
| 87 | + JsonObject top = root.createNestedObject("exampleUsermod"); |
| 88 | + top["great"] = userVar0; //save this var persistently whenever settings are saved |
| 89 | + } |
| 90 | + |
| 91 | + void readFromConfig(JsonObject& root) |
| 92 | + { |
| 93 | + JsonObject top = root["top"]; |
| 94 | + userVar0 = top["great"] | 42; //The value right of the pipe "|" is the default value in case your setting was not present in cfg.json (e.g. first boot) |
| 95 | + } |
| 96 | + |
| 97 | + uint16_t getId() |
| 98 | + { |
| 99 | + return USERMOD_ID_EXAMPLE; |
| 100 | + } |
| 101 | + |
| 102 | + |
| 103 | + void startWipe() |
| 104 | + { |
| 105 | + bri = briLast; //turn on |
| 106 | + transitionDelayTemp = 0; //no transition |
| 107 | + effectCurrent = FX_MODE_COLOR_WIPE; |
| 108 | + resetTimebase(); //make sure wipe starts from beginning |
| 109 | + |
| 110 | + //set wipe direction |
| 111 | + WS2812FX::Segment& seg = strip.getSegment(0); |
| 112 | + bool doReverse = (userVar0 == 2); |
| 113 | + seg.setOption(1, doReverse); |
| 114 | + |
| 115 | + colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); |
| 116 | + } |
| 117 | + |
| 118 | + void turnOff() |
| 119 | + { |
| 120 | + #ifdef STAIRCASE_WIPE_OFF |
| 121 | + transitionDelayTemp = 0; //turn off immediately after wipe completed |
| 122 | + #else |
| 123 | + transitionDelayTemp = 4000; //fade out slowly |
| 124 | + #endif |
| 125 | + bri = 0; |
| 126 | + colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); |
| 127 | + wipeState = 0; |
| 128 | + userVar0 = 0; |
| 129 | + previousUserVar0 = 0; |
| 130 | + } |
| 131 | + |
| 132 | + |
| 133 | + |
| 134 | + //More methods can be added in the future, this example will then be extended. |
| 135 | + //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! |
| 136 | +}; |
0 commit comments