hencou / esphome_components

Collection of own ESPhome components
25 stars 15 forks source link

Feature Request: Mi command passthrough #19

Closed Omar007 closed 9 months ago

Omar007 commented 10 months ago

The current ESPHome component supports the execution of some commands using either a switch or a button.

This can relatively easily be exposed as a service to be used in HA, e.g. something akin to:

    - service: mi_command
      variables:
        device_id: int
        group_id: int
        type: string
        command: string
      then:
        - lambda: |-
            const BulbId bulbId = {
              device_id,
              group_id,
              MiLightRemoteTypeHelpers::remoteTypeFromString(type.c_str())
            };
            id(mi_component).handleCommand(bulbId, command.c_str());

However, this is not expansive enough to allow the command from Mi events captured from some device using the on_command_received to then be straight up forwarded as-is to some other device/group/type.

If possible it'd be awesome to have a service available (or just a public C++ function that could then be called/used akin to the above) that can take any Mi JSON command string for a given device+type+group and (if relevant for a given light) update the state and send out the message for the light to change to that state.
This would allow something like https://github.com/sidoh/esp8266_milight_hub/wiki/Using-Milight-Remote-with-HomeAssistant#configure-hass to be realized.

hencou commented 10 months ago

Hi,

I added an extra method so now it's possible to send commands to a BulbId with the following command: id(mi_component).write_state(bulbId, command.c_str()); Please be aware that: -You need to give the "mi" component an id like "mi_component" -The device_id is expected in decimal, so when you have it as a hexadecimal string you need to convert it to decimal.

Omar007 commented 10 months ago

Just updated it locally. Only one thing of note in regards to the passthrough itself; for some reason it seems like it's resetting the brightness in certain cases even though that's not part of the command being passed through.

Aside from that, bulb changes made through this function do not seem to be reflected in the HA status. Which seems weird as I think there is a handler that should do so whenever the MiLight client has send out a package? :thinking:

Omar007 commented 10 months ago

Scanned a bit through the code but the above does indeed seem to be the case (Mi::onPacketSendHandler -> Mi::updateOutput ?) so not sure why the state is not reflected back in HA :thinking:

I do suspect this snippet of code has just become dead code: https://github.com/hencou/esphome_components/blob/3491c0432d7b679bb8b6ed8221c199d74bcbdec0/components/mi/mi.cpp#L310-L315

hencou commented 10 months ago

Hi,

The ESP module is not able to send and receive its own commands the same time. So its own sent commands are not sent back to HA, normally this is not needed because HA is sending the command and knows the state. When an external command is received (eg from a remote) the signal will be read and the status in HA will be updated.

Besides that, the module only updates the state of its own entities (as you already found above)

Omar007 commented 10 months ago

Oh yea I don't mean for it to send and receive it's own commands at the same time. In this case it was being send out by a device that itself has a light configured for the same device+type+group as was in the mi_command call, hence me wondering about it.

I'll dive into it some more later next week (I'm still playing around with things) but I figured in the end it would/might be possible to do something like the following:

  1. Some Mi device sends a message
  2. onPacketReceivedHandler calls on_command_received with callback registered that publishes the event to HA
  3. HA automation set to trigger on event
  4. Call mi_command service from HA automation with the command from the event but custom/different device+type+group
  5. Send out command over radio on any device <----- Up to here happening no problem
  6. a) device has a light for the given device+type+group; update the light's state accordingly and have it reflect in HA (which I figured would happen due to onPacketSendHandler? But does not, internal group state only or something?) b) device does not have a light for the given device+type+group; do nothing extra
  7. [opt.] other device detects the signal send out by the first device a) device has a light for the given device+type+group; update the light's state accordingly and have it reflect in HA (which I think does work thanks to onPacketReceivedHandler?) and do w/e is configured in on_command_received b) device does not have a light for the given device+type+group; does w/e is configured in on_command_received
hencou commented 10 months ago

Hi Omar,

Changed the logic a little, and now seems it possible to update the state. The state is now updated when it receives a command from a remote, or when it's received by a "mi_command". The state is still not updated when receiving a command from a ESPhome light entity.