NorthernMan54 / rtl_433_ESP

Trial port of the rtl_433 Library for use with OpenMQTTGateway on a ESP32 and a CC1101 Transceiver
GNU General Public License v3.0
494 stars 111 forks source link

Insteon Support #14

Closed kuestess closed 3 years ago

kuestess commented 3 years ago

@NorthernMan54 Really nice work, sir - I'm using this with OpenMQTT Gateway to control some fans and it works great! I noticed in the rtl_433 project that there is a decoder for Insteon RF packets. Since most devices are dual-band, thought this might be a potential inexpensive alternative to a Hub/PLM. I messed with your example code from the fsk branch and have the CC1101 detecting Insteon RF signals. Where I run into issues is at the packet decode - it starts to decode the packets, finds the Insteon preamble, but then completely crashes (hard reset) at the stage where it begins to parse the Insteon packet. No errors, nothing to help determine the cause. I'm far from an expert on RF or ESP32, but any guesses what might be causing the reset? Assume it might be a memory thing, but thought I'd reach out to see if you had ideas, or had decoding working for any other FSK devices. Thanks!

NorthernMan54 commented 3 years ago

Can you share the crash details? Or a log from just before the crash?

also can you share how your detecting insteon RF? I have some insteon devices, and may be able to duplicate this.

kuestess commented 3 years ago

Here's the code I've hacked together, based upon one of the FSK examples and modified to mimc the parameters from the insteonrf receive script. Behind this, I've added back the Insteon decoder from the rtl_433 project to handle the decoding.

#include <rtl_433_ESP.h>
#include <ArduinoJson.h>
#include <ArduinoLog.h>
#include <ELECHOUSE_CC1101_SRC_DRV.h>

#define CC1101_FREQUENCY 914.95
#define JSON_MSG_BUFFER 1024
#ifndef CC1101_GDO0
#define CC1101_GDO0 22
#endif
#ifndef CC1101_GDO2
#define CC1101_GDO2 4
#endif

#if CC1101_GDO0 == 2
#error "ERROR: GPIO2 Can not be connected to GDO0"
#endif

#define RAW_SIGNAL_DEBUG true

char messageBuffer[JSON_MSG_BUFFER];

rtl_433_ESP rf(-1); // use -1 to disable transmitter

void rtl_433_Callback(char* message) {
  DynamicJsonBuffer jsonBuffer2(JSON_MSG_BUFFER);
  JsonObject& RFrtl_433_ESPdata = jsonBuffer2.parseObject(message);
  logJson(RFrtl_433_ESPdata);
}

void logJson(JsonObject &jsondata)
{
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
  char JSONmessageBuffer[jsondata.measureLength() + 1];
#else
  char JSONmessageBuffer[JSON_MSG_BUFFER];
#endif
  jsondata.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
  Log.notice(F("Received message : %s" CR), JSONmessageBuffer);
}

void setup()
{
  Serial.begin(921600);
delay(1000);
#ifndef LOG_LEVEL
  LOG_LEVEL_SILENT
#endif
  Log.begin(LOG_LEVEL, &Serial);
  Log.notice(F(" " CR));
  Log.notice(F("****** setup ******" CR));

  rf.initReceiver(CC1101_GDO0, CC1101_GDO2, CC1101_FREQUENCY);
  rf.setCallback(rtl_433_Callback, messageBuffer, JSON_MSG_BUFFER);

  ELECHOUSE_cc1101.SetRx(CC1101_FREQUENCY); // set Receive on
  ELECHOUSE_cc1101.setModulation(0);
  ELECHOUSE_cc1101.setDeviation(75);
  ELECHOUSE_cc1101.setSyncMode(4);
  //ELECHOUSE_cc1101.setSyncWord(211, 145);
  //ELECHOUSE_cc1101.setManchester(0);
  //ELECHOUSE_cc1101.setDRate(220);
  ELECHOUSE_cc1101.setRxBW(200);
  rf.enableReceiver(CC1101_GDO2);
  Log.notice(F("****** setup complete ******" CR));
}

void loop()
{
  rf.loop();
}

As far as logs, not much there. - it simply hard resets with no error message. Output below.

����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������N:  
N: ****** setup ******
rtl_433_ESP(6): Pre initReceiver: 312672
rtl_433_ESP(5): CC1101 GDO0 gpio pin: 22
rtl_433_ESP(5): CC1101 GDO2 gpio pin: 4
rtl_433_ESP(5): CC1101 receive frequency: 914.950012
rtl_433_ESP(7): sizeof(*cfg->demod) 16
rtl_433_ESP(7): size of bitbuffer: 11352
rtl_433_ESP(7): size of pulse_data: 9628
rtl_433_ESP(6): # of device(s) configured 1
rtl_433_ESP(6): ssizeof(r_device): 76
rtl_433_ESP(6): cfg->devices size: 76
Registering protocol [1] "Insteon"
rtl_433_ESP(6): CC1101_MDMCFG1: 0x02
rtl_433_ESP(6): CC1101_MDMCFG2: 0x02
rtl_433_ESP(6): CC1101_MDMCFG3: 0x93
rtl_433_ESP(6): CC1101_MDMCFG4: 0x07
rtl_433_ESP(6): CC1101_DEVIATN: 0x47
rtl_433_ESP(6): CC1101_AGCCTRL0: 0xb2
rtl_433_ESP(6): CC1101_AGCCTRL1: 0x10
rtl_433_ESP(6): CC1101_AGCCTRL2: 0xc7
rtl_433_ESP(6): CC1101_IOCFG0: 0x0e
rtl_433_ESP(6): CC1101_IOCFG1: 0x2e
rtl_433_ESP(6): CC1101_IOCFG2: 0x0d
rtl_433_ESP(6): CC1101_FIFOTHR: 0x07
rtl_433_ESP(6): CC1101_SYNC0: 0x91
rtl_433_ESP(6): CC1101_SYNC1: 0xd3
rtl_433_ESP(6): CC1101_PKTLEN: 0x00
rtl_433_ESP(6): CC1101_PKTCTRL0: 0x32
rtl_433_ESP(6): CC1101_PKTCTRL1: 0x04
rtl_433_ESP(6): CC1101_ADDR: 0x00
rtl_433_ESP(6): CC1101_CHANNR: 0x00
rtl_433_ESP(6): CC1101_FSCTRL0: 0x4e
rtl_433_ESP(6): CC1101_FSCTRL1: 0x06
rtl_433_ESP(6): CC1101_FREQ0: 0xbd
rtl_433_ESP(6): CC1101_FREQ1: 0x30
rtl_433_ESP(6): CC1101_FREQ2: 0x23
rtl_433_ESP(6): CC1101_MCSM0: 0x18
rtl_433_ESP(6): CC1101_MCSM1: 0x30
rtl_433_ESP(6): CC1101_MCSM2: 0x07
rtl_433_ESP(6): CC1101_FOCCFG: 0x16
rtl_433_ESP(6): CC1101_BSCFG: 0x1c
rtl_433_ESP(6): CC1101_WOREVT0: 0x6b
rtl_433_ESP(6): CC1101_WOREVT1: 0x87
rtl_433_ESP(6): CC1101_WORCTRL: 0xf8
rtl_433_ESP(6): CC1101_FREND0: 0x10
rtl_433_ESP(6): CC1101_FREND1: 0x56
rtl_433_ESP(6): CC1101_FSCAL0: 0x1f
rtl_433_ESP(6): CC1101_FSCAL1: 0x2b
rtl_433_ESP(6): CC1101_FSCAL2: 0x2c
rtl_433_ESP(6): CC1101_FSCAL3: 0xef
rtl_433_ESP(6): CC1101_RCCTRL0: 0x00
rtl_433_ESP(6): CC1101_RCCTRL1: 0x41
rtl_433_ESP(6): Post initReceiver: 311700
N: ****** setup complete ******

rtl_433_ESP(6): Time: 7854, Signal length: 34113, Signal RSSI: -82, train: 1, messageCount: 0, pulses: 112
rtl_433_ESP(6): RAW (34113):  131 223 225 236 211 101 105 129 100 95 96 108 99 97 214 120 118 120 122 215 239 118 228 103 215 121 222 228 105 215 122 216 122 215 127 106 233 106 131 212 106 105 133 96 116 127 106 241 104 212 129 106 132 211 107 133 105 107 124 233 98 211 214 105 134 236 107 131 214 131 206 121 209 103 130 211 133 134 107 104 128 103 131 107 106 131 102 232 98 103 108 136 108 107 106 106 133 105 100 120 118 119 215 214 134 107 104 104 123 233 212 203 
rtl_433_ESP(6): Pre run_ook_demods: 302004
Exact bit width (in us) is 109.72 vs 110.00, 18 bit preamble
Exact bit width (in us) is 110.17 vs 110.00, 18 bit preamble
insteon_callback: new buffer 1 rows
insteon_callback: bitbuffer_search at row / search_index : 0, 0 0 (310)
insteon_callback: parse_insteon_pkt at: row / search_index : 0, 12 (310)
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������N:  
NorthernMan54 commented 3 years ago

I'm wondering if the Insteon_callback completes or if it crashes before exiting. Would adding a additional debug statement here work ?

https://github.com/merbanan/rtl_433/blob/3c61f600c678d8cba41ea7e61865890527a6b370/src/devices/insteon.c#L466

Also I'm surprised that your not getting any type of exception output, as I usually get a stack trace or something when it runs into an issue. Are you doing esp32 debug builds ? I have this in my visual studio code environment setup, so I can see where things fail.

  build_type = debug
  monitor_filters = esp32_exception_decoder

PS I'm on vacation so don't have access to my Insteon devices for a week

kuestess commented 3 years ago

Thanks @NorthernMan54! I do have those debug entries in my environment, but still not getting anything in the trace. Will try some debugging in the Insteon decoder to see what I can figure out. Enjoy your vacation!

NorthernMan54 commented 3 years ago

When I did the main port over to the ESP32, what I found was a challenge was stack usage, as the stack is smaller on the esp32 versus other environments and memory allocations onto the stack caused issues. So to get things to work during the port, I needed to move from the stack for objects from main memory instead.

So if you see something allocating large objects on the stack, that could be triggering it.

kuestess commented 3 years ago

@NorthernMan54 Did a little messing around with the code and it definitely is a memory issue - insteon_callback wasn't running at all. I was able to allocate to the heap and get it to run, however other memory issues popped up for downstream functions. I'm now getting CORRUPT HEAP: Bad head at 0x3ffb8af8. Expected 0xabba1234 got 0x8edbc56a which seems to likely indicate that its run out of memory. Decoding Insteon packets is relatively complex - starting to wonder whether the memory limitations of the ESP32 will keep this from working. Perhaps RPi is a better platform. I'm certainly not a C or ESP32 expert, but appreciate any ideas you might have.

NorthernMan54 commented 3 years ago

I was looking at the parse_insteon_pkt function, and it appears to drop a lot of variables onto the stack. Getting this to work is going to take alot of reworking of the Insteon message decoder code, with no guarantee of success. If adjusting the stack size did not resolve the issue, then is this worth the effort ? And just running rtl_433 on a RPI might be a better approach

When I did the original port, these were some of the changes I made rtl_433 code base to avoid stack usage.

From here

https://github.com/NorthernMan54/rtl_433_ESP/blob/e03f689d8836bc48b3db628b33f414a67633b3f3/src/rtl_433/pulse_demod.c#L294

To here

https://github.com/NorthernMan54/rtl_433_ESP/blob/e03f689d8836bc48b3db628b33f414a67633b3f3/src/rtl_433/pulse_demod.c#L24

kuestess commented 3 years ago

Completely agree, and in fact I've already moved to a different approach. Everything I fixed just created another downstream issue. Will probably still use ESP32 to capture the packets and then ship off to the Rpi either via serial or web socket to decode. Thanks for your insight!

kuestess commented 3 years ago

@NorthernMan54 Just a quick update on where I landed with this. Found this issue on the rtl_433 repo aimed at the same goal of running on low memory hardware: https://github.com/merbanan/rtl_433/issues/1726. The key change was @obones updates to the Manchester decode method to use a bitrow vs bitbuffer, which of course requires changes in the device-specific methods as well. I copied in the revised bitbuffer.c/bitbuffer.h and Insteon.c, and was able to get Insteon decoding working on the ESP32. I think you’re trying to maintain compatibility with rtl_433, but something like this may be needed for devices with Manchester decoding. Overall works pretty well, however range seems to be limited which I think is because my board is designed for 433MHz rather than 915MHz.

NorthernMan54 commented 3 years ago

I have also noticed that the range of my cc1101 is about 50 to 75% of my RTL_SDR @433mhz, so it may just be they way they work.

Would the changes you made conflict with the existing OOK or the FSK support ? If not maybe we should publish it.

kuestess commented 2 years ago

@NorthernMan54 Sorry for the delay - the revised bitbuffer.c makes changes to the Manchester decode method which require a rewrite of any decoders that use that method (probably just FSK) to use bitrows rather than a bitbuffer. Happy to clean it up and submit a PR if you want.