863 lines
25 KiB
C
863 lines
25 KiB
C
|
|
/* os_shim header files */
|
||
|
|
#include "os_types_api.h"
|
||
|
|
#include "os_utils_api.h"
|
||
|
|
|
||
|
|
/* common includes */
|
||
|
|
#include "iot_dbglog_api.h"
|
||
|
|
#include "iot_io_api.h"
|
||
|
|
#include "iot_version_api.h"
|
||
|
|
#include "iot_errno_api.h"
|
||
|
|
#include "iot_system_api.h"
|
||
|
|
#include "iot_oem_api.h"
|
||
|
|
|
||
|
|
/* smart grid internal header files */
|
||
|
|
#include "iot_sg_fr.h"
|
||
|
|
#include "iot_sg_cco_drv_api.h"
|
||
|
|
#include "iot_sg_cco_cmd.h"
|
||
|
|
#include "iot_cli_sg_api.h"
|
||
|
|
|
||
|
|
#if (IOT_SMART_GRID_ENABLE && PLC_SUPPORT_CCO_ROLE)
|
||
|
|
|
||
|
|
/* max count of mac address in a ul packet to CLI */
|
||
|
|
#define IOT_CLI_MAX_ADDR_COUNT (8)
|
||
|
|
|
||
|
|
/* default secondary node registration duration, in minute */
|
||
|
|
#define IOT_CLI_DEFAULT_SEC_NODE_REG_DUR (30)
|
||
|
|
|
||
|
|
/* defines secondary node registration time unit(1min), uint is 1s */
|
||
|
|
#define IOT_CLI_SEC_NODE_REG_TIME_UNIT_DUR (60)
|
||
|
|
|
||
|
|
typedef struct _cli_drv_data {
|
||
|
|
/* current meter reading power meter */
|
||
|
|
uint8_t cur_mr_pm[IOT_MAC_ADDR_LEN];
|
||
|
|
/* request sequence number */
|
||
|
|
uint8_t req_sn;
|
||
|
|
} cli_drv_data_t;
|
||
|
|
|
||
|
|
static cli_drv_data_t *cli_drv_data = NULL;
|
||
|
|
|
||
|
|
uint32_t cli_drv_init()
|
||
|
|
{
|
||
|
|
if (cli_drv_data) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
cli_drv_data = os_mem_malloc(IOT_SMART_GRID_MID, sizeof(cli_drv_data_t));
|
||
|
|
|
||
|
|
if (!cli_drv_data) {
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void cli_drv_deinit()
|
||
|
|
{
|
||
|
|
if (cli_drv_data) {
|
||
|
|
os_mem_free(cli_drv_data);
|
||
|
|
cli_drv_data = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief iot_cli_drv_request_rt_mr_data() - request route meter reading data
|
||
|
|
* @param ul_data: request meter reading data up link
|
||
|
|
*/
|
||
|
|
static void iot_cli_drv_request_rt_mr_data(
|
||
|
|
const iot_cli_request_rt_mr_data_ul *ul_data)
|
||
|
|
{
|
||
|
|
iot_pkt_t *pkt = NULL;
|
||
|
|
uint16_t pkt_len = 0;
|
||
|
|
iot_cli_request_rt_mr_data_ul *des_data = NULL;
|
||
|
|
|
||
|
|
pkt_len = iot_cli_sg_get_headroom_req() + sizeof(*ul_data);
|
||
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
||
|
|
IOT_ASSERT(pkt);
|
||
|
|
|
||
|
|
/* fill response info */
|
||
|
|
des_data = (iot_cli_request_rt_mr_data_ul*)iot_pkt_reserve(pkt,
|
||
|
|
iot_cli_sg_get_headroom_req());
|
||
|
|
os_mem_cpy(des_data, ul_data, sizeof(*ul_data));
|
||
|
|
iot_cli_sg_send_data_to_cli_interface(pkt,
|
||
|
|
IOT_CLI_SG_MSG_PRT_RT_REQ_MR_DATA, IOT_CLI_SG_REQ_ID_DEFAULT);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief iot_cli_drv_run_rt_mr_data() - send packet about the route meter
|
||
|
|
* reading data
|
||
|
|
* @param req: cli request route meter reading data down link
|
||
|
|
* @param pkt: iot_pkt_t containing the cli request pkt.
|
||
|
|
* @param consumed: 0 - iot_pkt is not consumed.
|
||
|
|
* otherwise - iot_pkt is consumed.
|
||
|
|
* @return: ERR_OK: success. others: fail
|
||
|
|
*/
|
||
|
|
static uint32_t iot_cli_drv_run_rt_mr_data(
|
||
|
|
iot_cli_sg_rpt_rt_mr_data_dl *req, iot_pkt_t *pkt, uint8_t *consumed)
|
||
|
|
{
|
||
|
|
iot_sg_wl_entry_info_t node_info = { 0 };
|
||
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN] = {0};
|
||
|
|
uint32_t result = ERR_OK;
|
||
|
|
|
||
|
|
*consumed = 0;
|
||
|
|
if (iot_sg_cco_rt_mr_get_state() != IOT_SG_CCO_RT_AMR_STATE_RUN) {
|
||
|
|
return ERR_NOT_READY;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (cli_drv_data->req_sn != req->sn) {
|
||
|
|
return ERR_INVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (req->read_flag) {
|
||
|
|
case SG_READ_PM_FAILED:
|
||
|
|
{
|
||
|
|
if (iot_mac_addr_cmp(cli_drv_data->cur_mr_pm, req->mac)) {
|
||
|
|
os_mem_set(cli_drv_data->cur_mr_pm, 0, IOT_MAC_ADDR_LEN);
|
||
|
|
if (0 == ++cli_drv_data->req_sn) {
|
||
|
|
cli_drv_data->req_sn = 1;
|
||
|
|
}
|
||
|
|
iot_sg_route_control(IOT_SG_CALLER_TYPE_CLI,
|
||
|
|
IOT_SG_CCO_RT_CTRL_MR_FAILED);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case SG_READ_PM_SUCCEED:
|
||
|
|
{
|
||
|
|
if (iot_mac_addr_cmp(cli_drv_data->cur_mr_pm, req->mac)) {
|
||
|
|
os_mem_set(cli_drv_data->cur_mr_pm, 0, IOT_MAC_ADDR_LEN);
|
||
|
|
if (0 == ++cli_drv_data->req_sn) {
|
||
|
|
cli_drv_data->req_sn = 1;
|
||
|
|
}
|
||
|
|
iot_sg_route_control(IOT_SG_CALLER_TYPE_CLI,
|
||
|
|
IOT_SG_CCO_RT_CTRL_MR_SUCCESS);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case SG_MAY_READ_PM:
|
||
|
|
{
|
||
|
|
if (!iot_mac_addr_cmp(cli_drv_data->cur_mr_pm, req->mac)) {
|
||
|
|
return ERR_INVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (iot_sg_get_wl_entry_info_by_mac(req->mac, &node_info)) {
|
||
|
|
/* failed to get meter info */
|
||
|
|
return ERR_NOT_EXIST;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (0 == ++cli_drv_data->req_sn) {
|
||
|
|
cli_drv_data->req_sn = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_sg_get_cco_mac(cco_mac);
|
||
|
|
|
||
|
|
/* update pkt to have meter reading data in its data block */
|
||
|
|
iot_pkt_set_data(pkt, req->data);
|
||
|
|
iot_pkt_set_tail(pkt, req->data + req->data_len);
|
||
|
|
|
||
|
|
result = (uint8_t)iot_sg_cco_cache_sg_mr_cmd(IOT_SG_RMT_ROUTER,
|
||
|
|
req->sn, SG_AFN_RMT_ROUTER, req->proto_type, cco_mac, req->mac, pkt,
|
||
|
|
IOT_SG_CALLER_TYPE_CLI, IOT_SG_CCO_TASK_PRIO_3,
|
||
|
|
iot_sg_cco_get_mr_timeout(IOT_SG_CALLER_TYPE_CLI,
|
||
|
|
IOT_SG_RMT_ROUTER), 1, IOT_SG_INVALID_TASK_ID, 1, 0);
|
||
|
|
if (ERR_OK == result) {
|
||
|
|
*consumed = 1;
|
||
|
|
iot_sg_cco_enable_mr(IOT_SG_CALLER_TYPE_CLI);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
result = ERR_INVAL;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief iot_cli_drv_route_mr_data() - running route meter
|
||
|
|
* reading data task
|
||
|
|
* @param req: cli request route meter reading data cmd down link
|
||
|
|
* @param pkt: iot_pkt_t containing the cli request pkt.
|
||
|
|
* @return 0 - iot_pkt is not consumed.
|
||
|
|
* otherwise - iot_pkt is consumed.
|
||
|
|
*/
|
||
|
|
static uint8_t iot_cli_drv_route_mr_data(iot_cli_sg_rpt_rt_mr_data_dl *req,
|
||
|
|
iot_pkt_t *pkt)
|
||
|
|
{
|
||
|
|
iot_pkt_t *buf_pkt = NULL;
|
||
|
|
iot_cli_sg_result_t *rsp = NULL;
|
||
|
|
uint16_t rsp_len;
|
||
|
|
uint8_t consumed = 0;
|
||
|
|
|
||
|
|
/* allocate buffer for response */
|
||
|
|
rsp_len = iot_cli_sg_get_headroom_req() +
|
||
|
|
sizeof(iot_cli_sg_result_t);
|
||
|
|
buf_pkt = iot_pkt_alloc(rsp_len, IOT_SMART_GRID_MID);
|
||
|
|
IOT_ASSERT(buf_pkt);
|
||
|
|
|
||
|
|
/* fill response info */
|
||
|
|
rsp = (iot_cli_sg_result_t*)iot_pkt_reserve(buf_pkt,
|
||
|
|
iot_cli_sg_get_headroom_req());
|
||
|
|
|
||
|
|
if (!iot_sg_cco_is_ready()) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (iot_sg_get_rt_mr_state() & IOT_SG_CALLER_TYPE_CCTT) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
if (!iot_sg_cco_get_power_status()) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!iot_sg_cco_get_online_sta_count()) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
rsp->result = ERR_OK;
|
||
|
|
switch (req->action) {
|
||
|
|
case IOT_CLI_SG_RT_START_MR_CMD:
|
||
|
|
{
|
||
|
|
/* restart : router shall restart meter reading*/
|
||
|
|
iot_sg_route_control(IOT_SG_CALLER_TYPE_CLI,
|
||
|
|
IOT_SG_CCO_RT_CTRL_RESTART);
|
||
|
|
cli_drv_data->req_sn = 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_RT_STOP_MR_CMD:
|
||
|
|
{
|
||
|
|
iot_sg_route_control(IOT_SG_CALLER_TYPE_CLI,
|
||
|
|
IOT_SG_CCO_RT_CTRL_MR_STOP);
|
||
|
|
cli_drv_data->req_sn = 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_RT_RUNNING_MR_CMD:
|
||
|
|
{
|
||
|
|
rsp->result = iot_cli_drv_run_rt_mr_data(req, pkt, &consumed);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
rsp->result = ERR_INVAL;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
end:
|
||
|
|
iot_cli_sg_send_data_to_cli_interface(buf_pkt,
|
||
|
|
IOT_CLI_SG_MSG_PRT_METER, 0);
|
||
|
|
return consumed;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief cli_drv_send_router_data_change - CCo to send router change msg
|
||
|
|
* @param sn: sequence number.
|
||
|
|
* @param mission_change: 1 - meter read finished
|
||
|
|
* 2 - search meter finished
|
||
|
|
* 3 - transformer detect finished
|
||
|
|
* @param intf_type: see IOT_SG_CALLER_TYPE_XXX
|
||
|
|
|
||
|
|
*/
|
||
|
|
static void cli_drv_send_router_data_change(uint8_t sn, uint8_t mission_change,
|
||
|
|
uint8_t intf_type)
|
||
|
|
{
|
||
|
|
(void)sn;
|
||
|
|
(void)intf_type;
|
||
|
|
|
||
|
|
if (IOT_SG_CCO_RT_CHG_STOP_SEARCH_METER == mission_change) {
|
||
|
|
iot_sg_printf("%s stop search meter \n", __FUNCTION__);
|
||
|
|
} else if (IOT_SG_CCO_RT_CHG_STOP_READ_METER == mission_change) {
|
||
|
|
iot_sg_printf("%s stop meter reading \n", __FUNCTION__);
|
||
|
|
} else if (IOT_SG_CCO_RT_CHG_STOP_TSFM_DETECT == mission_change) {
|
||
|
|
iot_sg_printf("%s stop transformer detect \n", __FUNCTION__);
|
||
|
|
} else {
|
||
|
|
iot_sg_printf("%s get error mission change \n", __FUNCTION__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief - report cctt meter data from CCO module.
|
||
|
|
* @param data: report meter data
|
||
|
|
* @param len: length of the data
|
||
|
|
* @param afn: afn for meter reading
|
||
|
|
* @param sn: concentrator cmd sn
|
||
|
|
* @param proto_type: proto type of data
|
||
|
|
* @param mac_field: address field of meter
|
||
|
|
* @param mr_result: read meter result
|
||
|
|
* @param plc_cost: time cost in PLC in 1ms
|
||
|
|
* @param mr_type: meter read type, see IOT_SG_RMT_XXX
|
||
|
|
* @param intf_type: see IOT_SG_CALLER_TYPE_XXX
|
||
|
|
* @retval: 0 -- successful case
|
||
|
|
* @retval: otherwise -- failure case
|
||
|
|
*/
|
||
|
|
static uint32_t cli_drv_rpt_meter_data_handler(uint8_t *data, uint16_t len,
|
||
|
|
uint32_t afn, uint16_t sn, uint32_t proto_type, uint8_t *mac_field,
|
||
|
|
uint8_t mr_result, uint32_t plc_cost, uint8_t mr_type, uint8_t intf_type)
|
||
|
|
{
|
||
|
|
(void)afn;
|
||
|
|
(void)sn;
|
||
|
|
(void)mac_field;
|
||
|
|
(void)mr_result;
|
||
|
|
(void)plc_cost;
|
||
|
|
(void)mr_type;
|
||
|
|
(void)intf_type;
|
||
|
|
iot_cli_sg_rpt_mr_data_ul *rsp = NULL;
|
||
|
|
iot_pkt_t *pkt = NULL;
|
||
|
|
uint16_t pkt_len;
|
||
|
|
|
||
|
|
if (NULL == data) {
|
||
|
|
len = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
pkt_len = iot_cli_sg_get_headroom_req() + sizeof(*rsp) + len;
|
||
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
||
|
|
IOT_ASSERT(pkt);
|
||
|
|
|
||
|
|
/* fill response info */
|
||
|
|
rsp = (iot_cli_sg_rpt_mr_data_ul*)iot_pkt_reserve(pkt,
|
||
|
|
iot_cli_sg_get_headroom_req());
|
||
|
|
rsp->result = ERR_OK;
|
||
|
|
rsp->proto_type = (uint8_t)proto_type;
|
||
|
|
rsp->sn = (uint8_t)sn;
|
||
|
|
os_mem_cpy(rsp->mac, mac_field, IOT_MAC_ADDR_LEN);
|
||
|
|
rsp->datalen = len;
|
||
|
|
if (len) {
|
||
|
|
os_mem_cpy(rsp->data, data, len);
|
||
|
|
}
|
||
|
|
iot_cli_sg_send_data_to_cli_interface(pkt,
|
||
|
|
IOT_CLI_SG_MSG_PRT_METER_DATA, IOT_CLI_SG_REQ_ID_DEFAULT);
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief cli_drv_rt_req_read_meter - router request meter reading.
|
||
|
|
* @param phase: power meter phase
|
||
|
|
* @param mac: power meter mac address, little-endian
|
||
|
|
* @param index: power meter index
|
||
|
|
* @param obj_type: communication object type, see PROTO_3762_FJ_OBJ_XXX
|
||
|
|
* @param intf_type: see IOT_SG_CALLER_TYPE_XXX
|
||
|
|
*/
|
||
|
|
void cli_drv_rt_req_read_meter(uint8_t phase, uint8_t *mac,
|
||
|
|
uint16_t index, uint8_t obj_type, uint8_t intf_type)
|
||
|
|
{
|
||
|
|
(void)obj_type;
|
||
|
|
(void)intf_type;
|
||
|
|
iot_cli_request_rt_mr_data_ul dec_data = { 0 };
|
||
|
|
|
||
|
|
iot_mac_addr_cpy(dec_data.mac_addr, mac);
|
||
|
|
dec_data.phase = phase;
|
||
|
|
dec_data.node_index = index;
|
||
|
|
dec_data.sn = cli_drv_data->req_sn;
|
||
|
|
/* request read meter */
|
||
|
|
dec_data.opt_flag = IOT_SG_RT_MR_REQUEST;
|
||
|
|
iot_cli_drv_request_rt_mr_data(&dec_data);
|
||
|
|
|
||
|
|
iot_mac_addr_cpy(cli_drv_data->cur_mr_pm, mac);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint8_t iot_cli_drv_read_meter_data(iot_cli_sg_rpt_mr_data_dl *req,
|
||
|
|
uint8_t req_id, iot_pkt_t *pkt)
|
||
|
|
{
|
||
|
|
iot_pkt_t *buf_pkt = NULL;
|
||
|
|
iot_cli_sg_result_t *rsp =NULL;
|
||
|
|
uint16_t rsp_len;
|
||
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN] = {0};
|
||
|
|
uint8_t consumed = 0;
|
||
|
|
uint8_t afn = 0;
|
||
|
|
uint8_t mr_result = 0;
|
||
|
|
uint32_t mr_count = 0;
|
||
|
|
|
||
|
|
/* allocate buffer for response */
|
||
|
|
rsp_len = iot_cli_sg_get_headroom_req() +
|
||
|
|
sizeof(iot_cli_sg_result_t);
|
||
|
|
buf_pkt = iot_pkt_alloc(rsp_len, IOT_SMART_GRID_MID);
|
||
|
|
IOT_ASSERT(buf_pkt);
|
||
|
|
|
||
|
|
/* fill response info */
|
||
|
|
rsp = (iot_cli_sg_result_t*)iot_pkt_reserve(buf_pkt,
|
||
|
|
iot_cli_sg_get_headroom_req());
|
||
|
|
|
||
|
|
if (!iot_sg_cco_is_ready()) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!iot_sg_cco_get_power_status()) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_mac_addr_reverse(req->mac);
|
||
|
|
|
||
|
|
if (iot_sg_cco_get_wl_cnt() &&
|
||
|
|
(!iot_sg_cco_wl_entry_exist(req->mac))) {
|
||
|
|
/* white list is not empty, */
|
||
|
|
/* meter to be read is not in white list. */
|
||
|
|
rsp->result = ERR_INVAL;
|
||
|
|
iot_sg_printf("cli mr data inval, meter mac error \n");
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (IOT_SG_RMT_CCTT_CON == req->mr_type) {
|
||
|
|
mr_result = iot_sg_cco_check_exceed_con_cnt(req->mac);
|
||
|
|
rsp->result = mr_result;
|
||
|
|
if (ERR_OK != mr_result) {
|
||
|
|
rsp->result = EXCEED_DEV_MAX_CONCURRENT_COUNT;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
if ((req->proto_type == PROTO_TYPE_698_45 ||
|
||
|
|
req->proto_type == PROTO_TYPE_RAW_DATA) &&
|
||
|
|
req->data_len > IOT_SG_CON_MR_MAX_69845_LEN) {
|
||
|
|
/* data type is 698.45, and length exceed max length, send NACK */
|
||
|
|
rsp->result = EXCEED_DEV_PKT_COUNT;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (req->proto_type == PROTO_TYPE_645_1997 ||
|
||
|
|
req->proto_type == PROTO_TYPE_645_2007) {
|
||
|
|
mr_count = iot_sg_cco_get_645_pkt_cnt(req->data, req->data_len);
|
||
|
|
if (0 == mr_count) {
|
||
|
|
rsp->result = ERR_INVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
if (mr_count > IOT_SG_CON_MR_MAX_645_CNT) {
|
||
|
|
/* data type is 645, and packet exceed max count, send NACK */
|
||
|
|
rsp->result = EXCEED_DEV_PKT_COUNT;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (iot_sg_cco_cache_has_sg_mr_cmd(req->mac)) {
|
||
|
|
rsp->result = ERR_EXIST;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
afn = SG_AFN_RMT_CCTT_CON;
|
||
|
|
} else if (IOT_SG_RMT_CCTT == req->mr_type) {
|
||
|
|
if (iot_sg_cco_cache_has_sg_mr_cmd_ex(req->mac, req->sn)) {
|
||
|
|
rsp->result = ERR_INVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
afn = SG_AFN_RMT_CCTT;
|
||
|
|
} else {
|
||
|
|
rsp->result = ERR_INVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_sg_get_cco_mac(cco_mac);
|
||
|
|
|
||
|
|
/* update pkt to have meter reading data in its data block */
|
||
|
|
iot_pkt_set_data(pkt, req->data);
|
||
|
|
iot_pkt_set_tail(pkt, req->data + req->data_len);
|
||
|
|
|
||
|
|
rsp->result = (uint8_t)iot_sg_cco_cache_sg_mr_cmd(req->mr_type,
|
||
|
|
req->sn, afn, req->proto_type, cco_mac, req->mac, pkt,
|
||
|
|
IOT_SG_CALLER_TYPE_CLI, IOT_SG_CCO_TASK_PRIO_3,
|
||
|
|
iot_sg_cco_get_mr_timeout(IOT_SG_CALLER_TYPE_CLI, req->mr_type),
|
||
|
|
1, IOT_SG_INVALID_TASK_ID, 1, 0);
|
||
|
|
if (rsp->result == ERR_OK) {
|
||
|
|
consumed = 1;
|
||
|
|
iot_sg_cco_enable_mr(IOT_SG_CALLER_TYPE_CLI);
|
||
|
|
} else {
|
||
|
|
rsp->result = ERR_INVAL;
|
||
|
|
if (IOT_SG_RMT_CCTT_CON == req->mr_type) {
|
||
|
|
rsp->result = EXCEED_DEV_MAX_CONCURRENT_COUNT;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
end:
|
||
|
|
iot_cli_sg_send_data_to_cli_interface(buf_pkt,
|
||
|
|
IOT_CLI_SG_MSG_PRT_METER, req_id);
|
||
|
|
return consumed;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void iot_cli_start_get_meter_list(
|
||
|
|
iot_cli_sg_start_sec_node_reg_dl_t *data, uint8_t req_id)
|
||
|
|
{
|
||
|
|
uint32_t dur_s = 0;
|
||
|
|
iot_cli_sg_result_t *rsp;
|
||
|
|
iot_pkt_t *buf_pkt;
|
||
|
|
uint16_t rsp_len;
|
||
|
|
|
||
|
|
/* allocate buffer for response */
|
||
|
|
rsp_len = iot_cli_sg_get_headroom_req() + sizeof(iot_cli_sg_result_t);
|
||
|
|
buf_pkt = iot_pkt_alloc(rsp_len, IOT_SMART_GRID_MID);
|
||
|
|
IOT_ASSERT(buf_pkt);
|
||
|
|
|
||
|
|
/* fill response info */
|
||
|
|
rsp = (iot_cli_sg_result_t*)iot_pkt_reserve(buf_pkt,
|
||
|
|
iot_cli_sg_get_headroom_req());
|
||
|
|
if (!iot_sg_cco_get_router_sec_node_reg_allowed()) {
|
||
|
|
rsp->result = ERR_NOSUPP;
|
||
|
|
} else if (iot_sg_cco_get_tsfm_detect_status() !=
|
||
|
|
IOT_SG_CCO_TSFM_DETECT_DONE) {
|
||
|
|
rsp->result = ERR_BUSY;
|
||
|
|
} else {
|
||
|
|
if (data->duration == 0) {
|
||
|
|
data->duration = IOT_CLI_DEFAULT_SEC_NODE_REG_DUR;
|
||
|
|
}
|
||
|
|
dur_s = data->duration * IOT_CLI_SEC_NODE_REG_TIME_UNIT_DUR;
|
||
|
|
rsp->result = (uint8_t)iot_sg_start_sec_node_reg(
|
||
|
|
IOT_SG_CALLER_TYPE_CLI, dur_s, IOT_CLI_MAX_ADDR_COUNT, 1);
|
||
|
|
}
|
||
|
|
iot_cli_sg_send_data_to_cli_interface(buf_pkt,
|
||
|
|
IOT_CLI_SG_MSG_RPT_START_METER_LIST, req_id);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief: iot_cli_handle_report_ack - deal with ack data that from cli.
|
||
|
|
* @param pkt: iot_pkt is ack data form cli
|
||
|
|
* pkt is not consumed
|
||
|
|
*/
|
||
|
|
static void iot_cli_handle_report_ack(iot_pkt_t *pkt)
|
||
|
|
{
|
||
|
|
iot_cli_sg_rpt_ack_dl_t *report_ack = NULL;
|
||
|
|
uint8_t pre_sn = cli_drv_data->req_sn;
|
||
|
|
|
||
|
|
if (!pkt) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
report_ack = (iot_cli_sg_rpt_ack_dl_t *)iot_pkt_block_ptr(pkt,
|
||
|
|
IOT_PKT_BLOCK_DATA);
|
||
|
|
|
||
|
|
iot_printf("%s get cli ack type: %d \n", __FUNCTION__, report_ack->type);
|
||
|
|
|
||
|
|
switch (report_ack->type) {
|
||
|
|
case IOT_CLI_SG_MR_DATA_RSP:
|
||
|
|
{
|
||
|
|
if (iot_sg_get_rt_mr_state() & IOT_SG_CALLER_TYPE_CLI) {
|
||
|
|
pre_sn = (0 == pre_sn ? 255 : (pre_sn - 1));
|
||
|
|
if (report_ack->sn == pre_sn) {
|
||
|
|
iot_sg_cco_recv_ack_to_report(1, report_ack->sn);
|
||
|
|
iot_sg_cco_rt_mr_result_ack(report_ack->sn);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_SEC_NODE_REG_DATA_RSP:
|
||
|
|
{
|
||
|
|
iot_sg_cco_recv_ack_to_report(1, report_ack->sn);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief: cli_drv_data_handler - handle data from CLI
|
||
|
|
* @param channel: data sources.
|
||
|
|
* @param pkt: iot_pkt containing data to be process
|
||
|
|
* @retval: 0-iot_pkt is not consumed
|
||
|
|
* @retval: otherwise iot_pkt is consumed
|
||
|
|
*/
|
||
|
|
static uint32_t cli_drv_data_handler(uint8_t channel, iot_pkt_t *pkt,
|
||
|
|
uint32_t ntb)
|
||
|
|
{
|
||
|
|
uint32_t consumed = 0;
|
||
|
|
iot_cli_sg_rpt_mr_data_dl *req;
|
||
|
|
iot_cli_sg_rpt_rt_mr_data_dl *rt_req;
|
||
|
|
iot_cli_sg_msg_header_t *hdr;
|
||
|
|
iot_cli_sg_start_sec_node_reg_dl_t *start_reg_req;
|
||
|
|
uint8_t* data_ptr = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
||
|
|
hdr = (iot_cli_sg_msg_header_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD);
|
||
|
|
|
||
|
|
(void)ntb;
|
||
|
|
(void)channel;
|
||
|
|
switch (hdr->msg_id) {
|
||
|
|
case IOT_CLI_SG_MSG_GET_METER:
|
||
|
|
{
|
||
|
|
/* handle con mr/cctt active mr */
|
||
|
|
req = (iot_cli_sg_rpt_mr_data_dl *)data_ptr;
|
||
|
|
consumed = iot_cli_drv_read_meter_data(req, hdr->req_id, pkt);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_MSG_GET_RT_METER:
|
||
|
|
{
|
||
|
|
/* handle router meter reading. */
|
||
|
|
rt_req = (iot_cli_sg_rpt_rt_mr_data_dl *)data_ptr;
|
||
|
|
consumed = iot_cli_drv_route_mr_data(rt_req, pkt);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_MSG_START_METER_LIST:
|
||
|
|
{
|
||
|
|
start_reg_req = (iot_cli_sg_start_sec_node_reg_dl_t *)data_ptr;
|
||
|
|
iot_cli_start_get_meter_list(start_reg_req, hdr->req_id);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_MSG_STOP_METER_LIST:
|
||
|
|
{
|
||
|
|
iot_sg_stop_sec_node_reg(IOT_SG_CALLER_TYPE_CLI,
|
||
|
|
IOT_SG_CCO_STOP_SEC_NODE_REG_CLI);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case IOT_CLI_SG_MSG_GET_REPORT_ACK:
|
||
|
|
{
|
||
|
|
iot_cli_handle_report_ack(pkt);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
iot_sg_printf("%s unable to handle msg id: 0n%d\n",
|
||
|
|
__FUNCTION__, hdr->msg_id);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return consumed;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_sec_node_info_handler(uint8_t sn, uint16_t index,
|
||
|
|
sec_node_query_t *sec_node_info)
|
||
|
|
{
|
||
|
|
iot_cli_sg_rpt_sec_node_info_ul_t *rsp = NULL;
|
||
|
|
uint16_t pkt_len = 0;
|
||
|
|
uint8_t cnt = 0, i = 0;
|
||
|
|
iot_pkt_t *pkt;
|
||
|
|
|
||
|
|
(void)index;
|
||
|
|
cnt = sec_node_info->contain_sec_node_count;
|
||
|
|
pkt_len = sizeof(*rsp) + sizeof(iot_cli_sg_sec_node_info_t) * cnt;
|
||
|
|
pkt_len += iot_cli_sg_get_headroom_req();
|
||
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
||
|
|
if (pkt == NULL) {
|
||
|
|
return ERR_NOMEM;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* fill response info */
|
||
|
|
rsp = (iot_cli_sg_rpt_sec_node_info_ul_t*)iot_pkt_reserve(pkt,
|
||
|
|
iot_cli_sg_get_headroom_req());
|
||
|
|
for (i = 0; i < sec_node_info->contain_sec_node_count; i++) {
|
||
|
|
rsp->node_info[i].proto_type =
|
||
|
|
sec_node_info->node_info[i].proto_type & 0x0F;
|
||
|
|
rsp->node_info->dev_type =
|
||
|
|
iot_sg_cco_get_node_cli_dev_type(sec_node_info->dev_type) & 0x0F;
|
||
|
|
iot_mac_addr_cpy(rsp->node_info[i].sta_mac, sec_node_info->sta_addr);
|
||
|
|
iot_mac_addr_cpy(rsp->node_info[i].meter_mac,
|
||
|
|
sec_node_info->node_info[i].mac);
|
||
|
|
}
|
||
|
|
rsp->sn = sn;
|
||
|
|
rsp->sec_node_count = 1;
|
||
|
|
rsp->rsp_sec_node_count = i;
|
||
|
|
iot_pkt_put(pkt, pkt_len - iot_cli_sg_get_headroom_req());
|
||
|
|
iot_cli_sg_send_data_to_cli_interface(pkt,
|
||
|
|
IOT_CLI_SG_MSG_PRT_SEARCH_METER_LIST, IOT_CLI_SG_REQ_ID_DEFAULT);
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_event_data_handler(uint8_t sn, uint8_t *pm_addr,
|
||
|
|
uint8_t dev_type, uint32_t proto_type, uint8_t evt_type,
|
||
|
|
uint8_t *data, uint16_t len)
|
||
|
|
{
|
||
|
|
(void)sn;
|
||
|
|
(void)pm_addr;
|
||
|
|
(void)dev_type;
|
||
|
|
(void)proto_type;
|
||
|
|
(void)evt_type;
|
||
|
|
(void)data;
|
||
|
|
(void)len;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_topo_handler(
|
||
|
|
uint8_t req_id, iot_plc_nw_topo_rpt_t *rpt)
|
||
|
|
{
|
||
|
|
(void)rpt;
|
||
|
|
(void)req_id;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_neighbor_net_handler(uint8_t req_id,
|
||
|
|
iot_sg_nb_nw_rpt_t *req)
|
||
|
|
{
|
||
|
|
(void)req_id;
|
||
|
|
(void)req;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_freq_band_handler(uint8_t req_id,
|
||
|
|
iot_plc_freq_band_info_query_rpt_t *req)
|
||
|
|
{
|
||
|
|
(void)req_id;
|
||
|
|
(void)req;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_freq_band_set_result_handler(uint8_t req_id,
|
||
|
|
uint8_t result)
|
||
|
|
{
|
||
|
|
(void)result;
|
||
|
|
(void)req_id;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_rf_channel_set_result_handler(uint8_t req_id,
|
||
|
|
uint8_t result)
|
||
|
|
{
|
||
|
|
(void)result;
|
||
|
|
(void)req_id;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_rpt_tx_power_set_result_handler(uint8_t req_id,
|
||
|
|
uint8_t result)
|
||
|
|
{
|
||
|
|
(void)result;
|
||
|
|
(void)req_id;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_rpt_nw_info_handler(uint8_t req_id,
|
||
|
|
iot_plc_nw_info_query_rpt_t *rpt)
|
||
|
|
{
|
||
|
|
(void)req_id;
|
||
|
|
(void)rpt;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_timer_handler()
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_log_to_flash_timer_handler()
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint8_t cli_drv_sta_state_chg_handler(uint8_t state, uint8_t *sta_mac)
|
||
|
|
{
|
||
|
|
(void)sta_mac;
|
||
|
|
(void)state;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_rpt_tsfm_detect_ret_handler(uint8_t *pm_mac,
|
||
|
|
uint8_t *tsfm_addr, uint8_t tsfm_status, uint8_t dev_type)
|
||
|
|
{
|
||
|
|
(void)pm_mac;
|
||
|
|
(void)tsfm_addr;
|
||
|
|
(void)tsfm_status;
|
||
|
|
(void)dev_type;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint8_t cli_drv_mr_data_valid_handler(uint8_t mr_type, uint8_t *pm_addr)
|
||
|
|
{
|
||
|
|
(void)pm_addr;
|
||
|
|
(void)mr_type;
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_tsfm_detect_done_handler(uint8_t tsfm_is_timeout)
|
||
|
|
{
|
||
|
|
(void)tsfm_is_timeout;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_rpt_reject_join_handler(iot_plc_sta_join_rejected_t *node)
|
||
|
|
{
|
||
|
|
(void)node;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_cco_state_chg_handler(uint8_t curr_state, uint8_t next_state,
|
||
|
|
uint8_t *cert_flag_chg)
|
||
|
|
{
|
||
|
|
(void)curr_state;
|
||
|
|
(void)next_state;
|
||
|
|
(void)cert_flag_chg;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_rpt_node_info_handler(uint8_t req_id,
|
||
|
|
iot_plc_node_info_rpt_t *rpt)
|
||
|
|
{
|
||
|
|
(void)req_id;
|
||
|
|
(void)rpt;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint32_t cli_drv_data_to_cctt_handler(iot_pkt_t *pkt)
|
||
|
|
{
|
||
|
|
iot_pkt_free(pkt);
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_nw_fmt_done_handler(void)
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_handle_node_state_chg_rpt(uint8_t sn,
|
||
|
|
sec_node_state_chg_t *node_chg)
|
||
|
|
{
|
||
|
|
(void)sn;
|
||
|
|
(void)node_chg;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_neighbor_dev_rpt(uint8_t req_id,
|
||
|
|
iot_plc_neighbor_dev_rpt_t *rpt)
|
||
|
|
{
|
||
|
|
(void)req_id;
|
||
|
|
(void)rpt;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_cco_info_rpt(uint8_t req_id, iot_sg_cco_info_rpt_t *rpt)
|
||
|
|
{
|
||
|
|
(void)req_id;
|
||
|
|
(void)rpt;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void cli_drv_bcast_result_rpt(uint8_t done)
|
||
|
|
{
|
||
|
|
(void)done;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_sg_cco_drv_t iot_sg_cli_drv = {
|
||
|
|
.drv_id = IOT_SG_CCTT_DRV_ID_CLI,
|
||
|
|
.init = cli_drv_init,
|
||
|
|
.deinit = cli_drv_deinit,
|
||
|
|
.data_type_mask = 0xFFFF,
|
||
|
|
.headroom = 0,
|
||
|
|
.meter_data_report_cb = cli_drv_rpt_meter_data_handler,
|
||
|
|
.event_data_report_cb = cli_drv_rpt_event_data_handler,
|
||
|
|
.sec_node_report_cb = cli_drv_sec_node_info_handler,
|
||
|
|
.topo_report_cb = cli_drv_rpt_topo_handler,
|
||
|
|
.neighbour_net_report_cb = cli_drv_rpt_neighbor_net_handler,
|
||
|
|
.freq_band_report_cb = cli_drv_rpt_freq_band_handler,
|
||
|
|
.freq_band_set_result_report_cb = cli_drv_rpt_freq_band_set_result_handler,
|
||
|
|
.rf_channel_set_result_report_cb = cli_drv_rpt_rf_channel_set_result_handler,
|
||
|
|
.tx_power_set_result_report_cb = cli_drv_rpt_tx_power_set_result_handler,
|
||
|
|
.nw_info_rpt_cb = cli_drv_rpt_nw_info_handler,
|
||
|
|
.report_router_status_change = cli_drv_send_router_data_change,
|
||
|
|
.cctt_data_handler = cli_drv_data_handler,
|
||
|
|
.timer1_func = cli_drv_timer_handler,
|
||
|
|
.timer2_func = cli_drv_timer_handler,
|
||
|
|
.timer3_func = cli_drv_timer_handler,
|
||
|
|
.timer4_func = cli_drv_timer_handler,
|
||
|
|
.timer5_func = cli_drv_timer_handler,
|
||
|
|
.timer6_func = cli_drv_timer_handler,
|
||
|
|
.log_to_flash_timer_func = cli_drv_log_to_flash_timer_handler,
|
||
|
|
.sta_state_chg_cb = cli_drv_sta_state_chg_handler,
|
||
|
|
.rpt_tsfm_detect_ret_cb = cli_drv_rpt_tsfm_detect_ret_handler,
|
||
|
|
.cco_status_chg_cb = cli_drv_cco_state_chg_handler,
|
||
|
|
.mr_data_valid_cb = cli_drv_mr_data_valid_handler,
|
||
|
|
.node_info_rpt_cb = cli_drv_rpt_node_info_handler,
|
||
|
|
.rt_request_mr_cb = cli_drv_rt_req_read_meter,
|
||
|
|
.tsfm_detect_done_cb = cli_drv_tsfm_detect_done_handler,
|
||
|
|
.reject_join_cb = cli_drv_rpt_reject_join_handler,
|
||
|
|
.passthrough_to_cctt_cb = cli_drv_data_to_cctt_handler,
|
||
|
|
.nw_fmt_done_cb = cli_drv_nw_fmt_done_handler,
|
||
|
|
.node_state_chg_cb = cli_drv_handle_node_state_chg_rpt,
|
||
|
|
.neighbor_dev_report_cb = cli_drv_neighbor_dev_rpt,
|
||
|
|
.cco_info_report_cb = cli_drv_cco_info_rpt,
|
||
|
|
.cco_rpt_bcast_result_cb = cli_drv_bcast_result_rpt,
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif /* IOT_SMART_GRID_ENABLE && PLC_SUPPORT_CCO_ROLE */
|
||
|
|
|