I am working on an app for a home automation device.
If I were using HomeKit exclusively I could add custom services or custom characteristics on standard services and these things would all be reported to my app via HomeKit. There is sample code from Apple that demonstrates how to do this.
When a Matter device is commissioned using HomeKit you might expect custom clusters and/or custom attributes in a standard cluster would be translated to appropriate HomeKit services and characteristics, but this doesn't appear to be the case.
Is there a way to have HomeKit do this?
If not it seems I would need to use Matter directly rather than via HomeKit to access custom features. But if I commission the device using Matter in my app then I understand a new fabric is created and the device would not show in the Home app. Maybe the user needs to commission the device twice, once with my custom app and once with the Home app? That seems like a poor user experience to me. Perhaps that is the price paid for using a cross-platform standard?
Is there a better way to get the same level of customization using Matter that I am able to get using HomeKit?
When a Matter device is commissioned using HomeKit you might expect custom clusters and/or custom attributes in a standard cluster would be translated to appropriate HomeKit services and characteristics, but this doesn't appear to be the case.
Is there a way to have HomeKit do this?
Yes, though the APIs involved are not entirely obvious.
The general process is that you can create a MTRDeviceController using specific parameters you get from HomeKit. That controller will then give you access to the relevant matter accessory through the HomeKit ecosystem, instead of needing to create your own ecosystem (which is how Matter.framework is typically used).
Note: Matter.framework has changed considerably over a very short period, so it's very possible that some of the specific details described may shift or change over time. Please explore the API and look for alternate paths before assuming the general approach here "doesn't work".
Getting into details, you'll create the MTRDeviceController controller using sharedController(withID:xpcConnect:). That method requires a controllerID and an xpcConnectBlock, both of which come from methods in HMHome.
Once you have your MTRDeviceController, you can then create an MTRBaseDevice using init(nodeID:controller:). The nodeID for that method come from the matterNodeID property of HMAccessory.
Two things to note about this process:
-
The MTRDeviceController you create here is NOT the same object you'd end up with if you created your own object for your own ecosystem. By design, large parts of it simply do not work- for example, you cannot commission an accessory "through" that object. Note that MTRBaseDevice will also not allow you to open a commissioning window. The role of this API path is SPECIFICALLY to provide access to HomeKit accessories through HomeKit's ecosystem, NOT facilitate broader ecosystem configuration.
-
The access you have through the MTRBaseDevice device is also somewhat limited. The issue here is that while the MTRBaseDevice itself should work fine, the MTRBaseDevice itself is not fully "compatible" with the all of the other classes in the matter framework, which contrains how you can use the object. Making that concrete, direct interaction with the accessory using the read/write/subscribe method of MTRDevice should work fine. However, if you create one of the higher level Matter device objects (for example, something like MTRClusterDoorLock) you'll find that the new object does't really work.
Note that while the usage restrictions on MTRBaseDevice usage (#2) are primarily a side effect of it's current implementation state (so they could change and improve over time), the commissioning limitations (#1) are an intentional design choice to prevent API abuse (and are unlikely to change).
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware