cflurin / homebridge-mqtt

Homebridge-mqtt is a Plugin for Homebridge.
Apache License 2.0
229 stars 39 forks source link

Multiple buttons in 1 statelessswitch #46

Closed yanovik closed 5 years ago

yanovik commented 6 years ago

Hello, not an issue. But I wonder how to create accessory statelessswitch with several buttons, like Hue has for its dimmer. Like this https://apple.insidercdn.com/gallery/23380-29428-Image-34-l.jpg Any ideas?

ihatemyisp commented 6 years ago

I think what you're looking for is the "StatelessProgrammableSwitch" service.

You would define a device/accessory, add as many "StatelessProgrammableSwitch" services as you have buttons to pressed/relays/etc. The service can be named with "Characteristic.Name".

Again, I'm not 100% on this, as I haven't looked into it past looking at the HomeKit Types definitions.

PaulWieland commented 6 years ago

@iancorbitt is right, you can create the stateless switch with that switch service from the type definitions. The question is, once you create it, how do you use it?

I was really hoping it was going to be a stateless switch that I could use for controlling some IR devices where you don't know the state but you want to send discrete IR commands (like Stereo Power On and another one for Stereo Power Off).

I created the stateless switch but tapping it in homekit doesn't seem to trigger any mqtt message saying that the button was pressed.

ihatemyisp commented 6 years ago

@fahrvergnuugen, care to share your JSON payloads for creating the switch so I can try on my end and help troubleshoot.

PaulWieland commented 6 years ago

{"name":"testStateless","service":"StatelessProgrammableSwitch"}

The switch shows in Home.app but it has an error that says

This accessory requires a home hub to be used with the Home app"

ihatemyisp commented 6 years ago

@fahrvergnuugen Are you running iOS 10.x?

Using your payload, I get this on iOS 11.2.5 dev beta:

2017-12-17 20 13 02 2017-12-17 20 13 11 2017-12-17 20 13 21

Much like yourself, I don't get any messages when clicking the button.

It looks like they've got this figure out in the hombridge-hue plugin, but in my digging, I can't figure it out. I've added a 2nd and 3rd StatelessProgrammableSwitch service and nothing changes in the above screenshots.

Maybe we can get some help from @ebaauw or @KhaosT...

ebaauw commented 6 years ago

Unlike a regular switch, you (as a HomeKit user) cannot tap a stateless programmable switch. It’s an event-only characteristic, no writes, no reads. You can assign actions to the button event (press, double press, long press), very much like HomeKit automations (in fact, these actions show as automations in other HomeKit apps). You need a HomeKit hub for these actions to execute, see https://support.apple.com/en-us/HT207057.

From your plugin, you need to expose an accessory with at least three services: Accessory Information (obviously), Label Namespace, and Stateless Programmable Switch. You might add additional Stateless Programmable Switch services for additional buttons, and a Battery service. Each Stateless Programmable Switch sevices takes two Characteristics: Programmable Switch Event and Label Index. The latter defines the order in which the buttons are displayed, the first defines the button event. See https://github.com/KhaosT/HAP-NodeJS/blob/efe4c05e9b9ed831eeba89e4b67fddd8c70cc4ec/lib/gen/HomeKitTypes.js#L1513. There were issues using the minValue and maxValue properties for the characteristic to limit the possible events, but validValues works.

PaulWieland commented 6 years ago

@ebaauw thanks for your explanation, but I'm still not groking what the intended purpose is of the stateless programmable switch. What practical use case does it have? When/why would you need to make a switch like this instead of a regular switch?

ebaauw commented 6 years ago

If you have a physical stateless switch (what's in a name ;-), which emits a pulse when pressed (like a doorbell), rather than a regular on/off switch, which remembers state (i.c. position of the switch). In particular, smart lighting remote dimmers/switches are stateless.

PaulWieland commented 6 years ago

Okay that's exactly what I thought. But what I don't understand is why the stateless switch isn't tappable in HomeKit... what purpose does it serve if you can't activate it? Is it meant to only receive a message that the physical switch was pressed?

In my case, I have a physical stateless switch (the On button on my stereo remote) that I want to mimick in HomeKit...but if you can't interact with it in Home.app/Eve I guess I'm barking up the wrong tree?

ebaauw commented 6 years ago

Is it meant to only receive a message that the physical switch was pressed?

That's my understanding: it's for exposing a physical stateless switch.

In my case, I have a physical stateless switch (the On button on my stereo remote) that I want to mimick in HomeKit...but if you can't interact with it in Home.app/Eve I guess I'm barking up the wrong tree?

Mimic, not expose. So I would use a regular switch and reset it to Off automatically 0.5 seconds (or so) after the user has switched it On. Ideally you'd want to use a write-only characteristic for this (like Identify), but I haven't found anything like it.

supersjimmie commented 6 years ago

Any more specific progress on this? I'm looking for a way to control some kind of stateless dimmer with 3 tip-buttons: UP on/off DOWN (and then it's a double dimmer, so actually it has 2x3 of those) How to handle the up and down?

ebaauw commented 6 years ago

The Up and Down would be different buttons, so you'd expose a single accessory with six Stateless Programmable Switch services, one for each button, see my earlier comment.

supersjimmie commented 6 years ago

Sorry @ebaauw I think I missed something in my question. As far as I understand, the stateless programmable switch is remotely-controlled, but I want it to be controlled from homebridge tó the switches.

To clarify more, those 6 buttons can be "tapped" with a 433MHz remote, and that is what I want to do from homekit. (have 6 buttons on my iphone from which I send a 433MHz "tap" to the dimmer, where the buttons on the iphone are like stateless, they turn off after a tap)

ebaauw commented 6 years ago

My bad. In that case you need to expose six Switch services. You'd need to reset the On characteristic of the switches for DimUp and DimDown, 500ms or so after the user has pressed them, so they can be pressed again.
I would still combine them into a single accessory, to prevent hitting the 99 accessories per HomeKit bridge limit. They will show as six tappable tiles in Apple's Home app.

I would probably be more intuitive to expose the dimmer as two LightBulb services, using Brightness as a slider instead of tapping DimUp and DimDown. That would be easiest with support from the dimmer to set the level, instead of only in- or decreasing it. Otherwise, you need to cache the old Brightness value, and translate the delta with the new value into several DimUp or DimDown commands. E.g. if Brightness changes from 50% to 75% percent, and there's 20 levels of dimming (5% each), you'd issue 5 DimUp commands.

supersjimmie commented 6 years ago

Thanks @ebaauw . Now what confuses me is that I have working code now that does exactly that: have the buttons in one acc, call the http request to the dimmer button, wait a short while and then send a notify with 'false'. But that notify is not sent at all, according to the logs.

I still think that brightness is not useful because the brightness slider could then be at the top while the real dimmer is somewhere low. Then you cannot slide up. Or the other way around, offcouse.

ebaauw commented 6 years ago

wait a short while and then send a notify with 'false'. But that notify is not sent at all, according to the logs.

You need to make sure the characteristic has “ev” (event, notify) permission and do an updateValue() or setValue() of the characteristic.

I still think that brightness is not useful because the brightness slider could then be at the top while the real dimmer is somewhere low.

It’s useful only, if the dimmer can report its current level, so you can sync the slider to it.

supersjimmie commented 6 years ago

You need to make sure the characteristic has “ev” (event, notify) permission and do an updateValue() or setValue() of the characteristic.

That part I got working, I can notify now.

It’s useful only, if the dimmer can report its current level, so you can sync the slider to it.

And that leads me back to the base of this issue, it's a one-way communication. So I send a 433MHz code to the dimmer but I cannot read anything from it.