8669 lines
282 KiB
C
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 */
|