Apologies in advance for the long post. I'm new to HomeKit and Matter but not to development, I'm trying to write a SwiftUI app for my smart home to store all of my HomeKit and Matter setup barcodes along with other bits of information.
The intention is to scan the QR codes with my App and then save that QR payload in a simple Database along with other manually entered device details. Example payloads:
X-HM://00GWIN0B5PHPG <-- Eufy V120 HomeKit Camera
MT:GE.01-C-03FOPP6B110 <-- Moes GU10 Matter Bulb
I have it 99% working, my app is even able to discern the manual pairing code from the above payloads. However one of the key feature of this is that I want to open a device entry in my app and tap the HomeKit or Matter code displayed in my app and and either:
a) Ideally pass it off to the Apple Home app to initiate pairing just like the native Camera App can.
b) Create a custom flow in my app using the HomeKit or Matter API's to initiate paring from within my app.
So ideally just like the flow that happens when you scan a setup QR with the normal camera and tap "Open in Home". However I want to trigger this flow with just knowing the Payload and not with scanning it via the camera.
I was hoping there might be something as simple as a URL scheme that I could call with the payload as a variable and it then deep links and switches to the Home app, but I haven't found any info relating to this that actually works.
This is some code I have tried with the HomeKit API but this also results in an error:
import HomeKit
func startHomePairing(with setupCode: String) {
// Handle HomeKit setup
guard let payload = HMAccessorySetupPayload(url: URL(string: setupCode)!) else {
print("Invalid HomeKit setup code or format.")
return
}
let setupRequest = HMAccessorySetupRequest()
setupRequest.payload = payload
let setupManager = HMAccessorySetupManager()
// Perform the setup request and handle the result
setupManager.performAccessorySetup(using: setupRequest) { result, error in
if let error = error {
// Error handling: print the error details
print("Error starting setup: \(error.localizedDescription)")
// Print more details for debugging
print("Full Error: \(error)")
} else {
// Success: pairing was successful
print("Successfully launched Home app for HomeKit setup.")
}
}
}
But when passing in the QR payloads above it give the following ..
HomeKit Code
[0CAB3B05] Failed to perform accessory setup using request: Error Domain=HMErrorDomain Code=17 "(null)"
Matter Code
Failed to create HMSetupAccessoryPayload from setup payload URL MT:GE.01-C-03FOPP6B110: Error Domain=HMErrorDomain Code=3 "(null)"
I have added the "HomeKit" and "Matter Allow Setup Payload" capabilities to my app, I have also ensured I have these in the .plist ..
<key>NSHomeKitUsageDescription</key>
<string>Access required to HomeKit to initiate pairing for new accessories</string>
I also added a call to ensure my app appears in the Settings / Privacy / HomeKit section. I originally thought was a seemingly simple task, but I am really struggling with how to make it work!
Apologies in advance for the long post.
Having hit the 7000 word count on more than one occasion, you have nothing to be ashamed of. My only concern is that my reply may not live up to the standard you've set.
SO, let me start with the errors you've been getting from HomeKit:
HomeKit Code Domain=HMErrorDomain Code=17
That would be "HMErrorCodeInsufficientPrivileges", which then leads to here:
So ideally just like the flow that happens when you scan a setup QR with the normal camera and tap "Open in Home". However I want to trigger this flow with just knowing the Payload and not with scanning it via the camera.
Unfortunately, the answer here is basically "no, that's not possible", at least for HAP accessories. The issue here is actually that part of the security model of HAP is that acquiring the setup code should require some level of physical access to the accessory. For example, the specification requires that the setup code NOT be stored, accessible, or derivable by the accessory itself.
There is an entitlement that allows that requirement to be bypassed but it's managed by the MFi program and it's generally only granted to specific hardware vendors who are either:
-
Adding HomeKit support to an already shipping accessory, so there isn't any HomeKit setup code to scan.
-
Creating an accessory which has some kind of "inherent" physical limitation which would make the standard pairing process cumbersome/awkward.
Switching to the matter side:
Matter Code Error Domain=HMErrorDomain Code=3
That would be "HMErrorCodeInvalidParameter", which is what I think you'd get if you passed a matter payload into payload. The matter payload has a different format, which would go through matterPayload.
I haven't specifically tried it, but I'd expect it to work fine. While Matter has a physical security model similar to HomeKit ("photograph QR codes to prove access"), the specification is much more open and we don't enforce that security in the same way HomeKit does.
One quick comment on this:
b) Create a custom flow in my app using the HomeKit or Matter API's to initiate paring from within my app.
On the HomeKit side, I would STRONGLY caution you against trying to do "manual" HomeKit pairing. The history here is a bit complicated but the HomeKit framework was actually introduced in iOS 8.0 while Home.app wasn't released until iOS 10.0. Because of that, there is an "original" pairing process which does not use the system UI and which is somewhat under programmatic control. That flow has also never ACTUALLY been deprecated and probably does sort of work in iOS 18.
However, that flow is a horrible pain to work with. For example, WAC and HAP pairing are handled through separate discovery and pairing process, which is exactly as annoying and error prone as it sounds. In fact, the ENTIRE reason "addAndSetupAccessoriesWithCompletionHandler" and the variants we've since replaced it with were created is because the original flow was so painful. Similarly, the main reason the old flow hasn't been deprecated is simply that developers migrated away from the older flow so quickly that we never felt an real need to "push" developers toward the new API.
In any case, I wanted to warn you about this because if you dig into the API enough you can probably what looks like our special secret manual pairing flow. It's isn't secret or special, just old and unpleasant.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware