Skip to content

Instantly share code, notes, and snippets.

@arcao
Last active January 28, 2017 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arcao/12cce928645c6050383206265f1fae6b to your computer and use it in GitHub Desktop.
Save arcao/12cce928645c6050383206265f1fae6b to your computer and use it in GitHub Desktop.
Improved biacz version (original: https://gist.github.com/biacz/5ad2f56b3d055a3fc7ac700c7bc7a294). Switching lights are postponed to perform together.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>
#include <RCSwitch.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include <Ticker.h>
// WiFi config
#define WIFI_SSID "Drueck mich!"
#define WIFI_PASSWORD "Key01@BM"
// MQTT config
#define MQTT_CLIENT_ID "bedroom_dht11"
#define MQTT_SERVER_IP ""
#define MQTT_SERVER_PORT 1883
#define MQTT_USER ""
#define MQTT_PASSWORD ""
// DHT sensor
#define DHT_PIN 13
#define DHT_TYPE DHT11
#define DHT_TOPIC "/house/livingroom/sensor_dht"
#define DHT_UPDATE_INTERVAL_IN_SEC 20
// lights config
#define LIGHT_POSTPONE_DELAY_IN_MS 200
struct LIGHT_SWITCH {
const char* name;
const char* status_topic;
const char* command_topic;
const char* socket_code;
bool state;
bool updateState;
};
LIGHT_SWITCH lights[] = {
{
"Steckdose Wohnzimmer Links",
"/house/livingroom/light_left/status",
"/house/livingroom/light_left/switch",
"00010",
false,
false
},
{
"Steckdose Wohnzimmer Rechts",
"/house/livingroom/light_right/status",
"/house/livingroom/light_right/switch",
"00001",
false,
false
},
{
"Steckdose Wohnzimmer Eingang",
"/house/livingroom/light_center/status",
"/house/livingroom/light_center/switch",
"10000",
false,
false
}
};
#define LIGHT_COUNT 3
#define LIGHT_ON "ON"
#define LIGHT_OFF "OFF"
// other config
#define HOUSE_CODE "11010"
#define JSON_CHAR_BUFFER_SIZE 200
DHT dht(DHT_PIN, DHT_TYPE);
WiFiClient wifiClient;
PubSubClient client(wifiClient);
RCSwitch mySwitch = RCSwitch();
Ticker postDhtTicker;
bool performPostDht = false;
Ticker applyLightsTicker;
bool applyLightsPlaned = false;
bool performApplyLights = false;
void applyLights() {
applyLightsPlaned = false;
for(int i=0; i < LIGHT_COUNT; i++) {
if (lights[i].updateState) {
lights[i].updateState = false;
if (lights[i].state)
mySwitch.switchOn(HOUSE_CODE, lights[i].socket_code);
if (!lights[i].state)
mySwitch.switchOff(HOUSE_CODE, lights[i].socket_code);
}
}
}
void callback(char* topic, byte* payload, unsigned int len) {
Serial.println(topic);// handle message topic
for(int i=0; i < LIGHT_COUNT; i++) {
if (strcmp(lights[i].command_topic, topic) == 0) {
// test if the payload is equal to "ON" or "OFF"
lights[i].state = strcmp(LIGHT_ON, (char*)payload) == 0;
lights[i].updateState = true;
Serial.print("INFO: Turn Light: ");
Serial.print(lights[i].name);
Serial.println((lights[i].state) ? " on!" : "off!");
client.publish(lights[i].status_topic,(lights[i].state) ? LIGHT_ON : LIGHT_OFF, true);
if (!applyLightsPlaned) {
applyLightsPlaned = true;
applyLightsTicker.once_ms(LIGHT_POSTPONE_DELAY_IN_MS, []{ performApplyLights = true; });
}
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.println("INFO: Attempting MQTT connection...");
// Attempt to connect
if (client.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD)) {
Serial.println("INFO: connected");
// subscribe and send state
for(int i=0; i < LIGHT_COUNT; i++) {
client.subscribe(lights[i].command_topic);
client.publish(lights[i].status_topic,(lights[i].state) ? LIGHT_ON : LIGHT_OFF, true);
}
} else {
Serial.print("ERROR: failed, rc=");
Serial.print(client.state());
Serial.println("DEBUG: try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setupLights() {
mySwitch.enableTransmit(2);
// turn off all lights
for(int i=0; i < LIGHT_COUNT; i++) {
mySwitch.switchOff(HOUSE_CODE, lights[i].socket_code);
lights[i].state = false;
lights[i].state = false;
}
}
void postDht() {
char buffer[JSON_CHAR_BUFFER_SIZE + 1];
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("ERROR: Failed to read from DHT sensor!");
return;
} else {
//Serial.println(h);
//Serial.println(t);
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["temperature"] = String(t);
root["humidity"] = String(h);
root.prettyPrintTo(Serial);
Serial.println();
root.printTo(buffer, JSON_CHAR_BUFFER_SIZE);
client.publish(DHT_TOPIC, buffer, true);
}
}
void setupDht() {
dht.begin();
applyLightsTicker.attach(DHT_UPDATE_INTERVAL_IN_SEC, []{ performPostDht = true; });
}
void setup() {
// init the serial
Serial.begin(115200);
Serial.println();
Serial.println();
setupLights();
setupDht();
// init the WiFi connection
Serial.print("INFO: Connecting to ");
Serial.println(WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("INFO: WiFi connected");
Serial.println("INFO: IP address: ");
Serial.println(WiFi.localIP());
t_httpUpdate_return ret = ESPhttpUpdate.update("http://beutler.nl/test.bin");
switch(ret) {
case HTTP_UPDATE_FAILED:
Serial.print("HTTP_UPDATE_FAILD Error (%d): %s ");
Serial.println(ESPhttpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println("HTTP_UPDATE_NO_UPDATES");
break;
case HTTP_UPDATE_OK:
Serial.println("HTTP_UPDATE_OK");
break;
}
// init the MQTT connection
client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (performPostDht) {
performPostDht = false;
postDht();
}
if (performApplyLights) {
performApplyLights = false;
applyLights();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment