Skip to content

Expose button events from DDF - #8151

Merged
manup merged 1 commit into
dresden-elektronik:masterfrom
manup:buttonevents_ddf
Apr 1, 2025
Merged

Expose button events from DDF#8151
manup merged 1 commit into
dresden-elektronik:masterfrom
manup:buttonevents_ddf

Conversation

@manup

@manup manup commented Mar 29, 2025

Copy link
Copy Markdown
Member

We already have a few DDFs which describe buttons and events. This PR exposes these to the introspect API.

WIP: Currently generic button names are returned in the API, will be fixed soon to return the actual names given in the DDF.

We already have a few DDFs which describe buttons and events. This PR exposes these to the introspect API.
@manup manup added this to the v2.29.3-beta milestone Mar 29, 2025
@ebaauw

ebaauw commented Mar 29, 2025

Copy link
Copy Markdown
Collaborator

Not sure what you mean by "introspect API"? I'm hoping buttons and possible event values will be exposed under /sensors/n/capabilities/buttons or something similar.

@manup

manup commented Mar 31, 2025

Copy link
Copy Markdown
Member Author

The introspection API is an experimental API which predates the capabilities (iirc). For switches which have entries in the button_maps.json it returned the buttons and events.

For example to query the button on the Hue Dimmer switch:

GET localhost/api/12345/devices/00:17:88:01:09:a6:06:d1-01-fc00/state/buttonevent/introspect
{
  "buttons": {
    "1": {
      "name": "Button 1"
    },
    "2": {
      "name": "Button 2"
    },
    "3": {
      "name": "Button 3"
    },
    "4": {
      "name": "Button 4"
    }
  },
  "type": "int32",
  "values": {
    "1000": {
      "action": "INITIAL_PRESS",
      "button": 1
    },
    "1001": {
      "action": "HOLD",
      "button": 1
    },
    "1002": {
      "action": "SHORT_RELEASE",
      "button": 1
    },
    "1003": {
      "action": "LONG_RELEASE",
      "button": 1
    },
    "2000": {
      "action": "INITIAL_PRESS",
      "button": 2
    },
    "2001": {
      "action": "HOLD",
      "button": 2
    },
    "2002": {
      "action": "SHORT_RELEASE",
      "button": 2
    },
    "2003": {
      "action": "LONG_RELEASE",
      "button": 2
    },
    "3000": {
      "action": "INITIAL_PRESS",
      "button": 3
    },
    "3001": {
      "action": "HOLD",
      "button": 3
    },
    "3002": {
      "action": "SHORT_RELEASE",
      "button": 3
    },
    "3003": {
      "action": "LONG_RELEASE",
      "button": 3
    },
    "4000": {
      "action": "INITIAL_PRESS",
      "button": 4
    },
    "4001": {
      "action": "HOLD",
      "button": 4
    },
    "4002": {
      "action": "SHORT_RELEASE",
      "button": 4
    },
    "4003": {
      "action": "LONG_RELEASE",
      "button": 4
    }
  }
}

In the Phoscon App we use this to build a generic UI widget with 4 buttons and due the known actions of the switch, respective rules can be created.

The API output is a bit clunky but I wanted the existing API to keep working for now.


The capabilities are indeed a good place to expose the same information. Ideally in a more dense:

capabilities/buttons

{
  "1": {
    "name": "Middle I/O button",
    "actions": { "PRESS", "HOLD", "..." }
  }
}

Or something like that?

Right now with this PR the data is parsed from the buttons and buttonevents attributes in the DDFs (see Hue Dimmer switch) but I'd like to deprecaqte that in favor of a more dense format.

@ebaauw

ebaauw commented Mar 31, 2025

Copy link
Copy Markdown
Collaborator

Or something like that?

If we just use numbers for the button IDs (related to the x in x00y), we might as well expose them as array instead of map. If we only expose values for the actions (the y in x00y), that should be an array as well (the example is not syntactically valid JSON). Do we want mnemonics for the actions instead of numeric values? API clients need to know the numeric values anyway to understand the state/buttonevent values, but I suppose an additional mapping is doable.

@manup

manup commented Mar 31, 2025

Copy link
Copy Markdown
Member Author

I'd also prefer numeric values, we can expose the numeric -> string mapping also on some endpoint but don't need to return them for every sensor/device object.

{
  "1": [0,1,2,3]
}

My favorite would be just two numbers: (button, actions bitmap):

{
  "1": 15,
  "2": 15
}

Here the second number is just a bitmap, where the bit represents the action, in this case 15 = PRESS,SHORT_RELEASE, HOLD, LONG_RELEASE. Javascript safely support 52-bits so we have 52 possible actions. But perhaps this is a bit cryptic :)

@ebaauw

ebaauw commented Mar 31, 2025

Copy link
Copy Markdown
Collaborator
{
  "1": [0,1,2,3]
}

Still using a map for the buttons. Might be needed if we have devices with gaps in the button numbers, but I'm not aware of any.

{
  "1": 15,
  "2": 15
}

Could even be a simple array of bitmaps [15, 15] to make it more cryptic (is there a prize for the most cryptic proposal?).

For me handling bitmaps vs arrays doesn't make much of a difference; I support the bitmap is easier on the database, but we'd probably use a bitmap internally and generate the array in the API output anyways.

Note that the supported buttonevent values might depend on the device configuration (cf. the Hue wall switch module, single vs dual rocker vs push button). Until now, I felt that, capabilities shouldn't change without a firmware update, but using capabilities to expose the possible button event values makes more sense than using config.

Related, we should also normalise the use of button events. Remember, the Hue dimmer family sends a series of INITIAL_PRESS (x000), SHORT_RELEASE (x002) on a short press and a series of INITIAL PRESS (x000), HOLD (x0001), HOLD, ..., LONG_RELEASE (x003) on a long press, where the HOLD repeats every second.

I need to know whether a HOLD might repeat or not. Alternatively we could use different values for repeating vs non-repeating HOLDs.

I expect an INITIAL_PRESS to be followed by SHORT_RELEASE or (HOLD and) LONG_RELEASE. I expect HOLD to be followed by LONG_RELEASE. In other words: if a switch only sends a command on press, it should be mapped to SHORT_RELEASE rather than to INITIAL_PRESS. Alternatively, we could distinguish between a standalone PRESS vs an INITIAL_PRESS as start of a series. I suppose that's also easier on non-Hue actions, like DOUBLE_PRESS, TREBLE_PRESS, QUADRUPLE PRESS, etc.

@manup

manup commented Mar 31, 2025

Copy link
Copy Markdown
Member Author

Hehe I'm a sucker for compressed minimal formats. The database doesn't need to hold this data since this is only parsed from DDFs in RAM for the session, no need to store it twice.

I think since we control the buttons numbering, there shouldn't be any gaps and even [15,15] would work. My only concern with this is if we want to expose more about a button, e.g. a button name, which can be helpful to build UIs.

For continuous button press we may steal from keyboard operating system APIs. Usually here when a key is pressed and events fire while it is pressed a counter is also part of the message.

{
  "buttonevent": 1001,
  "buttonrepeat": 5
}

(or eventduration?)

On the other hand due the lastchanged timestamp and dx conditions we already kind of have this.

@ebaauw

ebaauw commented Mar 31, 2025

Copy link
Copy Markdown
Collaborator

I can detect repeated x001 events alright. We increased the granularity of state/lastupdated to milliseconds for this. And, indeed, for the Hue dimmer family we also have state/eventduration (which is reported by the device itself).

What I meant is: I want to know whether the device is capable of sending repeated x001 button events. If it is, I expose a "repeat" setting, which causes a separate Short Press in HomeKit for each x001 event, rather than a single Long Press for the entire x000, x001, ..., x003 series. Particularly useful to control dimming or relative volume for non-Zigbee devices, using Zigbee controllers.

@manup

manup commented Mar 31, 2025

Copy link
Copy Markdown
Member Author

Would be good to have this info on a per button base. In case of the hue dimmer all 4 buttons are able to send repeated events, but there can be devices where only a subset of buttons support this and other buttons are simpler.

Not sure if it's the best approach but we could list a "special action" like x0?? which is never actually send but notifies the client that x001 events are indeed repeated 🤔

@manup

manup commented Apr 1, 2025

Copy link
Copy Markdown
Member Author

Merging for now to get introspection working. A followup PR will address the capabilities.

@manup
manup merged commit 55fb23d into dresden-elektronik:master Apr 1, 2025
@manup
manup deleted the buttonevents_ddf branch April 1, 2025 14:42
@brientim

brientim commented Apr 9, 2025

Copy link
Copy Markdown

Firstly thank you for the quick action and PR.

I have installed 2.29.03 released 8 Apr 2024 and I can confirm that hue switches are now displaying using introspection APi.

I note the transition to use DDF “configuration” will be addressed a separate PR and I think that will be a real positive outcome in addressing the discrepancy where the switch buttons are incorrectly mapped in the button_map.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants