1492 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1492 lines
		
	
	
		
			45 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.
 | |
| 
 | |
| ****************************************************************************/
 | |
| 
 | |
| /* os_ship header files */
 | |
| #include "os_timer_api.h"
 | |
| 
 | |
| /* iot common header files */
 | |
| #include "iot_board_api.h"
 | |
| #include "iot_app_api.h"
 | |
| #include "iot_io_api.h"
 | |
| #include "iot_sg_ctrl.h"
 | |
| #include "iot_plc_msg_sta_api.h"
 | |
| #include "iot_plc_sta_api.h"
 | |
| #include "proto_3762.h"
 | |
| #include "proto_3762_vendor.h"
 | |
| #include "proto_spg.h"
 | |
| #include "proto_645.h"
 | |
| #include "iot_cli_sg_ctrl_api.h"
 | |
| #include "iot_sg_msg.h"
 | |
| #include "iot_oem_api.h"
 | |
| #include "iot_sg_ctrl_gw_app.h"
 | |
| #include "iot_sg_ctrl_nw_app.h"
 | |
| #include "iot_gpio_api.h"
 | |
| #include "os_utils_api.h"
 | |
| 
 | |
| #if (IOT_SG_CONTROLLER_ENABLE)
 | |
| 
 | |
| static void iot_sg_ctrl_post_task_msg(uint16_t msg_type, uint16_t msg_id,
 | |
|     void *data);
 | |
| static void iot_sg_ctrl_proto_sta_read_meter(uint8_t *data, uint16_t len,
 | |
|     uint8_t app_sn);
 | |
| int iot_mcp23017_gpio_ex_init(void);
 | |
| 
 | |
| iot_sg_ctrl_global_t *sg_ctrl_global = NULL;
 | |
| extern iot_ctrl_drv_t g_sg_ctrl_drv;
 | |
| extern iot_ctrl_drv_t g_spg_ctrl_drv;
 | |
| net_led_ctrl_t ckb_led_blink[EXT_LED_MAX];
 | |
| 
 | |
| void iot_sg_ctrl_get_freq_band_msg()
 | |
| {
 | |
|     iot_plc_query_band_info(sg_ctrl_global->app_handle,
 | |
|         IOT_PLC_API_REQ_ID_DEFAULT);
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_set_freq_band_msg(uint8_t freq_band)
 | |
| {
 | |
|     sg_ctrl_global->config_freq_band = freq_band;
 | |
|     iot_plc_set_freq_band(sg_ctrl_global->app_handle,
 | |
|         IOT_PLC_API_REQ_ID_DEFAULT, freq_band);
 | |
| }
 | |
| 
 | |
| static uint32_t iot_sg_ctrl_init_scan_table()
 | |
| {
 | |
|     sg_ctrl_global->scan_handle.table = iot_addr_hash_table_create(
 | |
|         IOT_SMART_GRID_MID, IOT_SG_CTRL_SCAN_MAX_CNT, sizeof(scan_node_info_t),
 | |
|         IOT_SG_CTRL_SCAN_HASH_TABLE_SIZE);
 | |
|     if (!sg_ctrl_global->scan_handle.table) {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     sg_ctrl_global->scan_handle.scan_node_list = (scan_node_info_t **)
 | |
|         os_mem_malloc(IOT_SMART_GRID_MID, IOT_SG_CTRL_SCAN_MAX_CNT *
 | |
|             sizeof(scan_node_info_t *));
 | |
|     if (!sg_ctrl_global->scan_handle.scan_node_list) {
 | |
|         iot_addr_hash_table_delete(sg_ctrl_global->scan_handle.table);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     os_mem_set(sg_ctrl_global->scan_handle.scan_node_list, 0,
 | |
|         IOT_SG_CTRL_SCAN_MAX_CNT * sizeof(scan_node_info_t *));
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_sg_ctrl_get_scan_node_index()
 | |
| {
 | |
|     uint8_t i;
 | |
| 
 | |
|     for (i = 0; i < IOT_SG_CTRL_SCAN_MAX_CNT; i++) {
 | |
|         if (!sg_ctrl_global->scan_handle.scan_node_list[i]) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     return i;
 | |
| }
 | |
| 
 | |
| static uint32_t iot_sg_ctrl_add_scan_node(uint8_t* addr, uint32_t nid,
 | |
|     uint8_t band_id)
 | |
| {
 | |
|     scan_node_info_t *node_entry = NULL;
 | |
|     uint8_t index;
 | |
| 
 | |
|     /* check node */
 | |
|     node_entry = (scan_node_info_t *)iot_addr_hash_table_find(
 | |
|         sg_ctrl_global->scan_handle.table, addr);
 | |
| 
 | |
|     if (node_entry) {
 | |
|         /* refresh age */
 | |
|         node_entry->age = IOT_SG_CTRL_MAX_AGE;
 | |
|         return ERR_OK;
 | |
|     }
 | |
| 
 | |
|     /* add new node info */
 | |
|     if (sg_ctrl_global->scan_handle.total_scan_cnt >=
 | |
|         IOT_SG_CTRL_SCAN_MAX_CNT) {
 | |
|         iot_sg_ctrl_printf("%s add failed, total cnt : %d\n", __FUNCTION__,
 | |
|             sg_ctrl_global->scan_handle.total_scan_cnt);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     /* get new node index */
 | |
|     index = iot_sg_ctrl_get_scan_node_index();
 | |
|     IOT_ASSERT(index < IOT_SG_CTRL_SCAN_MAX_CNT);
 | |
| 
 | |
|     node_entry = (scan_node_info_t *)iot_addr_hash_table_alloc(
 | |
|         sg_ctrl_global->scan_handle.table);
 | |
|     if (node_entry) {
 | |
|         sg_ctrl_global->scan_handle.total_scan_cnt++;
 | |
|         node_entry->age = IOT_SG_CTRL_MAX_AGE;
 | |
|         node_entry->node_info.band_id = band_id;
 | |
|         node_entry->node_info.nid = nid;
 | |
|         node_entry->index = index;
 | |
|         iot_mac_addr_cpy(node_entry->entry.addr, addr);
 | |
|         iot_mac_addr_cpy(node_entry->node_info.addr, addr);
 | |
|         iot_mac_addr_reverse(node_entry->node_info.addr);
 | |
|         iot_addr_hash_table_add(sg_ctrl_global->scan_handle.table,
 | |
|             &node_entry->entry);
 | |
|         sg_ctrl_global->scan_handle.scan_node_list[index] = node_entry;
 | |
|         iot_sg_ctrl_printf("%s:  addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
 | |
|             __FUNCTION__, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
 | |
|         return ERR_OK;
 | |
|     }
 | |
|     iot_sg_ctrl_printf("add dest failed, alloc failed\n");
 | |
|     return ERR_FAIL;
 | |
| }
 | |
| 
 | |
| static uint32_t iot_sg_ctrl_del_scan_node(uint8_t* addr)
 | |
| {
 | |
|     scan_node_info_t *node_entry = NULL;
 | |
| 
 | |
|     if (!sg_ctrl_global->scan_handle.total_scan_cnt) {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     node_entry = (scan_node_info_t *)iot_addr_hash_table_find(
 | |
|         sg_ctrl_global->scan_handle.table, addr);
 | |
| 
 | |
|     if (!node_entry) {
 | |
|         return ERR_OK;
 | |
|     }
 | |
|     /* clr node list entry */
 | |
|     sg_ctrl_global->scan_handle.scan_node_list[node_entry->index] = NULL;
 | |
|     /* free entry */
 | |
|     iot_addr_hash_table_remove(sg_ctrl_global->scan_handle.table,
 | |
|         &(node_entry->entry));
 | |
|     iot_addr_hash_table_free(sg_ctrl_global->scan_handle.table,
 | |
|         &(node_entry->entry));
 | |
|     sg_ctrl_global->scan_handle.total_scan_cnt--;
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_scan_node_clear()
 | |
| {
 | |
|     uint16_t i;
 | |
|     uint16_t j;
 | |
|     scan_node_info_t *tmp_entry;
 | |
| 
 | |
|     for (i = 0, j = 0; ((i < IOT_SG_CTRL_SCAN_MAX_CNT) &&
 | |
|         (j < sg_ctrl_global->scan_handle.total_scan_cnt)); i++) {
 | |
|         tmp_entry = sg_ctrl_global->scan_handle.scan_node_list[i];
 | |
|         if (!tmp_entry) {
 | |
|             continue;
 | |
|         }
 | |
|         j++;
 | |
|         /* clr node list entry */
 | |
|         sg_ctrl_global->scan_handle.scan_node_list[tmp_entry->index] = NULL;
 | |
|         /* free entry */
 | |
|         iot_addr_hash_table_remove(sg_ctrl_global->scan_handle.table,
 | |
|             &(tmp_entry->entry));
 | |
|         iot_addr_hash_table_free(sg_ctrl_global->scan_handle.table,
 | |
|             &(tmp_entry->entry));
 | |
|     }
 | |
|     sg_ctrl_global->scan_handle.total_scan_cnt = 0;
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_scan_node_refresh()
 | |
| {
 | |
|     uint8_t i;
 | |
|     scan_node_info_t *tmp_entry;
 | |
| 
 | |
|     if (sg_ctrl_global->scan_handle.scan_period++ <
 | |
|         IOT_SG_CTRL_MAX_CHECK_PERIODIC) {
 | |
|         return;
 | |
|     }
 | |
|     sg_ctrl_global->scan_handle.scan_period = 0;
 | |
|     if (!sg_ctrl_global->scan_handle.total_scan_cnt) {
 | |
|         return;
 | |
|     }
 | |
|     for (i = 0; i < IOT_SG_CTRL_SCAN_MAX_CNT; i++) {
 | |
|         tmp_entry = sg_ctrl_global->scan_handle.scan_node_list[i];
 | |
|         if (!tmp_entry) {
 | |
|             continue;
 | |
|         }
 | |
|         tmp_entry->age--;
 | |
|         if (!tmp_entry->age) {
 | |
|             iot_sg_ctrl_del_scan_node(tmp_entry->node_info.addr);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static inline void iot_sg_ctrl_disable_scan_mode()
 | |
| {
 | |
|     if (sg_ctrl_global->scan_handle.scan_runing) {
 | |
|         /* disable discovery mode */
 | |
|         iot_plc_set_discovery_mode(sg_ctrl_global->app_handle, 0, 0);
 | |
|         sg_ctrl_global->scan_handle.scan_runing = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static uint32_t iot_sg_ctrl_enable_scan_mode()
 | |
| {
 | |
|     if (!sg_ctrl_global->scan_handle.scan_runing) {
 | |
|         /* start nw fmt */
 | |
|         iot_plc_start_nw_fmt(sg_ctrl_global->app_handle, 0);
 | |
| 
 | |
|         /* enable discovery mode */
 | |
|         iot_plc_set_discovery_mode(sg_ctrl_global->app_handle, 0, 1);
 | |
|         sg_ctrl_global->scan_handle.scan_runing = 1;
 | |
|     }
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_get_scan_node_cnt()
 | |
| {
 | |
|     return sg_ctrl_global->scan_handle.total_scan_cnt;
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_get_scan_node_info(ctrl_node_info_t *node_list,
 | |
|     uint8_t start_index, uint8_t cnt)
 | |
| {
 | |
|     uint8_t i;
 | |
|     uint8_t node_index;
 | |
|     uint8_t tmp_cnt = 0;
 | |
| 
 | |
|     if ((!sg_ctrl_global->scan_handle.total_scan_cnt) || (!cnt)) {
 | |
|         return tmp_cnt;
 | |
|     }
 | |
|     for (i = 0, node_index = 0; i < IOT_SG_CTRL_SCAN_MAX_CNT; i++) {
 | |
|         if (sg_ctrl_global->scan_handle.scan_node_list[i]) {
 | |
|             node_index++;
 | |
|         }
 | |
|         if (node_index >= start_index) {
 | |
|             os_mem_cpy(node_list + tmp_cnt,
 | |
|                 &(sg_ctrl_global->scan_handle.scan_node_list[i]->node_info),
 | |
|                 sizeof(*node_list));
 | |
|             tmp_cnt++;
 | |
|             if (tmp_cnt >= cnt) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return tmp_cnt;
 | |
| }
 | |
| 
 | |
| uint16_t iot_sg_ctrl_get_vendor_id()
 | |
| {
 | |
|     return iot_board_load_user_vendor_id();
 | |
| }
 | |
| 
 | |
| uint16_t iot_sg_ctrl_get_chip_code()
 | |
| {
 | |
|     uint16_t chip_code, tmp_chip_code;
 | |
|     chip_code = iot_oem_get_chip_code();
 | |
|     if (0 == chip_code) {
 | |
|         /* if chip code is invalid, let's set chip code to 01 */
 | |
|         chip_code = 0x3031;
 | |
|     } else {
 | |
|         tmp_chip_code = chip_code;
 | |
|         chip_code = (tmp_chip_code << 8) | ((tmp_chip_code & 0xFF00) >> 8);
 | |
|     }
 | |
|     return chip_code;
 | |
| }
 | |
| 
 | |
| static uint32_t iot_sg_ctrl_check_drv(iot_pkt_t *data)
 | |
| {
 | |
|     if (sg_ctrl_global->proto_type != IOT_CTRL_PROTO_INVALID) {
 | |
|         return ERR_OK;
 | |
|     }
 | |
|     if (sg_ctrl_global->ctrl_drv != (&g_sg_ctrl_drv)) {
 | |
|         /* set gw ctrl drv */
 | |
|         sg_ctrl_global->ctrl_drv = (&g_sg_ctrl_drv);
 | |
|     }
 | |
|     sg_ctrl_global->proto_type = IOT_CTRL_PROTO_3762;
 | |
|     if (ERR_OK != sg_ctrl_global->ctrl_drv->check_data_handle(data)) {
 | |
|         /* set spg ctrl drv */
 | |
|         sg_ctrl_global->ctrl_drv = (&g_spg_ctrl_drv);
 | |
|         sg_ctrl_global->proto_type = IOT_CTRL_PROTO_SPG;
 | |
|         /* check spg data */
 | |
|         if ((ERR_OK != sg_ctrl_global->ctrl_drv->check_data_handle(data)) ||
 | |
|             (ERR_OK != sg_ctrl_global->ctrl_drv->init())) {
 | |
|             sg_ctrl_global->proto_type = IOT_CTRL_PROTO_INVALID;
 | |
|             return ERR_NOSUPP;
 | |
|         }
 | |
|     }
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_cli_callback(void *param, iot_pkt_t *pkt)
 | |
| {
 | |
|     (void)param;
 | |
|     iot_sg_ctrl_post_task_msg(IOT_SG_CTRL_MSG_TYPE_CLI, IOT_SG_CTRL_MSG_ID_CLI,
 | |
|         pkt);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_cli_proto_connect_status_rpt(uint8_t *mac,
 | |
|     uint8_t ready)
 | |
| {
 | |
|     iot_pkt_t *buf_pkt;
 | |
|     iot_cli_sg_ctrl_is_ready_t *rsp;
 | |
| 
 | |
|     buf_pkt = iot_pkt_alloc(iot_cli_sg_get_headroom_req() +
 | |
|         sizeof(iot_cli_sg_ctrl_is_ready_t), IOT_SMART_GRID_MID);
 | |
|     if (!buf_pkt) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp = (iot_cli_sg_ctrl_is_ready_t*)iot_pkt_reserve(buf_pkt,
 | |
|         iot_cli_sg_get_headroom_req());
 | |
|     rsp->ready = ready;
 | |
|     iot_mac_addr_cpy(rsp->mac, mac);
 | |
| 
 | |
|     iot_cli_sg_send_data_to_cli_interface(buf_pkt,
 | |
|         IOT_CLI_SG_CTRL_MSG_RPT_IS_READY, 0);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_cli_rpt_data(uint8_t *data, uint16_t len)
 | |
| {
 | |
|     iot_pkt_t *buf_pkt;
 | |
|     iot_cli_sg_ctrl_data_ul_t *rsp;
 | |
|     uint16_t data_len = 0;
 | |
| 
 | |
|     data_len = iot_cli_sg_get_headroom_req();
 | |
|     data_len += len;
 | |
|     data_len += sizeof(iot_cli_sg_ctrl_data_ul_t);
 | |
|     buf_pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
 | |
|     if (!buf_pkt) {
 | |
|         return;
 | |
|     }
 | |
|     rsp = (iot_cli_sg_ctrl_data_ul_t *)iot_pkt_reserve(buf_pkt,
 | |
|         iot_cli_sg_get_headroom_req());
 | |
|     rsp->data_len = len;
 | |
|     rsp->proto = sg_ctrl_global->proto_type;
 | |
|     os_mem_cpy(rsp->data, data, len);
 | |
|     iot_cli_sg_send_data_to_cli_interface(buf_pkt,
 | |
|         IOT_CLI_SG_CTRL_MSG_RPT_DATA_UL, 0);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_cli_proto_connect(uint8_t req_id, uint8_t *data,
 | |
|     uint16_t len)
 | |
| {
 | |
|     iot_cli_sg_ctrl_join_node_dl *cmd = (iot_cli_sg_ctrl_join_node_dl*)data;
 | |
| 
 | |
|     if (len < sizeof(iot_cli_sg_ctrl_join_node_dl)) {
 | |
|         /* invalid data length */
 | |
|         iot_sg_ctrl_printf("%s data error \n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
|     sg_ctrl_global->dev_ready = 0;
 | |
|     iot_mac_addr_cpy(sg_ctrl_global->dst_mac_addr, cmd->node);
 | |
|     iot_plc_ctrl_proto_connect(sg_ctrl_global->app_handle,
 | |
|         req_id, cmd->node);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_cli_send_data(iot_pkt_t *pkt)
 | |
| {
 | |
|     iot_cli_sg_ctrl_data_dl_t *dl_data =
 | |
|         (iot_cli_sg_ctrl_data_dl_t *)iot_pkt_data(pkt);
 | |
|     uint32_t ret = ERR_OK;
 | |
| 
 | |
|     switch (iot_sg_ctrl_get_connect_role()) {
 | |
|     case IOT_PLC_DEV_ROLE_INVALID:
 | |
|     case IOT_PLC_DEV_ROLE_CCO:
 | |
|         if ((IOT_CTRL_PROTO_SPG != dl_data->proto) &&
 | |
|             (IOT_CTRL_PROTO_3762 != dl_data->proto)) {
 | |
|             iot_sg_ctrl_printf("sg ctrl not support proto :%lu \n",
 | |
|                 dl_data->proto);
 | |
|             iot_pkt_free(pkt);
 | |
|             ret = ERR_FAIL;
 | |
|             break;
 | |
|         }
 | |
|         sg_ctrl_global->proto_type = dl_data->proto;
 | |
|         iot_pkt_pull(pkt, sizeof(*dl_data));
 | |
|         ret = iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_MR_CCO,
 | |
|             (uint8_t)dl_data->app_sn, pkt);
 | |
|         break;
 | |
|     case IOT_PLC_DEV_ROLE_STA:
 | |
|     case IOT_PLC_DEV_ROLE_PCO:
 | |
|         iot_pkt_pull(pkt, sizeof(*dl_data));
 | |
|         ret = iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_MR_STA,
 | |
|             (uint8_t)dl_data->app_sn, pkt);
 | |
|         break;
 | |
|     default:
 | |
|         iot_pkt_free(pkt);
 | |
|         ret = ERR_FAIL;
 | |
|         break;
 | |
|     }
 | |
|     if (ERR_OK == ret) {
 | |
|         iot_sg_ctrl_printf("ctrl msg send ok \n");
 | |
|     } else {
 | |
|         iot_sg_ctrl_printf("ctrl msg send error \n");
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_handle_cli_msg(iot_sg_msg_t *sg_msg)
 | |
| {
 | |
|     iot_pkt_t *pkt = (iot_pkt_t *)sg_msg->data;
 | |
|     iot_cli_sg_msg_header_t *hdr;
 | |
| 
 | |
|     hdr = (iot_cli_sg_msg_header_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD);
 | |
|     iot_sg_ctrl_printf("ctrl cli msg: %lu \n", hdr->msg_id);
 | |
|     switch (hdr->msg_id) {
 | |
|     case IOT_CLI_SG_CTRL_MSG_REQ_JOIN_NODE:
 | |
|     {
 | |
|         iot_sg_ctrl_cli_proto_connect(hdr->req_id, iot_pkt_data(pkt),
 | |
|             (uint16_t)iot_pkt_data_len(pkt));
 | |
|         iot_pkt_free(pkt);
 | |
|         break;
 | |
|     }
 | |
|     case IOT_CLI_SG_CTRL_MSG_REQ_DATA_DL:
 | |
|     {
 | |
|         iot_sg_ctrl_cli_send_data(pkt);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         iot_pkt_free(pkt);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_pool_sn_exist(info_pool_t *pool, uint16_t app_sn,
 | |
|     uint8_t clr_flag)
 | |
| {
 | |
|     uint16_t i;
 | |
| 
 | |
|     if (pool->remain_cnt == IOT_SG_CTRL_POOL_NUM) {
 | |
|         return false;
 | |
|     }
 | |
|     for (i = 0; i < IOT_SG_CTRL_POOL_NUM; i++) {
 | |
|         if (pool->frm_info[i].send_pkt != NULL) {
 | |
|             if (pool->frm_info[i].app_sn == app_sn) {
 | |
|                 if (clr_flag) {
 | |
|                     iot_pkt_free(pool->frm_info[i].send_pkt);
 | |
|                     os_mem_set(&pool->frm_info[i], 0, sizeof(frame_info_t));
 | |
|                     pool->remain_cnt++;
 | |
|                 }
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_ul_sn_exist(uint16_t app_sn)
 | |
| {
 | |
|     uint16_t i;
 | |
| 
 | |
|     for (i = 0; i < IOT_SG_CTRL_UL_SIZE; i++) {
 | |
|         if (sg_ctrl_global->ul_sn[i] == (app_sn + 1)) {
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
|     sg_ctrl_global->ul_sn_index++;
 | |
|     if (sg_ctrl_global->ul_sn_index >= IOT_SG_CTRL_UL_SIZE) {
 | |
|         sg_ctrl_global->ul_sn_index = 0;
 | |
|     }
 | |
|     sg_ctrl_global->ul_sn[sg_ctrl_global->ul_sn_index] = app_sn + 1;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| static int8_t iot_sg_ctrl_pool_find_free_index(info_pool_t *pool)
 | |
| {
 | |
|     int8_t index;
 | |
|     int8_t found_indx = -1;
 | |
| 
 | |
|     for (index = 0; index < IOT_SG_CTRL_POOL_NUM; index++) {
 | |
|         if (pool->frm_info[index].send_pkt == NULL) {
 | |
|             found_indx = index;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return found_indx;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_sg_ctrl_pool_add_data(info_pool_t *pool, iot_pkt_t *add_pkt,
 | |
|     uint8_t index, uint16_t app_sn, uint8_t cmd_type, uint8_t retry_flag)
 | |
| {
 | |
|     if (pool->frm_info[index].send_pkt == NULL) {
 | |
|         pool->remain_cnt--;
 | |
|         os_mem_set(&pool->frm_info[index], 0, sizeof(frame_info_t));
 | |
|         pool->frm_info[index].app_sn = app_sn;
 | |
|         pool->frm_info[index].send_pkt = add_pkt;
 | |
|         pool->frm_info[index].send_cnt = 0;
 | |
|         if (!retry_flag) {
 | |
|             pool->frm_info[index].span_cnt = IOT_SG_CTRL_MAX_LIFE_SPAN_CNT -
 | |
|                 IOT_SG_CTRL_APP_RETRY_INTV_CNT;
 | |
|         } else {
 | |
|             pool->frm_info[index].span_cnt = 0;
 | |
|         }
 | |
|         pool->frm_info[index].cmd_type = cmd_type;
 | |
|         return ERR_OK;
 | |
|     } else {
 | |
|         return ERR_EXIST;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_rpt_cco_data(iot_pkt_t *rev_pkt)
 | |
| {
 | |
|     if (sg_ctrl_global->uart_h) {
 | |
|         iot_uart_send(sg_ctrl_global->uart_h, rev_pkt, NULL);
 | |
|     } else {
 | |
|         iot_sg_ctrl_cli_rpt_data(iot_pkt_data(rev_pkt),
 | |
|             (uint16_t)iot_pkt_data_len(rev_pkt));
 | |
|         iot_pkt_free(rev_pkt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_rpt_sta_data(uint8_t *data, uint16_t data_len, uint8_t msg_id)
 | |
| {
 | |
|     if (sg_ctrl_global->uart_h) {
 | |
|         sg_ctrl_global->ctrl_drv->event_report_handle(
 | |
|             (uint8_t)sg_ctrl_global->app_sn, sg_ctrl_global->dst_mac_addr,
 | |
|             0, sg_ctrl_global->proto_type, msg_id, data, data_len);
 | |
|     } else {
 | |
|         iot_sg_ctrl_cli_rpt_data(data, data_len);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_post_task_msg(uint16_t msg_type, uint16_t msg_id,
 | |
|     void *data)
 | |
| {
 | |
|     iot_task_msg_t *msg;
 | |
|     iot_ctrl_task_msg_t *task_msg;
 | |
|     iot_task_h task_hdl = sg_ctrl_global->task_handle;
 | |
| 
 | |
|     msg = iot_task_alloc_msg(task_hdl);
 | |
|     if (!msg) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     task_msg = (iot_ctrl_task_msg_t*)msg;
 | |
|     task_msg->msg.type = msg_type;
 | |
|     task_msg->msg.id = msg_id;
 | |
|     task_msg->data = data;
 | |
|     iot_task_queue_msg(sg_ctrl_global->task_handle, &task_msg->msg,
 | |
|         IOT_SG_CTRL_TASK_QUEUE_HP);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_periodic_timer_func(timer_id_t timer_id,
 | |
|     void *arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     (void)arg;
 | |
|     iot_sg_ctrl_post_task_msg(IOT_SG_CTRL_MSG_TYPE_TIME,
 | |
|         IOT_SG_CTRL_MSG_ID_TIMER_CHECK, NULL);
 | |
| }
 | |
| 
 | |
| /* once received a uart data, allocate a pkt, then post a msg to handle
 | |
|  * the data, the pkt will be transferred
 | |
|  */
 | |
| static void iot_sg_ctrl_uart_meter_port_func(uint8_t* buffer,
 | |
|     uint32_t buffer_len, uint8_t is_full_frame, uint32_t invalid_data_len)
 | |
| {
 | |
|     iot_pkt_t *pkt;
 | |
| 
 | |
|     (void)invalid_data_len;
 | |
|     (void)is_full_frame;
 | |
|     pkt = iot_pkt_alloc(buffer_len, IOT_SMART_GRID_MID);
 | |
|     if (pkt) {
 | |
|         os_mem_cpy(iot_pkt_put(pkt, buffer_len), buffer, buffer_len);
 | |
|         iot_sg_ctrl_post_task_msg(IOT_SG_CTRL_MSG_TYPE_UART,
 | |
|             IOT_SG_CTRL_MSG_ID_UART_RECV, pkt);
 | |
|     } else {
 | |
|         iot_sg_ctrl_printf("%s: alloc failed\n", __FUNCTION__);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_read_meter(uint8_t *data, uint16_t datalen, uint16_t sn)
 | |
| {
 | |
|     if (sg_ctrl_global->app_proto == IOT_SG_APP_CTRL_PROTO_GW) {
 | |
|         iot_sg_ctrl_gw_read_meter(data, datalen, sn);
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint32_t iot_sg_ctrl_config_uart(uint32_t baud, uint8_t parity,
 | |
|     uint8_t data, uint8_t stop, iot_frame_fmt *fmt)
 | |
| {
 | |
|     uint8_t ret = 0;
 | |
| 
 | |
|     ret = iot_uart_set_config(sg_ctrl_global->uart_h, baud, parity, data, stop);
 | |
|     if (!ret)
 | |
|         goto out;
 | |
|     ret = (uint8_t)iot_uart_set_frame(sg_ctrl_global->uart_h, fmt);
 | |
|     if (!ret)
 | |
|         goto out;
 | |
|     /* report the data to app after 3 bytes' interval */
 | |
|     ret = iot_uart_set_threshold(sg_ctrl_global->uart_h, UART_THR_RXTIMEOUT, 3);
 | |
|     if (!ret)
 | |
|         goto out;
 | |
|     /* report the data to app once received 100 bytes */
 | |
|     ret = iot_uart_set_threshold(sg_ctrl_global->uart_h, UART_THR_RXFULL, 100);
 | |
| out:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static iot_uart_h iot_sg_ctrl_open_uart(uint8_t port)
 | |
| {
 | |
|     iot_uart_h uart = NULL;
 | |
|     uart = iot_uart_open(port, iot_sg_ctrl_uart_meter_port_func,
 | |
|         IOT_SG_CTRL_UART_RECV_BUF_SIZE, NULL);
 | |
|     return uart;
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_set_cfg_after_app_reg()
 | |
| {
 | |
|     iot_plc_cfg_set_req_t cfg = {0};
 | |
|     iot_plc_app_h app_hdl = sg_ctrl_global->app_handle;
 | |
| 
 | |
|     /* enable whitelist */
 | |
|     iot_plc_set_whitelist(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|         IOT_PLC_WL_ENABLE, 0, NULL);
 | |
| 
 | |
|     /* stop network formation */
 | |
|     iot_plc_stop_nw_fmt(app_hdl);
 | |
| 
 | |
|     /* query device infor */
 | |
|     iot_plc_query_dev_info(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT);
 | |
| 
 | |
|     /* set configuration of local device */
 | |
|     cfg.reset = 1;
 | |
|     cfg.dev_type_valid = 1;
 | |
|     cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
 | |
|     iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
 | |
| 
 | |
|     /* disable watchdog */
 | |
|     iot_plc_wdg_set(app_hdl, 0, 0);
 | |
| 
 | |
|     /* start reload timer */
 | |
|     os_start_timer(sg_ctrl_global->ctrl_timer,
 | |
|         IOT_SG_CTRL_PERIODIC_TIMER_INTERVAL);
 | |
| }
 | |
| 
 | |
| void iot_ctrl_uart_send(iot_pkt_t *pkt)
 | |
| {
 | |
|     iot_uart_send(sg_ctrl_global->uart_h, pkt, NULL);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_send_status_rpt(
 | |
|     iot_plc_ctrl_proto_state_rpt_t *plc_rpt)
 | |
| {
 | |
|     uint8_t role = PROTO_CTRL_DEV_ROLE_STA;
 | |
|     uint8_t event = IOT_CTRL_EVENT_DEVICE_DISCONNECTED;
 | |
| 
 | |
|     if (plc_rpt->role == IOT_PLC_DEV_ROLE_CCO) {
 | |
|         role = PROTO_CTRL_DEV_ROLE_CCO;
 | |
|     }
 | |
| 
 | |
|     if (sg_ctrl_global->dev_ready == 1) {
 | |
|         event = IOT_CTRL_EVENT_DEVICE_CONNECTED;
 | |
|     }
 | |
|     sg_ctrl_global->ctrl_drv->event_report_handle(
 | |
|         (uint8_t)sg_ctrl_global->app_sn, plc_rpt->addr, role,
 | |
|         sg_ctrl_global->proto_type, event, NULL, 0);
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_get_ckq_data_sn(uint8_t *proto_header, uint8_t *app_sn)
 | |
| {
 | |
|     pkt_3762_hdr_t *rsp_hdr;
 | |
|     proto_spg_hdr_t *spg_rsp_hdr;
 | |
|     proto_spg_app_data_t *spg_app_data;
 | |
|     uint8_t is_report = 0;
 | |
| 
 | |
|     if (sg_ctrl_global->proto_type == IOT_CTRL_PROTO_3762) {
 | |
|         rsp_hdr = (pkt_3762_hdr_t *)proto_header;
 | |
|         *app_sn = rsp_hdr->user_data.res.dl_info.sn;
 | |
|         if (rsp_hdr->ctrl_byte.prm == PROTO_3762_PRM_MASTER) {
 | |
|             is_report = 1;
 | |
|         }
 | |
|     } else if (sg_ctrl_global->proto_type == IOT_CTRL_PROTO_SPG){
 | |
|         spg_rsp_hdr = (proto_spg_hdr_t*)(proto_header);
 | |
|         if (spg_rsp_hdr->ctrl_byte.addr) {
 | |
|             spg_app_data = (proto_spg_app_data_t*)(proto_header +
 | |
|                 PROTO_SPG_DATA_OFFSET + sizeof(proto_spg_addr_field_t));
 | |
|         } else {
 | |
|             spg_app_data = (proto_spg_app_data_t*)(proto_header +
 | |
|                 PROTO_SPG_DATA_OFFSET);
 | |
|         }
 | |
|         *app_sn = spg_app_data->seq;
 | |
|         if (spg_rsp_hdr->ctrl_byte.prm == PROTO_SPG_PRM_MASTER) {
 | |
|             is_report = 1;
 | |
|         }
 | |
|     } else {
 | |
|         iot_sg_ctrl_printf("%s : proto type error : %lu\n", __FUNCTION__,
 | |
|             sg_ctrl_global->proto_type);
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     return is_report;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_sg_ctrl_handle_plc_data_recv - handle plc data.
 | |
|  * @param pkt: include plc msg head and data.
 | |
|  * @retval 0: pkt is not consumed.
 | |
|  * @retval 1: pkt is consumed.
 | |
|  */
 | |
| static uint8_t iot_sg_ctrl_handle_plc_data_recv(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint16_t hdr_len;
 | |
|     uint8_t consumed = 0;
 | |
| 
 | |
|     hdr_len = sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_msdu_recv_t);
 | |
|     iot_pkt_pull(pkt, hdr_len);
 | |
| 
 | |
|     switch (sg_ctrl_global->connect_role) {
 | |
|     case IOT_PLC_DEV_ROLE_CCO:
 | |
|     {
 | |
|         if (sg_ctrl_global->app_proto == IOT_SG_APP_CTRL_PROTO_GW) {
 | |
|             iot_sg_ctrl_gw_handle_cco_app_data(pkt);
 | |
|         } else {
 | |
|             iot_sg_ctrl_nw_handle_cco_app_data(pkt);
 | |
|         }
 | |
|         consumed = 1;
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_DEV_ROLE_STA:
 | |
|     {
 | |
|         if (sg_ctrl_global->app_proto == IOT_SG_APP_CTRL_PROTO_GW) {
 | |
|             iot_sg_ctrl_gw_handle_sta_app_data(pkt);
 | |
|         } else {
 | |
|             iot_sg_ctrl_nw_handle_sta_app_data(pkt);
 | |
|         }
 | |
|         consumed = 1;
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
| 
 | |
|         break;
 | |
|     }
 | |
|     if (!consumed) {
 | |
|         iot_pkt_free(pkt);
 | |
|     }
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| static void iot_sg_clear_dl_data(void)
 | |
| {
 | |
|     uint8_t i;
 | |
|     info_pool_t *pool = &sg_ctrl_global->info_pool;
 | |
| 
 | |
|     if (pool->remain_cnt != IOT_SG_CTRL_POOL_NUM) {
 | |
|         for (i = 0; i < IOT_SG_CTRL_POOL_NUM; i++) {
 | |
|             if (pool->frm_info[i].send_pkt != NULL) {
 | |
|                 iot_pkt_free(pool->frm_info[i].send_pkt);
 | |
|                 pool->frm_info[i].send_pkt = NULL;
 | |
|             }
 | |
|             os_mem_set(&pool->frm_info[i], 0, sizeof(frame_info_t));
 | |
|         }
 | |
|         pool->remain_cnt = IOT_SG_CTRL_POOL_NUM;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_sg_clear_ul_sn()
 | |
| {
 | |
|     os_mem_set(sg_ctrl_global->ul_sn, 0, IOT_SG_CTRL_UL_SIZE);
 | |
|     sg_ctrl_global->ul_sn_index = 0;
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_rpt_connect_status(
 | |
|     iot_plc_ctrl_proto_state_rpt_t *rpt, uint8_t is_connect)
 | |
| {
 | |
|     if (sg_ctrl_global->uart_h) {
 | |
|         iot_sg_ctrl_send_status_rpt(rpt);
 | |
|     } else {
 | |
|         iot_sg_ctrl_cli_proto_connect_status_rpt(rpt->addr, is_connect);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief iot_sg_ctrl_plc_data_recv_handle - receive plc data
 | |
|  * @param pkt: include plc msg head and data, the pkt will be free
 | |
|  */
 | |
| static void iot_sg_ctrl_plc_handle(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t consumed = 0;
 | |
|     iot_plc_msg_header_t *hdr =
 | |
|         (iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
| 
 | |
|     if (hdr->app_id != IOT_PLC_APP_ID_BCAST &&
 | |
|         hdr->app_id != IOT_PLC_APP_SMART_GRID) {
 | |
|         goto drop;
 | |
|     }
 | |
| 
 | |
|     if (sg_ctrl_global->app_registered == 0 &&
 | |
|         hdr->msg_id != IOT_PLC_MSG_APP_REG_CONF) {
 | |
|         /* only handle app register confirm message before app registered */
 | |
|         goto drop;
 | |
|     }
 | |
| 
 | |
|     switch (hdr->msg_id) {
 | |
|     case IOT_PLC_MSG_DISCOVERY_NODE_RPT:
 | |
|     {   /* discovery node rpt */
 | |
|         iot_plc_discovery_node_rpt_t *rpt =
 | |
|             (iot_plc_discovery_node_rpt_t*)(hdr + 1);
 | |
|         iot_sg_ctrl_add_scan_node(rpt->addr, rpt->nid, rpt->band_id);
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_BAND_INFO_QUERY_RPT:
 | |
|     {
 | |
|         /* handle freq band query response */
 | |
|         iot_plc_freq_band_info_query_rpt_t *rpt;
 | |
|         rpt = (iot_plc_freq_band_info_query_rpt_t *)(hdr + 1);
 | |
|         if (sg_ctrl_global->freq_band != rpt->freq_band) {
 | |
|             /* record fq */
 | |
|             sg_ctrl_global->freq_band = rpt->freq_band;
 | |
|         }
 | |
|         if (sg_ctrl_global->ctrl_drv &&
 | |
|             sg_ctrl_global->ctrl_drv->freq_band_report_cb) {
 | |
|             sg_ctrl_global->ctrl_drv->freq_band_report_cb(rpt);
 | |
|         }
 | |
|         /* start scan mode */
 | |
|         iot_sg_ctrl_enable_scan_mode();
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_FREQ_BAND_SET_RPT:
 | |
|     {
 | |
|         /* handle freq band set response */
 | |
|         iot_plc_freq_band_set_rpt_t *rpt;
 | |
|         rpt = (iot_plc_freq_band_set_rpt_t *)(hdr + 1);
 | |
|         if ((!rpt->result) &&
 | |
|             (sg_ctrl_global->freq_band != sg_ctrl_global->config_freq_band)) {
 | |
|             sg_ctrl_global->freq_band = sg_ctrl_global->config_freq_band;
 | |
|             /* restart scan mode */
 | |
|             iot_sg_ctrl_disable_scan_mode();
 | |
|             /* clear all scan node info */
 | |
|             iot_sg_ctrl_scan_node_clear();
 | |
|             iot_sg_ctrl_enable_scan_mode();
 | |
|         }
 | |
|         if (sg_ctrl_global->ctrl_drv &&
 | |
|             sg_ctrl_global->ctrl_drv->freq_band_set_result_cb) {
 | |
|             sg_ctrl_global->ctrl_drv->freq_band_set_result_cb(rpt->result);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_APP_REG_CONF:
 | |
|     {
 | |
|         iot_plc_app_reg_conf_t* rpt = (iot_plc_app_reg_conf_t*)(hdr + 1);
 | |
|         iot_sg_ctrl_printf("%s: IOT_PLC_MSG_APP_REG_CONF result:%lu\n",
 | |
|             __FUNCTION__, rpt->result);
 | |
|         if (rpt->result == IOT_PLC_SUCCESS ||
 | |
|             rpt->result == IOT_PLC_SUCCESS_MODIFIED) {
 | |
|             sg_ctrl_global->app_registered = 1;
 | |
|             iot_sg_ctrl_set_cfg_after_app_reg();
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_CTRL_PROTO_CONNECT_CONF:
 | |
|     {
 | |
|         iot_plc_ctrl_proto_connect_conf_t* ctrl_conf =
 | |
|             (iot_plc_ctrl_proto_connect_conf_t*)(hdr + 1);
 | |
| 
 | |
|         if (ctrl_conf->err_no == ERR_OK) {
 | |
|             sg_ctrl_global->ctrl_drv->event_report_handle(
 | |
|                 (uint8_t)sg_ctrl_global->app_sn, NULL, 0,
 | |
|                 sg_ctrl_global->proto_type, IOT_CTRL_EVENT_DEVICE_CONNECT_CONF,
 | |
|                 NULL, 0);
 | |
|         } else {
 | |
|             iot_sg_ctrl_enable_scan_mode();
 | |
|             iot_sg_ctrl_printf("%s: IOT_PLC_MSG_CTRL_PROTO_CONNECT_CONF ,"
 | |
|                 "return nack 00h02 , err_no is %lu\n",
 | |
|                 __FUNCTION__, ctrl_conf->err_no);
 | |
|             sg_ctrl_global->ctrl_drv->event_report_handle(
 | |
|                 (uint8_t)sg_ctrl_global->app_sn, NULL, 0,
 | |
|                 sg_ctrl_global->proto_type, IOT_CTRL_EVENT_DEVICE_CONNECT_FAIL,
 | |
|                 NULL, 0);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_CTRL_PROTO_RECV:
 | |
|     {
 | |
|         iot_sg_ctrl_printf("%s : IOT_PLC_MSG_CTRL_PROTO_RECV \n", __FUNCTION__);
 | |
|         consumed = iot_sg_ctrl_handle_plc_data_recv(pkt);
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_DEV_STATE_CHANGE_RPT:
 | |
|     {
 | |
|         iot_plc_dev_state_change_rpt_t* rpt =
 | |
|             (iot_plc_dev_state_change_rpt_t*)(hdr + 1);
 | |
|         iot_sg_ctrl_printf("%s: IOT_PLC_MSG_DEV_STATE_CHANGE_RPT "
 | |
|             "local mac[%02X:%02X:%02X:%02X:%02X:%02X]\n",
 | |
|             __FUNCTION__, rpt->local_mac[0], rpt->local_mac[1],
 | |
|             rpt->local_mac[2], rpt->local_mac[3], rpt->local_mac[4],
 | |
|             rpt->local_mac[5]);
 | |
| 
 | |
|         if (rpt->is_ready) {
 | |
|             iot_gpio_value_set(IOT_EXT_PLC_LED_GPIO_LOGIC, LED_ON);
 | |
|             ckb_led_blink[EXT_LED_PLC].last_state = LED_ON;
 | |
|             ckb_led_blink[EXT_LED_PLC].blink_flag = 0;
 | |
|         } else {
 | |
|             ckb_led_blink[EXT_LED_PLC].blink_flag = 1;
 | |
|         }
 | |
| 
 | |
|         iot_mac_addr_cpy(sg_ctrl_global->local_mac_addr, rpt->local_mac);
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_DEV_INFO_RPT:
 | |
|     {
 | |
|         iot_plc_dev_info_rpt_t* rpt = (iot_plc_dev_info_rpt_t*)(hdr + 1);
 | |
|         iot_sg_ctrl_printf("%s: infor report--role %lu, dev type %lu,"
 | |
|             "local mac [%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__,
 | |
|             rpt->dev_role, rpt->dev_type, rpt->local_mac[0], rpt->local_mac[1],
 | |
|             rpt->local_mac[2], rpt->local_mac[3], rpt->local_mac[4],
 | |
|             rpt->local_mac[5]);
 | |
|         if (iot_mac_addr_valid(rpt->local_mac)) {
 | |
|             iot_mac_addr_cpy(sg_ctrl_global->local_mac_addr, rpt->local_mac);
 | |
|         } else {
 | |
|             IOT_ASSERT(0);
 | |
|         }
 | |
|         /* query band id */
 | |
|         iot_sg_ctrl_get_freq_band_msg();
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_CTRL_PROTO_STATUS_RPT:
 | |
|     {
 | |
|         iot_plc_ctrl_proto_state_rpt_t *rpt =
 | |
|             (iot_plc_ctrl_proto_state_rpt_t *)(hdr + 1);
 | |
| 
 | |
|         if ((rpt->state == IOT_PLC_CTRL_PROTO_STATE_CONNECTED) &&
 | |
|             sg_ctrl_global->dev_ready != 1) {
 | |
|             sg_ctrl_global->dev_ready = 1;
 | |
|             sg_ctrl_global->connect_role = rpt->role;
 | |
|             iot_sg_ctrl_rpt_connect_status(rpt, 1);
 | |
|             iot_sg_clear_dl_data();
 | |
|             iot_sg_clear_ul_sn();
 | |
|             sg_ctrl_global->connect_seq = rpt->sn;
 | |
|             iot_sg_ctrl_printf("%s: IOT_PLC_CTRL_PROTO_STATE_CONNECTED ,"
 | |
|                 "connected type is %lu\n", __FUNCTION__, rpt->role);
 | |
|         } else if ((rpt->state == IOT_PLC_CTRL_PROTO_STATE_DISCONNECTED) &&
 | |
|             sg_ctrl_global->dev_ready == 1) {
 | |
|             sg_ctrl_global->dev_ready = 0;
 | |
|             sg_ctrl_global->connect_role = IOT_PLC_DEV_ROLE_INVALID;
 | |
|             iot_sg_ctrl_rpt_connect_status(rpt, 0);
 | |
|             iot_sg_clear_dl_data();
 | |
|             iot_sg_clear_ul_sn();
 | |
|             iot_sg_ctrl_printf("%s: IOT_PLC_CTRL_PROTO_STATE_DISCONNECTED \n",
 | |
|                 __FUNCTION__);
 | |
|             /* start scan mode */
 | |
|             iot_sg_ctrl_enable_scan_mode();
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| drop:
 | |
|     if (!consumed)
 | |
|         iot_pkt_free(pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_reset_connet_status()
 | |
| {
 | |
|     if (sg_ctrl_global->dev_ready == 1) {
 | |
|         sg_ctrl_global->dev_ready = 0;
 | |
|         iot_sg_clear_dl_data();
 | |
|         iot_sg_clear_ul_sn();
 | |
|         iot_sg_ctrl_printf("%s: IOT_PLC_CTRL_PROTO_STATE_DISCONNECTED \n",
 | |
|             __FUNCTION__);
 | |
|         /* start scan mode */
 | |
|         iot_sg_ctrl_enable_scan_mode();
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint32_t iot_sg_ctrl_proto_connect(uint8_t *node_addr, uint8_t app_sn)
 | |
| {
 | |
|     iot_sg_ctrl_disable_scan_mode();
 | |
|     sg_ctrl_global->dev_ready = 0;
 | |
|     sg_ctrl_global->app_sn = app_sn;
 | |
|     iot_mac_addr_cpy(sg_ctrl_global->dst_mac_addr, node_addr);
 | |
|     iot_plc_ctrl_proto_connect(sg_ctrl_global->app_handle,
 | |
|         IOT_PLC_APP_SMART_GRID, node_addr);
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t iot_sg_ctrl_proto_connect_from_scan_node(uint8_t *node_addr,
 | |
|     uint8_t app_sn)
 | |
| {
 | |
|     scan_node_info_t *node_entry = NULL;
 | |
|     /* connect node */
 | |
|     uint8_t addr[IOT_MAC_ADDR_LEN];
 | |
| 
 | |
|     iot_mac_addr_cpy(addr, node_addr);
 | |
|     iot_mac_addr_reverse(addr);
 | |
| 
 | |
|     node_entry = (scan_node_info_t *)iot_addr_hash_table_find(
 | |
|         sg_ctrl_global->scan_handle.table, addr);
 | |
| 
 | |
|     if (!node_entry) {
 | |
|         /* addr invalid */
 | |
|         iot_sg_ctrl_printf("%s: invalid connect addr: "
 | |
|             "%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, addr[0], addr[1],
 | |
|             addr[2], addr[3], addr[4], addr[5]);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     return iot_sg_ctrl_proto_connect(node_addr, app_sn);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_proto_sta_read_meter(uint8_t *data, uint16_t len,
 | |
|     uint8_t app_sn)
 | |
| {
 | |
|     iot_sg_ctrl_read_meter(data, len, app_sn);
 | |
| }
 | |
| 
 | |
| uint32_t iot_sg_ctrl_send_data(uint8_t cmd_type, uint16_t app_sn,
 | |
|     iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t ret = ERR_OK;
 | |
|     uint8_t reason = 0;
 | |
|     uint8_t index;
 | |
|     uint8_t consumed = 0;
 | |
|     uint8_t retry_flag = 1;
 | |
| 
 | |
|     info_pool_t *info_pool = &(sg_ctrl_global->info_pool);
 | |
| 
 | |
|     if (sg_ctrl_global->dev_ready != 1) {
 | |
|         reason = 1;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     if (iot_sg_ctrl_pool_sn_exist(info_pool, app_sn, false)) {
 | |
|         reason = 2;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     index = iot_sg_ctrl_pool_find_free_index(info_pool);
 | |
|     if (index == -1) {
 | |
|         reason = 3;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     if (app_sn == IOT_CTRL_PASSTHROUGH_SN) {
 | |
|         retry_flag = 0;
 | |
|     }
 | |
| 
 | |
|     if (ERR_OK != iot_sg_ctrl_pool_add_data(info_pool, pkt, index,
 | |
|         app_sn, cmd_type, retry_flag)) {
 | |
|         reason = 4;
 | |
|         goto err;
 | |
|     }
 | |
|     consumed = 1;
 | |
| 
 | |
|     goto out;
 | |
| err:
 | |
|     iot_sg_ctrl_printf("%s: fail reason %lu \n", __FUNCTION__, reason);
 | |
|     ret = ERR_INVAL;
 | |
| out:
 | |
|     if (!consumed) {
 | |
|         iot_pkt_free(pkt);
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_cmd_send(frame_info_t *cmd)
 | |
| {
 | |
|     uint8_t *data = iot_pkt_block_ptr(cmd->send_pkt, IOT_PKT_BLOCK_DATA);
 | |
|     uint16_t data_len =
 | |
|         (uint16_t)iot_pkt_block_len(cmd->send_pkt, IOT_PKT_BLOCK_DATA);
 | |
|     switch (cmd->cmd_type) {
 | |
|     case PROTO_CTRL_CMD_TYPE_MR_CCO:
 | |
|     {
 | |
|         if (sg_ctrl_global->app_proto == IOT_SG_APP_CTRL_PROTO_GW) {
 | |
|             iot_sg_ctrl_gw_send_data_to_cco(data, data_len);
 | |
|         } else {
 | |
|             iot_sg_ctrl_nw_send_data_to_cco(data, data_len,
 | |
|                 sg_ctrl_global->connect_seq);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case  PROTO_CTRL_CMD_TYPE_MR_STA:
 | |
|     {
 | |
|         iot_sg_ctrl_proto_sta_read_meter(data, data_len, (uint8_t)cmd->app_sn);
 | |
|         break;
 | |
|     }
 | |
|     case PROTO_CTRL_CMD_TYPE_QR_CHIP_ID_STA:
 | |
|     {
 | |
|         if (sg_ctrl_global->app_proto == IOT_SG_APP_CTRL_PROTO_GW) {
 | |
|             iot_sg_ctrl_gw_get_id_info(data[0], cmd->app_sn, cmd->send_cnt);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case PROTO_CTRL_CMD_TYPE_PASSTHROUGH:
 | |
|     {
 | |
|         if (sg_ctrl_global->app_proto == IOT_SG_APP_CTRL_PROTO_NW) {
 | |
|             iot_sg_ctrl_nw_passthrough(data, data_len,
 | |
|                 sg_ctrl_global->connect_seq);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         iot_sg_ctrl_printf("%s invalid comand %lu\n", __FUNCTION__,
 | |
|             cmd->cmd_type);
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_buf_refresh(void)
 | |
| {
 | |
|     uint8_t i;
 | |
|     info_pool_t *pool = &sg_ctrl_global->info_pool;
 | |
| 
 | |
|     if (pool->remain_cnt != IOT_SG_CTRL_POOL_NUM) {
 | |
|         for (i = 0; i < IOT_SG_CTRL_POOL_NUM; i++) {
 | |
|             if (pool->frm_info[i].send_pkt != NULL) {
 | |
|                 if (pool->frm_info[i].span_cnt >=
 | |
|                     IOT_SG_CTRL_MAX_LIFE_SPAN_CNT) {
 | |
|                     iot_sg_ctrl_printf("%s: frame app_sn %lu is dropped for "
 | |
|                         "timeout\n", __FUNCTION__, pool->frm_info[i].app_sn);
 | |
|                     iot_pkt_free(pool->frm_info[i].send_pkt);
 | |
|                     os_mem_set(&pool->frm_info[i], 0, sizeof(frame_info_t));
 | |
|                     pool->remain_cnt++;
 | |
|                     IOT_ASSERT(pool->remain_cnt <= IOT_SG_CTRL_POOL_NUM);
 | |
|                 } else if ((pool->frm_info[i].span_cnt %
 | |
|                     IOT_SG_CTRL_APP_RETRY_INTV_CNT) == 0) {
 | |
|                     iot_sg_ctrl_cmd_send(&(pool->frm_info[i]));
 | |
|                     pool->frm_info[i].send_cnt++;
 | |
|                     iot_sg_ctrl_printf("%s: sending count, app_sn %lu, "
 | |
|                         "retry cnt %lu\n", __FUNCTION__,
 | |
|                         pool->frm_info[i].app_sn,
 | |
|                         pool->frm_info[i].send_cnt);
 | |
|                 }
 | |
|                 pool->frm_info[i].span_cnt++;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_timer_handle(iot_ctrl_task_msg_t* task_msg)
 | |
| {
 | |
|     switch (task_msg->msg.id) {
 | |
|     case IOT_SG_CTRL_MSG_ID_TIMER_CHECK:
 | |
|     {
 | |
|         iot_sg_ctrl_buf_refresh();
 | |
|         iot_sg_ctrl_scan_node_refresh();
 | |
|         if (ckb_led_blink[EXT_LED_PLC].blink_flag == 1) {
 | |
|             if (ckb_led_blink[EXT_LED_PLC].last_state == LED_OFF) {
 | |
|                 iot_gpio_value_set(IOT_EXT_PLC_LED_GPIO_LOGIC, LED_ON);
 | |
|                 ckb_led_blink[EXT_LED_PLC].last_state = LED_ON;
 | |
|             } else {
 | |
|                 iot_gpio_value_set(IOT_EXT_PLC_LED_GPIO_LOGIC, LED_OFF);
 | |
|                 ckb_led_blink[EXT_LED_PLC].last_state = LED_OFF;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (ckb_led_blink[EXT_LED_WARRING].last_state == LED_OFF) {
 | |
|             iot_gpio_value_set(IOT_EXT_WARN_LED_GPIO_LOGIC, LED_ON);
 | |
|             ckb_led_blink[EXT_LED_WARRING].last_state = LED_ON;
 | |
|         } else {
 | |
|             iot_gpio_value_set(IOT_EXT_WARN_LED_GPIO_LOGIC, LED_OFF);
 | |
|             ckb_led_blink[EXT_LED_WARRING].last_state = LED_OFF;
 | |
|         }
 | |
|         os_start_timer(sg_ctrl_global->ctrl_timer,
 | |
|             IOT_SG_CTRL_PERIODIC_TIMER_INTERVAL);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_task_handle_msg(iot_task_h task_h,
 | |
|     iot_task_msg_t *msg)
 | |
| {
 | |
|     iot_ctrl_task_msg_t *task_msg;
 | |
| 
 | |
|     IOT_ASSERT(task_h == sg_ctrl_global->task_handle);
 | |
|     IOT_ASSERT(msg);
 | |
| 
 | |
|     task_msg = (iot_ctrl_task_msg_t*)msg;
 | |
|     switch (task_msg->msg.type) {
 | |
|     case IOT_SG_CTRL_MSG_TYPE_PLC:
 | |
|     {
 | |
|         switch (task_msg->msg.id) {
 | |
|         case IOT_SG_CTRL_MSG_ID_PLC_RECV:
 | |
|         {
 | |
|             iot_sg_ctrl_plc_handle(task_msg->data);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_SG_CTRL_MSG_TYPE_TIME:
 | |
|     {
 | |
|         switch (task_msg->msg.id) {
 | |
|         case IOT_SG_CTRL_MSG_ID_TIMER_CHECK:
 | |
|         {
 | |
|             iot_sg_ctrl_timer_handle(task_msg);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_SG_CTRL_MSG_TYPE_UART:
 | |
|     {
 | |
|         switch (task_msg->msg.id) {
 | |
|         case IOT_SG_CTRL_MSG_ID_UART_RECV:
 | |
|         {
 | |
|             if (ERR_OK != iot_sg_ctrl_check_drv(
 | |
|                 (iot_pkt_t *)(task_msg->data))) {
 | |
|                 iot_pkt_free((iot_pkt_t *)(task_msg->data));
 | |
|                 iot_sg_ctrl_printf("ctrl data check fail, free pkt!\n");
 | |
|                 break;
 | |
|             }
 | |
|             sg_ctrl_global->ctrl_drv->ctrl_drv_data_handle(task_msg->data);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|             IOT_ASSERT(0);
 | |
|             break;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_SG_CTRL_MSG_TYPE_CLI:
 | |
|     {
 | |
|         iot_sg_ctrl_handle_cli_msg((iot_sg_msg_t *)msg);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
|     iot_task_free_msg(sg_ctrl_global->task_handle, msg);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_task_handle_msg_cancel(iot_task_h task_h,
 | |
|     iot_task_msg_t *msg)
 | |
| {
 | |
|     iot_ctrl_task_msg_t *task_msg;
 | |
|     IOT_ASSERT(task_h == sg_ctrl_global->task_handle);
 | |
|     IOT_ASSERT(msg);
 | |
| 
 | |
|     task_msg = (iot_ctrl_task_msg_t*)msg;
 | |
|     switch (task_msg->msg.type) {
 | |
|     case IOT_SG_CTRL_MSG_TYPE_PLC:
 | |
|     case IOT_SG_CTRL_MSG_TYPE_UART:
 | |
|     case IOT_SG_CTRL_MSG_TYPE_CLI:
 | |
|     {
 | |
|         if (task_msg->data) {
 | |
|             iot_pkt_free(task_msg->data);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_SG_CTRL_MSG_TYPE_TIME:
 | |
|     {
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
|     iot_task_free_msg(sg_ctrl_global->task_handle, msg);
 | |
| }
 | |
| 
 | |
| static void iot_sg_ctrl_msg_plc_recv(void *param, iot_pkt_t *pkt)
 | |
| {
 | |
|     (void)param;
 | |
|     iot_sg_ctrl_post_task_msg(IOT_SG_CTRL_MSG_TYPE_PLC,
 | |
|         IOT_SG_CTRL_MSG_ID_PLC_RECV, pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static uint32_t iot_sg_ctrl_task_init()
 | |
| {
 | |
|     uint32_t ret = ERR_OK;
 | |
|     iot_plc_app_t ctrl_app = {0};
 | |
|     iot_task_config_t task_cfg;
 | |
| 
 | |
|     if (sg_ctrl_global == NULL)
 | |
|     {
 | |
|         sg_ctrl_global = os_mem_malloc(IOT_SMART_GRID_MID,
 | |
|             sizeof(*sg_ctrl_global));
 | |
|     } else {
 | |
|         goto out;
 | |
|     }
 | |
|     if (!sg_ctrl_global) {
 | |
|         ret = ERR_NOMEM;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     iot_mcp23017_gpio_ex_init();
 | |
|     ckb_led_blink[EXT_LED_PLC].blink_flag = 1;
 | |
|     os_mem_set(sg_ctrl_global, 0, sizeof(iot_sg_ctrl_global_t));
 | |
|     task_cfg.stack_size = 0;
 | |
|     task_cfg.task_prio = IOT_SMART_GRID_TASK_PRIO;
 | |
|     task_cfg.msg_size = sizeof(iot_ctrl_task_msg_t);
 | |
|     task_cfg.msg_cnt = IOT_SG_CTRL_TASK_POOL_SIZE;
 | |
|     task_cfg.queue_cnt = IOT_SG_CTRL_TASK_QUEUE_MAX_PRIO;
 | |
|     task_cfg.queue_cfg[IOT_SG_CTRL_TASK_QUEUE_HP].quota = 0;
 | |
|     task_cfg.msg_exe_func = iot_sg_ctrl_task_handle_msg;
 | |
|     task_cfg.msg_cancel_func = iot_sg_ctrl_task_handle_msg_cancel;
 | |
| 
 | |
|     sg_ctrl_global->task_handle =
 | |
|         iot_task_create(IOT_SMART_GRID_MID, &task_cfg);
 | |
|     if (sg_ctrl_global->task_handle == NULL) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_1;
 | |
|     }
 | |
| 
 | |
| #if (IOT_GW_CTRL_APP_ENABLE)
 | |
|     sg_ctrl_global->app_proto = IOT_SG_APP_CTRL_PROTO_GW;
 | |
| #else
 | |
|     sg_ctrl_global->app_proto = IOT_SG_APP_CTRL_PROTO_NW;
 | |
| #endif
 | |
| 
 | |
|     if (iot_sg_ctrl_init_scan_table()) {
 | |
|         ret = ERR_NOMEM;
 | |
|         goto error_1;
 | |
|     }
 | |
|     sg_ctrl_global->ctrl_timer = os_create_timer(
 | |
|         IOT_SMART_GRID_MID, false, iot_sg_ctrl_periodic_timer_func,
 | |
|         sg_ctrl_global);
 | |
|     if (sg_ctrl_global->ctrl_timer == 0) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_2;
 | |
|     }
 | |
| 
 | |
|     sg_ctrl_global->ctrl_drv = &g_sg_ctrl_drv;
 | |
|     sg_ctrl_global->uart_h = iot_sg_ctrl_open_uart(
 | |
|         iot_board_get_uart(UART_METER_PORT));
 | |
|     if (sg_ctrl_global->uart_h == NULL) {
 | |
|         iot_sg_ctrl_printf("%s: open uart port failed!\n", __FUNCTION__);
 | |
|         sg_ctrl_global->cli_sg_interface.recv = iot_sg_ctrl_cli_callback;
 | |
|         sg_ctrl_global->cli_sg_interface.param = sg_ctrl_global;
 | |
|         ret = iot_cli_sg_interface_register(&sg_ctrl_global->cli_sg_interface);
 | |
|         if (ret) {
 | |
|             goto error_3;
 | |
|         }
 | |
|     } else if ((!sg_ctrl_global->ctrl_drv) ||
 | |
|         (ERR_OK != sg_ctrl_global->ctrl_drv->init())) {
 | |
|         goto error_4;
 | |
|     } else {
 | |
|         /* sg ctrl need check uart proto type */
 | |
|         sg_ctrl_global->proto_type = IOT_CTRL_PROTO_INVALID;
 | |
|     }
 | |
|     ctrl_app.app_id = IOT_PLC_APP_SMART_GRID;
 | |
|     ctrl_app.param = NULL;
 | |
|     ctrl_app.prio = 3;
 | |
|     ctrl_app.recv = iot_sg_ctrl_msg_plc_recv;
 | |
|     sg_ctrl_global->app_handle = iot_plc_register_app(&ctrl_app);
 | |
|     if (sg_ctrl_global->app_handle == NULL) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_4;
 | |
|     }
 | |
|     sg_ctrl_global->info_pool.remain_cnt = IOT_SG_CTRL_POOL_NUM;
 | |
|     sg_ctrl_global->connect_role = IOT_PLC_DEV_ROLE_INVALID;
 | |
|     goto out;
 | |
| error_4:
 | |
|     iot_uart_close(sg_ctrl_global->uart_h);
 | |
| error_3:
 | |
|     os_delete_timer(sg_ctrl_global->ctrl_timer);
 | |
| error_2:
 | |
|     iot_task_delete(sg_ctrl_global->task_handle);
 | |
| error_1:
 | |
|     os_mem_free(sg_ctrl_global);
 | |
|     sg_ctrl_global = NULL;
 | |
| out:
 | |
|     iot_sg_ctrl_printf("%s, ctrl initializing task done, ret: %lu\n",
 | |
|         __FUNCTION__, ret);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * app_sg_ctrl_entry: entry for iot_sg_ctrl app
 | |
|  * @return:
 | |
|  *  ERR_PENDING -   if application want to delay the plc network formation.
 | |
|  *  otherwise   -   plc network formation will be started automatically.
 | |
|  */
 | |
| uint32_t app_sg_ctrl_entry()
 | |
| {
 | |
|     uint32_t ret = ERR_PENDING;
 | |
|     /* if the firmware is release version(0), disabel log printing, if not,
 | |
|      * enable the log printing
 | |
|      */
 | |
|     if (iot_version_type() == 1) {
 | |
|         iot_cus_print_config(true);
 | |
|     } else {
 | |
|         iot_cus_print_config(false);
 | |
|     }
 | |
| 
 | |
|     if (!iot_sg_ctrl_task_init()) {
 | |
|         return ERR_OK;
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_get_connect_role()
 | |
| {
 | |
|     return sg_ctrl_global->connect_role;
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_id_info_rpt(uint8_t *id, uint8_t len, uint8_t id_type,
 | |
|     uint8_t dev_type)
 | |
| {
 | |
|     iot_sg_ctrl_id_info_t *id_info;
 | |
|     iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*id_info), IOT_SMART_GRID_MID);
 | |
| 
 | |
|     id_info = (iot_sg_ctrl_id_info_t *)iot_pkt_data(pkt);
 | |
|     id_info->dev_type = dev_type;
 | |
|     id_info->id_type = id_type;
 | |
|     id_info->id_len = len;
 | |
|     iot_mac_addr_cpy(id_info->addr, sg_ctrl_global->dst_mac_addr);
 | |
|     iot_mac_addr_reverse(id_info->addr);
 | |
|     os_mem_cpy(id_info->info, id, len);
 | |
| 
 | |
|     iot_pkt_put(pkt, sizeof(*id_info));
 | |
| 
 | |
|     iot_sg_ctrl_rpt_sta_data(iot_pkt_data(pkt), (uint16_t)iot_pkt_data_len(pkt),
 | |
|         IOT_CTRL_EVENT_ID_INFO);
 | |
|     iot_pkt_free(pkt);
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_data_rpt_drv(uint8_t sn, uint8_t evt_type, uint8_t *data,
 | |
|     uint16_t len)
 | |
| {
 | |
|     sg_ctrl_global->ctrl_drv->event_report_handle(sn, NULL, 0, 0, evt_type,
 | |
|         data, len);
 | |
| }
 | |
| 
 | |
| void iot_sg_ctrl_data_print(const char* str, uint8_t* buf, uint32_t len)
 | |
| {
 | |
|     uint16_t i = 0;
 | |
|     if (len > IOT_SG_CTRL_LOG_BUF_LEN) {
 | |
|         len = IOT_SG_CTRL_LOG_BUF_LEN;
 | |
|     }
 | |
|     iot_sg_ctrl_printf("%s ", str);
 | |
|     for (i = 0; i < len; ++i) {
 | |
|         iot_sg_ctrl_printf("%02X ", buf[i]);
 | |
|     }
 | |
|     iot_sg_ctrl_printf("\n");
 | |
| }
 | |
| 
 | |
| uint8_t iot_sg_ctrl_get_sta_passthrough_state()
 | |
| {
 | |
|     uint8_t i;
 | |
|     info_pool_t *info_pool = &(sg_ctrl_global->info_pool);
 | |
| 
 | |
|     for (i = 0; i < IOT_SG_CTRL_POOL_NUM; i++) {
 | |
|         if (info_pool->frm_info[i].send_pkt != NULL &&
 | |
|             info_pool->frm_info[i].app_sn == IOT_CTRL_PASSTHROUGH_SN) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int iot_mcp23017_gpio_ex_init(void)
 | |
| {
 | |
|     os_delay(100);
 | |
|     iot_gpio_open_as_output(IOT_EXT_PLC_LED_GPIO_LOGIC);
 | |
|     iot_gpio_open_as_output(IOT_EXT_WARN_LED_GPIO_LOGIC);
 | |
|     iot_gpio_set_opendrain_mode(IOT_EXT_PLC_LED_GPIO, 1);
 | |
|     iot_gpio_set_opendrain_mode(IOT_EXT_WARN_LED_GPIO, 1);
 | |
|     iot_gpio_value_set(IOT_EXT_PLC_LED_GPIO_LOGIC, LED_OFF);
 | |
|     iot_gpio_value_set(IOT_EXT_WARN_LED_GPIO_LOGIC, LED_OFF);
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #endif //(IOT_SG_CONTROLLER_ENABLE)
 |