Compare commits
7 Commits
d3da31d6db
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 57cfbe9a9c | |||
| d0b0041a40 | |||
| f4fbd95183 | |||
| 30a30b30de | |||
| d2ac7c4903 | |||
| 2bed562f44 | |||
| 23df52cbb6 |
10
README.md
10
README.md
@@ -6,10 +6,16 @@ But it might as well be used as a fast clock display for model railroads.
|
|||||||
|
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
|
|
||||||
* WS-2812 based adressable LED chain forming the 7-segment display
|
- WS-2812 based adressable LED chain forming the 7-segment display
|
||||||
* number of LEDs per segment is configurable
|
- number of LEDs per segment is configurable
|
||||||
|
|
||||||
|
This is, how it could look like (fyi: the big cargo car is 1:45 scale, the small one is 1:160):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The configuration menu allows the selection of real or fast clock and some options like colors, fastclock name or UTC time offset for real time:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Links / References
|
## Links / References
|
||||||
|
|
||||||
|
|||||||
BIN
doc/Clock1a.png
Normal file
BIN
doc/Clock1a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 178 KiB |
BIN
doc/WebConfig.png
Normal file
BIN
doc/WebConfig.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -26,6 +26,7 @@ class ClockClient
|
|||||||
void begin();
|
void begin();
|
||||||
void loop();
|
void loop();
|
||||||
static void setListenToClock(const char *_name) { name = String(_name); }
|
static void setListenToClock(const char *_name) { name = String(_name); }
|
||||||
|
static void setListenToClock(String _name) { name = String(_name); }
|
||||||
static const char * const getLastMessage();
|
static const char * const getLastMessage();
|
||||||
static String const getText() { return text; }
|
static String const getText() { return text; }
|
||||||
static String const getClock() { return clock; }
|
static String const getClock() { return clock; }
|
||||||
|
|||||||
@@ -128,11 +128,10 @@ void Config::loadFile(const char *filename, const char * const sectionConfigItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Config::writeAllConfigs(void) {
|
void Config::writeAllConfigs(void) {
|
||||||
boolean allChangesWritten = false;
|
|
||||||
logHeap();
|
logHeap();
|
||||||
|
debug.out(F("Write all changed configs, checking ")); debug.out(numberOfConfigItems); debug.outln(F(" items."));
|
||||||
while (!allChangesWritten) {
|
|
||||||
for (int i=0; i<numberOfConfigItems; ++i) {
|
for (int i=0; i<numberOfConfigItems; ++i) {
|
||||||
|
debug.out("["); debug.out(i); debug.out("] ");
|
||||||
debug.out(configItems[i].section);
|
debug.out(configItems[i].section);
|
||||||
debug.out(".");
|
debug.out(".");
|
||||||
debug.out(configItems[i].name);
|
debug.out(configItems[i].name);
|
||||||
@@ -142,12 +141,9 @@ void Config::writeAllConfigs(void) {
|
|||||||
debug.outln(configItems[i].value);
|
debug.outln(configItems[i].value);
|
||||||
if (configItems[i].changed) {
|
if (configItems[i].changed) {
|
||||||
writeConfigFile(configItems[i].section);
|
writeConfigFile(configItems[i].section);
|
||||||
break; // leave for-loop and restart search for changes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no further changes found, we are done
|
logHeap();
|
||||||
allChangesWritten = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::writeConfigFile(String filename) {
|
void Config::writeConfigFile(String filename) {
|
||||||
@@ -229,10 +225,12 @@ void Config::setString(String key, String value) {
|
|||||||
debug.out(F("ERROR: Tried to set new value, but cannot find config item ")); debug.outln(key);
|
debug.out(F("ERROR: Tried to set new value, but cannot find config item ")); debug.outln(key);
|
||||||
} else {
|
} else {
|
||||||
// debug.outln(configItems[index].value);
|
// debug.outln(configItems[index].value);
|
||||||
|
if (!configItems[index].value.equals(value)) {
|
||||||
configItems[index].value = String(value);
|
configItems[index].value = String(value);
|
||||||
configItems[index].changed = true;
|
configItems[index].changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Config::getInt(String key)
|
int Config::getInt(String key)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <DjSimpleFS.h>
|
#include "DjSimpleFS.h"
|
||||||
|
|
||||||
boolean SimpleFS::_initialized = false;
|
boolean SimpleFS::_initialized = false;
|
||||||
FSInfo SimpleFS::fsInfo;
|
FSInfo SimpleFS::fsInfo;
|
||||||
@@ -76,4 +76,3 @@ size_t SimpleFS::getMaxPathLength() {
|
|||||||
}
|
}
|
||||||
return fsInfo.maxPathLength;
|
return fsInfo.maxPathLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ SevenSegmentClock::colorSelection[] = {
|
|||||||
{ Red, "Red", 255, 0, 0 },
|
{ Red, "Red", 255, 0, 0 },
|
||||||
{ Green, "Green", 0, 255, 0 },
|
{ Green, "Green", 0, 255, 0 },
|
||||||
{ White, "White", 255, 255, 255 },
|
{ White, "White", 255, 255, 255 },
|
||||||
{ Yellow, "Yellow", 255, 255, 0 }
|
{ Yellow, "Yellow", 255, 255, 0 },
|
||||||
|
{ Magenta, "Magenta", 255, 0, 255 },
|
||||||
|
{ Magenta, "Cyan", 0, 255, 255 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int SevenSegmentClock::numberOfSupportedColors = sizeof(SevenSegmentClock::colorSelection) / sizeof(SevenSegmentClock::colorSelection[0]);
|
int SevenSegmentClock::numberOfSupportedColors = sizeof(SevenSegmentClock::colorSelection) / sizeof(SevenSegmentClock::colorSelection[0]);
|
||||||
@@ -173,23 +175,27 @@ void SevenSegmentClock::displayDigit(unsigned int digitNum, char charToDisplay)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SevenSegmentClock::displaySeperator(char seperatorCharacter) {
|
void SevenSegmentClock::displaySeperator(char seperatorCharacter) {
|
||||||
|
displaySeperator(seperatorCharacter, currentColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SevenSegmentClock::displaySeperator(char seperatorCharacter, uint32_t color) {
|
||||||
//Serial.print("displaySeperator: seperator="); Serial.println(seperatorCharacter);
|
//Serial.print("displaySeperator: seperator="); Serial.println(seperatorCharacter);
|
||||||
switch (seperatorCharacter) {
|
switch (seperatorCharacter) {
|
||||||
case '.':
|
case '.':
|
||||||
case ',':
|
case ',':
|
||||||
strip->setPixelColor(decimalPointLed, currentColor);
|
strip->setPixelColor(decimalPointLed, color);
|
||||||
strip->setPixelColor(clockSeperatorLed1, black);
|
strip->setPixelColor(clockSeperatorLed1, black);
|
||||||
strip->setPixelColor(clockSeperatorLed2, black);
|
strip->setPixelColor(clockSeperatorLed2, black);
|
||||||
break;
|
break;
|
||||||
case ':':
|
case ':':
|
||||||
strip->setPixelColor(decimalPointLed, black);
|
strip->setPixelColor(decimalPointLed, black);
|
||||||
strip->setPixelColor(clockSeperatorLed1, currentColor);
|
strip->setPixelColor(clockSeperatorLed1, color);
|
||||||
strip->setPixelColor(clockSeperatorLed2, currentColor);
|
strip->setPixelColor(clockSeperatorLed2, color);
|
||||||
break;
|
break;
|
||||||
case '|':
|
case '|':
|
||||||
strip->setPixelColor(decimalPointLed, currentColor);
|
strip->setPixelColor(decimalPointLed, color);
|
||||||
strip->setPixelColor(clockSeperatorLed1, currentColor);
|
strip->setPixelColor(clockSeperatorLed1, color);
|
||||||
strip->setPixelColor(clockSeperatorLed2, currentColor);
|
strip->setPixelColor(clockSeperatorLed2, color);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Serial.print("SevenSegmentClock::displaySeperator: Unknown character to be displayed: ");
|
Serial.print("SevenSegmentClock::displaySeperator: Unknown character to be displayed: ");
|
||||||
@@ -203,6 +209,14 @@ void SevenSegmentClock::displaySeperator(char seperatorCharacter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SevenSegmentClock::displaySeperator(uint32_t color) {
|
||||||
|
strip->setPixelColor(clockSeperatorLed1, color);
|
||||||
|
strip->setPixelColor(clockSeperatorLed2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SevenSegmentClock::displayDecimalPoint(uint32_t color) {
|
||||||
|
strip->setPixelColor(decimalPointLed, color);
|
||||||
|
}
|
||||||
|
|
||||||
void SevenSegmentClock::displayTime(int hour, int minute) {
|
void SevenSegmentClock::displayTime(int hour, int minute) {
|
||||||
if (clockHour != hour || clockMinute != minute) {
|
if (clockHour != hour || clockMinute != minute) {
|
||||||
@@ -236,7 +250,9 @@ void SevenSegmentClock::displayUpdate(void) {
|
|||||||
displayDigit(1, displayText[1]);
|
displayDigit(1, displayText[1]);
|
||||||
displayDigit(2, displayText[2]);
|
displayDigit(2, displayText[2]);
|
||||||
displayDigit(3, displayText[3]);
|
displayDigit(3, displayText[3]);
|
||||||
displaySeperator(':');
|
//displaySeperator(':');
|
||||||
|
displaySeperator(currentColor);
|
||||||
|
displayDecimalPoint(black);
|
||||||
break;
|
break;
|
||||||
case ClockBlinking:
|
case ClockBlinking:
|
||||||
if (currentlyBlinkOn) {
|
if (currentlyBlinkOn) {
|
||||||
@@ -244,17 +260,15 @@ void SevenSegmentClock::displayUpdate(void) {
|
|||||||
displayDigit(1, displayText[1]);
|
displayDigit(1, displayText[1]);
|
||||||
displayDigit(2, displayText[2]);
|
displayDigit(2, displayText[2]);
|
||||||
displayDigit(3, displayText[3]);
|
displayDigit(3, displayText[3]);
|
||||||
displaySeperator(':');
|
//displaySeperator(':');
|
||||||
|
displaySeperator(currentColor);
|
||||||
} else {
|
} else {
|
||||||
displayDigit(0, ' ');
|
displayDigit(0, ' ');
|
||||||
displayDigit(1, ' ');
|
displayDigit(1, ' ');
|
||||||
displayDigit(2, ' ');
|
displayDigit(2, ' ');
|
||||||
displayDigit(3, ' ');
|
displayDigit(3, ' ');
|
||||||
displaySeperator(' ');
|
//displaySeperator(' ');
|
||||||
}
|
displaySeperator(black);
|
||||||
if (millis() > nextBlinkSwitch_ms) {
|
|
||||||
currentlyBlinkOn = !currentlyBlinkOn;
|
|
||||||
nextBlinkSwitch_ms = millis() + (currentlyBlinkOn ? BLINK_ON_TIME_ms : BLINK_OFF_TIME_ms);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SeperatorBlinking:
|
case SeperatorBlinking:
|
||||||
@@ -263,13 +277,13 @@ void SevenSegmentClock::displayUpdate(void) {
|
|||||||
displayDigit(2, displayText[2]);
|
displayDigit(2, displayText[2]);
|
||||||
displayDigit(3, displayText[3]);
|
displayDigit(3, displayText[3]);
|
||||||
if (currentlyBlinkOn) {
|
if (currentlyBlinkOn) {
|
||||||
displaySeperator('|');
|
//displaySeperator('|');
|
||||||
|
displaySeperator(currentColor);
|
||||||
|
displayDecimalPoint(currentColor);
|
||||||
} else {
|
} else {
|
||||||
displaySeperator(' ');
|
//displaySeperator(' ');
|
||||||
}
|
displaySeperator(black);
|
||||||
if (millis() > nextBlinkSwitch_ms) {
|
displayDecimalPoint(black);
|
||||||
currentlyBlinkOn = !currentlyBlinkOn;
|
|
||||||
nextBlinkSwitch_ms = millis() + (currentlyBlinkOn ? BLINK_ON_TIME_ms : BLINK_OFF_TIME_ms);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DecimalPointBlinking:
|
case DecimalPointBlinking:
|
||||||
@@ -278,16 +292,31 @@ void SevenSegmentClock::displayUpdate(void) {
|
|||||||
displayDigit(2, displayText[2]);
|
displayDigit(2, displayText[2]);
|
||||||
displayDigit(3, displayText[3]);
|
displayDigit(3, displayText[3]);
|
||||||
if (currentlyBlinkOn) {
|
if (currentlyBlinkOn) {
|
||||||
displaySeperator('.');
|
//displaySeperator('.');
|
||||||
|
displayDecimalPoint(currentColor);
|
||||||
} else {
|
} else {
|
||||||
displaySeperator(' ');
|
//displaySeperator(' ');
|
||||||
|
displayDecimalPoint(black);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DecimalPointColoredBlinking:
|
||||||
|
displayDigit(0, displayText[0]);
|
||||||
|
displayDigit(1, displayText[1]);
|
||||||
|
displayDigit(2, displayText[2]);
|
||||||
|
displayDigit(3, displayText[3]);
|
||||||
|
if (currentlyBlinkOn) {
|
||||||
|
//displaySeperator('.', currentColor);
|
||||||
|
displayDecimalPoint(currentColor);
|
||||||
|
} else {
|
||||||
|
//displaySeperator('.', blinkColor);
|
||||||
|
displayDecimalPoint(blinkColor);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (millis() > nextBlinkSwitch_ms) {
|
if (millis() > nextBlinkSwitch_ms) {
|
||||||
currentlyBlinkOn = !currentlyBlinkOn;
|
currentlyBlinkOn = !currentlyBlinkOn;
|
||||||
nextBlinkSwitch_ms = millis() + (currentlyBlinkOn ? BLINK_ON_TIME_ms : BLINK_OFF_TIME_ms);
|
nextBlinkSwitch_ms = millis() + (currentlyBlinkOn ? BLINK_ON_TIME_ms : BLINK_OFF_TIME_ms);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
strip->show();
|
strip->show();
|
||||||
//Serial.print("Shown: "); Serial.print(displayText[0]); Serial.print(displayText[1]);
|
//Serial.print("Shown: "); Serial.print(displayText[0]); Serial.print(displayText[1]);
|
||||||
//Serial.print(':'); Serial.print(displayText[2]); Serial.println(displayText[3]);
|
//Serial.print(':'); Serial.print(displayText[2]); Serial.println(displayText[3]);
|
||||||
@@ -295,35 +324,68 @@ void SevenSegmentClock::displayUpdate(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SevenSegmentClock::red, SevenSegmentClock::green, SevenSegmentClock::blue, SevenSegmentClock::white, SevenSegmentClock::black, SevenSegmentClock::yellow;
|
|
||||||
uint8_t SevenSegmentClock::LedDataPin;
|
uint8_t SevenSegmentClock::LedDataPin;
|
||||||
Adafruit_NeoPixel *SevenSegmentClock::strip;
|
Adafruit_NeoPixel *SevenSegmentClock::strip;
|
||||||
|
|
||||||
void SevenSegmentClock::initColors(uint8_t _brightness) {
|
|
||||||
#if 0
|
|
||||||
SevenSegmentClock::red = strip->Color(_brightness, 0, 0);
|
|
||||||
SevenSegmentClock::green = strip->Color(0, _brightness, 0);
|
|
||||||
SevenSegmentClock::blue = strip->Color(0, 0, _brightness);
|
|
||||||
SevenSegmentClock::white = strip->Color(_brightness, _brightness, _brightness);
|
|
||||||
SevenSegmentClock::black = strip->Color(0, 0, 0);
|
|
||||||
SevenSegmentClock::yellow = strip->Color(_brightness, _brightness, 0);
|
|
||||||
SevenSegmentClock::setColor(SevenSegmentClock::getColor()); // reset color to enforce reclaculation
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SevenSegmentClock::setColor(Color color) {
|
void SevenSegmentClock::setColor(Color color) {
|
||||||
currentColorHandle = color;
|
currentColorHandle = color;
|
||||||
currentColor = getColorByHandle(color);
|
currentColor = getColorByHandle(color);
|
||||||
#if 0
|
|
||||||
switch (currentColorHandle) {
|
|
||||||
case Black: currentColor = SevenSegmentClock::black; break;
|
|
||||||
case Blue: currentColor = SevenSegmentClock::blue; break;
|
|
||||||
case Red: currentColor = SevenSegmentClock::red; break;
|
|
||||||
case Green: currentColor = SevenSegmentClock::green; break;
|
|
||||||
case White: currentColor = SevenSegmentClock::white; break;
|
|
||||||
case Yellow: currentColor = SevenSegmentClock::yellow; break;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
void SevenSegmentClock::setBlinkColor(Color color) {
|
||||||
|
blinkColorHandle=color;
|
||||||
|
blinkColor=getColorByHandle(color);
|
||||||
|
debug.out(F("setBlinkColor to ")); debug.outln(getColorName(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
String SevenSegmentClock::getColorName(Color handle) {
|
||||||
|
for (int i=0; i<numberOfSupportedColors; ++i) {
|
||||||
|
if (colorSelection[i].handle == handle)
|
||||||
|
return colorSelection[i].colorName;
|
||||||
|
}
|
||||||
|
debug.outln(F("ERROR: Unknown color / handle not known"), DEBUG_ERROR);
|
||||||
|
return String(F("ERROR: Unknown color handle"));
|
||||||
|
}
|
||||||
|
|
||||||
|
SevenSegmentClock::Color SevenSegmentClock::getColorHandle(int index) {
|
||||||
|
return colorSelection[index].handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SevenSegmentClock::getAdjustedStripColor(uint8_t red, uint8_t green, uint8_t blue) {
|
||||||
|
return strip->Color((red * brightness) / 255, (green * brightness) / 255, (blue * brightness) / 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 SevenSegmentClock::getColorByName(String name) {
|
||||||
|
for (int i=0; i<numberOfSupportedColors; ++i) {
|
||||||
|
if (colorSelection[i].colorName.equals(name)) {
|
||||||
|
return getAdjustedStripColor(colorSelection[i].red, colorSelection[i].green, colorSelection[i].blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug.out(F("ERROR: Unknown color name "), DEBUG_ERROR);
|
||||||
|
debug.outln(name, DEBUG_ERROR);
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 SevenSegmentClock::getColorByHandle(Color handle) {
|
||||||
|
for (int i=0; i<numberOfSupportedColors; ++i) {
|
||||||
|
if (colorSelection[i].handle == handle) {
|
||||||
|
return getAdjustedStripColor(colorSelection[i].red, colorSelection[i].green, colorSelection[i].blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug.outln(F("ERROR: Unknown color handle"), DEBUG_ERROR);
|
||||||
|
debug.out(F("Currently I know about ")); debug.out(numberOfSupportedColors); debug.outln(F(" colors."));
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
SevenSegmentClock::Color SevenSegmentClock::getColorHandleByName(String name) {
|
||||||
|
for (int i=0; i<numberOfSupportedColors; ++i) {
|
||||||
|
if (colorSelection[i].colorName.equals(name)) {
|
||||||
|
return colorSelection[i].handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug.out(F("ERROR: Unknown color name "), DEBUG_ERROR);
|
||||||
|
debug.outln(name, DEBUG_ERROR);
|
||||||
|
return Green; // default
|
||||||
}
|
}
|
||||||
|
|
||||||
void SevenSegmentClock::begin(void) {
|
void SevenSegmentClock::begin(void) {
|
||||||
@@ -332,9 +394,11 @@ void SevenSegmentClock::begin(void) {
|
|||||||
Serial.print("Pixels="); Serial.println(PixelCount);
|
Serial.print("Pixels="); Serial.println(PixelCount);
|
||||||
SevenSegmentClock::strip = new Adafruit_NeoPixel(PixelCount, LedDataPin, NEO_GRB + NEO_KHZ800);
|
SevenSegmentClock::strip = new Adafruit_NeoPixel(PixelCount, LedDataPin, NEO_GRB + NEO_KHZ800);
|
||||||
strip->begin();
|
strip->begin();
|
||||||
|
setClockHalted(true);
|
||||||
|
setBrightness(20);
|
||||||
|
setColor(Green);
|
||||||
|
setBlinkColor(Red);
|
||||||
|
black = strip->Color(0, 0, 0);
|
||||||
strip->clear();
|
strip->clear();
|
||||||
strip->show();
|
strip->show();
|
||||||
initColors(colorSaturation);
|
|
||||||
SevenSegmentClock::currentColor = SevenSegmentClock::blue;
|
|
||||||
SevenSegmentClock::currentColorHandle = SevenSegmentClock::Blue;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,88 +7,55 @@
|
|||||||
|
|
||||||
// avoid flickering of the display:
|
// avoid flickering of the display:
|
||||||
#define TIME_BETWEEN_DISPLAY_UPDATES_ms 100
|
#define TIME_BETWEEN_DISPLAY_UPDATES_ms 100
|
||||||
#define BLINK_OFF_TIME_ms 200
|
#define BLINK_OFF_TIME_ms 400
|
||||||
#define BLINK_ON_TIME_ms 200
|
#define BLINK_ON_TIME_ms 400
|
||||||
#define defaultLedDataPin 2
|
#define defaultLedDataPin 2
|
||||||
class SevenSegmentClock {
|
class SevenSegmentClock {
|
||||||
public:
|
public:
|
||||||
SevenSegmentClock(Debug& _debug, Config& _config):debug(_debug), config(_config) { LedDataPin=defaultLedDataPin; init(); };
|
SevenSegmentClock(Debug& _debug, Config& _config):debug(_debug), config(_config) { LedDataPin=defaultLedDataPin; };
|
||||||
SevenSegmentClock(Debug& _debug, Config& _config, uint8_t dataPin):debug(_debug), config(_config) { LedDataPin=dataPin; init(); };
|
SevenSegmentClock(Debug& _debug, Config& _config, uint8_t dataPin):debug(_debug), config(_config) { LedDataPin=dataPin; };
|
||||||
void begin(void);
|
void begin(void);
|
||||||
void displayTime(int hour, int minute);
|
void displayTime(int hour, int minute);
|
||||||
void displayUpdate(void);
|
void displayUpdate(void);
|
||||||
//void setClockSpeed(int _msPerModelSecond) { msPerModelSecond = _msPerModelSecond; setClockSpeed("x"); };
|
//void setClockSpeed(int _msPerModelSecond) { msPerModelSecond = _msPerModelSecond; setClockSpeed("x"); };
|
||||||
enum BlinkMode { NoBlinking, ClockBlinking, SeperatorBlinking, DecimalPointBlinking };
|
enum BlinkMode { NoBlinking, ClockBlinking, SeperatorBlinking, DecimalPointBlinking, DecimalPointColoredBlinking };
|
||||||
void setBlinkMode(BlinkMode _blinkMode) { blinkMode = _blinkMode; };
|
void setBlinkMode(BlinkMode _blinkMode) { blinkMode = _blinkMode; };
|
||||||
void setClockHalted(bool halted) { clockHalted = halted; };
|
void setClockHalted(bool halted) { clockHalted = halted; };
|
||||||
enum Color { Black, Red, Green, Blue, White, Yellow };
|
enum Color { Black, Red, Green, Blue, White, Yellow, Magenta, Cyan };
|
||||||
void setColor(Color color);
|
void setColor(Color color);
|
||||||
|
void setBlinkColor(Color color);
|
||||||
Color getColor(void) { return currentColorHandle; };
|
Color getColor(void) { return currentColorHandle; };
|
||||||
enum ClockDisplayStatus { Off, Booting, Halted, StandardClock, FastClock };
|
|
||||||
void displayDigit(unsigned int digitNum, char c);
|
void displayDigit(unsigned int digitNum, char c);
|
||||||
void displaySeperator(char seperatorCharacter);
|
void displaySeperator(char seperatorCharacter);
|
||||||
void setBrightness(uint8_t b) { brightness=b; initColors(b); };
|
void displaySeperator(char seperatorCharacter, uint32_t color);
|
||||||
|
void displaySeperator(uint32_t color);
|
||||||
|
void displayDecimalPoint(uint32_t color);
|
||||||
|
void setBrightness(uint8_t b) { brightness=b; };
|
||||||
uint8_t getBrightness(void) { return brightness; };
|
uint8_t getBrightness(void) { return brightness; };
|
||||||
int getNumberSupportedColors(void) { return numberOfSupportedColors; };
|
int getNumberSupportedColors(void) { return numberOfSupportedColors; };
|
||||||
String getColorName(int index) { return String(colorSelection[index].colorName); };
|
String getColorName(int index) { return String(colorSelection[index].colorName); };
|
||||||
String getColorName(Color handle) {
|
String getColorName(Color handle);
|
||||||
for (int i=0; i<numberOfSupportedColors; ++i) {
|
Color getColorHandle(int index);
|
||||||
if (colorSelection[i].handle == handle)
|
uint32_t getAdjustedStripColor(uint8_t red, uint8_t green, uint8_t blue);
|
||||||
return colorSelection[i].colorName;
|
uint32 getColorByName(String name);
|
||||||
}
|
uint32 getColorByHandle(Color handle);
|
||||||
debug.outln(F("ERROR: Unknown color / handle not known"), DEBUG_ERROR);
|
Color getColorHandleByName(String name);
|
||||||
return String(F("ERROR: Unknown color handle"));
|
|
||||||
};
|
|
||||||
Color getColorHandle(int index) { return colorSelection[index].handle; };
|
|
||||||
uint32_t getAdjustedStripColor(uint8_t red, uint8_t green, uint8_t blue) {
|
|
||||||
return strip->Color((red * brightness) / 255, (green * brightness) / 255, (blue * brightness) / 255);
|
|
||||||
}
|
|
||||||
uint32 getColorByName(String name) {
|
|
||||||
for (int i=0; i<numberOfSupportedColors; ++i) {
|
|
||||||
if (colorSelection[i].colorName.equals(name)) {
|
|
||||||
return getAdjustedStripColor(colorSelection[i].red, colorSelection[i].green, colorSelection[i].blue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug.out(F("ERROR: Unknown color name "), DEBUG_ERROR);
|
|
||||||
debug.outln(name, DEBUG_ERROR);
|
|
||||||
return 0xffffffff;
|
|
||||||
};
|
|
||||||
uint32 getColorByHandle(Color handle) {
|
|
||||||
for (int i=0; i<numberOfSupportedColors; ++i) {
|
|
||||||
if (colorSelection[i].handle == handle) {
|
|
||||||
return getAdjustedStripColor(colorSelection[i].red, colorSelection[i].green, colorSelection[i].blue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug.outln(F("ERROR: Unknown color handle"), DEBUG_ERROR);
|
|
||||||
return 0xffffffff;
|
|
||||||
};
|
|
||||||
Color getColorHandleByName(String name) {
|
|
||||||
for (int i=0; i<numberOfSupportedColors; ++i) {
|
|
||||||
if (colorSelection[i].colorName.equals(name)) {
|
|
||||||
return colorSelection[i].handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug.out(F("ERROR: Unknown color name "), DEBUG_ERROR);
|
|
||||||
debug.outln(name, DEBUG_ERROR);
|
|
||||||
return Green; // default
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
Debug& debug;
|
Debug& debug;
|
||||||
Config& config;
|
Config& config;
|
||||||
void init(void) { displayStatus = Off; clockHour=12; clockMinute=34; setClockHalted(true); currentColorHandle = Green; currentColor = green; };
|
|
||||||
static uint8_t LedDataPin;
|
static uint8_t LedDataPin;
|
||||||
static Adafruit_NeoPixel *strip;
|
static Adafruit_NeoPixel *strip;
|
||||||
static BlinkMode blinkMode;
|
static BlinkMode blinkMode;
|
||||||
static uint8_t brightness;
|
static uint8_t brightness;
|
||||||
static uint32_t red, green, blue, white, black, yellow;
|
|
||||||
ClockDisplayStatus displayStatus;
|
|
||||||
int clockHour;
|
int clockHour;
|
||||||
int clockMinute;
|
int clockMinute;
|
||||||
bool clockHalted;
|
bool clockHalted;
|
||||||
Color currentColorHandle;
|
Color currentColorHandle;
|
||||||
|
Color blinkColorHandle;
|
||||||
uint32_t currentColor;
|
uint32_t currentColor;
|
||||||
|
uint32_t blinkColor;
|
||||||
|
uint32_t black;
|
||||||
void displaySegment(unsigned int ledAddress, uint32_t color);
|
void displaySegment(unsigned int ledAddress, uint32_t color);
|
||||||
void initColors(uint8_t _brightness);
|
|
||||||
static struct ColorSelection {
|
static struct ColorSelection {
|
||||||
Color handle;
|
Color handle;
|
||||||
String colorName;
|
String colorName;
|
||||||
|
|||||||
202
src/WebUI.cpp
Normal file
202
src/WebUI.cpp
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
#include "WebUI.h"
|
||||||
|
|
||||||
|
static const String appName{"7SegDisplay-XL"};
|
||||||
|
static const char _HEAD[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\" name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/><title>{v}</title>";
|
||||||
|
static const char _STYLE[] PROGMEM = "<style>.c{text-align: center;} div,input{padding:5px;font-size:1em;} input{width:95%;} input.r{width:20%;} body{text-align: center;font-family:verdana;} button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;} .q{float: right;width: 64px;text-align: right;} .l{background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAALVBMVEX///8EBwfBwsLw8PAzNjaCg4NTVVUjJiZDRUUUFxdiZGSho6OSk5Pg4eFydHTCjaf3AAAAZElEQVQ4je2NSw7AIAhEBamKn97/uMXEGBvozkWb9C2Zx4xzWykBhFAeYp9gkLyZE0zIMno9n4g19hmdY39scwqVkOXaxph0ZCXQcqxSpgQpONa59wkRDOL93eAXvimwlbPbwwVAegLS1HGfZAAAAABJRU5ErkJggg==\") no-repeat left center;background-size: 1em;}</style>";
|
||||||
|
static const char _SCRIPT[] PROGMEM = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();}</script>";
|
||||||
|
static const char _HEAD_END[] PROGMEM = "</head><body><div style='text-align:left;display:inline-block;min-width:260px;'>";
|
||||||
|
static const char _PORTAL_OPTIONS[] PROGMEM = "<form action=\"/wifi\" method=\"get\"><button>Configure WiFi</button></form><br/><form action=\"/0wifi\" method=\"get\"><button>Configure WiFi (No Scan)</button></form><br/><form action=\"/i\" method=\"get\"><button>Info</button></form><br/><form action=\"/r\" method=\"post\"><button>Reset</button></form>";
|
||||||
|
static const char _ITEM[] PROGMEM = "<div><a href='#p' onclick='c(this)'>{v}</a> <span class='q {i}'>{r}%</span></div>";
|
||||||
|
static const char _FORM_START[] PROGMEM = "<form method='get' action='configSave'>";
|
||||||
|
static const char _FORM_CLOCKNAME[] PROGMEM = "<label for='n'>Fastclock name</label><input id='n' name='n' length=32 placeholder='clock name' value='{n}'><br/>";
|
||||||
|
static const char _FORM_CLOCKSFOUND_START[] PROGMEM = "Fastclocks seen:<br/><ul>";
|
||||||
|
static const char _FORM_CLOCKSFOUND_ITEM[] PROGMEM = "<li>{fc}</li>";
|
||||||
|
static const char _FORM_CLOCKSFOUND_END[] PROGMEM = "</ul><br/>";
|
||||||
|
static const char _FORM_CLOCKMODE_HEADLINE[] PROGMEM = "<br/>Clock mode:<br/>";
|
||||||
|
static const char _FORM_CLOCKMODE_DEMO[] PROGMEM = "<input class='r' id='md' name='m' type='radio' value='demo' {check}><label for='md'>Demo</label><br/>";
|
||||||
|
static const char _FORM_CLOCKMODE_REAL[] PROGMEM = "<input class='r' id='mr' name='m' type='radio' value='real' {check}><label for='md'>Real Clock</label><br/>";
|
||||||
|
static const char _FORM_CLOCKMODE_FAST[] PROGMEM = "<input class='r' id='mf' name='m' type='radio' value='fast' {check}><label for='md'>Fast Clock</label><br/>";
|
||||||
|
static const char _FORM_UTC_OFFSET[] PROGMEM = "<label for='utc'>UTC offset (minutes)</label><input id='utc' name='utc' length=4 placeholder='120'><br/>";
|
||||||
|
static const char _FORM_PARAM[] PROGMEM = "<br/><input id='{i}' name='{n}' maxlength={l} placeholder='{p}' value='{v}' {c}>";
|
||||||
|
static const char _FORM_COLOR_HEADLINE[] PROGMEM = "Display color:<br/>";
|
||||||
|
static const char _FORM_COLOR_template[] PROGMEM = "<input class='r' id='{cid}' name='c' type='radio' value='{cname}' {check}><label for='{cid}'>{cname}</label><br/>";
|
||||||
|
static const char _FORM_BRIGHTNESS[] PROGMEM = "<label for='b'>Brightness:</label><input id='b' name='b' type='range' min='10' max='255' value='{bright}'><br/>";
|
||||||
|
static const char _FORM_FASTCLOCK_INFO[] PROGMEM = "<div>Number of fastclocks found: {nfc}</div><br/>";
|
||||||
|
static const char _FORM_END[] PROGMEM = "<br/><button type='submit'>apply</button></form><br/>";
|
||||||
|
static const char _SAVE_PERM_BUTTON[] PROGMEM = "<br/><form action=\"/configSavePermanent\" method=\"get\"><button>Save permanently</button></form><br/>";
|
||||||
|
static const char _CONFIG_BUTTON[] PROGMEM = "<br/><form action=\"/config\" method=\"get\"><button>Configure</button></form><br/>";
|
||||||
|
static const char _VSPACE[] PROGMEM = "<br/><br/>";
|
||||||
|
static const char _SAVED[] PROGMEM = "<div>Credentials Saved<br />Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div>";
|
||||||
|
static const char _END[] PROGMEM = "</div></body></html>";
|
||||||
|
|
||||||
|
void WebUI::appConfig() {
|
||||||
|
String page = FPSTR(_HEAD);
|
||||||
|
String input;
|
||||||
|
String value;
|
||||||
|
int ivalue;
|
||||||
|
|
||||||
|
page.replace("{v}", "7Seg Config");
|
||||||
|
page += FPSTR(_SCRIPT);
|
||||||
|
page += FPSTR(_STYLE);
|
||||||
|
//page += _customHeadElement;
|
||||||
|
page += FPSTR(_HEAD_END);
|
||||||
|
page += String(F("<h1>"));
|
||||||
|
page += appName;
|
||||||
|
page += String(F("</h1>"));
|
||||||
|
page += String(F("<h3>Clock Options</h3>"));
|
||||||
|
//page += FPSTR(_PORTAL_OPTIONS);
|
||||||
|
page += FPSTR(_FORM_START);
|
||||||
|
page += FPSTR(_FORM_CLOCKMODE_HEADLINE);
|
||||||
|
input = FPSTR(_FORM_CLOCKMODE_DEMO);
|
||||||
|
input.replace("{check}", (config.getString("appMode").equals("Demo")) ? "checked" : "");
|
||||||
|
page += input;
|
||||||
|
input = FPSTR(_FORM_CLOCKMODE_REAL);
|
||||||
|
input.replace("{check}", (config.getString("appMode").equals("Realclock")) ? "checked" : "");
|
||||||
|
page += input;
|
||||||
|
input = FPSTR(_FORM_CLOCKMODE_FAST);
|
||||||
|
input.replace("{check}", (config.getString("appMode").equals("Fastclock")) ? "checked" : "");
|
||||||
|
page += input;
|
||||||
|
page += FPSTR(_VSPACE);
|
||||||
|
page += FPSTR(_FORM_UTC_OFFSET);
|
||||||
|
page += FPSTR(_VSPACE);
|
||||||
|
input = FPSTR(_FORM_CLOCKNAME);
|
||||||
|
value = config.getString("listenToClock");
|
||||||
|
input.replace("{n}", value);
|
||||||
|
page += input;
|
||||||
|
page += FPSTR(_FORM_CLOCKSFOUND_START);
|
||||||
|
String *knownClocks = fastclock.getKnownClocks();
|
||||||
|
for (int i=0; i<fastclock.getNumberOfKnownClocks(); ++i) {
|
||||||
|
input = FPSTR(_FORM_CLOCKSFOUND_ITEM);
|
||||||
|
input.replace("{fc}", knownClocks[i]);
|
||||||
|
page += input;
|
||||||
|
}
|
||||||
|
page += FPSTR(_FORM_CLOCKSFOUND_END);
|
||||||
|
|
||||||
|
page += FPSTR(_VSPACE);
|
||||||
|
page += FPSTR(_FORM_COLOR_HEADLINE);
|
||||||
|
for (int i=0; i<sevenSegmentClock.getNumberSupportedColors(); ++i) {
|
||||||
|
input = FPSTR(_FORM_COLOR_template);
|
||||||
|
input.replace("{cid}", sevenSegmentClock.getColorName(i));
|
||||||
|
input.replace("{cname}", sevenSegmentClock.getColorName(i));
|
||||||
|
input.replace("{check}", (config.getString("clockColor").equals(sevenSegmentClock.getColorName(i))) ? "checked" : "");
|
||||||
|
page += input;
|
||||||
|
}
|
||||||
|
|
||||||
|
page += FPSTR(_VSPACE);
|
||||||
|
input = FPSTR(_FORM_BRIGHTNESS);
|
||||||
|
value = String(sevenSegmentClock.getBrightness());
|
||||||
|
input.replace("{bright}", value);
|
||||||
|
page += input;
|
||||||
|
|
||||||
|
page += FPSTR(_VSPACE);
|
||||||
|
input = FPSTR(_FORM_FASTCLOCK_INFO);
|
||||||
|
ivalue = fastclock.getNumberOfKnownClocks();
|
||||||
|
value = String(ivalue);
|
||||||
|
//value = String("unknown");
|
||||||
|
input.replace("{nfc}", value);
|
||||||
|
page += input;
|
||||||
|
|
||||||
|
page += FPSTR(_FORM_END);
|
||||||
|
page += FPSTR(_END);
|
||||||
|
|
||||||
|
server->sendHeader("Content-Length", String(page.length()));
|
||||||
|
server->send(200, "text/html", page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebUI::appConfigSave(void) {
|
||||||
|
String page = FPSTR(_HEAD);
|
||||||
|
|
||||||
|
page.replace("{v}", "7Seg Config");
|
||||||
|
page += FPSTR(_SCRIPT);
|
||||||
|
page += FPSTR(_STYLE);
|
||||||
|
page += FPSTR(_HEAD_END);
|
||||||
|
page += String(F("<h1>"));
|
||||||
|
page += appName;
|
||||||
|
page += String(F("</h1>"));
|
||||||
|
|
||||||
|
debug.out(server->args(), DEBUG_MED_INFO); debug.outln(" arguments", DEBUG_MED_INFO);
|
||||||
|
for (int i=0; i<server->args(); ++i) {
|
||||||
|
debug.out(server->argName(i), DEBUG_MAX_INFO);
|
||||||
|
debug.out(": ", DEBUG_MAX_INFO);
|
||||||
|
debug.outln(server->arg(i), DEBUG_MAX_INFO);
|
||||||
|
}
|
||||||
|
if (server->hasArg("n")) {
|
||||||
|
String clockName = server->arg("n");
|
||||||
|
config.setString("listenToClock", clockName);
|
||||||
|
fastclock.setListenToClock(clockName);
|
||||||
|
page += F("<div>Set fastclock to listen to clock with name ");
|
||||||
|
page += clockName;
|
||||||
|
page += F(".</div>");
|
||||||
|
}
|
||||||
|
if (server->hasArg("b")) {
|
||||||
|
int brightness = server->arg("b").toInt();
|
||||||
|
sevenSegmentClock.setBrightness(brightness);
|
||||||
|
config.setInt("brightness", brightness);
|
||||||
|
page += F("<div>Set brightness to ");
|
||||||
|
page += server->arg("b");
|
||||||
|
page += F(".</div>");
|
||||||
|
}
|
||||||
|
if (server->hasArg("c")) {
|
||||||
|
String colorName = server->arg("c");
|
||||||
|
SevenSegmentClock::Color colorHandle = sevenSegmentClock.getColorHandleByName(server->arg("c"));
|
||||||
|
sevenSegmentClock.setColor(colorHandle);
|
||||||
|
config.setString("clockColor", colorName);
|
||||||
|
page += F("<div>Set color to ");
|
||||||
|
page += server->arg("c");
|
||||||
|
page += F(".</div>");
|
||||||
|
}
|
||||||
|
if (server->hasArg("m")) {
|
||||||
|
debug.out("setting clock mode to ", DEBUG_MAX_INFO); debug.outln(server->arg("m"), DEBUG_MAX_INFO);
|
||||||
|
page += F("<div>Set clock mode to ");
|
||||||
|
page += server->arg("m");
|
||||||
|
page += F(".</div>");
|
||||||
|
if (server->arg("m").equals("real")) config.setString("appMode", MODE_REALCLOCK);
|
||||||
|
else if (server->arg("m").equals("fast")) config.setString("appMode", MODE_FASTCLOCK);
|
||||||
|
else if (server->arg("m").equals("demo")) config.setString("appMode", MODE_DEMO);
|
||||||
|
else {
|
||||||
|
debug.outln("ERROR: Unknown application mode, going into demo mode", DEBUG_ERROR);
|
||||||
|
config.setString("appMode", MODE_DEMO);
|
||||||
|
page += F("<div>ERROR: Unknown clockmode, using default: demo.</div>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server->hasArg("utc")) {
|
||||||
|
page += F("<div>Set real clock offset to ");
|
||||||
|
int timeOffset;
|
||||||
|
if (server->arg("utc").equals("")) {
|
||||||
|
page += "120";
|
||||||
|
timeOffset = 120;
|
||||||
|
} else {
|
||||||
|
page += server->arg("utc");
|
||||||
|
timeOffset = server->arg("utc").toInt();
|
||||||
|
}
|
||||||
|
config.setInt("utcTimeOffsetMinutes", timeOffset);
|
||||||
|
timeClient.setTimeOffset(timeOffset * 60);
|
||||||
|
page += F(" minutes.</div>");
|
||||||
|
}
|
||||||
|
page += String(F("<div>Configuration updated.</div>"));
|
||||||
|
page += FPSTR(_CONFIG_BUTTON);
|
||||||
|
page += FPSTR(_SAVE_PERM_BUTTON);
|
||||||
|
page += FPSTR(_END);
|
||||||
|
server->sendHeader("Content-Length", String(page.length()));
|
||||||
|
server->send(200, "text/html", page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebUI::appConfigSavePermanent(void) {
|
||||||
|
String page = FPSTR(_HEAD);
|
||||||
|
|
||||||
|
page.replace("{v}", "7Seg Config");
|
||||||
|
page += FPSTR(_SCRIPT);
|
||||||
|
page += FPSTR(_STYLE);
|
||||||
|
page += FPSTR(_HEAD_END);
|
||||||
|
page += String(F("<h1>"));
|
||||||
|
page += appName;
|
||||||
|
page += String(F("</h1>"));
|
||||||
|
|
||||||
|
debug.outln("Writing configs to save them permanently", DEBUG_MAX_INFO);
|
||||||
|
config.writeAllConfigs();
|
||||||
|
page += String(F("<div>Configuration permanently saved.</div>"));
|
||||||
|
page += FPSTR(_CONFIG_BUTTON);
|
||||||
|
page += FPSTR(_END);
|
||||||
|
server->sendHeader("Content-Length", String(page.length()));
|
||||||
|
server->send(200, "text/html", page);
|
||||||
|
}
|
||||||
44
src/WebUI.h
Normal file
44
src/WebUI.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef _webui_included
|
||||||
|
#define _webui_included
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <NTPClient.h>
|
||||||
|
#include "DjDebug.h"
|
||||||
|
#include "DjConfig.h"
|
||||||
|
#include "SevenSegmentClock.h"
|
||||||
|
#include "ClockClient.h"
|
||||||
|
|
||||||
|
class WebUI {
|
||||||
|
public:
|
||||||
|
WebUI(Debug& _debug, Config& _config, NTPClient& _timeClient, ClockClient& _fastclock, SevenSegmentClock& _sevenSegmentClock):
|
||||||
|
debug(_debug), config(_config), timeClient(_timeClient), fastclock(_fastclock), sevenSegmentClock(_sevenSegmentClock) {
|
||||||
|
debug.outln(F("WebUI constructor called"));
|
||||||
|
};
|
||||||
|
void begin(void) {
|
||||||
|
server = new ESP8266WebServer(80);
|
||||||
|
server->on("/config", std::bind(&WebUI::appConfig, this));
|
||||||
|
server->on("/configSave", std::bind(&WebUI::appConfigSave, this));
|
||||||
|
server->on("/configSavePermanent", std::bind(&WebUI::appConfigSavePermanent, this));
|
||||||
|
//server->on("/config", HTTP_GET, appConfig);
|
||||||
|
//server->on("/configSave", HTTP_GET, appConfigSave);
|
||||||
|
//server->on("/configSavePermanent", HTTP_GET, appConfigSavePermanent);
|
||||||
|
|
||||||
|
server->begin();
|
||||||
|
};
|
||||||
|
void loop(void) {
|
||||||
|
server->handleClient();
|
||||||
|
};
|
||||||
|
void appConfig();
|
||||||
|
void appConfigSave();
|
||||||
|
void appConfigSavePermanent();
|
||||||
|
private:
|
||||||
|
Debug& debug;
|
||||||
|
Config& config;
|
||||||
|
NTPClient& timeClient;
|
||||||
|
ClockClient& fastclock;
|
||||||
|
SevenSegmentClock& sevenSegmentClock;
|
||||||
|
ESP8266WebServer *server;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
10
src/app.h
Normal file
10
src/app.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _app_included
|
||||||
|
#define _app_included
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define MODE_DEMO "Demo"
|
||||||
|
#define MODE_REALCLOCK "Realclock"
|
||||||
|
#define MODE_FASTCLOCK "Fastclock"
|
||||||
|
|
||||||
|
#endif
|
||||||
259
src/main.cpp
259
src/main.cpp
@@ -1,14 +1,10 @@
|
|||||||
#include <Arduino.h>
|
#include "app.h"
|
||||||
#include <FS.h> //this needs to be first, or it all crashes and burns...
|
#include <FS.h> //this needs to be first, or it all crashes and burns...
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <NTPClient.h> //https://github.com/esp8266/Arduino
|
#include <NTPClient.h> //https://github.com/esp8266/Arduino
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
//needed for library
|
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
#include <WiFiManager.h>
|
#include <WiFiManager.h>
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include "DjDebug.h"
|
#include "DjDebug.h"
|
||||||
@@ -16,6 +12,8 @@
|
|||||||
#include "SevenSegmentClock.h"
|
#include "SevenSegmentClock.h"
|
||||||
#include "DjDebug.h"
|
#include "DjDebug.h"
|
||||||
#include "ClockClient.h"
|
#include "ClockClient.h"
|
||||||
|
#include "WebUI.h"
|
||||||
|
#include "DjSimpleFS.h"
|
||||||
|
|
||||||
// NTP
|
// NTP
|
||||||
WiFiUDP ntpUDP;
|
WiFiUDP ntpUDP;
|
||||||
@@ -24,10 +22,6 @@ WiFiUDP ntpUDP;
|
|||||||
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
|
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
|
||||||
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000);
|
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000);
|
||||||
|
|
||||||
#define MODE_DEMO "Demo"
|
|
||||||
#define MODE_REALCLOCK "Realclock"
|
|
||||||
#define MODE_FASTCLOCK "Fastclock"
|
|
||||||
|
|
||||||
static const char *appName = "FastclockClient7Seg";
|
static const char *appName = "FastclockClient7Seg";
|
||||||
const char * const PROGMEM mainConfig[] = {
|
const char * const PROGMEM mainConfig[] = {
|
||||||
"appMode:string:" MODE_DEMO,
|
"appMode:string:" MODE_DEMO,
|
||||||
@@ -42,7 +36,9 @@ Config config(debug);
|
|||||||
ClockClient fastclock(debug, config);
|
ClockClient fastclock(debug, config);
|
||||||
SevenSegmentClock sevenSegmentClock(debug, config);
|
SevenSegmentClock sevenSegmentClock(debug, config);
|
||||||
ClockClient fastclockClient(debug, config);
|
ClockClient fastclockClient(debug, config);
|
||||||
ESP8266WebServer *server;
|
//ESP8266WebServer *server;
|
||||||
|
WebUI *webUI;
|
||||||
|
SimpleFS filesystem(debug);
|
||||||
|
|
||||||
//flag for saving data
|
//flag for saving data
|
||||||
bool shouldSaveConfig = false;
|
bool shouldSaveConfig = false;
|
||||||
@@ -88,228 +84,19 @@ void setupWifiConnection() {
|
|||||||
debug.out("subnet: ", DEBUG_MAX_INFO); debug.outln(WiFi.subnetMask(), DEBUG_MAX_INFO);
|
debug.out("subnet: ", DEBUG_MAX_INFO); debug.outln(WiFi.subnetMask(), DEBUG_MAX_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char _HEAD[] PROGMEM = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\" name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/><title>{v}</title>";
|
|
||||||
const char _STYLE[] PROGMEM = "<style>.c{text-align: center;} div,input{padding:5px;font-size:1em;} input{width:95%;} input.r{width:20%;} body{text-align: center;font-family:verdana;} button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;} .q{float: right;width: 64px;text-align: right;} .l{background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAALVBMVEX///8EBwfBwsLw8PAzNjaCg4NTVVUjJiZDRUUUFxdiZGSho6OSk5Pg4eFydHTCjaf3AAAAZElEQVQ4je2NSw7AIAhEBamKn97/uMXEGBvozkWb9C2Zx4xzWykBhFAeYp9gkLyZE0zIMno9n4g19hmdY39scwqVkOXaxph0ZCXQcqxSpgQpONa59wkRDOL93eAXvimwlbPbwwVAegLS1HGfZAAAAABJRU5ErkJggg==\") no-repeat left center;background-size: 1em;}</style>";
|
|
||||||
const char _SCRIPT[] PROGMEM = "<script>function c(l){document.getElementById('s').value=l.innerText||l.textContent;document.getElementById('p').focus();}</script>";
|
|
||||||
const char _HEAD_END[] PROGMEM = "</head><body><div style='text-align:left;display:inline-block;min-width:260px;'>";
|
|
||||||
const char _PORTAL_OPTIONS[] PROGMEM = "<form action=\"/wifi\" method=\"get\"><button>Configure WiFi</button></form><br/><form action=\"/0wifi\" method=\"get\"><button>Configure WiFi (No Scan)</button></form><br/><form action=\"/i\" method=\"get\"><button>Info</button></form><br/><form action=\"/r\" method=\"post\"><button>Reset</button></form>";
|
|
||||||
const char _ITEM[] PROGMEM = "<div><a href='#p' onclick='c(this)'>{v}</a> <span class='q {i}'>{r}%</span></div>";
|
|
||||||
const char _FORM_START[] PROGMEM = "<form method='get' action='configSave'>";
|
|
||||||
const char _FORM_CLOCKNAME[] PROGMEM = "<label for='n'>Fastclock name</label><input id='n' name='n' length=32 placeholder='clock name' value='{n}'><br/>";
|
|
||||||
const char _FORM_CLOCKSFOUND_START[] PROGMEM = "Fastclocks seen:<br/><ul>";
|
|
||||||
const char _FORM_CLOCKSFOUND_ITEM[] PROGMEM = "<li>{fc}</li>";
|
|
||||||
const char _FORM_CLOCKSFOUND_END[] PROGMEM = "</ul><br/>";
|
|
||||||
const char _FORM_CLOCKMODE_HEADLINE[] PROGMEM = "<br/>Clock mode:<br/>";
|
|
||||||
const char _FORM_CLOCKMODE_DEMO[] PROGMEM = "<input class='r' id='md' name='m' type='radio' value='demo' {check}><label for='md'>Demo</label><br/>";
|
|
||||||
const char _FORM_CLOCKMODE_REAL[] PROGMEM = "<input class='r' id='mr' name='m' type='radio' value='real' {check}><label for='md'>Real Clock</label><br/>";
|
|
||||||
const char _FORM_CLOCKMODE_FAST[] PROGMEM = "<input class='r' id='mf' name='m' type='radio' value='fast' {check}><label for='md'>Fast Clock</label><br/>";
|
|
||||||
const char _FORM_UTC_OFFSET[] PROGMEM = "<label for='utc'>UTC offset (minutes)</label><input id='utc' name='utc' length=4 placeholder='120'><br/>";
|
|
||||||
const char _FORM_PARAM[] PROGMEM = "<br/><input id='{i}' name='{n}' maxlength={l} placeholder='{p}' value='{v}' {c}>";
|
|
||||||
const char _FORM_COLOR_HEADLINE[] PROGMEM = "<br/>Display color:<br/>";
|
|
||||||
const char _FORM_COLOR_template[] PROGMEM = "<input class='r' id='{cid}' name='c' type='radio' value='{cname}' {check}><label for='{cid}'>{cname}</label><br/>";
|
|
||||||
const char _FORM_COLOR_BLUE[] PROGMEM = "<input class='r' id='cb' name='c' type='radio' value='Blue' {check}><label for='cb'>Blue</label><br/>";
|
|
||||||
const char _FORM_COLOR_RED[] PROGMEM = "<input class='r' id='cr' name='c' type='radio' value='Red' {check}><label for='cr'>Red</label><br/>";
|
|
||||||
const char _FORM_COLOR_GREEN[] PROGMEM = "<input class='r' id='cg' name='c' type='radio' value='Green' {check}><label for='cg'>Green</label><br/>";
|
|
||||||
const char _FORM_COLOR_WHITE[] PROGMEM = "<input class='r' id='cw' name='c' type='radio' value='White' {check}><label for='cw'>White</label><br/>";
|
|
||||||
const char _FORM_COLOR_YELLOW[] PROGMEM = "<input class='r' id='cy' name='c' type='radio' value='Yellow' {check}><label for='cy'>Yellow</label><br/>";
|
|
||||||
const char _FORM_BRIGHTNESS[] PROGMEM = "<label for='b'>Brightness:</label><input id='b' name='b' type='range' min='10' max='255' value='{bright}'><br/>";
|
|
||||||
const char _FORM_FASTCLOCK_INFO[] PROGMEM = "<div>Number of fastclocks found: {nfc}</div><br/>";
|
|
||||||
const char _FORM_END[] PROGMEM = "<br/><button type='submit'>apply</button></form><br/>";
|
|
||||||
const char _SAVE_PERM_BUTTON[] PROGMEM = "<br/><form action=\"/configSavePermanent\" method=\"get\"><button>Save permanently</button></form><br/>";
|
|
||||||
const char _CONFIG_BUTTON[] PROGMEM = "<br/><form action=\"/config\" method=\"get\"><button>Configure</button></form><br/>";
|
|
||||||
const char _VSPACE[] PROGMEM = "<br/><br/>";
|
|
||||||
const char _SAVED[] PROGMEM = "<div>Credentials Saved<br />Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div>";
|
|
||||||
const char _END[] PROGMEM = "</div></body></html>";
|
|
||||||
|
|
||||||
void appConfig() {
|
|
||||||
String page = FPSTR(_HEAD);
|
|
||||||
String input;
|
|
||||||
String value;
|
|
||||||
int ivalue;
|
|
||||||
|
|
||||||
page.replace("{v}", "7Seg Config");
|
|
||||||
page += FPSTR(_SCRIPT);
|
|
||||||
page += FPSTR(_STYLE);
|
|
||||||
//page += _customHeadElement;
|
|
||||||
page += FPSTR(_HEAD_END);
|
|
||||||
page += String(F("<h1>"));
|
|
||||||
page += appName;
|
|
||||||
page += String(F("</h1>"));
|
|
||||||
page += String(F("<h3>Clock Options</h3>"));
|
|
||||||
//page += FPSTR(_PORTAL_OPTIONS);
|
|
||||||
page += FPSTR(_FORM_START);
|
|
||||||
page += FPSTR(_FORM_CLOCKMODE_HEADLINE);
|
|
||||||
input = FPSTR(_FORM_CLOCKMODE_DEMO);
|
|
||||||
input.replace("{check}", (config.getString("appMode").equals("Demo")) ? "checked" : "");
|
|
||||||
page += input;
|
|
||||||
input = FPSTR(_FORM_CLOCKMODE_REAL);
|
|
||||||
input.replace("{check}", (config.getString("appMode").equals("Realclock")) ? "checked" : "");
|
|
||||||
page += input;
|
|
||||||
input = FPSTR(_FORM_CLOCKMODE_FAST);
|
|
||||||
input.replace("{check}", (config.getString("appMode").equals("Fastclock")) ? "checked" : "");
|
|
||||||
page += input;
|
|
||||||
page += FPSTR(_VSPACE);
|
|
||||||
page += FPSTR(_FORM_UTC_OFFSET);
|
|
||||||
page += FPSTR(_VSPACE);
|
|
||||||
input = FPSTR(_FORM_CLOCKNAME);
|
|
||||||
value = config.getString("listenToClock");
|
|
||||||
input.replace("{n}", value);
|
|
||||||
page += input;
|
|
||||||
page += FPSTR(_FORM_CLOCKSFOUND_START);
|
|
||||||
String *knownClocks = fastclock.getKnownClocks();
|
|
||||||
for (int i=0; i<fastclock.getNumberOfKnownClocks(); ++i) {
|
|
||||||
input = FPSTR(_FORM_CLOCKSFOUND_ITEM);
|
|
||||||
input.replace("{fc}", knownClocks[i]);
|
|
||||||
page += input;
|
|
||||||
}
|
|
||||||
page += FPSTR(_FORM_CLOCKSFOUND_END);
|
|
||||||
|
|
||||||
page += FPSTR(_VSPACE);
|
|
||||||
page += FPSTR(_FORM_COLOR_HEADLINE);
|
|
||||||
for (int i=0; i<sevenSegmentClock.getNumberSupportedColors(); ++i) {
|
|
||||||
input = FPSTR(_FORM_COLOR_template);
|
|
||||||
input.replace("{cid}", sevenSegmentClock.getColorName(i));
|
|
||||||
input.replace("{cname}", sevenSegmentClock.getColorName(i));
|
|
||||||
input.replace("{check}", (config.getString("clockColor").equals(sevenSegmentClock.getColorName(i))) ? "checked" : "");
|
|
||||||
page += input;
|
|
||||||
}
|
|
||||||
|
|
||||||
page += FPSTR(_VSPACE);
|
|
||||||
input = FPSTR(_FORM_BRIGHTNESS);
|
|
||||||
value = String(sevenSegmentClock.getBrightness());
|
|
||||||
input.replace("{bright}", value);
|
|
||||||
page += input;
|
|
||||||
|
|
||||||
page += FPSTR(_VSPACE);
|
|
||||||
input = FPSTR(_FORM_FASTCLOCK_INFO);
|
|
||||||
ivalue = fastclock.getNumberOfKnownClocks();
|
|
||||||
value = String(ivalue);
|
|
||||||
//value = String("unknown");
|
|
||||||
input.replace("{nfc}", value);
|
|
||||||
page += input;
|
|
||||||
|
|
||||||
page += FPSTR(_FORM_END);
|
|
||||||
page += FPSTR(_END);
|
|
||||||
|
|
||||||
server->sendHeader("Content-Length", String(page.length()));
|
|
||||||
server->send(200, "text/html", page);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRealClockTimeOffset(int offsetInMinutes) {
|
|
||||||
timeClient.setTimeOffset(offsetInMinutes * 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
void appConfigSave() {
|
|
||||||
String page = FPSTR(_HEAD);
|
|
||||||
|
|
||||||
page.replace("{v}", "7Seg Config");
|
|
||||||
page += FPSTR(_SCRIPT);
|
|
||||||
page += FPSTR(_STYLE);
|
|
||||||
page += FPSTR(_HEAD_END);
|
|
||||||
page += String(F("<h1>"));
|
|
||||||
page += appName;
|
|
||||||
page += String(F("</h1>"));
|
|
||||||
|
|
||||||
debug.out(server->args(), DEBUG_MED_INFO); debug.outln(" arguments", DEBUG_MED_INFO);
|
|
||||||
for (int i=0; i<server->args(); ++i) {
|
|
||||||
debug.out(server->argName(i), DEBUG_MAX_INFO);
|
|
||||||
debug.out(": ", DEBUG_MAX_INFO);
|
|
||||||
debug.outln(server->arg(i), DEBUG_MAX_INFO);
|
|
||||||
}
|
|
||||||
if (server->hasArg("b")) {
|
|
||||||
int brightness = server->arg("b").toInt();
|
|
||||||
sevenSegmentClock.setBrightness(brightness);
|
|
||||||
config.setInt("brightness", brightness);
|
|
||||||
page += F("<div>Set brightness to ");
|
|
||||||
page += server->arg("b");
|
|
||||||
page += F(".</div>");
|
|
||||||
}
|
|
||||||
if (server->hasArg("c")) {
|
|
||||||
String colorName = server->arg("c");
|
|
||||||
SevenSegmentClock::Color colorHandle = sevenSegmentClock.getColorHandleByName(server->arg("c"));
|
|
||||||
sevenSegmentClock.setColor(colorHandle);
|
|
||||||
config.setString("clockColor", colorName);
|
|
||||||
page += F("<div>Set color to ");
|
|
||||||
page += server->arg("c");
|
|
||||||
page += F(".</div>");
|
|
||||||
}
|
|
||||||
if (server->hasArg("m")) {
|
|
||||||
debug.out("setting clock mode to ", DEBUG_MAX_INFO); debug.outln(server->arg("m"), DEBUG_MAX_INFO);
|
|
||||||
page += F("<div>Set clock mode to ");
|
|
||||||
page += server->arg("m");
|
|
||||||
page += F(".</div>");
|
|
||||||
if (server->arg("m").equals("real")) config.setString("appMode", MODE_REALCLOCK);
|
|
||||||
else if (server->arg("m").equals("fast")) config.setString("appMode", MODE_FASTCLOCK);
|
|
||||||
else if (server->arg("m").equals("demo")) config.setString("appMode", MODE_DEMO);
|
|
||||||
else {
|
|
||||||
debug.outln("ERROR: Unknown application mode, going into demo mode", DEBUG_ERROR);
|
|
||||||
config.setString("appMode", MODE_DEMO);
|
|
||||||
page += F("<div>ERROR: Unknown clockmode, using default: demo.</div>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (server->hasArg("utc")) {
|
|
||||||
page += F("<div>Set real clock offset to ");
|
|
||||||
int timeOffset;
|
|
||||||
if (server->arg("utc").equals("")) {
|
|
||||||
page += "120";
|
|
||||||
timeOffset = 120;
|
|
||||||
} else {
|
|
||||||
page += server->arg("utc");
|
|
||||||
timeOffset = server->arg("utc").toInt();
|
|
||||||
}
|
|
||||||
config.setInt("utcTimeOffsetMinutes", timeOffset);
|
|
||||||
setRealClockTimeOffset(timeOffset);
|
|
||||||
page += F(" minutes.</div>");
|
|
||||||
}
|
|
||||||
page += String(F("<div>Configuration updated.</div>"));
|
|
||||||
page += FPSTR(_CONFIG_BUTTON);
|
|
||||||
page += FPSTR(_SAVE_PERM_BUTTON);
|
|
||||||
page += FPSTR(_END);
|
|
||||||
server->sendHeader("Content-Length", String(page.length()));
|
|
||||||
server->send(200, "text/html", page);
|
|
||||||
}
|
|
||||||
|
|
||||||
void appConfigSavePermanent() {
|
|
||||||
String page = FPSTR(_HEAD);
|
|
||||||
|
|
||||||
page.replace("{v}", "7Seg Config");
|
|
||||||
page += FPSTR(_SCRIPT);
|
|
||||||
page += FPSTR(_STYLE);
|
|
||||||
page += FPSTR(_HEAD_END);
|
|
||||||
page += String(F("<h1>"));
|
|
||||||
page += appName;
|
|
||||||
page += String(F("</h1>"));
|
|
||||||
|
|
||||||
debug.outln("Writing configs to save them permanently", DEBUG_MAX_INFO);
|
|
||||||
config.writeAllConfigs();
|
|
||||||
page += String(F("<div>Configuration permanently saved.</div>"));
|
|
||||||
page += FPSTR(_CONFIG_BUTTON);
|
|
||||||
page += FPSTR(_END);
|
|
||||||
server->sendHeader("Content-Length", String(page.length()));
|
|
||||||
server->send(200, "text/html", page);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
debug.out(F("Starting *** "), DEBUG_MAX_INFO); debug.outln(appName, DEBUG_MAX_INFO);
|
debug.out(F("Starting *** "), DEBUG_MAX_INFO); debug.outln(appName, DEBUG_MAX_INFO);
|
||||||
debug.out(F("Reset reason: "), DEBUG_MIN_INFO);
|
debug.out(F("Reset reason: "), DEBUG_MIN_INFO);
|
||||||
debug.outln(ESP.getResetReason(), DEBUG_MIN_INFO);
|
debug.outln(ESP.getResetReason(), DEBUG_MIN_INFO);
|
||||||
|
|
||||||
//clean FS, for testing
|
filesystem.begin();
|
||||||
//SPIFFS.format();
|
|
||||||
|
|
||||||
//read configuration from FS json
|
|
||||||
debug.outln(F("mounting FS..."), DEBUG_MAX_INFO);
|
|
||||||
|
|
||||||
if (SPIFFS.begin()) {
|
|
||||||
debug.outln(F("mounted file system"), DEBUG_MAX_INFO);
|
|
||||||
config.begin("main.cfg", mainConfig, sizeof(mainConfig)/sizeof(mainConfig[0]));
|
config.begin("main.cfg", mainConfig, sizeof(mainConfig)/sizeof(mainConfig[0]));
|
||||||
} else {
|
|
||||||
debug.outln(F("failed to mount FS"), DEBUG_ERROR);
|
|
||||||
config.begin("main.cfg", mainConfig, sizeof(mainConfig)/sizeof(mainConfig[0]));
|
|
||||||
}
|
|
||||||
setupWifiConnection();
|
setupWifiConnection();
|
||||||
debug.outln(F("Starting NTP Client"), DEBUG_MAX_INFO);
|
debug.outln(F("Starting NTP Client"), DEBUG_MAX_INFO);
|
||||||
timeClient.begin();
|
timeClient.begin();
|
||||||
|
timeClient.setTimeOffset(config.getInt("utcTimeOffsetMinutes") * 60);
|
||||||
|
|
||||||
debug.outln(F("Have following configuration:"), DEBUG_MAX_INFO);
|
debug.outln(F("Have following configuration:"), DEBUG_MAX_INFO);
|
||||||
debug.out(F(" App Mode: "), DEBUG_MAX_INFO); debug.outln(config.getString("appMode"), DEBUG_MAX_INFO);
|
debug.out(F(" App Mode: "), DEBUG_MAX_INFO); debug.outln(config.getString("appMode"), DEBUG_MAX_INFO);
|
||||||
@@ -318,8 +105,6 @@ void setup() {
|
|||||||
debug.out(F(" Clock listen port: "), DEBUG_MAX_INFO); debug.outln(config.getString("listenPort"), DEBUG_MAX_INFO);
|
debug.out(F(" Clock listen port: "), DEBUG_MAX_INFO); debug.outln(config.getString("listenPort"), DEBUG_MAX_INFO);
|
||||||
debug.out(F(" Real time UTC offset: "), DEBUG_MAX_INFO); debug.outln(config.getString("utcTimeOffsetMinutes"), DEBUG_MAX_INFO);
|
debug.out(F(" Real time UTC offset: "), DEBUG_MAX_INFO); debug.outln(config.getString("utcTimeOffsetMinutes"), DEBUG_MAX_INFO);
|
||||||
|
|
||||||
setRealClockTimeOffset(config.getInt("utcTimeOffsetMinutes"));
|
|
||||||
|
|
||||||
debug.outln(F("Starting fastclock ..."), DEBUG_MAX_INFO);
|
debug.outln(F("Starting fastclock ..."), DEBUG_MAX_INFO);
|
||||||
fastclock.begin();
|
fastclock.begin();
|
||||||
|
|
||||||
@@ -328,17 +113,14 @@ void setup() {
|
|||||||
sevenSegmentClock.setBrightness(config.getInt("brightness"));
|
sevenSegmentClock.setBrightness(config.getInt("brightness"));
|
||||||
sevenSegmentClock.setColor(sevenSegmentClock.getColorHandleByName(config.getString("clockColor")));
|
sevenSegmentClock.setColor(sevenSegmentClock.getColorHandleByName(config.getString("clockColor")));
|
||||||
|
|
||||||
// setting up web server for clock configuration
|
// setting up web server for clock configuration; intentionally very late
|
||||||
server = new ESP8266WebServer(80);
|
// as we need the web server during boot to be able to connect to/configure WiFi
|
||||||
server->on("/config", HTTP_GET, appConfig);
|
webUI = new WebUI(debug, config, timeClient, fastclock, sevenSegmentClock);
|
||||||
server->on("/configSave", HTTP_GET, appConfigSave);
|
webUI->begin();
|
||||||
server->on("/configSavePermanent", HTTP_GET, appConfigSavePermanent);
|
|
||||||
|
|
||||||
server->begin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hours = 0, minutes = 0;
|
static int hours = 0, minutes = 0;
|
||||||
uint32_t nextUpdate_ms = 0;
|
static uint32_t nextUpdate_ms = 0;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
timeClient.update();
|
timeClient.update();
|
||||||
@@ -355,11 +137,20 @@ void loop() {
|
|||||||
if (hours % 4 == 0) sevenSegmentClock.setBlinkMode(SevenSegmentClock::SeperatorBlinking); else sevenSegmentClock.setBlinkMode(SevenSegmentClock::NoBlinking);
|
if (hours % 4 == 0) sevenSegmentClock.setBlinkMode(SevenSegmentClock::SeperatorBlinking); else sevenSegmentClock.setBlinkMode(SevenSegmentClock::NoBlinking);
|
||||||
}
|
}
|
||||||
} else if (config.getString("appMode").equals(MODE_REALCLOCK)) {
|
} else if (config.getString("appMode").equals(MODE_REALCLOCK)) {
|
||||||
|
sevenSegmentClock.setClockHalted(!fastclock.isActive());
|
||||||
|
sevenSegmentClock.setBlinkMode(SevenSegmentClock::NoBlinking);
|
||||||
sevenSegmentClock.displayTime(timeClient.getHours(), timeClient.getMinutes());
|
sevenSegmentClock.displayTime(timeClient.getHours(), timeClient.getMinutes());
|
||||||
} else if (config.getString("appMode").equals(MODE_FASTCLOCK)) {
|
} else if (config.getString("appMode").equals(MODE_FASTCLOCK)) {
|
||||||
|
sevenSegmentClock.setClockHalted(!fastclock.isActive());
|
||||||
|
if (fastclock.isActive()) {
|
||||||
|
sevenSegmentClock.setBlinkMode(SevenSegmentClock::NoBlinking);
|
||||||
|
} else {
|
||||||
|
sevenSegmentClock.setBlinkMode(SevenSegmentClock::DecimalPointColoredBlinking);
|
||||||
|
}
|
||||||
sevenSegmentClock.displayTime(fastclock.getClockHours(), fastclock.getClockMinutes());
|
sevenSegmentClock.displayTime(fastclock.getClockHours(), fastclock.getClockMinutes());
|
||||||
} else { debug.outln("ERROR: Unknown appMode found.", DEBUG_ERROR); }
|
} else { debug.outln(F("ERROR: Unknown appMode found."), DEBUG_ERROR); }
|
||||||
|
|
||||||
sevenSegmentClock.displayUpdate();
|
sevenSegmentClock.displayUpdate();
|
||||||
server->handleClient();
|
webUI->loop();
|
||||||
|
filesystem.loop();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user