1604 lines
55 KiB
C
1604 lines
55 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
|
|
/* os_shim header files */
|
|
#include "os_types_api.h"
|
|
#include "os_timer_api.h"
|
|
#include "os_utils_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_config_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_module_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_utils_api.h"
|
|
#include "iot_bitmap_api.h"
|
|
#include "iot_pkt_api.h"
|
|
#include "iot_system_api.h"
|
|
#include "iot_plc_hw_tsfm_api.h"
|
|
#include "iot_plc_msg_api.h"
|
|
#include "iot_plc_led_api.h"
|
|
#include "iot_uart_api.h"
|
|
|
|
/* branch management internal header files */
|
|
#include "iot_brm_msg.h"
|
|
#include "iot_brm_common.h"
|
|
#include "iot_brm_rtc.h"
|
|
#include "iot_brm_nv.h"
|
|
#include "iot_brm_mr.h"
|
|
#include "iot_brm_ass_check.h"
|
|
|
|
/* breaker header files */
|
|
#include "iot_brm_brk.h"
|
|
|
|
/* protocol header file */
|
|
#include "proto_69845.h"
|
|
#include "proto_645.h"
|
|
#include "proto_645_vendor.h"
|
|
#include "proto_645_topo.h"
|
|
#include "proto_hw_tsfm.h"
|
|
#include "proto_3761.h"
|
|
|
|
#if IOT_BRM_ENABLE
|
|
|
|
/* define assembly check state */
|
|
/* assembly check not performed */
|
|
#define IOT_BRM_ASS_CHK_STATE_IDLE 0
|
|
/* in this state, waiting to receive more assembly information */
|
|
#define IOT_BRM_ASS_CHK_STATE_RECV_WAIT 1
|
|
/* in this state, the node probe command is to be issued */
|
|
#define IOT_BRM_ASS_CHK_STATE_NODE_READY 2
|
|
/* in this state, the probe command has been issued, waiting for response */
|
|
#define IOT_BRM_ASS_CHK_STATE_NODE_WAIT 3
|
|
#define IOT_BRM_ASS_CHK_STATE_NODE_PLC 4
|
|
/* in this state, wait for other check to be done */
|
|
#define IOT_BRM_ASS_CHK_STATE_WAIT_OTHER 5
|
|
/* in this state, the assembly check is done, wait for some time
|
|
* and restart.
|
|
*/
|
|
#define IOT_BRM_ASS_CHK_STATE_DONE 6
|
|
|
|
/* define wiring check status */
|
|
#define IOT_BRM_ASS_WIRE_CHK_STATE_IDLE 0
|
|
#define IOT_BRM_ASS_WIRE_CHK_STATE_DIRECT 1
|
|
#define IOT_BRM_ASS_WIRE_CHK_STATE_BD_SEND 2
|
|
#define IOT_BRM_ASS_WIRE_CHK_STATE_BD_RCV 3
|
|
#define IOT_BRM_ASS_WIRE_CHK_STATE_DONE 4
|
|
|
|
/* define meter assembly check status */
|
|
#define IOT_BRM_ASS_NODE_CHK_STATE_PEND 0 /* no check completed */
|
|
#define IOT_BRM_ASS_NODE_CHK_STATE_OK 1 /* assembly ok */
|
|
#define IOT_BRM_ASS_NODE_CHK_STATE_NOT_OK 2 /* assembly not ok */
|
|
|
|
|
|
/* define the send wait timeout for branch identification signals, uint is 1s */
|
|
#define IOT_BRM_ASS_WIRE_CHK_BD_SEND_TIMEOUT 50
|
|
/* define the receive wait timeout for branch identification signals */
|
|
#define IOT_BRM_ASS_WIRE_CHK_BD_RCV_TIMEOUT 90
|
|
|
|
/* define the max try number of assembly check to meter */
|
|
#define IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485_698_PROXY 1
|
|
#define IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485 2
|
|
#define IOT_BRM_ASS_NODE_CHK_TRY_MAX_PLC 3
|
|
|
|
/* define the duration for which the configuration will take effect,
|
|
* uint is 1s
|
|
*/
|
|
#define IOT_BRM_ASS_NODE_CHK_CONFIG_DUR 15
|
|
|
|
/* define timeout for node assembly check, uint is 1ms */
|
|
#define IOT_BRM_ASS_NODE_CHK_TIMEOUT_PLC 11000 /* PLC node */
|
|
#define IOT_BRM_ASS_NODE_CHK_TIMEOUT_RS485 1600 /* RS485 node */
|
|
#define IOT_BRM_ASS_NODE_CHK_TIMEOUT_RS485_FOR_3761 12000
|
|
#define IOT_BRM_ASS_NODE_CHK_TIMEOUT_RS485_FOR_69845 20000
|
|
|
|
/* define the timeout for continuous receiving of assembly check info,
|
|
* uint is 1ms.
|
|
*/
|
|
#define IOT_BRM_ASS_REV_ASS_INFO_TIMEOUT 5000
|
|
|
|
/* node assembly check info descriptor */
|
|
typedef struct _iot_brm_ass_node_entry {
|
|
/* node addr, little-endian */
|
|
uint8_t addr[IOT_MAC_ADDR_LEN];
|
|
/* assembly check state, see IOT_BRM_ASS_NODE_CHK_STATE_XXX */
|
|
uint8_t state : 2,
|
|
/* node proto type, see IOT_BRM_PROTO_TYPE_XXX */
|
|
pid : 3,
|
|
/* node baud rate id, see IOT_BRM_BUAD_ID_XXX */
|
|
bid : 3;
|
|
/* remaining try counter */
|
|
uint8_t re_try;
|
|
} iot_brm_ass_node_entry_t;
|
|
|
|
/* assembly check control descriptor */
|
|
typedef struct _iot_brm_ass_chk_ctrl {
|
|
/* checked nodes */
|
|
iot_brm_ass_node_entry_t node_ent[IOT_BRM_SUPPORT_NODE_MAX];
|
|
/* check state, see IOT_BRM_ASS_CHK_STATE_XXX */
|
|
uint8_t state :3,
|
|
/* wiring check state, see IOT_BRM_ASS_WIRE_CHK_STATE_XXX */
|
|
wire_chk_state :3,
|
|
/* flag mark to nodes are connected by PLC */
|
|
is_plc_con :1,
|
|
/* reserved for further use */
|
|
check_en_for_3761 :1;
|
|
/* phase line of current branch launch, see IOT_PLC_PHASE_X */
|
|
uint8_t phase;
|
|
/* PLC connect mode, only bit "is_plc_con"set, these bit fields
|
|
* are valid, see PROTO_645_EXT_BRM_ASS_CHK_PLC_MODE_XXX
|
|
*/
|
|
uint8_t plc_mode;
|
|
/* PLC communicate band, only bit "is_plc_con"set, these bit fields
|
|
* are valid, see PLC_LIB_FREQ_BAND_XXX
|
|
*/
|
|
uint8_t plc_band;
|
|
/* mr buffer's customer ID */
|
|
uint8_t custom_id;
|
|
/* wiring check counter */
|
|
uint32_t wire_chk_cnt;
|
|
/* plc check counter */
|
|
uint32_t plc_cfg_cmd_cnt;
|
|
/* baud rate index in use */
|
|
uint8_t b_idx;
|
|
/* wiring check status, see IOT_BRM_ASS_WIRE_XXX */
|
|
uint8_t wire_chk_st[IOT_BRM_PHASE_C];
|
|
/* start time stamp of check, uint is 1s */
|
|
uint32_t start_ts;
|
|
/* terminal communication port number, see PROTO_PORT_RS485_X */
|
|
uint8_t trans_port :2,
|
|
/* if communication success, lock the terminal port */
|
|
trans_port_lock :1,
|
|
/* fix the terminal baud rate, if communicate success with terminal */
|
|
b_idx_lock :1,
|
|
/* not used */
|
|
rsvd :4;
|
|
/* timer for check */
|
|
timer_id_t chk_timer;
|
|
/* baud rate table to be checking, only used for assembly check of 485 nodes
|
|
*/
|
|
uint32_t buad_tab[IOT_BRM_PROTO_TYPE_MAX][IOT_BRM_SUPPORT_BAUD_MAX];
|
|
/* protocol table to be checking */
|
|
uint8_t protocol_table[IOT_BRM_PROTO_TYPE_MAX];
|
|
} iot_brm_ass_chk_ctrl_t;
|
|
|
|
static iot_brm_ass_chk_ctrl_t g_ass_ccb = {
|
|
.state = IOT_BRM_ASS_CHK_STATE_IDLE,
|
|
.buad_tab = {
|
|
{0, 0, 0, 0, 0}, /* transparent transmission */
|
|
{1200, 0, 0, 0, 0}, /* dl/t 645-1997 */
|
|
{2400, 0, 0, 0, 0}, /* dl/t 645-2007 */
|
|
{9600, 0, 0, 0, 0}, /* dl/t 698-45 */
|
|
{9600, 2400, 0, 0, 0}, /* 376.1 */
|
|
{9600, 0, 0, 0, 0}, /* 698.45-trans */
|
|
{9600, 2400, 0, 0, 0}, /* 698.45-trans 376.1*/
|
|
{9600, 0, 0, 0, 0}, /* 698.45-trans 698.45*/
|
|
},
|
|
};
|
|
|
|
static uint8_t sn_3761;
|
|
static uint8_t sn_698;
|
|
|
|
static iot_brm_ass_node_entry_t *iot_brm_ass_first_pend_node(void)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_ass_node_entry_t *node;
|
|
uint8_t i;
|
|
for (i = 0; i < IOT_BRM_SUPPORT_NODE_MAX; i++) {
|
|
node = &ccb->node_ent[i];
|
|
if (!iot_mac_addr_valid(node->addr)) {
|
|
break;
|
|
}
|
|
if (node->state == IOT_BRM_ASS_NODE_CHK_STATE_PEND) {
|
|
return node;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static iot_brm_ass_node_entry_t *iot_brm_ass_find_node(uint8_t *addr)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_ass_node_entry_t *node;
|
|
uint8_t i;
|
|
for (i = 0; i < IOT_BRM_SUPPORT_NODE_MAX; i++) {
|
|
node = &ccb->node_ent[i];
|
|
if (!iot_mac_addr_valid(node->addr)) {
|
|
break;
|
|
}
|
|
if (iot_mac_addr_cmp(node->addr, addr)) {
|
|
return node;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_brm_ass_check_proto_table_init() - initialization the table to
|
|
load the protocols that will be used for check meter.
|
|
*/
|
|
static void iot_brm_ass_check_proto_table_init(void)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_terminal_cfg_t cfg;
|
|
/* Note that must use IOT_BRM_PROTO_TYPE_TRANSPARENT as the last protocol,
|
|
* and the baud rate table of each protocol in the protocol list must be
|
|
* consistent.
|
|
*/
|
|
if (ccb->is_plc_con) {
|
|
/* Protocol table for PLC communication with the meter */
|
|
ccb->protocol_table[0] = IOT_BRM_PROTO_TYPE_69845;
|
|
ccb->protocol_table[1] = IOT_BRM_PROTO_TYPE_645_2007;
|
|
ccb->protocol_table[2] = IOT_BRM_PROTO_TYPE_645_1997;
|
|
ccb->protocol_table[3] = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
} else if (ccb->check_en_for_3761) {
|
|
if (iot_brm_get_terminal_cfg(&cfg) != ERR_OK) {
|
|
/* unknown type proxy transfer */
|
|
iot_brm_printf("%s: please set the terminal info first.\n",
|
|
__FUNCTION__);
|
|
IOT_ASSERT(0);
|
|
} else if (cfg.is_698) {
|
|
/* Protocol table for 698.45 proxy transfer */
|
|
ccb->protocol_table[0] = IOT_BRM_PROTO_TYPE_69845_BY_69845;
|
|
ccb->protocol_table[1] = IOT_BRM_PROTO_TYPE_645_2007_BY_69845;
|
|
ccb->protocol_table[2] = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
} else {
|
|
/* Protocol table for 376.1 proxy transfer */
|
|
ccb->protocol_table[0] = IOT_BRM_PROTO_TYPE_69845_BY_3761;
|
|
ccb->protocol_table[1] = IOT_BRM_PROTO_TYPE_645_2007_BY_3761;
|
|
ccb->protocol_table[2] = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
}
|
|
} else {
|
|
/* Protocol table for direct communication with the meter */
|
|
ccb->protocol_table[0] = IOT_BRM_PROTO_TYPE_69845;
|
|
ccb->protocol_table[1] = IOT_BRM_PROTO_TYPE_645_2007;
|
|
ccb->protocol_table[2] = IOT_BRM_PROTO_TYPE_645_1997;
|
|
ccb->protocol_table[3] = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief iot_brm_ass_check_load_proto() - initialization the global variable
|
|
* for start a new protocol.
|
|
* @param node: Node that need to load protocol.
|
|
*/
|
|
static void iot_brm_ass_check_load_proto(
|
|
iot_brm_ass_node_entry_t *node)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_printf("%s pid: %d\n", __FUNCTION__, node->pid);
|
|
if (!ccb->b_idx_lock) {
|
|
ccb->b_idx = 0;
|
|
} else if (ccb->buad_tab[node->pid][ccb->b_idx] == 0) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
switch (node->pid) {
|
|
case IOT_BRM_PROTO_TYPE_69845:
|
|
case IOT_BRM_PROTO_TYPE_645_2007:
|
|
case IOT_BRM_PROTO_TYPE_645_1997:
|
|
{
|
|
if (ccb->is_plc_con)
|
|
node->re_try = IOT_BRM_ASS_NODE_CHK_TRY_MAX_PLC;
|
|
else
|
|
node->re_try = IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485;
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_69845_BY_3761:
|
|
case IOT_BRM_PROTO_TYPE_645_2007_BY_3761:
|
|
{
|
|
node->re_try = IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485;
|
|
if (!ccb->trans_port_lock)
|
|
ccb->trans_port = PROTO_PORT_RS485_2;
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_69845_BY_69845:
|
|
case IOT_BRM_PROTO_TYPE_645_2007_BY_69845:
|
|
{
|
|
node->re_try = IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485_698_PROXY;
|
|
if (!ccb->trans_port_lock)
|
|
ccb->trans_port = PROTO_PORT_RS485_1;
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_TRANSPARENT:
|
|
default:
|
|
/* never in this case, if goto here, please check protocol_table */
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief iot_brm_ass_check_proto_switch_next() - switch to next protocol in the
|
|
* protocol table.
|
|
* @param node: Node that need to switch protocol.
|
|
* @retval: 1 - for success case, 0 - for no more protocol in the table.
|
|
*/
|
|
static uint8_t iot_brm_ass_check_proto_switch_next(
|
|
iot_brm_ass_node_entry_t *node)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
uint8_t p_idx;
|
|
/* get the protocol index of the node's pid */
|
|
for (p_idx = 0; p_idx < IOT_BRM_PROTO_TYPE_MAX; p_idx++) {
|
|
if (ccb->protocol_table[p_idx] == node->pid) {
|
|
break;
|
|
}
|
|
}
|
|
p_idx++;
|
|
if (p_idx >= IOT_BRM_PROTO_TYPE_MAX
|
|
|| ccb->protocol_table[p_idx] == IOT_BRM_PROTO_TYPE_TRANSPARENT) {
|
|
/* all protocol are tried, switch to the first protocol, and return
|
|
* switch fail.
|
|
*/
|
|
node->pid = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
return 0;
|
|
}
|
|
node->pid = ccb->protocol_table[p_idx];
|
|
iot_brm_ass_check_load_proto(node);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_brm_ass_build_69845_detect_pkt() - build request packet for assembly
|
|
* check use 698.45 protocol.
|
|
* @param node: node information.
|
|
* @retval if success, return the request packet,
|
|
* otherwise, return NULL.
|
|
*/
|
|
static iot_pkt_t *iot_brm_ass_build_69845_detect_pkt(
|
|
iot_brm_ass_node_entry_t *node)
|
|
{
|
|
server_addr_info_t server = {0};
|
|
proto_69845_app_get_req_info_t req = {0};
|
|
req.type = PROTO_69845_APP_GET_NORMAL;
|
|
req.piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
|
|
req.piid.sn = 0;
|
|
req.oad.oi = PROTO_69845_APP_OI_ADDR;
|
|
req.oad.attribute_id = 2;
|
|
req.oad.attribute_char = 0;
|
|
req.oad.element_index = 0;
|
|
server.len = PROTO_69845_SA_LEN;
|
|
server.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server.addr, node->addr);
|
|
return proto_69845_build_get_req_msg(&req, &server);
|
|
}
|
|
|
|
/**
|
|
* @brief iot_brm_ass_build_3761_proxy_detect_pkt() - add wrap for use 376.1 protocol
|
|
* proxy transfer command request.
|
|
* @param content: original frame.
|
|
* @param baud: the baud rate of proxy device communicate with target device.
|
|
* @retval if success, return the proxy packet,
|
|
* otherwise, return NULL.
|
|
* @note this function will free content.
|
|
*/
|
|
static iot_pkt_t *iot_brm_ass_build_3761_proxy_detect_pkt(iot_pkt_t *content,
|
|
uint32_t baud)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_terminal_cfg_t config;
|
|
iot_pkt_t *fwd_pkt;
|
|
uint16_t dev_addr = PROTO_3761_BCAST_DEV_ADRR, area_code = 9999;
|
|
IOT_ASSERT(content != NULL);
|
|
if (iot_brm_get_terminal_cfg(&config) == ERR_OK && !config.is_698) {
|
|
dev_addr = config.terminal_addr.trans_3761.dev_addr;
|
|
area_code = config.terminal_addr.trans_3761.area_code;
|
|
}
|
|
sn_3761 = proto_3761_get_sn();
|
|
fwd_pkt = proto_3761_build_afn10f01_dl_msg(iot_pkt_data(content), \
|
|
(uint16_t)iot_pkt_data_len(content),
|
|
baud, ccb->trans_port, IOT_UART_PARITY_EVEN,
|
|
IOT_BRM_PROXY_TRANS_TIMEOUT, IOT_BRM_MID,
|
|
&dev_addr, &area_code, sn_3761);
|
|
iot_pkt_free(content);
|
|
return fwd_pkt;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_brm_ass_build_69845_proxy_detect_pkt() - add wrap for use 698.45 protocol
|
|
* proxy transfer command request.
|
|
* @param content: original frame.
|
|
* @param baud: the baud rate of proxy device communicate with target device.
|
|
* @retval if success, return the proxy packet,
|
|
* otherwise, return NULL.
|
|
* @note this function will free content.
|
|
*/
|
|
static iot_pkt_t *iot_brm_ass_build_69845_proxy_detect_pkt(iot_pkt_t *content,
|
|
uint32_t baud)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
server_addr_info_t server = {0};
|
|
iot_brm_terminal_cfg_t config;
|
|
iot_pkt_t *fwd_pkt;
|
|
if (iot_brm_get_terminal_cfg(&config) == ERR_OK && config.is_698) {
|
|
server.len = PROTO_69845_SA_LEN;
|
|
server.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server.addr, config.terminal_addr.trans_698_addr);
|
|
} else {
|
|
server = proto_69845_any_server_addr;
|
|
}
|
|
sn_698 = iot_brm_mr_698_get_apdu_sn();
|
|
fwd_pkt = proto_69845_build_proxy_trans_data_msg(iot_pkt_data(content), \
|
|
(uint16_t)iot_pkt_data_len(content),
|
|
baud, ccb->trans_port, PROTO_69845_PARITY_EVEN,
|
|
IOT_BRM_PROXY_TRANS_TIMEOUT, &server, sn_698);
|
|
iot_pkt_free(content);
|
|
return fwd_pkt;
|
|
}
|
|
|
|
static uint8_t iot_brm_ass_node_check_issue(uint32_t *to)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_ass_node_entry_t *node;
|
|
iot_pkt_t *pkt = NULL, *fwd_pkt;
|
|
uint8_t *preamble = NULL, *data, ret = ERR_OK, preamble_fill = 1;
|
|
uint32_t pre_len = 0;
|
|
node = iot_brm_ass_first_pend_node();
|
|
if (node == NULL) {
|
|
return ERR_NOT_EXIST;
|
|
}
|
|
/* When first time to check one node, load the first matching protocol */
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_TRANSPARENT) {
|
|
node->pid = ccb->protocol_table[0];
|
|
iot_brm_ass_check_load_proto(node);
|
|
}
|
|
|
|
switch (node->pid) {
|
|
case IOT_BRM_PROTO_TYPE_645_1997:
|
|
{
|
|
preamble = (uint8_t *)proto_645_preamble;
|
|
pre_len = PROTO_645_PREAMBLE_LEN;
|
|
pkt = proto_645_build_mr_msg(PROTO_645_1997_ID,
|
|
node->addr, PROTO_645_1997_DI_R_ADDR);
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_645_2007:
|
|
{
|
|
preamble = (uint8_t *)proto_645_preamble;
|
|
pre_len = PROTO_645_PREAMBLE_LEN;
|
|
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID,
|
|
node->addr, PROTO_645_2007_DI_R_ADDR);
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_69845:
|
|
{
|
|
preamble = (uint8_t *)proto_69845_preamble;
|
|
pre_len = PROTO_69845_PREAMBLE_LEN;
|
|
pkt = iot_brm_ass_build_69845_detect_pkt(node);
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_645_2007_BY_3761:
|
|
case IOT_BRM_PROTO_TYPE_645_2007_BY_69845:
|
|
{
|
|
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID,
|
|
node->addr, PROTO_645_2007_DI_R_ADDR);
|
|
if (pkt == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
data = iot_pkt_push(pkt, PROTO_645_PREAMBLE_LEN);
|
|
os_mem_cpy(data, proto_645_preamble, PROTO_645_PREAMBLE_LEN);
|
|
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_3761) {
|
|
/* add 376.1 proxy wrap */
|
|
fwd_pkt = iot_brm_ass_build_3761_proxy_detect_pkt(pkt, 2400);
|
|
} else {
|
|
/* add 698.45 proxy wrap */
|
|
fwd_pkt = iot_brm_ass_build_69845_proxy_detect_pkt(pkt, 2400);
|
|
}
|
|
|
|
if (fwd_pkt == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
preamble_fill = 0;
|
|
pkt = fwd_pkt;
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_69845_BY_3761:
|
|
case IOT_BRM_PROTO_TYPE_69845_BY_69845:
|
|
{
|
|
/* build 698.45 mr packet */
|
|
pkt = iot_brm_ass_build_69845_detect_pkt(node);
|
|
data = iot_pkt_push(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
os_mem_cpy(data, proto_69845_preamble, PROTO_69845_PREAMBLE_LEN);
|
|
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_69845_BY_3761) {
|
|
/* add 376.1 proxy wrap */
|
|
fwd_pkt = iot_brm_ass_build_3761_proxy_detect_pkt(pkt, 9600);
|
|
} else {
|
|
/* add 698.45 proxy wrap */
|
|
fwd_pkt = iot_brm_ass_build_69845_proxy_detect_pkt(pkt, 9600);
|
|
}
|
|
|
|
if (fwd_pkt == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
preamble_fill = 0;
|
|
pkt = fwd_pkt;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if (!pkt) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
if (preamble_fill) {
|
|
data = iot_pkt_push(pkt, pre_len);
|
|
os_mem_cpy(data, preamble, pre_len);
|
|
}
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_3761
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_69845_BY_3761) {
|
|
*to = IOT_BRM_ASS_NODE_CHK_TIMEOUT_RS485_FOR_3761
|
|
+ IOT_BRM_PROXY_TRANS_TIMEOUT * 1000;
|
|
} else if (node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_69845
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_69845_BY_69845) {
|
|
*to = IOT_BRM_ASS_NODE_CHK_TIMEOUT_RS485_FOR_69845
|
|
+ IOT_BRM_PROXY_TRANS_TIMEOUT * 1000;
|
|
} else {
|
|
*to = IOT_BRM_ASS_NODE_CHK_TIMEOUT_RS485;
|
|
}
|
|
iot_brm_printf("%s protocol id: %d, 485 port: %d\n", __FUNCTION__,
|
|
node->pid, ccb->trans_port);
|
|
iot_brm_rs485_config_buad_internal(ccb->buad_tab[node->pid][ccb->b_idx],
|
|
node->pid);
|
|
iot_brm_rs485_send(pkt);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t iot_brm_ass_node_check_issue_on_plc()
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_brm_ass_node_entry_t *node;
|
|
proto_69845_app_get_req_info_t req = {0};
|
|
server_addr_info_t server = {0};
|
|
uint8_t *preamble = NULL, *data;
|
|
uint8_t idx, ret = ERR_OK, allow_mr = 0;
|
|
uint32_t pre_len = 0;
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
uint8_t addr[IOT_MAC_ADDR_LEN];
|
|
node = iot_brm_ass_first_pend_node();
|
|
if (node) {
|
|
ccb->plc_cfg_cmd_cnt++;
|
|
iot_set_bcast_mac(addr);
|
|
iot_brm_send_config_cmd(addr, ccb->plc_band,
|
|
IOT_BRM_ASS_NODE_CHK_CONFIG_DUR, 1);
|
|
if (ccb->plc_cfg_cmd_cnt > 15) {
|
|
/* send the configuration command first, fix the band of the node
|
|
* not connected to the network, and start to read (check) the
|
|
* node.
|
|
*/
|
|
allow_mr = 1;
|
|
}
|
|
} else {
|
|
/* all nodes are check done */
|
|
ccb->plc_cfg_cmd_cnt = 0;
|
|
ret = ERR_NOT_EXIST;
|
|
goto out;
|
|
}
|
|
for (idx = 0; idx < IOT_BRM_SUPPORT_NODE_MAX && allow_mr; idx++) {
|
|
node = &ccb->node_ent[idx];
|
|
if (!iot_mac_addr_valid(node->addr)) {
|
|
/* reach valid address list boundary */
|
|
break;
|
|
}
|
|
if (node->state == IOT_BRM_ASS_NODE_CHK_STATE_OK
|
|
|| node->state == IOT_BRM_ASS_NODE_CHK_STATE_NOT_OK) {
|
|
/* node assembly check has ben completed, skip */
|
|
continue;
|
|
}
|
|
/* When first time to check one node, load the first protocol */
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_TRANSPARENT) {
|
|
node->pid = ccb->protocol_table[0];
|
|
iot_brm_ass_check_load_proto(node);
|
|
}
|
|
switch (node->pid) {
|
|
case IOT_BRM_PROTO_TYPE_645_1997:
|
|
{
|
|
preamble = (uint8_t *)proto_645_preamble;
|
|
pre_len = PROTO_645_PREAMBLE_LEN;
|
|
pkt = proto_645_build_mr_msg(PROTO_645_1997_ID,
|
|
node->addr, PROTO_645_1997_DI_R_ADDR);
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_645_2007:
|
|
{
|
|
preamble = (uint8_t *)proto_645_preamble;
|
|
pre_len = PROTO_645_PREAMBLE_LEN;
|
|
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID,
|
|
node->addr, PROTO_645_2007_DI_R_ADDR);
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_69845:
|
|
{
|
|
preamble = (uint8_t *)proto_69845_preamble;
|
|
pre_len = PROTO_69845_PREAMBLE_LEN;
|
|
req.type = PROTO_69845_APP_GET_NORMAL;
|
|
req.piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
|
|
req.piid.sn = 0;
|
|
req.oad.oi = PROTO_69845_APP_OI_ADDR;
|
|
req.oad.attribute_id = 2;
|
|
req.oad.attribute_char = 0;
|
|
req.oad.element_index = 0;
|
|
server.len = PROTO_69845_SA_LEN;
|
|
server.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server.addr, node->addr);
|
|
pkt = proto_69845_build_get_req_msg(&req, &server);
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
if (!pkt) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
data = iot_pkt_push(pkt, pre_len);
|
|
os_mem_cpy(data, preamble, pre_len);
|
|
ret = iot_brm_mr_buf_cmd_add(ccb->custom_id, node->addr, 0,
|
|
node->pid, pkt, IOT_BRM_ASS_NODE_CHK_TIMEOUT_PLC,
|
|
iot_brm_mr_cmd_prio_1, iot_brm_mr_type_ass_chk, 0);
|
|
if (ret) {
|
|
break;
|
|
}
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t iot_brm_ass_node_check_resp_handle(iot_pkt_t *pkt)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
proto_645_header_t *hdr_645;
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
uint8_t *ds, *data, *ser_addr;
|
|
uint8_t msg_addr[IOT_MAC_ADDR_LEN], proto_type;
|
|
uint32_t len, baud = 0, ret;
|
|
uint8_t accept = 0, sn;
|
|
uint8_t timeout, *addr;
|
|
iot_brm_ass_node_entry_t *node;
|
|
proto_3761_app_data_desc_t app = { 0 };
|
|
proto_3761_afn10f1_ul_t *ul;
|
|
iot_brm_terminal_cfg_t cfg;
|
|
uint16_t fn, pn, len_temp;
|
|
uint16_t terminal_dev_addr;
|
|
uint8_t terminal_area_code[PROTO_3761_AREA_CODE_LEN];
|
|
if (!ccb->is_plc_con) {
|
|
node = iot_brm_ass_first_pend_node();
|
|
timeout = (pkt == NULL);
|
|
} else {
|
|
addr = iot_pkt_data(pkt);
|
|
addr -= IOT_MAC_ADDR_LEN;
|
|
len = iot_pkt_data_len(pkt);
|
|
timeout = !len;
|
|
node = iot_brm_ass_find_node(addr);
|
|
}
|
|
if (!node || node->state != IOT_BRM_ASS_NODE_CHK_STATE_PEND) {
|
|
goto out;
|
|
}
|
|
if (timeout) {
|
|
iot_brm_printf("%s %02x%02x%02x%02x%02x%02x timeout...\n",
|
|
__FUNCTION__, node->addr[5], node->addr[4], node->addr[3],
|
|
node->addr[2], node->addr[1], node->addr[0]);
|
|
IOT_ASSERT(node->re_try);
|
|
node->re_try--;
|
|
if (!node->re_try) {
|
|
if (!ccb->is_plc_con) {
|
|
/* switch baud rate, when the terminal baud rate is not fixed */
|
|
if (!ccb->b_idx_lock)
|
|
ccb->b_idx++;
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_69845
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_69845_BY_69845) {
|
|
node->re_try = IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485_698_PROXY;
|
|
} else {
|
|
node->re_try = IOT_BRM_ASS_NODE_CHK_TRY_MAX_RS485;
|
|
}
|
|
if (ccb->b_idx_lock ||
|
|
ccb->b_idx >= IOT_BRM_SUPPORT_BAUD_MAX ||
|
|
!ccb->buad_tab[node->pid][ccb->b_idx]) {
|
|
/* if the terminal baud rate is not fixed, try all baud
|
|
* of the protocol; if fixed, to use current baud rate.
|
|
*/
|
|
if (!ccb->b_idx_lock)
|
|
ccb->b_idx = 0;
|
|
/* all baud rate checks are done, switch port or protocol */
|
|
if ((node->pid == IOT_BRM_PROTO_TYPE_69845_BY_3761
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_3761)
|
|
&& !ccb->trans_port_lock
|
|
&& ccb->trans_port == PROTO_PORT_RS485_2) {
|
|
ccb->trans_port = PROTO_PORT_RS485_1;
|
|
} else if ((node->pid == IOT_BRM_PROTO_TYPE_69845_BY_69845
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_69845)
|
|
&& !ccb->trans_port_lock
|
|
&& ccb->trans_port == PROTO_PORT_RS485_1) {
|
|
ccb->trans_port = PROTO_PORT_RS485_2;
|
|
} else if (iot_brm_ass_check_proto_switch_next(node) != 1) {
|
|
goto node_finish;
|
|
}
|
|
}
|
|
} else if (iot_brm_ass_check_proto_switch_next(node) != 1) {
|
|
goto node_finish;
|
|
}
|
|
}
|
|
goto out;
|
|
}
|
|
ds = iot_pkt_data(pkt);
|
|
len = iot_pkt_data_len(pkt);
|
|
switch (node->pid) {
|
|
case IOT_BRM_PROTO_TYPE_645_1997:
|
|
case IOT_BRM_PROTO_TYPE_645_2007:
|
|
{
|
|
hdr_645 = proto_645_format_check(ds, len, PROTO_645_DIR_SLAVE);
|
|
if (!hdr_645) {
|
|
goto out;
|
|
}
|
|
if (!iot_mac_addr_cmp(node->addr, hdr_645->addr)) {
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_69845:
|
|
{
|
|
hdr_698 = proto_69845_sanity_check(ds, (uint16_t)len);
|
|
if (!hdr_698) {
|
|
goto out;
|
|
}
|
|
ser_addr = proto_69845_get_ser_addr(hdr_698);
|
|
if (!iot_mac_addr_cmp(node->addr, ser_addr)) {
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_645_2007_BY_3761:
|
|
case IOT_BRM_PROTO_TYPE_69845_BY_3761:
|
|
{
|
|
ret = proto_3761_parse(ds, (uint16_t)len, &app);
|
|
if (ret || app.prm != 0 || app.dir == PROTO_3761_DIR_MASTER) {
|
|
goto out;
|
|
}
|
|
if (app.seq != sn_3761)
|
|
goto out;
|
|
data = app.data;
|
|
len_temp = app.len;
|
|
if (iot_brm_get_terminal_cfg(&cfg) == ERR_OK && !cfg.is_698) {
|
|
iot_uint32_to_bcd(cfg.terminal_addr.trans_3761.area_code,
|
|
PROTO_3761_AREA_CODE_LEN,
|
|
terminal_area_code);
|
|
terminal_dev_addr = cfg.terminal_addr.trans_3761.dev_addr;
|
|
} else {
|
|
iot_uint32_to_bcd(9999, PROTO_3761_AREA_CODE_LEN,
|
|
terminal_area_code);
|
|
terminal_dev_addr = PROTO_3761_BCAST_DEV_ADRR;
|
|
}
|
|
if (os_mem_cmp(app.addr_filed.area_code, terminal_area_code,
|
|
PROTO_3761_AREA_CODE_LEN) == 0
|
|
&& app.addr_filed.dev_addr == terminal_dev_addr) {
|
|
ccb->b_idx_lock = 1;
|
|
iot_brm_printf("%s lock interminal baud: %d\n", __FUNCTION__,
|
|
ccb->buad_tab[node->pid][ccb->b_idx]);
|
|
} else {
|
|
goto out;
|
|
}
|
|
switch (app.afn) {
|
|
case PROTO_3761_AFN_10:
|
|
{
|
|
ret = proto_3761_du_parse(&pn, &fn, &data, &len_temp);
|
|
if (ret) {
|
|
goto out;
|
|
}
|
|
switch (fn) {
|
|
case 0x01:
|
|
{
|
|
if (len_temp < sizeof(*ul)) {
|
|
goto out;
|
|
}
|
|
ul = (proto_3761_afn10f1_ul_t *)data;
|
|
len_temp -= sizeof(*ul);
|
|
data += sizeof(*ul);
|
|
if (len_temp < ul->len) {
|
|
goto out;
|
|
}
|
|
if (iot_brm_get_addr_from_message(data, len_temp, msg_addr,
|
|
&proto_type) != ERR_OK) {
|
|
goto out;
|
|
}
|
|
if (!iot_mac_addr_cmp(node->addr, msg_addr)) {
|
|
goto out;
|
|
}
|
|
ccb->trans_port_lock = 1;
|
|
iot_brm_printf("%s lock interminal port: %d\n", __FUNCTION__,
|
|
ccb->trans_port);
|
|
ret = iot_brm_get_terminal_cfg(&cfg);
|
|
if (ret || cfg.is_698) {
|
|
cfg.terminal_addr.trans_3761.dev_addr =
|
|
PROTO_3761_BCAST_DEV_ADRR;
|
|
cfg.terminal_addr.trans_3761.area_code = 9999;
|
|
}
|
|
cfg.is_698 = 0;
|
|
cfg.trans_port = ccb->trans_port;
|
|
iot_brm_set_terminal_cfg(&cfg);
|
|
break;
|
|
}
|
|
default:
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
goto out;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_PROTO_TYPE_645_2007_BY_69845:
|
|
case IOT_BRM_PROTO_TYPE_69845_BY_69845:
|
|
{
|
|
if (proto_69845_proxy_trans_resp_parse(&ds, (uint16_t*)&len, &sn)
|
|
!= ERR_OK) {
|
|
goto out;
|
|
}
|
|
if (sn != sn_698)
|
|
goto out;
|
|
ccb->b_idx_lock = 1;
|
|
iot_brm_printf("%s lock interminal baud: %d\n", __FUNCTION__,
|
|
ccb->buad_tab[node->pid][ccb->b_idx]);
|
|
if (iot_brm_get_addr_from_message(ds, (uint16_t)len, msg_addr,
|
|
&proto_type) != ERR_OK) {
|
|
goto out;
|
|
}
|
|
if (!iot_mac_addr_cmp(node->addr, msg_addr)) {
|
|
goto out;
|
|
}
|
|
ccb->trans_port_lock = 1;
|
|
iot_brm_printf("%s lock interminal port: %d\n", __FUNCTION__,
|
|
ccb->trans_port);
|
|
ret = iot_brm_get_terminal_cfg(&cfg);
|
|
if (ret || !cfg.is_698) {
|
|
os_mem_set(cfg.terminal_addr.trans_698_addr, 0xAA,
|
|
IOT_MAC_ADDR_LEN);
|
|
}
|
|
cfg.is_698 = 1;
|
|
cfg.trans_port = ccb->trans_port;
|
|
iot_brm_set_terminal_cfg(&cfg);
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
if (!ccb->is_plc_con) {
|
|
baud = ccb->buad_tab[node->pid][ccb->b_idx];
|
|
node->bid = iot_brm_baud_to_bid(baud);
|
|
}
|
|
accept = 1;
|
|
node_finish:
|
|
if (accept) {
|
|
node->state = IOT_BRM_ASS_NODE_CHK_STATE_OK;
|
|
iot_brm_printf("assembly ok: addr %02x%02x%02x%02x%02x%02x, pid %lu,"
|
|
" baud %lu\n", node->addr[5], node->addr[4], node->addr[3],
|
|
node->addr[2], node->addr[1], node->addr[0], node->pid, baud);
|
|
} else {
|
|
node->pid = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
node->state = IOT_BRM_ASS_NODE_CHK_STATE_NOT_OK;
|
|
iot_brm_printf("assembly fail: addr %02x%02x%02x%02x%02x%02x\n",
|
|
node->addr[5], node->addr[4], node->addr[3],
|
|
node->addr[2], node->addr[1], node->addr[0]);
|
|
}
|
|
out:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return accept;
|
|
}
|
|
|
|
void iot_brm_ass_check_bd_recv_handle(uint8_t *phase)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
uint8_t idx = ccb->phase - 1;
|
|
if (ccb->wire_chk_state != IOT_BRM_ASS_WIRE_CHK_STATE_BD_RCV)
|
|
return;
|
|
iot_brm_printf("%s in phase %lu", __FUNCTION__, phase ? (*phase) : 0);
|
|
if (phase != NULL) {
|
|
if (*phase != ccb->phase) {
|
|
/* if the signal is not received on the transmission phase line,
|
|
* ignore it to avoid crosstalk affecting the check result.
|
|
*/
|
|
return;
|
|
}
|
|
ccb->wire_chk_cnt = 0;
|
|
} else {
|
|
/* branch identification signal not received, there may be wiring
|
|
* errors.
|
|
*/
|
|
if (!ccb->wire_chk_st[idx])
|
|
ccb->wire_chk_st[idx] = PROTO_645_EXT_BRM_ASS_WIRE_ERR3;
|
|
}
|
|
if (iot_plc_hw_tsfm_is_3p()) {
|
|
switch (ccb->phase) {
|
|
case IOT_PLC_PHASE_A:
|
|
ccb->phase = IOT_PLC_PHASE_B;
|
|
break;
|
|
case IOT_PLC_PHASE_B:
|
|
ccb->phase = IOT_PLC_PHASE_C;
|
|
break;
|
|
case IOT_PLC_PHASE_C:
|
|
goto done;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_BD_SEND;
|
|
} else {
|
|
done:
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_DONE;
|
|
}
|
|
}
|
|
|
|
void iot_brm_ass_check_wiring(void)
|
|
{
|
|
uint8_t reason = 0;
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_meter_info_t *m;
|
|
iot_brm_meter_var_t *var;
|
|
uint8_t data[PROTO_645_VENDOR_BR_DATA_LEN];
|
|
uint8_t i, temp[IOT_BRM_PHASE_C] = { 0 };
|
|
hw_tsfm_send_cfg_t cfg = { 0 };
|
|
proto_hw_tsfm_hdr_t *topo_hdr;
|
|
uint32_t ret;
|
|
|
|
switch (ccb->wire_chk_state) {
|
|
case IOT_BRM_ASS_WIRE_CHK_STATE_DIRECT:
|
|
{
|
|
m = iot_brm_load_meter_info();
|
|
var = &m->var;
|
|
for (i = IOT_BRM_PHASE_A; i <= IOT_BRM_PHASE_C; i++) {
|
|
if (var->s[i] > 10) {
|
|
/* reverse power, two possibilities:
|
|
* 1. CT reverse connection
|
|
* 2. voltage sequence and current sequence do not correspond
|
|
*/
|
|
if (var->p[i] < 0) {
|
|
temp[i - 1] = PROTO_645_EXT_BRM_ASS_WIRE_ERR1;
|
|
}
|
|
} else if (var->i[i - 1] >= 100 && var->v[ i - 1] < 700) {
|
|
/* possibility:
|
|
* when single-phase connection is used, CT is not connected
|
|
* to the first current terminal
|
|
*/
|
|
temp[i - 1] = PROTO_645_EXT_BRM_ASS_WIRE_ERR2;
|
|
}
|
|
}
|
|
if (!temp[1]) {
|
|
if (var->v[0] > 700 && var->v[2] > 700 && var->v[1] < 300) {
|
|
temp[1] = PROTO_645_EXT_BRM_ASS_WIRE_ERR2;
|
|
}
|
|
}
|
|
|
|
if (temp[0] != ccb->wire_chk_st[0]
|
|
|| temp[1] != ccb->wire_chk_st[1]
|
|
|| temp[2] != ccb->wire_chk_st[2]) {
|
|
ccb->wire_chk_st[0] = temp[0];
|
|
ccb->wire_chk_st[1] = temp[1];
|
|
ccb->wire_chk_st[2] = temp[2];
|
|
ccb->wire_chk_cnt = 0;
|
|
} else if (ccb->wire_chk_cnt++ > 10) {
|
|
/* don't need to check branch identification */
|
|
if (iot_brm_is_brk()) {
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_DONE;
|
|
} else {
|
|
/* next: wiring check by branch identification */
|
|
ccb->wire_chk_cnt = 0;
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_BD_SEND;
|
|
ccb->phase = IOT_PLC_PHASE_A;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_WIRE_CHK_STATE_BD_SEND:
|
|
{
|
|
cfg.para.zc.ahead = 700;
|
|
cfg.para.zc.dur_output = IOT_PLC_HW_TSFM_OUTPUT_MAX_TIME;
|
|
cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
|
|
cfg.phase = ccb->phase;
|
|
topo_hdr = (proto_hw_tsfm_hdr_t*)data;
|
|
topo_hdr->data_id = PROTO_HW_TSFM_ID_TOPO_TEST;
|
|
topo_hdr->data_len = 0;
|
|
ret = proto_645_vendor_br_launch(data, sizeof(*topo_hdr), &cfg);
|
|
if (ret == ERR_OK) {
|
|
iot_brm_printf("%s send branch test ok\n", __FUNCTION__);
|
|
ccb->wire_chk_cnt = 0;
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_BD_RCV;
|
|
} else if (++ccb->wire_chk_cnt >= IOT_BRM_ASS_WIRE_CHK_BD_SEND_TIMEOUT) {
|
|
/* Send timeout, end check */
|
|
ccb->wire_chk_cnt = 0;
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_DONE;
|
|
reason = 1;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_WIRE_CHK_STATE_BD_RCV:
|
|
{
|
|
if (++ccb->wire_chk_cnt >= IOT_BRM_ASS_WIRE_CHK_BD_RCV_TIMEOUT) {
|
|
/* branch identification signal not received */
|
|
ccb->wire_chk_cnt = 0;
|
|
reason = 2;
|
|
iot_brm_ass_check_bd_recv_handle(NULL);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
if (reason) {
|
|
iot_brm_printf("%s fail reason %lu\n", __FUNCTION__, reason);
|
|
}
|
|
}
|
|
|
|
static void iot_brm_ass_check_result_save()
|
|
{
|
|
iot_brm_nv_ass_chk_info_t *ass_info;
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_ass_node_entry_t *node;
|
|
iot_time_tm_t tm;
|
|
uint32_t cur_ts;
|
|
uint8_t week, i;
|
|
uint8_t creator, port;
|
|
uint8_t bm_creator;
|
|
ass_info = (iot_brm_nv_ass_chk_info_t *)
|
|
iot_brm_nv_get_section(iot_brm_nv_id_ass_chk_info);
|
|
os_mem_set(ass_info, 0x0, sizeof(*ass_info));
|
|
|
|
iot_brm_rtc_get_time(&tm, &week);
|
|
ass_info->ts = iot_brm_rtctime_to_time(&tm);
|
|
cur_ts = (uint32_t)(os_boot_time64() / 1000);
|
|
ass_info->time_cons = (uint16_t)(cur_ts - ccb->start_ts);
|
|
ass_info->phase1_wire_st = ccb->wire_chk_st[0];
|
|
ass_info->phase2_wire_st = ccb->wire_chk_st[1];
|
|
ass_info->phase3_wire_st = ccb->wire_chk_st[2];
|
|
iot_brm_printf("%s cons = %lus, wire[%lu %lu %lu]\n",
|
|
__FUNCTION__, ass_info->time_cons,
|
|
ass_info->phase1_wire_st, ass_info->phase2_wire_st,
|
|
ass_info->phase3_wire_st);
|
|
bm_creator = (1 << IOT_BRM_OPERATOR_EXT) | (1 << IOT_BRM_OPERATOR_INTERNAL);
|
|
iot_brm_node_rm_by_creator(bm_creator);
|
|
for (i = 0; i < IOT_BRM_SUPPORT_NODE_MAX; i++) {
|
|
node = &ccb->node_ent[i];
|
|
if (!iot_mac_addr_valid(node->addr)) {
|
|
break;
|
|
}
|
|
iot_mac_addr_cpy(ass_info->ent[i].addr, node->addr);
|
|
ass_info->ent[i].pid = node->pid;
|
|
if (node->state == IOT_BRM_ASS_NODE_CHK_STATE_OK) {
|
|
/* if the node assembly check is ok, add it to the node list */
|
|
ass_info->ent[i].ass_ok = 1;
|
|
if (node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_3761
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_645_2007_BY_69845
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_69845_BY_3761
|
|
|| node->pid == IOT_BRM_PROTO_TYPE_69845_BY_69845)
|
|
creator = IOT_BRM_OPERATOR_EXT;
|
|
else
|
|
creator = IOT_BRM_OPERATOR_INTERNAL;
|
|
if (!ccb->is_plc_con) {
|
|
port = IOT_BRM_PORT_RS485;
|
|
} else if (ccb->plc_mode ==
|
|
PROTO_645_EXT_BRM_ASS_CHK_PLC_MODE_SAME) {
|
|
port = IOT_BRM_PORT_PLC_WEAK;
|
|
} else {
|
|
port = IOT_BRM_PORT_PLC;
|
|
}
|
|
iot_brm_node_add(node->addr, port, node->pid,
|
|
iot_brm_bid_to_baud(node->bid), NULL, NULL, NULL, creator);
|
|
} else if (node->state == IOT_BRM_ASS_NODE_CHK_STATE_NOT_OK) {
|
|
ass_info->ent[i].ass_ok = 0;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
ass_info->ent[i].bid = node->bid;
|
|
ass_info->ent[i].is_plc_chk = ccb->is_plc_con;
|
|
iot_brm_printf("|--ass addr %02x%02x%02x%02x%02x%02x %s, pid %lu, "
|
|
"baud %lu\n", node->addr[5], node->addr[4], node->addr[3],
|
|
node->addr[2], node->addr[1], node->addr[0],
|
|
ass_info->ent[i].ass_ok ? "yes" : "no",
|
|
node->pid, iot_brm_bid_to_baud((uint8_t)node->bid));
|
|
}
|
|
iot_brm_nv_update_section(iot_brm_nv_id_ass_chk_info);
|
|
iot_brm_sync_node_list_to_sg_app();
|
|
}
|
|
|
|
static uint8_t iot_brm_ass_other_check_is_done(void)
|
|
{
|
|
if (g_ass_ccb.wire_chk_state == IOT_BRM_ASS_WIRE_CHK_STATE_DONE) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void iot_brm_ass_check_handle(iot_brm_ass_event_t event,
|
|
void *data)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
uint32_t ret, dur = 50, accept;
|
|
switch (ccb->state) {
|
|
case IOT_BRM_ASS_CHK_STATE_RECV_WAIT:
|
|
{
|
|
switch (event) {
|
|
case iot_brm_ass_event_data:
|
|
{
|
|
if (data)
|
|
iot_pkt_free((iot_pkt_t *)data);
|
|
goto out;
|
|
}
|
|
case iot_brm_ass_event_timer:
|
|
{
|
|
iot_brm_ass_check_proto_table_init();
|
|
/* start assembly check */
|
|
if (!ccb->is_plc_con)
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_NODE_READY;
|
|
else {
|
|
/* make the local device work in the fixed band */
|
|
iot_brm_set_fb(ccb->plc_band);
|
|
ccb->plc_cfg_cmd_cnt = 0;
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_NODE_PLC;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_READY:
|
|
{
|
|
switch (event) {
|
|
case iot_brm_ass_event_data:
|
|
{
|
|
if (data)
|
|
iot_pkt_free((iot_pkt_t *)data);
|
|
goto out;
|
|
}
|
|
case iot_brm_ass_event_timer:
|
|
{
|
|
ret = iot_brm_ass_node_check_issue(&dur);
|
|
if (ret == ERR_OK) {
|
|
/* command issued success, set timeout, wait for command
|
|
* response.
|
|
*/
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_NODE_WAIT;
|
|
} else if (ret == ERR_NOT_EXIST) {
|
|
/* the node assembly check is done, and the results
|
|
* switch to other item check.
|
|
*/
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_WAIT_OTHER;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_WAIT:
|
|
{
|
|
switch (event) {
|
|
case iot_brm_ass_event_data:
|
|
{
|
|
accept = iot_brm_ass_node_check_resp_handle(
|
|
(iot_pkt_t *)data);
|
|
if (!accept) {
|
|
goto out;
|
|
}
|
|
os_stop_timer(ccb->chk_timer);
|
|
iot_brm_clean_msg(IOT_BRM_MSG_TYPE_TIMER,
|
|
IOT_BRM_MSG_ID_TIMER_ASS_CHK);
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_NODE_READY;
|
|
break;
|
|
}
|
|
case iot_brm_ass_event_timer:
|
|
{
|
|
iot_brm_ass_node_check_resp_handle(NULL);
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_NODE_READY;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_PLC:
|
|
{
|
|
switch (event) {
|
|
case iot_brm_ass_event_data:
|
|
{
|
|
iot_brm_ass_node_check_resp_handle((iot_pkt_t *)data);
|
|
goto out;
|
|
}
|
|
case iot_brm_ass_event_timer:
|
|
{
|
|
ret = iot_brm_ass_node_check_issue_on_plc();
|
|
if (ret == ERR_NOT_EXIST) {
|
|
/* the plc node assembly check is done, and the results
|
|
* switch to other item check.
|
|
*/
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_WAIT_OTHER;
|
|
}
|
|
dur = 1000;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_WAIT_OTHER:
|
|
{
|
|
switch (event) {
|
|
case iot_brm_ass_event_data:
|
|
{
|
|
if (data)
|
|
iot_pkt_free((iot_pkt_t *)data);
|
|
goto out;
|
|
}
|
|
case iot_brm_ass_event_timer:
|
|
{
|
|
if (iot_brm_ass_other_check_is_done()) {
|
|
/* save assembly check results */
|
|
iot_brm_ass_check_result_save();
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_DONE;
|
|
dur = 10000;
|
|
break;
|
|
}
|
|
dur = 1000;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_DONE:
|
|
{
|
|
switch (event) {
|
|
case iot_brm_ass_event_data:
|
|
{
|
|
iot_pkt_free((iot_pkt_t *)data);
|
|
goto out;
|
|
}
|
|
case iot_brm_ass_event_timer:
|
|
{
|
|
iot_system_restart(IOT_SYS_RST_REASON_CT2_REQ);
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
goto out;
|
|
}
|
|
os_start_timer(ccb->chk_timer, dur);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static uint8_t iot_brm_ass_node_add(uint8_t *addr)
|
|
{
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
iot_brm_ass_node_entry_t *node = NULL;
|
|
uint8_t i;
|
|
if (!proto_645_pm_addr_valid(addr))
|
|
return ERR_INVAL;
|
|
|
|
for (i = 0; i < IOT_BRM_SUPPORT_NODE_MAX; i++) {
|
|
node = ccb->node_ent + i;
|
|
if (!iot_mac_addr_valid(node->addr)) {
|
|
break;
|
|
} else if (iot_mac_addr_cmp(node->addr, addr) == 1) {
|
|
return ERR_EXIST;
|
|
}
|
|
}
|
|
if (i == IOT_BRM_SUPPORT_NODE_MAX)
|
|
return ERR_NOMEM;
|
|
iot_mac_addr_cpy(node->addr, addr);
|
|
node->pid = IOT_BRM_PROTO_TYPE_TRANSPARENT;
|
|
node->bid = 0;
|
|
node->state = IOT_BRM_ASS_NODE_CHK_STATE_PEND;
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint8_t iot_brm_ass_proto_band_to_plc_lib_band(uint8_t band)
|
|
{
|
|
uint8_t plc_band;
|
|
switch (band) {
|
|
case PROTO_645_EXT_BRM_ASS_CHK_PLC_BAND_1:
|
|
plc_band = PLC_LIB_FREQ_BAND_1;
|
|
break;
|
|
case PROTO_645_EXT_BRM_ASS_CHK_PLC_BAND_8:
|
|
plc_band = PLC_LIB_FREQ_BAND_8;
|
|
break;
|
|
case PROTO_645_EXT_BRM_ASS_CHK_PLC_BAND_2:
|
|
default:
|
|
plc_band = PLC_LIB_FREQ_BAND_2;
|
|
break;
|
|
}
|
|
return plc_band;
|
|
}
|
|
|
|
uint8_t iot_brm_ass_handle_check_req(uint8_t *ds,
|
|
uint8_t len)
|
|
{
|
|
proto_645_ext_brm_ass_chk_req_t *req;
|
|
iot_time_tm_t tm;
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
uint8_t i, reason = 0;
|
|
iot_brm_terminal_cfg_t cfg;
|
|
if (len < sizeof(*req)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
req = (proto_645_ext_brm_ass_chk_req_t *)ds;
|
|
len -= sizeof(*req);
|
|
if (len < req->cnt * sizeof(req->addr[0])) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
if (req->check_en_for_3761
|
|
&& iot_brm_get_terminal_cfg(&cfg) != ERR_OK) {
|
|
reason = 4;
|
|
goto out;
|
|
}
|
|
switch (ccb->state) {
|
|
case IOT_BRM_ASS_CHK_STATE_IDLE:
|
|
{
|
|
ccb->wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_DIRECT;
|
|
ccb->trans_port_lock = 0;
|
|
ccb->b_idx_lock = 0;
|
|
ccb->is_plc_con = req->is_plc_con;
|
|
ccb->check_en_for_3761 = req->check_en_for_3761;
|
|
ccb->plc_mode = req->plc_mode;
|
|
ccb->plc_band = iot_brm_ass_proto_band_to_plc_lib_band(req->band);
|
|
tm.tm_sec = iot_bcd_to_byte(req->tm.second);
|
|
tm.tm_min = iot_bcd_to_byte(req->tm.minute);
|
|
tm.tm_hour = iot_bcd_to_byte(req->tm.hour);
|
|
tm.tm_mday = iot_bcd_to_byte(req->tm.day);
|
|
tm.tm_mon = iot_bcd_to_byte(req->tm.month);
|
|
tm.tm_year = iot_bcd_to_byte(req->tm.year) + 2000;
|
|
iot_brm_rtc_set_time(&tm);
|
|
iot_brm_brk_correct_time((proto_645_corr_time_t*)&(req->tm));
|
|
iot_brm_set_gps_info((iot_brm_location_unit_t *)&req->latitude,
|
|
(iot_brm_location_unit_t *)&req->longitude);
|
|
iot_brm_printf("%s time %lu-%lu-%lu %lu:%lu:%lu, location [%c%1d%1d%1d."
|
|
"%1d%1d.%1d%1d%1d%1d, %c%1d%1d%1d.%1d%1d.%1d%1d%1d%1d], conn %lu, "
|
|
"ratio[%lu %lu]\n", __FUNCTION__, tm.tm_year, tm.tm_mon, tm.tm_mday,
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
|
req->latitude.symbol_3 ? 'S':'N', req->latitude.degree_2,
|
|
req->latitude.degree_1, req->latitude.degree_0,
|
|
req->latitude.min_1, req->latitude.min_0, req->latitude.sec_3,
|
|
req->latitude.sec_2, req->latitude.sec_1, req->latitude.sec_0,
|
|
req->longitude.symbol_3 ? 'W':'E', req->longitude.degree_2,
|
|
req->longitude.degree_1, req->longitude.degree_0,
|
|
req->longitude.min_1, req->longitude.min_0, req->longitude.sec_3,
|
|
req->longitude.sec_2, req->longitude.sec_1, req->longitude.sec_0,
|
|
req->is_plc_con, req->v_ratio, req->i_ratio);
|
|
ccb->start_ts = (uint32_t)(os_boot_time64() / 1000);
|
|
iot_brm_set_meter_ratio((uint32_t)req->v_ratio,
|
|
(uint32_t)req->i_ratio);
|
|
if ((ccb->is_plc_con && iot_brm_port_is_exist(IOT_BRM_PORT_PLC_WEAK))
|
|
|| (!ccb->is_plc_con && iot_brm_port_is_exist(IOT_BRM_PORT_RS485))) {
|
|
for (i = 0; i < req->cnt; i++) {
|
|
iot_brm_ass_node_add(req->addr[i]);
|
|
}
|
|
iot_brm_rs485_set_check_state();
|
|
if (ccb->is_plc_con) {
|
|
iot_brm_set_whitelist_enable();
|
|
}
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_RECV_WAIT;
|
|
} else {
|
|
ccb->state = IOT_BRM_ASS_CHK_STATE_WAIT_OTHER;
|
|
}
|
|
os_start_timer(ccb->chk_timer, IOT_BRM_ASS_REV_ASS_INFO_TIMEOUT);
|
|
iot_plc_led_request(IOT_PLC_LED_CHECK);
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_RECV_WAIT:
|
|
{
|
|
for (i = 0; i < req->cnt; i++) {
|
|
iot_brm_ass_node_add(req->addr[i]);
|
|
}
|
|
/* restart timer waiting for more assembly info */
|
|
os_start_timer(ccb->chk_timer, IOT_BRM_ASS_REV_ASS_INFO_TIMEOUT);
|
|
iot_brm_clean_msg(IOT_BRM_MSG_TYPE_TIMER, IOT_BRM_MSG_ID_TIMER_ASS_CHK);
|
|
break;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_READY:
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_WAIT:
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_PLC:
|
|
case IOT_BRM_ASS_CHK_STATE_WAIT_OTHER:
|
|
case IOT_BRM_ASS_CHK_STATE_DONE:
|
|
default:
|
|
{
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
}
|
|
out:
|
|
if (reason) {
|
|
iot_printf("%s fail, reason %lu\n", __FUNCTION__, reason);
|
|
return ERR_FAIL;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t iot_brm_ass_check_fill_result(uint8_t *ds, uint8_t len,
|
|
uint8_t start_index, uint8_t query_cnt)
|
|
{
|
|
proto_645_ext_brm_ass_chk_rsp_t *rsp;
|
|
iot_time_tm_t tm;
|
|
iot_brm_ass_chk_ctrl_t *ccb = &g_ass_ccb;
|
|
uint8_t i, cnt = 0, week;
|
|
iot_brm_nv_ass_chk_info_t *ass_info;
|
|
rsp = (proto_645_ext_brm_ass_chk_rsp_t *)ds;
|
|
iot_brm_meter_info_t *m = iot_brm_load_meter_info();
|
|
os_mem_set(rsp, 0x0, sizeof(*rsp));
|
|
iot_brm_get_gps_info((iot_brm_location_unit_t*)&rsp->latitude,
|
|
(iot_brm_location_unit_t*)&rsp->longitude);
|
|
iot_brm_rtc_get_time(&tm, &week);
|
|
proto_645_rtctime_to_YYMMDDhhmmss(&tm, (uint8_t*)&rsp->tm);
|
|
len -= sizeof(*rsp);
|
|
switch (ccb->state) {
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_READY:
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_WAIT:
|
|
case IOT_BRM_ASS_CHK_STATE_WAIT_OTHER:
|
|
case IOT_BRM_ASS_CHK_STATE_NODE_PLC:
|
|
case IOT_BRM_ASS_CHK_STATE_RECV_WAIT:
|
|
{
|
|
/* checking in progress */
|
|
rsp->state = 1;
|
|
rsp->time_cons = (uint16_t)(((uint32_t)(os_boot_time64() / 1000)) -
|
|
ccb->start_ts);
|
|
goto out;
|
|
}
|
|
case IOT_BRM_ASS_CHK_STATE_IDLE:
|
|
case IOT_BRM_ASS_CHK_STATE_DONE:
|
|
{
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
ass_info = (iot_brm_nv_ass_chk_info_t *)
|
|
iot_brm_nv_get_section(iot_brm_nv_id_ass_chk_info);
|
|
if (ass_info->ts == 0
|
|
&& ass_info->time_cons == 0) {
|
|
goto out;
|
|
}
|
|
rsp->phase1_wire_st = ass_info->phase1_wire_st;
|
|
rsp->phase2_wire_st = ass_info->phase2_wire_st;
|
|
rsp->phase3_wire_st = ass_info->phase3_wire_st;
|
|
rsp->state = 2;
|
|
rsp->time_cons = ass_info->time_cons;
|
|
for (i = 0; i < IOT_BRM_SUPPORT_NODE_MAX; i++) {
|
|
if (!iot_mac_addr_valid(ass_info->ent[i].addr)) {
|
|
break;
|
|
}
|
|
rsp->total_cnt++;
|
|
if (i < start_index) {
|
|
continue;
|
|
}
|
|
if (len < sizeof(rsp->result[0]) || cnt >= query_cnt) {
|
|
rsp->more = 1;
|
|
continue;
|
|
}
|
|
len -= sizeof(rsp->result[0]);
|
|
iot_mac_addr_cpy(rsp->result[cnt].addr,
|
|
ass_info->ent[i].addr);
|
|
rsp->result[cnt].result = ass_info->ent[i].ass_ok;
|
|
if (ass_info->ent[i].pid == IOT_BRM_PROTO_TYPE_645_2007_BY_3761
|
|
|| ass_info->ent[i].pid == IOT_BRM_PROTO_TYPE_645_2007_BY_69845)
|
|
rsp->result[cnt].pid = IOT_BRM_PROTO_TYPE_645_2007;
|
|
else if (ass_info->ent[i].pid == IOT_BRM_PROTO_TYPE_69845_BY_3761
|
|
|| ass_info->ent[i].pid == IOT_BRM_PROTO_TYPE_69845_BY_69845)
|
|
rsp->result[cnt].pid = IOT_BRM_PROTO_TYPE_69845;
|
|
else
|
|
rsp->result[cnt].pid = ass_info->ent[i].pid ;
|
|
rsp->result[cnt].bid = ass_info->ent[i].bid;
|
|
rsp->result[cnt].rsvd = ass_info->ent[i].is_plc_chk;
|
|
cnt++;
|
|
}
|
|
out:
|
|
rsp->cnt = cnt;
|
|
rsp->i_ratio = (uint8_t)m->i_ratio;
|
|
rsp->v_ratio = (uint8_t)m->v_ratio;
|
|
return sizeof(*rsp) + cnt * sizeof(rsp->result[0]);
|
|
}
|
|
|
|
static void iot_brm_ass_check_timer_func(timer_id_t timer_id,
|
|
void *arg)
|
|
{
|
|
(void)timer_id;
|
|
iot_brm_post_msg(IOT_BRM_MSG_TYPE_TIMER,
|
|
IOT_BRM_MSG_ID_TIMER_ASS_CHK,
|
|
IOT_BRM_MSG_QUEUE_LP, arg, 0);
|
|
}
|
|
|
|
static void iot_brm_ass_plc_mr_recv(void *arg, uint16_t ext_sn,
|
|
uint8_t *addr, iot_pkt_t *pkt, uint16_t rsp_bm, iot_brm_mr_type_t type)
|
|
{
|
|
(void)arg;
|
|
(void)ext_sn;
|
|
(void)rsp_bm;
|
|
(void)type;
|
|
uint8_t *_addr;
|
|
if (!pkt) {
|
|
pkt = iot_pkt_alloc(IOT_MAC_ADDR_LEN, IOT_BRM_MID);
|
|
if (pkt == NULL) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
iot_pkt_reserve(pkt, IOT_MAC_ADDR_LEN);
|
|
}
|
|
if (iot_pkt_block_len(pkt, IOT_PKT_BLOCK_HEAD) <
|
|
IOT_MAC_ADDR_LEN) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
_addr = iot_pkt_data(pkt);
|
|
_addr -= IOT_MAC_ADDR_LEN;
|
|
iot_mac_addr_cpy(_addr, addr);
|
|
iot_brm_data_print("iot_brm_ass_plc_mr_recv addr", _addr, IOT_MAC_ADDR_LEN);
|
|
iot_brm_data_print("iot_brm_ass_plc_mr_recv data", iot_pkt_data(pkt),
|
|
iot_pkt_data_len(pkt));
|
|
iot_brm_ass_check_handle(iot_brm_ass_event_data, pkt);
|
|
}
|
|
|
|
void iot_brm_ass_init(void)
|
|
{
|
|
g_ass_ccb.chk_timer= os_create_timer(IOT_BRM_MID,
|
|
false, iot_brm_ass_check_timer_func, NULL);
|
|
if (g_ass_ccb.chk_timer == 0) {
|
|
goto out;
|
|
}
|
|
g_ass_ccb.custom_id = iot_brm_mr_buf_customer_register(
|
|
iot_brm_ass_plc_mr_recv, NULL);
|
|
if (g_ass_ccb.custom_id == IOT_BRM_MR_CUSTOMER_INVALID) {
|
|
goto err_1;
|
|
}
|
|
|
|
g_ass_ccb.state = IOT_BRM_ASS_CHK_STATE_IDLE;
|
|
g_ass_ccb.wire_chk_cnt = 0;
|
|
g_ass_ccb.wire_chk_state = IOT_BRM_ASS_WIRE_CHK_STATE_IDLE;
|
|
goto out;
|
|
|
|
err_1:
|
|
os_delete_timer(g_ass_ccb.chk_timer);
|
|
g_ass_ccb.chk_timer =0;
|
|
out:
|
|
return;
|
|
}
|
|
|
|
#endif /* IOT_BRM_ENABLE */
|