/* * * Copyright (c) 2020 Project CHIP Authors * 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 "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include #include #include "FreeRTOS.h" #include #include #include #include #include #include #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #if CHIP_CONFIG_ENABLE_ICD_UAT #include "app/icd/server/ICDNotifier.h" #endif /* syscfg */ #include #define APP_TASK_STACK_SIZE (4096) #define APP_TASK_PRIORITY 4 #define APP_EVENT_QUEUE_SIZE 10 #define PCC_CLUSTER_ENDPOINT 1 #define ONOFF_CLUSTER_ENDPOINT 1 #define EXTENDED_DISCOVERY_TIMEOUT_SEC 20 #if (CHIP_CONFIG_ENABLE_ICD_SERVER == 1) #define LED_ENABLE 0 #else #define LED_ENABLE 1 #endif #define BUTTON_ENABLE 1 #define OTAREQUESTOR_INIT_TIMER_DELAY_MS 10000 using namespace chip; using namespace chip::app; using namespace chip::Credentials; using namespace chip::DeviceLayer; using namespace chip::DeviceManager; using namespace chip::app::Clusters; static TaskHandle_t sAppTaskHandle; static QueueHandle_t sAppEventQueue; #if (LED_ENABLE == 1) static LED_Handle sAppRedHandle; static LED_Handle sAppGreenHandle; #endif static Button_Handle sAppLeftHandle; static Button_Handle sAppRightHandle; AppTask AppTask::sAppTask; static DeviceCallbacks sDeviceCallbacks; #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR void StartTimer(uint32_t aTimeoutMs); void CancelTimer(void); #endif uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR static DefaultOTARequestor sRequestorCore; static DefaultOTARequestorStorage sRequestorStorage; static DefaultOTARequestorDriver sRequestorUser; static BDXDownloader sDownloader; static OTAImageProcessorImpl sImageProcessor; void InitializeOTARequestor(void) { // Initialize and interconnect the Requestor and Image Processor objects SetRequestorInstance(&sRequestorCore); sRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); sRequestorCore.Init(chip::Server::GetInstance(), sRequestorStorage, sRequestorUser, sDownloader); sImageProcessor.SetOTADownloader(&sDownloader); sDownloader.SetImageProcessorDelegate(&sImageProcessor); sRequestorUser.Init(&sRequestorCore, &sImageProcessor); } TimerHandle_t sOTAInitTimer = 0; #endif // The OTA Init Timer is only started upon the first Thread State Change // detected if the device is already on a Thread Network, or during the AppTask // Init sequence if the device is not yet on a Thread Network. Once the timer // has been started once, it does not need to be started again so the flag will // be set to false. bool isAppStarting = true; static const chip::EndpointId sIdentifyEndpointId = 0; static const uint32_t sIdentifyBlinkRateMs = 500; ::Identify stIdentify = { sIdentifyEndpointId, AppTask::IdentifyStartHandler, AppTask::IdentifyStopHandler, Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, AppTask::TriggerIdentifyEffectHandler }; void DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg) { switch (event->Type) { case DeviceEventType::kCHIPoBLEConnectionEstablished: PLAT_LOG("CHIPoBLE connection established"); break; case DeviceEventType::kCHIPoBLEConnectionClosed: PLAT_LOG("CHIPoBLE disconnected"); break; case DeviceEventType::kCommissioningComplete: PLAT_LOG("Commissioning complete"); break; case DeviceEventType::kThreadStateChange: PLAT_LOG("Thread State Change"); bool isThreadAttached = ThreadStackMgrImpl().IsThreadAttached(); if (isThreadAttached) { PLAT_LOG("Device is on the Thread Network"); #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR if (isAppStarting) { StartTimer(OTAREQUESTOR_INIT_TIMER_DELAY_MS); isAppStarting = false; } #endif } break; } } #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR void OTAInitTimerEventHandler(TimerHandle_t xTimer) { InitializeOTARequestor(); } #endif int AppTask::StartAppTask() { int ret = 0; sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); if (sAppEventQueue == NULL) { PLAT_LOG("Failed to allocate app event queue"); while (true) ; } // Start App task. if (xTaskCreate(AppTaskMain, "APP", APP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, APP_TASK_PRIORITY, &sAppTaskHandle) != pdPASS) { PLAT_LOG("Failed to create app task"); while (true) ; } return ret; } int AppTask::Init() { cc13xx_26xxLogInit(); // Init Chip memory management before the stack Platform::MemoryInit(); PLAT_LOG("Software Version: %d", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); PLAT_LOG("Software Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) { PLAT_LOG("PlatformMgr().InitChipStack() failed"); while (true) ; } #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR // Create FreeRTOS sw timer for OTA timer. sOTAInitTimer = xTimerCreate("OTAInitTmr", // Just a text name, not used by the RTOS kernel OTAREQUESTOR_INIT_TIMER_DELAY_MS, // timer period (mS) false, // no timer reload (==one-shot) (void *) this, // init timer id = light obj context OTAInitTimerEventHandler // timer callback handler ); if (sOTAInitTimer == NULL) { PLAT_LOG("sOTAInitTimer timer create failed"); } else { PLAT_LOG("sOTAInitTimer timer created successfully "); } #endif ret = ThreadStackMgr().InitThreadStack(); if (ret != CHIP_NO_ERROR) { PLAT_LOG("ThreadStackMgr().InitThreadStack() failed"); while (true) ; } #if CHIP_DEVICE_CONFIG_THREAD_FTD ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); #elif CHIP_CONFIG_ENABLE_ICD_SERVER ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); #else ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #endif if (ret != CHIP_NO_ERROR) { PLAT_LOG("ConnectivityMgr().SetThreadDeviceType() failed"); while (true) ; } ret = ThreadStackMgrImpl().StartThreadTask(); if (ret != CHIP_NO_ERROR) { PLAT_LOG("ThreadStackMgr().StartThreadTask() failed"); while (true) ; } PlatformMgr().AddEventHandler(DeviceEventCallback, reinterpret_cast(nullptr)); uiInit(); // Initialize device attestation config #ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS #ifdef CC13XX_26XX_FACTORY_DATA SetDeviceInstanceInfoProvider(&mFactoryDataProvider); SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); SetCommissionableDataProvider(&mFactoryDataProvider); #else SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); #endif #else SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); #endif // Initialize Pump module PLAT_LOG("Initialize Pump"); PumpMgr().Init(); PumpMgr().SetCallbacks(ActionInitiated, ActionCompleted); #if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY DnssdServer::Instance().SetExtendedDiscoveryTimeoutSecs(EXTENDED_DISCOVERY_TIMEOUT_SEC); #endif // Init ZCL Data Model PLAT_LOG("Initialize Server"); static CommonCaseDeviceServerInitParams initParams; static DefaultTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); chip::Server::GetInstance().Init(initParams); ConfigurationMgr().LogDeviceConfig(); bool isThreadEnabled = ThreadStackMgrImpl().IsThreadEnabled(); if (!isThreadEnabled && isAppStarting) { #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR PLAT_LOG("Thread is Disabled, enable OTA Requestor"); StartTimer(OTAREQUESTOR_INIT_TIMER_DELAY_MS); isAppStarting = false; #endif } // QR code will be used with CHIP Tool PrintOnboardingCodes(RendezvousInformationFlags(RendezvousInformationFlag::kBLE)); CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance(); ret = deviceMgr.Init(&sDeviceCallbacks); if (ret != CHIP_NO_ERROR) { PLAT_LOG("CHIPDeviceManager::Init() failed: %s", ErrorStr(ret)); while (true) ; } return 0; } void AppTask::AppTaskMain(void * pvParameter) { AppEvent event; sAppTask.Init(); while (true) { /* Task pend until we have stuff to do */ if (xQueueReceive(sAppEventQueue, &event, portMAX_DELAY) == pdTRUE) { sAppTask.DispatchEvent(&event); } } } void AppTask::PostEvent(const AppEvent * aEvent) { if (xQueueSend(sAppEventQueue, aEvent, 0) != pdPASS) { /* Failed to post the message */ } } #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR void StartTimer(uint32_t aTimeoutMs) { PLAT_LOG("Start OTA Init Timer") if (xTimerIsTimerActive(sOTAInitTimer)) { PLAT_LOG("app timer already started!"); CancelTimer(); } // timer is not active, change its period to required value (== restart). // FreeRTOS- Block for a maximum of 100 ticks if the change period command // cannot immediately be sent to the timer command queue. if (xTimerChangePeriod(sOTAInitTimer, pdMS_TO_TICKS(aTimeoutMs), 100) != pdPASS) { PLAT_LOG("sOTAInitTimer timer start() failed"); } } void CancelTimer(void) { if (xTimerStop(sOTAInitTimer, 0) == pdFAIL) { PLAT_LOG("sOTAInitTimer stop() failed"); } } #endif void AppTask::ActionInitiated(PumpManager::Action_t aAction, int32_t aActor) { // If the action has been initiated by the pump, update the pump trait // and start flashing the LEDs rapidly to indicate action initiation. if (aAction == PumpManager::START_ACTION) { PLAT_LOG("Pump start initiated"); ; // TODO } else if (aAction == PumpManager::STOP_ACTION) { PLAT_LOG("Stop initiated"); ; // TODO } #if (LED_ENABLE == 1) LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); LED_startBlinking(sAppGreenHandle, 50 /* ms */, LED_BLINK_FOREVER); LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); LED_startBlinking(sAppRedHandle, 110 /* ms */, LED_BLINK_FOREVER); #endif } void AppTask::ActionCompleted(PumpManager::Action_t aAction, int32_t aActor) { // if the action has been completed by the pump, update the pump trait. // Turn on the pump state LED if in a STARTED state OR // Turn off the pump state LED if in an STOPPED state. if (aAction == PumpManager::START_ACTION) { PLAT_LOG("Pump start completed"); #if (LED_ENABLE == 1) LED_stopBlinking(sAppGreenHandle); LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); LED_stopBlinking(sAppRedHandle); LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); #endif // Signal to the PCC cluster, that the pump is running sAppTask.UpdateClusterState(); } else if (aAction == PumpManager::STOP_ACTION) { PLAT_LOG("Pump stop completed"); #if (LED_ENABLE == 1) LED_stopBlinking(sAppGreenHandle); LED_setOff(sAppGreenHandle); LED_stopBlinking(sAppRedHandle); LED_setOff(sAppRedHandle); #endif // Signal to the PCC cluster, that the pump is NOT running sAppTask.UpdateClusterState(); } if (aActor == AppEvent::kEventType_ButtonLeft) { sAppTask.UpdateClusterState(); } } void AppTask::DispatchEvent(AppEvent * aEvent) { switch (aEvent->Type) { case AppEvent::kEventType_ButtonRight: if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type) { // Toggle Pump state if (!PumpMgr().IsStopped()) { PumpMgr().InitiateAction(0, PumpManager::STOP_ACTION); } else { PumpMgr().InitiateAction(0, PumpManager::START_ACTION); } } else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type) { #if CHIP_CONFIG_ENABLE_ICD_UAT PlatformMgr().ScheduleWork([](intptr_t) { app::ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); }); #endif } break; case AppEvent::kEventType_ButtonLeft: if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type) { // Post event for demonstration purposes, we must ensure that the // LogEvent is called in the right context which is the Matter mainloop // thru ScheduleWork() chip::DeviceLayer::PlatformMgr().ScheduleWork(sAppTask.PostEvents, reinterpret_cast(nullptr)); // Toggle BLE advertisements if (!ConnectivityMgr().IsBLEAdvertisingEnabled()) { if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR) { PLAT_LOG("Enabled BLE Advertisements"); } else { PLAT_LOG("OpenBasicCommissioningWindow() failed"); } } else { // Disable BLE advertisements ConnectivityMgr().SetBLEAdvertisingEnabled(false); PLAT_LOG("Disabled BLE Advertisements"); } } else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type) { chip::Server::GetInstance().ScheduleFactoryReset(); } break; case AppEvent::kEventType_IdentifyStart: #if (LED_ENABLE == 1) LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); LED_startBlinking(sAppGreenHandle, sIdentifyBlinkRateMs, LED_BLINK_FOREVER); #endif PLAT_LOG("Identify started"); break; case AppEvent::kEventType_IdentifyStop: #if (LED_ENABLE == 1) LED_stopBlinking(sAppGreenHandle); if (!PumpMgr().IsStopped()) { LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); } else { LED_setOff(sAppGreenHandle); } #endif PLAT_LOG("Identify stopped"); break; case AppEvent::kEventType_AppEvent: if (NULL != aEvent->Handler) { aEvent->Handler(aEvent); } break; case AppEvent::kEventType_None: default: break; } } void AppTask::InitOnOffClusterState() { Protocols::InteractionModel::Status status; ChipLogProgress(NotSpecified, "Init On/Off clusterstate"); // Write false as pump always boots in stopped mode status = OnOff::Attributes::OnOff::Set(ONOFF_CLUSTER_ENDPOINT, false); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Init On/Off state %x", to_underlying(status)); } } void AppTask::InitPCCClusterState() {} void AppTask::UpdateClusterState(void) { // We must ensure that the Cluster accessors gets called in the right context // which is the Matter mainloop thru ScheduleWork() chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateCluster, reinterpret_cast(nullptr)); } void AppTask::UpdateCluster(intptr_t context) { Protocols::InteractionModel::Status status; BitMask pumpStatus; ChipLogProgress(NotSpecified, "Update Cluster State"); // Update the PumpStatus PumpConfigurationAndControl::Attributes::PumpStatus::Get(PCC_CLUSTER_ENDPOINT, &pumpStatus); if (PumpMgr().IsStopped()) { pumpStatus.Clear(PumpConfigurationAndControl::PumpStatusBitmap::kRunning); } else { pumpStatus.Set(PumpConfigurationAndControl::PumpStatusBitmap::kRunning); } PumpConfigurationAndControl::Attributes::PumpStatus::Set(PCC_CLUSTER_ENDPOINT, pumpStatus); status = PumpConfigurationAndControl::Attributes::ControlMode::Set(PCC_CLUSTER_ENDPOINT, PumpConfigurationAndControl::ControlModeEnum::kConstantFlow); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Constant Flow error %x", to_underlying(status)); } status = PumpConfigurationAndControl::Attributes::ControlMode::Set( PCC_CLUSTER_ENDPOINT, PumpConfigurationAndControl::ControlModeEnum::kConstantPressure); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Constant Pressure error %x", to_underlying(status)); } status = PumpConfigurationAndControl::Attributes::ControlMode::Set( PCC_CLUSTER_ENDPOINT, PumpConfigurationAndControl::ControlModeEnum::kConstantSpeed); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Constant Speed error %x", to_underlying(status)); } status = PumpConfigurationAndControl::Attributes::ControlMode::Set( PCC_CLUSTER_ENDPOINT, PumpConfigurationAndControl::ControlModeEnum::kConstantTemperature); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Constant Temperature error %x", to_underlying(status)); } // Write the new values bool onOffState = !PumpMgr().IsStopped(); status = OnOff::Attributes::OnOff::Set(ONOFF_CLUSTER_ENDPOINT, onOffState); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating On/Off state %x", to_underlying(status)); } int16_t maxPressure = PumpMgr().GetMaxPressure(); status = PumpConfigurationAndControl::Attributes::MaxPressure::Set(PCC_CLUSTER_ENDPOINT, maxPressure); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxPressure %x", to_underlying(status)); } uint16_t maxSpeed = PumpMgr().GetMaxSpeed(); status = PumpConfigurationAndControl::Attributes::MaxSpeed::Set(PCC_CLUSTER_ENDPOINT, maxSpeed); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxSpeed %x", to_underlying(status)); } uint16_t maxFlow = PumpMgr().GetMaxFlow(); status = PumpConfigurationAndControl::Attributes::MaxFlow::Set(PCC_CLUSTER_ENDPOINT, maxFlow); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxFlow %x", to_underlying(status)); } int16_t minConstPress = PumpMgr().GetMinConstPressure(); status = PumpConfigurationAndControl::Attributes::MinConstPressure::Set(PCC_CLUSTER_ENDPOINT, minConstPress); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MinConstPressure %x", to_underlying(status)); } int16_t maxConstPress = PumpMgr().GetMaxConstPressure(); status = PumpConfigurationAndControl::Attributes::MaxConstPressure::Set(PCC_CLUSTER_ENDPOINT, maxConstPress); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxConstPressure %x", to_underlying(status)); } int16_t minCompPress = PumpMgr().GetMinCompPressure(); status = PumpConfigurationAndControl::Attributes::MinCompPressure::Set(PCC_CLUSTER_ENDPOINT, minCompPress); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MinCompPressure %x", to_underlying(status)); } int16_t maxCompPress = PumpMgr().GetMaxCompPressure(); status = PumpConfigurationAndControl::Attributes::MaxCompPressure::Set(PCC_CLUSTER_ENDPOINT, maxCompPress); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxCompPressure %x", to_underlying(status)); } uint16_t minConstSpeed = PumpMgr().GetMinConstSpeed(); status = PumpConfigurationAndControl::Attributes::MinConstSpeed::Set(PCC_CLUSTER_ENDPOINT, minConstSpeed); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MinConstSpeed %x", to_underlying(status)); } uint16_t maxConstSpeed = PumpMgr().GetMaxConstSpeed(); status = PumpConfigurationAndControl::Attributes::MaxConstSpeed::Set(PCC_CLUSTER_ENDPOINT, maxConstSpeed); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxConstSpeed %x", to_underlying(status)); } uint16_t minConstFlow = PumpMgr().GetMinConstFlow(); status = PumpConfigurationAndControl::Attributes::MinConstFlow::Set(PCC_CLUSTER_ENDPOINT, minConstFlow); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MinConstFlow %x", to_underlying(status)); } uint16_t maxConstFlow = PumpMgr().GetMaxConstFlow(); status = PumpConfigurationAndControl::Attributes::MaxConstFlow::Set(PCC_CLUSTER_ENDPOINT, maxConstFlow); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxConstFlow %x", to_underlying(status)); } int16_t minConstTemp = PumpMgr().GetMinConstTemp(); status = PumpConfigurationAndControl::Attributes::MinConstTemp::Set(PCC_CLUSTER_ENDPOINT, minConstTemp); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MinConstTemp %x", to_underlying(status)); } int16_t maxConstTemp = PumpMgr().GetMaxConstTemp(); status = PumpConfigurationAndControl::Attributes::MaxConstTemp::Set(PCC_CLUSTER_ENDPOINT, maxConstTemp); if (status != Protocols::InteractionModel::Status::Success) { ChipLogError(NotSpecified, "ERR: Updating MaxConstTemp %x", to_underlying(status)); } } void AppTask::PostEvents(intptr_t context) { // Example on posting events - here we post the general fault event on endpoints with PCC Server enabled for (auto endpoint : EnabledEndpointsWithServerCluster(PumpConfigurationAndControl::Id)) { PumpConfigurationAndControl::Events::GeneralFault::Type event; EventNumber eventNumber; ChipLogProgress(Zcl, "AppTask: Post PCC GeneralFault event"); // Using default priority for the event if (CHIP_NO_ERROR != LogEvent(event, endpoint, eventNumber)) { ChipLogError(Zcl, "AppTask: Failed to record GeneralFault event"); } } } void AppTask::IdentifyStartHandler(::Identify *) { AppEvent event; event.Type = AppEvent::kEventType_IdentifyStart; sAppTask.PostEvent(&event); } void AppTask::IdentifyStopHandler(::Identify *) { AppEvent event; event.Type = AppEvent::kEventType_IdentifyStop; sAppTask.PostEvent(&event); } void AppTask::TriggerIdentifyEffectHandler(::Identify * identify) { switch (identify->mCurrentEffectIdentifier) { case Clusters::Identify::EffectIdentifierEnum::kBlink: PLAT_LOG("Starting blink identifier effect"); IdentifyStartHandler(identify); break; case Clusters::Identify::EffectIdentifierEnum::kBreathe: PLAT_LOG("Breathe identifier effect not implemented"); break; case Clusters::Identify::EffectIdentifierEnum::kOkay: PLAT_LOG("Okay identifier effect not implemented"); break; case Clusters::Identify::EffectIdentifierEnum::kChannelChange: PLAT_LOG("Channel Change identifier effect not implemented"); break; case Clusters::Identify::EffectIdentifierEnum::kFinishEffect: PLAT_LOG("Finish identifier effect not implemented"); break; case Clusters::Identify::EffectIdentifierEnum::kStopEffect: PLAT_LOG("Stop identifier effect"); IdentifyStopHandler(identify); break; default: PLAT_LOG("No identifier effect"); } } #if (BUTTON_ENABLE == 1) void AppTask::ButtonLeftEventHandler(Button_Handle handle, Button_EventMask events) { AppEvent event; event.Type = AppEvent::kEventType_ButtonLeft; if (events & Button_EV_CLICKED) { event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked; } else if (events & Button_EV_LONGCLICKED) { event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked; } // button callbacks are in ISR context if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS) { /* Failed to post the message */ } } void AppTask::ButtonRightEventHandler(Button_Handle handle, Button_EventMask events) { AppEvent event; event.Type = AppEvent::kEventType_ButtonRight; if (events & Button_EV_CLICKED) { event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked; } else if (events & Button_EV_LONGCLICKED) { event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked; } // button callbacks are in ISR context if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS) { /* Failed to post the message */ } } #endif // BUTTON_ENABLE void AppTask::uiInit(void) { #if (LED_ENABLE == 1) LED_Params ledParams; // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); LED_Params_init(&ledParams); // default PWM LED sAppRedHandle = LED_open(CONFIG_LED_RED, &ledParams); LED_setOff(sAppRedHandle); LED_Params_init(&ledParams); // default PWM LED sAppGreenHandle = LED_open(CONFIG_LED_GREEN, &ledParams); LED_setOff(sAppGreenHandle); #endif // LED ENABLE #if (BUTTON_ENABLE == 1) Button_Params buttonParams; // Initialize buttons PLAT_LOG("Initialize buttons"); Button_init(); Button_Params_init(&buttonParams); buttonParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED; buttonParams.longPressDuration = 1000U; // ms sAppLeftHandle = Button_open(CONFIG_BTN_LEFT, &buttonParams); Button_setCallback(sAppLeftHandle, ButtonLeftEventHandler); Button_Params_init(&buttonParams); buttonParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED; buttonParams.longPressDuration = 1000U; // ms sAppRightHandle = Button_open(CONFIG_BTN_RIGHT, &buttonParams); Button_setCallback(sAppRightHandle, ButtonRightEventHandler); #endif // BUTTON ENABLE }