Announcement

Collapse
No announcement yet.

Scripting assistance - Parse/interpret MQTT data from temperature and humidity sensor

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Michael McSharry
    replied
    Every manufacturer has a different encoding mechanism for their devices. This example appears to be somebody's temp/humidity sensor reporting. Bert with the RFXCOM plugin has many of these decoded. I have a subset decoded in the mcsXapW800 xAP node.

    What I see are two levels of issues with the decoding. The first is how to interpret the raw data into engineering units. The second is to know the device encoding (e.g. is it humidity and where is in the humidity value)

    The SDR receiver is a valuable resource for decoding known 433 MHz transmissions. https://www.rtl-sdr.com/tag/433-mhz/ and in particular RTL_433. This part tells you what you are receiving so you have a chance of developing the script for the set of devices that you have on your RF that you want into HS. Overall this is not trivial.

    Leave a comment:


  • Scripting assistance - Parse/interpret MQTT data from temperature and humidity sensor

    I have a few battery operated temperature and humidity sensors (DIGOO DG-R8S 433MHZ) returning raw data to MCSMQTT via a Sonoff 433Mhz bridge.
    Dev: |TASMOTA_RFBRIDGE|RESULT:RfRawata
    Sub: tele/RFBRIDGE1/RESULT:RfRawata
    Pub: the following Topic on Device command
    AA B1 04 02C6 0FD2 07D0 2314 010202010102010102010101020202020202020201010102010102010202 0202010201020203 55
    I found the logic behind it to decode/extract the temp/humidity values (https://github.com/Portisch/RF-Bridg...BB1/issues/119 - last post)
    but Iooking at a way to end up with usable temp/humidity values in MCSMQTT or native HS3 devices.

    Someone also came up with a script on a different platform to parse the data (https://github.com/dgomes/homeGW/blob/master/digoo.cpp)

    Code:
     [TABLE]
    [TR]
    [TD]*/[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]#include <digoo.h>[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]digoo::digoo() {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]packet_size = 37;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]END_PACKET = 3000;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]MIN_PACKET = 650;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t digoo::getId(uint64_t packet) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t id = (packet >> 28) & 0xFF;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return id;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t digoo::getBattery(uint64_t packet) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t batt = (packet >> 24) & 0x8;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return batt ? 1 : 0;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t digoo::getChannel(uint64_t packet) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t channel = (packet >> 24) & 0x3;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return channel+1;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]float digoo::getTemperature(uint64_t packet) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]int16_t t = packet >> 12 & 0x0FFF;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]t = 0x0800 & t ? 0xF000 | t : t;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]float temperature = float(t) / 10;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return temperature;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t digoo::getHumidity(uint64_t packet) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t humidity = packet & 0xFF;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return humidity;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t digoo::isValidWeather(uint64_t ppacket) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]uint8_t humidity = getHumidity(ppacket);[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]//Specs http://www.amazon.co.uk/gp/product/B00327G0MA/ref=oh_details_o00_s00_i00[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]if (humidity > 100) { //sanity check according to specs[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return INVALID_HUMIDITY;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]float temperature = getTemperature(ppacket);[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]if (temperature < -20.0 || temperature > 50.0) { //sanity check according to specs[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return INVALID_TEMPERATURE;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]return OK;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]void digoo::processPacket() {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]packet = 0;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]for(unsigned i=1; i< bitsRead; i++) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]unsigned duration = timings[i];[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]if(duration > digoo::ONE) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]packet = packet << 1;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]bitSet(packet, 0);[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]} else if(duration > digoo::ZERO) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]packet = packet << 1;[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]bitClear(packet, 0);[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD] [/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]#ifdef DEBUG[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]Serial.print("~0x");[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]Serial.println((unsigned long) packet, HEX);[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]if (packet == 0) {[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]for(unsigned i=0; i < bitsRead; i++)[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]Serial.println(timings[i]);[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]#endif[/TD]
     		[/TR]
    [TR]
    [TD] [/TD]
     			[TD]}[/TD]
     		[/TR]
    [/TABLE]
    Based on feedback from Micheal (MCSMQTT), the best approach would be to register the topics with a script and mcsMQTT would call the script when one of those topics has been received.


    6.8 Scripting Callback
    If a user desires to handle the raw MQTT received payload in a script then a callback can be used to receive MQTT topics with their payload. This is setup with a call to the plug-in to register the script. The RegisterTopicReceivedScript callback expects an array of three parameters. The first is the filename that will be located in the HS scripts folder. The second is the name of the procedure in this file. The third is the Topic that will result in a callback. Multiple Topics can be requested with multiple calls to this function. MQTT Topic wildcards can also be used.

    hs.PluginFunction("mcsMQTT", "", "RegisterTopicReceivedScript",{"MyScriptFileName.vb", "MyFunctionName", "MyMQTTTopic"})

    As an example, the following two scripts are used in the file TestCallback.vb. The first (Main) was invoked by event with script action. The second (TheCallback) was invoked by mcsMQTT when it received the MQTT Topic “test/topic”.
    sub Main(parm as object)
    hs.WriteLog("TestCallback", "Registering Callback for Script")
    Dim callbackParameters = New String {"TestCallback", "TheCallback", "test/topic"}
    hs.PluginFunction(
    "mcsMQTT",
    "",
    "RegisterTopicReceivedScript",
    callbackParameters
    )
    End Sub
    sub TheCallback(parm as object)
    hs.Writelog("TestCallback", "Received Topic " & parm(0) & " with Payload " & parm(1))
    End Sub

    However, I don't have enough experience to translate the above script and have it interact with MCSMQTT;
    If anyone could volunteer some help to complete the script, I'll gladly do the testing.
    I guess it could help other users and/or provide basis for other 433Mhz raw data device integration.

    Thanks!

    see also: https://github.com/arendst/Tasmota/w...-RF-Bridge-433 "raw sniffing"
Working...
X