The following series of posts will document my journey to full Home Automation using the MQTT protocol, all custom hardware (Arduino and ESP8266 based), and all tied together using OpenHAB
- Part 1:Â Setting up the server / environment
- Part 2:Â Publish, Subscribe, Command, State, and WTFs
- Part 3:Â Hardware:Â Arduino with Ethernet Shield
- Part 4:Â Hardware:Â ESP8266 with NodeMCU firmware
- Part 5:Â Hardware:Â Sensors
- Part 5.1:Â Graphing Sensor Data
- Part 5.2:Â Combined Switch and Sensor
- Part 6:Â OpenHAB Automation Rules
This is a very quick post just to jot down a very simple mashup of Part 3 and Part 5. The sketch below listens for MQTT messages to switch, at every second, but only sends temperature updates every 5 seconds… Good tradeoff = always available to switch immediately, yet still low bandwidth since it doesnt send a temp update on each cycle of the loop:
Another twist here is that I added a physical button on D7 that also turns the device on/off and then publishes the state back to MQTT -> openhab so the virtual switch status matches what the physical is doing
#include <SPI.h> #include <Ethernet.h> #include <PubSubClient.h> #include <Wire.h> #include <LCD.h> #include <LiquidCrystal_I2C.h> float temp; int tempPin = 0; unsigned long interval=5000; // the time we need to wait unsigned long previousMillis=0; // millis() returns an unsigned long. int buttonPin = 7; boolean currentState = LOW;//stroage for current button state boolean lastState = LOW;//storage for last button state boolean ledState = LOW;//storage for the current state of the LED (off/on) // Update these with values suitable for your network. byte mac[]   = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; byte server[] = { 192, 168, 0, 100 }; byte ip[]    = { 192, 168, 0, 120 }; EthernetClient ethClient; PubSubClient client(server, 1883, callback, ethClient); LiquidCrystal_I2C   lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack byte bulb[8] = {    0b01110,    0b10001,    0b10001,    0b10001,    0b01110,    0b01010,    0b01110,    0b00100 }; byte plug[8] = {    0b01010,    0b01010,    0b11111,    0b10001,    0b10001,    0b01110,    0b00100,    0b00100 }; void callback(char* topic, byte* payload, unsigned int length) { Serial.println("Callback"); Serial.print("Topic:"); Serial.println(topic); Serial.print("Length:"); Serial.println(length); Serial.print("Payload:"); Serial.write(payload,length); Serial.println();  if (strcmp(topic,"/testsw/1")==0) {   if (payload[0] == '0')    {    digitalWrite(4, LOW);    lcd.home();    lcd.clear();    lcd.write((uint8_t)1);    lcd.print ("Turning Fan OFF");    delay(100);    client.publish("/testsw/1/state","0");    }    else if (payload[0] == '1')    {    digitalWrite(4, HIGH);    lcd.home();    lcd.clear();    lcd.write((uint8_t)1);    lcd.print ("Turning Fan ON");    delay(100);    client.publish("/testsw/1/state","1");    }   }  if (strcmp(topic,"/testsw/2")==0) {   if (payload[0] == '0')    {    digitalWrite(5, LOW);    lcd.home();    lcd.clear();    lcd.write((uint8_t)1);    lcd.print ("Turning Light OFF");    delay(100);    client.publish("/testsw/2/state","0");    }    else if (payload[0] == '1')    {    digitalWrite(5, HIGH);    lcd.home();    lcd.clear();    lcd.write((uint8_t)1);    lcd.print ("Turning Light ON");    delay(100);    client.publish("/testsw/2/state","1");    }   } } void setup() {  Serial.begin(9600);  pinMode(buttonPin, INPUT);//this time we will set the pin as INPUT  digitalWrite(buttonPin, HIGH);  lcd.begin (20,4); // for 16 x 2 LCD module  lcd.createChar(0, bulb);  lcd.createChar(1, plug);  lcd.home(); // set cursor to 0,0  lcd.print(" Starting ");  delay(1000);  Ethernet.begin(mac, ip);    lcd.home();    lcd.clear();    lcd.print("Ethernet Connected");      if (client.connect("arduinoClient")) {    lcd.home();    lcd.clear();    lcd.print("MTQQ Connected");    client.publish("outTopic","hello world");    client.subscribe("/testsw/#");  }  pinMode(4, OUTPUT);  digitalWrite(4, LOW);  pinMode(5, OUTPUT);  digitalWrite(5, LOW); } void loop() {  client.loop();    if ((unsigned long)(millis() - previousMillis) >= interval) {      previousMillis = millis();      temp = analogRead(tempPin);      temp = temp * 0.48828125;      Serial.print("TEMPERATURE = ");      Serial.print(temp);      Serial.print("*C");      Serial.println();         char temperature[10];      dtostrf(temp,4,3,temperature);      client.publish("/home/1/ard2/s1/state",temperature);   }    currentState = digitalRead(buttonPin);  if (currentState == HIGH && lastState == LOW){//if button has just been pressed    Serial.println("pressed");    delay(10);//crude form of button debouncing       //toggle the state of the LED    if (ledState == HIGH){      digitalWrite(4, LOW);      ledState = LOW;      client.publish("/testsw/1/state","0");    } else {      digitalWrite(4, HIGH);      ledState = HIGH;       client.publish("/testsw/1/state","1");    }  }   lastState = currentState; }