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.44k stars 1.99k forks source link

[BUG] Commission Fail with error "Inet Layer shutdown","BLE shutdown","System Layer shutdown","Discovery timed out","Mdns: Browse failure (src/platform/Darwin/DnssdImpl.cpp:412: CHIP Error 0x00000074: The operation has been cancelled)","XPC connection invalid" #35125

Closed JoeyYang2010 closed 2 months ago

JoeyYang2010 commented 2 months ago

Reproduction steps

Hi there: Below is my sample code, but I can not commission a sensor, the error is as below:

Inet Layer shutdown
BLE shutdown
System Layer shutdown
Can't start on new fabric that matches existing fabric
Creating NSError from /Library/Caches/com.apple.xbs/Sources/CHIPFramework/connectedhomeip/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm:834: CHIP Error 0x00000003: Incorrect state
Discovery timed out
Mdns: Browse failure (src/platform/Darwin/DnssdImpl.cpp:412: CHIP Error 0x00000074: The operation has been cancelled)
status MTRCommissioningStatus
XPC connection invalid

=============================== Code:

//
//  ViewController.swift
//  SampleHybridApp
//
//  Created by Ömer Faruk Öztürk on 18.07.2020.
//  Copyright © 2020 Omer Faruk Ozturk. All rights reserved.
//

import UIKit
import WebKit
import MatterSupport
import Matter
class ViewController: UIViewController {
    public var sController: MTRDeviceController?
    private var webView: WKWebView!
    private let callbackName = "callback"
    let matterQueue = DispatchQueue(label: "com.zigbee.chip.qrcodevc.callback", qos: .userInteractive)
    override func viewDidLoad() {
        super.viewDidLoad()
        Task {
            await self.setup()
        }

    }
    func setup() async {
        test()
    }
    func test() {
        let request = MatterAddDeviceRequest(
            topology: .init(ecosystemName: "RRRRRR", homes: [
                .init(displayName: "R11111"), .init(displayName: "R222222")
            ])
        )
        let topology = MatterAddDeviceRequest.Topology(ecosystemName: "RRRRRR", homes: [MatterAddDeviceRequest.Home(displayName: "R11111")])
        Task
        {
            do
            {
                print(1)
//                try await request.perform()
                print(2)
                let grpId = "123"
                let testKeys = MTRCSRKeys(groupId: grpId)
                let params = MTRDeviceControllerStartupParams(ipk: testKeys.ipk, fabricID: 1, nocSigner: testKeys)
                params.vendorID = NSNumber(value: 123)
//                params.operationalCertificateIssuerQueue = self.matterQueue
                let setupPayload : MTRSetupPayload
                do {
                    setupPayload = try MTRSetupPayload(onboardingPayload: "3228-130-8191" )
                } catch {
                    return
                }
                let factory = MTRDeviceControllerFactory.sharedInstance()
                let storage = ESPMatterStorage.shared
                let factoryParams = MTRDeviceControllerFactoryParams(storage: storage)
                do {
                    // Start the controller factory.
                    try factory.start(factoryParams)
                } catch {
                    // Handle any errors.
                    print("err",error)
                }
                let controller: MTRDeviceController
                do {
                    print(6)
                    controller = try factory.createController(onNewFabric: params)
                    print(6.1)
                    controller.setDeviceControllerDelegate(self, queue: self.matterQueue)
                    do {
                        try controller.setupCommissioningSession(with: setupPayload, newNodeID: 1)
                    }
                    catch {
                        print("ERROR pairAccessory: \(error.localizedDescription)")
                    }
                } catch {
                    print(8.1,error)
                    controller = try factory.createController(onExistingFabric: params)
                    print(8.2)
                    controller.setDeviceControllerDelegate(self, queue: self.matterQueue)
                    try controller.setupCommissioningSession(with: setupPayload, newNodeID: 1)
                    print(8)
                }
            }
            catch
            {
                print("Failed to set up a device with error: \(error)")
            }
        }
    }
    func sendEvent2WebToIncrementSumByOne() {
        webView.evaluateJavaScript("addToSum('1')", completionHandler: nil)
        print("\"addToSum\" event sent to web.")
    }
}

extension ViewController: WKScriptMessageHandler {

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        // Handle the events coming from javascript.
        guard message.name == callbackName else { return }

        // Access properties through the message body.
        print("Message received from Web: \"\(message.body)\"")

        // send back event to web
        sendEvent2WebToIncrementSumByOne()
    }
}

extension ViewController: WKUIDelegate {
    func webView(_ webView: WKWebView,
                 runJavaScriptAlertPanelWithMessage message: String,
                 initiatedByFrame frame: WKFrameInfo,
                 completionHandler: @escaping () -> Void) {

        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        let title = NSLocalizedString("OK", comment: "OK Button")
        let ok = UIAlertAction(title: title, style: .default) { (action: UIAlertAction) -> Void in
            alert.dismiss(animated: true, completion: nil)
        }
        alert.addAction(ok)
        present(alert, animated: true)
        completionHandler()
    }
}
@available(iOS 16.1, *)
class MyMatterAddDeviceExtensionRequestHandler: MatterAddDeviceExtensionRequestHandler
{
    override init() {
        print("aaaa")
        super.init()
    }
    override func validateDeviceCredential(_ deviceCredential: MatterAddDeviceExtensionRequestHandler.DeviceCredential) async throws
    {
        // Performs verification and attestation checks.
        print("validateDeviceCredential \(deviceCredential)")
    }

    override func selectWiFiNetwork(from wifiScanResults: [MatterAddDeviceExtensionRequestHandler.WiFiScanResult]) async throws -> MatterAddDeviceExtensionRequestHandler.WiFiNetworkAssociation {
        // If your application would like to specify a nondefault Wi-Fi network.

        let shouldSelectNetwork = true

        if shouldSelectNetwork {
            // Return the SSID and credentials known to your application.
            let ssid = Data()
            let credentials = Data()
            print("return network \(ssid) \(credentials)")
            return .network(ssid: ssid, credentials: credentials)
        } else {
            print("return default network")
            return .defaultSystemNetwork
        }
    }

    // Override this method to select a specific Thread network.
    override func selectThreadNetwork(from threadScanResults: [MatterAddDeviceExtensionRequestHandler.ThreadScanResult]) async throws -> MatterAddDeviceExtensionRequestHandler.ThreadNetworkAssociation {
        // If your application would like to specify a nondefault Thread network.
        let shouldSelectNetwork = true
        if shouldSelectNetwork {
            let extendedPANID = UInt64()
            return .network(extendedPANID: extendedPANID)
        } else {
            return .defaultSystemNetwork
        }
    }

    // Override this method to return the rooms in the home.
    override func rooms(in home: MatterAddDeviceRequest.Home?) async -> [MatterAddDeviceRequest.Room] {
        let rooms: [String] = ["Living Room", "Bedroom", "Office"];
        print("bbb")
        return rooms.map { MatterAddDeviceRequest.Room(displayName: $0) }
    }

    override func configureDevice(named name: String, in room: MatterAddDeviceRequest.Room?) async {
        // Use this function to configure the (now) commissioned device with the given name and room.
        // Configure the device with selected attributes.
        print("Configure device")
        class accessory {
            var name = "joey name"
            var roomName = "room name"
        }
        let accessory1 = accessory()
        accessory1.name = name
        accessory1.roomName = room?.displayName ?? "Room Name Not Available"
    }

    override func commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID) async throws
    {
//        os_log(.default, "Received request to fetch rooms in home: (String(describing: home))")
        print("Home: \(String(describing: home)) " + "payload: \(onboardingPayload) "  + "commissionID: \(commissioningID)")
    }
}
@available(iOS 16.4, *)
extension ViewController: MTRDeviceControllerDelegate {
    func controller(_ controller: MTRDeviceController, statusUpdate status: MTRCommissioningStatus) {
        // Check for `MTRCommissioningStatus.failed`, and if so, handle it.
        print("status",status)
    }

    func controller(_ controller: MTRDeviceController, commissioningComplete error: Error?) {
        // Check for error and handle it.
        // If no error, node is commissioned with `nodeID` as its node ID.
        print("commissioning complete",error)
    }

    func controller(_ controller: MTRDeviceController,commissioningSessionEstablishmentDone error: Error?) {
        // Check for error and handle it.
        print("commissioningSessionEstablishmentDone",error?.localizedDescription)
        do {
            // `myDesiredNodeID` must match the node ID passed to
            // `setupCommissioningSessionWithPayload`.
            try controller.commissionNode(withID: 1,commissioningParams: MTRCommissioningParameters())
        } catch {
            // Handle failure to start commissioning the node.
            print("errrr",error)
        }

        // Keep waiting for `commissioningComplete`.
    }
}
@available(iOS 16.4, *)
extension ViewController: MTROperationalCertificateIssuer {

    /// should skip attestation
    var shouldSkipAttestationCertificateValidation: Bool {
        print("shouldSkipAttestationCertificateValidation")
        return true
    }

    /// Issue operational certificate
    /// - Parameters:
    ///   - csrInfo: CSR info
    ///   - attestationInfo: attestation info
    ///   - controller: controller
    ///   - completion: completion
    func issueOperationalCertificate(forRequest csrInfo: MTROperationalCSRInfo, attestationInfo: MTRDeviceAttestationInfo, controller: MTRDeviceController, completion: @escaping (MTROperationalCertificateChain?, Error?) -> Void) {
        // Issue your certificates here.
        print("Issue NOC")
    }
}
extension ViewController: MTRDeviceAttestationDelegate {

    /// Device attestation completed
    /// - Parameters:
    ///   - controller: controller
    ///   - opaqueDeviceHandle: opaque device handle
    ///   - attestationDeviceInfo: attestation device info
    ///   - error: error
    func deviceAttestationCompleted(for controller: MTRDeviceController, opaqueDeviceHandle: UnsafeMutableRawPointer, attestationDeviceInfo: MTRDeviceAttestationDeviceInfo, error: Error?) {
        print("abc")
        do {
            try controller.continueCommissioningDevice(opaqueDeviceHandle, ignoreAttestationFailure: true)
        } catch {
            print(error.localizedDescription)
        }
    }

    /// Device attestation failed
    /// - Parameters:
    ///   - controller: controller
    ///   - opaqueDeviceHandle: opaque device handle
    ///   - error: error
    func deviceAttestationFailed(for controller: MTRDeviceController, opaqueDeviceHandle: UnsafeMutableRawPointer, error: Error) {
        print("abcd")
        do {
            try controller.continueCommissioningDevice(opaqueDeviceHandle, ignoreAttestationFailure: true)
        } catch {
            print(error.localizedDescription)
        }
    }
}

Bug prevalence

Each time

GitHub hash of the SDK that was being used

2024/4/19 master version

Platform

darwin

Platform Version(s)

No response

Anything else?

No response

bzbarsky-apple commented 2 months ago
                setupPayload = try MTRSetupPayload(onboardingPayload: "3228-130-8191" )

Where is that coming from?

What you should be doing is using the onboardingPayload passed to this:

    override func commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID) async throws

to do your commissioning attempt.

JoeyYang2010 commented 2 months ago

@bzbarsky-apple try await request.perform(), when I run this code so that I can get the onboardingPayload, the code will freeze so I input the Matter device code directly, I think that should can work?

JoeyYang2010 commented 2 months ago

Update the latest issue, class RequestHandler: MatterAddDeviceExtensionRequestHandler { override func commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID) async throws

is never called, so I can not get the onboardingPayload, I checked many bugs, but no clear response about this problem.

bzbarsky-apple commented 2 months ago

so I input the Matter device code directly, I think that should can work?

If it's the right code. The right code in this case is the one generated when the new commissioning window is opened, not the one printed on the device.

JoeyYang2010 commented 1 month ago

@bzbarsky-apple Did we have sample code using MatterSupport and Matter framework to commission device? Or do you know if I don't have a homepod or other apple's gateway, it may cause this issue?

JoeyYang2010 commented 1 month ago

@bzbarsky-apple For now, darwin.xcworkspace can not be compile on Xcode, I raise another ticket here and I saw others also raise similar issue here, but no response yet. When I try to use Apple's Matter/MatterSupport framework, I got the issue I raised here.

bzbarsky-apple commented 1 month ago

@JoeyYang2010 If strongly suggest you follow the instructions at https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/darwin.md#providing-feedback-to-apple to report issues that have to do with Apple-specific bits and not the open-source SDK.