Sandwich IoT
Published © GPL3+

Prototype a Smart Mirror-Tuya Developer

A morning routine can be enhanced with an impressive smart mirror that is ready to feed you whatever information you need at a glance as you

BeginnerFull instructions provided8 hours309
Prototype a Smart Mirror-Tuya Developer

Things used in this project

Hardware components

Tuya's Wi-Fi and Bluetooth LE combo module
×1
PCB assembly
×1
LED driver
×1
LED bead
×1
Touchpad
×1
Screen
×1
Spring
×1
XH connector wire
×1
XH connector wire
×1
XH connector wire
×1
XH connector wire
×1
Lithium battery
×1
Wireless charging transmitter and receive
×1
Structural channel made by laser engraving
×1
Structural channel made by 3D printing
×1
Flat-head self-tapping screw
×1
Flat-head self-tapping screw
×1
Jumper wire
×1
PIR sensor
×1

Story

Read more

Code

Code snippet #11

Plain text
VOID dev_obj_dp_cb(IN CONST TY_RECV_OBJ_DP_S *dp)
{
    PR_DEBUG("dp->cid:%s dp->dps_cnt:%d",dp->cid,dp->dps_cnt);
    UCHAR_T i = 0;

    for(i = 0;i < dp->dps_cnt;i++) {
        deal_dp_proc(&(dp->dps[i]));
        dev_report_dp_json_async(get_gw_cntl()->gw_if.id, dp->dps, dp->dps_cnt);
    }
}

VOID hw_report_all_dp_status(VOID)
{
    app_report_all_dp_status();
}

STATIC VOID dev_dp_query_cb(IN CONST TY_DP_QUERY_S *dp_qry) 
{
    PR_NOTICE("Recv DP Query Cmd");

    hw_report_all_dp_status();
}

Code snippet #12

Plain text
VOID dev_obj_dp_cb(IN CONST TY_RECV_OBJ_DP_S *dp)
{
    PR_DEBUG("dp->cid:%s dp->dps_cnt:%d",dp->cid,dp->dps_cnt);
    UCHAR_T i = 0;

    for(i = 0;i < dp->dps_cnt;i++) {
        deal_dp_proc(&(dp->dps[i]));
        dev_report_dp_json_async(get_gw_cntl()->gw_if.id, dp->dps, dp->dps_cnt);
    }
}

VOID hw_report_all_dp_status(VOID)
{
    app_report_all_dp_status();
}

STATIC VOID dev_dp_query_cb(IN CONST TY_DP_QUERY_S *dp_qry) 
{
    PR_NOTICE("Recv DP Query Cmd");

    hw_report_all_dp_status();
}

Code snippet #13

Plain text
├── src	
|    ├── mirror_driver
|    |    ├── tuya_mirror_pwm.c             // PWM driver
|    |    ├── tuya_mirror_key.c             // Code for touch keys
|    |    └── tuya_mirror_screen.c            // Code for the display
|    ├── mirror_soc                   // Code for interfaces of the SoC
|    ├── tuya_device.c             // Entry file of the application layer
|    ├── tuya_app.c            // Main application
|    ├── svc_weather_service.c   // Weather service components (not public-facing now)
|    └── tuya_mirror_control.c             // Logic for device features
| 
├── include  			  // Header file directory
|    ├── mirror_driver
|    |    ├── tuya_mirror_pwm.h      
|    |    ├── tuya_mirror_key.h   
|    |    └── tuya_mirror_screen.h         
|    ├── mirror_soc
|    ├── tuya_device.h
|    ├── tuya_app.h
|    ├── svc_weather_service.h
|    └── tuya_mirror_control.h
|
└── output                  // Compiled files

Code snippet #14

Plain text
├── src	
|    ├── mirror_driver
|    |    ├── tuya_mirror_pwm.c             // PWM driver
|    |    ├── tuya_mirror_key.c             // Code for touch keys
|    |    └── tuya_mirror_screen.c            // Code for the display
|    ├── mirror_soc                   // Code for interfaces of the SoC
|    ├── tuya_device.c             // Entry file of the application layer
|    ├── tuya_app.c            // Main application
|    ├── svc_weather_service.c   // Weather service components (not public-facing now)
|    └── tuya_mirror_control.c             // Logic for device features
| 
├── include  			  // Header file directory
|    ├── mirror_driver
|    |    ├── tuya_mirror_pwm.h      
|    |    ├── tuya_mirror_key.h   
|    |    └── tuya_mirror_screen.h         
|    ├── mirror_soc
|    ├── tuya_device.h
|    ├── tuya_app.h
|    ├── svc_weather_service.h
|    └── tuya_mirror_control.h
|
└── output                  // Compiled files

Code snippet #15

Plain text
OPERATE_RET device_init(VOID_T) 
{
  OPERATE_RET op_ret = OPRT_OK;

  TY_IOT_CBS_S wf_cbs = {
      status_changed_cb,\
      gw_ug_inform_cb,\
      gw_reset_cb,\
      dev_obj_dp_cb,\
      dev_raw_dp_cb,\
      dev_dp_query_cb,\
      NULL,
  };

  op_ret = tuya_iot_wf_soc_dev_init_param(WIFI_WORK_MODE_SEL, WF_START_SMART_ONLY, &wf_cbs, NULL, PRODECT_ID, DEV_SW_VERSION);
  if(OPRT_OK != op_ret) {
      PR_ERR("tuya_iot_wf_soc_dev_init_param error,err_num:%d",op_ret);
      return op_ret;
  }

  op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
  if(OPRT_OK != op_ret) {
      PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
      return op_ret;
  }

  op_ret = app_mirror_init(APP_MIRROR_NORMAL);
  if(OPRT_OK != op_ret) {
      PR_ERR("app init err!");
      return op_ret;
  }
  
  return op_ret;
}

Code snippet #16

Plain text
OPERATE_RET device_init(VOID_T) 
{
  OPERATE_RET op_ret = OPRT_OK;

  TY_IOT_CBS_S wf_cbs = {
      status_changed_cb,\
      gw_ug_inform_cb,\
      gw_reset_cb,\
      dev_obj_dp_cb,\
      dev_raw_dp_cb,\
      dev_dp_query_cb,\
      NULL,
  };

  op_ret = tuya_iot_wf_soc_dev_init_param(WIFI_WORK_MODE_SEL, WF_START_SMART_ONLY, &wf_cbs, NULL, PRODECT_ID, DEV_SW_VERSION);
  if(OPRT_OK != op_ret) {
      PR_ERR("tuya_iot_wf_soc_dev_init_param error,err_num:%d",op_ret);
      return op_ret;
  }

  op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
  if(OPRT_OK != op_ret) {
      PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
      return op_ret;
  }

  op_ret = app_mirror_init(APP_MIRROR_NORMAL);
  if(OPRT_OK != op_ret) {
      PR_ERR("app init err!");
      return op_ret;
  }
  
  return op_ret;
}

Code snippet #17

Plain text
    TY_IOT_CBS_S wf_cbs = {
        status_changed_cb,\
        gw_ug_inform_cb,\
        gw_reset_cb,\
        dev_obj_dp_cb,\
        dev_raw_dp_cb,\
        dev_dp_query_cb,\
        NULL,
    };

    op_ret = tuya_iot_wf_soc_dev_init_param(WIFI_WORK_MODE_SEL, WF_START_SMART_FIRST, &wf_cbs, NULL, PRODECT_ID, DEV_SW_VERSION);
    if(OPRT_OK != op_ret) {
        PR_ERR("tuya_iot_wf_soc_dev_init_param error,err_num:%d",op_ret);
        return op_ret;
    }

Code snippet #18

Plain text
    TY_IOT_CBS_S wf_cbs = {
        status_changed_cb,\
        gw_ug_inform_cb,\
        gw_reset_cb,\
        dev_obj_dp_cb,\
        dev_raw_dp_cb,\
        dev_dp_query_cb,\
        NULL,
    };

    op_ret = tuya_iot_wf_soc_dev_init_param(WIFI_WORK_MODE_SEL, WF_START_SMART_FIRST, &wf_cbs, NULL, PRODECT_ID, DEV_SW_VERSION);
    if(OPRT_OK != op_ret) {
        PR_ERR("tuya_iot_wf_soc_dev_init_param error,err_num:%d",op_ret);
        return op_ret;
    }

Code snippet #19

Plain text
    op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
    if(OPRT_OK != op_ret) {
        PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
        return op_ret;
    }

Code snippet #20

Plain text
    op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
    if(OPRT_OK != op_ret) {
        PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
        return op_ret;
    }

Code snippet #3

Plain text
├── src	
|    └── tuya_device.c            // Entry file of application layer
|
├── include  			  // Header file directory
|    └──  tuya_device.h
|
└── output                  // Compiled files

Code snippet #21

Plain text
    op_ret = app_mirror_init(APP_MIRROR_NORMAL);
    if(OPRT_OK != op_ret) {
        PR_ERR("app init err!");
        return op_ret;
    }

Code snippet #22

Plain text
    op_ret = app_mirror_init(APP_MIRROR_NORMAL);
    if(OPRT_OK != op_ret) {
        PR_ERR("app init err!");
        return op_ret;
    }

Code snippet #23

Plain text
OPERATE_RET app_mirror_init(IN APP_MIRROR_MODE mode)
{
   OPERATE_RET op_ret = OPRT_OK;

   if(APP_MIRROR_NORMAL == mode) {
       
       UCHAR_T read_buff[SAVE_DATA_LEN] = {0};
       uiSocFlashRead(APP_DATA_SAVE,APP_DATA_SAVE_OFFSET,SAVE_DATA_LEN,read_buff);
       mirror_data_load(read_buff);

       UCHAR_T i = 0;
       for(i = 0;i < SAVE_DATA_LEN;i++){
           PR_NOTICE("------- readbuff = %d -----",read_buff[i]);
       }

       mirror_device_init();

       tuya_hal_thread_create(NULL, "thread_data_get", 512*8, TRD_PRIO_4, sensor_data_get_thread, NULL);

       tuya_hal_thread_create(NULL, "thread_data_deal", 512*4, TRD_PRIO_4, sensor_data_deal_thread, NULL);

       tuya_hal_thread_create(NULL, "key_scan_thread", 512*4, TRD_PRIO_3, key_scan_thread, NULL);

       tuya_hal_thread_create(NULL, "diplay_send_thread", 512*4, TRD_PRIO_3, diplay_send_thread, NULL);

   }else {
       //not factory test mode
   }

   return op_ret;
}

Code snippet #24

Plain text
OPERATE_RET app_mirror_init(IN APP_MIRROR_MODE mode)
{
   OPERATE_RET op_ret = OPRT_OK;

   if(APP_MIRROR_NORMAL == mode) {
       
       UCHAR_T read_buff[SAVE_DATA_LEN] = {0};
       uiSocFlashRead(APP_DATA_SAVE,APP_DATA_SAVE_OFFSET,SAVE_DATA_LEN,read_buff);
       mirror_data_load(read_buff);

       UCHAR_T i = 0;
       for(i = 0;i < SAVE_DATA_LEN;i++){
           PR_NOTICE("------- readbuff = %d -----",read_buff[i]);
       }

       mirror_device_init();

       tuya_hal_thread_create(NULL, "thread_data_get", 512*8, TRD_PRIO_4, sensor_data_get_thread, NULL);

       tuya_hal_thread_create(NULL, "thread_data_deal", 512*4, TRD_PRIO_4, sensor_data_deal_thread, NULL);

       tuya_hal_thread_create(NULL, "key_scan_thread", 512*4, TRD_PRIO_3, key_scan_thread, NULL);

       tuya_hal_thread_create(NULL, "diplay_send_thread", 512*4, TRD_PRIO_3, diplay_send_thread, NULL);

   }else {
       //not factory test mode
   }

   return op_ret;
}

Code snippet #25

Plain text
#define TASKDELAY_SEC         1000

STATIC VOID sensor_data_get_thread(PVOID_T pArg)
{   
   while(1) {

       mirror_data_get_handle();

       tuya_hal_system_sleep(TASKDELAY_SEC);
   }
}

STATIC VOID diplay_send_thread(PVOID_T pArg)
{     
   while(1) {

       tuya_hal_system_sleep(TASKDELAY_SEC/2);

       mirror_display_poll();
   }
}

STATIC VOID key_scan_thread(PVOID_T pArg)
{   
   while(1) {

       mirror_key_poll();
      
       tuya_hal_system_sleep(25);       
   }
}

STATIC VOID sensor_data_deal_thread(PVOID_T pArg)
{   
   while(1) {
       
       tuya_hal_system_sleep(TASKDELAY_SEC/2);

       if(mirror_ctrl_data.Wifi_state == connecting)
       {
           mirror_wifi_light_handle();
       }else {

           mirror_ctrl_handle();
       }
   }
}

Code snippet #26

Plain text
#define TASKDELAY_SEC         1000

STATIC VOID sensor_data_get_thread(PVOID_T pArg)
{   
   while(1) {

       mirror_data_get_handle();

       tuya_hal_system_sleep(TASKDELAY_SEC);
   }
}

STATIC VOID diplay_send_thread(PVOID_T pArg)
{     
   while(1) {

       tuya_hal_system_sleep(TASKDELAY_SEC/2);

       mirror_display_poll();
   }
}

STATIC VOID key_scan_thread(PVOID_T pArg)
{   
   while(1) {

       mirror_key_poll();
      
       tuya_hal_system_sleep(25);       
   }
}

STATIC VOID sensor_data_deal_thread(PVOID_T pArg)
{   
   while(1) {
       
       tuya_hal_system_sleep(TASKDELAY_SEC/2);

       if(mirror_ctrl_data.Wifi_state == connecting)
       {
           mirror_wifi_light_handle();
       }else {

           mirror_ctrl_handle();
       }
   }
}

Code snippet #27

Plain text
void app_key_scan(unsigned char *trg,unsigned char *cont)
{
    unsigned char read_data;
    
    if(KEY_RELEAS_LEVEL) {
        read_data = 0x0F;
    }else {
        read_data = 0x00; 
    }

    read_data = (tuya_gpio_read(KEY_SWITCH_PIN)<<3)|(tuya_gpio_read(KEY_SET_PIN)<<2)|(tuya_gpio_read(KEY_UP_PIN)<<1)|(tuya_gpio_read(KEY_DOWN_PIN));
    *trg = (read_data & (read_data ^ (*cont)));
    *cont = read_data;
}

Code snippet #28

Plain text
void app_key_scan(unsigned char *trg,unsigned char *cont)
{
    unsigned char read_data;
    
    if(KEY_RELEAS_LEVEL) {
        read_data = 0x0F;
    }else {
        read_data = 0x00; 
    }

    read_data = (tuya_gpio_read(KEY_SWITCH_PIN)<<3)|(tuya_gpio_read(KEY_SET_PIN)<<2)|(tuya_gpio_read(KEY_UP_PIN)<<1)|(tuya_gpio_read(KEY_DOWN_PIN));
    *trg = (read_data & (read_data ^ (*cont)));
    *cont = read_data;
}

Code snippet #29

Plain text
VOID mirror_key_poll(VOID)
{
   MIRROR_CTRL_DATA_T *p;

   p = &mirror_ctrl_data;

   app_key_scan(&key_trg,&key_cont);
   
   switch (key_cont)
   {
   case KEY_CODE_RELEASE:

       if(key_buf != 0) {

           mirror_key_event(key_buf);
       }

       key_buf = 0;
       key_old = KEY_CODE_RELEASE;

       break;
   case KEY_CODE_SWITCH:

       vTaskDelay(10);
       app_key_scan(&key_trg,&key_cont);

       if(key_cont == KEY_CODE_SWITCH) {

           key_buf = KEY_CODE_SWITCH;
       }

       key_old = KEY_CODE_SWITCH;

       break;
   case KEY_CODE_SET_LIGHT_COLOR:

       if(key_old == KEY_CODE_SET_LIGHT_COLOR) {

           key_delay_cont++;
       }else{

           key_delay_cont = 0;
       }

       if(key_delay_cont >= 2) {

           key_buf = KEY_CODE_SET_LIGHT_COLOR;
       }

       if(key_delay_cont >= 200) {

           key_buf = 0;
           key_delay_cont = 0;
           tuya_iot_wf_gw_unactive();

           // start connect;
       }

       key_old = KEY_CODE_SET_LIGHT_COLOR;

       break;
   case KEY_CODE_UP:

       if(p->Mirror_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(p->Light_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(key_old == KEY_CODE_UP) {

           key_delay_cont++;
       }else{

           key_delay_cont = 0;
       }

       if(key_delay_cont >= 2) {

           key_buf = KEY_CODE_UP;
       }

       if(key_delay_cont >= 40) {

           key_buf = 0;

           if(p->Light_value <= 995) {

               p->Light_value += 10;

               mirror_pwm_set(p->Light_mode,p->Light_value);
           }
       }
       
       key_old = KEY_CODE_UP;
       break;
   case KEY_CODE_DOWN:

       if(p->Mirror_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(p->Light_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(key_old == KEY_CODE_DOWN) {

           key_delay_cont++;
       }else{

           key_delay_cont = 0;
       }

       if(key_delay_cont >= 2) {

           key_buf = KEY_CODE_DOWN;
       }

       if(key_delay_cont >= 40) {

           key_buf = 0;

           if(p->Light_value>=205) {

               p->Light_value -= 10;

               mirror_pwm_set(p->Light_mode,p->Light_value);
           } 
       }
       
       key_old = KEY_CODE_DOWN;        
       break;          
   default:
       break;
   }

}

Code snippet #30

Plain text
VOID mirror_key_poll(VOID)
{
   MIRROR_CTRL_DATA_T *p;

   p = &mirror_ctrl_data;

   app_key_scan(&key_trg,&key_cont);
   
   switch (key_cont)
   {
   case KEY_CODE_RELEASE:

       if(key_buf != 0) {

           mirror_key_event(key_buf);
       }

       key_buf = 0;
       key_old = KEY_CODE_RELEASE;

       break;
   case KEY_CODE_SWITCH:

       vTaskDelay(10);
       app_key_scan(&key_trg,&key_cont);

       if(key_cont == KEY_CODE_SWITCH) {

           key_buf = KEY_CODE_SWITCH;
       }

       key_old = KEY_CODE_SWITCH;

       break;
   case KEY_CODE_SET_LIGHT_COLOR:

       if(key_old == KEY_CODE_SET_LIGHT_COLOR) {

           key_delay_cont++;
       }else{

           key_delay_cont = 0;
       }

       if(key_delay_cont >= 2) {

           key_buf = KEY_CODE_SET_LIGHT_COLOR;
       }

       if(key_delay_cont >= 200) {

           key_buf = 0;
           key_delay_cont = 0;
           tuya_iot_wf_gw_unactive();

           // start connect;
       }

       key_old = KEY_CODE_SET_LIGHT_COLOR;

       break;
   case KEY_CODE_UP:

       if(p->Mirror_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(p->Light_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(key_old == KEY_CODE_UP) {

           key_delay_cont++;
       }else{

           key_delay_cont = 0;
       }

       if(key_delay_cont >= 2) {

           key_buf = KEY_CODE_UP;
       }

       if(key_delay_cont >= 40) {

           key_buf = 0;

           if(p->Light_value <= 995) {

               p->Light_value += 10;

               mirror_pwm_set(p->Light_mode,p->Light_value);
           }
       }
       
       key_old = KEY_CODE_UP;
       break;
   case KEY_CODE_DOWN:

       if(p->Mirror_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(p->Light_switch == FALSE) {

           key_buf = 0;

           return ;
       }

       if(key_old == KEY_CODE_DOWN) {

           key_delay_cont++;
       }else{

           key_delay_cont = 0;
       }

       if(key_delay_cont >= 2) {

           key_buf = KEY_CODE_DOWN;
       }

       if(key_delay_cont >= 40) {

           key_buf = 0;

           if(p->Light_value>=205) {

               p->Light_value -= 10;

               mirror_pwm_set(p->Light_mode,p->Light_value);
           } 
       }
       
       key_old = KEY_CODE_DOWN;        
       break;          
   default:
       break;
   }

}

Code snippet #4

Plain text
├── src	
|    └── tuya_device.c            // Entry file of application layer
|
├── include  			  // Header file directory
|    └──  tuya_device.h
|
└── output                  // Compiled files

Code snippet #31

Plain text
VOID screen_init(VOID);

VOID screen_display_time(INT_T hours, INT_T mins);

VOID screen_display_week(INT_T weeks);

VOID screen_display_year(INT_T year);

VOID screen_display_battery(BATTERY_STATE state);

VOID screen_display_day(INT_T month, INT_T day);

Code snippet #32

Plain text
VOID screen_init(VOID);

VOID screen_display_time(INT_T hours, INT_T mins);

VOID screen_display_week(INT_T weeks);

VOID screen_display_year(INT_T year);

VOID screen_display_battery(BATTERY_STATE state);

VOID screen_display_day(INT_T month, INT_T day);

Code snippet #33

Plain text
UINT8_T *icon_buff[] = {
   /* 0 ~ 9 and ':' */
   "2289100","2290660","2292220","2293780","2295340","2296900","2298460","2300020","2301580","2303140","2305600",

     /* character: 'Month', 'Day', 'Year' (11 to 13) */
   "2312464","2314264","2316064",

     /* character: 'Sunday' to 'Saturday' (14 to 20) */
   "2349832","2317864","2323192","2328520","2333848","2339176","2344504",

   /* '℃' and white block (21~22)*/
   "2386480","2387560",

     /* Icon of condition: sun, rain, and cloud (23 to 25)*/

   "2241228","2249420","2258520",

     /* Character of condition: sun, rain, and cloud (26 to 28)*/
   "2267620","2272380","2277140",

     /* Icon of battery: high, medium, low, and charging (29 to 32)*/
   "2355160","2362990","2370820","2378650",
};

Code snippet #34

Plain text
UINT8_T *icon_buff[] = {
   /* 0 ~ 9 and ':' */
   "2289100","2290660","2292220","2293780","2295340","2296900","2298460","2300020","2301580","2303140","2305600",

     /* character: 'Month', 'Day', 'Year' (11 to 13) */
   "2312464","2314264","2316064",

     /* character: 'Sunday' to 'Saturday' (14 to 20) */
   "2349832","2317864","2323192","2328520","2333848","2339176","2344504",

   /* '℃' and white block (21~22)*/
   "2386480","2387560",

     /* Icon of condition: sun, rain, and cloud (23 to 25)*/

   "2241228","2249420","2258520",

     /* Character of condition: sun, rain, and cloud (26 to 28)*/
   "2267620","2272380","2277140",

     /* Icon of battery: high, medium, low, and charging (29 to 32)*/
   "2355160","2362990","2370820","2378650",
};

Code snippet #35

Plain text
VOID screen_display_week(INT_T weeks)
{
 if((weeks < 0)||(weeks > 6)) {
     return;
 }

 uint8_t data_buff[40] = {0};
 
 snprintf(data_buff,sizeof(data_buff),"FSIMG(%s,280,95,72,37,0);\r\n",icon_buff[weeks+14]);

 tuya_uart_write(uart0, data_buff, strlen(data_buff));
}

Code snippet #36

Plain text
VOID screen_display_week(INT_T weeks)
{
 if((weeks < 0)||(weeks > 6)) {
     return;
 }

 uint8_t data_buff[40] = {0};
 
 snprintf(data_buff,sizeof(data_buff),"FSIMG(%s,280,95,72,37,0);\r\n",icon_buff[weeks+14]);

 tuya_uart_write(uart0, data_buff, strlen(data_buff));
}

Code snippet #37

Plain text
STATIC VOID mirror_date_get(VOID)
{
 if(mirror_ctrl_data.Wifi_state == connecting) {
     
     return;
 }

 POSIX_TM_S cur_time;
 if( uni_local_time_get(&cur_time) != OPRT_OK ) {
     PR_NOTICE("cant get local time");
 }

 mirror_ctrl_data.Mirror_time.sec = (UCHAR_T)cur_time.tm_sec;
 mirror_ctrl_data.Mirror_time.min = (UCHAR_T)cur_time.tm_min;
 mirror_ctrl_data.Mirror_time.hour = (UCHAR_T)cur_time.tm_hour;

 if(mirror_ctrl_data.Mirror_time.year != cur_time.tm_year) {

     mirror_ctrl_data.Mirror_time.year = (1900 + cur_time.tm_year);

 }

 if((mirror_ctrl_data.Mirror_time.mon != cur_time.tm_mon)||(mirror_ctrl_data.Mirror_time.mday != cur_time.tm_mday)) {

     mirror_ctrl_data.Mirror_time.mon= (UCHAR_T)cur_time.tm_mon;
     mirror_ctrl_data.Mirror_time.mday = (UCHAR_T)cur_time.tm_mday;

 }

 if(mirror_ctrl_data.Mirror_time.wday != cur_time.tm_wday) {
     mirror_ctrl_data.Mirror_time.wday = (UCHAR_T)cur_time.tm_wday;

 }
}

Code snippet #38

Plain text
STATIC VOID mirror_date_get(VOID)
{
 if(mirror_ctrl_data.Wifi_state == connecting) {
     
     return;
 }

 POSIX_TM_S cur_time;
 if( uni_local_time_get(&cur_time) != OPRT_OK ) {
     PR_NOTICE("cant get local time");
 }

 mirror_ctrl_data.Mirror_time.sec = (UCHAR_T)cur_time.tm_sec;
 mirror_ctrl_data.Mirror_time.min = (UCHAR_T)cur_time.tm_min;
 mirror_ctrl_data.Mirror_time.hour = (UCHAR_T)cur_time.tm_hour;

 if(mirror_ctrl_data.Mirror_time.year != cur_time.tm_year) {

     mirror_ctrl_data.Mirror_time.year = (1900 + cur_time.tm_year);

 }

 if((mirror_ctrl_data.Mirror_time.mon != cur_time.tm_mon)||(mirror_ctrl_data.Mirror_time.mday != cur_time.tm_mday)) {

     mirror_ctrl_data.Mirror_time.mon= (UCHAR_T)cur_time.tm_mon;
     mirror_ctrl_data.Mirror_time.mday = (UCHAR_T)cur_time.tm_mday;

 }

 if(mirror_ctrl_data.Mirror_time.wday != cur_time.tm_wday) {
     mirror_ctrl_data.Mirror_time.wday = (UCHAR_T)cur_time.tm_wday;

 }
}

Code snippet #39

Plain text
OPERATE_RET mirror_pwm_init(VOID);

OPERATE_RET mirror_pwm_set(UCHAR_T color, USHORT_T duty);

OPERATE_RET mirror_pwm_off(VOID);

Code snippet #40

Plain text
OPERATE_RET mirror_pwm_init(VOID);

OPERATE_RET mirror_pwm_set(UCHAR_T color, USHORT_T duty);

OPERATE_RET mirror_pwm_off(VOID);

Code snippet #5

Plain text
├── src	
|    └── tuya_device.c            // Entry file of application layer
|    └── tuya_app.c            // Main application file
|
├── include  			  // Header file directory
|    └──  tuya_device.h
|    └──  tuya_app.h
|
└── output                  // Compiled files

Code snippet #41

Plain text
OPERATE_RET mirror_pwm_set(UCHAR_T color, USHORT_T duty)
{
  FLOAT_T percent = 0.0;

  if(user_pwm_init_flag != TRUE){
      PR_ERR("user pwm not init!");
      return OPRT_INVALID_PARM;
  }

  percent = (FLOAT_T)(duty/1000.0);

  bk_pwm_stop(pChannelList[0]);
  bk_pwm_stop(pChannelList[1]);

  switch (color)
  {
  case 0:
      PR_NOTICE("set light cold");
      bk_pwm_update_param(pChannelList[0], pwm_period, (UINT32)(percent * pwm_period), 0, 0);
      bk_pwm_start(pChannelList[0]);
      break;
  case 1:
      PR_NOTICE("set light medium");
      bk_pwm_update_param(pChannelList[0], pwm_period, (UINT32)((percent * pwm_period)/2), 0, 0);
      bk_pwm_update_param(pChannelList[1], pwm_period, (UINT32)((percent * pwm_period)/2), 0, 0);
      bk_pwm_start(pChannelList[0]);
      bk_pwm_start(pChannelList[1]);
      break;
  case 2:
      PR_NOTICE("set light warm");
      bk_pwm_update_param(pChannelList[1], pwm_period, (UINT32)(percent * pwm_period), 0, 0);
      //bk_pwm_update_param(pChannelList[0], pwm_period, 0, 0, 0);
      bk_pwm_start(pChannelList[1]);
      break;
  default:
      break;
  }

  return OPRT_OK;
}

Code snippet #42

Plain text
OPERATE_RET mirror_pwm_set(UCHAR_T color, USHORT_T duty)
{
  FLOAT_T percent = 0.0;

  if(user_pwm_init_flag != TRUE){
      PR_ERR("user pwm not init!");
      return OPRT_INVALID_PARM;
  }

  percent = (FLOAT_T)(duty/1000.0);

  bk_pwm_stop(pChannelList[0]);
  bk_pwm_stop(pChannelList[1]);

  switch (color)
  {
  case 0:
      PR_NOTICE("set light cold");
      bk_pwm_update_param(pChannelList[0], pwm_period, (UINT32)(percent * pwm_period), 0, 0);
      bk_pwm_start(pChannelList[0]);
      break;
  case 1:
      PR_NOTICE("set light medium");
      bk_pwm_update_param(pChannelList[0], pwm_period, (UINT32)((percent * pwm_period)/2), 0, 0);
      bk_pwm_update_param(pChannelList[1], pwm_period, (UINT32)((percent * pwm_period)/2), 0, 0);
      bk_pwm_start(pChannelList[0]);
      bk_pwm_start(pChannelList[1]);
      break;
  case 2:
      PR_NOTICE("set light warm");
      bk_pwm_update_param(pChannelList[1], pwm_period, (UINT32)(percent * pwm_period), 0, 0);
      //bk_pwm_update_param(pChannelList[0], pwm_period, 0, 0, 0);
      bk_pwm_start(pChannelList[1]);
      break;
  default:
      break;
  }

  return OPRT_OK;
}

Code snippet #43

Plain text
STATIC VOID mirror_pir_detect(VOID)
{    
    if(tuya_gpio_read(PIR_IN_PORT)) {
        PR_NOTICE("-----------SOMEONE HERE-------------");
        mirror_ctrl_data.PIR_state = trigger;
    }
}

VOID mirror_data_get_handle(VOID)
{   
 	......
 	 // Detect PIR I/O port
 	mirror_pir_detect();
}

Code snippet #44

Plain text
STATIC VOID mirror_pir_detect(VOID)
{    
    if(tuya_gpio_read(PIR_IN_PORT)) {
        PR_NOTICE("-----------SOMEONE HERE-------------");
        mirror_ctrl_data.PIR_state = trigger;
    }
}

VOID mirror_data_get_handle(VOID)
{   
 	......
 	 // Detect PIR I/O port
 	mirror_pir_detect();
}

Code snippet #45

Plain text
STATIC VOID sensor_data_get_thread(PVOID_T pArg)
{   
 	 while(1) {
 	
 	     mirror_data_get_handle();
 	
 	     tuya_hal_system_sleep(TASKDELAY_SEC);
 	 }
}

Code snippet #46

Plain text
STATIC VOID sensor_data_get_thread(PVOID_T pArg)
{   
 	 while(1) {
 	
 	     mirror_data_get_handle();
 	
 	     tuya_hal_system_sleep(TASKDELAY_SEC);
 	 }
}

Code snippet #47

Plain text
VOID pir_data_handle(VOID)
{
 MIRROR_CTRL_DATA_T *p;

 p = &mirror_ctrl_data;

 if(p->PIR_state == trigger) {
     p->PIR_state = none;

     if((p->PIR_switch != TRUE)||(p->Mirror_switch != TRUE)) {

         return;
     }

     if(IsThisSysTimerRun(off_timer) == TRUE) {
         sys_stop_timer(off_timer);
         sys_start_timer(off_timer, 1000*600, TIMER_ONCE);
     }else {
         sys_start_timer(off_timer, 1000*600, TIMER_ONCE);
     }

     p->Light_switch = TRUE;

 }
}

Code snippet #48

Plain text
VOID pir_data_handle(VOID)
{
 MIRROR_CTRL_DATA_T *p;

 p = &mirror_ctrl_data;

 if(p->PIR_state == trigger) {
     p->PIR_state = none;

     if((p->PIR_switch != TRUE)||(p->Mirror_switch != TRUE)) {

         return;
     }

     if(IsThisSysTimerRun(off_timer) == TRUE) {
         sys_stop_timer(off_timer);
         sys_start_timer(off_timer, 1000*600, TIMER_ONCE);
     }else {
         sys_start_timer(off_timer, 1000*600, TIMER_ONCE);
     }

     p->Light_switch = TRUE;

 }
}

Code snippet #6

Plain text
├── src	
|    └── tuya_device.c            // Entry file of application layer
|    └── tuya_app.c            // Main application file
|
├── include  			  // Header file directory
|    └──  tuya_device.h
|    └──  tuya_app.h
|
└── output                  // Compiled files

Code snippet #7

Plain text
#ifndef __TUYA_APP_H__
#define __TUYA_APP_H__

#include "uni_log.h"
#include "tuya_cloud_error_code.h"
#include "tuya_cloud_com_defs.h"

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

/***********************************************************
*************************variable define********************
***********************************************************/
typedef enum{
    APP_MIRROR_NORMAL,       // Normal mode
    APP_MIRROR_PRODTEST      // Product test mode
}APP_MIRROR_MODE;

#define DPID_SWITCH                      1
#define DPID_SWITCH_LED                  2
#define DPID_LIGHT_MODE                  4
#define DPID_LIGHT_VALUE                 5
#define DPID_BATTERY_STATUS              101
#define DPID_PIR_MODE                    103
#define DPID_PIR_STATE                   105
/********************************************************************************
* FUNCTION:       app_mirror_init
* DESCRIPTION:    application initialization
* INPUT:          mode:application mode
* OUTPUT:         none
* RETURN:         none
* OTHERS:         none
* HISTORY:        January 12, 2021
*******************************************************************************/
OPERATE_RET app_mirror_init(IN APP_MIRROR_MODE mode);

/********************************************************************************
* FUNCTION:       deal_dp_proc
* DESCRIPTION:    deal the data sented by app
* INPUT:          root:app issued data structure
* OUTPUT:         none
* RETURN:         none
* OTHERS:         none
* HISTORY:        January 12, 2021
*******************************************************************************/
VOID deal_dp_proc(IN CONST TY_OBJ_DP_S *root);

/*********************************************************************************
* FUNCTION:       app_report_all_dp_status
* DESCRIPTION:    report all dp date
* INPUT:          none
* OUTPUT:         none
* RETURN:         none
* OTHERS:         dp_cnt needs to be modified when adding or deleting the dp function
* HISTORY:        January 12, 2021
*****************************************************************************/
VOID app_report_all_dp_status(VOID);

#ifdef __cplusplus
}
#endif /* __cplusplus */


#endif  /* __TUYA_APP_H__*/

Code snippet #8

Plain text
#ifndef __TUYA_APP_H__
#define __TUYA_APP_H__

#include "uni_log.h"
#include "tuya_cloud_error_code.h"
#include "tuya_cloud_com_defs.h"

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

/***********************************************************
*************************variable define********************
***********************************************************/
typedef enum{
    APP_MIRROR_NORMAL,       // Normal mode
    APP_MIRROR_PRODTEST      // Product test mode
}APP_MIRROR_MODE;

#define DPID_SWITCH                      1
#define DPID_SWITCH_LED                  2
#define DPID_LIGHT_MODE                  4
#define DPID_LIGHT_VALUE                 5
#define DPID_BATTERY_STATUS              101
#define DPID_PIR_MODE                    103
#define DPID_PIR_STATE                   105
/********************************************************************************
* FUNCTION:       app_mirror_init
* DESCRIPTION:    application initialization
* INPUT:          mode:application mode
* OUTPUT:         none
* RETURN:         none
* OTHERS:         none
* HISTORY:        January 12, 2021
*******************************************************************************/
OPERATE_RET app_mirror_init(IN APP_MIRROR_MODE mode);

/********************************************************************************
* FUNCTION:       deal_dp_proc
* DESCRIPTION:    deal the data sented by app
* INPUT:          root:app issued data structure
* OUTPUT:         none
* RETURN:         none
* OTHERS:         none
* HISTORY:        January 12, 2021
*******************************************************************************/
VOID deal_dp_proc(IN CONST TY_OBJ_DP_S *root);

/*********************************************************************************
* FUNCTION:       app_report_all_dp_status
* DESCRIPTION:    report all dp date
* INPUT:          none
* OUTPUT:         none
* RETURN:         none
* OTHERS:         dp_cnt needs to be modified when adding or deleting the dp function
* HISTORY:        January 12, 2021
*****************************************************************************/
VOID app_report_all_dp_status(VOID);

#ifdef __cplusplus
}
#endif /* __cplusplus */


#endif  /* __TUYA_APP_H__*/

Code snippet #9

Plain text
// Receive DP data from the cloud and parse the DP ID and data content.
VOID deal_dp_proc(IN CONST TY_OBJ_DP_S *root)
{
    UCHAR_T dpid;

    dpid = root->dpid;
    PR_DEBUG("dpid:%d",dpid);
    
    switch (dpid) {

    case DPID_SWITCH:
    
        // Get the DP content.
        mirror_ctrl_data.Mirror_switch = root->value.dp_bool;
        break;
        
    case DPID_SWITCH_LED:
    
        ......
        break;

    case DPID_LIGHT_MODE:
    
        ......
        break;

    case DPID_LIGHT_VALUE:
    
        ......
        break;

    case DPID_PIR_MODE:
    
        ......
        break;

    default:
        break;
    }
    
    app_report_all_dp_status();

    return;

}

// Report the DP data to the cloud. After the SDK determines the cloud is connected, it reports the data of all DPs.

VOID app_report_all_dp_status(VOID)
{
    OPERATE_RET op_ret = OPRT_OK;

    GW_WIFI_NW_STAT_E wifi_state = 0xFF;

    op_ret = get_wf_gw_nw_status(&wifi_state);
    if (OPRT_OK != op_ret) {
        PR_ERR("get wifi state err");
        return;
    }
    if (wifi_state <= STAT_AP_STA_DISC || wifi_state == STAT_STA_DISC) {
        return;
    }
    
    INT_T dp_cnt = 0;
    dp_cnt = 7;

    if(!mirror_ctrl_data.Wifi_state) {
        return;
    } 

    TY_OBJ_DP_S *dp_arr = (TY_OBJ_DP_S *)Malloc(dp_cnt*SIZEOF(TY_OBJ_DP_S));
    if(NULL == dp_arr) {
        PR_ERR("malloc failed");
        return;
    }

    memset(dp_arr, 0, dp_cnt*SIZEOF(TY_OBJ_DP_S));

    dp_arr[0].dpid = DPID_SWITCH;
    dp_arr[0].type = PROP_BOOL;
    dp_arr[0].time_stamp = 0;
    dp_arr[0].value.dp_value = mirror_ctrl_data.Mirror_switch;

    dp_arr[1].dpid = DPID_SWITCH_LED;
    dp_arr[1].type = PROP_BOOL;
    dp_arr[1].time_stamp = 0;
    dp_arr[1].value.dp_value = mirror_ctrl_data.Light_switch;

    dp_arr[2].dpid = DPID_LIGHT_MODE;
    dp_arr[2].type = PROP_ENUM;
    dp_arr[2].time_stamp = 0;
    dp_arr[2].value.dp_value = mirror_ctrl_data.Light_mode;

    dp_arr[3].dpid = DPID_LIGHT_VALUE;
    dp_arr[3].type = PROP_VALUE;
    dp_arr[3].time_stamp = 0;
    dp_arr[3].value.dp_value = mirror_ctrl_data.Light_value;
    
    dp_arr[4].dpid = DPID_BATTERY_STATUS;
    dp_arr[4].type = PROP_ENUM;
    dp_arr[4].time_stamp = 0;
    dp_arr[4].value.dp_value = mirror_ctrl_data.Battery_remain;

    dp_arr[5].dpid = DPID_PIR_MODE;
    dp_arr[5].type = PROP_BOOL;
    dp_arr[5].time_stamp = 0;
    dp_arr[5].value.dp_value = mirror_ctrl_data.PIR_switch;

    dp_arr[6].dpid = DPID_PIR_STATE;
    dp_arr[6].type = PROP_ENUM;
    dp_arr[6].time_stamp = 0;
    dp_arr[6].value.dp_value = mirror_ctrl_data.PIR_state;

    op_ret = dev_report_dp_json_async(NULL,dp_arr,dp_cnt);
    Free(dp_arr);
    if(OPRT_OK != op_ret) {
        PR_ERR("dev_report_dp_json_async relay_config data error,err_num",op_ret);
    }

    PR_DEBUG("dp_query report_all_dp_data");
    return;
}

Code snippet #10

Plain text
// Receive DP data from the cloud and parse the DP ID and data content.
VOID deal_dp_proc(IN CONST TY_OBJ_DP_S *root)
{
    UCHAR_T dpid;

    dpid = root->dpid;
    PR_DEBUG("dpid:%d",dpid);
    
    switch (dpid) {

    case DPID_SWITCH:
    
        // Get the DP content.
        mirror_ctrl_data.Mirror_switch = root->value.dp_bool;
        break;
        
    case DPID_SWITCH_LED:
    
        ......
        break;

    case DPID_LIGHT_MODE:
    
        ......
        break;

    case DPID_LIGHT_VALUE:
    
        ......
        break;

    case DPID_PIR_MODE:
    
        ......
        break;

    default:
        break;
    }
    
    app_report_all_dp_status();

    return;

}

// Report the DP data to the cloud. After the SDK determines the cloud is connected, it reports the data of all DPs.

VOID app_report_all_dp_status(VOID)
{
    OPERATE_RET op_ret = OPRT_OK;

    GW_WIFI_NW_STAT_E wifi_state = 0xFF;

    op_ret = get_wf_gw_nw_status(&wifi_state);
    if (OPRT_OK != op_ret) {
        PR_ERR("get wifi state err");
        return;
    }
    if (wifi_state <= STAT_AP_STA_DISC || wifi_state == STAT_STA_DISC) {
        return;
    }
    
    INT_T dp_cnt = 0;
    dp_cnt = 7;

    if(!mirror_ctrl_data.Wifi_state) {
        return;
    } 

    TY_OBJ_DP_S *dp_arr = (TY_OBJ_DP_S *)Malloc(dp_cnt*SIZEOF(TY_OBJ_DP_S));
    if(NULL == dp_arr) {
        PR_ERR("malloc failed");
        return;
    }

    memset(dp_arr, 0, dp_cnt*SIZEOF(TY_OBJ_DP_S));

    dp_arr[0].dpid = DPID_SWITCH;
    dp_arr[0].type = PROP_BOOL;
    dp_arr[0].time_stamp = 0;
    dp_arr[0].value.dp_value = mirror_ctrl_data.Mirror_switch;

    dp_arr[1].dpid = DPID_SWITCH_LED;
    dp_arr[1].type = PROP_BOOL;
    dp_arr[1].time_stamp = 0;
    dp_arr[1].value.dp_value = mirror_ctrl_data.Light_switch;

    dp_arr[2].dpid = DPID_LIGHT_MODE;
    dp_arr[2].type = PROP_ENUM;
    dp_arr[2].time_stamp = 0;
    dp_arr[2].value.dp_value = mirror_ctrl_data.Light_mode;

    dp_arr[3].dpid = DPID_LIGHT_VALUE;
    dp_arr[3].type = PROP_VALUE;
    dp_arr[3].time_stamp = 0;
    dp_arr[3].value.dp_value = mirror_ctrl_data.Light_value;
    
    dp_arr[4].dpid = DPID_BATTERY_STATUS;
    dp_arr[4].type = PROP_ENUM;
    dp_arr[4].time_stamp = 0;
    dp_arr[4].value.dp_value = mirror_ctrl_data.Battery_remain;

    dp_arr[5].dpid = DPID_PIR_MODE;
    dp_arr[5].type = PROP_BOOL;
    dp_arr[5].time_stamp = 0;
    dp_arr[5].value.dp_value = mirror_ctrl_data.PIR_switch;

    dp_arr[6].dpid = DPID_PIR_STATE;
    dp_arr[6].type = PROP_ENUM;
    dp_arr[6].time_stamp = 0;
    dp_arr[6].value.dp_value = mirror_ctrl_data.PIR_state;

    op_ret = dev_report_dp_json_async(NULL,dp_arr,dp_cnt);
    Free(dp_arr);
    if(OPRT_OK != op_ret) {
        PR_ERR("dev_report_dp_json_async relay_config data error,err_num",op_ret);
    }

    PR_DEBUG("dp_query report_all_dp_data");
    return;
}

Github

https://github.com/tuya/tuya-iotos-embeded-sdk-wifi-ble-bk7231n

Credits

Sandwich IoT
40 projects • 5 followers

Comments