inwudriver-weibo/app/mrs/sta/mrs_sta_srv.c

393 lines
11 KiB
C

/*
* Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved.
* Description: MRS sta service.
*/
#include "mrs_sta_srv.h"
#include "mrs_sta_startup.h"
#include "mrs_sta_evt.h"
#include "mrs_sta_simu_meter.h"
#include "mrs_sta_io.h"
#include "mrs_common_tools.h"
#include "app_nv.h"
#include "mrs_sta_tf.h"
#include "mrs_sta_power_failure.h"
#include "mrs_common_capture.h"
#if defined(MRS_USR_DEMO)
#include "mrs_sta_usr.h"
#endif
#if defined(PRODUCT_CFG_PRODUCT_TYPE_STA)
static mrs_sta_srv_ctx *g_sta_srv_ctx = TD_NULL;
td_void mrs_sta_init_timer_func(td_void);
td_void mrs_sta_init_nv_detect(td_void);
td_void mrs_sta_on_timer_queue_ttl(td_void);
td_void mrs_sta_on_timer_queue_notify(td_void);
td_void mrs_sta_on_timer_queue_lock(td_void);
td_u32 mrs_sta_nv_change_detect(td_u8 nv_id);
mrs_sta_srv_ctx *mrs_sta_get_srv_ctx(td_void)
{
return g_sta_srv_ctx;
}
mrs_sta_mr_queue *mrs_sta_get_queue(td_void)
{
if (g_sta_srv_ctx != TD_NULL) {
return &g_sta_srv_ctx->mr_queue;
}
return TD_NULL;
}
td_u32 mrs_sta_srv_init(td_void)
{
mrs_sta_srv_ctx *sta = TD_NULL;
mrs_simu_meter_inf simu = { 0, 0, 0, 0 };
td_bool simu_enable = TD_FALSE;
errno_t err;
if (g_sta_srv_ctx != TD_NULL) {
return EXT_ERR_INITILIZATION_ALREADY;
}
g_sta_srv_ctx = (mrs_sta_srv_ctx *)mrs_malloc(sizeof(mrs_sta_srv_ctx));
if (g_sta_srv_ctx == TD_NULL) {
return EXT_ERR_MALLOC_FAILUE;
}
err = memset_s(g_sta_srv_ctx, sizeof(mrs_sta_srv_ctx), 0, sizeof(mrs_sta_srv_ctx));
if (err != EOK) {
return EXT_ERR_FAILURE;
}
sta = g_sta_srv_ctx;
uapi_get_local_mac_addr(sta->mac, sizeof(sta->mac));
if (mrs_is_product_relay()) {
/* relay */
mrs_sta_set_mac_addr(sta->mac);
return EXT_ERR_SUCCESS;
}
mrs_sta_event_init();
mrs_sta_init_timer_func();
mrs_sta_init_nv_detect();
#if defined(MRS_USR_DEMO)
uapi_set_assoc_by_app_mac(TD_TRUE);
mrs_sta_usr_srv_init();
#else
mrs_proto_645_init();
#endif
mrs_sta_queue_init(&sta->mr_queue);
sta->baudrate = MRS_STA_DEFAULT_BAUDRATE;
if (uapi_nv_read(ID_NV_APP_SIMU_METER, &simu, sizeof(simu)) == EXT_ERR_SUCCESS) {
if (simu.simu_meter == 1) {
simu_enable = TD_TRUE;
}
}
mrs_simu_meter_enable(simu_enable);
mrs_io_init();
mrs_timer_start(MRS_TIMER_ID_STA_INIT, MRS_STA_INIT_TIME, EXT_TIMER_TYPE_ONCE);
return EXT_ERR_SUCCESS;
}
td_void mrs_sta_init_timer_func(td_void)
{
mrs_sta_register_on_timer_func(MRS_TIMER_ID_UART, mrs_proto_645_on_timer);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_QUEUE_LOCK, mrs_sta_on_timer_queue_lock);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_QUEUE, mrs_sta_on_timer_queue_notify);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_TTL, mrs_sta_on_timer_queue_ttl);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_INIT, mrs_sta_startup_detect);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_IO_EVTOUT, mrs_sta_io_evtout_timeout_handle);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_EVT_REPORT, mrs_sta_event_report_plc_timeout_handle);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_RST_IO, mrs_sta_reset_handle);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_PLC_LED_RX, mrs_sta_plc_rx_led_off);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_PLC_LED_TX, mrs_sta_plc_tx_led_off);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_TF_CYCLE_CHECK, mrs_sta_tf_cycle_check);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_POWER_FAILURE, mrs_sta_create_power_failure_frame_proc);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_PW_CHECK, mrs_pwf_check_main);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_POWER_FAILURE_ACK, mrs_sta_handle_wait_power_failure_ack);
mrs_sta_register_on_timer_func(MRS_TIMET_ID_PULL_RST_DELAY_TIMER, mrs_power_failure_pull_rst_handle);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_ENTER_TESTMODE, mrs_enter_test_mode);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_PHY_TRANS_TESTMODE, mrs_exit_phy_tans_test_mode);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_PHY_LOOP_TESTMODE, mrs_exit_phy_loop_test_mode);
mrs_sta_register_on_timer_func(MRS_TIMER_ID_STA_MAC_MSDU_TESTMODE, mrs_exit_mac_msdu_test_mode);
}
td_void mrs_sta_init_nv_detect(td_void)
{
uapi_nv_register_change_nofity_proc(ID_NV_APP_SIMU_METER, ID_NV_APP_SIMU_METER, mrs_sta_nv_change_detect);
}
td_u32 mrs_sta_nv_change_detect(td_u8 nv_id)
{
return mrs_msg_queue_send(MRS_MSG_ID_NV_CHANGE_NOTIFY, 0, nv_id, 0);
}
td_void mrs_msg_on_nv_change_notify(EXT_CONST mrs_queue_msg *msg)
{
switch (msg->param1) {
case ID_NV_APP_SIMU_METER:
mrs_simu_meter_nv_detect();
break;
default:
break;
}
}
td_void mrs_sta_register_on_timer_func(mrs_timer_id timer_id, mrs_on_timer_fct on_timer)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
if (timer_id >= MRS_TIMER_ID_MAX) {
return;
}
sta->on_timer[timer_id] = on_timer;
}
td_void mrs_sta_on_timer_queue_ttl(td_void)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
mrs_sta_queue_unlock(&sta->mr_queue);
mrs_sta_queue_handle(&sta->mr_queue);
}
td_void mrs_sta_on_timer_queue_notify(td_void)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
mrs_sta_queue_handle(&sta->mr_queue);
}
td_void mrs_sta_on_timer_queue_lock(td_void)
{
uapi_usr_reboot(EXT_SYS_REBOOT_CAUSE_USR1);
}
td_void mrs_msg_on_timer(EXT_CONST mrs_queue_msg *msg)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
td_u32 id = (td_u32)msg->param1;
if (id >= MRS_TIMER_ID_MAX) {
return;
}
if (sta->on_timer[id]) {
sta->on_timer[id]();
}
}
td_void mrs_sta_set_status(td_u8 status)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
sta->status = status;
}
td_u8 mrs_sta_get_status(td_void)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
return sta->status;
}
td_void mrs_sta_set_sync_mac_flag(td_bool flag)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
sta->sync_mac = flag;
}
td_bool mrs_sta_get_sync_mac_flag(td_void)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
return (td_bool)sta->sync_mac;
}
td_u32 mrs_sta_register_chl_notify(mrs_sta_chl_notify_fct callback, uintptr_t param)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
if (sta->chl_notify_handle != TD_NULL) {
return EXT_ERR_FULL;
}
sta->chl_notify_handle = callback;
sta->chl_notify_param = param;
return EXT_ERR_SUCCESS;
}
td_u32 mrs_sta_clear_chl_notify(mrs_sta_chl_notify_fct callback)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
if (sta->chl_notify_handle != callback) {
return EXT_ERR_NOT_FOUND;
}
sta->chl_notify_handle = TD_NULL;
sta->chl_notify_param = 0;
return EXT_ERR_SUCCESS;
}
td_u32 mrs_sta_chl_notify_handle(td_bool chl_status)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
if (sta->chl_notify_handle != TD_NULL) {
td_bool one_shot = TD_FALSE;
sta->chl_notify_handle(chl_status, sta->chl_notify_param, &one_shot);
if (one_shot == TD_TRUE) {
sta->chl_notify_handle = TD_NULL;
sta->chl_notify_param = 0;
}
}
return EXT_ERR_SUCCESS;
}
td_u32 mrs_sta_frame_buf_add(const mrs_mr_queue_item *item, const td_pbyte data, td_u16 data_len)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
mrs_sta_frame_buf_ctx *ctx = &sta->frame_buf;
mrs_sta_frame_buf_item *node = ctx->item + ctx->current;
if ((data == TD_NULL) || (data_len > MRS_645_FRAME_LEN_MAX)) {
return EXT_ERR_FAILURE;
}
node->id = item->id;
node->seq = item->seq;
node->valid = TD_TRUE;
node->data_len = data_len;
node->protocol = item->protocol;
node->timestamp = uapi_get_seconds();
if (memcpy_s(node->data, sizeof(node->data), data, data_len) != EOK) {
return EXT_ERR_FAILURE;
}
ctx->current = (ctx->current + 1) % MRS_CFG_STA_FRAME_BUF_CNT;
return EXT_ERR_SUCCESS;
}
td_bool mrs_sta_bc_buf_find(const td_pbyte data, td_u16 data_len)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
mrs_sta_frame_buf_ctx *ctx = &sta->frame_buf;
mrs_sta_frame_buf_item *node = ctx->item;
td_u32 timestamp = uapi_get_seconds();
td_u32 i;
for (i = 0; i < MRS_CFG_STA_FRAME_BUF_CNT; i++) {
if (node[i].valid == TD_FALSE) {
continue;
}
if (timestamp > node[i].timestamp + MRS_CFG_STA_FRAME_BUF_TIMEOUT) {
node[i].valid = TD_FALSE;
continue;
}
if ((node[i].data_len == data_len)
&& (memcmp(node[i].data, data, data_len)) == 0) {
/* Duplicated */
node[i].timestamp = timestamp;
return TD_TRUE;
}
}
return TD_FALSE;
}
td_u32 mrs_sta_frame_buf_find(const mrs_mr_queue_item *item, td_pbyte *data, td_u16 *data_len)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
td_u32 timestamp = uapi_get_seconds();
mrs_sta_frame_buf_ctx *ctx = &sta->frame_buf;
mrs_sta_frame_buf_item *node = ctx->item;
td_u8 i;
if ((data == TD_NULL) || (data_len == TD_NULL)) {
return EXT_ERR_FAILURE;
}
for (i = 0; i < MRS_CFG_STA_FRAME_BUF_CNT; i++) {
if (node->valid == TD_FALSE) {
continue;
}
if (timestamp > node->timestamp + MRS_CFG_STA_FRAME_BUF_TIMEOUT) {
node->valid = TD_FALSE;
continue;
}
if ((item->id == node->id) && (item->seq == node->seq)) {
*data = node->data;
*data_len = node->data_len;
node->timestamp = timestamp;
return EXT_ERR_SUCCESS;
}
}
return EXT_ERR_FAILURE;
}
td_bool mrs_sta_plc_retry_filter(EXT_CONST mrs_mr_queue_item *item)
{
td_u32 ret;
td_pbyte buf = TD_NULL;
td_u16 buf_len;
if (item->id == PLC_CMD_ID_BC) {
return mrs_sta_bc_buf_find((td_u8 *)item->data, item->data_len);
}
ret = mrs_sta_frame_buf_find(item, &buf, &buf_len);
if (ret != EXT_ERR_SUCCESS) {
return TD_FALSE;
}
switch (item->id) {
case PLC_CMD_ID_XR:
case PLC_CMD_ID_PR:
item->rx_handle(item, buf, buf_len);
return TD_TRUE;
default:
break;
}
return TD_FALSE;
}
td_u8 mrs_sta_get_meter_protocol(td_void)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
if ((mrs_is_product_relay()) || (sta == TD_NULL)) {
return 0;
}
return sta->protocol;
}
td_void mrs_sta_set_meter_protocol(td_u8 proto)
{
mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx();
if ((mrs_is_product_relay()) || (sta == TD_NULL)) {
return;
}
sta->protocol = proto;
}
#endif /* defined(PRODUCT_CFG_PRODUCT_TYPE_STA) */