2667 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2667 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | |
| 
 | |
| This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | |
| be copied by any method or incorporated into another program without
 | |
| the express written consent of Aerospace C.Power. This Information or any portion
 | |
| thereof remains the property of Aerospace C.Power. The Information contained herein
 | |
| is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | |
| liability for its use in any way and conveys no license or title under
 | |
| any patent or copyright and makes no representation or warranty that this
 | |
| Information is free from patent or copyright infringement.
 | |
| 
 | |
| ****************************************************************************/
 | |
| 
 | |
| /* iot common header files */
 | |
| #include "iot_io_api.h"
 | |
| #include "iot_module_api.h"
 | |
| #include "iot_errno_api.h"
 | |
| #include "iot_task_api.h"
 | |
| #include "iot_pkt_api.h"
 | |
| #include "iot_ipc_api.h"
 | |
| #include "iot_sg_ext_api.h"
 | |
| #include "iot_board_api.h"
 | |
| #include "iot_oem_api.h"
 | |
| #include "os_utils_api.h"
 | |
| #include "iot_task_api.h"
 | |
| #include "iot_i2c_api.h"
 | |
| #include "iot_pwm_api.h"
 | |
| #include "iot_gpio_api.h"
 | |
| #include "os_timer_api.h"
 | |
| #include "iot_plc_api.h"
 | |
| #include "iot_grapp.h"
 | |
| #include "iot_proto_ge.h"
 | |
| 
 | |
| #include "iot_light_ctrl_drv.h"
 | |
| #include "iot_proto_common.h"
 | |
| #include "iot_adc_api.h"
 | |
| #include "iot_energe_meter_api.h"
 | |
| #include "iot_version_api.h"
 | |
| #include "iot_ntoh_api.h"
 | |
| 
 | |
| #if IOT_LED_CTRL_APP_ENABLE && PLC_SUPPORT_STA_ROLE
 | |
| 
 | |
| #define IOT_LIGHT_MODULE_ID     IOT_GREE_APP_MID
 | |
| 
 | |
| #if (HW_PLATFORM == HW_PLATFORM_SIMU)
 | |
| #define ENABLE_LED_CTRL_HARDWARE                    (0)
 | |
| #define IOT_LIGHT_CTRL_ADC_MODULE_ENABLE            (0)
 | |
| #else
 | |
| #define ENABLE_LED_CTRL_HARDWARE                    (1)
 | |
| #if IOT_ENERGE_METER_ENABLE
 | |
| #define IOT_LIGHT_CTRL_ADC_MODULE_ENABLE            (1)
 | |
| #else
 | |
| #define IOT_LIGHT_CTRL_ADC_MODULE_ENABLE            (0)
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #define IOT_LED_TIMMING_RELAY_ON_DELAY  50   /* 50ms delay after power up */
 | |
| #define IOT_LED_TIMMING_POWERON_DELAY   1000 /* 1000ms delay after power up */
 | |
| 
 | |
| #define IOT_LIGHT_CURRENT_IN_THRESHOLD_MIN          50  /* 50mA */
 | |
| 
 | |
| /* GPIO config for power_on & relay */
 | |
| #define IOT_LIGHT_GPIO_POWER    28
 | |
| #define IOT_LIGHT_GPIO_RELAY    36
 | |
| 
 | |
| /* PWM output gpio, only A valid */
 | |
| #define IOT_LIGHT_GPIO_PWM_A    23
 | |
| #define IOT_LIGHT_GPIO_PWM_B    255
 | |
| /* PWM channel */
 | |
| #define IOT_LIGHT_PWM_CHANNEL   0
 | |
| #define IOT_LIGHT_PWM_PERIOD    4000 /* unit is 1Hz */
 | |
| 
 | |
| /* when IIC slaver stays in power on/off, the gpio level 0/1 */
 | |
| #define IOT_LIGHT_GPIO_VAL_POWER_ON     1
 | |
| #define IOT_LIGHT_GPIO_VAL_POWER_OFF    0
 | |
| 
 | |
| /* when relay makes led light stays in working/off, the gpio level 0/1 */
 | |
| #define IOT_LIGHT_GPIO_VAL_LED_ON   0
 | |
| #define IOT_LIGHT_GPIO_VAL_LED_OFF  1
 | |
| 
 | |
| /* for new data check logic. */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_SAMPLE_MAX_LEN  6
 | |
| #define IOT_LED_CTRL_DATA_CHECK_DELTA_MAX_LEN   6
 | |
| #define iot_led_drv_get_delta_val(a, b)     \
 | |
|     ((a) > (b) ? ((a) - (b)) : ((b) - (a)))
 | |
| /* this will not over IOT_LED_CTRL_DATA_CHECK_SAMPLE_MAX_LEN && bigger than 2. */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_SAMPLE_LEN_METER    6 /* meter data input */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_SAMPLE_LEN_LEAKAGE  6 /* leakage current */
 | |
| /* this will not over IOT_LED_CTRL_DATA_CHECK_DELTA_MAX_LEN */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_DELTA_LEN_METER     3 /* meter data input */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_DELTA_LEN_LEAKAGE   3 /* leakage current */
 | |
| /* delta value */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_DELTA_VALUE_METER   40000 /* 40V */
 | |
| #define IOT_LED_CTRL_DATA_CHECK_DELTA_VALUE_LEAKAGE 20 /* 20mA */
 | |
| 
 | |
| #if (IOT_PSRAM_ENABLE)
 | |
| /* number of messages pending in queue. */
 | |
| #define IOT_LED_CTRL_TASK_POOL_SIZE         (128)
 | |
| /* stack size of task */
 | |
| #define IOT_LED_CTRL_TASK_STACK_SIZE        1024
 | |
| #else
 | |
| /* number of messages pending in queue. */
 | |
| #define IOT_LED_CTRL_TASK_POOL_SIZE         (64)
 | |
| /* stack size of task */
 | |
| #define IOT_LED_CTRL_TASK_STACK_SIZE        512
 | |
| #endif
 | |
| 
 | |
| /* message type */
 | |
| #define IOT_LED_CTRL_MSG_DATA               (0)
 | |
| #define IOT_LED_CTRL_MSG_TIMER              (1)
 | |
| #define IOT_LED_CTRL_MSG_INTERNAL           (2)
 | |
| 
 | |
| /* message id for IOT_LED_CTRL_MSG_DATA */
 | |
| #define IOT_LED_CTRL_MSG_ID_UART_DATA       (0)
 | |
| #define IOT_LED_CTRL_MSG_ID_PLC_DATA        (1)
 | |
| #define IOT_LED_CTRL_MSG_ID_PLC_CCO_MAC     (2)
 | |
| 
 | |
| /* message id for IOT_LED_CTRL_MSG_TIMER */
 | |
| #define IOT_LED_CTRL_MSG_ID_TMR_TIMEOUT     (2)
 | |
| 
 | |
| /* message id for IOT_LED_CTRL_MSG_TIMER */
 | |
| #define IOT_LED_CTRL_MSG_ID_REPORT_TMR_TIMEOUT (3)
 | |
| 
 | |
| /* message id for IOT_LED_CTRL_MSG_INTERNAL */
 | |
| #define IOT_LED_CTRL_MSG_INTERNAL_LEAKAGE_CURRENT   (1)
 | |
| #define IOT_LED_CTRL_MSG_INTERNAL_IN_METER_PARAM    (2)
 | |
| #define IOT_LED_CTRL_MSG_INTERNAL_UPDATE_CCO_MAC    (3)
 | |
| 
 | |
| /* timer interval, ms */
 | |
| #define IOT_LED_TIMER_INTERVAL                      (100)
 | |
| 
 | |
| /* Openloop check time */
 | |
| #define IOT_LED_OPENLOOP_CHECK_TIME                 1000
 | |
| 
 | |
| /* input voltage abnormal check time */
 | |
| #define IOT_LED_IN_VOL_ABNOR_CHECK_TIME             5000
 | |
| 
 | |
| /* report timer interval, ms */
 | |
| #define IOT_LED_REPORT_TIMER_INTERVAL               (5 * 1000) /* 5s */
 | |
| 
 | |
| /* wati report ack time */
 | |
| #define IOT_LED_WAIT_REPORT_ACK_INTERVAL            (10 * 1000) /* 10s */
 | |
| 
 | |
| /* no ack report Max count */
 | |
| #define IOT_LED_REPORT_MAX_COUNT                    (5)
 | |
| 
 | |
| /* Leakage current threshold, unit is mA. */
 | |
| #define IOT_LIGHT_CTRL_LEAKAGE_CURRENT_THR          (30)
 | |
| 
 | |
| /* the correction result, successful or fail */
 | |
| enum _correction_result_e {
 | |
|     IOT_LIGHT_CORRECTION_SUCCESS = 1,
 | |
|     IOT_LIGHT_CORRECTION_FAIL    = 2,
 | |
| };
 | |
| 
 | |
| /* light state check bit */
 | |
| enum _iot_light_state_check_e{
 | |
|     IOT_LIGHT_CHECK_POWER_STATE         = 0,
 | |
|     IOT_LIGHT_CHECK_UNDER_VOLTAGE       = 1,
 | |
|     IOT_LIGHT_CHECK_OVER_VOLTAGE        = 2,
 | |
|     IOT_LIGHT_CHECK_OVER_POWER          = 3,
 | |
|     IOT_LIGHT_CHECK_OPEN_LOOP           = 4,
 | |
|     IOT_LIGHT_CHECK_SHORT_CIRCUIT       = 5,
 | |
|     IOT_LIGHT_CHECK_UN_START            = 6,
 | |
|     IOT_LIGHT_CHECK_LOW_TEMPERATURE     = 7,
 | |
|     IOT_LIGHT_CHECK_OVER_TEMPERATURE    = 8,
 | |
|     IOT_LIGHT_CHECK_OVER_LEAKCURRENT    = 9,
 | |
| };
 | |
| 
 | |
| //TODO: will be change according to customer needs
 | |
| #define IOT_LIGHT_VOLTAGE_MIN           (1760) /* 0.1V */
 | |
| #define IOT_LIGHT_VOLTAGE_MAX           (2640) /* 0.1V */
 | |
| #define IOT_LIGHT_POWER_MAX             (4000) /* 0.1W */
 | |
| 
 | |
| /* type of function send pkt data to ge. */
 | |
| typedef uint8_t(*data_send_to_ge)(uint8_t *buf, uint16_t buf_len);
 | |
| 
 | |
| typedef struct _iot_led_ctrl_data_check_t {
 | |
|     uint32_t first_run;     /* if this first run this check */
 | |
|     uint32_t delta_value;   /* delta value compare with new coming data. */
 | |
|     uint8_t  sample_cnt;    /* sample count of this check */
 | |
|     uint8_t  delta_cnt;     /* delta count of this check */
 | |
|     uint8_t  delta_index;   /* current index of data in delta queue */
 | |
|     int32_t  sample_queue[IOT_LED_CTRL_DATA_CHECK_SAMPLE_MAX_LEN];/* queue for sample data */
 | |
|     int32_t  delta_queue[IOT_LED_CTRL_DATA_CHECK_DELTA_MAX_LEN]; /* queue for delta data */
 | |
| }iot_led_ctrl_data_check_t;
 | |
| 
 | |
| /** led controller task message */
 | |
| typedef struct _iot_led_ctrl_msg {
 | |
|     /* iot task message */
 | |
|     iot_task_msg_t  task_msg;
 | |
|     /* pointer to message data */
 | |
|     void            *data;
 | |
|     /* another data field */
 | |
|     uint32_t        data2;
 | |
| } iot_led_ctrl_msg_t;
 | |
| 
 | |
| /* function type of command. */
 | |
| typedef void (*iot_light_fn_t)(void *data, uint32_t d_len);
 | |
| 
 | |
| typedef struct _iot_light_controller_handle_t {
 | |
|     /* command code. */
 | |
|     uint32_t        command;
 | |
|     /* function handle of command code. */
 | |
|     iot_light_fn_t  fn_command;
 | |
| } iot_light_ctrl_handle_t;
 | |
| 
 | |
| /* param of power. */
 | |
| typedef struct _iot_light_power_param_t {
 | |
|     /* device type. Reference to DEV_TYPE_LED_xxxW */
 | |
|     uint8_t  device_type;
 | |
|     /* temperature of power device. */
 | |
|     int8_t   temperature;
 | |
|     /* power factor of output power. */
 | |
|     uint8_t  factor;
 | |
|     /* brightness level of channel a LED light. */
 | |
|     uint8_t  light_level_a;
 | |
|     /* brightness level of channel b LED light. */
 | |
|     uint8_t  light_level_b;
 | |
|     /* leakage */
 | |
|     uint8_t  leakage;
 | |
|     /* if power up */
 | |
|     uint8_t  power_up;
 | |
|     /* if open loop */
 | |
|     uint8_t  open_loop;
 | |
|     /* voltage of input, over range */
 | |
|     uint8_t  vol_abnormal;
 | |
|     /* voltage of input. 0.1V */
 | |
|     uint16_t voltage_in;
 | |
|     /* current of input. 1mA */
 | |
|     uint16_t current_in;
 | |
|     /* voltage of output. 0.1V */
 | |
|     uint16_t voltage_out;
 | |
|     /* current of output. 1mA */
 | |
|     uint16_t current_out;
 | |
|     /* active power of input. 0.1W */
 | |
|     uint16_t power_in;
 | |
|     /* current of leakage. 1mA */
 | |
|     int16_t leakage_current;
 | |
|     /*
 | |
|     * power state.
 | |
|     * BIT : 9   8   7   6   5   4   3   2   1   0
 | |
|     * FUN : OLC  OT  LT  US  SC  OL  OP  OV  UV  PS
 | |
|     * OLC : Over LeakCurrent, see IOT_LIGHT_CTRL_LEAKAGE_CURRENT_THR defined
 | |
|     * OT : Over Temperature, 1 over, 0 normal.
 | |
|     * LT : Low Temperature, 1 low, 0 normal.
 | |
|     * US : Un Start, 1 cannot start, 0 normal.
 | |
|     * SC : Short Circuit, 1 short circuit, 0 normal.
 | |
|     * OL : Open Loop, 1 looped, 0 normal.
 | |
|     * OP : Over Power, 1 over, 0 normal.
 | |
|     * OV : Over Voltage, 1 over, 0 normal.
 | |
|     * UV : Under Voltage, 1 low, 0 normal. 165~265V
 | |
|     * PS : Power State , 1 on, 0 off.
 | |
|     */
 | |
|     uint16_t power_state;
 | |
| } iot_light_power_param_t;
 | |
| 
 | |
| typedef struct _iot_light_object_t {
 | |
|     /* Group this device belongs to. */
 | |
|     uint8_t                 group;
 | |
|     /* to control 3386c to reset. */
 | |
|     uint8_t                 gpio_power_on;
 | |
|     /* to control relay to protect led from over current. */
 | |
|     uint8_t                 gpio_relay;
 | |
|     /* param of this power. */
 | |
|     iot_light_power_param_t param;
 | |
| } iot_light_object_t;
 | |
| 
 | |
| typedef struct _iot_led_controller_t {
 | |
|     /* task handle */
 | |
|     iot_task_h          task;
 | |
|     /* timer handle */
 | |
|     timer_id_t          timer;
 | |
|     /* function to send data to ge */
 | |
|     data_send_to_ge     data_to_ge_fn;
 | |
|     /* led struct. */
 | |
|     iot_light_object_t  led;
 | |
|     /* led light mac address. */
 | |
|     uint8_t             local_mac[IOT_MAC_ADDR_LEN];
 | |
|     /* module ok? */
 | |
|     uint32_t            module_ready;
 | |
|     /* timer handle for report state */
 | |
|     timer_id_t          report_timer;
 | |
|     /* voltage check timer counter */
 | |
|     uint8_t             vol_abnormal_check_cnt;
 | |
|     /* report count without receive ack */
 | |
|     uint8_t             report_count;
 | |
|     /* save power state changes for report */
 | |
|     uint16_t            report_power_state;
 | |
|     /* flash info */
 | |
|     iot_led_pib_info_t  pib_info;
 | |
|     /* Leakage & meter data input check. */
 | |
|     iot_led_ctrl_data_check_t   check_leakage_current;
 | |
|     iot_led_ctrl_data_check_t   check_meter_voltage;
 | |
| } iot_led_ctrl_t;
 | |
| 
 | |
| /* This is the output current & voltage & pwm value on each brightness. */
 | |
| typedef struct _iot_led_param_table_on_brightness_t {
 | |
|     uint16_t i;   /* current of output. 1mA */
 | |
|     uint16_t v;   /* voltage of output. 0.1V */
 | |
|     uint16_t pwm; /* PWM , 1% */
 | |
| }iot_led_param_on_brightness_t;
 | |
| 
 | |
| #ifndef min
 | |
| #define min(a, b)   ((a) > (b) ? (b) : (a))
 | |
| #endif
 | |
| 
 | |
| #ifndef max
 | |
| #define max(a, b)   ((a) > (b) ? (a) : (b))
 | |
| #endif
 | |
| 
 | |
| static iot_led_ctrl_t iot_led_controller;
 | |
| 
 | |
| #define IOT_LIGHT_DATA_DUMP
 | |
| 
 | |
| void iot_light_save_led_info(void);
 | |
| 
 | |
| /* input : vol 1mV, cur 1mA, pow 1mW, fac 0.01% */
 | |
| #define iot_light_set_msg_meter_par(vol, cur, pow, fac, pmsg)\
 | |
|     do{\
 | |
|         (pmsg)->data = (void *)(((((fac) / 100) & 0xFFFF) << 16) \
 | |
|             | (((pow) / 100) & 0xFFFF));\
 | |
|         (pmsg)->data2 = (cur) & 0xFFFF;\
 | |
|         (pmsg)->data2 |= (((vol) / 100) & 0xFFFF) << 16;\
 | |
|     }while(0)
 | |
| 
 | |
| /* output : vol 0.1V, cur 1mA, pow 0.1W, fac 1% */
 | |
| #define iot_light_get_msg_meter_par(vol, cur, pow, fac, pmsg)\
 | |
|     do{\
 | |
|         (fac) = ((uint32_t)(pmsg)->data) >> 16;\
 | |
|         (pow) = ((uint32_t)(pmsg)->data) & 0xFFFF;\
 | |
|         (cur) = (pmsg)->data2 & 0xFFFF;\
 | |
|         (vol) = ((pmsg)->data2) >> 16;\
 | |
|     }while(0)
 | |
| 
 | |
| #ifdef IOT_LIGHT_DATA_DUMP
 | |
| extern void iot_common_bin_dump(uint8_t *data, uint32_t dlen);
 | |
| #define iot_light_data_dump(buf, len) \
 | |
|     iot_common_bin_dump((uint8_t *)buf, (uint32_t)len)
 | |
| #else
 | |
| #define iot_light_data_dump(buf, len)
 | |
| #endif
 | |
| 
 | |
| void iot_led_crtl_msg_post_to_ge(iot_pkt_t* resp_pkt);
 | |
| 
 | |
| #if (!ENABLE_LED_CTRL_HARDWARE)
 | |
| /**
 | |
|  * @brief iot_light_drv_set_led_brightness() - driver to set brightness of led.
 | |
|  * @param channel: A or B or A&B channel to control.
 | |
|  * @param percent: percent of brightness, 0~100 -> 0%~100%.
 | |
|  */
 | |
| void iot_light_drv_set_led_brightness(uint32_t channel, uint32_t percent)
 | |
| {
 | |
|     (void)channel;
 | |
|     (void)percent;
 | |
| }
 | |
| #else
 | |
| 
 | |
| #define IOT_LIGHT_BRITNESS_TABLE_POINTS_CNT 11 /* 0% ~ 100% */
 | |
| #define IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS   10 /* 10% between 2 points */
 | |
| /* param value from 0% to 100% on brightness */
 | |
| const static iot_led_param_on_brightness_t iot_led_param_tb[IOT_LIGHT_BRITNESS_TABLE_POINTS_CNT] = {
 | |
|     {0,     0,      0},
 | |
|     {40,    3600,   4},
 | |
|     {75,    3640,   6},
 | |
|     {113,   3680,   9},
 | |
|     {158,   3780,   11},
 | |
|     {195,   3840,   14},
 | |
|     {229,   3890,   18},
 | |
|     {269,   3950,   24},
 | |
|     {304,   3990,   30},
 | |
|     {337,   4030,   41},
 | |
|     {365,   4070,   78}
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_get_param_tb() - Get param table on given brightness value.
 | |
|  * @param brightness: percent of brightness, 0~100 -> 0%~100%.
 | |
|  * @param param_tb: table to return.
 | |
|  */
 | |
| static void iot_light_drv_get_param_tb(uint32_t brightness, iot_led_param_on_brightness_t *param_tb)
 | |
| {
 | |
|     uint32_t delta, percent, last_idx, next_idx;
 | |
| 
 | |
|     percent = min(brightness, IOT_LIGHT_BRIGHTNESS_MAX_LEVEL_THRESHOLD);
 | |
| 
 | |
|     /* Get the indexes of table before and after the brightness we want. */
 | |
|     last_idx = (percent / IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS);
 | |
|     next_idx = (0 == (percent % IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS)) ? last_idx : (last_idx + 1);
 | |
| 
 | |
|     /* Get param from brightness mapping table. */
 | |
|     if (last_idx == next_idx) {
 | |
|         /* the brightness just on one of tables. */
 | |
|         param_tb->pwm = iot_led_param_tb[last_idx].pwm;
 | |
|         param_tb->i = iot_led_param_tb[last_idx].i;
 | |
|         param_tb->v = iot_led_param_tb[last_idx].v;
 | |
|     } else {
 | |
|         /* the brightness between 2 tables. */
 | |
|         /* Get pwm */
 | |
|         delta = iot_led_param_tb[next_idx].pwm - iot_led_param_tb[last_idx].pwm;
 | |
|         param_tb->pwm = iot_led_param_tb[last_idx].pwm + ((percent % IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS)
 | |
|             * delta / IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS);
 | |
| 
 | |
|         /* Get current */
 | |
|         delta = iot_led_param_tb[next_idx].i - iot_led_param_tb[last_idx].i;
 | |
|         param_tb->i = iot_led_param_tb[last_idx].i + ((percent % IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS)
 | |
|             * delta / IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS);
 | |
| 
 | |
|         /* Get voltage */
 | |
|         delta = iot_led_param_tb[next_idx].v - iot_led_param_tb[last_idx].v;
 | |
|         param_tb->v = iot_led_param_tb[last_idx].v + ((percent % IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS)
 | |
|             * delta / IOT_LIGHT_BRITNESS_STEP_LEN_ON_POINTS);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_set_control_param() - Set PWM duty & update volgate-out/current-out
 | |
|  * by brightness value.
 | |
|  * @param brightness: percent of brightness, 0~100 -> 0%~100%.
 | |
|  */
 | |
| static void iot_light_drv_set_control_param(uint32_t brightness)
 | |
| {
 | |
|     iot_led_param_on_brightness_t param;
 | |
| 
 | |
|     /* Get param from brightness mapping table. */
 | |
|     iot_light_drv_get_param_tb(brightness, ¶m);
 | |
| 
 | |
|     iot_pwm_set_duty(IOT_LIGHT_PWM_CHANNEL, param.pwm * 100);
 | |
| 
 | |
|     /* Update v & i from table into led status. */
 | |
|     iot_led_controller.led.param.current_out = param.i;
 | |
|     iot_led_controller.led.param.voltage_out = param.v;
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]Set PWM duty as %d%%. v_out=%d(0.1v), i_out=%d(1mA).\n",
 | |
|         param.pwm, param.v, param.i);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_set_relay_on() - control the relay to enable led.
 | |
|  * @param relay_on: true -> enable led, false -> disable led.
 | |
|  */
 | |
| static void iot_light_drv_set_relay_on(uint32_t relay_on)
 | |
| {
 | |
|     int val = relay_on ? IOT_LIGHT_GPIO_VAL_LED_ON : IOT_LIGHT_GPIO_VAL_LED_OFF;
 | |
| 
 | |
|     if (ERR_OK != iot_gpio_value_set(iot_led_controller.led.gpio_relay, val)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]write relay failed.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_set_pi_on() - control the pi chip.
 | |
|  * @param pi_on: true -> power up, false -> power down.
 | |
|  */
 | |
| static void iot_light_drv_set_pi_on(uint32_t pi_on)
 | |
| {
 | |
|     int val = pi_on ? IOT_LIGHT_GPIO_VAL_POWER_ON : IOT_LIGHT_GPIO_VAL_POWER_OFF;
 | |
| 
 | |
|     if (ERR_OK != iot_gpio_value_set(iot_led_controller.led.gpio_power_on, val)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]write power failed.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_poweroff() - power off led.
 | |
|  */
 | |
| static void iot_light_drv_poweroff(void)
 | |
| {
 | |
|     /* Set poweroff. */
 | |
|     iot_led_controller.led.param.power_up = false;
 | |
| 
 | |
|     /* shutdown pi chip */
 | |
|     iot_light_drv_set_pi_on(false);
 | |
| 
 | |
|     /* set power off */
 | |
|     iot_light_drv_set_control_param(0);
 | |
| 
 | |
|     /* Set PWM as low */
 | |
|     if (ERR_OK != iot_gpio_open_as_output(IOT_LIGHT_GPIO_PWM_A)) {
 | |
|         iot_gpio_close(IOT_LIGHT_GPIO_PWM_A);
 | |
|         /* do not care about return. open an gpio will cut the signal off. */
 | |
|         iot_gpio_open_as_output(IOT_LIGHT_GPIO_PWM_A);
 | |
|     }
 | |
|     iot_gpio_value_set(IOT_LIGHT_GPIO_PWM_A, 0); /* Pull low */
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]iot_light_drv_poweroff.\n");
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_protect() - protect device.
 | |
|  */
 | |
| void iot_light_drv_protect(void)
 | |
| {
 | |
|     /* disable relay */
 | |
|     iot_light_drv_set_relay_on(false);
 | |
| 
 | |
|     /* power off led */
 | |
|     iot_light_drv_poweroff();
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_powerup() - power up led.
 | |
|  */
 | |
| static void iot_light_drv_powerup(uint32_t brightness)
 | |
| {
 | |
|     /* enable relay && delay */
 | |
|     iot_light_drv_set_relay_on(true);
 | |
|     os_delay(IOT_LED_TIMMING_RELAY_ON_DELAY);
 | |
| 
 | |
|     /* powerup pi chip && delay */
 | |
|     iot_light_drv_set_pi_on(true);
 | |
|     os_delay(IOT_LED_TIMMING_POWERON_DELAY);
 | |
| 
 | |
|     /* set pwm */
 | |
|     iot_light_drv_set_control_param(brightness);
 | |
| 
 | |
|     /* Close gpio pin, config it to link PWM signal. */
 | |
|     iot_gpio_close(IOT_LIGHT_GPIO_PWM_A);
 | |
|     iot_pwm_gpio_config(IOT_LIGHT_PWM_CHANNEL, IOT_LIGHT_GPIO_PWM_A, IOT_LIGHT_GPIO_PWM_B);
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]iot_light_drv_powerup.\n");
 | |
| 
 | |
|     /* Set powerup */
 | |
|     iot_led_controller.led.param.power_up = true;
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_set_led_brightness() - driver to set brightness of led.
 | |
|  * @param channel: A or B or A&B channel to control.
 | |
|  * @param percent: percent of brightness, 0~100 -> 0%~100%.
 | |
|  */
 | |
| void iot_light_drv_set_led_brightness(uint32_t channel, uint32_t percent)
 | |
| {
 | |
|     if (iot_led_controller.led.param.leakage) {
 | |
|         if(IOT_LIGHT_BRIGHTNESS_SHUTDOWN_THRESHOLD > percent) {
 | |
|             /* Clear leakage when shutdown. */
 | |
|             iot_led_controller.led.param.leakage = false;
 | |
|         } else {
 | |
|             iot_cus_printf("[LIGHT_DRV]Cannot control LED when leakage.\n");
 | |
|         }
 | |
|     } else if (iot_led_controller.led.param.vol_abnormal) {
 | |
|         iot_cus_printf("[LIGHT_DRV]Cannot control LED when voltage abnormal.\n");
 | |
|     } else if (IOT_LIGHT_BRIGHTNESS_SHUTDOWN_THRESHOLD > percent) {
 | |
|         iot_light_drv_poweroff();
 | |
|         iot_cus_printf("[LIGHT_DRV]Poweroff LED.\n");
 | |
|     } else if (!iot_led_controller.led.param.power_up) {
 | |
|         iot_light_drv_powerup(percent);
 | |
|         iot_cus_printf("[LIGHT_DRV]Powerup LED.\n");
 | |
|     } else {
 | |
|         iot_light_drv_set_control_param(percent);
 | |
|         iot_cus_printf("[LIGHT_DRV]Control brightness of LED as %d%%.\n", percent);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_initialize_pwm() - To initialize PWM module.
 | |
|  */
 | |
| static void iot_light_drv_initialize_pwm(void)
 | |
| {
 | |
|     uint32_t pwm_clk;
 | |
|     iot_gpio_open_as_output(IOT_LIGHT_GPIO_PWM_A);
 | |
| 
 | |
|     iot_gpio_value_set(IOT_LIGHT_GPIO_PWM_A, 0); /* Pull low */
 | |
| 
 | |
|     /* init pwm */
 | |
|     iot_pwm_hw_init(IOT_PWM_CHANNEL_0);
 | |
| 
 | |
|     pwm_clk = iot_pwm_get_ch_clk(IOT_PWM_CHANNEL_0);
 | |
| 
 | |
|     iot_pwm_set_period(IOT_PWM_CHANNEL_0, pwm_clk / IOT_LIGHT_PWM_PERIOD);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static uint16_t iot_light_drv_get_current_in(void)
 | |
| {
 | |
|     /* TODO : get current from ADC */
 | |
|     return iot_led_controller.led.param.current_in;
 | |
| }
 | |
| 
 | |
| static void iot_light_drv_open_loop_check(void)
 | |
| {
 | |
|     static uint32_t glance_wait = 0;
 | |
| 
 | |
|     /* Wait for 1S */
 | |
|     if (++glance_wait < (IOT_LED_OPENLOOP_CHECK_TIME / IOT_LED_TIMER_INTERVAL)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     glance_wait = 0;
 | |
| 
 | |
|     /* Power off */
 | |
|     if (!iot_led_controller.led.param.power_up) {
 | |
|         /* No need to restore the brightness */
 | |
|         iot_led_controller.led.param.open_loop = false;
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Check current */
 | |
|     if (iot_light_drv_get_current_in() < IOT_LIGHT_CURRENT_IN_THRESHOLD_MIN) {
 | |
|         /* Abnormal. Set PWM as lowest. Check again at last time. */
 | |
|         iot_led_controller.led.param.open_loop = true;
 | |
|         iot_light_drv_set_control_param(IOT_LIGHT_BRIGHTNESS_OPENLOOP_THRESHOLD);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* In open loop state already.. */
 | |
|     if (iot_led_controller.led.param.open_loop) {
 | |
|         /* Normal. Clear state && Restore brightness level */
 | |
|         iot_led_controller.led.param.open_loop = false;
 | |
|         iot_light_drv_set_led_brightness(IOT_LIGHT_CHAN_ALL,
 | |
|             iot_led_controller.led.param.light_level_a / 2);
 | |
|     } else {
 | |
|         /* Do nothing. It's normal. */
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_voltage_abnormal_check() - To check if input-volgate
 | |
|  * over range.
 | |
|  */
 | |
| static void iot_light_drv_voltage_abnormal_check(void)
 | |
| {
 | |
|     uint32_t abnormal = false;
 | |
| 
 | |
|     /* Wait for 5S */
 | |
|     if (++iot_led_controller.vol_abnormal_check_cnt
 | |
|         < (IOT_LED_IN_VOL_ABNOR_CHECK_TIME / IOT_LED_TIMER_INTERVAL)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_led_controller.vol_abnormal_check_cnt = 0;
 | |
| 
 | |
|     /* check if voltage abnormal. */
 | |
|     if ((iot_led_controller.led.param.voltage_in < IOT_LIGHT_VOLTAGE_MIN)
 | |
|         || (iot_led_controller.led.param.voltage_in > IOT_LIGHT_VOLTAGE_MAX)){
 | |
|         abnormal = true;
 | |
|     }
 | |
| 
 | |
|     if (abnormal) {
 | |
|         if (iot_led_controller.led.param.vol_abnormal) {
 | |
|             iot_cus_printf("[LIGHT_DRV]check voltage, stay in abnormal.\n");
 | |
|         } else {
 | |
|             iot_cus_printf("[LIGHT_DRV]check voltage, run into abnormal.\n");
 | |
|             /* do protect */
 | |
|             iot_light_drv_protect();
 | |
|             iot_led_controller.led.param.vol_abnormal = true;
 | |
|         }
 | |
|     } else {
 | |
|         if (iot_led_controller.led.param.vol_abnormal) {
 | |
|             iot_cus_printf("[LIGHT_DRV]check voltage, restore from abnormal.\n");
 | |
|             iot_led_controller.led.param.vol_abnormal = false;
 | |
|             /* restore brightness. */
 | |
|             iot_light_drv_set_led_brightness(IOT_LIGHT_CHAN_ALL,
 | |
|                 iot_led_controller.led.param.light_level_a / 2);
 | |
|         } else {
 | |
|             iot_cus_printf("[LIGHT_DRV]check voltage, stay in normal.\n");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_initialize_hardware() - initialize hardware of
 | |
|  * this module.
 | |
|  * @return ERR_FAIL - Operation failed, ERR_OK - Operation Successful
 | |
|  */
 | |
| uint32_t iot_light_drv_initialize_hardware(void)
 | |
| {
 | |
|     if (ERR_OK != iot_gpio_open_as_output(iot_led_controller.led.gpio_power_on)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]open gpio for power failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     /* power down pi chip */
 | |
|     iot_light_drv_set_pi_on(false);
 | |
| 
 | |
|     if (ERR_OK != iot_gpio_open_as_output(iot_led_controller.led.gpio_relay)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]open gpio for relay failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     /* set relay on */
 | |
|     iot_light_drv_set_relay_on(true);
 | |
| 
 | |
|     iot_light_drv_initialize_pwm();
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_set_light_level() - To set the brightness level of light
 | |
|  * on given channel.
 | |
|  * @param channel: A or B or A&B channel to control.
 | |
|  * @param level: level between 0 ~ 200.
 | |
|  */
 | |
| static void iot_light_drv_set_light_level(uint8_t channel, uint8_t level)
 | |
| {
 | |
|     uint8_t save_flag = 0;
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]Set level from a=%d b=%d to %d.\n",
 | |
|         iot_led_controller.led.param.light_level_a,
 | |
|         iot_led_controller.led.param.light_level_b, level);
 | |
| 
 | |
|     /*
 | |
|      * Do not care about channel, this controller just has a single led light.
 | |
|      */
 | |
|     if (iot_led_controller.led.param.light_level_a != level ||
 | |
|         iot_led_controller.led.param.light_level_b != level) {
 | |
|         save_flag = 1;
 | |
|         iot_led_controller.led.param.light_level_a = level;
 | |
|         iot_led_controller.led.param.light_level_b = level;
 | |
| 
 | |
|         iot_led_controller.pib_info.level_a = level;
 | |
|         iot_led_controller.pib_info.level_b = level;
 | |
|     }
 | |
| 
 | |
|     iot_light_drv_set_led_brightness(channel, level / 2);
 | |
| 
 | |
|     if (save_flag)
 | |
|         iot_light_save_led_info();
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_check_power_state_changed() check power state changed
 | |
|  * @return false - no change, true - changed.
 | |
|  */
 | |
| static bool_t iot_light_check_power_state_changed()
 | |
| {
 | |
|     uint16_t check_bit  = 0;
 | |
| 
 | |
|     /* check Under Voltage */
 | |
|     check_bit |= 1 << IOT_LIGHT_CHECK_UNDER_VOLTAGE;
 | |
|     /* check Over Voltage */
 | |
|     check_bit |= 1 << IOT_LIGHT_CHECK_OVER_VOLTAGE;
 | |
|     /* check Over Power */
 | |
|     check_bit |= 1 << IOT_LIGHT_CHECK_OVER_POWER;
 | |
|     /* check Open Loop */
 | |
|     check_bit |= 1 << IOT_LIGHT_CHECK_OPEN_LOOP;
 | |
|     /* check Un Start */
 | |
|     check_bit |= 1 << IOT_LIGHT_CHECK_UN_START;
 | |
|     /* check Over LeakCurrent */
 | |
|     check_bit |= 1 << IOT_LIGHT_CHECK_OVER_LEAKCURRENT;
 | |
| 
 | |
|     if ((iot_led_controller.report_power_state & check_bit) !=
 | |
|         (iot_led_controller.led.param.power_state &check_bit)) {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_report_power_state_handle() - report power state handle
 | |
|  */
 | |
| static void iot_light_drv_report_power_state_handle()
 | |
| {
 | |
|     /* save last state */
 | |
|     iot_led_controller.report_power_state =
 | |
|         iot_led_controller.led.param.power_state;
 | |
|     if (iot_led_controller.report_count <= IOT_LED_REPORT_MAX_COUNT) {
 | |
|         /* Generate random time */
 | |
|         uint32_t delay = os_rand() % IOT_LED_REPORT_TIMER_INTERVAL;
 | |
|         iot_led_controller.report_count++;
 | |
| 
 | |
| #if ENABLE_LED_CTRL_HARDWARE
 | |
|         /* set a report timer */
 | |
|         os_start_timer(iot_led_controller.report_timer, delay);
 | |
| #endif
 | |
|         iot_cus_printf("[LIGHT_DRV]report timer started, %d ms state=%X\n",
 | |
|             delay, iot_led_controller.report_power_state);
 | |
|     } else {
 | |
|         iot_cus_printf("[LIGHT_DRV]report count is %d\n",
 | |
|             iot_led_controller.report_count);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_drv_update_power_param() - timer trigger this to update
 | |
|  * param of power.
 | |
|  */
 | |
| static void iot_light_drv_update_power_param()
 | |
| {
 | |
|     static uint8_t cnt = 0;
 | |
| 
 | |
|     /* check power state */
 | |
|     if (iot_led_controller.led.param.power_up) {
 | |
|         iot_led_controller.led.param.power_state |=
 | |
|             1 << IOT_LIGHT_CHECK_POWER_STATE;
 | |
|     } else {
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_POWER_STATE);
 | |
|     }
 | |
| 
 | |
|     /* check voltage in */
 | |
|     if (iot_led_controller.led.param.voltage_in < IOT_LIGHT_VOLTAGE_MIN) {
 | |
|         iot_led_controller.led.param.power_state |=
 | |
|             1 << IOT_LIGHT_CHECK_UNDER_VOLTAGE;
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_OVER_VOLTAGE);
 | |
|     } else if (iot_led_controller.led.param.voltage_in > IOT_LIGHT_VOLTAGE_MAX) {
 | |
|         iot_led_controller.led.param.power_state |=
 | |
|             1 << IOT_LIGHT_CHECK_OVER_VOLTAGE;
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_UNDER_VOLTAGE);
 | |
|     } else {
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_OVER_VOLTAGE);
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_UNDER_VOLTAGE);
 | |
|     }
 | |
| 
 | |
|     /* check power in */
 | |
|     if (iot_led_controller.led.param.power_in > IOT_LIGHT_POWER_MAX) {
 | |
|         iot_led_controller.led.param.power_state |=
 | |
|             1 << IOT_LIGHT_CHECK_OVER_POWER;
 | |
|     } else {
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_OVER_POWER);
 | |
|     }
 | |
| 
 | |
|     /* check open loop */
 | |
|     if (iot_led_controller.led.param.open_loop) {
 | |
|         iot_led_controller.led.param.power_state |=
 | |
|             1 << IOT_LIGHT_CHECK_OPEN_LOOP;
 | |
|     } else {
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_OPEN_LOOP);
 | |
|     }
 | |
| 
 | |
|     /* check over leakage current */
 | |
|     if (iot_led_controller.led.param.leakage) {
 | |
|         iot_led_controller.led.param.power_state |=
 | |
|             1 << IOT_LIGHT_CHECK_OVER_LEAKCURRENT;
 | |
|     } else {
 | |
|         iot_led_controller.led.param.power_state &=
 | |
|             ~(1 << IOT_LIGHT_CHECK_OVER_LEAKCURRENT);
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]update_power_param power_state=0x%X\n",
 | |
|         iot_led_controller.led.param.power_state);
 | |
| 
 | |
|     cnt++;
 | |
|     if (iot_led_controller.module_ready) {
 | |
|         if (iot_light_check_power_state_changed()) {
 | |
|             cnt = 0;
 | |
|             iot_led_controller.report_count = 0;
 | |
|             iot_light_drv_report_power_state_handle();
 | |
|         } else if ((iot_led_controller.report_count > 0) &&
 | |
|             (iot_led_controller.report_count <
 | |
|             IOT_LED_REPORT_MAX_COUNT) &&
 | |
|             (cnt % (IOT_LED_WAIT_REPORT_ACK_INTERVAL / IOT_LED_TIMER_INTERVAL)
 | |
|             == 0)){
 | |
|             cnt = 0;
 | |
|             /* have no received report ack after 10sec, retry report state */
 | |
|             iot_light_drv_report_power_state_handle();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_process_response() - pass responsing data to remote cco.
 | |
|  * @param resp_pkt: pkt for responsing.
 | |
|  */
 | |
| static void iot_light_process_response(iot_pkt_t *resp_pkt) {
 | |
| 
 | |
|     iot_led_crtl_msg_post_to_ge(resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_calcuate_checksum() - Caculate the check-sum of frame.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  * @return : check-sum.
 | |
|  */
 | |
| static uint8_t iot_light_calcuate_checksum(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     uint8_t check_sum = 0, *p_byte_val = (uint8_t *)frame;
 | |
|     uint32_t byte_idx;
 | |
| 
 | |
|     for (byte_idx = 0; byte_idx < frame_len - 1; byte_idx++) {
 | |
|         check_sum += *p_byte_val++;
 | |
|     }
 | |
| 
 | |
|     return check_sum;
 | |
| }
 | |
| 
 | |
| #define iot_light_check_checksum_invalid(frame, frame_len, checksum) \
 | |
|     (iot_light_calcuate_checksum(frame, frame_len) == (checksum) ? false : true)
 | |
| /* Get checksum byte from tail of frame */
 | |
| #define iot_light_check_checksum_invalid_by_raw_data(frame, frame_len) \
 | |
|     (iot_light_calcuate_checksum(frame, frame_len) \
 | |
|         == (*((char *)frame + (frame_len - 1))) ? false : true)
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_get_param() - Command handle for getting
 | |
|  * param of this led power.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_get_param(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_cmd_frm_get_param_t *p_cmd_frame = frame;
 | |
|     iot_resp_frm_get_param_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
|     iot_light_power_param_t *p_param = &iot_led_controller.led.param;
 | |
| 
 | |
|     /* Check-sum check. */
 | |
|     if (iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Prepare for responsing. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_resp_frm_get_param_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->opcode = RESP_GET_PARAM;
 | |
|     p_resp_frame->device_type = p_param->device_type;
 | |
|     p_resp_frame->temperature = p_param->temperature;
 | |
|     p_resp_frame->voltage_in_h = (p_param->voltage_in >> 8) & 0xFF;
 | |
|     p_resp_frame->voltage_in_l = p_param->voltage_in & 0xFF;
 | |
|     p_resp_frame->current_in_h = (p_param->current_in >> 8) & 0xFF;
 | |
|     p_resp_frame->current_in_l = p_param->current_in & 0xFF;
 | |
|     p_resp_frame->voltage_out_h = (p_param->voltage_out >> 8) & 0xFF;
 | |
|     p_resp_frame->voltage_out_l = p_param->voltage_out & 0xFF;
 | |
|     p_resp_frame->current_out_h = (p_param->current_out >> 8) & 0xFF;
 | |
|     p_resp_frame->current_out_l = p_param->current_out & 0xFF;
 | |
|     p_resp_frame->power_in_h = (p_param->power_in >> 8) & 0xFF;
 | |
|     p_resp_frame->power_in_l = p_param->power_in & 0xFF;
 | |
|     p_resp_frame->factor = p_param->factor;
 | |
|     p_resp_frame->level = p_param->light_level_a;
 | |
|     p_resp_frame->power_state_h = (p_param->power_state >> 8) & 0xFF;
 | |
|     p_resp_frame->power_state_l = p_param->power_state & 0xFF;
 | |
| 
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_report_power_state() - Command handle for report power
 | |
|  * state to cco.
 | |
|  * @param power_state: the changed power state which will report to cco.
 | |
|  */
 | |
| static void iot_light_report_power_state(uint16_t power_state)
 | |
| {
 | |
|     iot_light_report_power_state_t *p_report_frame;
 | |
|     iot_pkt_t *p_report_pkt;
 | |
|     /* Prepare for responsing. */
 | |
|     if (NULL == (p_report_pkt = iot_pkt_alloc(sizeof(*p_report_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_report_frame));
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_report_frame = (iot_light_report_power_state_t *)iot_pkt_put(p_report_pkt,
 | |
|         sizeof(*p_report_frame));
 | |
| 
 | |
|     iot_printf("[LIGHT_DRV]report power state=%X\n", power_state);
 | |
|     /* Fill the response frame filed. */
 | |
|     p_report_frame->opcode = REPORT_POWER_STATE;
 | |
|     p_report_frame->power_state_h = (power_state >> 8) & 0xFF;
 | |
|     p_report_frame->power_state_l = power_state & 0xFF;
 | |
| 
 | |
|     p_report_frame->check_sum = iot_light_calcuate_checksum(p_report_frame,
 | |
|         sizeof(*p_report_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_report_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_level_a() - Command handle for setting
 | |
|  * brightness level of channel A LED lights.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_level_a(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     uint8_t level;
 | |
|     iot_cmd_frm_set_light_level_a_t *p_cmd_frame = frame;
 | |
|     iot_resp_frm_set_light_level_a_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
|     uint32_t tmp_time;
 | |
| 
 | |
|     /* Check-sum check. */
 | |
|     if (iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]set_level_a checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Get the brightness level. */
 | |
|     level = min(IOT_LIGHT_BRIGHTNESS_RAW_LEVEL_MAX, p_cmd_frame->level);
 | |
| 
 | |
|     tmp_time = os_boot_time32();
 | |
| 
 | |
|     /* Set brightness level. */
 | |
|     iot_light_drv_set_light_level(IOT_LIGHT_CHAN_A, level);
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]set light use time=%d\n",
 | |
|         os_boot_time32() - tmp_time);
 | |
| 
 | |
|     /* Prepare for responsing. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_resp_frm_set_light_level_a_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->opcode = RESP_SET_LIGHT_LEVEL_A;
 | |
|     p_resp_frame->level =  level;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_level_b() - Command handle for setting
 | |
|  * brightness level of channel B LED lights.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_level_b(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     uint8_t level;
 | |
|     iot_cmd_frm_set_light_level_b_t *p_cmd_frame = frame;
 | |
|     iot_resp_frm_set_light_level_b_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
| 
 | |
|     /* Check-sum check. */
 | |
|     if (iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]set_level_b checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Get the brightness level. */
 | |
|     level = min(IOT_LIGHT_BRIGHTNESS_RAW_LEVEL_MAX, p_cmd_frame->level);
 | |
| 
 | |
|     /* Set brightness level. */
 | |
|     iot_light_drv_set_light_level(IOT_LIGHT_CHAN_B, level);
 | |
| 
 | |
|     /* Prepare for responsing. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_resp_frm_set_light_level_b_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->opcode = RESP_SET_LIGHT_LEVEL_B;
 | |
|     p_resp_frame->level =  level;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_level_ab() - Command handle for setting
 | |
|  * brightness level of both A & B LED lights.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_level_ab(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     uint8_t level;
 | |
|     iot_cmd_frm_set_light_level_ab_t *p_cmd_frame = frame;
 | |
|     iot_resp_frm_set_light_level_ab_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
| 
 | |
|     /* Check-sum check. */
 | |
|     if (iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]set_level_ab checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Get the brightness level. */
 | |
|     level = min(IOT_LIGHT_BRIGHTNESS_RAW_LEVEL_MAX, p_cmd_frame->level);
 | |
| 
 | |
|     /* Set brightness level. */
 | |
|     iot_light_drv_set_light_level(IOT_LIGHT_CHAN_ALL, level);
 | |
| 
 | |
|     /* Prepare for responsing. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_resp_frm_set_light_level_ab_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->opcode = RESP_SET_LIGHT_LEVEL_AB;
 | |
|     p_resp_frame->level = level;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_level_group() - Command handle for setting
 | |
|  * brightness level of LED light in given group.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_level_group(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     uint8_t level, group, channel;
 | |
|     iot_cmd_frm_set_light_level_grp_t *p_cmd_frame = frame;
 | |
| 
 | |
|     /* Check-sum check. */
 | |
|     if (iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]set_level_group checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     level = p_cmd_frame->level;
 | |
|     group = p_cmd_frame->group;
 | |
|     channel = p_cmd_frame->channel;
 | |
| 
 | |
|     level = min(IOT_LIGHT_BRIGHTNESS_RAW_LEVEL_MAX, level);
 | |
| 
 | |
|     /* Check if this command is broadcast or for our group. */
 | |
|     if (group == 0 || group == iot_led_controller.led.group) {
 | |
|         iot_light_drv_set_light_level(channel, level);
 | |
|     }
 | |
| 
 | |
|     /* Broadcast command frame does not need a responsing. */
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_private_command_subopcode_alloc_packet() -
 | |
|  * Alloc packet buffer with reservd bytes for private used when sub-command response.
 | |
|  * @param length: length of buffer sub-command need to response..
 | |
|  * @return packet buffer or NULL if failed.
 | |
|  */
 | |
| static iot_pkt_t * iot_light_private_command_subopcode_alloc_packet
 | |
|     (uint32_t length)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t pkt_length;
 | |
| 
 | |
|     /* total length of packet. */
 | |
|     pkt_length = length + CMD_PRIVATE_RESPONSE_RESV_BY_HEAD +
 | |
|         CMD_PRIVATE_RESPONSE_RESV_BY_TAIL;
 | |
| 
 | |
|     if (NULL == (p_pkt = iot_pkt_alloc(pkt_length, IOT_LIGHT_MODULE_ID))) {
 | |
|         return NULL;
 | |
|     }
 | |
|     /* reserved for CMD_PRIVATE_RESPONSE_RESV_BY_HEAD */
 | |
|     iot_pkt_reserve(p_pkt, CMD_PRIVATE_RESPONSE_RESV_BY_HEAD);
 | |
| 
 | |
|     return p_pkt;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_private_command_sub_get_leakage_current() -
 | |
|  * sub command handle for private using, to get current of leakage.
 | |
|  * @param subfrm_data: data for processing.
 | |
|  * @param subfrm_dlen: length of data, just subframe data,
 | |
|  * no subopcode, no checksum.
 | |
|  * @return resp pkt for this sub command.
 | |
|  */
 | |
| static iot_pkt_t * iot_light_private_command_sub_get_leakage_current
 | |
|     (void *subfrm_data, uint32_t subfrm_dlen)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     iot_resp_frm_prv_sub_get_leakage_current_t *p_frm_leakage_data;
 | |
| 
 | |
|     (void)subfrm_data;
 | |
|     (void)subfrm_dlen;
 | |
| 
 | |
|     if (NULL == (p_pkt = iot_light_private_command_subopcode_alloc_packet
 | |
|         (sizeof(*p_frm_leakage_data)))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_frm_leakage_data));
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     p_frm_leakage_data = (iot_resp_frm_prv_sub_get_leakage_current_t*)
 | |
|         iot_pkt_put(p_pkt, sizeof(*p_frm_leakage_data));
 | |
|     /* Fill the current. */
 | |
|     p_frm_leakage_data->current_h = iot_led_controller.led.param.leakage_current >> 8;
 | |
|     p_frm_leakage_data->current_l = iot_led_controller.led.param.leakage_current & 0xFF;
 | |
| 
 | |
|     return p_pkt;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_private_command_sub_get_dev_info() -
 | |
|  * sub command handle for private using, to get information of device.
 | |
|  * @param subfrm_data: data for processing.
 | |
|  * @param subfrm_dlen: length of data, just subframe data,
 | |
|  * no subopcode, no checksum.
 | |
|  * @return resp pkt for this sub command.
 | |
|  */
 | |
| static iot_pkt_t * iot_light_private_command_sub_get_dev_info
 | |
|     (void *subfrm_data, uint32_t subfrm_dlen)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
| 
 | |
|     iot_resp_frm_prv_sub_get_dev_info_t *p_frm_version_data;
 | |
| 
 | |
|     (void)subfrm_data;
 | |
|     (void)subfrm_dlen;
 | |
| 
 | |
|     if (NULL == (p_pkt = iot_light_private_command_subopcode_alloc_packet
 | |
|         (sizeof(*p_frm_version_data)))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_frm_version_data));
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     p_frm_version_data = (iot_resp_frm_prv_sub_get_dev_info_t *)
 | |
|         iot_pkt_put(p_pkt, sizeof(*p_frm_version_data));
 | |
| 
 | |
|     /* Fill the version and mac. */
 | |
|     p_frm_version_data->fw_ver = iot_htonl(iot_version_hex());
 | |
|     iot_mac_addr_cpy(p_frm_version_data->local_mac, iot_led_controller.local_mac);
 | |
| 
 | |
|     return p_pkt;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_private_command() - Command handle for private using.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_private_command(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_cmd_frm_private_command_t *p_cmd_private = frame;
 | |
|     iot_resp_frm_private_command_t *p_resp_private;
 | |
|     iot_pkt_t *p_resp_pkt = NULL;
 | |
|     void *subfrm_data;
 | |
|     uint32_t subfrm_dlen;
 | |
|     uint8_t *p_data, cs;
 | |
| 
 | |
|     if (iot_light_check_checksum_invalid_by_raw_data(frame, frame_len)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]private_command checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]Private command subopcode - 0x%x.\n",
 | |
|                 p_cmd_private->sub_opcode);
 | |
| 
 | |
|     /* command frame : OPCODE SUBOPCODE D0 ~ Dn CHECKSUM, subframe include D0 ~ Dn. */
 | |
|     subfrm_data = p_cmd_private->data;
 | |
|     /* the data length of sub command, D0 ~ Dn. */
 | |
|     subfrm_dlen = frame_len - CMD_PRIVATE_RESPONSE_RESV_BY_HEAD - CMD_PRIVATE_RESPONSE_RESV_BY_TAIL;
 | |
| 
 | |
|     switch (p_cmd_private->sub_opcode)
 | |
|     {
 | |
|         case SUBCMD_GET_LEAKAGE_CURRENT:
 | |
|             p_resp_pkt = iot_light_private_command_sub_get_leakage_current(
 | |
|                 subfrm_data, subfrm_dlen);
 | |
|             break;
 | |
|         case SUBCMD_GET_DEV_INFO:
 | |
|             p_resp_pkt = iot_light_private_command_sub_get_dev_info(
 | |
|                 subfrm_data, subfrm_dlen);
 | |
|             break;
 | |
|         default:
 | |
|             iot_cus_printf("[LIGHT_DRV]Unknown subopcode\n");
 | |
|             /* Do not ASSERT here. */
 | |
|             break;
 | |
|     }
 | |
| 
 | |
|     /* This will extend sub response data up to a response frame. */
 | |
|     if (NULL != p_resp_pkt) {
 | |
|         /* Fill opcode && subopcode into packet. */
 | |
|         p_resp_private = (iot_resp_frm_private_command_t *)
 | |
|             iot_pkt_push(p_resp_pkt, CMD_PRIVATE_RESPONSE_RESV_BY_HEAD);
 | |
| 
 | |
|         p_resp_private->opcode = RESP_PRIVATE_COMMAND;
 | |
|         p_resp_private->sub_opcode = p_cmd_private->sub_opcode;
 | |
| 
 | |
|         /* put 1 byte checksum. */
 | |
|         p_data = iot_pkt_put(p_resp_pkt, CMD_PRIVATE_RESPONSE_RESV_BY_TAIL);
 | |
| 
 | |
|         /* calculate checksum */
 | |
|         cs = iot_light_calcuate_checksum(p_data, iot_pkt_data_len(p_resp_pkt));
 | |
|         /* point to the tail, the checksum byte */
 | |
|         p_data += iot_pkt_data_len(p_resp_pkt) - 1;
 | |
|         /* Fill checksum byte. */
 | |
|         *p_data = cs;
 | |
| 
 | |
|         /* response */
 | |
|         iot_light_process_response(p_resp_pkt);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_group() - Command handle for setting group of
 | |
|  * this device/led controller.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_group(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_cmd_frm_set_group_t *p_cmd_frame = frame;
 | |
|     iot_resp_frm_set_group_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
|     uint8_t save_flag = 0;
 | |
| 
 | |
|     /* Check-sum check. */
 | |
|     if (iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]set_group checksum invalid.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Set the group. */
 | |
|     if (iot_led_controller.led.group != p_cmd_frame->group) {
 | |
|         iot_led_controller.led.group = p_cmd_frame->group;
 | |
|         iot_led_controller.pib_info.group = iot_led_controller.led.group;
 | |
|         save_flag = 1;
 | |
|     }
 | |
| 
 | |
|     /* Prepare for responsing. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_resp_frm_set_group_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->opcode = RESP_SET_GROUP;
 | |
|     p_resp_frame->group = iot_led_controller.led.group;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     if (save_flag)
 | |
|         iot_light_save_led_info();
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_report_power_state_ack() - Command handle for report power
 | |
|  * state ack.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_report_power_state_ack(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_light_cmd_frame_report_ack_t *p_cmd_frame = frame;
 | |
|     /* Check-sum check. */
 | |
|     if (frame_len != sizeof(*p_cmd_frame)
 | |
|         || iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]power_state_ack check fail.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_led_controller.report_count = 0;
 | |
|     iot_cus_printf("[LIGHT_DRV]recv ack result=%d\n", p_cmd_frame->result);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void iot_light_save_led_info(void)
 | |
| {
 | |
|     iot_proto_custom_pib_info_save(&iot_led_controller.pib_info,
 | |
|         sizeof(iot_led_pib_info_t));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_correction_resp() - Command handle for set
 | |
|  * correction response
 | |
|  * @param subfn: correction subfn: input power/voltage/current, output current.
 | |
|  * @param result: correction ack result.
 | |
|  */
 | |
| static void iot_light_command_correction_resp(uint8_t subfn, uint8_t result)
 | |
| {
 | |
|     iot_light_resp_set_correction_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
| 
 | |
|     /* Prepare for response. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc correction_resp pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_light_resp_set_correction_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->header.cmd_type = RESP_SET_CORRECTION_DATA;
 | |
|     p_resp_frame->header.subfn = subfn;
 | |
|     p_resp_frame->result = result;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(
 | |
|         p_resp_frame, sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_correction() - Command handle set correction
 | |
|  * input power, voltage, current and output current table.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_correction(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_light_correction_header_t *header = frame;
 | |
|     bool_t save_flag = false;
 | |
|     uint8_t result = IOT_LIGHT_CORRECTION_FAIL;
 | |
|     if (frame_len >= 3) {
 | |
|         /* check correction subfn */
 | |
|         switch (header->subfn) {
 | |
|             case SUBCMD_SET_COR_DATA_IN_POWER:
 | |
|             {
 | |
|                 iot_light_correction_input_power_t *p_cmd_frame = frame;
 | |
| 
 | |
|                 iot_led_controller.pib_info.input_power = 1;
 | |
|                 iot_led_controller.pib_info.input_power_slope =
 | |
|                     (float)p_cmd_frame->input_power_slope;
 | |
|                 iot_led_controller.pib_info.input_power_intercept =
 | |
|                     (float)p_cmd_frame->input_power_intercept;
 | |
|                 save_flag = true;
 | |
|                 result = IOT_LIGHT_CORRECTION_SUCCESS;
 | |
|                 break;
 | |
|             }
 | |
|             case SUBCMD_SET_COR_DATA_IN_VOLTAGE:
 | |
|             {
 | |
|                 iot_light_correction_input_voltage_t *p_cmd_frame = frame;
 | |
| 
 | |
|                 iot_led_controller.pib_info.input_voltage = 1;
 | |
|                 iot_led_controller.pib_info.input_vol_slope =
 | |
|                     (float)p_cmd_frame->input_voltage_slope;
 | |
|                 iot_led_controller.pib_info.input_vol_intercept =
 | |
|                     (float)p_cmd_frame->input_voltage_intercept;
 | |
|                 save_flag = true;
 | |
|                 result = IOT_LIGHT_CORRECTION_SUCCESS;
 | |
|                 break;
 | |
|             }
 | |
|             case SUBCMD_SET_COR_DATA_IN_CURRENT:
 | |
|             {
 | |
|                 iot_light_correction_input_current_t *p_cmd_frame = frame;
 | |
| 
 | |
|                 iot_led_controller.pib_info.input_current = 1;
 | |
|                 iot_led_controller.pib_info.input_cur_slope =
 | |
|                     (float)p_cmd_frame->input_current_slope;
 | |
|                 iot_led_controller.pib_info.input_cur_intercept =
 | |
|                     (float)p_cmd_frame->input_current_intercept;
 | |
|                 save_flag = true;
 | |
|                 result = IOT_LIGHT_CORRECTION_SUCCESS;
 | |
|                 break;
 | |
|             }
 | |
|             case SUBCMD_SET_COR_DATA_OUTPUT_CURRENT:
 | |
|             {
 | |
|                 iot_light_correction_output_current_t *p_cmd_frame = frame;
 | |
|                 uint8_t index = 0;
 | |
| 
 | |
|                 /* set_cur must be multiple of 10 */
 | |
|                 if (p_cmd_frame->set_cur > 0 &&
 | |
|                     (p_cmd_frame->set_cur % 10 == 0)) {
 | |
|                     index = (p_cmd_frame->set_cur / 10) - 1;
 | |
|                     if (index == 9){
 | |
|                         iot_led_controller.pib_info.output_current = 1;
 | |
|                     }
 | |
|                     iot_led_controller.pib_info.cor_param[index] =
 | |
|                         p_cmd_frame->real_cur;
 | |
|                     save_flag = true;
 | |
|                     result = IOT_LIGHT_CORRECTION_SUCCESS;
 | |
|                 } else {
 | |
|                     iot_cus_printf("[LIGHT_DRV]set output cur_val=%d err\n",
 | |
|                         p_cmd_frame->set_cur);
 | |
|                     iot_light_command_correction_resp(header->subfn, result);
 | |
|                 }
 | |
|                 break;
 | |
|             }
 | |
|             default:
 | |
|             {
 | |
|                 IOT_ASSERT(0);
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (save_flag) {
 | |
|         /* save flash */
 | |
|         iot_light_save_led_info();
 | |
|         /* response */
 | |
|         iot_light_command_correction_resp(header->subfn, result);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_get_cor_param() - Command handle for get correction
 | |
|  * parameter.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_get_cor_param(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_light_get_correction_param_t *p_cmd_frame = frame;
 | |
|     iot_light_resp_get_cor_param_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
|     if ((SUBCMD_GET_COR_PARAM_METER != p_cmd_frame->header.subfn) ||
 | |
|         frame_len != sizeof(*p_cmd_frame)
 | |
|         || iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]get_cor_param check fail.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Prepare for response. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_light_resp_get_cor_param_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->header.cmd_type = RESP_GET_CORRECTION_PARAM;
 | |
|     p_resp_frame->header.subfn = SUBCMD_GET_COR_PARAM_METER;
 | |
|     p_resp_frame->result = IOT_LIGHT_CORRECTION_SUCCESS;
 | |
|     p_resp_frame->power = iot_led_controller.led.param.power_in;
 | |
|     p_resp_frame->voltage = iot_led_controller.led.param.voltage_in;
 | |
|     p_resp_frame->current = iot_led_controller.led.param.current_in;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_set_cor_param() - Command handle for set correction
 | |
|  * light level.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  */
 | |
| static void iot_light_command_set_cor_param(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     iot_light_set_correction_param_t *p_cmd_frame = frame;
 | |
|     iot_light_resp_set_cor_param_t *p_resp_frame;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
| 
 | |
|     if ((SUBCMD_SET_COR_PARAM_LIGHT_LEVEL != p_cmd_frame->header.subfn) ||
 | |
|         frame_len != sizeof(*p_cmd_frame) ||
 | |
|         iot_light_check_checksum_invalid(frame, frame_len,
 | |
|         p_cmd_frame->check_sum)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]set_cor_param check fail.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_light_drv_set_led_brightness(IOT_LIGHT_CHAN_ALL,
 | |
|         p_cmd_frame->level / 2);
 | |
| 
 | |
|     /* Prepare for response. */
 | |
|     if (NULL == (p_resp_pkt = iot_pkt_alloc(sizeof(*p_resp_frame),
 | |
|         IOT_LIGHT_MODULE_ID))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed len #%d.\n",
 | |
|             sizeof(*p_resp_frame));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_frame = (iot_light_resp_set_cor_param_t *)iot_pkt_put(p_resp_pkt,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* Fill the response frame filed. */
 | |
|     p_resp_frame->header.cmd_type = RESP_SET_CORRECTION_PARAM;
 | |
|     p_resp_frame->header.subfn = SUBCMD_SET_COR_PARAM_LIGHT_LEVEL;
 | |
|     p_resp_frame->result = IOT_LIGHT_CORRECTION_SUCCESS;
 | |
|     p_resp_frame->check_sum = iot_light_calcuate_checksum(p_resp_frame,
 | |
|         sizeof(*p_resp_frame));
 | |
| 
 | |
|     /* response to cco */
 | |
|     iot_light_process_response(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_command_handle_list[] - Command processing handle list.
 | |
|  */
 | |
| static iot_light_ctrl_handle_t iot_light_command_handle_list[] = {
 | |
|     {CMD_GET_PARAM,             iot_light_command_get_param},
 | |
|     {CMD_SET_LIGHT_LEVEL_AB,    iot_light_command_set_level_ab},
 | |
|     {CMD_SET_LIGHT_LEVEL_GRP,   iot_light_command_set_level_group},
 | |
|     {CMD_SET_LIGHT_LEVEL_A,     iot_light_command_set_level_a},
 | |
|     {CMD_SET_LIGHT_LEVEL_B,     iot_light_command_set_level_b},
 | |
|     {CMD_SET_GROUP,             iot_light_command_set_group},
 | |
|     {CMD_PRIVATE_COMMAND,       iot_light_private_command},
 | |
|     {CMD_REPORT_POWER_STATE_ACK,iot_light_report_power_state_ack},
 | |
|     {CMD_SET_CORRECTION_DATA,   iot_light_command_set_correction},
 | |
|     {CMD_GET_CORRECTION_PARAM,  iot_light_command_get_cor_param},
 | |
|     {CMD_SET_CORRECTION_PARAM,  iot_light_command_set_cor_param},
 | |
| };
 | |
| 
 | |
| #define iot_light_cmd_list_size()   \
 | |
|     (sizeof(iot_light_command_handle_list) /\
 | |
|     sizeof(iot_light_command_handle_list[0]))
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_get_command_handle() - Return the command handle from given
 | |
|  * command code.
 | |
|  * @param command: command code.
 | |
|  * @return NULL - No matchable handle, else related handle.
 | |
|  */
 | |
| static iot_light_ctrl_handle_t *iot_light_get_command_handle(uint32_t command) {
 | |
|     uint32_t cmd_idx;
 | |
|     iot_light_ctrl_handle_t *handle = NULL;
 | |
| 
 | |
|     for (cmd_idx = 0; cmd_idx < iot_light_cmd_list_size(); cmd_idx++) {
 | |
|         if (iot_light_command_handle_list[cmd_idx].command == command) {
 | |
|             handle = &iot_light_command_handle_list[cmd_idx];
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* return NULL if no command found. */
 | |
|     return handle;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_light_process_command() - The main entrance for processing led
 | |
|  * control frame.
 | |
|  * @param frame: frame buffer for processing include check-sum byte.
 | |
|  * @param frame_len: length of this frame include check-sum byte.
 | |
|  * @return ERR_FAIL - Operation failed, ERR_OK - Operation Successful
 | |
|  */
 | |
| static uint32_t iot_light_process_command(void *frame, uint32_t frame_len)
 | |
| {
 | |
|     uint32_t command;
 | |
|     iot_light_ctrl_handle_t *handle;
 | |
| 
 | |
|     /* Check param */
 | |
|     if (NULL == frame || frame_len < IOT_LIGHT_MIN_FRAME_LEN) {
 | |
|         iot_cus_printf("[LIGHT_DRV]param invalid, frame %p len #%d.\n", frame,
 | |
|             frame_len);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     /* get command byte from frame. */
 | |
|     command = iot_light_get_cmd(frame);
 | |
| 
 | |
|     iot_light_data_dump(frame, frame_len);
 | |
| 
 | |
|     /* find function handle by command */
 | |
|     if (NULL == (handle = iot_light_get_command_handle(command))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]no command handle for 0x#%x.\n", command);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]process command 0x#%x, command_fn=%p.\n",
 | |
|         command, handle->fn_command);
 | |
| 
 | |
|     /* execute this command. */
 | |
|     handle->fn_command(frame, frame_len);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_data_check_with_delta()- check new data with data_check logic.
 | |
|  * @pcheck : data_check infor for this new data.
 | |
|  * @new_data : new data for checking.
 | |
|  * @out_data : final out data for checking.
 | |
|  * @return : true - data changed, else - not changed.
 | |
|  */
 | |
| static uint32_t iot_led_ctrl_data_check_with_delta(iot_led_ctrl_data_check_t *pcheck,
 | |
|     uint32_t new_data, uint32_t *out_data)
 | |
| {
 | |
|     uint32_t i, avg = 0, ret;
 | |
| 
 | |
|     if ((NULL == pcheck)
 | |
|         || (NULL == out_data)
 | |
|         || (0 == pcheck->sample_cnt)
 | |
|         || (0 == pcheck->delta_cnt)){
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /* First running, fill sample queue with new data. */
 | |
|     if (pcheck->first_run) {
 | |
|         pcheck->first_run = false;
 | |
|         for (i = 0; i < pcheck->sample_cnt; i++) {
 | |
|             pcheck->sample_queue[i] = new_data;
 | |
|         }
 | |
|         pcheck->delta_index = 0;
 | |
|         *out_data = new_data;
 | |
|         ret = false;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     /* Get average of sample queue. */
 | |
|     for (i = 0, avg = 0; i < pcheck->sample_cnt; i++) {
 | |
|         avg += pcheck->sample_queue[i];
 | |
|     }
 | |
|     avg /= i;
 | |
| 
 | |
|     /* Check if new data has a delta over delta_value */
 | |
|     if (iot_led_drv_get_delta_val(avg, new_data) <= pcheck->delta_value) {
 | |
|         /* This is a normal sample data. */
 | |
|         /* 1. Clear delta queue */
 | |
|         pcheck->delta_index = 0;
 | |
|         /* 2. Store this new data at the tail of sample queue */
 | |
|         os_mem_cpy(&pcheck->sample_queue[0], &pcheck->sample_queue[1],
 | |
|             (pcheck->sample_cnt - 1) * sizeof(pcheck->sample_queue[0]));
 | |
|         pcheck->sample_queue[pcheck->sample_cnt - 1] = new_data;
 | |
|         *out_data = new_data;
 | |
|         ret = false;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     /* Check if delta queue full */
 | |
|     if (pcheck->delta_index + 1 >= pcheck->delta_cnt) {
 | |
|         /* This delta queue full, that means data chenged. */
 | |
|         /* 1. flush delta queue into sample queue. */
 | |
|         pcheck->delta_queue[pcheck->delta_cnt - 1] = new_data;
 | |
|         /* Get the len of data need to copy. */
 | |
|         i = min(pcheck->delta_cnt, pcheck->sample_cnt);
 | |
|         /* move tail to head */
 | |
|         os_mem_cpy(pcheck->sample_queue, pcheck->sample_queue + i,
 | |
|             (pcheck->sample_cnt - i) * sizeof(pcheck->sample_queue[0]));
 | |
|         /* copy delta queue into sample queue */
 | |
|         os_mem_cpy(pcheck->sample_queue + (pcheck->sample_cnt - i),
 | |
|             pcheck->delta_queue, i * sizeof(pcheck->sample_queue[0]));
 | |
|         /* 2. Clear delta queue */
 | |
|         pcheck->delta_index = 0;
 | |
| 
 | |
|         *out_data = new_data;
 | |
|         ret = true;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     /* Store new data into delta queue */
 | |
|     pcheck->delta_queue[pcheck->delta_index++] = new_data;
 | |
| 
 | |
|     /* return last normal sample data for this time. */
 | |
|     *out_data = pcheck->sample_queue[pcheck->sample_cnt - 1];
 | |
|     ret = false;
 | |
| 
 | |
| out:
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]sample: delta %d, avg %d, new data %d, out data %d, ret %d.\n",
 | |
|         pcheck->delta_value, avg, new_data, *out_data, ret);
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_handle_uart_data_msg() - process the data from uart port.
 | |
|  * @msg : message from uart port.
 | |
|  */
 | |
| static void iot_led_ctrl_handle_uart_data_msg(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     /* TODO : STA has nothing to do with uart data for now. */
 | |
|     iot_pkt_free((iot_pkt_t *)msg->data);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_handle_plc_data_msg() - process the data from PLC.
 | |
|  * @msg : message from remote device by PLC.
 | |
|  */
 | |
| static void iot_led_ctrl_handle_plc_data_msg(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *frame_buf;
 | |
|     uint32_t frame_len;
 | |
| 
 | |
|     if ((NULL == msg) || (NULL == (p_pkt = (iot_pkt_t *)msg->data))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]invalid param.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     frame_buf = iot_pkt_data(p_pkt);
 | |
|     frame_len = iot_pkt_data_len(p_pkt);
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]plc received pkt #%p, frame #%p, length #%d.\n",
 | |
|         p_pkt, frame_buf, frame_len);
 | |
| 
 | |
|     if (ERR_OK != iot_light_process_command(frame_buf, frame_len)) {
 | |
|         iot_cus_printf("[LIGHT_DRV]process command failed.\n");
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_handle_plc_data_msg() - process the data from PLC.
 | |
|  * @msg : message from remote device by PLC.
 | |
|  */
 | |
| static void iot_led_ctrl_handle_plc_cco_mac_msg(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *frame_buf;
 | |
| 
 | |
|     if ((NULL == msg) || (NULL == (p_pkt = (iot_pkt_t *)msg->data))) {
 | |
|         iot_cus_printf("[LIGHT_DRV]invalid param.\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     frame_buf = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]join cco[%x:%x:%x:%x:%x:%x].\n",
 | |
|         frame_buf[0], frame_buf[1], frame_buf[2], frame_buf[3],
 | |
|         frame_buf[4], frame_buf[5]);
 | |
| 
 | |
|     iot_led_crtl_set_mac(frame_buf);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void iot_led_crtl_msg_post(uint16_t msg_type, uint16_t msg_id, iot_pkt_t * data)
 | |
| {
 | |
|     iot_task_msg_t      *msg;
 | |
|     iot_led_ctrl_msg_t  *task_msg;
 | |
|     msg = iot_task_alloc_msg_with_reserved(iot_led_controller.task, 0);
 | |
|     if (NULL == msg) {
 | |
|         if (NULL != data) {
 | |
|             iot_pkt_free(data);
 | |
|         }
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     task_msg = (iot_led_ctrl_msg_t*)msg;
 | |
|     task_msg->task_msg.type = msg_type;
 | |
|     task_msg->task_msg.id = msg_id;
 | |
|     task_msg->data = data;
 | |
|     task_msg->data2 = 0;
 | |
|     iot_task_queue_msg(iot_led_controller.task, &task_msg->task_msg, 0);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_crtl_leakage_evt_func() - check leakage current callback
 | |
|  * function.
 | |
|  * @current : read current value, 1mA.
 | |
|  */
 | |
| void iot_led_crtl_leakage_evt_func(uint32_t current)
 | |
| {
 | |
|     uint32_t r_cur, changed;
 | |
|     iot_led_ctrl_msg_t *msg;
 | |
| 
 | |
|     changed = iot_led_ctrl_data_check_with_delta
 | |
|         (&iot_led_controller.check_leakage_current, current, &r_cur);
 | |
| 
 | |
|     (void)r_cur; /* NOT used. */
 | |
| 
 | |
|     if (changed) {
 | |
|         iot_cus_printf("[LIGHT_DRV]leak changed: I %d(mA).\n", current);
 | |
|     } else {
 | |
|         iot_cus_printf("[LIGHT_DRV]leak not change: I %d(mA).\n", current);
 | |
|     }
 | |
| 
 | |
|     /* Keep the value for updating param. */
 | |
|     iot_led_controller.led.param.leakage_current = (int16_t)current;
 | |
| 
 | |
|     if (((current >= IOT_LIGHT_CTRL_LEAKAGE_CURRENT_THR)
 | |
|         || (changed && iot_led_controller.led.param.power_up))
 | |
|         && (!iot_led_controller.led.param.leakage))
 | |
|     {
 | |
|         msg = (iot_led_ctrl_msg_t *)iot_task_alloc_msg(iot_led_controller.task);
 | |
|         if (msg) {
 | |
|             msg->task_msg.type = IOT_LED_CTRL_MSG_INTERNAL;
 | |
|             msg->task_msg.id = IOT_LED_CTRL_MSG_INTERNAL_LEAKAGE_CURRENT;
 | |
|             msg->data2 = current;
 | |
|             iot_task_queue_msg(iot_led_controller.task, &msg->task_msg, 0);
 | |
|         } else {
 | |
|             IOT_ASSERT(0);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_input_in_meter_param()
 | |
|    input meter data callback
 | |
|  * @voltage : read voltage value, 1mV.
 | |
|  * @current : read current value, 1mA.
 | |
|  * @power : read power value, 1mW.
 | |
|  * @factor : factor value, 0.01%.
 | |
|  */
 | |
| void iot_led_ctrl_input_in_meter_param(uint32_t voltage, uint32_t current,
 | |
|     uint32_t power, uint32_t factor)
 | |
| {
 | |
|     uint32_t r_vol;
 | |
|     iot_led_ctrl_msg_t *msg;
 | |
| 
 | |
|     iot_led_ctrl_data_check_with_delta
 | |
|         (&iot_led_controller.check_meter_voltage, voltage, &r_vol);
 | |
| 
 | |
|      /* This meter data is abnormal, drop. */
 | |
|     if (voltage != r_vol) {
 | |
|         iot_cus_printf("[LIGHT_DRV]meter data dropped:V %d(mV)," \
 | |
|             "I %d(mA),P %d(mW), F %d%%(0.01%%).\n",
 | |
|             voltage, current, power, factor);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]meter data confirmed:V %d(mV)," \
 | |
|         "I %d(mA),P %d(mW), F %d%%(0.01%%).\n",
 | |
|         voltage, current, power, factor);
 | |
| 
 | |
|     msg = (iot_led_ctrl_msg_t *)iot_task_alloc_msg(iot_led_controller.task);
 | |
| 
 | |
|     if (msg) {
 | |
|         msg->task_msg.type = IOT_LED_CTRL_MSG_INTERNAL;
 | |
|         msg->task_msg.id = IOT_LED_CTRL_MSG_INTERNAL_IN_METER_PARAM;
 | |
|         iot_light_set_msg_meter_par(voltage, current, power, factor, msg);
 | |
|         iot_task_queue_msg(iot_led_controller.task, &msg->task_msg, 0);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #if IOT_LIGHT_CTRL_ADC_MODULE_ENABLE
 | |
| static void iot_light_ctrl_leakage_current_process(int32_t leakage_current)
 | |
| {
 | |
|     /* leakage protect. */
 | |
|     iot_light_drv_protect();
 | |
| 
 | |
|     /* set flag */
 | |
|     iot_led_controller.led.param.leakage = true;
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]leakage_current:%d(mA), " \
 | |
|         "large than threshold, close relay!\n", leakage_current);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_handle_data_msg() - process data from current/other task.
 | |
|  * @msg : message.
 | |
|  */
 | |
| static void iot_led_ctrl_handle_data_msg(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     switch (msg->task_msg.id) {
 | |
|         case IOT_LED_CTRL_MSG_ID_UART_DATA:
 | |
|         {
 | |
|             iot_led_ctrl_handle_uart_data_msg(msg);
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_ID_PLC_DATA:
 | |
|         {
 | |
|             iot_led_ctrl_handle_plc_data_msg(msg);
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_ID_PLC_CCO_MAC:
 | |
|         {
 | |
|             iot_led_ctrl_handle_plc_cco_mac_msg(msg);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|         {
 | |
|             iot_cus_printf("[LIGHT_DRV]unknown message id #%d.\n",
 | |
|                 msg->task_msg.id);
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_handle_timer_msg() - process data from local timer.
 | |
|  * @msg : message.
 | |
|  */
 | |
| static void iot_led_ctrl_handle_timer_msg(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     switch (msg->task_msg.id) {
 | |
|         case IOT_LED_CTRL_MSG_ID_TMR_TIMEOUT:
 | |
|         {
 | |
|             if (mac_addr_is_valid_addr(iot_led_controller.local_mac)) {
 | |
|                 iot_light_drv_update_power_param();
 | |
|             } else {
 | |
|                 iot_cus_printf("[LIGHT_DRV]local mac is invalid.\n");
 | |
|             }
 | |
| #if (ENABLE_LED_CTRL_HARDWARE)
 | |
|             iot_light_drv_voltage_abnormal_check();
 | |
|             iot_light_drv_open_loop_check();
 | |
| #endif
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_ID_REPORT_TMR_TIMEOUT:
 | |
|         {
 | |
|             /* report power state to cco */
 | |
|             iot_light_report_power_state(*(uint16_t*)msg->data);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|         {
 | |
|             iot_cus_printf("[LIGHT_DRV]unknown message id #%d.\n",
 | |
|                 msg->task_msg.id);
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_update_input_meter_param() - update input meter data.
 | |
|  * @msg : message.
 | |
|  */
 | |
| static void iot_led_ctrl_update_input_meter_param(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     uint16_t cur, pow, vol, fac;
 | |
| 
 | |
|     iot_light_get_msg_meter_par(vol, cur, pow, fac, msg);
 | |
| 
 | |
|     iot_led_controller.led.param.current_in = cur;
 | |
|     iot_led_controller.led.param.voltage_in = vol;
 | |
|     iot_led_controller.led.param.power_in = pow;
 | |
|     iot_led_controller.led.param.factor = (uint8_t)fac;
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]Update meter : I %d(1mA), V %d(0.1V), P %d(0.1W), F %d(1%%).\n",
 | |
|         cur, vol, pow, fac);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_handle_internal_msg() - process data from intrnal.
 | |
|  * @msg : message.
 | |
|  */
 | |
| static void iot_led_ctrl_handle_internal_msg(iot_led_ctrl_msg_t *msg)
 | |
| {
 | |
|     switch (msg->task_msg.id) {
 | |
|         case IOT_LED_CTRL_MSG_INTERNAL_LEAKAGE_CURRENT:
 | |
|         {
 | |
| #if IOT_LIGHT_CTRL_ADC_MODULE_ENABLE
 | |
|             iot_light_ctrl_leakage_current_process((int32_t)msg->data2);
 | |
| #endif
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_INTERNAL_IN_METER_PARAM:
 | |
|         {
 | |
|             iot_led_ctrl_update_input_meter_param(msg);
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_INTERNAL_UPDATE_CCO_MAC:
 | |
|         {
 | |
|             uint8_t *cco_mac = iot_pkt_data((iot_pkt_t *)msg->data);
 | |
|             /* only disconnect net can update */
 | |
|             if (!iot_led_controller.module_ready &&
 | |
|                 iot_mac_addr_valid(cco_mac)) {
 | |
|                 iot_cus_printf("[LIGHT_DRV]update cco mac\n");
 | |
|                 iot_mac_addr_cpy(iot_led_controller.pib_info.cco_mac, cco_mac);
 | |
|             }
 | |
| 
 | |
|             iot_pkt_free((iot_pkt_t *)msg->data);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|         {
 | |
|             iot_cus_printf("[LIGHT_DRV]unknown message id #%d.\n",
 | |
|                 msg->task_msg.id);
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_task_timer_exe() - timer timeout callback function.
 | |
|  * @timer_id : timer id with that timer who causes this api-call.
 | |
|  * @arg : param past to this callback api.
 | |
|  */
 | |
| void iot_led_ctrl_task_timer_exe(timer_id_t timer_id, void * arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     (void)arg;
 | |
| 
 | |
|     iot_led_crtl_msg_post(IOT_LED_CTRL_MSG_TIMER,
 | |
|         IOT_LED_CTRL_MSG_ID_TMR_TIMEOUT, NULL);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_report_timer_exe() - report timer timeout callback
 | |
|  * function.
 | |
|  * @timer_id : timer id with that timer who causes this api-call.
 | |
|  * @arg : param past to this callback api.
 | |
|  */
 | |
| void iot_led_ctrl_report_timer_exe(timer_id_t timer_id, void * arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
| 
 | |
|     iot_led_crtl_msg_post(IOT_LED_CTRL_MSG_TIMER,
 | |
|         IOT_LED_CTRL_MSG_ID_REPORT_TMR_TIMEOUT, arg);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_task_msg_exe() - message process callback function.
 | |
|  * @task_h : task id with that task who causes this api-call.
 | |
|  * @msg : message past to this callback api.
 | |
|  */
 | |
| static void iot_led_ctrl_task_msg_exe(iot_task_h task_h, iot_task_msg_t *msg)
 | |
| {
 | |
|     iot_led_ctrl_msg_t *task_msg = (iot_led_ctrl_msg_t*)msg;
 | |
| 
 | |
|     switch (task_msg->task_msg.type) {
 | |
|         case IOT_LED_CTRL_MSG_DATA:
 | |
|         {
 | |
|             iot_led_ctrl_handle_data_msg(task_msg);
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_TIMER:
 | |
|         {
 | |
|             iot_led_ctrl_handle_timer_msg(task_msg);
 | |
|             break;
 | |
|         }
 | |
|         case IOT_LED_CTRL_MSG_INTERNAL:
 | |
|         {
 | |
|             iot_led_ctrl_handle_internal_msg(task_msg);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|         {
 | |
|             iot_cus_printf("[LIGHT_DRV]unknown message type #%d.\n",
 | |
|                 task_msg->task_msg.type);
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     iot_task_free_msg(task_h, msg);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_led_ctrl_task_msg_cancel() - message cancel callback function.
 | |
|  * @task_h : task id with that task who causes this api-call.
 | |
|  * @msg : message past to this callback api.
 | |
|  */
 | |
| static void iot_led_ctrl_task_msg_cancel(iot_task_h task_h, iot_task_msg_t *msg)
 | |
| {
 | |
|     iot_led_ctrl_msg_t *task_msg = (iot_led_ctrl_msg_t *)msg;
 | |
| 
 | |
|     switch(task_msg->task_msg.type)
 | |
|     {
 | |
|         case IOT_LED_CTRL_MSG_DATA:
 | |
|         case IOT_LED_CTRL_MSG_TIMER:
 | |
|         {
 | |
|             iot_pkt_free(task_msg->data);
 | |
|         }
 | |
|         default:
 | |
|         {
 | |
|             iot_cus_printf("[LIGHT_DRV]unknown message type #%d.\n",
 | |
|                 task_msg->task_msg.type);
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     iot_task_free_msg(task_h, msg);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static uint32_t iot_led_ctrl_ge_handle_connect_ind(uint8_t *p_pkt_data)
 | |
| {
 | |
|     uint8_t *p_buffer;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     ge_frame_conn_ind_rpt_set_subfn9_t *p_frame;
 | |
| 
 | |
|     p_frame = (ge_frame_conn_ind_rpt_set_subfn9_t *)p_pkt_data;
 | |
| 
 | |
|     if ((PROTO_GE_PLC_SET_CMD != p_frame->hdr.hdr.fn)
 | |
|         || (PROTO_CONN_IND_RPT_CMD != p_frame->hdr.subfn)) {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_pkt = iot_pkt_alloc(IOT_MAC_ADDR_LEN, IOT_LIGHT_MODULE_ID);
 | |
| 
 | |
|     if (NULL == p_pkt) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_buffer = iot_pkt_put(p_pkt, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     os_mem_cpy(p_buffer, p_frame->mac, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     iot_led_crtl_msg_post(IOT_LED_CTRL_MSG_DATA,
 | |
|         IOT_LED_CTRL_MSG_ID_PLC_CCO_MAC, p_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| 
 | |
| }
 | |
| 
 | |
| static uint32_t iot_led_ctrl_ge_handle_data_recv(uint8_t *p_pkt_data)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *p_buffer;
 | |
|     ge_frame_data_send_set_subfn160_t *p_frame;
 | |
|     uint8_t data_len = 0;
 | |
| 
 | |
|     p_frame = (ge_frame_data_send_set_subfn160_t *)p_pkt_data;
 | |
| 
 | |
|     if ((PROTO_GE_PLC_SET_CMD != p_frame->hdr.hdr.fn)
 | |
|         || (PROTO_GE_DATA_CMD != p_frame->hdr.subfn)
 | |
|         || (p_frame->hdr.hdr.data_len <= IOT_MAC_ADDR_LEN * 2)) {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (!iot_mac_addr_valid(iot_led_controller.pib_info.cco_mac)) {
 | |
|         iot_cus_printf("[LIGHT_DRV][war]cco mac is invalid, drop\n");
 | |
|         return ERR_FAIL;
 | |
|     } else if (!iot_mac_addr_cmp(iot_led_controller.pib_info.cco_mac,
 | |
|         p_frame->data)) {
 | |
|         iot_cus_printf("[LIGHT_DRV][war]recv data from %02X:%02X:%02X:%02X:"
 | |
|             "%02X:%02X, drop\n", p_frame->data[0], p_frame->data[1],
 | |
|             p_frame->data[2], p_frame->data[3],
 | |
|             p_frame->data[4], p_frame->data[5]);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     /* IOT_MAC_ADDR_LEN * 2 for src & dst MAC. */
 | |
|     data_len = p_frame->hdr.hdr.data_len - IOT_MAC_ADDR_LEN * 2;
 | |
| 
 | |
|     p_pkt = iot_pkt_alloc(data_len, IOT_LIGHT_MODULE_ID);
 | |
| 
 | |
|     if (NULL == p_pkt) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_buffer = iot_pkt_put(p_pkt, data_len);
 | |
| 
 | |
|     /* skip 6 bytes src mac, we do not care about. */
 | |
|     os_mem_cpy(p_buffer, p_frame->data + IOT_MAC_ADDR_LEN, data_len);
 | |
| 
 | |
|     iot_led_crtl_msg_post(IOT_LED_CTRL_MSG_DATA,
 | |
|         IOT_LED_CTRL_MSG_ID_PLC_DATA, p_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* register to proto to update cco mac */
 | |
| uint32_t iot_led_ctrl_update_cco_mac(uint8_t *cco_mac)
 | |
| {
 | |
|     iot_pkt_t *p_pkt = iot_pkt_alloc(IOT_MAC_ADDR_LEN, IOT_LIGHT_MODULE_ID);
 | |
| 
 | |
|     if (NULL == p_pkt) {
 | |
|         iot_cus_printf("[LIGHT_DRV]alloc pkt failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     iot_mac_addr_cpy(iot_pkt_data(p_pkt), cco_mac);
 | |
|     iot_pkt_put(p_pkt, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     iot_led_crtl_msg_post(IOT_LED_CTRL_MSG_INTERNAL,
 | |
|         IOT_LED_CTRL_MSG_INTERNAL_UPDATE_CCO_MAC, p_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static uint32_t iot_led_ctrl_ge_handle_data_send(iot_pkt_t* resp_pkt)
 | |
| {
 | |
|     ge_frame_data_send_set_subfn160_t *p_frame_hdr;
 | |
|     ge_frm_tail_t *p_frame_tl;
 | |
|     iot_pkt_t *p_frame_pkt;
 | |
|     uint8_t *p_start;
 | |
|     uint32_t frame_len, resp_data_len;
 | |
| 
 | |
|     /* attach 6bytes src mac in front of data. */
 | |
|     resp_data_len = iot_pkt_data_len(resp_pkt) + IOT_MAC_ADDR_LEN;
 | |
| 
 | |
|     frame_len = resp_data_len + sizeof(*p_frame_hdr) + sizeof(*p_frame_tl);
 | |
| 
 | |
|     if (NULL == (p_frame_pkt = iot_pkt_alloc(frame_len, IOT_LIGHT_MODULE_ID))) {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_start = iot_pkt_data(p_frame_pkt);
 | |
|     iot_pkt_put(p_frame_pkt, frame_len);
 | |
| 
 | |
|     p_frame_hdr = (ge_frame_data_send_set_subfn160_t *)p_start;
 | |
| 
 | |
|     /* Fill frame header. */
 | |
|     p_frame_hdr->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE;
 | |
|     p_frame_hdr->hdr.hdr.data_len = (uint8_t)(resp_data_len + IOT_MAC_ADDR_LEN);
 | |
|     p_frame_hdr->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
 | |
|     p_frame_hdr->hdr.subfn = PROTO_GE_DATA_CMD;
 | |
| 
 | |
|     /* Send to cco */
 | |
|     iot_mac_addr_cpy(p_frame_hdr->dest_mac,
 | |
|         iot_led_controller.pib_info.cco_mac);
 | |
| 
 | |
|     /* Fill frame body. */
 | |
|     p_frame_hdr->force_tx_connless = 0;
 | |
|     p_frame_hdr->force_noaggr = 0;
 | |
|     p_frame_hdr->resv = 0;
 | |
|     p_frame_hdr->data_type = 0;
 | |
| 
 | |
|     iot_mac_addr_cpy(p_frame_hdr->data, iot_led_controller.local_mac);
 | |
| 
 | |
|     os_mem_cpy(p_frame_hdr->data + IOT_MAC_ADDR_LEN, iot_pkt_data(resp_pkt),
 | |
|         resp_data_len - IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     p_frame_tl = (ge_frm_tail_t *)(p_frame_hdr->data + resp_data_len);
 | |
| 
 | |
|     p_frame_tl->check_sum = (uint16_t)ge_frm_checksum_calc(p_start,
 | |
|         (uint16_t)(resp_data_len + sizeof(*p_frame_hdr)));
 | |
|     p_frame_tl->tail = 0xFF;
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]frame send to GE.\n");
 | |
|     iot_light_data_dump(iot_pkt_data(p_frame_pkt),
 | |
|         iot_pkt_data_len(p_frame_pkt));
 | |
| 
 | |
|     /* TODO : send to ge */
 | |
| 
 | |
|     if (NULL != iot_led_controller.data_to_ge_fn) {
 | |
|         iot_led_controller.data_to_ge_fn(iot_pkt_data(p_frame_pkt),
 | |
|             (uint16_t)iot_pkt_data_len(p_frame_pkt));
 | |
|     } else {
 | |
|         iot_cus_printf("[LIGHT_DRV]no function for send data.\n");
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_frame_pkt);
 | |
|     iot_pkt_free(resp_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* get a valid ge frame from the data, return the frame header */
 | |
| ge_extend_fn_hdr_t *iot_ge_frame_format_check(uint8_t *data,
 | |
|     uint32_t data_len)
 | |
| {
 | |
|     ge_extend_fn_hdr_t *hdr = NULL;
 | |
|     uint16_t crc_data;
 | |
|     uint32_t pos = 0;
 | |
| 
 | |
|     while(pos < data_len) {
 | |
| 
 | |
|         if (pos + GE_FRM_CHECK_SUM_FIELD_POS > data_len) {
 | |
|             /* frame length error */
 | |
|             break;
 | |
|         }
 | |
|         hdr = (ge_extend_fn_hdr_t*)(data + pos);
 | |
|         if (hdr->hdr.preamble == GE_FRM_PREAMBLE_CODE &&
 | |
|             hdr->hdr.data_len <= GE_FRM_PLD_MAX_LEN &&
 | |
|             pos + hdr->hdr.data_len + GE_FRM_MIN_LEN <= data_len) {
 | |
|             /* crc check */
 | |
|             crc_data = iot_gree_get_crc_byte(
 | |
|                 &data[pos + hdr->hdr.data_len + GE_FRM_CHECK_SUM_FIELD_POS]);
 | |
|             if (crc_data == ge_frm_checksum_calc(data + pos, hdr->hdr.data_len +
 | |
|                 GE_FRM_CHECK_SUM_FIELD_POS) && GE_FRM_TAIL_CODE ==
 | |
|                 data[pos + hdr->hdr.data_len + GE_FRM_TAIL_CODE_FIELD_POS]) {
 | |
|                 return hdr;
 | |
|             }
 | |
|         }
 | |
|         pos++;
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint32_t iot_led_crtl_msg_post_to_led(iot_pkt_t *p_pkt_frame)
 | |
| {
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]frame receive from GE.\n");
 | |
|     uint8_t *pkt_data = iot_pkt_data(p_pkt_frame);
 | |
|     uint32_t pkt_data_len = iot_pkt_data_len(p_pkt_frame);
 | |
|     ge_extend_fn_hdr_t *hdr = NULL;
 | |
|     uint32_t fe_cnt = 0;
 | |
| 
 | |
|     iot_light_data_dump(pkt_data, pkt_data_len);
 | |
| 
 | |
|     while (pkt_data_len > 0) {
 | |
|         hdr = iot_ge_frame_format_check(pkt_data, pkt_data_len);
 | |
|         if (hdr == NULL) {
 | |
|             /* have not find vaild frame */
 | |
|             break;
 | |
|         }
 | |
|         if ((PROTO_GE_PLC_SET_CMD == hdr->hdr.fn) &&
 | |
|             (PROTO_CONN_IND_RPT_CMD == hdr->subfn)) {
 | |
|             iot_led_ctrl_ge_handle_connect_ind((uint8_t*)hdr);
 | |
|         } else if ((PROTO_GE_PLC_SET_CMD == hdr->hdr.fn) &&
 | |
|            (PROTO_GE_DATA_CMD == hdr->subfn)) {
 | |
|             iot_led_ctrl_ge_handle_data_recv((uint8_t*)hdr);
 | |
|         } else {
 | |
|             /* we donot need this frame. */
 | |
|             iot_cus_printf("[LIGHT_DRV]unknown %02X-%02X, dropped.\n",
 | |
|                 hdr->hdr.fn, hdr->subfn);
 | |
|         }
 | |
|         fe_cnt = (uint8_t*)hdr - pkt_data;
 | |
|         pkt_data_len -= (fe_cnt + hdr->hdr.data_len + GE_FRM_MIN_LEN);
 | |
|         pkt_data = (uint8_t*)hdr + hdr->hdr.data_len + GE_FRM_MIN_LEN;
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt_frame);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| void iot_led_crtl_msg_post_to_ge(iot_pkt_t* resp_pkt)
 | |
| {
 | |
|     if (ERR_OK == iot_led_ctrl_ge_handle_data_send(resp_pkt)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void iot_led_crtl_set_mac(uint8_t *cco)
 | |
| {
 | |
|     if (NULL != cco) {
 | |
|         os_mem_cpy(iot_led_controller.pib_info.cco_mac, cco, IOT_MAC_ADDR_LEN);
 | |
|         iot_light_save_led_info();
 | |
|     }
 | |
| 
 | |
|     if (mac_addr_is_valid_addr(iot_led_controller.pib_info.cco_mac)
 | |
|         && (!iot_led_controller.module_ready)) {
 | |
|         iot_led_controller.module_ready = true;
 | |
|         iot_led_controller.report_count = 0;
 | |
|         iot_led_controller.report_power_state = 0;
 | |
|     }
 | |
| 
 | |
|     if ((!mac_addr_is_valid_addr(iot_led_controller.pib_info.cco_mac))
 | |
|         && iot_led_controller.module_ready) {
 | |
|         iot_led_controller.module_ready = false;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void iot_led_ctrl_register_get_data_fn(void *fn)
 | |
| {
 | |
|     if (NULL != fn) {
 | |
|         iot_led_controller.data_to_ge_fn = (data_send_to_ge)fn;
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint32_t iot_led_ctrl_task_init(void)
 | |
| {
 | |
|     iot_task_config_t task_cfg;
 | |
|     iot_oem_base_cfg_t *oem_base_cfg;
 | |
| 
 | |
|     /* Clear led object. */
 | |
|     os_mem_set(&iot_led_controller, 0x0, sizeof(iot_led_controller));
 | |
| 
 | |
|     /* gpio pin config. */
 | |
|     iot_led_controller.led.gpio_power_on = IOT_LIGHT_GPIO_POWER;
 | |
|     iot_led_controller.led.gpio_relay = IOT_LIGHT_GPIO_RELAY;
 | |
| 
 | |
|     /* Set led type for default */
 | |
|     iot_led_controller.led.param.device_type = DEV_TYPE_LED_150W;
 | |
| 
 | |
|     /* TODO : set unready. */
 | |
|     iot_led_controller.module_ready = false;
 | |
| #if (ENABLE_LED_CTRL_HARDWARE)
 | |
|     /* initialize hardware for this module. */
 | |
|     if (ERR_OK != iot_light_drv_initialize_hardware()) {
 | |
|         iot_cus_printf("[LIGHT_DRV]initialize hardware failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     iot_oem_get_base_cfg(&oem_base_cfg);
 | |
| 
 | |
|     iot_mac_addr_cpy(iot_led_controller.local_mac, oem_base_cfg->module_mac);
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]local cco[%x:%x:%x:%x:%x:%x].\n",
 | |
|         iot_led_controller.local_mac[0], iot_led_controller.local_mac[1],
 | |
|         iot_led_controller.local_mac[2], iot_led_controller.local_mac[3],
 | |
|         iot_led_controller.local_mac[4], iot_led_controller.local_mac[5]);
 | |
| 
 | |
|     /* create task */
 | |
|     os_mem_set(&task_cfg, 0x0, sizeof(task_cfg));
 | |
|     task_cfg.stack_size = IOT_LED_CTRL_TASK_STACK_SIZE;
 | |
|     task_cfg.task_prio = IOT_GRAPP_PROTO_TASK_PRIO;
 | |
|     task_cfg.msg_size = sizeof(iot_led_ctrl_msg_t);
 | |
|     task_cfg.msg_cnt = IOT_LED_CTRL_TASK_POOL_SIZE;
 | |
|     task_cfg.queue_cnt = 1;
 | |
|     task_cfg.queue_cfg[0].quota = 0;
 | |
|     task_cfg.msg_exe_func = iot_led_ctrl_task_msg_exe;
 | |
|     task_cfg.msg_cancel_func = iot_led_ctrl_task_msg_cancel;
 | |
| 
 | |
|     iot_led_controller.task = iot_task_create(IOT_LIGHT_MODULE_ID, &task_cfg);
 | |
| 
 | |
|     if (NULL == iot_led_controller.task) {
 | |
|         iot_cus_printf("[LIGHT_DRV]create task failed.\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     iot_led_controller.timer = os_create_timer
 | |
|         (IOT_LIGHT_MODULE_ID, true, iot_led_ctrl_task_timer_exe, NULL);
 | |
| 
 | |
|     if (0 == iot_led_controller.timer) {
 | |
|         iot_cus_printf("[LIGHT_DRV]create timer failed.\n");
 | |
|         iot_task_delete(iot_led_controller.task);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     os_start_timer(iot_led_controller.timer, IOT_LED_TIMER_INTERVAL);
 | |
| 
 | |
|     iot_led_controller.report_timer = os_create_timer
 | |
|         (IOT_LIGHT_MODULE_ID, false, iot_led_ctrl_report_timer_exe,
 | |
|         (void*)&iot_led_controller.report_power_state);
 | |
|     if (0 == iot_led_controller.report_timer) {
 | |
|         iot_cus_printf("[LIGHT_DRV]create report_timer failed.\n");
 | |
|         iot_task_delete(iot_led_controller.task);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     iot_proto_custom_pib_info_load(&iot_led_controller.pib_info,
 | |
|         sizeof(iot_led_pib_info_t));
 | |
|     iot_led_controller.led.group = iot_led_controller.pib_info.group;
 | |
|     iot_led_controller.led.param.light_level_a =
 | |
|         iot_led_controller.pib_info.level_a;
 | |
|     iot_led_controller.led.param.light_level_b =
 | |
|         iot_led_controller.pib_info.level_b;
 | |
|     iot_cus_printf("[LIGHT_DRV]load group=%d level_a=%d level_b=%d\n",
 | |
|         iot_led_controller.led.group,
 | |
|         iot_led_controller.led.param.light_level_a,
 | |
|         iot_led_controller.led.param.light_level_b);
 | |
|     iot_proto_register_update_cco_mac_to_uplayer(
 | |
|         iot_led_ctrl_update_cco_mac);
 | |
| 
 | |
|     /* init data check. */
 | |
|     iot_led_controller.check_leakage_current.first_run = true;
 | |
|     iot_led_controller.check_leakage_current.delta_cnt =
 | |
|         IOT_LED_CTRL_DATA_CHECK_DELTA_LEN_LEAKAGE;
 | |
|     iot_led_controller.check_leakage_current.sample_cnt =
 | |
|         IOT_LED_CTRL_DATA_CHECK_SAMPLE_LEN_LEAKAGE;
 | |
|     iot_led_controller.check_leakage_current.delta_value =
 | |
|         IOT_LED_CTRL_DATA_CHECK_DELTA_VALUE_LEAKAGE;
 | |
| 
 | |
|     iot_led_controller.check_meter_voltage.first_run = true;
 | |
|     iot_led_controller.check_meter_voltage.delta_cnt =
 | |
|         IOT_LED_CTRL_DATA_CHECK_DELTA_LEN_METER;
 | |
|     iot_led_controller.check_meter_voltage.sample_cnt =
 | |
|         IOT_LED_CTRL_DATA_CHECK_SAMPLE_LEN_METER;
 | |
|     iot_led_controller.check_meter_voltage.delta_value =
 | |
|         IOT_LED_CTRL_DATA_CHECK_DELTA_VALUE_METER;
 | |
| 
 | |
| /* TODO : Disable ADC feature. Wait ADC code from iot2.2. */
 | |
| #if (0)//IOT_LIGHT_CTRL_ADC_MODULE_ENABLE
 | |
|     /* Register leak current callback function. */
 | |
|     iot_energe_meter_leak_curr_cb_register(iot_led_crtl_leakage_evt_func);
 | |
|     /* Register get meter data callback function. */
 | |
|     iot_energe_meter_get_meter_data_cb_register(iot_led_ctrl_input_in_meter_param);
 | |
| #endif
 | |
| 
 | |
|     /* power up at 100% */
 | |
|     iot_light_drv_set_light_level(IOT_LIGHT_CHAN_ALL, IOT_LIGHT_BRIGHTNESS_RAW_LEVEL_MAX);
 | |
| 
 | |
| 
 | |
|     iot_cus_printf("[LIGHT_DRV]led control task create successfully.\n");
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 |