Files
kunlun/app/smart_grid/protocol/proto_645_topo.c

1431 lines
47 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
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_utils_api.h"
/* iot common header files */
#include "iot_app_api.h"
#include "iot_utils_api.h"
#include "iot_upgrade_api.h"
#include "iot_oem_api.h"
#include "iot_board_api.h"
#include "iot_bitmap_api.h"
#include "iot_io_api.h"
#include "iot_system_api.h"
#include "iot_plc_hw_topo_api.h"
#include "iot_plc_hw_tsfm_api.h"
/* smart grid internal header files */
#include "iot_sg.h"
#include "iot_sg_sta.h"
#include "proto_645.h"
#include "proto_645_vendor.h"
#include "proto_645_topo.h"
#include "iot_sg_sta_tsfm.h"
#include "iot_sg_sta_ext.h"
#include "proto_hw_tsfm.h"
#if (IOT_SMART_GRID_BRANCH_DETECT_ENABLE)
/* define branch recognition launch max length */
#define proto_645_vendor_br_lunch_max_len 10
/* define effective time of branch1 sn, uint is 1s. */
#define PROTO_645_EXT_TOPO_SN_VALID_TIME 30 * 60
/* define send mode, zero-crossing perturbance method. */
#define PROTO_645_EXT_SEND_MODE_ZC 0
/* define send mode, encoded pulse current injection method. */
#define PROTO_645_EXT_SEND_MODE_ENCODED_LOAD 1
/* define send mode, pulse current injection method done by PA */
#define PROTO_645_EXT_SEND_MODE_PA 2
#pragma pack(push) /* save the pack status */
#pragma pack(1) /* 1 byte align */
/* branch recognition launch optional payload */
typedef struct _proto_645_ext_br_launch_opt {
/* encode frequncy tone num for pa mode. each tone num is 75MHz/(1 << 14) */
uint16_t pa_freq_tone_num;
/* reserved for further use */
uint8_t rsvd[16];
} proto_645_ext_br_launch_opt_t;
/* branch recognition launch payload */
typedef struct _proto_645_ext_br_launch {
/* node sequence number */
uint16_t node_seq;
/* ahead interval time of sending data relative to zero-crossing point,
* uint is 1us. less than or equal to IOT_PLC_HW_TSFM_MAX_AHEAD_TIME,
* greater than or equal to IOT_PLC_HW_TSFM_MIN_AHEAD_TIME.
* If mode is IOT_PLC_HW_TSFM_MODE_PA
* or IOT_PLC_HW_TSFM_SEND_MODE_ENCODED_LOAD, uint is 1ms,
* ahead mean that transmitter send delay, greater than or equal to
* IOT_PLC_HW_TSFM_SEND_DELAY_MIN, less than or equal to
* IOT_PLC_HW_TSFM_SEND_DELAY_MAX.
*/
uint16_t ahead;
/* duration of bit data output, uint is 1us
* less than or equal to IOT_PLC_HW_TSFM_OUTPUT_MAX_TIME,
* greater than or equal to IOT_PLC_HW_TSFM_OUTPUT_MIN_TIME.
*/
uint16_t dur_output;
/* repeat cnt */
uint8_t repeat_cnt;
/* send mode, see IOT_PLC_HW_TSFM_SEND_MODE_XXX */
uint16_t send_mode : 4,
/* branch detect launch sequence number */
launch_sn : 8,
/* whether enable opt_data area
* 0 - not enable(opt_data length is 0); 1 - enable.
*/
opt_data_en : 1,
/* reserved for further use */
rsvd : 3;
/* optional data */
proto_645_ext_br_launch_opt_t opt_data[0];
} proto_645_ext_br_launch_t;
/* br test command payload */
typedef struct _proto_645_ext_br_test_req {
/* specified phase for br test, see PROTO_645_2007_EXT_BRM_PHASE_XXX */
uint8_t phase : 2,
/* plc rising edge zc send tsfm flag, it's phase negative zc flag. */
rising_send : 1,
/* reserved for further use */
rsvd : 5;
/* send mode, see PROTO_645_EXT_SEND_MODE_XXX */
uint8_t send_mode;
} proto_645_ext_br_test_req_t;
/* query br test reasult response */
typedef struct _proto_645_ext_br_test_query_rsp_opt {
/* energy */
uint32_t energy[IOT_PLC_PHASE_CNT];
/* current, unit is 1uA */
uint32_t current[IOT_PLC_PHASE_CNT];
/* reserved for further use */
uint8_t rsvd[7];
} proto_645_ext_br_test_query_rsp_opt_t;
/* query br test reasult response */
typedef struct _proto_645_ext_br_test_query_rsp {
/* tsfm topo rec phase info
* bit0 represent phase A
* bit1 represent phase B
* bit2 represent phase C
*/
uint8_t phase :3,
/* weather enable optional result data,
* 0 - not enable(the length of opt_data is 0); 1 - enable
*/
opt_data_en :1,
/* reserve for future */
rsvd :4;
/* optional result data */
proto_645_ext_br_test_query_rsp_opt_t opt_data[0];
} proto_645_ext_br_test_query_rsp_t;
/* branch recognition info query payload */
typedef struct _proto_645_ext_br_info_query {
/* data block sequence */
uint8_t block_seq : 6,
/* phase type, see PROTO_645_2007_EXT_BRM_PHASE_XXX */
phase_type : 2;
} proto_645_ext_br_info_query_t;
/* branch recognition receive optional payload */
typedef struct _proto_645_ext_br_receive_opt {
/* encode frequncy tone num for pa mode. each tone num is 75MHz/(1 << 14) */
uint16_t pa_freq_tone_num;
/* reserved for further use */
uint8_t rsvd[16];
} proto_645_ext_br_receive_opt_t;
/* branch recognition information clean down-link.
* for PROTO_645_2007_EXT_DI_BR_INFO_CLEAN
*/
typedef struct _proto_645_07_ext_brm_clean_dl {
/* receive phase, see PROTO_645_2007_EXT_BRM_PHASE_XXX */
uint8_t phase : 2,
/* reserve for future */
reserve : 5,
/* whether enable opt_data area
* 0 - not enable(opt_data length is 0); 1 - enable.
*/
opt_data_en : 1;
/* optional data */
proto_645_ext_br_receive_opt_t opt_data[0];
} proto_645_07_ext_brm_clean_dl_t;
#pragma pack(pop) /* restore the pack status */
uint32_t proto_645_vendor_br_rsp_check(proto_645_header_t *hdr,
proto_645_ext_br_rsp_cache_t *br_cache)
{
uint32_t ret = ERR_INVAL;
proto_645_ext_br_rsp_data_t *rsp_data;
if (hdr->control.dir != PROTO_645_DIR_SLAVE) {
goto out;
}
if (hdr->control.fn != PROTO_645_2007_EXT_FN_BR) {
goto out;
}
if (hdr->control.ack != PROTO_645_ACK_NORMAL) {
goto out;
}
if (hdr->len < sizeof(*rsp_data)) {
goto out;
}
if (br_cache != NULL) {
proto_645_sub33_handle(hdr->data, hdr->len);
rsp_data = (proto_645_ext_br_rsp_data_t *)hdr->data;
br_cache->di = rsp_data->di;
br_cache->result = rsp_data->result;
br_cache->format = rsp_data->format;
iot_mac_addr_cpy(br_cache->addr, hdr->addr);
br_cache->data_len = hdr->len - sizeof(*rsp_data);
if (br_cache->data_len) {
br_cache->data = rsp_data->data;
} else {
br_cache->data = NULL;
}
}
ret = ERR_OK;
out:
return ret;
}
uint32_t proto_645_vendor_conn_fwd_br_rsp_check(uint8_t **data,
uint32_t *data_len)
{
uint32_t di, ret = ERR_FAIL;
proto_645_header_t *hdr;
hdr = proto_645_format_check(*data, *data_len, PROTO_645_DIR_SLAVE);
if (!hdr) {
goto out;
}
if (hdr->control.fn != PROTO_645_2007_EXT_FN_BR) {
goto out;
}
if (hdr->control.ack != PROTO_645_ACK_NORMAL) {
goto out;
}
if (ERR_OK != proto_645_get_di_by_sub33(hdr->data, hdr->len,
PROTO_645_2007_ID, &di)) {
goto out;
}
if (di != PROTO_645_2007_EXT_BRM_FWD_DATA) {
ret = ERR_NOSUPP;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
*data = hdr->data + PROTO_645_2007_DI_LEN;
*data_len = hdr->len - PROTO_645_2007_DI_LEN;
ret = ERR_OK;
out:
return ret;
}
iot_pkt_t *proto_645_vendor_build_br_launch_req(uint8_t *addr,
uint8_t *fwd_addr, uint16_t node_seq, uint16_t ahead, uint16_t dur_output,
uint8_t repeat_cnt, uint8_t send_mode, uint8_t launch_sn, uint16_t pa_freq)
{
iot_pkt_t *pkt, *temp_pkt;
uint8_t data_buff[sizeof(proto_645_ext_br_launch_t) +
sizeof(proto_645_ext_br_launch_opt_t)] = { 0 };
proto_645_ext_br_launch_t *br_launch;
proto_645_ext_br_launch_opt_t *br_launch_opt;
br_launch = (proto_645_ext_br_launch_t *)data_buff;
br_launch->ahead = ahead;
br_launch->dur_output = dur_output;
br_launch->node_seq = node_seq;
br_launch->repeat_cnt = repeat_cnt;
br_launch->send_mode = send_mode;
br_launch->launch_sn = launch_sn;
br_launch->opt_data_en = 1;
br_launch_opt = br_launch->opt_data;
br_launch_opt->pa_freq_tone_num = pa_freq;
temp_pkt = proto_645_vendor_build_br_msg(addr, data_buff,
sizeof(data_buff), PROTO_645_2007_EXT_DI_BR_LAUNCH,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
if (!fwd_addr) {
return temp_pkt;
}
if (!temp_pkt) {
return NULL;
}
pkt = proto_645_vendor_build_br_msg(fwd_addr, iot_pkt_data(temp_pkt),
(uint8_t)iot_pkt_data_len(temp_pkt), PROTO_645_2007_EXT_BRM_FWD_DATA,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
iot_pkt_free(temp_pkt);
return pkt;
}
iot_pkt_t *proto_645_vendor_build_br_launch_state_req(uint8_t *addr,
uint8_t *fwd_addr)
{
iot_pkt_t *pkt, *temp_pkt;
temp_pkt = proto_645_vendor_build_br_msg(addr, NULL, 0,
PROTO_645_2007_EXT_DI_BR_LAUNCH_STATE, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
if (!fwd_addr) {
return temp_pkt;
}
if (!temp_pkt) {
return NULL;
}
pkt = proto_645_vendor_build_br_msg(fwd_addr, iot_pkt_data(temp_pkt),
(uint8_t)iot_pkt_data_len(temp_pkt), PROTO_645_2007_EXT_BRM_FWD_DATA,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
iot_pkt_free(temp_pkt);
return pkt;
}
iot_pkt_t *proto_645_vendor_build_br_info_query_req(uint8_t *addr, uint8_t seq,
uint8_t phase_type)
{
proto_645_ext_br_info_query_t req;
req.block_seq = seq;
req.phase_type = phase_type;
return proto_645_vendor_build_br_msg(addr, (uint8_t *)&req, sizeof(req),
PROTO_645_2007_EXT_DI_BR_INFO_QUERY, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
iot_pkt_t *proto_645_vendor_build_br_tsfm_addr_clear_req(uint8_t *addr)
{
return proto_645_vendor_build_br_msg(addr, NULL, 0,
PROTO_645_2007_EXT_DI_TSFM_LAUNCH_CLEAR, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
iot_pkt_t *proto_645_vendor_build_br_info_clean_req(uint8_t *addr,
uint8_t send_phase, uint16_t pa_freq)
{
proto_645_07_ext_brm_clean_dl_t *req;
proto_645_ext_br_receive_opt_t *opt_data;
uint8_t buff[sizeof(*req) + sizeof(*opt_data)] = { 0 };
uint8_t len = sizeof(*req);
req = (proto_645_07_ext_brm_clean_dl_t *)buff;
req->phase = send_phase;
req->opt_data_en = 1;
len += sizeof(*opt_data);
opt_data = req->opt_data;
opt_data->pa_freq_tone_num = pa_freq;
return proto_645_vendor_build_br_msg(addr, buff, len,
PROTO_645_2007_EXT_DI_BR_INFO_CLEAN, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
iot_pkt_t *proto_645_vendor_build_br_nei_node_info_query_req(uint8_t *addr,
uint8_t seq)
{
proto_645_07_ext_brm_nei_node_info_dl_t qr = { 0 };
qr.sn = seq;
return proto_645_vendor_build_br_msg(addr, (uint8_t *)&qr, sizeof(qr),
PROTO_645_2007_EXT_BRM_DI_NEI_NODE_INFO, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
iot_pkt_t *proto_645_vendor_build_br_tsfm_info_query_req(uint8_t *addr,
uint8_t *fwd_addr)
{
iot_pkt_t *pkt, *temp_pkt;
temp_pkt = proto_645_vendor_build_br_msg(addr, NULL, 0,
PROTO_645_2007_EXT_BRM_DI_CONN_NODE_TSFM_INFO, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
if (!temp_pkt) {
return NULL;
}
pkt = proto_645_vendor_build_br_msg(fwd_addr, iot_pkt_data(temp_pkt),
(uint8_t)iot_pkt_data_len(temp_pkt), PROTO_645_2007_EXT_BRM_FWD_DATA,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
iot_pkt_free(temp_pkt);
return pkt;
}
iot_pkt_t *proto_645_vendor_build_br_meter_info_query_req(uint8_t *addr,
uint8_t seq, uint8_t ver)
{
proto_645_ext_br_meter_query_t qr = { 0 };
qr.block_seq = seq;
qr.ver = ver;
return proto_645_vendor_build_br_msg(addr,(uint8_t *) &qr, sizeof(qr),
PROTO_645_2007_EXT_DI_BR_METER_QUERY, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
iot_pkt_t *proto_645_vendor_build_br_info_add_pm_req(uint8_t *addr,
uint8_t *data, uint8_t len)
{
return proto_645_vendor_build_br_msg(addr, data, len,
PROTO_645_2007_EXT_BRM_CCO_ADD_PM, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
#if IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ
iot_pkt_t *proto_645_vendor_build_br_launch_req_bj(uint8_t *addr,
uint16_t node_seq, uint16_t bit_dur, uint16_t high_dur, uint16_t low_dur,
uint8_t launch_sn)
{
proto_645_ext_br_launch_bj_t br_launch = { 0 };
br_launch.node_seq = node_seq;
br_launch.chara_bit_dur = bit_dur;
br_launch.pulse_high_dur = high_dur;
br_launch.pulse_low_dur = low_dur;
br_launch.launch_sn = launch_sn;
return proto_645_build_msg(addr, (uint8_t *)&br_launch, sizeof(br_launch),
PROTO_645_2007_EXT_DI_BR_BJ_LAUNCH, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_WRITE_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
}
iot_pkt_t *proto_645_vendor_build_br_info_query_req_bj(uint8_t *addr,
uint16_t start_idx, uint8_t num)
{
proto_645_ext_br_info_query_bj_t req = { 0 };
uint8_t max_num = (PROTO_645_MAX_DATA_LEN - PROTO_645_2007_DI_LEN -
sizeof(proto_645_ext_br_energy_rsp_bj_t)) /
sizeof(proto_645_ext_br_energy_unit_bj_t);
req.start_index = start_idx;
req.num = min(num, max_num);
return proto_645_build_msg(addr, (uint8_t *)&req, sizeof(req),
PROTO_645_2007_EXT_DI_BR_BJ_INFO_QUERY, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_READ_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
}
iot_pkt_t *proto_645_vendor_build_br_info_clean_req_bj(uint8_t *addr,
uint16_t bit_dur, uint32_t freq)
{
proto_645_ext_br_init_bj_t req = { 0 };
req.chara_bit_dur = bit_dur;
req.freq[0] = freq & 0xff;
req.freq[1] = (freq >> 8) & 0xff;
req.freq[2] = (freq >> 16) & 0xff;
return proto_645_build_msg(addr, (uint8_t *)&req, sizeof(req),
PROTO_645_2007_EXT_DI_BR_BJ_INIT, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_WRITE_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
}
#endif /* IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ */
#if IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_ZJ
iot_pkt_t *proto_645_vendor_build_br_launch_req_zj(uint8_t *addr,
uint16_t bit_dur, uint16_t high_dur, uint16_t low_dur, uint32_t freq,
uint8_t *code, uint8_t code_len, proto_645_07_time_ymdhms_t *timep)
{
iot_pkt_t *pkt;
uint16_t pkt_len, len;
proto_645_header_t *hdr;
proto_645_ext_br2_launch_zj_hdr_t *br_launch;
proto_645_ext_br2_launch_zj_tail_t *br_tail;
len = sizeof(proto_645_ext_br2_launch_zj_hdr_t) +
sizeof(proto_645_ext_br2_launch_zj_tail_t) + code_len;
pkt_len = PROTO_645_PREAMBLE_LEN + sizeof(proto_645_header_t) +
PROTO_645_2007_DI_LEN + len + sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
if (!pkt) {
return NULL;
}
iot_pkt_reserve(pkt, PROTO_645_PREAMBLE_LEN);
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_WRITE_DATA,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
proto_645_2007_di_to_byte(PROTO_645_2007_EXT_DI_BR2_LAUNCH_ZJ, hdr->data);
hdr->len += PROTO_645_2007_DI_LEN;
br_launch = (proto_645_ext_br2_launch_zj_hdr_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
br_launch->trans_type = PROTO_645_EXT_BR2_HANDLE;
if (timep) {
br_launch->tm = *timep;
} else {
os_mem_set(&br_launch->tm, 0xff, sizeof(br_launch->tm));
}
br_launch->chara_bit_dur = bit_dur;
br_launch->freq[0] = freq & 0xff;
br_launch->freq[1] = (freq >> 8) & 0xff;
br_launch->freq[2] = (freq >> 16) & 0xff;
br_launch->code_len = code_len;
os_mem_cpy(br_launch->code, code, code_len);
br_tail = (proto_645_ext_br2_launch_zj_tail_t*)(br_launch->code + code_len);
br_tail->pulse_high_dur = high_dur;
br_tail->pulse_low_dur = low_dur;
os_mem_set(&br_tail->code, 0, sizeof(br_tail->code));
hdr->len += len;
proto_645_add33_handle(hdr->data, hdr->len);
/* fill tail */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, pkt_len - PROTO_645_PREAMBLE_LEN);
return pkt;
}
iot_pkt_t *proto_645_vendor_build_br_info_query_req_zj(uint8_t *addr,
uint16_t start_idx, uint8_t cnt, proto_645_corr_time_t *start_time)
{
proto_645_ext_br2_recv_rec_dl_t req = {0};
req.start_time = *start_time;
req.start_index = start_idx;
req.cnt = cnt;
return proto_645_build_msg(addr, (uint8_t *)&req, sizeof(req),
PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_ZJ, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_READ_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
}
#endif /* IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_ZJ */
static uint8_t proto_645_vendor_br_ret_to_result(uint32_t ret)
{
uint8_t result;
switch (ret) {
case ERR_OK:
{
result = PROTO_645_2007_EXT_BR_RESULT_OK;
break;
}
case ERR_BUSY:
{
result = PROTO_645_2007_EXT_BR_RESULT_BUSY;
break;
}
case ERR_NOSUPP:
{
result = PROTO_645_2007_EXT_BR_RESULT_NOSUPP;
break;
}
case ERR_FAIL:
{
result = PROTO_645_2007_EXT_BR_RESULT_FAIL;
break;
}
case ERR_INVAL:
default:
result = PROTO_645_2007_EXT_BR_RESULT_INVAL;
break;
}
return result;
}
uint32_t proto_645_vendor_br_launch(uint8_t *data, uint8_t len,
hw_tsfm_send_cfg_t *cfg)
{
uint32_t ret = ERR_INVAL;
if (!len || len > proto_645_vendor_br_lunch_max_len) {
goto out;
}
ret = iot_plc_hw_tsfm_get_transmitter_state();
if (ret == ERR_OK) {
iot_plc_hw_tsfm_send(data, len, cfg);
}
out:
return ret;
}
static uint8_t proto_645_vendor_send_mode_auto_adap(uint8_t send_mode)
{
uint8_t mode, supp_mode;
supp_mode = iot_plc_hw_tsfm_get_supp_mode();
if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_PA &&
supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_LOAD)) {
mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
} else if (!(supp_mode & (1 << send_mode))) {
if (supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_ZC)) {
mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
} else if (supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_LOAD)) {
mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
} else if (supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_PA)) {
mode = IOT_PLC_HW_TSFM_SEND_MODE_PA;
} else {
mode = IOT_PLC_HW_TSFM_SEND_MODE_INVALID;
}
} else {
mode = send_mode;
}
return mode;
}
iot_pkt_t *proto_645_vendor_handle_br_launch_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
uint8_t reason = 0, dev_type, send_mode, len;
uint8_t data[PROTO_645_VENDOR_BR_DATA_LEN];
uint8_t addr[IOT_MAC_ADDR_LEN];
iot_pkt_t *pkt = NULL;
proto_645_ext_br_launch_t *br_launch = NULL;
proto_645_ext_br_launch_opt_t *br_launch_opt = NULL;
hw_tsfm_send_cfg_t cfg = { 0 };
proto_hw_tsfm_hdr_t *topo_hdr;
proto_hw_tsfm_topo_sn_t *topo_data;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
uint8_t result, repeat_cnt, encode = 0;
uint32_t ret = ERR_OK, last_ts, now_ts;
proto_645_ext_br_rsp_data_t *rsp = NULL;
proto_645_ext_br_send_rsp_t *rsp_data = NULL;
proto_645_header_t *build_hdr;
if (hdr->len < sizeof(*br_launch) + PROTO_645_2007_DI_LEN) {
reason = 1;
goto out;
}
os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
reason = 2;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
br_launch = (proto_645_ext_br_launch_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
if (br_launch->opt_data_en && (hdr->len >= sizeof(*br_launch) +
sizeof(*br_launch_opt) + PROTO_645_2007_DI_LEN)) {
br_launch_opt = br_launch->opt_data;
}
last_ts = sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.last_ts;
now_ts = (uint32_t)(os_boot_time64() / 1000);
if (((now_ts - last_ts) >= PROTO_645_EXT_TOPO_SN_VALID_TIME) && last_ts) {
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_is_valid = 0;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn = 0;
}
if (br_launch->launch_sn == sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn
&& sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_is_valid) {
result = PROTO_645_2007_EXT_BR_RESULT_OK;
send_mode = sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_send_mode;
reason = 4;
goto resp;
}
if (br_launch->send_mode < IOT_PLC_HW_TSFM_SEND_MODE_MAX) {
send_mode = (uint8_t)br_launch->send_mode;
encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_1;
} else {
if (sta_glb->drv) {
dev_type = (uint8_t)sta_glb->drv->get_device_type();
dev_type = iot_sg_sta_to_plc_dev_type(dev_type);
if (dev_type == IOT_PLC_DEV_TYPE_BRK_MONITOR
|| dev_type == IOT_PLC_DEV_TYPE_TSFM_MONITOR
|| dev_type == IOT_PLC_DEV_TYPE_SWITCH_MONITOR) {
send_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
} else {
send_mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_1;
}
} else {
send_mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_1;
}
}
send_mode = proto_645_vendor_send_mode_auto_adap(send_mode);
if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_INVALID) {
result = PROTO_645_2007_EXT_BR_RESULT_NOSUPP;
goto resp;
}
if (send_mode != IOT_PLC_HW_TSFM_SEND_MODE_PA) {
if (((now_ts - last_ts) < PROTO_645_EXT_TOPO_REPEAT_INTERVAL)
&& last_ts) {
result = PROTO_645_2007_EXT_BR_RESULT_BUSY;
reason = 5;
goto resp;
}
}
cfg.phase = IOT_PLC_PHASE_A;
repeat_cnt = br_launch->repeat_cnt;
cfg.mod_mode = send_mode;
if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_LOAD) {
cfg.cnt = repeat_cnt + 1;
repeat_cnt = 0;
if (encode) {
encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_2;
}
cfg.para.load.encode = encode;
cfg.para.load.pulse_high_dur = IOT_PLC_HW_TSFM_LOAD_SIG_HIGH_DUR_DEF;
cfg.para.load.pulse_low_dur = IOT_PLC_HW_TSFM_LOAD_SIG_LOW_DUR_DEF;
/* the characteristic bit duration is assigned to 0, and the
* corresponding value is determined by the lower layer according
* to the actual hardware configuration.
*/
cfg.para.load.chara_bit_dur = 0;
} else if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_PA) {
cfg.cnt = repeat_cnt + 1;
repeat_cnt = 0;
cfg.para.pa.offset_time = br_launch->ahead;
if (br_launch_opt) {
cfg.para.pa.freq_tone_num = br_launch_opt->pa_freq_tone_num;
}
} else {
cfg.cnt = 1;
cfg.para.zc.ahead = br_launch->ahead;
cfg.para.zc.dur_output = br_launch->dur_output;
}
if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_LOAD ||
send_mode == IOT_PLC_HW_TSFM_SEND_MODE_PA) {
topo_data = (proto_hw_tsfm_topo_sn_t*)data;
topo_data->sn = br_launch->node_seq;
len = sizeof(*topo_data);
} else {
topo_hdr = (proto_hw_tsfm_hdr_t*)data;
topo_hdr->data_id = PROTO_HW_TSFM_ID_TOPO_SN;
topo_hdr->data_len = sizeof(*topo_data);
topo_data = (proto_hw_tsfm_topo_sn_t*)topo_hdr->data;
topo_data->sn = br_launch->node_seq;
len = PROTO_645_VENDOR_BR_DATA_LEN;
}
if (!sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt) {
ret = proto_645_vendor_br_launch(data, len, &cfg);
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_send_mode = send_mode;
} else {
ret = ERR_BUSY;
}
result = proto_645_vendor_br_ret_to_result(ret);
iot_printf("%s ahead %lu, dur_output %lu, sn %lu, result %lu, repeat cnt "
"%lu\n", __FUNCTION__, br_launch->ahead, br_launch->dur_output,
br_launch->node_seq, result, repeat_cnt);
if (result == PROTO_645_2007_EXT_BR_RESULT_OK) {
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_is_valid = 1;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn = br_launch->launch_sn;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.last_ts = now_ts;
if (!sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt && repeat_cnt) {
if (repeat_cnt > PROTO_645_EXT_BRM_REPEAT_CNT_MAX) {
sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt =
PROTO_645_EXT_BRM_REPEAT_CNT_MAX;
} else {
sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt = repeat_cnt;
}
sta_glb->hw_tsfm_info.tsfm_topo_info.send_mode = send_mode;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.encode =
cfg.para.load.encode;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch1.ahead =
br_launch->ahead;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch1.dur_output =
br_launch->dur_output;
sta_glb->hw_tsfm_info.tsfm_topo_info.branch1.sn =
br_launch->node_seq;
}
}
resp:
pkt = iot_pkt_alloc(sizeof(*rsp) + sizeof(*rsp_data) +
sizeof(*build_hdr) + sizeof(proto_645_tailer_t), IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
build_hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(build_hdr, hdr->addr, PROTO_645_2007_EXT_FN_BR,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
build_hdr->len = sizeof(*rsp) + sizeof(*rsp_data);
rsp = (proto_645_ext_br_rsp_data_t *)build_hdr->data;
proto_645_2007_di_to_byte(di, rsp);
rsp->result = result;
rsp->format = 1;
rsp_data = (proto_645_ext_br_send_rsp_t *)rsp->data;
rsp_data->send_mode = send_mode;
switch (iot_plc_hw_tsfm_get_load_capacity()) {
case IOT_PLC_HW_TSFM_LOAD_CAP_2000MA:
{
rsp_data->load_capacity = PROTO_645_EXT_BR_LOAD_CAP_2000MA;
break;
}
default:
rsp_data->load_capacity = PROTO_645_EXT_BR_LOAD_CAP_400MA;
break;
}
os_mem_set(rsp_data->rsvd, 0, sizeof(rsp_data->rsvd));
if (result != PROTO_645_2007_EXT_BR_RESULT_OK) {
os_mem_set(rsp_data, 0, sizeof(*rsp_data));
}
proto_645_add33_handle(build_hdr->data, build_hdr->len);
proto_645_tail_init(build_hdr);
iot_pkt_put(pkt, sizeof(*rsp) + sizeof(*rsp_data) +
sizeof(*build_hdr) + sizeof(proto_645_tailer_t));
out:
if (reason) {
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_launch_state_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
uint8_t reason;
iot_pkt_t *pkt = NULL;
uint8_t addr[IOT_MAC_ADDR_LEN];
uint8_t result;
uint32_t ret;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (hdr->len < PROTO_645_2007_DI_LEN) {
reason = 1;
goto drop;
}
os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
reason = 2;
goto drop;
}
if (!sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt) {
ret = iot_plc_hw_tsfm_get_transmitter_state();
} else {
ret = ERR_BUSY;
}
result = proto_645_vendor_br_ret_to_result(ret);
iot_printf("%s result %lu\n", __FUNCTION__, result);
pkt = proto_645_vendor_build_br_msg(hdr->addr, &result, sizeof(result), di,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
goto out;
drop:
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
out:
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_recv_init_bj(proto_645_header_t *hdr)
{
iot_pkt_t *pkt = NULL;
uint8_t addr[IOT_MAC_ADDR_LEN];
uint8_t reason = PROTO_645_2007_ERR_OK;
proto_645_ext_br_init_bj_t *cmd;
iot_sg_ext_cus_topo_rcv_cfg_t cfg = { 0 };
os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr->addr)) {
return pkt;
}
if (hdr->len < (sizeof(*cmd) + PROTO_645_2007_DI_LEN)) {
reason = PROTO_645_2007_ERR_OTHER;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
cmd = (proto_645_ext_br_init_bj_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
cfg.fc = (cmd->freq[0]) | (cmd->freq[1] << 8) |
(cmd->freq[2] << 16);
cfg.chara_bit_dur = cmd->chara_bit_dur;
if (cfg.chara_bit_dur > PROTO_645_EXT_BR_BJ_CHARA_BIT_DUR_MAX) {
cfg.chara_bit_dur = PROTO_645_EXT_BR_BJ_CHARA_BIT_DUR_DEFAULT;
}
cfg.fr_code_len = 0;
cfg.similarity_thr = cmd->similarity_thr;
iot_sg_ext_topo_rcv_cfg_to_cus(&cfg);
iot_sg_sta_clear_tsfm_topo_info();
out:
if (reason) {
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
pkt = proto_645_2007_build_nack_msg(reason, hdr->addr,
PROTO_645_2007_FN_WRITE_DATA);
} else {
pkt = proto_645_2007_build_ack_msg(hdr->addr,
PROTO_645_2007_FN_WRITE_DATA);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_info_query_req_bj(
proto_645_header_t *hdr)
{
iot_pkt_t *pkt = NULL;
uint8_t *data;
uint8_t addr[IOT_MAC_ADDR_LEN], reason = 0, report_num = 0, data_len = 0;
uint16_t max_unit_count, map_len, i, idx;
proto_645_header_t *resp_hdr;
proto_645_ext_br_info_query_bj_t *br_info_query;
proto_645_ext_br_energy_rsp_bj_t *resp_data;
proto_645_ext_br_energy_unit_bj_t *energy_uint;
iot_sg_sta_hw_tsfm_t *hw_tsfm = &p_sg_glb->desc.sta->hw_tsfm_info;
iot_sg_sta_tsfm_topo_bm_t *local_bm = hw_tsfm->tsfm_topo_info.sn_bm;
if (!local_bm) {
reason = 1;
goto drop;
}
if (hdr->len < sizeof(*br_info_query) + PROTO_645_2007_DI_LEN) {
reason = 2;
goto drop;
}
os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr->addr)) {
reason = 3;
goto drop;
}
proto_645_sub33_handle(hdr->data, hdr->len);
br_info_query = (proto_645_ext_br_info_query_bj_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
if ( br_info_query->start_index >= PROTO_645_EXT_BR_BJ_NODE_ID_MAX) {
reason = 4;
goto drop;
}
pkt = iot_pkt_alloc(sizeof(*resp_hdr) + PROTO_645_MAX_DATA_LEN +
sizeof(proto_645_tailer_t), IOT_SMART_GRID_MID);
if (pkt == NULL) {
reason = 5;
goto drop;
}
data = iot_pkt_data(pkt);
resp_hdr = (proto_645_header_t*)data;
proto_645_header_init(resp_hdr, hdr->addr, hdr->control.fn,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
proto_645_2007_di_to_byte(PROTO_645_2007_EXT_DI_BR_BJ_INFO_QUERY,
resp_hdr->data);
data_len += PROTO_645_2007_DI_LEN;
resp_data = (proto_645_ext_br_energy_rsp_bj_t *)(resp_hdr->data +
PROTO_645_2007_DI_LEN);
/* count all valid sn in bitmap of topo sn in all phase */
resp_data->total_number = (uint16_t)iot_bitmap_cbs(local_bm->map,
sizeof(local_bm->map));
max_unit_count = (PROTO_645_MAX_DATA_LEN - PROTO_645_2007_DI_LEN -
sizeof(*resp_data)) / sizeof(*energy_uint);
max_unit_count = min(max_unit_count, br_info_query->num);
map_len = sizeof(local_bm->map);
for (i = 1, idx = 0; i < map_len * 8; i++) {
if (!iot_bitmap_is_set(local_bm->map, map_len, i + 1))
continue;
if (idx >= br_info_query->start_index) {
resp_data->energy_list[report_num].sn = i;
resp_data->energy_list[report_num].energy = local_bm->table[i - 1];
report_num++;
if (report_num >= max_unit_count) {
break;
}
}
idx++;
}
data_len += sizeof(*resp_data) + report_num * sizeof(*energy_uint);
resp_data->start_index = br_info_query->start_index;
resp_data->report_number = report_num;
resp_hdr->len = data_len;
proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
proto_645_tail_init(resp_hdr);
iot_pkt_put(pkt, data_len + sizeof(*resp_hdr) + sizeof(proto_645_tailer_t));
drop:
if (reason)
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_info_query_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
iot_pkt_t *pkt = NULL;
uint8_t addr[IOT_MAC_ADDR_LEN], reason;
uint16_t data_len, total_len;
uint32_t ret;
iot_sg_sta_tsfm_topo_desc_t bitmap_info = {0};
proto_645_ext_br_info_query_t *br_info_query;
proto_645_ext_br_rsp_data_t *resp_data;
proto_645_ext_br_info_rsp_t *br_info;
proto_645_ext_br_energy_rsp_t *br1_info;
proto_645_ext_br_energy_unit_t *energy_uint;
proto_645_header_t *resp_hdr;
if (hdr->len < sizeof(*br_info_query) + PROTO_645_2007_DI_LEN) {
reason = 1;
goto drop;
}
os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
reason = 2;
goto drop;
}
proto_645_sub33_handle(hdr->data, hdr->len);
br_info_query = (proto_645_ext_br_info_query_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
ret = iot_sg_sta_get_tsfm_topo_bitmap_info(&bitmap_info,
br_info_query->phase_type, br_info_query->block_seq);
data_len = sizeof(*resp_data);
if (ret) {
data_len = data_len + sizeof(*br_info);
iot_printf("%s resp nack %lu\n", __FUNCTION__);
} else {
if (bitmap_info.energy_cnt) {
iot_printf("%s energy_list start %lu, cnt %lu\n",
__FUNCTION__, bitmap_info.energy_idx, bitmap_info.energy_cnt);
data_len = data_len + sizeof(*br1_info) +
bitmap_info.energy_cnt * sizeof(*energy_uint);
} else if (bitmap_info.length) {
iot_printf("%s bitmap len %lu, first sn %lu, phase %lu\n",
__FUNCTION__, bitmap_info.length, bitmap_info.first_sn,
br_info_query->phase_type);
data_len = data_len + sizeof(*br_info) + bitmap_info.length;
} else {
IOT_ASSERT(0);
}
}
total_len = data_len + sizeof(*resp_hdr) + sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
if (pkt) {
resp_hdr = (proto_645_header_t *)iot_pkt_data(pkt);
/* fill in 645 header */
proto_645_header_init(resp_hdr, hdr->addr, PROTO_645_2007_EXT_FN_BR,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
resp_hdr->len = (uint8_t)data_len;
resp_data = (proto_645_ext_br_rsp_data_t*)resp_hdr->data;
proto_645_2007_di_to_byte(di, (uint8_t*)&resp_data->di);
resp_data->result = PROTO_645_2007_EXT_BR_RESULT_OK;
if (bitmap_info.energy_cnt) {
resp_data->format = 1;
br1_info = (proto_645_ext_br_energy_rsp_t*)resp_data->data;
br1_info->data_block_total = bitmap_info.block_cnt;
br1_info->data_block_seq = bitmap_info.curr_seq;
br1_info->phase_type = br_info_query->phase_type;
br1_info->energy_cnt = (uint8_t)bitmap_info.energy_cnt;
iot_sg_sta_tsfm_topo_fill_energy_info(
(uint8_t*)&br1_info->energy_list,
br_info_query->phase_type,
bitmap_info.energy_idx,
bitmap_info.energy_cnt);
} else {
resp_data->format = 0;
br_info = (proto_645_ext_br_info_rsp_t*)resp_data->data;
br_info->data_block_total = bitmap_info.block_cnt;
br_info->data_block_seq = bitmap_info.curr_seq;
br_info->phase_type = br_info_query->phase_type;
br_info->bm_data_len = (uint8_t)bitmap_info.length +
sizeof(br_info->start_index);
br_info->start_index = bitmap_info.first_sn;
iot_sg_sta_tsfm_topo_fill_bitmap_info(br_info->bitmap,
&bitmap_info, br_info_query->phase_type);
}
proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(resp_hdr);
iot_pkt_put(pkt, total_len);
}
goto out;
drop:
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
out:
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_info_clean_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
iot_pkt_t *pkt = NULL;
uint8_t addr[IOT_MAC_ADDR_LEN], reason;
uint16_t total_len, data_len;
uint8_t user_type = iot_oem_get_user_type();
proto_645_header_t *resp_hdr;
proto_645_ext_br_rsp_data_t *rsp_hdr;
proto_645_ext_br_clear_rsp_t *rsp_clear;
proto_645_07_ext_brm_clean_dl_t *clean_info;
iot_sg_ext_cus_topo_rcv_cfg_t cfg = { 0 };
if (hdr->len < (sizeof(*clean_info) + PROTO_645_2007_DI_LEN)) {
reason = 1;
goto drop;
}
os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
reason = 2;
goto drop;
}
data_len = sizeof(*rsp_hdr) + sizeof(*rsp_clear);
total_len = sizeof(*resp_hdr) + data_len + sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 3;
goto drop;
}
resp_hdr = (proto_645_header_t *)iot_pkt_put(pkt, total_len);
/* fill in 645 header */
proto_645_header_init(resp_hdr, hdr->addr, PROTO_645_2007_EXT_FN_BR,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
resp_hdr->len = (uint8_t)data_len;
rsp_hdr = (proto_645_ext_br_rsp_data_t *)resp_hdr->data;
proto_645_2007_di_to_byte(di, (uint8_t *)&rsp_hdr->di);
rsp_hdr->result = PROTO_645_2007_EXT_BR_RESULT_OK;
rsp_clear = (proto_645_ext_br_clear_rsp_t *)rsp_hdr->data;
proto_645_sub33_handle(hdr->data, hdr->len);
if (user_type == USER_TYPE_BRM_SMALL_LOAD_GOLDEN) {
cfg.chara_bit_dur = IOT_PLC_HW_TSFM_LOAD_CHARA_DUR_TEST / 1000;
} else {
cfg.chara_bit_dur = 300;
}
cfg.fc = IOT_HW_TOPO_DECODE_FREQ_LOAD_DEF;
iot_sg_ext_topo_rcv_cfg_to_cus(&cfg);
iot_sg_sta_clear_tsfm_topo_info();
iot_printf("%s chara bit dur: %d, fc: %lu\n", __FUNCTION__,
cfg.chara_bit_dur, cfg.fc);
if (IOT_BSRM_MODE || IOT_BRM_ENABLE) {
rsp_clear->br_ident = 1;
}
rsp_clear->send_supp_mode = iot_plc_hw_tsfm_get_supp_mode();
proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(resp_hdr);
goto out;
drop:
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
out:
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_test_req(
proto_645_header_t *hdr, uint32_t di)
{
uint8_t data[PROTO_645_VENDOR_BR_DATA_LEN];
iot_pkt_t *pkt = NULL;
hw_tsfm_send_cfg_t cfg = { 0 };
proto_hw_tsfm_hdr_t *topo_hdr;
proto_hw_tsfm_topo_sn_t *topo_data;
uint8_t result, len;
proto_645_ext_br_test_req_t *br_test_req;
uint32_t ret = ERR_OK;
if (hdr->len < PROTO_645_2007_DI_LEN + sizeof(*br_test_req)) {
cfg.phase = PROTO_645_2007_EXT_BRM_PHASE_A;
cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
goto send;
}
br_test_req = (proto_645_ext_br_test_req_t *)(hdr->data + \
PROTO_645_2007_DI_LEN);
if (br_test_req->phase > PROTO_645_2007_EXT_MAX_PHASE_NUM) {
result = PROTO_645_2007_EXT_BR_RESULT_INVAL;
goto out;
}
cfg.phase = br_test_req->phase;
switch (br_test_req->send_mode) {
case PROTO_645_EXT_SEND_MODE_ZC:
{
cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
cfg.cnt = 1;
cfg.para.zc.ahead = 500;
cfg.para.zc.dur_output = 300;
cfg.para.zc.is_rising = br_test_req->rising_send;
break;
}
case PROTO_645_EXT_SEND_MODE_ENCODED_LOAD:
{
cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
cfg.cnt = 1;
cfg.para.load.encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_2;
cfg.para.load.pulse_high_dur = IOT_PLC_HW_TSFM_LOAD_SIG_HIGH_DUR_DEF;
cfg.para.load.pulse_low_dur = IOT_PLC_HW_TSFM_LOAD_SIG_LOW_DUR_DEF;
/* the characteristic bit duration is assigned to 0, and the
* corresponding value is determined by the lower layer according
* to the actual hardware configuration.
*/
cfg.para.load.chara_bit_dur = 0;
break;
}
case PROTO_645_EXT_SEND_MODE_PA:
{
cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_PA;
cfg.cnt = 2;
cfg.para.pa.offset_time = 500;
break;
}
default:
result = PROTO_645_2007_EXT_BR_RESULT_INVAL;
goto out;
}
send:
if (cfg.mod_mode == IOT_PLC_HW_TSFM_SEND_MODE_ZC) {
topo_hdr = (proto_hw_tsfm_hdr_t *)data;
topo_hdr->data_id = PROTO_HW_TSFM_ID_TOPO_TEST;
topo_hdr->data_len = 0;
len = sizeof(*topo_hdr) + topo_hdr->data_len;
} else {
topo_data = (proto_hw_tsfm_topo_sn_t *)data;
topo_data->sn = PROTO_HW_TSFM_ID_TOPO_TEST;
len = sizeof(*topo_data);
}
ret = proto_645_vendor_br_launch(data, len, &cfg);
result = proto_645_vendor_br_ret_to_result(ret);
iot_printf("%s mode %lu ahead %lu, dur_output %lu, result %lu\n",
__FUNCTION__, cfg.mod_mode, cfg.para.zc.ahead, cfg.para.zc.dur_output,
result);
out:
pkt = proto_645_vendor_build_br_msg(hdr->addr, &result, sizeof(result),
di, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
return pkt;
}
iot_pkt_t *proto_645_vendor_handle_br_test_query_req(
proto_645_header_t *hdr, uint32_t di)
{
proto_645_ext_br_test_query_rsp_t *rsp = NULL;
proto_645_ext_br_test_query_rsp_opt_t *rsp_opt = NULL;
uint8_t data_buff[sizeof(*rsp) + sizeof(*rsp_opt)] = { 0 };
iot_pkt_t *pkt = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
uint8_t i;
rsp = (proto_645_ext_br_test_query_rsp_t *)data_buff;
rsp_opt = rsp->opt_data;
rsp->phase = sta_glb->hw_tsfm_info.topo_phase_rec & 0x07;
rsp->opt_data_en = 1;
for (i = 0; i < IOT_PLC_PHASE_CNT; i++) {
rsp_opt->energy[i] = sta_glb->hw_tsfm_info.topo_energy_rec[i];
}
iot_printf("%s phase rec info %02x, energy [%lu, %lu, %lu], "
"current [%lu, %lu, %lu]\n", __FUNCTION__, rsp->phase,
rsp_opt->energy[0], rsp_opt->energy[1], rsp_opt->energy[2],
rsp_opt->current[0], rsp_opt->current[1], rsp_opt->current[2]);
pkt = proto_645_vendor_build_br_msg(hdr->addr, data_buff, sizeof(data_buff),
di, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
return pkt;
}
#else /* IOT_SMART_GRID_BRANCH_DETECT_ENABLE */
iot_pkt_t *proto_645_vendor_build_br_launch_req(uint8_t *addr,
uint8_t *fwd_addr, uint16_t node_seq, uint16_t ahead, uint16_t dur_output,
uint8_t repeat_cnt, uint8_t send_mode, uint8_t launch_sn, uint16_t pa_freq)
{
(void)addr;
(void)fwd_addr;
(void)node_seq;
(void)ahead;
(void)dur_output;
(void)repeat_cnt;
(void)send_mode;
(void)launch_sn;
(void)pa_freq;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_launch_state_req(uint8_t *addr,
uint8_t *fwd_addr)
{
(void)addr;
(void)fwd_addr;
return NULL;
}
iot_pkt_t *proto_645_vendor_handle_br_recv_init_bj(proto_645_header_t *hdr)
{
(void)hdr;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_info_query_req(uint8_t *addr,
uint8_t seq, uint8_t phase_type)
{
(void)addr;
(void)seq;
(void)phase_type;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_tsfm_addr_clear_req(uint8_t *addr)
{
(void)addr;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_info_clean_req(uint8_t *addr,
uint8_t send_phase, uint16_t pa_freq)
{
(void)addr;
(void)send_phase;
(void)pa_freq;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_nei_node_info_query_req(uint8_t *addr,
uint8_t seq)
{
(void)addr;
(void)seq;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_tsfm_info_query_req(uint8_t *addr,
uint8_t *fwd_addr)
{
(void)addr;
(void)fwd_addr;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_meter_info_query_req(uint8_t *addr,
uint8_t seq, uint8_t ver)
{
(void)addr;
(void)seq;
(void)ver;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_info_add_pm_req(uint8_t *addr,
uint8_t *data, uint8_t len)
{
(void)addr;
(void)data;
(void)len;
return NULL;
}
#if IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ
iot_pkt_t *proto_645_vendor_build_br_launch_req_bj(uint8_t *addr,
uint16_t node_seq, uint16_t bit_dur, uint16_t high_dur, uint16_t low_dur,
uint8_t launch_sn)
{
(void)addr;
(void)node_seq;
(void)bit_dur;
(void)high_dur;
(void)low_dur;
(void)launch_sn;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_info_query_req_bj(uint8_t *addr,
uint16_t start_idx, uint8_t num)
{
(void)addr;
(void)start_idx;
(void)num;
return NULL;
}
iot_pkt_t *proto_645_vendor_build_br_info_clean_req_bj(uint8_t *addr,
uint16_t bit_dur, uint32_t freq)
{
(void)addr;
(void)bit_dur;
(void)freq;
return NULL;
}
#endif /* IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ */
uint32_t proto_645_vendor_br_rsp_check(proto_645_header_t *hdr,
proto_645_ext_br_rsp_cache_t *br_rsp)
{
(void)hdr;
(void)br_rsp;
return ERR_NOSUPP;
}
uint32_t proto_645_vendor_conn_fwd_br_rsp_check(uint8_t **data,
uint32_t *data_len)
{
(void)data;
(void)data_len;
return ERR_NOSUPP;
}
iot_pkt_t *proto_645_vendor_handle_br_launch_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
(void)hdr;
(void)di;
(void)flag_addr_check;
return NULL;
}
iot_pkt_t *proto_645_vendor_handle_br_launch_state_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
(void)hdr;
(void)di;
(void)flag_addr_check;
return NULL;
}
iot_pkt_t *proto_645_vendor_handle_br_info_query_req_bj(
proto_645_header_t *hdr)
{
(void)hdr;
return NULL;
}
iot_pkt_t *proto_645_vendor_handle_br_info_query_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
(void)hdr;
(void)di;
(void)flag_addr_check;
return NULL;
}
iot_pkt_t *proto_645_vendor_handle_br_info_clean_req(
proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
{
(void)hdr;
(void)di;
(void)flag_addr_check;
return NULL;
}
uint32_t proto_645_vendor_br_launch(uint8_t *data, uint8_t len,
hw_tsfm_send_cfg_t *cfg)
{
(void)data;
(void)len;
(void)cfg;
return ERR_NOSUPP;
}
iot_pkt_t *proto_645_vendor_handle_br_test_req(
proto_645_header_t *hdr, uint32_t di)
{
(void)hdr;
(void)di;
return NULL;
}
iot_pkt_t *proto_645_vendor_handle_br_test_query_req(
proto_645_header_t *hdr, uint32_t di)
{
(void)hdr;
(void)di;
return NULL;
}
#endif /* IOT_SMART_GRID_BRANCH_DETECT_ENABLE */