diff --git a/.cproject b/.cproject
index 5ea270d..b1266e5 100644
--- a/.cproject
+++ b/.cproject
@@ -19,49 +19,40 @@
@@ -72,7 +63,7 @@
-
+
@@ -87,5 +78,9 @@
-
+
+
+
+
+
diff --git a/.project b/.project
index 5c3c06b..97747a4 100644
--- a/.project
+++ b/.project
@@ -34,42 +34,32 @@
core/core
2
- ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.18/cores/arduino
+ ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.21/cores/arduino
core/variant
2
- ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.18/variants/eightanaloginputs
-
-
- libraries/Adafruit_GFX_Library
- 2
- ECLIPSE_HOME/arduinoPlugin/libraries/Adafruit_GFX_Library/1.1.8
+ ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.21/variants/eightanaloginputs
libraries/Adafruit_NeoPixel
2
- ECLIPSE_HOME/arduinoPlugin/libraries/Adafruit_NeoPixel/1.0.6
-
-
- libraries/EEPROM
- 2
- ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.18/libraries/EEPROM
-
-
- libraries/MyNodeManager
- 2
- ECLIPSE_HOME/arduinoPlugin/libraries/MyNodeManager/1.0.0
+ ECLIPSE_HOME/arduinoPlugin/libraries/Adafruit_NeoPixel/1.1.6
libraries/MySensors
2
ECLIPSE_HOME/arduinoPlugin/libraries/MySensors/2.2.0
+
+ libraries/NodeManager
+ 2
+ ECLIPSE_HOME/arduinoPlugin/libraries/NodeManager/1.0.0
+
libraries/SPI
2
- ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.18/libraries/SPI
+ ECLIPSE_HOME/arduinoPlugin/packages/arduino/hardware/avr/1.6.21/libraries/SPI
diff --git a/NotificationLEDs.h b/NotificationLEDs.h
index eb60dda..d64b5c8 100644
--- a/NotificationLEDs.h
+++ b/NotificationLEDs.h
@@ -8,6 +8,23 @@
#include
+
+#define EEPROM_POS_STATUSTABLE 1
+#define EEPROM_POS_HOUROFFSET 2
+
+union _eeprom_NotificationLEDs_StatusTable {
+ struct {
+ int hourOffset : 1;
+ } status;
+ uint8_t data;
+};
+
+
+// mathematically correct modulo
+#define MOD(a,b) ((((a)%(b))+(b))%(b))
+
+
+
template<
uint8_t _tpin,
uint8_t _trgbwId,
@@ -33,6 +50,10 @@ public:
void powerOn() noexcept;
void returnToLastMode() noexcept;
+ void sendRGBWStatus() noexcept;
+ void sendDimmerStatus() noexcept;
+ void sendPowerSwitchStatus() noexcept;
+
void defaultScene_config(uint8_t id) noexcept;
void defaultScene_init() noexcept;
void defaultScene_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept;
@@ -41,6 +62,7 @@ public:
void overrideScene_init() noexcept;
void overrideScene_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept;
+ void analogClock_setup() noexcept;
void analogClock_config() noexcept;
void analogClock_init() noexcept;
void analogClock_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept;
@@ -57,6 +79,10 @@ public:
void pulse1_init() noexcept;
void pulse1_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept;
+ void follow1_config() noexcept;
+ void follow1_init() noexcept;
+ void follow1_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept;
+
protected:
unsigned long lastSendTime = 0;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(_tpixelCount, _tpin, NEO_GRBW + NEO_KHZ800);
@@ -110,6 +136,19 @@ protected:
uint8_t pulseValue = 0;
unsigned long lastMillis = 0;
} pulse1;
+ struct {
+ union {
+ uint8_t wrgb[4];
+ uint32_t color = 0x00FF0000;
+ } color;
+ uint8_t maxCycles = 5;
+ int8_t followDir = 1;
+ int8_t followPos = 0;
+ uint8_t waitTime = 50;
+ uint8_t currentCycles = 0;
+ bool finishing = false;
+ unsigned long lastMillis = 0;
+ } follow1;
} sceneData;
};
@@ -138,6 +177,7 @@ template<
> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
::setup() noexcept {
pixels.begin();
+ analogClock_setup();
defaultScene_init();
}
@@ -163,6 +203,62 @@ template<
}
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::sendRGBWStatus() noexcept {
+ if (mode > 0 && sceneMode == 1) {
+ _sendValue(true, _trgbwId, V_STATUS);
+ char rgbw[9] = "00000000";
+ // WRGB => RGBW
+ String tmp((staticColor.color & 0xFF000000) >> 24 | ((staticColor.color & 0x00FFFFFF) << 8));
+ memcpy(rgbw+(8-tmp.length()), tmp.c_str(), tmp.length());
+ _sendValue(rgbw, _trgbwId, V_RGBW);
+ } else {
+ _sendValue(false, _trgbwId, V_STATUS);
+ }
+}
+
+
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::sendDimmerStatus() noexcept {
+ if (sceneMode == 0) {
+ _sendValue(brightness, _tdimmerId, V_PERCENTAGE);
+ } else {
+ uint16_t cb = max(staticColor.wrgb[0], max(staticColor.wrgb[1], max(staticColor.wrgb[2], staticColor.wrgb[3]))) * 100 / 255;
+ _sendValue(cb, _tdimmerId, V_PERCENTAGE);
+ }
+}
+
+
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::sendPowerSwitchStatus() noexcept {
+ _sendValue(mode == 0 ? 0 : 1, _tpowerSwitchId, V_STATUS);
+}
+
+
template<
uint8_t _tpin,
uint8_t _trgbwId,
@@ -184,22 +280,11 @@ template<
if (lastSendTime == 0 || currentMillis - lastSendTime >= _msgSendInterval) {
// RGBW Sensor
- char rgbw[9] = "00000000";
- // WRGB => RGBW
- String tmp((staticColor.color & 0xFF000000) >> 24 | ((staticColor.color & 0x00FFFFFF) << 8));
- memcpy(rgbw+(8-tmp.length()), tmp.c_str(), tmp.length());
- _sendValue(rgbw, _trgbwId, V_RGBW);
-
+ sendRGBWStatus();
//Dimmer
- if (sceneMode == 0) {
- _sendValue(brightness, _tdimmerId, V_STATUS);
- } else {
- uint16_t cb = max(staticColor.wrgb[0], max(staticColor.wrgb[1], max(staticColor.wrgb[2], staticColor.wrgb[3]))) * 100 / 255;
- _sendValue(cb, _tdimmerId, V_STATUS);
- }
-
+ sendDimmerStatus();
//Power Switch
- _sendValue(mode == 0 ? 0 : 1, _tpowerSwitchId, V_STATUS);
+ sendPowerSwitchStatus();
lastSendTime = currentMillis;
}
@@ -223,7 +308,7 @@ template<
// Set Message
if (msg.getCommand() == C_SET) {
if (msg.type == V_STATUS) {
- auto onOff = msg.getByte();
+ auto onOff = msg.getBool();
if (onOff) {
enableStaticColor();
} else {
@@ -248,13 +333,14 @@ template<
setStaticColor((color & 0xFFFFFF00) >> 8 | ((color & 0xFF) << 24));
retval = true;
}
+ if (retval) {
+ sendPowerSwitchStatus();
+ sendRGBWStatus();
+ sendDimmerStatus();
+ }
// Request Message
} else if (msg.getCommand() == C_REQ) {
- char rgbw[9] = "00000000";
- // WRGB => RGBW
- String tmp((staticColor.color & 0xFF000000) >> 24 | ((staticColor.color & 0x00FFFFFF) << 8));
- memcpy(rgbw+(8-tmp.length()), tmp.c_str(), tmp.length());
- _sendValue(rgbw, _trgbwId, V_RGBW);
+ sendRGBWStatus();
retval = true;
}
}
@@ -281,15 +367,11 @@ template<
setStaticColor(staticColor.color);
}
retval = true;
+ sendDimmerStatus();
}
// Request Message
} else if (msg.getCommand() == C_REQ) {
- if (sceneMode == 0) {
- _sendValue(brightness, _tdimmerId, V_STATUS);
- } else {
- uint16_t cb = max(staticColor.wrgb[0], max(staticColor.wrgb[1], max(staticColor.wrgb[2], staticColor.wrgb[3]))) * 100 / 255;
- _sendValue(cb, _tdimmerId, V_STATUS);
- }
+ sendDimmerStatus();
retval = true;
}
}
@@ -306,10 +388,13 @@ template<
powerOn();
}
retval = true;
+ sendPowerSwitchStatus();
+ sendRGBWStatus();
+ sendDimmerStatus();
}
// Request Message
} else if (msg.getCommand() == C_REQ) {
- _sendValue(mode == 0 ? 0 : 1, _tpowerSwitchId, V_STATUS);
+ sendPowerSwitchStatus();
retval = true;
}
}
@@ -578,6 +663,9 @@ template<
if (id == 0) {
overrideScene = id;
pulse1_config();
+ } else if (id == 1) {
+ overrideScene = id;
+ follow1_config();
}
}
@@ -594,6 +682,8 @@ template<
::overrideScene_init() noexcept {
if (overrideScene == 0) {
pulse1_init();
+ } else if (overrideScene == 1) {
+ follow1_init();
}
}
@@ -610,12 +700,15 @@ template<
::overrideScene_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept {
if (overrideScene == 0) {
pulse1_loop(currentUnixTime, currentMillis);
+ } else if (overrideScene == 1) {
+ follow1_loop(currentUnixTime, currentMillis);
}
}
#include "SceneAnalogClock.h"
#include "SceneColorWheel.h"
#include "ScenePulse.h"
+#include "SceneFollow.h"
diff --git a/SceneAnalogClock.h b/SceneAnalogClock.h
index 4bb601a..ccc7f84 100644
--- a/SceneAnalogClock.h
+++ b/SceneAnalogClock.h
@@ -8,6 +8,24 @@
#include "NotificationLEDs.h"
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::analogClock_setup() noexcept {
+ _eeprom_NotificationLEDs_StatusTable statusTable;
+ statusTable.data = loadState(EEPROM_POS_STATUSTABLE);
+ if (statusTable.status.hourOffset == 1) {
+ sceneData.analogClock.hourOffset = (int8_t)loadState(EEPROM_POS_HOUROFFSET);
+ }
+}
+
+
template<
uint8_t _tpin,
uint8_t _trgbwId,
@@ -22,6 +40,11 @@ template<
if (token && token[0] != ' ') {
auto offset = atoi(token);
sceneData.analogClock.hourOffset = offset;
+ _eeprom_NotificationLEDs_StatusTable statusTable;
+ statusTable.data = loadState(EEPROM_POS_STATUSTABLE);
+ statusTable.status.hourOffset = 1;
+ saveState(EEPROM_POS_HOUROFFSET, offset);
+ saveState(EEPROM_POS_STATUSTABLE, statusTable.data);
}
token = strtok(NULL, _configDelims);
if (token && token[0] != ' ') {
diff --git a/SceneColorWheel.h b/SceneColorWheel.h
index f7af58c..56ae151 100644
--- a/SceneColorWheel.h
+++ b/SceneColorWheel.h
@@ -26,9 +26,6 @@ void _colorWheel_mapIndex(uint16_t c, uint16_t& r, uint16_t& g, uint16_t& b) {
}
}
-// mathematically correct modulo
-#define MOD(a,b) ((((a)%(b))+(b))%(b))
-
template<
uint8_t _tpin,
uint8_t _trgbwId,
diff --git a/SceneFollow.h b/SceneFollow.h
new file mode 100644
index 0000000..e38dd00
--- /dev/null
+++ b/SceneFollow.h
@@ -0,0 +1,105 @@
+#ifndef SCENEFOLLOW_H_
+#define SCENEFOLLOW_H_
+
+#include
+#include
+#include
+#include
+#include "NotificationLEDs.h"
+
+
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::follow1_config() noexcept {
+ auto token = strtok(NULL, _configDelims);
+ if (token && token[0] != ' ') {
+ auto color = strtoul(token, NULL, 16);
+ sceneData.follow1.color.color = color;
+ }
+ token = strtok(NULL, _configDelims);
+ if (token && token[0] != ' ') {
+ auto maxCycles = atoi(token);
+ sceneData.follow1.maxCycles = maxCycles;
+ }
+ token = strtok(NULL, _configDelims);
+ if (token && token[0] != ' ') {
+ auto followDir = atoi(token);
+ sceneData.follow1.followDir = followDir;
+ }
+ token = strtok(NULL, _configDelims);
+ if (token && token[0] != ' ') {
+ auto waitTime = atoi(token);
+ sceneData.follow1.waitTime = waitTime;
+ }
+}
+
+
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::follow1_init() noexcept {
+ for (uint8_t i = 0; i < _tpixelCount; i++) {
+ pixels.setPixelColor(i, 0);
+ }
+ pixels.show();
+ if (sceneData.follow1.followDir > 0) {
+ sceneData.follow1.followPos = 0;
+ } else {
+ sceneData.follow1.followPos = 11;
+ }
+ sceneData.follow1.finishing = false;
+ sceneData.follow1.currentCycles = 0;
+ sceneData.follow1.lastMillis = 0;
+}
+
+
+template<
+ uint8_t _tpin,
+ uint8_t _trgbwId,
+ uint8_t _tdimmerId,
+ uint8_t _tpowerSwitchId,
+ uint8_t _tcommandId,
+ uint16_t _tpixelCount,
+ unsigned long _msgSendInterval
+> void NotificationLEDs<_tpin, _trgbwId, _tdimmerId, _tpowerSwitchId, _tcommandId, _tpixelCount, _msgSendInterval>
+::follow1_loop(unsigned long currentUnixTime, unsigned long currentMillis) noexcept {
+ if (currentMillis - sceneData.follow1.lastMillis >= sceneData.follow1.waitTime) {
+ if (sceneData.follow1.finishing) {
+ auto delPos = MOD(sceneData.follow1.followPos-sceneData.follow1.followDir*4, 12);
+ pixels.setPixelColor(delPos, 0);
+ pixels.show();
+ sceneData.follow1.followPos += sceneData.follow1.followDir;
+ if (sceneData.follow1.followPos > 4 && sceneData.follow1.followPos < 7) {
+ returnToLastMode();
+ }
+ } else {
+ pixels.setPixelColor(sceneData.follow1.followPos, sceneData.follow1.color.color);
+ auto delPos = MOD(sceneData.follow1.followPos-sceneData.follow1.followDir*4, 12);
+ pixels.setPixelColor(delPos, 0);
+ pixels.show();
+ sceneData.follow1.followPos += sceneData.follow1.followDir;
+ if (sceneData.follow1.followPos < 0 || sceneData.follow1.followPos > 11) {
+ sceneData.follow1.followPos = MOD(sceneData.follow1.followPos, 12);
+ if (sceneData.follow1.maxCycles > 0 && sceneData.follow1.currentCycles > sceneData.follow1.maxCycles) {
+ sceneData.follow1.finishing = true;
+ }
+ }
+ }
+ sceneData.follow1.lastMillis = currentMillis;
+ }
+}
+
+#endif /* SCENEFOLLOW_H_ */