diff --git a/ESP8266-MQTT-Teufel-Subwoofer/.gitignore b/ESP8266-MQTT-Teufel-Subwoofer/.gitignore new file mode 100644 index 0000000..0401f59 --- /dev/null +++ b/ESP8266-MQTT-Teufel-Subwoofer/.gitignore @@ -0,0 +1 @@ +ESP8266-MQTT-Teufel-Subwoofer.h diff --git a/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template new file mode 100644 index 0000000..41d0062 --- /dev/null +++ b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.h.template @@ -0,0 +1,13 @@ +// WiFi configuration +const char* ssid = "http://kiel.freifunk.net/"; +const char* password = ""; + +// MQTT Broker +const char* mqtt_server = "broker.mqtt-dashboard.com"; + +// Device identification +const char* mqtt_device_name = "esp8266benq" + +// MQTT topics +const char* mqtt_topic_power = "benq/power"; +const char* mqtt_topic_lamptime = "benq/lamptime"; diff --git a/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino new file mode 100644 index 0000000..9424f7e --- /dev/null +++ b/ESP8266-MQTT-Teufel-Subwoofer/ESP8266-MQTT-Teufel-Subwoofer.ino @@ -0,0 +1,206 @@ +/********************************************************************** + * 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-Teufel-Subwoofer + * + * Links the ESP8266 based subwoofer control board to an mqtt broker. + * The program uses multiple topics for incoming and outgoing messages. + * Incoming topics: + * - /power + * Outgoing topics: + * + **********************************************************************/ + +#include +#include +#include "ESP8266-MQTT-Teufel-Subwoofer.h" + +#define DEBUGTOSERIAL 1 + +// Timestamp for last publish +long lastMsg = 0; +long publishInterval = 5000; +// Message buffer +char msg[50]; + +// Last known power state +int powerState = 0; + +// Pin config +const int powerSwitchPin = 12; +const int powerProbePin = 13; + +// Global mqtt client object +WiFiClient espClient; +PubSubClient client(espClient); + +/* + * Initial setup for arduino + */ +void setup() { + + // Configure pins + pinMode(powerSwitchPin, OUTPUT); + digitalWrite(powerSwitchPin, LOW); + + // 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()); + } +} + +/* + * 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 (int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + } + + if (strcmp(topic, mqtt_topic_power) == 0) { + if (length == 1) { + if (DEBUGTOSERIAL) { + Serial.println("Setting new power state"); + } + if ((char)payload[0] == '0') { + if (powerState == HIGH) { + // Turn power off + togglePowerButton(); + } + } else { + if (powerState == LOW) { + // Turn power off + togglePowerButton(); + } + } + } + } +} + +/* + * 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_name)) { + if (DEBUGTOSERIAL) { + Serial.println("connected"); + } + // subscribe to incoming topics + client.subscribe(mqtt_topic_power); + } 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 togglePowerButton() { + digitalWrite(powerSwitchPin, HIGH); + delay(100); + digitalWrite(powerSwitchPin, LOW); +} + +void updatePowerState() { + // Read value from digital pin (Levels are inverted) + powerState = 1 - digitalRead(powerProbePin); + + if (DEBUGTOSERIAL) { + Serial.print("New power state determined: "); + Serial.println(powerState); + } + + snprintf(msg, 49, "%d", powerState); + client.publish(mqtt_topic_powerState, msg); +} + +void loop() { + // 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; + updatePowerState(); + } +}