4.1 ZCL 简介
前述章节讲解了如何使用AF层通信API,但是现在用得更多的是基于ZCL的数据通信方式。ZCL的全称是ZigBee Cluster Library,中文意思是ZigBee集群库。ZCL与AF的关系如图所示:
图中共有3个层次,分别是AF、ZCL和应用层,分别详细讲解一下。
一. AF层
在前述章节已经详细讲解了AF层,可以调用AF层的数据通信API实现ZigBee设备之间的数据发送与接收。然而,直接使用AF层通信API的最大问题是不同公司开发的设备难以做到互联互通。
二. 应用层
开发者此层次中专注于开发设备的各个功能。在讲解AF通信的章节中,我们就是在应用层中直接调用AF层的通信API来发送和接收数据的。
三. ZCL层简介
ZigBee联盟在AF层与应用层之间构建了ZCL层,其最大的作用就是实现了各个ZigBee设备的互联互通。ZCL定义了ZigBee设备的各种应用领域(Profile)、设备类型(Device)、集群(Cluster)、设备属性和命令,这些定义均由ZigBee联盟统一定制。各个厂商在开发ZigBee设备时都遵循这些定义,便实现了互联互通了。
四. ZCL层的架构
(1)ZCL的大部分内容在Z-Stack 3.0 中的以下目录中:
...\\Z-Stack 3.0.1\\Components\\stack\\zcl
(2)它的部分内容如图所示。
(3)一个设备一般只会使用ZCL中的部分内容,例如本书一直讲解的这个SampleSwitch工程使用了这些内容,如图所示。
五. 代码分析
(1)我们对ZCL中的代码简单分析一下,打开zcl.h文件,可以找到ZCL层数据发送函数zcl_SendCommand(),代码如下:
/*********************************************************************
* @fn zcl_SendCommand
*
* @brief Used to send Profile and Cluster Specific Command messages.
*
* NOTE: The calling application is responsible for incrementing
* the Sequence Number.
*
* @param srcEp - source endpoint
* @param destAddr - destination address
* @param clusterID - cluster ID
* @param cmd - command ID
* @param specific - whether the command is Cluster Specific
* @param direction - client/server direction of the command
* @param disableDefaultRsp - disable Default Response command
* @param manuCode - manufacturer code for proprietary extensions to a profile
* @param seqNumber - identification number for the transaction
* @param cmdFormatLen - length of the command to be sent
* @param cmdFormat - command to be sent
*
* @return ZSuccess if OK
*/
ZStatus_t zcl_SendCommand( uint8 srcEP, afAddrType_t *destAddr,
uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction,
uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
uint16 cmdFormatLen, uint8 *cmdFormat )
{
endPointDesc_t *epDesc;
zclFrameHdr_t hdr;
uint8 *msgBuf;
uint16 msgLen;
uint8 *pBuf;
uint8 options;
ZStatus_t status;
epDesc = afFindEndPointDesc( srcEP );
if ( epDesc == NULL )
{
return ( ZInvalidParameter ); // EMBEDDED RETURN
}
#if defined ( INTER_PAN )
if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) )
{
options = AF_TX_OPTIONS_NONE;
}
else
#endif
{
options = zclGetClusterOption( srcEP, clusterID );
// The cluster might not have been defined to use security but if this message
// is in response to another message that was using APS security this message
// will be sent with APS security
if ( !( options & AF_EN_SECURITY ) )
{
afIncomingMSGPacket_t *origPkt = zcl_getRawAFMsg();
if ( ( origPkt != NULL ) && ( origPkt->SecurityUse == TRUE ) )
{
options |= AF_EN_SECURITY;
}
}
}
zcl_memset( &hdr, 0, sizeof( zclFrameHdr_t ) );
// Not Profile wide command (like READ, WRITE)
if ( specific )
{
hdr.fc.type = ZCL_FRAME_TYPE_SPECIFIC_CMD;
}
else
{
hdr.fc.type = ZCL_FRAME_TYPE_PROFILE_CMD;
}
if ( ( epDesc->simpleDesc == NULL ) ||
( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type,
cmd, epDesc->simpleDesc->AppProfId ) == FALSE ) )
{
return ( ZFailure ); // EMBEDDED RETURN
}
// Fill in the Maufacturer Code
if ( manuCode != 0 )
{
hdr.fc.manuSpecific = 1;
hdr.manuCode = manuCode;
}
// Set the Command Direction
if ( direction )
{
hdr.fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR;
}
else
{
hdr.fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR;
}
// Set the Disable Default Response field
if ( disableDefaultRsp )
{
hdr.fc.disableDefaultRsp = 1;
}
else
{
hdr.fc.disableDefaultRsp = 0;
}
// Fill in the Transaction Sequence Number
hdr.transSeqNum = seqNum;
// Fill in the command
hdr.commandID = cmd;
// calculate the needed buffer size
msgLen = zclCalcHdrSize( &hdr );
msgLen += cmdFormatLen;
// Allocate the buffer needed
msgBuf = zcl_mem_alloc( msgLen );
if ( msgBuf != NULL )
{
// Fill in the ZCL Header
pBuf = zclBuildHdr( &hdr, msgBuf );
// Fill in the command frame
zcl_memcpy( pBuf, cmdFormat, cmdFormatLen );
status = AF_DataRequest( destAddr, epDesc, clusterID, msgLen, msgBuf,
&zcl_TransID, options, AF_DEFAULT_RADIUS );
zcl_mem_free ( msgBuf );
}
else
{
status = ZMemError;
}
return ( status );
}
可以看到zcl_SendCommand()函数中,其实是调用AF层的数据发送函数AF_DataRequest()来发送数据的。
(2)在zcl.c文件中还有一个名为zcl_event_loop()的函数。在这个函数中,我们可以看到AF层数据的接收和处理,代码如图所示。
以上的分析也印正了ZCL层的底层就是AF层。
4.2 ZCL 内容详解
ZCL主要包含有应用领域(Profile)、设备类型(Device)、集群(Cluster)、属性(Attribute)和命令(Command)这几部分内容。
一. 应用领域(Profile)
(1)前面的章节已经多次提过Profile了,在这里做一个正式的介绍。在ZigBee协议中,Profile是指应用领域。ZigBee协议中定义了多个Profile,例如面向家居自动的ZHA(ZigBee Home Automation)、面向照明的ZLL(ZigBee Light Link)等。本文一直在使用智能插座就是属于ZHA这个Profile的产品。
(2)ZigBee协议给每种类型的Profile分配了一个固定的ID,打开Profile/zcl_ha.h文件,可以找到ZHA Profile的ID值,代码如下:
// Zigbee Home Automation Profile Identification
#define ZCL_HA_PROFILE_ID 0x0104
(3)打开协议栈中的Components\stack\zcl\zcl_ll.h文件,可以找到ZLL Profile的ID值,代码如下:
// Zigbee Light Link Profile Identification
#define ZLL_PROFILE_ID 0xc05e
(4)使用这个方式,还可以查看其它Profile的ID。在讲解简单描述符的章节中,曾经讲到AppProfId字段表示这个简单描述符所属的应用场景,它的取值其实就是这些Profile ID。
二. 设备类型(Device)
(1)每种Profile可以包含多种类型的设备,例如ZHA Profile中包含智能插座、温湿度传感器、窗帘控制器等类型的设备。每种类型的设备都被分配了一个ID,称为Device ID,并且在同一个Profile,每个Device ID都是不同的。
(2)在 ZigBee 3.0 中,ZHA Profile中的各个设备类型被划分为5大类,分别是Generic、Lighting、Closures、HVAC(Heating Ventilation and Air Conditioning,供暖通风与空气调节)和IAS(Intruder Alarm Systems,入侵报警系统)。
(3)ZHA相关的源文件是Profile工程目录下的zcl_ha.h和zcl_ha.c。打开zcl_ha.h文件,可以找到以上所有设备类型的Device ID,代码如下:
(3A)Generic
// Generic Device IDs
#define ZCL_HA_DEVICEID_ON_OFF_SWITCH 0x0000
#define ZCL_HA_DEVICEID_LEVEL_CONTROL_SWITCH 0x0001
#define ZCL_HA_DEVICEID_ON_OFF_OUTPUT 0x0002
#define ZCL_HA_DEVICEID_LEVEL_CONTROLLABLE_OUTPUT 0x0003
#define ZCL_HA_DEVICEID_SCENE_SELECTOR 0x0004
#define ZCL_HA_DEVICEID_CONFIGURATION_TOOL 0x0005
#define ZCL_HA_DEVICEID_REMOTE_CONTROL 0x0006
#define ZCL_HA_DEVICEID_COMBINED_INTERFACE 0x0007
#define ZCL_HA_DEVICEID_RANGE_EXTENDER 0x0008
#define ZCL_HA_DEVICEID_MAINS_POWER_OUTLET 0x0009
#define ZCL_HA_DEVICEID_DOOR_LOCK 0x000A
#define ZCL_HA_DEVICEID_DOOR_LOCK_CONTROLLER 0x000B
#define ZCL_HA_DEVICEID_SIMPLE_SENSOR 0x000C
#define ZCL_HA_DEVICEID_CONSUMPTION_AWARENESS_DEVICE 0x000D
#define ZCL_HA_DEVICEID_HOME_GATEWAY 0x0050
#define ZCL_HA_DEVICEID_SMART_PLUG 0x0051
#define ZCL_HA_DEVICEID_WHITE_GOODS 0x0052
#define ZCL_HA_DEVICEID_METER_INTERFACE 0x0053
(3B)Lighting
// Lighting Device IDs
#define ZCL_HA_DEVICEID_ON_OFF_LIGHT 0x0100
#define ZCL_HA_DEVICEID_DIMMABLE_LIGHT 0x0101
#define ZCL_HA_DEVICEID_COLORED_DIMMABLE_LIGHT 0x0102
#define ZCL_HA_DEVICEID_ON_OFF_LIGHT_SWITCH 0x0103
#define ZCL_HA_DEVICEID_DIMMER_SWITCH 0x0104
#define ZCL_HA_DEVICEID_COLOR_DIMMER_SWITCH 0x0105
#define ZCL_HA_DEVICEID_LIGHT_SENSOR 0x0106
#define ZCL_HA_DEVICEID_OCCUPANCY_SENSOR 0x0107
(3C)Closures
// Closures Device IDs
#define ZCL_HA_DEVICEID_SHADE 0x0200
#define ZCL_HA_DEVICEID_SHADE_CONTROLLER 0x0201
#define ZCL_HA_DEVICEID_WINDOW_COVERING_DEVICE 0x0202
#define ZCL_HA_DEVICEID_WINDOW_COVERING_CONTROLLER 0x0203
(3D)HVAC
// HVAC Device IDs
#define ZCL_HA_DEVICEID_HEATING_COOLING_UNIT 0x0300
#define ZCL_HA_DEVICEID_THERMOSTAT 0x0301
#define ZCL_HA_DEVICEID_TEMPERATURE_SENSOR 0x0302
#define ZCL_HA_DEVICEID_PUMP 0x0303
#define ZCL_HA_DEVICEID_PUMP_CONTROLLER 0x0304
#define ZCL_HA_DEVICEID_PRESSURE_SENSOR 0x0305
#define ZCL_HA_DEVICEID_FLOW_SENSOR 0x0306
#define ZCL_HA_DEVICEID_MINI_SPLIT_AC 0x0307
(3E)IAS
// Intruder Alarm Systems (IAS) Device IDs
#define ZCL_HA_DEVICEID_IAS_CONTROL_INDICATING_EQUIPMENT 0x0400
#define ZCL_HA_DEVICEID_IAS_ANCILLARY_CONTROL_EQUIPMENT 0x0401
#define ZCL_HA_DEVICEID_IAS_ZONE 0x0402
#define ZCL_HA_DEVICEID_IAS_WARNING_DEVICE 0x0403
(4)ZLL相关的源文件在工程目录Profile下的zcl_ll.h和zcl_ll.c,打开zcl_ll.h文件,可以找到ZLL Profile(领域)定义的Device ID,代码如下:
// ZLL Basic Lighting Device IDs
#define ZLL_DEVICEID_ON_OFF_LIGHT 0x0000
#define ZLL_DEVICEID_ON_OFF_PLUG_IN_UNIT 0x0010
#define ZLL_DEVICEID_DIMMABLE_LIGHT 0x0100
#define ZLL_DEVICEID_DIMMABLE_PLUG_IN_UNIT 0x0110
// ZLL Color Lighting Device IDs
#define ZLL_DEVICEID_COLOR_LIGHT 0x0200
#define ZLL_DEVICEID_EXTENDED_COLOR_LIGHT 0x0210
#define ZLL_DEVICEID_COLOR_TEMPERATURE_LIGHT 0x0220
// ZLL Lighting Remotes Device IDs
#define ZLL_DEVICEID_COLOR_CONTORLLER 0x0800
#define ZLL_DEVICEID_COLOR_SCENE_CONTROLLER 0x0810
#define ZLL_DEVICEID_NON_COLOR_CONTORLLER 0x0820
#define ZLL_DEVICEID_NON_COLOR_SCENE_CONTROLLER 0x0830
#define ZLL_DEVICEID_CONTROL_BRIDGE 0x0840
#define ZLL_DEVICEID_ON_OFF_SENSOR 0x0850
(5)使用这个方式,还可以查看其它Profile中可以被使用的Device ID,在讲解简单描述符的章节中,曾经讲到AppDeviceId字段表示这个设备的类型,它的取值其实就是这些Device ID值。
三. 集群(Cluster)
(1)Cluster的作用是什么呢?读者可以保持着这个疑问继续往下阅读。
(2)在讲解AF通信的章节中,笔者自定义了3个Cluster ID,每个Cluster ID都代表着一个Cluster,用于表示不同的通信类型。这3个Cluster是笔者自定义的,并不是由ZigBee联盟定义的,因此只有自己写的代码能够理解它们的意义,其它开发者并不知道,所以这3个Cluster可以理解为是私有的。
(3)然而,ZigBee联盟已经定义了许多标准的Cluster,可供所有开发者使用,这些Cluster可以理解为是公有的。每一个Cluster分配有一个唯一的ID,称为 Cluster ID。这些Cluster可以分成两类:属于特定Profile的Cluster,以及各个Profile共用的、不属于某个Profile的一般性Cluster(General Clusters)。
(4)Cluster ID的定义在文件zcl.h中,本文列举部分Cluster,代码如下:
(4A)General Clusters
// General Clusters
#define ZCL_CLUSTER_ID_GEN_BASIC 0x0000
#define ZCL_CLUSTER_ID_GEN_POWER_CFG 0x0001
#define ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG 0x0002
#define ZCL_CLUSTER_ID_GEN_IDENTIFY 0x0003
#define ZCL_CLUSTER_ID_GEN_GROUPS 0x0004
#define ZCL_CLUSTER_ID_GEN_SCENES 0x0005
#define ZCL_CLUSTER_ID_GEN_ON_OFF 0x0006
#define ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG 0x0007
#define ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL 0x0008
#define ZCL_CLUSTER_ID_GEN_ALARMS 0x0009
#define ZCL_CLUSTER_ID_GEN_TIME 0x000A
#define ZCL_CLUSTER_ID_GEN_LOCATION 0x000B
#define ZCL_CLUSTER_ID_GEN_ANALOG_INPUT_BASIC 0x000C
#define ZCL_CLUSTER_ID_GEN_ANALOG_OUTPUT_BASIC 0x000D
#define ZCL_CLUSTER_ID_GEN_ANALOG_VALUE_BASIC 0x000E
#define ZCL_CLUSTER_ID_GEN_BINARY_INPUT_BASIC 0x000F
#define ZCL_CLUSTER_ID_GEN_BINARY_OUTPUT_BASIC 0x0010
#define ZCL_CLUSTER_ID_GEN_BINARY_VALUE_BASIC 0x0011
#define ZCL_CLUSTER_ID_GEN_MULTISTATE_INPUT_BASIC 0x0012
#define ZCL_CLUSTER_ID_GEN_MULTISTATE_OUTPUT_BASIC 0x0013
#define ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC 0x0014
#define ZCL_CLUSTER_ID_GEN_COMMISSIONING 0x0015
#define ZCL_CLUSTER_ID_GEN_PARTITION 0x0016
#define ZCL_CLUSTER_ID_GEN_POWER_PROFILE 0x001A
#define ZCL_CLUSTER_ID_GEN_APPLIANCE_CONTROL 0x001B
#define ZCL_CLUSTER_ID_GEN_POLL_CONTROL 0x0020
(4B)Retail Clusters
// Retail Clusters
#define ZCL_CLUSTER_ID_MOBILE_DEVICE_CONFIGURATION 0x0022
#define ZCL_CLUSTER_ID_NEIGHBOR_CLEANING 0x0023
#define ZCL_CLUSTER_ID_NEAREST_GATEWAY 0x0024
(4C)Closures Clusters
// Closures Clusters
#define ZCL_CLUSTER_ID_CLOSURES_SHADE_CONFIG 0x0100
#define ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK 0x0101
#define ZCL_CLUSTER_ID_CLOSURES_WINDOW_COVERING 0x0102
(4D)HVAC Clusters
// HVAC Clusters
#define ZCL_CLUSTER_ID_HVAC_PUMP_CONFIG_CONTROL 0x0200
#define ZCL_CLUSTER_ID_HVAC_THERMOSTAT 0x0201
#define ZCL_CLUSTER_ID_HVAC_FAN_CONTROL 0x0202
#define ZCL_CLUSTER_ID_HVAC_DIHUMIDIFICATION_CONTROL 0x0203
#define ZCL_CLUSTER_ID_HVAC_USER_INTERFACE_CONFIG 0x0204
(4E)Lighting Clusters
// Lighting Clusters
#define ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL 0x0300
#define ZCL_CLUSTER_ID_LIGHTING_BALLAST_CONFIG 0x0301
(4F)Measurement and Sensing Clusters
// Measurement and Sensing Clusters
#define ZCL_CLUSTER_ID_MS_ILLUMINANCE_MEASUREMENT 0x0400
#define ZCL_CLUSTER_ID_MS_ILLUMINANCE_LEVEL_SENSING_CONFIG 0x0401
#define ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT 0x0402
#define ZCL_CLUSTER_ID_MS_PRESSURE_MEASUREMENT 0x0403
#define ZCL_CLUSTER_ID_MS_FLOW_MEASUREMENT 0x0404
#define ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY 0x0405
#define ZCL_CLUSTER_ID_MS_OCCUPANCY_SENSING 0x0406
(4G)Security and Safety (SS) Clusters
// Security and Safety (SS) Clusters
#define ZCL_CLUSTER_ID_SS_IAS_ZONE 0x0500
#define ZCL_CLUSTER_ID_SS_IAS_ACE 0x0501
#define ZCL_CLUSTER_ID_SS_IAS_WD 0x0502
(4H)Protocol Interfaces
// Protocol Interfaces
#define ZCL_CLUSTER_ID_PI_GENERIC_TUNNEL 0x0600
#define ZCL_CLUSTER_ID_PI_BACNET_PROTOCOL_TUNNEL 0x0601
#define ZCL_CLUSTER_ID_PI_ANALOG_INPUT_BACNET_REG 0x0602
#define ZCL_CLUSTER_ID_PI_ANALOG_INPUT_BACNET_EXT 0x0603
#define ZCL_CLUSTER_ID_PI_ANALOG_OUTPUT_BACNET_REG 0x0604
#define ZCL_CLUSTER_ID_PI_ANALOG_OUTPUT_BACNET_EXT 0x0605
#define ZCL_CLUSTER_ID_PI_ANALOG_VALUE_BACNET_REG 0x0606
#define ZCL_CLUSTER_ID_PI_ANALOG_VALUE_BACNET_EXT 0x0607
#define ZCL_CLUSTER_ID_PI_BINARY_INPUT_BACNET_REG 0x0608
#define ZCL_CLUSTER_ID_PI_BINARY_INPUT_BACNET_EXT 0x0609
#define ZCL_CLUSTER_ID_PI_BINARY_OUTPUT_BACNET_REG 0x060A
#define ZCL_CLUSTER_ID_PI_BINARY_OUTPUT_BACNET_EXT 0x060B
#define ZCL_CLUSTER_ID_PI_BINARY_VALUE_BACNET_REG 0x060C
#define ZCL_CLUSTER_ID_PI_BINARY_VALUE_BACNET_EXT 0x060D
#define ZCL_CLUSTER_ID_PI_MULTISTATE_INPUT_BACNET_REG 0x060E
#define ZCL_CLUSTER_ID_PI_MULTISTATE_INPUT_BACNET_EXT 0x060F
#define ZCL_CLUSTER_ID_PI_MULTISTATE_OUTPUT_BACNET_REG 0x0610
#define ZCL_CLUSTER_ID_PI_MULTISTATE_OUTPUT_BACNET_EXT 0x0611
#define ZCL_CLUSTER_ID_PI_MULTISTATE_VALUE_BACNET_REG 0x0612
#define ZCL_CLUSTER_ID_PI_MULTISTATE_VALUE_BACNET_EXT 0x0613
#define ZCL_CLUSTER_ID_PI_11073_PROTOCOL_TUNNEL 0x0614
#define ZCL_CLUSTER_ID_PI_ISO7818_PROTOCOL_TUNNEL 0x0615
#define ZCL_CLUSTER_ID_PI_RETAIL_TUNNEL 0x0617
(4I)Smart Energy (SE) Clusters
// Smart Energy (SE) Clusters
#define ZCL_CLUSTER_ID_SE_PRICE 0x0700
#define ZCL_CLUSTER_ID_SE_DRLC 0x0701
#define ZCL_CLUSTER_ID_SE_METERING 0x0702
#define ZCL_CLUSTER_ID_SE_MESSAGING 0x0703
#define ZCL_CLUSTER_ID_SE_TUNNELING 0x0704
#define ZCL_CLUSTER_ID_SE_PREPAYMENT 0x0705
#define ZCL_CLUSTER_ID_SE_ENERGY_MGMT 0x0706
#define ZCL_CLUSTER_ID_SE_CALENDAR 0x0707
#define ZCL_CLUSTER_ID_SE_DEVICE_MGMT 0x0708
#define ZCL_CLUSTER_ID_SE_EVENTS 0x0709
#define ZCL_CLUSTER_ID_SE_MDU_PAIRING 0x070A
#define ZCL_CLUSTER_ID_SE_KEY_ESTABLISHMENT 0x0800
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_INFORMATION 0x0900
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_CHATTING 0x0904
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE 0x0905
#define ZCL_CLUSTER_ID_HA_APPLIANCE_IDENTIFICATION 0x0B00
#define ZCL_CLUSTER_ID_HA_METER_IDENTIFICATION 0x0B01
#define ZCL_CLUSTER_ID_HA_APPLIANCE_EVENTS_ALERTS 0x0B02
#define ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS 0x0B03
#define ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT 0x0B04
#define ZCL_CLUSTER_ID_HA_DIAGNOSTIC 0x0B05
(4J)Light Link cluster
// Light Link cluster
#define ZCL_CLUSTER_ID_TOUCHLINK 0x1000
(5)每个Cluster中可以包含多个特定的属性(Attribute)和命令(Command)。
四. 属性(Attribute)
(1)与面向对象编程思想中属性类似,这里的属性是用来描述描述某一类事物的特点的,例如老虎的属性有性别、年龄和体重等属性。ZigBee联盟除了预定义了多个Cluster,还为每个Cluster预定义了一组对应的属性供开发者使用。Cluster应该包含哪几个属性,可由开发者自行定义。
(2)打开zcl_samplesw_data.c文件,可以找到如图所示代码。
上述代码中创建了一个属性数组,这是一个结构体数组。分析一下其中的第1个元素:
{
ZCL_CLUSTER_ID_GEN_BASIC,//Basic Cluster,由ZigBee联盟预定义
{ //Attribute record
ATTRID_BASIC_ZCL_VERSION,//ZCL版本号属性,由ZigBee联盟自定义
ZCL_DATATYPE_UINT8,//说明这个属性的数据类型是8个比特位的变量(无符号整型变量)
ACCESS_CONTROL_READ,//说明这个属性只能被读取不能被修改
(void*)&zclSampleSw_ZCLVersion//函数引用,暂不做讲解
}
}
(3)上述代码的设计有点特别,其主要工作内容是往ZCL_CLUSTER_ID_GEN_BASIC这个Cluster中添加ATTRID_BASIC_ZCL_VERSION这个属性,并且说明这个属性的数据类型和只能被读取。
(4)再观察一下下面的两个元素,会发现其实是把另外两个属性也添加进ZCL_CLUSTER_ID_GEN_BASIC这个Cluster中。如此一来,这个Cluster便包含了3个属性,以及这3个属性对应的操作命令。
五 命令(Command)
(1)开发者可以让源设备向目标设备的某个Cluster发送命令。当目标设备接收到这条命令时,需要执行与该Cluster相关的处理,例如修改该Cluster的中的属性等。
(2)每个Cluster都包含有一组特定的命令,即每个Cluster只能接收一组特定的命令。命令可以分为两种,分别是基础命令和属性关联命令。
- (2A)基础命令
每个Cluster均包含基础命令,即基础命令能被所有Cluster接收,例如读命令、写命令和上报命令等,这部分命令的定义在zcl.h文件中,如图所示。 - (2B)Cluster限定命令
Cluster限定命令只存在于某些特定的Cluster中,即Cluster限定命令只能被某些特定的Cluster接收。打开zcl_general.h,可以找到如图所示代码:
(3)其中的COMMAND_OFF和COMMAND_ON就是专门作用于ON_OFF Cluster的命令。
六. Cluster应用举例
(1)现在终于可以举个例子说明Cluster的用途了。现在需要设计一盏支持亮度调整的ZigBee灯,可以用两个Cluster来描述其服务,分别是开关Cluster和亮度Cluster。
- 开关Cluster用于表示和控制这个灯的开关状态,因此开关Cluster应该包含一个开关属性,并且能够被开命令和关命令来控制。
- 亮度Cluster用于表示和控制这个灯的亮度,因此亮度Cluster应该包含一个亮度属性,并且能够被调整亮度命令来控制。
(2)从这个例子可以看出Cluster的作用是非常强大的,可用于在逻辑上实现设备的各个服务,而且其用途远不止于此,后续章节将讲解Cluster的更多用途。