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