esp-signed-updater-mqtt/src/main.cpp

160 lines
4.7 KiB
C++

/* ----------------------------------------------------------------------------
* "THE TSCHUNK LICENSE" (Revision 42):
* <christian@staudte.it> 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 <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <FastLED.h>
#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<LED_CHIPSET, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
#else
FastLED.addLeds<LED_CHIPSET, DATA_PIN, CLOCK_PIN, COLOR_ORDER>(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();
}