1 /*
2  * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3  */
4 
5 #include "common/log.h"
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <ctype.h>
10 // #include <aos/aos.h>
11 #include <aos/kernel.h>
12 
13 // #include <misc/printk.h>
14 // #include <misc/byteorder.h>
15 // #include <aos/hal/gpio.h>
16 // #include <aos/hal/pwm.h>
17 
18 // #include <bluetooth.h>
19 // #include <soc.h>
20 
21 #include <api/mesh.h>
22 #include "genie_service.h"
23 #include "light.h"
24 #include "light_driver.h"
25 
26 static light_param_t light_param;
27 static sig_model_element_state_t light_elem_stat[ELEMENT_NUM];
28 static sig_model_powerup_t light_powerup[ELEMENT_NUM];
29 
30 #ifdef CONFIG_BT_MESH_CFG_CLI
31 static struct bt_mesh_cfg_cli cfg_cli = {};
32 #endif
33 
34 static struct bt_mesh_model primary_element[] = {
35     MESH_MODEL_CFG_SRV_NULL(),
36     MESH_MODEL_HEALTH_SRV_NULL(),
37 #ifdef CONFIG_BT_MESH_CFG_CLI
38     BT_MESH_MODEL_CFG_CLI(&cfg_cli),
39 #endif
40     MESH_MODEL_GEN_ONOFF_SRV(&light_elem_stat[0]),
41     MESH_MODEL_LIGHTNESS_SRV(&light_elem_stat[0]),
42     MESH_MODEL_CTL_SRV(&light_elem_stat[0]),
43     MESH_MODEL_SCENE_SRV(&light_elem_stat[0]),
44 };
45 
46 static struct bt_mesh_model primary_vendor_element[] = {
47     MESH_MODEL_VENDOR_SRV(&light_elem_stat[0]),
48 };
49 
50 struct bt_mesh_elem light_elements[] = {
51     BT_MESH_ELEM(0, primary_element, primary_vendor_element, GENIE_ADDR_LIGHT),
52 };
53 
54 #ifdef CONFIG_GENIE_OTA
genie_sal_ota_is_allow_reboot(void)55 bool genie_sal_ota_is_allow_reboot(void)
56 {
57     // the device will reboot when it is off
58     if (light_elem_stat[0].state.onoff[TYPE_PRESENT] == 0) {
59         // save light para, always off
60         light_powerup[0].last_onoff = 0;
61         genie_storage_write_userdata(GFI_MESH_POWERUP, (uint8_t *)light_powerup, sizeof(light_powerup));
62         LIGHT_DBG("Allow to reboot!");
63 
64         return true;
65     }
66 
67     LIGHT_DBG("light is no so no reboot!");
68 
69     return false;
70 }
71 #endif
72 
_mesh_delay_timer_cb(void * p_timer,void * p_arg)73 static void _mesh_delay_timer_cb(void *p_timer, void *p_arg)
74 {
75     sig_model_element_state_t *p_elem = (sig_model_element_state_t *)p_arg;
76 
77 #ifdef CONFIG_MESH_MODEL_TRANS
78     sig_model_transition_timer_stop(p_elem);
79 #endif
80     sig_model_event(SIG_MODEL_EVT_DELAY_END, p_arg);
81 }
82 
83 #ifdef CONFIG_MESH_MODEL_TRANS
_mesh_trans_timer_cycle(void * p_timer,void * p_arg)84 static void _mesh_trans_timer_cycle(void *p_timer, void *p_arg)
85 {
86     sig_model_element_state_t *p_elem = (sig_model_element_state_t *)p_arg;
87     sig_model_state_t *p_state = &p_elem->state;
88 
89     sig_model_transition_timer_stop(p_elem);
90 
91     // do cycle
92     sig_model_event(SIG_MODEL_EVT_TRANS_CYCLE, p_arg);
93     // BT_DBG(">>>>>%d %d", (u32_t)cur_time, (u32_t)p_elem->state.trans_end_time);
94 
95     if (p_state->trans == 0) {
96         sig_model_event(SIG_MODEL_EVT_TRANS_END, p_arg);
97     } else {
98         k_timer_start(&p_state->trans_timer, SIG_MODEL_TRANSITION_INTERVAL);
99     }
100 }
101 #endif
102 
light_elem_state_init(void)103 void light_elem_state_init(void)
104 {
105     uint8_t index = 0;
106     genie_storage_status_e ret;
107 
108     memset(light_elem_stat, 0, sizeof(light_elem_stat));
109 
110     // load light param
111     ret = genie_storage_read_userdata(GFI_MESH_POWERUP, (uint8_t *)light_powerup, sizeof(light_powerup));
112     for (index = 0; index < ELEMENT_NUM; index++) {
113         light_elem_stat[index].element_id = index;
114 
115         if (ret == GENIE_STORAGE_SUCCESS) {
116             // Use saved data
117             memcpy(&light_elem_stat[index].powerup, &light_powerup[index], sizeof(sig_model_powerup_t));
118         } else {
119             // Use default value
120 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
121             light_elem_stat[index].powerup.last_onoff = GEN_ONOFF_DEFAULT;
122 #endif
123 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
124             light_elem_stat[index].powerup.last_lightness = LIGHTNESS_DEFAULT;
125 #endif
126 #ifdef CONFIG_MESH_MODEL_CTL_SRV
127             light_elem_stat[index].powerup.last_color_temperature = COLOR_TEMPERATURE_DEFAULT;
128 #endif
129 #ifdef CONFIG_MESH_MODEL_SCENE_SRV
130             light_elem_stat[index].powerup.last_scene = SCENE_DEFAULT;
131 #endif
132         }
133 
134 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
135         light_elem_stat[index].state.onoff[TYPE_PRESENT] = 0;
136         light_elem_stat[index].state.onoff[TYPE_TARGET] = light_elem_stat[index].powerup.last_onoff;
137 #endif
138 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
139         light_elem_stat[index].state.lightness[TYPE_PRESENT] = 0;
140         light_elem_stat[index].state.lightness[TYPE_TARGET] = light_elem_stat[index].powerup.last_lightness;
141 #endif
142 #ifdef CONFIG_MESH_MODEL_CTL_SRV
143         light_elem_stat[index].state.color_temperature[TYPE_PRESENT] = COLOR_TEMPERATURE_MIN;
144         light_elem_stat[index].state.color_temperature[TYPE_TARGET] =
145             light_elem_stat[index].powerup.last_color_temperature;
146 #endif
147 #ifdef CONFIG_MESH_MODEL_SCENE_SRV
148         light_elem_stat[index].state.scene[TYPE_PRESENT] = GENIE_SCENE_NORMAL;
149         light_elem_stat[index].state.scene[TYPE_TARGET] = light_elem_stat[index].powerup.last_scene;
150 #endif
151 
152 #ifdef CONFIG_MESH_MODEL_TRANS
153         k_timer_init(&light_elem_stat[index].state.delay_timer, _mesh_delay_timer_cb, &light_elem_stat[index]);
154         k_timer_init(&light_elem_stat[index].state.trans_timer, _mesh_trans_timer_cycle, &light_elem_stat[index]);
155 
156         light_elem_stat[index].state.trans = TRANSITION_DEFAULT_VALUE;
157         light_elem_stat[index].state.delay = DELAY_DEFAULT_VAULE;
158         if (light_elem_stat[index].state.trans) {
159             light_elem_stat[index].state.trans_start_time =
160                 k_uptime_get() + light_elem_stat[index].state.delay * DELAY_TIME_UNIT;
161             light_elem_stat[index].state.trans_end_time =
162                 light_elem_stat[index].state.trans_start_time +
163                 sig_model_transition_get_transition_time(light_elem_stat[index].state.trans);
164         }
165 
166 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
167         if (light_elem_stat[index].state.onoff[TYPE_TARGET] == 1) {
168             // light on
169             sig_model_event(SIG_MODEL_EVT_DELAY_START, &light_elem_stat[index]);
170         }
171 #endif
172 #else // No CONFIG_MESH_MODEL_TRANS
173 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
174         light_elem_stat[index].state.onoff[TYPE_PRESENT] = light_elem_stat[index].state.onoff[TYPE_TARGET];
175         if (light_elem_stat[index].state.onoff[TYPE_TARGET] == 1) {
176             // light on
177             // light_driver_update(1, light_elem_stat[index].state.lightness[TYPE_TARGET], light_elem_stat[index].state.color_temperature[TYPE_TARGET]);
178         }
179 #endif
180 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
181         light_elem_stat[index].state.lightness[TYPE_PRESENT] = light_elem_stat[index].state.lightness[TYPE_TARGET];
182 #endif
183 #ifdef CONFIG_MESH_MODEL_CTL_SRV
184         light_elem_stat[index].state.color_temperature[TYPE_PRESENT] =
185             light_elem_stat[index].state.color_temperature[TYPE_TARGET];
186 #endif
187 #ifdef CONFIG_MESH_MODEL_SCENE_SRV
188         light_elem_stat[index].state.scene[TYPE_PRESENT] = light_elem_stat[index].state.scene[TYPE_TARGET];
189 #endif
190 #endif
191     }
192 }
193 
194 #ifdef MESH_MODEL_VENDOR_TIMER
light_ctl_handle_order_msg(vendor_attr_data_t * attr_data)195 static void light_ctl_handle_order_msg(vendor_attr_data_t *attr_data)
196 {
197     GENIE_LOG_INFO("type:%04x data:%04x\r\n", attr_data->type, attr_data->para);
198 
199     if (attr_data->type == ATTR_TYPE_GENERIC_ONOFF) {
200 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
201         light_elem_stat[0].state.onoff[TYPE_TARGET] = attr_data->para;
202 
203         if (light_elem_stat[0].state.onoff[TYPE_PRESENT] != light_elem_stat[0].state.onoff[TYPE_TARGET]) {
204             sig_model_event(SIG_MODEL_EVT_DELAY_START, &light_elem_stat[0]);
205         }
206 #endif
207     }
208 }
209 #endif
210 
light_param_reset(void)211 static void light_param_reset(void)
212 {
213     genie_storage_delete_userdata(GFI_MESH_POWERUP);
214 }
215 
light_save_state(sig_model_element_state_t * p_elem)216 static void light_save_state(sig_model_element_state_t *p_elem)
217 {
218     uint8_t *p_read = NULL;
219 
220     if (p_elem->state.lightness[TYPE_PRESENT] != 0) {
221         p_elem->powerup.last_lightness = p_elem->state.lightness[TYPE_PRESENT];
222         light_powerup[p_elem->element_id].last_lightness = p_elem->state.lightness[TYPE_PRESENT];
223     }
224 
225     p_elem->powerup.last_color_temperature = p_elem->state.color_temperature[TYPE_PRESENT];
226     light_powerup[p_elem->element_id].last_color_temperature = p_elem->state.color_temperature[TYPE_PRESENT];
227     // always on
228     p_elem->powerup.last_onoff = p_elem->state.onoff[TYPE_PRESENT];
229     light_powerup[p_elem->element_id].last_onoff = p_elem->state.onoff[TYPE_PRESENT];
230 
231     p_read = aos_malloc(sizeof(light_powerup));
232     if (!p_read) {
233         GENIE_LOG_WARN("no mem");
234         return;
235     }
236 
237     genie_storage_read_userdata(GFI_MESH_POWERUP, p_read, sizeof(light_powerup));
238 
239     if (memcmp(light_powerup, p_read, sizeof(light_powerup))) {
240         LIGHT_DBG("save %d %d %d", light_powerup[0].last_onoff, light_powerup[0].last_lightness,
241                   light_powerup[0].last_color_temperature);
242         genie_storage_write_userdata(GFI_MESH_POWERUP, (uint8_t *)light_powerup, sizeof(light_powerup));
243     }
244 
245     aos_free(p_read);
246 #ifdef CONFIG_GENIE_OTA
247     if (light_powerup[0].last_onoff == 0 && genie_ota_is_ready() == 1) {
248         // Means have ota, wait for reboot while light off
249         GENIE_LOG_INFO("reboot by ota");
250         aos_reboot();
251     }
252 #endif
253 }
254 
light_update(sig_model_element_state_t * p_elem)255 static void light_update(sig_model_element_state_t *p_elem)
256 {
257     static uint8_t last_onoff = 0;
258     static uint16_t last_lightness = 0;
259     static uint16_t last_temperature = 0;
260 
261     uint8_t onoff = p_elem->state.onoff[TYPE_PRESENT];
262     uint16_t lightness = p_elem->state.lightness[TYPE_PRESENT];
263     uint16_t temperature = p_elem->state.color_temperature[TYPE_PRESENT];
264 
265     if (last_onoff != onoff || last_lightness != lightness || last_temperature != temperature) {
266         last_onoff = onoff;
267         last_lightness = lightness;
268         last_temperature = temperature;
269         // LIGHT_DBG("%d,%d,%d", onoff, lightness, temperature);
270         // light_driver_update(onoff, lightness, temperature);
271     }
272 }
273 
_cal_flash_next_step(uint32_t delta_time)274 void _cal_flash_next_step(uint32_t delta_time)
275 {
276     uint16_t lightness_end;
277 
278     if (delta_time < 1000) {
279         lightness_end = light_param.target_lightness;
280         light_param.present_color_temperature = light_param.target_color_temperature;
281     } else {
282         lightness_end = light_param.lightness_start;
283         delta_time %= 1000;
284     }
285 
286     if (delta_time > LED_BLINK_ON_TIME) {
287         delta_time -= LED_BLINK_ON_TIME;
288         light_param.present_lightness = light_param.lightness_start * delta_time / LED_BLINK_OFF_TIME;
289     } else {
290         light_param.present_lightness = lightness_end * (LED_BLINK_ON_TIME - delta_time) / LED_BLINK_ON_TIME;
291     }
292     // LIGHT_DBG("delta %d, lightness %04x", delta_time, light_param.present_lightness);
293 }
294 
_led_blink_timer_cb(void * p_timer,void * p_arg)295 static void _led_blink_timer_cb(void *p_timer, void *p_arg)
296 {
297     uint32_t cur_time = k_uptime_get();
298 
299     if (cur_time >= light_param.color_temperature_end) {
300         // light_driver_update(1, light_param.target_lightness, light_param.target_color_temperature);
301     } else {
302         _cal_flash_next_step(light_param.color_temperature_end - cur_time);
303         // light_driver_update(1, light_param.present_lightness, light_param.present_color_temperature);
304         k_timer_start(&light_param.led_blink_timer, SIG_MODEL_TRANSITION_INTERVAL);
305     }
306 }
307 
light_led_blink(uint8_t times,uint8_t reset)308 static void light_led_blink(uint8_t times, uint8_t reset)
309 {
310     if (light_elem_stat[0].state.onoff[TYPE_PRESENT] == 1) {
311         if (light_elem_stat[0].state.lightness[TYPE_PRESENT]) {
312             light_param.lightness_start = light_param.present_lightness =
313                 light_elem_stat[0].state.lightness[TYPE_PRESENT];
314         } else {
315             light_param.lightness_start = light_param.present_lightness = LIGHTNESS_DEFAULT;
316         }
317 
318         if (light_elem_stat[0].state.color_temperature[TYPE_PRESENT]) {
319             light_param.present_color_temperature = light_elem_stat[0].state.color_temperature[TYPE_PRESENT];
320         } else {
321             light_param.present_color_temperature = COLOR_TEMPERATURE_DEFAULT;
322         }
323 
324         if (reset) {
325             light_param.target_lightness = LIGHTNESS_DEFAULT;
326             light_param.target_color_temperature = COLOR_TEMPERATURE_DEFAULT;
327         } else {
328             light_param.target_lightness = light_param.present_lightness;
329             light_param.target_color_temperature = light_param.present_color_temperature;
330         }
331 
332         light_param.color_temperature_end = k_uptime_get() + times * LED_BLINK_PERIOD;
333     } else {
334         if (light_elem_stat[0].powerup.last_lightness && !reset) {
335             light_param.lightness_start = light_param.target_lightness = light_elem_stat[0].powerup.last_lightness;
336         } else {
337             light_param.lightness_start = light_param.target_lightness = LIGHTNESS_DEFAULT;
338         }
339 
340         light_param.present_lightness = 0;
341         if (light_elem_stat[0].powerup.last_color_temperature) {
342             light_param.present_color_temperature = light_elem_stat[0].powerup.last_color_temperature;
343         } else {
344             light_param.present_color_temperature = COLOR_TEMPERATURE_DEFAULT;
345         }
346 
347         if (reset) {
348             light_param.target_color_temperature = COLOR_TEMPERATURE_DEFAULT;
349         } else {
350             light_param.target_color_temperature = light_param.present_color_temperature;
351         }
352 
353         light_param.color_temperature_end = k_uptime_get() + times * LED_BLINK_PERIOD - LED_BLINK_OFF_TIME;
354     }
355     // LIGHT_DBG("%d (%d-%d) tar %04x", times, k_uptime_get(), light_param.color_temperature_end, light_param.target_lightness);
356 
357     k_timer_start(&light_param.led_blink_timer, SIG_MODEL_TRANSITION_INTERVAL);
358 }
359 
light_report_poweron_state(sig_model_element_state_t * p_elem)360 static void light_report_poweron_state(sig_model_element_state_t *p_elem)
361 {
362     uint16_t index = 0;
363     uint8_t payload[20];
364     genie_transport_payload_param_t transport_payload_param;
365 
366 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
367     payload[index++] = ATTR_TYPE_GENERIC_ONOFF & 0xff;
368     payload[index++] = (ATTR_TYPE_GENERIC_ONOFF >> 8) & 0xff;
369     payload[index++] = p_elem->state.onoff[TYPE_TARGET];
370 #endif
371 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
372     payload[index++] = ATTR_TYPE_LIGHTNESS & 0xff;
373     payload[index++] = (ATTR_TYPE_LIGHTNESS >> 8) & 0xff;
374     payload[index++] = p_elem->state.lightness[TYPE_TARGET] & 0xff;
375     payload[index++] = (p_elem->state.lightness[TYPE_TARGET] >> 8) & 0xff;
376 #endif
377 #ifdef CONFIG_MESH_MODEL_CTL_SRV
378     payload[index++] = ATTR_TYPE_COLOR_TEMPERATURE & 0xff;
379     payload[index++] = (ATTR_TYPE_COLOR_TEMPERATURE >> 8) & 0xff;
380     payload[index++] = p_elem->state.color_temperature[TYPE_TARGET] & 0xff;
381     payload[index++] = (p_elem->state.color_temperature[TYPE_TARGET] >> 8) & 0xff;
382 #endif
383 #ifdef CONFIG_MESH_MODEL_SCENE_SRV
384     payload[index++] = ATTR_TYPE_SENCE & 0xff;
385     payload[index++] = (ATTR_TYPE_SENCE >> 8) & 0xff;
386     payload[index++] = p_elem->state.scene[TYPE_TARGET] & 0xff;
387     payload[index++] = (p_elem->state.scene[TYPE_TARGET] >> 8) & 0xff;
388 #endif
389 
390     memset(&transport_payload_param, 0, sizeof(genie_transport_payload_param_t));
391     transport_payload_param.opid = VENDOR_OP_ATTR_INDICATE;
392     transport_payload_param.p_payload = payload;
393     transport_payload_param.payload_len = index;
394     transport_payload_param.retry_cnt = GENIE_TRANSPORT_DEFAULT_RETRY_COUNT;
395 
396     genie_transport_send_payload(&transport_payload_param);
397 }
398 
light_ctl_event_handler(genie_event_e event,void * p_arg)399 static void light_ctl_event_handler(genie_event_e event, void *p_arg)
400 {
401     switch (event) {
402     case GENIE_EVT_SW_RESET: {
403         light_param_reset();
404         // light_led_blink(3, 1);
405     } break;
406     case GENIE_EVT_MESH_READY: {
407         // User can report data to cloud at here
408         GENIE_LOG_INFO("User report data\n");
409         light_report_poweron_state(&light_elem_stat[0]);
410     } break;
411     case GENIE_EVT_SDK_MESH_PROV_SUCCESS: {
412         GENIE_LOG_INFO("Mesh Prov success\n");
413         light_blink();
414         // light_led_blink(3, 0);
415     } break;
416 #ifdef CONFIG_MESH_MODEL_TRANS
417     case GENIE_EVT_USER_TRANS_CYCLE:
418 #endif
419     case GENIE_EVT_USER_ACTION_DONE: {
420         sig_model_element_state_t *p_elem = (sig_model_element_state_t *)p_arg;
421         light_update(p_elem);
422         if (event == GENIE_EVT_USER_ACTION_DONE) {
423             light_save_state(p_elem);
424         }
425     } break;
426     case GENIE_EVT_SIG_MODEL_MSG: {
427         sig_model_msg *p_msg = (sig_model_msg *)p_arg;
428 
429         if (p_msg) {
430             GENIE_LOG_INFO("SIG mesg ElemID(%d) in %s\n", p_msg->element_id, __func__);
431             if (p_msg->opcode == 0x8202) {
432                 if (p_msg->data[0] == 0x00) {
433                     light_set(0);
434                     GENIE_LOG_INFO("rec SIG mesg: turn off cmd in ElemID(%d)\n", p_msg->element_id);
435                 } else if (p_msg->data[0] == 0x01) {
436                     light_set(1);
437                     GENIE_LOG_INFO("rec SIG mesg: turn on cmd in ElemID(%d)\n", p_msg->element_id);
438                 }
439             }
440         }
441     } break;
442     case GENIE_EVT_VENDOR_MODEL_MSG: {
443         genie_transport_model_param_t *p_msg = (genie_transport_model_param_t *)p_arg;
444 
445         if (p_msg && p_msg->p_model && p_msg->p_model->user_data) {
446             sig_model_element_state_t *p_elem_state = (sig_model_element_state_t *)p_msg->p_model->user_data;
447             GENIE_LOG_INFO("ElemID(%d) TID(%02X)\n", p_elem_state->element_id, p_msg->tid);
448             (void)p_elem_state;
449         }
450     } break;
451 #ifdef CONIFG_GENIE_MESH_USER_CMD
452     case GENIE_EVT_DOWN_MSG: {
453         genie_down_msg_t *p_msg = (genie_down_msg_t *)p_arg;
454         // User handle this msg,such as send to MCU
455         // if (p_msg) {
456         // }
457     } break;
458 #endif
459 #ifdef MESH_MODEL_VENDOR_TIMER
460     case GENIE_EVT_TIMEOUT: {
461         vendor_attr_data_t *pdata = (vendor_attr_data_t *)p_arg;
462         // User handle vendor timeout event at here
463         if (pdata) {
464             light_ctl_handle_order_msg(pdata);
465         }
466     } break;
467 #endif
468     default:
469         break;
470     }
471 }
472 
473 #ifdef CONFIG_PM_SLEEP
light_ctl_lpm_cb(genie_lpm_wakeup_reason_e reason,genie_lpm_status_e status,void * args)474 static void light_ctl_lpm_cb(genie_lpm_wakeup_reason_e reason, genie_lpm_status_e status, void *args)
475 {
476     if (status == STATUS_WAKEUP) {
477         GENIE_LOG_INFO("wakeup by %s", (reason == WAKEUP_BY_IO) ? "io" : "timer");
478     } else {
479         GENIE_LOG_INFO("sleep");
480     }
481 }
482 #endif
483 
light_init(void)484 static void light_init(void)
485 {
486     light_driver_init();
487     light_set(0);
488     light_elem_state_init();
489     k_timer_init(&light_param.led_blink_timer, _led_blink_timer_cb, NULL);
490 }
491 
application_start(int argc,char ** argv)492 int application_start(int argc, char **argv)
493 {
494     genie_service_ctx_t context;
495 
496     aos_set_log_level(LOG_INFO);
497 
498     GENIE_LOG_INFO("BTIME:%s\n", __DATE__ "," __TIME__);
499     printf("enter %s:%d\n", __func__, __LINE__);
500 
501     light_init();
502 
503     memset(&context, 0, sizeof(genie_service_ctx_t));
504     context.prov_timeout = MESH_PBADV_TIME;
505     context.event_cb = light_ctl_event_handler;
506     context.p_mesh_elem = light_elements;
507     context.mesh_elem_counts = sizeof(light_elements) / sizeof(struct bt_mesh_elem);
508 
509 #ifdef CONFIG_PM_SLEEP
510     context.lpm_conf.is_auto_enable = 1;
511     context.lpm_conf.lpm_wakeup_io = 14;
512 
513     context.lpm_conf.genie_lpm_cb = light_ctl_lpm_cb;
514 
515     // User can config sleep time and wakeup time when not config GLP
516     context.lpm_conf.sleep_ms = 1000;
517     context.lpm_conf.wakeup_ms = 30;
518 #endif
519 
520     genie_service_init(&context);
521 
522 #ifdef CONFIG_BT_MESH_SHELL
523     extern void cli_reg_cmd_blemesh(void);
524     cli_reg_cmd_blemesh();
525 #endif
526 
527     // aos_loop_run();
528 
529     return 0;
530 }
531