3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * Copyright (c) 2020 Silicon Labs
22 * Licensed under the Apache License, Version 2.0 (the "License");
23 * you may not use this file except in compliance with the License.
24 * You may obtain a copy of the License at
26 * http://www.apache.org/licenses/LICENSE-2.0
28 * Unless required by applicable law or agreed to in writing, software
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
37 * @brief Routines for the ZLL Scenes Server plugin.
38 *******************************************************************************
40 * <b>Copyright 2018 Silicon Laboratories Inc.
42 *******************************************************************************
44 * The licensor of this software is Silicon
45 * Laboratories Inc. Your use of this software is
46 * governed by the terms of Silicon Labs Master
47 * Software License Agreement (MSLA) available at
48 * www.silabs.com/about-us/legal/master-software-license-agreement.
49 * This software is distributed to you in Source Code
50 * format and is governed by the sections of the MSLA
51 * applicable to Source Code.
53 ******************************************************************************/
55 #include "../../include/af.h"
56 #include "../scenes/scenes.h"
58 #define ZCL_SCENES_CLUSTER_MODE_COPY_ALL_SCENES_MASK EMBER_BIT(0)
60 bool emberAfScenesClusterEnhancedAddSceneCallback(uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, uint8_t * sceneName,
61 uint8_t * extensionFieldSets)
63 return emberAfPluginScenesServerParseAddScene(emberAfCurrentCommand(), groupId, sceneId, transitionTime, sceneName,
67 bool emberAfScenesClusterEnhancedViewSceneCallback(uint16_t groupId, uint8_t sceneId)
69 return emberAfPluginScenesServerParseViewScene(emberAfCurrentCommand(), groupId, sceneId);
72 bool emberAfScenesClusterCopySceneCallback(uint8_t mode, uint16_t groupIdFrom, uint8_t sceneIdFrom, uint16_t groupIdTo,
75 EmberStatus sendStatus;
76 EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD;
77 bool copyAllScenes = (mode & ZCL_SCENES_CLUSTER_MODE_COPY_ALL_SCENES_MASK);
80 emberAfScenesClusterPrintln("RX: CopyScene 0x%x, 0x%2x, 0x%x, 0x%2x, 0x%x", mode, groupIdFrom, sceneIdFrom, groupIdTo,
83 // If a group id is specified but this endpoint isn't in it, take no action.
84 if ((groupIdFrom != ZCL_SCENES_GLOBAL_SCENE_GROUP_ID &&
85 !emberAfGroupsClusterEndpointInGroupCallback(emberAfCurrentEndpoint(), groupIdFrom)) ||
86 (groupIdTo != ZCL_SCENES_GLOBAL_SCENE_GROUP_ID &&
87 !emberAfGroupsClusterEndpointInGroupCallback(emberAfCurrentEndpoint(), groupIdTo)))
89 status = EMBER_ZCL_STATUS_INVALID_FIELD;
93 for (i = 0; i < EMBER_AF_PLUGIN_SCENES_TABLE_SIZE; i++)
95 EmberAfSceneTableEntry from;
96 emberAfPluginScenesServerRetrieveSceneEntry(from, i);
97 if (from.endpoint == emberAfCurrentEndpoint() && from.groupId == groupIdFrom &&
98 (copyAllScenes || from.sceneId == sceneIdFrom))
100 uint8_t j, index = EMBER_AF_SCENE_TABLE_NULL_INDEX;
101 for (j = 0; j < EMBER_AF_PLUGIN_SCENES_TABLE_SIZE; j++)
103 EmberAfSceneTableEntry to;
108 emberAfPluginScenesServerRetrieveSceneEntry(to, j);
109 if (to.endpoint == emberAfCurrentEndpoint() && to.groupId == groupIdTo &&
110 to.sceneId == (copyAllScenes ? from.sceneId : sceneIdTo))
115 else if (index == EMBER_AF_SCENE_TABLE_NULL_INDEX && to.endpoint == EMBER_AF_SCENE_TABLE_UNUSED_ENDPOINT_ID)
121 // If the target index is still zero, the table is full.
122 if (index == EMBER_AF_SCENE_TABLE_NULL_INDEX)
124 status = EMBER_ZCL_STATUS_INSUFFICIENT_SPACE;
128 // Save the "from" entry to the "to" index. This makes a copy of "from"
129 // with the correct group and scene ids and leaves the original in tact.
130 from.groupId = groupIdTo;
133 from.sceneId = sceneIdTo;
135 emberAfPluginScenesServerSaveSceneEntry(from, index);
139 emberAfPluginScenesServerIncrNumSceneEntriesInUse();
140 emberAfScenesSetSceneCountAttribute(emberAfCurrentEndpoint(), emberAfPluginScenesServerNumSceneEntriesInUse());
143 // If we aren't copying all scenes, we can stop here.
144 status = EMBER_ZCL_STATUS_SUCCESS;
153 // Copy Scene commands are only responded to when they are addressed to a
155 if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY)
157 emberAfFillCommandScenesClusterCopySceneResponse(status, groupIdFrom, sceneIdFrom);
158 sendStatus = emberAfSendResponse();
159 if (EMBER_SUCCESS != sendStatus)
161 emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "copy_scene", sendStatus);
167 EmberAfStatus emberAfPluginZllScenesServerRecallSceneZllExtensions(uint8_t endpoint)
169 bool globalSceneControl = true;
170 EmberAfStatus status = emberAfWriteServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, ZCL_GLOBAL_SCENE_CONTROL_ATTRIBUTE_ID,
171 (uint8_t *) &globalSceneControl, ZCL_BOOLEAN_ATTRIBUTE_TYPE);
172 if (status != EMBER_ZCL_STATUS_SUCCESS)
174 emberAfScenesClusterPrintln("ERR: writing global scene control %x", status);