diff --git a/examples/lighting-app/linux/BUILD.gn b/examples/lighting-app/linux/BUILD.gn index cfa89da29e0594..47c14536d9a7c3 100644 --- a/examples/lighting-app/linux/BUILD.gn +++ b/examples/lighting-app/linux/BUILD.gn @@ -36,6 +36,7 @@ config("includes") { executable("chip-lighting-app") { sources = [ + "LightingAppCommandDelegate.cpp", "include/CHIPProjectAppConfig.h", "main.cpp", ] @@ -45,6 +46,7 @@ executable("chip-lighting-app") { "${chip_root}/examples/lighting-app/lighting-common:lighting-manager", "${chip_root}/examples/platform/linux:app-main", "${chip_root}/src/lib", + "${chip_root}/third_party/jsoncpp", ] if (chip_examples_enable_imgui_ui) { diff --git a/examples/lighting-app/linux/LightingAppCommandDelegate.cpp b/examples/lighting-app/linux/LightingAppCommandDelegate.cpp new file mode 100644 index 00000000000000..d0b772f6f04845 --- /dev/null +++ b/examples/lighting-app/linux/LightingAppCommandDelegate.cpp @@ -0,0 +1,353 @@ +/* + * + * Copyright (c) 2023 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 "LightingAppCommandDelegate.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::DeviceLayer; + +LightingAppCommandHandler * LightingAppCommandHandler::FromJSON(const char * json) +{ + Json::Reader reader; + Json::Value value; + + if (!reader.parse(json, value)) + { + ChipLogError(NotSpecified, + "AllClusters App: Error parsing JSON with error %s:", reader.getFormattedErrorMessages().c_str()); + return nullptr; + } + + if (value.empty() || !value.isObject()) + { + ChipLogError(NotSpecified, "AllClusters App: Invalid JSON command received"); + return nullptr; + } + + if (!value.isMember("Name") || !value["Name"].isString()) + { + ChipLogError(NotSpecified, "AllClusters App: Invalid JSON command received: command name is missing"); + return nullptr; + } + + return Platform::New(std::move(value)); +} + +void LightingAppCommandHandler::HandleCommand(intptr_t context) +{ + auto * self = reinterpret_cast(context); + std::string name = self->mJsonValue["Name"].asString(); + + VerifyOrExit(!self->mJsonValue.empty(), ChipLogError(NotSpecified, "Invalid JSON event command received")); + + if (name == "SoftwareFault") + { + self->OnSoftwareFaultEventHandler(Clusters::SoftwareDiagnostics::Events::SoftwareFault::Id); + } + else if (name == "HardwareFaultChange") + { + self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id); + } + else if (name == "RadioFaultChange") + { + self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id); + } + else if (name == "NetworkFaultChange") + { + self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id); + } + else if (name == "SwitchLatched") + { + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + self->OnSwitchLatchedHandler(newPosition); + } + else if (name == "InitialPress") + { + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + self->OnSwitchInitialPressedHandler(newPosition); + } + else if (name == "LongPress") + { + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + self->OnSwitchLongPressedHandler(newPosition); + } + else if (name == "ShortRelease") + { + uint8_t previousPosition = static_cast(self->mJsonValue["PreviousPosition"].asUInt()); + self->OnSwitchShortReleasedHandler(previousPosition); + } + else if (name == "LongRelease") + { + uint8_t previousPosition = static_cast(self->mJsonValue["PreviousPosition"].asUInt()); + self->OnSwitchLongReleasedHandler(previousPosition); + } + else if (name == "MultiPressOngoing") + { + uint8_t newPosition = static_cast(self->mJsonValue["NewPosition"].asUInt()); + uint8_t count = static_cast(self->mJsonValue["CurrentNumberOfPressesCounted"].asUInt()); + self->OnSwitchMultiPressOngoingHandler(newPosition, count); + } + else if (name == "MultiPressComplete") + { + uint8_t previousPosition = static_cast(self->mJsonValue["PreviousPosition"].asUInt()); + uint8_t count = static_cast(self->mJsonValue["TotalNumberOfPressesCounted"].asUInt()); + self->OnSwitchMultiPressCompleteHandler(previousPosition, count); + } + else if (name == "PowerOnReboot") + { + self->OnRebootSignalHandler(BootReasonType::kPowerOnReboot); + } + else if (name == "BrownOutReset") + { + self->OnRebootSignalHandler(BootReasonType::kBrownOutReset); + } + else if (name == "SoftwareWatchdogReset") + { + self->OnRebootSignalHandler(BootReasonType::kSoftwareWatchdogReset); + } + else if (name == "HardwareWatchdogReset") + { + self->OnRebootSignalHandler(BootReasonType::kHardwareWatchdogReset); + } + else if (name == "SoftwareUpdateCompleted") + { + self->OnRebootSignalHandler(BootReasonType::kSoftwareUpdateCompleted); + } + else if (name == "SoftwareReset") + { + self->OnRebootSignalHandler(BootReasonType::kSoftwareReset); + } + else + { + ChipLogError(NotSpecified, "Unhandled command: Should never happens"); + } + +exit: + Platform::Delete(self); +} + +bool LightingAppCommandHandler::IsClusterPresentOnAnyEndpoint(ClusterId clusterId) +{ + EnabledEndpointsWithServerCluster enabledEndpoints(clusterId); + + return (enabledEndpoints.begin() != enabledEndpoints.end()); +} + +void LightingAppCommandHandler::OnRebootSignalHandler(BootReasonType bootReason) +{ + if (ConfigurationMgr().StoreBootReason(static_cast(bootReason)) == CHIP_NO_ERROR) + { + Server::GetInstance().GenerateShutDownEvent(); + PlatformMgr().ScheduleWork([](intptr_t) { PlatformMgr().StopEventLoopTask(); }); + } + else + { + ChipLogError(NotSpecified, "Failed to store boot reason:%d", static_cast(bootReason)); + } +} + +void LightingAppCommandHandler::OnGeneralFaultEventHandler(uint32_t eventId) +{ + if (!IsClusterPresentOnAnyEndpoint(Clusters::GeneralDiagnostics::Id)) + return; + + if (eventId == Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id) + { + GeneralFaults previous; + GeneralFaults current; + + using GeneralDiagnostics::HardwareFaultEnum; + + // On Linux Simulation, set following hardware faults statically. + ReturnOnFailure(previous.add(to_underlying(HardwareFaultEnum::kRadio))); + ReturnOnFailure(previous.add(to_underlying(HardwareFaultEnum::kPowerSource))); + + ReturnOnFailure(current.add(to_underlying(HardwareFaultEnum::kRadio))); + ReturnOnFailure(current.add(to_underlying(HardwareFaultEnum::kSensor))); + ReturnOnFailure(current.add(to_underlying(HardwareFaultEnum::kPowerSource))); + ReturnOnFailure(current.add(to_underlying(HardwareFaultEnum::kUserInterfaceFault))); + Clusters::GeneralDiagnosticsServer::Instance().OnHardwareFaultsDetect(previous, current); + } + else if (eventId == Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id) + { + GeneralFaults previous; + GeneralFaults current; + + // On Linux Simulation, set following radio faults statically. + ReturnOnFailure(previous.add(EMBER_ZCL_RADIO_FAULT_ENUM_WI_FI_FAULT)); + ReturnOnFailure(previous.add(EMBER_ZCL_RADIO_FAULT_ENUM_THREAD_FAULT)); + + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_ENUM_WI_FI_FAULT)); + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_ENUM_CELLULAR_FAULT)); + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_ENUM_THREAD_FAULT)); + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_ENUM_NFC_FAULT)); + Clusters::GeneralDiagnosticsServer::Instance().OnRadioFaultsDetect(previous, current); + } + else if (eventId == Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id) + { + GeneralFaults previous; + GeneralFaults current; + + // On Linux Simulation, set following radio faults statically. + ReturnOnFailure(previous.add(to_underlying(Clusters::GeneralDiagnostics::NetworkFaultEnum::kHardwareFailure))); + ReturnOnFailure(previous.add(to_underlying(Clusters::GeneralDiagnostics::NetworkFaultEnum::kNetworkJammed))); + + ReturnOnFailure(current.add(to_underlying(Clusters::GeneralDiagnostics::NetworkFaultEnum::kHardwareFailure))); + ReturnOnFailure(current.add(to_underlying(Clusters::GeneralDiagnostics::NetworkFaultEnum::kNetworkJammed))); + ReturnOnFailure(current.add(to_underlying(Clusters::GeneralDiagnostics::NetworkFaultEnum::kConnectionFailed))); + Clusters::GeneralDiagnosticsServer::Instance().OnNetworkFaultsDetect(previous, current); + } + else + { + ChipLogError(NotSpecified, "Unknow event ID:%d", eventId); + } +} + +void LightingAppCommandHandler::OnSoftwareFaultEventHandler(uint32_t eventId) +{ + VerifyOrReturn(eventId == Clusters::SoftwareDiagnostics::Events::SoftwareFault::Id, + ChipLogError(NotSpecified, "Unknown software fault event received")); + + if (!IsClusterPresentOnAnyEndpoint(Clusters::SoftwareDiagnostics::Id)) + return; + + Clusters::SoftwareDiagnostics::Events::SoftwareFault::Type softwareFault; + char threadName[kMaxThreadNameLength + 1]; + + softwareFault.id = static_cast(getpid()); + Platform::CopyString(threadName, std::to_string(softwareFault.id).c_str()); + + softwareFault.name.SetValue(CharSpan::fromCharString(threadName)); + + std::time_t result = std::time(nullptr); + // Using size of 50 as it is double the expected 25 characters "Www Mmm dd hh:mm:ss yyyy\n". + char timeChar[50]; + if (std::strftime(timeChar, sizeof(timeChar), "%c", std::localtime(&result))) + { + softwareFault.faultRecording.SetValue(ByteSpan(Uint8::from_const_char(timeChar), strlen(timeChar))); + } + + Clusters::SoftwareDiagnosticsServer::Instance().OnSoftwareFaultDetect(softwareFault); +} + +void LightingAppCommandHandler::OnSwitchLatchedHandler(uint8_t newPosition) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The latching switch is moved to a new position:%d", newPosition); + + Clusters::SwitchServer::Instance().OnSwitchLatch(endpoint, newPosition); +} + +void LightingAppCommandHandler::OnSwitchInitialPressedHandler(uint8_t newPosition) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The new position when the momentary switch starts to be pressed:%d", newPosition); + + Clusters::SwitchServer::Instance().OnInitialPress(endpoint, newPosition); +} + +void LightingAppCommandHandler::OnSwitchLongPressedHandler(uint8_t newPosition) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The new position when the momentary switch has been pressed for a long time:%d", newPosition); + + Clusters::SwitchServer::Instance().OnLongPress(endpoint, newPosition); +} + +void LightingAppCommandHandler::OnSwitchShortReleasedHandler(uint8_t previousPosition) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The the previous value of the CurrentPosition when the momentary switch has been released:%d", + previousPosition); + + Clusters::SwitchServer::Instance().OnShortRelease(endpoint, previousPosition); +} + +void LightingAppCommandHandler::OnSwitchLongReleasedHandler(uint8_t previousPosition) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); + ChipLogDetail(NotSpecified, + "The the previous value of the CurrentPosition when the momentary switch has been released after having been " + "pressed for a long time:%d", + previousPosition); + + Clusters::SwitchServer::Instance().OnLongRelease(endpoint, previousPosition); +} + +void LightingAppCommandHandler::OnSwitchMultiPressOngoingHandler(uint8_t newPosition, uint8_t count) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, newPosition); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to set CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The new position when the momentary switch has been pressed in a multi-press sequence:%d", + newPosition); + ChipLogDetail(NotSpecified, "%d times the momentary switch has been pressed", count); + + Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpoint, newPosition, count); +} + +void LightingAppCommandHandler::OnSwitchMultiPressCompleteHandler(uint8_t previousPosition, uint8_t count) +{ + EndpointId endpoint = 0; + + EmberAfStatus status = Switch::Attributes::CurrentPosition::Set(endpoint, 0); + VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(NotSpecified, "Failed to reset CurrentPosition attribute")); + ChipLogDetail(NotSpecified, "The previous position when the momentary switch has been pressed in a multi-press sequence:%d", + previousPosition); + ChipLogDetail(NotSpecified, "%d times the momentary switch has been pressed", count); + + Clusters::SwitchServer::Instance().OnMultiPressComplete(endpoint, previousPosition, count); +} + +void LightingAppCommandDelegate::OnEventCommandReceived(const char * json) +{ + auto handler = LightingAppCommandHandler::FromJSON(json); + if (nullptr == handler) + { + ChipLogError(NotSpecified, "AllClusters App: Unable to instantiate a command handler"); + return; + } + + chip::DeviceLayer::PlatformMgr().ScheduleWork(LightingAppCommandHandler::HandleCommand, reinterpret_cast(handler)); +} diff --git a/examples/lighting-app/linux/LightingAppCommandDelegate.h b/examples/lighting-app/linux/LightingAppCommandDelegate.h new file mode 100644 index 00000000000000..6cbf83d7cdaa1f --- /dev/null +++ b/examples/lighting-app/linux/LightingAppCommandDelegate.h @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "NamedPipeCommands.h" + +#include +#include + +class LightingAppCommandHandler +{ +public: + static LightingAppCommandHandler * FromJSON(const char * json); + + static void HandleCommand(intptr_t context); + + LightingAppCommandHandler(Json::Value && jasonValue) : mJsonValue(std::move(jasonValue)) {} + +private: + Json::Value mJsonValue; + + bool IsClusterPresentOnAnyEndpoint(chip::ClusterId clusterId); + + /** + * Should be called when a reason that caused the device to start-up has been set. + */ + void OnRebootSignalHandler(chip::DeviceLayer::BootReasonType bootReason); + + /** + * Should be called when a general fault takes place on the Node. + */ + void OnGeneralFaultEventHandler(uint32_t eventId); + + /** + * Should be called when a software fault takes place on the Node. + */ + void OnSoftwareFaultEventHandler(uint32_t eventId); + + /** + * Should be called when the latching switch is moved to a new position. + */ + void OnSwitchLatchedHandler(uint8_t newPosition); + + /** + * Should be called when the momentary switch starts to be pressed. + */ + void OnSwitchInitialPressedHandler(uint8_t newPosition); + + /** + * Should be called when the momentary switch has been pressed for a "long" time. + */ + void OnSwitchLongPressedHandler(uint8_t newPosition); + + /** + * Should be called when the momentary switch has been released. + */ + void OnSwitchShortReleasedHandler(uint8_t previousPosition); + + /** + * Should be called when the momentary switch has been released after having been pressed for a long time. + */ + void OnSwitchLongReleasedHandler(uint8_t previousPosition); + + /** + * Should be called to indicate how many times the momentary switch has been pressed in a multi-press + * sequence, during that sequence. + */ + void OnSwitchMultiPressOngoingHandler(uint8_t newPosition, uint8_t count); + + /** + * Should be called to indicate how many times the momentary switch has been pressed in a multi-press + * sequence, after it has been detected that the sequence has ended. + */ + void OnSwitchMultiPressCompleteHandler(uint8_t previousPosition, uint8_t count); +}; + +class LightingAppCommandDelegate : public NamedPipeCommandDelegate +{ +public: + void OnEventCommandReceived(const char * json) override; +}; diff --git a/examples/lighting-app/linux/README.md b/examples/lighting-app/linux/README.md index f41a351da1bebb..ff2c9b1bf50611 100644 --- a/examples/lighting-app/linux/README.md +++ b/examples/lighting-app/linux/README.md @@ -143,3 +143,115 @@ Obtain tracing json file. $ ./{PIGWEED_REPO}/pw_trace_tokenized/py/pw_trace_tokenized/get_trace.py -s localhost:33000 \ -o {OUTPUT_FILE} -t {ELF_FILE} {PIGWEED_REPO}/pw_trace_tokenized/pw_trace_protos/trace_rpc.proto ``` + +## Trigger event using lighting-app event named pipe + +You can send a command to lighting-app to trigger specific event via +lighting-app event named pipe /tmp/chip_lighting_fifo-. + +### Trigger `SoftwareFault` events + +1. Generate event `SoftwareFault` when a software fault takes place on the Node. + +``` +$ echo '{"Name":"SoftwareFault"}' > /tmp/chip_lighting_fifo- +``` + +### Trigger `HardwareFault` events + +1. Generate event `HardwareFaultChange` to indicate a change in the set of + hardware faults currently detected by the Node. + +``` +$ echo '{"Name":"HardwareFaultChange"}' > /tmp/chip_lighting_fifo- +``` + +2. Generate event `RadioFaultChange` to indicate a change in the set of radio + faults currently detected by the Node. + +``` +$ echo '{"Name":"RadioFaultChange"}' > /tmp/chip_lighting_fifo- +``` + +3. Generate event `NetworkFaultChange` to indicate a change in the set of + network faults currently detected by the Node. + +``` +$ echo '{"Name":"NetworkFaultChange"}' > /tmp/chip_lighting_fifo- +``` + +4. Generate event `BootReason` to indicate the reason that caused the device to + start-up, from the following set of `BootReasons`. + +- `PowerOnReboot` The Node has booted as the result of physical interaction + with the device resulting in a reboot. + +- `BrownOutReset` The Node has rebooted as the result of a brown-out of the + Node’s power supply. + +- `SoftwareWatchdogReset` The Node has rebooted as the result of a software + watchdog timer. + +- `HardwareWatchdogReset` The Node has rebooted as the result of a hardware + watchdog timer. + +- `SoftwareUpdateCompleted` The Node has rebooted as the result of a completed + software update. + +- `SoftwareReset` The Node has rebooted as the result of a software initiated + reboot. + +``` +$ echo '{"Name":""}' > /tmp/chip_lighting_fifo- +``` + +### Trigger Switch events + +1. Generate event `SwitchLatched`, when the latching switch is moved to a new + position. + +``` +$ echo '{"Name":"SwitchLatched","NewPosition":3}' > /tmp/chip_lighting_fifo- +``` + +2. Generate event `InitialPress`, when the momentary switch starts to be + pressed. + +``` +$ echo '{"Name":"InitialPress","NewPosition":3}' > /tmp/chip_lighting_fifo- +``` + +3. Generate event `LongPress`, when the momentary switch has been pressed for a + "long" time. + +``` +$ echo '{"Name":"LongPress","NewPosition":3}' > /tmp/chip_lighting_fifo- +``` + +4. Generate event `ShortRelease`, when the momentary switch has been released. + +``` +$ echo '{"Name":"ShortRelease","PreviousPosition":3}' > /tmp/chip_lighting_fifo- +``` + +5. Generate event `LongRelease` when the momentary switch has been released and + after having been pressed for a long time. + +``` +$ echo '{"Name":"LongRelease","PreviousPosition":3}' > /tmp/chip_lighting_fifo- +``` + +6. Generate event `MultiPressOngoing` to indicate how many times the momentary + switch has been pressed in a multi-press sequence, during that sequence. + +``` +$ echo '{"Name":"MultiPressOngoing","NewPosition":3,"CurrentNumberOfPressesCounted":4}' > /tmp/chip_lighting_fifo- +``` + +7. Generate event `MultiPressComplete` to indicate how many times the momentary + switch has been pressed in a multi-press sequence, after it has been detected + that the sequence has ended. + +``` +$ echo '{"Name":"MultiPressComplete","PreviousPosition":3,"TotalNumberOfPressesCounted":2}' > /tmp/chip_lighting_fifo- +``` diff --git a/examples/lighting-app/linux/main.cpp b/examples/lighting-app/linux/main.cpp index 00e94b2c1d413e..5689a0cd68979c 100644 --- a/examples/lighting-app/linux/main.cpp +++ b/examples/lighting-app/linux/main.cpp @@ -16,6 +16,7 @@ * limitations under the License. */ +#include "LightingAppCommandDelegate.h" #include "LightingManager.h" #include @@ -37,6 +38,13 @@ using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; +namespace { + +constexpr const char kChipEventFifoPathPrefix[] = "/tmp/chip_lighting_fifo_"; +NamedPipeCommands sChipNamedPipeCommands; +LightingAppCommandDelegate sLightingAppCommandDelegate; +} // namespace + void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, uint8_t * value) { @@ -66,7 +74,24 @@ void emberAfOnOffClusterInitCallback(EndpointId endpoint) // TODO: implement any additional Cluster Server init actions } -void ApplicationInit() {} +void ApplicationInit() +{ + std::string path = kChipEventFifoPathPrefix + std::to_string(getpid()); + + if (sChipNamedPipeCommands.Start(path, &sLightingAppCommandDelegate) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to start CHIP NamedPipeCommands"); + sChipNamedPipeCommands.Stop(); + } +} + +void ApplicationExit() +{ + if (sChipNamedPipeCommands.Stop() != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to stop CHIP NamedPipeCommands"); + } +} int main(int argc, char * argv[]) {