Hubitat's button implementation

Just a quick note, button controllers produce button events, they normally don't consume them.
Button controller apps subscribe to button events produced by button controllers. It seems you want to send a button event to this driver as a command shortcut. This is possible using custom commands in rule, but likely more confusing that just implementing each command in rule separately...

1 Like

I was thinking that each button would be an event which could be the sub routines listed accordingly. Thinking more of a virtual button(s) on a single device. I don’t want to create child devices and/or multiple devices for this capability.

Recommendations?

Do you mean that the physical button presses on the Roomba are visible to Hubitat and you want those to be exposed as button events? You could certainly do that. But it sounds like you want something else: you could make the driver expose buttons that can effectively only be "virtually" pressed to trigger some event on the Roomba itself, but I'd agree with the above that a custom command might be the way to go--and certainly more intuitive. (Apps like Button Controller aren't designed to press buttons; they're designed to handle button presses. Some apps are indeed capable of "pressing" buttons as hinted at above, but such behavior is often confusing to users. Rule Machine or a custom app can call custom commands on a device.)

Regardless, there is no reason to create child devices (or multiple standalone devices). You can implement as many custom commands as you want, or if you want to go the button route, you can pretend (I think? still not clear) that the device has so many pushable buttons and make the driver handle these events accordingly [EDIT: not the phrasing I wanted...can you tell I'm an app person?].

Drivers can't subscribe to platform events like apps do.

You could create a custom command in this driver, sendButtonEvent, that takes one numeric parameter, 1..5, within this method you would then look at the value then call each of start, stop ect, however this is more confusion in my opinion than simply publishing each command separatly from custom commands in rule.
In other words as a custom command for this device stop() makes more sense to me than sendButtonEvent(1)...

1 Like

@aaron I agree completely with @mike.maxwell . Also, just to clarify, you don't even need to create RM "Custom Commands" any longer. You can simply use RM's "Run Custom Action" action which allow you to select the custom commands of a particular device.

You may also want to try to map the most popular commands into existing capabilities, where it makes sense. For example, instead of using custom commands for start() and stop(), why not simply add the Switch capability and implement these two commands as on() and off(). This would allow commonly used commands to be called from any App that supports the Switch capability. Just an idea...

1 Like

These are all great ideas.

Ultimately my goal was just to expose those functions as a button. My thought pattern was:

  • RM calls the Roomba "Pushable Button" #1
  • Roomba driver "feels" a button pushed
  • Button #1 now calls XYZ routine mapped to that button number

My thought on this was from another post about the same subject but the example given was what I have above BUT they just called the push(btn) routine in the driver.

This originally was a request to have "dock" be a momentary switch which @plantucha provided me an example of what he was doing. I am hoping to go a little further with it to reveal at least start, stop and dock.

Make sense? Probably not.

Should not any holdable button also have the released capability since in order to distinguish between pushed and held the device needs to send a released event?

Yup. You need to add the releasable button capability and handle it.

https://docs.hubitat.com/index.php?title=Driver_Capability_List#ReleasableButton

It really depends on the device. If it's not a real button and you're making things up, you can do whatever, but for real/physical buttons, the landscape varies. Some send events on push (or release but really counted as a push) only. Some send separate events for push and hold, and that's it. Some, but not all, send an event for release after a hold. In rare cases, the device sends just a push and release, and Hubitat calculates the rest based on your driver, but the only device I'm aware of that natively works like that with Hubitat are Lutron's Picos (quite possibly because the mesh protocols wouldn't work well for this).

On the Hubitat side, all buttons must implement Pushable. You can optionally implement Holdable and, if Holdable, Releaseable. (There's also DoubleTapable [sic.] that is not related to any of the latter two.)

Thank you @bertabcd1234 for your answer.

So, in that case, I have to write my own driver for my Samsung Buttons? HE's driver seems to allow them to work as pushable and holdable but not releasable. Am I correct?
Thanks again.

Push and held are not the same as buttons that support this would send different events for both of these. Therefore not every button will send the release event so that is why it is a separate capability.
As an example I have a button device that will send events on push, doubletapped and held but nothing when held is released.

I'm pretty sure the SmartThings Button only sends a message under one of these three circumstances:

  • shortly after a short press of the button ("pushed" on Hubitat)--this slight delay is necessary to make sure you aren't doing the next (hold) action instead
  • immediately after a long press of the button ("held" on Hubitat)
  • immediately after two quick, successive presses of the button ("double tapped" on Hubitat)

I do not believe the Hubitat driver is doing anything special here--the button decides when to send what event, and there appears to be no way you could make "released" make sense here (it does not send something when the button is first pressed down and then something on release of that same press; i.e., Hubitat's driver is not doing any time-based calculations here...the only driver I'm aware of that does is the Lutron Pico drivers, an oddity they presumably made an exception for due to the better reliability of timing here compared to a mesh protocol).

Thank you,
However, I'm surprised that despite being able to detect a long press, it cannot detect a release. In order to detect a long press it must have, inside the device/chip code itself, a corresponding event to the "pressing" being stopped, hence it should be able to parse a released event... I don't see how it can know that the button is being held without distinguishing pressed and not-pressed (or released)...

There are many button devices which don't report both, many even report held before actually releasing the button. The combinations on how press/hold/release is (not) reported exist in all possible combinations of the three. As for the why you'd have to ask the manufacturers.

1 Like

I'm fully aware I'm being stubborn here but I can't shake it: how does the core programming of the device itself detects that the press has lasted longer than a simple push, then?

if must look like something like this:

if(digitalRead() == 1) // button pressed
{
startingTime = millis() // time stamp
while(millis() - startingTime < 2000 millis && digitalRead() == 1)
{
wait for as long as the digital port reads 1, meaning button is being pressed
}
if(millis() - startingTime < 300) // if elapsed time is less than 1 second
{
parse a "pushed" event
}
else if(millis() - startingTime >= 300) // if more than 1 second
{
then parse a "held" event
}

In other words the device core system must have a digitalRead() = 0 and a digitalRead() = 1 values and, therefore, should be able to parse a released option. The only issue seems that it has been decided to simply ignore this possibility within the core programming of the chipset itself and that's what bugs me: why? and, most of all, why most buttons do the same. I must be missing something, for sure, but I can't help think that a button is a the simplest device one can build... as a matter of fact I do have buttons built on my own and paired with my hub which I use on a daily basis. I only purchased those buttons because they have a nicer look...

Just because the device "tracks" something internally--and it undoubtedly does so it knows the difference between a push or hold--doesn't mean that it gets sent as a message over Zigbee.

2 Likes

1 second is an eternity for held, held is more natural when it's in the range of 250 to 500ms, it begins to be feel awkward after 750ms

3 Likes

Exactly!

And then we devices like a Lutron Pico Remote that only sends "Pushed" and "Released". In order for Hubitat to use "Held" for these devices, the Hubitat Driver has to implement the logic to infer whether the button was simply pushed, or held. This is why Pico remotes, on Hubitat, have a user selectable setting for how long the button must be 'held' for.

1 Like

Indeed, you stand me corrected! :slight_smile:

Hi @ogiewon,
If it can do that then it should be able to infer the released state too, shouldn't it? There's no way it can infer that the button has been held for a period of time without being able to detect the release of the button.