/* ---------------------------------------------------------------------------- * "THE TSCHUNK LICENSE" (Revision 42): * wrote this file. As long as you retain this notice * you can do whatever you want with this stuff. If we meet some day, and you * think this stuff is worth it, you can buy me a Tschunk in return. * ---------------------------------------------------------------------------*/ #include #include #include #include #include "elapsedMillis.h" #include "signedUpdatesHelper.h" // most of these configuration settings should be changed in the file platformio.ini #define WIFI_SSID INI_SSID #define WIFI_PSK INI_PSK #define MQTT_SERVER INI_SERVER #define MQTT_ROOM INI_ROOM #define MQTT_DEVICE INI_DEVICE #define MQTT_RETAIN true #define UPDATE_URL "http://" MQTT_SERVER "/arduino-download.php?room=" MQTT_ROOM "&device=" MQTT_DEVICE #define UPDATE_VERSION INI_VERSION const char* const topic_state = MQTT_ROOM "/" MQTT_DEVICE "/state"; const char* const topic_bright = MQTT_ROOM "/" MQTT_DEVICE "/brightness"; const char* const topic_color = MQTT_ROOM "/" MQTT_DEVICE "/color"; const char* const topic_lwt = MQTT_ROOM "/" MQTT_DEVICE "/lwt"; const char* const topic_rssi = MQTT_ROOM "/" MQTT_DEVICE "/stats/rssi"; const char* const topic_vers = MQTT_ROOM "/" MQTT_DEVICE "/stats/update-version"; const char* const topic_upderr = MQTT_ROOM "/" MQTT_DEVICE "/stats/update-error"; #define LED_CHIPSET APA102 #define COLOR_ORDER BGR #define NUM_LEDS 1 #define DATA_PIN 4 #define CLOCK_PIN 5 #define SWITCH_PIN 15 bool is_auto_mode = false; int brightness = 0; String updateStatus; WiFiClient wifiClient, wifiClient2; PubSubClient mqttClient; CRGB leds[NUM_LEDS]; // by noby inline uint8_t parse_hex_nibble(uint8_t nibble) { return isdigit(nibble) ? nibble - '0' : toupper(nibble) - 'A'; } CRGB parse_colorcode(const char* payload) { uint8_t r = ((parse_hex_nibble(payload[0]) << 4)) | parse_hex_nibble(payload[1]); uint8_t g = ((parse_hex_nibble(payload[2]) << 4)) | parse_hex_nibble(payload[3]); uint8_t b = ((parse_hex_nibble(payload[4]) << 4)) | parse_hex_nibble(payload[5]); return CRGB(r, g, b); } void mqtt_callback(char* topic, byte* payload, unsigned int length) { if (strcmp(topic, topic_state) == 0 && length == 1) { if ((char)payload[0] == '0') { FastLED.setBrightness(0); is_auto_mode = false; } else if ((char)payload[0] == '1') { FastLED.setBrightness(brightness); is_auto_mode = false; } else if ((char)payload[0] == '2') { FastLED.setBrightness(0); is_auto_mode = true; } } else if (strcmp(topic, topic_bright) == 0 && length >= 1) { brightness = atoi((const char*) payload); FastLED.setBrightness(brightness); } else if (strcmp(topic, topic_color) == 0 && length == 6) { fill_solid(leds, NUM_LEDS, parse_colorcode((const char*)payload)); } } void mqtt_connect() { String mqtt_client_id = MQTT_DEVICE + ESP.getChipId(); if (mqttClient.connect(mqtt_client_id.c_str(), topic_lwt, 0, true, "offline")) { mqttClient.publish(topic_lwt, "online", MQTT_RETAIN); mqttClient.subscribe(topic_state); mqttClient.subscribe(topic_bright); mqttClient.subscribe(topic_color); } } void publish_stats() { if (mqttClient.connected()) { mqttClient.publish(topic_rssi, String(WiFi.RSSI()).c_str(), MQTT_RETAIN); mqttClient.publish(topic_vers, UPDATE_VERSION, MQTT_RETAIN); mqttClient.publish(topic_upderr, updateStatus.c_str()); } } void setup() { // FastLED setup #ifndef CLOCK_PIN FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); #else FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); #endif // Wifi setup WiFi.hostname(MQTT_ROOM "_" MQTT_DEVICE); WiFi.begin(WIFI_SSID, WIFI_PSK); while (WiFi.status() != WL_CONNECTED) delay(500); // MQTT setup mqttClient.setClient(wifiClient); mqttClient.setServer(MQTT_SERVER, 1883); mqttClient.setCallback(mqtt_callback); // misc setup randomSeed(micros()); signedUpdatesHelperInit(); } elapsedSeconds lastReconnect = 0; elapsedMillis lastLedShow = 0; elapsedSeconds lastStats = 0; elapsedSeconds lastUpdate = 0; void loop() { if (WiFi.status() == WL_CONNECTED && !mqttClient.connected()) { if (lastReconnect > 5) { lastReconnect = 0; mqtt_connect(); } } if (is_auto_mode) { FastLED.setBrightness(digitalRead(SWITCH_PIN) == HIGH ? brightness : 0); } if (lastLedShow > 200) { lastLedShow = 0; FastLED.show(); } if (lastStats > 120) { lastStats = 0; publish_stats(); } if (lastUpdate > 300) { lastUpdate = 0; updateStatus = signedUpdatesHelperRun(wifiClient2, UPDATE_URL, UPDATE_VERSION); } mqttClient.loop(); }