3826 lines
116 KiB
C
3826 lines
116 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_utils_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_bitmap_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_errno_api.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "iot_system_api.h"
|
|
#include "iot_version_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_rtc_api.h"
|
|
|
|
/* smart grid internal header files */
|
|
#include "iot_sg_cco_drv_api.h"
|
|
#include "iot_gw_drv_fj.h"
|
|
#include "proto_645.h"
|
|
#include "proto_645_fj.h"
|
|
#include "proto_3762.h"
|
|
#include "proto_3762_fj.h"
|
|
#include "iot_sg_cco_cmd.h"
|
|
|
|
/* change uart baud rate delay time, unit is 1ms */
|
|
#define IOT_GW_DRV_FJ_DELAY_TIME_1 (100)
|
|
#define IOT_GW_DRV_FJ_DELAY_TIME_2 (200)
|
|
#define IOT_GW_DRV_FJ_DELAY_TIME_3 (300)
|
|
#define IOT_GW_DRV_FJ_DELAY_TIME_4 (400)
|
|
#define IOT_GW_DRV_FJ_DELAY_TIME_5 (700)
|
|
|
|
/* bcast task interval send time, unit is 1s */
|
|
#define IOT_GW_DRV_FJ_BCAST_TASK_SEND_INTERVAL (30)
|
|
|
|
/* multi di report max data length */
|
|
#define IOT_SG_DRV_FJ_MULTI_DI_MAX_LEN (200)
|
|
|
|
/* multi di max request cnt */
|
|
#define IOT_SG_DRV_FJ_MULTI_DI_MAX_CNT (16)
|
|
|
|
#if (IOT_SMART_GRID_FJ_ENABLE)
|
|
|
|
extern cctt_drv_data_t *drv_data;
|
|
|
|
static uint32_t iot_gw_drv_fj_meter_data_52h_f1(uint8_t *data, uint16_t len,
|
|
uint16_t sn, uint8_t *mac_field, uint8_t obj_type);
|
|
|
|
/* iot_gw_drv_fj_send_uart_build - send data to UART
|
|
* @role: role of the device sending command. see IOT_SG_3762_ROLE_XXX
|
|
* master send command unsolicitedly while slave reply the command
|
|
* @afn: afn of 3762 datagram
|
|
* @fn: fn of 3762 datagram
|
|
* @pkt: iot_pkt with app data in data block, and enough space in
|
|
* head block and tail block.
|
|
* @cctt_cmd_sn:sn of the 3762 command
|
|
* @cctt_flag: report flag, 0 - allow report controller, 1 - only report cctt.
|
|
* return - 0 for succeed case
|
|
* - other value for failed case
|
|
*/
|
|
static uint32_t iot_gw_drv_fj_send_uart_build(uint8_t role,
|
|
uint8_t afn, uint8_t fn, iot_pkt_t *pkt, uint16_t cctt_cmd_sn,
|
|
uint8_t cctt_flag)
|
|
{
|
|
uint8_t *data = NULL;
|
|
uint16_t index = 0;
|
|
uint8_t *cs_ptr = NULL; //pointer to checksum
|
|
pkt_3762_hdr_t *pkt_hdr = NULL;
|
|
uint16_t app_data_len = (uint16_t)iot_pkt_data_len(pkt);
|
|
|
|
data = iot_pkt_push(pkt, proto_3762_get_header_len(0));
|
|
IOT_ASSERT(data);
|
|
pkt_hdr = (pkt_3762_hdr_t*)data;
|
|
pkt_hdr->sof_byte = PROTO_3762_SOF_BYTE;
|
|
pkt_hdr->ctrl_byte.dir = PROTO_3762_DIR_UP_LINK;
|
|
|
|
if (!role) {
|
|
/* response Message */
|
|
pkt_hdr->ctrl_byte.prm = PROTO_3762_PRM_SLAVE;
|
|
} else {
|
|
/* report message */
|
|
pkt_hdr->ctrl_byte.prm = PROTO_3762_PRM_MASTER;
|
|
if (cctt_cmd_sn == IOT_SG_INVALID_CCTT_SN) {
|
|
cctt_cmd_sn = iot_sg_cco_get_sn_for_cctt();
|
|
}
|
|
}
|
|
pkt_hdr->ctrl_byte.phy_type = PROTO_3762_PHY_TYPE_RESERVE;
|
|
|
|
/* user_data = &data[index]; */
|
|
os_mem_set(&pkt_hdr->user_data.res.ul_info, 0, sizeof(pkt_hdr->user_data));
|
|
pkt_hdr->user_data.res.ul_info.sn = (uint8_t)cctt_cmd_sn;
|
|
pkt_hdr->user_data.res.ul_info.event_flag = 0;
|
|
|
|
index += sizeof(pkt_3762_hdr_t);
|
|
|
|
/* set AFN */
|
|
data[index] = afn;
|
|
index++;
|
|
/* set Fn */
|
|
data[index] = 1 << ((fn-1) % 8); /* DT1 */
|
|
index++;
|
|
data[index] = (fn-1) / 8; /* DT2 */
|
|
index++;
|
|
|
|
/* skip app data as app data is already in iot_pkt */
|
|
index += app_data_len;
|
|
cs_ptr = &data[index++]; /* set the checksum byte pointer */
|
|
data[index] = PROTO_3762_EOF_BYTE;
|
|
index++;
|
|
pkt_hdr->len = index;
|
|
*cs_ptr = proto_3762_get_checksum(data[PROTO_3762_CTRL_OFFSET],
|
|
data + PROTO_3762_DATA_OFFSET,
|
|
index - PROTO_3762_DATA_OFFSET - 2);
|
|
|
|
// put checksum and back code. 2 byte.
|
|
iot_pkt_put(pkt, PROTO_3762_CS_BCODE_LEN);
|
|
iot_sg_data_print("<--uart send--:", iot_pkt_data(pkt),
|
|
iot_pkt_block_len(pkt, IOT_PKT_BLOCK_DATA));
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO,
|
|
IOT_SG_PROTO_UART_SEND, 0);
|
|
//IOT_SG_PROTO_UART_SEND, 1, output_buf);
|
|
|
|
if (iot_sg_cco_get_ctrl_proto_status() && !cctt_flag) {
|
|
/* send data to controller */
|
|
iot_sg_cco_send_ctrl_proto(pkt);
|
|
} else {
|
|
/* send data to UART */
|
|
iot_sg_cco_send_uart(pkt, IOT_SG_CCO_LOCAL_PROTO_DATA_SOURCE_CCTT);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_send_uart_sn_ext(uint8_t role,
|
|
uint8_t afn, uint8_t fn, iot_pkt_t *pkt, uint16_t cctt_cmd_sn)
|
|
{
|
|
return iot_gw_drv_fj_send_uart_build(role, afn, fn, pkt, cctt_cmd_sn, 0);
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_send_uart(uint8_t role, uint8_t afn, uint8_t fn,
|
|
uint8_t *app_data, uint16_t len, uint8_t sn)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
uint8_t *pkt_data;
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, len), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt_data);
|
|
os_mem_cpy(pkt_data, app_data, len);
|
|
iot_pkt_put(pkt, len);
|
|
return iot_gw_drv_fj_send_uart_sn_ext(role, afn, fn, pkt, sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_send_50h01_ack(uint16_t sn)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
uint8_t *pkt_data;
|
|
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, 0), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt_data);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_50, PROTO_3762_F1, pkt,
|
|
sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_send_50h02_nack_reject(uint8_t reason, uint16_t sn)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
uint8_t *pkt_data;
|
|
uint8_t *err_no;
|
|
uint8_t len;
|
|
|
|
len = sizeof(*err_no);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, len), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt_data);
|
|
err_no = (uint8_t *)pkt_data;
|
|
*err_no = reason;
|
|
iot_pkt_put(pkt, len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_50, PROTO_3762_F2, pkt,
|
|
sn);
|
|
}
|
|
|
|
static void iot_gw_drv_dj_reset_bcast_task_param()
|
|
{
|
|
drv_data->fj_data.bcast_task.channel_delay = 0;
|
|
drv_data->fj_data.bcast_task.time = 0;
|
|
drv_data->fj_data.bcast_task.sn = IOT_SG_INVALID_CCTT_SN;
|
|
if (drv_data->fj_data.bcast_task.bcast_pkt) {
|
|
iot_pkt_free(drv_data->fj_data.bcast_task.bcast_pkt);
|
|
drv_data->fj_data.bcast_task.bcast_pkt = NULL;
|
|
}
|
|
}
|
|
|
|
static void iot_gw_drv_fj_reset_parameter_info()
|
|
{
|
|
/* reset fujian proto parameter info */
|
|
drv_data->fj_data.delay_fix_flag = 0;
|
|
drv_data->fj_data.amr_model = CCTT_DRV_AMR_MODEL_IDLE;
|
|
drv_data->fj_data.plan_id = 0;
|
|
drv_data->fj_data.cmd_id = 0;
|
|
drv_data->fj_data.tsfm_enable_645 = 0;
|
|
drv_data->fj_data.same_tsfm_cnt = 0;
|
|
drv_data->fj_data.diff_tsfm_cnt = 0;
|
|
os_mem_set(drv_data->fj_data.obj_type_buf, 0,
|
|
sizeof(drv_data->fj_data.obj_type_buf));
|
|
iot_gw_drv_dj_reset_bcast_task_param();
|
|
}
|
|
|
|
static void iot_gw_drv_fj_handle_51h_init(uint8_t fn, uint8_t sn)
|
|
{
|
|
switch (fn) {
|
|
case PROTO_3762_F1:
|
|
{
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
os_delay(iot_sg_cco_sys_reset_wait_time());
|
|
iot_system_restart(IOT_SYS_RST_REASON_CCTT_REQ);
|
|
break;
|
|
}
|
|
case PROTO_3762_F2:
|
|
{
|
|
iot_sg_cco_reset_parameter_info();
|
|
cctt_drv_reset_parameter_info();
|
|
iot_gw_drv_fj_reset_parameter_info();
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F3:
|
|
{
|
|
iot_sg_cco_reset_communication_info();
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_tsfm_start(uint8_t *addr, uint8_t fn,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_fj_write_data_head_t *write_data;
|
|
proto_645_fj_tsfm_enable_t *tsfm_enable;
|
|
uint32_t timeout;
|
|
|
|
if (fn == PROTO_645_2007_FN_WRITE_DATA) {
|
|
if (len < sizeof(*write_data) + sizeof(*tsfm_enable)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
return pkt;
|
|
}
|
|
write_data = (proto_645_fj_write_data_head_t *)data;
|
|
tsfm_enable = (proto_645_fj_tsfm_enable_t *)write_data->data;
|
|
if (iot_sg_cco_get_tsfm_detect_status() ==
|
|
IOT_SG_CCO_TSFM_DETECT_DONE) {
|
|
cctt_drv_set_tsfm_detect_way(1);
|
|
}
|
|
timeout = tsfm_enable->timeout * 60;
|
|
iot_sg_cco_set_tsfm_detect_enabled(0, 1,
|
|
drv_data->qr_sta_tsfm_detect_ret, &timeout, 1, 1);
|
|
pkt = proto_645_2007_build_ack_msg(addr, fn);
|
|
} else if (fn == PROTO_645_2007_FN_READ_DATA) {
|
|
pkt = proto_645_fj_build_tsfm_enable_resp(addr,
|
|
PROTO_645_FJ_TSFM_DETECT_WAY_PERIOD,
|
|
(uint16_t)(iot_sg_cco_get_tsfm_detect_time_left() / 60));
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_diff_tsfm_node(uint8_t *addr,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
uint8_t count = 0, rpt_count = 0, err_code = 0, pkt_len;
|
|
uint16_t i, j;
|
|
uint16_t total_cnt = drv_data->fj_data.diff_tsfm_cnt;
|
|
iot_pkt_t *pkt = NULL, *pkt_645 = NULL;
|
|
iot_sg_pm_node_info_t pm_info = { 0 };
|
|
proto_645_fj_qr_diff_tsfm_node_ul_t *rsp;
|
|
proto_645_fj_qr_diff_tsfm_node_dl_t *req =
|
|
(proto_645_fj_qr_diff_tsfm_node_dl_t *)data;
|
|
|
|
if (len < sizeof(*req)) {
|
|
err_code = PROTO_645_FJ_ERR_LEN;
|
|
goto err;
|
|
}
|
|
if (req->start_index == 0) {
|
|
err_code = PROTO_645_FJ_ERR_OTHER;
|
|
goto err;
|
|
}
|
|
|
|
count = (uint8_t)min(total_cnt - req->start_index + 1,
|
|
min(req->node_count, PROTO_645_FJ_REQ_NODE_MAX_CNT));
|
|
|
|
pkt_len = sizeof(*rsp) + (count * sizeof(rsp->mac[0]));
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (proto_645_fj_qr_diff_tsfm_node_ul_t *)iot_pkt_data(pkt);
|
|
j = 0;
|
|
for (i = IOT_SG_METER_START_INDEX; (i < IOT_SG_METER_END_INDEX) &&
|
|
(rpt_count < count); ++i) {
|
|
if ((ERR_OK != iot_sg_cco_get_pm_info_by_index(i, &pm_info)) ||
|
|
((pm_info.tsfm_status != IOT_SG_CCO_PM_TO_TSFM_3) &&
|
|
(pm_info.tsfm_status != IOT_SG_CCO_PM_TO_TSFM_4))) {
|
|
continue;
|
|
}
|
|
j++;
|
|
if (j < req->start_index) {
|
|
continue;
|
|
}
|
|
iot_mac_addr_cpy(rsp->mac[rpt_count], pm_info.meter_mac);
|
|
rpt_count++;
|
|
}
|
|
|
|
rsp->total_count = total_cnt;
|
|
rsp->ack_node_count = rpt_count;
|
|
iot_pkt_put(pkt, sizeof(*rsp) + sizeof(rsp->mac[0]) * rpt_count);
|
|
|
|
pkt_645 = proto_645_fj_build_qr_diff_tsfm_node(addr, iot_pkt_data(pkt),
|
|
(uint8_t)iot_pkt_data_len(pkt));
|
|
iot_pkt_free(pkt);
|
|
|
|
goto out;
|
|
err:
|
|
pkt_645 = proto_645_2007_build_nack_msg(err_code, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_node_reg_start(uint8_t *addr, uint8_t fn,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_fj_write_data_head_t *write_data;
|
|
proto_645_fj_node_reg_enable_t *reg_enable;
|
|
|
|
if (fn == PROTO_645_2007_FN_WRITE_DATA) {
|
|
if (len < sizeof(*write_data) + sizeof(*reg_enable)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
return pkt;
|
|
}
|
|
write_data = (proto_645_fj_write_data_head_t *)data;
|
|
reg_enable = (proto_645_fj_node_reg_enable_t *)write_data->data;
|
|
if (!iot_sg_get_sec_node_reg_state()) {
|
|
drv_data->fj_data.fj_new_node_check = 1;
|
|
}
|
|
if (reg_enable->timeout == 0xFFFF) {
|
|
iot_sg_start_sec_node_reg(IOT_SG_CALLER_TYPE_CCTT, 0xFFFFF * 60, 1,
|
|
0);
|
|
} else {
|
|
iot_sg_start_sec_node_reg(IOT_SG_CALLER_TYPE_CCTT,
|
|
reg_enable->timeout * 60, 1, 1);
|
|
}
|
|
pkt = proto_645_2007_build_ack_msg(addr, fn);
|
|
drv_data->sec_node_reg_type = CCTT_DRV_SEC_NODE_REG_START_TYPE_FJ_645;
|
|
} else if (fn == PROTO_645_2007_FN_READ_DATA) {
|
|
pkt = proto_645_fj_build_node_reg_enable_resp(addr,
|
|
(uint16_t)(iot_sg_cco_get_sec_node_reg_timeout_left() / 60));
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_not_reg_node(uint8_t *addr,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
uint8_t count = 0, rpt_count = 0, err_code = 0, pkt_len;
|
|
uint16_t i;
|
|
uint16_t total_cnt = iot_sg_cco_get_mac_list_cnt();
|
|
iot_pkt_t *pkt = NULL, *pkt_645 = NULL;
|
|
proto_645_fj_qr_not_reg_node_ul_t *rsp;
|
|
proto_645_fj_qr_not_reg_node_dl_t *req =
|
|
(proto_645_fj_qr_not_reg_node_dl_t *)data;
|
|
uint32_t ret;
|
|
|
|
if (len < sizeof(*req)) {
|
|
err_code = PROTO_645_FJ_ERR_LEN;
|
|
goto err;
|
|
}
|
|
if (req->start_index == 0) {
|
|
err_code = PROTO_645_FJ_ERR_OTHER;
|
|
goto err;
|
|
}
|
|
|
|
if (req->start_index - 1 < total_cnt) {
|
|
count = (uint8_t)min(total_cnt - (req->start_index - 1),
|
|
min(req->node_count, PROTO_645_FJ_REQ_NODE_MAX_CNT));
|
|
}
|
|
|
|
pkt_len = sizeof(*rsp) + (count * sizeof(rsp->mac[0]));
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (proto_645_fj_qr_not_reg_node_ul_t *)iot_pkt_data(pkt);
|
|
for (i = req->start_index - 1; i < req->start_index - 1 + count; ++i) {
|
|
ret = iot_sg_cco_get_mac_list_pm_addr(i, rsp->mac[rpt_count]);
|
|
if (ret == ERR_OK) {
|
|
rpt_count++;
|
|
}
|
|
}
|
|
rsp->total_count = total_cnt;
|
|
rsp->ack_node_count = rpt_count;
|
|
iot_pkt_put(pkt, sizeof(*rsp) + sizeof(rsp->mac[0]) * rpt_count);
|
|
|
|
pkt_645 = proto_645_fj_build_qr_not_reg_node(addr, iot_pkt_data(pkt),
|
|
(uint8_t)iot_pkt_data_len(pkt));
|
|
iot_pkt_free(pkt);
|
|
|
|
goto out;
|
|
err:
|
|
pkt_645 = proto_645_2007_build_nack_msg(err_code, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_chip_id(uint8_t *addr)
|
|
{
|
|
iot_sg_cco_net_node_info_t info = { 0 };
|
|
|
|
BUILD_BUG_ON(sizeof(proto_645_fj_chip_id_t) ==
|
|
sizeof(iot_plc_chip_id_t));
|
|
if (ERR_OK != iot_sg_cco_get_net_node_info_by_mac(addr, &info)) {
|
|
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_NOT_IN_NET, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return proto_645_fj_build_query_chip_id(addr, (uint8_t *)&info.chip_id,
|
|
sizeof(info.chip_id));
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_mod_id(uint8_t *addr)
|
|
{
|
|
uint8_t mod_id[PROTO_645_FJ_MOD_ID_SIZE] = { 0 };
|
|
iot_sg_cco_net_node_info_t info = { 0 };
|
|
uint8_t i = 0;
|
|
|
|
BUILD_BUG_ON(IOT_SG_CCO_MODULE_ID_INFO_LEN * 2 <= PROTO_645_FJ_MOD_ID_SIZE);
|
|
|
|
if (ERR_OK != iot_sg_cco_get_net_node_info_by_mac(addr, &info)) {
|
|
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_NOT_IN_NET, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
for (i = 0; i < IOT_SG_CCO_MODULE_ID_INFO_LEN; i++) {
|
|
mod_id[i * 2] = (info.module_id_info[i] & 0x0F) + 0x30;
|
|
mod_id[i * 2 + 1] = ((info.module_id_info[i] >> 4) & 0x0F) + 0x30;
|
|
}
|
|
iot_data_reverse(mod_id, PROTO_645_FJ_MOD_ID_SIZE);
|
|
|
|
return proto_645_fj_build_query_mod_id(addr, mod_id, sizeof(mod_id));
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_mod_ver(uint8_t *addr)
|
|
{
|
|
iot_sg_cco_net_node_info_t info = { 0 };
|
|
proto_645_fj_mod_ver_info_t ver_info = { 0 };
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
|
|
if (ERR_OK != iot_sg_cco_get_net_node_info_by_mac(addr, &info)) {
|
|
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_NOT_IN_NET, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
ver_info.vendor_id = (info.vendor_id << 8) |
|
|
((info.vendor_id & 0xFF00) >> 8);
|
|
ver_info.chip_code = (info.chip_code << 8) |
|
|
((info.chip_code & 0xFF00) >> 8);
|
|
ver_info.day = iot_byte_to_bcd((uint8_t)info.build_time_d);
|
|
ver_info.month = iot_byte_to_bcd((uint8_t)info.build_time_m);
|
|
ver_info.year = iot_byte_to_bcd((uint8_t)info.build_time_y);
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
if (iot_mac_addr_cmp(cco_mac, addr)) {
|
|
ver_info.version[0] = (info.sw_version & 0xFF);
|
|
ver_info.version[1] = (info.sw_version >> 8);
|
|
} else {
|
|
ver_info.version[0] = (info.sw_version >> 8);
|
|
ver_info.version[1] = (info.sw_version & 0xFF);
|
|
}
|
|
|
|
return proto_645_fj_build_query_mod_ver(addr, (uint8_t *)&ver_info,
|
|
sizeof(ver_info));
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_proto_645_qr_topo(uint8_t *data, uint16_t len)
|
|
{
|
|
proto_645_fj_query_topo_dl_t *req = (proto_645_fj_query_topo_dl_t *)data;
|
|
if (len < sizeof(*req)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
drv_data->count_for_topo = max(PROTO_645_FJ_TOPO_RPT_MAX_CNT,
|
|
req->node_count);
|
|
drv_data->start_index_for_topo = req->start_index;
|
|
iot_sg_cco_get_topo_msg(CCTT_REQ_ID_DRV_GET_TOPO_645,
|
|
IOT_PLC_CCO_TOPO_REQ_DATA_VER_V2, drv_data->start_index_for_topo,
|
|
drv_data->count_for_topo);
|
|
return ERR_OK;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_set_band(uint8_t *addr, uint8_t *data,
|
|
uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_fj_write_data_head_t *write_data;
|
|
proto_645_fj_set_band_t *req;
|
|
|
|
if (len < sizeof(*write_data) + sizeof(*req)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
return pkt;
|
|
}
|
|
write_data = (proto_645_fj_write_data_head_t *)data;
|
|
req = (proto_645_fj_set_band_t *)write_data->data;
|
|
|
|
if (req->freq_band > PLC_LIB_FREQ_BAND_3) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
return pkt;
|
|
}
|
|
iot_sg_cco_set_freq_band_msg(CCTT_REQ_ID_DRV_SET_FREQ_BAND_645,
|
|
req->freq_band);
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_band(uint8_t *addr, uint8_t fn,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
if (fn == PROTO_645_2007_FN_WRITE_DATA) {
|
|
pkt = iot_gw_drv_fj_set_band(addr, data, len);
|
|
} else if (fn == PROTO_645_2007_FN_READ_DATA) {
|
|
iot_sg_cco_get_freq_band_msg(CCTT_REQ_ID_DRV_GET_FREQ_BAND_645);
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_proto_645_qr_chip_id_info(uint8_t *addr,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
uint8_t reason = PROTO_645_FJ_ERR_OTHER;
|
|
uint16_t i = 0;
|
|
uint8_t j = 0;
|
|
proto_645_fj_query_chip_info_ul_t *rsp;
|
|
iot_pkt_t *pkt = NULL, *pkt_645 = NULL;
|
|
iot_sg_cco_net_node_info_t info = { 0 };
|
|
uint16_t total_cnt = iot_sg_cco_get_net_node_cnt();
|
|
uint16_t rpt_cnt = 0;
|
|
uint16_t start_index, node_count;
|
|
proto_645_fj_query_chip_info_dl_t *req;
|
|
|
|
BUILD_BUG_ON(sizeof(iot_plc_chip_id_t) == sizeof(proto_645_fj_chip_id_t));
|
|
|
|
req = (proto_645_fj_query_chip_info_dl_t *)data;
|
|
start_index = req->start_index;
|
|
node_count = req->node_count;
|
|
|
|
if (len < sizeof(*req)) {
|
|
reason = PROTO_645_FJ_ERR_OTHER;
|
|
goto err;
|
|
}
|
|
|
|
if (start_index == 0) {
|
|
reason = PROTO_645_FJ_ERR_LEN;
|
|
goto err;
|
|
}
|
|
|
|
if (start_index <= total_cnt) {
|
|
rpt_cnt = min(total_cnt - start_index + 1,
|
|
min(node_count, PROTO_645_FJ_MAX_RPT_NODE_CNT));
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(sizeof(*rsp) + rpt_cnt * sizeof(rsp->node_info[0]),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (proto_645_fj_query_chip_info_ul_t *)iot_pkt_data(pkt);
|
|
rsp->total_node_cnt = total_cnt;
|
|
rsp->start_index = start_index;
|
|
for (i = start_index; i < start_index + rpt_cnt; ++i) {
|
|
if (iot_sg_cco_get_net_node_info_by_index(1, i, &info) == ERR_OK) {
|
|
iot_mac_addr_cpy(rsp->node_info[j].mac, info.addr);
|
|
rsp->node_info[j].dev_type = info.dev_type;
|
|
rsp->node_info[j].sw_version = info.sw_version;
|
|
os_mem_cpy(&rsp->node_info[j].chip_id, &info.chip_id,
|
|
sizeof(rsp->node_info[j].chip_id));
|
|
j++;
|
|
}
|
|
}
|
|
rsp->ack_node_count = j;
|
|
iot_pkt_put(pkt, sizeof(*rsp) + j * sizeof(rsp->node_info[0]));
|
|
|
|
pkt_645 = proto_645_fj_build_qr_chip_id_f112_resp(addr,
|
|
iot_pkt_data(pkt), (uint8_t)iot_pkt_data_len(pkt));
|
|
iot_pkt_free(pkt);
|
|
goto out;
|
|
|
|
err:
|
|
pkt_645 = proto_645_2007_build_nack_msg(reason, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_op_wl_qr(uint8_t *addr, uint8_t *data,
|
|
uint8_t len)
|
|
{
|
|
uint16_t i = 0;
|
|
uint32_t rsp_len;
|
|
iot_pkt_t *pkt, *result_pkt, *pkt_645;
|
|
proto_645_fj_query_wl_info_ul_t *rsp;
|
|
iot_sg_wl_entry_info_transfer_t *p_node_info;
|
|
proto_645_fj_query_wl_info_dl_t *req =
|
|
(proto_645_fj_query_wl_info_dl_t *)data;
|
|
|
|
if (len < sizeof(*req)) {
|
|
goto err;
|
|
}
|
|
|
|
result_pkt = iot_sg_cco_get_wl_entry_info(req->start_index,
|
|
min(req->count, PROTO_645_FJ_WL_MAX_RPT_CNT));
|
|
IOT_ASSERT(result_pkt);
|
|
p_node_info = (iot_sg_wl_entry_info_transfer_t*)iot_pkt_data(result_pkt);
|
|
|
|
/* allocate buffer for response */
|
|
rsp_len = sizeof(proto_645_fj_query_wl_info_ul_t);
|
|
rsp_len += p_node_info->count * sizeof(proto_645_fj_wl_sec_node_info_t);
|
|
pkt = iot_pkt_alloc(rsp_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
/* fill response info */
|
|
rsp = (proto_645_fj_query_wl_info_ul_t*)iot_pkt_data(pkt);
|
|
rsp->total_count = p_node_info->total_count;
|
|
rsp->count = 0;
|
|
|
|
for (i = 0; i < p_node_info->count; ++i) {
|
|
rsp->count++;
|
|
iot_mac_addr_cpy(rsp->sec_node[i].sec_node_mac,
|
|
p_node_info->info[i].mac_addr);
|
|
}
|
|
|
|
iot_pkt_put(pkt, sizeof(*rsp) + rsp->count * sizeof(rsp->sec_node[0]));
|
|
pkt_645 = proto_645_fj_build_qr_wl_resp(addr, iot_pkt_data(pkt),
|
|
(uint8_t)iot_pkt_data_len(pkt));
|
|
|
|
iot_pkt_free(result_pkt);
|
|
iot_pkt_free(pkt);
|
|
goto out;
|
|
|
|
err:
|
|
pkt_645 = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_handle_op_wl_set_rm(uint8_t cnt,
|
|
uint8_t addr[][IOT_MAC_ADDR_LEN])
|
|
{
|
|
uint8_t i = 0;
|
|
uint32_t ret = ERR_FAIL;
|
|
|
|
for (i = 0; i < cnt; ++i) {
|
|
iot_sg_printf("%d %02X:%02X:%02X:%02X:%02X:%02X\n", i, addr[i][0],
|
|
addr[i][1], addr[i][2], addr[i][3], addr[i][4], addr[i][5]);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_CCO_RMV_SEC_NODE_ADDR, 7, i, addr[i][0], addr[i][1],
|
|
addr[i][2], addr[i][3], addr[i][4], addr[i][5]);
|
|
}
|
|
|
|
if (cnt == 0) {
|
|
iot_sg_cco_clear_all_wl_addr();
|
|
return ERR_OK;
|
|
}
|
|
|
|
for (i = 0; i < cnt; ++i) {
|
|
if (iot_sg_cco_wl_entry_exist(addr[i])) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cnt != i) {
|
|
/* to delete this mac address from WHITELIST */
|
|
iot_sg_cco_remove_wl_addr(IOT_SG_CALLER_TYPE_CCTT, cnt - i,
|
|
(uint8_t *)addr[i]);
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_handle_op_wl_set_add(uint8_t count,
|
|
uint8_t addr[][IOT_MAC_ADDR_LEN])
|
|
{
|
|
iot_pkt_t *pkt;
|
|
uint8_t add_cnt = 0;
|
|
iot_sg_wl_op_info_t *wl_req;
|
|
iot_sg_wl_entry_info_t node;
|
|
uint32_t data_len = 0, ret = ERR_FAIL;
|
|
uint16_t cnt, i, j;
|
|
|
|
if (count == 0) {
|
|
goto out;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (!iot_mac_addr_valid(addr[i]) || iot_mac_is_bcast(addr[i]) ||
|
|
proto_645_is_bcast(addr[i])) {
|
|
/* secondary node addr is invalid */
|
|
goto out;
|
|
}
|
|
|
|
for (j = i + 1; j < count; j++) {
|
|
if (iot_mac_addr_cmp(addr[i], addr[j])) {
|
|
/* a duplicate secondary node address in a message */
|
|
ret = ERR_EXIST;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
ret = iot_sg_get_wl_entry_info_by_mac(addr[i], &node);
|
|
if (ret) {
|
|
add_cnt++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!add_cnt) {
|
|
/* all the secondary node addresses are duplicated. */
|
|
ret = ERR_EXIST;
|
|
goto out;
|
|
}
|
|
|
|
if (add_cnt > 0 && (add_cnt > iot_sg_cco_get_free_wl_entry_count())) {
|
|
ret = ERR_NOSUPP;
|
|
goto out;
|
|
}
|
|
add_cnt = 0;
|
|
do {
|
|
cnt = (IOT_SG_CCO_MSG_LONG_BUF_SIZE - sizeof(*wl_req)) /
|
|
sizeof(wl_req->node_info[0]);
|
|
cnt = min(cnt, count - add_cnt);
|
|
data_len = sizeof(*wl_req) + sizeof(wl_req->node_info[0]) * cnt;
|
|
pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
wl_req = (iot_sg_wl_op_info_t *)iot_pkt_data(pkt);
|
|
wl_req->count = (uint8_t)cnt;
|
|
wl_req->rm_ts = 0;
|
|
for (i = 0, j = add_cnt; i < cnt; ++i, ++j) {
|
|
iot_mac_addr_cpy(wl_req->node_info[i].mac, addr[j]);
|
|
wl_req->node_info[i].node_index = IOT_SG_CCO_WL_INVAL_INDEX;
|
|
iot_sg_printf("%lu %lu %02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
i, wl_req->node_info[i].proto_type,
|
|
wl_req->node_info[i].mac[0], wl_req->node_info[i].mac[1],
|
|
wl_req->node_info[i].mac[2], wl_req->node_info[i].mac[3],
|
|
wl_req->node_info[i].mac[4], wl_req->node_info[i].mac[5]);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_CCO_ADD_SEC_NODE_ADDR, 8,
|
|
i, wl_req->node_info[i].proto_type,
|
|
wl_req->node_info[i].mac[0], wl_req->node_info[i].mac[1],
|
|
wl_req->node_info[i].mac[2], wl_req->node_info[i].mac[3],
|
|
wl_req->node_info[i].mac[4], wl_req->node_info[i].mac[5]);
|
|
}
|
|
|
|
iot_pkt_put(pkt, data_len);
|
|
/* to add this mac address into WHITELIST */
|
|
iot_sg_cco_add_wl_addr(IOT_SG_CALLER_TYPE_CCTT, pkt);
|
|
add_cnt += (uint8_t)cnt;
|
|
} while (count > add_cnt);
|
|
ret = ERR_OK;
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_op_wl_set(uint8_t *addr, uint8_t *data,
|
|
uint8_t len)
|
|
{
|
|
uint32_t ret = ERR_FAIL;
|
|
iot_pkt_t *pkt_645;
|
|
uint8_t reason = PROTO_645_FJ_ERR_OTHER;
|
|
proto_645_fj_write_data_head_t *write_data =
|
|
(proto_645_fj_write_data_head_t *)data;
|
|
proto_645_fj_set_wl_info_t *req =
|
|
(proto_645_fj_set_wl_info_t *)write_data->data;
|
|
|
|
if (len < sizeof(*write_data) + sizeof(*req) +
|
|
req->count * IOT_MAC_ADDR_LEN) {
|
|
goto err;
|
|
}
|
|
|
|
if (req->op) {
|
|
ret = iot_gw_drv_fj_handle_op_wl_set_add(req->count, req->mac_addr);
|
|
} else {
|
|
ret = iot_gw_drv_fj_handle_op_wl_set_rm(req->count, req->mac_addr);
|
|
}
|
|
|
|
if (ret == ERR_OK) {
|
|
pkt_645 = proto_645_2007_build_ack_msg(addr,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
goto out;
|
|
}
|
|
|
|
err:
|
|
if (ret == ERR_EXIST) {
|
|
reason = PROTO_645_FJ_ERR_MAC_REPET;
|
|
}
|
|
pkt_645 = proto_645_2007_build_nack_msg(reason, addr,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_op_wl(uint8_t *addr, uint8_t fn,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
if (fn == PROTO_645_2007_FN_WRITE_DATA) {
|
|
pkt = iot_gw_drv_fj_handle_op_wl_set(addr, data, len);
|
|
} else if (fn == PROTO_645_2007_FN_READ_DATA) {
|
|
pkt = iot_gw_drv_fj_handle_op_wl_qr(addr, data, len);
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_set_major_node_mac(uint8_t *addr, uint8_t *data,
|
|
uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_fj_write_data_head_t *write_data;
|
|
proto_645_fj_set_major_node_mac_t *req;
|
|
|
|
if (len < sizeof(*write_data) + sizeof(*req)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
return pkt;
|
|
}
|
|
write_data = (proto_645_fj_write_data_head_t *)data;
|
|
req = (proto_645_fj_set_major_node_mac_t *)write_data->data;
|
|
|
|
/* the mac is valid when all mac cell is 0x00 or 0xFF, */
|
|
if (iot_mac_is_bcast(req->mac) || (!iot_mac_addr_valid(req->mac)) ||
|
|
(proto_645_is_bcast(req->mac))) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_MAC_INVALID, addr,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
return pkt;
|
|
}
|
|
|
|
/* save major node address */
|
|
iot_sg_cco_set_major_node_mac(req->mac);
|
|
/* set mac address of CCo */
|
|
iot_mac_addr_reverse(req->mac);
|
|
if (ERR_OK == iot_sg_set_cco_mac_addr(req->mac, 1)) {
|
|
/* don't trigger network formation if mac addr is set successfully. */
|
|
cctt_drv_stop_net_formation_delay();
|
|
}
|
|
|
|
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_major_node_mac(uint8_t *addr, uint8_t fn,
|
|
uint8_t *data, uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
if (fn == PROTO_645_2007_FN_WRITE_DATA) {
|
|
pkt = iot_gw_drv_fj_set_major_node_mac(addr, data, len);
|
|
} else if (fn == PROTO_645_2007_FN_READ_DATA) {
|
|
pkt = proto_645_fj_build_qr_major_node_mac(addr);
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_proto_645_file_send_type1(uint8_t *addr,
|
|
uint8_t *data, uint8_t data_len)
|
|
{
|
|
iot_pkt_t *pkt_645 = NULL;
|
|
uint32_t result = ERR_OK;
|
|
uint8_t file_type = IOT_SG_FILE_TYPE_STA;
|
|
uint8_t work_type = 0;
|
|
proto_645_fj_send_file_dl_t *req = (proto_645_fj_send_file_dl_t*)data;
|
|
uint32_t ack_no = req->seg_index;
|
|
|
|
if (data_len < sizeof(proto_645_fj_send_file_dl_t)) {
|
|
goto err;
|
|
}
|
|
|
|
iot_sg_printf("sg_upgrade: action = %d, seg_len = %d, file_cmd = %d, "
|
|
"is_last = %d, seg_index/total_set_cnt = %d/%d. sn = %d\n",
|
|
req->action, req->cur_seg_len, req->file_cmd,
|
|
req->is_last_seg, req->seg_index, req->total_seg_cnt, 0);
|
|
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_UPGRADE_FILE_TYPE, 7,
|
|
req->action, req->cur_seg_len, req->file_cmd,
|
|
req->is_last_seg, req->seg_index, req->total_seg_cnt, 0);
|
|
|
|
work_type = iot_sg_cco_get_router_work_type();
|
|
|
|
if ((IOT_SG_CCO_ROUTER_WORK_TYPE_SM == work_type) ||
|
|
((IOT_SG_CCO_ROUTER_WORK_TYPE_MR == work_type) &&
|
|
(iot_sg_get_rt_mr_state() & IOT_SG_CALLER_TYPE_CCTT))) {
|
|
/* search meter, rt mr, con mr, upgrading, only 1 of these 4
|
|
* kinds of operations is allowed at any time. cctt mr is
|
|
* allowed when upgrading.
|
|
*/
|
|
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
|
|
goto out;
|
|
}
|
|
|
|
switch (req->action) {
|
|
case PROTO_645_FJ_UPGRADE_CLEAR_FILE:
|
|
{
|
|
iot_sg_cco_handle_stop_upgrade(1);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_UPGRADE_CCO_STA_MODULE:
|
|
case PROTO_645_FJ_UPGRADE_LOCAL_MODULE:
|
|
file_type = IOT_SG_FILE_TYPE_CCO;
|
|
case PROTO_645_FJ_UPGRADE_STA_MODULE:
|
|
{
|
|
if (req->total_seg_cnt == 0 ||
|
|
req->cur_seg_len == 0) {
|
|
/* reject invalid data packet. */
|
|
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
|
|
break;
|
|
}
|
|
|
|
if (0 == req->seg_index) {
|
|
result = iot_sg_cco_start_recv_upgrade(file_type, 0, NULL,
|
|
req->cur_seg_len, req->total_seg_cnt, 0, 0, 0);
|
|
if (ERR_OK != result) {
|
|
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
result = iot_sg_cco_handle_file_segment(req->data,
|
|
req->cur_seg_len, req->seg_index);
|
|
if (ERR_OK != result) {
|
|
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
pkt_645 = proto_645_fj_build_upgrade_send_file_ack(addr, ack_no);
|
|
goto out;
|
|
|
|
err:
|
|
pkt_645 = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_opposite_phase(uint8_t *addr)
|
|
{
|
|
iot_sg_cco_net_node_info_t info = { 0 };
|
|
|
|
if (ERR_OK != iot_sg_cco_get_net_node_info_by_mac(addr, &info)) {
|
|
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_NOT_IN_NET, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return proto_645_fj_build_opposite_phase_info(addr,
|
|
PROTO_645_2007_FN_READ_DATA, info.opposite_phase);
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_phase_info(uint8_t *addr)
|
|
{
|
|
iot_sg_cco_net_node_info_t info = { 0 };
|
|
|
|
if (ERR_OK != iot_sg_cco_get_net_node_info_by_mac(addr, &info)) {
|
|
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_NOT_IN_NET, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return proto_645_fj_build_qr_phase_info(addr, info.phy_phase1);
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_reset_cnt(uint8_t *addr)
|
|
{
|
|
uint16_t reset_cnt = 0;
|
|
|
|
reset_cnt = (uint16_t)(iot_board_get_reset_count(SYSTEM_RESET_WDT) +
|
|
iot_board_get_reset_count(SYSTEM_RESET_SOFT) +
|
|
iot_board_get_reset_count(SYSTEM_RESET_PWR));
|
|
|
|
return proto_645_fj_build_module_reset_cnt(addr, reset_cnt);
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_pd_cnt(uint8_t *addr)
|
|
{
|
|
uint16_t pd_cnt = 0;
|
|
|
|
iot_sg_cco_get_reset_info_from_pib(IOT_SG_CCO_RESET_INFO_OP_PD_CNT,
|
|
(uint8_t *)&pd_cnt);
|
|
|
|
return proto_645_fj_build_module_pd_cnt(addr, pd_cnt);
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_qr_pd_valid_time(uint8_t *addr,
|
|
uint8_t fn, uint8_t *data, uint8_t len)
|
|
{
|
|
uint8_t valid_time = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_fj_write_data_head_t *write_data;
|
|
proto_645_fj_pd_valid_time_t *req;
|
|
|
|
if (fn == PROTO_645_2007_FN_WRITE_DATA) {
|
|
if (len < sizeof(*req) + sizeof(*write_data)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
return pkt;
|
|
}
|
|
|
|
write_data = (proto_645_fj_write_data_head_t *)data;
|
|
req = (proto_645_fj_pd_valid_time_t *)write_data->data;
|
|
if (!req->pd_valid_time) {
|
|
req->pd_valid_time = IOT_SG_CCO_PD_DEFAULT_VALID_TIME;
|
|
}
|
|
|
|
if (req->pd_valid_time > IOT_SG_CCO_PD_MAX_VALID_TIME) {
|
|
req->pd_valid_time = IOT_SG_CCO_PD_MAX_VALID_TIME;
|
|
}
|
|
iot_sg_cco_update_reset_info_to_pib(
|
|
IOT_SG_CCO_RESET_INFO_OP_PD_VALID_TIME, &req->pd_valid_time);
|
|
pkt = proto_645_2007_build_ack_msg(addr, fn);
|
|
} else if (fn == PROTO_645_2007_FN_READ_DATA) {
|
|
iot_sg_cco_get_reset_info_from_pib(
|
|
IOT_SG_CCO_RESET_INFO_OP_PD_VALID_TIME, &valid_time);
|
|
pkt = proto_645_fj_build_pd_valid_time(addr, valid_time);
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_proto_645_file_query_bitmap(uint8_t *addr)
|
|
{
|
|
iot_pkt_t *pkt_645 = NULL;
|
|
iot_sg_upgrade_info_t query_info = { 0 };
|
|
uint16_t max_array_index;
|
|
uint8_t bitmap[PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN] = { 0 };
|
|
uint16_t bitmap_size;
|
|
uint16_t start_array_index;
|
|
uint32_t query_bitmap_cbs;
|
|
uint32_t bitmap_cbs = 0;
|
|
uint8_t recvdone = 0;
|
|
|
|
iot_sg_cco_query_upgrade_info(&query_info);
|
|
|
|
if (query_info.state == IOT_SG_CCO_UPGRADE_ST_IDLE) {
|
|
/* recv done */
|
|
start_array_index = 0;
|
|
recvdone = 0;
|
|
goto done;
|
|
}
|
|
|
|
/* upgrade file segment bitmap size */
|
|
bitmap_size = (query_info.block_cnt + 7) >> 3;
|
|
/* upgrade file segment bitmap array size */
|
|
max_array_index = (PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN - 1 + bitmap_size) /
|
|
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN;
|
|
|
|
for (start_array_index = 0; start_array_index < max_array_index - 1;
|
|
start_array_index++) {
|
|
bitmap_size = iot_sg_cco_query_upgrade_bitmap_info(bitmap,
|
|
start_array_index * PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN,
|
|
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
|
|
query_bitmap_cbs = iot_bitmap_cbs(bitmap, bitmap_size);
|
|
if (query_bitmap_cbs !=
|
|
(PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN << 3)) {
|
|
/* not recv done */
|
|
iot_bitmap_reverse(bitmap, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
|
|
goto out;
|
|
}
|
|
bitmap_cbs += query_bitmap_cbs;
|
|
}
|
|
|
|
bitmap_size = iot_sg_cco_query_upgrade_bitmap_info(bitmap,
|
|
start_array_index * PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN,
|
|
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
|
|
query_bitmap_cbs = iot_bitmap_cbs(bitmap, bitmap_size);
|
|
bitmap_cbs += query_bitmap_cbs;
|
|
if (bitmap_cbs >= query_info.block_cnt) {
|
|
/* recv done */
|
|
recvdone = 1;
|
|
} else {
|
|
/* not recv done */
|
|
iot_bitmap_reverse(bitmap, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
|
|
goto out;
|
|
}
|
|
done:
|
|
if (recvdone) {
|
|
os_mem_set(bitmap, 0 , PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
|
|
} else {
|
|
os_mem_set(bitmap, 0xFF, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
|
|
}
|
|
out:
|
|
pkt_645 = proto_645_fj_build_upgrade_query_file_ack(addr, start_array_index,
|
|
bitmap);
|
|
return pkt_645;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_proto_645_query_work_power(uint8_t *addr)
|
|
{
|
|
proto_645_fj_qr_work_power_t rsp;
|
|
|
|
rsp.work_power = PROTO_645_FJ_WORK_POWER;
|
|
return proto_645_fj_build_work_power_rpt(addr, (uint8_t *)&rsp,
|
|
sizeof(rsp));
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_get_di_data(uint8_t *cco_mac, uint32_t di,
|
|
uint8_t *addr, uint8_t *data_645, uint8_t data_len_645, uint8_t fn,
|
|
uint8_t is_multi)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
switch (di) {
|
|
case PROTO_645_FJ_DI_TSFM_DETECT_START:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_tsfm_start(cco_mac, fn, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_TSFM_RESULT_RPT:
|
|
{
|
|
pkt = proto_645_fj_build_tsfm_detect_result(cco_mac,
|
|
PROTO_645_2007_FN_READ_DATA,
|
|
(uint16_t)(iot_sg_cco_get_tsfm_detect_used_time() / 60),
|
|
drv_data->fj_data.same_tsfm_cnt, drv_data->fj_data.diff_tsfm_cnt);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_DIFF_TSFM_NODE:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_diff_tsfm_node(cco_mac, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_NODE_REG_START:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_node_reg_start(cco_mac, fn, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_NOT_REG_NODE:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_not_reg_node(cco_mac, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_CHIP_ID:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_chip_id(addr);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_MOD_ID:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_mod_id(addr);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_MOD_VER:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_mod_ver(addr);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_OPPOSITE_PHASE:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_opposite_phase(addr);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_PHASE_INFO:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_phase_info(addr);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_TOPO:
|
|
{
|
|
if (is_multi) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
break;
|
|
}
|
|
if (iot_gw_drv_fj_proto_645_qr_topo(data_645, data_len_645) != ERR_OK) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_NB_NW_INFO:
|
|
{
|
|
if (is_multi) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
break;
|
|
}
|
|
iot_sg_cco_get_nb_nw_info_msg(CCTT_REQ_ID_DRV_GET_NB_NW_INFO_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_FREQ_BAND:
|
|
{
|
|
if (is_multi) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
break;
|
|
}
|
|
pkt = iot_gw_drv_fj_handle_band(cco_mac, fn, data_645, data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_CHIP_ID_F112:
|
|
{
|
|
pkt = iot_gw_drv_fj_proto_645_qr_chip_id_info(cco_mac, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_OP_WL:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_op_wl(cco_mac, fn, data_645, data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_MAJOR_NODE_MAC:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_major_node_mac(cco_mac, fn, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_UPGRADE_SEND_FILE:
|
|
{
|
|
if (is_multi) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
break;
|
|
}
|
|
pkt = iot_gw_drv_fj_proto_645_file_send_type1(cco_mac, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_MODULE_RESET_CNT:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_reset_cnt(cco_mac);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_PD_CNT:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_pd_cnt(cco_mac);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_PD_EVT_VALID_TIME:
|
|
{
|
|
pkt = iot_gw_drv_fj_handle_qr_pd_valid_time(cco_mac, fn, data_645,
|
|
data_len_645);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_UPGRADE_REQ_FILE:
|
|
{
|
|
if (is_multi) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
break;
|
|
}
|
|
pkt = iot_gw_drv_fj_proto_645_file_query_bitmap(cco_mac);
|
|
break;
|
|
}
|
|
case PROTO_645_FJ_DI_QR_MOD_WORK_V:
|
|
{
|
|
pkt = iot_gw_drv_fj_proto_645_query_work_power(cco_mac);
|
|
break;
|
|
}
|
|
default:
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
fn);
|
|
break;
|
|
}
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_get_multi_di_data(uint8_t *di_data,
|
|
uint8_t di_data_len, uint8_t *data, uint8_t *data_len, uint8_t *addr)
|
|
{
|
|
uint32_t di;
|
|
uint32_t ret = ERR_FAIL;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_header_t *hdr;
|
|
proto_645_fj_multi_data_t *multi_data = (proto_645_fj_multi_data_t *)data;
|
|
uint8_t *data_645;
|
|
uint8_t data_645_len = di_data_len - PROTO_645_2007_DI_LEN;
|
|
|
|
di = proto_645_2007_byte_to_di(di_data);
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
data_645 = di_data + PROTO_645_2007_DI_LEN;
|
|
pkt = iot_gw_drv_fj_get_di_data(cco_mac, di, addr, data_645, data_645_len,
|
|
PROTO_645_2007_FN_READ_DATA, 1);
|
|
|
|
if (pkt) {
|
|
hdr = proto_645_format_check(iot_pkt_data(pkt), iot_pkt_data_len(pkt),
|
|
PROTO_645_DIR_SLAVE);
|
|
proto_645_get_di_by_sub33(hdr->data, (uint8_t)hdr->len,
|
|
PROTO_645_2007_ID, &di);
|
|
proto_645_sub33_handle(hdr->data, hdr->len);
|
|
if (hdr->control.ack == PROTO_645_ACK_NORMAL) {
|
|
if (hdr->len + *data_len + sizeof(multi_data->data_len)
|
|
<= IOT_SG_DRV_FJ_MULTI_DI_MAX_LEN) {
|
|
multi_data->data_len = hdr->len;
|
|
os_mem_cpy(multi_data->data , hdr->data, hdr->len);
|
|
*data_len = *data_len + hdr->len + sizeof(*multi_data);
|
|
ret = ERR_OK;
|
|
} else {
|
|
ret = ERR_NOSUPP;
|
|
}
|
|
} else {
|
|
if (*data_len + sizeof(multi_data->data_len) + PROTO_645_2007_DI_LEN
|
|
< IOT_SG_DRV_FJ_MULTI_DI_MAX_LEN) {
|
|
multi_data->data_len = PROTO_645_2007_DI_LEN;
|
|
os_mem_cpy(multi_data->data , di_data, PROTO_645_2007_DI_LEN);
|
|
*data_len = *data_len + PROTO_645_2007_DI_LEN +
|
|
sizeof(*multi_data);
|
|
ret = ERR_OK;
|
|
} else {
|
|
ret = ERR_NOSUPP;
|
|
}
|
|
}
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static iot_pkt_t *iot_gw_drv_fj_handle_multi_di(uint8_t *cco_addr,
|
|
uint8_t *data, uint8_t len, uint8_t *addr)
|
|
{
|
|
iot_pkt_t *pkt = NULL, *pkt_645 = NULL;
|
|
uint8_t *pkt_data, *data_ptr;
|
|
uint8_t pkt_data_len = 0;
|
|
uint32_t ret = ERR_FAIL;
|
|
proto_645_fj_multi_di_read_t *req = (proto_645_fj_multi_di_read_t *)data;
|
|
proto_645_fj_multi_di_list_t *list_data;
|
|
proto_645_fj_multi_di_t *rsp;
|
|
uint8_t i;
|
|
|
|
if (len < sizeof(*req)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, cco_addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
return pkt;
|
|
}
|
|
|
|
if (!req->di_cnt) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_addr,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
return pkt;
|
|
}
|
|
|
|
if (req->di_cnt > IOT_SG_DRV_FJ_MULTI_DI_MAX_CNT) {
|
|
req->di_cnt = IOT_SG_DRV_FJ_MULTI_DI_MAX_CNT;
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(IOT_SG_DRV_FJ_MULTI_DI_MAX_LEN, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
pkt_data = iot_pkt_data(pkt);
|
|
pkt_data_len = sizeof(rsp->di_cnt);
|
|
rsp = (proto_645_fj_multi_di_t *)pkt_data;
|
|
list_data = (proto_645_fj_multi_di_list_t *)req->di_list;
|
|
|
|
for (i = 0; i < req->di_cnt; ++i) {
|
|
data_ptr = pkt_data + pkt_data_len;
|
|
ret = iot_gw_drv_fj_get_multi_di_data(list_data->data, list_data->len,
|
|
data_ptr, &pkt_data_len, addr);
|
|
if (ret == ERR_NOSUPP) {
|
|
goto out;
|
|
}
|
|
list_data = (proto_645_fj_multi_di_list_t *)(list_data->data +
|
|
list_data->len);
|
|
rsp->di_cnt++;
|
|
}
|
|
|
|
out:
|
|
pkt_645 = proto_645_fj_build_multi_di_rpt(cco_addr, pkt_data, pkt_data_len);
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return pkt_645;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_process_raw_cmd(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
uint32_t di, ret = ERR_FAIL;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_header_t *hdr;
|
|
uint8_t *data_645;
|
|
uint8_t data_len_645;
|
|
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
hdr = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
|
|
if (!hdr) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
PROTO_645_2007_FN_READ_DATA);
|
|
goto out;
|
|
}
|
|
if (ERR_OK != proto_645_get_di_by_sub33(hdr->data, (uint8_t)hdr->len,
|
|
PROTO_645_2007_ID, &di)) {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
hdr->control.fn);
|
|
goto out;
|
|
}
|
|
proto_645_sub33_handle(hdr->data, hdr->len);
|
|
data_645 = hdr->data + PROTO_645_2007_DI_LEN;
|
|
data_len_645 = hdr->len - PROTO_645_2007_DI_LEN;
|
|
if (di == PROTO_645_FJ_MULTI_DI_READ) {
|
|
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
|
|
pkt = iot_gw_drv_fj_handle_multi_di(cco_mac, data_645, data_len_645,
|
|
hdr->addr);
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
hdr->control.fn);
|
|
}
|
|
} else {
|
|
pkt = iot_gw_drv_fj_get_di_data(cco_mac, di, hdr->addr, data_645,
|
|
data_len_645, hdr->control.fn, 0);
|
|
}
|
|
|
|
out:
|
|
if (pkt) {
|
|
iot_gw_drv_fj_meter_data_52h_f1(iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), sn, cco_mac,
|
|
PROTO_3762_FJ_OBJ_CCO);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cache_obj_type(uint8_t sn, uint8_t obj_type)
|
|
{
|
|
uint8_t i;
|
|
for (i = 0; i < CCTT_DRV_CACHE_OBJ_TYPE_MAX_CNT; ++i) {
|
|
if (!drv_data->fj_data.obj_type_buf[i].used_flag) {
|
|
drv_data->fj_data.obj_type_buf[i].sn = sn;
|
|
drv_data->fj_data.obj_type_buf[i].obj_type = obj_type;
|
|
drv_data->fj_data.obj_type_buf[i].used_flag = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint8_t iot_gw_drv_fj_get_obj_type(uint8_t sn, uint8_t clear)
|
|
{
|
|
uint8_t i, obj_type = PROTO_3762_FJ_OBJ_RSVD;
|
|
for (i = 0; i < CCTT_DRV_CACHE_OBJ_TYPE_MAX_CNT; ++i) {
|
|
if (drv_data->fj_data.obj_type_buf[i].used_flag &&
|
|
(drv_data->fj_data.obj_type_buf[i].sn == sn)) {
|
|
if (clear) {
|
|
drv_data->fj_data.obj_type_buf[i].used_flag = 0;
|
|
}
|
|
obj_type = drv_data->fj_data.obj_type_buf[i].obj_type;
|
|
break;
|
|
}
|
|
}
|
|
return obj_type;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_handle_write_corr_time(proto_645_header_t *hdr)
|
|
{
|
|
uint32_t di;
|
|
iot_time_tm_t tm = { 0 };
|
|
proto_645_07_time_ymdhms_t *corr_time;
|
|
proto_645_fj_ntb_corr_time_t *corr_time_ntb;
|
|
|
|
if (!hdr) {
|
|
return ERR_FAIL;
|
|
}
|
|
if (ERR_OK != proto_645_get_di_by_sub33(hdr->data, (uint8_t)hdr->len,
|
|
PROTO_645_2007_ID, &di)) {
|
|
return ERR_FAIL;
|
|
}
|
|
if (di != PROTO_645_FJ_DI_MOD_TM &&
|
|
di != PROTO_645_FJ_DI_MOD_CT_NTB) {
|
|
return ERR_FAIL;
|
|
}
|
|
if (hdr->control.fn != PROTO_645_2007_FN_WRITE_DATA) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
proto_645_sub33_handle(hdr->data, hdr->len);
|
|
if (di == PROTO_645_FJ_DI_MOD_CT_NTB) {
|
|
corr_time_ntb = (proto_645_fj_ntb_corr_time_t *)(hdr->data +
|
|
sizeof(proto_645_write_data_dest_t));
|
|
tm.tm_sec = iot_bcd_to_byte(corr_time_ntb->sec);
|
|
tm.tm_min = iot_bcd_to_byte(corr_time_ntb->min);
|
|
tm.tm_hour = iot_bcd_to_byte(corr_time_ntb->hour);
|
|
tm.tm_mday = iot_bcd_to_byte(corr_time_ntb->day);
|
|
tm.tm_mon = iot_bcd_to_byte(corr_time_ntb->mon);
|
|
tm.tm_year = 2000 + iot_bcd_to_byte(corr_time_ntb->year);
|
|
corr_time_ntb->ntb = iot_sg_cco_get_ntb();
|
|
} else {
|
|
corr_time = (proto_645_07_time_ymdhms_t *)(hdr->data +
|
|
sizeof(proto_645_write_data_dest_t));
|
|
tm.tm_sec = iot_bcd_to_byte(corr_time->second);
|
|
tm.tm_min = iot_bcd_to_byte(corr_time->minute);
|
|
tm.tm_hour = iot_bcd_to_byte(corr_time->hour);
|
|
tm.tm_mday = iot_bcd_to_byte(corr_time->day);
|
|
tm.tm_mon = iot_bcd_to_byte(corr_time->month);
|
|
tm.tm_year = 2000 + iot_bcd_to_byte(corr_time->year);
|
|
}
|
|
iot_rtc_set(&tm);
|
|
proto_645_add33_handle(hdr->data, hdr->len);
|
|
proto_645_tail_init(hdr);
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_write_corr_time_check(uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t obj_type, uint8_t *comm_addr)
|
|
{
|
|
proto_645_header_t *hdr;
|
|
iot_pkt_t *pkt;
|
|
uint8_t sta_mac[IOT_MAC_ADDR_LEN];
|
|
|
|
hdr = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
|
|
if (iot_gw_drv_fj_handle_write_corr_time(hdr) != ERR_OK) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
if (proto_645_is_bcast(hdr->addr)) {
|
|
iot_sg_broadcast_data(IOT_SG_CALLER_TYPE_CCTT, 0, data, len, NULL);
|
|
} else {
|
|
if(iot_sg_cco_meter_mac_to_sta_mac(hdr->addr, sta_mac)) {
|
|
iot_mac_addr_cpy(sta_mac, hdr->addr);
|
|
iot_mac_addr_reverse(sta_mac);
|
|
}
|
|
iot_sg_broadcast_data(IOT_SG_CALLER_TYPE_CCTT, 0, data, len, sta_mac);
|
|
}
|
|
|
|
pkt = proto_645_2007_build_ack_msg(hdr->addr, hdr->control.fn);
|
|
if (pkt) {
|
|
iot_gw_drv_fj_meter_data_52h_f1(iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), sn, comm_addr, obj_type);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_cmd_52h_f1(uint8_t *data, uint16_t len,
|
|
uint8_t sn, iot_pkt_t *pkt)
|
|
{
|
|
(void)sn;
|
|
uint32_t ret_val;
|
|
uint32_t consumed = 0;
|
|
uint8_t reason;
|
|
uint8_t dest_mac[IOT_MAC_ADDR_LEN];
|
|
uint8_t src_mac[IOT_MAC_ADDR_LEN];
|
|
afn52_fn01_data_fwd_dl_t *req_data = (afn52_fn01_data_fwd_dl_t *)data;
|
|
|
|
if (len < sizeof(*req_data)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
len -= sizeof(*req_data);
|
|
if (len < req_data->data_len) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
if (!iot_sg_cco_is_ready()) {
|
|
reason = MASTER_IS_BUSY;
|
|
goto err;
|
|
}
|
|
if (!iot_sg_cco_get_power_status()) {
|
|
reason = MASTER_IS_BUSY;
|
|
goto err;
|
|
}
|
|
iot_sg_cco_get_major_node_mac(src_mac);
|
|
if (req_data->obj_type == PROTO_3762_FJ_OBJ_CCO) {
|
|
if (!iot_mac_addr_cmp(req_data->mac_addr, src_mac)) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
iot_gw_drv_fj_process_raw_cmd(req_data->data, req_data->data_len, sn);
|
|
goto out;
|
|
}
|
|
|
|
if (iot_sg_cco_get_mr_pkt_mac(dest_mac, req_data->data,
|
|
req_data->data_len, PROTO_TYPE_RAW_DATA) != ERR_OK) {
|
|
iot_mac_addr_cpy(dest_mac, req_data->mac_addr);
|
|
}
|
|
if (iot_gw_drv_fj_write_corr_time_check(req_data->data, req_data->data_len,
|
|
sn, req_data->obj_type, req_data->mac_addr) == ERR_OK) {
|
|
return consumed;
|
|
}
|
|
if (iot_sg_cco_get_wl_cnt() && iot_sg_cco_wl_is_enabled() &&
|
|
!iot_sg_cco_wl_entry_exist(dest_mac) &&
|
|
!iot_sg_cco_wlii_entry_exist(dest_mac)) {
|
|
/* white list is not empty, meter is not in white list. */
|
|
reason = METER_NO_NOT_EXIST;
|
|
goto err;
|
|
}
|
|
|
|
if (iot_sg_cco_cache_has_sg_mr_cmd_ex(dest_mac, sn)) {
|
|
iot_sg_printf("duplicate mac %02X:%02X:%02X:%02X:%02X:%02X, "
|
|
"sn=0n%lu\n", dest_mac[0], dest_mac[1], dest_mac[2],
|
|
dest_mac[3], dest_mac[4], dest_mac[5], sn);
|
|
iot_sg_cco_add_null_mr_data(IOT_SG_CALLER_TYPE_CCTT,
|
|
sn, PROTO_3762_FJ_AFN_52, src_mac, dest_mac, IOT_SG_RMT_CCTT_CON,
|
|
PROTO_TYPE_RAW_DATA);
|
|
goto out;
|
|
}
|
|
|
|
iot_gw_drv_fj_cache_obj_type(sn, req_data->obj_type);
|
|
iot_mac_addr_cpy(drv_data->cur_mr_pm, dest_mac);
|
|
iot_counter_inc(drv_data->mr_pkg_statistics.cctt_mr_cnt);
|
|
iot_pkt_set_data(pkt, req_data->data);
|
|
iot_pkt_set_tail(pkt, req_data->data + req_data->data_len);
|
|
ret_val = iot_sg_cco_cache_sg_mr_cmd(IOT_SG_RMT_CCTT_CON, sn,
|
|
PROTO_3762_FJ_AFN_52, PROTO_TYPE_RAW_DATA, src_mac, dest_mac, pkt,
|
|
IOT_SG_CALLER_TYPE_CCTT, CCTT_DRV_PRIO_MR,
|
|
iot_sg_cco_get_mr_timeout(IOT_SG_CALLER_TYPE_CCTT, IOT_SG_RMT_CCTT_CON),
|
|
1, IOT_SG_INVALID_TASK_ID, 1, 0);
|
|
if (ERR_OK == ret_val) {
|
|
consumed = 1;
|
|
}
|
|
|
|
goto out;
|
|
err:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
out:
|
|
return consumed;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_handle_52h_data_fwd(uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t fn, iot_pkt_t *pkt)
|
|
{
|
|
uint32_t pkt_consumed = 0;
|
|
switch (fn) {
|
|
case PROTO_3762_F1:
|
|
{
|
|
pkt_consumed = iot_gw_drv_fj_cmd_52h_f1(data, len, sn, pkt);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
break;
|
|
}
|
|
return pkt_consumed;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_53h_f1(uint8_t sn)
|
|
{
|
|
afn53_fn01_predict_mr_param_qr_t req = { 0 };
|
|
|
|
req.max_cnt = IOT_SG_CCO_APP_WLII_MAX_NUM;
|
|
req.mr_cnt = 1;
|
|
iot_gw_drv_fj_send_uart(0, PROTO_3762_FJ_AFN_53, PROTO_3762_F1,
|
|
(uint8_t *)&req, sizeof(req), sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_53h_f2(uint8_t sn)
|
|
{
|
|
afn53_fn02_cco_mac_t mac = {0};
|
|
|
|
iot_sg_cco_get_major_node_mac(mac.cco_mac);
|
|
iot_gw_drv_fj_send_uart(0, PROTO_3762_FJ_AFN_53, PROTO_3762_F2,
|
|
(uint8_t*)&mac, sizeof(mac), sn);
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_check_object_type(uint8_t obj_type)
|
|
{
|
|
|
|
if (obj_type != PROTO_3762_FJ_OBJ_STA &&
|
|
obj_type != PROTO_3762_FJ_OBJ_COLLECTOR &&
|
|
obj_type != PROTO_3762_FJ_OBJ_CCO) {
|
|
return ERR_FAIL;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_53h_f4(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn53_fn04_hw_info_req_t *req;
|
|
afn53_fn04_hw_info_rsp_t *rsp;
|
|
iot_build_info_t ts_info;
|
|
iot_sg_cco_net_node_info_t node_info = { 0 };
|
|
uint32_t ret;
|
|
iot_pkt_t *pkt = NULL;
|
|
uint16_t pkt_len;
|
|
uint8_t reason;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
|
|
if (len < sizeof(*req)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
|
|
req = (afn53_fn04_hw_info_req_t *)data;
|
|
if (iot_gw_drv_fj_check_object_type(req->comm_obj.type) != ERR_OK) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
|
|
pkt_len = sizeof(*rsp);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (afn53_fn04_hw_info_rsp_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
|
|
iot_mac_addr_cpy(rsp->comm_obj.mac_addr, req->comm_obj.mac_addr);
|
|
rsp->comm_obj.type = req->comm_obj.type;
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
switch (req->comm_obj.type) {
|
|
case PROTO_3762_FJ_OBJ_CCO:
|
|
{
|
|
rsp->hw_info.vendor_id = iot_sg_get_vendor_id();
|
|
rsp->hw_info.chip_code = iot_sg_get_chip_code();
|
|
iot_version_get_user_build_info(&ts_info);
|
|
rsp->hw_info.day = iot_byte_to_bcd(ts_info.day);
|
|
rsp->hw_info.month = iot_byte_to_bcd(ts_info.month);
|
|
rsp->hw_info.year = iot_byte_to_bcd(ts_info.year);
|
|
rsp->hw_info.version[0] = (ts_info.sw_ver & 0xFF);
|
|
rsp->hw_info.version[1] = (ts_info.sw_ver >> 8);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_OBJ_STA:
|
|
case PROTO_3762_FJ_OBJ_COLLECTOR:
|
|
{
|
|
if (iot_mac_addr_cmp(req->comm_obj.mac_addr, cco_mac)) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
ret = iot_sg_cco_get_net_node_info_by_mac(req->comm_obj.mac_addr,
|
|
&node_info);
|
|
if (ret != ERR_OK) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
rsp->hw_info.vendor_id = node_info.vendor_id;
|
|
rsp->hw_info.chip_code = node_info.chip_code;
|
|
rsp->hw_info.day = iot_byte_to_bcd((uint8_t)node_info.build_time_d);
|
|
rsp->hw_info.month = iot_byte_to_bcd((uint8_t)node_info.build_time_m);
|
|
rsp->hw_info.year = iot_byte_to_bcd((uint8_t)node_info.build_time_y);
|
|
rsp->hw_info.version[0] = (node_info.sw_version & 0xFF);
|
|
rsp->hw_info.version[1] = (node_info.sw_version >> 8);
|
|
break;
|
|
}
|
|
default:
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
|
|
iot_pkt_put(pkt, pkt_len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_53, PROTO_3762_F4, pkt,
|
|
sn);
|
|
return;
|
|
err:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
}
|
|
|
|
static uint8_t iot_gw_drv_fj_is_report_phy_phase(uint8_t phase,
|
|
uint8_t opposite_3p, uint8_t pm_type)
|
|
{
|
|
uint8_t lack_phase;
|
|
|
|
if (pm_type == 0) {
|
|
return 1;
|
|
}
|
|
|
|
lack_phase = iot_sg_cco_is_lack_phase(phase, pm_type);
|
|
/* the three phase meter is lack of phase, and the meter is
|
|
* L/N reversed, cco don't report phase to cctt.
|
|
*/
|
|
if (lack_phase && opposite_3p) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_53h_f5(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn53_fn05_phase_req_t *req;
|
|
afn53_fn05_phase_rsp_t *rsp;
|
|
uint8_t reason;
|
|
iot_pkt_t *pkt = NULL;
|
|
uint16_t pkt_len;
|
|
iot_sg_cco_net_node_info_t node_info = { 0 };
|
|
uint32_t ret;
|
|
|
|
if (len < sizeof(*req)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
|
|
req = (afn53_fn05_phase_req_t *)data;
|
|
if (iot_gw_drv_fj_check_object_type(req->comm_obj.type) != ERR_OK) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
|
|
pkt_len = sizeof(*rsp);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (afn53_fn05_phase_rsp_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
|
|
iot_mac_addr_cpy(rsp->comm_obj.mac_addr, req->comm_obj.mac_addr);
|
|
rsp->comm_obj.type = req->comm_obj.type;
|
|
switch (req->comm_obj.type) {
|
|
case PROTO_3762_FJ_OBJ_CCO:
|
|
{
|
|
rsp->phy_phase = PROTO_SG_PHASE_A;
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_OBJ_STA:
|
|
case PROTO_3762_FJ_OBJ_COLLECTOR:
|
|
{
|
|
ret = iot_sg_cco_get_net_node_info_by_mac(req->comm_obj.mac_addr,
|
|
&node_info);
|
|
if (ret != ERR_OK) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
if(iot_gw_drv_fj_is_report_phy_phase(node_info.phase,
|
|
node_info.opposite_3p, node_info.pm_type)) {
|
|
rsp->phy_phase = node_info.phy_phase1;
|
|
} else {
|
|
rsp->phy_phase = 0;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
|
|
iot_pkt_put(pkt, pkt_len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_53, PROTO_3762_F5, pkt,
|
|
sn);
|
|
return;
|
|
err:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_53h_f6(uint8_t sn)
|
|
{
|
|
iot_sg_cco_uart_conf_t uart_conf = { 0 };
|
|
afn53_fn06_uart_conf_t *rsp;
|
|
iot_pkt_t *pkt;
|
|
uint16_t pkt_len;
|
|
|
|
pkt_len = sizeof(*rsp);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (afn53_fn06_uart_conf_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
iot_sg_cco_get_uart_config(&uart_conf);
|
|
rsp->baud = uart_conf.baud_rate;
|
|
rsp->max_baud = uart_conf.max_baud_rate;
|
|
rsp->rec_time = uart_conf.rec_time;
|
|
iot_pkt_put(pkt, pkt_len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_53, PROTO_3762_F6, pkt,
|
|
sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_53h_f10(uint8_t sn)
|
|
{
|
|
afn53_fn10_query_proto_mode_t *pro_mode;
|
|
iot_pkt_t *pkt = NULL;
|
|
uint16_t pkt_len;
|
|
|
|
pkt_len = sizeof(*pro_mode);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
pro_mode = (afn53_fn10_query_proto_mode_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
|
|
if (drv_data->fj_data.fj_proto) {
|
|
pro_mode->proto_mode = PROTO_3762_FJ_PRO_MODE_FJ;
|
|
} else {
|
|
pro_mode->proto_mode = PROTO_3762_FJ_PRO_MODE_GW;
|
|
}
|
|
|
|
iot_pkt_put(pkt, pkt_len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_53, PROTO_3762_F10, pkt,
|
|
sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_handle_53h_data_query(uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t fn)
|
|
{
|
|
switch (fn) {
|
|
case PROTO_3762_F1:
|
|
{
|
|
iot_gw_drv_fj_cmd_53h_f1(sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F2:
|
|
{
|
|
iot_gw_drv_fj_cmd_53h_f2(sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F4:
|
|
{
|
|
iot_gw_drv_fj_cmd_53h_f4(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F5:
|
|
{
|
|
iot_gw_drv_fj_cmd_53h_f5(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F6:
|
|
{
|
|
iot_gw_drv_fj_cmd_53h_f6(sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F10:
|
|
{
|
|
iot_gw_drv_fj_cmd_53h_f10(sn);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f1(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn01_set_master_address_req_t *req;
|
|
req = (afn55_fn01_set_master_address_req_t*)data;
|
|
|
|
if (len < sizeof(*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
/* the mac is valid when all mac cell is 0x00 or 0xFF, */
|
|
if (iot_mac_is_bcast(req->mac) || (!iot_mac_addr_valid(req->mac)) ||
|
|
(proto_645_is_bcast(req->mac))) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA, sn);
|
|
return;
|
|
}
|
|
|
|
/* save major node address */
|
|
iot_sg_cco_set_major_node_mac(req->mac);
|
|
/* set mac address of CCo */
|
|
iot_mac_addr_reverse(req->mac);
|
|
if (ERR_OK == iot_sg_set_cco_mac_addr(req->mac, 1)) {
|
|
/* don't trigger network formation if mac addr is set successfully. */
|
|
cctt_drv_stop_net_formation_delay();
|
|
}
|
|
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_bcast_task_send(uint8_t *data, uint16_t len)
|
|
{
|
|
if (data && len) {
|
|
iot_sg_printf("broadcast data length = %d\n", len);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_CCO_START_BROADCAST_DATA_LEN_ID, 1, len);
|
|
iot_sg_broadcast_data(IOT_SG_CALLER_TYPE_CCTT, 0, data, len, NULL);
|
|
}
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f3(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
proto_645_header_t *hdr645;
|
|
afn55_fn03_bcast_cmd_t *req;
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *pkt_data = NULL;
|
|
|
|
if (len < sizeof(*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
req = (afn55_fn03_bcast_cmd_t *)data;
|
|
pkt = iot_pkt_alloc(req->len, IOT_SMART_GRID_MID);
|
|
if (pkt == NULL) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
pkt_data = iot_pkt_data(pkt);
|
|
|
|
hdr645 = proto_645_format_check(req->data, req->len, PROTO_645_DIR_MASTER);
|
|
if (hdr645 == NULL) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA, sn);
|
|
return;
|
|
}
|
|
/* check correct time message */
|
|
iot_gw_drv_fj_handle_write_corr_time(hdr645);
|
|
|
|
os_mem_cpy(pkt_data, req->data, req->len);
|
|
iot_pkt_put(pkt, req->len);
|
|
|
|
iot_gw_drv_dj_reset_bcast_task_param();
|
|
|
|
drv_data->fj_data.bcast_task.time = req->bcast_time;
|
|
drv_data->fj_data.bcast_task.channel_delay = 0;
|
|
drv_data->fj_data.bcast_task.bcast_pkt = pkt;
|
|
|
|
iot_sg_cco_bcast_task_start(req->bcast_time,
|
|
IOT_GW_DRV_FJ_BCAST_TASK_SEND_INTERVAL);
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f4(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn04_bcast_cmd_t *req;
|
|
|
|
if (len < sizeof(*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
req = (afn55_fn04_bcast_cmd_t *)data;
|
|
iot_gw_drv_dj_reset_bcast_task_param();
|
|
|
|
drv_data->fj_data.bcast_task.time = req->bcast_time;
|
|
drv_data->fj_data.bcast_task.channel_delay = 1;
|
|
|
|
iot_sg_cco_bcast_task_start(req->bcast_time,
|
|
IOT_GW_DRV_FJ_BCAST_TASK_SEND_INTERVAL);
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
void iot_gw_drv_fj_rpt_bcast_task_end()
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
iot_gw_drv_dj_reset_bcast_task_param();
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, 0), IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F6, pkt,
|
|
IOT_SG_INVALID_CCTT_SN);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_channel_delay_rpt()
|
|
{
|
|
afn_56_fn_05_channel_delay_ul_t *rpt;
|
|
iot_pkt_t *pkt;
|
|
uint16_t pkt_len;
|
|
|
|
pkt_len = sizeof(*rpt);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rpt = (afn_56_fn_05_channel_delay_ul_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
|
|
rpt->delay_time = PROTO_3762_FJ_BCAST_CHANNEL_DELAY_TIME;
|
|
|
|
iot_pkt_put(pkt, pkt_len);
|
|
drv_data->fj_data.bcast_task.sn = iot_sg_cco_get_sn_for_cctt();
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F5, pkt,
|
|
drv_data->fj_data.bcast_task.sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_rpt_bcast_task_interval()
|
|
{
|
|
if (!drv_data->fj_data.bcast_task.channel_delay) {
|
|
iot_gw_drv_fj_bcast_task_send(
|
|
iot_pkt_data(drv_data->fj_data.bcast_task.bcast_pkt),
|
|
(uint16_t)iot_pkt_data_len(drv_data->fj_data.bcast_task.bcast_pkt));
|
|
} else {
|
|
iot_gw_drv_fj_channel_delay_rpt();
|
|
}
|
|
}
|
|
|
|
void iot_gw_drv_fj_bcast_task_handle(uint8_t done)
|
|
{
|
|
if (done) {
|
|
iot_gw_drv_fj_rpt_bcast_task_end();
|
|
} else {
|
|
iot_gw_drv_fj_rpt_bcast_task_interval();
|
|
}
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f2(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn02_node_evt_rpt_ctrl_t *req;
|
|
iot_sg_cco_node_evt_rpt_ctrl_t *node_info;
|
|
iot_sg_cco_node_evt_ctrl_info *crtl_info;
|
|
uint16_t pkt_len;
|
|
iot_pkt_t *pkt;
|
|
uint8_t total_cnt = 0;
|
|
uint8_t i;
|
|
|
|
if (len < sizeof (*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
req = (afn55_fn02_node_evt_rpt_ctrl_t *)data;
|
|
if (len < (sizeof(*req) + (req->total_cnt * sizeof(evt_rpt_ctrl_t)))) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
if (iot_sg_cco_get_node_evt_ctrl_state()) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
return;
|
|
}
|
|
|
|
pkt_len = req->total_cnt * sizeof(*crtl_info);
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
|
|
|
if (pkt == NULL) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
node_info = (iot_sg_cco_node_evt_rpt_ctrl_t *)iot_pkt_data(pkt);
|
|
|
|
for (i = 0; i < req->total_cnt; ++i) {
|
|
if (req->evt_ctrl[i].comm_obj.type != PROTO_3762_FJ_OBJ_STA &&
|
|
req->evt_ctrl[i].comm_obj.type != PROTO_3762_FJ_OBJ_COLLECTOR) {
|
|
continue;
|
|
}
|
|
iot_mac_addr_cpy(node_info->node_evt_ctrl[total_cnt].mac_addr,
|
|
req->evt_ctrl[i].comm_obj.mac_addr);
|
|
iot_mac_addr_reverse(node_info->node_evt_ctrl[total_cnt].mac_addr);
|
|
node_info->node_evt_ctrl[total_cnt].enable = req->evt_ctrl[i].enable;
|
|
total_cnt++;
|
|
}
|
|
if (total_cnt == 0) {
|
|
iot_pkt_free(pkt);
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA, sn);
|
|
return;
|
|
}
|
|
pkt_len = total_cnt * sizeof(*crtl_info);
|
|
iot_pkt_put(pkt, pkt_len);
|
|
|
|
iot_sg_cco_start_node_evt_rpt_ctrl(pkt, total_cnt);
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f6(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn06_start_node_reg_t *node_reg;
|
|
uint32_t dur_s;
|
|
|
|
if (len < sizeof(*node_reg)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
node_reg = (afn55_fn06_start_node_reg_t *)data;
|
|
|
|
if (IOT_SG_CCO_ROUTER_WORK_TYPE_UPGRADE ==
|
|
iot_sg_cco_get_router_work_type()) {
|
|
/* sec node reg is not allowed when upgrading. */
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
return;
|
|
}
|
|
|
|
if (!iot_sg_cco_get_router_sec_node_reg_allowed()) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
return;
|
|
}
|
|
|
|
if (iot_sg_get_sec_node_reg_state()) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
return;
|
|
}
|
|
|
|
if (drv_data->tsfm_and_reg_is_doing) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
return;
|
|
}
|
|
|
|
/* IOT_SG_CCO_TSFM_DETECT_DOING just used for transformer detect enable
|
|
* case.
|
|
*/
|
|
if (iot_sg_get_sec_node_reg_state() & IOT_SG_CALLER_TYPE_CLI) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
} else {
|
|
if (node_reg->duration == 0) {
|
|
node_reg->duration = IOT_SG_DEFAULT_SEC_NODE_REG_DUR;
|
|
}
|
|
|
|
dur_s = node_reg->duration * PROTO_3762_SEC_NODE_REG_TIME_UNIT_DUR;
|
|
iot_sg_start_sec_node_reg(IOT_SG_CALLER_TYPE_CCTT, dur_s,
|
|
IOT_SG_CCO_MAX_SEC_NODE_SEND_CNT, 1);
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
drv_data->fj_data.fj_new_node_check = 0;
|
|
drv_data->sec_node_reg_type = CCTT_DRV_SEC_NODE_REG_START_TYPE_FJ_3762;
|
|
}
|
|
}
|
|
|
|
static void iot_gw_drv_fj_55h_f7(uint8_t sn)
|
|
{
|
|
/* stop predict meter reading */
|
|
if (iot_sg_cco_predict_mr_get_state()) {
|
|
if (IOT_SG_CCO_ROUTER_WORK_TYPE_MR ==
|
|
iot_sg_cco_get_router_work_type()) {
|
|
iot_sg_cco_set_router_work_type(IOT_SG_CCO_ROUTER_WORK_TYPE_RESVD);
|
|
}
|
|
iot_sg_cco_stop_predict_mr();
|
|
}
|
|
/* stop sec node register */
|
|
if (iot_sg_get_sec_node_reg_state() & IOT_SG_CALLER_TYPE_CCTT) {
|
|
if (IOT_SG_CCO_ROUTER_WORK_TYPE_SM ==
|
|
iot_sg_cco_get_router_work_type()) {
|
|
iot_sg_cco_set_router_work_type(IOT_SG_CCO_ROUTER_WORK_TYPE_RESVD);
|
|
}
|
|
iot_sg_stop_sec_node_reg(IOT_SG_CALLER_TYPE_CCTT,
|
|
IOT_SG_CCO_STOP_SEC_NODE_REG_CCTT);
|
|
}
|
|
/* stop bcast task */
|
|
if (iot_sg_cco_get_bcast_task_state()) {
|
|
iot_sg_cco_bcast_task_param_reset();
|
|
iot_gw_drv_dj_reset_bcast_task_param();
|
|
}
|
|
/* reset parameter in any case */
|
|
iot_sg_cco_clear_all_wlii_addr();
|
|
drv_data->rt_mr_pending = 0;
|
|
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_55h_f8(uint8_t sn)
|
|
{
|
|
if (iot_sg_cco_allow_ctrl_rt_mr()) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
return;
|
|
}
|
|
if (iot_sg_cco_get_wlii_cnt() == 0) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(METER_NO_NOT_EXIST, sn);
|
|
return;
|
|
}
|
|
|
|
if (iot_sg_cco_get_online_sta_count()) {
|
|
iot_sg_cco_start_predict_mr();
|
|
} else {
|
|
drv_data->rt_mr_pending = 1;
|
|
}
|
|
drv_data->fj_data.amr_model = CCTT_DRV_AMR_MODEL_PREDICT_MR;
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_55h_f9(uint8_t *data, uint16_t len, uint8_t sn)
|
|
{
|
|
uint8_t reason, add_cnt = 0, proto_type = PROTO_TYPE_RAW_DATA;
|
|
uint16_t i, j, cnt, predict_node_cnt;
|
|
uint32_t rm_ts, data_len = 0;
|
|
iot_pkt_t *pkt, *pkt_ii;
|
|
iot_sg_wl_op_info_t *wl_req;
|
|
predict_node_info_t *node_info = NULL;
|
|
afn55_fn09_predict_mr_node_req_t *req;
|
|
iot_sg_wl_entry_info_t node;
|
|
uint16_t bcast_99_cnt = 0;
|
|
|
|
if (iot_sg_cco_rt_mr_get_state() == IOT_SG_CCO_RT_AMR_STATE_RUN) {
|
|
reason = MASTER_IS_BUSY;
|
|
goto reject;
|
|
}
|
|
if (len < sizeof(*req)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto reject;
|
|
}
|
|
|
|
req = (afn55_fn09_predict_mr_node_req_t *)data;
|
|
if (req->total_cnt > IOT_SG_CCO_APP_WLII_MAX_NUM) {
|
|
reason = INVALID_DATA;
|
|
goto reject;
|
|
}
|
|
|
|
len -= sizeof(*req);
|
|
if (len < sizeof(*req->node)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto reject;
|
|
}
|
|
|
|
predict_node_cnt = len / sizeof(*req->node);
|
|
if ((predict_node_cnt > req->total_cnt) ||
|
|
(predict_node_cnt > iot_sg_cco_get_free_wl_entry_count()) ||
|
|
(predict_node_cnt > iot_sg_cco_get_free_wlii_entry_count())) {
|
|
reason = INVALID_DATA;
|
|
goto reject;
|
|
}
|
|
|
|
node_info = req->node;
|
|
for (i = 0; i < predict_node_cnt; ++i) {
|
|
if ((!iot_mac_addr_valid(node_info[i].mac)) ||
|
|
(iot_mac_is_bcast(node_info[i].mac))) {
|
|
/* secondary node addr is invalid */
|
|
reason = INVALID_FORMAT;
|
|
goto reject;
|
|
}
|
|
for (j = i + 1; j < predict_node_cnt; j++) {
|
|
if (iot_mac_addr_cmp(node_info[i].mac, node_info[j].mac)) {
|
|
/* a duplicate secondary node address in a message */
|
|
reason = METER_NO_DUPLICATED;
|
|
goto reject;
|
|
}
|
|
}
|
|
|
|
if (iot_sg_get_wlii_entry_info_by_mac(node_info[i].mac, &node)) {
|
|
add_cnt++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!add_cnt) {
|
|
/* all the secondary node addresses are duplicated. */
|
|
reason = METER_NO_DUPLICATED;
|
|
goto reject;
|
|
}
|
|
|
|
if (req->delay_fix_flag) {
|
|
drv_data->fj_data.delay_fix_flag = 1;
|
|
}
|
|
|
|
add_cnt = 0;
|
|
rm_ts = (uint32_t)((os_boot_time64() / 1000) +
|
|
IOT_SG_CCO_AUTO_RM_WL_TIMEOUT);
|
|
do {
|
|
cnt = (IOT_SG_CCO_MSG_LONG_BUF_SIZE - sizeof(*wl_req)) /
|
|
sizeof(wl_req->node_info[0]);
|
|
cnt = min(cnt, predict_node_cnt - add_cnt);
|
|
data_len = sizeof(*wl_req) + sizeof(wl_req->node_info[0]) * cnt;
|
|
pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
wl_req = (iot_sg_wl_op_info_t *)iot_pkt_data(pkt);
|
|
wl_req->count = (uint8_t)cnt;
|
|
wl_req->rm_ts = rm_ts;
|
|
for (i = 0, j = add_cnt; i < cnt; ++i, ++j) {
|
|
if (proto_645_is_bcast(node_info[j].mac)) {
|
|
bcast_99_cnt = i;
|
|
}
|
|
iot_mac_addr_cpy(wl_req->node_info[i].mac, node_info[j].mac);
|
|
wl_req->node_info[i].obj_type = node_info[j].obj_type;
|
|
wl_req->node_info[i].node_index = IOT_SG_CCO_WL_INVAL_INDEX;
|
|
iot_sg_cco_get_pm_proto_type(node_info[j].mac, &proto_type);
|
|
wl_req->node_info[i].proto_type = proto_type;
|
|
iot_sg_printf("add wl %lu %lu %02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
i, wl_req->node_info[i].proto_type,
|
|
wl_req->node_info[i].mac[0], wl_req->node_info[i].mac[1],
|
|
wl_req->node_info[i].mac[2], wl_req->node_info[i].mac[3],
|
|
wl_req->node_info[i].mac[4], wl_req->node_info[i].mac[5]);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_CCO_ADD_SEC_NODE_ADDR, 8,
|
|
i, wl_req->node_info[i].proto_type,
|
|
wl_req->node_info[i].mac[0], wl_req->node_info[i].mac[1],
|
|
wl_req->node_info[i].mac[2], wl_req->node_info[i].mac[3],
|
|
wl_req->node_info[i].mac[4], wl_req->node_info[i].mac[5]);
|
|
}
|
|
|
|
pkt_ii = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt_ii);
|
|
os_mem_cpy(iot_pkt_data(pkt_ii), iot_pkt_data(pkt), data_len);
|
|
iot_pkt_put(pkt_ii, data_len);
|
|
iot_sg_cco_add_wlii_addr(IOT_SG_CALLER_TYPE_CCTT, pkt_ii);
|
|
|
|
/* proto_645_bcast_addr should't be joined white list */
|
|
if (proto_645_is_bcast(wl_req->node_info[bcast_99_cnt].mac)) {
|
|
if (bcast_99_cnt + 1 < i) {
|
|
os_mem_cpy(&(wl_req->node_info[bcast_99_cnt]),
|
|
&(wl_req->node_info[bcast_99_cnt + 1]),
|
|
(i - 1 - bcast_99_cnt) * sizeof(iot_sg_wl_op_entry_t));
|
|
}
|
|
data_len = data_len - sizeof(iot_sg_wl_op_entry_t);
|
|
wl_req->count--;
|
|
}
|
|
iot_pkt_put(pkt, data_len);
|
|
iot_sg_cco_add_wl_addr(IOT_SG_CALLER_TYPE_CCTT, pkt);
|
|
|
|
add_cnt += (uint8_t)cnt;
|
|
} while (predict_node_cnt > add_cnt);
|
|
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
goto out;
|
|
reject:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f10(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn10_set_proto_mode_t *set_data;
|
|
|
|
if (len < sizeof(*set_data)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
set_data = (afn55_fn10_set_proto_mode_t *)data;
|
|
switch (set_data->proto_mode) {
|
|
case PROTO_3762_FJ_PRO_MODE_FJ:
|
|
{
|
|
if (!drv_data->fj_data.fj_proto) {
|
|
drv_data->fj_data.fj_proto = 1;
|
|
cctt_drv_callback_function_switch();
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_PRO_MODE_GW:
|
|
{
|
|
if (drv_data->fj_data.fj_proto) {
|
|
drv_data->fj_data.fj_proto = 0;
|
|
cctt_drv_callback_function_switch();
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA, sn);
|
|
return;
|
|
}
|
|
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static uint8_t iot_gw_drv_fj_baud_type_convert(uint8_t baud)
|
|
{
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_300 == IOT_SG_CCO_BAUD_IDX_300);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_600 == IOT_SG_CCO_BAUD_IDX_600);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_1200 == IOT_SG_CCO_BAUD_IDX_1200);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_2400 == IOT_SG_CCO_BAUD_IDX_2400);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_4800 == IOT_SG_CCO_BAUD_IDX_4800);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_7200 == IOT_SG_CCO_BAUD_IDX_7200);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_9600 == IOT_SG_CCO_BAUD_IDX_9600);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_19200 == IOT_SG_CCO_BAUD_IDX_19200);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_38400 == IOT_SG_CCO_BAUD_IDX_38400);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_57600 == IOT_SG_CCO_BAUD_IDX_57600);
|
|
BUILD_BUG_ON(PROTO_3762_FJ_BAUD_115200 == IOT_SG_CCO_BAUD_IDX_115200);
|
|
|
|
return baud;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f11(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn11_set_baud_rate_t *req;
|
|
iot_sg_cco_uart_conf_t uart_conf = { 0 };
|
|
uint16_t delay_time = 0;
|
|
|
|
if (len < sizeof(*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
req = (afn55_fn11_set_baud_rate_t *)data;
|
|
if (req->baud > PROTO_3762_FJ_BAUD_115200) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA, sn);
|
|
return;
|
|
}
|
|
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
iot_sg_cco_get_uart_config(&uart_conf);
|
|
switch (uart_conf.baud_rate) {
|
|
case IOT_SG_CCO_BAUD_IDX_300:
|
|
{
|
|
delay_time = IOT_GW_DRV_FJ_DELAY_TIME_5;
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_BAUD_IDX_600:
|
|
{
|
|
delay_time = IOT_GW_DRV_FJ_DELAY_TIME_4;
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_BAUD_IDX_1200:
|
|
{
|
|
delay_time = IOT_GW_DRV_FJ_DELAY_TIME_3;
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_BAUD_IDX_2400:
|
|
{
|
|
delay_time = IOT_GW_DRV_FJ_DELAY_TIME_2;
|
|
break;
|
|
}
|
|
default:
|
|
delay_time = IOT_GW_DRV_FJ_DELAY_TIME_1;
|
|
break;
|
|
}
|
|
|
|
os_delay(delay_time);
|
|
os_mem_set(&uart_conf, 0 , sizeof(uart_conf));
|
|
uart_conf.baud_rate = iot_gw_drv_fj_baud_type_convert(req->baud);
|
|
uart_conf.baud_rate_flag = 1;
|
|
iot_sg_cco_set_uart_config(&uart_conf);
|
|
cctt_drv_config_uart(iot_sg_cco_uart_idx_to_bps(uart_conf.baud_rate));
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f12(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn12_set_baud_rec_time_t *req;
|
|
uint16_t rec_time;
|
|
iot_sg_cco_uart_conf_t uart_conf = { 0 };
|
|
|
|
if (len < sizeof(*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
req = (afn55_fn12_set_baud_rec_time_t *)data;
|
|
rec_time = req->rec_time;
|
|
if (rec_time < PROTO_3762_FJ_BAUD_REC_TIME_MIN) {
|
|
rec_time = PROTO_3762_FJ_BAUD_REC_TIME_MIN;
|
|
}
|
|
if (rec_time > PROTO_3762_FJ_BAUD_REC_TIME_MAX) {
|
|
rec_time = PROTO_3762_FJ_BAUD_REC_TIME_MAX;
|
|
}
|
|
|
|
uart_conf.rec_time = rec_time;
|
|
uart_conf.rec_time_flag = 1;
|
|
iot_sg_cco_set_uart_config(&uart_conf);
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_cmd_55h_f13(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn55_fn13_set_max_baud_rate_t *req;
|
|
iot_sg_cco_uart_conf_t uart_conf = { 0 };
|
|
|
|
if (len < sizeof(*req)) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA_LEN, sn);
|
|
return;
|
|
}
|
|
|
|
req = (afn55_fn13_set_max_baud_rate_t *)data;
|
|
if (req->max_baud > IOT_SG_CCO_BAUD_IDX_115200) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(INVALID_DATA, sn);
|
|
return;
|
|
}
|
|
|
|
uart_conf.max_baud_rate = req->max_baud;
|
|
uart_conf.max_baud_rate_flag = 1;
|
|
iot_sg_cco_set_uart_config(&uart_conf);
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_55h_f18(uint8_t sn)
|
|
{
|
|
if (iot_sg_cco_allow_ctrl_rt_mr()) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_IS_BUSY, sn);
|
|
return;
|
|
}
|
|
if (iot_sg_cco_get_wlii_cnt() == 0) {
|
|
iot_gw_drv_fj_send_50h02_nack_reject(METER_NO_NOT_EXIST, sn);
|
|
return;
|
|
}
|
|
|
|
if (iot_sg_cco_get_online_sta_count()) {
|
|
iot_sg_cco_start_predict_mr();
|
|
} else {
|
|
drv_data->rt_mr_pending = 1;
|
|
}
|
|
drv_data->fj_data.amr_model = CCTT_DRV_AMR_MODEL_PREDICT_MR_NEW;
|
|
iot_gw_drv_fj_send_50h01_ack(sn);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_handle_55h_data_set(uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t fn)
|
|
{
|
|
switch (fn) {
|
|
case PROTO_3762_F1:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f1(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F2:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f2(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F3:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f3(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F4:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f4(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F6:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f6(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F7:
|
|
{
|
|
iot_gw_drv_fj_55h_f7(sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F8:
|
|
{
|
|
iot_gw_drv_fj_55h_f8(sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F9:
|
|
{
|
|
iot_gw_drv_fj_55h_f9(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F10:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f10(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F11:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f11(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F12:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f12(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F13:
|
|
{
|
|
iot_gw_drv_fj_cmd_55h_f13(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F18:
|
|
{
|
|
iot_gw_drv_fj_55h_f18(sn);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void iot_gw_drv_fj_handle_50h_ack(uint8_t fn, uint8_t sn)
|
|
{
|
|
switch (fn) {
|
|
case PROTO_3762_F1:
|
|
{
|
|
iot_sg_cco_handle_predict_mr_ack(0, sn);
|
|
iot_sg_cco_recv_ack_to_report(1, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F2:
|
|
{
|
|
iot_sg_cco_recv_ack_to_report(1, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F3:
|
|
{
|
|
iot_sg_cco_handle_predict_mr_ack(1, sn);
|
|
iot_sg_cco_recv_ack_to_report(1, sn);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_cmd_56h_f3(uint8_t *data, uint16_t len,
|
|
uint16_t sn, iot_pkt_t *pkt)
|
|
{
|
|
(void)sn;
|
|
uint32_t ret_val;
|
|
uint32_t consumed = 0;
|
|
uint8_t reason;
|
|
uint8_t dest_mac[IOT_MAC_ADDR_LEN];
|
|
uint8_t src_mac[IOT_MAC_ADDR_LEN];
|
|
afn56_fn03_amr_data_dl_t *rsp_data = (afn56_fn03_amr_data_dl_t *)data;
|
|
|
|
BUILD_BUG_ON(SG_AFN_PREDICT_MR == PROTO_3762_FJ_AFN_56);
|
|
|
|
if (iot_sg_cco_predict_mr_get_con_cnt() >=
|
|
IOT_SG_CCO_PREDICT_MR_CON_MAX_CNT) {
|
|
goto out;
|
|
}
|
|
if (len < sizeof(*rsp_data)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
len -= sizeof(*rsp_data);
|
|
if (len < rsp_data->data_len) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
|
|
if (iot_sg_cco_predict_mr_get_state() != IOT_SG_CCO_PREDICT_MR_STATE_RUN) {
|
|
return consumed;
|
|
}
|
|
|
|
/* get mac address field from data packet. */
|
|
if (iot_sg_cco_get_mr_pkt_mac(dest_mac, rsp_data->data, rsp_data->data_len,
|
|
PROTO_TYPE_RAW_DATA) != ERR_OK) {
|
|
iot_mac_addr_cpy(dest_mac, rsp_data->mac_addr);
|
|
}
|
|
if (!iot_sg_cco_wlii_entry_exist(dest_mac)) {
|
|
reason = METER_NO_NOT_EXIST;
|
|
goto err;
|
|
}
|
|
iot_sg_cco_get_major_node_mac(src_mac);
|
|
drv_data->fj_data.plan_id = rsp_data->plan_id;
|
|
drv_data->fj_data.cmd_id = rsp_data->cmd_id;
|
|
|
|
/* update pkt to have meter reading data in its data block */
|
|
iot_pkt_set_data(pkt, rsp_data->data);
|
|
iot_pkt_set_tail(pkt, rsp_data->data + rsp_data->data_len);
|
|
|
|
ret_val = iot_sg_cco_intern_dl_send(IOT_SG_CCO_INTERN_SEND_PREDICT_MR,
|
|
pkt, dest_mac);
|
|
if (ERR_OK == ret_val) {
|
|
consumed = 1;
|
|
}
|
|
goto out;
|
|
|
|
err:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
out:
|
|
return consumed;
|
|
}
|
|
|
|
static uint8_t iot_gw_drv_fj_cmd_56h_f5(uint8_t *data, uint16_t len,
|
|
uint8_t sn)
|
|
{
|
|
afn_56_fn_05_channel_delay_dl_t *req;
|
|
proto_645_header_t *hdr645;
|
|
uint8_t reason;
|
|
|
|
if (drv_data->fj_data.bcast_task.channel_delay != 1) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
|
|
if (len < sizeof(*req)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
|
|
req = (afn_56_fn_05_channel_delay_dl_t *)data;
|
|
if (req->len < (len - sizeof(*req))) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
|
|
hdr645 = proto_645_format_check(req->data, req->len, PROTO_645_DIR_MASTER);
|
|
if (hdr645 == NULL) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
}
|
|
/* check correct time message */
|
|
iot_gw_drv_fj_handle_write_corr_time(hdr645);
|
|
|
|
if (sn != drv_data->fj_data.bcast_task.sn) {
|
|
reason = INVALID_DATA;
|
|
goto err;
|
|
} else {
|
|
drv_data->fj_data.bcast_task.sn = IOT_SG_INVALID_CCTT_SN;
|
|
}
|
|
|
|
iot_gw_drv_fj_bcast_task_send(req->data, req->len);
|
|
goto out;
|
|
err:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
out:
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_cmd_56h_f13(uint8_t *data, uint16_t len,
|
|
uint16_t sn, iot_pkt_t *pkt)
|
|
{
|
|
(void)sn;
|
|
uint8_t reason;
|
|
uint32_t cnt, ret_val, consumed = 0;
|
|
uint8_t dest_mac[IOT_MAC_ADDR_LEN];
|
|
uint8_t src_mac[IOT_MAC_ADDR_LEN];
|
|
afn56_fn13_amr_data_dl_t *rsp_data = (afn56_fn13_amr_data_dl_t *)data;
|
|
|
|
if (iot_sg_cco_predict_mr_get_con_cnt() >=
|
|
IOT_SG_CCO_PREDICT_MR_CON_MAX_CNT) {
|
|
goto out;
|
|
}
|
|
if (len < sizeof(*rsp_data)) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
len -= sizeof(*rsp_data);
|
|
if (len < rsp_data->data_len) {
|
|
reason = INVALID_DATA_LEN;
|
|
goto err;
|
|
}
|
|
|
|
if (iot_sg_cco_predict_mr_get_state() != IOT_SG_CCO_PREDICT_MR_STATE_RUN) {
|
|
return consumed;
|
|
}
|
|
|
|
if ((rsp_data->proto_type == PROTO_TYPE_698_45 ||
|
|
rsp_data->proto_type == PROTO_TYPE_RAW_DATA) &&
|
|
rsp_data->data_len > IOT_SG_CON_MR_MAX_69845_LEN) {
|
|
/* data type is 698.45, and length exceed max length, send NACK */
|
|
reason = EXCEED_MAX_PKT_COUNT;
|
|
goto err;
|
|
}
|
|
|
|
if (rsp_data->proto_type == PROTO_TYPE_645_1997 ||
|
|
rsp_data->proto_type == PROTO_TYPE_645_2007) {
|
|
cnt = iot_sg_cco_get_645_pkt_cnt(rsp_data->data, rsp_data->data_len);
|
|
if (cnt == 0) {
|
|
reason = INVALID_FORMAT;
|
|
goto err;
|
|
}
|
|
if (cnt > IOT_SG_CON_MR_MAX_645_CNT) {
|
|
/* data type is 645, and packet exceed max count, send NACK */
|
|
reason = EXCEED_MAX_PKT_COUNT;
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
/* get mac address field from data packet. */
|
|
if (iot_sg_cco_get_mr_pkt_mac(dest_mac, rsp_data->data, rsp_data->data_len,
|
|
PROTO_TYPE_RAW_DATA) != ERR_OK) {
|
|
iot_mac_addr_cpy(dest_mac, rsp_data->mac_addr);
|
|
}
|
|
if (!iot_sg_cco_wlii_entry_exist(dest_mac)) {
|
|
reason = METER_NO_NOT_EXIST;
|
|
goto err;
|
|
}
|
|
iot_sg_cco_get_major_node_mac(src_mac);
|
|
drv_data->fj_data.plan_id = rsp_data->plan_id;
|
|
drv_data->fj_data.cmd_id = rsp_data->cmd_id;
|
|
|
|
/* update pkt to have meter reading data in its data block */
|
|
iot_pkt_set_data(pkt, rsp_data->data);
|
|
iot_pkt_set_tail(pkt, rsp_data->data + rsp_data->data_len);
|
|
ret_val = iot_sg_cco_intern_dl_send(IOT_SG_CCO_INTERN_SEND_PREDICT_MR,
|
|
pkt, dest_mac);
|
|
if (ERR_OK == ret_val) {
|
|
consumed = 1;
|
|
}
|
|
goto out;
|
|
|
|
err:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(reason, sn);
|
|
out:
|
|
return consumed;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_handle_56h_data_rpt(uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t fn, iot_pkt_t *pkt)
|
|
{
|
|
uint32_t pkt_consumed = 0;
|
|
switch (fn) {
|
|
case PROTO_3762_F3:
|
|
{
|
|
pkt_consumed = iot_gw_drv_fj_cmd_56h_f3(data, len, sn, pkt);
|
|
break;
|
|
}
|
|
case PROTO_3762_F5:
|
|
{
|
|
pkt_consumed = iot_gw_drv_fj_cmd_56h_f5(data, len, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_F13:
|
|
{
|
|
pkt_consumed = iot_gw_drv_fj_cmd_56h_f13(data, len, sn, pkt);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_send_50h02_nack_reject(MASTER_UNSUPPORTED_CMD, sn);
|
|
break;
|
|
}
|
|
return pkt_consumed;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_handle_cmd(uint8_t afn, uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t fn, uint32_t *pkt_consumed, iot_pkt_t *pkt)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
*pkt_consumed = 0;
|
|
|
|
switch (afn) {
|
|
case PROTO_3762_FJ_AFN_50:
|
|
{
|
|
iot_gw_drv_fj_handle_50h_ack(fn, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_AFN_51:
|
|
{
|
|
iot_gw_drv_fj_handle_51h_init(fn, sn);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_AFN_52:
|
|
{
|
|
*pkt_consumed = iot_gw_drv_fj_handle_52h_data_fwd(data, len, sn, fn,
|
|
pkt);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_AFN_53:
|
|
{
|
|
iot_gw_drv_fj_handle_53h_data_query(data, len, sn, fn);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_AFN_55:
|
|
{
|
|
iot_gw_drv_fj_handle_55h_data_set(data, len, sn, fn);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_AFN_56:
|
|
{
|
|
*pkt_consumed = iot_gw_drv_fj_handle_56h_data_rpt(data, len, sn, fn,
|
|
pkt);
|
|
break;
|
|
}
|
|
default:
|
|
ret = ERR_FAIL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_meter_data_52h_f1(uint8_t *data, uint16_t len,
|
|
uint16_t sn, uint8_t *mac_field, uint8_t obj_type)
|
|
{
|
|
uint16_t pkt_len;
|
|
iot_pkt_t *pkt;
|
|
uint8_t *pkt_data;
|
|
afn52_fn01_data_fwd_ul_t *meter_data;
|
|
|
|
if (data == NULL) {
|
|
len = 0;
|
|
}
|
|
|
|
pkt_len = len + sizeof(*meter_data);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt_data);
|
|
meter_data = (afn52_fn01_data_fwd_ul_t*)pkt_data;
|
|
|
|
iot_pkt_put(pkt, sizeof(*meter_data));
|
|
iot_mac_addr_cpy(meter_data->mac_addr, mac_field);
|
|
meter_data->obj_type = obj_type;
|
|
meter_data->data_len = len;
|
|
|
|
iot_pkt_put(pkt, len);
|
|
os_mem_cpy(meter_data->data, data, len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(0, PROTO_3762_FJ_AFN_52, PROTO_3762_F1,
|
|
pkt, sn);
|
|
if (meter_data->data_len) {
|
|
iot_counter_inc(drv_data->mr_pkg_statistics.cctt_mr_success_cnt);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_meter_data_56h_f4(uint8_t *data, uint16_t len,
|
|
uint16_t sn, uint8_t *mac_field)
|
|
{
|
|
uint16_t pkt_len;
|
|
iot_pkt_t *pkt;
|
|
uint8_t *pkt_data;
|
|
iot_sg_wl_entry_info_t node;
|
|
afn56_fn04_amr_data_rpt_ul_t *meter_data;
|
|
|
|
if (data == NULL) {
|
|
len = 0;
|
|
}
|
|
|
|
pkt_len = len + sizeof(*meter_data);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt_data);
|
|
|
|
iot_sg_get_wlii_entry_info_by_mac(mac_field, &node);
|
|
meter_data = (afn56_fn04_amr_data_rpt_ul_t*)pkt_data;
|
|
meter_data->plan_id = drv_data->fj_data.plan_id;
|
|
meter_data->cmd_id = drv_data->fj_data.cmd_id;
|
|
meter_data->obj_type = node.obj_type;
|
|
iot_mac_addr_cpy(meter_data->mac_addr, mac_field);
|
|
meter_data->data_len = (uint8_t)len;
|
|
iot_pkt_put(pkt, sizeof(*meter_data));
|
|
|
|
os_mem_cpy(meter_data->data, data, len);
|
|
iot_pkt_put(pkt, len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F4,
|
|
pkt, sn);
|
|
if (meter_data->data_len) {
|
|
iot_counter_inc(drv_data->mr_pkg_statistics.router_mr_success_cnt);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_meter_data_56h_f14(uint8_t *data, uint16_t len,
|
|
uint16_t sn, uint8_t *mac_field)
|
|
{
|
|
uint16_t pkt_len;
|
|
iot_pkt_t *pkt;
|
|
uint8_t *pkt_data;
|
|
iot_sg_wl_entry_info_t node;
|
|
afn56_fn14_amr_data_rpt_ul_t *meter_data;
|
|
|
|
if (data == NULL) {
|
|
len = 0;
|
|
}
|
|
|
|
pkt_len = len + sizeof(*meter_data);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt_data);
|
|
|
|
iot_sg_get_wlii_entry_info_by_mac(mac_field, &node);
|
|
meter_data = (afn56_fn14_amr_data_rpt_ul_t*)pkt_data;
|
|
meter_data->plan_id = drv_data->fj_data.plan_id;
|
|
meter_data->cmd_id = drv_data->fj_data.cmd_id;
|
|
meter_data->obj_type = node.obj_type;
|
|
iot_mac_addr_cpy(meter_data->mac_addr, mac_field);
|
|
meter_data->data_len = len;
|
|
iot_pkt_put(pkt, sizeof(*meter_data));
|
|
|
|
os_mem_cpy(meter_data->data, data, len);
|
|
iot_pkt_put(pkt, len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F14,
|
|
pkt, sn);
|
|
if (meter_data->data_len) {
|
|
iot_counter_inc(drv_data->mr_pkg_statistics.router_mr_success_cnt);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void iot_gw_drv_fj_meter_data_handler(uint8_t *data, uint16_t len,
|
|
uint32_t afn, uint16_t sn, uint32_t proto_type, uint8_t *mac_field,
|
|
uint8_t mr_result, uint32_t plc_cost, uint8_t mr_type)
|
|
{
|
|
(void)proto_type;
|
|
(void)plc_cost;
|
|
(void)mr_type;
|
|
uint8_t obj_type;
|
|
uint8_t err_code = PROTO_645_FJ_ERR_RESP_TIMEOUT;
|
|
|
|
switch (afn) {
|
|
case PROTO_3762_FJ_AFN_52:
|
|
{
|
|
obj_type = iot_gw_drv_fj_get_obj_type((uint8_t)sn, 1);
|
|
iot_gw_drv_fj_meter_data_52h_f1(data, len, sn, mac_field, obj_type);
|
|
break;
|
|
}
|
|
case PROTO_3762_FJ_AFN_56:
|
|
{
|
|
if ((iot_sg_cco_predict_mr_get_state() ==
|
|
IOT_SG_CCO_PREDICT_MR_STATE_RUN)) {
|
|
if (mr_result == IOT_SG_CCO_MR_FAIL) {
|
|
data = &err_code;
|
|
len = sizeof(err_code);
|
|
}
|
|
switch (drv_data->fj_data.amr_model) {
|
|
case CCTT_DRV_AMR_MODEL_PREDICT_MR:
|
|
{
|
|
iot_gw_drv_fj_meter_data_56h_f4(data, len, sn, mac_field);
|
|
break;
|
|
}
|
|
case CCTT_DRV_AMR_MODEL_PREDICT_MR_NEW:
|
|
{
|
|
iot_gw_drv_fj_meter_data_56h_f14(data, len, sn, mac_field);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
iot_sg_printf("%s error meter data, AFN:%lu, sn:%lu",__FUNCTION__, afn,
|
|
sn);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static uint8_t iot_gw_drv_fj_type_convert_dev_to_obj(uint8_t dev_type)
|
|
{
|
|
uint8_t obj_type = PROTO_3762_DEV_TYPE_METER;
|
|
|
|
switch (dev_type) {
|
|
case IOT_SG_CCO_DEV_TYPE_COLLECTOR:
|
|
{
|
|
obj_type = PROTO_3762_FJ_OBJ_COLLECTOR;
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_DEV_TYPE_METER:
|
|
{
|
|
obj_type = PROTO_3762_FJ_OBJ_METER;
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_DEV_TYPE_STA:
|
|
{
|
|
obj_type = PROTO_3762_FJ_OBJ_STA;
|
|
break;
|
|
}
|
|
default:
|
|
iot_sg_printf("%s unknown device type!", __FUNCTION__);
|
|
break;
|
|
}
|
|
|
|
return obj_type;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_normal_event_report(uint8_t sn, uint8_t *pm_addr,
|
|
uint8_t *data, uint16_t len, uint8_t obj_type)
|
|
{
|
|
uint16_t pkt_len;
|
|
uint8_t *pkt_data;
|
|
iot_pkt_t *pkt;
|
|
afn56_fn02_node_evt_rpt_t *evt_rpt_data;
|
|
|
|
if (!data) {
|
|
len = 0;
|
|
}
|
|
pkt_len = len + sizeof(*evt_rpt_data);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len), IOT_SMART_GRID_MID);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
IOT_ASSERT(pkt);
|
|
|
|
evt_rpt_data = (afn56_fn02_node_evt_rpt_t *)pkt_data;
|
|
evt_rpt_data->obj_type = obj_type;
|
|
iot_mac_addr_cpy(evt_rpt_data->mac_addr, pm_addr);
|
|
evt_rpt_data->data_len = (uint8_t)len;
|
|
iot_pkt_put(pkt, sizeof(*evt_rpt_data));
|
|
|
|
if (len) {
|
|
os_mem_cpy(evt_rpt_data->data, data, len);
|
|
iot_pkt_put(pkt, len);
|
|
}
|
|
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F2, pkt,
|
|
sn);
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t iot_gw_drv_fj_power_event_report(uint8_t sn, uint8_t *pm_addr,
|
|
uint8_t *data, uint16_t len, uint8_t evt_type, uint8_t obj_type)
|
|
{
|
|
uint8_t addr[IOT_MAC_ADDR_LEN];
|
|
uint8_t i, offset = 0;
|
|
uint16_t cnt = 0;
|
|
iot_pkt_t *pkt_645 = NULL, *evt_data_pkt = NULL;
|
|
proto_645_fj_power_evt_rpt_t *evt_data;
|
|
iot_sg_power_evt_pm_info_t *pm_info = (iot_sg_power_evt_pm_info_t *)data;
|
|
|
|
if (evt_type == IOT_SG_CCO_EVENT_POWER_DOWN_C ||
|
|
evt_type == IOT_SG_CCO_EVENT_POWER_UP_C) {
|
|
cnt = len / sizeof(iot_sg_power_evt_pm_info_t);
|
|
len = len - cnt * sizeof(pm_info->power_state);
|
|
} else {
|
|
cnt = len / IOT_MAC_ADDR_LEN;
|
|
}
|
|
if (!cnt) {
|
|
iot_sg_printf("%s cnt err\n", __FUNCTION__);
|
|
return 0;
|
|
}
|
|
evt_data_pkt = iot_pkt_alloc(sizeof(*evt_data) + cnt * IOT_MAC_ADDR_LEN,
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(evt_data_pkt);
|
|
|
|
evt_data = (proto_645_fj_power_evt_rpt_t *)iot_pkt_data(evt_data_pkt);
|
|
iot_pkt_put(evt_data_pkt, sizeof(*evt_data));
|
|
if (evt_type == IOT_SG_CCO_EVENT_POWER_DOWN ||
|
|
evt_type == IOT_SG_CCO_EVENT_POWER_DOWN_C) {
|
|
evt_data->evt_type = 0;
|
|
} else {
|
|
evt_data->evt_type = 1;
|
|
}
|
|
evt_data->rpt_cnt = (uint8_t)cnt;
|
|
|
|
iot_pkt_put(evt_data_pkt, cnt * IOT_MAC_ADDR_LEN);
|
|
if (evt_type == IOT_SG_CCO_EVENT_POWER_DOWN_C ||
|
|
evt_type == IOT_SG_CCO_EVENT_POWER_UP_C) {
|
|
for (i = 0; i < cnt; i++) {
|
|
os_mem_cpy(evt_data->data + offset, pm_info->mac, IOT_MAC_ADDR_LEN);
|
|
pm_info += 1;
|
|
offset += IOT_MAC_ADDR_LEN;
|
|
}
|
|
} else {
|
|
os_mem_cpy(evt_data->data, data, cnt * IOT_MAC_ADDR_LEN);
|
|
}
|
|
|
|
if (cnt == 1) {
|
|
iot_mac_addr_cpy(addr, pm_addr);
|
|
} else {
|
|
iot_mac_addr_cpy(addr, proto_645_bcast_addr);
|
|
}
|
|
pkt_645 = proto_645_fj_build_power_evt_rpt(addr, iot_pkt_data(evt_data_pkt),
|
|
(uint8_t)iot_pkt_data_len(evt_data_pkt));
|
|
iot_pkt_free(evt_data_pkt);
|
|
|
|
iot_gw_drv_fj_normal_event_report(sn, pm_addr, iot_pkt_data(pkt_645),
|
|
(uint8_t)iot_pkt_data_len(pkt_645), obj_type);
|
|
if (pkt_645) {
|
|
iot_pkt_free(pkt_645);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_ctrl_connect_report(uint8_t sn,
|
|
uint8_t *pm_addr, uint8_t *data, uint16_t len)
|
|
{
|
|
iot_sg_ctrl_connect_evt_rpt_t *rpt_data;
|
|
iot_pkt_t *pkt_645;
|
|
uint16_t pkt_len;
|
|
uint8_t *pkt_data;
|
|
iot_pkt_t *pkt;
|
|
afn56_fn02_node_evt_rpt_t *evt_rpt_data;
|
|
|
|
if (len < sizeof(*rpt_data)) {
|
|
return;
|
|
}
|
|
|
|
rpt_data = (iot_sg_ctrl_connect_evt_rpt_t *)data;
|
|
pkt_645 = proto_645_fj_build_ctrl_evt_rpt(rpt_data->ctrl_mac,
|
|
rpt_data->state);
|
|
if (pkt_645 == NULL) {
|
|
iot_sg_printf("%s pkt build fail, connect state:%lu\n", __FUNCTION__,
|
|
rpt_data->state);
|
|
return;
|
|
}
|
|
|
|
pkt_len = (uint16_t)iot_pkt_data_len(pkt_645) + sizeof(*evt_rpt_data);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len), IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
pkt_data = iot_pkt_reserve(pkt, proto_3762_get_rsvd_len(0));
|
|
|
|
evt_rpt_data = (afn56_fn02_node_evt_rpt_t *)pkt_data;
|
|
evt_rpt_data->obj_type = PROTO_3762_FJ_OBJ_CCO;
|
|
iot_mac_addr_cpy(evt_rpt_data->mac_addr, pm_addr);
|
|
evt_rpt_data->data_len = (uint8_t)iot_pkt_data_len(pkt_645);
|
|
|
|
os_mem_cpy(evt_rpt_data->data, iot_pkt_data(pkt_645),
|
|
iot_pkt_data_len(pkt_645));
|
|
iot_pkt_put(pkt, pkt_len);
|
|
iot_pkt_free(pkt_645);
|
|
|
|
iot_gw_drv_fj_send_uart_build(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F2, pkt,
|
|
sn, 1);
|
|
}
|
|
|
|
static void iot_gw_drv_fj_opposite_phase_report(uint8_t sn, uint8_t *pm_addr,
|
|
uint8_t *data, uint16_t len, uint8_t obj_type)
|
|
{
|
|
iot_pkt_t *pkt_645;
|
|
|
|
if (!data || !len) {
|
|
iot_sg_printf("%s fail\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
pkt_645 = proto_645_fj_build_opposite_phase_info(pm_addr,
|
|
PROTO_645_FJ_FN_ACTIVE_RPT, *data);
|
|
iot_gw_drv_fj_normal_event_report(sn, pm_addr, iot_pkt_data(pkt_645),
|
|
(uint8_t)iot_pkt_data_len(pkt_645), obj_type);
|
|
if (pkt_645) {
|
|
iot_pkt_free(pkt_645);
|
|
}
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_event_report_handler(uint8_t sn, uint8_t *pm_addr,
|
|
uint8_t dev_type, uint32_t proto_type, uint8_t evt_type, uint8_t *data,
|
|
uint16_t len)
|
|
{
|
|
(void)proto_type;
|
|
uint8_t obj_type;
|
|
|
|
obj_type = iot_gw_drv_fj_type_convert_dev_to_obj(dev_type);
|
|
|
|
switch (evt_type) {
|
|
case IOT_SG_CCO_EVENT_POWER_DOWN:
|
|
case IOT_SG_CCO_EVENT_POWER_UP:
|
|
case IOT_SG_CCO_EVENT_POWER_DOWN_C:
|
|
case IOT_SG_CCO_EVENT_POWER_UP_C:
|
|
{
|
|
iot_gw_drv_fj_power_event_report(sn, pm_addr, data, len, evt_type,
|
|
obj_type);
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_EVENT_CTRL:
|
|
{
|
|
iot_gw_drv_fj_ctrl_connect_report(sn, pm_addr, data, len);
|
|
break;
|
|
}
|
|
case IOT_SG_CCO_EVENT_OPPOSITE_PHASE:
|
|
{
|
|
iot_gw_drv_fj_opposite_phase_report(sn, pm_addr, data, len, obj_type);
|
|
break;
|
|
}
|
|
default:
|
|
iot_gw_drv_fj_normal_event_report(sn, pm_addr, data, len, obj_type);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_node_rpt_645(uint8_t sn,
|
|
sec_node_query_t *sec_node_info)
|
|
{
|
|
uint8_t obj_type = 0;
|
|
uint8_t addr_p[IOT_MAC_ADDR_LEN], cco_mac[IOT_MAC_ADDR_LEN];
|
|
iot_pkt_t *pkt;
|
|
|
|
if (iot_sg_cco_is_pm(sec_node_info->dev_type)) {
|
|
obj_type = PROTO_3762_FJ_OBJ_STA;
|
|
iot_mac_addr_cpy(addr_p, sec_node_info->node_info[0].mac);
|
|
} else {
|
|
obj_type = PROTO_3762_FJ_OBJ_COLLECTOR;
|
|
if (!sec_node_info->contain_sec_node_count) {
|
|
iot_mac_addr_cpy(addr_p, sec_node_info->dev_addr);
|
|
} else {
|
|
iot_mac_addr_cpy(addr_p, sec_node_info->node_info[0].mac);
|
|
}
|
|
}
|
|
if (drv_data->fj_data.fj_new_node_check) {
|
|
/* only report nodes not in white list. */
|
|
if (iot_sg_cco_wl_entry_exist(addr_p)) {
|
|
goto out;
|
|
}
|
|
}
|
|
iot_sg_printf("sec_node_rpt: sec_node_cnt = %lu, m_addr = "
|
|
"%02x%02x%02x%02x%02x%02x\n", sec_node_info->contain_sec_node_count,
|
|
addr_p[5], addr_p[4], addr_p[3], addr_p[2], addr_p[1], addr_p[0]);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_CCO_DRV_CCTT_SEC_NODE_RPT_ID, 7,
|
|
sec_node_info->contain_sec_node_count, addr_p[5], addr_p[4], addr_p[3],
|
|
addr_p[2], addr_p[1], addr_p[0]);
|
|
|
|
if (!iot_sg_cco_wl_entry_exist(addr_p)) {
|
|
iot_sg_cco_save_pm_to_mac_list(addr_p);
|
|
}
|
|
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
pkt = proto_645_fj_build_list_abnormal_node_rpt(addr_p,
|
|
PROTO_645_FJ_LIST_ERR_NOT_REG, cco_mac);
|
|
if (!pkt) {
|
|
iot_sg_printf("%s no pkt\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
iot_gw_drv_fj_normal_event_report(sn, addr_p, iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), obj_type);
|
|
iot_pkt_free(pkt);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static void iot_gw_drv_fj_node_rpt_3762(uint8_t sn,
|
|
sec_node_query_t *sec_node_info)
|
|
{
|
|
uint8_t i;
|
|
afn56_fn01_sec_node_info_t *rsp;
|
|
iot_pkt_t *pkt;
|
|
uint32_t pkt_len;
|
|
uint8_t *addr_p;
|
|
uint8_t rpt_cnt = 0;
|
|
|
|
pkt_len = proto_3762_get_pkt_len(0, sizeof(*rsp) +
|
|
sec_node_info->contain_sec_node_count * sizeof(rsp->mac_addr[0]));
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
rsp = (afn56_fn01_sec_node_info_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
|
|
if (iot_sg_cco_is_pm(sec_node_info->dev_type)) {
|
|
if (drv_data->fj_data.fj_new_node_check) {
|
|
/* only report nodes not in white list. */
|
|
if (iot_sg_cco_wl_entry_exist(sec_node_info->node_info[0].mac)) {
|
|
goto drop;
|
|
}
|
|
}
|
|
iot_mac_addr_cpy(rsp->mac_addr[0], sec_node_info->node_info[0].mac);
|
|
rpt_cnt = 1;
|
|
|
|
if (!iot_sg_cco_wl_entry_exist(rsp->mac_addr[0])) {
|
|
iot_sg_cco_save_pm_to_mac_list(rsp->mac_addr[0]);
|
|
}
|
|
} else {
|
|
/* fill in the sec node information that needs to be transmitted */
|
|
for (i = 0; i < sec_node_info->contain_sec_node_count; i++) {
|
|
addr_p = sec_node_info->node_info[i].mac;
|
|
if (drv_data->fj_data.fj_new_node_check) {
|
|
/* only report nodes not in white list. */
|
|
if (iot_sg_cco_wl_entry_exist(addr_p)) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!iot_sg_cco_wl_entry_exist(addr_p)) {
|
|
iot_sg_cco_save_pm_to_mac_list(addr_p);
|
|
}
|
|
|
|
iot_sg_printf("sec_node_rpt: sec_node_cnt = %lu, m_addr = "
|
|
"%02x%02x%02x%02x%02x%02x\n",
|
|
sec_node_info->contain_sec_node_count, addr_p[5],
|
|
addr_p[4], addr_p[3], addr_p[2], addr_p[1], addr_p[0]);
|
|
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_INFO_LVL_2,
|
|
IOT_SG_CCO_DRV_CCTT_SEC_NODE_RPT_ID,
|
|
7, sec_node_info->contain_sec_node_count, addr_p[5], addr_p[4],
|
|
addr_p[3], addr_p[2], addr_p[1], addr_p[0]);
|
|
iot_mac_addr_cpy(rsp->mac_addr[rpt_cnt], addr_p);
|
|
rpt_cnt++;
|
|
}
|
|
}
|
|
|
|
rsp->sec_node_count = rpt_cnt;
|
|
iot_pkt_put(pkt, sizeof(*rsp) + rpt_cnt * sizeof(rsp->mac_addr[0]));
|
|
if (rpt_cnt) {
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, PROTO_3762_F1,
|
|
pkt, sn);
|
|
} else {
|
|
goto drop;
|
|
}
|
|
|
|
goto out;
|
|
|
|
drop:
|
|
iot_pkt_free(pkt);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_node_info_handler(uint8_t sn, uint16_t index,
|
|
sec_node_query_t *sec_node_info)
|
|
{
|
|
(void)index;
|
|
|
|
switch (drv_data->sec_node_reg_type) {
|
|
case CCTT_DRV_SEC_NODE_REG_START_TYPE_FJ_3762:
|
|
{
|
|
iot_gw_drv_fj_node_rpt_3762(sn, sec_node_info);
|
|
break;
|
|
}
|
|
case CCTT_DRV_SEC_NODE_REG_START_TYPE_FJ_645:
|
|
{
|
|
iot_gw_drv_fj_node_rpt_645(sn, sec_node_info);
|
|
break;
|
|
}
|
|
default:
|
|
iot_sg_printf("error sec node reg start type\n");
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void iot_gw_drv_fj_rt_req_read_meter(uint8_t *mac, uint8_t obj_type)
|
|
{
|
|
uint8_t fn;
|
|
uint16_t pkt_len;
|
|
iot_pkt_t *pkt = NULL;
|
|
afn56_fn03_fn13_amr_data_ul_t *req_data;
|
|
|
|
if (drv_data->fj_data.amr_model == CCTT_DRV_AMR_MODEL_PREDICT_MR) {
|
|
fn = PROTO_3762_F3;
|
|
} else {
|
|
fn = PROTO_3762_F13;
|
|
}
|
|
|
|
pkt_len = sizeof(*req_data);
|
|
pkt = iot_pkt_alloc(proto_3762_get_pkt_len(0, pkt_len),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
req_data = (afn56_fn03_fn13_amr_data_ul_t *)iot_pkt_reserve(pkt,
|
|
proto_3762_get_rsvd_len(0));
|
|
if (drv_data->fj_data.delay_fix_flag) {
|
|
req_data->delay_time = PROTO_3762_FJ_COMM_DELAY;
|
|
} else {
|
|
req_data->delay_time = 0;
|
|
}
|
|
req_data->obj_type = obj_type;
|
|
iot_mac_addr_cpy(req_data->mac_addr, mac);
|
|
|
|
iot_pkt_put(pkt, pkt_len);
|
|
iot_gw_drv_fj_send_uart_sn_ext(1, PROTO_3762_FJ_AFN_56, fn, pkt,
|
|
IOT_SG_INVALID_CCTT_SN);
|
|
}
|
|
|
|
/**
|
|
* @brief iot_gw_drv_fj_drv_topo_rpt - topo data from CCO module.
|
|
* @param req: req topo data
|
|
*/
|
|
static void iot_gw_drv_fj_drv_topo_rpt(iot_plc_nw_topo_rpt_t *rpt)
|
|
{
|
|
uint8_t i = 0;
|
|
proto_645_fj_query_topo_ul_t *rsp;
|
|
iot_pkt_t *pkt = NULL, *pkt_645 = NULL;
|
|
iot_plc_node_info_v2_t *node;
|
|
uint8_t rpt_cnt = 0;
|
|
uint32_t data_len = 0;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
|
|
node = (iot_plc_node_info_v2_t *)rpt->data;
|
|
data_len = sizeof(*rsp) +
|
|
max(drv_data->count_for_topo, rpt->count) * sizeof(rsp->node_info[0]);
|
|
pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
|
|
rsp = (proto_645_fj_query_topo_ul_t *)iot_pkt_data(pkt);
|
|
for (i = 0; i < rpt->count; ++i) {
|
|
iot_mac_addr_cpy(rsp->node_info[rpt_cnt].mac, node[i].addr);
|
|
iot_mac_addr_reverse(rsp->node_info[rpt_cnt].mac);
|
|
rsp->node_info[rpt_cnt].tei = node[i].sta_tei;
|
|
rsp->node_info[rpt_cnt].pco_tei = node[i].proxy_tei;
|
|
rsp->node_info[rpt_cnt].level = node[i].level;
|
|
rsp->node_info[rpt_cnt].role = node[i].role;
|
|
rpt_cnt++;
|
|
}
|
|
|
|
rsp->node_count = rpt->total_count;
|
|
rsp->ack_node_count = rpt_cnt;
|
|
rsp->node_start_index = drv_data->start_index_for_topo;
|
|
iot_pkt_put(pkt, sizeof(*rsp) + sizeof(rsp->node_info[0]) * rpt_cnt);
|
|
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
pkt_645 = proto_645_fj_build_qr_topo_resp(cco_mac, iot_pkt_data(pkt),
|
|
(uint8_t)iot_pkt_data_len(pkt));
|
|
|
|
if (pkt_645) {
|
|
iot_gw_drv_fj_meter_data_52h_f1(iot_pkt_data(pkt_645),
|
|
(uint16_t)iot_pkt_data_len(pkt_645), drv_data->cctt_cmd_sn, cco_mac,
|
|
PROTO_3762_FJ_OBJ_CCO);
|
|
iot_pkt_free(pkt_645);
|
|
}
|
|
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
void iot_gw_drv_fj_topo_handler(uint8_t req_id, iot_plc_nw_topo_rpt_t *rpt)
|
|
{
|
|
switch (req_id) {
|
|
case CCTT_REQ_ID_DRV_GET_TOPO_645:
|
|
{
|
|
iot_gw_drv_fj_drv_topo_rpt(rpt);
|
|
break;
|
|
}
|
|
default:
|
|
iot_sg_printf("iot_gw_drv_fj_topo_handler: invalid req id %d.\n",
|
|
req_id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void iot_gw_drv_fj_nb_nw_info_handler(iot_sg_nb_nw_rpt_t *req)
|
|
{
|
|
proto_645_fj_net_info_t *rsp;
|
|
iot_pkt_t *pkt, *pkt_645 = NULL;
|
|
|
|
pkt = iot_pkt_alloc(sizeof(*rsp) + req->count * sizeof(rsp->nb_nid[0]),
|
|
IOT_SMART_GRID_MID);
|
|
IOT_ASSERT(pkt);
|
|
rsp = (proto_645_fj_net_info_t*)iot_pkt_data(pkt);
|
|
proto_3762_nid_to_buf(iot_sg_cco_get_nid(), rsp->local_nid);
|
|
rsp->total_node_cnt = (uint8_t)req->count;
|
|
iot_sg_cco_get_major_node_mac(rsp->local_mac);
|
|
iot_pkt_put(pkt, sizeof(*rsp));
|
|
for (uint16_t i = 0; i < req->count; ++i) {
|
|
proto_3762_nid_to_buf(req->nb_info[i].nid, rsp->nb_nid[i]);
|
|
iot_pkt_put(pkt, sizeof(rsp->nb_nid[0]));
|
|
}
|
|
|
|
pkt_645 = proto_645_fj_build_qr_nb_nw_info_resp(rsp->local_mac,
|
|
iot_pkt_data(pkt), (uint8_t)iot_pkt_data_len(pkt));
|
|
|
|
if (pkt_645) {
|
|
iot_gw_drv_fj_meter_data_52h_f1(iot_pkt_data(pkt_645),
|
|
(uint16_t)iot_pkt_data_len(pkt_645), drv_data->cctt_cmd_sn,
|
|
rsp->local_mac, PROTO_3762_FJ_OBJ_CCO);
|
|
iot_pkt_free(pkt_645);
|
|
}
|
|
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
void iot_gw_drv_fj_qr_band_resp(iot_plc_freq_band_info_query_rpt_t *req)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
pkt = proto_645_fj_build_qr_freq_band_resp(cco_mac, req->freq_band);
|
|
|
|
if (pkt) {
|
|
iot_gw_drv_fj_meter_data_52h_f1(iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), drv_data->cctt_cmd_sn,
|
|
cco_mac, PROTO_3762_FJ_OBJ_CCO);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
void iot_gw_drv_fj_set_band_resp(uint8_t result)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
|
|
/* some cctt shall restart CCO, so reserve 1s to save the value to pib */
|
|
os_delay(1000);
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
if (!result) {
|
|
pkt = proto_645_2007_build_ack_msg(cco_mac,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
} else {
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, cco_mac,
|
|
PROTO_645_2007_FN_WRITE_DATA);
|
|
}
|
|
|
|
if (pkt) {
|
|
iot_gw_drv_fj_meter_data_52h_f1(iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), drv_data->cctt_cmd_sn,
|
|
cco_mac, PROTO_3762_FJ_OBJ_CCO);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void iot_gw_drv_fj_rpt_node_tsfm_evt(uint8_t *pm_mac, uint8_t *tsfm_addr,
|
|
uint8_t tsfm_status, uint8_t dev_type)
|
|
{
|
|
uint8_t err_type = 0, rpt_new_node_evt = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t tsfm_addr_tmp[IOT_MAC_ADDR_LEN];
|
|
|
|
if ((tsfm_status == IOT_SG_CCO_PM_TO_TSFM_1) ||
|
|
(tsfm_status == IOT_SG_CCO_PM_TO_TSFM_2)) {
|
|
drv_data->fj_data.same_tsfm_cnt++;
|
|
} else {
|
|
if (tsfm_status == IOT_SG_CCO_PM_TO_TSFM_4) {
|
|
err_type = PROTO_645_FJ_LIST_ERR_DIFF_TSFM;
|
|
rpt_new_node_evt = 1;
|
|
}
|
|
drv_data->fj_data.diff_tsfm_cnt++;
|
|
}
|
|
|
|
if (rpt_new_node_evt) {
|
|
iot_mac_addr_cpy(tsfm_addr_tmp, tsfm_addr);
|
|
iot_mac_addr_reverse(tsfm_addr_tmp);
|
|
pkt = proto_645_fj_build_list_abnormal_node_rpt(pm_mac, err_type,
|
|
tsfm_addr_tmp);
|
|
iot_sg_cco_handle_evt_rpt(NULL, pm_mac, pkt, NULL,
|
|
IOT_SG_CCO_EVENT_NORMAL, dev_type, 0);
|
|
}
|
|
}
|
|
|
|
void iot_gw_drv_fj_rpt_tsfm_detect_result(uint8_t sn)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
|
|
|
|
iot_sg_cco_get_major_node_mac(cco_mac);
|
|
pkt = proto_645_fj_build_tsfm_detect_result(cco_mac,
|
|
PROTO_645_FJ_FN_ACTIVE_RPT,
|
|
(uint16_t)(iot_sg_cco_get_tsfm_detect_used_time() / 60),
|
|
drv_data->fj_data.same_tsfm_cnt, drv_data->fj_data.diff_tsfm_cnt);
|
|
iot_gw_drv_fj_normal_event_report(sn, cco_mac, iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), PROTO_3762_FJ_OBJ_CCO);
|
|
}
|
|
#else /* IOT_SMART_GRID_FJ_ENABLE */
|
|
uint32_t iot_gw_drv_fj_handle_cmd(uint8_t afn, uint8_t *data, uint16_t len,
|
|
uint8_t sn, uint8_t fn, uint32_t *pkt_consumed, iot_pkt_t *pkt)
|
|
{
|
|
(void)afn;
|
|
(void)data;
|
|
(void)len;
|
|
(void)sn;
|
|
(void)fn;
|
|
(void)pkt_consumed;
|
|
(void)pkt;
|
|
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_node_info_handler(uint8_t sn, uint16_t index,
|
|
sec_node_query_t *sec_node_info)
|
|
{
|
|
(void)sn;
|
|
(void)index;
|
|
(void)sec_node_info;
|
|
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
uint32_t iot_gw_drv_fj_event_report_handler(uint8_t sn, uint8_t *pm_addr,
|
|
uint8_t dev_type, uint32_t proto_type, uint8_t evt_type, uint8_t *data,
|
|
uint16_t len)
|
|
{
|
|
(void)sn;
|
|
(void)pm_addr;
|
|
(void)dev_type;
|
|
(void)proto_type;
|
|
(void)evt_type;
|
|
(void)data;
|
|
(void)len;
|
|
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
void iot_gw_drv_fj_bcast_task_handle(uint8_t done)
|
|
{
|
|
(void)done;
|
|
}
|
|
|
|
void iot_gw_drv_fj_meter_data_handler(uint8_t *data, uint16_t len,
|
|
uint32_t afn, uint16_t sn, uint32_t proto_type, uint8_t *mac_field,
|
|
uint8_t mr_result, uint32_t plc_cost, uint8_t mr_type)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)afn;
|
|
(void)sn;
|
|
(void)proto_type;
|
|
(void)mac_field;
|
|
(void)mr_result;
|
|
(void)plc_cost;
|
|
(void)mr_type;
|
|
}
|
|
|
|
void iot_gw_drv_fj_rt_req_read_meter(uint8_t *mac, uint8_t obj_type)
|
|
{
|
|
(void)mac;
|
|
(void)obj_type;
|
|
}
|
|
|
|
void iot_gw_drv_fj_topo_handler(uint8_t req_id, iot_plc_nw_topo_rpt_t *rpt)
|
|
{
|
|
(void)req_id;
|
|
(void)rpt;
|
|
}
|
|
|
|
void iot_gw_drv_fj_nb_nw_info_handler(iot_sg_nb_nw_rpt_t *req)
|
|
{
|
|
(void)req;
|
|
}
|
|
|
|
void iot_gw_drv_fj_qr_band_resp(iot_plc_freq_band_info_query_rpt_t *req)
|
|
{
|
|
(void)req;
|
|
}
|
|
|
|
void iot_gw_drv_fj_set_band_resp(uint8_t result)
|
|
{
|
|
(void)result;
|
|
}
|
|
|
|
void iot_gw_drv_fj_rpt_node_tsfm_evt(uint8_t *pm_mac, uint8_t *tsfm_addr,
|
|
uint8_t tsfm_status, uint8_t dev_type)
|
|
{
|
|
(void)pm_mac;
|
|
(void)tsfm_addr;
|
|
(void)tsfm_status;
|
|
(void)dev_type;
|
|
}
|
|
|
|
void iot_gw_drv_fj_rpt_tsfm_detect_result(uint8_t sn)
|
|
{
|
|
(void)sn;
|
|
}
|
|
#endif /* IOT_SMART_GRID_FJ_ENABLE */
|