Some code clean, and buffer overflow prevention (2) (#126)

* Remove trailing whitespaces

* RFM69toMQTT: Add the emitting nodeID to the topic, +

 - And remove radio.receiveDone() that is unecessary.
 - Send the ACK before the publish to MQTT, to be faster
 - Prevent buffer overflow, Terminate the data with a "\0"
   - Fix issue with the sender doesn't end its string with "\0"
     and rely only on DATALEN.

* Change topic subjectGTWRFM69toMQTT to be distinct from the commands

 + comments

* MQTTtoRFM69: deduplicate the code

 - Check once and only once if the topic is good.
 - Have or not RCV_ marked doesn't change the structure, as
   valueRCV is correctly set anyway
 + realign

* MQTTtoRFM69: Limit the size of the data

 - Cut the packet to the limit of what can transmit RFM69
   - and terminate the string

* RFM69toMQTT: ACK MQTT message on subjectGTWRFM69toMQTT now contains the nodeID

* RFM69: Publish to MQTT the RSSI on transmit and ACK
This commit is contained in:
Philippe LUC authored and Florian committed 2017-10-01 15:50:25 +02:00
1 parent d9e2e1d482
commit 254e616f31
2 files changed
+83 -65

No files matched your search

+66 -52
View File
@@ -1,9 +1,9 @@
/* /*
OpenMQTTGateway - ESP8266 or Arduino program for home automation OpenMQTTGateway - ESP8266 or Arduino program for home automation
Act as a wifi or ethernet gateway between your RF/infrared IR signal and a MQTT broker Act as a wifi or ethernet gateway between your RF/infrared IR signal and a MQTT broker
Send and receiving command by MQTT Send and receiving command by MQTT
This gateway enables to: This gateway enables to:
- receive MQTT data from a topic and send RF signal corresponding to the received MQTT data with an RFM69 module - receive MQTT data from a topic and send RF signal corresponding to the received MQTT data with an RFM69 module
- publish MQTT data to a different topic related to received signal from an RFM69 module - publish MQTT data to a different topic related to received signal from an RFM69 module
@@ -12,9 +12,9 @@
Library and code by Felix Rusu - felix@lowpowerlab.com Library and code by Felix Rusu - felix@lowpowerlab.com
Modification of the code nanohab from bbx10 https://github.com/bbx10/nanohab Modification of the code nanohab from bbx10 https://github.com/bbx10/nanohab
Copyright: (c)Florian ROBERT Copyright: (c)Florian ROBERT
This file is part of OpenMQTTGateway. This file is part of OpenMQTTGateway.
OpenMQTTGateway is free software: you can redistribute it and/or modify OpenMQTTGateway is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
@@ -103,7 +103,7 @@ void setupRFM69(void) {
{ {
trc(F("RFM69 initialization failed")); trc(F("RFM69 initialization failed"));
} }
if (GC_IS_RFM69HCW) { if (GC_IS_RFM69HCW) {
radio.setHighPower(); // Only for RFM69HCW & HW! radio.setHighPower(); // Only for RFM69HCW & HW!
} }
@@ -138,32 +138,52 @@ void setupRFM69(void) {
} }
} }
#ifdef subjectRFM69toMQTTrssi
void publishRSSI(int16_t rssi) {
// Send the value of the rssi to MQTT
char buff[sizeof(subjectRFM69toMQTTrssi)+4];
sprintf(buff, "%s/%d", subjectRFM69toMQTTrssi, radio.SENDERID);
char buff_rssi[5];
sprintf(buff_rssi, "%d", radio.RSSI);
boolean result = client.publish(buff, buff_rssi);
}
#else
#define publishRSSI(input)
#endif
boolean RFM69toMQTT(void) { boolean RFM69toMQTT(void) {
//check if something was received (could be an interrupt from the radio) //check if something was received (could be an interrupt from the radio)
if (radio.receiveDone()) if (radio.receiveDone())
{ {
uint8_t data[RF69_MAX_DATA_LEN+1]; // For the null character
uint8_t data[RF69_MAX_DATA_LEN]; uint8_t SENDERID = radio.SENDERID;
uint8_t DATALEN = radio.DATALEN;
uint16_t RSSI = radio.RSSI;
//save packet because it may be overwritten //save packet because it may be overwritten
memcpy(data, (void *)radio.DATA, radio.DATALEN); memcpy(data, (void *)radio.DATA, DATALEN);
client.publish(subjectRFM69toMQTT,(char *)data); data[DATALEN] = '\0'; // Terminate the string
trc(F("Data received"));
trc((const char *)data);
// Ack as soon as possible
//check if sender wanted an ACK //check if sender wanted an ACK
if (radio.ACKRequested()) if (radio.ACKRequested())
{ {
radio.sendACK(); radio.sendACK();
} }
radio.receiveDone(); //put radio in RX mode
//updateClients(senderId, rssi, (const char *)data); //updateClients(senderId, rssi, (const char *)data);
trc(F("Data received"));
trc((const char *)data);
char buff[sizeof(subjectRFM69toMQTT)+4];
sprintf(buff, "%s/%d", subjectRFM69toMQTT, SENDERID);
client.publish(buff,(char *)data);
publishRSSI(RSSI);
return true; return true;
} else { } else {
radio.receiveDone(); //put radio in RX mode
return false; return false;
} }
} }
@@ -172,53 +192,48 @@ boolean MQTTtoRFM69(char * topicOri, char * datacallback) {
int loops; int loops;
uint32_t startMillis; uint32_t startMillis;
static uint32_t deltaMillis = 0; static uint32_t deltaMillis = 0;
// RF DATA ANALYSIS
//We look into the subject to see if a special RF protocol is defined bool good_topic = true;
for (int i=0; i<strlen(subjectMQTTtoRFM69); i++) {
if (topicOri[i] != subjectMQTTtoRFM69[i])
good_topic = false;
}
if (!good_topic) {
Serial.println("Wrong topic");
return false;
}
trc(F("MQTTtoRFM69"));
char data[RF69_MAX_DATA_LEN+1];
memcpy(data, (void *)datacallback, RF69_MAX_DATA_LEN);
data[RF69_MAX_DATA_LEN] = '\0';
//We look into the subject to see if a special RF protocol is defined
String topic = topicOri; String topic = topicOri;
int valueRCV = defaultRFM69ReceiverId; //default receiver id value int valueRCV = defaultRFM69ReceiverId; //default receiver id value
int pos = topic.lastIndexOf(RFM69receiverKey); int pos = topic.lastIndexOf(RFM69receiverKey);
if (pos != -1){ if (pos != -1){
pos = pos + +strlen(RFM69receiverKey); pos = pos + +strlen(RFM69receiverKey);
valueRCV = (topic.substring(pos,pos + 3)).toInt(); valueRCV = (topic.substring(pos,pos + 3)).toInt();
trc(F("RFM69 receiver ID:")); trc(F("RFM69 receiver ID:"));
trc(String(valueRCV)); trc(String(valueRCV));
} }
if ((topic == subjectMQTTtoRFM69) && (valueRCV == defaultRFM69ReceiverId)){
trc(F("MQTTtoRFM69 default"));
loops = 10; loops = 10;
startMillis = millis(); startMillis = millis();
while (loops--) { while (loops--) {
if(radio.sendWithRetry(valueRCV, datacallback, strlen(datacallback)+1)) { if(radio.sendWithRetry(valueRCV, data, strlen(data))) {
deltaMillis = millis() - startMillis; deltaMillis = millis() - startMillis;
Serial.print(" OK "); Serial.print(" OK ");
Serial.println(deltaMillis); Serial.println(deltaMillis);
// Acknowledgement to the GTWRF topic // Acknowledgement to the GTWRF topic
boolean result = client.publish(subjectGTWRFM69toMQTT, datacallback); char buff[sizeof(subjectGTWRFM69toMQTT)+4];
if (result)trc(F("Ack published")); sprintf(buff, "%s/%d", subjectGTWRFM69toMQTT, radio.SENDERID);
return true; boolean result = client.publish(buff, data);
} if (result)trc(F("Ack published"));
else {
Serial.print("!"); publishRSSI(radio.RSSI);
}
delay(50);
}
if (loops <= 0) {
deltaMillis = 0;
trc(F("RFM69 sending failed"));
return false;
}
} else if (valueRCV != defaultRFM69ReceiverId) {
trc(F("MQTTtoRFM69 user parameters"));
loops = 10;
startMillis = millis();
while (loops--) {
if(radio.sendWithRetry(valueRCV, datacallback, strlen(datacallback)+1)) {
deltaMillis = millis() - startMillis;
Serial.print(" OK ");
Serial.println(deltaMillis);
// Acknowledgement to the GTWRF topic
boolean result = client.publish(subjectGTWRFM69toMQTT, datacallback);
if (result)trc(F("Ack published"));
return true; return true;
} }
else { else {
@@ -228,9 +243,8 @@ if ((topic == subjectMQTTtoRFM69) && (valueRCV == defaultRFM69ReceiverId)){
} }
if (loops <= 0) { if (loops <= 0) {
deltaMillis = 0; deltaMillis = 0;
trc(F("RFM69 sending failed")); trc(F("RFM69 sending failed"));
return false; return false;
} }
}
} }
#endif #endif
+17 -13
View File
@@ -1,15 +1,15 @@
/* /*
OpenMQTTGateway - ESP8266 or Arduino program for home automation 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 Act as a wifi or ethernet gateway between your 433mhz/infrared IR signal and a MQTT broker
Send and receiving command by MQTT Send and receiving command by MQTT
This files enables to set your parameter for the radiofrequency gateways (ZgatewayRF and ZgatewayRF2) with RCswitch and newremoteswitch library This files enables to set your parameter for the radiofrequency gateways (ZgatewayRF and ZgatewayRF2) with RCswitch and newremoteswitch library
Copyright: (c)Florian ROBERT Copyright: (c)Florian ROBERT
This file is part of OpenMQTTGateway. This file is part of OpenMQTTGateway.
OpenMQTTGateway is free software: you can redistribute it and/or modify OpenMQTTGateway is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
@@ -25,12 +25,18 @@
*/ */
/*----------------------RFM69 topics & parameters -------------------------*/ /*----------------------RFM69 topics & parameters -------------------------*/
// Topic where the message from RFM69 will be published by the gateway,
// appended with the nodeID of the sender
#define subjectRFM69toMQTT "home/RFM69toMQTT" #define subjectRFM69toMQTT "home/RFM69toMQTT"
#define subjectRFM69toMQTTrssi "home/RFM69toMQTT/rssi" // Upon reception of a packed, the RSSI of that packet will be publish to this topic,
// appended with the nodeID of the sender
#define subjectRFM69toMQTTrssi "home/RFM69toMQTT/rssi" // Comment this if you don't want the RSSI to be published.
#define subjectRFM69toMQTTsender "home/RFM69toMQTT/sender" #define subjectRFM69toMQTTsender "home/RFM69toMQTT/sender"
// Topic subscribed by the gateway. Messages received will be sent to RFM69
#define subjectMQTTtoRFM69 "home/commands/MQTTtoRFM69" #define subjectMQTTtoRFM69 "home/commands/MQTTtoRFM69"
#define RFM69receiverKey "RCV_" // receiver id will be defined if a subject contains RFM69receiverKey followed by a value of 3 digits #define RFM69receiverKey "RCV_" // receiver id will be defined if a subject contains RFM69receiverKey followed by a value of 3 digits
#define subjectGTWRFM69toMQTT "home/RFM69toMQTT" // On reception of an ack from RFM69, the message that has been sent is published here
#define subjectGTWRFM69toMQTT "home/RFM69toMQTT/acked"
#define defaultRFM69ReceiverId 99 #define defaultRFM69ReceiverId 99
// Default values // Default values
@@ -48,9 +54,9 @@ const char PROGMEM RFM69AP_NAME[] = "RFM69-AP";
#define IS_RFM69HCW true // set to 'true' if you are using an RFM69HCW module #define IS_RFM69HCW true // set to 'true' if you are using an RFM69HCW module
#define POWER_LEVEL 31 #define POWER_LEVEL 31
/*-------------------PIN DEFINITIONS----------------------*/ /*-------------------PIN DEFINITIONS----------------------*/
#ifdef ESP8266 #ifdef ESP8266
#define RFM69_CS D1 #define RFM69_CS D1
#define RFM69_IRQ D8 // GPIO15/D8 #define RFM69_IRQ D8 // GPIO15/D8
#define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ) #define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ)
#define RFM69_RST D4 // GPIO02/D4 #define RFM69_RST D4 // GPIO02/D4
@@ -61,5 +67,3 @@ const char PROGMEM RFM69AP_NAME[] = "RFM69-AP";
#define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ) #define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ)
#define RFM69_RST 9 #define RFM69_RST 9
#endif #endif