Skip to content

Commit b2f95e2

Browse files
committed
Implement scene cluster
1 parent 3f209bc commit b2f95e2

File tree

7 files changed

+160
-8
lines changed

7 files changed

+160
-8
lines changed

makefiles/src.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ $(BUILD_PATH)/$(SRC_DIR)/zigbee/basic_cluster.o \
1919
$(BUILD_PATH)/$(SRC_DIR)/zigbee/group_cluster.o \
2020
$(BUILD_PATH)/$(SRC_DIR)/zigbee/switch_cluster.o \
2121
$(BUILD_PATH)/$(SRC_DIR)/zigbee/relay_cluster.o \
22+
$(BUILD_PATH)/$(SRC_DIR)/zigbee/scene_cluster.o \
2223
$(BUILD_PATH)/$(SRC_DIR)/zigbee/endpoint.o \
2324
$(BUILD_PATH)/$(SRC_DIR)/zigbee/bdb_callbacks.o \
2425
$(BUILD_PATH)/$(SRC_DIR)/zigbee/general.o \

src/app_cfg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ extern "C" {
8787
//#define ZCL_IAS_ZONE_SUPPORT 1
8888
#define ZCL_POLL_CTRL_SUPPORT 0
8989
#define ZCL_GROUP_SUPPORT 1
90+
#define ZCL_SCENE_SUPPORT 1
9091
#define ZCL_OTA_SUPPORT 1
9192
#define TOUCHLINK_SUPPORT 0
9293
#define FIND_AND_BIND_SUPPORT 0

src/device_config/config_parser.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "zigbee/group_cluster.h"
44
#include "zigbee/relay_cluster.h"
55
#include "zigbee/switch_cluster.h"
6+
#include "zigbee/scene_cluster.h"
67
#include "zigbee/general.h"
78
#include "ota.h"
89

@@ -43,6 +44,10 @@ u8 switch_clusters_cnt = 0;
4344
zigbee_relay_cluster relay_clusters[4];
4445
u8 relay_clusters_cnt = 0;
4546

47+
// Each relay cluster should have one scene cluster
48+
zigbee_scene_cluster scene_clusters[4];
49+
#define relay_clusters_cnt switch_clusters_cnt
50+
4651
zigbee_endpoint endpoints[10];
4752

4853

@@ -234,9 +239,14 @@ void parse_config()
234239
}
235240
for (int index = 0; index < relay_clusters_cnt; index++)
236241
{
242+
relay_clusters[index].scene_cluster = scene_clusters + index;
243+
scene_clusters[index].relay_cluster = relay_clusters + index;
244+
237245
relay_cluster_add_to_endpoint(&relay_clusters[index], &endpoints[switch_clusters_cnt + index]);
238246
// Group cluster is stateless, safe to add to multiple endpoints
239247
group_cluster_add_to_endpoint(&group_cluster, &endpoints[switch_clusters_cnt + index]);
248+
249+
scene_cluster_add_to_endpoint(scene_clusters + index, &endpoints[switch_clusters_cnt + index]);
240250
}
241251

242252
for (int index = 0; index < total_endpoints; index++)

src/zigbee/relay_cluster.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "custom_zcl/zcl_onoff_indicator.h"
88
#include "base_components/millis.h"
99

10-
10+
#include "scene_cluster.h"
1111

1212
status_t relay_cluster_callback(zigbee_relay_cluster *cluster, zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload);
1313
status_t relay_cluster_callback_trampoline(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload);
@@ -90,12 +90,13 @@ void relay_cluster_add_to_endpoint(zigbee_relay_cluster *cluster, zigbee_endpoin
9090

9191
// Identify stuff
9292
SETUP_ATTR_FOR_TABLE(cluster->identify_attr_infos, 0, ZCL_ATTRID_IDENTIFY_TIME, ZCL_DATA_TYPE_UINT16, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->identify_time);
93+
SETUP_ATTR_FOR_TABLE(cluster->identify_attr_infos, 1, ZCL_ATTRID_GLOBAL_CLUSTER_REVISION, ZCL_DATA_TYPE_UINT16, ACCESS_CONTROL_READ, zcl_attr_global_clusterRevision);
9394

9495
zigbee_endpoint_add_cluster(endpoint, 1, ZCL_CLUSTER_GEN_IDENTIFY);
9596
info = zigbee_endpoint_reserve_info(endpoint);
9697
info->clusterId = ZCL_CLUSTER_GEN_IDENTIFY;
9798
info->manuCode = MANUFACTURER_CODE_NONE;
98-
info->attrNum = 1;
99+
info->attrNum = 2;
99100
info->attrTbl = cluster->identify_attr_infos;
100101
info->clusterRegisterFunc = zcl_identify_register;
101102
info->clusterAppCb = identify_cluster_callback_trampoline;
@@ -258,11 +259,16 @@ void relay_cluster_restore_relay_state(zigbee_relay_cluster *cluster)
258259
}
259260
}
260261

261-
static void relay_cluster_set_on_off(zigbee_relay_cluster *cluster, enum relay_state state)
262+
void relay_cluster_set_on_off(zigbee_relay_cluster *cluster, enum relay_state state, bool from_scene)
262263
{
263264
bool on = state == RELAY_ON ? true : false;
264265
cluster->on_off = on;
265266

267+
if (cluster->scene_cluster && !from_scene)
268+
{
269+
cluster->scene_cluster->scene_valid = false;
270+
}
271+
266272
if (relay_cluster_control_phys_relay(cluster))
267273
{
268274
if (on)
@@ -287,15 +293,15 @@ void relay_cluster_on(zigbee_relay_cluster *cluster)
287293
cluster->off_wait_time = 0;
288294
}
289295

290-
relay_cluster_set_on_off(cluster, RELAY_ON);
296+
relay_cluster_set_on_off(cluster, RELAY_ON, false);
291297
}
292298

293299
void relay_cluster_off(zigbee_relay_cluster *cluster)
294300
{
295301
cluster->on_wait_time = 0;
296302
cluster->on_off_count_from = millis();
297303

298-
relay_cluster_set_on_off(cluster, RELAY_OFF);
304+
relay_cluster_set_on_off(cluster, RELAY_OFF, false);
299305
}
300306

301307
void relay_cluster_toggle(zigbee_relay_cluster *cluster)
@@ -342,7 +348,7 @@ void relay_cluster_on_with_timed_off(zigbee_relay_cluster *cluster, zcl_onoffCtr
342348

343349
if (!cluster_on)
344350
{
345-
relay_cluster_set_on_off(cluster, RELAY_ON);
351+
relay_cluster_set_on_off(cluster, RELAY_ON, false);
346352
}
347353
}
348354

src/zigbee/relay_cluster.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ enum relay_state {
2020
RELAY_ON = 1,
2121
};
2222

23-
typedef struct
23+
typedef struct zigbee_relay_cluster
2424
{
2525
u8 relay_idx;
2626
u8 endpoint;
@@ -42,10 +42,12 @@ typedef struct
4242
u16 toggles_left;
4343

4444
u16 identify_time;
45-
zclAttrInfo_t identify_attr_infos[1];
45+
zclAttrInfo_t identify_attr_infos[2];
4646

4747
bool on_off;
4848
bool indicator_led_on;
49+
50+
struct zigbee_scene_cluster *scene_cluster;
4951
} zigbee_relay_cluster;
5052

5153
void relay_cluster_add_to_endpoint(zigbee_relay_cluster *cluster, zigbee_endpoint *endpoint);
@@ -65,4 +67,7 @@ void gen_identify_callback_attr_write_trampoline(u8 clusterId, zclWriteCmd_t *pW
6567
bool relay_cluster_is_on(zigbee_relay_cluster *cluster);
6668
bool relay_cluster_is_identifying(zigbee_relay_cluster *cluster);
6769

70+
bool relay_cluster_get_on_off(zigbee_relay_cluster *cluster);
71+
void relay_cluster_set_on_off(zigbee_relay_cluster *cluster, bool new_state, bool from_scene);
72+
6873
#endif

src/zigbee/scene_cluster.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include "scene_cluster.h"
2+
#include "relay_cluster.h"
3+
#include "cluster_common.h"
4+
5+
zigbee_scene_cluster *scene_cluster_by_endpoint[10] = {};
6+
7+
static void store_scene(zcl_sceneEntry_t *scene_entry, zigbee_scene_cluster *cluster);
8+
static void recall_scene(zcl_sceneEntry_t *scene_entry, zigbee_scene_cluster *cluster);
9+
10+
static const u8 scene_name_support = 0x01;
11+
12+
void scene_cluster_add_to_endpoint(zigbee_scene_cluster *cluster, zigbee_endpoint *endpoint)
13+
{
14+
SETUP_ATTR(0, ZCL_ATTRID_SCENE_SCENE_COUNT, ZCL_DATA_TYPE_UINT8, ACCESS_CONTROL_READ, cluster->scene_count);
15+
SETUP_ATTR(1, ZCL_ATTRID_SCENE_CURRENT_SCENE, ZCL_DATA_TYPE_UINT8, ACCESS_CONTROL_READ, cluster->current_scene);
16+
SETUP_ATTR(2, ZCL_ATTRID_SCENE_CURRENT_GROUP, ZCL_DATA_TYPE_UINT16, ACCESS_CONTROL_READ, cluster->current_group);
17+
SETUP_ATTR(3, ZCL_ATTRID_SCENE_SCENE_VALID, ZCL_DATA_TYPE_BOOLEAN, ACCESS_CONTROL_READ, cluster->scene_valid);
18+
SETUP_ATTR(4, ZCL_ATTRID_SCENE_NAME_SUPPORT, ZCL_DATA_TYPE_BITMAP8, ACCESS_CONTROL_READ, scene_name_support);
19+
SETUP_ATTR(5, ZCL_ATTRID_SCENE_LAST_CONFIG_BY, ZCL_DATA_TYPE_IEEE_ADDR, ACCESS_CONTROL_READ, cluster->last_configured_by);
20+
SETUP_ATTR(6, ZCL_ATTRID_GLOBAL_CLUSTER_REVISION, ZCL_DATA_TYPE_UINT16, ACCESS_CONTROL_READ, zcl_attr_global_clusterRevision);
21+
22+
zigbee_endpoint_add_cluster(endpoint, 1, ZCL_CLUSTER_GEN_SCENES);
23+
zcl_specClusterInfo_t *info = zigbee_endpoint_reserve_info(endpoint);
24+
info->clusterId = ZCL_CLUSTER_GEN_SCENES;
25+
info->manuCode = MANUFACTURER_CODE_NONE;
26+
info->attrNum = SCENE_CLUSTER_ATTR_NUM;
27+
info->attrTbl = cluster->attr_infos;
28+
info->clusterRegisterFunc = zcl_scene_register;
29+
info->clusterAppCb = scene_cluster_callback;
30+
}
31+
32+
status_t scene_cluster_callback(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload)
33+
{
34+
zigbee_scene_cluster *cluster = scene_cluster_by_endpoint[pAddrInfo->dstEp];
35+
36+
status_t status = ZCL_STA_SUCCESS;
37+
38+
if (pAddrInfo->dirCluster == ZCL_FRAME_CLIENT_SERVER_DIR)
39+
{
40+
switch (cmdId)
41+
{
42+
case ZCL_CMD_SCENE_STORE_SCENE:
43+
store_scene(cmdPayload, cluster);
44+
break;
45+
case ZCL_CMD_SCENE_RECALL_SCENE:
46+
recall_scene(cmdPayload, cluster);
47+
break;
48+
default:
49+
break;
50+
}
51+
}
52+
else
53+
{
54+
status = ZCL_STA_UNSUP_CLUSTER_COMMAND;
55+
}
56+
57+
return status;
58+
}
59+
60+
static void recall_scene(zcl_sceneEntry_t *scene_entry, zigbee_scene_cluster *cluster)
61+
{
62+
u8 *pData = scene_entry->extField;
63+
u16 clusterID = 0xFFFF;
64+
u8 extLen = 0;
65+
66+
while (pData < scene_entry->extField + scene_entry->extFieldLen) {
67+
clusterID = BUILD_U16(pData[0], pData[1]);
68+
pData += 2;//cluster id
69+
70+
extLen = *pData++;//length
71+
72+
if (clusterID == ZCL_CLUSTER_GEN_ON_OFF && cluster->relay_cluster) {
73+
if (extLen >= 1) {
74+
u8 onOff = *pData++;
75+
76+
relay_cluster_set_on_off(cluster->relay_cluster, onOff, true);
77+
extLen--;
78+
}
79+
}
80+
81+
pData += extLen;
82+
}
83+
}
84+
85+
static void store_scene(zcl_sceneEntry_t *scene_entry, zigbee_scene_cluster *cluster)
86+
{
87+
u8 extLen = 0;
88+
89+
if (cluster->relay_cluster) {
90+
bool on_off = cluster->relay_cluster->on_off;
91+
92+
scene_entry->extField[extLen++] = LO_UINT16(ZCL_CLUSTER_GEN_ON_OFF);
93+
scene_entry->extField[extLen++] = HI_UINT16(ZCL_CLUSTER_GEN_ON_OFF);
94+
scene_entry->extField[extLen++] = sizeof(u8);
95+
scene_entry->extField[extLen++] = on_off;
96+
}
97+
98+
// Add other clusters to save here...
99+
100+
scene_entry->extFieldLen = extLen;
101+
}

src/zigbee/scene_cluster.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef _SCENE_CLUSTER_H_
2+
#define _SCENE_CLUSTER_H_
3+
4+
#include "tl_common.h"
5+
#include "zb_common.h"
6+
#include "zcl_include.h"
7+
#include "endpoint.h"
8+
9+
#define SCENE_CLUSTER_ATTR_NUM 7
10+
11+
typedef struct zigbee_scene_cluster
12+
{
13+
u8 scene_count;
14+
u8 current_scene;
15+
u16 current_group;
16+
bool scene_valid;
17+
addrExt_t last_configured_by;
18+
19+
struct zigbee_relay_cluster *relay_cluster;
20+
21+
zclAttrInfo_t attr_infos[SCENE_CLUSTER_ATTR_NUM];
22+
} zigbee_scene_cluster;
23+
24+
void scene_cluster_add_to_endpoint(zigbee_scene_cluster *cluster, zigbee_endpoint *endpoint);
25+
26+
status_t scene_cluster_callback(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload);
27+
28+
#endif

0 commit comments

Comments
 (0)