/* * * 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 "controller/InvokeInteraction.h" #include "controller/ReadInteraction.h" #include #if CONFIG_ENABLE_CHIP_SHELL #include "lib/shell/Engine.h" #include "lib/shell/commands/Help.h" #endif // ENABLE_CHIP_SHELL using namespace chip; using namespace chip::app; #if CONFIG_ENABLE_CHIP_SHELL using Shell::Engine; using Shell::shell_command_t; using Shell::streamer_get; using Shell::streamer_printf; Engine sShellSwitchThermostatSubCommands; Engine sShellSwitchThermostatReadSubCommands; Engine sShellSwitchGroupsThermostatSubCommands; #endif // defined(ENABLE_CHIP_SHELL) void ProcessThermostatUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device) { auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) { ChipLogProgress(NotSpecified, "Read Thermostat attribute succeeds"); }; auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) { ChipLogError(NotSpecified, "Read Thermostat attribute failed: %" CHIP_ERROR_FORMAT, error.Format()); }; VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); switch (data->attributeId) { case Clusters::Thermostat::Attributes::AttributeList::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::LocalTemperature::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::AbsMinHeatSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::AbsMaxHeatSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::AbsMinCoolSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::AbsMaxCoolSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::PICoolingDemand::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::PIHeatingDemand::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::MinHeatSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::MaxHeatSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::MinCoolSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::MaxCoolSetpointLimit::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::ControlSequenceOfOperation::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; case Clusters::Thermostat::Attributes::SystemMode::Id: Controller::ReadAttribute( peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); break; } } void ProcessThermostatUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device) { auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { ChipLogProgress(NotSpecified, "Thermostat command succeeds"); }; auto onFailure = [](CHIP_ERROR error) { ChipLogError(NotSpecified, "Thermostat command failed: %" CHIP_ERROR_FORMAT, error.Format()); }; VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); Clusters::Thermostat::Commands::SetpointRaiseLower::Type setpointRaiseLowerCommand; switch (data->commandId) { case Clusters::Thermostat::Commands::SetpointRaiseLower::Id: setpointRaiseLowerCommand.mode = static_cast(data->args[0]); setpointRaiseLowerCommand.amount = static_cast(data->args[1]); Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, setpointRaiseLowerCommand, onSuccess, onFailure); break; } } void ProcessThermostatGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding) { Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); Clusters::Thermostat::Commands::SetpointRaiseLower::Type setpointRaiseLowerCommand; switch (data->commandId) { case Clusters::Thermostat::Commands::SetpointRaiseLower::Id: setpointRaiseLowerCommand.mode = static_cast(data->args[0]); setpointRaiseLowerCommand.amount = static_cast(data->args[1]); Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, setpointRaiseLowerCommand); break; } } #if CONFIG_ENABLE_CHIP_SHELL /******************************************************** * Thermostat switch shell functions *********************************************************/ CHIP_ERROR ThermostatHelpHandler(int argc, char ** argv) { sShellSwitchThermostatSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatSwitchCommandHandler(int argc, char ** argv) { if (argc == 0) { return ThermostatHelpHandler(argc, argv); } return sShellSwitchThermostatSubCommands.ExecCommand(argc, argv); } CHIP_ERROR SetpointRaiseLowerSwitchCommandHandler(int argc, char ** argv) { if (argc != 2) { return ThermostatHelpHandler(argc, argv); } BindingCommandData * data = Platform::New(); data->commandId = Clusters::Thermostat::Commands::SetpointRaiseLower::Id; data->clusterId = Clusters::Thermostat::Id; data->args[0] = atoi(argv[0]); data->args[1] = atoi(argv[1]); DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } /******************************************************** * Thermostat Read switch shell functions *********************************************************/ CHIP_ERROR ThermostatReadHelpHandler(int argc, char ** argv) { sShellSwitchThermostatReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatRead(int argc, char ** argv) { if (argc == 0) { return ThermostatReadHelpHandler(argc, argv); } return sShellSwitchThermostatReadSubCommands.ExecCommand(argc, argv); } CHIP_ERROR ThermostatReadAttributeList(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::AttributeList::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadLocalTemperature(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::LocalTemperature::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadAbsMinHeatSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::AbsMinHeatSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadAbsMaxHeatSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::AbsMaxHeatSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadAbsMinCoolSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::AbsMinCoolSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadAbsMaxCoolSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::AbsMaxCoolSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadPiCoolingDemand(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::PICoolingDemand::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadPiHeatingDemand(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::PIHeatingDemand::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadOccupiedCoolingSetpoint(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadOccupiedHeatingSetpoint(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadMinHeatSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::MinHeatSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadMaxHeatSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::MaxHeatSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadMinCoolSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::MinCoolSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadMaxCoolSetpointLimit(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::MaxCoolSetpointLimit::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadControlSequenceOfOperation(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::ControlSequenceOfOperation::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } CHIP_ERROR ThermostatReadSystemMode(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->attributeId = Clusters::Thermostat::Attributes::SystemMode::Id; data->clusterId = Clusters::Thermostat::Id; data->isReadAttribute = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } /******************************************************** * Groups Thermostat switch shell functions *********************************************************/ CHIP_ERROR GroupsThermostatHelpHandler(int argc, char ** argv) { sShellSwitchGroupsThermostatSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); return CHIP_NO_ERROR; } CHIP_ERROR GroupsThermostatSwitchCommandHandler(int argc, char ** argv) { if (argc == 0) { return GroupsThermostatHelpHandler(argc, argv); } return sShellSwitchGroupsThermostatSubCommands.ExecCommand(argc, argv); } CHIP_ERROR GroupsSetpointRaiseLowerSwitchCommandHandler(int argc, char ** argv) { BindingCommandData * data = Platform::New(); data->commandId = Clusters::Thermostat::Commands::SetpointRaiseLower::Id; data->clusterId = Clusters::Thermostat::Id; data->isGroup = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); return CHIP_NO_ERROR; } #endif // CONFIG_ENABLE_CHIP_SHELL