3 #include "chip-zcl-zpro-codec.h"
5 #include <support/BufferWriter.h>
6 #include <support/SafeInt.h>
7 #include <support/logging/CHIPLogging.h>
9 #include <app/util/basic-types.h>
10 #include <lib/support/Span.h>
13 using namespace chip::System;
14 using namespace chip::Encoding::LittleEndian;
16 static uint16_t doEncodeApsFrame(BufferWriter & buf, ClusterId clusterId, EndpointId sourceEndpoint,
17 EndpointId destinationEndpoint, EmberApsOption options, GroupId groupId, uint8_t sequence,
18 uint8_t radius, bool isMeasuring)
21 uint8_t control_byte = 0;
22 buf.Put(control_byte) // Put in a control byte
25 .Put8(destinationEndpoint)
26 .EndianPut(options, sizeof(EmberApsOption))
31 size_t result = buf.Needed();
34 ChipLogDetail(Zcl, "Measured APS frame size %d", result);
38 ChipLogDetail(Zcl, "Successfully encoded %d bytes", result);
42 ChipLogError(Zcl, "Error encoding APS Frame: Buffer too small");
46 if (!CanCastTo<uint16_t>(result))
48 ChipLogError(Zcl, "Can't fit our measured size in uint16_t");
52 return static_cast<uint16_t>(result);
55 uint16_t encodeApsFrame(uint8_t * buffer, uint16_t buf_length, EmberApsFrame * apsFrame)
57 BufferWriter buf(buffer, buf_length);
58 return doEncodeApsFrame(buf, apsFrame->clusterId, apsFrame->sourceEndpoint, apsFrame->destinationEndpoint,
59 apsFrame->options, apsFrame->groupId, apsFrame->sequence, apsFrame->radius, !buffer);
62 #define COMMAND_HEADER(name, clusterId) \
63 const char * kName = name; \
65 PacketBufferWriter buf(System::PacketBufferHandle::New(kMaxBufferSize)); \
68 ChipLogError(Zcl, "Could not allocate packet buffer while trying to encode %s command", kName); \
69 return PacketBufferHandle(); \
72 if (doEncodeApsFrame(buf, clusterId, kSourceEndpoint, destinationEndpoint, 0, 0, 0, 0, false)) \
75 #define COMMAND_FOOTER() \
79 ChipLogError(Zcl, "Command %s can't fit in the allocated buffer", kName); \
81 return buf.Finalize();
86 #define EMBER_ZCL_REPORTING_DIRECTION_REPORTED 0x00
88 {{#zcl_global_commands}}
89 #define ZCL_{{asDelimitedMacro label}}_COMMAND_ID ({{asHex code 2}})
90 {{/zcl_global_commands}}
92 {{#chip_server_clusters}}
93 #define {{define}}_ID {{asHex code 4}}
94 {{#chip_server_cluster_commands}}
95 #define ZCL_{{asDelimitedMacro name}}_COMMAND_ID ({{asHex code 2}})
96 {{/chip_server_cluster_commands}}
98 {{/chip_server_clusters}}
100 // TODO: Find a way to calculate maximum message length for clusters
101 // https://github.com/project-chip/connectedhomeip/issues/965
102 constexpr uint16_t kMaxBufferSize = 1024;
104 // This is a cluster-specific command so low two bits are 0b01. The command
105 // is standard, so does not need a manufacturer code, and we're sending
106 // client to server, so all the remaining bits are 0.
107 constexpr uint8_t kFrameControlClusterSpecificCommand = 0x01;
109 // This is a global command, so the low bits are 0b00. The command is
110 // standard, so does not need a manufacturer code, and we're sending client
111 // to server, so all the remaining bits are 0.
112 constexpr uint8_t kFrameControlGlobalCommand = 0x00;
114 // Pick source endpoint as 1 for now
115 constexpr EndpointId kSourceEndpoint = 1;
117 {{#chip_server_clusters}}
120 {{#chip_server_cluster_commands}}
122 * Command {{asCamelCased name false}}
124 PacketBufferHandle encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(uint8_t seqNum, EndpointId destinationEndpoint{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}})
126 COMMAND_HEADER("{{asType name}}", {{parent.define}}_ID);
127 {{#chip_server_cluster_command_arguments}}
128 {{#if (isByteString type)}}
129 if (!CanCastTo<uint8_t>({{asCamelCased label}}.size()))
131 ChipLogError(Zcl, "Error encoding %s command. String too long: %zu", kName, {{asCamelCased label}}.size());
132 return PacketBufferHandle();
134 {{else if (isString type)}}
135 size_t {{asCamelCased label}}StrLen = strlen({{asCamelCased label}});
136 if (!CanCastTo<uint8_t>({{asCamelCased label}}StrLen))
138 ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, {{asCamelCased label}}StrLen);
139 return PacketBufferHandle();
142 {{/chip_server_cluster_command_arguments}}
144 {{#if (isManufacturerSpecificCommand)}}
145 .Put8(kFrameControlClusterSpecificCommand | (1u << 2))
146 .Put16({{asHex mfgCode 4}})
148 .Put8(kFrameControlClusterSpecificCommand)
151 .Put8(ZCL_{{asDelimitedMacro name}}_COMMAND_ID)
152 {{#chip_server_cluster_command_arguments}}
153 {{#if (isByteString type)}}
154 .Put(static_cast<uint8_t>({{asCamelCased label}}.size()))
155 .Put({{asCamelCased label}}.data(), {{asCamelCased label}}.size())
156 {{else if (isString type)}}
157 .Put(static_cast<uint8_t>({{asCamelCased label}}StrLen))
158 .Put({{asCamelCased label}})
159 {{else if (isSignedType)}}
160 .Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>({{asCamelCased label}}))
162 .Put{{chipTypePutLength}}({{asCamelCased label}})
164 {{/chip_server_cluster_command_arguments}}
169 {{/chip_server_cluster_commands}}
170 PacketBufferHandle encode{{asCamelCased name false}}ClusterDiscoverAttributes(uint8_t seqNum, EndpointId destinationEndpoint)
172 COMMAND_HEADER("Discover{{asCamelCased name false}}Attributes", {{define}}_ID);
173 buf.Put8(kFrameControlGlobalCommand)
175 .Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID)
181 {{#chip_server_cluster_attributes}}
183 * Attribute {{asCamelCased name false}}
185 PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(uint8_t seqNum, EndpointId destinationEndpoint)
187 COMMAND_HEADER("Read{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID);
188 buf.Put8(kFrameControlGlobalCommand)
190 .Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID)
191 .Put16({{asHex attributeCode 4}});
195 {{#if (isWritableAttribute)}}
196 PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(uint8_t seqNum, EndpointId destinationEndpoint, {{asUnderlyingZclType type}} {{asCamelCased name}})
198 COMMAND_HEADER("Write{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID);
199 buf.Put8(kFrameControlGlobalCommand)
201 .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID)
202 .Put16({{asHex attributeCode 4}})
203 .Put8({{atomicTypeId}})
204 .Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>({{asCamelCased name}}));
209 {{#if (isReportableAttribute)}}
210 PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterConfigure{{asCamelCased name false}}Attribute(uint8_t seqNum, EndpointId destinationEndpoint, uint16_t minInterval, uint16_t maxInterval{{#unless (isDiscreteType)}}, {{chipType}} change{{/unless}})
212 COMMAND_HEADER("Report{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID);
213 buf.Put8(kFrameControlGlobalCommand)
215 .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID)
216 .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED)
217 .Put16({{asHex attributeCode 4}})
218 .Put8({{atomicTypeId}})
221 {{#unless (isDiscreteType)}}
222 buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>(change));
228 {{/chip_server_cluster_attributes}}
229 {{/chip_server_clusters}}