I can't find a way to create an event trigger with a presence-based predicate
- ideally for a particular user at home;
- or at least, for all users at home.
Just for the record, the rationale: I need to keep the heating on in the user's private room when he is at home, off when he is not. The idea is to have a trigger based on a low temperature event (I can do that and works all right), which would then check whether the user is at home through the predicate; if so, it would open the radiator valve (the action also tested and also working all right); if not, it would do nothing.
How to?
Since I could find no API to create an HMPresenceEvent for a particular user, I've set it up in the Home application, and tried to use it this way (I happen to have only one such at the moment in Home, so there's no need to check the attributes):
HMPresenceEvent *pevent;
for (HMEventTrigger *t in home.triggers) if ([t isKindOfClass:HMEventTrigger.class])
for (HMPresenceEvent *e in t.events) if ([e isKindOfClass:HMPresenceEvent.class]) {
pevent=[e copy];
break;
}
NSPredicate *p=[HMEventTrigger predicateForEvaluatingTriggerWithPresence:pevent];
HMEventTrigger *et=[[HMEventTrigger alloc] initWithName:@"TEST PRESENCE" events:... endEvents:nil recurrences:nil predicate:p];
alas, this raises the “NSInvalidArgumentException: Invalid parameter; (user info absent)” exception. Looks like copy loses this information somehow?!? Without appropriate public APIs one can't say :(
(Since I can set up these events in the Home application freely with any kinds of action, it seems to be patently absurd not to open these APIs for privacy reasons, but that's another question, not for this ticket.)
Anyway, I've tried to resort to checking for “all users at home” through
pevent=[[HMPresenceEvent alloc] initWithPresenceEventType:HMPresenceEventTypeAtHome presenceUserType:HMPresenceEventUserTypeHomeUsers];
where HMPresenceEventUserTypeHomeUsers is documented as “Presence of all home users”. Nevertheless, when I log out the result, I get just “any user“:
[Presence-Event: type: HMPresenceTypeAnyUserAtHome, mode: HMPresenceEventActivationGranularityHome]
That's unusable for me. I need to check for presence of all users (if checking for a particular one is really forbidden for some inexplicable reason).
Please help. How to properly set up a trigger predicate for (ideally) a given specific HMUser, or at the very least, for a presence of all registered home users. Thanks!
I can't find a way to create an event trigger with a presence-based predicate
So, adding some context, as it was originally envisioned, HomeKit was intended to provide a shared API that would allow any HomeKit app to interact with the user home through a single, common API.
Unfortunately, that's not how things worked out. With the benefit of hindsight, the problem was that because we didn't initially implement Home.app, we didn't really "know" how/what everything should work, which meant the framework doesn't actually work the way it turned out it "should". As the most glaring example, it's now pretty clear that the central abstraction of the framework should be a HMService, NOT HMAccessory.
In any case, once Home.app came into existence, the focus also shifted from providing that "common" data set every client could interact with into providing useful end user features, even if they couldn't/wouldn't be exposed to other apps. One thing to understand here is that the vast majority of HomeKit apps are vendor specific app that primarily exist to support that vendors accessories. There are a few "general purpose" apps that do provide "full" control (like Home.app), but many of those were actually created by our original hardware vendors who needed a general control app... because Home.app didn't exist.
The result of all this is that, yes, Home.app has significant functionality that isn't exposed through the public API and may never be, as that simply isn't really one of the teams goals and hasn't been for a many, many years.
Getting into some specifics:
Since I could find no API to create an HMPresenceEvent for a particular user
This was never exposed as API due to privacy concerns.
alas, this raises the “NSInvalidArgumentException: Invalid parameter; (user info absent)” exception. Looks like copy loses this information somehow?!? Without appropriate public APIs one can't say :(
Yes. The object you're interacting with through the public API isn't the same object Home.app interacted with, which means things don't translate properly into the public API. Unfortunately, all I can really recommend here is that you don't interact with automations you didn't create.
That's unusable for me. I need to check for presence of all users (if checking for a particular one is really forbidden for some inexplicable reason).
So, what you're asking for doesn't exist.
where HMPresenceEventUserTypeHomeUsers is documented as “Presence of all home users”.
Here is what the HMPresenceEventUserTypeHomeUsers class reference says:
"All users associated with a home trigger a presence event."
That is, any user who's associated with the home will trigger a presense event, not all of them being in the home at the same time. Note that the type "HMPresenceTypeAnyUserAtHome" is the private internal type that represents this particular type. It just happens to have a more accurate name then the public event.
That jumping back to here:
ideally for a particular user at home;
In terms of the public API, this should work if the user you want the automation to work for sets up the automation using "HMPresenceEventUserTypeCurrentUser". That is, the two public option here are:
-
HMPresenceEventUserTypeHomeUsers-> Any of the users in the home will trigger the automation.
-
HMPresenceEventUserTypeCurrentUser-> "I" (meaning, the user setting up the automation) will trigger the event.
...and what you can't do in the public API is setup an automation that's tied to some other user.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware