OpenHAB – 433 MHz Sender mit MQTT anbinden

29. Juli 2017 at 09:42
Print Friendly, PDF & Email

Meine Funksteckdosen von Elro werden über openhab angesteuert.
Die Anbindung erfolgt über MQTT und als Gateway wird ein Arduino UNO verwendet.
Als Format für die Meldungen habe ich JSON gewählt, um ggfs. später andere Clients für die Ansteuerung des Senders verwenden zu können.

OpenHAB

433.items

// 433.items
Switch Light_433_EG_1 "MQTT Flur EG Unten" (gLightsRandom,g433Switches) {
mqtt=">[mosquitto:house/433/ardu1/cmnd:command:*:MAP(433lightEG1.map)]" }
Switch Light_433_DG_1 "MQTT Flur DG Unten" (gLightsRandom,g433Switches) {
mqtt=">[mosquitto:house/433/ardu1/cmnd:command:*:MAP(433lightDG1.map)]" }

433lightEG1.map

ON={ "code":"00001" , "device" : "01000", "state":1}
OFF={"code":"00001" , "device" : "01000", "state":0}

433lightDG1.map

ON={ "code":"00001" , "device" : "10000", "state":1}
OFF={"code":"00001" , "device" : "10000", "state":0}

Arduino

/*
* 433 Sender controlled by MQTT messages
* Module will connect to MQTT broker and subscribe to a topic
* When receiving a json string via MQTTT, the module will call the send function and provide a feedback through MQTT
* Every 60 seconds the uptime will be send to the MQTT broker
*
* In : MQTT messages
* Out : 433 RF
* Date : 2017-07-29
*
* Hardware Setup
* 433 RF Sender on PIN2
*
*/
#include "Arduino.h"
#include <Ethernet.h>
#include <PubSubClient.h>
#include <RCSwitch.h>
#include <avr/wdt.h>
#define PIN_433TX 2 // Data Pin of 433 Sender
const char* charMqttTopic_433_Cmnd = "house/433/ardu1/cmnd";
const char* charMqttTopic_433_State = "house/433/ardu1/state";
const char* charMqttTopic_433_Online = "house/433/ardu1/online";
const char* charMqttTopic_433_Uptime = "house/433/ardu1/uptime";
RCSwitch mySwitch = RCSwitch();
// used for test purposes only
const char* housecode = "00001";
const char* socketcodes[] = {"10000" , "01000" , "00100", "00010" };
const char* socketnames[] = {"A" , "B" , "C" , "D" };
//int numofsockets = sizeof(socketcodes)/4;
 
//Ethernet and pubsub setup BEGIN
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x20 }; // Be sure this address is unique in your network
IPAddress myIP (192,168,1,2);
IPAddress MQTTserver (192,168,1,3);
EthernetClient ethClient;
PubSubClient MQTTclient(ethClient);
// Run the sketch and let it run for 30 seconds or so.
// You should never see the “Arduino Rebooted” message again after reboot.
// Then, comment out the RESETWATCHDOG statement like this:
#define RESETWATCHDOG
unsigned long utimer_Uptime = 0;
unsigned long ulMqttUptime = 0;
unsigned long ulMqttBoottime = 0;
static char jsonData[80];
#define MAX_TOKEN_STRING 10
static char cTokenCode [MAX_TOKEN_STRING];
static char cTokenDevice [MAX_TOKEN_STRING];
static char cTokenState [MAX_TOKEN_STRING];
static char cTokenCount [MAX_TOKEN_STRING];
static char cTokenDelay [MAX_TOKEN_STRING];
 
// ---------------------------------------------------------------------------------------- json_lookup_char
bool json_lookup_char ( const char* cSource, const char* cToken, char cReply[]){
char *ptr;
cReply[0]='\0'; // set null to 1st char in target
//Serial.print("\njson_lookup_char: ");
//Serial.println(cSource);
//Serial.print("Token >");
//Serial.print(cToken[0]);
ptr = strstr (cSource, cToken); // set pointer to 1st char in cSource matching token
if(!ptr){
Serial.print(" json_lookup_char > ");
Serial.print(cToken[0]);
Serial.println("< not found");
return false;
}
//Serial.println("< ok");
//Serial.print("1 *ptr >");Serial.print(*ptr);Serial.println("<");
//Serial.print("Token >");
//Serial.print(":");
ptr = strstr (ptr, ":"); // set pointer to :
if(!ptr){
Serial.print(" json_lookup_char > ");
Serial.println(": not found");
return false;
}
//Serial.println("< ok");
ptr++;
//if (*ptr=='"')
// ptr ++;
// read char and copy to
for (int i=0, x=0;i<MAX_TOKEN_STRING+1;i++){
if (!ptr)
break;
if (*ptr==','|| *ptr=='}') // read until ,}
break;
if (*ptr!=' '&& *ptr!='"') { // skip space + "
cReply[x ] = *ptr; // copy single char to target
cReply[x+1] = '\0'; // set end of string
x++;
}
ptr++;
} // for
//Serial.print(" result >");
//Serial.print(cReply);
//Serial.println("<");
return true;
}
// ---------------------------------------------------------------------------------------- callback
void callback(char* topic, byte* payload, unsigned int length) {
int iTokenState =0;
int iTokenCount =0;
int iTokenDelay =0;
#ifdef RESETWATCHDOG
wdt_reset();
#endif
Serial.print("MQTT Message arrived > [");
Serial.print(topic);
Serial.print("], length: ");
Serial.print(length);
Serial.print("] ");
for (unsigned int i=0;i<length;i++) {
jsonData[i] = (char)payload[i];
jsonData[i+1] = '\0';
Serial.print((char)payload[i]);
}
Serial.println();
if(strcmp(topic,charMqttTopic_433_Cmnd)==0) { // whatever you want for this topic
Serial.println("MQTT > 433 cmd received ...");
// 10011 10000 für Steckdose A
// JSON {code:"10011", device:"10000", state:1, count:1, delay:200}
// MQTT Message arrived > [house/433/ardu1/cmnd], length: 71] {code:00001 , device:10000, state:1, count:3. delay:100 }
if( json_lookup_char(jsonData,"code" , cTokenCode) ==false) return;
if( json_lookup_char(jsonData,"device", cTokenDevice) ==false) return;
if( json_lookup_char(jsonData,"state" , cTokenState) ==false) return;
iTokenState = atoi(cTokenState);
// Serial.print ("iTokenState > ");Serial.print (iTokenState);Serial.println(" <");
json_lookup_char(jsonData,"count" , cTokenCount);
iTokenCount = atoi(cTokenCount);
// Serial.print ("iTokenCount > ");Serial.print (iTokenCount);Serial.println(" <");
if(iTokenCount==0)
iTokenCount = 1;
json_lookup_char(jsonData,"delay" , cTokenDelay);
iTokenDelay = atoi(cTokenDelay);
// Serial.print ("iTokenDelay > ");Serial.print (iTokenDelay);Serial.println(" <");
if(iTokenDelay==0)
iTokenDelay = 50;
Serial.print ("433-send> code>"); Serial.print (cTokenCode);
Serial.print ("< device>"); Serial.print (cTokenDevice);
Serial.print ("< state>"); Serial.print (iTokenState);
Serial.print ("< count>"); Serial.print (iTokenCount);
Serial.print ("< delay>"); Serial.print (iTokenDelay);
Serial.print (" > ");
// 433-send> code: device: state:1 count:3 delay:100 >
#ifdef RESETWATCHDOG
wdt_reset();
#endif
switch (iTokenState)
{
case 0:
Serial.print(" mySwitch.switchOff >");
for (int i=0;i<iTokenCount;i++) {
mySwitch.switchOff(cTokenCode, cTokenDevice);
Serial.print("+");
delay(iTokenDelay);
}
MQTTclient.publish(charMqttTopic_433_State,"0");
break;
case 1:
Serial.print(" mySwitch.switchOn >");
for (int i=0;i<iTokenCount;i++) {
mySwitch.switchOn(cTokenCode, cTokenDevice);
//mySwitch.switchOn("00001", "10000");
Serial.print("+");
delay(iTokenDelay);
}
MQTTclient.publish(charMqttTopic_433_State,"1");
break;
default:
Serial.print(" Error >");
MQTTclient.publish(charMqttTopic_433_State,"invalid state");
break;
}
Serial.println (" DONE\n");
} // 433 cmd received
 
} // end of function
void switch_test() {
for(int i = 0; i <3; i++) {
Serial.print (socketnames[i]);
Serial.print (" on");
mySwitch.switchOn(housecode, socketcodes[i]);
delay(500);
Serial.println (" off");
mySwitch.switchOff(housecode, socketcodes[i]);
delay(500);
}
} // end of function
 
// ---------------------------------------------------------------------------------------- OW_read_pub_old
void Heartbeat_pub() {
MQTTclient.publish(charMqttTopic_433_Online,"true");
char buffer [33];
int iUptime = (millis()-ulMqttBoottime)/1000;
Serial.print ("heartbeat - uptime> ");
Serial.println (itoa(iUptime, buffer, 10));
MQTTclient.publish(charMqttTopic_433_Uptime, itoa(iUptime, buffer, 10) );
}
// ---------------------------------------------------------------------------------------- reconnect
void reconnect() {
// Loop until we're reconnected
while (!MQTTclient.connected()) {
#ifdef RESETWATCHDOG
wdt_reset();
#endif
Serial.print("\n------------------------------------------------ Attempting MQTT connection...");
if (MQTTclient.connect("arduinoClient")) { // Attempt to connect
Serial.println("connected");
Heartbeat_pub();
// ... and resubscribe
// MQTTclient.subscribe("house/1wire/ardu1/cmnd");
MQTTclient.subscribe(charMqttTopic_433_Cmnd); // house/433/ardu1/cmnd
Serial.print("MQTT sub >");
Serial.println(charMqttTopic_433_Cmnd);
}
else {
Serial.print("failed, rc=");
Serial.print(MQTTclient.state());
Serial.println(" try again in 5 seconds");
// Wait 3 seconds before retrying
delay(3000);
}
}
Serial.println("--------------------------------------------------------------- connected");
} // end of function
 
// ---------------------------------------------------------------------------------------- setup
void setup(void) {
#ifdef RESETWATCHDOG
wdt_disable(); // immediately disable watchdog timer
delay(2L * 1000L); // pause before enabling WDT - This gives the IDE a chance to call the bootloader
wdt_enable(WDTO_8S);// enable watchdog timer
#endif
Serial.begin(115200);
delay(200);
Serial.println("\n\n+++++++++++++++++++++++++++++++++++++");
Serial.println("++ 1-Wire MQTT - 2017-07-29 ++");
Serial.println("+++++++++++++++++++++++++++++++++++++");
Ethernet.begin(mac, myIP);
Serial.print("My IP address: "); // print the Ethernet board/shield's IP address:
Serial.println(Ethernet.localIP());
delay(1000);// give the Ethernet shield a second to initialize
MQTTclient.setServer(MQTTserver, 1883);
MQTTclient.setCallback(callback);
#ifdef RESETWATCHDOG
wdt_reset();
#endif
mySwitch.enableTransmit(PIN_433TX); // Pin 2 = Data PIN of 433 Sender
ulMqttBoottime = utimer_Uptime = millis();
} // end of function
// ---------------------------------------------------------------------------------------- loop
void loop(void) {
// listen for incoming clients
//EthernetClient client = server.available();
// size_t size;
#ifdef RESETWATCHDOG
wdt_reset();
#endif
if (!MQTTclient.connected()) { //Connect to MQTT
reconnect();
}
MQTTclient.loop(); // callback/receive MQTT
if (millis() - utimer_Uptime > 60000) {
Heartbeat_pub();
// switch_test();
utimer_Uptime = millis();
}
} // end of function