32c269f7a3a91dd3abab16515ef86db978b03d24
[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 CHIPUnsupportedAttributeCallbackBridge : public Callback::Callback<DefaultSuccessCallback> {
74 public:
75     CHIPUnsupportedAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue)
76         : Callback::Callback<DefaultSuccessCallback>(CallbackFn, this)
77     {
78     }
79
80     ~CHIPUnsupportedAttributeCallbackBridge() {};
81
82     static void CallbackFn(void * context)
83     {
84         CHIPUnsupportedAttributeCallbackBridge * callback = reinterpret_cast<CHIPUnsupportedAttributeCallbackBridge *>(context);
85         if (callback && callback->mQueue) {
86             dispatch_async(callback->mQueue, ^{
87                 NSError* error = [NSError errorWithDomain:CHIPErrorDomain code:CHIPErrorCodeUndefinedError userInfo:@{NSLocalizedDescriptionKey:@"Unsupported attribute type"}];
88                 callback->mHandler(error, nil);
89                 callback->Cancel();
90                 delete callback;
91             });
92         }
93     };
94
95 private:
96     ResponseHandler mHandler;
97     dispatch_queue_t mQueue;
98 };
99
100 class CHIPBooleanAttributeCallbackBridge : public Callback::Callback<BooleanAttributeCallback> {
101 public:
102     CHIPBooleanAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
103         : Callback::Callback<BooleanAttributeCallback>(CallbackFn, this)
104         , mHandler(handler)
105         , mQueue(queue)
106         , mKeepAlive(keepAlive)
107     {
108     }
109
110     ~CHIPBooleanAttributeCallbackBridge() {};
111
112     static void CallbackFn(void * context, bool value)
113     {
114         CHIPBooleanAttributeCallbackBridge * callback = reinterpret_cast<CHIPBooleanAttributeCallbackBridge *>(context);
115         if (callback && callback->mQueue) {
116             dispatch_async(callback->mQueue, ^{
117                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithBool:value] });
118                 if (!callback->mKeepAlive)
119                 {
120                     callback->Cancel();
121                     delete callback;
122                 }
123             });
124         }
125     };
126
127 private:
128     ResponseHandler mHandler;
129     dispatch_queue_t mQueue;
130     bool mKeepAlive;
131 };
132
133 class CHIPInt8uAttributeCallbackBridge : public Callback::Callback<Int8uAttributeCallback> {
134 public:
135     CHIPInt8uAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
136         : Callback::Callback<Int8uAttributeCallback>(CallbackFn, this)
137         , mHandler(handler)
138         , mQueue(queue)
139         , mKeepAlive(keepAlive)
140     {
141     }
142
143     ~CHIPInt8uAttributeCallbackBridge() {};
144
145     static void CallbackFn(void * context, uint8_t value)
146     {
147         CHIPInt8uAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt8uAttributeCallbackBridge *>(context);
148         if (callback && callback->mQueue) {
149             dispatch_async(callback->mQueue, ^{
150                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithUnsignedChar:value] });
151                 if (!callback->mKeepAlive)
152                 {
153                     callback->Cancel();
154                     delete callback;
155                 }
156             });
157         }
158     };
159
160 private:
161     ResponseHandler mHandler;
162     dispatch_queue_t mQueue;
163     bool mKeepAlive;
164 };
165
166 class CHIPInt8sAttributeCallbackBridge : public Callback::Callback<Int8sAttributeCallback> {
167 public:
168     CHIPInt8sAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
169         : Callback::Callback<Int8sAttributeCallback>(CallbackFn, this)
170         , mHandler(handler)
171         , mQueue(queue)
172         , mKeepAlive(keepAlive)
173     {
174     }
175
176     ~CHIPInt8sAttributeCallbackBridge() {};
177
178     static void CallbackFn(void * context, int8_t value)
179     {
180         CHIPInt8sAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt8sAttributeCallbackBridge *>(context);
181         if (callback && callback->mQueue) {
182             dispatch_async(callback->mQueue, ^{
183                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithChar:value] });
184                 if (!callback->mKeepAlive)
185                 {
186                     callback->Cancel();
187                     delete callback;
188                 }
189             });
190         }
191     };
192
193 private:
194     ResponseHandler mHandler;
195     dispatch_queue_t mQueue;
196     bool mKeepAlive;
197 };
198
199 class CHIPInt16uAttributeCallbackBridge : public Callback::Callback<Int16uAttributeCallback> {
200 public:
201     CHIPInt16uAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
202         : Callback::Callback<Int16uAttributeCallback>(CallbackFn, this)
203         , mHandler(handler)
204         , mQueue(queue)
205         , mKeepAlive(keepAlive)
206     {
207     }
208
209     ~CHIPInt16uAttributeCallbackBridge() {};
210
211     static void CallbackFn(void * context, uint16_t value)
212     {
213         CHIPInt16uAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt16uAttributeCallbackBridge *>(context);
214         if (callback && callback->mQueue) {
215             dispatch_async(callback->mQueue, ^{
216                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithUnsignedShort:value] });
217                 if (!callback->mKeepAlive)
218                 {
219                     callback->Cancel();
220                     delete callback;
221                 }
222             });
223         }
224     };
225
226 private:
227     ResponseHandler mHandler;
228     dispatch_queue_t mQueue;
229     bool mKeepAlive;
230 };
231
232 class CHIPInt16sAttributeCallbackBridge : public Callback::Callback<Int16sAttributeCallback> {
233 public:
234     CHIPInt16sAttributeCallbackBridge(ResponseHandler handler, dispatch_queue_t queue, bool keepAlive = false)
235         : Callback::Callback<Int16sAttributeCallback>(CallbackFn, this)
236         , mHandler(handler)
237         , mQueue(queue)
238         , mKeepAlive(keepAlive)
239     {
240     }
241
242     ~CHIPInt16sAttributeCallbackBridge() {};
243
244     static void CallbackFn(void * context, int16_t value)
245     {
246         CHIPInt16sAttributeCallbackBridge * callback = reinterpret_cast<CHIPInt16sAttributeCallbackBridge *>(context);
247         if (callback && callback->mQueue) {
248             dispatch_async(callback->mQueue, ^{
249                 callback->mHandler(nil, @{ @"value": [NSNumber numberWithShort:value] });
250                 if (!callback->mKeepAlive)
251                 {
252                     callback->Cancel();
253                     delete callback;
254                 }
255             });
256         }
257     };
258
259 private:
260     ResponseHandler mHandler;
261     dispatch_queue_t mQueue;
262     bool mKeepAlive;
263 };
264
265 {{#all_user_clusters}}
266 {{#if (isClient side) }}
267 {{#if (user_cluster_has_enabled_command name side)}}
268 {{#all_user_cluster_commands}}
269 {{#if (isStrEqual clusterName parent.name)}}
270 {{#if (isCommandAvailable parent.side incoming outgoing commandSource name)}}
271 class CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge : public Callback::Callback<{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback>
272 {
273 public:
274     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) {}
275
276     ~CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge() {};
277
278     static void CallbackFn(void * context{{#zcl_command_arguments}}{{#unless (isStrEqual label "status")}}, {{asUnderlyingZclType type}} {{asSymbol label}}{{/unless}}{{/zcl_command_arguments}})
279     {
280         CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge * callback = reinterpret_cast<CHIP{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}CallbackBridge *>(context);
281         if (callback && callback->mQueue)
282         {
283             dispatch_async(callback->mQueue, ^{
284                 callback->mHandler(nil, @{
285                   {{#zcl_command_arguments}}
286                   {{#unless (isStrEqual label "status")}}
287                   {{#if isArray}}
288                   // {{asSymbol label}}: {{asUnderlyingZclType type}}
289                   // Conversion from this type to Objc is not properly implemented yet
290                   {{else if (isShortString type)}}
291                   @"{{asSymbol label}}": [NSString stringWithFormat:@"%s", {{asSymbol label}}],
292                   {{else}}
293                   @"{{asSymbol label}}": [NSNumber numberWith{{asObjectiveCNumberType label type}}:{{asSymbol label}}],
294                   {{/if}}
295                   {{/unless}}
296                   {{/zcl_command_arguments}}
297                 });
298                 callback->Cancel();
299                 delete callback;
300             });
301         }
302     };
303
304 private:
305     ResponseHandler mHandler;
306     dispatch_queue_t mQueue;
307 };
308
309 {{/if}}
310 {{/if}}
311 {{/all_user_cluster_commands}}
312 {{/if}}
313 {{/if}}
314 {{/all_user_clusters}}
315
316 @interface CHIPCluster ()
317 @property (readonly, nonatomic) dispatch_queue_t callbackQueue;
318 - (Controller::ClusterBase *)getCluster;
319 @end
320
321 @implementation CHIPCluster
322 - (instancetype)initWithDevice:(CHIPDevice *)device endpoint:(EndpointId)endpoint queue:(dispatch_queue_t)queue
323 {
324     if (self = [super init]) {
325         Controller::ClusterBase * cppCluster = [self getCluster];
326         if (cppCluster == nullptr)
327         {
328             return nil;
329         }
330     
331         CHIP_ERROR err = cppCluster->Associate([device internalDevice], endpoint);
332         if (err != CHIP_NO_ERROR) {
333             return nil;
334         }
335
336         _callbackQueue = queue;
337     }
338     return self;
339 }
340
341 - (Controller::ClusterBase *)getCluster
342 {
343     return nullptr;
344 }
345 @end
346
347
348 {{#chip_clusters}}
349
350 @interface CHIP{{asCamelCased name false}} ()
351 @property (readonly) Controller::{{asCamelCased name false}}Cluster cppCluster;
352 @end
353
354 @implementation CHIP{{asCamelCased name false}}
355
356 - (Controller::ClusterBase *)getCluster
357 {
358     return &_cppCluster;
359 }
360
361 {{#chip_server_cluster_commands}}
362 {{#if (zcl_command_arguments_count this.id)}}
363 - (void){{asCamelCased name}}:{{#chip_server_cluster_command_arguments}}{{#if (isFirstElement index)}}{{else}}{{asCamelCased label}}:{{/if}}({{#if (isByteString type)}}NSData *{{else}}{{asBasicType chipType}}{{/if}}){{asCamelCased label}} {{/chip_server_cluster_command_arguments}}completionHandler:(ResponseHandler)completionHandler
364 {{else}}
365 - (void){{asCamelCased name}}:(ResponseHandler)completionHandler
366 {{/if}}
367 {
368 {{#if (hasSpecificResponse name)}}
369     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]);
370 {{else}}
371     CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(completionHandler, [self callbackQueue]);
372 {{/if}}
373     if (!onSuccess) {
374         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
375         return;
376     }
377
378     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
379     if (!onFailure) {
380         delete onSuccess;
381         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
382         return;
383     }
384
385     CHIP_ERROR err = self.cppCluster.{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(){{#chip_server_cluster_command_arguments}}, {{#if (isByteString type)}}chip::ByteSpan((const uint8_t*){{asCamelCased label}}.bytes, {{asCamelCased label}}.length){{else}}{{asCamelCased label}}{{/if}}{{/chip_server_cluster_command_arguments}});
386     if (err != CHIP_NO_ERROR) {
387         delete onSuccess;
388         delete onFailure;
389         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
390     }
391 }
392 {{/chip_server_cluster_commands}}
393
394 {{#chip_server_cluster_attributes}}
395 - (void)readAttribute{{asCamelCased name false}}:(ResponseHandler)completionHandler
396 {
397     CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge * onSuccess = new CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge(completionHandler, [self callbackQueue]);
398     if (!onSuccess) {
399         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
400         return;
401     }
402
403     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
404     if (!onFailure) {
405         delete onSuccess;
406         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
407         return;
408     }
409
410     CHIP_ERROR err = self.cppCluster.ReadAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel());
411     if (err != CHIP_NO_ERROR) {
412         delete onSuccess;
413         delete onFailure;
414         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
415     }
416 }
417
418 {{#if (isWritableAttribute)}}
419 - (void)writeAttribute{{asCamelCased name false}}:({{asUnderlyingZclType type}})value completionHandler:(ResponseHandler)completionHandler
420 {
421     CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(completionHandler, [self callbackQueue]);
422     if (!onSuccess) {
423         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
424         return;
425     }
426
427     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
428     if (!onFailure) {
429         delete onSuccess;
430         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
431         return;
432     }
433
434     CHIP_ERROR err = self.cppCluster.WriteAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), value);
435     if (err != CHIP_NO_ERROR) {
436         delete onSuccess;
437         delete onFailure;
438         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
439     }
440 }
441
442 {{/if}}
443 {{#if (isReportableAttribute)}}
444 - (void) configureAttribute{{asCamelCased name false}}:(uint16_t)minInterval  maxInterval:(uint16_t)maxInterval{{#unless (isDiscreteType)}} change:({{chipType}})change{{/unless}} completionHandler:(ResponseHandler)completionHandler
445 {
446     CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(completionHandler, [self callbackQueue]);
447     if (!onSuccess) {
448         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
449         return;
450     }
451
452     CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(completionHandler, [self callbackQueue]);
453     if (!onFailure) {
454         delete onSuccess;
455         completionHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
456         return;
457     }
458
459
460     CHIP_ERROR err = self.cppCluster.ConfigureAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), minInterval, maxInterval{{#unless (isDiscreteType)}}, change{{/unless}});
461     if (err != CHIP_NO_ERROR) {
462         delete onSuccess;
463         delete onFailure;
464         completionHandler([CHIPError errorForCHIPErrorCode:err], nil);
465     }
466 }
467
468 - (void) reportAttribute{{asCamelCased name false}}:(ResponseHandler)reportHandler
469 {
470     CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge * onReport = new CHIP{{asCallbackAttributeType atomicTypeId}}AttributeCallbackBridge(reportHandler, [self callbackQueue], true);
471     if (!onReport) {
472         reportHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
473         return;
474     }
475
476     CHIP_ERROR err = self.cppCluster.ReportAttribute{{asCamelCased name false}}(onReport->Cancel());
477     if (err != CHIP_NO_ERROR) {
478         delete onReport;
479         reportHandler([CHIPError errorForCHIPErrorCode:err], nil);
480     }
481 }
482
483 {{/if}}
484 {{/chip_server_cluster_attributes}}
485
486 @end
487
488 {{/chip_clusters}}