├── RFLink_to_MQTT └── RFLink_to_MQTT.ino ├── readme.md └── rfmqtt.yaml /RFLink_to_MQTT/RFLink_to_MQTT.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Link between the RF reciever/transmitter project based on an arduino mega, RFLink and MQTT 3 | Link to RFLink: http://www.nemcon.nl/blog2/download 4 | This includes wiring and device compatability for RFLink. 5 | This is used as per the RFLink instructions except that 6 | an ESP8266 is used for the serial communication instead of a computer via USB 7 | 8 | 9 | RFLink is designed to be used by a computer using USB 10 | This bridge uses and ESP8266 as the interface, which then encodes the recieved RF data and publishes it as JSON to an MQTT server 11 | 12 | RF433 data is recieved by the RFLink and passed on to the ESP8266 13 | The ESP8266 packages it up into a JSON statement and publishes it ot the MQTT broker 14 | format on the MQTT broker is: (Recieved RF codes) 15 | 16 | Topic: RF/name_of_device-ID_of_device - this tries to have a unique topic per name/id combo. 17 | Note - the name and ID are as determined by the RFLink program - it may not be the label printed on the device sending data! 18 | 19 | Payload example: {"raw":"20;B3;DKW2012;ID=004c;TEMP=00eb;HUM=3f;WINSP=0000;WINGS=0000;RAIN=0003;WINDIR=0008;\r","TEMP":23.50,"HUM":3,"WINSP":"0000","WINGS":"0000","RAIN":3,"WINDIR":8} 20 | see RFLink documentation for more details: http://www.nemcon.nl/blog2/protref 21 | 22 | Sending commands to the RFLink example: (how to send codes to the RFLink) 23 | Topic: RF/command 24 | Payload: 10;Eurodomest;02d0f2;06;ALLON\n 25 | Note that the \n on the end is critical at the moment. Otherwise the ESP will either crash or the RFLink will ignore 26 | 27 | 28 | 29 | I inculde the raw data in full for debugging, then the split out components form RFink 30 | There is some conversions made to make the data more useable: 31 | Temp is converted to a float from hex 32 | Wind direction is converted to a compass heading 33 | etc - details in the parseData function below 34 | 35 | 36 | Requirements: 37 | Arduino mega 2560 and RF reciever and or transmitter (see RFLink for recommended devices and wiring) 38 | ESP8266 device (I have used a node MCU V1.0) 39 | Arduino libraries: SoftwareSerial.h and ArduinoJson.h 40 | an MQTT broker runnning. Tested with Mosquitto on a raspberry Pi 2 41 | 42 | Optional: 43 | Somethig to read and react to the MQTT measurements 44 | I am using Home Assistant, also running on the same Pi : https://home-assistant.io/ 45 | 46 | 47 | Setup: 48 | 1) Confirm RFLink working on its own through your USB port - then you know you are getting data recieved etc 49 | Collect some data form your RF433 devices on the system monitor screen and save them for step 2 50 | 51 | 2) Set sketch to be in test mode (testmode = true). 52 | Load this firmware onto the ESP8266 and run in test mode (so it listens to the PC over USB, not the RFLink) 53 | Input some data as recieved in step 1. Check that the ESP connects to your system and publishes topics as expected 54 | 55 | 3) Load updated firmware - setting testmode to false (see section for user inputs below) 56 | Wire the ESP to the RFLink ESP d5 & d6 to Mega 0 & 1. 57 | Check your mqtt broker for recieved data being published. 58 | 59 | 4) Setup your home automation to react to the published data and pubish commands to the RFLink 60 | 61 | To Do: 62 | 1) ESP will sometimes crash with unexpected output from RFLink. 63 | I think it is when you get messages starting with 20 but not with as as many semicolon delimited fields as expected. 64 | Currently, I ensure that the Mega (RFLink) is up before restarting the ESP. 65 | 66 | 2) Tidy up the callback behaviour for sending data to the RFLink - data is fickle and if you do not terminate with \n it will crash the ESP 67 | 68 | 69 | Phil Wilson December 2016 70 | 71 | */ 72 | #include 73 | 74 | // Key User Configuration here: 75 | SoftwareSerial swSer(14, 12, false, 256); // d5 & d6 on the nodu MC v1.0 76 | 77 | const char* ssid = "SSID"; // network SSID for ESP8266 to connect to 78 | const char* password = "Password"; // password for the network above 79 | const char* mqtt_server = "10.1.1.235"; // address of the MQTT server that we will communicte with 80 | char* client_name = "espRF"; // production version client name for MQTT login - must be unique on your system 81 | 82 | // some testing switches 83 | boolean testmode = false; // if true, then do not listen to softwareserial but normal serial for input 84 | boolean enableMQTT = true; // if false, do not transmit MQTT codes - for testing really 85 | 86 | 87 | 88 | // ****************************************************************** 89 | 90 | 91 | 92 | // ArduinoJson credits - used for building JSON to post to MQTT 93 | 94 | // Copyright Benoit Blanchon 2014-2016 95 | // MIT License 96 | // 97 | // Arduino JSON library 98 | // https://github.com/bblanchon/ArduinoJson 99 | #include 100 | 101 | 102 | 103 | const byte numChars = 128; 104 | char receivedChars[numChars]; 105 | char tempChars[numChars]; // temporary array for use when parsing 106 | 107 | // variables to hold the parsed data 108 | 109 | char messageFromPC[numChars] = {0}; 110 | char RFName[30]; // name of protocol from RFLINK 111 | char RFID[30]; //ID from RFLINK ie ID=XXXX; 112 | char RFData[numChars]; //the rest from RFLINK - will include one or many pieces of data 113 | char RFDataTemp[numChars]; //temporary area for processing RFData - when we look for temp and convert etc 114 | String MQTTTopic = "RF/"; 115 | const char* willTopic = "RF/status"; 116 | boolean willRetain = true; 117 | const char* willMessage = "offline" ; 118 | 119 | const char* commandTopic = "RF/command"; // command topic ESP will subscribe to and pass as commands to the RFLink 120 | 121 | const float TempMax = 50.0; // max temp - if we get a value greater than this, ignore it as an assumed error 122 | const int HumMax = 101; // max hum - if we get a value greater than this, ignore it as an assumed error 123 | 124 | 125 | //============ 126 | #include 127 | #include 128 | #include 129 | #include 130 | // if having problems with larger payloads, increase #define MQTT_MAX_PACKET_SIZE 128 in PubSubClient.h to a larger value before compiling 131 | // to allow larger payloads - needed if you have a weather station (because I also include raw data in the json payload in case you need it for deugging) 132 | #include 133 | 134 | 135 | WiFiClient espClient; 136 | PubSubClient client(espClient); 137 | 138 | boolean newData = false; 139 | String switch1; 140 | String strTopic; 141 | char* strPayload =""; 142 | String strOutputt = ""; 143 | String strOutputth = ""; 144 | 145 | // array of wind directions - used by weather stations. output from the RFLink under WINDIR is an integr 0-15 - will lookup the array for the compass text version 146 | String CompassDirTable[17] = {"N","NNE","NE","ENE","E","ESE", "SE","SSE","S","SSW","SW","WSW", "W","WNW","NW","NNW","N"}; 147 | 148 | void setup_wifi() { 149 | 150 | delay(10); 151 | // We start by connecting to a WiFi network 152 | Serial.println(); 153 | Serial.print("Connecting to "); 154 | Serial.println(ssid); 155 | 156 | WiFi.begin(ssid, password); 157 | 158 | while (WiFi.status() != WL_CONNECTED) 159 | { 160 | delay(500); 161 | Serial.print("."); 162 | } 163 | 164 | Serial.println(""); 165 | Serial.println("WiFi connected"); 166 | Serial.println("IP address: "); 167 | Serial.println(WiFi.localIP()); 168 | } 169 | 170 | void callback(char* topic, byte* payload, unsigned int length) { 171 | payload[length] = '\0'; // terminate payload 172 | strPayload = ((char*)payload); 173 | char* strPayloadTrimmed = strPayload + 1; // strip off first character as it is a double quote 174 | String strPayloadTrimmed2 = strPayload + 1; 175 | 176 | Serial.println("Command coming in!: "); // got someting 177 | // strPayload += "\n"; 178 | Serial.println(strPayload); // got someting 179 | swSer.print(strPayload); // snd data to the RFLink 180 | 181 | if(strncmp(strPayloadTrimmed,"10",2) == 0) // starts with 10 182 | { 183 | Serial.println("got a command - test result: "); 184 | // Serial.println(strPayload); 185 | // Serial.println(strtok(strPayload,34)); 186 | // Serial.println(sizeof(strPayload)); 187 | // Serial.println(strPayloadTrimmed2.length()); 188 | 189 | strPayloadTrimmed2.remove(strPayloadTrimmed2.length()-1,1); 190 | 191 | // Serial.println(strPayloadTrimmed[strPayloadTrimmed2.length()]); 192 | Serial.println(strPayloadTrimmed2); 193 | 194 | // swSer.print(strPayload); // snd data to the RFLink 195 | } 196 | 197 | } 198 | 199 | 200 | void reconnect() { 201 | // Loop until we're reconnected 202 | while (!client.connected()) { 203 | Serial.print("Attempting MQTT connection..."); 204 | // Attempt to connect 205 | if (client.connect(client_name, willTopic, 0, willRetain, willMessage)) { 206 | Serial.println("connected"); 207 | // Once connected, update status to online - will Message will drop in if we go offline ... 208 | client.publish(willTopic,"online",true); 209 | 210 | client.subscribe(commandTopic);// subscribe to the command topic - will listen here for comands to the RFLink 211 | 212 | } else { 213 | Serial.print("failed, rc="); 214 | Serial.print(client.state()); 215 | Serial.println(" try again in 5 seconds"); 216 | // Wait 5 seconds before retrying 217 | delay(5000); 218 | } 219 | } 220 | } 221 | 222 | void setup() { 223 | if (testmode){client_name = "espRFTest3";} // in test mode - change client name to be different from production 224 | // JSON parsing library setup 225 | DynamicJsonBuffer jsonBuffer; 226 | 227 | // Create the root of the object tree. 228 | // 229 | // It's a reference to the JsonObject, the actual bytes are inside the 230 | // JsonBuffer with all the other nodes of the object tree. 231 | // Memory is freed when jsonBuffer goes out of scope. 232 | JsonObject& root = jsonBuffer.createObject(); 233 | 234 | Serial.begin(57600); 235 | swSer.begin(57600); // this is the baud rate of the RF LINK 236 | // expected format examples: - will treat as 5 components (Packet Count ignored). 237 | // 20;02;Imagintronix;ID=0001;TEMP=00dc;HUM=88; 238 | // 20;0D;UPM_Esic;ID=0001;TEMP=00df;HUM=67;BAT=OK; 239 | 240 | // Node [nn]: 20 - means message from system - proceed if prefix is 20. Other values are 10 fofr sent message and 11 for recursive 241 | // Packet Count [hh]: next is packet count - ignore (2 digit hexdecimal) 242 | // Name [text]: Name of the protocol used 243 | // ID [ID=text]: ID - proceed if ID indentified. If not there, is not a recieved code, just a message from system 244 | // Data [text]: remainder is data from the sensor - concateate & send as a JSON data block 245 | 246 | setup_wifi(); 247 | client.setServer(mqtt_server, 1883); 248 | client.setCallback(callback); 249 | 250 | Serial.println("\nRFLINK serial listener started"); 251 | Serial.println("Example data 20;0D;UPM_Esic;ID=test;TEMP=00df;HUM=67;BAT=OK;"); 252 | Serial.println("Example data 20;B3;DKW2012;ID=test;TEMP=00eb;HUM=3f;WINSP=008c;WINGS=00cd;RAIN=0003;WINDIR=0008;"); 253 | Serial.println(); 254 | 255 | // Hostname defaults to esp8266-[ChipID] 256 | ArduinoOTA.setHostname(client_name); 257 | 258 | // No authentication by default 259 | // ArduinoOTA.setPassword((const char *)"123"); 260 | 261 | ArduinoOTA.onStart([]() { 262 | Serial.println("OTA Start"); 263 | }); 264 | ArduinoOTA.onEnd([]() { 265 | Serial.println("\nEnd"); 266 | }); 267 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 268 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 269 | }); 270 | ArduinoOTA.onError([](ota_error_t error) { 271 | Serial.printf("Error[%u]: ", error); 272 | if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); 273 | else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); 274 | else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); 275 | else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); 276 | else if (error == OTA_END_ERROR) Serial.println("End Failed"); 277 | }); 278 | ArduinoOTA.begin(); 279 | Serial.println("oTA Ready"); 280 | Serial.print("IP address: "); 281 | Serial.println(WiFi.localIP()); 282 | // end OTA stuff in setup 283 | } 284 | 285 | 286 | 287 | 288 | //============ 289 | 290 | void recvWithStartEndMarkers() { 291 | static byte ndx = 0; 292 | char endMarker = '\n'; 293 | char rc; 294 | 295 | if (testmode == false) { // we are in live mode and will parse from swSer rather than serial 296 | 297 | 298 | while (swSer.available() > 0 && newData == false) { 299 | rc = swSer.read(); 300 | 301 | if (rc != endMarker) { 302 | receivedChars[ndx] = rc; 303 | ndx++; 304 | if (ndx >= numChars) { 305 | ndx = numChars - 1; 306 | } 307 | } 308 | else { 309 | receivedChars[ndx] = '\0'; // terminate the string 310 | ndx = 0; 311 | newData = true; 312 | } 313 | 314 | 315 | } 316 | } else { // test use - read from serial as though it was from swSer 317 | 318 | 319 | // 320 | while (Serial.available() > 0 && newData == false) { 321 | rc = Serial.read(); 322 | 323 | if (rc != endMarker) { 324 | receivedChars[ndx] = rc; 325 | ndx++; 326 | if (ndx >= numChars) { 327 | ndx = numChars - 1; 328 | } 329 | } 330 | else { 331 | receivedChars[ndx] = '\0'; // terminate the string 332 | ndx = 0; 333 | newData = true; 334 | } 335 | } 336 | 337 | 338 | } 339 | // 340 | 341 | } 342 | 343 | //============ 344 | 345 | float hextofloat(char* hexchars) {return float(strtol(hexchars,NULL,16));} 346 | int hextoint(char* hexchars) {return strtol(hexchars,NULL,16);} 347 | 348 | void parseData() { // split the data into its parts 349 | DynamicJsonBuffer jsonBuffer; 350 | JsonObject& root = jsonBuffer.createObject(); 351 | 352 | char * strtokIndx; // this is used by strtok() as an index 353 | char * strtokIndx2; // this is used by strtok() as an index 354 | float tmpfloat = 0.0; // temporary float used in tests 355 | int tmpint = 0; // temporary int used in tests 356 | 357 | strtokIndx = strtok(tempChars,";"); // get the first part - the string 358 | strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC 359 | if (strcmp(messageFromPC,"20") == 0 ) { // 20 means a message recieved from RFLINK - this is what we are interested in breaking up for use 360 | 361 | strtokIndx = strtok(NULL, ";" ); // this continues where the previous call left off - which we will ignore as it is the packet count 362 | strtokIndx = strtok(NULL, ";" ); // this should be the name 363 | strcpy( RFName , strtokIndx ); // copy name to RFName 364 | 365 | strtokIndx = strtok(NULL, ";"); 366 | strcpy( RFID , strtokIndx); // copy next block to RFID 367 | 368 | strtokIndx = strtok(NULL, "\n"); // search for the rest of the buffer input ending in \n 369 | strcpy(RFData , strtokIndx ); // copy remainder of block to RFData 370 | // now find if we have TEMP= in RFData and convert from hex to int 371 | strcpy(RFDataTemp , RFData ); // temp copy of RFData so we can search for temp and convert from hex to decimal 372 | 373 | // Read each command pair 374 | char* command = strtok(RFDataTemp, ";"); 375 | root["raw"] = receivedChars; // copy the raw data to the json in case we need to debug 376 | while (command != 0 and strlen(command)>4 ) 377 | { 378 | // Split the command in two values 379 | char* separator = strchr(command, '='); 380 | if (separator != 0) 381 | { 382 | // Actually split the string in 2: replace '=' with 0 383 | *separator = 0; 384 | String NamePart = command; 385 | ++separator; 386 | if (NamePart == "TEMP") { // test if it is TEMP, which is HEX 387 | tmpfloat = hextofloat(separator)*0.10; //convert from hex to float and divide by 10 - using multiply as it is faster than divide 388 | if (tmpfloat < TempMax) //test if we are inside the maximum test point - if not, assume spurious data 389 | {root.set( NamePart ,tmpfloat ); // passed spurious test - add data to root 390 | } } /// end of TEMP block 391 | else if (NamePart == "HUM") { // test if it is HUM, which is int 392 | if (strcmp(RFName,"DKW2012") == 0 ) { // digitech weather station - assume it is a hex humidity, not straight int 393 | tmpint = hextoint(separator);} 394 | else { 395 | tmpint = atoi(separator);} // end of setting tmpint to the value we want to use & test 396 | if (tmpint > 0 and tmpint < HumMax) //test if we are inside the maximum test point - if not, assume spurious data 397 | {root.set( NamePart ,tmpint); } // passed the test - add the data to rot, otherwise it will not be added as spurious 398 | } // end of HUM block 399 | else if (NamePart == "RAIN") // test if it is RAIN, which is HEX 400 | {root.set( NamePart ,hextofloat(separator)*0.10 );} // - add data to root 401 | else if (NamePart == "WINSP") // test if it is WINSP, which is HEX 402 | {root.set( NamePart ,hextofloat(separator)*0.10 );} // - add data to root 403 | else if (NamePart == "WINGS") // test if it is WINGS, which is HEX 404 | {root.set( NamePart ,hextofloat(separator)*0.10 );} // - add data to root 405 | else if (NamePart == "WINDIR") // test if it is WINDIR, which is 0-15 representing the wind angle / 22.5 - convert to compas text 406 | {root[NamePart] = CompassDirTable[atoi(separator)] ;} 407 | else // check if an int, add as int, else add as text 408 | if (atoi(separator) == 0) // not an integer 409 | {root[NamePart] = separator ;} // do normal string add 410 | else 411 | {root.set( NamePart , atoi(separator) ); }// do int add 412 | } 413 | 414 | 415 | // Find the next command in input string 416 | command = strtok(NULL, ";"); 417 | } 418 | 419 | // 420 | // strtokIndx2 = strtok(RFDataTemp,";"); // get the first part - the string 421 | } 422 | /* Serial.print("MQTT Topic: RF/"); 423 | Serial.print(RFName); 424 | Serial.print("-"); 425 | Serial.print(RFID); 426 | Serial.println("/"); 427 | root.printTo(Serial); 428 | Serial.println(); 429 | */ 430 | else { // not a 20 code- something else 431 | Serial.println("doing the else - not a 20 code "); 432 | strcpy(RFData , strtokIndx ); // copy all of it to RFData 433 | strcpy( RFName , "unknown" ); 434 | strcpy( RFID , ""); 435 | } 436 | // client.publish("RF/" + RFName + "-" + RFID , root ); 437 | // build the topic ("RF/" + RFName + "-" + RFID ); 438 | 439 | MQTTTopic = "RF/" ; 440 | MQTTTopic += String(RFName); 441 | MQTTTopic += "-" ; 442 | MQTTTopic += String(RFID) ; 443 | size_t lenM = MQTTTopic.length(); // returns length of the json 444 | size_t sizeM = lenM + 1; 445 | 446 | char MQTTTopicConst[lenM]; 447 | MQTTTopic.toCharArray(MQTTTopicConst,sizeM) ; 448 | 449 | // place the json data into variable 'json' for publishing over MQTT 450 | size_t len = root.measureLength(); // returns length of the json 451 | size_t size = len+1; 452 | char json[size]; 453 | root.printTo(json,size); 454 | 455 | Serial.print(MQTTTopicConst); 456 | Serial.print(" "); 457 | Serial.println(json); 458 | client.publish(MQTTTopicConst , json ); 459 | 460 | } 461 | 462 | //============ 463 | 464 | void showParsedData() { 465 | Serial.print("Got something : "); 466 | Serial.println(receivedChars); 467 | // mqtt structure 468 | /* 469 | Serial.print("MQTT: /RF/"); 470 | Serial.print(RFName); 471 | Serial.print("-"); 472 | Serial.print(RFID); 473 | Serial.println("/"); 474 | Serial.print("{"); 475 | Serial.print(RFData); 476 | Serial.println("} @@"); 477 | */ 478 | 479 | } 480 | 481 | 482 | //============ 483 | 484 | void loop() { 485 | recvWithStartEndMarkers(); 486 | if (newData == true) { 487 | strcpy(tempChars, receivedChars); 488 | // this temporary copy is necessary to protect the original data 489 | // because strtok() used in parseData() replaces the commas with \0 490 | parseData(); 491 | //showParsedData(); 492 | newData = false; 493 | } 494 | if (!client.connected() and enableMQTT ) { 495 | reconnect(); 496 | } 497 | client.loop(); 498 | 499 | // listen for OTA reprogramming 500 | ArduinoOTA.handle(); 501 | } 502 | 503 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Link between the RF reciever/transmitter project based on an arduino mega, RFLink and MQTT 2 | Link to RFLink: http://www.nemcon.nl/blog2/download 3 | This includes wiring and device compatability for RFLink. 4 | This is used as per the RFLink instructions except that 5 | an ESP8266 is used for the serial communication instead of a computer via USB 6 | 7 | 8 | RFLink is designed to be used by a computer using USB 9 | This bridge uses and ESP8266 as the interface, which then encodes the recieved RF data and publishes it as JSON to an MQTT server 10 | 11 | RF433 data is recieved by the RFLink and passed on to the ESP8266 12 | The ESP8266 packages it up into a JSON statement and publishes it ot the MQTT broker 13 | format on the MQTT broker is: (Recieved RF codes) 14 | 15 | Topic: RF/name_of_device-ID_of_device - this tries to have a unique topic per name/id combo. 16 | Note - the name and ID are as determined by the RFLink program - it may not be the label printed on the device sending data! 17 | 18 | Payload example: {"raw":"20;B3;DKW2012;ID=004c;TEMP=00eb;HUM=3f;WINSP=0000;WINGS=0000;RAIN=0003;WINDIR=0009;\r","TEMP":23.50,"HUM":3,"WINSP":"0000","WINGS":"0000","RAIN":3,"WINDIR":"SSW"} 19 | see RFLink documentation for more details: http://www.nemcon.nl/blog2/protref 20 | 21 | Sending commands to the RFLink example: (how to send codes to the RFLink) 22 | 23 | Topic: RF/command 24 | 25 | Payload: 10;Eurodomest;02d0f2;06;ALLON\n 26 | Note that the \n on the end is critical at the moment. Otherwise the ESP will either crash or the RFLink will ignore 27 | 28 | 29 | 30 | I included the raw data in full for debugging, then the split out components from RFink 31 | There is some conversions made to make the data more useable: 32 | Temp is converted to a float from hex 33 | Wind direction is converted to a compass heading 34 | etc - details in the parseData function in the .ino file 35 | 36 | 37 | Requirements: 38 | Arduino mega 2560 and RF reciever and or transmitter (see RFLink for recommended devices and wiring) 39 | ESP8266 device (I have used a node MCU V1.0) 40 | an MQTT broker runnning. Tested with Mosquitto on a raspberry Pi 2 41 | 42 | Optional: 43 | Somethig to read and react to the MQTT measurements 44 | I am using Home Assistant, also running on the same Pi : https://home-assistant.io/ 45 | 46 | Note: If you want to use a username and password for your mqtt broker, Change line 205 in the RFLink_to_MQTT.ino to include username and password as per the PubSubClient API. see https://pubsubclient.knolleary.net/api.html#connect4 47 | 48 | Setup: 49 | 1) Confirm RFLink working on its own through your USB port - then you know you are getting data recieved etc 50 | Collect some data from your RF433 devices on the system monitor screen and save them for step 2 51 | 52 | 2) Set sketch to be in test mode (testmode = true). 53 | Load this firmware onto the ESP8266 and run in test mode (so it listens to the PC over USB, not the RFLink) 54 | Input some data as recieved in step 1. Check that the ESP connects to your system and publishes topics as expected 55 | 56 | 3) Load updated firmware - setting testmode to false (see section for user inputs below) 57 | Wire the ESP to the RFLink ESP d5 & d6 to Mega 0 & 1. 58 | Check your mqtt broker for recieved data being published. 59 | 60 | 4) Setup your home automation to react to the published data and pubish commands to the RFLink 61 | 62 | To Do: 63 | 1) ESP will sometimes crash with unexpected output from RFLink. 64 | I think it is when you get messages starting with 20 but not with as as many semicolon delimited fields as expected. 65 | Currently, I ensure that the Mega (RFLink) is up before restarting the ESP. 66 | 67 | 2) Tidy up the callback behaviour for sending data to the RFLink - data is fickle and if you do not terminate with \n it will crash the ESP 68 | 69 | 70 | Phil Wilson December 2016 71 | -------------------------------------------------------------------------------- /rfmqtt.yaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | binary_sensor: 6 | # status of the bridge - so we can tell if it is online or not via its will 7 | - platform: mqtt 8 | state_topic: "RF/status" 9 | name: "RF Bridge Status" 10 | qos: 0 11 | payload_on: "online" 12 | payload_off: "offline" 13 | sensor_class: connectivity 14 | 15 | # generic RF433 PIR sensors. These only tell me an "on" status. Change them to off with an automation 16 | - platform: mqtt 17 | name: "PIR1" 18 | sensor_class: motion 19 | state_topic: "RF/Chuango-ID=2aaaaa" 20 | qos: 0 21 | payload_on: "ON" 22 | payload_off: "OFF" 23 | value_template: '{{ value_json.CMD }}' 24 | 25 | sensor: 26 | # ninja blocks WT450 temp / humidity sensor #1 27 | - platform: mqtt 28 | state_topic: 'RF/UPM_Esic-ID=0001' 29 | name: 'Temperature' 30 | unit_of_measurement: '°C' 31 | value_template: '{{ value_json.TEMP }}' 32 | - platform: mqtt 33 | state_topic: 'RF/UPM_Esic-ID=0001' 34 | name: 'Humidity' 35 | unit_of_measurement: '%' 36 | value_template: '{{ value_json.HUM }}' 37 | 38 | # ninja blocks WT450 temp / humidity sensor #2 39 | - platform: mqtt 40 | state_topic: 'RF/UPM_Esic-ID=0002' 41 | name: 'Temperature' 42 | unit_of_measurement: '°C' 43 | value_template: '{{ value_json.TEMP }}' 44 | - platform: mqtt 45 | state_topic: 'RF/UPM_Esic-ID=0002' 46 | name: 'Humidity' 47 | unit_of_measurement: '%' 48 | value_template: '{{ value_json.HUM }}' 49 | 50 | 51 | switch: 52 | #watts clever RF switch - this is triggered by the RFLink when the command is sent 53 | # optimistic required as you get no response from the RFLink when you send a command apart from OK 54 | # and there is no way t tell if the actuion actually worked!! 55 | - platform: mqtt 56 | name: "Watts3" 57 | state_topic: "RF/Eurodomest-ID=02d0f2" 58 | command_topic: "RF/command" 59 | qos: 0 60 | payload_on: "10;Eurodomest;02d0f2;02;OFF\n" 61 | payload_off: "10;Eurodomest;02d0f2;06;ALLON\n" 62 | optimistic: true 63 | 64 | # This is a ninjablocks button (generic 433) 65 | # setup as a switch rather than binary sensor to use the template and try and set it on and off 66 | - platform: mqtt 67 | name: "Button1" 68 | state_topic: "RF/EV1527-ID=015743" 69 | command_topic: "RF/EV1527-ID=015743" 70 | # command_topic: "RF/TriState-ID=02a981" 71 | qos: 0 72 | payload_on: "ON" 73 | payload_off: "OFF" 74 | value_template: '{{ value_json.CMD }}' 75 | --------------------------------------------------------------------------------