Switch back ON if power fails, with monitoring input state. Openhab+Arduino

Hi guys,
i need help or some pointers in the right direction, because im new in the Openhab world and also im little bit confused :slight_smile: .
So i have AC mini split system to cool down my gear in the summer and i managed to turn it on through relay with openhab, but the problem is when the power outage happens the AC unit is off and it not come back on. How can i make some rule or something that checks every minute the last state that i pressed OFF or ON and if it is OFF when the power outage happens to turn back ON, but also to notify me by email :slight_smile:. I can put relay on my AC to check if its ON or OFF and connect it to Arduino.

Thanks in advance!!!
Here is my Arduino.ino

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// for DHT22 sensor
#include "DHT.h"
#define DHT1PIN 2
#define DHT1TYPE DHT22
#define DHT2PIN 7
#define DHT2TYPE DHT22
DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);
unsigned long readTime;
#define relay1 4

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,120);
IPAddress server(192, 168, 1, 106);
char message_buff[100]; // this buffers our incoming messages so we can do something on certain commands

EthernetClient ethClient;
PubSubClient client(ethClient);
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):


String readString;



void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  int i=0;
  for (i=0;i<length;i++) {
    Serial.print((char)payload[i]);
    message_buff[i] = payload[i];
  }
  message_buff[i] = '\0';
  String msgString = String(message_buff);
  if (msgString.equals("OFF")) {
    client.publish("openhab/floor1/command","acknowedging OFF");
  }
  else if(msgString.equals("ON")){
    client.publish("openhab/floor1/command","acknowedging ON");
  }
  Serial.println();
  //Bounce relay
  if ( msgString == "ON" ) {
     digitalWrite(relay1,HIGH); }
     
  if ( msgString == "OFF" ) {  
     digitalWrite(relay1,LOW);
  }
}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("openhab","floor1 sensor, reporting in");
      // ... and resubscribe
      client.subscribe("openhab/floor1/command");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() 
{
  pinMode(relay1,OUTPUT);
  dht1.begin();
  dht2.begin();
 // Open serial communications and wait for port to open:
  Serial.begin(57600);
  client.setServer("192.168.1.106", 1883);
  client.setCallback(callback); 
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);

  delay(1500);
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  readTime = 0;
}

void loop() 
{
  
  if (!client.connected()) {
    reconnect();
  }
  
  client.loop();
  
  /// publish reading every 10 seconds 
  if(millis() > readTime+10000){
    sensorRead();
  }
  
}


void sensorRead(){
  readTime = millis();
 // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // get data from DHT22 sensor
          float h1 = dht1.readHumidity();
          float t1 = dht1.readTemperature();
          float h2 = dht2.readHumidity();
          float t2 = dht2.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h1) || isnan(t1) || isnan(h2) || isnan(t2)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht1.computeHeatIndex(t1, h1, false);
  float hic1 = dht2.computeHeatIndex(t2, h2, false);
  
  char buffer[10];
  dtostrf(t1,0, 0, buffer);
  client.publish("openhab/floor1/temperature1",buffer);
  //Serial.println(buffer);
  dtostrf(h1,0, 0, buffer);
  client.publish("openhab/floor1/humidity1",buffer);
  dtostrf(t2,0, 0, buffer);
  client.publish("openhab/floor1/temperature2",buffer);
  //Serial.println(buffer);
  dtostrf(h2,0, 0, buffer);
  client.publish("openhab/floor1/humidity2",buffer);
  client.subscribe("openhab/floor1/relay1");
  
  //client.publish("inTopic/humidity",sprintf(buf, "%f", h));
  /*Serial.print("Humidity1: ");
  Serial.print(h1);
  Serial.print(" %\t");
  Serial.print("Temperature1: ");
  Serial.print(t1);
  Serial.print(" *C ");
  Serial.print(h2);
  Serial.print(" %\t");
  Serial.print("Temperature2: ");
  Serial.print(t2);
  Serial.print(" *C ");
  Serial.print(f);
  Serial.print(" *F\t");
  Serial.print("Heat index: ");
  Serial.print(hic);
  Serial.print(" *C ");
  Serial.print(hif);
  Serial.println(" *F"); */
}

default.items

/* MQTT Sensors */

Number Floor1_Temp "Floor1 Temperature 1 [%.1f °C]" <temperature> (Floor1,Temperature) {mqtt="<[mymosquitto:openhab/floor1/temperature1:state:default]"}
Number Floor1_Humidity "Floor1 Humidity 1 [%.1f %%]" <water> (Floor1,Humidity) {mqtt="<[mymosquitto:openhab/floor1/humidity1:state:default]"}
Number Floor1_Temp2 "Floor1 Temperature 2 [%.1f °C]" <temperature> (Floor1,Temperature) {mqtt="<[mymosquitto:openhab/floor1/temperature2:state:default]"}
Number Floor1_Humidity2 "Floor1 Humidity 2 [%.1f %%]" <water> (Floor1,Humidity) {mqtt="<[mymosquitto:openhab/floor1/humidity2:state:default]"}
Switch Relay1 "Relay"           <garagedoor>    (All) {mqtt=">[mymosquitto:openhab/floor1/relay1:command:ON:ON],>[mymosquitto:openhab/floor1/relay1:command:OFF:OFF]"}

default.sitemap

sitemap default label="Main Menu"
{
        Frame label="Floor1_Temp" {
                Text item=Floor1_Temp
        }
		Frame label="Floor1_Humidity" {
                Text item=Floor1_Humidity
        }
		Frame label="Floor1_Temp2" {
                Text item=Floor1_Temp2
        }
		Frame label="Floor1_Humidity2" {
                Text item=Floor1_Humidity2
        }
		Switch item=Relay1 mappings=[OFF="OFF", ON="ON"] 
		
		Chart item=Floor1_Temp period=D
		Chart item=Floor1_Temp2 period=D
		{
        
		

How does openHAB know you lost power? Does openHAB go down too? I’ll assume so in which case we really need to send the command to turn the AC ON if the state of the AC was ON when OH went down.

This can very simply be implemented using persistence and a System started rule.

Set up persistence, MapDB is a good choice as it only saves the most recent state so it never grows which makes it great for restoring state of Items on startup but pretty worthless if you need to analyze the data. Configure persistence to save everyChange and restoreOnStartup for the AC Item at a minimum.

Persistence with restoreOnStartup will cause all persisted Items to be initialized to their previous state rather than “uninitialized”.

Then the rule simply checks to see if the AC Item is ON and if so it sends the ON command again to turn on the AC.

rule "Reset AC on startup"
when
    System started
then
    if(AC.state == ON) {
        AC.sendCommand(ON)
        // send email notification
    }
end

I don’t think you need another relay to check the state of the AC in this case. However, getting positive feedback is always a good thing.

The big assumption is that sending repeated ON commands to the relay will not cause the relay to simply toggle. In other words, if I send ON to the relay it should switch on or remain on if it already was on.

Hi Rich Koshak,
thanks for the quick answer!

Wow this is really simple :slight_smile:, it never come to my mind that when the power outage occurs, the openhab also loose power and the startup command is brilliant :). I will try it tomorrow and see what happens.
Thanks again!!!
Have a nice day

Lets say i also want to monitor the input from the second relay, can you help me out with the code in arduino? I managed to program the input but it publishes on the MQTT on every update with my temp readings, i want to make it publish only when the change happens, from OPEN > CLOSE or CLOSE > OPEN. switch5 is my second relay , here is the Code

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// for DHT22 sensor
#include "DHT.h"
#define DHT1PIN 2
#define DHT1TYPE DHT22
#define DHT2PIN 7
#define DHT2TYPE DHT22
DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);
unsigned long readTime;
#define relay1 4
#define switch5 5


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,120);
IPAddress server(192, 168, 1, 106);
char message_buff[100]; // this buffers our incoming messages so we can do something on certain commands

EthernetClient ethClient;
PubSubClient client(ethClient);
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):


String readString;



void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  int i=0;
  for (i=0;i<length;i++) {
    Serial.print((char)payload[i]);
    message_buff[i] = payload[i];
  }
  message_buff[i] = '\0';
  String msgString = String(message_buff);
  if (msgString.equals("OFF")) {
    client.publish("openhab/floor1/command","acknowedging OFF");
  }
  else if(msgString.equals("ON")){
    client.publish("openhab/floor1/command","acknowedging ON");
  }
  
  
  Serial.println();
  //Bounce relay
  if ( msgString == "ON" ) {
     digitalWrite(relay1,HIGH); 
     }
     
  if ( msgString == "OFF" ) {  
     digitalWrite(relay1,LOW);
  }


//publish switch1 status
  if (digitalRead(switch5)==HIGH){
  client.publish("openhab/floor1/switch5","OPEN");  
  }
  else {
  client.publish("openhab/floor1/switch5","CLOSE");
  }

}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("openhab","floor1 sensor, reporting in");
      // ... and resubscribe
      client.subscribe("openhab/floor1/command");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() 
{
  pinMode(switch5,INPUT_PULLUP);
  pinMode(relay1,OUTPUT);
  dht1.begin();
  dht2.begin();
 // Open serial communications and wait for port to open:
  Serial.begin(57600);
  client.setServer("192.168.1.106", 1883);
  client.setCallback(callback); 
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);

  delay(1500);
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  readTime = 0;
}

void loop() 
{
  
  if (!client.connected()) {
    reconnect();
  }
  
  client.loop();
  
  /// publish reading every 10 seconds 
  if(millis() > readTime+10000){
    sensorRead();
  }
  
}

void sensorRead(){
  readTime = millis();
 // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // get data from DHT22 sensor
          float h1 = dht1.readHumidity();
          float t1 = dht1.readTemperature();
          float h2 = dht2.readHumidity();
          float t2 = dht2.readTemperature();
          
  // Check if any reads failed and exit early (to try again).
  if (isnan(h1) || isnan(t1) || isnan(h2) || isnan(t2)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht1.computeHeatIndex(t1, h1, false);
  float hic1 = dht2.computeHeatIndex(t2, h2, false);
  
 //publish switch1 status
  if (digitalRead(switch5)==HIGH){
  client.publish("openhab/floor1/switch5","OPEN");  
    Serial.println("Your Door is Closed");
  }
  else {
    client.publish("openhab/floor1/switch5","CLOSE");
    Serial.println("Your Door is Open");
}
    
    
   
  
  
  
  char buffer[10];
  dtostrf(t1,0, 0, buffer);
  client.publish("openhab/floor1/temperature1",buffer);
  //Serial.println(buffer);
  dtostrf(h1,0, 0, buffer);
  client.publish("openhab/floor1/humidity1",buffer);
  dtostrf(t2,0, 0, buffer);
  client.publish("openhab/floor1/temperature2",buffer);
  //Serial.println(buffer);
  dtostrf(h2,0, 0, buffer);
  client.publish("openhab/floor1/humidity2",buffer);
  client.subscribe("openhab/floor1/relay1");
  
  
  //client.publish("inTopic/humidity",sprintf(buf, "%f", h));
  /*Serial.print("Humidity1: ");
  Serial.print(h1);
  Serial.print(" %\t");
  Serial.print("Temperature1: ");
  Serial.print(t1);
  Serial.print(" *C ");
  Serial.print(h2);
  Serial.print(" %\t");
  Serial.print("Temperature2: ");
  Serial.print(t2);
  Serial.print(" *C ");
  Serial.print(f);
  Serial.print(" *F\t");
  Serial.print("Heat index: ");
  Serial.print(hic);
  Serial.print(" *C ");
  Serial.print(hif);
  Serial.println(" *F"); */
}

I know that im doing it wrong in this lines

//publish switch1 status
  if (digitalRead(switch5)==HIGH){
  client.publish("openhab/floor1/switch5","OPEN");  
  }
  else {
  client.publish("openhab/floor1/switch5","CLOSE");
  }

Nope. I’ve not touched Arduino stuff yet. I know a lot of “in theory” but have little practical experience and no coding experience.

For that you need to keep track of whatever the previous state of switch5 was the last time you read it and see if the state is the same or different. Only if it is different do you client.publish.

I don’t know how variables work in Arduino so I don’t know where you need to put this but you need something like

int switch5Last; // does digitalRead return an int? Whatever the appropriate data type and whereever it is appropriate so the value is preserved for each time through the loop

...
    // Did switch5 change state?
    int switch5Curr = digitalRead(switch5);
    if(switch5Curr !=switch5Last) {
        switch5Last = switch5Curr
        if(switch5Curr == HIGH) client.publish("openhab/floor1/switch5", "OPEN")
        else client.publish("openhab/floor1/switch5", "CLOSED")
    }