Hello,
My goal is to get a working home automatisation system with pyshical push buttons that will control outputs, but at the same time have Openhab control these outputs as well by means of MQTT.
So far I managed to get the communication bit working where I publish messages with Mosquitto on my Raspberry pi.
I can also control the outputs using my smartphone, but the problem comes when I try to move on to the next step in my project: Publishing messages to Mosquitto whenever a state change happens with my physical push button.
The pushbutton works properly using edge detection (see code below), but an unexpected thing happens when I change the command from pinoutput to publishing on Mosquitto: A massive spam.
I guess this is to be expected since otherwise an output like a LED wouldnât stay turned on, but I fear that if I keep it like this and have up to 30 pushbuttons do the same thing, my Raspberry Pi wonât be handle it since itâs supposed to run 24/7.
How can I make it so that instead of it spamming, it will instead publish the message once upon state change?
If you have any other suggestions on how I can solve this then please go on ahead.
Also, looking forward I see another problem coming up: If the output is high (light on) and I change the output to low on my smartphone, how will the arduino sketch change the state low as well? But first things first
Code:
#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#define MQTT_SERVER_NAME "192.168.1.122"
#define MQTT_SERVER_PORT 1883
#define MQTT_CLIENTID "test"
#define MQTT_USER_NAME "openhab"
#define MQTT_USER_PASS NULL
#define MQTT_DOMAIN "openhab"
#define MQTT_TOPIC_LIGHT MQTT_DOMAIN"/"MQTT_CLIENTID"/light"
#define MQTT_TOPIC_CTRL MQTT_DOMAIN"/"MQTT_CLIENTID"/control"
// MAC Address of Arduino Ethernet Sheild (on sticker on shield)
byte MAC_ADDRESS[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
byte ip[] = {192,168,1,105};
PubSubClient client;
EthernetClient eclient;
// Pin 9 is the LED output pin
int PIN_LED = 9;
// defines and variable for sensor/control mode
#define MODE_OFF 0 // not sensing light, LED off
#define MODE_ON 1 // not sensing light, LED on
int senseMode;
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
int PIN_INPUT_2 = 2; // the number of the input pin
int PIN_OUTPUT_7 = 7; // the number of the output pin
unsigned long time;
unsigned long runNumber = 0;
char message_buff[100];
void setup()
{
// initialize the digital pin as an output.
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_OUTPUT_7, OUTPUT);
pinMode(PIN_INPUT_2, INPUT);
// init serial link for debugging
Serial.begin(9600);
Ethernet.begin(MAC_ADDRESS, ip);
if (Ethernet.begin(MAC_ADDRESS) == 0)
{
Serial.println("Failed to configure Ethernet using DHCP");
return;
}
// print your local IP address:
Serial.print("Local IP=");
Serial.println(Ethernet.localIP());
client = PubSubClient(MQTT_SERVER_NAME, MQTT_SERVER_PORT, callback, eclient);
}
void loop()
{
if (!client.connected())
{
Serial.println("Reconnect to mqtt");
// clientID, username, MD5 encoded password
if ( client.connect(MQTT_CLIENTID, MQTT_USER_NAME, MQTT_USER_PASS) ) {
Serial.println(" Connect client ["MQTT_CLIENTID"] OK");
if ( client.publish(MQTT_TOPIC_LIGHT, "I'm alive "__TIME__)) {
Serial.println(" Publishing alive message to ["MQTT_TOPIC_LIGHT"] OK");
if ( client.subscribe(MQTT_TOPIC_CTRL) ) {
Serial.println(" Subscribe to ["MQTT_TOPIC_CTRL"] OK");
} else {
Serial.println(" subscribe failed");
}
} else {
Serial.println(" publish failed");
}
} else {
Serial.println(" connect failed");
}
}
// read the pushbutton input pin:
buttonState = digitalRead(PIN_INPUT_2);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button
// went from off to on:
buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
} else {
// if the current state is LOW then the button
// went from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(200);
}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
// turns on the LED every four button pushes by
// checking the modulo of the button push counter.
// the modulo function gives you the remainder of
// the division of two numbers:
if (buttonPushCounter % 2 == 0) {
client.publish(MQTT_TOPIC_LIGHT, "LED_7_ON");
} else {
client.publish(MQTT_TOPIC_LIGHT, "LED_7_OFF");
}
switch (senseMode) {
case MODE_OFF:
// light should be off
digitalWrite(PIN_LED, LOW);
break;
case MODE_ON:
// light should be on
digitalWrite(PIN_LED, HIGH);
break;
}
// MQTT client loop processing
client.loop();
}
// handles message arrived on subscribed topic(s)
void callback(char * topic, byte * payload, unsigned int length) {
int i = 0;
Serial.println("Message arrived: topic: " + String(topic));
Serial.println("Length: " + String(length, DEC));
// create character buffer with ending null terminator (string)
for (i = 0; i < length; i++) {
message_buff[i] = payload[i];
}
message_buff[i] = '\0';
String msgString = String(message_buff);
Serial.println("Payload: " + msgString);
if (msgString.equals("OFF")) {
senseMode = MODE_OFF;
Serial.println("Switching to OFF mode");
} else if (msgString.equals("ON")) {
senseMode = MODE_ON;
Serial.println("Switching to ON mode");
}
}