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
This gateway enables to:
- 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
@@ -12,9 +12,9 @@
Library and code by Felix Rusu - felix@lowpowerlab.com
Modification of the code nanohab from bbx10 https://github.com/bbx10/nanohab
Copyright: (c)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
@@ -103,7 +103,7 @@ void setupRFM69(void) {
{
trc(F("RFM69 initialization failed"));
}
if (GC_IS_RFM69HCW) {
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) {
//check if something was received (could be an interrupt from the radio)
if (radio.receiveDone())
{
uint8_t data[RF69_MAX_DATA_LEN];
uint8_t data[RF69_MAX_DATA_LEN+1]; // For the null character
uint8_t SENDERID = radio.SENDERID;
uint8_t DATALEN = radio.DATALEN;
uint16_t RSSI = radio.RSSI;
//save packet because it may be overwritten
memcpy(data, (void *)radio.DATA, radio.DATALEN);
client.publish(subjectRFM69toMQTT,(char *)data);
trc(F("Data received"));
trc((const char *)data);
memcpy(data, (void *)radio.DATA, DATALEN);
data[DATALEN] = '\0'; // Terminate the string
// Ack as soon as possible
//check if sender wanted an ACK
if (radio.ACKRequested())
{
radio.sendACK();
}
radio.receiveDone(); //put radio in RX mode
//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;
} else {
radio.receiveDone(); //put radio in RX mode
return false;
}
}
@@ -172,53 +192,48 @@ boolean MQTTtoRFM69(char * topicOri, char * datacallback) {
int loops;
uint32_t startMillis;
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;
int valueRCV = defaultRFM69ReceiverId; //default receiver id value
int pos = topic.lastIndexOf(RFM69receiverKey);
int pos = topic.lastIndexOf(RFM69receiverKey);
if (pos != -1){
pos = pos + +strlen(RFM69receiverKey);
valueRCV = (topic.substring(pos,pos + 3)).toInt();
trc(F("RFM69 receiver ID:"));
trc(String(valueRCV));
}
if ((topic == subjectMQTTtoRFM69) && (valueRCV == defaultRFM69ReceiverId)){
trc(F("MQTTtoRFM69 default"));
loops = 10;
startMillis = millis();
while (loops--) {
if(radio.sendWithRetry(valueRCV, datacallback, strlen(datacallback)+1)) {
if(radio.sendWithRetry(valueRCV, data, strlen(data))) {
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;
}
else {
Serial.print("!");
}
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"));
char buff[sizeof(subjectGTWRFM69toMQTT)+4];
sprintf(buff, "%s/%d", subjectGTWRFM69toMQTT, radio.SENDERID);
boolean result = client.publish(buff, data);
if (result)trc(F("Ack published"));
publishRSSI(radio.RSSI);
return true;
}
else {
@@ -228,9 +243,8 @@ if ((topic == subjectMQTTtoRFM69) && (valueRCV == defaultRFM69ReceiverId)){
}
if (loops <= 0) {
deltaMillis = 0;
trc(F("RFM69 sending failed"));
return false;
trc(F("RFM69 sending failed"));
return false;
}
}
}
#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
This files enables to set your parameter for the radiofrequency gateways (ZgatewayRF and ZgatewayRF2) with RCswitch and newremoteswitch library
Copyright: (c)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
@@ -25,12 +25,18 @@
*/
/*----------------------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 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"
// Topic subscribed by the gateway. Messages received will be sent to RFM69
#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 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
// 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 POWER_LEVEL 31
/*-------------------PIN DEFINITIONS----------------------*/
/*-------------------PIN DEFINITIONS----------------------*/
#ifdef ESP8266
#define RFM69_CS D1
#define RFM69_CS D1
#define RFM69_IRQ D8 // GPIO15/D8
#define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ)
#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_RST 9
#endif