inwudriver-weibo/app/mrs/cco/mrs_cco_power_failure.c

433 lines
14 KiB
C
Raw Permalink Normal View History

/*
* Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved.
* Description: MRS CCO POWER FAILURE handle.
*/
#include "soc_mdm_mac.h"
#include "mrs_cco_evt.h"
#include "mrs_proto_1376_2.h"
#include "mrs_common_tools.h"
#include "mrs_cco_srv.h"
#include "mrs_cco_queue.h"
#include "mrs_cco_power_failure.h"
#if defined(PRODUCT_CFG_PRODUCT_TYPE_CCO)
diag_cmd_pwf_result_query g_power_failure_mrs_dfx_info = { 0 };
td_bool mrs_cco_not_reply_ack(td_u8 rcv_mac[EXT_PLC_MAC_ADDR_LEN])
{
td_u16 i;
td_u16 check_tei = 0;
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
ext_mdm_nm_topo_node_info *topo_info = TD_NULL;
if (power_failure_info->power_failure_bitmap == TD_NULL) {
return TD_TRUE;
}
uapi_get_topo_info(&topo_info);
for (i = 0; i < EXT_MDM_NM_TOPO_NODE_NUM_MAX; i++) {
if (memcmp(topo_info[i].mac, rcv_mac, EXT_PLC_MAC_ADDR_LEN) == 0) {
check_tei = i + 1;
break;
}
}
return mrs_power_failure_bit_check(power_failure_info->power_failure_bitmap, check_tei);
}
td_u32 mrs_cco_evt_report(td_void)
{
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
power_failure_info->is_ready_to_send_power_failure = TD_TRUE;
return mrs_timer_start(MRS_TIMER_ID_CCO_POWER_FAILURE, power_failure_info->converge_time * MRS_US_TO_S_MASK,
EXT_TIMER_TYPE_ONCE);
}
/* cco timeout processing for response event report timer */
td_void mrs_cco_rsp_power_failure_evt(td_void)
{
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
if (mrs_cco_create_rsp_power_frame() != EXT_ERR_SUCCESS) { }
power_failure_info->is_ready_to_send_power_failure = TD_FALSE;
if (power_failure_info->cco_diff_bitmap == TD_NULL) {
return;
}
if (memset_s(power_failure_info->cco_diff_bitmap, POWER_FAILURE_BITMAP_LEN, 0,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
return;
}
if (power_failure_info->cco_erease_bitmap_flag == TD_FALSE) {
/* erase data 4 minutes later(set time according to reality) */
mrs_timer_start(MRS_TIMER_ID_CCO_ERASE_DATA,
power_failure_info->converge_time * MRS_US_TO_S_MASK * CCO_ERASE_BITMAP, EXT_TIMER_TYPE_ONCE);
power_failure_info->cco_erease_bitmap_flag = TD_TRUE;
}
}
td_u32 mrs_cco_report_rsp_power_info(td_u32 pk_num, td_u16 *start_tei)
{
td_u32 i;
td_u32 ret;
td_u16 data_length = 0;
mrs_cco_evt_item *item = TD_NULL;
mrs_cco_evt_ctx *evt = mrs_cco_get_evt_ctx();
td_u8 *data = TD_NULL;
for (i = 0; i < pk_num; i++) {
ret = mrs_cco_create_report_frame(&data, &data_length, start_tei);
if (ret != EXT_ERR_SUCCESS) {
break;
}
item = (mrs_cco_evt_item *)mrs_malloc(sizeof(mrs_cco_evt_item) + data_length);
if (item == TD_NULL) {
mrs_free(data);
mrs_free(item);
return EXT_ERR_NO_MORE_MEMORY;
}
if (memset_s(item, sizeof(mrs_cco_evt_item) + data_length, 0,
sizeof(mrs_cco_evt_item) + data_length) != EXT_ERR_SUCCESS) {
mrs_free(data);
mrs_free(item);
return EXT_ERR_FAILURE;
}
item->data_len = data_length;
item->fn = 9; /* fn 9 */
if (memcpy_s(item->data, item->data_len, data, item->data_len) != EOK) {
mrs_free(data);
mrs_free(item);
return EXT_ERR_MEMCPY_FAIL;
}
mrs_queue_enqueue(&evt->evt_q, &item->link);
evt->evt_q_num++;
mrs_free(data);
evt->acd_flg = TD_TRUE;
/* function of reporting by self.(fn = 9, power down report) */
mrs_cco_evt_report_active();
}
return EXT_ERR_SUCCESS;
}
td_u32 mrs_cco_create_rsp_power_frame(td_void)
{
td_u32 ret;
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
td_u16 bitmap_max_tei;
td_u16 bitmap_min_tei;
td_u32 bitmap_tei_cnt;
td_u32 pk_num;
td_u16 start_tei;
/* get bitmap to be sent */
mrs_cco_report_bitmap();
if (power_failure_info->cco_diff_bitmap == TD_NULL) {
return EXT_ERR_FAILURE;
}
bitmap_min_tei = mrs_calc_min_tei(power_failure_info->cco_diff_bitmap);
bitmap_max_tei = mrs_calc_max_tei(power_failure_info->cco_diff_bitmap);
/* calc quantity of power down modules */
bitmap_tei_cnt = mrs_cco_get_bitmap_tei_cnt(bitmap_min_tei, bitmap_max_tei, power_failure_info->cco_diff_bitmap);
start_tei = bitmap_min_tei;
pk_num = (bitmap_tei_cnt + MAX_REPORT_TEI_CNT - 1) / MAX_REPORT_TEI_CNT;
/* create report frame */
ret = mrs_cco_report_rsp_power_info(pk_num, &start_tei);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
/* maintainable info */
mrs_cco_power_failure_dfx_info();
return ret;
}
/* create report frame (376.2 treaty:data_len= 1 + 6xN bytes / supplementary content copy to buffer */
td_u32 mrs_cco_create_report_frame(td_pbyte *buf, td_u16 *data_len, td_u16 *start_tei_pos)
{
td_u32 ret = EXT_ERR_SUCCESS;
mrs_proto_1376_2_encode encode;
mrs_cco_srv_ctx *cco = mrs_cco_get_srv_ctx();
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
td_u16 bitmap_max_tei;
td_u32 bitmap_tei_cnt;
td_u16 report_data_len;
td_byte *pf_data = TD_NULL;
td_u8 report_tei_cnt;
td_u16 next_tei_pos = 0;
td_u8 *bitmap = power_failure_info->cco_diff_bitmap;
bitmap_max_tei = mrs_calc_max_tei(bitmap);
bitmap_tei_cnt = mrs_cco_get_bitmap_tei_cnt(*start_tei_pos, bitmap_max_tei, bitmap);
if (bitmap_tei_cnt > MAX_REPORT_TEI_CNT) {
report_data_len = MAX_REPORT_TEI_CNT * EXT_PLC_MAC_ADDR_LEN;
report_tei_cnt = MAX_REPORT_TEI_CNT;
} else {
report_data_len = (td_u16)(bitmap_tei_cnt * EXT_PLC_MAC_ADDR_LEN);
report_tei_cnt = (td_u8)bitmap_tei_cnt;
}
do {
/* fill data unit */
pf_data = mrs_malloc(report_data_len + 1);
if (pf_data == TD_NULL) {
return EXT_ERR_MALLOC_FAILUE;
}
pf_data[0] = report_tei_cnt; /* report quantity of slave nodes */
/* fill address of power down module */
mrs_cco_report_mac_addr(bitmap, *start_tei_pos, report_data_len, pf_data + 1, &next_tei_pos);
*start_tei_pos = next_tei_pos;
/* fill 3762 frame stucture */
if (memset_s(&encode, sizeof(mrs_proto_1376_2_encode), 0, sizeof(mrs_proto_1376_2_encode)) != EXT_ERR_SUCCESS) {
mrs_free(pf_data);
return EXT_ERR_FAILURE;
}
encode.data = pf_data;
encode.length = report_data_len + 1;
encode.prm = 1;
encode.seq = ++cco->seq;
encode.afn = 6; /* afn 6 */
encode.fn = 9; /* fn 9 */
if (memcpy_s(encode.dst_addr, sizeof(encode.dst_addr), cco->main_node,
EXT_PLC_MAC_ADDR_LEN) != EXT_ERR_SUCCESS) {
break;
}
mrs_hex_invert(encode.dst_addr, EXT_PLC_MAC_ADDR_LEN);
ret = mrs_proto_1376_2_create_frame(&encode, buf, data_len);
mrs_free(encode.data);
} while (0);
mrs_free(pf_data);
return ret;
}
/* get MAC address of power down tei */
td_void mrs_cco_report_mac_addr(td_u8 *diff_bitmap, td_u16 start_pos, td_u16 report_len, td_u8 *mac_addr,
td_u16 *next_pos)
{
td_u16 i;
td_u16 j;
td_u16 bitmap_max_tei;
td_u16 query_index = 0;
ext_mdm_nm_topo_node_info *topo_info = TD_NULL;
td_u8 mac_cnt = 0;
/* get max tei */
bitmap_max_tei = mrs_calc_max_tei(diff_bitmap);
uapi_get_topo_info(&topo_info);
for (i = start_pos; i <= bitmap_max_tei && mac_cnt < report_len; i++) {
/* station power down test */
if (mrs_power_failure_bit_check(diff_bitmap, i) == TD_FALSE) {
continue;
}
/* fill mac address to power-down data unit searched from power-down stations in topo */
for (j = query_index; j < EXT_MDM_NM_TOPO_NODE_NUM_MAX; j++) {
if (j + 1 != i) {
continue;
}
if (memcpy_s(mac_addr + mac_cnt, EXT_PLC_MAC_ADDR_LEN, topo_info[j].mac, EXT_PLC_MAC_ADDR_LEN) != EOK) {
continue;
}
query_index = j + 1;
mrs_hex_invert(mac_addr + mac_cnt, EXT_PLC_MAC_ADDR_LEN);
mac_cnt += EXT_PLC_MAC_ADDR_LEN;
*next_pos = i;
break;
}
}
/* update start index for next reporting */
*next_pos += 1;
}
/* get bitmap which not sent before */
td_void mrs_cco_report_bitmap(td_void)
{
td_u16 i;
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
td_u8 *bitmap_diff = power_failure_info->cco_diff_bitmap;
td_u8 *bitmap_cur = power_failure_info->power_failure_bitmap;
td_u8 *bitmap_last_send = power_failure_info->cco_last_send_bitmap;
if (bitmap_diff == TD_NULL) {
return;
}
if (bitmap_cur == TD_NULL) {
return;
}
if (bitmap_last_send == TD_NULL) {
return;
}
for (i = 0; i < POWER_FAILURE_BITMAP_LEN * BIT_SIZE; i++) {
/* update the difference if the bit of the station is power down present and power on last time */
if (mrs_power_failure_bit_check(bitmap_cur, i) == TD_TRUE &&
mrs_power_failure_bit_check(bitmap_last_send, i) == TD_FALSE) {
mrs_power_failure_bit_set(bitmap_diff, i);
}
}
if (memcpy_s(bitmap_last_send, POWER_FAILURE_BITMAP_LEN, bitmap_cur, POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
return;
}
}
td_u32 mrs_cco_get_bitmap_tei_cnt(td_u16 bitmap_min_tei, td_u16 bitmap_max_tei, td_u8 *bitmap)
{
td_u32 count = 0;
td_u16 i;
td_u16 j;
td_u16 query_index = 0;
ext_mdm_nm_topo_node_info *topo_info = TD_NULL;
uapi_get_topo_info(&topo_info);
if (topo_info == TD_NULL) {
return count;
}
for (i = bitmap_min_tei; i <= bitmap_max_tei; i++) {
/* station power down test */
if (mrs_power_failure_bit_check(bitmap, i) == TD_FALSE) {
continue;
}
for (j = query_index; j < EXT_MDM_NM_TOPO_NODE_NUM_MAX; j++) {
if (topo_info[j].state == STATE_NOT_USED) {
continue;
}
/* verify if station in topo and validity of address */
if ((j + 1 == i) && (!mrs_invalid_meter(topo_info[j].mac))) {
count++;
query_index = j + 1;
break;
}
}
}
return count;
}
/* CCO erase data */
td_void mrs_cco_erase_bitmap(td_void)
{
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
td_u8 *cco_temp_diff_bitmap = TD_NULL;
cco_temp_diff_bitmap = (td_u8 *)mrs_malloc(POWER_FAILURE_BITMAP_LEN);
if (cco_temp_diff_bitmap == TD_NULL) {
return;
}
/* get bitmap to be sent */
mrs_cco_report_bitmap();
do {
if (power_failure_info->cco_diff_bitmap != TD_NULL) {
if (memcpy_s(cco_temp_diff_bitmap, POWER_FAILURE_BITMAP_LEN, power_failure_info->cco_diff_bitmap,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
break;
}
if (memset_s(power_failure_info->cco_diff_bitmap, POWER_FAILURE_BITMAP_LEN, 0,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
break;
}
}
if (mrs_cco_erase_common_bitmap(power_failure_info) != EXT_ERR_SUCCESS) {
break;
}
if (power_failure_info->cco_diff_bitmap != TD_NULL) {
if (memcpy_s(power_failure_info->cco_diff_bitmap, POWER_FAILURE_BITMAP_LEN, cco_temp_diff_bitmap,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
break;
}
}
if (power_failure_info->power_failure_bitmap != TD_NULL) {
if (memcpy_s(power_failure_info->power_failure_bitmap, POWER_FAILURE_BITMAP_LEN, cco_temp_diff_bitmap,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
break;
}
}
} while (0);
mrs_free(cco_temp_diff_bitmap);
}
td_u32 mrs_cco_erase_common_bitmap(mrs_power_failure_ctrl_st *power_failure_info)
{
if (power_failure_info->power_failure_bitmap != TD_NULL &&
memset_s(power_failure_info->power_failure_bitmap, POWER_FAILURE_BITMAP_LEN, 0,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
if (power_failure_info->cco_last_send_bitmap != TD_NULL &&
memset_s(power_failure_info->cco_last_send_bitmap, POWER_FAILURE_BITMAP_LEN, 0,
POWER_FAILURE_BITMAP_LEN) != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
if (memset_s(&g_power_failure_mrs_dfx_info, sizeof(diag_cmd_pwf_result_query), 0,
sizeof(diag_cmd_pwf_result_query)) != EXT_ERR_SUCCESS) {
return EXT_ERR_FAILURE;
}
power_failure_info->cco_erease_bitmap_flag = TD_FALSE;
return EXT_ERR_SUCCESS;
}
/* function for get maintainable info */
td_void mrs_cco_power_failure_dfx_info(td_void)
{
td_u16 i;
mrs_power_failure_ctrl_st *power_failure_info = mrs_get_power_failure_ctrl();
diag_cmd_pwf_result_query *ind = &g_power_failure_mrs_dfx_info;
for (i = 0; i < POWER_FAILURE_BITMAP_LEN * BIT_SIZE; i++) {
if (mrs_power_failure_bit_check(power_failure_info->cco_diff_bitmap, i) == TD_TRUE) {
ind->pwf_tei_cnt++;
}
}
ind->rcv_pwf_frame_time = uapi_get_seconds();
}
td_u32 mrs_cmd_pwf(td_u16 id, td_pvoid cmd, td_u16 cmd_size, td_u8 option)
{
diag_cmd_pwf_result_query *ind = &g_power_failure_mrs_dfx_info;
ext_unref_param(cmd_size);
ext_unref_param(cmd);
return uapi_diag_report_packet(id, option, (td_pbyte)ind, sizeof(diag_cmd_pwf_result_query), TD_FALSE);
}
#endif