From af5e4e8ec9b2645f1e6e9dd4e43f21ca7911e39b Mon Sep 17 00:00:00 2001
From: Florian <1technophile@users.noreply.github.com>
Date: Fri, 24 Nov 2017 23:00:21 +0100
Subject: [PATCH] Zgateway srfb (#143)
* compatibility with sonoff rf bridge
#81
* update extract_char call
---
OpenMQTTGateway.ino | 58 ++++++++---
User_config.h | 10 +-
ZgatewayBT.ino | 21 +---
ZgatewaySRFB.ino | 236 ++++++++++++++++++++++++++++++++++++++++++++
config_SRFB.h | 62 ++++++++++++
tests/Test_config.h | 2 +
6 files changed, 356 insertions(+), 33 deletions(-)
create mode 100644 ZgatewaySRFB.ino
create mode 100644 config_SRFB.h
diff --git a/OpenMQTTGateway.ino b/OpenMQTTGateway.ino
index 1210dc4c..f5b8a4e6 100644
--- a/OpenMQTTGateway.ino
+++ b/OpenMQTTGateway.ino
@@ -135,7 +135,12 @@ void setup()
{
#ifdef ESP8266
//Launch serial for debugging purposes
- Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY);
+ #ifdef ZgatewaySRFB
+ Serial.begin(SERIAL_BAUD); // in the case of sonoff RF Bridge the link to the RF emitter/receiver is made by serial and need TX/RX
+ #else
+ Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY);
+ #endif
+
//Begining wifi connection in case of ESP8266
setup_wifi();
// Port defaults to 8266
@@ -282,29 +287,28 @@ void loop()
#endif
// Receive loop, if data received by RF433 or IR send it by MQTT
#ifdef ZgatewayRF
- boolean resultRF = RFtoMQTT();
- if(resultRF)
+ if(RFtoMQTT())
trc(F("RFtoMQTT OK"));
#endif
#ifdef ZgatewayRF2
- boolean resultRF2 = RF2toMQTT();
- if(resultRF2)
+ if(RF2toMQTT())
trc(F("RF2toMQTT OK"));
#endif
+ #ifdef ZgatewaySRFB
+ if(SRFBtoMQTT())
+ trc(F("SRFBtoMQTT OK"));
+ #endif
#ifdef ZgatewayIR
- boolean resultIR = IRtoMQTT();
- if(resultIR)
+ if(IRtoMQTT())
trc(F("IRtoMQTT OK"));
delay(100);
#endif
#ifdef ZgatewayBT
- boolean resultBT = BTtoMQTT();
- if(resultBT)
+ if(BTtoMQTT())
trc(F("BTtoMQTT OK"));
#endif
#ifdef ZgatewayRFM69
- boolean resultRFM69 = RFM69toMQTT();
- if(resultRFM69)
+ if(RFM69toMQTT())
trc(F("RFM69toMQTT OK"));
#endif
}
@@ -373,6 +377,9 @@ void receivingMQTT(char * topicOri, char * datacallback) {
#ifdef ZgatewayRF2
MQTTtoRF2(topicOri, datacallback);
#endif
+#ifdef ZgatewaySRFB
+ MQTTtoSRFB(topicOri, datacallback);
+#endif
#ifdef ZgatewayIR
MQTTtoIR(topicOri, datacallback);
#endif
@@ -381,6 +388,35 @@ void receivingMQTT(char * topicOri, char * datacallback) {
#endif
}
+void extract_char(char * token_char, char * subset, int start ,int l, boolean reverse, boolean isNumber){
+ char tmp_subset[l+1];
+ memcpy( tmp_subset, &token_char[start], l );
+ tmp_subset[l] = '\0';
+ if (isNumber){
+ char tmp_subset2[l+1];
+ if (reverse) revert_hex_data(tmp_subset, tmp_subset2, l+1);
+ else strncpy( tmp_subset2, tmp_subset , l+1);
+ long long_value = strtoul(tmp_subset2, NULL, 16);
+ sprintf(tmp_subset2, "%d", long_value);
+ strncpy( subset, tmp_subset2 , l+1);
+ }else{
+ if (reverse) revert_hex_data(tmp_subset, subset, l+1);
+ else strncpy( subset, tmp_subset , l+1);
+ }
+}
+
+void revert_hex_data(char * in, char * out, int l){
+ //reverting array 2 by 2 to get the data in good order
+ int i = l-2 , j = 0;
+ while ( i != -2 ) {
+ if (i%2 == 0) out[j] = in[i+1];
+ else out[j] = in[i-1];
+ j++;
+ i--;
+ }
+ out[l-1] = '\0';
+}
+
//trace
void trc(String msg){
if (TRACE) {
diff --git a/User_config.h b/User_config.h
index 310f0e17..76bcdf37 100644
--- a/User_config.h
+++ b/User_config.h
@@ -29,8 +29,6 @@
along with this program. If not, see .
*/
-/*----------------------------USER PARAMETERS-----------------------------*/
-#define SERIAL_BAUD 115200
/*-------------DEFINE YOUR NETWORK PARAMETERS BELOW----------------*/
//MQTT Parameters definition
#define mqtt_server "192.168.1.17"
@@ -70,6 +68,8 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress
#define ZgatewayRF
#include "config_RF.h"
//#define ZgatewayRF2
+ //#define ZgatewaySRFB
+ //#include "config_SRFB.h"
#define ZgatewayIR
#include "config_IR.h"
#define ZgatewayBT
@@ -117,6 +117,12 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress
#endif
/*----------------------------OTHER PARAMETERS-----------------------------*/
/*-------------------CHANGING THEM IS NOT COMPULSORY-----------------------*/
+/*----------------------------USER PARAMETERS-----------------------------*/
+#ifdef ZgatewaySRFB
+ #define SERIAL_BAUD 19200
+#else
+ #define SERIAL_BAUD 115200
+#endif
/*--------------MQTT general topics-----------------*/
// global MQTT subject listened by the gateway to execute commands (send RF, IR or others)
#define subjectMQTTtoX "home/commands/#"
diff --git a/ZgatewayBT.ino b/ZgatewayBT.ino
index 57d2da9f..b224c732 100644
--- a/ZgatewayBT.ino
+++ b/ZgatewayBT.ino
@@ -83,7 +83,7 @@ boolean BTtoMQTT() {
for(int i =0; i<6;i++)
{
- extract_char(token_char,d[i].extract,d[i].start, d[i].len ,d[i].reverse);
+ extract_char(token_char,d[i].extract,d[i].start, d[i].len ,d[i].reverse, false);
if (i == 3) d[5].len = (int)strtol(d[i].extract, NULL, 16) * 2; // extracting the length of the rest data
}
@@ -162,25 +162,6 @@ boolean process_miflora_data(char * rest_data, char * mac_adress){
return true;
}
-void revert_hex_data(char * in, char * out, int l){
- //reverting array 2 by 2 to get the data in good order
- int i = l-2 , j = 0;
- while ( i != -2 ) {
- if (i%2 == 0) out[j] = in[i+1];
- else out[j] = in[i-1];
- j++;
- i--;
- }
- out[l-1] = '\0';
-}
-
-void extract_char(char * token_char, char * subset, int start ,int l, boolean reverse){
- char tmp_subset[l+1];
- memcpy( tmp_subset, &token_char[start], l );
- tmp_subset[l] = '\0';
- if (reverse) revert_hex_data(tmp_subset, subset, l+1);
- else strncpy( subset, tmp_subset , l+1);
-}
#endif
#ifdef ZgatewayBT_stable
diff --git a/ZgatewaySRFB.ino b/ZgatewaySRFB.ino
new file mode 100644
index 00000000..f8e8ff87
--- /dev/null
+++ b/ZgatewaySRFB.ino
@@ -0,0 +1,236 @@
+/*
+ OpenMQTTGateway - ESP8266 or Arduino program for home automation
+
+ Act as a wifi or ethernet gateway between your 433mhz/infrared IR signal and a MQTT broker
+ Send and receiving command by MQTT
+
+ This gateway enables to:
+ - receive MQTT data from a topic and send RF 433Mhz signal corresponding to the received MQTT data using SONOFF RF BRIDGE
+ - publish MQTT data to a different topic related to received 433Mhz signal using SONOFF RF BRIDGE
+
+ This implementation into OpenMQTTGateway is based on Xose Pérez work ESPURNA (https://bitbucket.org/xoseperez/espurna)
+
+ Copyright (C) 2016-2017 by Xose Pérez
+ OpenMQTTGateway integration by Florian ROBERT
+
+ This file is part of OpenMQTTGateway.
+
+ OpenMQTTGateway is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenMQTTGateway is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef ZgatewaySRFB
+
+unsigned char _uartbuf[RF_MESSAGE_SIZE+3] = {0};
+unsigned char _uartpos = 0;
+
+void MQTTtoSRFB(char * topicOri, char * datacallback) {
+
+ // RF DATA ANALYSIS
+ String topic = topicOri;
+
+ if (topic == subjectMQTTtoSRFB){
+
+ int valueRPT = 0;
+ int valueMiniPLSL = 0;
+ int valueMaxiPLSL = 0;
+ int valueSYNC = 0;
+
+ int pos = topic.lastIndexOf(SRFBRptKey);
+ if (pos != -1){
+ pos = pos + +strlen(SRFBRptKey);
+ valueRPT = (topic.substring(pos,pos + 1)).toInt();
+ trc(F("SRFB Repeat:"));
+ trc(String(valueRPT));
+ }
+
+ int pos2 = topic.lastIndexOf(SRFBminipulselengthKey);
+ if (pos2 != -1) {
+ pos2 = pos2 + strlen(SRFBminipulselengthKey);
+ valueMiniPLSL = (topic.substring(pos2,pos2 + 3)).toInt();
+ trc(F("RF Mini Pulse Lgth:"));
+ trc(String(valueMiniPLSL));
+ }
+
+ int pos3 = topic.lastIndexOf(SRFBmaxipulselengthKey);
+ if (pos3 != -1){
+ pos3 = pos3 + strlen(SRFBmaxipulselengthKey);
+ valueMaxiPLSL = (topic.substring(pos3,pos3 + 2)).toInt();
+ trc(F("RF Maxi Pulse Lgth:"));
+ trc(String(valueMaxiPLSL));
+ }
+
+ int pos4 = topic.lastIndexOf(SRFBsyncKey);
+ if (pos4 != -1){
+ pos4 = pos4 + strlen(SRFBsyncKey);
+ valueSYNC = (topic.substring(pos4,pos4 + 2)).toInt();
+ trc(F("RF sync:"));
+ trc(String(valueSYNC));
+ }
+
+ trc(F("MQTTtoSRFB default prts"));
+ if (valueRPT == 0) valueRPT = 1;
+ if (valueMiniPLSL == 0) valueMiniPLSL = 320;
+ if (valueMaxiPLSL == 0) valueMaxiPLSL = 900;
+ if (valueSYNC == 0) valueSYNC = 9500;
+
+ byte hex_valueMiniPLSL[2];
+ hex_valueMiniPLSL[0] = (int)((valueMiniPLSL >> 8) & 0xFF) ;
+ hex_valueMiniPLSL[1] = (int)(valueMiniPLSL & 0xFF) ;
+
+ byte hex_valueMaxiPLSL[2];
+ hex_valueMaxiPLSL[0] = (int)((valueMaxiPLSL >> 8) & 0xFF) ;
+ hex_valueMaxiPLSL[1] = (int)(valueMaxiPLSL & 0xFF) ;
+
+ byte hex_valueSYNC[2];
+ hex_valueSYNC[0] = (int)((valueSYNC >> 8) & 0xFF) ;
+ hex_valueSYNC[1] = (int)(valueSYNC & 0xFF) ;
+
+ unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295
+ byte hex_data[3];
+ hex_data[0] = (unsigned long)((data >> 16) & 0xFF) ;
+ hex_data[1] = (unsigned long)((data >> 8) & 0xFF) ;
+ hex_data[2] = (unsigned long)(data & 0xFF) ;
+
+ byte message_b[RF_MESSAGE_SIZE];
+
+ memcpy(message_b, hex_valueSYNC, 2);
+ memcpy(message_b + 2, hex_valueMiniPLSL, 2);
+ memcpy(message_b + 4, hex_valueMaxiPLSL, 2);
+ memcpy(message_b + 6, hex_data, 3);
+
+ _rfbSend(message_b, valueRPT);
+ // Acknowledgement to the GTWRF topic
+ boolean result = client.publish(subjectGTWSRFBtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also
+ if (result) trc(F("MQTTtoSRFB ack pub."));
+ }
+}
+
+void _rfbSend(byte * message) {
+ Serial.println();
+ Serial.write(RF_CODE_START);
+ Serial.write(RF_CODE_RFOUT);
+ for (unsigned char j=0; j0) {
+ unsigned long start = millis();
+ while (millis() - start < RF_SEND_DELAY) delay(1);
+ }
+ _rfbSend(message);
+ }
+}
+
+boolean SRFBtoMQTT() {
+
+ static bool receiving = false;
+
+ while (Serial.available()) {
+ yield();
+ byte c = Serial.read();
+
+ if (receiving) {
+ if (c == RF_CODE_STOP) {
+ _rfbDecode();
+ receiving = false;
+ } else {
+ _uartbuf[_uartpos++] = c;
+ }
+ } else if (c == RF_CODE_START) {
+ _uartpos = 0;
+ receiving = true;
+ }
+
+ }
+ return receiving;
+}
+
+void _rfbDecode() {
+
+ static unsigned long last = 0;
+ if (millis() - last < RF_RECEIVE_DELAY) return;
+ last = millis();
+
+ byte action = _uartbuf[0];
+ char buffer[RF_MESSAGE_SIZE * 2 + 1] = {0};
+
+ if (action == RF_CODE_RFIN) {
+ _rfbToChar(&_uartbuf[1], buffer);
+ client.publish(subjectSRFBtoMQTTRaw,buffer);
+
+ char val[7]= {0};
+ extract_char(buffer, val, 12 ,7, false,true);
+ client.publish(subjectSRFBtoMQTT,val);
+
+ char val_Tsyn[4]= {0};
+ extract_char(buffer, val_Tsyn, 0 ,4, false, true);
+ client.publish(subjectSRFBtoMQTTTsyn,val_Tsyn);
+
+ char val_Thigh[4]= {0};
+ extract_char(buffer, val_Thigh, 4 ,4, false, true);
+ client.publish(subjectSRFBtoMQTTThigh,val_Thigh);
+
+ char val_Tlow[4]= {0};
+ extract_char(buffer, val_Tlow, 8 ,4, false, true);
+ client.publish(subjectSRFBtoMQTTTlow,val_Tlow);
+
+ _rfbAck();
+ }
+}
+
+void _rfbAck() {
+ trc("[RFBRIDGE] Sending ACK\n");
+ Serial.println();
+ Serial.write(RF_CODE_START);
+ Serial.write(RF_CODE_ACK);
+ Serial.write(RF_CODE_STOP);
+ Serial.flush();
+ Serial.println();
+}
+
+/*
+From an hexa char array ("A220EE...") to a byte array (half the size)
+ */
+bool _rfbToArray(const char * in, byte * out) {
+ if (strlen(in) != RF_MESSAGE_SIZE * 2) return false;
+ char tmp[3] = {0};
+ for (unsigned char p = 0; p
+
+ This file is part of OpenMQTTGateway.
+
+ OpenMQTTGateway is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenMQTTGateway is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/*-------------------RF topics & parameters----------------------*/
+//433Mhz MQTT Subjects and keys
+#define subjectMQTTtoSRFB "home/commands/MQTTtoSRFB"
+#define subjectMQTTtoSRFBRaw "home/commands/MQTTtoSRFB/Raw"
+#define subjectSRFBtoMQTTTsyn "home/SRFBtoMQTT/Tsyn"
+#define subjectSRFBtoMQTTTlow "home/SRFBtoMQTT/Tlow"
+#define subjectSRFBtoMQTTThigh "home/SRFBtoMQTT/Thigh"
+#define subjectSRFBtoMQTT "home/SRFBtoMQTT"
+#define subjectGTWSRFBtoMQTT "home/SRFBtoMQTT"
+#define subjectSRFBtoMQTTRaw "home/SRFBtoMQTT/Raw"
+#define SRFBRptKey "RPT_"
+#define SRFBmaxipulselengthKey "Thigh_"
+#define SRFBminipulselengthKey "Tlow_"
+#define SRFBsyncKey "Tsyn_"
+// -----------------------------------------------------------------------------
+// RFBRIDGE
+// -----------------------------------------------------------------------------
+
+#define RF_SEND_TIMES 4 // How many times to send the message
+#define RF_SEND_DELAY 500 // Interval between sendings in ms
+#define RF_RECEIVE_DELAY 500 // Interval between recieving in ms (avoid debouncing)
+
+// -----------------------------------------------------------------------------
+// DEFINITIONS
+// -----------------------------------------------------------------------------
+
+#define RF_MESSAGE_SIZE 9
+#define RF_CODE_START 0xAA
+#define RF_CODE_ACK 0xA0
+#define RF_CODE_RFIN 0xA4
+#define RF_CODE_RFOUT 0xA5
+#define RF_CODE_STOP 0x55
+
+
+
diff --git a/tests/Test_config.h b/tests/Test_config.h
index 81208f71..ac1337b1 100644
--- a/tests/Test_config.h
+++ b/tests/Test_config.h
@@ -69,6 +69,8 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress
#ifdef ESP8266 // for nodemcu, weemos and esp8266
#define ZgatewayRF
#include "config_RF.h"
+ #define ZgatewaySRFB
+ #include "config_SRFB.h"
#define ZgatewayRF2
#define ZgatewayIR
#include "config_IR.h"