From 148024414848c616bc360db21f896fb313557950 Mon Sep 17 00:00:00 2001 From: Lazar Kovacic Date: Tue, 4 May 2021 19:28:55 +0200 Subject: [PATCH] Updating TV example app to add support for on-off level control commands (#6417) Problem TV example app does not support on and off commands TV example app does not support level control commands Summary of Changes - Added attribute change callback so that developper can detect on-off attribute change and implement logic for TV - Added LevelControl.cpp file so that developper can use it and change current level-control.h file. We do not need all the logic from the current level-control cluster. Handeling step command is enough. Test - Tested locally using chip-tool client and newly created tv-server - Used the zap_regen_all.py and gn_build.sh to verify the building is successful --- examples/tv-app/linux/BUILD.gn | 1 + .../include/cluster-change-attribute.cpp | 65 +++++++ .../include/level-control/LevelControl.cpp | 180 ++++++++++++++++++ examples/tv-app/linux/main.cpp | 4 - 4 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 examples/tv-app/linux/include/cluster-change-attribute.cpp create mode 100644 examples/tv-app/linux/include/level-control/LevelControl.cpp diff --git a/examples/tv-app/linux/BUILD.gn b/examples/tv-app/linux/BUILD.gn index d882f0c763745a..259651bf8cb744 100644 --- a/examples/tv-app/linux/BUILD.gn +++ b/examples/tv-app/linux/BUILD.gn @@ -29,6 +29,7 @@ executable("chip-tv-app") { "include/application-launcher/ApplicationLauncherManager.h", "include/audio-output/AudioOutputManager.cpp", "include/audio-output/AudioOutputManager.h", + "include/cluster-change-attribute.cpp", "include/cluster-init.cpp", "include/content-launcher/ContentLauncherManager.cpp", "include/content-launcher/ContentLauncherManager.h", diff --git a/examples/tv-app/linux/include/cluster-change-attribute.cpp b/examples/tv-app/linux/include/cluster-change-attribute.cpp new file mode 100644 index 00000000000000..0ea165efa5002a --- /dev/null +++ b/examples/tv-app/linux/include/cluster-change-attribute.cpp @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2021 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 "gen/attribute-id.h" +#include "gen/cluster-id.h" +#include + +using namespace chip; + +enum TvCommand +{ + PowerToggle, + MuteToggle +}; + +void runTvCommand(TvCommand command) +{ + switch (command) + { + case PowerToggle: + // TODO: Insert your code here to send power toggle command + break; + case MuteToggle: + // TODO: Insert your code here to send mute toggle command + break; + + default: + break; + } +} + +void emberAfPostAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t mask, + uint16_t manufacturerCode, uint8_t type, uint8_t size, uint8_t * value) +{ + if (clusterId == ZCL_ON_OFF_CLUSTER_ID && attributeId == ZCL_ON_OFF_ATTRIBUTE_ID) + { + ChipLogProgress(Zcl, "Received on/off command for cluster id: %d", clusterId); + + if (endpoint == 0) + { + ChipLogProgress(Zcl, "Execute POWER_TOGGLE"); + runTvCommand(PowerToggle); + } + else if (endpoint == 1) + { + ChipLogProgress(Zcl, "Execute MUTE_TOGGLE"); + runTvCommand(MuteToggle); + } + } +} diff --git a/examples/tv-app/linux/include/level-control/LevelControl.cpp b/examples/tv-app/linux/include/level-control/LevelControl.cpp new file mode 100644 index 00000000000000..aaf79c7de14d5e --- /dev/null +++ b/examples/tv-app/linux/include/level-control/LevelControl.cpp @@ -0,0 +1,180 @@ +/* + * + * Copyright (c) 2021 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 + +#include "gen/af-structs.h" +#include "gen/attribute-id.h" +#include "gen/attribute-type.h" +#include "gen/cluster-id.h" +#include "gen/command-id.h" + +using namespace chip; + +#define MAX_LEVEL 99 +#define MIN_LEVEL 1 + +typedef struct +{ + CommandId commandId; + uint16_t storedLevel; + bool increasing; +} EmberAfLevelControlState; + +static EmberAfLevelControlState stateTable[EMBER_AF_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT]; + +static EmberAfLevelControlState * getState(EndpointId endpoint) +{ + uint8_t ep = emberAfFindClusterServerEndpointIndex(endpoint, ZCL_LEVEL_CONTROL_CLUSTER_ID); + return (ep == 0xFF ? NULL : &stateTable[ep]); +} + +static void stepHandler(CommandId commandId, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTimeDs, uint8_t optionMask, + uint8_t optionOverride) +{ + + EndpointId endpoint = emberAfCurrentEndpoint(); + EmberAfLevelControlState * state = getState(endpoint); + EmberAfStatus status; + uint8_t currentLevel; + + status = emberAfReadServerAttribute(endpoint, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, + (uint8_t *) ¤tLevel, sizeof(currentLevel)); + + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + emberAfLevelControlClusterPrintln("ERR: reading current level %x", status); + goto send_default_response; + } + + switch (stepMode) + { + case EMBER_ZCL_STEP_MODE_UP: + state->increasing = true; + if (MAX_LEVEL >= currentLevel + stepSize) + { + currentLevel = currentLevel + stepSize; + } + break; + case EMBER_ZCL_STEP_MODE_DOWN: + state->increasing = false; + if (MIN_LEVEL <= currentLevel - stepSize) + { + currentLevel = currentLevel - stepSize; + } + break; + default: + status = EMBER_ZCL_STATUS_INVALID_FIELD; + goto send_default_response; + } + + if (currentLevel != state->storedLevel) + { + int volumeIncrementCount = abs(currentLevel - state->storedLevel); + for (int i = 0; i < volumeIncrementCount; ++i) + { + if (state->increasing) + { + ChipLogProgress(Zcl, "Volume UP"); + // TODO: Insert your code here to send volume up command + } + else + { + ChipLogProgress(Zcl, "Volume DOWN"); + // TODO: Insert your code here to send volume down command + } + } + status = emberAfWriteServerAttribute(endpoint, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, + (uint8_t *) ¤tLevel, ZCL_INT8U_ATTRIBUTE_TYPE); + state->storedLevel = currentLevel; + ChipLogProgress(Zcl, "Setting volume to new level %d", state->storedLevel); + } + +send_default_response: + if (emberAfCurrentCommand()->apsFrame->clusterId == ZCL_LEVEL_CONTROL_CLUSTER_ID) + { + emberAfSendImmediateDefaultResponse(status); + } +} + +bool emberAfLevelControlClusterStepCallback(uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, + uint8_t optionOverride) +{ + stepHandler(ZCL_STEP_COMMAND_ID, stepMode, stepSize, transitionTime, optionMask, optionOverride); + return true; +} + +bool emberAfLevelControlClusterMoveCallback(unsigned char, unsigned char, unsigned char, unsigned char) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterMoveToLevelCallback(unsigned char, unsigned short, unsigned char, unsigned char) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(unsigned char, unsigned short) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterMoveWithOnOffCallback(unsigned char, unsigned char) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterStopCallback(unsigned char, unsigned char) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterStopWithOnOffCallback() +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfOnOffClusterLevelControlEffectCallback(unsigned char, bool) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterServerInitCallback(unsigned char) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterStepWithOnOffCallback(unsigned char, unsigned char, unsigned short) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} + +bool emberAfLevelControlClusterServerTickCallback(unsigned char) +{ + ChipLogProgress(Zcl, "Not supported"); + return true; +} diff --git a/examples/tv-app/linux/main.cpp b/examples/tv-app/linux/main.cpp index 64bd0db8a7ef6c..6b5c859328aefc 100644 --- a/examples/tv-app/linux/main.cpp +++ b/examples/tv-app/linux/main.cpp @@ -51,10 +51,6 @@ using namespace chip; using namespace chip::Transport; using namespace chip::DeviceLayer; -void emberAfPostAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t mask, - uint16_t manufacturerCode, uint8_t type, uint8_t size, uint8_t * value) -{} - bool emberAfBasicClusterMfgSpecificPingCallback(chip::app::Command * commandObj) { emberAfSendDefaultResponse(emberAfCurrentCommand(), EMBER_ZCL_STATUS_SUCCESS);