#include "millisDelay.h"
#include <Adafruit_NeoPixel.h>
#include <stdio.h>
#define LED_PIN 21
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 12
#define SECONDS_PER_LED 300
#define STATE_UNSET -1
#define STATE_AVAILABLE 0
#define STATE_DND 1
#define DIM_FACTOR 0.1
#define VERSION "1.0.0"
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_RGBW + NEO_KHZ800);
bool dnd = false;
millisDelay dndTimer;
uint32_t dndColor;
int dndCountdownStep;
int currentState = STATE_UNSET;
unsigned long dndTime;
void setup() {
dndCountdownStep = 0;
// put your setup code here, to run once:
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
setDefaultDndColor();
Serial.begin(115200);
Serial.println("OneThing DND Display");
startDnd(1800);
}
void loop() {
checkCommand();
checkState();
}
void checkCommand() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
if(command == "HELLO") {
Serial.println("OneThing DND Display");
} else if(command == "VERSION") {
Serial.println(VERSION);
} else if(command == "DND:OFF") {
endDnd();
Serial.println("OK");
} else if(command == "DND:ON") {
startDnd(0);
Serial.println("OK");
} else if(command.startsWith("DND:ON:")) {
String secondsParam = command.substring(7);
long seconds = secondsParam.toInt();
startDnd(seconds * 1000);
Serial.println("OK");
}
}
}
void checkState()
{
int state;
int step = 0;
if(dnd) {
state = STATE_DND;
if(dndTime > 0) {
if(dndTimer.justFinished()) {
state = STATE_AVAILABLE;
endDnd();
} else {
unsigned long remaining = dndTimer.remaining();
unsigned long threshold = ((unsigned long)LED_COUNT * (unsigned long)SECONDS_PER_LED * 1000);
//Serial.println(remaining);
//Serial.println(threshold);
if(remaining < threshold) {
//Serial.println((unsigned long)SECONDS_PER_LED * 1000);
//Serial.println(threshold - remaining);
step = (threshold - remaining) / ((unsigned long)SECONDS_PER_LED * 1000);
//Serial.println(step);
}
}
}
} else {
state = STATE_AVAILABLE;
}
updateState(state, step);
}
void startDnd(unsigned long ms)
{
dnd = true;
dndTime = ms;
if(ms > 0) {
dndTimer.start(ms);
}
//Serial.print(ms);
//Serial.println("Starting DND");
}
void endDnd()
{
dnd = false;
dndTime = 0;
}
void updateState(int newState, int countdownStep)
{
if(currentState == newState && (newState != STATE_DND || dndCountdownStep == countdownStep)) {
return;
}
switch(newState) {
case STATE_AVAILABLE:
displayAvailable();
break;
case STATE_DND:
displayDnd(countdownStep);
break;
}
currentState = newState;
dndCountdownStep = countdownStep;
}
void setDefaultDndColor()
{
dndColor = rgbw(255, 0, 0, 0);
}
void displayAvailable()
{
colorWipe(rgbw(0, 0, 0, 127), 50);
Serial.println("Set to available");
}
void displayDnd(int step)
{
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
if(i < step) {
strip.setPixelColor(i, dimmed(dndColor, DIM_FACTOR));
} else {
strip.setPixelColor(i, dndColor);
}
strip.show(); // Update strip to match
}
Serial.println("Set to DND");
}
uint32_t rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
uint8_t colors[] = {b,r,g,w};
return *((uint32_t*) colors);
}
uint32_t dimmed(uint32_t color, float factor) {
uint8_t colors[4] = {0};
for(int j=0; j < 4; j++)
{
uint8_t c = ((uint8_t*)&dndColor)[j];
c = c * factor;
colors[j] = c;
}
return *((uint32_t*) colors);
}
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}