1492 lines
45 KiB
C
1492 lines
45 KiB
C
|
/****************************************************************************
|
||
|
|
||
|
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)
|