320 lines
8.1 KiB
C++
320 lines
8.1 KiB
C++
#include <Adafruit_NeoPixel.h>
|
|
#include <ArduinoJson.h>
|
|
#include <ESP8266WiFi.h>
|
|
#include <ESP8266HTTPClient.h>
|
|
|
|
#include <DNSServer.h>
|
|
#include <ESP8266WebServer.h>
|
|
#include <WiFiManager.h>
|
|
#include <EEPROM.h>
|
|
|
|
|
|
#define STATION_UID "93" // location id
|
|
#define HOST "bici.lbsfilm.at"
|
|
|
|
#define REFRESH 1000
|
|
|
|
#define OFFSET 1
|
|
|
|
#define SEGLEN 5 // SegmentLength
|
|
#define SEPLEN 2 // SeperatorLength
|
|
#define NUM_LEDS 142 //SEGLEN * 4 * 7 + 2
|
|
#define DATA_PIN D5 // Data pin for led comunication
|
|
|
|
Adafruit_NeoPixel clock = Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);
|
|
|
|
byte digits[12][7] = {
|
|
{ 0, 1, 1, 1, 1, 1, 1 }, // Digit 0
|
|
{ 0, 1, 0, 0, 0, 0, 1 }, // Digit 1
|
|
{ 1, 1, 1, 0, 1, 1, 0 }, // Digit 2
|
|
{ 1, 1, 1, 0, 0, 1, 1 }, // Digit 3
|
|
{ 1, 1, 0, 1, 0, 0, 1 }, // Digit 4
|
|
{ 1, 0, 1, 1, 0, 1, 1 }, // Digit 5
|
|
{ 1, 0, 1, 1, 1, 1, 1 }, // Digit 6
|
|
{ 0, 1, 1, 0, 0, 0, 1 }, // Digit 7
|
|
{ 1, 1, 1, 1, 1, 1, 1 }, // Digit 8
|
|
{ 1, 1, 1, 1, 0, 1, 1 }, // Digit 9
|
|
{ 1, 1, 1, 1, 0, 0, 0 }, // Digit *0
|
|
{ 0, 0, 1, 1, 1, 1, 0 } // Digit C
|
|
};
|
|
|
|
long oldTime = 0;
|
|
String bicislots = "";
|
|
String bicis = "";
|
|
|
|
String hours = "";
|
|
String minutes = "";
|
|
|
|
char stationId[6] = "93";
|
|
bool displayOn = false;
|
|
|
|
//flag for saving data
|
|
bool shouldSaveConfig = false;
|
|
|
|
//callback notifying us of the need to save config
|
|
void saveConfigCallback () {
|
|
Serial.println("Should save config");
|
|
shouldSaveConfig = true;
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
//EEPROM.begin(512);
|
|
//stationId = EEPROM.read(25);
|
|
|
|
|
|
WiFiManagerParameter custom_station_id("server", "station id", stationId, 6);
|
|
WiFiManager wifiManager;
|
|
|
|
wifiManager.setSaveConfigCallback(saveConfigCallback);
|
|
wifiManager.autoConnect("ConfigureClock");
|
|
wifiManager.addParameter(&custom_station_id);
|
|
Serial.println(custom_station_id.getValue());
|
|
if (shouldSaveConfig) {
|
|
Serial.println("saving config");
|
|
//EEPROM.write(25);
|
|
}
|
|
|
|
clock.begin();
|
|
clock.show(); // Initialize all pixels to 'off'
|
|
colon(clock.Color(255, 255, 255));
|
|
delay(1000);
|
|
colorWipe( clock.Color(0, 100, 150), 10);
|
|
colorWipe( clock.Color(0, 0, 0), 5);
|
|
//displayNumber("99:99", clock.Color(150, 150, 150));
|
|
//countUp( clock.Color(0, 100, 150), 100);
|
|
}
|
|
|
|
|
|
void loop() // Main loop
|
|
{
|
|
// Check motion sensor
|
|
// get data and time
|
|
displayOn = digitalRead(D6);
|
|
|
|
if (millis() - oldTime > REFRESH) {
|
|
uint32_t c = clock.Color(10, 10, 10);
|
|
getData();
|
|
if(displayOn) displayNumber(hours + ":" + minutes, c);
|
|
Serial.println(hours + ":" + minutes);
|
|
}
|
|
}
|
|
|
|
void getData() {
|
|
HTTPClient https;
|
|
String URL = "https://" + String(HOST) + "/stations?stationId=" + String(STATION_UID);
|
|
https.begin( URL, "1D:62:C5:06:5E:45:51:26:2F:56:A5:BD:E9:5E:F1:33:C8:6C:66:05"); //HTTPS
|
|
int httpCode = https.GET();
|
|
|
|
if (httpCode > 0) {
|
|
// HTTP header has been send and Server response header has been handled
|
|
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
|
|
|
|
// file found at server
|
|
if (httpCode == HTTP_CODE_OK) {
|
|
String payload = https.getString();
|
|
Serial.println(payload);
|
|
// Compute optimal size of the JSON buffer according to what we need to parse.
|
|
// See https://bblanchon.github.io/ArduinoJson/assistant/
|
|
|
|
// Allocate a temporary memory pool
|
|
DynamicJsonBuffer jsonBuffer(650);
|
|
|
|
JsonObject& root = jsonBuffer.parseObject(payload);
|
|
|
|
if (!root.success()) {
|
|
Serial.println("JSON parsing failed!");
|
|
return;
|
|
}
|
|
|
|
Serial.println("JSON parsing SUCCEDED!");
|
|
const char* bicislotsChar = root["empty_slots"];
|
|
bicislots = String(bicislotsChar);
|
|
const char* bicisChar = root["free_bikes"];
|
|
bicis = String(bicisChar);
|
|
|
|
const char* hoursChar = root["time"]["hours"];
|
|
hours = String(hoursChar);
|
|
const char* minutesChar = root["time"]["minutes"];
|
|
minutes = String(minutesChar);
|
|
|
|
int offsetting = hours.toInt();
|
|
offsetting = offsetting + OFFSET;
|
|
if (offsetting == 24) offsetting = 0;
|
|
if (offsetting < 10) hours = "0" + String(offsetting, DEC);
|
|
else hours = String(offsetting, DEC);
|
|
|
|
}
|
|
} else {
|
|
Serial.printf("[HTTP] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
|
|
}
|
|
|
|
https.end();
|
|
oldTime = millis();
|
|
}
|
|
|
|
|
|
/* LED FX */
|
|
|
|
// Fill the dots one after the other with a color
|
|
void colorWipe(uint32_t c, uint8_t wait) {
|
|
for (uint16_t i = 0; i < clock.numPixels(); i++) {
|
|
clock.setPixelColor(i, c);
|
|
clock.show();
|
|
delay(wait);
|
|
}
|
|
}
|
|
|
|
void rainbow(uint8_t wait) {
|
|
uint16_t i, j;
|
|
|
|
for (j = 0; j < 256; j++) {
|
|
for (i = 0; i < clock.numPixels(); i++) {
|
|
clock.setPixelColor(i, Wheel((i + j) & 255));
|
|
}
|
|
clock.show();
|
|
delay(wait);
|
|
}
|
|
}
|
|
|
|
// Slightly different, this makes the rainbow equally distributed throughout
|
|
void rainbowCycle(uint8_t wait) {
|
|
uint16_t i, j;
|
|
|
|
for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
|
|
for (i = 0; i < clock.numPixels(); i++) {
|
|
clock.setPixelColor(i, Wheel(((i * 256 / clock.numPixels()) + j) & 255));
|
|
}
|
|
clock.show();
|
|
delay(wait);
|
|
}
|
|
}
|
|
|
|
//Theatre-style crawling lights.
|
|
void theaterChase(uint32_t c, uint8_t wait) {
|
|
for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
|
|
for (int q = 0; q < 3; q++) {
|
|
for (uint16_t i = 0; i < clock.numPixels(); i = i + 3) {
|
|
clock.setPixelColor(i + q, c); //turn every third pixel on
|
|
}
|
|
clock.show();
|
|
|
|
delay(wait);
|
|
|
|
for (uint16_t i = 0; i < clock.numPixels(); i = i + 3) {
|
|
clock.setPixelColor(i + q, 0); //turn every third pixel off
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Theatre-style crawling lights with rainbow effect
|
|
void theaterChaseRainbow(uint8_t wait) {
|
|
for (int j = 0; j < 256; j++) { // cycle all 256 colors in the wheel
|
|
for (int q = 0; q < 3; q++) {
|
|
for (uint16_t i = 0; i < clock.numPixels(); i = i + 3) {
|
|
clock.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
|
|
}
|
|
clock.show();
|
|
|
|
delay(wait);
|
|
|
|
for (uint16_t i = 0; i < clock.numPixels(); i = i + 3) {
|
|
clock.setPixelColor(i + q, 0); //turn every third pixel off
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Input a value 0 to 255 to get a color value.
|
|
// The colours are a transition r - g - b - back to r.
|
|
uint32_t Wheel(byte WheelPos) {
|
|
WheelPos = 255 - WheelPos;
|
|
if (WheelPos < 85) {
|
|
return clock.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
|
}
|
|
if (WheelPos < 170) {
|
|
WheelPos -= 85;
|
|
return clock.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
|
}
|
|
WheelPos -= 170;
|
|
return clock.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
|
}
|
|
|
|
// ############### The LED Strip handling ###################
|
|
|
|
void displayNumber(String string, uint32_t color) {
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
if (i < 2) fillNumber(i, string[i] - 48, color);
|
|
else fillNumber(i, string[i + 1] - 48, color);
|
|
}
|
|
|
|
if (string[2] == ':') colon(color);
|
|
else nocolon();
|
|
|
|
}
|
|
|
|
void noclock() {
|
|
for (int led = 0; led < clock.numPixels(); led++) {
|
|
clock.setPixelColor(led, 0);
|
|
}
|
|
clock.show();
|
|
}
|
|
|
|
|
|
void colon(uint32_t color) {
|
|
for (int led = 0; led < SEPLEN; led++) {
|
|
int currentLed = SEGLEN * 14 + led;
|
|
clock.setPixelColor(currentLed, color);
|
|
}
|
|
clock.show();
|
|
}
|
|
|
|
void nocolon() {
|
|
for (int led = 0; led < SEPLEN; led++) {
|
|
int currentLed = SEGLEN * 14 + led;
|
|
clock.setPixelColor(currentLed, 0);
|
|
}
|
|
clock.show();
|
|
}
|
|
|
|
void fillNumber(int position, int digit, uint32_t color) {
|
|
int offset = 0;
|
|
if (position > 3)return;
|
|
if (position < 0)return;
|
|
if (position > 1) offset = SEPLEN;
|
|
|
|
for (int seg = 0; seg < 7; seg++) {
|
|
for (int led = 0; led < SEGLEN; led++) {
|
|
int currentLed = position * 5 * 7 + seg * 5 + led + offset;
|
|
if (digits[digit][seg] == 1) {
|
|
clock.setPixelColor(currentLed, color);
|
|
} else {
|
|
clock.setPixelColor(currentLed, clock.Color(0, 0, 0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void countUp(uint32_t color, int wait) {
|
|
fillNumber(0, 8, clock.Color(0,0,0));
|
|
|
|
for (int num3 = 0; num3 < 10; num3++) {
|
|
fillNumber(1, num3, color);
|
|
|
|
for (int num2 = 0; num2 < 10; num2++) {
|
|
fillNumber(2, num2, color);
|
|
|
|
for (int num1 = 0; num1 < 10; num1++) {
|
|
fillNumber(3, num1, color);
|
|
|
|
clock.show();
|
|
delay(wait);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|