Skip to content

Commit

Permalink
Use named pipe instead of signal to trigger the event (#20560)
Browse files Browse the repository at this point in the history
* Use named pipe instead of signal to trigger the event

* Address review comments

* Refactor using NamedPipeCommands and NamedPipeCommandDelegate for future customization
  • Loading branch information
yufengwangca authored and pull[bot] committed Oct 19, 2023
1 parent 8879e73 commit 15ca724
Show file tree
Hide file tree
Showing 10 changed files with 616 additions and 254 deletions.
261 changes: 261 additions & 0 deletions examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp
Original file line number Diff line number Diff line change
@@ -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 <app-common/zap-generated/att-storage.h>
#include <app-common/zap-generated/attribute-type.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/clusters/general-diagnostics-server/general-diagnostics-server.h>
#include <app/clusters/software-diagnostics-server/software-diagnostics-server.h>
#include <app/clusters/switch-server/switch-server.h>
#include <app/server/Server.h>
#include <platform/PlatformManager.h>

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<intptr_t>(this));
}

void AllClustersCommandDelegate::HandleEventCommand(intptr_t context)
{
auto * self = reinterpret_cast<AllClustersCommandDelegate *>(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<uint32_t>(bootReason)) != CHIP_NO_ERROR)
{
Server::GetInstance().DispatchShutDownAndStopEventLoop();
}
else
{
ChipLogError(NotSpecified, "Failed to store boot reason:%d", static_cast<uint32_t>(bootReason));
}
}

void AllClustersCommandDelegate::OnGeneralFaultEventHandler(uint32_t eventId)
{
if (!IsClusterPresentOnAnyEndpoint(Clusters::GeneralDiagnostics::Id))
return;

if (eventId == Clusters::GeneralDiagnostics::Events::HardwareFaultChange::Id)
{
GeneralFaults<kMaxHardwareFaults> previous;
GeneralFaults<kMaxHardwareFaults> 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<kMaxRadioFaults> previous;
GeneralFaults<kMaxRadioFaults> 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<kMaxNetworkFaults> previous;
GeneralFaults<kMaxNetworkFaults> 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<uint64_t>(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);
}
}
56 changes: 56 additions & 0 deletions examples/all-clusters-app/linux/AllClustersCommandDelegate.h
Original file line number Diff line number Diff line change
@@ -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 <platform/DiagnosticDataProvider.h>

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);
};
2 changes: 2 additions & 0 deletions examples/all-clusters-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading

0 comments on commit 15ca724

Please sign in to comment.