diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp new file mode 100644 index 00000000000000..fcd5703cf30e6a --- /dev/null +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp @@ -0,0 +1,261 @@ +/* + * + * Copyright (c) 2022 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 "AllClustersCommandDelegate.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::DeviceLayer; + +void AllClustersCommandDelegate::OnEventCommandReceived(const char * command) +{ + mCurrentCommand.assign(command); + + DeviceLayer::PlatformMgr().ScheduleWork(HandleEventCommand, reinterpret_cast(this)); +} + +void AllClustersCommandDelegate::HandleEventCommand(intptr_t context) +{ + auto * self = reinterpret_cast(context); + + if (self->mCurrentCommand == "SoftwareFault") + { + self->OnSoftwareFaultEventHandler(Clusters::SoftwareDiagnostics::Events::SoftwareFault::Id); + } + else if (self->mCurrentCommand == "HardwareFaultChange") + { + self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id); + } + else if (self->mCurrentCommand == "RadioFaultChange") + { + self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id); + } + else if (self->mCurrentCommand == "NetworkFaultChange") + { + self->OnGeneralFaultEventHandler(Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id); + } + else if (self->mCurrentCommand == "SwitchLatched") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::SwitchLatched::Id); + } + else if (self->mCurrentCommand == "InitialPress") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::InitialPress::Id); + } + else if (self->mCurrentCommand == "LongPress") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::LongPress::Id); + } + else if (self->mCurrentCommand == "ShortRelease") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::ShortRelease::Id); + } + else if (self->mCurrentCommand == "LongRelease") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::LongRelease::Id); + } + else if (self->mCurrentCommand == "MultiPressOngoing") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::MultiPressOngoing::Id); + } + else if (self->mCurrentCommand == "MultiPressComplete") + { + self->OnSwitchEventHandler(Clusters::Switch::Events::MultiPressComplete::Id); + } + else if (self->mCurrentCommand == "PowerOnReboot") + { + self->OnRebootSignalHandler(BootReasonType::kPowerOnReboot); + } + else if (self->mCurrentCommand == "BrownOutReset") + { + self->OnRebootSignalHandler(BootReasonType::kBrownOutReset); + } + else if (self->mCurrentCommand == "SoftwareWatchdogReset") + { + self->OnRebootSignalHandler(BootReasonType::kSoftwareWatchdogReset); + } + else if (self->mCurrentCommand == "HardwareWatchdogReset") + { + self->OnRebootSignalHandler(BootReasonType::kHardwareWatchdogReset); + } + else if (self->mCurrentCommand == "SoftwareUpdateCompleted") + { + self->OnRebootSignalHandler(BootReasonType::kSoftwareUpdateCompleted); + } + else if (self->mCurrentCommand == "SoftwareReset") + { + self->OnRebootSignalHandler(BootReasonType::kSoftwareReset); + } + else + { + ChipLogError(NotSpecified, "Unhandled command: Should never happens"); + } +} + +bool AllClustersCommandDelegate::IsClusterPresentOnAnyEndpoint(ClusterId clusterId) +{ + EnabledEndpointsWithServerCluster enabledEndpoints(clusterId); + + return (enabledEndpoints.begin() != enabledEndpoints.end()); +} + +void AllClustersCommandDelegate::OnRebootSignalHandler(BootReasonType bootReason) +{ + if (ConfigurationMgr().StoreBootReason(static_cast(bootReason)) != CHIP_NO_ERROR) + { + Server::GetInstance().DispatchShutDownAndStopEventLoop(); + } + else + { + ChipLogError(NotSpecified, "Failed to store boot reason:%d", static_cast(bootReason)); + } +} + +void AllClustersCommandDelegate::OnGeneralFaultEventHandler(uint32_t eventId) +{ + if (!IsClusterPresentOnAnyEndpoint(Clusters::GeneralDiagnostics::Id)) + return; + + if (eventId == Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id) + { + GeneralFaults previous; + GeneralFaults current; + +#if CHIP_CONFIG_TEST + // On Linux Simulation, set following hardware faults statically. + ReturnOnFailure(previous.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_RADIO)); + ReturnOnFailure(previous.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_POWER_SOURCE)); + + ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_RADIO)); + ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_SENSOR)); + ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_POWER_SOURCE)); + ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_USER_INTERFACE_FAULT)); +#endif + Clusters::GeneralDiagnosticsServer::Instance().OnHardwareFaultsDetect(previous, current); + } + else if (eventId == Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id) + { + GeneralFaults previous; + GeneralFaults current; + +#if CHIP_CONFIG_TEST + // On Linux Simulation, set following radio faults statically. + ReturnOnFailure(previous.add(EMBER_ZCL_RADIO_FAULT_TYPE_WI_FI_FAULT)); + ReturnOnFailure(previous.add(EMBER_ZCL_RADIO_FAULT_TYPE_THREAD_FAULT)); + + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_WI_FI_FAULT)); + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_CELLULAR_FAULT)); + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_THREAD_FAULT)); + ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_NFC_FAULT)); +#endif + Clusters::GeneralDiagnosticsServer::Instance().OnRadioFaultsDetect(previous, current); + } + else if (eventId == Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id) + { + GeneralFaults previous; + GeneralFaults current; + +#if CHIP_CONFIG_TEST + // On Linux Simulation, set following radio faults statically. + ReturnOnFailure(previous.add(EMBER_ZCL_NETWORK_FAULT_TYPE_HARDWARE_FAILURE)); + ReturnOnFailure(previous.add(EMBER_ZCL_NETWORK_FAULT_TYPE_NETWORK_JAMMED)); + + ReturnOnFailure(current.add(EMBER_ZCL_NETWORK_FAULT_TYPE_HARDWARE_FAILURE)); + ReturnOnFailure(current.add(EMBER_ZCL_NETWORK_FAULT_TYPE_NETWORK_JAMMED)); + ReturnOnFailure(current.add(EMBER_ZCL_NETWORK_FAULT_TYPE_CONNECTION_FAILED)); +#endif + Clusters::GeneralDiagnosticsServer::Instance().OnNetworkFaultsDetect(previous, current); + } + else + { + ChipLogError(NotSpecified, "Unknow event ID:%d", eventId); + } +} + +void AllClustersCommandDelegate::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); + char * asctime = std::asctime(std::localtime(&result)); + softwareFault.faultRecording.SetValue(ByteSpan(Uint8::from_const_char(asctime), strlen(asctime))); + + Clusters::SoftwareDiagnosticsServer::Instance().OnSoftwareFaultDetect(softwareFault); +} + +void AllClustersCommandDelegate::OnSwitchEventHandler(uint32_t eventId) +{ + EndpointId endpoint = 1; + uint8_t newPosition = 20; + uint8_t previousPosition = 10; + uint8_t count = 3; + + if (eventId == Clusters::Switch::Events::SwitchLatched::Id) + { + Clusters::SwitchServer::Instance().OnSwitchLatch(endpoint, newPosition); + } + else if (eventId == Clusters::Switch::Events::InitialPress::Id) + { + Clusters::SwitchServer::Instance().OnInitialPress(endpoint, newPosition); + } + else if (eventId == Clusters::Switch::Events::LongPress::Id) + { + Clusters::SwitchServer::Instance().OnLongPress(endpoint, newPosition); + } + else if (eventId == Clusters::Switch::Events::ShortRelease::Id) + { + Clusters::SwitchServer::Instance().OnShortRelease(endpoint, previousPosition); + } + else if (eventId == Clusters::Switch::Events::LongRelease::Id) + { + Clusters::SwitchServer::Instance().OnLongRelease(endpoint, previousPosition); + } + else if (eventId == Clusters::Switch::Events::MultiPressOngoing::Id) + { + Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpoint, newPosition, count); + } + else if (eventId == Clusters::Switch::Events::MultiPressComplete::Id) + { + Clusters::SwitchServer::Instance().OnMultiPressComplete(endpoint, newPosition, count); + } + else + { + ChipLogError(NotSpecified, "Unknow event ID:%d", eventId); + } +} diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.h b/examples/all-clusters-app/linux/AllClustersCommandDelegate.h new file mode 100644 index 00000000000000..74285343a0f809 --- /dev/null +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2022 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 + +class AllClustersCommandDelegate : public NamedPipeCommandDelegate +{ +public: + void OnEventCommandReceived(const char * command) override; + +private: + std::string mCurrentCommand; + + static void HandleEventCommand(intptr_t context); + + 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 a switch operation takes place on the Node. + */ + void OnSwitchEventHandler(uint32_t eventId); +}; diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 52139ef1338da2..f09889e8870ffb 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -24,7 +24,9 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", + "AllClustersCommandDelegate.cpp", "AppOptions.cpp", + "NamedPipeCommands.cpp", "include/tv-callbacks.cpp", "include/tv-callbacks.h", "main-common.cpp", diff --git a/examples/all-clusters-app/linux/NamedPipeCommands.cpp b/examples/all-clusters-app/linux/NamedPipeCommands.cpp new file mode 100644 index 00000000000000..a7f1de478d75fd --- /dev/null +++ b/examples/all-clusters-app/linux/NamedPipeCommands.cpp @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2022 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 "NamedPipeCommands.h" + +#include +#include +#include +#include +#include + +static constexpr const size_t kChipEventCmdBufSize = 80; + +CHIP_ERROR NamedPipeCommands::Start(std::string & path, NamedPipeCommandDelegate * delegate) +{ + VerifyOrReturnError(!mStarted, CHIP_NO_ERROR); + VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + mStarted = true; + mDelegate = delegate; + mChipEventFifoPath = path; + + // Creating the named file(FIFO) + VerifyOrReturnError((mkfifo(path.c_str(), 0666) == 0) || (errno == EEXIST), CHIP_ERROR_OPEN_FAILED); + VerifyOrReturnError( + pthread_create(&mChipEventCommandListener, nullptr, EventCommandListenerTask, reinterpret_cast(this)) == 0, + CHIP_ERROR_UNEXPECTED_EVENT); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR NamedPipeCommands::Stop() +{ + VerifyOrReturnError(mStarted, CHIP_NO_ERROR); + + mStarted = false; + mDelegate = nullptr; + + VerifyOrReturnError(pthread_cancel(mChipEventCommandListener) == 0, CHIP_ERROR_CANCELLED); + + // Wait further for the thread to terminate if we had previously created it. + VerifyOrReturnError(pthread_join(mChipEventCommandListener, nullptr) == 0, CHIP_ERROR_SHUT_DOWN); + + VerifyOrReturnError(unlink(mChipEventFifoPath.c_str()) == 0, CHIP_ERROR_WRITE_FAILED); + mChipEventFifoPath.clear(); + + return CHIP_NO_ERROR; +} + +void * NamedPipeCommands::EventCommandListenerTask(void * arg) +{ + char readbuf[kChipEventCmdBufSize]; + + NamedPipeCommands * self = reinterpret_cast(arg); + + for (;;) + { + int fd = open(self->mChipEventFifoPath.c_str(), O_RDONLY); + if (fd == -1) + { + ChipLogError(NotSpecified, "Failed to open Event FIFO"); + break; + } + + ssize_t readBytes = read(fd, readbuf, kChipEventCmdBufSize); + readbuf[readBytes - 1] = '\0'; + ChipLogProgress(NotSpecified, "Received payload: \"%s\" and length is %ld\n", readbuf, readBytes); + + // Process the received command request from event fifo + self->mDelegate->OnEventCommandReceived(readbuf); + + close(fd); + } + + return nullptr; +} diff --git a/examples/all-clusters-app/linux/NamedPipeCommands.h b/examples/all-clusters-app/linux/NamedPipeCommands.h new file mode 100644 index 00000000000000..16b8cd4cd32c2a --- /dev/null +++ b/examples/all-clusters-app/linux/NamedPipeCommands.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2022 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 +#include + +class NamedPipeCommandDelegate +{ +public: + virtual ~NamedPipeCommandDelegate() = default; + virtual void OnEventCommandReceived(const char * payload) = 0; +}; + +class NamedPipeCommands +{ +public: + CHIP_ERROR Start(std::string & path, NamedPipeCommandDelegate * delegate); + CHIP_ERROR Stop(); + +private: + bool mStarted = false; + pthread_t mChipEventCommandListener; + std::string mChipEventFifoPath; + NamedPipeCommandDelegate * mDelegate = nullptr; + + static void * EventCommandListenerTask(void * arg); +}; diff --git a/examples/all-clusters-app/linux/README.md b/examples/all-clusters-app/linux/README.md index d0ce8dba69774d..f92e6995ef4be1 100644 --- a/examples/all-clusters-app/linux/README.md +++ b/examples/all-clusters-app/linux/README.md @@ -70,3 +70,115 @@ The binary can be run with `-help=1` to see more available options. Running with `ASAN_OPTIONS="handle_abort=2"` set in the environment may produce nicer stack traces. + +### Trigger event using all-cluster-app event named pipe + +You can send a command to all-cluster-app to trigger specific event via +all-cluster-app event named pipe /tmp/chip_all_clusters_fifo-. + +#### Trigger `SoftwareFault` events + +1. Generate event `SoftwareFault` when a software fault takes place on the Node. + +``` +$ echo SoftwareFault > /tmp/chip_all_clusters_fifo- +``` + +#### Trigger `HardwareFault` events + +1. Generate event `HardwareFaultChange` to indicate a change in the set of + hardware faults currently detected by the Node. + +``` +$ echo HardwareFaultChange > /tmp/chip_all_clusters_fifo- +``` + +2. Generate event `RadioFaultChange` to indicate a change in the set of radio + faults currently detected by the Node. + +``` +$ echo RadioFaultChange > /tmp/chip_all_clusters_fifo- +``` + +3. Generate event `NetworkFaultChange` to indicate a change in the set of + network faults currently detected by the Node. + +``` +$ echo NetworkFaultChange > /tmp/chip_all_clusters_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 > /tmp/chip_all_clusters_fifo- +``` + +#### Trigger Switch events + +1. Generate event `SwitchLatched`, when the latching switch is moved to a new + position. + +``` +$ echo SwitchLatched > /tmp/chip_all_clusters_fifo- +``` + +2. Generate event `InitialPress`, when the momentary switch starts to be + pressed. + +``` +$ echo InitialPress > /tmp/chip_all_clusters_fifo- +``` + +3. Generate event `LongPress`, when the momentary switch has been pressed for a + "long" time. + +``` +$ echo LongPress > /tmp/chip_all_clusters_fifo- +``` + +4. Generate event `ShortRelease`, when the momentary switch has been released. + +``` +$ echo ShortRelease > /tmp/chip_all_clusters_fifo- +``` + +5. Generate event `LongRelease` when the momentary switch has been released and + after having been pressed for a long time. + +``` +$ echo LongRelease > /tmp/chip_all_clusters_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 MultiPressOngoing > /tmp/chip_all_clusters_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 MultiPressComplete > /tmp/chip_all_clusters_fifo- +``` diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index ea2b7e5094c95e..c017d3c61a05a0 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -16,16 +16,15 @@ * limitations under the License. */ +#include "main-common.h" +#include "AllClustersCommandDelegate.h" #include "include/tv-callbacks.h" #include #include #include #include -#include #include #include -#include -#include #include #include #include @@ -55,155 +54,13 @@ using namespace chip::app; using namespace chip::DeviceLayer; namespace { -static LowPowerManager lowPowerManager; -bool IsClusterPresentOnAnyEndpoint(ClusterId clusterId) -{ - bool retval = false; - - for (auto endpointId : EnabledEndpointsWithServerCluster(clusterId)) - { - IgnoreUnusedVariable(endpointId); - retval = true; - } - - return retval; -} - -/** - * Should be called when a software fault takes place on the Node. - */ -void HandleSoftwareFaultEvent(intptr_t arg) -{ - 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); - char * asctime = std::asctime(std::localtime(&result)); - softwareFault.faultRecording.SetValue(ByteSpan(Uint8::from_const_char(asctime), strlen(asctime))); - - Clusters::SoftwareDiagnosticsServer::Instance().OnSoftwareFaultDetect(softwareFault); -} - -/** - * Should be called when a general fault takes place on the Node. - */ -void HandleGeneralFaultEvent(intptr_t arg) -{ - uint32_t eventId = static_cast(arg); - - if (!IsClusterPresentOnAnyEndpoint(Clusters::GeneralDiagnostics::Id)) - return; - - if (eventId == Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id) - { - GeneralFaults previous; - GeneralFaults current; - -#if CHIP_CONFIG_TEST - // On Linux Simulation, set following hardware faults statically. - ReturnOnFailure(previous.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_RADIO)); - ReturnOnFailure(previous.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_POWER_SOURCE)); - - ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_RADIO)); - ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_SENSOR)); - ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_POWER_SOURCE)); - ReturnOnFailure(current.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_USER_INTERFACE_FAULT)); -#endif - Clusters::GeneralDiagnosticsServer::Instance().OnHardwareFaultsDetect(previous, current); - } - else if (eventId == Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id) - { - GeneralFaults previous; - GeneralFaults current; - -#if CHIP_CONFIG_TEST - // On Linux Simulation, set following radio faults statically. - ReturnOnFailure(previous.add(EMBER_ZCL_RADIO_FAULT_TYPE_WI_FI_FAULT)); - ReturnOnFailure(previous.add(EMBER_ZCL_RADIO_FAULT_TYPE_THREAD_FAULT)); - - ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_WI_FI_FAULT)); - ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_CELLULAR_FAULT)); - ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_THREAD_FAULT)); - ReturnOnFailure(current.add(EMBER_ZCL_RADIO_FAULT_TYPE_NFC_FAULT)); -#endif - Clusters::GeneralDiagnosticsServer::Instance().OnRadioFaultsDetect(previous, current); - } - else if (eventId == Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id) - { - GeneralFaults previous; - GeneralFaults current; +constexpr const char kChipEventFifoPathPrefix[] = "/tmp/chip_all_cluster_fifo_"; +LowPowerManager sLowPowerManager; +NamedPipeCommands sChipNamedPipeCommands; +AllClustersCommandDelegate sAllClustersCommandDelegate; -#if CHIP_CONFIG_TEST - // On Linux Simulation, set following radio faults statically. - ReturnOnFailure(previous.add(EMBER_ZCL_NETWORK_FAULT_TYPE_HARDWARE_FAILURE)); - ReturnOnFailure(previous.add(EMBER_ZCL_NETWORK_FAULT_TYPE_NETWORK_JAMMED)); - - ReturnOnFailure(current.add(EMBER_ZCL_NETWORK_FAULT_TYPE_HARDWARE_FAILURE)); - ReturnOnFailure(current.add(EMBER_ZCL_NETWORK_FAULT_TYPE_NETWORK_JAMMED)); - ReturnOnFailure(current.add(EMBER_ZCL_NETWORK_FAULT_TYPE_CONNECTION_FAILED)); -#endif - Clusters::GeneralDiagnosticsServer::Instance().OnNetworkFaultsDetect(previous, current); - } - else - { - ChipLogError(DeviceLayer, "Unknow event ID:%d", eventId); - } -} - -/** - * Should be called when a switch operation takes place on the Node. - */ -void HandleSwitchEvent(intptr_t arg) -{ - uint32_t eventId = static_cast(arg); - - EndpointId endpoint = 1; - uint8_t newPosition = 20; - uint8_t previousPosition = 10; - uint8_t count = 3; - - if (eventId == Clusters::Switch::Events::SwitchLatched::Id) - { - Clusters::SwitchServer::Instance().OnSwitchLatch(endpoint, newPosition); - } - else if (eventId == Clusters::Switch::Events::InitialPress::Id) - { - Clusters::SwitchServer::Instance().OnInitialPress(endpoint, newPosition); - } - else if (eventId == Clusters::Switch::Events::LongPress::Id) - { - Clusters::SwitchServer::Instance().OnLongPress(endpoint, newPosition); - } - else if (eventId == Clusters::Switch::Events::ShortRelease::Id) - { - Clusters::SwitchServer::Instance().OnShortRelease(endpoint, previousPosition); - } - else if (eventId == Clusters::Switch::Events::LongRelease::Id) - { - Clusters::SwitchServer::Instance().OnLongRelease(endpoint, previousPosition); - } - else if (eventId == Clusters::Switch::Events::MultiPressOngoing::Id) - { - Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpoint, newPosition, count); - } - else if (eventId == Clusters::Switch::Events::MultiPressComplete::Id) - { - Clusters::SwitchServer::Instance().OnMultiPressComplete(endpoint, newPosition, count); - } - else - { - ChipLogError(DeviceLayer, "Unknow event ID:%d", eventId); - } -} +// TODO(#20664) REPL test will fail if signal SIGINT is not caught, temporarily keep following logic. // when the shell is enabled, don't intercept signals since it prevents the user from // using expected commands like CTRL-C to quit the application. (see issue #17845) @@ -220,21 +77,6 @@ void OnRebootSignalHandler(int signum) BootReasonType bootReason = BootReasonType::kUnspecified; switch (signum) { - case SIGVTALRM: - bootReason = BootReasonType::kPowerOnReboot; - break; - case SIGALRM: - bootReason = BootReasonType::kBrownOutReset; - break; - case SIGILL: - bootReason = BootReasonType::kSoftwareWatchdogReset; - break; - case SIGTRAP: - bootReason = BootReasonType::kHardwareWatchdogReset; - break; - case SIGIO: - bootReason = BootReasonType::kSoftwareUpdateCompleted; - break; case SIGINT: bootReason = BootReasonType::kSoftwareReset; break; @@ -248,97 +90,11 @@ void OnRebootSignalHandler(int signum) Server::GetInstance().DispatchShutDownAndStopEventLoop(); } -void OnSoftwareFaultSignalHandler(int signum) -{ - ChipLogDetail(DeviceLayer, "Caught signal %d", signum); - - VerifyOrDie(signum == SIGUSR1); - PlatformMgr().ScheduleWork(HandleSoftwareFaultEvent); -} - -void OnGeneralFaultSignalHandler(int signum) -{ - ChipLogDetail(DeviceLayer, "Caught signal %d", signum); - - uint32_t eventId; - switch (signum) - { - case SIGUSR2: - eventId = Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id; - break; - case SIGHUP: - eventId = Clusters::GeneralDiagnostics::Events::RadioFaultChange::Id; - break; - case SIGTTIN: - eventId = Clusters::GeneralDiagnostics::Events::NetworkFaultChange::Id; - break; - default: - ChipLogError(NotSpecified, "Unhandled signal: Should never happens"); - chipDie(); - break; - } - - PlatformMgr().ScheduleWork(HandleGeneralFaultEvent, static_cast(eventId)); -} - -void OnSwitchSignalHandler(int signum) -{ - ChipLogDetail(DeviceLayer, "Caught signal %d", signum); - - uint32_t eventId; - switch (signum) - { - case SIGTSTP: - eventId = Clusters::Switch::Events::SwitchLatched::Id; - break; - case SIGSTOP: - eventId = Clusters::Switch::Events::InitialPress::Id; - break; - case SIGTTOU: - eventId = Clusters::Switch::Events::LongPress::Id; - break; - case SIGWINCH: - eventId = Clusters::Switch::Events::ShortRelease::Id; - break; - case SIGQUIT: - eventId = Clusters::Switch::Events::LongRelease::Id; - break; - case SIGFPE: - eventId = Clusters::Switch::Events::MultiPressOngoing::Id; - break; - case SIGPIPE: - eventId = Clusters::Switch::Events::MultiPressComplete::Id; - break; - default: - ChipLogError(NotSpecified, "Unhandled signal: Should never happens"); - chipDie(); - break; - } - - PlatformMgr().ScheduleWork(HandleSwitchEvent, static_cast(eventId)); -} void SetupSignalHandlers() { // sigaction is not used here because Tsan interceptors seems to // never dispatch the signals on darwin. - signal(SIGALRM, OnRebootSignalHandler); - signal(SIGVTALRM, OnRebootSignalHandler); - signal(SIGILL, OnRebootSignalHandler); - signal(SIGTRAP, OnRebootSignalHandler); - signal(SIGTERM, OnRebootSignalHandler); - signal(SIGIO, OnRebootSignalHandler); signal(SIGINT, OnRebootSignalHandler); - signal(SIGUSR1, OnSoftwareFaultSignalHandler); - signal(SIGUSR2, OnGeneralFaultSignalHandler); - signal(SIGHUP, OnGeneralFaultSignalHandler); - signal(SIGTTIN, OnGeneralFaultSignalHandler); - signal(SIGTSTP, OnSwitchSignalHandler); - signal(SIGSTOP, OnSwitchSignalHandler); - signal(SIGTTOU, OnSwitchSignalHandler); - signal(SIGWINCH, OnSwitchSignalHandler); - signal(SIGQUIT, OnSwitchSignalHandler); - signal(SIGFPE, OnSwitchSignalHandler); - signal(SIGPIPE, OnSwitchSignalHandler); } #endif // !defined(ENABLE_CHIP_SHELL) @@ -485,10 +241,26 @@ void ApplicationInit() { sEthernetNetworkCommissioningInstance.Init(); } + + std::string path = kChipEventFifoPathPrefix + std::to_string(getpid()); + + if (sChipNamedPipeCommands.Start(path, &sAllClustersCommandDelegate) != 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"); + } } void emberAfLowPowerClusterInitCallback(EndpointId endpoint) { - ChipLogProgress(Zcl, "TV Linux App: LowPower::SetDefaultDelegate"); - chip::app::Clusters::LowPower::SetDefaultDelegate(endpoint, &lowPowerManager); + ChipLogProgress(NotSpecified, "TV Linux App: LowPower::SetDefaultDelegate"); + chip::app::Clusters::LowPower::SetDefaultDelegate(endpoint, &sLowPowerManager); } diff --git a/examples/all-clusters-app/linux/main-common.h b/examples/all-clusters-app/linux/main-common.h new file mode 100644 index 00000000000000..d6e076b4416798 --- /dev/null +++ b/examples/all-clusters-app/linux/main-common.h @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2022 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 + +void ApplicationExit(); diff --git a/examples/all-clusters-app/linux/main.cpp b/examples/all-clusters-app/linux/main.cpp index ec71f22c42cc0c..6da40d72d82d4f 100644 --- a/examples/all-clusters-app/linux/main.cpp +++ b/examples/all-clusters-app/linux/main.cpp @@ -19,6 +19,7 @@ #include "AppMain.h" #include "AppOptions.h" #include "binding-handler.h" +#include "main-common.h" int main(int argc, char * argv[]) { @@ -28,5 +29,7 @@ int main(int argc, char * argv[]) LinuxDeviceOptions::GetInstance().dacProvider = AppOptions::GetDACProvider(); ChipLinuxAppMainLoop(); + ApplicationExit(); + return 0; } diff --git a/examples/chip-tool/commands/common/Command.cpp b/examples/chip-tool/commands/common/Command.cpp index 1c645754788d8e..0f738bc4da8ae8 100644 --- a/examples/chip-tool/commands/common/Command.cpp +++ b/examples/chip-tool/commands/common/Command.cpp @@ -55,7 +55,7 @@ bool Command::InitArguments(int argc, char ** argv) } } - VerifyOrExit((size_t) (argc) >= mandatoryArgsCount && (argvExtraArgsCount == 0 || (argvExtraArgsCount && optionalArgsCount)), + VerifyOrExit((size_t)(argc) >= mandatoryArgsCount && (argvExtraArgsCount == 0 || (argvExtraArgsCount && optionalArgsCount)), ChipLogError(chipTool, "InitArgs: Wrong arguments number: %d instead of %u", argc, static_cast(mandatoryArgsCount)));