Files
kunlun/app/sg_ctrl/iot_sg_ctrl.c

1492 lines
45 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
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)