diff --git a/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.h.template b/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.h.template index 468a63f..3708b16 100644 --- a/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.h.template +++ b/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.h.template @@ -2,6 +2,9 @@ const char* ssid = "http://kiel.freifunk.net/"; const char* password = ""; +// OTA Hostname +const char* ota_hostname = "BenQ"; + // MQTT Broker const char* mqtt_server = "broker.mqtt-dashboard.com"; diff --git a/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.ino b/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.ino index 540bacb..c8bbad9 100644 --- a/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.ino +++ b/ESP8266-MQTT-BenQ/ESP8266-MQTT-BenQ.ino @@ -94,7 +94,7 @@ void setup_wifi() { Serial.print("My IP address: "); Serial.println(WiFi.localIP()); } - ArduinoOTA.setHostname("esp8266-BenQ"); + ArduinoOTA.setHostname(ota_hostname); ArduinoOTA.begin(); } diff --git a/ESP8266-MQTT-MagicBox/.gitignore b/ESP8266-MQTT-MagicBox/.gitignore new file mode 100644 index 0000000..bdcbd34 --- /dev/null +++ b/ESP8266-MQTT-MagicBox/.gitignore @@ -0,0 +1 @@ +ESP8266-MQTT-MagicBox.h diff --git a/ESP8266-MQTT-MagicBox/ESP8266-MQTT-MagicBox.h.template b/ESP8266-MQTT-MagicBox/ESP8266-MQTT-MagicBox.h.template new file mode 100644 index 0000000..1cde57b --- /dev/null +++ b/ESP8266-MQTT-MagicBox/ESP8266-MQTT-MagicBox.h.template @@ -0,0 +1,16 @@ +// WiFi configuration +const char* ssid = "http://kiel.freifunk.net/"; +const char* password = ""; + +// OTA Hostname +const char* ota_hostname = "MagicBox"; + +// MQTT Broker +const char* mqtt_server = "broker.mqtt-dashboard.com"; + +// Device identification +const char* mqtt_device = "magicBox"; + +// MQTT topics +const char* mqtt_topic_port = "magicBox/port"; +const char* mqtt_topic_portState = "magicBox/portState"; diff --git a/ESP8266-MQTT-MagicBox/ESP8266-MQTT-MagicBox.ino b/ESP8266-MQTT-MagicBox/ESP8266-MQTT-MagicBox.ino new file mode 100644 index 0000000..d3782bf --- /dev/null +++ b/ESP8266-MQTT-MagicBox/ESP8266-MQTT-MagicBox.ino @@ -0,0 +1,252 @@ +/********************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2015 Nis Wechselberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + **********************************************************************/ + +/********************************************************************** + * ESP8266-MQTT-MagicBox + * + * Links the ESP8266 based control board to an mqtt broker. + * The program uses multiple topics for incoming and outgoing messages. + * Incoming topics: + * - /port + * Outgoing topics: + * - /portState + **********************************************************************/ + +#include +#include +#include +#include +#include +#include "ESP8266-MQTT-MagicBox.h" + +#define DEBUGTOSERIAL 1 + +// Timestamp for last publish +unsigned long lastMsg = 0; +long publishInterval = 5000; +// Message buffer +char msg[50]; + +// Last known power state +uint8_t portState = 0; +uint32_t codes[] = {0xFFAA55, 0xFFA857, 0xFFBA45, 0xFF38C7}; + +// Pin config +const uint8_t irSendPin = 12; +const uint8_t probe1 = 13; +const uint8_t probe2 = 14; +const uint8_t probe3 = 16; +const uint8_t probe4 = 5; + +// Global mqtt client object +WiFiClient espClient; +PubSubClient client(espClient); + +/* + * Initial setup for arduino + */ +void setup() { + + // Configure pins + pinMode(irSendPin, OUTPUT); + digitalWrite(irSendPin, HIGH); + + // Configure serial port + Serial.begin(115200); + delay(10); + + // Prepare WiFi connection + setup_wifi(); + + // Connect to mqtt broker + client.setServer(mqtt_server, 1883); + client.setCallback(incoming_mqtt); +} + +/* + * Prepares the wireless connection + */ +void setup_wifi() { + // Connect to the WiFi as a client + WiFi.mode(WIFI_STA); + + // Do the connection + if (DEBUGTOSERIAL) { + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + } + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + if (DEBUGTOSERIAL) { + Serial.print("."); + } + } + if (DEBUGTOSERIAL) { + Serial.println(""); + Serial.println("WiFi connected"); + + // Print IP address to serial + Serial.print("My IP address: "); + Serial.println(WiFi.localIP()); + } + ArduinoOTA.setHostname(ota_hostname); + ArduinoOTA.begin(); +} + +/* + * Callback method for incoming mqtt messages + */ +void incoming_mqtt(char* topic, byte* payload, unsigned int length) { + if (DEBUGTOSERIAL) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (unsigned int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + } + + if (strcmp(topic, mqtt_topic_port) == 0) { + if (length == 1) { + if (DEBUGTOSERIAL) { + Serial.println("Setting new port active"); + } + uint8_t desiredPortState = 0; + char request = (char) payload[0]; + if (request == '1' || request == '2' || request == '3' || request == '4') { + desiredPortState = request - '0'; + } + + if (desiredPortState != 0 && desiredPortState != portState) { + changePort(desiredPortState); + } + } + } +} + +void changePort(uint8_t newPort) { + if (newPort > 0 && newPort < 5) { + replicateNEC(irSendPin, codes[newPort - 1], 32); + } +} + +void replicateNEC(int pin, uint32_t data, int dataLength) { + + if (DEBUGTOSERIAL) { + Serial.print("Sending code "); + Serial.println(data, HEX); + } + // Prepare mask + uint32_t mask = 1L << (dataLength -1); + // Write initial 9ms+4.5ms pulse + digitalWrite(pin, LOW); + delayMicroseconds(9000); + digitalWrite(pin, HIGH); + delayMicroseconds(4500); + + // Write pulses from data + while (mask > 0) { + digitalWrite(pin, LOW); + delayMicroseconds(562); + digitalWrite(pin, HIGH); + delayMicroseconds(562); + if (data & mask) { + delayMicroseconds(1124); + } + mask = mask >> 1; + } + + // Write trailing pulse + digitalWrite(pin, LOW); + delayMicroseconds(562); + digitalWrite(pin, HIGH); +} + +/* + * Blocking reconnect to the mqtt broker + */ +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + if (DEBUGTOSERIAL) { + Serial.print("Attempting MQTT connection..."); + } + // Attempt to connect + if (client.connect(mqtt_device)) { + if (DEBUGTOSERIAL) { + Serial.println("connected"); + } + // subscribe to incoming topics + client.subscribe(mqtt_topic_port); + } else { + if (DEBUGTOSERIAL) { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + } + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void updatePortState() { + // Read value from digital pin (Levels are inverted) + if (digitalRead(probe1)) portState = 1; + if (digitalRead(probe2)) portState = 2; + if (digitalRead(probe3)) portState = 3; + if (digitalRead(probe4)) portState = 4; + + if (DEBUGTOSERIAL) { + Serial.print("Output port "); + Serial.print(portState); + Serial.println(" selected"); + } + + snprintf(msg, 49, "%d", portState); + client.publish(mqtt_topic_portState, msg); +} + +void loop() { + // Check OTA update + ArduinoOTA.handle(); + + // Ensure MQTT connection + if (!client.connected()) { + reconnect(); + } + + // Check the inbox + client.loop(); + + // Maybe push the current status + long now = millis(); + if (now - lastMsg > publishInterval) { + lastMsg = now; + updatePortState(); + } +} diff --git a/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.h.template b/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.h.template index 993bbdf..b078e38 100644 --- a/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.h.template +++ b/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.h.template @@ -2,14 +2,21 @@ const char* ssid = "http://kiel.freifunk.net/"; const char* password = ""; +// OTA Hostname +const char* ota_hostname = "RGBControl"; + // MQTT Broker const char* mqtt_server = "broker.mqtt-dashboard.com"; // Device identification -const char* mqtt_device = "esp8266client" +const char* mqtt_device = "esp8266RGBControl" // MQTT topics -const char* mqtt_topic_power = "esp8266client/power"; -const char* mqtt_topic_color = "esp8266client/color"; -const char* mqtt_topic_breathe = "esp8266client/breathe"; -const char* mqtt_topic_cycle = "esp8266client/cycle"; +const char* mqtt_topic_power = "RGBControl/power"; +const char* mqtt_topic_powerState = "RGBControl/powerState"; +const char* mqtt_topic_color = "RGBControl/color"; +const char* mqtt_topic_colorState = "RGBControl/colorState"; +const char* mqtt_topic_breathe = "RGBControl/breathe"; +const char* mqtt_topic_breatheState = "RGBControl/breatheState"; +const char* mqtt_topic_cycle = "RGBControl/cycle"; +const char* mqtt_topic_cycleState = "RGBControl/cycleState"; diff --git a/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.ino b/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.ino index 71ac668..4fec48c 100644 --- a/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.ino +++ b/ESP8266-MQTT-RGBControl/ESP8266-MQTT-RGBControl.ino @@ -78,6 +78,13 @@ unsigned char decColor = 0; // Timestamp for last color update unsigned long lastColorUpdate = 0; + +// Timestamp for last publish +unsigned long lastMsg = 0; +unsigned long publishInterval = 5000; +// Message buffer +char msg[50]; + /* * Initial setup for arduino */ @@ -117,7 +124,7 @@ void setup_wifi() { Serial.print("My IP address: "); Serial.println(WiFi.localIP()); - ArduinoOTA.setHostname("esp8266-Lighting2"); + ArduinoOTA.setHostname(ota_hostname); ArduinoOTA.begin(); } @@ -293,6 +300,20 @@ void setColor() { } } +void publishState() { + snprintf(msg, 49, "%d", powerFactor); + client.publish(mqtt_topic_powerState, msg); + + snprintf(msg, 49, "#%02X%02X%02X", rgbColor[0], rgbColor[1], rgbColor[2]); + client.publish(mqtt_topic_colorState, msg); + + snprintf(msg, 49, "%d", doBreathe); + client.publish(mqtt_topic_breatheState, msg); + + snprintf(msg, 49, "%d", doColorCycle); + client.publish(mqtt_topic_cycleState, msg); +} + void loop() { // Check OTA update ArduinoOTA.handle(); @@ -302,11 +323,16 @@ void loop() { } client.loop(); + unsigned long now = millis(); if (isPowerSet & isColorSet & isCycleSet & isBreatheSet) { - unsigned long now = millis(); if (now - lastColorUpdate > 30) { lastColorUpdate = now; updateLight(); } } + + if (now - lastMsg > publishInterval) { + lastMsg = now; + publishState(); + } } diff --git a/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.h.template b/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.h.template index 468a63f..bb06573 100644 --- a/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.h.template +++ b/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.h.template @@ -2,12 +2,17 @@ const char* ssid = "http://kiel.freifunk.net/"; const char* password = ""; +// OTA Hostname +const char* ota_hostname = "TeufelDS5"; + // MQTT Broker const char* mqtt_server = "broker.mqtt-dashboard.com"; // Device identification -const char* mqtt_device = "esp8266benq" +const char* mqtt_device = "esp8266TeufelDS5" // MQTT topics -const char* mqtt_topic_power = "benq/power"; -const char* mqtt_topic_lamptime = "benq/lamptime"; +const char* mqtt_topic_command = "teufelds5/command"; +const char* mqtt_topic_volume = "teufelds5/volume"; +const char* mqtt_topic_powerState = "teufelds5/powerState"; +const char* mqtt_topic_volumeState = "teufelds5/volumeState"; diff --git a/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.ino b/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.ino index 5b1ec7d..187e884 100644 --- a/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.ino +++ b/ESP8266-MQTT-Teufel-DS5/ESP8266-MQTT-Teufel-DS5.ino @@ -138,7 +138,7 @@ void setup_wifi() { Serial.print("My IP address: "); Serial.println(WiFi.localIP()); } - ArduinoOTA.setHostname("esp8266-TeufelDS5"); + ArduinoOTA.setHostname(ota_hostname); ArduinoOTA.begin(); } diff --git a/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template index 6e143b1..f956d85 100644 --- a/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template +++ b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template @@ -2,12 +2,15 @@ const char* ssid = "http://kiel.freifunk.net/"; const char* password = ""; +// OTA Hostname +const char* ota_hostname = "TeufelSub"; + // MQTT Broker const char* mqtt_server = "broker.mqtt-dashboard.com"; // Device identification -const char* mqtt_device = "livingroom/teufelSub"; +const char* mqtt_device = "teufelSub"; // MQTT topics -const char* mqtt_topic_power = "livingroom/teufelSub/power"; -const char* mqtt_topic_powerState = "livingroom/teufelSub/powerState"; +const char* mqtt_topic_power = "teufelSub/power"; +const char* mqtt_topic_powerState = "teufelSub/powerState"; diff --git a/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino index df886a2..1d19bd4 100644 --- a/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino +++ b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino @@ -108,7 +108,7 @@ void setup_wifi() { Serial.print("My IP address: "); Serial.println(WiFi.localIP()); } - ArduinoOTA.setHostname("esp8266-TeufelSub"); + ArduinoOTA.setHostname(ota_hostname); ArduinoOTA.begin(); }