7cc96d217d086c5385617b50590fea29db14c81a
[platform/upstream/connectedhomeip.git] / src / app / zap-templates / templates / chip / encoder-src.zapt
1 {{> header}}
2
3 #include "chip-zcl-zpro-codec.h"
4
5 #include <support/BufferWriter.h>
6 #include <support/SafeInt.h>
7 #include <support/logging/CHIPLogging.h>
8
9 #include <app/util/basic-types.h>
10 #include <lib/support/Span.h>
11
12 using namespace chip;
13 using namespace chip::System;
14 using namespace chip::Encoding::LittleEndian;
15
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)
19 {
20
21     uint8_t control_byte = 0;
22     buf.Put(control_byte) // Put in a control byte
23         .Put16(clusterId)
24         .Put8(sourceEndpoint)
25         .Put8(destinationEndpoint)
26         .EndianPut(options, sizeof(EmberApsOption))
27         .Put16(groupId)
28         .Put8(sequence)
29         .Put8(radius);
30
31     size_t result = buf.Needed();
32     if (isMeasuring)
33     {
34         ChipLogDetail(Zcl, "Measured APS frame size %d", result);
35     }
36     else if (buf.Fit())
37     {
38         ChipLogDetail(Zcl, "Successfully encoded %d bytes", result);
39     }
40     else
41     {
42         ChipLogError(Zcl, "Error encoding APS Frame: Buffer too small");
43         result = 0;
44     }
45
46     if (!CanCastTo<uint16_t>(result))
47     {
48         ChipLogError(Zcl, "Can't fit our measured size in uint16_t");
49         result = 0;
50     }
51
52     return static_cast<uint16_t>(result);
53 }
54
55 uint16_t encodeApsFrame(uint8_t * buffer, uint16_t buf_length, EmberApsFrame * apsFrame)
56 {
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);
60 }
61
62 #define COMMAND_HEADER(name, clusterId)                                                                                            \
63     const char * kName = name;                                                                                                     \
64                                                                                                                                    \
65     PacketBufferWriter buf(System::PacketBufferHandle::New(kMaxBufferSize));                                                       \
66     if (buf.IsNull())                                                                                                              \
67     {                                                                                                                              \
68         ChipLogError(Zcl, "Could not allocate packet buffer while trying to encode %s command", kName);                            \
69         return PacketBufferHandle();                                                                                               \
70     }                                                                                                                              \
71                                                                                                                                    \
72     if (doEncodeApsFrame(buf, clusterId, kSourceEndpoint, destinationEndpoint, 0, 0, 0, 0, false))                                 \
73     {
74
75 #define COMMAND_FOOTER()                                                                                                           \
76     }                                                                                                                              \
77     if (!buf.Fit())                                                                                                                \
78     {                                                                                                                              \
79         ChipLogError(Zcl, "Command %s can't fit in the allocated buffer", kName);                                                  \
80     }                                                                                                                              \
81     return buf.Finalize();
82
83
84 {{> clusters_header}}
85
86 #define EMBER_ZCL_REPORTING_DIRECTION_REPORTED 0x00
87
88 {{#zcl_global_commands}}
89 #define ZCL_{{asDelimitedMacro label}}_COMMAND_ID ({{asHex code 2}})
90 {{/zcl_global_commands}}
91
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}}
97
98 {{/chip_server_clusters}}
99
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;
103
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;
108
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;
113
114 // Pick source endpoint as 1 for now
115 constexpr EndpointId kSourceEndpoint = 1;
116
117 {{#chip_server_clusters}}
118 {{> cluster_header}}
119
120 {{#chip_server_cluster_commands}}
121 /*
122  * Command {{asCamelCased name false}}
123  */
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}})
125 {
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()))
130     {
131         ChipLogError(Zcl, "Error encoding %s command. String too long: %zu", kName, {{asCamelCased label}}.size());
132         return PacketBufferHandle();
133     }
134     {{else if (isString type)}}
135     size_t {{asCamelCased label}}StrLen = strlen({{asCamelCased label}});
136     if (!CanCastTo<uint8_t>({{asCamelCased label}}StrLen))
137     {
138         ChipLogError(Zcl, "Error encoding %s command. String too long: %d", kName, {{asCamelCased label}}StrLen);
139         return PacketBufferHandle();
140     }
141     {{/if}}
142     {{/chip_server_cluster_command_arguments}}
143       buf
144     {{#if (isManufacturerSpecificCommand)}}
145         .Put8(kFrameControlClusterSpecificCommand | (1u << 2))
146         .Put16({{asHex mfgCode 4}})
147     {{else}}
148         .Put8(kFrameControlClusterSpecificCommand)
149     {{/if}}
150        .Put8(seqNum)
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}}))
161     {{else}}
162        .Put{{chipTypePutLength}}({{asCamelCased label}})
163     {{/if}}
164     {{/chip_server_cluster_command_arguments}}
165     ;
166     COMMAND_FOOTER();
167 }
168
169 {{/chip_server_cluster_commands}}
170 PacketBufferHandle encode{{asCamelCased name false}}ClusterDiscoverAttributes(uint8_t seqNum, EndpointId destinationEndpoint)
171 {
172     COMMAND_HEADER("Discover{{asCamelCased name false}}Attributes", {{define}}_ID);
173     buf.Put8(kFrameControlGlobalCommand)
174        .Put8(seqNum)
175        .Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID)
176        .Put16(0x0000)
177        .Put8(0xFF);
178     COMMAND_FOOTER();
179 }
180
181 {{#chip_server_cluster_attributes}}
182 /*
183  * Attribute {{asCamelCased name false}}
184  */
185 PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterRead{{asCamelCased name false}}Attribute(uint8_t seqNum, EndpointId destinationEndpoint)
186 {
187     COMMAND_HEADER("Read{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID);
188     buf.Put8(kFrameControlGlobalCommand)
189        .Put8(seqNum)
190        .Put8(ZCL_READ_ATTRIBUTES_COMMAND_ID)
191        .Put16({{asHex attributeCode 4}});
192     COMMAND_FOOTER();
193 }
194
195 {{#if (isWritableAttribute)}}
196 PacketBufferHandle encode{{asCamelCased parent.name false}}ClusterWrite{{asCamelCased name false}}Attribute(uint8_t seqNum, EndpointId destinationEndpoint, {{asUnderlyingZclType type}} {{asCamelCased name}})
197 {
198     COMMAND_HEADER("Write{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID);
199     buf.Put8(kFrameControlGlobalCommand)
200        .Put8(seqNum)
201        .Put8(ZCL_WRITE_ATTRIBUTES_COMMAND_ID)
202        .Put16({{asHex attributeCode 4}})
203        .Put8({{atomicTypeId}})
204        .Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>({{asCamelCased name}}));
205     COMMAND_FOOTER();
206 }
207
208 {{/if}}
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}})
211 {
212     COMMAND_HEADER("Report{{asCamelCased parent.name false}}{{asCamelCased name false}}", {{parent.define}}_ID);
213     buf.Put8(kFrameControlGlobalCommand)
214        .Put8(seqNum)
215        .Put8(ZCL_CONFIGURE_REPORTING_COMMAND_ID)
216        .Put8(EMBER_ZCL_REPORTING_DIRECTION_REPORTED)
217        .Put16({{asHex attributeCode 4}})
218        .Put8({{atomicTypeId}})
219        .Put16(minInterval)
220        .Put16(maxInterval);
221     {{#unless (isDiscreteType)}}
222     buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>(change));
223     {{/unless}}
224     COMMAND_FOOTER();
225 }
226
227 {{/if}}
228 {{/chip_server_cluster_attributes}}
229 {{/chip_server_clusters}}