@@ -240,4 +240,134 @@ void ZigbeeEP::zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message) {
240
240
}
241
241
}
242
242
243
+ void ZigbeeEP::addTimeCluster (tm time, int32_t gmt_offset) {
244
+ // default values for time cluster
245
+ time_t utc_time = 0 ;
246
+ time_t undefined_time = 0xffffffff ;
247
+ uint8_t time_status = 0 ;
248
+
249
+ // Check if time is set
250
+ if (time .tm_year > 0 ) {
251
+ // Convert time to UTC
252
+ utc_time = mktime (&time );
253
+ }
254
+
255
+ // Create time cluster server attributes
256
+ esp_zb_attribute_list_t *time_cluster_server = esp_zb_zcl_attr_list_create (ESP_ZB_ZCL_CLUSTER_ID_TIME);
257
+ esp_zb_time_cluster_add_attr (time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, (void *)&gmt_offset);
258
+ esp_zb_time_cluster_add_attr (time_cluster_server, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, (void *)&utc_time);
259
+ // Create time cluster client attributes
260
+ esp_zb_attribute_list_t *time_cluster_client = esp_zb_zcl_attr_list_create (ESP_ZB_ZCL_CLUSTER_ID_TIME);
261
+ // Add time clusters to cluster list
262
+ esp_zb_cluster_list_add_time_cluster (_cluster_list, time_cluster_server, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
263
+ esp_zb_cluster_list_add_time_cluster (_cluster_list, time_cluster_client, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
264
+
265
+ }
266
+
267
+ void ZigbeeEP::setTime (tm time) {
268
+ time_t utc_time = mktime (&time );
269
+ esp_zb_lock_acquire (portMAX_DELAY);
270
+ esp_zb_zcl_set_attribute_val (_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, &utc_time, false );
271
+ esp_zb_lock_release ();
272
+ }
273
+
274
+ void ZigbeeEP::setTimezone (int32_t gmt_offset) {
275
+ esp_zb_lock_acquire (portMAX_DELAY);
276
+ esp_zb_zcl_set_attribute_val (_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, &gmt_offset, false );
277
+ esp_zb_lock_release ();
278
+ }
279
+
280
+ tm ZigbeeEP::getTime (uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
281
+ /* Read peer time */
282
+ esp_zb_zcl_read_attr_cmd_t read_req;
283
+
284
+ if (short_addr >= 0 ) {
285
+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
286
+ read_req.zcl_basic_cmd .dst_addr_u .addr_short = (uint16_t )short_addr;
287
+ } else {
288
+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
289
+ memcpy (read_req.zcl_basic_cmd .dst_addr_u .addr_long , ieee_addr, sizeof (esp_zb_ieee_addr_t ));
290
+ }
291
+
292
+ uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ID};
293
+ read_req.attr_number = ZB_ARRAY_LENTH (attributes);
294
+ read_req.attr_field = attributes;
295
+
296
+ read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
297
+
298
+ read_req.zcl_basic_cmd .dst_endpoint = endpoint;
299
+ read_req.zcl_basic_cmd .src_endpoint = _endpoint;
300
+
301
+ // clear read time
302
+ _read_time = 0 ;
303
+
304
+ log_v (" Reading time from endpoint %d" , endpoint);
305
+ esp_zb_zcl_read_attr_cmd_req (&read_req);
306
+
307
+ // Wait for response or timeout
308
+ if (xSemaphoreTake (lock, ZB_CMD_TIMEOUT) != pdTRUE) {
309
+ log_e (" Error while reading time" );
310
+ return tm ();
311
+ }
312
+
313
+ struct tm *timeinfo = localtime (&_read_time);
314
+ if (timeinfo) {
315
+ return *timeinfo;
316
+ } else {
317
+ log_e (" Error while converting time" );
318
+ return tm ();
319
+ }
320
+ }
321
+
322
+ int32_t ZigbeeEP::getTimezone (uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
323
+ /* Read peer timezone */
324
+ esp_zb_zcl_read_attr_cmd_t read_req;
325
+
326
+ if (short_addr >= 0 ) {
327
+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
328
+ read_req.zcl_basic_cmd .dst_addr_u .addr_short = (uint16_t )short_addr;
329
+ } else {
330
+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
331
+ memcpy (read_req.zcl_basic_cmd .dst_addr_u .addr_long , ieee_addr, sizeof (esp_zb_ieee_addr_t ));
332
+ }
333
+
334
+ uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID};
335
+ read_req.attr_number = ZB_ARRAY_LENTH (attributes);
336
+ read_req.attr_field = attributes;
337
+
338
+ read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
339
+
340
+ read_req.zcl_basic_cmd .dst_endpoint = endpoint;
341
+ read_req.zcl_basic_cmd .src_endpoint = _endpoint;
342
+
343
+ // clear read timezone
344
+ _read_timezone = 0 ;
345
+
346
+ log_v (" Reading timezone from endpoint %d" , endpoint);
347
+ esp_zb_zcl_read_attr_cmd_req (&read_req);
348
+
349
+ // Wait for response or timeout
350
+ if (xSemaphoreTake (lock, ZB_CMD_TIMEOUT) != pdTRUE) {
351
+ log_e (" Error while reading timezone" );
352
+ }
353
+
354
+ return _read_timezone;
355
+ }
356
+
357
+ void ZigbeeEP::zbReadTimeCluster (const esp_zb_zcl_attribute_t *attribute) {
358
+ /* Time cluster attributes */
359
+ if (attribute->id == ESP_ZB_ZCL_ATTR_TIME_TIME_ID && attribute->data .type == ESP_ZB_ZCL_ATTR_TYPE_UTC_TIME) {
360
+ log_v (" Time attribute received" );
361
+ log_v (" Time: %lld" , *(uint32_t *)attribute->data .value );
362
+ _read_time = *(uint32_t *)attribute->data .value ;
363
+ xSemaphoreGive (lock);
364
+ }
365
+ else if (attribute->id == ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID && attribute->data .type == ESP_ZB_ZCL_ATTR_TYPE_S32) {
366
+ log_v (" Timezone attribute received" );
367
+ log_v (" Timezone: %d" , *(int32_t *)attribute->data .value );
368
+ _read_timezone = *(int32_t *)attribute->data .value ;
369
+ xSemaphoreGive (lock);
370
+ }
371
+ }
372
+
243
373
#endif // SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED
0 commit comments