393 lines
11 KiB
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) */
|
||
|
|
|