xoseperez / espurna

Home automation firmware for ESP8266-based devices
http://tinkerman.cat
GNU General Public License v3.0
2.98k stars 636 forks source link

Request: Websocket support for IR #2186

Open Omar-95 opened 4 years ago

Omar-95 commented 4 years ago

Is your feature request related to a problem? Please describe. I use espurna on lolin-nodemcu as IR Transmitter to control rgb led strip which works great by sending mqtt messages from mqtt dashboard installed on my phone.

But it would be great to add rgb remote controller to web interface, I have already rebuild web interface using gulp and added an IR Transmitter panel which contains the rgb remote controller which have 24 buttons. after rebuilding web interface my index.all.html.gz.h size is 305KB

Also I have been able to send an websocket action when any button is pressed on web remote.

Describe the solution you'd like It would be great to add websocket interface to ir.ino if possible.

Describe alternatives you've considered another solution that I though of since we already can send ir code via mqtt, Is to send an mqtt message when a button on the web ui is pressed something like the sendAction function in the custom.js but instead of websocket action, an mqtt message.

Additional context This is how IR Remote panel looks like. Annotation 2020-03-17 232403

mcspr commented 4 years ago

So, we would need something like this?

wsRegister().
    onAction([](uint32_t client_id, const char* action, JsonObject& data) {
        if (strcmp(action, "irsend") == 0) {
            ... some code to schedule ir.send(data["type"], data["code"], data["bits"]) ...
        }
    });

And I assume remote button set is hard-coded into the firmware somehow? Either in WebUI itself or some c++ code that sends it to the UI at some point during the initialization.

Omar-95 commented 4 years ago

First of all, I apologize for the late reply.

Yes this exactly what we need and yeah the remote button set is hard coded into the firmware in ir_button.h

Luckily my rgb remote uses IR_BUTTON_SET == 2.

Also the WebUI will send only the id of clicked button in JsonObject& data.

Please check these files for more details about edits in the webUI side and feel free to modify.

html.zip

Omar-95 commented 4 years ago

I still can't figure how to use IR_BUTTON[IR_BUTTON_COUNT][3] variable in ir.send(). As an alternative i added a group of #define in ir_button.h which looks like this

#define IR_BPLUS 0xF700FF #define IR_BMINUS 0xF7807F :: :: #define IR_SMOOTH 0xF7E817

As for the ir.ino i imagine it will look like this

wsRegister(). onAction([](uint32_t client_id, const char* action, JsonObject& data) { if (strcmp(action, "irsend") == 0) { switch( data["id"] ) { case 1: ir.send(NEC,IR_BPLUS,32); break; case 2: ir.send(NEC,IR_BMINUS,32); break; :: :: case 24: ir.send(NEC,IIR_SMOOTH,32); break; } delay(1000); });

mcspr commented 4 years ago

https://github.com/xoseperez/espurna/blob/a71f233caa8ba8f2dd729d16cd6c7ef84799901d/code/espurna/ir.ino#L280 ? i -> data["id"], with a check that it does not go over IR_BUTTON_COUNT.

I am not using IR though, so I am not really sure:


Also note that the callback should be something like

{
    if (strcmp(action, "irsend") == 0) {
        JsonVariant _id = id["id"];
        if (!_id.success()) return;
        const auto id = id.as<int>();
        if (id >= IR_BUTTON_COUNT) return;
        const uint32_t code = pgm_read_dword(&IR_BUTTON[id][0]);
        schedule_function([code]() { ir.send(NEC, code, 32); });
    }
}

ESP WebSocket callback happens right after network receives data, right inside of the network callback. If you call delay() or if ir.send() does, board will panic and crash because of the internal assert condition.

Omar-95 commented 4 years ago

why NEC type?

The RGB remote controller sends commands using NEC Protocol, i know that by using IRrecvDumpv2 example to decode the remote controller codes. and after getting all the codes i found out that these codes are already embedded in the firmware in ir_button.h

The IRrecvdumpv2 result for Brightness_Up button.

Encoding  : NEC
Code      : F700FF (32 bits)

why 32 bit, not 24 (as button_set length never goes over 3 bytes)

NEC IR protocol encodes the keys using a 32bit frame format as shown below.

NEC Frame Format
    Address  | Complement of Address        |      Command       | Complement of Command
LSB-MSB(0-7) |        LSB-MSB(8-15)         |   LSB-MSB(16-23)   | LSB-MSB(24-31)

board will panic and crash because of the internal assert condition.

Thank you for this precious note, at first i tried to implement Websockets in ir.ino without know this. And my nodemcu kept crashing every time i press a button on WebUI, This is why i asked for help.

Omar-95 commented 4 years ago

@mcspr Good News, I got the IR transmitter working flawlessly using WebUI.

now I am working on supporting REST API for ir.ino to be able to use it with google assistant.

Thanks again for showing me how to implement websocket, without your help this wouldn't be possible.

Omar-95 commented 4 years ago

I would like to contribute to this great project by an idea but I need your opinion about it.

Now we have the RGB Remote template implemented in the WebUI, how about I add two more templates on for air conditioner remote and tv remote?

The _ir_type and _ir_code can be added using WEBUI, also I want the users to have option to choose which template they want build whether Tv remote or AC remote or all of them.

I am really excited about working with IR since it only needs a 2n2222 transistor and IR Tx led that I salvaged from a broken tv remote, the only thing that I had to buy was the IR Receiver which is needed to decode remote signal and get the code.

mcspr commented 4 years ago

Good to hear. Some other things I have also noticed:

Now we have the RGB Remote template implemented in the WebUI, how about I add two more templates on for air conditioner remote and tv remote? The _ir_type and _ir_code can be added using WEBUI, also I want the users to have option to choose which template they want build whether Tv remote or AC remote or all of them.

Sure. Do you mean that codes would be sourced from the settings kv storage and not pre-defined button set? Or that user will select specific button set?

Omar-95 commented 4 years ago

existing code does _ir_receiver.disableIRIn(); before sending stuff, this should also be incorporated into the sender function?

Nice observation, this is included in sender function now. I have read that _ir_receiver.disableIRIn(); should be used to decrease power consumption also without it some esp8266 and esp32 panic.

we probably need slightly different approach for sending due to the #1669 (also see #2182).

Your suggested approach worked flawlessly, by removing delay(...) call and scheduling ir_sender function which also doesn't need to have delay inside it.

We should treat sending as a separate task of sorts and avoid using globals for configuration.

I don't understand what you mean by that, could you clarify more?

Do you mean that codes would be sourced from the settings kv storage and not pre-defined button set?

Yes, i was thinking that users should enter code in the webUI and to be stored in kv storage, but when i gave it another thought, i found that working with pre-defined button sets isn't that bad, it won't use that much storage space and more easier to implement.

I got a couple question, How to enable users to choose remote control templates they want to use? should each template be treated as a separate webui image?