Files
kunlun/app/smart_grid/sta/iot_sg_sta_nw.c
2024-09-28 14:24:04 +08:00

8669 lines
282 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_shim header files */
#include "os_types_api.h"
#include "os_timer_api.h"
#include "os_utils_api.h"
#include "iot_system_api.h"
/* iot common header files */
#include "iot_plc_sta_api.h"
#include "iot_app_api.h"
#include "iot_errno_api.h"
#include "iot_queue_api.h"
#include "iot_mem_pool_api.h"
#include "iot_dbglog_api.h"
#include "iot_io_api.h"
#include "iot_bitmap_api.h"
#include "iot_oem_api.h"
#include "iot_board_api.h"
#include "iot_crc_api.h"
/* smart grid internal header files */
#include "iot_sg_fr.h"
#include "iot_sg.h"
#include "iot_sg_msg.h"
#include "iot_sg_sta.h"
#include "proto_nw_app.h"
#include "proto_645.h"
#include "proto_645_vendor.h"
#include "proto_69845.h"
#include "proto_spg.h"
#include "iot_sg_sta_drv_api.h"
#include "iot_sg_sta_upgrade.h"
#include "iot_sg_sta_nw.h"
#include "iot_sg_sta_ext.h"
#if (PLC_SUPPORT_STA_ROLE && IOT_NW_APP_ENABLE)
/* when sta isn't power off, collect power off event messages published by
* neighbor nodes timeout, uint is 1ms.
*/
#define IOT_SG_STA_NW_COLLECT_EVENT_RPT_DUR (30 * 1000)
/* when sta isn't power off, collect power off event messages published by
* neighbor nodes timeout, uint is 1ms.
*/
#define IOT_SG_STA_GD_COLLECT_EVENT_RPT_DUR (60 * 1000)
/* define max cnt of collect feature data */
#define IOT_SG_STA_NW_TSFM_COLLECT_MAX (85)
/* define ctrl passthrough proto minimum baud rate allowed */
#define IOT_SG_STA_NW_CTRL_PASSTHR_MIN_BAUD (1200)
/* define max node count of neighbor info query */
#define IOT_SG_STA_NW_NEIGHBOR_QUERY_MAX_CNT (20)
/* define load cure di data response max len, cco nw_app_fwd_ul_t data_len
* max support 253 byte, reserved 3 byte is 250 byte.
* max len = 250 + sizeof(nw_app_header_t) + sizeof(nw_app_data_t) +
* sizeof(nw_app_fwd_ul_t);
*/
#define IOT_SG_STA_NW_LC_DI_DATA_RESP_MAX_LEN (278)
/* define nw rtc update delta */
#define IOT_SG_STA_NW_RTC_UPDATE_DELTA (60)
/* define nw power on report boardcast retry count */
#define IOT_SG_STA_NW_BCAST_RETRY_CNT 3
/* define state score enable valid time, unit is 1s */
#define IOT_SG_STA_SCORE_EN_VALID_TIME (60 * 60 * 6)
static uint8_t iot_sg_sta_nw_bcast1_addr[IOT_MAC_ADDR_LEN] =
{ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99 };
static uint8_t iot_sg_sta_nw_bcast2_addr[IOT_MAC_ADDR_LEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
uint32_t iot_sg_sta_nw_correct_time_req_check(uint8_t *data, uint32_t len)
{
uint8_t addr[IOT_MAC_ADDR_LEN] = { 0 };
uint32_t ret = ERR_INVAL;
nw_app_header_t *nw_app_hdr;
nw_app_data_t *nw_app_data_hdr;
nw_app_control_t *nw_control;
nw_app_fwd_dl_t *mr_req;
if (len < sizeof(nw_app_header_t) + sizeof(nw_app_data_t)) {
goto out;
}
len -= sizeof(nw_app_header_t) + sizeof(nw_app_data_t);
nw_app_hdr = (nw_app_header_t *)data;
nw_app_data_hdr = (nw_app_data_t *)(nw_app_hdr + 1);
nw_control = &nw_app_data_hdr->control_field;
if (nw_app_hdr->port != NW_APP_PORT || nw_app_hdr->id != NW_APP_ID
|| nw_app_data_hdr->ver != NW_APP_VERSION) {
goto out;
}
if (nw_control->frame_type != NW_APP_FRAME_TYPE_DATA_FWD) {
goto out;
}
if (nw_app_data_hdr->work_id != NW_APP_WORK_DATA_FWD_TRANSPARENT) {
goto out;
}
if (len < sizeof(*mr_req)) {
goto out;
}
len -= sizeof(*mr_req);
mr_req = (nw_app_fwd_dl_t *)nw_app_data_hdr->data;
if (mr_req->data_len > len) {
goto out;
}
if (proto_645_corr_msg_check(mr_req->data, mr_req->data_len,
addr) == ERR_OK) {
if (proto_645_is_bcast(addr) || iot_sg_sta_node_find_by_addr(addr)) {
ret = ERR_OK;
goto out;
}
}
if (proto_69845_corr_msg_check(mr_req->data, mr_req->data_len,
addr) == ERR_OK) {
if (proto_69845_is_any_server_addr(addr) ||
iot_sg_sta_node_find_by_addr(addr)) {
ret = ERR_OK;
goto out;
}
}
out:
return ret;
}
uint32_t iot_sg_sta_nw_sec_check(uint8_t *data, uint32_t len,
bool_t *is_mr_pkt)
{
uint8_t reason = 0;
uint32_t ret = ERR_OK;
uint32_t tmp = sizeof(nw_app_header_t) + sizeof(nw_app_data_t);
nw_app_header_t *nw_app_hdr = NULL;
nw_app_data_t *nw_app_data_hdr = NULL;
nw_app_control_t *nw_control = NULL;
if (len < tmp) {
reason = 1;
goto drop;
}
nw_app_hdr = (nw_app_header_t *)data;
nw_app_data_hdr = (nw_app_data_t *)(nw_app_hdr + 1);
nw_control = &nw_app_data_hdr->control_field;
if ((nw_app_hdr->port != NW_APP_PORT && nw_app_hdr->port != NW_APP_PORT_MGR
&& nw_app_hdr->port != NW_APP_PORT_PT)
|| nw_app_hdr->id != NW_APP_ID
|| nw_app_data_hdr->ver != NW_APP_VERSION) {
reason = 2;
goto drop;
}
if (nw_app_data_hdr->len > (len - tmp)) {
reason = 3;
goto drop;
}
if (nw_app_hdr->port == NW_APP_PORT_MGR &&
nw_control->frame_type != NW_APP_FRAME_TYPE_DATA_FWD &&
nw_control->frame_type != NW_APP_FRAME_TYPE_CMD &&
nw_control->frame_type != NW_APP_FRAME_TYPE_RPT &&
nw_control->frame_type != NW_APP_FRAME_TYPE_BCAST_CMD &&
nw_control->frame_type != NW_APP_FRAME_TYPE_PT) {
reason = 4;
goto drop;
}
switch (nw_control->frame_type) {
case NW_APP_FRAME_TYPE_DATA_FWD:
{
/* check if this is downlink request */
if (nw_control->dir != NW_APP_CONTROL_DOWN_LINK
|| nw_control->start != NW_APP_CONTROL_PRM_MASTER) {
reason = 5;
goto drop;
}
if ((nw_app_data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANSPARENT ||
nw_app_data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANS_MODULE)
&& is_mr_pkt) {
*is_mr_pkt = true;
}
break;
}
default:
break;
}
goto out;
drop:
ret = ERR_FAIL;
iot_sg_printf("%s drop %lu, frame_type %lu id %lu\n", __FUNCTION__, reason,
(nw_app_data_hdr ? nw_app_data_hdr->control_field.frame_type : 0),
(nw_app_data_hdr ? nw_app_data_hdr->work_id : 0));
out:
return ret;
}
uint8_t iot_sg_sta_nw_sn_cmp(uint8_t *dst_hdr,
uint8_t *src_hdr)
{
uint8_t ret = 0;
nw_app_header_t *hdr, *hdr_queue;
nw_app_data_t *hdr_data, *hdr_data_queue;
IOT_ASSERT(dst_hdr && src_hdr);
hdr = (nw_app_header_t *)src_hdr;
hdr_data = (nw_app_data_t *)(hdr + 1);
hdr_queue = (nw_app_header_t *)dst_hdr;
hdr_data_queue = (nw_app_data_t *)(hdr_queue + 1);
if ((hdr_data_queue->work_id != hdr_data->work_id)
|| (hdr_data_queue->control_field.frame_type !=
hdr_data->control_field.frame_type)) {
goto out;
}
/* if packet sequence in reqeust queue is equal to the packet
* sequence in current pkt, the pkt already exists in the queue
*/
if (hdr_data_queue->sn == hdr_data->sn) {
ret = 1;
}
out:
return ret;
}
uint32_t iot_sg_sta_nw_get_pm_addr(iot_pkt_t *pkt, uint8_t *addr)
{
uint8_t *ser_addr;
uint32_t ret = ERR_FAIL;
nw_app_header_t *hdr;
nw_app_data_t *data_hdr;
nw_app_fwd_dl_t *req;
nw_app_fwd_module_dl_t *req_mod;
proto_645_header_t *hdr_645;
proto_69845_frame_head_info_t *hdr_69845;
hdr = (nw_app_header_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
data_hdr = (nw_app_data_t *)(hdr + 1);
switch (data_hdr->control_field.frame_type) {
case NW_APP_FRAME_TYPE_DATA_FWD:
{
if (data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANSPARENT) {
req = (nw_app_fwd_dl_t *)data_hdr->data;
hdr_645 = proto_645_format_check(req->data, req->data_len,
PROTO_645_DIR_MASTER);
if (hdr_645) {
if (proto_645_pm_addr_valid(hdr_645->addr)) {
iot_mac_addr_cpy(addr, hdr_645->addr);
ret = ERR_OK;
goto out;
}
} else {
hdr_69845 = proto_69845_sanity_check(req->data,
(uint16_t)req->data_len);
if (hdr_69845) {
ser_addr = proto_69845_get_ser_addr(hdr_69845);
iot_mac_addr_cpy(addr, ser_addr);
ret = ERR_OK;
goto out;
}
}
iot_mac_addr_cpy(addr, req->dst_addr);
ret = ERR_OK;
} else if (data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANS_MODULE) {
req_mod = (nw_app_fwd_module_dl_t *)data_hdr->data;
hdr_645 = proto_645_format_check(req_mod->data, req_mod->data_len,
PROTO_645_DIR_MASTER);
if (hdr_645) {
if (proto_645_pm_addr_valid(hdr_645->addr)) {
iot_mac_addr_cpy(addr, hdr_645->addr);
ret = ERR_OK;
goto out;
}
} else {
hdr_69845 = proto_69845_sanity_check(req_mod->data,
(uint16_t)req_mod->data_len);
if (hdr_69845) {
ser_addr = proto_69845_get_ser_addr(hdr_69845);
iot_mac_addr_cpy(addr, ser_addr);
ret = ERR_OK;
goto out;
}
}
iot_mac_addr_cpy(addr, req_mod->dst_addr);
ret = ERR_OK;
}
break;
}
default:
break;
}
out:
return ret;
}
uint32_t iot_sg_sta_nw_queue_app_cache_check(iot_pkt_t *pkt,
uint8_t link_type)
{
uint32_t ret = ERR_OK;
nw_app_header_t *hdr;
nw_app_data_t *hdr_data;
iot_plc_msdu_recv_t *msdu;
msdu = (iot_plc_msdu_recv_t *)(iot_pkt_data(pkt) - sizeof(*msdu));
hdr = (nw_app_header_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
hdr_data = (nw_app_data_t *)(hdr + 1);
switch (hdr_data->control_field.frame_type) {
case NW_APP_FRAME_TYPE_DATA_FWD:
{
if (hdr_data->work_id == NW_APP_WORK_DATA_FWD_TRANSPARENT ||
hdr_data->work_id == NW_APP_WORK_DATA_FWD_TRANS_MODULE) {
ret = iot_sg_sta_mr_cache_check(hdr_data->sn, msdu->src, link_type,
IOT_SG_STA_MR_TYPE_DEF);
}
break;
}
default:
break;
}
return ret;
}
void iot_sg_sta_nw_queue_app_drop(uint8_t *hdr, uint8_t reason)
{
nw_app_header_t *drop_hdr = (nw_app_header_t*)hdr;
nw_app_data_t *drop_data_hdr = NULL;
if (drop_hdr) {
drop_data_hdr = (nw_app_data_t *)(drop_hdr + 1);
}
iot_sg_printf("%s reason %lu frame_type %lu id %lu\n", __FUNCTION__, reason,
((drop_data_hdr) ? drop_data_hdr->control_field.frame_type : 0),
((drop_data_hdr) ? drop_data_hdr->work_id : 0));
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO,
IOT_SG_STA_QUEUE_NW_APP_OTHER_ID, 3,
((drop_data_hdr) ? drop_data_hdr->control_field.frame_type : 0),
((drop_data_hdr) ? drop_data_hdr->work_id : 0), reason);
}
static uint8_t iot_sg_sta_nw_to_drv_data_type(uint8_t work_id,
uint8_t *data, uint16_t len)
{
uint8_t proto645_type;
proto_645_header_t *hdr_645 = NULL;
proto_69845_frame_head_info_t *hdr_698 = NULL;
uint8_t type = IOT_SG_STA_DATA_TYPE_TRANS;
switch (work_id) {
case NW_APP_WORK_DATA_FWD_TRANSPARENT:
{
type = IOT_SG_STA_DATA_TYPE_TRANS;
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
if (hdr_645) {
proto645_type = proto_645_type_identify(hdr_645);
switch (proto645_type) {
case PROTO_645_2007_ID:
{
type = IOT_SG_STA_DATA_TYPE_645_07;
break;
}
case PROTO_645_1997_ID:
{
type = IOT_SG_STA_DATA_TYPE_645_97;
break;
}
default:
break;
}
} else {
hdr_698 = proto_69845_sanity_check(data, len);
if (hdr_698) {
type = IOT_SG_STA_DATA_TYPE_69845;
}
}
break;
}
default:
break;
}
return type;
}
uint32_t iot_sg_sta_nw_parse_mr_frame(uint8_t *hdr)
{
uint32_t ret = ERR_FAIL, reason = 0, tmp;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *header;
nw_app_data_t *data_hdr;
nw_app_fwd_dl_t *mr_req = NULL;
nw_app_fwd_module_dl_t *mr_req_mod = NULL;
IOT_ASSERT(hdr);
header = (nw_app_header_t *)hdr;
data_hdr = (nw_app_data_t *)(header + 1);
if (header->port == NW_APP_PORT_MGR &&
data_hdr->control_field.frame_type == NW_APP_FRAME_TYPE_DATA_FWD &&
data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANS_MODULE) {
if (data_hdr->len < sizeof(nw_app_fwd_module_dl_t)) {
reason = 1;
goto drop;
}
mr_req_mod = (nw_app_fwd_module_dl_t *)data_hdr->data;
tmp = data_hdr->len - sizeof(*mr_req_mod);
if (tmp < mr_req_mod->data_len) {
reason = 2;
goto drop;
}
} else {
if (data_hdr->len < sizeof(nw_app_fwd_dl_t)) {
reason = 3;
goto drop;
}
mr_req = (nw_app_fwd_dl_t *)data_hdr->data;
tmp = data_hdr->len - sizeof(*mr_req);
if (tmp < mr_req->data_len) {
reason = 4;
goto drop;
}
}
sta_glb->mr.max_retry = IOT_SG_STA_RETRY_CNT_NON_CON_MR;
sta_glb->mr.timeout_retry = 0;
sta_glb->mr.nack_retry = 0;
sta_glb->mr.mr_interval = 0;
sta_glb->mr.frame_cnt = 1;
if (mr_req_mod) {
sta_glb->mr.frame_data[0] = mr_req_mod->data;
sta_glb->mr.frame_len[0] = mr_req_mod->data_len;
sta_glb->mr.data_type = iot_sg_sta_nw_to_drv_data_type(
data_hdr->work_id, mr_req_mod->data, mr_req_mod->data_len);
} else {
sta_glb->mr.frame_data[0] = mr_req->data;
sta_glb->mr.frame_len[0] = mr_req->data_len;
sta_glb->mr.data_type = iot_sg_sta_nw_to_drv_data_type(
data_hdr->work_id, mr_req->data, mr_req->data_len);
sta_glb->mr.mr_timeout = mr_req->dev_timeout * 100;
}
if (!sta_glb->mr.mr_timeout) {
sta_glb->mr.mr_timeout = IOT_SG_STA_MR_TIMEOUT;
}
ret = ERR_OK;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static void iot_sg_sta_nw_send_mr_rsp(void)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_mr_stats_t *mr_stats = &sta_glb->mr.mr_info;
nw_app_header_t *rsp_hdr;
nw_app_data_t *rsp_data_hdr;
if (sta_glb->mr.read_rsp == NULL) {
goto drop;
}
IOT_ASSERT(sta_glb->mr.app_hdr);
iot_counter_inc(mr_stats->cctt_mr_sus_cnt);
rsp_hdr = (nw_app_header_t *)sta_glb->mr.app_hdr;
rsp_data_hdr = (nw_app_data_t *)(rsp_hdr + 1);
iot_sg_sta_send_mr_rsp(rsp_data_hdr->sn, IOT_SG_STA_MR_TYPE_DEF);
goto out;
drop:
sta_glb->mr.app_hdr = NULL;
out:
return;
}
static void iot_sg_sta_nw_mr_done(uint8_t data_type,
iot_pkt_t *rsp_pkt)
{
(void)data_type;
uint8_t *data;
uint16_t total_size, payload_size;
uint32_t ret;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_mr_stats_t *mr_stats = &sta_glb->mr.mr_info;
iot_plc_msdu_recv_t *msdu;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data_hdr, *rsp_data_hdr;
nw_app_fwd_dl_t *req = NULL;
nw_app_fwd_module_dl_t *req_mod = NULL;
nw_app_fwd_ul_t *rsp;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_pkt_t *plc_pkt;
data = iot_pkt_block_ptr(req_pkt, IOT_PKT_BLOCK_DATA);
msdu = (iot_plc_msdu_recv_t *)(data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)data;
req_data_hdr = (nw_app_data_t *)(req_hdr + 1);
if (req_hdr->port == NW_APP_PORT_MGR &&
req_data_hdr->control_field.frame_type == NW_APP_FRAME_TYPE_DATA_FWD &&
req_data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANS_MODULE) {
req_mod = (nw_app_fwd_module_dl_t *)req_data_hdr->data;
} else {
req = (nw_app_fwd_dl_t *)req_data_hdr->data;
}
if (rsp_pkt == NULL) {
/* handle timeout case */
iot_counter_inc(mr_stats->mr_err_cnts[IOT_SG_STA_MR_ERR_NON_CON_TO]);
if (sta_glb->mr.retry_cnt < sta_glb->mr.max_retry
&& !p_sg_glb->plc_state.cert_test_detected
&& sta_glb->drv->get_device_type() ==
IOT_SG_STA_DEV_TYPE_POWER_METER) {
sta_glb->mr.retry_cnt++;
iot_sg_printf("%s read pid %lu timeout, retry %lu\n", __FUNCTION__,
0, sta_glb->mr.retry_cnt);
goto re_issue;
}
goto next_req;
}
payload_size = (uint16_t)iot_pkt_data_len(rsp_pkt);
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) + sizeof(*rsp)
+ payload_size;
if (sta_glb->req.link_type == IOT_SG_LINK_TYPE_PLC_CTRL) {
plc_pkt = iot_plc_alloc_ctrl_proto_msdu(p_sg_glb->plc_app_h,
msdu->src, p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT,
total_size, IOT_PLC_LOCAL_RETRY_CNT);
} else {
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE,
msdu->src, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, total_size, IOT_PLC_LOCAL_RETRY_CNT);
}
if (plc_pkt) {
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
/* fill in header */
rsp_hdr = (nw_app_header_t*)data;
rsp_hdr->port = req_hdr->port;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->reserved = 0;
rsp_data_hdr = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_DATA_FWD;
rsp_data_hdr->work_id = req_data_hdr->work_id;
rsp_data_hdr->ver = NW_APP_VERSION;
rsp_data_hdr->sn = req_data_hdr->sn;
rsp_data_hdr->len = (uint16_t)(sizeof(*rsp) + iot_pkt_data_len(rsp_pkt));
rsp = (nw_app_fwd_ul_t *)rsp_data_hdr->data;
if (req_mod) {
iot_mac_addr_cpy(rsp->src_addr, req_mod->dst_addr);
iot_mac_addr_cpy(rsp->dst_addr, req_mod->src_addr);
rsp->work_code = req_mod->work_code;
rsp->work_code_other = req_mod->work_code_other;
} else {
iot_mac_addr_cpy(rsp->src_addr, req->dst_addr);
iot_mac_addr_cpy(rsp->dst_addr, req->src_addr);
rsp->work_code = 0;
rsp->work_code_other = 0;
}
rsp->data_len = (uint16_t)iot_pkt_data_len(rsp_pkt);
os_mem_cpy(rsp->data, iot_pkt_data(rsp_pkt), iot_pkt_data_len(rsp_pkt));
iot_pkt_put(plc_pkt, total_size);
sta_glb->mr.read_rsp = plc_pkt;
sta_glb->mr.app_hdr = (uint8_t*)rsp_hdr;
iot_sg_sta_nw_send_mr_rsp();
} else {
iot_sg_printf("%s drop id %lu\n", __FUNCTION__, req_hdr->id);
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO,
IOT_SG_STA_METER_READ_DONE_SINGLE_ID, 1, req_hdr->id);
}
iot_pkt_free(rsp_pkt);
goto next_req;
re_issue:
ret = iot_sg_sta_issue_frame();
if (ret == ERR_PENDING) {
return;
}
next_req:
/* mark current meter read done */
sta_glb->mr.meter_read_on = 0;
/* trigger next request in the queue */
iot_sg_sta_start_next_app_other();
}
static void iot_sg_sta_nw_ctrl_passthrough_done(uint8_t data_type,
iot_pkt_t *rsp_pkt)
{
(void)data_type;
uint16_t total_size, payload_size;
uint8_t *req_data, *rsp_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data_hdr, *rsp_data_hdr;
nw_app_ctrl_proto_passthrough_t *rsp, *req;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_pkt_t *plc_pkt;
req_data = iot_pkt_data(req_pkt);
msdu = (iot_plc_msdu_recv_t *)(req_data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)req_data;
req_data_hdr = (nw_app_data_t *)(req_hdr + 1);
req = (nw_app_ctrl_proto_passthrough_t*)(req_data_hdr + 1);
if (rsp_pkt == NULL) {
/* handle timeout case */
goto next_req;
}
if (!sta_glb->ctrl_proto_connected) {
iot_sg_data_print("iot_sg_sta_nw_ctrl_passthrough_done drop disconnect",
iot_pkt_data(rsp_pkt), iot_pkt_data_len(rsp_pkt));
iot_pkt_free(rsp_pkt);
goto next_req;
}
payload_size = (uint16_t)iot_pkt_data_len(rsp_pkt);
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) +
sizeof(*rsp) + payload_size;
plc_pkt = iot_plc_alloc_ctrl_proto_msdu(p_sg_glb->plc_app_h,
msdu->src, p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT,
total_size, IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
rsp_data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
/* fill in header */
rsp_hdr = (nw_app_header_t *)rsp_data;
rsp_hdr->id = req_hdr->id;
rsp_hdr->port = req_hdr->port;
rsp_hdr->reserved = 0;
rsp_data_hdr = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data_hdr->control_field.frame_type =
req_data_hdr->control_field.frame_type;
rsp_data_hdr->work_id = req_data_hdr->work_id;
rsp_data_hdr->ver = NW_APP_VERSION;
rsp_data_hdr->sn = req_data_hdr->sn;
rsp_data_hdr->len = (uint16_t)(sizeof(*rsp) +
iot_pkt_data_len(rsp_pkt));
rsp = (nw_app_ctrl_proto_passthrough_t *)(rsp_data_hdr + 1);
rsp->proto_type = req->proto_type;
rsp->prm = 0;
rsp->sn = sta_glb->ctrl_proto_sn;
os_mem_cpy(rsp->baud, req->baud, sizeof(req->baud));
rsp->data_len = payload_size;
/* fill in payload */
os_mem_cpy(rsp->data, iot_pkt_data(rsp_pkt), rsp->data_len);
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s drop id %lu\n", __FUNCTION__, req_hdr->id);
}
iot_pkt_free(rsp_pkt);
next_req:
/* mark current meter read done */
sta_glb->mr.meter_read_on = 0;
/* trigger next request in the queue */
iot_sg_sta_start_next_app_other();
}
static void iot_sg_sta_nw_route_fwd_done(uint8_t data_type,
iot_pkt_t *rsp_pkt)
{
(void)data_type;
uint16_t total_size, payload_size;
uint8_t *req_data, *rsp_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data_hdr, *rsp_data_hdr;
nw_app_route_fwd_t *rsp, *req;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_pkt_t *plc_pkt;
req_data = iot_pkt_data(req_pkt);
msdu = (iot_plc_msdu_recv_t *)(req_data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)req_data;
req_data_hdr = (nw_app_data_t *)(req_hdr + 1);
req = (nw_app_route_fwd_t*)(req_data_hdr + 1);
if (rsp_pkt == NULL) {
/* handle timeout case */
goto next_req;
}
payload_size = (uint16_t)iot_pkt_data_len(rsp_pkt);
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) +
sizeof(*rsp) + payload_size;
if (sta_glb->req.link_type == IOT_SG_LINK_TYPE_PLC_CTRL) {
plc_pkt = iot_plc_alloc_ctrl_proto_msdu(p_sg_glb->plc_app_h,
msdu->src, p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT,
total_size, IOT_PLC_LOCAL_RETRY_CNT);
} else {
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE,
msdu->src, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, total_size, IOT_PLC_LOCAL_RETRY_CNT);
}
if (plc_pkt) {
rsp_data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
/* fill in header */
rsp_hdr = (nw_app_header_t *)rsp_data;
rsp_hdr->id = req_hdr->id;
rsp_hdr->port = req_hdr->port;
rsp_hdr->reserved = 0;
rsp_data_hdr = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data_hdr->control_field.frame_type =
req_data_hdr->control_field.frame_type;
rsp_data_hdr->work_id = req_data_hdr->work_id;
rsp_data_hdr->ver = NW_APP_VERSION;
rsp_data_hdr->sn = req_data_hdr->sn;
rsp_data_hdr->len = (uint16_t)(sizeof(*rsp) +
iot_pkt_data_len(rsp_pkt));
rsp = (nw_app_route_fwd_t *)(rsp_data_hdr + 1);
iot_mac_addr_cpy(rsp->src_addr, req->dst_addr);
iot_mac_addr_cpy(rsp->dst_addr, req->src_addr);
rsp->data_len = payload_size;
/* fill in payload */
os_mem_cpy(rsp->data, iot_pkt_data(rsp_pkt), rsp->data_len);
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s drop id %lu\n", __FUNCTION__, req_hdr->id);
}
iot_pkt_free(rsp_pkt);
next_req:
/* mark current meter read done */
sta_glb->mr.meter_read_on = 0;
/* trigger next request in the queue */
iot_sg_sta_start_next_app_other();
}
void iot_sg_sta_nw_mr_counter_inc(uint8_t *hdr)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
(void)hdr;
iot_counter_inc(sta_glb->mr.mr_info.rec_valid_cctt_mr_cnt);
}
void iot_sg_sta_nw_mr_done_intern(uint8_t data_type,
iot_pkt_t *rsp_pkt)
{
uint8_t *data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *req_hdr;
nw_app_data_t *data_hdr;
IOT_ASSERT(sta_glb->mr.meter_read_on);
data = iot_pkt_data(sta_glb->req.pkt);
req_hdr = (nw_app_header_t *)data;
data_hdr = (nw_app_data_t *)(req_hdr + 1);
switch (data_hdr->control_field.frame_type) {
case NW_APP_FRAME_TYPE_DATA_FWD:
{
if (data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANSPARENT ||
data_hdr->work_id == NW_APP_WORK_DATA_FWD_TRANS_MODULE) {
iot_sg_sta_nw_mr_done(data_type, rsp_pkt);
} else {
IOT_ASSERT(0);
iot_pkt_free(rsp_pkt);
}
break;
}
case NW_APP_FRAME_TYPE_CTRL:
{
if (data_hdr->work_id == NW_APP_WORK_CTRL_PASSTHROUGH) {
iot_sg_sta_nw_ctrl_passthrough_done(data_type, rsp_pkt);
} else {
iot_pkt_free(rsp_pkt);
}
break;
}
case NW_APP_FRAME_TYPE_ROUTE_FWD:
{
if (data_hdr->work_id == NW_APP_ROUTE_FWD_DATA) {
iot_sg_sta_nw_route_fwd_done(data_type, rsp_pkt);
} else {
iot_pkt_free(rsp_pkt);
}
break;
}
default:
iot_pkt_free(rsp_pkt);
break;
}
}
static void iot_sg_sta_nw_fill_pd_bitmap_info(
nw_app_evt_data_bitmap_t *bitmap, iot_sg_sta_pd_bitmap_desc_t *bitmap_info)
{
uint16_t i;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_power_off_bm_t *local_power_off_bm = &sta_glb->evt.power_off_bm;
IOT_ASSERT(bitmap);
IOT_ASSERT(iot_bitmap_ffs(local_power_off_bm->map,
sizeof(local_power_off_bm->map)));
IOT_ASSERT(NW_APP_EVENT_TEI_IS_VALID(bitmap_info->first_tei)
&& NW_APP_EVENT_TEI_IS_VALID(bitmap_info->last_tei));
bitmap->tei = bitmap_info->first_tei;
for (i = bitmap_info->first_tei; i <= bitmap_info->last_tei; i++) {
if (iot_bitmap_is_set(local_power_off_bm->map,
sizeof(local_power_off_bm->map),
NW_APP_TEI_TO_BM(i))) {
iot_bitmap_set(bitmap->map, (uint8_t)(bitmap_info->length),
NW_APP_TEI_TO_BM(i - bitmap_info->first_tei));
}
}
local_power_off_bm->updated = 0;
}
uint32_t iot_sg_sta_nw_pd_evt_bm_send(uint8_t msg_type)
{
uint8_t updated = 0, *data, user_type = iot_sg_sta_get_user_type();
uint16_t data_len;
uint32_t size, ret, dev_type;
iot_pkt_t *plc_pkt;
iot_sg_sta_pd_bitmap_desc_t bitmap_info = {0};
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *req_hdr;
nw_app_data_t *data_hdr;
nw_app_evt_data_field_t *evt_data;
nw_app_evt_data_field_gd_t *evt_data_gd;
nw_app_rpt_evt_rpt_gd_t *evt_rpt_gd;
nw_app_evt_data_bitmap_t *bitmap_data;
ret = iot_sg_sta_get_pd_bitmap_info(&bitmap_info, &updated);
if (ret) {
ret = ERR_NOT_EXIST;
goto out;
}
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
data_len = sizeof(*evt_data) + sizeof(*bitmap_data)
+ bitmap_info.length;
} else {
data_len = sizeof(*evt_rpt_gd) + sizeof(*evt_data_gd) +
sizeof(*bitmap_data) + bitmap_info.length;
}
size = sizeof(*req_hdr) + sizeof(*data_hdr) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, msg_type,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, (uint16_t)size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt == NULL) {
ret = ERR_NOMEM;
goto out;
}
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
req_hdr = (nw_app_header_t*)data;
req_hdr->id = NW_APP_ID;
req_hdr->reserved = 0;
data_hdr = (nw_app_data_t *)(req_hdr + 1);
data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
data_hdr->control_field.start = NW_APP_CONTROL_PRM_MASTER;
data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
data_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_RPT;
data_hdr->ver = NW_APP_VERSION;
if (updated) {
sta_glb->evt.power_off_send_cnt = 0;
data_hdr->sn = iot_sg_sta_get_event_rpt_seq();
sta_glb->evt.power_off_rpt_seq = data_hdr->sn;
} else {
data_hdr->sn = sta_glb->evt.power_off_rpt_seq;
}
data_hdr->len = data_len;
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
req_hdr->port = NW_APP_PORT;
data_hdr->work_id = NW_APP_WORK_RPT_EVT_RPT;
evt_data = (nw_app_evt_data_field_t *)(data_hdr + 1);
evt_data->fn_code = NW_APP_EVENT_FN_MODULE_RPT;
evt_data->type = NW_APP_EVENT_TYPE_POWER_DOWN;
bitmap_data = (nw_app_evt_data_bitmap_t *)(evt_data + 1);
} else {
req_hdr->port = NW_APP_PORT_MGR;
data_hdr->work_id = NW_APP_WORK_RPT_POWER_RPT;
evt_rpt_gd = (nw_app_rpt_evt_rpt_gd_t *)(data_hdr + 1);
evt_rpt_gd->header_len = sizeof(*evt_rpt_gd);
dev_type = sta_glb->drv->get_device_type();
evt_rpt_gd->fn = (dev_type == IOT_SG_STA_DEV_TYPE_POWER_METER) ? \
NW_APP_EVENT_FN_STA_RPT : NW_APP_EVENT_FN_COLLECTOR_RPT;
evt_rpt_gd->data_len = data_len - sizeof(*evt_rpt_gd);
sta_glb->drv->get_login_addr(evt_rpt_gd->pm_addr);
evt_data_gd = (nw_app_evt_data_field_gd_t *)evt_rpt_gd->data;
evt_data_gd->evt_type = NW_APP_EVENT_TYPE_POWER_DOWN;
bitmap_data = (nw_app_evt_data_bitmap_t *)evt_data_gd->data;
}
iot_sg_sta_nw_fill_pd_bitmap_info(bitmap_data, &bitmap_info);
iot_pkt_put(plc_pkt, size);
/* print sn before iot_pkt being freed. */
iot_sg_printf("%s seq %lu\n", __FUNCTION__, data_hdr->sn);
ret = iot_sg_send_msdu(plc_pkt, IOT_SG_LINK_TYPE_SWC);
out:
return ret;
}
uint32_t iot_sg_sta_nw_pd_evt_addrs_send(uint8_t msg_type)
{
uint8_t i, *data, user_type = iot_sg_sta_get_user_type();
iot_pkt_t *plc_pkt;
uint16_t size_base, size;
uint32_t ret = ERR_NOT_EXIST, dev_type;
nw_app_header_t *req_hdr;
nw_app_data_t *data_hdr;
nw_app_evt_data_field_t *evt_data;
nw_app_evt_data_field_gd_t *evt_data_gd;
nw_app_rpt_evt_rpt_gd_t *evt_rpt_gd;
nw_app_evt_data_addr_t *addrs_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_pd_addrs_ctrl_t *pd_addr_ctrl = &sta_glb->evt.pd_addr_ctrl;
iot_sg_sta_pd_addrs_buf_t *addrs_buf = pd_addr_ctrl->addrs_buf;
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
size_base = sizeof(*req_hdr) +sizeof(*data_hdr) + sizeof(*evt_data)
+ sizeof(*addrs_data);
} else {
size_base = sizeof(*req_hdr) +sizeof(*data_hdr) + sizeof(*evt_rpt_gd)
+ sizeof(evt_data_gd) + sizeof(*addrs_data);
}
for (i = 0; i < IOT_SG_STA_PD_ADDRS_BUF_CNT; i++) {
if (addrs_buf[i].pkt == NULL) {
break;
}
size = (uint16_t)iot_pkt_data_len(addrs_buf[i].pkt) + size_base;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
msg_type, IOT_PLC_ACK_TYPE_NONE,
p_sg_glb->plc_state.cco_addr, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, size, IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt == NULL) {
ret = ERR_NOMEM;
break;
}
data = iot_pkt_tail(plc_pkt);
req_hdr = (nw_app_header_t*)data;
req_hdr->id = NW_APP_ID;
req_hdr->reserved = 0;
data_hdr = (nw_app_data_t *)(req_hdr + 1);
data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
data_hdr->control_field.start = NW_APP_CONTROL_PRM_MASTER;
data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
data_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_RPT;
data_hdr->ver = NW_APP_VERSION;
data_hdr->len = size - sizeof(*req_hdr) - sizeof(*data_hdr);
if (addrs_buf[i].updated) {
sta_glb->evt.power_off_send_cnt = 0;
data_hdr->sn = iot_sg_sta_get_event_rpt_seq();
addrs_buf[i].updated = 0;
addrs_buf[i].seq = data_hdr->sn;
} else {
data_hdr->sn = addrs_buf[i].seq;
}
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
req_hdr->port = NW_APP_PORT;
data_hdr->work_id = NW_APP_WORK_RPT_EVT_RPT;
evt_data = (nw_app_evt_data_field_t *)(data_hdr + 1);
evt_data->fn_code = NW_APP_EVENT_FN_MODULE_RPT;
evt_data->type = NW_APP_EVENT_TYPE_POWER_DOWN_ADDR;
addrs_data = (nw_app_evt_data_addr_t *)(evt_data + 1);
} else {
req_hdr->port = NW_APP_PORT_MGR;
data_hdr->work_id = NW_APP_WORK_RPT_POWER_RPT;
evt_rpt_gd = (nw_app_rpt_evt_rpt_gd_t *)(data_hdr + 1);
evt_rpt_gd->header_len = sizeof(*evt_rpt_gd);
dev_type = sta_glb->drv->get_device_type();
evt_rpt_gd->fn = (dev_type == IOT_SG_STA_DEV_TYPE_POWER_METER) ? \
NW_APP_EVENT_FN_STA_RPT : NW_APP_EVENT_FN_COLLECTOR_RPT;
evt_rpt_gd->data_len = data_hdr->len - sizeof(*evt_rpt_gd);
sta_glb->drv->get_login_addr(evt_rpt_gd->pm_addr);
evt_data_gd = (nw_app_evt_data_field_gd_t *)evt_rpt_gd->data;
evt_data_gd->evt_type = NW_APP_EVENT_TYPE_POWER_DOWN_ADDR;
addrs_data = (nw_app_evt_data_addr_t *)evt_data_gd->data;
}
addrs_data->pm_count = addrs_buf[i].pm_cnt;
os_mem_cpy(addrs_data->pm_info, iot_pkt_data(addrs_buf[i].pkt),
iot_pkt_data_len(addrs_buf[i].pkt));
iot_pkt_put(plc_pkt, sizeof(*req_hdr) + sizeof(*data_hdr) +
data_hdr->len);
iot_sg_printf("%s seq %lu pm_cnt %lu\n", __FUNCTION__, data_hdr->sn,
addrs_data->pm_count);
ret = iot_sg_send_msdu(plc_pkt, IOT_SG_LINK_TYPE_SWC);
}
return ret;
}
static uint32_t iot_sg_sta_nw_dev_type_from_sg(uint32_t dev_type)
{
uint8_t nw_dev_type = 0;
switch (dev_type) {
case IOT_SG_STA_DEV_TYPE_POWER_METER:
nw_dev_type = NW_APP_DEV_TYPE_POWER_METER;
break;
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T1:
nw_dev_type = NW_APP_DEV_TYPE_COLLECTOR_T1;
break;
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T2:
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T3:
nw_dev_type = NW_APP_DEV_TYPE_COLLECTOR_T2;
break;
default:
IOT_ASSERT(0);
break;
}
return nw_dev_type;
}
static void iot_sg_sta_nw_power_on_msg_fill(nw_app_power_evt_pm_info_t *pm_info,
uint8_t cnt)
{
uint32_t idx, i;
iot_sg_sta_node_desc_t *node;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
IOT_ASSERT(cnt);
for (idx = 0, i = 0; (i < cnt) && (idx < IOT_SG_STA_SEC_NODE_MAX); idx++) {
if (sta_glb->node_list[idx] != NULL) {
node = sta_glb->node_list[idx];
iot_mac_addr_cpy(pm_info[i].mac, node->entry.addr);
if (node->obsolete) {
pm_info[i].power_state = 0;
} else {
pm_info[i].power_state = 1;
}
i++;
}
}
}
uint32_t iot_sg_sta_nw_power_on_evt_send(uint8_t flag_bcast)
{
uint8_t *data, addr[IOT_MAC_ADDR_LEN], msg_type = IOT_PLC_MSG_TYPE_UNICAST;
uint8_t cnt = IOT_PLC_LOCAL_RETRY_CNT;
uint8_t user_type = iot_sg_sta_get_user_type();
uint16_t data_len = 0;
uint32_t size = 0, device, ret = ERR_OK;
iot_pkt_t *plc_pkt;
nw_app_header_t *hdr;
nw_app_data_t *data_hdr;
nw_app_evt_data_field_t *power_on_info;
nw_app_evt_data_field_gd_t *power_on_info_gd;
nw_app_rpt_evt_rpt_gd_t *evt_rpt_gd;
nw_app_evt_data_addr_t *addrmap_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_power_on_addrmap_desc_t *pu_ctrl =
&sta_glb->evt.pu_addr_ctrl;
device = sta_glb->drv->get_device_type();
device = iot_sg_sta_nw_dev_type_from_sg(device);
sta_glb->drv->get_login_addr(addr);
switch (device) {
case NW_APP_DEV_TYPE_POWER_METER:
case NW_APP_DEV_TYPE_COLLECTOR_T1:
{
if (user_type ==
USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
data_len = sizeof(*power_on_info) + sizeof(*addrmap_data) +
sizeof(nw_app_power_evt_pm_info_t);
} else {
data_len = sizeof(*power_on_info_gd) + sizeof(*evt_rpt_gd) +
sizeof(*addrmap_data) + sizeof(nw_app_power_evt_pm_info_t);
}
size = sizeof(*hdr) + sizeof(*data_hdr) + data_len;
break;
}
case NW_APP_DEV_TYPE_COLLECTOR_T2:
{
if (!pu_ctrl->check_cnt) {
/* if the number of detected meters under collector II is zero
* after the power-on detection, meters currently in the node_list
* will be reported as the power-on meter.
*/
pu_ctrl->check_cnt = iot_sg_node_reg_get_node_cnt();
}
if (!pu_ctrl->check_cnt) {
/* If the number of detected meters is zero after the
* the power-on detection, power-on evt report fail.
*/
ret = ERR_FAIL;
goto out;
}
if (user_type ==
USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
data_len = sizeof(*power_on_info) + sizeof(*addrmap_data) +
pu_ctrl->check_cnt * sizeof(nw_app_power_evt_pm_info_t);
} else {
data_len = sizeof(*power_on_info_gd) + sizeof(*evt_rpt_gd) +
sizeof(*addrmap_data) +
pu_ctrl->check_cnt * sizeof(nw_app_power_evt_pm_info_t);
}
size = sizeof(*hdr) + sizeof(*data_hdr) + data_len;
break;
}
default:
IOT_ASSERT(0);
}
if (flag_bcast) {
msg_type = IOT_PLC_MSG_TYPE_BCAST_TO_CCO;
cnt = IOT_SG_STA_NW_BCAST_RETRY_CNT;
}
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
msg_type, IOT_PLC_ACK_TYPE_NONE,
p_sg_glb->plc_state.cco_addr, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, (uint16_t)size, cnt);
if (plc_pkt == NULL) {
ret = ERR_NOMEM;
goto out;
}
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
hdr = (nw_app_header_t*)data;
hdr->id = NW_APP_ID;
hdr->reserved = 0;
data_hdr = (nw_app_data_t *)(hdr + 1);
data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
data_hdr->control_field.start = NW_APP_CONTROL_PRM_MASTER;
data_hdr->control_field.respond = NW_APP_CONTROL_NEED_RSP;
data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
data_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_RPT;
data_hdr->ver = NW_APP_VERSION;
data_hdr->len = data_len;
if (!sta_glb->evt.power_on_rpt_seq) {
data_hdr->sn = iot_sg_sta_get_event_rpt_seq();
sta_glb->evt.power_on_rpt_seq = data_hdr->sn;
} else {
data_hdr->sn = sta_glb->evt.power_on_rpt_seq;
}
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
hdr->port = NW_APP_PORT;
data_hdr->work_id = NW_APP_WORK_RPT_EVT_RPT;
power_on_info = (nw_app_evt_data_field_t *)data_hdr->data;
power_on_info->fn_code = NW_APP_EVENT_FN_MODULE_RPT;
power_on_info->type = NW_APP_EVENT_TYPE_POWER_UP_ADDR;
addrmap_data = (nw_app_evt_data_addr_t *)(power_on_info + 1);
} else {
hdr->port = NW_APP_PORT_MGR;
data_hdr->work_id = NW_APP_WORK_RPT_POWER_RPT;
evt_rpt_gd = (nw_app_rpt_evt_rpt_gd_t *)data_hdr->data;
evt_rpt_gd->header_len = sizeof(*evt_rpt_gd);
evt_rpt_gd->fn = (device == IOT_SG_STA_DEV_TYPE_POWER_METER) ? \
NW_APP_EVENT_FN_STA_RPT : NW_APP_EVENT_FN_COLLECTOR_RPT;
evt_rpt_gd->data_len = data_hdr->len - sizeof(*evt_rpt_gd);
sta_glb->drv->get_login_addr(evt_rpt_gd->pm_addr);
power_on_info_gd = (nw_app_evt_data_field_gd_t *)evt_rpt_gd->data;
power_on_info_gd->evt_type = NW_APP_EVENT_TYPE_POWER_UP_ADDR;
addrmap_data = (nw_app_evt_data_addr_t *)power_on_info_gd->data;
}
switch (device) {
case NW_APP_DEV_TYPE_POWER_METER:
case NW_APP_DEV_TYPE_COLLECTOR_T1:
{
addrmap_data->pm_count = 1;
iot_mac_addr_cpy(addrmap_data->pm_info[0].mac, addr);
addrmap_data->pm_info[0].power_state = 1;
break;
}
case NW_APP_DEV_TYPE_COLLECTOR_T2:
{
addrmap_data->pm_count = pu_ctrl->check_cnt;
iot_sg_sta_nw_power_on_msg_fill(addrmap_data->pm_info,
(uint8_t)addrmap_data->pm_count);
break;
}
default:
IOT_ASSERT(0);
}
iot_pkt_put(plc_pkt, size);
iot_sg_send_msdu(plc_pkt, IOT_SG_LINK_TYPE_PLC);
iot_sg_printf("%s seq %lu\n", __FUNCTION__,
data_hdr->sn);
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
IOT_SG_STA_POWERON_EVT_RPT_ID, 1, data_hdr->sn);
out:
return ret;
}
uint32_t iot_sg_sta_nw_event_send(uint8_t *addr, uint8_t *data_ptr,
uint32_t len, uint8_t new_evt, uint8_t rtp_type)
{
uint8_t *data, idx;
uint32_t ret = ERR_OK;
uint32_t size, data_len;
iot_pkt_t *plc_pkt;
nw_app_header_t *hdr;
nw_app_data_t *hdr_data;
nw_app_rpt_evt_rpt_t *event;
nw_app_pm_score_info_t *score_data;
nw_app_score_evt_data_field_t *evt_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_score_info_t *score_info = NULL;
switch (rtp_type) {
case IOT_SG_STA_RPT_METER_NORMAL_EVT:
{
data_len = (sizeof(*event) + len);
break;
}
case IOT_SG_STA_RPT_MODULE_SCORE_EVT:
{
if (!data_ptr) {
ret = ERR_INVAL;
goto out;
}
score_info = (iot_sg_sta_score_info_t *)data_ptr;
data_len = (score_info->meter_cnt * sizeof(*score_data) +
sizeof(*evt_data));
break;
}
default:
ret = ERR_NOSUPP;
goto out;
}
size = sizeof(*hdr) + sizeof(*hdr_data) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, (uint16_t)size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt == NULL) {
ret = ERR_NOMEM;
goto out;
}
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
/* create guo wang app header for the new packet */
hdr = (nw_app_header_t*)data;
hdr->port = NW_APP_PORT;
hdr->id = NW_APP_ID;
hdr->reserved = 0;
hdr_data = (nw_app_data_t *)(hdr + 1);
hdr_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
hdr_data->control_field.start = NW_APP_CONTROL_PRM_MASTER;
hdr_data->control_field.respond = NW_APP_CONTROL_NEED_RSP;
hdr_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
hdr_data->control_field.frame_type = NW_APP_FRAME_TYPE_RPT;
hdr_data->work_id = NW_APP_WORK_RPT_EVT_RPT;
hdr_data->ver = NW_APP_VERSION;
if (new_evt) {
hdr_data->sn = iot_sg_sta_get_event_rpt_seq();
sta_glb->evt.pm_evt_rpt_seq = hdr_data->sn;
} else {
hdr_data->sn = sta_glb->evt.pm_evt_rpt_seq;
}
hdr_data->len = (uint16_t)data_len;
switch (rtp_type) {
case IOT_SG_STA_RPT_METER_NORMAL_EVT:
{
event = (nw_app_rpt_evt_rpt_t *)hdr_data->data;
iot_mac_addr_cpy(event->meter_addr, addr);
if (data_ptr && len) {
os_mem_cpy(event->data, data_ptr, len);
}
break;
}
case IOT_SG_STA_RPT_MODULE_SCORE_EVT:
{
evt_data = (nw_app_score_evt_data_field_t *)hdr_data->data;
evt_data->fn_code = NW_APP_EVENT_FN_SCORE_RPT;
for (idx = 0; idx < score_info->meter_cnt; idx++) {
evt_data->pm_info[idx].score = score_info->pm_info[idx].score;
evt_data->pm_info[idx].err_bm = score_info->pm_info[idx].err_bm;
iot_mac_addr_cpy(evt_data->pm_info[idx].pm_mac,
score_info->pm_info[idx].pm_mac);
}
break;
}
default:
IOT_ASSERT(0);
break;
}
iot_pkt_put(plc_pkt, size);
ret = iot_sg_send_msdu(plc_pkt, IOT_SG_LINK_TYPE_PLC);
out:
return ret;
}
uint32_t iot_sg_sta_nw_event_send_with_seq(uint8_t *addr, uint8_t *data_ptr,
uint32_t len, uint16_t seq, uint8_t rpt_type)
{
uint8_t *data, idx;
uint32_t ret = ERR_OK, size, data_len;
iot_pkt_t *plc_pkt;
nw_app_header_t *hdr;
nw_app_data_t *hdr_data;
nw_app_rpt_evt_rpt_t *event;
nw_app_pm_score_info_t *score_data;
nw_app_score_evt_data_field_t *evt_data;
iot_sg_sta_score_info_t *score_info = NULL;
switch (rpt_type) {
case IOT_SG_STA_RPT_METER_NORMAL_EVT:
{
data_len = (sizeof(*event) + len);
break;
}
case IOT_SG_STA_RPT_MODULE_SCORE_EVT:
{
if (!data_ptr) {
ret = ERR_INVAL;
goto out;
}
score_info = (iot_sg_sta_score_info_t *)data_ptr;
data_len =
(score_info->meter_cnt * sizeof(*score_data) + sizeof(*evt_data));
break;
}
case IOT_SG_STA_RPT_MODULE_EC_EVT:
{
if (!data_ptr || !len) {
ret = ERR_INVAL;
goto out;
}
data_len = len;
break;
}
default:
ret = ERR_NOSUPP;
goto out;
}
size = sizeof(*hdr) + sizeof(*hdr_data) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, (uint16_t)size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt == NULL) {
ret = ERR_NOMEM;
goto out;
}
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
hdr = (nw_app_header_t *)data;
if (rpt_type == IOT_SG_STA_RPT_MODULE_EC_EVT) {
hdr->port = NW_APP_PORT_MGR;
} else {
hdr->port = NW_APP_PORT;
}
hdr->id = NW_APP_ID;
hdr->reserved = 0;
hdr_data = (nw_app_data_t *)(hdr + 1);
hdr_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
hdr_data->control_field.start = NW_APP_CONTROL_PRM_MASTER;
hdr_data->control_field.respond = NW_APP_CONTROL_NEED_RSP;
hdr_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
hdr_data->control_field.frame_type = NW_APP_FRAME_TYPE_RPT;
if (rpt_type == IOT_SG_STA_RPT_MODULE_EC_EVT) {
hdr_data->work_id = NW_APP_WORK_RPT_EDGE_COMPUTING;
} else {
hdr_data->work_id = NW_APP_WORK_RPT_EVT_RPT;
}
hdr_data->ver = NW_APP_VERSION;
hdr_data->sn = seq;
hdr_data->len = (uint16_t)data_len;
switch (rpt_type) {
case IOT_SG_STA_RPT_METER_NORMAL_EVT:
{
event = (nw_app_rpt_evt_rpt_t *)hdr_data->data;
iot_mac_addr_cpy(event->meter_addr, addr);
if (data_ptr && len) {
os_mem_cpy(event->data, data_ptr, len);
}
break;
}
case IOT_SG_STA_RPT_MODULE_SCORE_EVT:
{
evt_data = (nw_app_score_evt_data_field_t *)hdr_data->data;
evt_data->fn_code = NW_APP_EVENT_FN_SCORE_RPT;
for (idx = 0; idx < score_info->meter_cnt; idx++) {
evt_data->pm_info[idx].score = score_info->pm_info[idx].score;
evt_data->pm_info[idx].err_bm = score_info->pm_info[idx].err_bm;
iot_mac_addr_cpy(
evt_data->pm_info[idx].pm_mac, score_info->pm_info[idx].pm_mac);
}
break;
}
case IOT_SG_STA_RPT_MODULE_EC_EVT:
{
os_mem_cpy(hdr_data->data, data_ptr, len);
break;
}
default:
IOT_ASSERT(0);
break;
}
iot_pkt_put(plc_pkt, size);
ret = iot_sg_send_msdu(plc_pkt, IOT_SG_LINK_TYPE_PLC);
out:
return ret;
}
uint32_t iot_sg_sta_nw_report_ec_health_event(
uint8_t *addr, uint8_t score, iot_sg_sta_drv_score_bit_map_t *bitmap)
{
iot_pkt_t *pkt = NULL;
uint8_t pm_addr[IOT_MAC_ADDR_LEN];
uint16_t seq = 0;
uint32_t ret = ERR_FAIL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_ec_t *ec_info = sta_glb->ext_info.ec_info;
iot_sg_sta_drv_t *drv = sta_glb->drv;
nw_app_health_status_rpt_t *data;
if (!ec_info) {
ret = ERR_NOSUPP;
goto out;
}
pkt = iot_pkt_alloc(sizeof(*data), IOT_SMART_GRID_MID);
if (!pkt) {
ret = ERR_NOMEM;
goto out;
}
data = (nw_app_health_status_rpt_t *)iot_pkt_put(pkt, sizeof(*data));
os_mem_set(data, 0, sizeof(data));
data->evt_type = NW_APP_EDGE_COMP_EVT_TYPE_HEALTH_STATUS;
os_mem_cpy(data->pm_mac, addr, IOT_MAC_ADDR_LEN);
data->value = score;
os_mem_cpy(data->err_bitmap, bitmap, sizeof(*bitmap));
drv->get_login_addr(pm_addr);
seq = iot_sg_sta_get_event_rpt_seq();
ret = iot_sg_sta_nw_event_send_with_seq(pm_addr, (uint8_t *)data,
sizeof(*data), seq, IOT_SG_STA_RPT_MODULE_EC_EVT);
ec_info->health_evt_info.seq = seq;
out:
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_nw_report_ec_overvoltage_event(uint8_t *addr,
uint8_t is_three_phase, uint16_t av, uint16_t bv, uint16_t cv)
{
iot_pkt_t *pkt = NULL;
uint8_t pm_addr[IOT_MAC_ADDR_LEN];
uint16_t seq = 0;
uint32_t ret = ERR_FAIL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_ec_t *ec_info = sta_glb->ext_info.ec_info;
iot_sg_sta_drv_t *drv = sta_glb->drv;
nw_app_overvoltage_monitor_rpt_t *data;
if (!ec_info) {
goto out;
}
pkt = iot_pkt_alloc(sizeof(*data), IOT_SMART_GRID_MID);
if (!pkt) {
ret = ERR_NOMEM;
goto out;
}
data = (nw_app_overvoltage_monitor_rpt_t *)iot_pkt_put(pkt, sizeof(*data));
data->evt_type = NW_APP_EDGE_COMP_EVT_TYPE_OVERVOLTAGE;
os_mem_cpy(data->pm_mac, addr, IOT_MAC_ADDR_LEN);
data->pm_type = is_three_phase;
data->phase_a = av;
data->phase_b = bv;
data->phase_c = cv;
drv->get_login_addr(pm_addr);
seq = iot_sg_sta_get_event_rpt_seq();
ret = iot_sg_sta_nw_event_send_with_seq(pm_addr, (uint8_t *)data,
sizeof(*data), seq, IOT_SG_STA_RPT_MODULE_EC_EVT);
ec_info->ov_evt_info.seq = seq;
out:
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_nw_report_ec_undervoltage_event(uint8_t *addr,
uint8_t is_three_phase, uint16_t av, uint16_t bv, uint16_t cv)
{
iot_pkt_t *pkt = NULL;
uint8_t pm_addr[IOT_MAC_ADDR_LEN];
uint16_t seq = 0;
uint32_t ret = ERR_FAIL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_ec_t *ec_info = sta_glb->ext_info.ec_info;
iot_sg_sta_drv_t *drv = sta_glb->drv;
nw_app_undervoltage_monitor_rpt_t *data;
if (!ec_info) {
goto out;
}
pkt = iot_pkt_alloc(sizeof(*data), IOT_SMART_GRID_MID);
if (!pkt) {
ret = ERR_NOMEM;
goto out;
}
data = (nw_app_undervoltage_monitor_rpt_t *)iot_pkt_put(pkt, sizeof(*data));
data->evt_type = NW_APP_EDGE_COMP_EVT_TYPE_UNDERVOLTAGE;
os_mem_cpy(data->pm_mac, addr, IOT_MAC_ADDR_LEN);
data->pm_type = is_three_phase;
data->phase_a = av;
data->phase_b = bv;
data->phase_c = cv;
drv->get_login_addr(pm_addr);
seq = iot_sg_sta_get_event_rpt_seq();
ret = iot_sg_sta_nw_event_send_with_seq(pm_addr, (uint8_t *)data,
sizeof(*data), seq, IOT_SG_STA_RPT_MODULE_EC_EVT);
ec_info->uv_evt_info.seq = seq;
out:
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_nw_report_ec_second_pulse_event(
uint8_t *addr, uint16_t err_val)
{
iot_pkt_t *pkt = NULL;
uint8_t pm_addr[IOT_MAC_ADDR_LEN];
uint16_t seq = 0;
uint32_t ret = ERR_FAIL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_ec_t *ec_info = sta_glb->ext_info.ec_info;
iot_sg_sta_drv_t *drv = sta_glb->drv;
nw_app_sec_pulse_monitor_rpt_t *data;
if (!ec_info) {
goto out;
}
pkt = iot_pkt_alloc(sizeof(*data), IOT_SMART_GRID_MID);
if (!pkt) {
ret = ERR_NOMEM;
goto out;
}
data = (nw_app_sec_pulse_monitor_rpt_t *)iot_pkt_put(pkt, sizeof(*data));
data->evt_type = NW_APP_EDGE_COMP_EVT_TYPE_SEC_PULSE;
os_mem_cpy(data->pm_mac, addr, IOT_MAC_ADDR_LEN);
data->max_pulse_error = err_val;
drv->get_login_addr(pm_addr);
seq = iot_sg_sta_get_event_rpt_seq();
ret = iot_sg_sta_nw_event_send_with_seq(pm_addr, (uint8_t *)data,
sizeof(*data), seq, IOT_SG_STA_RPT_MODULE_EC_EVT);
ec_info->pulse_evt_info.seq = seq;
out:
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
static void iot_sg_sta_nw_event_ack_handle(nw_app_data_t *hdr)
{
nw_app_nack_t *nack = NULL;
if (!iot_sg_sta_check_pm_event_rpt_seq(hdr->sn)) {
return;
}
switch (hdr->work_id) {
case NW_APP_WORK_ACK:
{
iot_sg_sta_event_ack_handle(IOT_SG_STA_EVENT_RPT_OK);
break;
}
case NW_APP_WORK_NACK:
{
nack = (nw_app_nack_t *)hdr->data;
iot_sg_printf("%s nack %lu\n", __FUNCTION__, nack->reason);
switch (nack->reason) {
case NW_APP_NACK_CCO_BUSY:
{
iot_sg_sta_event_ack_handle(IOT_SG_STA_EVENT_RPT_BUF_FULL);
break;
}
default:
break;
}
break;
}
default:
iot_sg_printf("%s work id %lu err\n", __FUNCTION__, hdr->work_id);
break;
}
}
static void iot_sg_sta_nw_ack_nack_handle(nw_app_data_t *hdr)
{
if(iot_sg_sta_ext_ec_event_ack_handle(hdr->sn, 0) == ERR_OK) {
return;
}
iot_sg_sta_nw_event_ack_handle(hdr);
}
static void iot_sg_sta_nw_send_nack(uint8_t reason)
{
uint16_t total_size;
uint8_t *data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
nw_app_nack_t *nack;
IOT_ASSERT(req_pkt);
data = iot_pkt_data(req_pkt);
msdu = (iot_plc_msdu_recv_t *)(data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)data;
req_data = (nw_app_data_t *)(req_hdr + 1);
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data) + sizeof(*nack);
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_ACK_NACK, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_ACK_NACK;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_NACK;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = 1;
nack = (nw_app_nack_t *)rsp_data->data;
nack->reason = reason;
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s pkt err", __FUNCTION__);
}
}
static void iot_sg_sta_nw_send_ack()
{
uint16_t total_size;
uint8_t *data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
data = iot_pkt_data(req_pkt);
msdu = (iot_plc_msdu_recv_t *)(data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)data;
req_data = (nw_app_data_t *)(req_hdr + 1);
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_ACK_NACK, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_ACK_NACK;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_ACK;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = 0;
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s pkt err", __FUNCTION__);
}
}
static uint8_t iot_sg_sta_nw_data_type(uint8_t data_type)
{
uint8_t ret = NW_APP_DATA_TYPE_TRANSPARENT;
switch (data_type) {
case IOT_SG_STA_DATA_TYPE_645_97:
ret = NW_APP_DATA_TYPE_645_1997;
break;
case IOT_SG_STA_DATA_TYPE_645_07:
ret = NW_APP_DATA_TYPE_645_2007;
break;
}
return ret;
}
static void iot_sg_sta_nw_send_query_sm_result()
{
uint16_t total_size, payload_size;
uint8_t idx, node_cnt, *data, *req;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_cmd_query_meter_result_t *sm_result;
nw_app_base_meter_info_t *meter_info;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
node_cnt = iot_sg_node_reg_get_node_cnt();
payload_size = sizeof(*sm_result) + sizeof(*meter_info) * node_cnt;
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data) + payload_size;
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_QUERY_SM_RESULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_QUERY_SEARCH_METER_RESULT;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
sm_result = (nw_app_cmd_query_meter_result_t *)(rsp_data->data);
sm_result->meter_count = node_cnt;
sm_result->rsvd[0] = 0;
sm_result->rsvd[1] = 0;
sm_result->rsvd[2] = 0;
meter_info = sm_result->meter_info;
iot_sg_printf("%s cnt %lu\n", __FUNCTION__, sm_result->meter_count);
for (idx = 0; idx < IOT_SG_STA_SEC_NODE_MAX; idx++) {
if (sta_glb->node_list[idx]
&& !sta_glb->node_list[idx]->obsolete) {
os_mem_cpy(meter_info->meter_addr,
sta_glb->node_list[idx]->entry.addr, IOT_MAC_ADDR_LEN);
iot_sg_printf("%lu -- addr %02x%02x%02x%02x%02x%02x\n",
(idx + 1), meter_info->meter_addr[5],
meter_info->meter_addr[4], meter_info->meter_addr[3],
meter_info->meter_addr[2], meter_info->meter_addr[1],
meter_info->meter_addr[0]);
meter_info->proto_type = iot_sg_sta_nw_data_type(
sta_glb->node_list[idx]->data_type);
meter_info->reserved = 0;
meter_info += 1;
}
}
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s pkt err", __FUNCTION__);
}
}
static uint32_t iot_sg_sta_nw_query_sm_result(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
uint32_t ret = ERR_OK;
if (data_hdr->len != 0) {
ret = ERR_FAIL;
goto out;
}
iot_sg_sta_start_sec_node_reg(IOT_SG_STA_NODE_REG_REASON_QUERY);
if (!sta_glb->node_reg.node_reg_on) {
iot_sg_sta_nw_send_query_sm_result();
}
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_add_sm_list(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
uint8_t reason, dl_payload_size;
iot_sg_sta_drv_t *dev_drv = p_sg_glb->desc.sta->drv;
iot_sg_sta_drv_meter_list_t *drv_meter_list;
nw_app_cmd_dl_meter_list_t *meter_list;
meter_list = (nw_app_cmd_dl_meter_list_t *)data_hdr->data;
dl_payload_size = sizeof(*meter_list)
+ sizeof(nw_app_base_meter_info_t) * meter_list->meter_count;
if (data_hdr->len < dl_payload_size) {
ret = ERR_FAIL;
reason = NW_APP_NACK_FORMAT_ERROR;
goto nack;
}
if (!dev_drv->add_sm_list) {
ret = ERR_FAIL;
reason = NW_APP_NACK_WORD_ID_NO_SUPPORT;
goto nack;
}
drv_meter_list = (iot_sg_sta_drv_meter_list_t *)meter_list;
ret = dev_drv->add_sm_list(drv_meter_list);
if(ret != ERR_OK) {
reason = NW_APP_NACK_METER_LEVEL_NO_ACK;
goto nack;
}
iot_sg_sta_nw_send_ack();
goto out;
nack:
iot_sg_sta_nw_send_nack(reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_sec_node_evt(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
uint8_t reason;
nw_app_cmd_sec_node_evt_t *sec_node_evt;
sec_node_evt = (nw_app_cmd_sec_node_evt_t *)(data_hdr->data);
if (data_hdr->len < sizeof(*sec_node_evt)) {
ret = ERR_FAIL;
reason = NW_APP_NACK_FORMAT_ERROR;
goto nack;
}
switch (sec_node_evt->evt_rpt_enable) {
case NW_APP_CMD_SEC_NODE_EVENT_DIS:
{
iot_sg_sta_event_ack_handle(IOT_SG_STA_EVENT_RPT_DISABLED);
break;
}
case NW_APP_CMD_SEC_NODE_EVENT_EN:
{
iot_sg_sta_event_ack_handle(IOT_SG_STA_EVENT_RPT_ENABLED);
break;
}
default:
ret = ERR_FAIL;
reason = NW_APP_NACK_WORD_ID_NO_SUPPORT;
goto nack;
break;
}
iot_sg_sta_nw_send_ack();
goto out;
nack:
iot_sg_sta_nw_send_nack(reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_sec_node_reboot(iot_pkt_t *pkt,
uint8_t *data, uint16_t len)
{
uint32_t ret = ERR_OK, delay;
uint8_t reason;
nw_app_cmd_sec_node_reboot_t *sec_node_reboot;
sec_node_reboot = (nw_app_cmd_sec_node_reboot_t*)data;
if (len < sizeof(sec_node_reboot)) {
ret = ERR_FAIL;
reason = NW_APP_NACK_FORMAT_ERROR;
goto nack;
}
delay = (sec_node_reboot->delay) * 1000;
if (delay > NW_APP_SEC_REBOOT_DELAY_MAX_TIME)
delay = NW_APP_SEC_REBOOT_DELAY_MAX_TIME;
iot_sg_sta_nw_send_ack();
if (delay != 0)
os_delay(delay);
iot_system_restart(IOT_SYS_RST_REASON_APP_REQ);
goto out;
nack:
iot_sg_sta_nw_send_nack(reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint16_t iot_sg_sta_nw_sec_node_info_size_ul(uint8_t *info_id,
uint8_t info_cnt)
{
uint16_t payload_size = 0, base_len;
uint8_t idx;
payload_size += sizeof(info_cnt);
base_len = sizeof(nw_app_base_sec_node_info_t);
for (idx = 0; idx < info_cnt; idx++) {
switch (info_id[idx]) {
case NW_APP_CMD_SEC_NODE_INFO_OEM_CODE:
{
payload_size += sizeof(nw_app_base_sec_node_vendor_id_t) + base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_VER_INFO:
case NW_APP_CMD_SEC_NODE_INFO_SW_CHIP_VER_INFO:
case NW_APP_CMD_SEC_NODE_INFO_APP_VER_INFO:
case NW_APP_CMD_SEC_NODE_INFO_HW_MOD_VER_INFO:
case NW_APP_CMD_SEC_NODE_INFO_HW_CHIP_VER_INFO:
{
payload_size += sizeof(nw_app_base_sec_node_ver_t) + base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_BOOTLOADER:
{
payload_size += sizeof(nw_app_base_sec_node_bootloader_ver_t)
+ base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_UPGRADE_CRC:
{
payload_size += sizeof(nw_app_base_sec_node_upfile_crc_t)
+ base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_UPGRADE_LEN:
{
payload_size += sizeof(nw_app_base_sec_node_upfile_len_t)
+ base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_CHIP_CODE:
{
payload_size += sizeof(nw_app_base_sec_node_chip_code_t) + base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_VER_DATE:
case NW_APP_CMD_SEC_NODE_INFO_SW_CHIP_VER_DATE:
case NW_APP_CMD_SEC_NODE_INFO_HW_MOD_DATE:
case NW_APP_CMD_SEC_NODE_INFO_HW_CHIP_VER_DATE:
{
payload_size += sizeof(nw_app_base_sec_node_ver_date_t) + base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_UPGRADE_WORDS:
{
payload_size += sizeof(nw_app_base_upgrade_words_t) + base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_MOD_MAC:
{
payload_size += sizeof(nw_app_base_module_mac_t) + base_len;
break;
}
case NW_APP_CMD_SEC_NODE_INFO_DEV_ID:
{
payload_size += IOT_CHIP_MMID_LEN + base_len;
break;
}
default:
break;
}
}
return payload_size;
}
static uint8_t iot_sg_sta_nw_get_upgrade_exit_reason(uint8_t state)
{
uint8_t result = NW_APP_UPGRADE_WORDS_OTHERS;
switch (state) {
case IOT_SG_STA_UPGRADE_EXIT_NORMAL:
case IOT_SG_STA_UPGRADE_EXIT_SAME_VER:
{
result = NW_APP_UPGRADE_WORDS_NORMAL;
break;
}
case IOT_SG_STA_UPGRADE_EXIT_MISMATCH:
{
result = NW_APP_UPGRADE_WORDS_MISMATCH;
break;
}
default:
break;
}
return result;
}
void iot_sg_sta_nw_21meter_mode_mac_get(uint8_t *mac)
{
uint8_t cus_code = 0, i;
uint32_t tmp = 1;
nw_app_21meter_module_mac_tmp_t mac_tmp = { 0 };
nw_app_21meter_module_dev_id_t id_data = { 0 };
BUILD_BUG_ON(IOT_CHIP_MMID_LEN == sizeof(id_data));
iot_oem_get_chip_mmid((uint8_t *)&id_data, IOT_CHIP_MMID_LEN);
for (i = 0; i < NW_APP_21METER_SERIAL_NUM_LEN; i++) {
mac_tmp.serial_number += (tmp * (id_data.serial_number[i] - 0x30));
tmp *= 10;
}
mac_tmp.year_code = (id_data.year_code[1] - 0x30) * 10 +
(id_data.year_code[0] - 0x30) - 20;
mac_tmp.vendor_code = (id_data.vendor_code[1] - 0x30) * 10 +
(id_data.vendor_code[0] - 0x30);
if (id_data.dev_type[1] == 'E' && id_data.dev_type[0] == 'M') {
mac_tmp.dev_type = NW_APP_21METER_DEV_TYPE_1P;
} else if (id_data.dev_type[1] == 'E' && id_data.dev_type[0] == 'S') {
mac_tmp.dev_type = NW_APP_21METER_DEV_TYPE_3P;
} else if (id_data.dev_type[1] == 'E' && id_data.dev_type[0] == 'J') {
mac_tmp.dev_type = NW_APP_21METER_DEV_TYPE_CCTT;
} else if (id_data.dev_type[1] == 'E' && id_data.dev_type[0] == 'C') {
mac_tmp.dev_type = NW_APP_21METER_DEV_TYPE_CT1;
} else if (id_data.dev_type[1] == 'Z' && id_data.dev_type[0] == 'C') {
mac_tmp.dev_type = NW_APP_21METER_DEV_TYPE_CT2;
}
cus_code = (id_data.provincial_code[1] - 0x30) * 10 +
(id_data.provincial_code[0] - 0x30);
if (cus_code == NW_APP_DEV_ID_CUS_CODE_GUANGDONG) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_GUANGDONG;
} else if (cus_code == NW_APP_DEV_ID_CUS_CODE_GUANGXI) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_GUANGXI;
} else if (cus_code == NW_APP_DEV_ID_CUS_CODE_YUNNAN) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_YUNNAN;
} else if (cus_code == NW_APP_DEV_ID_CUS_CODE_GUIZHOU) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_GUIZHOU;
} else if (cus_code == NW_APP_DEV_ID_CUS_CODE_HAINAN) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_HAINAN;
} else if (cus_code == NW_APP_DEV_ID_CUS_CODE_GUANGZHOU) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_GUANGZHOU;
} else if (cus_code == NW_APP_DEV_ID_CUS_CODE_SHENZHEN) {
mac_tmp.cus_code = NW_APP_MODULR_CUS_CODE_SHENZHEN;
}
BUILD_BUG_ON(IOT_MAC_ADDR_LEN == sizeof(mac_tmp) - 2);
os_mem_cpy(mac, ((uint8_t *)&mac_tmp + 1), IOT_MAC_ADDR_LEN);
}
static uint32_t iot_sg_sta_nw_sec_node_info_fill_data_ul(uint8_t *info_id,
uint8_t info_cnt, nw_app_cmd_sec_info_query_ul_t *rsp_info,
uint16_t rsp_info_len)
{
uint32_t ret = ERR_INVAL, part;
uint8_t idx, *tmp_data, temp, reason = 0;
nw_app_base_sec_node_info_t *temp_info;
nw_app_base_sec_node_vendor_id_t *base_vid;
nw_app_base_sec_node_ver_t *base_sw_mod_ver;
nw_app_base_sec_node_bootloader_ver_t *base_boot;
nw_app_base_sec_node_upfile_crc_t *base_crc;
nw_app_base_sec_node_upfile_len_t *base_up_len;
nw_app_base_sec_node_chip_code_t *base_chip;
nw_app_base_sec_node_ver_date_t *base_sw_mod_date;
nw_app_base_upgrade_words_t *base_upgrade_word;
nw_app_base_module_mac_t *mod_mac;
nw_app_base_sec_node_ver_t *base_hw_mod_ver;
nw_app_base_sec_node_ver_date_t *base_hw_mod_date;
nw_app_base_sec_node_ver_t *base_hw_chip_ver;
nw_app_base_sec_node_ver_date_t *base_hw_chip_date;
iot_build_info_t info;
iot_oem_hw_ver_info_t hw_ver_info;
iot_sg_sta_upgrade_info_t *upgrade_info =
&p_sg_glb->desc.sta->upgrade_info;
tmp_data = (uint8_t *)rsp_info->info;
iot_version_get_user_build_info(&info);
iot_oem_get_hw_ver_info(&hw_ver_info);
if (rsp_info_len < sizeof(*rsp_info)) {
reason = 1;
goto out;
}
rsp_info->count = 0;
rsp_info_len -= sizeof(*rsp_info);
for (idx = 0; idx < info_cnt; idx++) {
temp_info = (nw_app_base_sec_node_info_t *)tmp_data;
switch (info_id[idx]) {
case NW_APP_CMD_SEC_NODE_INFO_OEM_CODE:
{
if (rsp_info_len < sizeof(*base_vid) + sizeof(*temp_info)) {
reason = 2;
goto out;
}
rsp_info_len -= sizeof(*base_vid) + sizeof(*temp_info);
base_vid = (nw_app_base_sec_node_vendor_id_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_vid);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_OEM_CODE;
base_vid->vendor_id = iot_sg_get_vendor_id();
tmp_data += sizeof(*base_vid) + sizeof(*temp_info);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_VER_INFO:
case NW_APP_CMD_SEC_NODE_INFO_SW_CHIP_VER_INFO:
case NW_APP_CMD_SEC_NODE_INFO_APP_VER_INFO:
{
if (rsp_info_len < sizeof(*base_sw_mod_ver) + sizeof(*temp_info)) {
reason = 3;
goto out;
}
rsp_info_len -= sizeof(*base_sw_mod_ver) + sizeof(*temp_info);
base_sw_mod_ver = (nw_app_base_sec_node_ver_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_sw_mod_ver);
temp_info->id = info_id[idx];
if (info_id[idx] == NW_APP_CMD_SEC_NODE_INFO_APP_VER_INFO) {
base_sw_mod_ver->ver = 0x11;
} else {
base_sw_mod_ver->ver = info.sw_ver;
}
tmp_data += sizeof(*base_sw_mod_ver) + sizeof(*temp_info);
iot_sg_printf("%s - sw ver: %.4X\n", __FUNCTION__,
base_sw_mod_ver->ver);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_BOOTLOADER:
{
if (rsp_info_len < sizeof(*base_boot) + sizeof(*temp_info)) {
reason = 4;
goto out;
}
rsp_info_len -= sizeof(*base_boot) + sizeof(*temp_info);
base_boot = (nw_app_base_sec_node_bootloader_ver_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_boot);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_BOOTLOADER;
base_boot->bootloader_ver = iot_version_bootloader();
tmp_data += sizeof(*base_boot) + sizeof(*temp_info);
iot_sg_printf("%s - boot ver: %.4X\n", __FUNCTION__,
base_boot->bootloader_ver);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_UPGRADE_CRC:
{
if (rsp_info_len < sizeof(*base_crc) + sizeof(*temp_info)) {
reason = 5;
goto out;
}
if (iot_upgrade_get_part(&part) != ERR_OK) {
reason = 6;
goto out;
}
rsp_info_len -= sizeof(*base_crc) + sizeof(*temp_info);
base_crc = (nw_app_base_sec_node_upfile_crc_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_crc);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_UPGRADE_CRC;
base_crc->upfile_crc = iot_upgrade_get_fw_crc(part);
tmp_data += sizeof(*base_crc) + sizeof(*temp_info);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_UPGRADE_LEN:
{
if (rsp_info_len < sizeof(*base_up_len) + sizeof(*temp_info)) {
reason = 7;
goto out;
}
if (iot_upgrade_get_part(&part) != ERR_OK) {
reason = 8;
goto out;
}
rsp_info_len -= sizeof(*base_up_len) + sizeof(*temp_info);
base_up_len = (nw_app_base_sec_node_upfile_len_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_up_len);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_UPGRADE_LEN;
base_up_len->upfile_len = iot_upgrade_get_fw_size(part);
tmp_data += sizeof(*base_up_len) + sizeof(*temp_info);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_CHIP_CODE:
{
if (rsp_info_len < sizeof(*base_chip) + sizeof(*temp_info)) {
reason = 9;
goto out;
}
rsp_info_len -= sizeof(*base_chip) + sizeof(*temp_info);
base_chip = (nw_app_base_sec_node_chip_code_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_chip);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_CHIP_CODE;
base_chip->chip_code = iot_sg_get_chip_code();
tmp_data += sizeof(*base_chip) + sizeof(*temp_info);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_VER_DATE:
case NW_APP_CMD_SEC_NODE_INFO_SW_CHIP_VER_DATE:
{
if (rsp_info_len < sizeof(*base_sw_mod_date) + sizeof(*temp_info)) {
reason = 10;
goto out;
}
rsp_info_len -= sizeof(*base_sw_mod_date) + sizeof(*temp_info);
base_sw_mod_date = (nw_app_base_sec_node_ver_date_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_sw_mod_date);
temp_info->id = info_id[idx];
base_sw_mod_date->day = info.day;
base_sw_mod_date->month = info.month;
base_sw_mod_date->year = info.year;
tmp_data += sizeof(*base_sw_mod_date) + sizeof(*temp_info);
iot_sg_printf("%s - sw build date: %lu-%lu-%lu\n",
__FUNCTION__, base_sw_mod_date->year,
base_sw_mod_date->month, base_sw_mod_date->day);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_UPGRADE_WORDS:
{
if (rsp_info_len < sizeof(*base_upgrade_word) +
sizeof(*temp_info)) {
reason = 11;
goto out;
}
rsp_info_len -= sizeof(*base_upgrade_word) + sizeof(*temp_info);
base_upgrade_word = (nw_app_base_upgrade_words_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_upgrade_word);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_UPGRADE_WORDS;
base_upgrade_word->word1 = iot_sg_sta_nw_get_upgrade_exit_reason(
upgrade_info->exit_reason);
tmp_data += sizeof(*base_upgrade_word) + sizeof(*temp_info);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_MOD_MAC:
{
if (rsp_info_len < sizeof(*mod_mac) + sizeof(*temp_info)) {
reason = 12;
goto out;
}
rsp_info_len -= sizeof(*mod_mac) + sizeof(*temp_info);
mod_mac = (nw_app_base_module_mac_t *)(temp_info + 1);
temp_info->data_len = sizeof(*mod_mac);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_MOD_MAC;
if (iot_sg_sta_nw_new_meter_check()) {
iot_sg_sta_nw_21meter_mode_mac_get(mod_mac->mac);
} else {
iot_oem_get_module_mac(mod_mac->mac);
if (!iot_mac_addr_valid(mod_mac->mac)) {
os_mem_set(mod_mac->mac, 0xFF, IOT_MAC_ADDR_LEN);
}
iot_mac_addr_reverse(mod_mac->mac);
}
tmp_data += sizeof(*mod_mac) + sizeof(*temp_info);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_HW_MOD_VER_INFO:
{
if (rsp_info_len < sizeof(*base_hw_mod_ver) + sizeof(*temp_info)) {
reason = 13;
goto out;
}
rsp_info_len -= sizeof(*base_hw_mod_ver) + sizeof(*temp_info);
base_hw_mod_ver = (nw_app_base_sec_node_ver_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_hw_mod_ver);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_HW_MOD_VER_INFO;
os_mem_cpy(&base_hw_mod_ver->ver, hw_ver_info.module_version,
min(sizeof(base_hw_mod_ver->ver),
sizeof(hw_ver_info.module_version)));
tmp_data += sizeof(*base_hw_mod_ver) + sizeof(*temp_info);
iot_sg_printf("%s - hw chip version: %04X\n",
__FUNCTION__, base_hw_mod_ver->ver);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_HW_MOD_DATE:
{
if (rsp_info_len < sizeof(*base_hw_mod_date) + sizeof(*temp_info)) {
reason = 14;
goto out;
}
rsp_info_len -= sizeof(*base_hw_mod_date) + sizeof(*temp_info);
base_hw_mod_date =
(nw_app_base_sec_node_ver_date_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_hw_mod_date);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_HW_MOD_DATE;
base_hw_mod_date->year =
iot_bcd_to_byte(hw_ver_info.module_version_year);
base_hw_mod_date->month =
iot_bcd_to_byte(hw_ver_info.module_version_month);
base_hw_mod_date->day =
iot_bcd_to_byte(hw_ver_info.module_version_day);
tmp_data += sizeof(*base_hw_mod_date) + sizeof(*temp_info);
iot_sg_printf("%s - hw module build date: %lu-%lu-%lu\n",
__FUNCTION__, base_hw_mod_date->year,
base_hw_mod_date->month, base_hw_mod_date->day);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_HW_CHIP_VER_INFO:
{
if (rsp_info_len < sizeof(*base_hw_chip_ver) + sizeof(*temp_info)) {
reason = 15;
goto out;
}
rsp_info_len -= sizeof(*base_hw_chip_ver) + sizeof(*temp_info);
base_hw_chip_ver = (nw_app_base_sec_node_ver_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_hw_chip_ver);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_HW_CHIP_VER_INFO;
temp = iot_ascii_to_byte(hw_ver_info.chip_ver[0]) +
iot_ascii_to_byte(hw_ver_info.chip_ver[1]) * 10;
temp = iot_byte_to_bcd(temp);
base_hw_chip_ver->ver = temp;
temp = iot_ascii_to_byte(hw_ver_info.chip_ver[2]) +
iot_ascii_to_byte(hw_ver_info.chip_ver[3]) * 10;
temp = iot_byte_to_bcd(temp);
base_hw_chip_ver->ver |= temp << 8;
tmp_data += sizeof(*base_hw_chip_ver) + sizeof(*temp_info);
iot_sg_printf("%s - hw chip version: %04X\n", __FUNCTION__,
base_hw_chip_ver->ver);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_HW_CHIP_VER_DATE:
{
if (rsp_info_len < sizeof(*base_hw_chip_date) + sizeof(*temp_info)) {
reason = 16;
goto out;
}
rsp_info_len -= sizeof(*base_hw_chip_date) + sizeof(*temp_info);
base_hw_chip_date =
(nw_app_base_sec_node_ver_date_t *)(temp_info + 1);
temp_info->data_len = sizeof(*base_hw_chip_date);
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_HW_CHIP_VER_DATE;
base_hw_chip_date->year = iot_bcd_to_byte(hw_ver_info.chip_year);
base_hw_chip_date->month = iot_bcd_to_byte(hw_ver_info.chip_month);
base_hw_chip_date->day = iot_bcd_to_byte(hw_ver_info.chip_day);
tmp_data += sizeof(*base_hw_chip_date) + sizeof(*temp_info);
iot_sg_printf("%s - hw chip build date: %lu-%lu-%lu\n",
__FUNCTION__, base_hw_chip_date->year,
base_hw_chip_date->month, base_hw_chip_date->day);
break;
}
case NW_APP_CMD_SEC_NODE_INFO_DEV_ID:
{
if (rsp_info_len < IOT_CHIP_MMID_LEN + sizeof(*temp_info)) {
reason = 17;
goto out;
}
rsp_info_len -= IOT_CHIP_MMID_LEN + sizeof(*temp_info);
temp_info->data_len = IOT_CHIP_MMID_LEN;
temp_info->id = NW_APP_CMD_SEC_NODE_INFO_DEV_ID;
tmp_data += sizeof(*temp_info);
iot_oem_get_chip_mmid(tmp_data, IOT_CHIP_MMID_LEN);
tmp_data += IOT_CHIP_MMID_LEN;
break;
}
default:
continue;
}
rsp_info->count++;
}
ret = ERR_OK;
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_nw_sec_node_info_send(uint8_t *info_id,
uint8_t info_cnt, uint8_t flag_broadcast)
{
uint32_t ret = ERR_OK;
uint16_t total_size, payload_size = 0;
uint8_t *req, *rsp, tmp_size;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_cmd_sec_info_query_ul_t *rsp_info;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
nw_app_broadcast_cmd_hdr *req_bcast_hdr = NULL, *resp_bcast_hdr;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
if (flag_broadcast) {
req_bcast_hdr = (nw_app_broadcast_cmd_hdr*)req_data->data;
}
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
tmp_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
payload_size = iot_sg_sta_nw_sec_node_info_size_ul(info_id, info_cnt);
if (flag_broadcast) {
payload_size += sizeof(*resp_bcast_hdr);
}
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_QUERY_SEC_NODE_INFO, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (!plc_pkt) {
iot_sg_printf("%s pkt err", __FUNCTION__);
ret = ERR_NOMEM;
goto out;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
if (flag_broadcast) {
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_BCAST_CMD;
} else {
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
}
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_SEC_NODE_INFO_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
if (flag_broadcast) {
resp_bcast_hdr = (nw_app_broadcast_cmd_hdr*)rsp_data->data;
if (iot_mac_addr_valid(req_bcast_hdr->dst_addr)) {
iot_mac_addr_cpy(resp_bcast_hdr->src_addr,
req_bcast_hdr->dst_addr);
} else {
iot_mac_addr_cpy(resp_bcast_hdr->src_addr,
p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(resp_bcast_hdr->src_addr);
}
if (iot_mac_addr_valid(req_bcast_hdr->src_addr)) {
iot_mac_addr_cpy(resp_bcast_hdr->dst_addr,
req_bcast_hdr->src_addr);
} else {
iot_mac_addr_cpy(resp_bcast_hdr->dst_addr,
p_sg_glb->plc_state.cco_addr);
iot_mac_addr_reverse(resp_bcast_hdr->dst_addr);
}
rsp_info = (nw_app_cmd_sec_info_query_ul_t*)resp_bcast_hdr->data;
} else {
rsp_info = (nw_app_cmd_sec_info_query_ul_t*)rsp_data->data;
}
ret = iot_sg_sta_nw_sec_node_info_fill_data_ul(info_id, info_cnt, rsp_info,
payload_size);
if (ret != ERR_OK) {
iot_pkt_free(plc_pkt);
goto out;
}
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_sec_node_info_query(iot_pkt_t *pkt,
uint8_t *data, uint16_t len, uint8_t flag_broadcast)
{
uint32_t ret = ERR_OK;
uint8_t info_count, *info_id, dl_payload_size;
nw_app_cmd_sec_info_query_dl_t *sec_info;
sec_info = (nw_app_cmd_sec_info_query_dl_t *)data;
info_count = sec_info->count;
info_id = sec_info->info_id;
dl_payload_size = sizeof(*sec_info) + sizeof(*info_id) * info_count;
if (len < dl_payload_size) {
ret = ERR_FAIL;
goto out;
}
iot_sg_sta_nw_sec_node_info_send(info_id, info_count, flag_broadcast);
out:
iot_pkt_free(pkt);
return ret;
}
static uint8_t iot_sg_sta_nw_to_plc_dev_type(uint8_t dev_type)
{
uint8_t plc_dev_type;
switch (dev_type) {
case IOT_SG_STA_DEV_TYPE_POWER_METER:
plc_dev_type = IOT_PLC_DEV_TYPE_POWER_METER;
break;
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T1:
plc_dev_type = IOT_PLC_DEV_TYPE_COLLECTOR_1;
break;
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T2:
plc_dev_type = IOT_PLC_DEV_TYPE_COLLECTOR_2;
break;
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T3:
plc_dev_type = IOT_PLC_DEV_TYPE_SWITCH_MONITOR;
break;
default:
IOT_ASSERT(0);
plc_dev_type = IOT_PLC_DEV_TYPE_INVAL;
break;
}
return plc_dev_type;
}
static uint32_t iot_sg_sta_nw_node_id_send(uint8_t id_type)
{
uint32_t ret = ERR_OK;
uint16_t total_size, data_len;
uint8_t *req, *rsp;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
iot_oem_base_cfg_t *base_cfg = NULL;
nw_app_cmd_id_info_hdr_ul_t *id_info;
nw_app_cmd_node_id_t *node_id;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
data_len = sizeof(*id_info) + sizeof(*node_id);
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_SEC_NODE_ID_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = data_len;
id_info = (nw_app_cmd_id_info_hdr_ul_t *)rsp_data->data;
id_info->id_type = id_type;
id_info->id_len = NW_APP_NODE_ID_INFO_LEN;
node_id = (nw_app_cmd_node_id_t *)(id_info + 1);
iot_mac_addr_cpy(node_id->meter_mac, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(node_id->meter_mac);
BUILD_BUG_ON(NW_APP_NODE_ID_INFO_LEN >=
max(IOT_OEM_DEVICE_ID_LEN, IOT_CHIP_MMID_LEN));
switch (id_type) {
case NW_APP_ID_TYPE_MOD_COMPATIBLE:
case NW_APP_ID_TYPE_MOD:
{
iot_oem_get_base_cfg(&base_cfg);
os_mem_cpy(node_id->id_info, base_cfg->dev_id,
IOT_OEM_DEVICE_ID_LEN);
break;
}
case NW_APP_ID_TYPE_CHIP:
{
iot_oem_get_chip_mmid(node_id->id_info, IOT_CHIP_MMID_LEN);
break;
}
default:
ret = ERR_INVAL;
goto out;
}
if (sta_glb->drv) {
node_id->dev_type = (uint8_t)sta_glb->drv->get_device_type();
node_id->dev_type =
iot_sg_sta_nw_to_plc_dev_type(node_id->dev_type);
} else {
node_id->dev_type = IOT_PLC_DEV_TYPE_POWER_METER;
}
if (iot_plc_pm_power_check() == ERR_OK) {
node_id->super_cap = 1;
} else {
node_id->super_cap = 0;
}
node_id->fix_position = 0;
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
}
out:
return ret;
}
static uint32_t iot_sg_sta_nw_node_id_query(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint8_t meter_mac[IOT_MAC_ADDR_LEN];
uint32_t ret = ERR_OK;
nw_app_cmd_id_dl_t *id_dl;
if (data_hdr->len < sizeof(*id_dl)) {
ret = ERR_INVAL;
goto out;
}
id_dl = (nw_app_cmd_id_dl_t *)data_hdr->data;
iot_mac_addr_cpy(meter_mac, id_dl->meter_mac);
iot_mac_addr_reverse(meter_mac);
if (!iot_mac_addr_cmp(meter_mac, p_sg_glb->plc_state.addr) ||
id_dl->id_type > NW_APP_ID_TYPE_MOD) {
ret = ERR_INVAL;
goto out;
}
iot_sg_sta_nw_node_id_send(id_dl->id_type);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_add_addr_map_list(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
uint8_t reason, dl_payload_size;
iot_sg_sta_drv_t *dev_drv = p_sg_glb->desc.sta->drv;
iot_sg_sta_drv_map_list_t *drv_map_list;
nw_app_cmd_dl_map_list_t *map_list;
map_list = (nw_app_cmd_dl_map_list_t *)data_hdr->data;
dl_payload_size = sizeof(*map_list)
+ sizeof(nw_app_base_map_list_info_t) * map_list->list_count;
if (data_hdr->len < dl_payload_size) {
ret = ERR_FAIL;
reason = NW_APP_NACK_FORMAT_ERROR;
goto nack;
}
if (!dev_drv->add_map_list) {
ret = ERR_FAIL;
reason = NW_APP_NACK_WORD_ID_NO_SUPPORT;
goto nack;
}
drv_map_list = (iot_sg_sta_drv_map_list_t *)map_list;
ret = dev_drv->add_map_list(drv_map_list);
if (ret != ERR_OK) {
reason = NW_APP_NACK_METER_LEVEL_NO_ACK;
goto nack;
}
iot_sg_sta_nw_send_ack();
goto out;
nack:
iot_sg_sta_nw_send_nack(reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_neighbour_query(iot_pkt_t *pkt,
uint8_t *data, uint16_t len, uint8_t flag_broadcast)
{
uint32_t ret = ERR_OK;
uint8_t reason, cnt;
nw_app_neighbor_query_req *req;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (len < sizeof(*req)) {
ret = ERR_FAIL;
reason = 1;
goto drop;
}
req = (nw_app_neighbor_query_req *)data;
if (!req->cnt) {
ret = ERR_FAIL;
reason = 2;
goto drop;
}
if (req->cnt > IOT_SG_STA_NW_NEIGHBOR_QUERY_MAX_CNT) {
cnt = IOT_SG_STA_NW_NEIGHBOR_QUERY_MAX_CNT;
} else {
cnt = req->cnt;
}
iot_plc_query_neighbor_dev(p_sg_glb->plc_app_h,
IOT_SG_STA_QUERY_NEIG_NODE_FROM_PLC, req->index, cnt,
IOT_PLC_QUERY_TOPO_START_AS_INDEX);
sta_glb->plc_query.neig_info_query_on = 1;
sta_glb->plc_query.neig_info_timeout = 5;
sta_glb->plc_query.flag_broadcast = flag_broadcast;
ret = ERR_PENDING;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (ret != ERR_PENDING) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_nw_neighbor_info_resp(iot_plc_neighbor_dev_rpt_t *rpt,
uint8_t flag_broadcast)
{
uint32_t ret = ERR_OK;
uint16_t total_size, data_len;
uint8_t *req, *rsp, i;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
nw_app_neighbor_query_resp *resp;
nw_app_neighbor_node_info_t *node_info;
nw_app_broadcast_cmd_hdr *req_bcast_hdr = NULL, *resp_bcast_hdr;
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
if (flag_broadcast) {
req_bcast_hdr = (nw_app_broadcast_cmd_hdr*)req_data->data;
}
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
data_len = sizeof(*resp) + (rpt->cnt * sizeof(*node_info));
if (flag_broadcast) {
data_len += sizeof(*resp_bcast_hdr);
}
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt == NULL) {
ret = ERR_NOMEM;
goto out;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT_MGR;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
if (flag_broadcast) {
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_BCAST_CMD;
} else {
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
}
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_NEIGHBOUR_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = data_len;
if (flag_broadcast) {
resp_bcast_hdr = (nw_app_broadcast_cmd_hdr*)rsp_data->data;
if (iot_mac_addr_valid(req_bcast_hdr->dst_addr)) {
iot_mac_addr_cpy(resp_bcast_hdr->src_addr,
req_bcast_hdr->dst_addr);
} else {
iot_mac_addr_cpy(resp_bcast_hdr->src_addr,
p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(resp_bcast_hdr->src_addr);
}
if (iot_mac_addr_valid(req_bcast_hdr->src_addr)) {
iot_mac_addr_cpy(resp_bcast_hdr->dst_addr,
req_bcast_hdr->src_addr);
} else {
iot_mac_addr_cpy(resp_bcast_hdr->dst_addr,
p_sg_glb->plc_state.cco_addr);
iot_mac_addr_reverse(resp_bcast_hdr->dst_addr);
}
resp = (nw_app_neighbor_query_resp*)resp_bcast_hdr->data;
} else {
resp = (nw_app_neighbor_query_resp *)rsp_data->data;
}
resp->total_cnt = rpt->total_cnt;
resp->cnt = (uint8_t)rpt->cnt;
for (i = 0; i < rpt->cnt; i++) {
iot_mac_addr_cpy(resp->node_info[i].mac, rpt->node[i].addr);
iot_mac_addr_reverse(resp->node_info[i].mac);
resp->node_info[i].tei = (uint16_t)rpt->node[i].tei;
resp->node_info[i].proxy_tei = (uint16_t)rpt->node[i].proxy_tei;
resp->node_info[i].level = (uint8_t)rpt->node[i].level;
resp->node_info[i].ul_sr = rpt->node[i].ul_tf_sr;
resp->node_info[i].dl_sr = rpt->node[i].dl_tf_sr;
resp->node_info[i].ul_dl_sr =
(rpt->node[i].ul_tf_sr * rpt->node[i].dl_tf_sr) / 100;
resp->node_info[i].snr = rpt->node[i].snr;
resp->node_info[i].signal_attenuation = rpt->node[i].attenuation;
}
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
out:
return ret;
}
uint8_t iot_sg_sta_nw_zc_state_get(void)
{
uint8_t state = PROTO_SPG_THREE_PHASE_ZC_UNKNOWN;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_properties_global_t *zc_info = &sta_glb->node_properties;
if (iot_sg_sta_is_3p_module()) {
if (zc_info->phase == 7) {
if (zc_info->opposite_3p || zc_info->opposite_phase) {
state = PROTO_SPG_THREE_PHASE_ZC_ERR;
goto out;
}
state = PROTO_SPG_THREE_PHASE_ZC_ABC;
} else {
if (!zc_info->phase) {
state = PROTO_SPG_THREE_PHASE_ZC_UNKNOWN;
goto out;
}
if (zc_info->zc_repeat_3p) {
state = PROTO_SPG_THREE_PHASE_ZC_SAME;
goto out;
}
state = PROTO_SPG_THREE_PHASE_ZC_DISC;
}
} else {
state = PROTO_SPG_SINGLE_PHASE_ZC_SUPP;
}
out:
return state;
}
static void iot_sg_sta_nw_run_state_query_handle(uint8_t cnt, uint8_t *id,
uint8_t flag_broadcast)
{
uint16_t total_size, data_len;
uint8_t *req, *rsp, i, id_cnt = 0, id_idx = 0, reset_reason;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
nw_app_run_state_query_resp_t *resp;
nw_app_run_state_id_hdr_t *id_hdr;
nw_app_node_runtime_info_t *runtime;
nw_app_node_run_other_info_t *other_info;
nw_app_broadcast_cmd_hdr *req_bcast_hdr = NULL, *resp_bcast_hdr;
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
if (flag_broadcast) {
req_bcast_hdr = (nw_app_broadcast_cmd_hdr*)req_data->data;
}
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
data_len = sizeof(*resp);
for (i = 0; i < cnt; i++) {
switch (id[i]) {
case NW_APP_RUN_STATE_ID_RUNTIME:
{
data_len += sizeof(nw_app_node_runtime_info_t);
break;
}
case NW_APP_RUN_STATE_ID_ZC:
case NW_APP_RUN_STATE_ID_UART:
case NW_APP_RUN_STATE_ID_LEAVE:
case NW_APP_RUN_STATE_ID_RESET:
{
data_len += sizeof(nw_app_node_run_other_info_t);
break;
}
default:
continue;
}
data_len += sizeof(*id_hdr);
id_cnt++;
}
if (flag_broadcast) {
data_len += sizeof(*resp_bcast_hdr);
}
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt == NULL) {
return;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT_MGR;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
if (flag_broadcast) {
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_BCAST_CMD;
} else {
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
}
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_RUN_STATE_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = data_len;
if (flag_broadcast) {
resp_bcast_hdr = (nw_app_broadcast_cmd_hdr*)rsp_data->data;
if (iot_mac_addr_valid(req_bcast_hdr->dst_addr)) {
iot_mac_addr_cpy(resp_bcast_hdr->src_addr,
req_bcast_hdr->dst_addr);
} else {
iot_mac_addr_cpy(resp_bcast_hdr->src_addr,
p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(resp_bcast_hdr->src_addr);
}
if (iot_mac_addr_valid(req_bcast_hdr->src_addr)) {
iot_mac_addr_cpy(resp_bcast_hdr->dst_addr,
req_bcast_hdr->src_addr);
} else {
iot_mac_addr_cpy(resp_bcast_hdr->dst_addr,
p_sg_glb->plc_state.cco_addr);
iot_mac_addr_reverse(resp_bcast_hdr->dst_addr);
}
resp = (nw_app_run_state_query_resp_t*)resp_bcast_hdr->data;
} else {
resp = (nw_app_run_state_query_resp_t*)rsp_data->data;
}
resp->cnt = id_cnt;
if (!resp->cnt) {
goto out;
}
for (i = 0; i < cnt; i++) {
id_hdr = (nw_app_run_state_id_hdr_t *)&resp->data[id_idx];
switch (id[i]) {
case NW_APP_RUN_STATE_ID_RUNTIME:
{
id_hdr->id = NW_APP_RUN_STATE_ID_RUNTIME;
id_hdr->len = sizeof(nw_app_node_runtime_info_t);
runtime = (nw_app_node_runtime_info_t *)id_hdr->data;
runtime->runtime = (uint32_t)(os_boot_time64() / 1000);
break;
}
case NW_APP_RUN_STATE_ID_ZC:
{
id_hdr->id = NW_APP_RUN_STATE_ID_ZC;
id_hdr->len = sizeof(nw_app_node_run_other_info_t);
other_info = (nw_app_node_run_other_info_t *)id_hdr->data;
other_info->result = iot_sg_sta_nw_zc_state_get();
break;
}
case NW_APP_RUN_STATE_ID_UART:
{
id_hdr->id = NW_APP_RUN_STATE_ID_UART;
id_hdr->len = sizeof(nw_app_node_run_other_info_t);
other_info = (nw_app_node_run_other_info_t *)id_hdr->data;
other_info->result = iot_sg_sta_uart_state_get();
break;
}
case NW_APP_RUN_STATE_ID_LEAVE:
{
id_hdr->id = NW_APP_RUN_STATE_ID_LEAVE;
id_hdr->len = sizeof(nw_app_node_run_other_info_t);
other_info = (nw_app_node_run_other_info_t *)id_hdr->data;
if (p_sg_glb->plc_state.leave_net_reason >
IOT_PLC_LEAVE_REASON_LEAVE_IND) {
other_info->result = IOT_PLC_LEAVE_REASON_UNKNOWN;
} else {
other_info->result = p_sg_glb->plc_state.leave_net_reason;
}
break;
}
case NW_APP_RUN_STATE_ID_RESET:
{
id_hdr->id = NW_APP_RUN_STATE_ID_RESET;
id_hdr->len = sizeof(nw_app_node_run_other_info_t);
other_info = (nw_app_node_run_other_info_t *)id_hdr->data;
iot_board_get_boot_reason(&reset_reason);
if (reset_reason == IOT_SYS_RST_REASON_UPGRADE) {
other_info->result = NW_APP_RUN_RESET_REASON_UPGRADE;
} else if (reset_reason == IOT_SYS_RST_REASON_APP_REQ) {
other_info->result = NW_APP_RUN_RESET_REASON_CCO;
} else {
other_info->result = NW_APP_RUN_RESET_REASON_POWER;
}
break;
}
default:
iot_sg_printf("%s err id %lu\n", __FUNCTION__, id[cnt]);
continue;
}
id_idx += (sizeof(*id_hdr) + id_hdr->len);
}
out:
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
}
static uint32_t iot_sg_sta_nw_run_state_query(iot_pkt_t *pkt,
uint8_t *data, uint16_t len, uint8_t flag_broadcast)
{
uint32_t ret = ERR_OK;
nw_app_run_state_query_req_t *req;
if (len < sizeof(*req)) {
ret = ERR_FAIL;
goto out;
}
req = (nw_app_run_state_query_req_t *)data;
if (!req->cnt || (len - sizeof(*req)) <
(req->cnt * sizeof(req->id[0]))) {
ret = ERR_FAIL;
goto out;
}
iot_sg_sta_nw_run_state_query_handle(req->cnt, req->id, flag_broadcast);
out:
iot_pkt_free(pkt);
return ret;
}
static uint8_t iot_sg_sta_nw_feature_chg_proto_to_sg(uint8_t type)
{
uint8_t feature_type = IOT_SG_STA_TSFM_FEATURE_INVALID;
switch (type) {
case NW_APP_TSFM_FEATURE_VOLTAGE:
{
feature_type = IOT_SG_STA_TSFM_FEATURE_VOLTAGE;
break;
}
case NW_APP_TSFM_FEATURE_FREQUENCY:
{
feature_type = IOT_SG_STA_TSFM_FEATURE_FREQUENCY;
break;
}
case NW_APP_TSFM_FEATURE_PERIOD:
{
feature_type = IOT_SG_STA_TSFM_FEATURE_PERIOD;
break;
}
default:
break;
}
return feature_type;
}
static uint8_t iot_sg_sta_nw_feature_chg_sg_to_proto(uint8_t type)
{
uint8_t feature_type = NW_APP_TSFM_FEATURE_INVALID;
switch (type) {
case IOT_SG_STA_TSFM_FEATURE_VOLTAGE:
{
feature_type = NW_APP_TSFM_FEATURE_VOLTAGE;
break;
}
case IOT_SG_STA_TSFM_FEATURE_FREQUENCY:
{
feature_type = NW_APP_TSFM_FEATURE_FREQUENCY;
break;
}
case IOT_SG_STA_TSFM_FEATURE_PERIOD:
{
feature_type = NW_APP_TSFM_FEATURE_PERIOD;
break;
}
default:
break;
}
return feature_type;
}
static uint32_t iot_sg_sta_nw_tsfm_ntb_delta(uint32_t start_ntb)
{
uint32_t delta, delta1, delta2, curr_ntb;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_tsfm_collect_info_t *collect = &sta_glb->tsfm_collect_info;
curr_ntb = iot_plc_get_ntb(p_sg_glb->plc_app_h);
if (start_ntb > curr_ntb) {
delta1 = (start_ntb - curr_ntb);
delta2 = 0xffffffff - start_ntb + curr_ntb;
} else {
delta1 = (curr_ntb - start_ntb);
delta2 = 0xffffffff - curr_ntb + start_ntb;
}
delta = min(delta1, delta2);
delta = NW_APP_NTB_TO_MS(delta);
if (collect->feature_type == NW_APP_TSFM_FEATURE_PERIOD) {
delta += (collect->cnt * 20) + 50;
}
return delta;
}
static uint32_t iot_sg_sta_nw_tsfm_collect_start(uint8_t req_feature_type,
uint8_t *data, uint32_t len)
{
uint8_t feature_type;
uint32_t ret = ERR_OK, reason, delta;
nw_app_tsfm_collect_start_t *start;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_tsfm_collect_info_t *collect = &sta_glb->tsfm_collect_info;
if (len < sizeof(*start)) {
reason = 1;
ret = ERR_FAIL;
goto drop;
}
if (req_feature_type != NW_APP_TSFM_FEATURE_PERIOD
&& req_feature_type != NW_APP_TSFM_FEATURE_FREQUENCY
&& req_feature_type != NW_APP_TSFM_FEATURE_VOLTAGE) {
reason = 2;
ret = ERR_FAIL;
goto drop;
}
start = (nw_app_tsfm_collect_start_t*)data;
feature_type = iot_sg_sta_nw_feature_chg_sg_to_proto(collect->feature_type);
if ((req_feature_type == feature_type)
&& (start->seq == collect->seq)) {
reason = 3;
ret = ERR_FAIL;
goto drop;
}
if (((req_feature_type != NW_APP_TSFM_FEATURE_PERIOD)
&& (start->interval == 0)) || (start->cnt == 0)) {
reason = 4;
ret = ERR_FAIL;
goto drop;
}
iot_sg_sta_tsfm_collect_stop();
/* set collect cfg */
collect->feature_type =
iot_sg_sta_nw_feature_chg_proto_to_sg(req_feature_type);
collect->start_ntb = start->start_ntb;
collect->interval = start->interval;
collect->cnt = min(start->cnt, IOT_SG_STA_NW_TSFM_COLLECT_MAX);
collect->collected_cnt = 0;
collect->seq = start->seq;
collect->clct_type = IOT_PLC_ZC_CT_DEFAULT_EDGE;
os_mem_set(collect->phase_cnt, 0, sizeof(collect->phase_cnt));
collect->data = NULL;
delta = iot_sg_sta_nw_tsfm_ntb_delta(collect->start_ntb);
iot_sg_sta_start_tsfm_feature_collect_timer(delta);
goto out;
drop:
iot_sg_printf("%s err %lu, feature %lu\n", __FUNCTION__, reason,
req_feature_type);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_tsfm_collect_report(uint8_t *dst,
uint8_t req_feature_type)
{
uint8_t *data, i, m, *data_dst, *data_src, *bcd, feature_type;
uint32_t len = 0, ret = ERR_OK, reason, pkt_len, data_len, rsvd_len = 0;
proto_645_v_t *v;
proto_645_freq_t *freq;
iot_pkt_t *rsp_pkt;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_sg_sta_tsfm_collect_info_t *collect = &sta_glb->tsfm_collect_info;
nw_app_header_t *app_hdr, *req_app_hdr;
nw_app_data_t *app_info_hdr, *req_app_info_hdr;
nw_app_tsfm_detect_t *query_data;
nw_app_tsfm_detect_guangdong_t *query_data_gd;
nw_app_tsfm_collect_report_t *report_data;
nw_app_tsfm_collect_data_t *data_hdr;
req_app_hdr = (nw_app_header_t*)iot_pkt_data(req_pkt);
req_app_info_hdr = (nw_app_data_t *)(req_app_hdr + 1);
if (req_feature_type != NW_APP_TSFM_FEATURE_PERIOD
&& req_feature_type != NW_APP_TSFM_FEATURE_VOLTAGE
&& req_feature_type != NW_APP_TSFM_FEATURE_FREQUENCY) {
reason = 1;
ret = ERR_FAIL;
goto drop;
}
feature_type = iot_sg_sta_nw_feature_chg_sg_to_proto(collect->feature_type);
if (collect->data && collect->collected_cnt
&& (feature_type == req_feature_type)) {
switch (feature_type) {
case NW_APP_TSFM_FEATURE_VOLTAGE:
{
rsvd_len = sizeof(*data_hdr);
len = collect->phase_cnt[0] + collect->phase_cnt[1] +
collect->phase_cnt[2];
len *= sizeof(nw_app_tsfm_collect_v_t);
len += rsvd_len;
break;
}
case NW_APP_TSFM_FEATURE_FREQUENCY:
{
rsvd_len = sizeof(*data_hdr);
len = collect->phase_cnt[0] + collect->phase_cnt[1] +
collect->phase_cnt[2];
len *= sizeof(nw_app_tsfm_collect_freq_t);
len += rsvd_len;
break;
}
case NW_APP_TSFM_FEATURE_PERIOD:
{
rsvd_len = sizeof(*data_hdr);
len = iot_pkt_data_len(collect->data);
break;
}
default:
break;
}
} else {
len = 0;
}
if (req_app_info_hdr->work_id == NW_APP_WORK_CMD_TSFM) {
data_len = sizeof(*query_data) + sizeof(*report_data) +
max(rsvd_len, len);
} else {
data_len = sizeof(*query_data_gd) + sizeof(*report_data) +
max(rsvd_len, len);
}
pkt_len = data_len + sizeof(*app_hdr) + sizeof(*app_info_hdr);
rsp_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, dst, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, (uint16_t)pkt_len, IOT_PLC_LOCAL_RETRY_CNT);
data = iot_pkt_block_ptr(rsp_pkt, IOT_PKT_BLOCK_TAIL);
app_hdr = (nw_app_header_t *)data;
app_hdr->id = NW_APP_ID;
app_hdr->port = NW_APP_PORT;
app_hdr->reserved = NW_APP_CONTROL;
app_info_hdr = (nw_app_data_t*)(app_hdr + 1);
app_info_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
app_info_hdr->control_field.reserved = 0;
app_info_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
app_info_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
app_info_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
app_info_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
app_info_hdr->sn = req_app_info_hdr->sn;
app_info_hdr->ver = req_app_info_hdr->ver;
app_info_hdr->len = (uint16_t)data_len;
if (req_app_info_hdr->work_id == NW_APP_WORK_CMD_TSFM) {
app_info_hdr->work_id = NW_APP_WORK_CMD_TSFM;
query_data = (nw_app_tsfm_detect_t*)app_info_hdr->data;
query_data->header_len = sizeof(*query_data);
query_data->phase = NW_APP_DATA_PHASE_DEFAULT;
iot_mac_addr_cpy(query_data->addr, p_sg_glb->plc_state.addr);
query_data->feature_type = req_feature_type;
query_data->collect_type = NW_APP_TSFM_COLLECT_REPORT;
report_data = (nw_app_tsfm_collect_report_t*)query_data->data;
} else {
app_info_hdr->work_id = NW_APP_WORK_CMD_TSFM_GD;
query_data_gd = (nw_app_tsfm_detect_guangdong_t *)app_info_hdr->data;
query_data_gd->header_len = sizeof(*query_data_gd);
query_data_gd->phase = NW_APP_DATA_PHASE_DEFAULT;
iot_mac_addr_cpy(query_data_gd->addr, p_sg_glb->plc_state.addr);
query_data_gd->feature_type = req_feature_type;
query_data_gd->collect_type = NW_APP_TSFM_COLLECT_REPORT;
report_data = (nw_app_tsfm_collect_report_t*)query_data_gd->data;
}
report_data->tei = p_sg_glb->plc_state.dev_tei;
report_data->seq = collect->seq;
if (collect->data && collect->collected_cnt
&& (feature_type == req_feature_type)) {
data_hdr = (nw_app_tsfm_collect_data_t*)report_data->data;
switch (feature_type) {
case NW_APP_TSFM_FEATURE_VOLTAGE:
{
report_data->cnt = collect->phase_cnt[0] +
collect->phase_cnt[1] + collect->phase_cnt[2];
report_data->clct_type = 0;
data_hdr->start_ntb = collect->start_ntb_first;
data_hdr->rsvd = 0;
data_hdr->phase1_cnt = collect->phase_cnt[0];
data_hdr->phase2_cnt = collect->phase_cnt[1];
data_hdr->phase3_cnt = collect->phase_cnt[2];
data_src = iot_pkt_data(collect->data);
data_dst = (uint8_t *)data_hdr->data;
for (m = 0; m < 3; m++) {
v = (proto_645_v_t*)data_src;
for (i = 0; i < collect->collected_cnt; i++) {
if (m == 0) {
bcd = v->a;
} else if (m == 1) {
bcd = v->b;
} else {
bcd = v->c;
}
if (iot_bcd_data_check(bcd, PROTO_645_V_LEN)) {
os_mem_cpy(data_dst, bcd, PROTO_645_V_LEN);
data_dst += PROTO_645_V_LEN;
}
v++;
}
}
break;
}
case NW_APP_TSFM_FEATURE_FREQUENCY:
{
report_data->cnt = collect->phase_cnt[0] +
collect->phase_cnt[1] + collect->phase_cnt[2];
report_data->clct_type = 0;
data_hdr->start_ntb = collect->start_ntb_first;
data_hdr->rsvd = 0;
data_hdr->phase1_cnt = collect->phase_cnt[0];
data_hdr->phase2_cnt = collect->phase_cnt[1];
data_hdr->phase3_cnt = collect->phase_cnt[2];
data_src = iot_pkt_data(collect->data);
data_dst = (uint8_t *)data_hdr->data;
os_mem_cpy(data_dst, data_src,
sizeof(*freq) * collect->collected_cnt);
break;
}
case NW_APP_TSFM_FEATURE_PERIOD:
{
report_data->cnt = collect->collected_cnt;
report_data->clct_type = p_sg_glb->plc_state.collect_type;
data_src = iot_pkt_data(collect->data);
BUILD_BUG_ON(sizeof(iot_plc_zc_data_t) ==
sizeof(nw_app_tsfm_collect_data_t));
data_dst = (uint8_t *)data_hdr;
os_mem_cpy(data_dst, data_src, iot_pkt_data_len(collect->data));
break;
}
default:
break;
}
} else {
report_data->cnt = 0;
report_data->clct_type = p_sg_glb->plc_state.collect_type;
if (rsvd_len) {
os_mem_set(report_data->data, 0, rsvd_len);
}
}
iot_pkt_put(rsp_pkt, pkt_len);
iot_sg_send_msdu(rsp_pkt, sta_glb->req.link_type);
goto out;
drop:
iot_sg_printf("%s err %lu, feature %lu\n", __FUNCTION__, reason,
req_feature_type);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_tsfm_result_send(uint8_t *dst)
{
uint32_t ret = ERR_OK;
uint16_t pkt_len, data_len;
uint8_t *data;
iot_pkt_t *rsp_pkt;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_tsfm_detect_result_t *tsfm_data = NULL;
nw_app_tsfm_detect_t *query_data = NULL;
nw_app_tsfm_detect_guangdong_t *query_data_gd;
nw_app_data_t *app_info_hdr = NULL, *req_app_info_hdr;
nw_app_header_t *app_hdr = NULL, *req_app_hdr;
iot_sg_sta_tsfm_result_t tsfm_result;
req_app_hdr = (nw_app_header_t*)iot_pkt_data(sta_glb->req.pkt);
req_app_info_hdr = (nw_app_data_t *)(req_app_hdr + 1);
if (req_app_info_hdr->work_id == NW_APP_WORK_CMD_TSFM) {
data_len = sizeof(*tsfm_data) + sizeof(*query_data);
} else {
data_len = sizeof(*tsfm_data) + sizeof(*query_data_gd);
}
pkt_len = sizeof(*app_hdr) + sizeof(*app_info_hdr) + data_len;
rsp_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, dst, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, pkt_len, IOT_PLC_LOCAL_RETRY_CNT);
if (!rsp_pkt) {
ret = ERR_NOMEM;
goto out;
}
data = iot_pkt_block_ptr(rsp_pkt, IOT_PKT_BLOCK_TAIL);
app_hdr = (nw_app_header_t *)data;
app_hdr->id = NW_APP_ID;
app_hdr->port = NW_APP_PORT;
app_hdr->reserved = NW_APP_CONTROL;
app_info_hdr = (nw_app_data_t*)(app_hdr + 1);
app_info_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
app_info_hdr->control_field.reserved = 0;
app_info_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
app_info_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
app_info_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
app_info_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
app_info_hdr->sn = req_app_info_hdr->sn;
app_info_hdr->ver = req_app_info_hdr->ver;
app_info_hdr->len = data_len;
if (req_app_info_hdr->work_id == NW_APP_WORK_CMD_TSFM) {
app_info_hdr->work_id = NW_APP_WORK_CMD_TSFM;
query_data = (nw_app_tsfm_detect_t *)app_info_hdr->data;
query_data->header_len = sizeof(*query_data);
/* for cert test case 3.3.7.3, fill the phase field with 0 to avoid
* possible test failures.
*/
query_data->phase = NW_APP_DATA_PHASE_DEFAULT;
iot_mac_addr_cpy(query_data->addr, p_sg_glb->plc_state.addr);
query_data->feature_type = sta_glb->tsfm_collect_info.feature_type;
query_data->collect_type = NW_APP_TSFM_COLLECT_RESULT;
tsfm_data = (nw_app_tsfm_detect_result_t *)query_data->data;
} else {
app_info_hdr->work_id = NW_APP_WORK_CMD_TSFM_GD;
query_data_gd = (nw_app_tsfm_detect_guangdong_t *)app_info_hdr->data;
query_data_gd->header_len = sizeof(*query_data_gd);
query_data_gd->phase = NW_APP_DATA_PHASE_DEFAULT;
iot_mac_addr_cpy(query_data_gd->addr, p_sg_glb->plc_state.addr);
query_data_gd->feature_type = sta_glb->tsfm_collect_info.feature_type;
query_data_gd->collect_type = NW_APP_TSFM_COLLECT_RESULT;
tsfm_data = (nw_app_tsfm_detect_result_t *)query_data_gd->data;
}
tsfm_data->tei = p_sg_glb->plc_state.dev_tei;
iot_sg_sta_get_tsfm_result(&tsfm_result);
if (tsfm_result.hw_tsfm_done) {
tsfm_data->done = tsfm_result.hw_tsfm_done;
tsfm_data->result = tsfm_result.hw_tsfm_result;
iot_mac_addr_cpy(tsfm_data->tsfm_addr, tsfm_result.hw_tsfm_addr);
} else {
tsfm_data->done = tsfm_result.sw_tsfm_done;
tsfm_data->result = tsfm_result.sw_tsfm_result;
iot_mac_addr_cpy(tsfm_data->tsfm_addr, tsfm_result.sw_tsfm_addr);
}
iot_pkt_put(rsp_pkt, pkt_len);
iot_plc_send_msdu(p_sg_glb->plc_app_h, rsp_pkt);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_tsfm_result_send_pw(uint8_t *dst)
{
uint32_t ret = ERR_OK;
uint16_t pkt_len;
uint8_t *data;
iot_pkt_t *rsp_pkt;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_tsfm_detect_result_pw_t *tsfm_data = NULL;
nw_app_tsfm_detect_t *query_data = NULL;
nw_app_data_t *app_info_hdr = NULL, *req_app_info_hdr;
nw_app_header_t *app_hdr = NULL, *req_app_hdr;
iot_sg_sta_tsfm_result_t tsfm_result;
req_app_hdr = (nw_app_header_t*)iot_pkt_data(sta_glb->req.pkt);
req_app_info_hdr = (nw_app_data_t *)(req_app_hdr + 1);
pkt_len = sizeof(*tsfm_data) + sizeof(*app_hdr) + sizeof(*query_data)
+ sizeof(*app_info_hdr);
rsp_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, dst, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, pkt_len, IOT_PLC_LOCAL_RETRY_CNT);
if (!rsp_pkt) {
ret = ERR_NOMEM;
goto out;
}
data = iot_pkt_block_ptr(rsp_pkt, IOT_PKT_BLOCK_TAIL);
app_hdr = (nw_app_header_t *)data;
app_hdr->id = NW_APP_ID;
app_hdr->port = NW_APP_PORT;
app_hdr->reserved = NW_APP_CONTROL;
app_info_hdr = (nw_app_data_t*)(app_hdr + 1);
app_info_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
app_info_hdr->control_field.reserved = 0;
app_info_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
app_info_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
app_info_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
app_info_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
app_info_hdr->work_id = NW_APP_WORK_CMD_TSFM;
app_info_hdr->sn = req_app_info_hdr->sn;
app_info_hdr->ver = req_app_info_hdr->ver;
app_info_hdr->len = sizeof(*query_data) + sizeof(*tsfm_data);
query_data = (nw_app_tsfm_detect_t *)app_info_hdr->data;
query_data->header_len = sizeof(*query_data);
/* for cert test case 3.3.7.3, fill the phase field with 0 to avoid
* possible test failures.
*/
query_data->phase = NW_APP_DATA_PHASE_DEFAULT;
iot_mac_addr_cpy(query_data->addr, p_sg_glb->plc_state.addr);
query_data->feature_type = sta_glb->tsfm_collect_info.feature_type;
query_data->collect_type = NW_APP_TSFM_COLLECT_RESULT_PW;
tsfm_data = (nw_app_tsfm_detect_result_pw_t *)query_data->data;
tsfm_data->tei = p_sg_glb->plc_state.dev_tei;
iot_sg_sta_get_tsfm_result(&tsfm_result);
if (tsfm_result.hw_tsfm_done) {
tsfm_data->done = tsfm_result.hw_tsfm_done;
tsfm_data->result = tsfm_result.hw_tsfm_result;
} else {
tsfm_data->done = tsfm_result.sw_tsfm_done;
tsfm_data->result = tsfm_result.sw_tsfm_result;
}
iot_mac_addr_cpy(tsfm_data->tsfm_addr, tsfm_result.sw_tsfm_addr);
iot_mac_addr_cpy(tsfm_data->hw_tsfm_addr, tsfm_result.hw_tsfm_addr);
iot_pkt_put(rsp_pkt, pkt_len);
iot_plc_send_msdu(p_sg_glb->plc_app_h, rsp_pkt);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_tsfm_detect_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint8_t addr[IOT_MAC_ADDR_LEN], *data;
uint8_t phase, collect_type, feature_type;
uint32_t ret = ERR_OK, reason = 0, data_len;
iot_plc_msdu_recv_t *msdu;
nw_app_tsfm_detect_guangdong_t *req_gd =
(nw_app_tsfm_detect_guangdong_t *)data_hdr->data;
nw_app_tsfm_detect_t *req = (nw_app_tsfm_detect_t *)data_hdr->data;
if (data_hdr->work_id == NW_APP_WORK_CMD_TSFM) {
/* check length */
if (sizeof(*req) > data_hdr->len) {
reason = 1;
ret = ERR_INVAL;
goto out;
}
data_len = data_hdr->len - sizeof(*req);
feature_type = req->feature_type;
collect_type = req->collect_type;
phase = req->phase;
data = req->data;
iot_mac_addr_cpy(addr, req->addr);
} else {
/* check length */
if (sizeof(*req_gd) > data_hdr->len) {
reason = 2;
ret = ERR_INVAL;
goto out;
}
data_len = data_hdr->len - sizeof(*req_gd);
feature_type = req_gd->feature_type;
collect_type = req_gd->collect_type;
phase = (uint8_t)req_gd->phase;
data = req_gd->data;
iot_mac_addr_cpy(addr, req_gd->addr);
}
msdu = (iot_plc_msdu_recv_t *)(iot_pkt_data(pkt) - sizeof(*msdu));
iot_sg_printf("%s msg_type %lu fr %lu addr %02x%02x%02x%02x%02x%02x phase "
"%lu\n", __FUNCTION__, collect_type, feature_type, addr[0], addr[1],
addr[2], addr[3], addr[4], addr[5], phase);
switch (collect_type) {
case NW_APP_TSFM_COLLECT_START:
{
ret = iot_sg_sta_nw_tsfm_collect_start(feature_type, data, data_len);
if (ret) {
reason = 6;
}
break;
}
case NW_APP_TSFM_COLLECT_COLLECT:
{
if (iot_mac_is_bcast(msdu->dst)) {
if ((!iot_mac_is_bcast(addr)) &&
(!iot_mac_addr_cmp(addr, p_sg_glb->plc_state.addr))) {
ret = ERR_FAIL;
reason = 7;
goto out;
}
}
ret = iot_sg_sta_nw_tsfm_collect_report(msdu->src, feature_type);
if (ret) {
reason = 8;
}
break;
}
case NW_APP_TSFM_COLLECT_QUERY:
{
if (iot_mac_is_bcast(msdu->dst)) {
if ((!iot_mac_is_bcast(addr)) &&
(!iot_mac_addr_cmp(addr, p_sg_glb->plc_state.addr))) {
ret = ERR_FAIL;
reason = 9;
goto out;
}
}
/* for unicast messages, not checking addr */
ret = iot_sg_sta_nw_tsfm_result_send(msdu->src);
if (ret) {
reason = 10;
}
break;
}
case NW_APP_TSFM_COLLECT_QUERY_PW:
{
if (iot_mac_is_bcast(msdu->dst)) {
if ((!iot_mac_is_bcast(addr)) &&
(!iot_mac_addr_cmp(addr, p_sg_glb->plc_state.addr))) {
ret = ERR_FAIL;
reason = 11;
goto out;
}
}
/* for unicast messages, not checking addr */
ret = iot_sg_sta_nw_tsfm_result_send_pw(msdu->src);
if (ret) {
reason = 12;
}
break;
}
case NW_APP_TSFM_COLLECT_REPORT:
break;
default:
ret = ERR_NOSUPP;
reason = 13;
break;
}
out:
if (ret) {
iot_sg_printf("tsfm detect drop %lu\n", reason);
}
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_sec_node_net_send(void)
{
int64_t delta_time = 0;
uint64_t cur_ts;
uint32_t ret = ERR_OK;
uint16_t total_size;
uint8_t *req, *rsp;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
iot_time_tm_t time;
nw_app_cmd_net_info_t *net_info;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data) + sizeof(*net_info);
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (!plc_pkt) {
ret = ERR_NOMEM;
goto out;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_SEC_NODE_NET_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = sizeof(*net_info);
net_info = (nw_app_cmd_net_info_t *)rsp_data->data;
iot_mac_addr_cpy(net_info->major_node_mac, p_sg_glb->plc_state.cco_addr);
iot_mac_addr_reverse(net_info->major_node_mac);
iot_mac_addr_cpy(net_info->meter_mac, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(net_info->meter_mac);
net_info->comm_mode = NW_APP_COMM_MOD_CARRIER;
if (iot_sg_sta_rtc_get(&time, 0) == ERR_OK) {
cur_ts = os_boot_time64();
delta_time -= (int64_t)((cur_ts - sta_glb->joined_ts) / 1000);
iot_rtc_delta_add(delta_time, &time);
net_info->join_year = iot_byte_to_bcd(time.tm_year % 100);
net_info->join_mon = iot_byte_to_bcd(time.tm_mon);
net_info->join_day = iot_byte_to_bcd(time.tm_mday);
net_info->join_hour = iot_byte_to_bcd(time.tm_hour);
net_info->join_min = iot_byte_to_bcd(time.tm_min);
net_info->join_sec = iot_byte_to_bcd(time.tm_sec);
} else {
net_info->join_year = 0xFF;
net_info->join_mon = 0xFF;
net_info->join_day = 0xFF;
net_info->join_hour = 0xFF;
net_info->join_min = 0xFF;
net_info->join_sec = 0xFF;
}
net_info->in_net = p_sg_glb->dev_is_ready;
net_info->cost_time = (uint32_t)(sta_glb->joined_ts / 1000);
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_sec_node_net_query(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
uint8_t node_mac[IOT_MAC_ADDR_LEN];
if (data_hdr->len < sizeof(node_mac)) {
ret = ERR_INVAL;
goto out;
}
iot_mac_addr_cpy(node_mac, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(node_mac);
if (!iot_mac_addr_cmp(node_mac, data_hdr->data)) {
ret = ERR_INVAL;
goto out;
}
iot_sg_sta_nw_sec_node_net_send();
out:
iot_pkt_free(pkt);
return ret;
}
/**
* @brief: unicast to local broadcast.
* @param pkt: the iot_pkt with application protocol data in it.
* the pkt is not consumed.
*/
static void iot_sg_sta_nw_upgrade_local_bcast(iot_pkt_t *pkt)
{
uint8_t *data_ptr = NULL;
nw_app_header_t *app_hdr = NULL;
nw_app_data_t *app_data = NULL;
iot_pkt_t *msdu_pkt = NULL;
nw_app_cmd_file_t *file_trans = NULL;
nw_app_cmd_file_data_dl_t *recv_data = NULL;
uint16_t pkt_len = sizeof(*app_hdr) + sizeof(*app_data) +
sizeof(*file_trans) + sizeof(*recv_data);
uint8_t result = 0;
if ((uint16_t)iot_pkt_block_len(pkt, IOT_PKT_BLOCK_DATA) < pkt_len) {
result = 1;
goto out;
}
app_hdr = (nw_app_header_t*)iot_pkt_data(pkt);
app_data = (nw_app_data_t*)(app_hdr + 1);
/* nw app upgrade packet header */
file_trans = (nw_app_cmd_file_t*)(app_data + 1);
if ((!app_hdr) || (!app_data) || (!file_trans)) {
result = 2;
goto out;
}
file_trans->id = (uint8_t)NW_APP_CMD_FILE_DATA;
recv_data = (nw_app_cmd_file_data_dl_t *)file_trans->data;
pkt_len += recv_data->data_len;
if (iot_pkt_block_len(pkt, IOT_PKT_BLOCK_DATA) != pkt_len) {
result = 3;
goto out;
}
msdu_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_BCAST_1HOP, IOT_PLC_ACK_TYPE_NONE,
p_sg_glb->plc_state.cco_addr, p_sg_glb->plc_state.addr,
NW_APP_PRIO_FILE_TRANS, pkt_len, 0);
if (!msdu_pkt) {
result = 4;
goto out;
}
data_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
os_mem_cpy(data_ptr, iot_pkt_data(pkt), pkt_len);
iot_pkt_put(msdu_pkt, pkt_len);
/* send out the command */
iot_plc_send_msdu(p_sg_glb->plc_app_h, msdu_pkt);
iot_sg_printf("sg_upgrade: send local bcast.\n");
return;
out:
iot_sg_printf("sg_upgrade: local bcast data error %d.\n", result);
}
static uint8_t iot_sg_sta_nw_clct_task_pm_type_to_nw(uint8_t pm_type)
{
uint8_t type = NW_APP_CLCT_TASK_PM_TYPE_SINGE;
switch (pm_type) {
case IOT_SG_EXT_CLCT_TASK_PM_TYPE_3P:
{
type = NW_APP_CLCT_TASK_PM_TYPE_3P;
break;
}
case IOT_SG_EXT_CLCT_TASK_PM_TYPE_INVALID:
{
type = NW_APP_CLCT_TASK_PM_TYPE_INVALID;
break;
}
case IOT_SG_EXT_CLCT_TASK_PM_TYPE_SINGE:
default:
break;
}
return type;
}
static uint8_t iot_sg_sta_nw_clct_task_proto_type_to_nw(uint8_t proto_type)
{
uint8_t type = NW_APP_CLCT_TASK_PROTO_TYPE_645_07;
switch (proto_type) {
case IOT_SG_EXT_CLCT_TASK_PROTO_TYPE_645_97:
{
type = NW_APP_CLCT_TASK_PROTO_TYPE_645_97;
break;
}
case IOT_SG_EXT_CLCT_TASK_PROTO_TYPE_UNKNOWN:
{
type = NW_APP_CLCT_TASK_PROTO_TYPE_UNKNOWN;
break;
}
case IOT_SG_EXT_CLCT_TASK_PROTO_TYPE_645_07:
default:
break;
}
return type;
}
static uint8_t iot_sg_sta_nw_clct_task_period_to_nw(uint8_t clct_period)
{
uint8_t period = NW_APP_CLCT_TASK_PERIOD_DEFAULT;
switch (clct_period) {
case IOT_SG_EXT_CLCT_TASK_PERIOD_15MIN:
{
period = NW_APP_CLCT_TASK_PERIOD_15MIN;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_30MIN:
{
period = NW_APP_CLCT_TASK_PERIOD_30MIN;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_60MIN:
{
period = NW_APP_CLCT_TASK_PERIOD_60MIN;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_DAY:
{
period = NW_APP_CLCT_TASK_PERIOD_DAY;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_15MIN_LR:
{
period = NW_APP_CLCT_TASK_PERIOD_15MIN_LR;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_30MIN_LR:
{
period = NW_APP_CLCT_TASK_PERIOD_30MIN_LR;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_60MIN_LR:
{
period = NW_APP_CLCT_TASK_PERIOD_60MIN_LR;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_SINGLE:
{
period = NW_APP_CLCT_TASK_PERIOD_SINGLE;
break;
}
case IOT_SG_EXT_CLCT_TASK_PERIOD_DEFAULT:
default:
break;
}
return period;
}
static uint8_t iot_sg_sta_nw_clct_task_pm_type_to_local(uint8_t pm_type)
{
uint8_t type = IOT_SG_EXT_CLCT_TASK_PM_TYPE_SINGE;
switch (pm_type) {
case NW_APP_CLCT_TASK_PM_TYPE_3P:
{
type = IOT_SG_EXT_CLCT_TASK_PM_TYPE_3P;
break;
}
case NW_APP_CLCT_TASK_PM_TYPE_INVALID:
{
type = IOT_SG_EXT_CLCT_TASK_PM_TYPE_INVALID;
break;
}
case NW_APP_CLCT_TASK_PM_TYPE_SINGE:
default:
break;
}
return type;
}
static uint8_t iot_sg_sta_nw_clct_task_proto_type_to_local(uint8_t proto_type)
{
uint8_t type = IOT_SG_EXT_CLCT_TASK_PROTO_TYPE_645_07;
switch (proto_type) {
case NW_APP_CLCT_TASK_PROTO_TYPE_645_97:
{
type = IOT_SG_EXT_CLCT_TASK_PROTO_TYPE_645_97;
break;
}
case NW_APP_CLCT_TASK_PROTO_TYPE_UNKNOWN:
{
type = IOT_SG_EXT_CLCT_TASK_PROTO_TYPE_UNKNOWN;
break;
}
case NW_APP_CLCT_TASK_PROTO_TYPE_645_07:
default:
break;
}
return type;
}
static uint8_t iot_sg_sta_nw_clct_task_period_to_local(uint8_t clct_period)
{
uint8_t period = IOT_SG_EXT_CLCT_TASK_PERIOD_DEFAULT;
switch (clct_period) {
case NW_APP_CLCT_TASK_PERIOD_15MIN:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_15MIN;
break;
}
case NW_APP_CLCT_TASK_PERIOD_30MIN:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_30MIN;
break;
}
case NW_APP_CLCT_TASK_PERIOD_60MIN:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_60MIN;
break;
}
case NW_APP_CLCT_TASK_PERIOD_DAY:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_DAY;
break;
}
case NW_APP_CLCT_TASK_PERIOD_15MIN_LR:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_15MIN_LR;
break;
}
case NW_APP_CLCT_TASK_PERIOD_30MIN_LR:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_30MIN_LR;
break;
}
case NW_APP_CLCT_TASK_PERIOD_60MIN_LR:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_60MIN_LR;
break;
}
case NW_APP_CLCT_TASK_PERIOD_SINGLE:
{
period = IOT_SG_EXT_CLCT_TASK_PERIOD_SINGLE;
break;
}
case NW_APP_CLCT_TASK_PERIOD_DEFAULT:
default:
break;
}
return period;
}
static uint32_t iot_sg_sta_nw_clct_init(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
(void)data_hdr;
uint8_t *req;
iot_plc_msdu_recv_t *msdu;
req = iot_pkt_data(pkt);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
if (!iot_mac_is_bcast(msdu->dst)) {
iot_sg_sta_nw_send_ack();
}
iot_pkt_free(pkt);
return ERR_OK;
}
static uint32_t iot_sg_sta_nw_correct_time(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason;
iot_time_tm_t cctt_tm, curr_tm;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_clct_task_correct_time_req_t *req;
req = (nw_app_clct_task_correct_time_req_t *)data_hdr->data;
/* check correct time count */
if (sta_glb->correct_time_cnt >= IOT_SG_STA_CORRECT_TIME_CNT_MAX) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
if (data_hdr->len < sizeof(*req)) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
if (!iot_mac_addr_cmp(req->major_mac, p_sg_glb->plc_state.cco_addr)) {
reason = 3;
ret = ERR_INVAL;
goto drop;
}
if (iot_sg_sta_rtc_get(&curr_tm, 0)) {
reason = 4;
ret = ERR_INVAL;
goto drop;
}
/* calc the delta between correct time and rtc */
cctt_tm.tm_year = iot_bcd_to_byte(req->year) + 2000;
cctt_tm.tm_mon = iot_bcd_to_byte(req->month);
cctt_tm.tm_mday = iot_bcd_to_byte(req->day);
cctt_tm.tm_hour = iot_bcd_to_byte(req->hour);
cctt_tm.tm_min = iot_bcd_to_byte(req->minute);
cctt_tm.tm_sec = iot_bcd_to_byte(req->second);
iot_sg_sta_rtc_set(&cctt_tm, 1);
iot_sg_sta_start_get_time();
(sta_glb->correct_time_cnt)++;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_meter_state_score_query_handle(void)
{
uint8_t idx, reason, cnt = 0, meter_cnt = 0;
uint16_t data_len = 0;
uint32_t ret = ERR_OK, dev_type;
uint64_t cur_ts, delta_ts;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_drv_meter_ss_data_t ss_data;
iot_sg_sta_score_info_t *score_info;
iot_sg_sta_node_desc_t *node;
iot_pkt_t *pkt = NULL;
if (sta_glb->ext_info.score_info.enable) {
/* meter is scoring, only after score can respond. */
reason = 1;
ret = ERR_BUSY;
goto drop;
}
cur_ts = os_boot_time64() / 1000;
delta_ts = cur_ts - sta_glb->ext_info.score_info.score_en_ts;
if (delta_ts > IOT_SG_STA_SCORE_EN_VALID_TIME) {
/* enable score time too long,
* score data invalid need again enable state score.
*/
sta_glb->ext_info.score_info.enable = 1;
reason = 2;
ret = ERR_TIMEOVER;
goto drop;
}
dev_type = sta_glb->drv->get_device_type();
if (dev_type == IOT_SG_STA_DEV_TYPE_POWER_METER) {
meter_cnt++;
} else {
for (idx = 0; idx < IOT_SG_STA_SEC_NODE_MAX; idx++) {
if (sta_glb->node_list[idx]) {
meter_cnt++;
}
}
}
data_len = meter_cnt * sizeof(iot_sg_sta_pm_score_info_t) +
sizeof(*score_info);
pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 3;
ret = ERR_NOMEM;
goto drop;
}
score_info = (iot_sg_sta_score_info_t *)iot_pkt_put(pkt, data_len);
score_info->meter_cnt = meter_cnt;
for (idx = 0; idx < IOT_SG_STA_SEC_NODE_MAX; idx++) {
if (!sta_glb->node_list[idx]) {
continue;
}
if (cnt >= meter_cnt) {
break;
}
node = sta_glb->node_list[idx];
iot_mac_addr_cpy(score_info->pm_info[cnt].pm_mac, node->entry.addr);
ret = iot_sg_sta_flash_score_data_read(node->entry.addr,
(uint8_t *)&ss_data, sizeof(ss_data),
IOT_SG_STA_METER_DATA_TYPE_GUANGZHOU_SS);
if (ret == ERR_OK) {
score_info->pm_info[cnt].score = ss_data.score;
os_mem_cpy(&score_info->pm_info[cnt].err_bm, &ss_data.bit_map,
sizeof(ss_data.bit_map));
} else {
score_info->pm_info[cnt].score = 100;
score_info->pm_info[cnt].err_bm = 0;
}
cnt++;
}
if (sta_glb->proto == IOT_SG_STA_APP_PROTO_GW) {
/* reserve for gw proto */
ret = ERR_NOSUPP;
} else {
ret = iot_sg_sta_nw_score_query_resp(score_info);
}
if (ret != ERR_OK) {
reason = 4;
goto drop;
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_nw_meter_state_score_report(uint8_t new_evt, uint8_t meter_cnt)
{
uint8_t idx, fault_cnt = 0, pm_addr[IOT_MAC_ADDR_LEN];
uint16_t data_len = 0;
uint32_t ret = ERR_OK;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_drv_meter_ss_data_t ss_data;
iot_sg_sta_score_info_t *score_info = NULL;
iot_sg_sta_evt_global_t *evt = &sta_glb->evt;
iot_sg_sta_drv_t *drv = sta_glb->drv;
iot_sg_sta_node_desc_t *node;
iot_pkt_t *cache_pkt = NULL;
if (evt->retry_cnt >= 3) {
iot_sg_printf("%s retry max\n", __FUNCTION__);
iot_sg_module_report_reset_status(0);
ret = ERR_TIMEOVER;
goto out;
}
if (!meter_cnt) {
ret = ERR_INVAL;
goto out;
}
data_len = meter_cnt * sizeof(iot_sg_sta_pm_score_info_t) +
sizeof(*score_info);
cache_pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
if (!cache_pkt) {
ret = ERR_NOMEM;
goto out;
}
score_info = (iot_sg_sta_score_info_t *)iot_pkt_put(cache_pkt, data_len);
for (idx = 0; idx < IOT_SG_STA_SEC_NODE_MAX; idx++) {
if (!sta_glb->node_list[idx]) {
continue;
}
if (fault_cnt >= meter_cnt) {
break;
}
node = sta_glb->node_list[idx];
ret = iot_sg_sta_flash_score_data_read(node->entry.addr,
(uint8_t *)&ss_data, sizeof(ss_data),
IOT_SG_STA_METER_DATA_TYPE_GUANGZHOU_SS);
if (ret == ERR_OK && ss_data.score < IOT_SG_EXT_STATE_WEIGHT_SCORE_60) {
score_info->pm_info[fault_cnt].score = ss_data.score;
os_mem_cpy(&score_info->pm_info[fault_cnt].err_bm, &ss_data.bit_map,
sizeof(ss_data.bit_map));
iot_mac_addr_cpy(score_info->pm_info[fault_cnt].pm_mac,
node->entry.addr);
fault_cnt++;
}
}
if (!fault_cnt) {
ret = ERR_INVAL;
goto out;
}
score_info->meter_cnt = fault_cnt;
drv->get_login_addr(pm_addr);
ret = iot_sg_sta_report_event_with_type(pm_addr, (uint8_t *)score_info,
data_len, new_evt, IOT_SG_STA_RPT_MODULE_SCORE_EVT);
if (ret == ERR_OK) {
drv->disable_event_rpt();
evt->retry_cnt++;
evt->score_rpt_cnt = meter_cnt;
}
out:
if (cache_pkt) {
iot_pkt_free(cache_pkt);
}
return ret;
}
void iot_sg_sta_nw_score_event_func_handle(uint8_t fn)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
switch (fn) {
case IOT_SG_STA_EVENT_RPT_OK:
case IOT_SG_STA_EVENT_RPT_DISABLED:
{
sta_glb->evt.score_rpt_cnt = 0;
iot_sg_module_report_reset_status(0);
break;
}
case IOT_SG_STA_EVENT_RPT_BUF_FULL:
case IOT_SG_STA_EVENT_RPT_TIMEOUT:
{
iot_sg_module_report_reset_status(1);
iot_sg_sta_nw_meter_state_score_report(0, sta_glb->evt.score_rpt_cnt);
break;
}
default:
IOT_ASSERT(0);
}
}
uint32_t iot_sg_sta_nw_score_query_resp(iot_sg_sta_score_info_t *score_info)
{
uint32_t ret = ERR_OK;
uint16_t total_size, payload_size = 0;
uint8_t *req, *rsp, tmp_size, cnt;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
nw_app_pm_score_info_t *score_data;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
tmp_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
payload_size = score_info->meter_cnt * sizeof(nw_app_pm_score_info_t);
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (!plc_pkt) {
ret = ERR_NOMEM;
goto out;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_PM_SCORE_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
score_data = (nw_app_pm_score_info_t *)rsp_data->data;
for (cnt = 0; cnt < score_info->meter_cnt; cnt++) {
score_data[cnt].score = score_info->pm_info[cnt].score;
score_data[cnt].err_bm = score_info->pm_info[cnt].err_bm;
iot_mac_addr_cpy(score_data[cnt].pm_mac,
score_info->pm_info[cnt].pm_mac);
}
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_pm_score_query(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason = 0;
uint8_t pm_addr[IOT_MAC_ADDR_LEN];
nw_app_query_score_dl_t *score_dl = NULL;
if (data_hdr->len < sizeof(score_dl)) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
score_dl = (nw_app_query_score_dl_t *)data_hdr->data;
iot_mac_addr_cpy(pm_addr, score_dl->meter_mac);
iot_mac_addr_reverse(pm_addr);
if (!iot_mac_addr_cmp(pm_addr, p_sg_glb->plc_state.addr)) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
ret = iot_sg_sta_nw_meter_state_score_query_handle();
if (ret != ERR_OK) {
reason = 3;
goto drop;
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_task_tm_handle(nw_app_clct_task_time_t *task_tm)
{
uint32_t ret = ERR_OK, reason;
int64_t delta = 0;
uint8_t corr_flag = 0;
iot_time_tm_t curr_tm, cctt_tm;
if (!iot_bcd_data_check((uint8_t *)task_tm,
sizeof(nw_app_clct_task_time_t))) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
cctt_tm.tm_year = iot_bcd_to_byte(task_tm->year) + 2000;
cctt_tm.tm_mon = iot_bcd_to_byte(task_tm->month);
cctt_tm.tm_mday = iot_bcd_to_byte(task_tm->day);
cctt_tm.tm_hour = iot_bcd_to_byte(task_tm->hour);
cctt_tm.tm_min = iot_bcd_to_byte(task_tm->min);
cctt_tm.tm_sec = iot_bcd_to_byte(task_tm->sec);
if (iot_sg_sta_rtc_get(&curr_tm, 1) != ERR_OK) {
corr_flag = 1;
} else {
delta = iot_rtc_delta_calc(&curr_tm, &cctt_tm);
if (IOT_ABS(delta) > IOT_SG_STA_TM_DELTA_MAX_CLCT_TASK) {
corr_flag = 1;
} else {
corr_flag = 0;
}
}
if (corr_flag) {
iot_sg_sta_rtc_set(&cctt_tm, 1);
iot_sg_sta_start_get_time();
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_clct_add_resp(uint8_t result)
{
uint32_t ret = ERR_OK;
uint16_t total_size, payload_size = 0;
uint8_t *req, *rsp, tmp_size;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_clct_task_add_resp_t *rsp_info;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
tmp_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
payload_size = sizeof(nw_app_clct_task_add_resp_t);
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_CLCT_ADD;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
rsp_info = (nw_app_clct_task_add_resp_t *)rsp_data->data;
rsp_info->result = result;
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s pkt err\n", __FUNCTION__);
}
return ret;
}
static uint32_t iot_sg_sta_nw_clct_add(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason, data_len;
uint8_t result = NW_APP_CLCT_TASK_ADD_OK;
uint8_t meter_type, di_len, i;
uint16_t receive_crc;
nw_app_clct_task_add_req_t *req;
nw_app_clct_task_info_t *task_info = NULL;
iot_sg_sta_ext_clct_task_cfg_t task_cfg;
iot_sg_sta_node_desc_t *node;
nw_app_clct_task_time_t *task_tm;
nw_app_clct_task_id_97_t *task_id_97 = NULL;
nw_app_clct_task_id_07_t *task_id_07 = NULL;
req = (nw_app_clct_task_add_req_t *)data_hdr->data;
if (data_hdr->len < sizeof(*req)) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
if (!iot_mac_addr_cmp(req->cco_addr, p_sg_glb->plc_state.cco_addr)) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
task_info = (nw_app_clct_task_info_t *)(&req->task_info);
if (task_info->di_cnt > NW_APP_CLCT_TASK_DI_MAX) {
reason = 3;
ret = ERR_INVAL;
goto drop;
}
if (task_info->fn.proto_type == NW_APP_CLCT_TASK_PROTO_TYPE_645_97) {
di_len = sizeof(nw_app_clct_task_id_97_t);
task_id_97 = (nw_app_clct_task_id_97_t *)task_info->data;
} else if (task_info->fn.proto_type == NW_APP_CLCT_TASK_PROTO_TYPE_645_07) {
di_len = sizeof(nw_app_clct_task_id_07_t);
task_id_07 = (nw_app_clct_task_id_07_t *)task_info->data;
} else {
reason = 4;
result = NW_APP_CLCT_TASK_ADD_ERR_PROTO;
ret = ERR_INVAL;
goto rsp;
}
node = iot_sg_sta_node_find_by_addr(req->pm_addr);
if (node == NULL) {
reason = 5;
ret = ERR_INVAL;
goto drop;
}
if (node->is_three_phase) {
meter_type = NW_APP_CLCT_TASK_PM_TYPE_3P;
} else {
meter_type = NW_APP_CLCT_TASK_PM_TYPE_SINGE;
}
if (task_info->fn.meter_type != meter_type) {
reason = 6;
result = NW_APP_CLCT_TASK_ADD_ERR_PM;
ret = ERR_INVAL;
goto rsp;
}
if (task_info->fn.proto_type != node->data_type) {
reason = 7;
result = NW_APP_CLCT_TASK_ADD_ERR_PROTO;
ret = ERR_INVAL;
goto rsp;
}
os_mem_cpy(&receive_crc, &task_info->data[task_info->di_cnt * di_len],
sizeof(uint16_t));
data_len = sizeof(*task_info) + task_info->di_cnt * di_len -
sizeof(task_info->task_id);
if (iot_getcrc16((uint8_t *)&task_info->fn, data_len, IOT_CRC16_TYPE_XMODEM)
!= receive_crc) {
reason = 8;
result = NW_APP_CLCT_TASK_ADD_ERR_CRC;
ret = ERR_INVAL;
goto rsp;
}
/* fill protocol data */
task_cfg.proto_type =
iot_sg_sta_nw_clct_task_proto_type_to_local(
(uint8_t)task_info->fn.proto_type);
task_cfg.meter_type =
iot_sg_sta_nw_clct_task_pm_type_to_local(
(uint8_t)task_info->fn.meter_type);
task_cfg.period =
iot_sg_sta_nw_clct_task_period_to_local(task_info->period);
task_cfg.di_cnt = task_info->di_cnt;
task_cfg.timeout = task_info->timeout;
task_cfg.base_min = task_info->base_time.base_min;
task_cfg.base_hour = task_info->base_time.base_hour;
task_cfg.base_day = task_info->base_time.base_day;
for (i = 0; i < task_cfg.di_cnt; i++) {
if (task_info->fn.proto_type == NW_APP_CLCT_TASK_PROTO_TYPE_645_07) {
task_cfg.id_info[i].control_code = task_id_07[i].control_code;
task_cfg.id_info[i].len_data = task_id_07[i].len_data;
task_cfg.id_info[i].di =
proto_645_2007_byte_to_di((uint8_t *)&task_id_07[i].di);
} else {
task_cfg.id_info[i].control_code = task_id_97[i].control_code;
task_cfg.id_info[i].len_data = task_id_97[i].len_data;
task_cfg.id_info[i].di =
(uint32_t)proto_645_1997_byte_to_di(
(uint8_t *)&task_id_97[i].di);
}
}
task_cfg.crc = receive_crc;
if (iot_sg_sta_ext_clct_task_add(req->pm_addr, p_sg_glb->plc_state.cco_addr,
task_info->task_id, &task_cfg) != ERR_OK) {
reason = 9;
ret = ERR_INVAL;
goto drop;
}
/* current task time handle */
task_tm = &req->tm;
iot_sg_sta_nw_task_tm_handle(task_tm);
goto out;
rsp:
iot_sg_sta_nw_clct_add_resp(result);
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (ret == ERR_OK) {
iot_sg_sta_nw_clct_add_resp(result);
}
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_clct_del_resp(uint8_t result)
{
uint32_t ret = ERR_OK;
uint16_t total_size, payload_size = 0;
uint8_t *req, *rsp, tmp_size;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_clct_task_del_resp_t *rsp_info;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
tmp_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
payload_size = sizeof(nw_app_clct_task_del_resp_t);
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_CLCT_DEL;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
rsp_info = (nw_app_clct_task_del_resp_t *)rsp_data->data;
rsp_info->result = result;
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s pkt err\n", __FUNCTION__);
}
return ret;
}
static uint32_t iot_sg_sta_nw_clct_del(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason;
uint8_t i, id_valid = 0;
nw_app_clct_task_del_req_t *req;
iot_sg_sta_ext_clct_task_id_t task_info;
iot_sg_sta_node_desc_t *node;
req = (nw_app_clct_task_del_req_t *)data_hdr->data;
if (data_hdr->len < sizeof(*req)) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
node = iot_sg_sta_node_find_by_addr(req->pm_addr);
if (node == NULL) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
if (iot_sg_sta_ext_clct_get_task_info(req->pm_addr, &task_info) != ERR_OK) {
reason = 3;
ret = ERR_INVAL;
goto drop;
}
for (i = 0; i < task_info.cnt; i++) {
if (task_info.task_id[i] == req->task_id) {
id_valid = 1;
break;
}
}
if (!id_valid) {
reason = 4;
ret = ERR_INVAL;
iot_sg_sta_nw_clct_del_resp(NW_APP_CLCT_TASK_DEL_ERR_NOTASK);
goto drop;
}
if (iot_sg_sta_ext_clct_task_del(req->pm_addr, req->task_id) != ERR_OK) {
reason = 5;
ret = ERR_INVAL;
goto drop;
}
iot_sg_sta_nw_clct_del_resp(NW_APP_CLCT_TASK_DEL_OK);
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_clct_id_query(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason;
nw_app_clct_task_id_query_req_t *req;
iot_sg_sta_ext_clct_task_id_t task_info;
iot_sg_sta_node_desc_t *node;
uint16_t total_size, payload_size = 0;
uint8_t *rsp, tmp_size;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_clct_task_id_query_resp_t *rsp_info;
nw_app_header_t *rsp_hdr;
nw_app_data_t *rsp_data;
req = (nw_app_clct_task_id_query_req_t *)data_hdr->data;
if (data_hdr->len < sizeof(*req)) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
node = iot_sg_sta_node_find_by_addr(req->pm_addr);
if (node == NULL) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
if (iot_sg_sta_ext_clct_get_task_info(req->pm_addr, &task_info) != ERR_OK) {
reason = 3;
ret = ERR_INVAL;
goto drop;
}
/* collect id query resp */
msdu = (iot_plc_msdu_recv_t *)((uint8_t *)data_hdr -
sizeof(nw_app_header_t) - sizeof(iot_plc_msdu_recv_t));
tmp_size = sizeof(nw_app_header_t) + sizeof(nw_app_data_t);
payload_size = sizeof(nw_app_clct_task_id_query_resp_t) +
task_info.cnt * sizeof(task_info.task_id[0]);
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (!plc_pkt) {
reason = 4;
ret = ERR_INVAL;
goto drop;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_CLCT_ID_QUERY;
rsp_data->sn = data_hdr->sn;
rsp_data->ver = data_hdr->ver;
rsp_data->len = payload_size;
rsp_info = (nw_app_clct_task_id_query_resp_t *)rsp_data->data;
iot_mac_addr_cpy(rsp_info->pm_addr, req->pm_addr);
rsp_info->max_cnt = task_info.max_cnt;
rsp_info->task_cnt = task_info.cnt;
os_mem_cpy(rsp_info->task_id, task_info.task_id,
task_info.cnt * sizeof(task_info.task_id[0]));
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_clct_info_query_resp(uint8_t di_len,
uint8_t valid_flag, void *result)
{
uint32_t ret = ERR_OK;
uint16_t total_size, payload_size = 0;
uint8_t *req, *rsp, tmp_size;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_clct_task_id_info_query_nor_resp_t *rsp_info_nor = NULL;
nw_app_clct_task_id_info_query_abn_resp_t *rsp_info_abn = NULL;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
tmp_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
if (valid_flag == NW_APP_CLCT_TASK_DATA_VALID) {
payload_size = sizeof(nw_app_clct_task_id_info_query_nor_resp_t) +
di_len + sizeof(uint16_t);
} else {
payload_size = sizeof(nw_app_clct_task_id_info_query_abn_resp_t);
}
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_QUERY_SEC_NODE_INFO, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_CLCT_INFO_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
if (valid_flag == NW_APP_CLCT_TASK_DATA_VALID) {
rsp_info_nor =
(nw_app_clct_task_id_info_query_nor_resp_t *)rsp_data->data;
os_mem_cpy(rsp_info_nor, result, payload_size);
} else {
rsp_info_abn =
(nw_app_clct_task_id_info_query_abn_resp_t *)rsp_data->data;
os_mem_cpy(rsp_info_abn, result, payload_size);
}
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s pkt err\n", __FUNCTION__);
}
return ret;
}
static uint32_t iot_sg_sta_nw_clct_info_query(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason = 0;
uint8_t valid_flag = NW_APP_CLCT_TASK_DATA_VALID, valid_reason = 0;
uint8_t i, di_len = 0;
uint8_t cco_addr[IOT_MAC_ADDR_LEN] = {0};
nw_app_clct_task_id_info_query_req_t * req;
nw_app_clct_task_id_info_query_nor_resp_t query_nor_resp;
nw_app_clct_task_id_info_query_abn_resp_t query_abn_resp;
iot_sg_sta_ext_clct_task_id_t task_id = {0};
iot_sg_sta_ext_clct_task_cfg_t task_cfg = {0};
nw_app_clct_task_info_t *task_info = NULL;
iot_sg_sta_node_desc_t *node = NULL;
nw_app_clct_task_id_97_t *task_id_97 = NULL;
nw_app_clct_task_id_07_t *task_id_07 = NULL;
req = (nw_app_clct_task_id_info_query_req_t *)data_hdr->data;
if (data_hdr->len < sizeof(*req)) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
node = iot_sg_sta_node_find_by_addr(req->pm_addr);
if (node == NULL) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
if (!iot_mac_addr_cmp(req->cco_addr, p_sg_glb->plc_state.cco_addr)) {
reason = 3;
ret = ERR_INVAL;
goto drop;
}
if (iot_sg_sta_ext_clct_get_task_info(req->pm_addr, &task_id) != ERR_OK) {
reason = 4;
ret = ERR_INVAL;
goto drop;
}
for (i = 0; i < IOT_SG_EXT_CLCT_TASK_CNT_MAX; i++) {
if (task_id.task_id[i] == req->task_id) {
break;
}
}
if (i >= IOT_SG_EXT_CLCT_TASK_CNT_MAX) {
valid_flag = NW_APP_CLCT_TASK_DATA_INVALID;
valid_reason = NW_APP_CLCT_TASK_DATA_ERR_NOTASK;
goto handle;
}
if (iot_sg_sta_ext_clct_get_task_id_info(req->pm_addr, req->task_id,
cco_addr, &task_cfg) != ERR_OK) {
reason = 5;
ret = ERR_INVAL;
goto drop;
}
if (!iot_mac_addr_cmp(cco_addr, req->cco_addr)) {
reason = 6;
ret = ERR_INVAL;
valid_flag = NW_APP_CLCT_TASK_DATA_INVALID;
valid_reason = NW_APP_CLCT_TASK_DATA_ERR_NOCCO;
}
handle:
if (valid_flag == NW_APP_CLCT_TASK_DATA_VALID) {
iot_mac_addr_cpy(query_nor_resp.pm_addr, req->pm_addr);
query_nor_resp.info_valid_flag = valid_flag;
task_info = (nw_app_clct_task_info_t *)&query_nor_resp.task_info;
task_info->task_id = req->task_id;
task_info->fn.meter_type =
iot_sg_sta_nw_clct_task_pm_type_to_nw(task_cfg.meter_type);
task_info->fn.proto_type =
iot_sg_sta_nw_clct_task_proto_type_to_nw(task_cfg.proto_type);
task_info->timeout = task_cfg.timeout;
task_info->base_time.base_min = task_cfg.base_min;
task_info->base_time.base_hour = task_cfg.base_hour;
task_info->base_time.base_day = task_cfg.base_day;
task_info->period =
iot_sg_sta_nw_clct_task_period_to_nw(task_cfg.period);
task_info->di_cnt = task_cfg.di_cnt;
if (task_cfg.proto_type == NW_APP_CLCT_TASK_PROTO_TYPE_645_97) {
di_len = sizeof(nw_app_clct_task_id_97_t);
task_id_97 = (nw_app_clct_task_id_97_t *)task_info->data;
} else {
di_len = sizeof(nw_app_clct_task_id_07_t);
task_id_07 = (nw_app_clct_task_id_07_t *)task_info->data;
}
for (i = 0; i < task_cfg.di_cnt; i++) {
if (task_info->fn.proto_type == NW_APP_CLCT_TASK_PROTO_TYPE_645_07) {
task_id_07[i].control_code = task_cfg.id_info[i].control_code;
task_id_07[i].di = task_cfg.id_info[i].di;
proto_645_2007_di_to_byte(task_cfg.id_info[i].di,
&task_id_07[i].di);
task_id_07[i].len_data = task_cfg.id_info[i].len_data;
} else {
task_id_97[i].control_code = task_cfg.id_info[i].control_code;
proto_645_1997_di_to_byte(task_cfg.id_info[i].di,
&task_id_97[i].di);
task_id_97[i].len_data = task_cfg.id_info[i].len_data;
}
}
os_mem_cpy(&task_info->data[task_info->di_cnt * di_len], &task_cfg.crc,
sizeof(uint16_t));
iot_sg_sta_nw_clct_info_query_resp(di_len, valid_flag, &query_nor_resp);
} else {
iot_mac_addr_cpy(query_abn_resp.pm_addr, req->pm_addr);
query_abn_resp.info_valid_flag = valid_flag;
query_abn_resp.err = valid_reason;
iot_sg_sta_nw_clct_info_query_resp(di_len, valid_flag,
&query_abn_resp);
goto drop;
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_clct_data_query_resp(uint8_t *addr,
uint8_t valid_flag, uint8_t task_id, uint8_t cnt, uint16_t crc,
uint16_t task_data_len, iot_time_tm_t *start_time, iot_time_tm_t *curr_time,
uint8_t err)
{
uint32_t ret = ERR_OK, reason;
uint16_t total_size, payload_size = 0;
uint8_t *req, *rsp, tmp_size;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *req_pkt = sta_glb->req.pkt;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *plc_pkt;
nw_app_clct_data_query_nor_resp_t *rsp_info_nor;
nw_app_clct_data_query_abn_resp_t *rsp_info_abn;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data, *rsp_data;
IOT_ASSERT(req_pkt);
(void)start_time;
(void)cnt;
req = iot_pkt_data(req_pkt);
req_hdr = (nw_app_header_t *)req;
req_data = (nw_app_data_t *)(req_hdr + 1);
msdu = (iot_plc_msdu_recv_t *)(req - sizeof(*msdu));
tmp_size = sizeof(*rsp_hdr) + sizeof(*rsp_data);
if (valid_flag == NW_APP_CLCT_TASK_DATA_VALID) {
payload_size = sizeof(nw_app_clct_data_query_nor_resp_t) + task_data_len;
} else {
payload_size = sizeof(nw_app_clct_data_query_abn_resp_t);
}
total_size = tmp_size + payload_size;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h,
IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, total_size,
IOT_PLC_LOCAL_RETRY_CNT);
if (!plc_pkt) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
rsp = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)rsp;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_CLCT_DATA_QUERY;
rsp_data->sn = req_data->sn;
rsp_data->ver = req_data->ver;
rsp_data->len = payload_size;
if (valid_flag == NW_APP_CLCT_TASK_DATA_VALID) {
rsp_info_nor = (nw_app_clct_data_query_nor_resp_t *)rsp_data->data;
if (iot_sg_sta_ext_clct_fill_task_data(addr, task_id, start_time, cnt,
rsp_info_nor->data, task_data_len) != ERR_OK) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
iot_mac_addr_cpy(rsp_info_nor->pm_addr, addr);
rsp_info_nor->tm.sec = curr_time->tm_sec;
rsp_info_nor->tm.min = curr_time->tm_min;
rsp_info_nor->tm.hour = curr_time->tm_hour;
rsp_info_nor->tm.day = curr_time->tm_mday;
rsp_info_nor->tm.month = curr_time->tm_mon;
rsp_info_nor->tm.year = (uint8_t)curr_time->tm_year;
rsp_info_nor->data_valid_flag = valid_flag;
rsp_info_nor->task_id = task_id;
rsp_info_nor->crc_code = crc;
} else {
rsp_info_abn = (nw_app_clct_data_query_abn_resp_t *)rsp_data->data;
iot_mac_addr_cpy(rsp_info_abn->pm_addr, addr);
rsp_info_abn->tm.sec = curr_time->tm_sec;
rsp_info_abn->tm.min = curr_time->tm_min;
rsp_info_abn->tm.hour = curr_time->tm_hour;
rsp_info_abn->tm.day = curr_time->tm_mday;
rsp_info_abn->tm.month = curr_time->tm_mon;
rsp_info_abn->tm.year = (uint8_t)curr_time->tm_year;
rsp_info_abn->data_valid_flag = valid_flag;
rsp_info_abn->err = err;
}
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
goto out;
drop:
if (plc_pkt) {
iot_pkt_free(plc_pkt);
}
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_clct_data_query(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK, reason;
uint32_t task_data_len;
uint8_t valid_flag = NW_APP_CLCT_TASK_DATA_VALID, valid_reason = 0, i;
uint8_t cco_addr[IOT_MAC_ADDR_LEN] = {0};
iot_sg_sta_node_desc_t *node;
nw_app_clct_data_query_req_t *req;
iot_sg_sta_ext_clct_task_id_t task_info;
iot_sg_sta_ext_clct_task_cfg_t task_cfg;
iot_time_tm_t start_time, curr_time;
req = (nw_app_clct_data_query_req_t *)data_hdr->data;
if (data_hdr->len < sizeof(*req)) {
reason = 1;
ret = ERR_INVAL;
goto drop;
}
node = iot_sg_sta_node_find_by_addr(req->pm_addr);
if (node == NULL) {
reason = 2;
ret = ERR_INVAL;
goto drop;
}
if (!iot_mac_addr_cmp(req->cco_addr, p_sg_glb->plc_state.cco_addr)) {
reason = 3;
ret = ERR_INVAL;
goto drop;
}
if (iot_sg_sta_ext_clct_get_task_info(req->pm_addr, &task_info) != ERR_OK) {
reason = 4;
ret = ERR_INVAL;
goto drop;
}
for (i = 0; i < task_info.cnt; i++) {
if (task_info.task_id[i] == req->task_id) {
break;
}
}
if (i >= task_info.cnt) {
reason = 5;
ret = ERR_INVAL;
valid_flag = NW_APP_CLCT_TASK_DATA_INVALID;
valid_reason = NW_APP_CLCT_TASK_DATA_ERR_NOTASK;
goto handle;
}
if (iot_sg_sta_ext_clct_get_task_id_info(req->pm_addr, req->task_id,
cco_addr, &task_cfg) != ERR_OK) {
reason = 6;
ret = ERR_INVAL;
goto drop;
}
if (!iot_mac_addr_cmp(cco_addr, req->cco_addr)) {
reason = 7;
ret = ERR_INVAL;
valid_flag = NW_APP_CLCT_TASK_DATA_INVALID;
valid_reason = NW_APP_CLCT_TASK_DATA_ERR_NOCCO;
}
handle:
if (iot_sg_sta_rtc_get(&curr_time, 1) != ERR_OK) {
reason = 8;
ret = ERR_INVAL;
goto drop;
}
if (valid_flag == NW_APP_CLCT_TASK_DATA_VALID) {
start_time.tm_year = curr_time.tm_year;
start_time.tm_mon = curr_time.tm_mon;
if (req->start_time.base_day) {
start_time.tm_mday = (uint8_t)req->start_time.base_day;
} else {
start_time.tm_mday = curr_time.tm_mday;
}
start_time.tm_hour = (uint8_t)req->start_time.base_hour;
start_time.tm_min = (uint8_t)req->start_time.base_min;
start_time.tm_sec = 0;
task_data_len = iot_sg_sta_ext_clct_get_task_data_len(req->pm_addr,
req->task_id, req->cnt);
if (iot_sg_sta_nw_clct_data_query_resp(req->pm_addr, valid_flag,
req->task_id, req->cnt, task_cfg.crc, (uint16_t)task_data_len,
&start_time, &curr_time, 0) != ERR_OK) {
reason = 9;
ret = ERR_INVAL;
goto drop;
}
} else {
if (iot_sg_sta_nw_clct_data_query_resp(req->pm_addr, valid_flag, 0, 0,
0, 0, NULL, &curr_time, valid_reason) != ERR_OK) {
reason = 10;
ret = ERR_INVAL;
goto drop;
}
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
iot_pkt_free(pkt);
return ret;
}
#if IOT_SMART_GRID_EDGE_COMPUTING_ENABLE
static uint32_t iot_sg_sta_nw_set_edge_computing(
iot_pkt_t *pkt, nw_app_data_t *data_hdr)
{
uint8_t reason = 0, addr[IOT_MAC_ADDR_LEN], *data = NULL;;
uint16_t size = 0;
uint32_t ret = ERR_OK;
iot_plc_msdu_recv_t *msdu;
iot_pkt_t *resp_pkt = NULL;
nw_app_header_t *rsp_hdr;
nw_app_data_t *rsp_data;
nw_app_edge_computing_dl_t *edge_dl;
nw_app_edge_computing_ul_t *edge_ul;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_flash_nw_edge_computing_cfg_info_t cfg = {0};
iot_mac_addr_cpy(addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(addr);
iot_sg_printf("%s\n", __FUNCTION__);
edge_dl = (nw_app_edge_computing_dl_t *)data_hdr->data;
if (!iot_mac_addr_cmp(edge_dl->dest_addr, addr)) {
reason = 1;
goto ack;
}
cfg.overvoltage_enable = !edge_dl->edge_conf.overvoltage_switch;
cfg.threshold_overvoltage = edge_dl->edge_conf.overvoltage_threshold;
cfg.period_overvoltage = edge_dl->edge_conf.overvoltage_period;
cfg.count_overvoltage = edge_dl->edge_conf.overvoltage_rpt_round;
cfg.undervoltage_enable = !edge_dl->edge_conf.undervoltage_switch;
cfg.threshold_undervoltage = edge_dl->edge_conf.undervoltage_threshold;
cfg.period_undervoltage = edge_dl->edge_conf.undervoltage_period;
cfg.count_undervoltage = edge_dl->edge_conf.undervoltage_rpt_round;
cfg.pulse_check_enable = !edge_dl->edge_conf.pulse_switch;
cfg.threshold_pulse = edge_dl->edge_conf.pulse_threshold;
cfg.health_check_enable = !edge_dl->edge_conf.health_status_switch;
cfg.pm_use_life = edge_dl->edge_conf.used_limit_threshold;
if (iot_sg_sta_ec_set_config(&cfg)) {
reason = 2;
}
ack:
data = iot_pkt_data(sta_glb->req.pkt);
msdu = (iot_plc_msdu_recv_t *)(data - sizeof(*msdu));
size = sizeof(*rsp_hdr) + sizeof(*data_hdr) + sizeof(*edge_ul);
resp_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, msdu->src, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, size, IOT_PLC_LOCAL_RETRY_CNT);
if (!resp_pkt) {
reason = 3;
ret = ERR_INVAL;
goto out;
}
rsp_hdr =
(nw_app_header_t *)iot_pkt_block_ptr(resp_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = NW_APP_CONTROL;
rsp_data = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_EDGE_COMPUTING;
rsp_data->sn = data_hdr->sn;
rsp_data->ver = data_hdr->ver;
rsp_data->len = sizeof(*edge_ul);
edge_ul = (nw_app_edge_computing_ul_t *)rsp_data->data;
iot_meter_addr_cpy(edge_ul->src_addr, edge_dl->dest_addr);
iot_meter_addr_cpy(edge_ul->dest_addr, edge_dl->src_addr);
edge_ul->edge_computing_task = edge_dl->edge_computing_task;
edge_ul->result = reason;
iot_pkt_put(resp_pkt, size);
iot_sg_send_msdu(resp_pkt, sta_glb->req.link_type);
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
iot_pkt_free(pkt);
return ret;
}
#else
static uint32_t iot_sg_sta_nw_set_edge_computing(
iot_pkt_t *pkt, nw_app_data_t *data_hdr)
{
(void)data_hdr;
iot_pkt_free(pkt);
return ERR_OK;
}
#endif
static uint32_t iot_sg_sta_nw_cmd_handle(iot_pkt_t *pkt, nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
if (iot_sg_sta_get_user_type() == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
switch (data_hdr->work_id) {
case NW_APP_WORK_CMD_TSFM:
{
ret = iot_sg_sta_nw_tsfm_detect_handle(pkt, data_hdr);
goto out;
}
case NW_APP_WORK_CMD_PM_SCORE_QUERY:
{
ret = iot_sg_sta_nw_pm_score_query(pkt, data_hdr);
goto out;
}
case NW_APP_WORK_CMD_SEC_NODE_ID_QUERY:
{
ret = iot_sg_sta_nw_node_id_query(pkt, data_hdr);
goto out;
}
default:
break;
}
}
switch (data_hdr->work_id) {
case NW_APP_WORK_CMD_QUERY_SEARCH_METER_RESULT:
{
ret = iot_sg_sta_nw_query_sm_result(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_DL_SEARCH_METER_LIST:
{
ret = iot_sg_sta_nw_add_sm_list(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_FILE_TRANSFER:
{
IOT_ASSERT(0);
break;
}
case NW_APP_WORK_CMD_SEC_NODE_EVT:
{
ret = iot_sg_sta_nw_sec_node_evt(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_SEC_NODE_REBOOT:
{
ret = iot_sg_sta_nw_sec_node_reboot(pkt, data_hdr->data, data_hdr->len);
break;
}
case NW_APP_WORK_CMD_SEC_NODE_INFO_QUERY:
{
ret = iot_sg_sta_nw_sec_node_info_query(pkt, data_hdr->data,
data_hdr->len, 0);
break;
}
case NW_APP_WORK_CMD_DL_ADDR_MAP_LIST:
{
ret = iot_sg_sta_nw_add_addr_map_list(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_RUN_STATE_QUERY:
{
ret = iot_sg_sta_nw_run_state_query(pkt, data_hdr->data,
data_hdr->len, 0);
break;
}
case NW_APP_WORK_CMD_NEIGHBOUR_QUERY:
{
ret = iot_sg_sta_nw_neighbour_query(pkt, data_hdr->data,
data_hdr->len, 0);
break;
}
case NW_APP_WORK_CMD_TSFM_GD:
{
ret = iot_sg_sta_nw_tsfm_detect_handle(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CLCT_ADD:
{
ret = iot_sg_sta_nw_clct_add(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_SEC_NODE_NET_QUERY:
{
ret = iot_sg_sta_nw_sec_node_net_query(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CORRECT:
{
ret = iot_sg_sta_nw_correct_time(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CLCT_INIT:
{
ret = iot_sg_sta_nw_clct_init(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CLCT_DEL:
{
ret = iot_sg_sta_nw_clct_del(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CLCT_ID_QUERY:
{
ret = iot_sg_sta_nw_clct_id_query(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CLCT_INFO_QUERY:
{
ret = iot_sg_sta_nw_clct_info_query(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_CLCT_DATA_QUERY:
{
ret = iot_sg_sta_nw_clct_data_query(pkt, data_hdr);
break;
}
case NW_APP_WORK_CMD_EDGE_COMPUTING:
{
ret = iot_sg_sta_nw_set_edge_computing(pkt, data_hdr);
break;
}
default:
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
break;
}
out:
return ret;
}
static uint32_t iot_sg_sta_nw_pd_addrs_collect(uint8_t *buf, uint16_t len)
{
uint8_t reason = 0;
nw_app_evt_data_addr_t *in_addrs;
in_addrs = (nw_app_evt_data_addr_t *)buf;
if (in_addrs->pm_count == 0) {
reason = 1;
goto ignore;
}
len -= sizeof(*in_addrs);
if (len < (in_addrs->pm_count * sizeof(*in_addrs->pm_info))) {
reason = 2;
goto ignore;
}
BUILD_BUG_ON(sizeof(iot_sg_sta_pd_addrs_info_t) ==
sizeof(nw_app_power_evt_pm_info_t));
if (!iot_sg_sta_pd_addrs_merge(
(iot_sg_sta_pd_addrs_info_t*)in_addrs->pm_info,
in_addrs->pm_count)) {
reason = 3;
goto ignore;
}
return ERR_OK;
ignore:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
return ERR_FAIL;
}
static uint32_t iot_sg_sta_nw_poweroff_event_collect(uint8_t *buf, uint16_t len)
{
uint32_t ret = ERR_OK;
nw_app_evt_data_field_t *power_off_info;
nw_app_evt_data_bitmap_t *bitmap_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
power_off_info = (nw_app_evt_data_field_t*)buf;
len -= sizeof(*power_off_info);
switch (power_off_info->type) {
case NW_APP_EVENT_TYPE_POWER_DOWN:
{
bitmap_data = (nw_app_evt_data_bitmap_t *)(power_off_info + 1);
len -= sizeof(*bitmap_data);
iot_sg_sta_bitmap_merge(bitmap_data->map, bitmap_data->tei, len,
&sta_glb->evt.power_off_bm);
break;
}
case NW_APP_EVENT_TYPE_POWER_DOWN_ADDR:
{
ret = iot_sg_sta_nw_pd_addrs_collect((uint8_t *)(power_off_info + 1),
len);
break;
}
default:
ret = ERR_INVAL;
break;
}
return ret;
}
static uint32_t iot_sg_sta_nw_event_ul(nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (!data_hdr->len) {
ret = ERR_INVAL;
goto out;
}
switch (data_hdr->data[0]) {
case NW_APP_EVENT_FN_MODULE_RPT:
{
/* collect power off event messages published by neighbor nodes. */
ret = iot_sg_sta_nw_poweroff_event_collect(data_hdr->data,
data_hdr->len);
if ((sta_glb->evt.power_off_rpt_status ==
IOT_SG_STA_POWEROFF_IDLE) && (ret == ERR_OK)) {
/* local dev isn't power off. When sta receive a power off
* event messages published by neighbor nodes, sta start 30s
* delay for collecting power off event messages.
*/
sta_glb->evt.power_off_rpt_status =
IOT_SG_STA_POWEROFF_COLLECT;
os_start_timer(sta_glb->power_off_timer,
IOT_SG_STA_NW_COLLECT_EVENT_RPT_DUR);
}
break;
}
default:
ret = ERR_INVAL;
break;
}
out:
return ret;
}
static uint32_t iot_sg_sta_nw_event(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_INVAL;
/* check direction */
if (data_hdr->control_field.dir) {
/* direction is from STA */
ret= iot_sg_sta_nw_event_ul(data_hdr);
}
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_rpt_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
switch (data_hdr->work_id) {
case NW_APP_WORK_RPT_EVT_RPT:
{
ret = iot_sg_sta_nw_event(pkt, data_hdr);
break;
}
default:
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
break;
}
return ret;
}
static uint32_t iot_sg_sta_nw_gd_poweroff_event_collect(uint8_t *buf,
uint16_t len)
{
uint32_t ret = ERR_OK;
nw_app_evt_data_field_gd_t *power_off_info_gd;
nw_app_evt_data_bitmap_t *bitmap_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
power_off_info_gd = (nw_app_evt_data_field_gd_t*)buf;
len -= sizeof(*power_off_info_gd);
switch (power_off_info_gd->evt_type) {
case NW_APP_EVENT_TYPE_POWER_DOWN:
{
bitmap_data = (nw_app_evt_data_bitmap_t *)(power_off_info_gd + 1);
len -= sizeof(*bitmap_data);
iot_sg_sta_bitmap_merge(bitmap_data->map, bitmap_data->tei, len,
&sta_glb->evt.power_off_bm);
break;
}
case NW_APP_EVENT_TYPE_POWER_DOWN_ADDR:
{
ret = iot_sg_sta_nw_pd_addrs_collect((uint8_t *)(power_off_info_gd + 1),
len);
break;
}
default:
ret = ERR_INVAL;
break;
}
return ret;
}
static uint32_t iot_sg_sta_nw_poweroff_collect_dur_get(void)
{
uint32_t dur = IOT_SG_STA_NW_COLLECT_EVENT_RPT_DUR;
if (iot_sg_sta_get_user_type() == USER_TYPE_SOUTHEN_NEW_POWER_GRID) {
dur = IOT_SG_STA_GD_COLLECT_EVENT_RPT_DUR;
}
return dur;
}
static uint32_t iot_sg_sta_nw_gd_event_ul(nw_app_data_t *data_hdr)
{
uint8_t reason = 0;
uint32_t ret = ERR_OK;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_rpt_evt_rpt_gd_t *evt_rpt;
if (data_hdr->len < sizeof(*evt_rpt)) {
reason = 1;
ret = ERR_INVAL;
goto out;
}
evt_rpt = (nw_app_rpt_evt_rpt_gd_t *)data_hdr->data;
if (evt_rpt->header_len != sizeof(*evt_rpt)) {
reason = 2;
ret = ERR_INVAL;
goto out;
}
if (!evt_rpt->data_len ||
data_hdr->len - sizeof(*evt_rpt) < evt_rpt->data_len) {
reason = 3;
ret = ERR_INVAL;
goto out;
}
switch (evt_rpt->fn) {
case NW_APP_EVENT_FN_STA_RPT:
case NW_APP_EVENT_FN_COLLECTOR_RPT:
{
/* collect power off event messages published by neighbor nodes. */
ret = iot_sg_sta_nw_gd_poweroff_event_collect(evt_rpt->data,
(uint16_t)evt_rpt->data_len);
if ((sta_glb->evt.power_off_rpt_status ==
IOT_SG_STA_POWEROFF_IDLE) && (ret == ERR_OK)) {
/* local dev isn't power off. When sta receive a power off
* event messages published by neighbor nodes, sta start 30s
* delay for collecting power off event messages.
*/
sta_glb->evt.power_off_rpt_status =
IOT_SG_STA_POWEROFF_COLLECT;
os_start_timer(sta_glb->power_off_timer,
iot_sg_sta_nw_poweroff_collect_dur_get());
}
break;
}
default:
reason = 4;
ret = ERR_INVAL;
break;
}
out:
if (ret != ERR_OK) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_nw_gd_event_dl(nw_app_data_t *data_hdr)
{
uint8_t reason = 0;
uint32_t ret = ERR_OK;
nw_app_rpt_evt_rpt_gd_t *evt_rpt;
if (data_hdr->len < sizeof(*evt_rpt)) {
reason = 1;
ret = ERR_INVAL;
goto out;
}
evt_rpt = (nw_app_rpt_evt_rpt_gd_t *)data_hdr->data;
if (evt_rpt->header_len != sizeof(*evt_rpt)) {
reason = 2;
ret = ERR_INVAL;
goto out;
}
switch (evt_rpt->fn) {
case NW_APP_EVENT_FN_CONF_ACK:
{
if (iot_sg_sta_check_power_on_rpt_seq(data_hdr->sn)) {
iot_sg_sta_power_on_ack_handle();
} else if (iot_sg_sta_check_power_off_fwd_seq(data_hdr->sn)) {
iot_sg_sta_power_off_fwd_ack_handle(data_hdr->sn);
}
break;
}
default:
reason = 3;
ret = ERR_INVAL;
break;
}
out:
if (ret != ERR_OK) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_nw_gd_event(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_INVAL;
/* check direction */
if (data_hdr->control_field.dir) {
/* direction is from STA */
ret = iot_sg_sta_nw_gd_event_ul(data_hdr);
} else {
/* direction is from CCO */
ret = iot_sg_sta_nw_gd_event_dl(data_hdr);
}
iot_pkt_free(pkt);
return ret;
}
static uint32_t iot_sg_sta_nw_gd_rpt_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
switch (data_hdr->work_id) {
case NW_APP_WORK_RPT_POWER_RPT:
{
ret = iot_sg_sta_nw_gd_event(pkt, data_hdr);
break;
}
default:
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
break;
}
return ret;
}
static uint8_t iot_sg_sta_nw_ctrl_proto_to_local(uint8_t proto_type)
{
/* protocol_type: the default is 0 transparent transmission.
* other, reserve for future. see nw protocol.
*/
(void)proto_type;
return IOT_SG_STA_DATA_TYPE_TRANS;
}
static uint32_t iot_sg_sta_nw_ctrl_passthrouh_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint8_t reason = 0, baud_len, proto_type;
uint32_t ret = ERR_FAIL, len, baud = 0;
nw_app_ctrl_proto_passthrough_t *req_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (!sta_glb->drv) {
reason = 1;
goto drop;
}
if (data_hdr->len < sizeof(*req_data)) {
reason = 2;
goto drop;
}
req_data = (nw_app_ctrl_proto_passthrough_t*)(data_hdr + 1);
if (req_data->prm != NW_APP_CTRL_PRM_MASTER) {
reason = 3;
goto drop;
}
len = data_hdr->len - sizeof(*req_data);
if (len < req_data->data_len) {
reason = 4;
goto drop;
}
if (req_data->sn != sta_glb->ctrl_proto_sn) {
reason = 5;
ret = ERR_NOMEM;
goto drop;
}
baud_len = min(sizeof(baud), sizeof(req_data->baud));
for (uint8_t i = 1; i <= baud_len; i++) {
baud |= req_data->baud[baud_len - i];
if (baud_len - i) {
baud <<= 8;
}
}
proto_type = iot_sg_sta_nw_ctrl_proto_to_local(req_data->proto_type);
sta_glb->mr.max_retry = 0;
sta_glb->mr.timeout_retry = 0;
sta_glb->mr.nack_retry = 0;
sta_glb->mr.mr_interval = 100;
sta_glb->mr.mr_timeout = IOT_SG_STA_MR_TIMEOUT;
sta_glb->mr.data_type = proto_type;
sta_glb->mr.read_ack = 0;
sta_glb->mr.retry_cnt = 0;
sta_glb->mr.frame_idx = 0;
sta_glb->mr.frame_data[0] = req_data->data;
sta_glb->mr.frame_len[0] = req_data->data_len;
sta_glb->mr.frame_cnt = 1;
if (baud < IOT_SG_STA_NW_CTRL_PASSTHR_MIN_BAUD) {
sta_glb->mr.mr_baud = 0;
} else {
sta_glb->mr.mr_baud = baud;
}
/* trigger the first pending frame */
ret = iot_sg_sta_issue_frame();
if (ret == ERR_PENDING) {
sta_glb->mr.meter_read_on = 1;
} else if (ret) {
reason = 6;
goto drop;
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (sta_glb->mr.meter_read_on == 0) {
/* for pending case, the pkt will be freed in
* iot_sg_sta_meter_read_done_intern function.
*/
iot_pkt_free(pkt);
}
return ret;
}
static uint32_t iot_sg_sta_nw_ctrl_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret = ERR_OK;
switch (data_hdr->work_id) {
case NW_APP_WORK_CTRL_PASSTHROUGH:
{
ret = iot_sg_sta_nw_ctrl_passthrouh_handle(pkt, data_hdr);
break;
}
default:
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
break;
}
return ret;
}
static uint32_t iot_sg_sta_nw_fwd_to_meter(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint32_t ret;
if (data_hdr->work_id != NW_APP_WORK_DATA_FWD_TRANSPARENT) {
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
goto out;
}
ret = iot_sg_sta_meter_read(pkt, iot_pkt_data(pkt));
out:
return ret;
}
static uint32_t iot_sg_sta_nw_correct_time_get(
iot_time_tm_t *tm, uint8_t *data, uint32_t length)
{
uint8_t *ds = data;
uint16_t oi;
uint32_t len = length, ret = ERR_FAIL;
proto_645_header_t *hdr_645;
proto_645_corr_time_t *time;
apdu_info_t apdu = { 0 };
proto_69845_frame_head_info_t *hdr_698;
proto_69845_apdu_t *apdu_hdr;
proto_69845_app_action_req_t *req_hdr;
proto_69845_app_action_req_single_t *action_hdr;
proto_69845_app_data_time_s_t *time_698;
hdr_645 = proto_645_format_check(ds, len, PROTO_645_DIR_MASTER);
if (hdr_645) {
if (hdr_645->control.fn == PROTO_645_2007_FN_CORRECT_TIME
&& hdr_645->len >= sizeof(*time)) {
proto_645_sub33_handle(hdr_645->data, hdr_645->len);
if (iot_bcd_data_check(hdr_645->data, hdr_645->len)
&& (hdr_645->len >= sizeof(*time))) {
time = (proto_645_corr_time_t*)&hdr_645->data;
tm->tm_year = iot_bcd_to_byte(time->year) + 2000;
tm->tm_mon = iot_bcd_to_byte(time->month);
tm->tm_mday = iot_bcd_to_byte(time->day);
tm->tm_hour = iot_bcd_to_byte(time->hour);
tm->tm_min = iot_bcd_to_byte(time->minute);
tm->tm_sec = iot_bcd_to_byte(time->second);
ret = ERR_OK;
}
}
} else if (proto_69845_parse(&ds, &len, &hdr_698, &apdu) == ERR_OK) {
if (len < (sizeof(*apdu_hdr) + sizeof(*req_hdr)
+ sizeof(*action_hdr) + sizeof(*time_698))) {
goto out;
}
proto_69845_oi_to_byte(PROTO_69845_APP_OI_TIME, (uint8_t*)&oi);
apdu_hdr = (proto_69845_apdu_t*)ds;
req_hdr = (proto_69845_app_action_req_t*)apdu_hdr->data;
action_hdr = (proto_69845_app_action_req_single_t*)req_hdr->data;
time_698 = (proto_69845_app_data_time_s_t*)action_hdr->data.data;
if (apdu_hdr->type == PROTO_69845_C_APP_ACTION_REQ
&& req_hdr->data_type == PROTO_69845_APP_ACTION_NORMAL
&& action_hdr->omd.oi == oi
&& action_hdr->omd.method_id == PROTO_OMD_CORRECT_TIME_METHOD_ID
&& action_hdr->data.data_type == PROTO_69845_APP_DATA_TIME_S) {
tm->tm_year = iot_bytes_to_uint16((uint8_t*)&time_698->year, 1);
tm->tm_mon = time_698->month;
tm->tm_mday = time_698->day;
tm->tm_hour = time_698->hour;
tm->tm_min = time_698->minute;
tm->tm_sec = time_698->second;
ret = ERR_OK;
}
}
out:
return ret;
}
static void iot_sg_sta_nw_sz_sys_tm_set(iot_time_tm_t sys_tm)
{
iot_time_tm_t curr_tm = { 0 };
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (iot_sg_sta_rtc_get(&curr_tm, 0) == ERR_OK) {
if (sta_glb->ct_rec.year == curr_tm.tm_year &&
sta_glb->ct_rec.mon == curr_tm.tm_mon &&
sta_glb->ct_rec.day == curr_tm.tm_mday) {
iot_sg_printf("%s fail\n", __FUNCTION__);
return;
}
}
sta_glb->ct_rec.year = curr_tm.tm_year;
sta_glb->ct_rec.mon = curr_tm.tm_mon;
sta_glb->ct_rec.day = curr_tm.tm_mday;
iot_sg_sta_rtc_set(&sys_tm, 1);
iot_sg_sta_ext_auto_ct_set(1, 1);
iot_sg_sta_start_get_time();
}
static uint32_t iot_sg_sta_nw_fwd_to_module_corr_time(
nw_app_trans_module_corr_time_t *module_corr, uint16_t len, iot_pkt_t *pkt)
{
uint8_t reason = 0;
uint16_t data_len;
uint32_t ret = ERR_FAIL, dev_type;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_time_tm_t iot_ts = { 0 };
if (module_corr->port != NW_APP_CORRECT_TIME_PORT_ID) {
reason = 1;
goto out;
}
if (module_corr->seq == sta_glb->accur_corr_seq
&& sta_glb->flag_accur_valid) {
reason = 2;
goto out;
}
data_len = len - sizeof(*module_corr);
if (iot_sg_sta_get_user_type() == USER_TYPE_SOUTHEN_POWER_GRID_SHENZHEN) {
dev_type = sta_glb->drv->get_device_type();
if (dev_type != IOT_SG_STA_DEV_TYPE_POWER_METER) {
reason = 3;
goto out;
}
if (iot_sg_sta_nw_correct_time_get(&iot_ts, module_corr->data,
data_len) != ERR_OK) {
reason = 4;
goto out;
}
iot_sg_sta_cur_ntb_correct_ts(module_corr->cco_ntb, &iot_ts);
iot_sg_sta_nw_sz_sys_tm_set(iot_ts);
} else {
iot_sg_sta_correct_time_compensate(module_corr->cco_ntb,
module_corr->data, data_len);
iot_pkt_set_data(pkt, module_corr->data);
iot_pkt_set_tail(pkt, (module_corr->data + data_len));
ret = sta_glb->drv->correct_time(pkt, 1);
pkt = NULL;
if (ret) {
reason = 5;
goto out;
}
}
sta_glb->accur_corr_seq = module_corr->seq;
sta_glb->flag_accur_valid = 1;
ret = ERR_OK;
out:
if (reason) {
iot_sg_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint8_t iot_sg_sta_nw_is_lc_di(uint32_t di)
{
uint8_t last_byte = (uint8_t)(di & 0x000000FFu);
switch (di) {
case PROTO_645_2007_DI_V_A:
case PROTO_645_2007_DI_V_B:
case PROTO_645_2007_DI_V_C:
case PROTO_645_2007_DI_V_ALL:
case PROTO_645_2007_DI_I_A:
case PROTO_645_2007_DI_I_B:
case PROTO_645_2007_DI_I_C:
case PROTO_645_2007_DI_I_ALL:
case PROTO_645_2007_DI_P_T:
case PROTO_645_2007_DI_P_A:
case PROTO_645_2007_DI_P_B:
case PROTO_645_2007_DI_P_C:
case PROTO_645_2007_DI_P_ALL:
case PROTO_645_2007_DI_Q_T:
case PROTO_645_2007_DI_Q_A:
case PROTO_645_2007_DI_Q_B:
case PROTO_645_2007_DI_Q_C:
case PROTO_645_2007_DI_Q_ALL:
case PROTO_645_2007_DI_S_T:
case PROTO_645_2007_DI_S_A:
case PROTO_645_2007_DI_S_B:
case PROTO_645_2007_DI_S_C:
case PROTO_645_2007_DI_S_ALL:
case PROTO_645_2007_DI_PF_T:
case PROTO_645_2007_DI_PF_A:
case PROTO_645_2007_DI_PF_B:
case PROTO_645_2007_DI_PF_C:
case PROTO_645_2007_DI_PF_ALL:
case PROTO_645_2007_DI_PA_A:
case PROTO_645_2007_DI_PA_B:
case PROTO_645_2007_DI_PA_C:
case PROTO_645_2007_DI_PA_ALL:
case PROTO_645_2007_DI_VW_A:
case PROTO_645_2007_DI_VW_B:
case PROTO_645_2007_DI_VW_C:
case PROTO_645_2007_DI_VW_ALL:
case PROTO_645_2007_DI_IW_A:
case PROTO_645_2007_DI_IW_B:
case PROTO_645_2007_DI_IW_C:
case PROTO_645_2007_DI_IW_ALL:
case PROTO_645_2007_DI_I_N:
case PROTO_645_2007_DI_FREQ:
case PROTO_645_2007_DI_1MIN_AVG_P:
case PROTO_645_2007_DI_EPT_DEMAND:
case PROTO_645_2007_DI_EQT_DEMAND:
case PROTO_645_2007_DI_AT_DEMAND:
case PROTO_645_2007_DI_TEMP:
case PROTO_645_2007_CLOCK_BATTERY_V:
case PROTO_645_2007_MR_BATTERY_V:
case PROTO_645_2007_INTER_BATTERY_TIME:
{
return 1;
}
default:
break;
}
switch (di & 0xFFFFFF00) {
case PROTO_645_2007_DI_VHC_A:
case PROTO_645_2007_DI_VHC_B:
case PROTO_645_2007_DI_VHC_C:
case PROTO_645_2007_DI_IHC_A:
case PROTO_645_2007_DI_IHC_B:
case PROTO_645_2007_DI_IHC_C:
{
if ((1 <= last_byte && last_byte <= 0x15) || last_byte == 0xFF) {
return 1;
}
break;
}
default:
break;
}
return 0;
}
static uint8_t iot_sg_sta_nw_sz_lc_cfg_fill(
iot_sg_sta_flash_nw_task_cfg_info_t *task_cfg,
nw_app_lc_cfg_di_info_sz_t *cfg_di_info)
{
uint32_t di;
nw_app_lc_cfg_di_unit_sz_t *di_unit;
uint8_t interval, changed = 0, i, j;
for (i = 0; i < cfg_di_info->di_cnt; i++) {
di_unit = &cfg_di_info->di_unit[i];
di = proto_645_2007_byte_to_di(di_unit->di);
interval = di_unit->interval;
if (!iot_sg_sta_nw_is_lc_di(di)) {
continue;
}
for (j = 0; j < task_cfg->di_cnt; j++) {
if (di == task_cfg->di_info[j].di)
break;
}
if (j < IOT_SG_STA_FLASH_NW_CFG_DI_MAX_CNT) {
if (interval && interval < 15) {
/* minimum interval is 15 minutes */
interval = 15;
} else if (interval % 15 != 0) {
/* interval needs to be a multiple of 15, if not, use the
* most recent value.
*/
interval = (interval + 7) / 15 * 15;
}
if (j >= task_cfg->di_cnt) {
/* if task_cfg not have this di before, add it*/
task_cfg->di_info[j].di = di;
task_cfg->di_cnt++;
} else if (task_cfg->di_info[j].interval == interval) {
/* if this DI is present in the task_cfg, and the interval
* is the same, do not change it.
*/
continue;
}
task_cfg->di_info[j].interval = interval;
changed = 1;
} else {
break;
}
}
return changed;
}
static void iot_sg_sta_nw_fwd_to_module_load_curve_rsp(uint8_t *rsp_data,
uint16_t data_len)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *plc_pkt;
uint8_t *data;
iot_plc_msdu_recv_t *msdu;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data_hdr, *rsp_data_hdr;
nw_app_fwd_module_dl_t *req_fwd_hdr;
nw_app_fwd_ul_t *rsp_fwd_hdr;
uint16_t total_size;
data = iot_pkt_data(sta_glb->req.pkt);
msdu = (iot_plc_msdu_recv_t *)(data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)data;
req_data_hdr = (nw_app_data_t *)(req_hdr + 1);
req_fwd_hdr = (nw_app_fwd_module_dl_t *)req_data_hdr->data;
total_size = sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) +
sizeof(*rsp_fwd_hdr) + data_len;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, msdu->src, p_sg_glb->plc_state.addr,
NW_APP_PRIO_DEFAULT, total_size, IOT_PLC_LOCAL_RETRY_CNT);
if (plc_pkt) {
data = iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
/* fill in header */
rsp_hdr = (nw_app_header_t *)data;
rsp_hdr->id = req_hdr->id;
rsp_hdr->port = req_hdr->port;
rsp_hdr->reserved = 0;
rsp_data_hdr = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data_hdr->control_field.frame_type =
req_data_hdr->control_field.frame_type;
rsp_data_hdr->work_id = req_data_hdr->work_id;
rsp_data_hdr->ver = NW_APP_VERSION;
rsp_data_hdr->sn = req_data_hdr->sn;
rsp_data_hdr->len = (uint16_t)(sizeof(*rsp_fwd_hdr) + data_len);
rsp_fwd_hdr = (nw_app_fwd_ul_t *)(rsp_data_hdr + 1);
if (iot_mac_addr_cmp(req_fwd_hdr->dst_addr, iot_sg_sta_nw_bcast1_addr)
|| iot_mac_addr_cmp(req_fwd_hdr->dst_addr,
iot_sg_sta_nw_bcast2_addr)) {
iot_mac_addr_cpy(rsp_fwd_hdr->src_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(rsp_fwd_hdr->src_addr);
} else {
iot_mac_addr_cpy(rsp_fwd_hdr->src_addr, req_fwd_hdr->dst_addr);
}
iot_mac_addr_cpy(rsp_fwd_hdr->dst_addr, req_fwd_hdr->src_addr);
rsp_fwd_hdr->work_code_other = req_fwd_hdr->work_code_other;
rsp_fwd_hdr->work_code = req_fwd_hdr->work_code;
rsp_fwd_hdr->data_len = data_len;
/* fill in payload */
os_mem_cpy(rsp_fwd_hdr->data, rsp_data, data_len);
iot_pkt_put(plc_pkt, total_size);
iot_sg_send_msdu(plc_pkt, sta_glb->req.link_type);
} else {
iot_sg_printf("%s drop id %lu\n", __FUNCTION__, req_hdr->id);
}
}
static uint8_t iot_sg_sta_ext_nw_lc_di_data_len_get(uint32_t query_di)
{
uint8_t last_byte = (uint8_t)(query_di & 0x000000FFu), data_len = 0;
switch (query_di) {
case PROTO_645_2007_DI_V_A:
case PROTO_645_2007_DI_V_B:
case PROTO_645_2007_DI_V_C:
case PROTO_645_2007_DI_NW_CR_V_A:
case PROTO_645_2007_DI_NW_CR_V_B:
case PROTO_645_2007_DI_NW_CR_V_C:
{
data_len = PROTO_645_V_LEN;
break;
}
case PROTO_645_2007_DI_V_ALL:
case PROTO_645_2007_DI_NW_CR_V_ALL:
{
data_len = sizeof(proto_645_v_t);
break;
}
case PROTO_645_2007_DI_I_A:
case PROTO_645_2007_DI_I_B:
case PROTO_645_2007_DI_I_C:
case PROTO_645_2007_DI_I_N:
case PROTO_645_2007_DI_NW_CR_I_A:
case PROTO_645_2007_DI_NW_CR_I_B:
case PROTO_645_2007_DI_NW_CR_I_C:
case PROTO_645_2007_DI_NW_CR_I_N:
{
data_len = PROTO_645_07_A_LEN;
break;
}
case PROTO_645_2007_DI_I_ALL:
case PROTO_645_2007_DI_NW_CR_I_ALL:
{
data_len = sizeof(proto_645_07_a_t);
break;
}
case PROTO_645_2007_DI_P_T:
case PROTO_645_2007_DI_P_A:
case PROTO_645_2007_DI_P_B:
case PROTO_645_2007_DI_P_C:
case PROTO_645_2007_DI_Q_T:
case PROTO_645_2007_DI_Q_A:
case PROTO_645_2007_DI_Q_B:
case PROTO_645_2007_DI_Q_C:
case PROTO_645_2007_DI_S_T:
case PROTO_645_2007_DI_S_A:
case PROTO_645_2007_DI_S_B:
case PROTO_645_2007_DI_S_C:
case PROTO_645_2007_DI_1MIN_AVG_P:
case PROTO_645_2007_DI_EPT_DEMAND:
case PROTO_645_2007_DI_EQT_DEMAND:
case PROTO_645_2007_DI_AT_DEMAND:
case PROTO_645_2007_DI_NW_CR_P_T:
case PROTO_645_2007_DI_NW_CR_P_A:
case PROTO_645_2007_DI_NW_CR_P_B:
case PROTO_645_2007_DI_NW_CR_P_C:
case PROTO_645_2007_DI_NW_CR_Q_T:
case PROTO_645_2007_DI_NW_CR_Q_A:
case PROTO_645_2007_DI_NW_CR_Q_B:
case PROTO_645_2007_DI_NW_CR_Q_C:
case PROTO_645_2007_DI_NW_CR_EPT_DEMAND:
case PROTO_645_2007_DI_NW_CR_EQT_DEMAND:
{
data_len = PROTO_645_07_P_LEN;
break;
}
case PROTO_645_2007_DI_Q_ALL:
case PROTO_645_2007_DI_P_ALL:
case PROTO_645_2007_DI_S_ALL:
case PROTO_645_2007_DI_NW_CR_P_ALL:
case PROTO_645_2007_DI_NW_CR_Q_ALL:
{
data_len = sizeof(proto_645_07_p_t);
break;
}
case PROTO_645_2007_DI_PF_T:
case PROTO_645_2007_DI_PF_A:
case PROTO_645_2007_DI_PF_B:
case PROTO_645_2007_DI_PF_C:
case PROTO_645_2007_DI_NW_CR_PF_T:
case PROTO_645_2007_DI_NW_CR_PF_A:
case PROTO_645_2007_DI_NW_CR_PF_B:
case PROTO_645_2007_DI_NW_CR_PF_C:
{
data_len = PROTO_645_07_PF_LEN;
break;
}
case PROTO_645_2007_DI_PF_ALL:
case PROTO_645_2007_DI_NW_CR_PF_ALL:
{
data_len = sizeof(proto_645_07_pf_t);
break;
}
case PROTO_645_2007_DI_PA_A:
case PROTO_645_2007_DI_PA_B:
case PROTO_645_2007_DI_PA_C:
{
data_len = PROTO_645_PHASE_ANGLE_LEN;
break;
}
case PROTO_645_2007_DI_PA_ALL:
{
data_len = sizeof(proto_645_07_phase_angle_t);
break;
}
case PROTO_645_2007_DI_VW_A:
case PROTO_645_2007_DI_VW_B:
case PROTO_645_2007_DI_VW_C:
case PROTO_645_2007_DI_IW_A:
case PROTO_645_2007_DI_IW_B:
case PROTO_645_2007_DI_IW_C:
{
data_len = PROTO_645_WAVEFORM_DIS_LEN;
break;
}
case PROTO_645_2007_DI_VW_ALL:
case PROTO_645_2007_DI_IW_ALL:
{
data_len = sizeof(proto_645_07_waveform_dis_t);
break;
}
case PROTO_645_2007_DI_FREQ:
{
data_len = sizeof(proto_645_freq_t);
break;
}
case PROTO_645_2007_DI_TEMP:
{
data_len = PROTO_645_TEMPERATURE_LEN;
break;
}
case PROTO_645_2007_CLOCK_BATTERY_V:
case PROTO_645_2007_MR_BATTERY_V:
{
data_len = PROTO_645_V_LEN;
break;
}
case PROTO_645_2007_INTER_BATTERY_TIME:
{
data_len = PROTO_645_INTER_BATTERY_TIME_LEN;
break;
}
case PROTO_645_2007_DI_NW_CR_EP_POS:
case PROTO_645_2007_DI_NW_CR_EP_NEG:
case PROTO_645_2007_DI_NW_CR_EQ_POS:
case PROTO_645_2007_DI_NW_CR_EQ_NEG:
case PROTO_645_2007_DI_NW_CR_EQ_QRT1:
case PROTO_645_2007_DI_NW_CR_EQ_QRT2:
case PROTO_645_2007_DI_NW_CR_EQ_QRT3:
case PROTO_645_2007_DI_NW_CR_EQ_QRT4:
{
data_len = IOT_SG_STA_METER_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_NW_CR_EPEQ_ALL:
{
data_len = sizeof(iot_sg_meter_total_energy_all_t);
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_QRT_ALL:
{
data_len = sizeof(iot_sg_meter_qr_total_energy_all_t);
break;
}
case PROTO_645_2007_DI_NW_CR_DEMAND_ALL:
{
data_len = sizeof(iot_sg_meter_cur_demand_all_t);
break;
}
default:
break;
}
switch (query_di & 0xFFFFFF00) {
case PROTO_645_2007_DI_VHC_A:
case PROTO_645_2007_DI_VHC_B:
case PROTO_645_2007_DI_VHC_C:
case PROTO_645_2007_DI_IHC_A:
case PROTO_645_2007_DI_IHC_B:
case PROTO_645_2007_DI_IHC_C:
{
if (last_byte == 0xff) {
data_len = sizeof(proto_645_07_harmonic_cont_t);
} else {
data_len = PROTO_645_HARMONIC_CONT_LEN;
}
break;
}
default:
break;
}
return data_len;
}
static void iot_sg_sta_ext_nw_lc_unit_data_write(uint8_t *data,
iot_sg_meter_lc_uint_nw_data_t *lc_data, uint32_t di, uint8_t di_data_len)
{
uint8_t *unit_data = NULL, last_byte = (uint8_t)(di & 0x000000FFu);
proto_645_07_harmonic_cont_unit_t *hc_unit = NULL;
switch (di) {
case PROTO_645_2007_DI_V_A:
case PROTO_645_2007_DI_NW_CR_V_A:
case PROTO_645_2007_DI_V_ALL:
case PROTO_645_2007_DI_NW_CR_V_ALL:
{
unit_data = lc_data->v.a;
break;
}
case PROTO_645_2007_DI_V_B:
case PROTO_645_2007_DI_NW_CR_V_B:
{
unit_data = lc_data->v.b;
break;
}
case PROTO_645_2007_DI_V_C:
case PROTO_645_2007_DI_NW_CR_V_C:
{
unit_data = lc_data->v.c;
break;
}
case PROTO_645_2007_DI_I_A:
case PROTO_645_2007_DI_NW_CR_I_A:
case PROTO_645_2007_DI_I_ALL:
case PROTO_645_2007_DI_NW_CR_I_ALL:
{
unit_data = lc_data->i.a;
break;
}
case PROTO_645_2007_DI_I_B:
case PROTO_645_2007_DI_NW_CR_I_B:
{
unit_data = lc_data->i.b;
break;
}
case PROTO_645_2007_DI_I_C:
case PROTO_645_2007_DI_NW_CR_I_C:
{
unit_data = lc_data->i.c;
break;
}
case PROTO_645_2007_DI_P_T:
case PROTO_645_2007_DI_NW_CR_P_T:
case PROTO_645_2007_DI_P_ALL:
case PROTO_645_2007_DI_NW_CR_P_ALL:
{
unit_data = lc_data->active_power.total;
break;
}
case PROTO_645_2007_DI_P_A:
case PROTO_645_2007_DI_NW_CR_P_A:
{
unit_data = lc_data->active_power.a;
break;
}
case PROTO_645_2007_DI_P_B:
case PROTO_645_2007_DI_NW_CR_P_B:
{
unit_data = lc_data->active_power.b;
break;
}
case PROTO_645_2007_DI_P_C:
case PROTO_645_2007_DI_NW_CR_P_C:
{
unit_data = lc_data->active_power.c;
break;
}
case PROTO_645_2007_DI_Q_T:
case PROTO_645_2007_DI_NW_CR_Q_T:
case PROTO_645_2007_DI_Q_ALL:
case PROTO_645_2007_DI_NW_CR_Q_ALL:
{
unit_data = lc_data->reactive_power.total;
break;
}
case PROTO_645_2007_DI_Q_A:
case PROTO_645_2007_DI_NW_CR_Q_A:
{
unit_data = lc_data->reactive_power.a;
break;
}
case PROTO_645_2007_DI_Q_B:
case PROTO_645_2007_DI_NW_CR_Q_B:
{
unit_data = lc_data->reactive_power.b;
break;
}
case PROTO_645_2007_DI_Q_C:
case PROTO_645_2007_DI_NW_CR_Q_C:
{
unit_data = lc_data->reactive_power.c;
break;
}
case PROTO_645_2007_DI_S_T:
case PROTO_645_2007_DI_S_ALL:
{
unit_data = lc_data->apparent_power.total;
break;
}
case PROTO_645_2007_DI_S_A:
{
unit_data = lc_data->apparent_power.a;
break;
}
case PROTO_645_2007_DI_S_B:
{
unit_data = lc_data->apparent_power.b;
break;
}
case PROTO_645_2007_DI_S_C:
{
unit_data = lc_data->apparent_power.c;
break;
}
case PROTO_645_2007_DI_PF_T:
case PROTO_645_2007_DI_NW_CR_PF_T:
case PROTO_645_2007_DI_PF_ALL:
case PROTO_645_2007_DI_NW_CR_PF_ALL:
{
unit_data = lc_data->power_factor.total;
break;
}
case PROTO_645_2007_DI_PF_A:
case PROTO_645_2007_DI_NW_CR_PF_A:
{
unit_data = lc_data->power_factor.a;
break;
}
case PROTO_645_2007_DI_PF_B:
case PROTO_645_2007_DI_NW_CR_PF_B:
{
unit_data = lc_data->power_factor.b;
break;
}
case PROTO_645_2007_DI_PF_C:
case PROTO_645_2007_DI_NW_CR_PF_C:
{
unit_data = lc_data->power_factor.c;
break;
}
case PROTO_645_2007_DI_PA_A:
case PROTO_645_2007_DI_PA_ALL:
{
unit_data = lc_data->phase_angle.a;
break;
}
case PROTO_645_2007_DI_PA_B:
{
unit_data = lc_data->phase_angle.b;
break;
}
case PROTO_645_2007_DI_PA_C:
{
unit_data = lc_data->phase_angle.c;
break;
}
case PROTO_645_2007_DI_VW_A:
case PROTO_645_2007_DI_VW_ALL:
{
unit_data = lc_data->v_waveform_dis.a;
break;
}
case PROTO_645_2007_DI_VW_B:
{
unit_data = lc_data->v_waveform_dis.b;
break;
}
case PROTO_645_2007_DI_VW_C:
{
unit_data = lc_data->v_waveform_dis.c;
break;
}
case PROTO_645_2007_DI_IW_A:
case PROTO_645_2007_DI_IW_ALL:
{
unit_data = lc_data->i_waveform_dis.a;
break;
}
case PROTO_645_2007_DI_IW_B:
{
unit_data = lc_data->i_waveform_dis.b;
break;
}
case PROTO_645_2007_DI_IW_C:
{
unit_data = lc_data->i_waveform_dis.c;
break;
}
case PROTO_645_2007_DI_I_N:
case PROTO_645_2007_DI_NW_CR_I_N:
{
unit_data = lc_data->n;
break;
}
case PROTO_645_2007_DI_FREQ:
{
unit_data = lc_data->freq.bcd;
break;
}
case PROTO_645_2007_DI_1MIN_AVG_P:
{
unit_data = lc_data->average_p;
break;
}
case PROTO_645_2007_DI_EPT_DEMAND:
case PROTO_645_2007_DI_NW_CR_EPT_DEMAND:
case PROTO_645_2007_DI_NW_CR_DEMAND_ALL:
{
unit_data = lc_data->cur_demand.ap_demand;
break;
}
case PROTO_645_2007_DI_EQT_DEMAND:
case PROTO_645_2007_DI_NW_CR_EQT_DEMAND:
{
unit_data = lc_data->cur_demand.rp_demand;
break;
}
case PROTO_645_2007_DI_AT_DEMAND:
{
unit_data = lc_data->at_demand;
break;
}
case PROTO_645_2007_DI_TEMP:
{
unit_data = lc_data->temperature;
break;
}
case PROTO_645_2007_CLOCK_BATTERY_V:
{
unit_data = lc_data->clock_battery_v;
break;
}
case PROTO_645_2007_MR_BATTERY_V:
{
unit_data = lc_data->mr_battery_v;
break;
}
case PROTO_645_2007_INTER_BATTERY_TIME:
{
unit_data = lc_data->work_time;
break;
}
case PROTO_645_2007_DI_NW_CR_EP_POS:
case PROTO_645_2007_DI_NW_CR_EPEQ_ALL:
{
unit_data= lc_data->energy_t.ept_pos_t;
break;
}
case PROTO_645_2007_DI_NW_CR_EP_NEG:
{
unit_data= lc_data->energy_t.ept_neg_t;
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_POS:
{
unit_data= lc_data->energy_t.cre1_t;
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_NEG:
{
unit_data= lc_data->energy_t.cre2_t;
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_QRT1:
case PROTO_645_2007_DI_NW_CR_EQ_QRT_ALL:
{
unit_data = lc_data->qr_energy_t.re_1st_et;
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_QRT2:
{
unit_data = lc_data->qr_energy_t.re_2st_et;
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_QRT3:
{
unit_data = lc_data->qr_energy_t.re_3st_et;
break;
}
case PROTO_645_2007_DI_NW_CR_EQ_QRT4:
{
unit_data = lc_data->qr_energy_t.re_4st_et;
break;
}
default:
break;
}
switch (di & 0xFFFFFF00) {
case PROTO_645_2007_DI_VHC_A:
{
hc_unit = lc_data->a_v_hc.hc;
break;
}
case PROTO_645_2007_DI_VHC_B:
{
hc_unit = lc_data->b_v_hc.hc;
break;
}
case PROTO_645_2007_DI_VHC_C:
{
hc_unit = lc_data->c_v_hc.hc;
break;
}
case PROTO_645_2007_DI_IHC_A:
{
hc_unit = lc_data->a_i_hc.hc;
break;
}
case PROTO_645_2007_DI_IHC_B:
{
hc_unit = lc_data->b_i_hc.hc;
break;
}
case PROTO_645_2007_DI_IHC_C:
{
hc_unit = lc_data->c_i_hc.hc;
break;
}
default:
break;
}
if (hc_unit) {
if (last_byte == 0xff) {
unit_data = (uint8_t *)hc_unit;
} else {
if (!last_byte || last_byte > 0x15) {
goto out;
}
unit_data = (uint8_t *)(hc_unit + (last_byte - 1));
}
}
out:
if (unit_data) {
os_mem_cpy(data, unit_data, di_data_len);
} else {
os_mem_set(data, 0xff, di_data_len);
}
}
static void iot_sg_sta_ext_sz_lc_data_fill(uint8_t *addr, uint8_t *data,
iot_time_tm_t *start_tm, uint8_t cnt, uint32_t di, uint8_t di_data_len,
uint16_t inter_time)
{
uint64_t delta;
uint16_t latest_idx, n, i, delta_cnt, start_idx = 0;
uint32_t ret, write_cnt = 0;
uint8_t *w_data = data, first_point = 0;
iot_time_tm_t tm_old = {0}, tm_new = {0};
iot_sg_meter_lc_uint_nw_data_t *lc_cache;
iot_pkt_t *pkt = NULL;
if (!addr || !data || !start_tm) {
return;
}
pkt = iot_pkt_alloc(sizeof(*lc_cache), IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
lc_cache = (iot_sg_meter_lc_uint_nw_data_t *)
iot_pkt_put(pkt, sizeof(*lc_cache));
if (iot_sg_sta_flash_unit_data_find_by_time(addr, &start_idx, start_tm,
(uint8_t *)lc_cache, sizeof(*lc_cache),
IOT_SG_STA_METER_DATA_TYPE_NW_TASK, 0) != ERR_OK) {
goto out;
}
ret = iot_sg_sta_flash_unit_data_find_latest(addr, &latest_idx,
(uint8_t *)lc_cache, sizeof(*lc_cache),
IOT_SG_STA_METER_DATA_TYPE_NW_TASK);
if (ret != ERR_OK) {
goto out;
}
iot_sg_printf("%s start idx:%d latest idx:%d\n", __FUNCTION__, start_idx,
latest_idx);
if (latest_idx >= start_idx) {
n = latest_idx - start_idx + 1;
} else {
n = IOT_SG_STA_METER_NW_LC_CNT - (start_idx - latest_idx) + 1;
}
os_mem_cpy(&tm_new, start_tm, sizeof(tm_new));
for (i = 0; i < n; i++) {
if (write_cnt == cnt) {
break;
}
ret = iot_sg_sta_flash_unit_data_read(addr, start_idx,
(uint8_t *)lc_cache, sizeof(*lc_cache),
IOT_SG_STA_METER_DATA_TYPE_NW_TASK);
if (ret == ERR_OK) {
tm_old = tm_new;
tm_new.tm_year = (uint16_t)lc_cache->year + 2000;
tm_new.tm_mon = (uint8_t)lc_cache->month;
tm_new.tm_mday = (uint8_t)lc_cache->day;
tm_new.tm_hour = (uint8_t)lc_cache->hour;
tm_new.tm_min = (uint8_t)lc_cache->minute;
delta = iot_rtc_delta_calc(&tm_old, &tm_new);
if (delta >= (inter_time * IOT_SG_STA_METER_NW_LC_CNT)) {
delta_cnt = IOT_SG_STA_METER_NW_LC_CNT;
} else {
delta_cnt = (uint16_t)(delta / inter_time);
if (delta % inter_time) {
/* if it's not the whole point, find the next point */
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
goto done;
}
}
if (!first_point) {
first_point = 1;
if (!delta_cnt) {
goto write;
} else {
if (delta_cnt >= cnt) {
os_mem_set(w_data, 0xFF, cnt * di_data_len);
write_cnt = cnt;
break;
}
/* delta_cnt contains the first invalid point */
os_mem_set(w_data, 0xFF, delta_cnt * di_data_len);
write_cnt += delta_cnt;
w_data += delta_cnt * di_data_len;
goto write;
}
} else {
if (!delta_cnt) {
/* load record delta time too short
* ignore current data unit.
*/
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
goto done;
} else if (delta_cnt == 1) {
goto write;
} else {
if ((write_cnt + delta_cnt) > cnt) {
delta_cnt = (uint8_t)(cnt - write_cnt);
os_mem_set(w_data, 0xFF, delta_cnt * di_data_len);
write_cnt = cnt;
break;
}
os_mem_set(w_data, 0xFF, (delta_cnt - 1) * di_data_len);
w_data += ((delta_cnt - 1) * di_data_len);
write_cnt += (delta_cnt - 1);
}
}
write:
iot_sg_sta_ext_nw_lc_unit_data_write(w_data, lc_cache, di,
di_data_len);
write_cnt++;
w_data += di_data_len;
}
done:
start_idx++;
if (start_idx >= IOT_SG_STA_METER_NW_LC_CNT) {
start_idx = 0;
}
}
out:
if (write_cnt < cnt) {
os_mem_set(w_data, 0xFF, (cnt - write_cnt) * di_data_len);
}
if (pkt) {
iot_pkt_free(pkt);
}
}
static void iot_sg_sta_ext_nw_lc_data_fill(uint8_t *addr, uint8_t *data,
iot_time_tm_t *start_tm, uint8_t cnt, uint32_t di, uint8_t di_data_len,
uint16_t inter_time, uint16_t node_count, uint16_t start_idx,
iot_sg_meter_lc_uint_nw_data_t *lc_cache)
{
uint64_t delta;
uint16_t i, delta_cnt;
uint32_t ret, write_cnt = 0;
uint8_t *w_data = data, first_point = 0;
iot_time_tm_t tm_old = {0}, tm_new = {0};
if (!addr || !data || !start_tm || !lc_cache) {
return;
}
if (!node_count) {
goto out;
}
iot_sg_printf("%s start idx:%d count:%d\n", __FUNCTION__, start_idx,
node_count);
os_mem_cpy(&tm_new, start_tm, sizeof(tm_new));
for (i = 0; i < node_count; i++) {
if (write_cnt == cnt) {
break;
}
ret = iot_sg_sta_flash_unit_data_read(addr, start_idx,
(uint8_t *)lc_cache, sizeof(*lc_cache),
IOT_SG_STA_METER_DATA_TYPE_NW_TASK);
if (ret == ERR_OK) {
tm_old = tm_new;
tm_new.tm_year = (uint16_t)lc_cache->year + 2000;
tm_new.tm_mon = (uint8_t)lc_cache->month;
tm_new.tm_mday = (uint8_t)lc_cache->day;
tm_new.tm_hour = (uint8_t)lc_cache->hour;
tm_new.tm_min = (uint8_t)lc_cache->minute;
delta = iot_rtc_delta_calc(&tm_old, &tm_new);
if (delta >= (inter_time * IOT_SG_STA_METER_NW_LC_CNT)) {
delta_cnt = IOT_SG_STA_METER_NW_LC_CNT;
} else {
delta_cnt = (uint16_t)(delta / inter_time);
if (delta % inter_time) {
/* if it's not the whole point, find the next point */
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
goto done;
}
}
if (!first_point) {
first_point = 1;
if (!delta_cnt) {
goto write;
} else {
if (delta_cnt >= cnt) {
os_mem_set(w_data, 0xFF, cnt * di_data_len);
write_cnt = cnt;
break;
}
/* delta_cnt contains the first invalid point */
os_mem_set(w_data, 0xFF, delta_cnt * di_data_len);
write_cnt += delta_cnt;
w_data += delta_cnt * di_data_len;
goto write;
}
} else {
if (!delta_cnt) {
/* load record delta time too short
* ignore current data unit.
*/
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
goto done;
} else if (delta_cnt == 1) {
goto write;
} else {
if ((write_cnt + delta_cnt) > cnt) {
delta_cnt = (uint8_t)(cnt - write_cnt);
os_mem_set(w_data, 0xFF, delta_cnt * di_data_len);
write_cnt = cnt;
break;
}
os_mem_set(w_data, 0xFF, (delta_cnt - 1) * di_data_len);
w_data += ((delta_cnt - 1) * di_data_len);
write_cnt += (delta_cnt - 1);
}
}
write:
iot_sg_sta_ext_nw_lc_unit_data_write(
w_data, lc_cache, di, di_data_len);
write_cnt++;
w_data += di_data_len;
}
done:
start_idx++;
if (start_idx >= IOT_SG_STA_METER_NW_LC_CNT) {
start_idx = 0;
}
}
out:
if (write_cnt < cnt) {
os_mem_set(w_data, 0xFF, (cnt - write_cnt) * di_data_len);
}
}
static uint32_t iot_sg_sta_ext_sz_lc_di_inter_time_get(uint16_t *inter_time,
iot_sg_sta_flash_nw_task_cfg_info_t *cfg, uint32_t query_di)
{
uint32_t cfg_di;
uint8_t ret = ERR_INVAL, min_di_cnt, i;
if (!inter_time || !cfg) {
goto out;
}
min_di_cnt = min(cfg->di_cnt, IOT_SG_STA_FLASH_NW_CFG_DI_MAX_CNT);
for (i = 0; i < min_di_cnt; i++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&cfg->di_info[i].di);
if (cfg_di == query_di) {
if (cfg->di_info[i].interval) {
*inter_time = cfg->di_info[i].interval * 60;
ret = ERR_OK;
}
goto out;
}
}
out:
return ret;
}
static uint32_t iot_sg_sta_ext_sz_lc_di_data_query_resp_fill(
uint16_t *rsp_data_len, uint8_t *rsp_data, uint16_t max_len,
uint8_t *dl_data, uint16_t dl_len)
{
uint8_t pm_addr[IOT_MAC_ADDR_LEN];
uint8_t reason = 0, i, di_data_len = 0, di_fill_cnt, task_type;
uint16_t fill_len = 0, inter_time = 0;
uint32_t query_di, ret = ERR_FAIL;
nw_app_lc_data_query_ul_sz_t *query_ul;
nw_app_lc_data_query_dl_sz_t *query_dl;
nw_app_lc_data_query_info_sz_t *query_info_ul;
iot_sg_sta_flash_nw_task_cfg_info_t *cfg;
iot_time_tm_t start_tm = {0};
iot_pkt_t *cfg_pkt = NULL;
if (dl_len < sizeof(*query_dl)) {
reason = 1;
goto drop;
}
query_dl = (nw_app_lc_data_query_dl_sz_t *)dl_data;
dl_len -= sizeof(*query_dl);
if (query_dl->meter_type == NW_APP_LR_METER_TYPE_SINGLE_PHASE) {
if (p_sg_glb->module_type != MODULE_TYPE_STA) {
reason = 2;
goto drop;
}
task_type = IOT_SG_STA_METER_NW_CFG_SINGLE;
} else if (query_dl->meter_type == NW_APP_LR_METER_TYPE_THREE_PHASE) {
if (p_sg_glb->module_type != MODULE_TYPE_3_PHASE_STA) {
reason = 3;
goto drop;
}
task_type = IOT_SG_STA_METER_NW_CFG_3P;
} else {
reason = 4;
goto drop;
}
if (!query_dl->di_cnt) {
reason = 5;
goto drop;
}
if (sizeof(*query_ul) > max_len) {
reason = 6;
goto drop;
}
query_ul = (nw_app_lc_data_query_ul_sz_t *)rsp_data;
query_ul->fn = NW_APP_LR_FN_READ_DI_DATA_SZ;
query_ul->meter_type = query_dl->meter_type;
max_len -= sizeof(*query_ul);
fill_len += sizeof(*query_ul);
rsp_data += sizeof(*query_ul);
cfg_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!cfg_pkt) {
reason = 7;
goto drop;
}
cfg = (iot_sg_sta_flash_nw_task_cfg_info_t *)
iot_pkt_put(cfg_pkt, sizeof(*cfg));
if (iot_sg_sta_flash_nw_task_cfg_get(cfg, task_type, NULL) != ERR_OK) {
reason = 8;
goto out;
}
for (i = 0; i < query_dl->di_cnt; i++) {
if (dl_len < sizeof(nw_app_lc_data_query_info_sz_t)) {
reason = 9;
break;
}
dl_len -= sizeof(nw_app_lc_data_query_info_sz_t);
start_tm.tm_year = iot_bcd_to_byte(query_dl->query_info[i].year)
+ 2000;
start_tm.tm_mon = iot_bcd_to_byte(query_dl->query_info[i].mon);
start_tm.tm_mday = iot_bcd_to_byte(query_dl->query_info[i].day);
start_tm.tm_hour = iot_bcd_to_byte(query_dl->query_info[i].hour);
start_tm.tm_min = iot_bcd_to_byte(query_dl->query_info[i].min);
query_di = proto_645_2007_byte_to_di(
(uint8_t *)&query_dl->query_info[i].di);
if (iot_sg_sta_ext_sz_lc_di_inter_time_get(&inter_time, cfg, query_di)
!= ERR_OK) {
continue;
}
iot_sg_ext_set_integral_point(&start_tm, inter_time, 1);
di_data_len = iot_sg_sta_ext_nw_lc_di_data_len_get(query_di);
if (!di_data_len) {
continue;
}
if (sizeof(*query_info_ul) > max_len) {
reason = 10;
break;
}
if ((sizeof(*query_info_ul) +
di_data_len * query_dl->query_info[i].n) > max_len) {
di_fill_cnt = (uint8_t)((max_len -
sizeof(*query_info_ul)) / di_data_len);
if (!di_fill_cnt) {
reason = 11;
break;
}
} else {
di_fill_cnt = query_dl->query_info[i].n;
}
query_info_ul = (nw_app_lc_data_query_info_sz_t *)rsp_data;
query_info_ul->di = query_dl->query_info[i].di;
query_info_ul->n = di_fill_cnt;
query_info_ul->year =
iot_byte_to_bcd((uint8_t)(start_tm.tm_year - 2000));
query_info_ul->mon = iot_byte_to_bcd(start_tm.tm_mon);
query_info_ul->day = iot_byte_to_bcd(start_tm.tm_mday);
query_info_ul->hour = iot_byte_to_bcd(start_tm.tm_hour);
query_info_ul->min = iot_byte_to_bcd(start_tm.tm_min);
query_ul->di_cnt++;
max_len -= sizeof(*query_info_ul);
rsp_data += sizeof(*query_info_ul);
fill_len += sizeof(*query_info_ul);
iot_mac_addr_cpy(pm_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(pm_addr);
iot_sg_sta_ext_sz_lc_data_fill(pm_addr, rsp_data,
&start_tm, di_fill_cnt, query_di, di_data_len, inter_time);
max_len -= di_data_len * di_fill_cnt;
rsp_data += di_data_len * di_fill_cnt;
fill_len += di_data_len * di_fill_cnt;
}
ret = ERR_OK;
*rsp_data_len = fill_len;
goto out;
drop:
*rsp_data_len = 0;
out:
if (cfg_pkt) {
iot_pkt_free(cfg_pkt);
}
if (reason) {
iot_sg_printf("%s reason %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_ext_nw_lc_di_data_query_resp_fill(uint8_t *pm_addr,
uint16_t *rsp_data_len, uint8_t *rsp_data, uint16_t max_len,
uint8_t *dl_data, uint16_t dl_len)
{
uint8_t max_n;
uint8_t reason = 0, i, di_data_len = 0;
uint16_t fill_len = 0, data_total_len = 0;
uint16_t start_idx = 0, latest_idx = 0, num = 0;
uint32_t ret = ERR_FAIL;
iot_pkt_t *pkt = NULL;
nw_app_lr_data_read_dl_t *read_dl;
nw_app_lr_data_read_ul_t *read_ul;
nw_app_lr_di_data_ul_t *di_data_ul;
iot_sg_meter_lc_uint_nw_data_t *cache;
iot_time_tm_t start_tm = {0};
if (dl_len < sizeof(*read_dl)) {
reason = 1;
goto drop;
}
read_dl = (nw_app_lr_data_read_dl_t *)dl_data;
dl_len -= sizeof(*read_dl);
if (!read_dl->di_cnt || !read_dl->interval) {
reason = 2;
goto drop;
}
if (dl_len < read_dl->di_cnt * PROTO_645_2007_DI_LEN) {
reason = 3;
goto drop;
}
if (sizeof(*read_ul) > max_len) {
reason = 4;
goto drop;
}
read_ul = (nw_app_lr_data_read_ul_t *)rsp_data;
read_ul->fn = NW_APP_LR_FN_READ_DI_DATA;
read_ul->meter_type = read_dl->meter_type;
read_ul->interval = read_dl->interval;
start_tm.tm_year = iot_bcd_to_byte(read_dl->year) + 2000;
start_tm.tm_mon = iot_bcd_to_byte(read_dl->mon);
start_tm.tm_mday = iot_bcd_to_byte(read_dl->day);
start_tm.tm_hour = iot_bcd_to_byte(read_dl->hour);
start_tm.tm_min = iot_bcd_to_byte(read_dl->min);
if ((read_dl->interval <= 60) && !(60 % read_dl->interval)) {
iot_sg_ext_set_integral_point(&start_tm, read_dl->interval * 60, 1);
}
read_ul->year = iot_byte_to_bcd((uint8_t)(start_tm.tm_year - 2000));
read_ul->mon = iot_byte_to_bcd(start_tm.tm_mon);
read_ul->day = iot_byte_to_bcd(start_tm.tm_mday);
read_ul->hour = iot_byte_to_bcd(start_tm.tm_hour);
read_ul->min = iot_byte_to_bcd(start_tm.tm_min);
max_len -= sizeof(*read_ul);
fill_len += sizeof(*read_ul);
rsp_data += sizeof(*read_ul);
for (i = 0; i < read_dl->di_cnt; i++) {
di_data_len = iot_sg_sta_ext_nw_lc_di_data_len_get(read_dl->di[i]);
if (!di_data_len) {
continue;
}
data_total_len += di_data_len;
}
pkt = iot_pkt_alloc(sizeof(*cache), IOT_SMART_GRID_MID);
if (!pkt) {
reason = 5;
goto drop;
}
cache = (iot_sg_meter_lc_uint_nw_data_t *)iot_pkt_put(pkt, sizeof(*cache));
if (!iot_sg_sta_flash_unit_data_find_by_time(pm_addr, &start_idx, &start_tm,
(uint8_t *)cache, sizeof(*cache),
IOT_SG_STA_METER_DATA_TYPE_NW_TASK, 0) &&
!iot_sg_sta_flash_unit_data_find_latest(pm_addr, &latest_idx,
(uint8_t *)cache, sizeof(*cache),
IOT_SG_STA_METER_DATA_TYPE_NW_TASK)) {
iot_sg_printf("%s start idx:%d latest idx:%d\n", __FUNCTION__,
start_idx, latest_idx);
if (latest_idx >= start_idx) {
num = latest_idx - start_idx + 1;
} else {
num = IOT_SG_STA_METER_NW_LC_CNT - (start_idx - latest_idx) + 1;
}
}
max_n = (uint8_t)((max_len -
read_dl->di_cnt * sizeof(*di_data_ul)) / data_total_len);
if (!max_n) {
max_n = 1;
}
if (max_n < read_dl->n) {
read_ul->n = max_n;
} else {
read_ul->n = read_dl->n;
}
for (i = 0; i < read_dl->di_cnt; i++) {
di_data_len = iot_sg_sta_ext_nw_lc_di_data_len_get(read_dl->di[i]);
if (!di_data_len) {
continue;
}
if (sizeof(*di_data_ul) > max_len) {
reason = 6;
break;
}
if ((sizeof(*di_data_ul) + di_data_len * read_ul->n) > max_len) {
reason = 7;
break;
}
di_data_ul = (nw_app_lr_di_data_ul_t *)rsp_data;
di_data_ul->di = read_dl->di[i];
read_ul->di_cnt++;
max_len -= sizeof(*di_data_ul);
rsp_data += sizeof(*di_data_ul);
fill_len += sizeof(*di_data_ul);
iot_sg_sta_ext_nw_lc_data_fill(pm_addr, rsp_data, &start_tm,
read_ul->n, read_dl->di[i], di_data_len, read_dl->interval * 60,
num, start_idx, cache);
max_len -= di_data_len * read_ul->n;
rsp_data += di_data_len * read_ul->n;
fill_len += di_data_len * read_ul->n;
}
ret = ERR_OK;
*rsp_data_len = fill_len;
goto out;
drop:
*rsp_data_len = 0;
out:
if (reason) {
iot_sg_printf("%s reason %lu\n", __FUNCTION__, reason);
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
static uint32_t iot_sg_sta_nw_lc_data_read_handle(uint8_t *data,
uint16_t data_len)
{
uint8_t reason = 0, *req_data, hdr_len;
uint16_t max_len;
uint32_t ret = ERR_INVAL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *plc_pkt = NULL;
iot_plc_msdu_recv_t *msdu;
nw_app_header_t *req_hdr, *rsp_hdr;
nw_app_data_t *req_data_hdr, *rsp_data_hdr;
nw_app_fwd_module_dl_t *req_fwd_hdr;
nw_app_fwd_ul_t *rsp;
req_data = iot_pkt_data(sta_glb->req.pkt);
msdu = (iot_plc_msdu_recv_t *)(req_data - sizeof(*msdu));
req_hdr = (nw_app_header_t *)req_data;
req_data_hdr = (nw_app_data_t *)(req_hdr + 1);
req_fwd_hdr = (nw_app_fwd_module_dl_t *)req_data_hdr->data;
plc_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_FILE_TRANS,
IOT_SG_STA_NW_LC_DI_DATA_RESP_MAX_LEN, IOT_PLC_LOCAL_RETRY_CNT);
if (!plc_pkt) {
reason = 1;
goto drop;
}
max_len = IOT_SG_STA_NW_LC_DI_DATA_RESP_MAX_LEN;
hdr_len = sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) + sizeof(*rsp);
if (hdr_len > max_len) {
reason = 2;
goto drop;
}
max_len -= hdr_len;
/* fill in header */
rsp_hdr = (nw_app_header_t *)iot_pkt_block_ptr(plc_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr->id = req_hdr->id;
rsp_hdr->port = req_hdr->port;
rsp_hdr->reserved = 0;
rsp_data_hdr = (nw_app_data_t *)(rsp_hdr + 1);
rsp_data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data_hdr->control_field.frame_type =
req_data_hdr->control_field.frame_type;
rsp_data_hdr->work_id = req_data_hdr->work_id;
rsp_data_hdr->ver = NW_APP_VERSION;
rsp_data_hdr->sn = req_data_hdr->sn;
rsp = (nw_app_fwd_ul_t *)rsp_data_hdr->data;
if (iot_mac_addr_cmp(req_fwd_hdr->dst_addr, iot_sg_sta_nw_bcast1_addr) ||
iot_mac_addr_cmp(req_fwd_hdr->dst_addr, iot_sg_sta_nw_bcast2_addr)) {
iot_mac_addr_cpy(rsp->src_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(rsp->src_addr);
} else {
iot_mac_addr_cpy(rsp->src_addr, req_fwd_hdr->dst_addr);
}
iot_mac_addr_cpy(rsp->dst_addr, req_fwd_hdr->src_addr);
rsp->work_code_other = req_fwd_hdr->work_code_other;
rsp->work_code = req_fwd_hdr->work_code;
if (iot_sg_sta_get_user_type() == USER_TYPE_SOUTHEN_POWER_GRID_SHENZHEN) {
if (iot_sg_sta_ext_sz_lc_di_data_query_resp_fill(&rsp->data_len,
rsp->data, max_len, data, data_len) != ERR_OK) {
reason = 3;
goto drop;
}
} else {
if (iot_sg_sta_ext_nw_lc_di_data_query_resp_fill(req_fwd_hdr->dst_addr,
&rsp->data_len, rsp->data, max_len, data, data_len) != ERR_OK) {
reason = 4;
goto drop;
}
}
rsp_data_hdr->len = (uint16_t)(sizeof(*rsp) + rsp->data_len);
iot_pkt_put(plc_pkt,
sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) + rsp_data_hdr->len);
iot_plc_send_msdu(p_sg_glb->plc_app_h, plc_pkt);
ret = ERR_OK;
goto out;
drop:
if (plc_pkt) {
iot_pkt_free(plc_pkt);
}
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
uint32_t iot_sg_sta_nw_sz_load_curve(uint8_t is_bcast,
uint8_t fn, uint8_t *data, uint16_t data_len)
{
uint32_t ret = ERR_OK, di;
nw_app_lc_cfg_info_sz_t *cfg_info;
nw_app_lc_cfg_di_info_sz_t *cfg_di_info;
nw_app_lc_interval_time_query_dl_sz_t *cfg_query_dl;
nw_app_lc_interval_time_query_ul_sz_t *cfg_query_ul;
nw_app_lc_cfg_di_unit_sz_t *di_unit;
iot_sg_sta_flash_nw_task_cfg_info_t *task_cfg;
iot_pkt_t *pkt = NULL, *rsp_pkt = NULL;
uint16_t di_unit_len;
uint16_t rsp_len;
uint8_t task_type, valid = 0, i, j, cnt = 0, reason = 0;
switch (fn) {
case NW_APP_LR_FN_CFG_CLCT_INTERVAL_SZ:
{
if (data_len < sizeof(*cfg_info)) {
ret = ERR_INVAL;
reason = 1;
goto out;
}
cfg_info = (nw_app_lc_cfg_info_sz_t *)data;
data += sizeof(*cfg_info);
data_len -= sizeof(*cfg_info);
pkt = iot_pkt_alloc(sizeof(*task_cfg), IOT_SMART_GRID_MID);
if (!pkt) {
ret = ERR_INVAL;
reason = 2;
goto out;
}
task_cfg = (iot_sg_sta_flash_nw_task_cfg_info_t *)iot_pkt_put(pkt,
sizeof(*task_cfg));
for (i = 0; i < NW_APP_LR_METER_TYPE_MAX; i++) {
if (data_len < sizeof(*cfg_di_info)) {
break;
}
cfg_di_info = (nw_app_lc_cfg_di_info_sz_t *)data;
data += sizeof(*cfg_di_info);
data_len -= sizeof(*cfg_di_info);
di_unit_len = sizeof(*cfg_di_info->di_unit) * cfg_di_info->di_cnt;
if (data_len < di_unit_len) {
break;
}
data += di_unit_len;
data_len -= di_unit_len;
if (cfg_di_info->meter_type == NW_APP_LR_METER_TYPE_SINGLE_PHASE) {
task_type = IOT_SG_STA_METER_NW_CFG_SINGLE;
} else if (cfg_di_info->meter_type ==
NW_APP_LR_METER_TYPE_THREE_PHASE) {
task_type = IOT_SG_STA_METER_NW_CFG_3P;
} else {
continue;
}
os_mem_set(task_cfg, 0, sizeof(*task_cfg));
task_cfg->flag_start = cfg_info->flag_start;
if (!iot_sg_sta_nw_sz_lc_cfg_fill(task_cfg, cfg_di_info) &&
task_cfg->flag_start) {
continue;
}
if (iot_sg_sta_flash_nw_task_cfg_save(task_cfg, task_type) ==
ERR_OK) {
valid = 1;
}
}
if (!valid) {
ret = ERR_INVAL;
reason = 3;
goto out;
}
if (!is_bcast) {
iot_sg_sta_nw_send_ack();
}
break;
}
case NW_APP_LR_FN_QUERY_CLCT_INTERVAL_SZ:
{
if (is_bcast) {
ret = ERR_INVAL;
reason = 4;
goto out;
}
cfg_query_dl = (nw_app_lc_interval_time_query_dl_sz_t *)data;
if (data_len < (sizeof(*cfg_query_dl) +
cfg_query_dl->di_cnt * PROTO_645_2007_DI_LEN)) {
ret = ERR_INVAL;
reason = 5;
goto out;
}
rsp_len = sizeof(*cfg_query_ul) + cfg_query_dl->di_cnt *
sizeof(*di_unit);
rsp_pkt = iot_pkt_alloc(rsp_len, IOT_SMART_GRID_MID);
if (!rsp_pkt) {
ret = ERR_INVAL;
reason = 6;
goto out;
}
cfg_query_ul = (nw_app_lc_interval_time_query_ul_sz_t *)iot_pkt_data(
rsp_pkt);
cfg_query_ul->fn = cfg_query_dl->fn;
cfg_query_ul->meter_type = cfg_query_dl->meter_type;
cfg_query_ul->di_cnt = 0;
pkt = iot_pkt_alloc(sizeof(*task_cfg), IOT_SMART_GRID_MID);
if (!pkt) {
ret = ERR_INVAL;
reason = 7;
goto out;
}
task_cfg = (iot_sg_sta_flash_nw_task_cfg_info_t *)iot_pkt_put(pkt,
sizeof(*task_cfg));
if (cfg_query_dl->meter_type == NW_APP_LR_METER_TYPE_SINGLE_PHASE) {
task_type = IOT_SG_STA_METER_NW_CFG_SINGLE;
} else if (cfg_query_dl->meter_type ==
NW_APP_LR_METER_TYPE_THREE_PHASE) {
task_type = IOT_SG_STA_METER_NW_CFG_3P;
} else {
ret = ERR_INVAL;
reason = 8;
goto out;
}
if (iot_sg_sta_flash_nw_task_cfg_get(task_cfg,
task_type, NULL) != ERR_OK) {
os_mem_set(task_cfg, 0, sizeof(*task_cfg));
}
for (i = 0; i < cfg_query_dl->di_cnt; i++) {
di = proto_645_2007_byte_to_di((uint8_t *)&cfg_query_dl->di[i]);
if (!iot_sg_sta_nw_is_lc_di(di)) {
continue;
}
for (j = 0; j < task_cfg->di_cnt; j++) {
if (di == task_cfg->di_info[j].di) {
di_unit = &cfg_query_ul->di_unit[cnt];
proto_645_2007_di_to_byte(di, di_unit->di);
di_unit->interval = task_cfg->di_info[j].interval;
cnt++;
break;
}
}
}
cfg_query_ul->di_cnt = cnt;
rsp_len = sizeof(*cfg_query_ul) + cnt * sizeof(*di_unit);
iot_pkt_put(rsp_pkt, rsp_len);
iot_sg_sta_nw_fwd_to_module_load_curve_rsp(iot_pkt_data(rsp_pkt),
rsp_len);
break;
}
case NW_APP_LR_FN_READ_DI_DATA_SZ:
{
ret = iot_sg_sta_nw_lc_data_read_handle(data, data_len);
break;
}
default:
ret = ERR_NOSUPP;
reason = 9;
break;
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
if (rsp_pkt) {
iot_pkt_free(rsp_pkt);
}
if (reason) {
iot_sg_printf("%s fail reason %lu\n", __FUNCTION__, reason);
}
return ret;
}
uint32_t iot_sg_sta_nw_load_curve(uint8_t is_bcast,
uint8_t fn, uint8_t *data, uint16_t data_len)
{
uint8_t reason = 0;
uint32_t ret = ERR_OK;
nw_app_lr_cfg_info_t *cfg_info;
switch (fn) {
case NW_APP_LR_FN_CFG_CLCT_INTERVAL:
{
if (data_len < sizeof(*cfg_info)) {
ret = ERR_INVAL;
reason = 1;
goto out;
}
cfg_info = (nw_app_lr_cfg_info_t *)data;
if (iot_sg_sta_ext_nw_lc_interval_save(cfg_info->interval) == ERR_OK) {
iot_sg_sta_ext_tm_reset();
if (!is_bcast) {
iot_sg_sta_nw_send_ack();
}
} else {
if (!is_bcast) {
iot_sg_sta_nw_send_nack(NW_APP_NACK_OTHER);
}
reason = 2;
ret = ERR_FAIL;
}
break;
}
case NW_APP_LR_FN_READ_DI_DATA:
{
ret = iot_sg_sta_nw_lc_data_read_handle(data, data_len);
break;
}
default:
ret = ERR_NOSUPP;
reason = 3;
break;
}
out:
if (reason) {
iot_sg_printf("%s fail reason %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_nw_fwd_to_module_load_curve(uint8_t is_bcast,
uint8_t fn, uint8_t *data, uint16_t data_len)
{
uint32_t ret = ERR_OK;
if (iot_sg_sta_get_user_type() == USER_TYPE_SOUTHEN_POWER_GRID_SHENZHEN) {
ret = iot_sg_sta_nw_sz_load_curve(is_bcast, fn, data, data_len);
} else {
ret = iot_sg_sta_nw_load_curve(is_bcast, fn, data, data_len);
}
return ret;
}
static uint32_t iot_sg_sta_nw_fwd_to_module(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint8_t reason = 0, is_bcast = 0, work_code;
uint32_t ret = ERR_INVAL, tmp_len;
nw_app_fwd_module_dl_t *fwd_mod;
nw_app_trans_module_corr_time_t *module_corr;
if (data_hdr->work_id != NW_APP_WORK_DATA_FWD_TRANS_MODULE) {
reason = 1;
goto drop;
}
if (data_hdr->len < sizeof(*fwd_mod)) {
reason = 2;
goto drop;
}
fwd_mod = (nw_app_fwd_module_dl_t *)data_hdr->data;
if (!iot_sg_sta_node_find_by_addr(fwd_mod->dst_addr)) {
if (!iot_mac_addr_cmp(fwd_mod->dst_addr, iot_sg_sta_nw_bcast1_addr) &&
!iot_mac_addr_cmp(fwd_mod->dst_addr, iot_sg_sta_nw_bcast2_addr)) {
reason = 3;
goto drop;
} else {
is_bcast = 1;
}
}
if (iot_sg_sta_get_user_type() == USER_TYPE_SOUTHEN_POWER_GRID_SHENZHEN) {
work_code = fwd_mod->work_code_other;
} else {
work_code = fwd_mod->work_code;
}
switch (work_code) {
case NW_APP_WORK_CODE_TRANS_645:
{
ret = iot_sg_sta_meter_read(pkt, iot_pkt_data(pkt));
break;
}
case NW_APP_WORK_CODE_CORR_TIME:
{
tmp_len = data_hdr->len - sizeof(*fwd_mod);
if (tmp_len < fwd_mod->data_len) {
reason = 4;
goto drop;
}
if ((fwd_mod->data_len < sizeof(*module_corr))
|| (tmp_len < sizeof(*module_corr))) {
reason = 5;
goto drop;
}
module_corr = (nw_app_trans_module_corr_time_t*)fwd_mod->data;
ret = iot_sg_sta_nw_fwd_to_module_corr_time(module_corr,
fwd_mod->data_len, pkt);
break;
}
case NW_APP_WORK_CODE_LOAD_CURVE:
{
if (!fwd_mod->data_len) {
goto drop;
}
ret = iot_sg_sta_nw_fwd_to_module_load_curve(is_bcast, fwd_mod->data[0],
fwd_mod->data, fwd_mod->data_len);
iot_pkt_free(pkt);
break;
}
default:
reason = 6;
goto drop;
}
goto out;
drop:
ret = ERR_FAIL;
iot_pkt_free(pkt);
iot_sg_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_broadcast_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint8_t reason = 0, dev_addr[IOT_MAC_ADDR_LEN], *data;
uint16_t data_len = data_hdr->len;
uint32_t ret = ERR_OK;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_broadcast_cmd_hdr *broadcast_hdr;
if (data_len < sizeof(*broadcast_hdr)) {
reason = 1;
goto drop;
}
broadcast_hdr = (nw_app_broadcast_cmd_hdr*)data_hdr->data;
sta_glb->drv->get_device_addr(dev_addr);
if ((iot_sg_sta_node_find_by_addr(broadcast_hdr->dst_addr) == NULL)
&& !iot_mac_addr_cmp(dev_addr, broadcast_hdr->dst_addr)) {
reason = 2;
goto drop;
}
data_len = data_len - sizeof(*broadcast_hdr);
data = broadcast_hdr->data;
switch (data_hdr->work_id) {
case NW_APP_WORK_CMD_SEC_NODE_REBOOT:
{
ret = iot_sg_sta_nw_sec_node_reboot(pkt, data, data_len);
break;
}
case NW_APP_WORK_CMD_SEC_NODE_INFO_QUERY:
{
ret = iot_sg_sta_nw_sec_node_info_query(pkt, data, data_len, 1);
break;
}
case NW_APP_WORK_CMD_RUN_STATE_QUERY:
{
ret = iot_sg_sta_nw_run_state_query(pkt, data, data_len, 1);
break;
}
case NW_APP_WORK_CMD_NEIGHBOUR_QUERY:
{
ret = iot_sg_sta_nw_neighbour_query(pkt, data, data_len, 1);
break;
}
default:
reason = 3;
goto drop;
}
goto out;
drop:
ret = ERR_FAIL;
iot_pkt_free(pkt);
iot_sg_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static uint32_t iot_sg_sta_nw_route_fwd_handle(iot_pkt_t *pkt,
nw_app_data_t *data_hdr)
{
uint8_t reason = 0, dev_addr[IOT_MAC_ADDR_LEN];
uint16_t data_len = data_hdr->len;
uint32_t ret = ERR_OK;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_route_fwd_t *route_fwd_hdr;
if (data_hdr->work_id != NW_APP_ROUTE_FWD_DATA) {
reason = 1;
goto drop;
}
if (data_len < sizeof(*route_fwd_hdr)) {
reason = 2;
goto drop;
}
route_fwd_hdr = (nw_app_route_fwd_t*)data_hdr->data;
sta_glb->drv->get_device_addr(dev_addr);
if ((iot_sg_sta_node_find_by_addr(route_fwd_hdr->dst_addr) == NULL)
&& !iot_mac_addr_cmp(dev_addr, route_fwd_hdr->dst_addr)) {
reason = 3;
goto drop;
}
sta_glb->mr.max_retry = 0;
sta_glb->mr.timeout_retry = 0;
sta_glb->mr.nack_retry = 0;
sta_glb->mr.mr_interval = 100;
sta_glb->mr.mr_timeout = IOT_SG_STA_MR_TIMEOUT;
sta_glb->mr.data_type = IOT_SG_STA_DATA_TYPE_TRANS;
sta_glb->mr.read_ack = 0;
sta_glb->mr.retry_cnt = 0;
sta_glb->mr.frame_idx = 0;
sta_glb->mr.frame_data[0] = route_fwd_hdr->data;
sta_glb->mr.frame_len[0] = route_fwd_hdr->data_len;
sta_glb->mr.frame_cnt = 1;
sta_glb->mr.mr_baud = 0;
/* trigger the first pending frame */
ret = iot_sg_sta_issue_frame();
if (ret == ERR_PENDING) {
sta_glb->mr.meter_read_on = 1;
} else if (ret) {
reason = 4;
goto drop;
}
goto out;
drop:
ret = ERR_FAIL;
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (sta_glb->mr.meter_read_on == 0) {
/* for pending case, the pkt will be freed in
* iot_sg_sta_meter_read_done_intern function.
*/
iot_pkt_free(pkt);
}
return ret;
}
static uint32_t iot_sg_sta_nw_pt_test_handle(iot_pkt_t *pkt,
nw_app_data_t *req_data_hdr)
{
uint8_t reason = 0, dev_addr[IOT_MAC_ADDR_LEN];
uint32_t ret = ERR_FAIL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *rsp_hdr;
nw_app_data_t *rsp_data_hdr = NULL;
iot_pkt_t *msdu_pkt = NULL;
uint16_t pkt_len = 0, rsp_work_data_len = 0;
uint8_t *data;
iot_build_info_t build_info;
uint8_t *req_work_data = (uint8_t *)(req_data_hdr + 1);
sta_glb->drv->get_device_addr(dev_addr);
switch (req_data_hdr->work_id) {
case NW_APP_WORT_ID_PT_QR_MAC:
{
nw_app_pt_qr_t *qr;
if (req_data_hdr->len < sizeof(*qr)) {
reason = 1;
goto drop;
}
qr = (nw_app_pt_qr_t *)req_work_data;
if (!iot_mac_addr_cmp(dev_addr, qr->node_addr)) {
reason = 2;
goto drop;
}
rsp_work_data_len = sizeof(nw_app_pt_set_mac_rsp_t);
break;
}
case NW_APP_WORT_ID_PT_SET_MAC:
{
nw_app_pt_set_mac_req_t *req;
if (req_data_hdr->len < sizeof(*req)) {
reason = 3;
goto drop;
}
req = (nw_app_pt_set_mac_req_t *)req_work_data;
if (!iot_mac_addr_cmp(dev_addr, req->node_addr)) {
reason = 4;
goto drop;
}
rsp_work_data_len = sizeof(nw_app_pt_set_mac_rsp_t);
iot_mac_addr_reverse(req->mac);
iot_oem_set_module_mac(req->mac);
break;
}
case NW_APP_WORT_ID_PT_READ_VER:
{
nw_app_pt_qr_t *qr;
if (req_data_hdr->len < sizeof(*qr)) {
reason = 5;
goto drop;
}
qr = (nw_app_pt_qr_t *)req_work_data;
if (!iot_mac_addr_cmp(dev_addr, qr->node_addr)) {
reason = 6;
goto drop;
}
rsp_work_data_len = sizeof(nw_app_pt_ver_rsp_t);
break;
}
default:
reason = 7;
goto drop;
}
pkt_len = sizeof(*rsp_hdr) + sizeof(*rsp_data_hdr) + rsp_work_data_len;
msdu_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_DEFAULT, pkt_len,
IOT_PLC_LOCAL_RETRY_CNT);
IOT_ASSERT(msdu_pkt);
data = iot_pkt_tail(msdu_pkt);
rsp_hdr = (nw_app_header_t *)data;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT_PT;
rsp_hdr->reserved = 0;
rsp_data_hdr = (nw_app_data_t*)(rsp_hdr + 1);
rsp_data_hdr->control_field.frame_type = NW_APP_FRAME_TYPE_PT;
rsp_data_hdr->control_field.reserved = 0;
rsp_data_hdr->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data_hdr->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data_hdr->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data_hdr->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data_hdr->work_id = req_data_hdr->work_id;
rsp_data_hdr->ver = NW_APP_VERSION;
rsp_data_hdr->sn = req_data_hdr->sn;
rsp_data_hdr->len = rsp_work_data_len;
data = (uint8_t *)(rsp_data_hdr + 1);
switch (rsp_data_hdr->work_id) {
case NW_APP_WORT_ID_PT_QR_MAC:
case NW_APP_WORT_ID_PT_SET_MAC:
{
nw_app_pt_set_mac_rsp_t *rsp = (nw_app_pt_set_mac_rsp_t *)data;
iot_mac_addr_cpy(rsp->node_addr, dev_addr);
iot_oem_get_module_mac(rsp->mac);
iot_mac_addr_reverse(rsp->mac);
break;
}
case NW_APP_WORT_ID_PT_READ_VER:
{
nw_app_pt_ver_rsp_t *ver_rsp = (nw_app_pt_ver_rsp_t *)data;
iot_mac_addr_cpy(ver_rsp->node_addr, dev_addr);
rsp_work_data_len = sizeof(nw_app_pt_ver_rsp_t);
ver_rsp->vendor_id = iot_oem_get_vendor_id();
ver_rsp->chip_id = iot_sg_get_chip_code();
iot_version_get_user_build_info(&build_info);
ver_rsp->ver_ext = build_info.sw_ver;
ver_rsp->ver_ext_day = build_info.day;
ver_rsp->ver_ext_mon = build_info.month;
ver_rsp->ver_ext_year = build_info.year;
iot_sg_printf("ext_ver: %c%c-%c%c-%02x%02x%02x-%02x%02x\n",
((uint8_t*)&ver_rsp->vendor_id)[1],
((uint8_t*)&ver_rsp->vendor_id)[0],
((uint8_t*)&ver_rsp->chip_id)[1],
((uint8_t*)&ver_rsp->chip_id)[0],
ver_rsp->ver_ext_year, ver_rsp->ver_ext_mon, ver_rsp->ver_ext_day,
((uint8_t*)&ver_rsp->ver_ext)[1],
((uint8_t*)&ver_rsp->ver_ext)[0]);
ver_rsp->ver_chip_hw = 0x0;
ver_rsp->ver_chip_hw_day = 0;
ver_rsp->ver_chip_hw_day = 0;
ver_rsp->ver_chip_hw_day = 0;
ver_rsp->ver_chip_sw = 0x0;
ver_rsp->ver_chip_sw_day = 0;
ver_rsp->ver_chip_sw_day = 0;
ver_rsp->ver_chip_sw_day = 0;
if (p_sg_glb->plc_state.nw_ppm < -15 ||
p_sg_glb->plc_state.nw_ppm > 15) {
ver_rsp->ver_inter = 0;
} else {
ver_rsp->ver_inter = iot_version_packed();
}
ver_rsp->ver_inter_day = iot_byte_to_bcd(build_info.day);
ver_rsp->ver_inter_mon = iot_byte_to_bcd(build_info.month);
ver_rsp->ver_inter_year = iot_byte_to_bcd(build_info.year);
iot_sg_printf("inter_ver: %02x%02x%02x-%02x%02x\n",
ver_rsp->ver_inter_year, ver_rsp->ver_inter_mon,
ver_rsp->ver_inter_day,
((uint8_t*)&ver_rsp->ver_inter)[1],
((uint8_t*)&ver_rsp->ver_inter)[0]);
break;
}
default:
reason = 8;
goto drop;
}
sta_glb->nw_pt_detected = 1;
iot_plc_query_dev_info(p_sg_glb->plc_app_h, IOT_SG_UPDATE_PPM_INTO_OEM);
ret = ERR_OK;
goto out;
drop:
iot_printf("%s drop reason %lu\n", __FUNCTION__, reason);
out:
if (pkt) {
iot_pkt_free(pkt);
}
iot_pkt_put(msdu_pkt, pkt_len);
iot_plc_send_msdu(p_sg_glb->plc_app_h, msdu_pkt);
return ret;
}
uint32_t iot_sg_sta_nw_handle_app_other(iot_pkt_t *pkt)
{
uint32_t ret = ERR_OK;
nw_app_header_t *hdr;
nw_app_data_t *data_hdr;
hdr = (nw_app_header_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
data_hdr = (nw_app_data_t *)(hdr + 1);
iot_sg_printf("%s msg frame %lu id %lu\n", __FUNCTION__,
data_hdr->control_field.frame_type, data_hdr->work_id);
switch (data_hdr->control_field.frame_type) {
case NW_APP_FRAME_TYPE_DATA_FWD:
{
if (hdr->port == NW_APP_PORT) {
ret = iot_sg_sta_nw_fwd_to_meter(pkt, data_hdr);
} else if (hdr->port == NW_APP_PORT_MGR) {
ret = iot_sg_sta_nw_fwd_to_module(pkt, data_hdr);
} else {
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
}
break;
}
case NW_APP_FRAME_TYPE_ACK_NACK:
{
iot_sg_sta_nw_ack_nack_handle(data_hdr);
iot_pkt_free(pkt);
break;
}
case NW_APP_FRAME_TYPE_CMD:
{
ret = iot_sg_sta_nw_cmd_handle(pkt, data_hdr);
break;
}
case NW_APP_FRAME_TYPE_RPT:
{
if (hdr->port == NW_APP_PORT) {
ret = iot_sg_sta_nw_rpt_handle(pkt, data_hdr);
} else if (hdr->port == NW_APP_PORT_MGR) {
ret = iot_sg_sta_nw_gd_rpt_handle(pkt, data_hdr);
} else {
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
}
break;
}
case NW_APP_FRAME_TYPE_CTRL:
{
ret = iot_sg_sta_nw_ctrl_handle(pkt, data_hdr);
break;
}
case NW_APP_FRAME_TYPE_BCAST_CMD:
{
ret = iot_sg_sta_nw_broadcast_handle(pkt, data_hdr);
break;
}
case NW_APP_FRAME_TYPE_ROUTE_FWD:
{
ret = iot_sg_sta_nw_route_fwd_handle(pkt, data_hdr);
break;
}
case NW_APP_FRAME_TYPE_PT:
{
if (hdr->port == NW_APP_PORT_PT && os_boot_time64() < 60000) {
ret = iot_sg_sta_nw_pt_test_handle(pkt, data_hdr);
} else {
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
}
break;
}
default:
iot_pkt_free(pkt);
ret = ERR_NOSUPP;
break;
}
return ret;
}
static uint16_t iot_sg_sta_nw_get_query_block(uint16_t block_cnt)
{
if (NW_APP_UPGRADE_QUERY_ALL_BLOCK == block_cnt) {
return IOT_SG_STA_QUERY_ALL_BLOCK;
}
return block_cnt;
}
void iot_sg_sta_nw_handle_app_upgrade(iot_pkt_t *pkt)
{
uint32_t consumed = 0;
nw_app_header_t *app_hdr;
nw_app_data_t *app_data;
nw_app_cmd_file_t *file_trans;
nw_app_cmd_file_data_dl_t *recv_data = NULL;
nw_app_cmd_file_finish_dl_t *finish_data = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_cmd_file_dl_file_info_dl_t *file_info = NULL;
uint8_t session_type = p_sg_glb->desc.sta->upgrade_info.session_type;
app_hdr = (nw_app_header_t*)iot_pkt_data(pkt);
/* nw app general header */
if (app_hdr->id != NW_APP_ID || app_hdr->port != NW_APP_PORT) {
goto exit_label;
}
/* nw app data header */
app_data = (nw_app_data_t*)(app_hdr + 1);
if (app_data->work_id != NW_APP_WORK_CMD_FILE_TRANSFER) {
goto exit_label;
}
sta_glb->upgrade_info.upgrade_sn = app_data->sn;
/* nw app upgrade packet header */
file_trans = (nw_app_cmd_file_t*)(app_data + 1);
switch (file_trans->id) {
case NW_APP_CMD_FILE_INFO:
{
file_info = (nw_app_cmd_file_dl_file_info_dl_t *)(file_trans + 1);
if (NW_APP_FILE_ATTRIBUTE_CLR == file_info->file_type) {
iot_sg_sta_handle_stop_upgrade(0,
(uint8_t)app_data->control_field.respond);
} else {
iot_sg_sta_handle_start_upgrade(file_info->file_id,
file_info->window, 0, file_info->file_size,
file_info->file_block_count, file_info->file_crc,
(uint8_t)app_data->control_field.respond,
IOT_SG_STA_UPGRADE_SESSION_TYPE_NW);
}
break;
}
case NW_APP_CMD_QUERY_RECV_STATUS:
{
nw_app_cmd_file_pkg_state_dl_t *query = NULL;
query = (nw_app_cmd_file_pkg_state_dl_t *)(file_trans + 1);
iot_sg_sta_handle_upgrade_query_status(query->file_tran_id,
query->start_block_id,
iot_sg_sta_nw_get_query_block(query->block_state_bitmap),
IOT_SG_STA_UPGRADE_SESSION_TYPE_NW);
break;
}
case NW_APP_CMD_FILE_DATA_B:
{
/* unicast to local broadcast */
iot_sg_sta_nw_upgrade_local_bcast(pkt);
}
case NW_APP_CMD_FILE_DATA:
{
recv_data = (nw_app_cmd_file_data_dl_t *)(file_trans->data);
if (IOT_SG_STA_UPGRADE_SESSION_TYPE_NW != session_type) {
break;
}
iot_sg_sta_handle_upgrade_data(recv_data->file_tran_id,
recv_data->data_len, recv_data->file_block_id, recv_data->data,
pkt, (uint8_t)app_data->control_field.respond);
consumed = 1;
break;
}
case NW_APP_CMD_FILE_SEND_DONE:
{
finish_data = (nw_app_cmd_file_finish_dl_t*)(file_trans->data);
if (IOT_SG_STA_UPGRADE_SESSION_TYPE_NW != session_type) {
break;
}
iot_sg_sta_handle_upgrade_execute(finish_data->file_tran_id,
finish_data->reset_dur, 0,
(uint8_t)app_data->control_field.respond);
break;
}
default:
iot_cus_printf("%s: invalid id=%lu\n", __FUNCTION__, file_trans->id);
break;
}
exit_label:
if (!consumed) {
iot_pkt_free(pkt);
}
}
void iot_sg_sta_nw_msg_handle(iot_pkt_t *pkt,
uint8_t *data)
{
uint32_t total_len = iot_pkt_data_len(pkt);
nw_app_data_t *nw_app_data_hdr = NULL;
nw_app_control_t *control = NULL;
if (iot_sg_sta_nw_sec_check(data, total_len, NULL)) {
goto drop;
}
nw_app_data_hdr = (nw_app_data_t *)(data + sizeof(nw_app_header_t));
control = &nw_app_data_hdr->control_field;
/* check upgrade pkt */
if (nw_app_data_hdr->work_id == NW_APP_WORK_CMD_FILE_TRANSFER
&& control->frame_type == NW_APP_FRAME_TYPE_CMD) {
iot_sg_sta_nw_handle_app_upgrade(pkt);
} else {
switch (control->frame_type) {
case NW_APP_FRAME_TYPE_ACK_NACK:
case NW_APP_FRAME_TYPE_DATA_FWD:
case NW_APP_FRAME_TYPE_CMD:
case NW_APP_FRAME_TYPE_RPT:
case NW_APP_FRAME_TYPE_BCAST_CMD:
case NW_APP_FRAME_TYPE_ROUTE_FWD:
case NW_APP_FRAME_TYPE_PT:
iot_sg_sta_queue_app_other(pkt, IOT_SG_LINK_TYPE_PLC);
break;
default:
goto drop;
}
}
goto out;
drop:
if (pkt) {
iot_pkt_free(pkt);
}
out:
return;
}
/*
* @brief: convert plc upgrading err code to nw upgrading err code
* @param err_code: plc upgrading err code, see IOT_PLC_UPGRADE_XXX
* @return: nw upgrading error code, see NW_APP_UPGRADE_XX
*/
static uint16_t iot_upgrade_err_code_plc_to_nw(uint32_t err_code)
{
uint16_t result;
switch (err_code) {
case IOT_PLC_UPGRADE_OK:
{
result = NW_APP_UPGRADE_OK;
break;
}
case IOT_PLC_UPGRADE_STATE_ERR:
{
result = NW_APP_UPGRADE_STATE_ERR;
break;
}
case IOT_PLC_UPGRADE_ERR_SAME_VERSION:
{
result = NW_APP_UPGRADE_ERR_SAME_VERSION;
break;
}
case IOT_PLC_UPGRADE_FLASH_ERROR:
{
result = NW_APP_UPGRADE_FLASH_ERROR;
break;
}
case IOT_PLC_UPGRADE_TRAIL_RUN_REJ:
{
result = NW_APP_UPGRADE_TRAIL_RUN_REJ;
break;
}
case IOT_PLC_UPGRADE_ERR_NO_MEM:
{
result = NW_APP_UPGRADE_ERR_NO_MEM;
break;
}
case IOT_PLC_UPGRADE_ERR_BLOCK_SIZE:
{
result = NW_APP_UPGRADE_ERR_BLOCK_SIZE;
break;
}
default:
result = NW_APP_UPGRADE_OTHER_ERR;
break;
}
return result;
}
void iot_sg_sta_nw_send_start_ack(uint32_t id, uint8_t msg_type,
uint32_t result)
{
uint8_t *data_ptr = NULL;
iot_pkt_t *msdu_pkt = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *rsp_hdr = NULL;
nw_app_data_t *rsp_data = NULL;
nw_app_cmd_file_t *file_trans = NULL;
nw_app_cmd_file_dl_file_info_ul_t *file_info = NULL;
uint16_t pkt_len = 0;
uint8_t data_len = sizeof(*file_trans) + sizeof(*file_info);
pkt_len = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
msdu_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, msg_type,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_FILE_TRANS, pkt_len,
IOT_PLC_LOCAL_RETRY_CNT);
IOT_ASSERT(msdu_pkt);
data_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data_ptr;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = 0;
rsp_data = (nw_app_data_t*)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_FILE_TRANSFER;
rsp_data->ver = NW_APP_VERSION;
rsp_data->sn = sta_glb->upgrade_info.upgrade_sn;
rsp_data->len = data_len;
file_trans = (nw_app_cmd_file_t*)(rsp_data + 1);
file_trans->id = NW_APP_CMD_FILE_INFO;
file_trans->rsvd[0] = 0;
file_trans->rsvd[1] = 0;
file_trans->rsvd[2] = 0;
file_info = (nw_app_cmd_file_dl_file_info_ul_t*)(file_trans + 1);
file_info->file_tran_id = id;
file_info->error_code = iot_upgrade_err_code_plc_to_nw(result);
if (result == IOT_PLC_UPGRADE_OK) {
file_info->result = NW_APP_RECV_UPGRADE_INFO_SUCCESS;
} else {
file_info->result = NW_APP_RECV_UPGRADE_INFO_FAIL;
}
iot_pkt_put(msdu_pkt, pkt_len);
/* send out the command */
iot_plc_send_msdu(p_sg_glb->plc_app_h, msdu_pkt);
}
void iot_sg_sta_nw_send_upgrade_data_ack(uint32_t id, uint32_t result)
{
uint8_t *data_ptr = NULL;
iot_pkt_t *msdu_pkt = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *rsp_hdr = NULL;
nw_app_data_t *rsp_data = NULL;
nw_app_cmd_file_t *file_trans = NULL;
nw_app_cmd_file_dl_file_data_ul_t *upgrade_ul = NULL;
uint16_t pkt_len = 0;
uint8_t data_len = sizeof(*file_trans) + sizeof(*upgrade_ul);
pkt_len = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
msdu_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, IOT_PLC_MSG_TYPE_UNICAST,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_FILE_TRANS, pkt_len,
IOT_PLC_LOCAL_RETRY_CNT);
IOT_ASSERT(msdu_pkt);
data_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data_ptr;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = 0;
rsp_data = (nw_app_data_t*)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_FILE_TRANSFER;
rsp_data->ver = NW_APP_VERSION;
rsp_data->sn = sta_glb->upgrade_info.upgrade_sn;
rsp_data->len = data_len;
file_trans = (nw_app_cmd_file_t*)(rsp_data + 1);
file_trans->id = NW_APP_CMD_FILE_DATA;
file_trans->rsvd[0] = 0;
file_trans->rsvd[1] = 0;
file_trans->rsvd[2] = 0;
upgrade_ul = (nw_app_cmd_file_dl_file_data_ul_t*)(file_trans + 1);
upgrade_ul->file_tran_id = id;
if (IOT_PLC_UPGRADE_OK == result) {
upgrade_ul->result = NW_APP_RECV_UPGRADE_INFO_SUCCESS;
} else {
upgrade_ul->result = NW_APP_RECV_UPGRADE_INFO_FAIL;
}
iot_pkt_put(msdu_pkt, pkt_len);
/* send out the command */
iot_plc_send_msdu(p_sg_glb->plc_app_h, msdu_pkt);
}
void iot_sg_sta_nw_send_exe_ack(uint32_t id, uint8_t msg_type,
uint32_t result)
{
uint8_t *data_ptr = NULL;
iot_pkt_t *msdu_pkt = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *rsp_hdr = NULL;
nw_app_data_t *rsp_data = NULL;
nw_app_cmd_file_t *file_trans = NULL;
nw_app_cmd_file_send_done_ul_t *upgrade_ul = NULL;
uint16_t pkt_len = 0;
uint8_t data_len = sizeof(*file_trans) + sizeof(*upgrade_ul);
pkt_len = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
msdu_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, msg_type,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_FILE_TRANS, pkt_len,
IOT_PLC_LOCAL_RETRY_CNT);
IOT_ASSERT(msdu_pkt);
data_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data_ptr;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = 0;
rsp_data = (nw_app_data_t*)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_FILE_TRANSFER;
rsp_data->ver = NW_APP_VERSION;
rsp_data->sn = sta_glb->upgrade_info.upgrade_sn;
rsp_data->len = data_len;
file_trans = (nw_app_cmd_file_t*)(rsp_data + 1);
file_trans->id = NW_APP_CMD_FILE_SEND_DONE;
file_trans->rsvd[0] = 0;
file_trans->rsvd[1] = 0;
file_trans->rsvd[2] = 0;
upgrade_ul = (nw_app_cmd_file_send_done_ul_t*)(file_trans + 1);
upgrade_ul->file_tran_id = id;
if (IOT_PLC_UPGRADE_OK == result) {
upgrade_ul->result = NW_APP_RECV_UPGRADE_INFO_SUCCESS;
} else {
upgrade_ul->result = NW_APP_RECV_UPGRADE_INFO_FAIL;
}
iot_pkt_put(msdu_pkt, pkt_len);
/* send out the command */
iot_plc_send_msdu(p_sg_glb->plc_app_h, msdu_pkt);
}
void iot_sg_sta_nw_send_stop_ack(uint32_t id, uint32_t result)
{
iot_sg_sta_nw_send_start_ack(id, IOT_PLC_MSG_TYPE_UNICAST, result);
}
static uint8_t iot_sg_sta_nw_get_upgrade_state(uint16_t state)
{
uint8_t result = 0;
switch (state) {
case IOT_SG_STA_UPGRADE_ST_IDLE:
{
result = NW_APP_FILE_ST_IDLE;
}
break;
case IOT_SG_STA_UPGRADE_ST_RECEIVE:
{
result = NW_APP_FILE_ST_SENDING;
if (iot_sg_sta_recv_all_block()) {
result = NW_APP_FILE_ST_SEND_DONE;
}
}
break;
case IOT_SG_STA_UPGRADE_ST_RECV_DONE:
{
result = NW_APP_FILE_ST_DEST_DONE;
}
break;
default:
break;
}
return result;
}
void iot_sg_sta_nw_send_query_reply(uint32_t id, uint32_t start_seq,
uint16_t status, iot_pkt_t *bitmap_pkt, uint8_t msg_type)
{
uint8_t *data_ptr = NULL;
uint8_t *bitmap = NULL;
iot_pkt_t *msdu_pkt = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
nw_app_header_t *rsp_hdr = NULL;
nw_app_data_t *rsp_data = NULL;
nw_app_cmd_file_t *file_trans = NULL;
nw_app_cmd_file_pkg_state_ul_t *file_info = NULL;
uint16_t pkt_len = 0;
uint16_t data_len = 0;
uint16_t bitmap_len = 0;
uint16_t i = 0;
if (bitmap_pkt == NULL) {
return;
}
bitmap = iot_pkt_data(bitmap_pkt);
bitmap_len = (uint16_t)iot_pkt_data_len(bitmap_pkt);
data_len = sizeof(*file_trans) + sizeof(*file_info) + bitmap_len;
pkt_len = sizeof(*rsp_hdr) + sizeof(*rsp_data) + data_len;
msdu_pkt = iot_plc_alloc_msdu(p_sg_glb->plc_app_h, msg_type,
IOT_PLC_ACK_TYPE_NONE, p_sg_glb->plc_state.cco_addr,
p_sg_glb->plc_state.addr, NW_APP_PRIO_FILE_TRANS, pkt_len,
IOT_PLC_LOCAL_RETRY_CNT);
IOT_ASSERT(msdu_pkt);
data_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
rsp_hdr = (nw_app_header_t *)data_ptr;
rsp_hdr->id = NW_APP_ID;
rsp_hdr->port = NW_APP_PORT;
rsp_hdr->reserved = 0;
rsp_data = (nw_app_data_t*)(rsp_hdr + 1);
rsp_data->control_field.frame_type = NW_APP_FRAME_TYPE_CMD;
rsp_data->control_field.reserved = 0;
rsp_data->control_field.work_append = NW_APP_CONTROL_NO_VENDOR_INFO;
rsp_data->control_field.respond = NW_APP_CONTROL_NO_NEED_RSP;
rsp_data->control_field.start = NW_APP_CONTROL_PRM_SLAVE;
rsp_data->control_field.dir = NW_APP_CONTROL_UP_LINK;
rsp_data->work_id = NW_APP_WORK_CMD_FILE_TRANSFER;
rsp_data->ver = NW_APP_VERSION;
rsp_data->sn = sta_glb->upgrade_info.upgrade_sn;
rsp_data->len = data_len;
file_trans = (nw_app_cmd_file_t*)(rsp_data + 1);
file_trans->id = NW_APP_CMD_QUERY_RECV_STATUS;
file_trans->rsvd[0] = 0;
file_trans->rsvd[1] = 0;
file_trans->rsvd[2] = 0;
file_info = (nw_app_cmd_file_pkg_state_ul_t*)(file_trans + 1);
file_info->file_tran_id = id;
file_info->start_seq = (uint16_t)start_seq;
file_info->status = iot_sg_sta_nw_get_upgrade_state(status);
file_info->reserved = 0;
for (i = 0; i < bitmap_len; i++) {
bitmap[i] = iot_byte_reverse(bitmap[i]);
}
os_mem_cpy(file_info->bm, bitmap, bitmap_len);
iot_pkt_put(msdu_pkt, pkt_len);
/* send out the command */
iot_plc_send_msdu(p_sg_glb->plc_app_h, msdu_pkt);
iot_pkt_free(bitmap_pkt);
}
void iot_sg_sta_nw_ctrl_proto_msg_handle(iot_pkt_t *pkt)
{
uint8_t reason = 0;
uint32_t len;
nw_app_header_t *hdr;
nw_app_data_t *data_hdr;
iot_pkt_pull(pkt, sizeof(iot_plc_msg_header_t)
+ sizeof(iot_plc_msdu_recv_t));
len = iot_pkt_data_len(pkt);
if (len <= sizeof(*hdr) + sizeof(*data_hdr)) {
reason = 1;
goto drop;
}
hdr = (nw_app_header_t *)iot_pkt_data(pkt);
if (hdr->port != NW_APP_PORT || hdr->id != NW_APP_ID) {
reason = 2;
goto drop;
}
data_hdr = (nw_app_data_t*)(hdr + 1);
if (data_hdr->control_field.frame_type != NW_APP_FRAME_TYPE_CTRL
&& data_hdr->control_field.frame_type != NW_APP_FRAME_TYPE_DATA_FWD) {
reason = 3;
goto drop;
}
if (data_hdr->work_id != NW_APP_WORK_CTRL_PROTO
&& data_hdr->work_id != NW_APP_WORK_CTRL_PASSTHROUGH) {
reason = 4;
goto drop;
}
if (!p_sg_glb->desc.sta->ctrl_proto_connected) {
reason = 5;
goto drop;
}
iot_sg_sta_queue_app_other(pkt, IOT_SG_LINK_TYPE_PLC_CTRL);
goto out;
drop:
iot_pkt_free(pkt);
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return;
}
void iot_sg_sta_nw_rtc_update_rpt(uint32_t ts, uint32_t cco_ntb)
{
uint8_t user_type = iot_sg_sta_get_user_type();
int64_t delta_time;
iot_time_tm_t curr_tm, rtc_tm = {0};
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_SHENZHEN
|| user_type == USER_TYPE_SOUTHEN_POWER_GRID_GX) {
return;
}
curr_tm.tm_year = 2000;
curr_tm.tm_mon = 1;
curr_tm.tm_mday = 1;
curr_tm.tm_hour = 0;
curr_tm.tm_min = 0;
curr_tm.tm_sec = 0;
delta_time = ts;
iot_rtc_delta_add(delta_time, &curr_tm);
iot_sg_sta_cur_ntb_correct_ts(cco_ntb, &curr_tm);
iot_sg_sta_rtc_get(&rtc_tm, 0);
iot_sg_sta_rtc_set(&curr_tm, 1);
delta_time = iot_rtc_delta_calc(&rtc_tm, &curr_tm);
if (IOT_ABS(delta_time) >= IOT_SG_STA_NW_RTC_UPDATE_DELTA) {
/* reset next read data time */
iot_sg_sta_ext_tm_reset();
}
}
#else /* PLC_SUPPORT_STA_ROLE && IOT_NW_APP_ENABLE */
void iot_sg_sta_nw_mr_done_intern(uint8_t data_type,
iot_pkt_t *rsp_pkt)
{
(void)data_type;
if (rsp_pkt) {
iot_pkt_free(rsp_pkt);
}
}
uint32_t iot_sg_sta_nw_handle_app_other(iot_pkt_t *pkt)
{
if (pkt) {
iot_pkt_free(pkt);
}
return ERR_INVAL;
}
void iot_sg_sta_nw_msg_handle(iot_pkt_t *pkt,
uint8_t *data)
{
(void)data;
if (pkt) {
iot_pkt_free(pkt);
}
}
uint32_t iot_sg_sta_nw_score_query_resp(iot_sg_sta_score_info_t *score_info)
{
(void)score_info;
return ERR_NOSUPP;
}
void iot_sg_sta_nw_ctrl_proto_msg_handle(iot_pkt_t *pkt)
{
if (pkt) {
iot_pkt_free(pkt);
}
}
uint32_t iot_sg_sta_nw_neighbor_info_resp(iot_plc_neighbor_dev_rpt_t *rpt,
uint8_t flag_broadcast)
{
(void)rpt;
(void)flag_broadcast;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_nw_correct_time_req_check(uint8_t *data, uint32_t len)
{
(void)data;
(void)len;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_nw_meter_state_score_report(uint8_t new_evt,
uint8_t meter_cnt)
{
(void)new_evt;
(void)meter_cnt;
return ERR_NOSUPP;
}
void iot_sg_sta_nw_score_event_func_handle(uint8_t fn)
{
(void)fn;
}
uint32_t iot_sg_sta_nw_report_ec_health_event(
uint8_t *addr, uint8_t score, iot_sg_sta_drv_score_bit_map_t *bitmap)
{
(void)addr;
(void)score;
(void)bitmap;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_nw_report_ec_overvoltage_event(uint8_t *addr,
uint8_t is_three_phase, uint16_t av, uint16_t bv, uint16_t cv)
{
(void)addr;
(void)is_three_phase;
(void)av;
(void)bv;
(void)cv;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_nw_report_ec_undervoltage_event(uint8_t *addr,
uint8_t is_three_phase, uint16_t av, uint16_t bv, uint16_t cv)
{
(void)addr;
(void)is_three_phase;
(void)av;
(void)bv;
(void)cv;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_nw_report_ec_second_pulse_event(
uint8_t *addr, uint16_t err_val)
{
(void)addr;
(void)err_val;
return ERR_NOSUPP;
}
#endif /* PLC_SUPPORT_STA_ROLE && IOT_NW_APP_ENABLE */