858 lines
31 KiB
C
858 lines
31 KiB
C
|
|
/*
|
||
|
|
* Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved.
|
||
|
|
* Description: MRS CCO Transfomer Identify handle.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "mrs_cco_tf.h"
|
||
|
|
#include "mrs_common_tools.h"
|
||
|
|
#include "mrs_cco_srv.h"
|
||
|
|
#include "mrs_cco_queue.h"
|
||
|
|
#include "mrs_proto_1376_2.h"
|
||
|
|
|
||
|
|
#if defined(PRODUCT_CFG_PRODUCT_TYPE_CCO)
|
||
|
|
|
||
|
|
#define MRS_TF_SEARCH_METER_REPORT_NUM 8
|
||
|
|
#define MRS_TF_METER_NODE_SIZE 12
|
||
|
|
|
||
|
|
#define MRS_TF_PROCESS_FINISHED 2
|
||
|
|
#define MRS_TF_REPORT_CHECK_CNT 5 /* Number of cycles that meet the reporting conditions but are not reported */
|
||
|
|
|
||
|
|
/* STA's identify result */
|
||
|
|
typedef struct {
|
||
|
|
td_u8 addr[METER_ADDR_LEN]; /* Address to be reported to the concentrator. If the address is a meter, the address
|
||
|
|
is a meter address. If the address is a repeater, the MAC address of the repeater is
|
||
|
|
directly reported. */
|
||
|
|
td_u8 mac[EXT_PLC_MAC_ADDR_LEN];
|
||
|
|
|
||
|
|
td_u16 tei : 12;
|
||
|
|
td_u16 period_num : 4; /* Number of periods when the node meets the reporting condition. If the value is greater
|
||
|
|
than or equal to 5, the node needs to report the number of cycles immediately. */
|
||
|
|
td_u8 protocol : 4;
|
||
|
|
td_u8 type : 4;
|
||
|
|
td_u8 pad;
|
||
|
|
|
||
|
|
td_bool is_ack; /* is receive ack */
|
||
|
|
td_u8 result; /* Transformer district identification result */
|
||
|
|
td_u8 query_cnt;
|
||
|
|
td_bool is_report; /* Whether it has been reported to the concentrator */
|
||
|
|
} mrs_cco_tf_sta_result;
|
||
|
|
|
||
|
|
/* CCO transformer district identification context */
|
||
|
|
typedef struct {
|
||
|
|
td_u8 status; /* identify state */
|
||
|
|
td_bool last_white_switch; /* Indicates whether to enable the whitelist function before the identification. */
|
||
|
|
td_u16 plc_seq; /* PLC packet sequence number */
|
||
|
|
|
||
|
|
td_u32 begin_time; /* unit:s */
|
||
|
|
td_u32 identify_duration; /* unit:s */
|
||
|
|
td_u32 report_duration; /* Identification completion, reporting time£¬unit:s */
|
||
|
|
|
||
|
|
td_u16 sta_num;
|
||
|
|
td_u16 query_idx;
|
||
|
|
|
||
|
|
td_u16 report_idx; /* Indicates the reported STA index. */
|
||
|
|
td_u16 afn06_f4_length; /* Indicates the reported 06F4 frame length. */
|
||
|
|
|
||
|
|
td_u16 p1376_seq; /* Indicates the sequence number of the packet sent to the collector. */
|
||
|
|
td_u8 afn06_f4_buf[97]; /* 97 bytes = (1+ MRS_TF_SEARCH_METER_REPORT_NUM x MRS_TF_METER_NODE_SIZE) */
|
||
|
|
td_bool is_show_dfx_log;
|
||
|
|
|
||
|
|
td_s8 query_pend_cnt;
|
||
|
|
td_u8 pad[3]; /* reserved 3B */
|
||
|
|
|
||
|
|
mrs_cco_tf_sta_result sta_results[0];
|
||
|
|
} mrs_cco_tf_ctx;
|
||
|
|
|
||
|
|
td_void mrs_cco_clear_sta_tf_result(td_void);
|
||
|
|
td_void mrs_cco_delete_invalid_sta_record(ext_mdm_nm_topo_node_info *topo_infos);
|
||
|
|
td_void mrs_cco_realign_sta_record(td_void);
|
||
|
|
td_void mrs_cco_add_new_sta_record(ext_mdm_nm_topo_node_info *topo_infos);
|
||
|
|
td_u32 mrs_cco_send_tf_query_cmd(td_u8 sta_mac[METER_ADDR_LEN]);
|
||
|
|
td_bool mrs_cco_tf_is_notify_complete(td_void);
|
||
|
|
td_void mrs_cco_tf_result_report(td_pvoid param);
|
||
|
|
td_void mrs_cco_tf_report_06_f4(td_void);
|
||
|
|
td_void mrs_cco_tf_report_06_f3(td_u8 status);
|
||
|
|
td_u16 mrs_cco_not_report_num(EXT_OUT td_bool *need_report);
|
||
|
|
|
||
|
|
mrs_cco_tf_ctx *g_mrs_cco_tf_ctx_hdl = TD_NULL;
|
||
|
|
mrs_cco_tf_inf g_mrs_tf_conf;
|
||
|
|
|
||
|
|
mrs_cco_tf_ctx *mrs_cco_get_tf_ctx(td_void)
|
||
|
|
{
|
||
|
|
return g_mrs_cco_tf_ctx_hdl;
|
||
|
|
}
|
||
|
|
|
||
|
|
mrs_cco_tf_inf *mrs_cco_get_tf_conf(td_void)
|
||
|
|
{
|
||
|
|
return &g_mrs_tf_conf;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_cco_tf_refresh_nv_para(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
mrs_cco_tf_inf nv_data;
|
||
|
|
td_u32 ret1;
|
||
|
|
td_u32 ret2;
|
||
|
|
|
||
|
|
if (tf_conf == TD_NULL) {
|
||
|
|
return EXT_ERR_NO_INITILIZATION;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret1 = uapi_nv_read(ID_NV_APP_MRS_CCO_TF, (td_pvoid)&nv_data, sizeof(nv_data));
|
||
|
|
ret2 = (td_u32)memcpy_s(tf_conf, sizeof(mrs_cco_tf_inf), &nv_data, sizeof(mrs_cco_tf_inf));
|
||
|
|
if ((ret1 != EXT_ERR_SUCCESS) || (ret2 != EXT_ERR_SUCCESS)) {
|
||
|
|
tf_conf->identify_duration = IDENTIFY_DURATION_DEFAULT;
|
||
|
|
tf_conf->identify_duration_rate = IDENTIFY_DURATION_RATE;
|
||
|
|
tf_conf->report_duration = REPORT_DURATION_DEFAULT;
|
||
|
|
tf_conf->start_cmd_interval = START_CMD_SEND_INTERVAL;
|
||
|
|
tf_conf->stop_cmd_interval = SEND_STOP_CMD_INTERVAL;
|
||
|
|
tf_conf->query_sta_interval = QUERY_STA_INTERVAL;
|
||
|
|
tf_conf->refrash_topo_interval = REFRESH_STA_LIST_INTERVAL;
|
||
|
|
tf_conf->query_sta_timeout = QUERY_STA_TIMEOUT;
|
||
|
|
tf_conf->query_max_cnt = QUERY_MAX_CNT;
|
||
|
|
tf_conf->delay_white_list_duration = DELAY_WHITE_LIST_DEFAULT;
|
||
|
|
uapi_nv_write(ID_NV_APP_MRS_CCO_TF, (td_pvoid)tf_conf, sizeof(mrs_cco_tf_inf));
|
||
|
|
}
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_dfx_report_message(EXT_IN td_u16 id, EXT_IN td_pvoid packet, EXT_IN td_u16 packet_size)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
if (tf_ctx != TD_NULL) {
|
||
|
|
if (tf_ctx->is_show_dfx_log == TD_FALSE) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ext_diag_layer_msg layer_msg;
|
||
|
|
layer_msg.id = id;
|
||
|
|
layer_msg.src_mod_id = EXT_MOD_ID_APP_COMMON;
|
||
|
|
layer_msg.dest_mod_id = EXT_MOD_ID_APP_COMMON;
|
||
|
|
layer_msg.data = packet;
|
||
|
|
layer_msg.data_size = packet_size;
|
||
|
|
(td_void) diag_report_sys_msg(layer_msg, EXT_MSG_SYS_L3);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_reset_all_timer(td_void)
|
||
|
|
{
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_SEND_START_CMD);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_SEND_STOP_CMD);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_REFRESH_STA_LIST);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_IDENTIFY_PROC);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_REPORT_PROC);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_QUERY_INTERVAL);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_COMPLETE);
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_QUERY_TIMEOUT);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Starts the transformer district identification. It is invoked when the concentrator AFN11-F5 is received or enabled
|
||
|
|
through the APP. */
|
||
|
|
td_u32 mrs_cco_start_tf_identify(td_u32 duration)
|
||
|
|
{
|
||
|
|
mrs_cco_srv_ctx *cco = mrs_cco_get_srv_ctx();
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
td_u32 len = sizeof(mrs_cco_tf_ctx) + sizeof(mrs_cco_tf_sta_result) * EXT_MDM_NM_TOPO_NODE_NUM_MAX;
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = TD_NULL;
|
||
|
|
|
||
|
|
if (g_mrs_cco_tf_ctx_hdl == TD_NULL) {
|
||
|
|
g_mrs_cco_tf_ctx_hdl = (mrs_cco_tf_ctx *)uapi_malloc(EXT_MOD_ID_APP_COMMON, len);
|
||
|
|
if (g_mrs_cco_tf_ctx_hdl == TD_NULL) {
|
||
|
|
return EXT_ERR_MALLOC_FAILURE;
|
||
|
|
}
|
||
|
|
(td_void) memset_s(g_mrs_cco_tf_ctx_hdl, len, 0, len);
|
||
|
|
|
||
|
|
if (mrs_cco_tf_refresh_nv_para() != EXT_ERR_SUCCESS) {
|
||
|
|
uapi_free(EXT_MOD_ID_APP_COMMON, g_mrs_cco_tf_ctx_hdl);
|
||
|
|
g_mrs_cco_tf_ctx_hdl = TD_NULL;
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
tf_ctx = g_mrs_cco_tf_ctx_hdl;
|
||
|
|
tf_ctx->is_show_dfx_log = TD_TRUE;
|
||
|
|
|
||
|
|
tf_ctx->identify_duration = ext_minute_2_sec(duration) * tf_conf->identify_duration_rate / 100; /* 100 ms */
|
||
|
|
tf_ctx->report_duration = ext_minute_2_sec(duration) - tf_ctx->identify_duration;
|
||
|
|
|
||
|
|
if (tf_ctx->identify_duration == 0) {
|
||
|
|
tf_ctx->identify_duration = ext_minute_2_sec(tf_conf->identify_duration);
|
||
|
|
tf_ctx->report_duration = ext_minute_2_sec(tf_conf->report_duration);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (tf_ctx->status != MRS_TF_STATUE_IDENTIFYING && tf_ctx->status != MRS_TF_STATUS_REPORT_RESULT) {
|
||
|
|
if (tf_ctx->last_white_switch != TD_TRUE) {
|
||
|
|
(td_void) uapi_get_white_list_switch(&tf_ctx->last_white_switch);
|
||
|
|
}
|
||
|
|
(td_void) uapi_set_white_list_switch(TD_FALSE, TD_FALSE, EXT_MAC_WHITE_LIST_TF_IDENTIFY);
|
||
|
|
|
||
|
|
mrs_cco_clear_sta_tf_result();
|
||
|
|
mrs_cco_refresh_sta_tf_record();
|
||
|
|
}
|
||
|
|
tf_ctx->begin_time = uapi_get_seconds();
|
||
|
|
tf_ctx->status = MRS_TF_STATUE_IDENTIFYING;
|
||
|
|
|
||
|
|
mrs_cco_send_tf_start_cmd();
|
||
|
|
mrs_cco_reset_all_timer();
|
||
|
|
|
||
|
|
cco->status = MRS_CCO_STATUS_SEARCH_METER;
|
||
|
|
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_IDENTIFY_PROC, uapi_sec_2_ms(tf_ctx->identify_duration), EXT_TIMER_TYPE_ONCE);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_SEND_START_CMD, uapi_sec_2_ms(tf_conf->start_cmd_interval), EXT_TIMER_TYPE_PERIOD);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_REFRESH_STA_LIST, uapi_sec_2_ms(tf_conf->refrash_topo_interval),
|
||
|
|
EXT_TIMER_TYPE_PERIOD);
|
||
|
|
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Query the registration result of the slave node. */
|
||
|
|
td_void mrs_cco_query_tf_identify(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_SEND_START_CMD); /* Stop sending the START command periodically. */
|
||
|
|
|
||
|
|
tf_ctx->status = MRS_TF_STATUS_REPORT_RESULT;
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_REPORT_PROC, uapi_sec_2_ms(tf_ctx->report_duration), EXT_TIMER_TYPE_ONCE);
|
||
|
|
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_QUERY_INTERVAL, uapi_sec_2_ms(tf_conf->query_sta_interval), EXT_TIMER_TYPE_ONCE);
|
||
|
|
|
||
|
|
tf_ctx->query_idx = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_stop_tf_identify(td_void)
|
||
|
|
{
|
||
|
|
td_u16 cnt;
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_srv_ctx *cco = mrs_cco_get_srv_ctx();
|
||
|
|
td_bool need_report = TD_FALSE;
|
||
|
|
|
||
|
|
mrs_cco_send_tf_stop_cmd(); /* Send the command for stopping the slave node registration. */
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
cnt = mrs_cco_not_report_num(&need_report);
|
||
|
|
if (cnt > 0) {
|
||
|
|
mrs_cco_tf_result_report(TD_NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
tf_ctx->status = MRS_TF_STATUS_COMPLETED;
|
||
|
|
mrs_cco_tf_report_06_f3(MRS_TF_PROCESS_FINISHED);
|
||
|
|
|
||
|
|
cco->status = MRS_CCO_STATUS_IDLE;
|
||
|
|
tf_ctx->p1376_seq = 0;
|
||
|
|
tf_ctx->query_idx = 0;
|
||
|
|
tf_ctx->query_pend_cnt = 0;
|
||
|
|
|
||
|
|
mrs_cco_reset_all_timer();
|
||
|
|
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_SEND_STOP_CMD, uapi_sec_2_ms(tf_conf->stop_cmd_interval), EXT_TIMER_TYPE_PERIOD);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_COMPLETE, uapi_sec_2_ms(tf_conf->delay_white_list_duration), EXT_TIMER_TYPE_ONCE);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Clear the identification result. */
|
||
|
|
td_void mrs_cco_clear_sta_tf_result(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
td_u32 clear_size;
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
tf_ctx->sta_num = 0;
|
||
|
|
clear_size = sizeof(mrs_cco_tf_sta_result) * EXT_MDM_NM_TOPO_NODE_NUM_MAX;
|
||
|
|
(td_void) memset_s(tf_ctx->sta_results, clear_size, 0, clear_size);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Update the identification result list based on the latest topology. */
|
||
|
|
td_void mrs_cco_refresh_sta_tf_record(td_void)
|
||
|
|
{
|
||
|
|
ext_mdm_nm_topo_node_info *topo_infos = TD_NULL;
|
||
|
|
|
||
|
|
uapi_get_topo_info(&topo_infos);
|
||
|
|
if (topo_infos == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
mrs_cco_delete_invalid_sta_record(topo_infos);
|
||
|
|
mrs_cco_realign_sta_record();
|
||
|
|
mrs_cco_add_new_sta_record(topo_infos);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Delete the stations that are not in the topology from the identification result list. */
|
||
|
|
td_void mrs_cco_delete_invalid_sta_record(ext_mdm_nm_topo_node_info *topo_infos)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
td_u16 i;
|
||
|
|
td_u16 j;
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < tf_ctx->sta_num; i++) {
|
||
|
|
for (j = 0; j < EXT_MDM_NM_TOPO_NODE_NUM_MAX; j++) {
|
||
|
|
if (memcmp(tf_ctx->sta_results[i].mac, topo_infos[j].mac, EXT_PLC_MAC_ADDR_LEN) == 0 &&
|
||
|
|
topo_infos[j].state != STATE_NOT_USED) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (j >= EXT_MDM_NM_TOPO_NODE_NUM_MAX) {
|
||
|
|
(td_void) memset_s(&tf_ctx->sta_results[i], sizeof(tf_ctx->sta_results[i]),
|
||
|
|
0, sizeof(tf_ctx->sta_results[i]));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Move the valid records in the identification result list to the top. */
|
||
|
|
td_void mrs_cco_realign_sta_record(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
td_u16 i;
|
||
|
|
td_u16 j = 0;
|
||
|
|
errno_t ret;
|
||
|
|
|
||
|
|
/* Find the first invalid node. */
|
||
|
|
while (tf_ctx->sta_results[j].tei > 0 && j < tf_ctx->sta_num) {
|
||
|
|
j++;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Move the valid records forward. */
|
||
|
|
for (i = j + 1; i < tf_ctx->sta_num; i++) {
|
||
|
|
if (tf_ctx->sta_results[i].tei == 0) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = memcpy_s(&tf_ctx->sta_results[j], sizeof(tf_ctx->sta_results[j]), &tf_ctx->sta_results[i],
|
||
|
|
sizeof(tf_ctx->sta_results[i]));
|
||
|
|
if (ret == EXT_ERR_SUCCESS) {
|
||
|
|
j++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
tf_ctx->sta_num = j;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Add the points that are not included in the identification result list in the topology view. */
|
||
|
|
td_void mrs_cco_add_new_sta_record(ext_mdm_nm_topo_node_info *topo_infos)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
td_u16 topo_idx;
|
||
|
|
td_u16 record_idx;
|
||
|
|
mrs_cco_tf_sta_result *sta_list = TD_NULL;
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
sta_list = tf_ctx->sta_results;
|
||
|
|
|
||
|
|
for (topo_idx = 0; topo_idx < EXT_MDM_NM_TOPO_NODE_NUM_MAX; topo_idx++) {
|
||
|
|
if (topo_infos[topo_idx].state == STATE_NOT_USED || topo_idx + 1 <= 1) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (record_idx = 0; record_idx < tf_ctx->sta_num; record_idx++) {
|
||
|
|
if (memcmp(topo_infos[topo_idx].mac, sta_list[record_idx].mac, EXT_PLC_MAC_ADDR_LEN) == 0) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (record_idx >= tf_ctx->sta_num && tf_ctx->sta_num < EXT_MDM_NM_TOPO_NODE_NUM_MAX) {
|
||
|
|
(td_void) memset_s(&sta_list[tf_ctx->sta_num], sizeof(sta_list[tf_ctx->sta_num]), 0,
|
||
|
|
sizeof(sta_list[tf_ctx->sta_num]));
|
||
|
|
sta_list[tf_ctx->sta_num].tei = topo_idx + 1;
|
||
|
|
if (memcpy_s(sta_list[tf_ctx->sta_num].mac, sizeof(sta_list[tf_ctx->sta_num].mac),
|
||
|
|
topo_infos[topo_idx].mac, EXT_PLC_MAC_ADDR_LEN) != EXT_ERR_SUCCESS) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
tf_ctx->sta_num++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* The CCO sends a command to the STA to identify the transformer district. */
|
||
|
|
td_void mrs_cco_send_tf_start_cmd(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_plc_frame_data plc;
|
||
|
|
mrs_plc_start_search_meter tf_cmd;
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
tf_ctx->plc_seq++;
|
||
|
|
|
||
|
|
(td_void) memset_s(&tf_cmd, sizeof(tf_cmd), 0, sizeof(tf_cmd));
|
||
|
|
tf_cmd.interface_ver = MRS_PLC_PROTO_VERSION;
|
||
|
|
tf_cmd.stru_len = sizeof(tf_cmd);
|
||
|
|
tf_cmd.force_resp = 0;
|
||
|
|
tf_cmd.option = MRS_SM_START_SEARCH;
|
||
|
|
tf_cmd.seq = tf_ctx->plc_seq;
|
||
|
|
|
||
|
|
(td_void) memset_s(&plc, sizeof(plc), 0, sizeof(plc));
|
||
|
|
plc.id = PLC_CMD_ID_START_SEARCH;
|
||
|
|
plc.payload_len = sizeof(tf_cmd);
|
||
|
|
plc.payload = (td_pbyte)&tf_cmd;
|
||
|
|
plc.bc_flag = TD_TRUE;
|
||
|
|
(td_void) memset_s(plc.addr, sizeof(plc.addr), 0xFF, EXT_PLC_MAC_ADDR_LEN);
|
||
|
|
|
||
|
|
mrs_cco_tf_dfx_report_message(EXT_DSID_APP_MRS_TF_CCO_PLC_START_SEND, (td_pvoid)&tf_cmd, sizeof(tf_cmd));
|
||
|
|
|
||
|
|
mrs_plc_frame_send(&plc);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Query the number of nodes that report conditions but are not reported to the concentrator. If a point meets the
|
||
|
|
reporting condition and is not reported for five times, it needs to be reported immediately. */
|
||
|
|
td_u16 mrs_cco_not_report_num(EXT_OUT td_bool *need_report)
|
||
|
|
{
|
||
|
|
td_u16 num = 0;
|
||
|
|
td_u16 i;
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_tf_sta_result *sta_list = tf_ctx->sta_results;
|
||
|
|
|
||
|
|
for (i = 0; i < tf_ctx->sta_num; i++) {
|
||
|
|
if (sta_list[i].query_cnt == 0) {
|
||
|
|
return num;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (sta_list[i].is_ack == TD_TRUE && sta_list[i].is_report == TD_FALSE &&
|
||
|
|
sta_list[i].result == MRS_TF_RESULT_BELONG) {
|
||
|
|
if (num == 0) {
|
||
|
|
tf_ctx->report_idx = i; /* Indicates the start position of the report. */
|
||
|
|
}
|
||
|
|
if (sta_list[i].period_num >= MRS_TF_REPORT_CHECK_CNT) {
|
||
|
|
*need_report = TD_TRUE;
|
||
|
|
}
|
||
|
|
sta_list[i].period_num++;
|
||
|
|
num++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return num;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Querying the Slave Node Registration Process */
|
||
|
|
td_void mrs_cco_query_tf_proc(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
td_u8 query_cnt = 0;
|
||
|
|
td_u16 i;
|
||
|
|
td_u16 cnt;
|
||
|
|
td_bool need_report = TD_FALSE;
|
||
|
|
mrs_cco_tf_sta_result *sta_list = TD_NULL;
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
sta_list = tf_ctx->sta_results;
|
||
|
|
for (i = tf_ctx->query_idx; i < tf_ctx->sta_num && query_cnt < tf_conf->query_sta_max_way; i++) {
|
||
|
|
if (sta_list[i].is_ack == TD_TRUE || sta_list[i].query_cnt > tf_conf->query_max_cnt) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (mrs_cco_send_tf_query_cmd(sta_list[i].mac) != EXT_ERR_SUCCESS) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
sta_list[i].query_cnt++;
|
||
|
|
query_cnt++;
|
||
|
|
|
||
|
|
tf_ctx->query_pend_cnt++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i >= tf_ctx->sta_num) {
|
||
|
|
tf_ctx->query_idx = 0;
|
||
|
|
} else {
|
||
|
|
tf_ctx->query_idx = i;
|
||
|
|
}
|
||
|
|
|
||
|
|
cnt = mrs_cco_not_report_num(&need_report);
|
||
|
|
if (cnt >= MRS_TF_SEARCH_METER_REPORT_NUM || need_report == TD_TRUE) {
|
||
|
|
mrs_cco_tf_result_report(TD_NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (tf_ctx->status == MRS_TF_STATUS_COMPLETED) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (tf_ctx->query_pend_cnt > 0) {
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_QUERY_TIMEOUT, uapi_sec_2_ms(tf_conf->query_sta_timeout), EXT_TIMER_TYPE_ONCE);
|
||
|
|
} else {
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_QUERY_INTERVAL);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_QUERY_INTERVAL, uapi_sec_2_ms(tf_conf->query_sta_interval),
|
||
|
|
EXT_TIMER_TYPE_ONCE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_cco_send_tf_query_cmd(td_u8 sta_mac[EXT_PLC_MAC_ADDR_LEN])
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_plc_frame_data plc;
|
||
|
|
mrs_plc_meterlist_dl tf_cmd;
|
||
|
|
td_u8 cco_mac[EXT_PLC_MAC_ADDR_LEN] = { 0 };
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
tf_ctx->plc_seq++;
|
||
|
|
(td_void) memset_s(&tf_cmd, sizeof(tf_cmd), 0, sizeof(tf_cmd));
|
||
|
|
tf_cmd.interface_ver = MRS_PLC_PROTO_VERSION;
|
||
|
|
tf_cmd.stru_len = sizeof(tf_cmd);
|
||
|
|
tf_cmd.option = MRS_SM_SEARCH_RESULT;
|
||
|
|
tf_cmd.enable = MRS_TF_DISABLE;
|
||
|
|
tf_cmd.seq = tf_ctx->plc_seq;
|
||
|
|
uapi_get_my_mac(cco_mac, sizeof(cco_mac));
|
||
|
|
(td_void) memcpy_s(tf_cmd.src, sizeof(tf_cmd.src), cco_mac, EXT_PLC_MAC_ADDR_LEN);
|
||
|
|
(td_void) memcpy_s(tf_cmd.dst, sizeof(tf_cmd.dst), sta_mac, EXT_PLC_MAC_ADDR_LEN);
|
||
|
|
|
||
|
|
(td_void) memset_s(&plc, sizeof(plc), 0, sizeof(plc));
|
||
|
|
plc.id = PLC_CMD_ID_METER_LIST;
|
||
|
|
plc.payload_len = sizeof(tf_cmd);
|
||
|
|
plc.payload = (td_pbyte)&tf_cmd;
|
||
|
|
|
||
|
|
if (memcpy_s(plc.addr, sizeof(plc.addr), sta_mac, EXT_PLC_MAC_ADDR_LEN) != EXT_ERR_SUCCESS) {
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
mrs_cco_tf_dfx_report_message(EXT_DSID_APP_MRS_TF_CCO_PLC_QUERY_SEND, (td_pvoid *)&tf_cmd, sizeof(tf_cmd));
|
||
|
|
return mrs_plc_frame_send(&plc);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* The CCO sends a stop command to the STA. */
|
||
|
|
td_void mrs_cco_send_tf_stop_cmd(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_plc_frame_data plc;
|
||
|
|
mrs_plc_stop_search_meter tf_cmd;
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
tf_ctx->plc_seq++;
|
||
|
|
|
||
|
|
(td_void) memset_s(&tf_cmd, sizeof(tf_cmd), 0, sizeof(tf_cmd));
|
||
|
|
tf_cmd.interface_ver = MRS_PLC_PROTO_VERSION;
|
||
|
|
tf_cmd.stru_len = sizeof(tf_cmd);
|
||
|
|
tf_cmd.seq = tf_ctx->plc_seq;
|
||
|
|
|
||
|
|
(td_void) memset_s(&plc, sizeof(plc), 0, sizeof(plc));
|
||
|
|
plc.id = PLC_CMD_ID_STOP_SEARCH;
|
||
|
|
plc.payload_len = sizeof(mrs_plc_stop_search_meter);
|
||
|
|
plc.payload = (td_pbyte)&tf_cmd;
|
||
|
|
plc.bc_flag = TD_TRUE;
|
||
|
|
(td_void) memset_s(plc.addr, sizeof(plc.addr), 0xFF, EXT_PLC_MAC_ADDR_LEN);
|
||
|
|
|
||
|
|
mrs_cco_tf_dfx_report_message(EXT_DSID_APP_MRS_TF_CCO_PLC_STOP_SEND, (td_pvoid *)&tf_cmd, sizeof(tf_cmd));
|
||
|
|
mrs_plc_frame_send(&plc);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_get_tf_report_data(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
td_pbyte buf;
|
||
|
|
td_u16 offset = 1;
|
||
|
|
td_u8 num = 0;
|
||
|
|
|
||
|
|
buf = tf_ctx->afn06_f4_buf;
|
||
|
|
while ((tf_ctx->report_idx < tf_ctx->sta_num) && (num < MRS_TF_SEARCH_METER_REPORT_NUM)) {
|
||
|
|
if (tf_ctx->sta_results[tf_ctx->report_idx].result == MRS_TF_RESULT_BELONG &&
|
||
|
|
tf_ctx->sta_results[tf_ctx->report_idx].is_report == TD_FALSE &&
|
||
|
|
!mrs_invalid_meter(tf_ctx->sta_results[tf_ctx->report_idx].addr)) {
|
||
|
|
num++;
|
||
|
|
tf_ctx->p1376_seq++;
|
||
|
|
/* addr */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].addr[0]; /* addr 0 byte */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].addr[1]; /* addr 1 byte */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].addr[2]; /* addr 2 byte */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].addr[3]; /* addr 3 byte */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].addr[4]; /* addr 4 byte */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].addr[5]; /* addr 5 byte */
|
||
|
|
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].protocol; /* protocol */
|
||
|
|
buf[offset++] = (td_u8)(tf_ctx->p1376_seq & 0xff); /* seq: Lo */
|
||
|
|
buf[offset++] = (td_u8)((tf_ctx->p1376_seq >> 8) & 0xff); /* seq: Hi ,left move 8 bits */
|
||
|
|
buf[offset++] = tf_ctx->sta_results[tf_ctx->report_idx].type; /* device type */
|
||
|
|
buf[offset++] = 0; /* sub node num */
|
||
|
|
buf[offset++] = 0; /* sub node num of this frame */
|
||
|
|
|
||
|
|
tf_ctx->sta_results[tf_ctx->report_idx].is_report = TD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
tf_ctx->report_idx++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (num == 0) {
|
||
|
|
tf_ctx->afn06_f4_length = 0;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
buf[0] = num;
|
||
|
|
tf_ctx->afn06_f4_length = 1 + MRS_TF_METER_NODE_SIZE * num;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_report_06_f3(td_u8 status)
|
||
|
|
{
|
||
|
|
td_u32 ret;
|
||
|
|
mrs_proto_1376_2_encode encode;
|
||
|
|
mrs_cco_srv_ctx *cco = mrs_cco_get_srv_ctx();
|
||
|
|
mrs_cco_queue_item *item = TD_NULL;
|
||
|
|
td_pbyte payload = TD_NULL;
|
||
|
|
td_u16 payload_len = 0;
|
||
|
|
td_u8 data = status;
|
||
|
|
|
||
|
|
memset_s(&encode, sizeof(encode), 0, sizeof(encode));
|
||
|
|
encode.afn = 0x06; /* afn is 0x06 */
|
||
|
|
encode.fn = 0x03; /* fn is 0x03 */
|
||
|
|
encode.data = &data;
|
||
|
|
encode.length = sizeof(data);
|
||
|
|
encode.prm = 1;
|
||
|
|
encode.seq = ++cco->seq;
|
||
|
|
ret = mrs_proto_1376_2_create_frame(&encode, &payload, &payload_len);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
item = (mrs_cco_queue_item *)mrs_malloc(sizeof(mrs_cco_queue_item) + payload_len);
|
||
|
|
if (item == TD_NULL) {
|
||
|
|
mrs_free(payload);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset_s(item, sizeof(mrs_cco_queue_item) + payload_len, 0, sizeof(mrs_cco_queue_item) + payload_len);
|
||
|
|
item->valid = TD_TRUE;
|
||
|
|
item->afn = 0x06;
|
||
|
|
item->fn = 0x03;
|
||
|
|
item->retry_max = MRS_CCO_TF_REPORT_RETRY_MAX;
|
||
|
|
item->timeout = MRS_CCO_TF_REPORT_TIMEOUT;
|
||
|
|
item->data_len = payload_len;
|
||
|
|
if (memcpy_s(item->data, item->data_len, payload, payload_len) != EOK) {
|
||
|
|
mrs_free(payload);
|
||
|
|
mrs_free(item);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
mrs_cco_queue_enqueue(item);
|
||
|
|
mrs_cco_queue_active();
|
||
|
|
mrs_cco_tf_dfx_report_message(EXT_DSID_APP_MRS_TF_CCO_UART_SEND, (td_pvoid)payload, payload_len);
|
||
|
|
mrs_free(payload);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_report_06_f4(td_void)
|
||
|
|
{
|
||
|
|
td_u32 ret;
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_srv_ctx *cco = mrs_cco_get_srv_ctx();
|
||
|
|
mrs_proto_1376_2_encode encode;
|
||
|
|
mrs_cco_queue_item *item = TD_NULL;
|
||
|
|
td_pbyte payload = TD_NULL;
|
||
|
|
td_u16 payload_len = 0;
|
||
|
|
|
||
|
|
(td_void) memset_s(&encode, sizeof(encode), 0, sizeof(encode));
|
||
|
|
encode.afn = 0x06;
|
||
|
|
encode.fn = 0x04;
|
||
|
|
encode.data = tf_ctx->afn06_f4_buf;
|
||
|
|
encode.length = tf_ctx->afn06_f4_length;
|
||
|
|
encode.prm = 1;
|
||
|
|
encode.seq = ++cco->seq;
|
||
|
|
ret = mrs_proto_1376_2_create_frame(&encode, &payload, &payload_len);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
item = (mrs_cco_queue_item *)mrs_malloc(sizeof(mrs_cco_queue_item) + payload_len);
|
||
|
|
if (item == TD_NULL) {
|
||
|
|
mrs_free(payload);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
(td_void) memset_s(item, sizeof(mrs_cco_queue_item) + payload_len, 0, sizeof(mrs_cco_queue_item) + payload_len);
|
||
|
|
item->valid = TD_TRUE;
|
||
|
|
item->afn = 0x06; /* 0x06 is afn num */
|
||
|
|
item->fn = 0x04; /* 0x04 is fn num */
|
||
|
|
item->retry_max = MRS_CCO_TF_REPORT_RETRY_MAX;
|
||
|
|
item->timeout = MRS_CCO_TF_REPORT_TIMEOUT;
|
||
|
|
item->data_len = payload_len;
|
||
|
|
if (memcpy_s(item->data, item->data_len, payload, payload_len) != EOK) {
|
||
|
|
mrs_free(payload);
|
||
|
|
mrs_free(item);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
item->rx_handle = mrs_cco_tf_result_report; /* This command is invoked when the cco receives the 00-f1 or 00-f2
|
||
|
|
from the concentrator. */
|
||
|
|
mrs_cco_queue_enqueue(item);
|
||
|
|
mrs_cco_queue_active();
|
||
|
|
mrs_cco_tf_dfx_report_message(EXT_DSID_APP_MRS_TF_CCO_UART_SEND, (td_pvoid)payload, payload_len);
|
||
|
|
mrs_free(payload);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_finished(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_SEND_STOP_CMD);
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
(td_void) uapi_set_white_list_switch(tf_ctx->last_white_switch, TD_FALSE, EXT_MAC_WHITE_LIST_TF_IDENTIFY);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_query_timeout(td_void)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
tf_ctx->query_pend_cnt = 0;
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_QUERY_INTERVAL);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_QUERY_INTERVAL, uapi_sec_2_ms(tf_conf->query_sta_interval), EXT_TIMER_TYPE_ONCE);
|
||
|
|
}
|
||
|
|
|
||
|
|
mrs_cco_tf_sta_result *mrs_cco_get_sta_tf_result(td_u8 sta_mac[EXT_PLC_MAC_ADDR_LEN])
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
td_u16 i;
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return TD_NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < tf_ctx->sta_num; i++) {
|
||
|
|
if (memcmp(sta_mac, tf_ctx->sta_results[i].mac, EXT_PLC_MAC_ADDR_LEN) == 0) {
|
||
|
|
return &tf_ctx->sta_results[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return TD_NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_plc_frame_rx(mrs_plc_frame_data *plc)
|
||
|
|
{
|
||
|
|
mrs_plc_meterlist_up *tf_sta_response = TD_NULL;
|
||
|
|
mrs_cco_tf_sta_result *sta_result = TD_NULL;
|
||
|
|
mrs_cmd_meterlist_item *meter_item = TD_NULL;
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
mrs_cco_tf_inf *tf_conf = mrs_cco_get_tf_conf();
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
tf_ctx->query_pend_cnt--;
|
||
|
|
if (tf_ctx->query_pend_cnt <= 0) {
|
||
|
|
tf_ctx->query_pend_cnt = 0;
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_QUERY_TIMEOUT);
|
||
|
|
|
||
|
|
mrs_timer_stop(MRS_TIMER_ID_TF_QUERY_INTERVAL);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_TF_QUERY_INTERVAL, uapi_sec_2_ms(tf_conf->query_sta_interval),
|
||
|
|
EXT_TIMER_TYPE_ONCE);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (plc == TD_NULL || plc->payload == TD_NULL ||
|
||
|
|
plc->payload_len < sizeof(mrs_plc_meterlist_up) + sizeof(mrs_cmd_meterlist_item)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
mrs_cco_tf_dfx_report_message(EXT_DSID_APP_MRS_TF_CCO_PLC_RECV, (td_pvoid *)plc->payload, plc->payload_len);
|
||
|
|
|
||
|
|
tf_sta_response = (mrs_plc_meterlist_up *)plc->payload;
|
||
|
|
meter_item = (mrs_cmd_meterlist_item *)tf_sta_response->meter_list;
|
||
|
|
|
||
|
|
sta_result = mrs_cco_get_sta_tf_result(tf_sta_response->src);
|
||
|
|
if (sta_result == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
sta_result->result = tf_sta_response->result;
|
||
|
|
(td_void) memcpy_s(sta_result->addr, MRS_METER_ADDR_LEN, tf_sta_response->asset, MRS_METER_ADDR_LEN);
|
||
|
|
if (tf_sta_response->type == MRS_DEVICE_TYPE_PLC_METER) {
|
||
|
|
sta_result->type = MRS_DEVICE_TYPE_1376_2_METER;
|
||
|
|
if (mrs_invalid_meter(sta_result->addr)) {
|
||
|
|
(td_void) memcpy_s(sta_result->addr, EXT_PLC_MAC_ADDR_LEN, tf_sta_response->id, EXT_PLC_MAC_ADDR_LEN);
|
||
|
|
}
|
||
|
|
} else if (tf_sta_response->type == MRS_DEVICE_TYPE_PLC_RELAY) {
|
||
|
|
sta_result->type = MRS_DEVICE_TYPE_1376_2_RELAY;
|
||
|
|
}
|
||
|
|
sta_result->protocol = meter_item->protocol;
|
||
|
|
sta_result->is_ack = TD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_cco_tf_result_report(td_pvoid param)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
ext_unref_param(param);
|
||
|
|
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
mrs_cco_get_tf_report_data();
|
||
|
|
|
||
|
|
if (tf_ctx->afn06_f4_length > 0) {
|
||
|
|
mrs_cco_tf_report_06_f4();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_dfx_tf_ctrl(diag_cmd_tf_ctrl_req *req, td_u16 cmd_size, td_u8 option)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx;
|
||
|
|
diag_cmd_tf_ctrl_ind ind;
|
||
|
|
td_u32 pass_duration;
|
||
|
|
|
||
|
|
if (req == TD_NULL || cmd_size < sizeof(diag_cmd_tf_ctrl_req)) {
|
||
|
|
return EXT_ERR_INVALID_PARAMETER;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (req->cmd_type == TF_CMD_TYPE_START_IDENTIFY) {
|
||
|
|
mrs_cco_start_tf_identify(req->duration);
|
||
|
|
} else if (req->cmd_type == TF_CMD_TYPE_STOP_IDENTIFY) {
|
||
|
|
mrs_cco_stop_tf_identify();
|
||
|
|
} else {
|
||
|
|
}
|
||
|
|
(td_void) memset_s(&ind, sizeof(ind), 0, sizeof(ind));
|
||
|
|
|
||
|
|
tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
ind.ret = EXT_ERR_SUCCESS;
|
||
|
|
if (tf_ctx == TD_NULL) {
|
||
|
|
ind.tf_status = 0;
|
||
|
|
ind.last_duration = 0;
|
||
|
|
} else {
|
||
|
|
ind.tf_status = tf_ctx->status;
|
||
|
|
pass_duration = mrs_time_sub_duration(uapi_get_seconds(), tf_ctx->begin_time);
|
||
|
|
if (tf_ctx->status == MRS_TF_STATUE_IDENTIFYING) {
|
||
|
|
ind.last_duration = tf_ctx->identify_duration > pass_duration ?
|
||
|
|
(tf_ctx->identify_duration - pass_duration) : 0;
|
||
|
|
} else if (tf_ctx->status == MRS_TF_STATUS_REPORT_RESULT) {
|
||
|
|
ind.last_duration = (tf_ctx->identify_duration + tf_ctx->report_duration) > pass_duration ?
|
||
|
|
(tf_ctx->identify_duration + tf_ctx->report_duration - pass_duration) : 0;
|
||
|
|
} else {
|
||
|
|
ind.last_duration = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return uapi_diag_report_packet(ID_DIAG_CMD_TF_CTRL, option, (td_pbyte)&ind, sizeof(ind), TD_FALSE);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_dfx_tf_result_query(const diag_cmd_tf_result_req *req, td_u16 cmd_size, td_u8 option)
|
||
|
|
{
|
||
|
|
mrs_cco_tf_ctx *tf_ctx = mrs_cco_get_tf_ctx();
|
||
|
|
diag_cmd_tf_result_ind ind;
|
||
|
|
td_u32 i;
|
||
|
|
|
||
|
|
(td_void) memset_s(&ind, sizeof(ind), 0, sizeof(ind));
|
||
|
|
if (tf_ctx == TD_NULL || req == TD_NULL || cmd_size < sizeof(diag_cmd_tf_result_req)) {
|
||
|
|
return uapi_diag_report_packet(ID_DIAG_CMD_TF_RESULT_QUERY, option, (td_pbyte)&ind, sizeof(ind), TD_FALSE);
|
||
|
|
}
|
||
|
|
|
||
|
|
ind.total_num = tf_ctx->sta_num;
|
||
|
|
ind.report_begin_idx = (td_u16)req->begin_idx;
|
||
|
|
|
||
|
|
for (i = req->begin_idx; i < tf_ctx->sta_num; i++) {
|
||
|
|
(td_void) memcpy_s(ind.results[i - req->begin_idx].sta_mac, EXT_PLC_MAC_ADDR_LEN,
|
||
|
|
tf_ctx->sta_results[i].mac, EXT_PLC_MAC_ADDR_LEN);
|
||
|
|
ind.results[i - req->begin_idx].tei = tf_ctx->sta_results[i].tei;
|
||
|
|
ind.results[i - req->begin_idx].result = tf_ctx->sta_results[i].result;
|
||
|
|
|
||
|
|
ind.report_num++;
|
||
|
|
if (ind.report_num >= DIAG_TF_RESULT_REPORT_NUM) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return uapi_diag_report_packet(ID_DIAG_CMD_TF_RESULT_QUERY, option, (td_pbyte)&ind, sizeof(ind), TD_FALSE);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif /* defined(PRODUCT_CFG_PRODUCT_TYPE_CCO) */
|
||
|
|
|