add support for nexus protocol to rc-switch library
Description:
New feature:
-
This adds support for nexus protocol to rc-switch library.
Nexus protocol is used by temperature and humidity sensor that operate at 433 MHz. It is used by various brands.
Checklist:
- [X] The pull request is done against the latest development branch
- [x] Only relevant files were touched
- [X] Only one feature/fix was added per PR and the code change compiles without warnings
- [x] The code change is tested and works with Tasmota core ESP8266 V.2.7.7
- [X] The code change is tested and works with Tasmota core ESP32 V.3.0.2
- [X] I accept the CLA.
A reference to the protocol description would be nice.
The best documentation I found so far is this one: https://github.com/aquaticus/nexus433 I double checked and compared timings to what I have seen on my scope btw.
Do you wish to have a protocol description or reverence in code or commit message?
I think this one is related https://github.com/Portisch/RF-Bridge-EFM8BB1/issues/119 and https://github.com/merbanan/rtl_433/blob/master/src/devices/nexus.c
@slo617 Is the change of RCSWITCH_SEPARATION_LIMIT needed?
I remember there are side effects when changing.
Found the regarding PR https://github.com/arendst/Tasmota/pull/14421
Honestly reluctant to change this value
Yes, change of RCSWITCH_SEPARATION_LIMIT is needed to use the new protocol.
Old value was 2600ms (3 years ago). I changed from 4100 to 7*500=3500. This is still higher than the old value.
7*500 is the exact length of the 'low' part of the sync signal. (Actually there is only the low-part...)
I can not find that issue #14 mentioned in the comment. I do not know why 4100 was chosen. I guess it was just the next bigger value.
In my tests, everything still seem to work fine.
Anyhow, if there really still is an issue, maybe we should iterate over all protocols that are enabled at run-time and chose the same time as the shortest 'low' part of the sync signal, as suggested by the comment in code.
The value 4100 is choosen because there where issues with the value before (2600).
Reducing to the suggested lower value of 3500 may break implemented protocols.
Sorry no merge, as long it is not verified all currently implemented protocols do still work with this lowered value.
The Tasmota lib is based on the 1technophile build/fork. More infos about the issue(s) can be found there. Starting point: https://github.com/1technophile/rc-switch/pull/7
Honestly I will not invest a lot of time again in this just because one protocols is added.
Feel free to change the lib / Tasmota to make this value adjustable.
Sure, got that, but why 4100? How was that calculated? Why not 4000 or 4200?
Anyhow, I took a look into the code once again...
A new (potential) message is detected if there is a pulse with a length of at least RCSWITCH_SEPARATION_LIMIT milliseconds.
So RCSWITCH_SEPARATION_LIMIT must be equal or shorter than the initial pulse, but must not be equal or shorter than any following pulses of the message. Otherwise a new start would be detected within the message.
But as far as I can see, that is still the case for the same protocols it was before my change.
It is a long time ago. Don't remember the details. It is not just calculated. Many real life tests with different values where done. Overall the current choosen 4100 is working quiet well for most. Again no change without real life tests. -> We have been there with "the calculated value should work fine"
That #define RCSWITCH_SEPARATION_LIMIT 4100 could be "wrapped" in #ifdef, allowing it to be a build time option, which you can change in a custom build. While not "ideal", this would make it feasible to use a protocol needing to deviate from the currently chosen default.
This PR has been automatically marked as stale because it hasn't any activity in last few weeks. It will be closed if no further activity occurs. Thank you for your contributions.
I reverted my changes on RCSWITCH_SEPARATION_LIMIT. Instead I added a new function that calculates the correct limit from the values of the activated protocols. It does so by searching for min and max timings and choosing the value in the middle.
If conflicting timings are found it will fall back to RCSWITCH_SEPARATION_LIMIT, which is the case if all protocols are enabled. In that case an info-message is logged.
I tested with all protocols by sending messages from one tasmota device to another tasmota device. (Both are ESP32 in my case.)
In addition to those protocols that had worked before, after my change I got also protocols 4, 16, 17, 18, 23, 25, 26, 27, 29, 32 and 34 working - which had not worked out-of-the-box before.
Protocols 12-14 are marked as "not working" or "test" - I could not get them working before and after my changes. Same with Protocol 15 which has no documentation.
Protocols 11, 14, 15, 37 have a header of 0 (zero) pulses and will keep using RCSWITCH_SEPARATION_LIMIT. (And I could not manage to send and receive them with my test setup.)
Same for Protocols 19 and 31 which "data pulses" that are longer than "header pulses". These will also keep unsing RCSWITCH_SEPARATION_LIMIT, and I am not sure if receiving these protocol with rc-switch is possible at all. (But sending should be possible of cause.)
In addition protocols 24, 28, 30, 33, 35, 36 have not worked before and after my change. Protocol 24 has no transition between two set or two cleared bits, not sure if it can be received at all.
I also fine-tuned the new protocol a bit, so that sending is working too.
like this approach. Imho worth to give it a try. @arendst What do you think about?
It's a good idea to add protocol 38 not only for nexus but also for many other devices with long code. For long codes (over 0xFFFFFFFF) the 'xdrv_17_rcswitch.ino' driver does not display them correctly. Mainly I modified: on line 54: unsigned long long data = mySwitch.getReceivedValue(); // it should be 'long long' in accordance with rc_switch on lines 65 - 70: char stemp[24]; if (Settings->flag.rf_receive_decimal) { // SetOption28 - RF receive data format (0 = hexadecimal, 1 = decimal) snprintf_P(stemp, sizeof(stemp), PSTR("%lu"), data); } else { if (data <= 0xFFFFFFFF) { // otherwise it still doesn't display the entire reception in hexa format snprintf_P(stemp, sizeof(stemp), PSTR(""0x%lX""), (uint32_t) (data)); } else { snprintf_P(stemp, sizeof(stemp), PSTR(""0x%lX%08lX""), (uint32_t) (data>>32),(uint32_t) (data)); // this is the solution I found for the correct display } } I only made these changes because I found the hex format advantageous and it works. There are others to check. I have no experience with github, but I hope it helps. @arendst What do you think about?