YOGYUI

Matter - Open/Close Commissioning Window in Code (SDK) 본문

홈네트워크(IoT)/Matter

Matter - Open/Close Commissioning Window in Code (SDK)

요겨 2023. 7. 22. 12:04
반응형

매터(Matter) 기기의 커미셔닝 윈도우(commissioning window)는 매터 컨트롤러 노드에서 'Administrator Commissioning Cluster (cluster id: 0x003C)'의 'OpenCommissioningWindow (command id: 0x00)' 혹은 'OpenBasicCommissioningWindow (command id: 0x01)' 명령 전송을 통해 열거나, 'RevokeCommissioning (command id: 0x02)' 명령 전송을 통해 활성화/비활성화하게 된다

클러스터 정보: Matter Specification - Administrator Commissioning Cluster

예시: Matter - 여러 IoT 플랫폼(애플, 구글)에 기기 등록하기

 

하지만 특정 상황에서는 다른 노드의 도움(?)없이 디바이스 단독으로 윈도우를 열고 닫을 수 있어야 하는데(윈도우 타임아웃 후 다시 열어줘야 하는 상황 등), 이를 위해 단순하게 matter 명령을 호출하면 crash가 발생하게 된다 (matter thread에서 붙잡고 있는 리소스에 강제적으로 접근하게 될 경우 발생)

https://docs.espressif.com/projects/esp-matter/en/latest/esp32/faq.html#a1-11-chip-stack-locking-error-code-is-unsafe-racy

 

따라서 뮤텍스 혹은 세마포어로 리소스를 잠시 lock을 걸어 스레드 작업을 잠시 중단시키거나, 혹은 matter thread 작업 큐에 특정 작업을 스케쥴링시켜줘야 하는데, 이리저리 작업해보니 lock보다는 queue scheduling이 훨씬 잘 작동하는 걸 알 수 있었다


아래와 같이 commissioning window open/close하는 정적 함수 Handler를 선언해둔 뒤, 

chip::DeviceLayer::PlatformMgr().ScheduleWork() 함수를 통해 해당 함수를 work schedule에 등록하면 아무 문제없이 윈도우 제어를 할 수 있다

#include <platform/PlatformManager.h>
#include <app/server/Server.h>
#include <app/FailSafeContext.h>
#include <app/server/CommissioningWindowManager.h>
#include <SystemClock.h>
#include <CHIPError.h>

using namespace chip;
using namespace chip::app;
using namespace chip::DeviceLayer;

static void Handler(intptr_t context) {
    CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
    if (commissionMgr.IsCommissioningWindowOpen()) {
        commissionMgr.CloseCommissioningWindow();
    }

    if (context > 0) {
        FailSafeContext & failSafeContext = Server::GetInstance().GetFailSafeContext();
        auto commissioningTimeout = System::Clock::Seconds16(context);

        printf("Try to open basic commissioning window (timeout: %u)\n", commissioningTimeout);
        if (commissionMgr.IsCommissioningWindowOpen()) {
            printf("Commissioning window is already opened (busy)\n");
            return;
        }
        
        if (!failSafeContext.IsFailSafeFullyDisarmed()) {
            printf("Fail safe is not full disarmed (busy)\n");
            return;
        }
        
        if (commissioningTimeout > commissionMgr.MaxCommissioningTimeout()) {
            printf("Timeout max limit exceeded\n");
            return;
        }
        
        if (commissioningTimeout < commissionMgr.MinCommissioningTimeout()) {
            printf("Timeout min limit exceeded\n");
            return;
        }

        ChipError ret = commissionMgr.OpenBasicCommissioningWindow(commissioningTimeout, chip::CommissioningWindowAdvertisement::kDnssdOnly);
        if (ret != CHIP_NO_ERROR) {
            printf("Failed to open basic commissioning window (ret: %d)\n", ret.Format());
        }
    }
}

void open_commissioning_window(uint16_t timeout) {
    ChipError ret = PlatformMgr().ScheduleWork(Handler, (intptr_t)timeout);
    if (ret != CHIP_NO_ERROR) {
        printf("failed(%d)\n", ret);
    }
}

void close_commissioning_window() {
    open_commissioning_window(0);
}

예제 프로젝트를 GitHub에 커밋했다

https://github.com/YOGYUI/esp-matter-commissioning-window

 

GitHub - YOGYUI/esp-matter-commissioning-window

Contribute to YOGYUI/esp-matter-commissioning-window development by creating an account on GitHub.

github.com

ESP-32의 GPIO0에 연결된 택트 버튼을 싱글 클릭 혹은 더블 클릭하여 커미셔닝 윈도우를 수동으로 열기/닫기할 수 있다

콘솔 로그 예시는 다음과 같다

[Single click: open commissioning window]

I (85666) logger: [MatterCommWndWorkHandler] Try to open basic commissioning window (timeout: 300) [system.cpp:228]
I (85666) chip[DIS]: Updating services using commissioning mode 1
I (85676) chip[DIS]: CHIP minimal mDNS started advertising.
I (85676) chip[DIS]: Advertise commission parameter vendorID=65521 productID=32768 discriminator=3840/15 cm=1
I (85696) chip[DIS]: CHIP minimal mDNS configured as 'Commissionable node device'; instance name: FE2021427B97C1B6.
I (85706) chip[DIS]: mDNS service published: _matterc._udp
I (85706) logger: [CSystem::matter_event_callback] Commissioning window opened [system.cpp:197]

[Double click: close commissioning window]

I (49126) chip[SVR]: Closing pairing window
I (49126) chip[DIS]: Updating services using commissioning mode 0
I (49126) chip[DIS]: CHIP minimal mDNS started advertising.
I (49136) logger: [CSystem::matter_event_callback] Commissioning window closed [system.cpp:200]

[참고]

https://docs.espressif.com/projects/esp-matter/en/latest/esp32/faq.html#a1-11-chip-stack-locking-error-code-is-unsafe-racy

반응형