Files
kunlun/app/smart_grid/driver/cco/iot_gw_drv_fj.c
2024-09-28 14:24:04 +08:00

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 */