Weird HomeKit characteristic updates

My application essentially

  • goes through all accessories in a home (with some filtering to select just some of them)
  • goes through all services of an accessory
  • goes through all characteristics of a service (with some filtering, dtto)

If the acc is reachable, non-blocked, and if the characteristic has the SupportsEventNotification property, then (and only then)

  • my controller is set as the accessory delegate
  • the characteristic is sent the enableNotification:completionHandler: message
  • my controller, of course, implements the accessory:service:didUpdateValueForCharacteristic: method.

It works well most time, but I have bumped into two separate problems:

(i) occasionally, although a device does change its characteristic all right in reality (typically triggered by an automation and observed personally), I do not get the appropriate accessory:service:didUpdateValueForCharacteristic: message at all.

Is that normal? I sort of presume it would happen, if there's some communication glitch inside of the HomeKit ecosystem, right?

The best way to alleviate this problem would be to set up a timer and e.g., once a minute poll all observed characteristics using readValueWithCompletionHandler:, and if the current value differs from the previously seen one, assume it did change and simulate the update internally, right? Or is there a better approach?

(ii) what seems to me even more weird, occasionally I get the accessory:service:didUpdateValueForCharacteristic: message for a characteristic which I did not observe (it never was sent enableNotification:completionHandler:).

The solution is of course trivial, I simply ignore these superfluous updates, but I wonder: is it sort of normal, or does that mean my application must have a bug somewhere?

Thanks!

Answered by DTS Engineer in 908473022

(i) Occasionally, although a device does change its characteristic all right in reality (typically triggered by an automation and observed personally), I do not get the appropriate accessory:service:didUpdateValueForCharacteristic: message at all. Is that normal? I sort of presume it would happen, if there's some communication glitch inside of the HomeKit ecosystem, right?

Basically, yes, that's not unusual. Determining EXACTLY what happens can be a bit painful, but, off the top of my head, it can happen because:

  • Communication issues mean you "missed" the notification.

  • The accessory itself is what actually generates the notification, and not all accessories ACTUALLY generate a notification for every change that occurs, even if the characteristic itself supports notifications.

The best way to alleviate this problem would be to set up a timer and, e.g., once a minute poll all observed characteristics using readValueWithCompletionHandler:, and if the current value differs from the previously seen one, assume it did change and simulate the update internally, right?

Yes, though I'd also recommend thinking about how the user actually interacts with your app and how important the "current" state is within that context. The issue here is that HomeKit app developers spend a lot of time staring at their app, which means they tend to be very annoyed/aware if/when its state doesn't match reality. The problem is that basically "no one" uses HomeKit like that— they open the app, perform one or more actions, then close it again. That doesn't mean getting the current state has no value*, but it does mean that focusing too much on the issue can be counterproductive.

*If you watch closely, you can see Home.app do it when it's opened

(ii) What seems to me even more weird, occasionally I get the accessory:service:didUpdateValueForCharacteristic: message for a characteristic which I did not observe (it never was sent enableNotification:completionHandler:). The solution is of course trivial; I simply ignore these superfluous updates, but I wonder: is it sort of normal, or does that mean my application must have a bug somewhere?

Normal as well. Again, determining the EXACT cause is tricky, but the common cause here is that when an accessory doesn't have an active connection, it notifies of "changes" but updates its GSN (Global State Number). That value change then triggers a reconnect and, as part of the reconnection process, they then read the entire state of the accessory. That can then trigger a "didUpdateValueForCharacteristic" message back to your app to let you know about the "change".

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Accepted Answer

(i) Occasionally, although a device does change its characteristic all right in reality (typically triggered by an automation and observed personally), I do not get the appropriate accessory:service:didUpdateValueForCharacteristic: message at all. Is that normal? I sort of presume it would happen, if there's some communication glitch inside of the HomeKit ecosystem, right?

Basically, yes, that's not unusual. Determining EXACTLY what happens can be a bit painful, but, off the top of my head, it can happen because:

  • Communication issues mean you "missed" the notification.

  • The accessory itself is what actually generates the notification, and not all accessories ACTUALLY generate a notification for every change that occurs, even if the characteristic itself supports notifications.

The best way to alleviate this problem would be to set up a timer and, e.g., once a minute poll all observed characteristics using readValueWithCompletionHandler:, and if the current value differs from the previously seen one, assume it did change and simulate the update internally, right?

Yes, though I'd also recommend thinking about how the user actually interacts with your app and how important the "current" state is within that context. The issue here is that HomeKit app developers spend a lot of time staring at their app, which means they tend to be very annoyed/aware if/when its state doesn't match reality. The problem is that basically "no one" uses HomeKit like that— they open the app, perform one or more actions, then close it again. That doesn't mean getting the current state has no value*, but it does mean that focusing too much on the issue can be counterproductive.

*If you watch closely, you can see Home.app do it when it's opened

(ii) What seems to me even more weird, occasionally I get the accessory:service:didUpdateValueForCharacteristic: message for a characteristic which I did not observe (it never was sent enableNotification:completionHandler:). The solution is of course trivial; I simply ignore these superfluous updates, but I wonder: is it sort of normal, or does that mean my application must have a bug somewhere?

Normal as well. Again, determining the EXACT cause is tricky, but the common cause here is that when an accessory doesn't have an active connection, it notifies of "changes" but updates its GSN (Global State Number). That value change then triggers a reconnect and, as part of the reconnection process, they then read the entire state of the accessory. That can then trigger a "didUpdateValueForCharacteristic" message back to your app to let you know about the "change".

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks a lot!

As for

how the user actually interacts with your app and how important the "current" state is within that context

well this is the very private local app of mine we are debating elsewhere (https://developer.apple.com/forums/thread/849339) and the one and only user is yours truly :)

Its main purpose is to create and keep a log of (a) all the temperatures[1], (b) closely related characteristics (like e.g., a power outlet which controls a heater, or the current state of a radiator valve).

[1] but for HomePod's, whose API is private. I've filled a feature request FB21802284, but actually, never mind that; I've simply placed a cheap temperature sensor nearby :)

As for the reason why I do that, I am working on my own home heating control, tailored to my own needs. Among others, I need to analyse the previous temps. None of the thermostats out there which I've checked worked the way I'd like to, so I am going to DIY (well DIMyself :))

Given that, the current values per se are not that important, and missing a temperature event or two is a small issue. Contrariwise, alas, missing an event from a power outlet is sort of inconvenient, for I would not know that the appropriate heater was on (or off) at all.

Weird HomeKit characteristic updates
 
 
Q