Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EFR32] Adding shell commands to light-switch example #15515

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions examples/light-switch-app/efr32/include/binding-handler.h
Original file line number Diff line number Diff line change
@@ -16,7 +16,17 @@
*/
#pragma once

#include "app-common/zap-generated/ids/Clusters.h"
#include "app-common/zap-generated/ids/Commands.h"
#include "lib/core/CHIPError.h"

CHIP_ERROR InitBindingHandler();
void SwitchToggleOnOff(intptr_t context);
void SwitchOnOffOn(intptr_t context);
void SwitchOnOffOff(intptr_t context);

struct BindingCommandData
{
chip::CommandId commandId;
chip::ClusterId clusterId;
};
142 changes: 127 additions & 15 deletions examples/light-switch-app/efr32/src/binding-handler.cpp
Original file line number Diff line number Diff line change
@@ -18,51 +18,163 @@
#include "binding-handler.h"

#include "AppConfig.h"
#include "app-common/zap-generated/ids/Clusters.h"
#include "app-common/zap-generated/ids/Commands.h"
#include "app/CommandSender.h"
#include "app/clusters/bindings/BindingManager.h"
#include "app/server/Server.h"
#include "controller/InvokeInteraction.h"

#if defined(ENABLE_CHIP_SHELL)
#include "lib/shell/Engine.h"
#endif // ENABLE_CHIP_SHELL

using namespace chip;
using namespace chip::app;

#if defined(ENABLE_CHIP_SHELL)
using Shell::Engine;
using Shell::shell_command_t;
using Shell::streamer_get;
using Shell::streamer_printf;
#endif // defined(ENABLE_CHIP_SHELL)

namespace {
void BoundDeviceChangedHandler(const EmberBindingTableEntry & binding, chip::DeviceProxy * peer_device, void * context)
{
using namespace chip;
using namespace chip::app;

void ProcessOnOffBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding, DeviceProxy * peer_device)
{
auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
ChipLogProgress(NotSpecified, "OnOff command succeeds");
};

auto onFailure = [](CHIP_ERROR error) {
ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format());
};

switch (commandId)
{
case Clusters::OnOff::Commands::Toggle::Id:
Clusters::OnOff::Commands::Toggle::Type toggleCommand;
Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
toggleCommand, onSuccess, onFailure);
break;

case Clusters::OnOff::Commands::On::Id:
Clusters::OnOff::Commands::On::Type onCommand;
Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
onCommand, onSuccess, onFailure);
break;

case Clusters::OnOff::Commands::Off::Id:
Clusters::OnOff::Commands::Off::Type offCommand;
Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
offCommand, onSuccess, onFailure);
break;

default:
ChipLogError(NotSpecified, "Invalid binding command data - commandId is not supported");
break;
}
}

void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, DeviceProxy * peer_device, void * context)
{
VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "Invalid context for Light switch handler"););
BindingCommandData * data = static_cast<BindingCommandData *>(context);

if (binding.type == EMBER_MULTICAST_BINDING)
{
ChipLogError(NotSpecified, "Group binding is not supported now");
return;
}
else if (binding.type == EMBER_UNICAST_BINDING && binding.local == 1 &&
(!binding.clusterId.HasValue() || binding.clusterId.Value() == data->clusterId))
{

switch (data->clusterId)
{
case Clusters::OnOff::Id:
ProcessOnOffBindingCommand(data->commandId, binding, peer_device);
break;
default:
ChipLogError(NotSpecified, "Invalid binding command data - clusterId is not supported");
break;
}
}

if (binding.type == EMBER_UNICAST_BINDING && binding.local == 1 && binding.clusterId.HasValue() &&
binding.clusterId.Value() == Clusters::OnOff::Id)
Platform::Delete(data);
}

#ifdef ENABLE_CHIP_SHELL
CHIP_ERROR SwitchCommandHandler(int argc, char ** argv)
{
if (argc == 1 && strcmp(argv[0], "on") == 0)
{
Clusters::OnOff::Commands::Toggle::Type toggleCommand;
Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
toggleCommand, onSuccess, onFailure);
DeviceLayer::PlatformMgr().ScheduleWork(SwitchOnOffOn, 0);
}
else if (argc == 1 && strcmp(argv[0], "off") == 0)
{
DeviceLayer::PlatformMgr().ScheduleWork(SwitchOnOffOff, 0);
}
else if (argc == 1 && strcmp(argv[0], "toggle") == 0)
{
DeviceLayer::PlatformMgr().ScheduleWork(SwitchToggleOnOff, 0);
}
else
{
streamer_printf(streamer_get(), "Usage: switch [on|off|toggle]");
}
return CHIP_NO_ERROR;
}

static void RegisterSwitchCommands()
{
static const shell_command_t sSwitchCommand = { SwitchCommandHandler, "switch",
"Switch commands. Usage: switch [on|off|toggle]" };
Engine::Root().RegisterCommands(&sSwitchCommand, 1);
return;
}
#endif // ENABLE_CHIP_SHELL
} // namespace

void SwitchToggleOnOff(intptr_t context)
{
chip::BindingManager::GetInstance().NotifyBoundClusterChanged(1, chip::app::Clusters::OnOff::Id, nullptr);
BindingCommandData * data = Platform::New<BindingCommandData>();
VerifyOrReturn(data != nullptr, ChipLogError(NotSpecified, "SwitchToggleOnOff - Out of Memory of work data"));

data->clusterId = Clusters::OnOff::Id;
data->commandId = Clusters::OnOff::Commands::Toggle::Id;

BindingManager::GetInstance().NotifyBoundClusterChanged(1 /* endpointId */, Clusters::OnOff::Id, static_cast<void *>(data));
}

void SwitchOnOffOn(intptr_t context)
{
BindingCommandData * data = Platform::New<BindingCommandData>();
VerifyOrReturn(data != nullptr, ChipLogError(NotSpecified, "SwitchOnOffOn - Out of Memory of work data"));

data->clusterId = Clusters::OnOff::Id;
data->commandId = Clusters::OnOff::Commands::On::Id;

BindingManager::GetInstance().NotifyBoundClusterChanged(1 /* endpointId */, Clusters::OnOff::Id, static_cast<void *>(data));
}

void SwitchOnOffOff(intptr_t context)
{
BindingCommandData * data = Platform::New<BindingCommandData>();
VerifyOrReturn(data != nullptr, ChipLogError(NotSpecified, "SwitchOnOffOff - Out of Memory of work data"));

data->clusterId = Clusters::OnOff::Id;
data->commandId = Clusters::OnOff::Commands::Off::Id;

BindingManager::GetInstance().NotifyBoundClusterChanged(1 /* endpointId */, Clusters::OnOff::Id, static_cast<void *>(data));
}

CHIP_ERROR InitBindingHandler()
{
chip::BindingManager::GetInstance().SetAppServer(&chip::Server::GetInstance());
chip::BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(BoundDeviceChangedHandler);
BindingManager::GetInstance().SetAppServer(&Server::GetInstance());
BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler);

#if defined(ENABLE_CHIP_SHELL)
RegisterSwitchCommands();
#endif

return CHIP_NO_ERROR;
}