#include #include #include #include #include #include #define LED_PIN 0 #define COLOR_ORDER GRB #define CHIPSET WS2811 #define BRIGHTNESS 10 #ifndef STASSID #define STASSID "FNT-Gast" #define STAPSK "Laserjet09" #endif #define APIKEY "e471293b25fdb6697c0a862f2695df5f" const char* ssid = STASSID; const char* password = STAPSK; // networking and json String apiUrl; int status = WL_IDLE_STATUS; ESP8266WiFiMulti WiFiMulti; WiFiClient client; HTTPClient http; boolean tempView = false; int respCode = 0; unsigned long startMillis1; unsigned long currentMillis1; unsigned long startMillis2; unsigned long currentMillis2; boolean firstIteration = true; void connectWiFi() { // We start by connecting to a WiFi network WiFi.mode(WIFI_STA); WiFiMulti.addAP(ssid, password); Serial.println(); Serial.println(); Serial.print("Wait for WiFi... "); while (WiFiMulti.run() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); delay(500); } String buildAPIUrl (double lat, double lon, const String& apiKey) { const String latStr(lat, 4); const String lonStr(lon, 4); return String("http://api.openweathermap.org/data/2.5/weather?lat=" + latStr + "&lon=" + lonStr + "&appid=" + apiKey + "&units=metric"); } // Params for width and height const uint8_t kMatrixWidth = 16; const uint8_t kMatrixHeight = 16; uint16_t XY( uint8_t x, uint8_t y) { uint16_t i; if ( x & 0x01) { i = kMatrixHeight * (kMatrixWidth - (x + 1)) + y; } else { i = kMatrixHeight * (kMatrixWidth - x) - (y + 1); } return i; } #define NUM_LEDS (kMatrixWidth * kMatrixHeight) CRGB leds_plus_safety_pixel[ NUM_LEDS + 1]; CRGB* const leds( leds_plus_safety_pixel + 1); uint16_t XYsafe( uint8_t x, uint8_t y) { if ( x >= kMatrixWidth) return -1; if ( y >= kMatrixHeight) return -1; return XY(x, y); } uint8_t sun_yx[16][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1}, {0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0}, {0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0}, {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; uint8_t cloud_yx[16][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; uint8_t rain_yx[16][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0} }; uint8_t cloudSun_yx[16][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; uint8_t celsius[5][16] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; uint8_t empty[11][8] = { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0} }; uint8_t zero[11][8] = { {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }; uint8_t one[11][8] = { {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 1, 1, 0, 0, 0, 0}, {0, 1, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 0} }; uint8_t two[11][8] = { {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0} }; uint8_t three[11][8] = { {0, 0, 1, 1, 1, 0, 0, 0}, {0, 1, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 0} }; uint8_t four[11][8] = { {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 1, 0, 0, 0}, {0, 1, 0, 0, 1, 0, 0, 0}, {0, 1, 0, 0, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0} }; uint8_t five[11][8] = { {0, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }; uint8_t six[11][8] = { {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }; uint8_t seven[11][8] = { {0, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0} }; uint8_t eight[11][8] = { {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }; uint8_t nine[11][8] = { {0, 0, 1, 1, 1, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 0, 0} }; uint8_t (*digitOne)[8]; uint8_t (*digitTwo)[8]; void drawFrame(uint8_t arr[][16], String identifier) { FastLED.clear(); FastLED.show(); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { uint8_t elem = arr[i][j]; if (elem == 1) { if (identifier == "Rain") { if (i >= 12) { leds[ XYsafe(i, j)] = CRGB::Blue; } else { leds[ XYsafe(i, j)] = CRGB::WhiteSmoke; } } else if (identifier == "Clouds") { leds[ XYsafe(i, j)] = CRGB::WhiteSmoke; } else if (identifier == "Sun") { leds[ XYsafe(i, j)] = CRGB::Yellow; } else if (identifier == "CloudSun") { if ((((i >= 0) && (i <= 8)) && ((j >= 0) && (j <= 2))) || (((i >= 0) && (i <= 4)) && ((j >= 0) && (j <= 15)))) { leds[ XYsafe(i, j)] = CRGB::Yellow; Serial.println("Yellow!"); } else { leds[ XYsafe(i, j)] = CRGB::WhiteSmoke; Serial.println("White!"); } } } } } FastLED.show(); } void drawTemp() { FastLED.clear(); FastLED.show(); for (int i = 0; i < 5; i++) { for (int j = 0; j < 16; j++) { // Celsius Symbol uint8_t elemCelsius = celsius[i][j]; if (elemCelsius == 1) { leds[ XYsafe(i, j)] = CRGB::WhiteSmoke; } } } } void drawFirstDigit(int num) { for (int i = 0; i < 11; i++) { for (int j = 0; j < 8; j++) { uint8_t elem; switch (num) { case 1: elem = one[i][j]; break; case 2: elem = two[i][j]; break; case 3: elem = three[i][j]; break; case 4: elem = four[i][j]; break; case 5: elem = five[i][j]; break; case 6: elem = six[i][j]; break; case 7: elem = seven[i][j]; break; case 8: elem = eight[i][j]; break; case 9: elem = nine[i][j]; break; default: elem = 0; break; } if (elem == 1) { leds[ XYsafe(i + 5, j)] = CRGB::WhiteSmoke; } } } } void drawSecondDigit(int num) { for (int i = 0; i < 11; i++) { for (int j = 0; j < 8; j++) { uint8_t elem; switch (num) { case 1: elem = one[i][j]; break; case 2: elem = two[i][j]; break; case 3: elem = three[i][j]; break; case 4: elem = four[i][j]; break; case 5: elem = five[i][j]; break; case 6: elem = six[i][j]; break; case 7: elem = seven[i][j]; break; case 8: elem = eight[i][j]; break; case 9: elem = nine[i][j]; break; default: elem = zero[i][j]; break; } if (elem == 1) { leds[ XYsafe(i + 5, j + 8)] = CRGB::WhiteSmoke; } } } FastLED.show(); } int extractDigit(int num, int i) { return num / i % 10 ; } void loop() { currentMillis1 = millis(); currentMillis2 = millis(); if (firstIteration || (currentMillis1 - startMillis1 >= 180000)) { respCode = http.GET(); firstIteration = false; startMillis1 = currentMillis1; } if (respCode > 0) { JsonDocument payload; const String response = http.getString(); deserializeJson(payload, response); if (currentMillis2 - startMillis2 >= 3000) { if (tempView) { Serial.print("Response: "); Serial.println(response); int temp = (int) payload["main"]["temp"]; Serial.print("Temp: "); Serial.println(temp); int firstDigit = extractDigit(temp, 10); int secondDigit = extractDigit(temp, 1); Serial.print("First digit: "); Serial.println(firstDigit); Serial.print("Second digit: "); Serial.println(secondDigit); drawTemp(); drawFirstDigit(firstDigit); drawSecondDigit(secondDigit); } else { if (String("Clouds") == String(payload["weather"][0]["main"])) { if (payload["weather"][0]["id"] >= 803) { drawFrame(cloud_yx, "Clouds"); } else { drawFrame(cloudSun_yx, "CloudSun"); } } else if (String("Rain") == String(payload["weather"][0]["main"]) || String("Drizzle") == String(payload["weather"][0]["main"])) { drawFrame(rain_yx, "Rain"); } else if (String("Clear") == String(payload["weather"][0]["main"])) { drawFrame(sun_yx, "Sun"); } else { drawFrame(cloudSun_yx, "CloudSun"); } } tempView = !tempView; startMillis2 = currentMillis2; } } else { Serial.print("error "); Serial.println(respCode); } } void setup() { startMillis1 = millis(); startMillis2 = millis(); Serial.begin(115200); // weather api const float lat = 48.9517; const float lon = 10.1703; apiUrl = buildAPIUrl(lat, lon, APIKEY); connectWiFi(); if (WiFi.status() != WL_CONNECTED) { Serial.println(WiFi.status()); } http.begin(client, apiUrl); FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalSMD5050); FastLED.setBrightness( BRIGHTNESS ); }