gurumitts / pylutron-caseta

Apache License 2.0
153 stars 98 forks source link

Feature Request: Add support for sending push/hold events to a Pico #96

Open jessedhillon opened 2 years ago

jessedhillon commented 2 years ago

If you have multiple lights or shades controlled by a single remote, those devices move much more synchronously than if you try to recreate the same grouping in something like Home Assistant. For example, I have three window shades controlled by a single Pico. When I use the raise/lower or open/close buttons, they all move in unison. When I create an automation in HA to send a command to three devices, there is a noticeable lag in start time between the devices.

The LEAP protocol supports sending button hrefs the commands PressAndRelease, PressAndHold, and Release -- this is what the mobile app sends when you use it to drive a Pico. The target is the button's href, e.g. /button/125/commandprocessor. A remote's button definition can be retrieved by sending a ReadRequest to the button group's URL, e.g. /buttongroup/7. When the button itself is targeted with PressAndRelease, the bridge sends the commands to the related device in a coordinated manner as described.

The button model in pylutron could be updated to support these commands, and then HA could be updated to make use of the new capabilities as well. There is also a MultiTap command but I don't know what it does, and I don't have any devices that can be configured for multiple tap responses (thinking double/triple taps?)

swails commented 2 years ago

You can often emulate the same effect by creating scenes in caseta and triggering those from home assistant.

That's how I got the lights in my bathroom to come on together pending an occupancy event (different scenes at different dimness settings based on time of day).

One advantage of this strategy is that you can tweak it by changing the scene in caseta without having to hand-tune the automation in HA.

The one thing you don't get that button presses give you is the ability to do a press event to move shades in unison and have them stop on release (rather than a predefined position like you would get with a scene).

jessedhillon commented 2 years ago

Yes you're right, for the most part this would work as long as your intention is always to achieve an absolute position or luminance, and not a relative one (e.g. higher/lower, instead of open/close/X%). It would require you to set up probably two zones for each room in the house though, which could be a pain (although scene creation is also something that pylutron could do).

I'm going to submit a patch to add press_and_hold, press, release, and press_and_release functions which work on buttongroup ID + button number pairs (e.g. buttongroup 4, button 0 for the first button).

NickWaterton commented 2 years ago

I just added the button press control to my implementation. You just need to add:

    async def _button_action(self, button_id, action):
        '''
        Will perform action on the button of a pico device with the given button_id.
        :param button_id: device id of specific button
        :param action one of "PressAndRelease", "PressAndHold", "Release"
        '''
        await self._request(
            "CreateRequest",
            f"/button/{button_id}/commandprocessor",
            {"Command": {"CommandType": action}},
        )

    async def click(self, button_id):
        return await self._button_action(button_id, "PressAndRelease")

    async def press(self, button_id):
        return await self._button_action(button_id, "PressAndHold")

    async def release(self, button_id):
        return await self._button_action(button_id, "Release")

The button_id is not the device_id of the pico remote., but you can get the button_id's easily enough with get_buttons() which returns a dictionary like this (this is just a single entry, you actually get all the buttons):

{'device_id': '101', 'current_state': 'Release', 'button_number': 0, 'name': 'Master Bedroom_Pico 1', 'type': 'Pico3ButtonRaiseLower', 'model': 'PJ2-3BRL-GXX-X01', 'serial': 69006633}

Where the device_id is actually the button_id.

So to click the ON button (button 0) of Pico remote Master Bedroom_Pico 1 you use:

await self.click('101')