/* * * Copyright (c) 2021 Project CHIP Authors * Copyright (c) 2021 Google LLC. * Copyright 2024 NXP * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "AppTaskBase.h" #include "AppEvent.h" #include "AppFactoryData.h" #include "CHIPDeviceManager.h" #include "CommonDeviceCallbacks.h" #include #include #include #include #include #include #include "lib/core/ErrorStr.h" #include #if defined(MATTER_DM_PLUGIN_USER_LABEL) || defined(MATTER_DM_PLUGIN_FIXED_LABEL) #ifndef CONFIG_DEVICE_INFO_PROVIDER_IMPL #define CONFIG_DEVICE_INFO_PROVIDER_IMPL 1 #endif #endif #if CONFIG_DEVICE_INFO_PROVIDER_IMPL #include #endif /* Flag generated by Zap */ #ifdef MATTER_DM_PLUGIN_BINDING #include "binding-handler.h" #endif #if CONFIG_NET_L2_OPENTHREAD #include #include #endif #if CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT #include "WifiConnect.h" #endif #if CONFIG_OPERATIONAL_KEYSTORE #include "OperationalKeystore.h" #endif #if CONFIG_CHIP_OTA_PROVIDER #include #endif #if CONFIG_DIAG_LOGS_DEMO #include "DiagnosticLogsDemo.h" #endif #if CONFIG_LOW_POWER #include "LowPower.h" #endif #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR #include "OTARequestorInitiator.h" #endif #if CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR #include #endif #ifdef ENABLE_CHIP_SHELL #include #endif #ifdef SMOKE_CO_ALARM #include #include #endif #if CHIP_CONFIG_ENABLE_ICD_SERVER #include #endif #if CHIP_DEVICE_CONFIG_ENABLE_TBR #include "platform/OpenThread/GenericThreadBorderRouterDelegate.h" #include #endif #ifndef CONFIG_THREAD_DEVICE_TYPE #define CONFIG_THREAD_DEVICE_TYPE kThreadDeviceType_Router #endif using namespace chip; using namespace chip::TLV; using namespace ::chip::Credentials; using namespace ::chip::DeviceLayer; using namespace ::chip::DeviceManager; using namespace ::chip::app::Clusters; #if CONFIG_DEVICE_INFO_PROVIDER_IMPL chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; #endif #if CONFIG_CHIP_WIFI || CHIP_DEVICE_CONFIG_ENABLE_WPA app::Clusters::NetworkCommissioning::Instance sNetworkCommissioningInstance(0, chip::NXP::App::GetAppTask().GetWifiDriverInstance()); #elif CONFIG_CHIP_ETHERNET app::Clusters::NetworkCommissioning::Instance sNetworkCommissioningInstance(0, chip::NXP::App::GetAppTask().GetEthernetDriverInstance()); #endif #if CHIP_DEVICE_CONFIG_ENABLE_TBR static constexpr EndpointId kThreadBRMgmtEndpoint = 2; static CharSpan sBrName("NXP-BR", strlen("NXP-BR")); #endif #if CHIP_CONFIG_ENABLE_ICD_SERVER || (CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR) static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; #endif #ifdef SMOKE_CO_ALARM static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; #endif #if CONFIG_NET_L2_OPENTHREAD void LockOpenThreadTask(void) { chip::NXP::App::GetAppTask().AppMatter_DisallowDeviceToSleep(); chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); } void UnlockOpenThreadTask(void) { chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); chip::NXP::App::GetAppTask().AppMatter_AllowDeviceToSleep(); } #endif void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) { GetAppTask().PreInitMatterServerInstance(); #if CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; initParams.testEventTriggerDelegate = &testEventTriggerDelegate; #endif #ifdef SMOKE_CO_ALARM static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; static SmokeCOTestEventTriggerHandler sSmokeCOTestEventTriggerHandler{}; VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sSmokeCOTestEventTriggerHandler) == CHIP_NO_ERROR); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; #endif #if CHIP_CONFIG_ENABLE_ICD_SERVER static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; #endif #if CONFIG_OPERATIONAL_KEYSTORE initParams.operationalKeystore = chip::NXP::App::OperationalKeystore::GetInstance(); #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); #if CONFIG_NET_L2_OPENTHREAD // Init ZCL Data Model and start server chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; nativeParams.lockCb = LockOpenThreadTask; nativeParams.unlockCb = UnlockOpenThreadTask; nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance(); initParams.endpointNativeParams = static_cast(&nativeParams); #endif VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); auto * persistentStorage = &Server::GetInstance().GetPersistentStorage(); #if CONFIG_OPERATIONAL_KEYSTORE chip::NXP::App::OperationalKeystore::Init(persistentStorage); #endif #if CONFIG_DEVICE_INFO_PROVIDER_IMPL gExampleDeviceInfoProvider.SetStorageDelegate(persistentStorage); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); #endif GetAppTask().PostInitMatterServerInstance(); #if CONFIG_DIAG_LOGS_DEMO chip::NXP::App::DiagnosticLogsDemo::DisplayUsage(); #endif #if CONFIG_CHIP_OTA_PROVIDER InitOTAServer(); #endif #if CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT VerifyOrDie(WifiConnectAtboot(chip::NXP::App::GetAppTask().GetWifiDriverInstance()) == CHIP_NO_ERROR); #endif #if CHIP_DEVICE_CONFIG_ENABLE_TBR GetAppTask().EnableTbrManagementCluster(); #endif } CHIP_ERROR chip::NXP::App::AppTaskBase::Init() { CHIP_ERROR err = CHIP_NO_ERROR; /* Init Chip memory management before the stack */ chip::Platform::MemoryInit(); #if CONFIG_LOW_POWER chip::NXP::App::LowPower::Init(); #endif /* Initialize Matter factory data before initializing the Matter stack */ err = AppFactoryData_PreMatterStackInit(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "Pre Factory Data Provider init failed"); goto exit; } /* * Initialize the CHIP stack. * Would also initialize all required platform modules */ err = PlatformMgr().InitChipStack(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "PlatformMgr().InitChipStack() failed: %s", ErrorStr(err)); goto exit; } /* Initialize Matter factory data after initializing the Matter stack */ err = AppFactoryData_PostMatterStackInit(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "Post Factory Data Provider init failed"); goto exit; } /* * Register all application callbacks allowing to be informed of stack events */ err = CHIPDeviceManager::GetInstance().Init(&GetDeviceCallbacks()); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "CHIPDeviceManager.Init() failed: %s", ErrorStr(err)); goto exit; } /* Make sure to initialize the Matter CLI which will include the ot-cli first. * In fact it is mandatory to enable first the ot-cli before initializing the Matter openthread layer * which would modify some contexts of the openthread instance. */ err = AppMatter_Register(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "Error during APP features registration")); #if CONFIG_NET_L2_OPENTHREAD err = ThreadStackMgr().InitThreadStack(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "Error during ThreadStackMgr().InitThreadStack()"); return err; } err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::CONFIG_THREAD_DEVICE_TYPE); if (err != CHIP_NO_ERROR) { return err; } #endif /* * Schedule an event to the Matter stack to initialize * the ZCL Data Model and start server */ PlatformMgr().ScheduleWork(InitServer, 0); /* Flag generated by Zap */ #ifdef MATTER_DM_PLUGIN_BINDING /* Init binding handlers */ err = InitBindingHandlers(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "InitBindingHandlers failed: %s", ErrorStr(err)); goto exit; } #endif #if CONFIG_CHIP_WIFI || CHIP_DEVICE_CONFIG_ENABLE_WPA sNetworkCommissioningInstance.Init(); #ifdef ENABLE_CHIP_SHELL Shell::SetWiFiDriver(chip::NXP::App::GetAppTask().GetWifiDriverInstance()); #endif #elif CONFIG_CHIP_ETHERNET sNetworkCommissioningInstance.Init(); #endif #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR if (err == CHIP_NO_ERROR) { /* If an update is under test make it permanent */ OTARequestorInitiator::Instance().HandleSelfTest(); } #endif ConfigurationMgr().LogDeviceConfig(); // QR code will be used with CHIP Tool PrintOnboardingInfo(); PrintCurrentVersion(); /* Start a task to run the CHIP Device event loop. */ err = PlatformMgr().StartEventLoopTask(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "Error during PlatformMgr().StartEventLoopTask()"); goto exit; } #if CONFIG_NET_L2_OPENTHREAD // Start OpenThread task err = ThreadStackMgrImpl().StartThreadTask(); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "Error during ThreadStackMgrImpl().StartThreadTask()"); } #endif exit: return err; } void chip::NXP::App::AppTaskBase::StartCommissioning(intptr_t arg) { /* Check the status of the commissioning */ if (ConfigurationMgr().IsFullyProvisioned()) { ChipLogProgress(DeviceLayer, "Device already commissioned"); } else if (chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) { ChipLogProgress(DeviceLayer, "Commissioning window already opened"); } else { chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); } } void chip::NXP::App::AppTaskBase::StopCommissioning(intptr_t arg) { /* Check the status of the commissioning */ if (ConfigurationMgr().IsFullyProvisioned()) { ChipLogProgress(DeviceLayer, "Device already commissioned"); } else if (!chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) { ChipLogProgress(DeviceLayer, "Commissioning window not opened"); } else { chip::Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow(); } } void chip::NXP::App::AppTaskBase::SwitchCommissioningState(intptr_t arg) { /* Check the status of the commissioning */ if (ConfigurationMgr().IsFullyProvisioned()) { ChipLogProgress(DeviceLayer, "Device already commissioned"); } else if (!chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) { chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); } else { chip::Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow(); } } void chip::NXP::App::AppTaskBase::StartCommissioningHandler(void) { /* Publish an event to the Matter task to always set the commissioning state in the Matter task context */ PlatformMgr().ScheduleWork(StartCommissioning, 0); } void chip::NXP::App::AppTaskBase::StopCommissioningHandler(void) { /* Publish an event to the Matter task to always set the commissioning state in the Matter task context */ PlatformMgr().ScheduleWork(StopCommissioning, 0); } void chip::NXP::App::AppTaskBase::SwitchCommissioningStateHandler(void) { /* Publish an event to the Matter task to always set the commissioning state in the Matter task context */ PlatformMgr().ScheduleWork(SwitchCommissioningState, 0); } void chip::NXP::App::AppTaskBase::FactoryResetHandler(void) { /* Emit the ShutDown event before factory reset */ chip::Server::GetInstance().GenerateShutDownEvent(); chip::Server::GetInstance().ScheduleFactoryReset(); } void chip::NXP::App::AppTaskBase::PrintOnboardingInfo() { #if CONFIG_NETWORK_LAYER_BLE auto flags = chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE); #else auto flags = chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kOnNetwork); #endif /* CONFIG_NETWORK_LAYER_BLE */ chip::PayloadContents payload; CHIP_ERROR err = GetPayloadContents(payload, flags); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); } #if CONFIG_USER_ACTION_REQUIRED payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; #endif PrintOnboardingCodes(payload); } void chip::NXP::App::AppTaskBase::PrintCurrentVersion() { // Print the current software version char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 }; auto err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer)); ReturnOnFailure(err); uint32_t currentVersion; err = ConfigurationMgr().GetSoftwareVersion(currentVersion); ReturnOnFailure(err); ChipLogProgress(DeviceLayer, "Current Software Version: %s, %d", currentSoftwareVer, static_cast(currentVersion)); } #if CHIP_DEVICE_CONFIG_ENABLE_TBR void chip::NXP::App::AppTaskBase::EnableTbrManagementCluster() { auto * persistentStorage = &Server::GetInstance().GetPersistentStorage(); static ThreadBorderRouterManagement::GenericOpenThreadBorderRouterDelegate sThreadBRDelegate(persistentStorage); static ThreadBorderRouterManagement::ServerInstance sThreadBRMgmtInstance(kThreadBRMgmtEndpoint, &sThreadBRDelegate, Server::GetInstance().GetFailSafeContext()); // Initialize TBR name sThreadBRDelegate.SetThreadBorderRouterName(sBrName); // Initialize TBR cluster sThreadBRMgmtInstance.Init(); } #endif