project-chip / connectedhomeip

Matter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.
https://buildwithmatter.com
Apache License 2.0
7.25k stars 1.93k forks source link

[Darwin] Unable to read attributes using MTRBaseCluster classes over XPC #28826

Open pdrtrifork opened 11 months ago

pdrtrifork commented 11 months ago

Reproduction steps

We are currently working on an iPhone app that is supposed to communicate with specific Matter devices using the HomeKit and Matter frameworks.

I am able to access device attributes using [MTRBaseDevice readAttributesWithEndpointID:clusterID:attributeID:params:queue:completion:], but not using e.g. [MTRBaseClusterBasicInformation readAttributeLocationWithCompletion:] (location is just an example).

  1. Get a HMHome instance from HMHomeManager
  2. Find an accessory with a matterNodeID
  3. Instantiate a MTRDeviceController using MTRDeviceController.sharedController(withID:,xpcConnect:)
  4. Instantiate a MTRBaseDevice using MTRBaseDevice(nodeID:,controller:)
  5. Instantiate a MTRBaseClusterBasicInformation using MTRBaseClusterBasicInformation(device:,endpointID: 0, queue: DispatchQueue.main)
  6. Invoke e.g. baseCluster.readAttributeLocation(completion:)

Below are the important pieces of code:

let defaultLog = Logger()
var controller:MTRDeviceController? = nil
var home:HMHome? = nil
var device:MTRBaseDevice? = nil
var basicInformationCluster:MTRBaseClusterBasicInformation? = nil

// ...

let matterId:NSString = self.home!.matterControllerID as NSString
self.controller = MTRDeviceController.sharedController(withID: matterId, xpcConnect: home!.matterControllerXPCConnectBlock)

let accessoryNodeID = 1660509092 as NSNumber
self.device = MTRBaseDevice(nodeID: accessoryNodeID, controller: self.controller!)
self.basicInformationCluster = MTRBaseClusterBasicInformation(device: device!, endpointID: 0, queue: DispatchQueue.main)

// Not working
defaultLog.info("Getting location using readAttributeLocation(completion:)")
self.basicInformationCluster!.readAttributeLocation(completion: { (location:String?, error:Error?) in
    if let error = error {
        defaultLog.error("readAttributeLocation(completion:), error = \(error)")
    }
    if let location = location {
        defaultLog.info("readAttributeLocation(completion:), location=\(location)")
    }
})

// Not working
defaultLog.info("Getting location using readAttributeLocation()")
Task {
    do {
        let location = try await self.basicInformationCluster!.readAttributeLocation()
        defaultLog.info("readAttributeLocation(), location=\(location)")
    } catch {
        defaultLog.error("readAttributeLocation() failed")
    }
}

// Working
defaultLog.info("Getting location using readAttributes(withEndpointID:clusterID:attributeID:params:queue:)")
self.device!.readAttributes(withEndpointID: 0, clusterID: 0x0028, attributeID: 1, params: nil, queue: DispatchQueue.main) { (values:[[String : Any]]?, error:Error?) in
    if let error = error {
        defaultLog.error("readAttributes(withEndpointID:clusterID:attributeID:params:queue:), error = \(error)")
    }
    if let values = values {
        values.forEach { v in
            if let data = v[MTRDataKey] as? NSDictionary, let path = v["attributePath"] as? MTRAttributePath, let value = data[MTRValueKey] as? NSObject {
                defaultLog.info("readAttributes(withEndpointID:clusterID:attributeID:params:queue:), \(path) = \(value)")
            }
        }
    }
}

Platform

darwin

Platform Version(s)

iOS 16.6, Xcode 14.3.1 (14E300c)

Type

Manually tested with SDK

(Optional) If manually tested please explain why this is only manually tested

We created an iPhone app with the minimal amount of code to access Apple Home, and get an device controller and device using HomeKit and Matter SDK's.

Anything else?

No response

bzbarsky-apple commented 11 months ago

Yes, the MTRBaseCluster classes do not work with XPC-remoted MTRBaseDevice instances. They do work with non-remoted MTRBaseDevice.

They should probably just fail init when initializing with a remoted MTRBaseDevice.... @kpark-apple unless you have plans to make that part work?

pdrtrifork commented 11 months ago

Thank you for the swift reply. We will just use [MTRBaseDevice readAttributesWithEndpointID:clusterID:attributeID:params:queue:completion:] for the time being.

Gernot commented 10 months ago

Thank you for reporting this. We are also working on an app that accesses Matter via HomeKit/XPC, and I am very surprised about the limitations. I expected unrestricted access to everything the Matter framework provides and am very surprised to find issues like this.

bzbarsky-apple commented 10 months ago

The XPC bits are extremely limited so far. They don't even support all function on MTRBaseDevice. In my opinion we should not have released them at all in their current state, but ...

woody-apple commented 9 months ago

Note, this API is likely to be deprecated soon, and we will encourage folks to use MTRDevice (with similar functionality).

max-vyshnevskyi commented 5 months ago

Greetings @bzbarsky-apple @woody-apple @kpark-apple! Is there a way to open the commissioning window for XPC-remoted MTRBaseDevice / MRTDevice instances? Currently, I'm encountering an "MTRBaseDevice / MRTDevice doesn't support openCommissioningWindowWithDiscriminator over XPC" error. My goal is to add all Matter accessories from the Apple Home to our fabric. Could you possibly suggest an alternative approach to accomplish this? Unfortunately, I'm unable to find relevant documentation for this case.

bzbarsky-apple commented 4 months ago

Is there a way to open the commissioning window for XPC-remoted MTRBaseDevice / MRTDevice instances?

Not via the convenience APIs. You'd have to explicitly send OpenCommissioningWindow commands.