arendst / Tasmota

Alternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at
https://tasmota.github.io/docs
GNU General Public License v3.0
22.16k stars 4.8k forks source link

Can't send a data value of 0 via IR module. #2751

Closed crankyoldgit closed 6 years ago

crankyoldgit commented 6 years ago

Can't send a data value of 0 via the IR module.

The IR subsystem fails to send a message when the data payload is 0 (zero).

To Reproduce Send a MQTT message to the irsend module. e.g. topic: "cmnd/SONOFF_DEVICE/irsend" payload: '{"Protocol": "SAMSUNG","Bits":32,"data":0}' Expected behavior A Samsung 32bit message with a value of 0 should be transmitted. e.g. A call of irsend->sendSAMSUNG(0, 32); should be made. It doesn't.

Screenshots N/A

Additional context I think the bug is here: https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/xdrv_02_irremote.ino#L301

        data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0);
        if (protocol && bits && data) {

When data is 0, it evaluates as False in the above if statement.

Most simple fix is to change:

        if (protocol && bits && data) {

to:

        if (protocol && bits) {

Technically a more correct fix is to check if you had a parsing error (you can't do that with strtoul()) and to NOT assume a return value of 0 from strtoul() is a parse error, a str of "0" is valid and a potential value, and a real result of strtoul().

TL;DR: When strtoul() returns zero, it isn't always a failure to convert.

Workarounds: Specify a value that has the lower bits as zero. e.g. 2^32 which has the lower 32 bits as 0, but the entire value is != 0. e.g. 0b100000000000000000000000000000000

MQTT example of the workaround:

payload: '{"Protocol": "SAMSUNG","Bits":32,"data":0}'  // does nothing
payload: '{"Protocol": "SAMSUNG","Bits":32,"data":4294967296}'  // works (sends a 0 IR message)

Ref: https://github.com/markszabo/IRremoteESP8266/issues/447#issuecomment-389745404

arendst commented 6 years ago

I agree. I went for your simple fix and PR

Another solution would be to test for any string length before using strtoul