arduino-sketches

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 6  →  ?path2? @ 7
/arduinoLightStrip/arduinoLightStrip.ino
@@ -0,0 +1,327 @@
/*************************************************************************/
/* Copyright (C) 2021 Wizardry and Steamworks - License: GNU GPLv3 */
/*************************************************************************/
 
// The AP to connect to via Wifi.
#define STA_SSID ""
// The AP Wifi password.
#define STA_PSK ""
// The MQTT broker to connect to.
#define MQTT_HOST ""
// The MQTT broker username.
#define MQTT_USERNAME ""
// The MQTT broker password.
#define MQTT_PASSWORD ""
// The MQTT broker port.
#define MQTT_PORT 1883
// The default MQTT client ID is "esp-CHIPID" where CHIPID is the ESP8266
// or ESP32 chip identifier.
#define MQTT_CLIENT_ID() String("esp-" + String(GET_CHIP_ID(), HEX))
// The authentication password to use for OTA updates.
#define OTA_PASSWORD ""
// The OTA port on which updates take place.
#define OTA_PORT 8266
// The default topic that the sketch subscribes to is "esp/CHIPID" where
// CHIPID is the ESP8266 or ESP32 chip identifier.
#define MQTT_TOPIC() String("esp/" + String(GET_CHIP_ID(), HEX))
 
// Platform specific defines.
#if defined(ARDUINO_ARCH_ESP8266)
#define GET_CHIP_ID() (ESP.getChipId())
#elif defined(ARDUINO_ARCH_ESP32)
#define GET_CHIP_ID() ((uint16_t)(ESP.getEfuseMac()>>32))
#endif
 
// Miscellaneous defines.
#define CHIP_ID_HEX (String(GET_CHIP_ID()).c_str())
#define HOSTNAME() String("esp-" + String(GET_CHIP_ID(), HEX))
 
// Platform specific libraries.
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <ESPmDNS.h>
#endif
// General libraries.
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#if defined(ARDUINO_ARCH_ESP32)
#include <FS.h>
#include <SPIFFS.h>
#endif
 
// Define LED strip PWM pins.
#if defined(ARDUINO_ARCH_ESP8266)
#define R_PIN D5
#define G_PIN D6
#define B_PIN D7
#elif defined(ARDUINO_ARCH_ESP32)
#define R_PIN 33
#define G_PIN 34
#define B_PIN 35
#endif
 
const char *sta_ssid = STA_SSID;
const char *sta_psk = STA_PSK;
const char *mqtt_host = MQTT_HOST;
const char *mqtt_username = MQTT_USERNAME;
const char *mqtt_password = MQTT_PASSWORD;
const int mqtt_port = MQTT_PORT;
const char *ota_password = OTA_PASSWORD;
const int ota_port = OTA_PORT;
 
WiFiClient espClient;
PubSubClient mqttClient(espClient);
 
/*************************************************************************/
/* Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 */
/*************************************************************************/
int wasMapValueToRange(int v, int xMin, int xMax, int yMin, int yMax) {
return yMin + (
( yMax - yMin ) * ( v - xMin ) / ( xMax - xMin )
);
}
void mqttCallback(char *topic, byte *payload, unsigned int length) {
String msgTopic = String(topic);
// payload is not null terminated and casting will not work
char msgPayload[length + 1];
snprintf(msgPayload, length + 1, "%s", payload);
Serial.println("Message received on topic: " + String(topic) + " with payload: " + String(msgPayload));
 
// Parse the payload sent to the MQTT topic as a JSON document.
StaticJsonDocument<256> doc;
Serial.println("Deserializing message....");
DeserializationError error = deserializeJson(doc, msgPayload);
if (error) {
Serial.println("Failed to parse MQTT payload as JSON: " + String(error.c_str()));
return;
}
 
Serial.println("Message deserialized....");
 
// Ignore message with no identifier in the payload.
if (!doc.containsKey("id")) {
return;
}
 
// Do not listen to self.
String id = (const char *)doc["id"];
if (id == String(MQTT_CLIENT_ID().c_str())) {
return;
}
 
// Set the pin values while mapping from RGB to [0, 3.3]V (PWMRANGE)
const int r = wasMapValueToRange((const int)doc["r"], 0, 255, 0, PWMRANGE);
analogWrite(R_PIN, r);
 
const int g = wasMapValueToRange((const int)doc["g"], 0, 255, 0, PWMRANGE);
analogWrite(G_PIN, g);
 
const int b = wasMapValueToRange((const int)doc["b"], 0, 255, 0, PWMRANGE);
analogWrite(B_PIN, b);
 
Serial.println("R: " + String(r) + ", G: " + String(g) + ", B: " + String(b));
 
// Announce the action.
StaticJsonDocument<256> msg;
msg["R"] = r;
msg["G"] = g;
msg["B"] = b;
 
char msgPublish[256];
serializeJson(msg, msgPublish);
mqttClient.publish(MQTT_TOPIC().c_str(), (const char*) msgPublish);
}
 
bool mqttConnect() {
Serial.println("Attempting to connect to MQTT broker: " + String(mqtt_host));
mqttClient.setServer(mqtt_host, mqtt_port);
 
StaticJsonDocument<256> msg;
char msgPublish[256];
if (mqttClient.connect(MQTT_CLIENT_ID().c_str(), mqtt_username, mqtt_password)) {
Serial.println("Established connection with MQTT broker using client ID: " + MQTT_CLIENT_ID());
mqttClient.setCallback(mqttCallback);
msg["action"] = "connected";
serializeJson(msg, msgPublish);
mqttClient.publish(MQTT_TOPIC().c_str(), (const char*) msgPublish);
Serial.println("Attempting to subscribe to MQTT topic: " + MQTT_TOPIC());
if (!mqttClient.subscribe(MQTT_TOPIC().c_str())) {
Serial.println("Failed to subscribe to MQTT topic: " + MQTT_TOPIC());
return false;
}
Serial.println("Subscribed to MQTT topic: " + MQTT_TOPIC());
msg.clear();
msg["action"] = "subscribed";
serializeJson(msg, msgPublish);
mqttClient.publish(MQTT_TOPIC().c_str(), (const char*) msgPublish);
return true;
}
else {
Serial.println("Connection to MQTT broker failed with MQTT client state: " + String(mqttClient.state()));
}
 
return false;
}
 
bool loopWifiConnected() {
// Process OTA loop first since emergency OTA updates might be needed.
ArduinoOTA.handle();
 
// Process MQTT client loop.
if (!mqttClient.connected()) {
// If the connection to the MQTT broker has failed then sleep before carrying on.
if (!mqttConnect()) {
return false;
}
}
mqttClient.loop();
 
return true;
}
 
void setup() {
Serial.begin(115200);
Serial.println("Booted, setting up Wifi in 10s...");
delay(10000);
 
// Initialize pins.
pinMode(R_PIN, OUTPUT);
analogWrite(R_PIN, 0);
pinMode(G_PIN, OUTPUT);
analogWrite(G_PIN, 0);
pinMode(B_PIN, OUTPUT);
analogWrite(B_PIN, 0);
 
WiFi.mode(WIFI_STA);
#if defined(ARDUINO_ARCH_ESP8266)
WiFi.hostname(HOSTNAME().c_str());
#elif defined(ARDUINO_ARCH_ESP32)
WiFi.setHostname(HOSTNAME().c_str());
#endif
WiFi.begin(sta_ssid, sta_psk);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Failed to connect to Wifi, rebooting in 5s...");
delay(5000);
ESP.restart();
}
 
Serial.print("Connected to Wifi: ");
Serial.println(WiFi.localIP());
 
Serial.println("Setting up OTA in 10s...");
delay(10000);
 
// Port defaults to 8266
ArduinoOTA.setPort(ota_port);
 
// Hostname defaults to esp-[ChipID]
ArduinoOTA.setHostname(HOSTNAME().c_str());
 
// Set the OTA password
ArduinoOTA.setPassword(ota_password);
 
ArduinoOTA.onStart([]() {
switch (ArduinoOTA.getCommand()) {
case U_FLASH: // Sketch
Serial.println("OTA start updating sketch.");
break;
#if defined(ARDUINO_ARCH_ESP8266)
case U_FS:
#elif defined(ARDUINO_ARCH_ESP32)
case U_SPIFFS:
#endif
Serial.println("OTA start updating filesystem.");
SPIFFS.end();
break;
default:
Serial.println("Unknown OTA update type.");
break;
}
});
ArduinoOTA.onEnd([]() {
Serial.println("OTA update complete.");
//SPIFFS.begin();
#if defined(ARDUINO_ARCH_ESP8266)
// For what it's worth, check the filesystem on ESP8266.
//SPIFFS.check();
#endif
ESP.restart();
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("OTA update progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("OTA update error [%u]: ", error);
switch (error) {
case OTA_AUTH_ERROR:
Serial.println("OTA authentication failed");
break;
case OTA_BEGIN_ERROR:
Serial.println("OTA begin failed");
break;
case OTA_CONNECT_ERROR:
Serial.println("OTA connect failed");
break;
case OTA_RECEIVE_ERROR:
Serial.println("OTA receive failed");
break;
case OTA_END_ERROR:
Serial.println("OTA end failed");
break;
default:
Serial.println("Unknown OTA failure");
break;
}
ESP.restart();
});
ArduinoOTA.begin();
 
// Set up MQTT client.
mqttClient.setServer(mqtt_host, mqtt_port);
mqttClient.setCallback(mqttCallback);
 
// Touchdown.
Serial.println("Setup complete.");
}
 
void loop() {
// Check the Wifi connection status.
int wifiStatus = WiFi.status();
switch (wifiStatus) {
case WL_CONNECTED:
if (!loopWifiConnected()) {
delay(1000);
break;
}
delay(1);
break;
case WL_NO_SHIELD:
Serial.println("No Wifi shield present.");
goto DEFAULT_CASE;
break;
case WL_NO_SSID_AVAIL:
Serial.println("Configured SSID not found.");
goto DEFAULT_CASE;
break;
// Temporary statuses indicating transitional states.
case WL_IDLE_STATUS:
case WL_SCAN_COMPLETED:
delay(1000);
break;
// Fatal Wifi statuses trigger a delayed ESP restart.
case WL_CONNECT_FAILED:
case WL_CONNECTION_LOST:
case WL_DISCONNECTED:
default:
Serial.println("Wifi connection failed with status: " + String(wifiStatus));
DEFAULT_CASE:
delay(10000);
ESP.restart();
break;
}
}