Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / app / zap-templates / templates / chip / CHIPClustersObjc-src.zapt
1 {{> header}}
2
3 #import <Foundation/Foundation.h>
4
5 #import "CHIPDevice.h"
6 #import "CHIPDevice_Internal.h"
7 #import "ChipError.h"
8 #import "gen/CHIPClustersObjc.h"
9 #import "gen/CHIPClientCallbacks.h"
10
11 #include <controller/CHIPClusters.h>
12 #include <lib/support/Span.h>
13
14 using namespace ::chip;
15
16 class CHIPDefaultSuccessCallbackBridge : public Callback::Callback<DefaultSuccessCallback> {
17 public:
18     CHIPDefaultSuccessCallbackBridge(ResponseHandler handler, dispatch_queue_t queue)
19         : Callback::Callback<DefaultSuccessCallback>(CallbackFn, this)
20         , mHandler(handler)
21         , mQueue(queue)
22     {
23     }
24
25     ~CHIPDefaultSuccessCallbackBridge() {};
26
27     static void CallbackFn(void * context)
28     {
29         CHIPDefaultSuccessCallbackBridge * callback = reinterpret_cast<CHIPDefaultSuccessCallbackBridge *>(context);
30         if (callback && callback->mQueue) {
31             dispatch_async(callback->mQueue, ^{
32                 callback->mHandler(nil, nil);
33                 callback->Cancel();
34                 delete callback;
35             });
36         }
37     };
38
39 private:
40     ResponseHandler mHandler;
41     dispatch_queue_t mQueue;
42 };
43
44 class CHIPDefaultFailureCallbackBridge : public Callback::Callback<DefaultFailureCallback> {
45 public:
46     CHIPDefaultFailureCallbackBridge(ResponseHandler handler, dispatch_queue_t queue)
47         : Callback::Callback<DefaultFailureCallback>(CallbackFn, this)
48         , mHandler(handler)
49         , mQueue(queue)
50     {
51     }
52
53     ~CHIPDefaultFailureCallbackBridge() {};
54
55     static void CallbackFn(void * context, uint8_t status)
56     {
57         CHIPDefaultFailureCallbackBridge * callback = reinterpret_cast<CHIPDefaultFailureCallbackBridge *>(context);
58         if (callback && callback->mQueue) {
59             dispatch_async(callback->mQueue, ^{
60                 NSError* error = [NSError errorWithDomain:CHIPErrorDomain code:status userInfo:@{NSLocalizedDescriptionKey:@""}];
61                 callback->mHandler(error, nil);
62                 callback->Cancel();
63                 delete callback;
64             });
65         }
66     };
67
68 private:
69     ResponseHandler mHandler;
70     dispatch_queue_t mQueue;
71 };
72
73 class CHIPStringAttributeCallbackBridge : public Callback::Callback<StringAttributeCallback> {
74 public:
75     CHIPStringAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool octetString, bool keepAlive = false)
76         : Callback::Callback<StringAttributeCallback>(CallbackFn, this)
77         , mHandler(handler)
78         , mQueue(queue)
79         , mOctetString(octetString)
80         , mKeepAlive(keepAlive)
81     {
82     }
83
84     ~CHIPStringAttributeCallbackBridge() {};
85
86     static void CallbackFn(void * context, chip::ByteSpan value)
87     {
88         CHIPStringAttributeCallbackBridge * callback = reinterpret_cast<CHIPStringAttributeCallbackBridge *>(context);
89         if (callback && callback->mQueue) {
90             dispatch_async(callback->mQueue, ^{
91                 if (callback->mOctetString)
92                 {
93                     NSData *data = [NSData dataWithBytes: value.data() length: value.size()];
94                     callback->mHandler(nil, @{ @"value": data });
95                 }
96                 else
97                 {
98                     NSString * str = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSUTF8StringEncoding];
99                     callback->mHandler(nil, @{ @"value": str });
100                 }
101
102                 if (!callback->mKeepAlive)
103                 {
104                     callback->Cancel();
105                     delete callback;
106                 }
107             });
108         }
109     };
110
111 private:
112     ResponseHandler mHandler;
113     dispatch_queue_t mQueue;
114     bool mOctetString;
115     bool mKeepAlive;
116 };
117
118 class CHIPBooleanAttributeCallbackBridge : public Callback::Callback<BooleanAttributeCallback> {
119 public:
120     CHIPBooleanAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
121         : Callback::Callback<BooleanAttributeCallback>(CallbackFn, this)
122         , mHandler(handler)
123         , mQueue(queue)
124         , mKeepAlive(keepAlive)
125     {
126     }
127
128     ~CHIPBooleanAttributeCallbackBridge() {};
129
130     static void CallbackFn(void * context, bool value)
131     {
132         CHIPBooleanAttributeCallbackBridge * callback = reinterpret_cast<CHIPBooleanAttributeCallbackBridge *>(context);
133         if (callback && callback->mQueue) {
134             dispatch_async(callback->mQueue, ^{
135                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithBool:value] });
136                 if (!callback->mKeepAlive)
137                 {
138                     callback->Cancel();
139                     delete callback;
140                 }
141             });
142         }
143     };
144
145 private:
146     ResponseHandler mHandler;
147     dispatch_queue_t mQueue;
148     bool mKeepAlive;
149 };
150
151 class CHIPInt8uAttributeCallbackBridge : public Callback::Callback<Int8uAttributeCallback> {
152 public:
153     CHIPInt8uAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
154         : Callback::Callback<Int8uAttributeCallback>(CallbackFn, this)
155         , mHandler(handler)
156         , mQueue(queue)
157         , mKeepAlive(keepAlive)
158     {
159     }
160
161     ~CHIPInt8uAttributeCallbackBridge() {};
162
163     static void CallbackFn(void * context, uint8_t value)
164     {
165         CHIPInt8uAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt8uAttributeCallbackBridge *>(context);
166         if (callback && callback->mQueue) {
167             dispatch_async(callback->mQueue, ^{
168                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithUnsignedChar:value] });
169                 if (!callback->mKeepAlive)
170                 {
171                     callback->Cancel();
172                     delete callback;
173                 }
174             });
175         }
176     };
177
178 private:
179     ResponseHandler mHandler;
180     dispatch_queue_t mQueue;
181     bool mKeepAlive;
182 };
183
184 class CHIPInt8sAttributeCallbackBridge : public Callback::Callback<Int8sAttributeCallback> {
185 public:
186     CHIPInt8sAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
187         : Callback::Callback<Int8sAttributeCallback>(CallbackFn, this)
188         , mHandler(handler)
189         , mQueue(queue)
190         , mKeepAlive(keepAlive)
191     {
192     }
193
194     ~CHIPInt8sAttributeCallbackBridge() {};
195
196     static void CallbackFn(void * context, int8_t value)
197     {
198         CHIPInt8sAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt8sAttributeCallbackBridge *>(context);
199         if (callback && callback->mQueue) {
200             dispatch_async(callback->mQueue, ^{
201                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithChar:value] });
202                 if (!callback->mKeepAlive)
203                 {
204                     callback->Cancel();
205                     delete callback;
206                 }
207             });
208         }
209     };
210
211 private:
212     ResponseHandler mHandler;
213     dispatch_queue_t mQueue;
214     bool mKeepAlive;
215 };
216
217 class CHIPInt16uAttributeCallbackBridge : public Callback::Callback<Int16uAttributeCallback> {
218 public:
219     CHIPInt16uAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
220         : Callback::Callback<Int16uAttributeCallback>(CallbackFn, this)
221         , mHandler(handler)
222         , mQueue(queue)
223         , mKeepAlive(keepAlive)
224     {
225     }
226
227     ~CHIPInt16uAttributeCallbackBridge() {};
228
229     static void CallbackFn(void * context, uint16_t value)
230     {
231         CHIPInt16uAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt16uAttributeCallbackBridge *>(context);
232         if (callback && callback->mQueue) {
233             dispatch_async(callback->mQueue, ^{
234                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithUnsignedShort:value] });
235                 if (!callback->mKeepAlive)
236                 {
237                     callback->Cancel();
238                     delete callback;
239                 }
240             });
241         }
242     };
243
244 private:
245     ResponseHandler mHandler;
246     dispatch_queue_t mQueue;
247     bool mKeepAlive;
248 };
249
250 class CHIPInt32uAttributeCallbackBridge : public Callback::Callback<Int32uAttributeCallback> {
251 public:
252     CHIPInt32uAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
253         : Callback::Callback<Int32uAttributeCallback>(CallbackFn, this)
254         , mHandler(handler)
255         , mQueue(queue)
256         , mKeepAlive(keepAlive)
257     {
258     }
259
260     ~CHIPInt32uAttributeCallbackBridge() {};
261
262     static void CallbackFn(void * context, uint32_t value)
263     {
264         CHIPInt32uAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt32uAttributeCallbackBridge *>(context);
265         if (callback && callback->mQueue) {
266             dispatch_async(callback->mQueue, ^{
267                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithUnsignedLong:value] });
268                 if (!callback->mKeepAlive)
269                 {
270                     callback->Cancel();
271                     delete callback;
272                 }
273             });
274         }
275     };
276
277 private:
278     ResponseHandler mHandler;
279     dispatch_queue_t mQueue;
280     bool mKeepAlive;
281 };
282
283 class CHIPInt16sAttributeCallbackBridge : public Callback::Callback<Int16sAttributeCallback> {
284 public:
285     CHIPInt16sAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
286         : Callback::Callback<Int16sAttributeCallback>(CallbackFn, this)
287         , mHandler(handler)
288         , mQueue(queue)
289         , mKeepAlive(keepAlive)
290     {
291     }
292
293     ~CHIPInt16sAttributeCallbackBridge() {};
294
295     static void CallbackFn(void * context, int16_t value)
296     {
297         CHIPInt16sAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt16sAttributeCallbackBridge *>(context);
298         if (callback && callback->mQueue) {
299             dispatch_async(callback->mQueue, ^{
300                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithShort:value] });
301                 if (!callback->mKeepAlive)
302                 {
303                     callback->Cancel();
304                     delete callback;
305                 }
306             });
307         }
308     };
309
310 private:
311     ResponseHandler mHandler;
312     dispatch_queue_t mQueue;
313     bool mKeepAlive;
314 };
315
316 {{#all_user_clusters}}
317 {{#if (isClient side) }}
318 {{#if (user_cluster_has_enabled_command name side)}}
319 {{#all_user_cluster_commands}}
320 {{#if (isStrEqual clusterName parent.name)}}
321 {{#if (isCommandAvailable parent.side incoming outgoing commandSource name)}}
322 class CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge : public Callback::Callback<{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback>
323 {
324 public:
325     CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge(ResponseHandler handler, dispatch_queue_t queue): Callback::Callback<{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback>(CallbackFn, this), mHandler(handler), mQueue(queue) {}
326
327     ~CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge() {};
328
329     static void CallbackFn(void * context{{#zcl_command_arguments}}{{#unless (isStrEqual label "status")}}, {{asUnderlyingZclType type}} {{asSymbol label}}{{/unless}}{{/zcl_command_arguments}})
330     {
331         CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge * callback = reinterpret_cast<CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge *>(context);
332         if (callback && callback->mQueue)
333         {
334             dispatch_async(callback->mQueue, ^{
335                 callback->mHandler(nil, @{
336                   {{#zcl_command_arguments}}
337                   {{#unless (isStrEqual label "status")}}
338                   {{#if isArray}}
339                   // {{asSymbol label}}: {{asUnderlyingZclType type}}
340                   // Conversion from this type to Objc is not properly implemented yet
341                   {{else if (isShortString type)}}
342                   @"{{asSymbol label}}": [NSString stringWithFormat:@"%s", {{asSymbol label}}],
343                   {{else}}
344                   @"{{asSymbol label}}": [NSNumber numberWith{{asObjectiveCNumberType label type}}:{{asSymbol label}}],
345                   {{/if}}
346                   {{/unless}}
347                   {{/zcl_command_arguments}}
348                 });
349                 callback->Cancel();
350                 delete callback;
351             });
352         }
353     };
354
355 private:
356     ResponseHandler mHandler;
357     dispatch_queue_t mQueue;
358 };
359
360 {{/if}}
361 {{/if}}
362 {{/all_user_cluster_commands}}
363 {{/if}}
364 {{/if}}
365 {{/all_user_clusters}}
366
367 @interface CHIPCluster ()
368 @property (readonly, nonatomic) dispatch_queue_t callbackQueue;
369 - (Controller::ClusterBase *)getCluster;
370 @end
371
372 @implementation CHIPCluster
373 - (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(EndpointId)endpoint queue:(dispatch_queue_t)queue
374 {
375     if (self = [super init]) {
376         Controller::ClusterBase * cppCluster = [self getCluster];
377         if (cppCluster == nullptr)
378         {
379             return nil;
380         }
381     
382         CHIP_ERROR err = cppCluster->Associate([device internalDevice], endpoint);
383         if (err != CHIP_NO_ERROR) {
384             return nil;
385         }
386
387         _callbackQueue = queue;
388     }
389     return self;
390 }
391
392 - (Controller::ClusterBase *)getCluster
393 {
394     return nullptr;
395 }
396 @end
397
398
399 {{#chip_clusters}}
400
401 @interface CHIP{{asCamelCased name false}} ()
402 @property (readonly) Controller::{{asCamelCased name false}}Cluster cppCluster;
403 @end
404
405 @implementation CHIP{{asCamelCased name false}}
406
407 - (Controller::ClusterBase *)getCluster
408 {
409     return &_cppCluster;
410 }
411
412 {{#chip_server_cluster_commands}}
413 {{#if (zcl_command_arguments_count this.id)}}
414 - (void){{asCamelCased name}}:{{#chip_server_cluster_command_arguments}}{{#if (isFirstElement index)}}{{else}}{{asCamelCased label}}:{{/if}}({{asObjectiveCBasicType type}}){{asCamelCased label}} {{/chip_server_cluster_command_arguments}}completionHandler:(ResponseHandler)completionHandler
415 {{else}}
416 - (void){{asCamelCased name}}:(ResponseHandler)completionHandler
417 {{/if}}
418 {
419 {{#if (hasSpecificResponse name)}}
420     CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}ResponseCallbackBridge * onSuccess = new CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}ResponseCallbackBridge(completionHandler, [self callbackQueue]);
421 {{else}}
422     CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(completionHandler, [self callbackQueue]);
423 {{/if}}
424     if (!onSuccess) {
425         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
426         return;
427     }
428
429     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
430     if (!onFailure) {
431         delete onSuccess;
432         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
433         return;
434     }
435
436     CHIP_ERROR err = self.cppCluster.{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(){{#chip_server_cluster_command_arguments}}, {{#if (isOctetString type)}}chip::ByteSpan((const uint8_t*){{asCamelCased label}}.bytes, {{asCamelCased label}}.length){{else if (isCharString type)}}chip::ByteSpan((const uint8_t*)[{{asCamelCased label}} dataUsingEncoding:NSUTF8StringEncoding].bytes, [{{asCamelCased label}} lengthOfBytesUsingEncoding:NSUTF8StringEncoding]){{else}}{{asCamelCased label}}{{/if}}{{/chip_server_cluster_command_arguments}});
437     if (err != CHIP_NO_ERROR) {
438         delete onSuccess;
439         delete onFailure;
440         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
441     }
442 }
443 {{/chip_server_cluster_commands}}
444
445 {{#chip_server_cluster_attributes}}
446 - (void)readAttribute{{asCamelCased name false}}:(ResponseHandler)completionHandler
447 {
448     CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge * onSuccess = new CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge(completionHandler, [self callbackQueue]{{#if (isString type)}},{{#if (isOctetString type)}}true{{else}}false{{/if}}{{/if}});
449     if (!onSuccess) {
450         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
451         return;
452     }
453
454     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
455     if (!onFailure) {
456         delete onSuccess;
457         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
458         return;
459     }
460
461     CHIP_ERROR err = self.cppCluster.ReadAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel());
462     if (err != CHIP_NO_ERROR) {
463         delete onSuccess;
464         delete onFailure;
465         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
466     }
467 }
468
469 {{#if (isWritableAttribute)}}
470 - (void)writeAttribute{{asCamelCased name false}}:({{asObjectiveCBasicType type}})value completionHandler:(ResponseHandler)completionHandler
471 {
472     CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(completionHandler, [self callbackQueue]);
473     if (!onSuccess) {
474         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
475         return;
476     }
477
478     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
479     if (!onFailure) {
480         delete onSuccess;
481         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
482         return;
483     }
484
485     {{#if (isOctetString type)}}
486     CHIP_ERROR err = self.cppCluster.WriteAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), chip::ByteSpan((const uint8_t*)value.bytes, value.length));
487     {{else if (isCharString type)}}
488     NSData * data = [value dataUsingEncoding:NSUTF8StringEncoding];
489     CHIP_ERROR err = self.cppCluster.WriteAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), chip::ByteSpan((const uint8_t*)data.bytes, data.length));
490     {{else}}
491     CHIP_ERROR err = self.cppCluster.WriteAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), value);
492     {{/if}}
493     if (err != CHIP_NO_ERROR) {
494         delete onSuccess;
495         delete onFailure;
496         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
497     }
498 }
499
500 {{/if}}
501 {{#if (isReportableAttribute)}}
502 - (void) configureAttribute{{asCamelCased name false}}:(uint16_t)minInterval  maxInterval:(uint16_t)maxInterval{{#unless (isDiscreteType)}} change:({{chipType}})change{{/unless}} completionHandler:(ResponseHandler)completionHandler
503 {
504     CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(completionHandler, [self callbackQueue]);
505     if (!onSuccess) {
506         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
507         return;
508     }
509
510     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
511     if (!onFailure) {
512         delete onSuccess;
513         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
514         return;
515     }
516
517
518     CHIP_ERROR err = self.cppCluster.ConfigureAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), minInterval, maxInterval{{#unless (isDiscreteType)}}, change{{/unless}});
519     if (err != CHIP_NO_ERROR) {
520         delete onSuccess;
521         delete onFailure;
522         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
523     }
524 }
525
526 - (void) reportAttribute{{asCamelCased name false}}:(ResponseHandler)reportHandler
527 {
528     CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge * onReport = new CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge(reportHandler, [self callbackQueue]{{#if (isString type)}},{{#if (isOctetString type)}}true{{else}}false{{/if}}{{/if}}, true);
529     if (!onReport) {
530         reportHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
531         return;
532     }
533
534     CHIP_ERROR err = self.cppCluster.ReportAttribute{{asCamelCased name false}}(onReport->Cancel());
535     if (err != CHIP_NO_ERROR) {
536         delete onReport;
537         reportHandler([CHIPError errorForCHIPErrorCode:err], nil);
538     }
539 }
540
541 {{/if}}
542 {{/chip_server_cluster_attributes}}
543
544 @end
545
546 {{/chip_clusters}}