Files
kunlun/app/bsrm/iot_bsrm.c
2024-09-28 14:24:04 +08:00

4292 lines
136 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_module_api.h"
#include "iot_errno_api.h"
#include "iot_task_api.h"
#include "iot_board_api.h"
#include "iot_oem_api.h"
#include "iot_utils_api.h"
#include "iot_system_api.h"
#include "iot_bitops_api.h"
#include "iot_bitmap_api.h"
#include "iot_gpio_api.h"
#include "iot_upgrade_api.h"
#include "iot_bsrm_common.h"
#include "iot_bsrm.h"
#include "iot_plc_hw_tsfm_api.h"
#include "iot_plc_msg_api.h"
#include "iot_bsrm_rec.h"
#include "iot_bsrm_nv.h"
#include "proto_hw_tsfm.h"
#include "iot_bsrm_flash.h"
#include "proto_645_fj.h"
#include "iot_bsrm_upgrade.h"
#include "proto_645_vendor.h"
#include "proto_69845.h"
#include "iot_plc_hw_topo_api.h"
#include "iot_bsrm_pm_upgrade.h"
#include "iot_sg_ext_sta_api.h"
/* define extend bsrm app task stack size */
#define IOT_BSRM_TASK_STACK_SZIE (1024)
/* define extend bsrm app task prio */
#define IOT_BSRM_TASK_PRIO (7)
/* define extend bsrm app message pool size */
#define IOT_BSRM_MSG_POOL_SIZE (128)
/* define extend bsrm app PLC data default priority */
#define IOT_BSRM_PLC_DEFAULT_PRIO (0)
/* define bsrm uart buf size */
#define IOT_BSRM_UART_BUF_SIZE (2048)
/* define periodic timer interval, uint is 1ms */
#define IOT_BSRM_PERIOND_TIMER_INTERVAL (1000)
/* define request addr and tm timer interval, uint is 1s */
#define IOT_BSRM_REQ_TIMER_TIMEOUT (60)
/* define request max count */
#define IOT_BSRM_REQ_MAX_CNT (15)
/* define auto correct tm timer interval, uint is 1s */
#define IOT_BSRM_AUTO_CORRECT_TM_INTERVAL (24 * 60 * 60)
/* define periodic timer interval, uint is 1ms */
#define IOT_BSRM_MR_TIMER_HANDLE_PERIOD (100)
/* the timeout time for 645 response data timeout, uint is 1ms. */
#define IOT_BSRM_MR_TIMER_RSP_TIMEOUT (2000)
#define IOT_BSRM_MR_EVT_NODIFY_TIMEOUT (1000)
#define IOT_BSRM_MR_FWD_TAKEN_TIMEOUT (3000)
/* energy base coeff uint: 0.0001 */
#define IOT_BSRM_BRANCH_BASE_COEFF_VAL (10000)
/* enable/disable bsrm app data print */
#define IOT_BSRM_DEBUG 1
/* the timeout time for branch event, uint is 1s. */
#define IOT_BSRM_BRANCH_EVT_TIMEOUT (60 * 15)
/* branch identification record countdown, uint is 1s */
#define IOT_BSRM_BR_REC_CD (6)
/* bsrm trans mode */
/* default mode, bsrm get tm and addr from uart */
#define IOT_BSRM_SESSION_MODE_DEFAULT (0)
/* trans mode, sg data tranlate to uart */
#define IOT_BSRM_SESSION_MODE_TRANS (1)
/* defines the maximum number of event notification tries */
#define IOT_BSRM_EVT_NODIFY_TRY_MAX (3)
/* define check event gpio interrupt max times, unit: 1/s */
#define IOT_BSRM_EVENT_CHECK_TIMES (5)
/* define bsrm br2 phase */
#define IOT_BSRM_BR2_PHASE_UNKNOWN (0)
#define IOT_BSRM_BR2_PHASE_A (1)
#define IOT_BSRM_BR2_PHASE_B (2)
#define IOT_BSRM_BR2_PHASE_C (3)
#define IOT_BSRM_BR2_PHASE_ALL (4)
/* define bsrm br2 recode max response count */
#define IOT_BSRM_BR_REC_MAX_RESP_CNT (4)
/* br rec fragmenting transmission window duration, uins is 1s */
#define IOT_BSRM_BR_REC_FRAG_WIN_DUR (300)
#if IOT_BSRM_MODE
/* ipc address of sg app */
static iot_ipc_addr_t sg_app_addr =
{ IOT_IPC_FID_SG_EXT_SDK, IOT_IPC_CID_SG_EXT_SG_APP};
static iot_bsrm_global_t *p_bsrm_glb = NULL;
typedef struct _iot_bsrm_rating_current_param {
/* rating current value, unit: A */
uint32_t rating_current;
/* transfer ratio */
float ratio;
/* current sampling resistance, unit: 1.0ohm */
float resistance;
} iot_bsrm_rating_current_t;
/* zhengtai current ratio coeff data table */
const iot_bsrm_rating_current_t rating_cur_tab[] = {
{80, 2000.0, 2.0}, {100, 2000.0, 2.0}, {125, 3200.0, 2.0},
{160, 3200.0, 2.0}, {200, 5000.0, 2.0}, {250, 5000.0, 2.0},
{315, 6666.667, 2.0}, {400, 6666.667, 2.0}, {500, 9000.0, 2.0},
{630, 9000.0, 2.0}, {700, 10000.0, 2.0}, {800, 10000.0, 2.0}
};
#if IOT_BSRM_DEBUG
void iot_bsrm_data_print(const char* str, uint8_t* buf, uint32_t len)
{
static char log_buf[1024];
uint32_t offset = 0;
offset = iot_sprintf(log_buf, "%s[len:%d]", str, len);
for (uint32_t i = 0; i < len; ++i) {
offset += iot_sprintf(log_buf + offset, "%02X ", buf[i]);
if (IOT_ARRAY_CNT(log_buf) <= offset + 4) {
break;
}
}
log_buf[offset] = 0;
iot_bsrm_printf("%s\n", log_buf);
}
#else
void iot_bsrm_data_print(const char* str, uint8_t* buf, uint32_t len)
{
(void)str;
(void)buf;
(void)len;
}
#endif
/* calculating Week of zeller formula */
static uint8_t iot_bsrm_zeller_calc_week(iot_time_tm_t *tm)
{
iot_time_tm_t tm_temp = *tm;
if (tm_temp.tm_mon < 3) {
tm_temp.tm_year -= 1;
tm_temp.tm_mon += 12;
}
int32_t c = tm_temp.tm_year / 100;
int32_t y = tm_temp.tm_year % 100;
int32_t ans = (c / 4 - 2 * c + y + y / 4 + ( 26 * ( tm_temp.tm_mon + 1)) \
/ 10 + tm_temp.tm_mday - 1 ) % 7;
if (ans < 0)
ans += 7;
return (uint8_t)ans;
}
static void iot_bsrm_post_msg(uint16_t msg_type, uint16_t msg_id,
uint8_t prio, void *data, uint32_t data2)
{
iot_bsrm_msg_t *msg;
msg = (iot_bsrm_msg_t *)iot_task_alloc_msg(p_bsrm_glb->task_h);
IOT_ASSERT(msg);
msg->task_msg.type = msg_type;
msg->task_msg.id = msg_id;
msg->data = data;
msg->data2 = data2;
iot_task_queue_msg(p_bsrm_glb->task_h, &msg->task_msg, prio);
}
static void iot_bsrm_clean_msg(uint16_t msg_type, uint16_t msg_id)
{
iot_task_clean_msg(p_bsrm_glb->task_h, msg_type, msg_id);
}
/* callback function for bsrm receive data */
static void iot_bsrm_uart_recv(uint8_t* buffer, uint32_t buffer_len,
bool_t is_full_frame, uint32_t invalid_data_len)
{
(void)is_full_frame;
(void)invalid_data_len;
iot_pkt_t *pkt=NULL;
iot_bsrm_data_print("uart recv data:", buffer, buffer_len);
if (0 == buffer_len) {
return;
}
pkt = iot_pkt_alloc(buffer_len, IOT_BSRM_MID);
IOT_ASSERT(pkt);
os_mem_cpy(iot_pkt_put(pkt, buffer_len), buffer, buffer_len);
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_UART,
IOT_BSRM_MSG_ID_UART_DATA, IOT_BSRM_MSG_QUEUE_LP, (void *)pkt,
0);
}
static void iot_bsrm_mr_timer_func(timer_id_t timer_id, void *arg)
{
(void)timer_id;
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_TIMER,
IOT_BSRM_MSG_ID_TIMER_CHECK_MR, IOT_BSRM_MSG_QUEUE_LP, arg, 0);
}
static void iot_brm_stop_mr_timer(void)
{
os_stop_timer(p_bsrm_glb->mr_timer);
iot_task_clean_msg(p_bsrm_glb->task_h, IOT_BSRM_MSG_TYPE_TIMER,
IOT_BSRM_MSG_ID_TIMER_CHECK_MR);
}
static void iot_bsrm_restart_mr_timer(uint32_t dur)
{
iot_brm_stop_mr_timer();
os_start_timer(p_bsrm_glb->mr_timer, dur);
}
void iot_bsrm_uart_send(iot_pkt_t *pkt)
{
iot_bsrm_data_print("uart send data:", iot_pkt_data(pkt),
iot_pkt_data_len(pkt));
iot_uart_send(p_bsrm_glb->handle, pkt, NULL);
}
static void iot_bsrm_fwd_data(iot_pkt_t *pkt)
{
switch (p_bsrm_glb->mr_status) {
case IOT_BSRM_MR_STATE_IDLE:
case IOT_BSRM_MR_STATE_READY:
{
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_FWD;
}
case IOT_BSRM_MR_STATE_FWD:
{
iot_bsrm_uart_send(pkt);
iot_bsrm_restart_mr_timer(3000);
break;
}
case IOT_BSRM_MR_STATE_EVT_NODIF:
case IOT_BSRM_MR_STATE_SYNC_CUR_RATIO_COEFF:
case IOT_BSRM_MR_STATE_PM_UPGRADE:
{
if (p_bsrm_glb->fwd_pkt) {
iot_pkt_free(p_bsrm_glb->fwd_pkt);
p_bsrm_glb->fwd_pkt = pkt;
}
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void iot_bsrm_send_pkt_to_sg_app(iot_pkt_t *pkt)
{
iot_sg_ext_header_t *hdr;
uint8_t *data;
if (iot_pkt_block_len(pkt, IOT_PKT_BLOCK_HEAD) < sizeof(*hdr)) {
IOT_ASSERT(0);
}
data = (uint8_t *)iot_pkt_push(pkt, sizeof(*hdr));
hdr = (iot_sg_ext_header_t *)data;
hdr->mid = IOT_SG_EXT_MID_UART_DATA_FROM_CUS;
iot_ipc_send(p_bsrm_glb->ipc_h, &sg_app_addr, pkt);
}
static void iot_bsrm_send_data_to_sg_app(uint8_t *data, uint32_t len)
{
iot_sg_ext_header_t *hdr;
iot_pkt_t *pkt;
uint8_t *ds;
pkt = iot_pkt_alloc(len + sizeof(*hdr), IOT_BSRM_MID);
if (pkt == NULL)
return;
iot_bsrm_data_print("bsrm to sg app:", data, len);
ds = iot_pkt_reserve(pkt, sizeof(*hdr));
os_mem_cpy(ds, data, len);
iot_pkt_put(pkt, len);
iot_bsrm_send_pkt_to_sg_app(pkt);
}
static void iot_bsrm_cmd_guard(uint32_t value)
{
if (p_bsrm_glb->mr_status == IOT_BSRM_MR_STATE_IDLE) {
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_READY;
os_start_timer(p_bsrm_glb->mr_timer, value);
}
}
static void iot_bsrm_set_correct_tm_base()
{
/* sync tm done */
p_bsrm_glb->sync_tm_done = 1;
iot_rtc_set(&p_bsrm_glb->correct_tm);
}
static void iot_bsrm_set_correct_tm(uint8_t flag)
{
if (flag) {
p_bsrm_glb->sync_tm_state = IOT_BSRM_SYNC_TIME_STATE_IDLE;
p_bsrm_glb->mr_tm_interval = 0;
iot_bsrm_set_correct_tm_base();
iot_bsrm_printf("%s tm: %d/%d/%d %d:%d:%d\n", __FUNCTION__,
p_bsrm_glb->correct_tm.tm_year,
p_bsrm_glb->correct_tm.tm_mon,
p_bsrm_glb->correct_tm.tm_mday,
p_bsrm_glb->correct_tm.tm_hour,
p_bsrm_glb->correct_tm.tm_min,
p_bsrm_glb->correct_tm.tm_sec);
} else {
/* ready sync tm */
p_bsrm_glb->sync_tm_state = IOT_BSRM_SYNC_TIME_STATE_YMD;
p_bsrm_glb->mr_tm_interval = 0;
iot_bsrm_cmd_guard(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
iot_bsrm_printf("bsrm correct tm begin\n");
}
}
static void iot_bsrm_set_addr(uint8_t *addr)
{
iot_mac_addr_cpy(p_bsrm_glb->addr, addr);
if (!p_bsrm_glb->addr_valid) {
/* ready sync tm */
if (p_bsrm_glb->session_mode == IOT_BSRM_SESSION_MODE_DEFAULT) {
iot_bsrm_set_correct_tm(0);
}
p_bsrm_glb->addr_valid = 1;
if (p_bsrm_glb->cur_coeff_sync_sts == IOT_BSRM_SYNC_CUR_COEFF_IDLE) {
/* ready sync current coeff */
p_bsrm_glb->cur_coeff_sync_sts = IOT_BSRM_SYNC_CUR_COEFF_DOING;
iot_bsrm_cmd_guard(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
}
}
iot_bsrm_printf("bsrm set addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
}
static uint8_t iot_bsrm_addr_check(uint8_t *dst_addr)
{
if (!p_bsrm_glb->addr_valid) {
return 1;
}
return proto_645_mac_addr_cmp(p_bsrm_glb->addr, dst_addr);
}
static void iot_bsrm_check_renew_addr(uint8_t *addr)
{
if (!proto_645_pm_addr_valid(addr))
return;
if (!p_bsrm_glb->addr_valid ||
!iot_mac_addr_cmp(addr, p_bsrm_glb->addr)) {
/* renew addr */
iot_bsrm_set_addr(addr);
}
}
static void iot_bsrm_check_done_handle()
{
/* stop bsrm check timer */
os_stop_timer(p_bsrm_glb->mr_timer);
iot_bsrm_clean_msg(IOT_BSRM_MSG_TYPE_TIMER,
IOT_BSRM_MSG_ID_TIMER_CHECK_MR);
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_IDLE;
if (p_bsrm_glb->mr_addr_pend ||
(p_bsrm_glb->sync_tm_state != IOT_BSRM_SYNC_TIME_STATE_IDLE)) {
iot_bsrm_cmd_guard(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
}
}
static uint32_t iot_bsrm_handle_slave_data(iot_pkt_t *pkt)
{
proto_645_header_t *hdr_645;
uint8_t ret = ERR_FAIL;
uint32_t di;
proto_645_time_hms_t *t_hms;
proto_645_time_ymd_t *t_ymd;
hdr_645 = proto_645_format_check(iot_pkt_data(pkt), iot_pkt_data_len(pkt),
PROTO_645_DIR_SLAVE);
if (hdr_645 == NULL) {
goto out;
}
ret = ERR_OK;
proto_645_sub33_handle(hdr_645->data, hdr_645->len);
di = proto_645_2007_byte_to_di(hdr_645->data);
hdr_645->len -= PROTO_645_2007_DI_LEN;
iot_bsrm_check_renew_addr(hdr_645->addr);
switch (p_bsrm_glb->mr_status) {
case IOT_BSRM_MR_GET_ADDR:
{
break;
}
case IOT_BSRM_MR_STATE_SYNC_TIME:
{
if ((di == PROTO_645_2007_DI_TIME_YMD) &&
(p_bsrm_glb->sync_tm_state == IOT_BSRM_SYNC_TIME_STATE_YMD)) {
t_ymd = (proto_645_time_ymd_t *)(hdr_645->data +
PROTO_645_2007_DI_LEN);
p_bsrm_glb->correct_tm.tm_mday = iot_bcd_to_byte(t_ymd->day);
p_bsrm_glb->correct_tm.tm_mon = iot_bcd_to_byte(t_ymd->month);
p_bsrm_glb->correct_tm.tm_year = iot_bcd_to_byte(t_ymd->year) +
2000;
iot_bsrm_printf("correct ymd success\n");
/* get ymd success, then get hms, set correct tm pend, get hms */
p_bsrm_glb->sync_tm_state = IOT_BSRM_SYNC_TIME_STATE_HMS;
} else if ((di == PROTO_645_2007_DI_TIME_HMS) &&
(p_bsrm_glb->sync_tm_state == IOT_BSRM_SYNC_TIME_STATE_HMS)) {
t_hms = (proto_645_time_hms_t *)(hdr_645->data +
PROTO_645_2007_DI_LEN);
p_bsrm_glb->correct_tm.tm_hour = iot_bcd_to_byte(t_hms->hour);
p_bsrm_glb->correct_tm.tm_min = iot_bcd_to_byte(t_hms->minute);
p_bsrm_glb->correct_tm.tm_sec = iot_bcd_to_byte(t_hms->second);
iot_bsrm_printf("correct hms success\n");
iot_bsrm_set_correct_tm(1);
} else {
iot_bsrm_printf("%s cancle 645 di: %04x \n", __FUNCTION__, di);
goto out;
}
break;
}
default:
iot_bsrm_printf("%s cancle 645 di: %04x \n", __FUNCTION__, di);
goto out;
}
iot_bsrm_check_done_handle();
out:
return ret;
}
static uint8_t iot_bsrm_handle_upgrade(uint8_t *data, uint8_t data_len,
uint8_t *out_buf, uint8_t *len)
{
uint32_t result = ERR_OK;
proto_645_fj_send_file_dl_t *req = (proto_645_fj_send_file_dl_t*)data;
proto_645_fj_send_file_ul_t rsp;
uint8_t err_code = PROTO_645_2007_ERR_OK;
if (data_len < sizeof(proto_645_fj_send_file_dl_t)) {
err_code = PROTO_645_2007_ERR_OTHER;
goto out;
}
iot_bsrm_printf("sg_upgrade: action = %d, seg_len = %d, file_cmd = %d, "
"is_last = %d, seg_index/total_set_cnt = %d/%d. sn = %d\n",
req->action, req->cur_seg_len, req->file_cmd,
req->is_last_seg, req->seg_index, req->total_seg_cnt, 0);
rsp.segment_index = req->seg_index;
switch (req->action) {
case PROTO_645_FJ_UPGRADE_CLEAR_FILE:
{
iot_bsrm_upgrade_stop();
break;
}
case PROTO_645_FJ_UPGRADE_CCO_STA_MODULE:
case PROTO_645_FJ_UPGRADE_LOCAL_MODULE:
case PROTO_645_FJ_UPGRADE_STA_MODULE:
{
if (req->total_seg_cnt == 0 ||
req->cur_seg_len == 0) {
/* reject invalid data packet. */
rsp.segment_index = PROTO_645_FJ_INVALID_SEG_INDEX;
break;
}
if (0 == req->seg_index) {
iot_bsrm_upgrade_start(req->total_seg_cnt, req->cur_seg_len);
if (ERR_OK != result) {
rsp.segment_index = PROTO_645_FJ_INVALID_SEG_INDEX;
break;
}
}
result = iot_bsrm_upgrade_data(req->seg_index, req->cur_seg_len,
req->data);
if (ERR_OK != result) {
rsp.segment_index = PROTO_645_FJ_INVALID_SEG_INDEX;
}
break;
}
default:
break;
}
*len = sizeof(rsp.segment_index);
os_mem_cpy(out_buf, &rsp, *len);
out:
return err_code;
}
static uint8_t iot_bsrm_branch_info_evt_req_handle(uint32_t di,
uint8_t *out_buf, uint8_t *remain_len, uint16_t *len_out)
{
uint8_t ret, i, err_code = PROTO_645_2007_ERR_OK;
uint8_t entry_len;
uint8_t *p_rsp = NULL;
uint32_t di_3_1, di_0;
iot_time_tm_t tm;
iot_bsrm_nv_info_t *nv_info;
proto_645_ext_br2_evt_cnt_ul_t *evt_cnt_rsp = NULL;
iot_bsrm_branch_evt_rec_entry_t *evt_buff;
proto_645_ext_br2_evt_rec_ul_t *evt_rec_rsp = NULL;
proto_645_ext_br2_evt_rec_entry_t *evt_rec_data = NULL;
proto_645_ext_br2_evt_rec_dx_ul_t *evt_rec_rsp_dx = NULL;
proto_645_ext_br2_evt_rec_entry_dx_t *evt_rec_data_dx = NULL;
di_3_1 = di & 0xFFFFFF00;
if (di_3_1 != PROTO_645_2007_EXT_DI_BR2_EVT_RECORD_ZJ &&
di_3_1 != PROTO_645_2007_EXT_DI_BR2_EVT_RECORD_DX) {
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
return err_code;
}
di_0 = di & 0xFF;
nv_info = (iot_bsrm_nv_info_t *)iot_bsrm_nv_get_section(
iot_bsrm_nv_id_info);
if (!di_0) {
evt_cnt_rsp = (proto_645_ext_br2_evt_cnt_ul_t *)(out_buf + *len_out);
proto_645_unsig_to_bcd(nv_info->evt_occur_cnt, PROTO_645_NUM_LEN,
evt_cnt_rsp->evt_cnt);
*len_out += sizeof(*evt_cnt_rsp);
*remain_len -= sizeof(*evt_cnt_rsp);
} else {
ret = iot_bsrm_evt_read(di_0, (uint8_t **)&evt_buff);
switch (di_3_1) {
case PROTO_645_2007_EXT_DI_BR2_EVT_RECORD_ZJ:
{
evt_rec_rsp =
(proto_645_ext_br2_evt_rec_ul_t *)(out_buf + *len_out);
*len_out += sizeof(*evt_rec_rsp);
*remain_len -= sizeof(*evt_rec_rsp);
if (ret != ERR_OK) {
evt_rec_rsp->id_len = 0;
evt_rec_rsp->signal_cnt = 0;
break;
}
evt_rec_rsp->signal_cnt = evt_buff->data_cnt;
for (i = 0; i < evt_rec_rsp->signal_cnt; i++) {
if (evt_buff->record_data[i].id_code_len >
evt_rec_rsp->id_len) {
evt_rec_rsp->id_len = evt_buff->record_data[i].id_code_len;
}
}
p_rsp = (uint8_t *)evt_rec_rsp->data;
for (i = 0; i < evt_rec_rsp->signal_cnt; i++) {
entry_len = evt_rec_rsp->id_len + sizeof(*evt_rec_data) +
PROTO_645_EXT_EVT_READ_RESERVE_LEN_ZJ;
if (*remain_len < entry_len) {
break;
}
evt_rec_data = (proto_645_ext_br2_evt_rec_entry_t *)p_rsp;
iot_bsrm_time_to_rtctime(evt_buff->record_data[i].ts, &tm);
evt_rec_data->signal_time.year = (uint8_t)(tm.tm_year - 2000);
evt_rec_data->signal_time.month = tm.tm_mon;
evt_rec_data->signal_time.day = tm.tm_mday;
evt_rec_data->signal_time.hour = tm.tm_hour;
evt_rec_data->signal_time.minute = tm.tm_min;
evt_rec_data->signal_time.second = tm.tm_sec;
evt_rec_data->phase = evt_buff->record_data[i].phase;
evt_rec_data->signal1_rssi =
evt_buff->record_data[i].signal1_rssi;
evt_rec_data->signal2_rssi =
evt_buff->record_data[i].signal2_rssi;
evt_rec_data->noise = evt_buff->record_data[i].noise;
p_rsp += sizeof(*evt_rec_data);
os_mem_cpy(p_rsp, &evt_buff->record_data[i].id_code,
evt_buff->record_data[i].id_code_len);
p_rsp += evt_buff->record_data[i].id_code_len;
os_mem_set(p_rsp, 0,
evt_rec_rsp->id_len - evt_buff->record_data[i].id_code_len);
p_rsp +=
evt_rec_rsp->id_len - evt_buff->record_data[i].id_code_len;
os_mem_set(p_rsp, 0, PROTO_645_EXT_EVT_READ_RESERVE_LEN_ZJ);
p_rsp += PROTO_645_EXT_EVT_READ_RESERVE_LEN_ZJ;
*len_out += entry_len;
*remain_len -= entry_len;
}
break;
}
case PROTO_645_2007_EXT_DI_BR2_EVT_RECORD_DX:
{
evt_rec_rsp_dx =
(proto_645_ext_br2_evt_rec_dx_ul_t *)(out_buf + *len_out);
*len_out += sizeof(*evt_rec_rsp_dx);
*remain_len -= sizeof(*evt_rec_rsp_dx);
if (ret != ERR_OK) {
evt_rec_rsp->id_len = 0;
evt_rec_rsp->signal_cnt = 0;
break;
}
evt_rec_rsp_dx->signal_cnt = evt_buff->data_cnt;
evt_rec_data_dx = evt_rec_rsp_dx->data;
for (i = 0; i < evt_rec_rsp_dx->signal_cnt; i++) {
entry_len = sizeof(*evt_rec_data_dx);
if (*remain_len < entry_len) {
break;
}
iot_bsrm_time_to_rtctime(evt_buff->record_data[i].ts, &tm);
evt_rec_data_dx->signal_time.year =
(uint8_t)(tm.tm_year - 2000);
evt_rec_data_dx->signal_time.month = tm.tm_mon;
evt_rec_data_dx->signal_time.day = tm.tm_mday;
evt_rec_data_dx->signal_time.hour = tm.tm_hour;
evt_rec_data_dx->signal_time.minute = tm.tm_min;
evt_rec_data_dx->signal_time.second = tm.tm_sec;
evt_rec_data_dx->phase = evt_buff->record_data[i].phase;
evt_rec_data_dx->signal1_rssi =
evt_buff->record_data[i].signal1_rssi;
evt_rec_data_dx->signal2_rssi =
evt_buff->record_data[i].signal2_rssi;
evt_rec_data_dx->signal_fund_wave = 0;
evt_rec_data_dx->noise = evt_buff->record_data[i].noise;
os_mem_cpy(evt_rec_data_dx->id_code,
&evt_buff->record_data[i].id_code,
sizeof(evt_rec_data_dx->id_code));
evt_rec_data_dx++;
*len_out += entry_len;
*remain_len -= entry_len;
}
break;
}
default:
break;
}
}
return err_code;
}
static uint32_t iot_bsrm_handle_upgrade_query_bitmap(uint8_t *out_buf,
uint8_t *len)
{
iot_bsrm_upgrade_info_t query_info = { 0 };
uint16_t max_array_index;
uint16_t bitmap_size;
uint16_t start_array_index;
uint32_t query_bitmap_cbs;
uint32_t bitmap_cbs = 0;
uint8_t recvdone = 0;
proto_645_fj_query_file_ul_t *rsp = (proto_645_fj_query_file_ul_t *)out_buf;
uint8_t *bitmap = rsp->array_bitmap;
os_mem_set(bitmap, 0, sizeof(rsp->array_bitmap));
iot_bsrm_query_upgrade_info(&query_info);
if (query_info.state <= IOT_BSRM_UPGRADE_ST_IDLE) {
/* recv done */
start_array_index = 0;
recvdone = 1;
goto out;
}
/* upgrade file segment bitmap size */
bitmap_size = (uint16_t)((query_info.block_cnt + 7) >> 3);
/* upgrade file segment bitmap array size */
max_array_index = (PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN - 1 + bitmap_size) /
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN;
for (start_array_index = 0; start_array_index < max_array_index - 1;
start_array_index++) {
bitmap_size = (uint16_t)iot_bsrm_upgrade_query_bitmap_info(bitmap,
start_array_index * PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN,
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
query_bitmap_cbs = iot_bitmap_cbs(bitmap, bitmap_size);
if (query_bitmap_cbs !=
(PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN << 3)) {
/* not recv done */
recvdone = 0;
goto out;
}
bitmap_cbs += query_bitmap_cbs;
}
bitmap_size = (uint16_t)iot_bsrm_upgrade_query_bitmap_info(bitmap,
start_array_index * PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN,
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
query_bitmap_cbs = iot_bitmap_cbs(bitmap, bitmap_size);
bitmap_cbs += query_bitmap_cbs;
if (bitmap_cbs >= query_info.block_cnt) {
/* recv done */
recvdone = 1;
} else {
/* not recv done */
recvdone = 0;
}
out:
if (recvdone) {
os_mem_set(bitmap, 0 , PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
} else {
iot_bitmap_reverse(bitmap, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
}
rsp->array_index = start_array_index;
*len = sizeof(*rsp);
return ERR_OK;
}
static uint32_t iot_bsrm_get_ct_coeff()
{
iot_bsrm_nv_param_t *param = \
(iot_bsrm_nv_param_t *)iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
if ((param->i_coeff == 0xFFFFFFFF) ||
(param->i_coeff == 0)) {
param->i_coeff = IOT_BSRM_BRANCH_BASE_COEFF_VAL;
}
return param->i_coeff;
}
uint32_t iot_bsrm_set_pm_upgrade_guard_code(uint16_t guard_code)
{
uint32_t ret = ERR_FAIL;
iot_bsrm_nv_param_t *param = (iot_bsrm_nv_param_t *)
iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
if (guard_code != param->upgrade_pm_guard_code) {
param->upgrade_pm_guard_code = guard_code;
iot_bsrm_nv_update_section(iot_bsrm_nv_id_param);
ret = ERR_OK;
}
iot_bsrm_printf("%s flag: %d \n", __FUNCTION__,
param->upgrade_pm_guard_code);
return ret;
}
uint16_t iot_bsrm_get_pm_upgrade_guard_code()
{
iot_bsrm_nv_param_t *param = (iot_bsrm_nv_param_t *)\
iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
iot_bsrm_printf("%s upgrade pm flag: %d \n", __FUNCTION__,
param->upgrade_pm_guard_code);
return param->upgrade_pm_guard_code;
}
static void iot_bsrm_load_nv(void)
{
uint32_t tmp_coeff = 0;
hw_topo_ratio_coeff_t coeff = { 0 };
uint8_t i;
/* set the current ratio coefficient to topo module */
tmp_coeff = iot_bsrm_get_ct_coeff();
if (tmp_coeff) {
for (i = 0; i < IOT_PLC_PHASE_CNT; i++) {
coeff.i_ratio_coeff[i] = tmp_coeff;
}
iot_plc_hw_topo_ratio_cfg(&coeff);
}
}
static void iot_bsrm_set_ct_coeff(uint32_t i_coeff)
{
uint8_t i;
hw_topo_ratio_coeff_t coeff = { 0 };
iot_bsrm_nv_param_t *param;
param = (iot_bsrm_nv_param_t *)\
iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
if (i_coeff &&
param->i_coeff != i_coeff) {
param->i_coeff = i_coeff;
for (i = 0; i < IOT_PLC_PHASE_CNT; i++) {
coeff.i_ratio_coeff[i] = param->i_coeff;
}
iot_plc_hw_topo_ratio_cfg(&coeff);
iot_bsrm_nv_update_section(iot_bsrm_nv_id_param);
iot_bsrm_printf("%s %lu\n", __FUNCTION__, i_coeff);
}
}
static void iot_bsrm_set_br_recv_param(iot_bsrm_br_param_t *br_param)
{
uint8_t reason = 0;
hw_topo_rcv_cfg_t cfg = { 0 };
iot_bsrm_nv_param_t *nv_param = (iot_bsrm_nv_param_t *)
iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
if (!os_mem_cmp(&nv_param->br_param, br_param, sizeof(*br_param))) {
goto out;
}
if (!br_param->fc) {
reason = 1;
goto out;
}
if (!br_param->chara_bit_dur) {
reason = 2;
goto out;
}
if (br_param->id_code_len > IOT_BSRM_BRANCH_ID_CODE_MAX) {
reason = 3;
goto out;
}
if (br_param->id_code_len) {
os_mem_cpy(&nv_param->br_param, br_param, sizeof(*br_param));
iot_bsrm_nv_update_section(iot_bsrm_nv_id_param);
}
out:
if (reason) {
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
} else {
cfg.phase = IOT_PLC_PHASE_ALL;
cfg.fc_valid = br_param->fc ? 1 : 0;
cfg.fc = br_param->fc;
cfg.chara_bit_dur = br_param->chara_bit_dur;
cfg.dur_valid = br_param->chara_bit_dur ? 1 : 0;
cfg.data_len = min(br_param->id_code_len,
IOT_HW_TOPO_MAX_NUMBER_OF_CODES);
os_mem_cpy(cfg.data, br_param->id_code, cfg.data_len);
iot_plc_hw_topo_rcv_cfg(&cfg);
iot_bsrm_printf("%s fc:%lu Hz, bit_dur:%lu ms, ", __FUNCTION__,
br_param->fc, br_param->chara_bit_dur);
iot_bsrm_data_print("code", br_param->id_code, cfg.data_len);
}
}
static void iot_bsrm_br_rec_clear(void)
{
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_INTERNAL,
IOT_BSRM_MSG_ID_INTERNAL_BR_REC_CLEAR, IOT_BSRM_MSG_QUEUE_LP, NULL,
0);
}
static uint8_t iot_bsrm_proto_645_r_extend_data_hander(uint8_t *in_data,
uint8_t in_len, uint8_t *out_buf, uint8_t *len_out)
{
proto_645_ext_bsrm_trans_cmd_t *bsrm_ext_cmd;
proto_645_ext_ct_coeff_t *i_coeff;
uint8_t err_code = PROTO_645_2007_ERR_OTHER;
if (in_len < sizeof(*bsrm_ext_cmd)) {
goto out;
}
in_len -= sizeof(*bsrm_ext_cmd);
bsrm_ext_cmd = (proto_645_ext_bsrm_trans_cmd_t *)in_data;
switch (bsrm_ext_cmd->fn) {
case PROTO_645_EXT_BSRM_TANS_CMD_FN_W_CT_COEFF:
{
if (in_len < sizeof(*i_coeff)) {
break;
}
i_coeff = (proto_645_ext_ct_coeff_t *)bsrm_ext_cmd->data;
iot_bsrm_set_ct_coeff(i_coeff->coeff);
*len_out = 0;
err_code = PROTO_645_2007_ERR_OK;
break;
}
case PROTO_645_EXT_BSRM_TANS_CMD_FN_R_CT_COEFF:
{
proto_645_2007_di_to_byte(PROTO_645_EXT_BSRM_DI_TANS_CMD, out_buf);
*len_out = PROTO_645_2007_DI_LEN;
bsrm_ext_cmd =
(proto_645_ext_bsrm_trans_cmd_t *)(out_buf + PROTO_645_2007_DI_LEN);
bsrm_ext_cmd->fn = PROTO_645_EXT_BSRM_TANS_CMD_FN_R_CT_COEFF;
i_coeff = (proto_645_ext_ct_coeff_t *)bsrm_ext_cmd->data;
i_coeff->coeff = iot_bsrm_get_ct_coeff();
*len_out += sizeof(*bsrm_ext_cmd) + sizeof(*i_coeff);
err_code = PROTO_645_2007_ERR_OK;
break;
}
default:
break;
}
out:
return err_code;
}
static uint8_t iot_bsrm_plc_phase_to_br2_phase(uint8_t plc_phase)
{
uint8_t br2_phase = IOT_BSRM_BR2_PHASE_UNKNOWN;
switch (plc_phase) {
case IOT_PLC_PHASE_ALL:
{
br2_phase = IOT_BSRM_BR2_PHASE_ALL;
break;
}
case IOT_PLC_PHASE_A:
{
br2_phase = IOT_BSRM_BR2_PHASE_A;
break;
}
case IOT_PLC_PHASE_B:
{
br2_phase = IOT_BSRM_BR2_PHASE_B;
break;
}
case IOT_PLC_PHASE_C:
{
br2_phase = IOT_BSRM_BR2_PHASE_C;
break;
}
default:
break;
}
return br2_phase;
}
static uint8_t iot_bsrm_proto_645_r_data_hander(uint8_t *in_data,
uint8_t in_len, uint8_t *out_buf, uint8_t *len_out)
{
uint32_t di;
uint8_t err_code = PROTO_645_2007_ERR_OK;
iot_time_tm_t tm;
proto_645_time_hms_t *t_hms;
proto_645_time_ymd_t *t_ymd;
proto_645_07_time_t *t_all;
proto_645_ext_read_ver_rsp_t *ver_info;
uint16_t len = 0;
uint8_t ret;
uint32_t ts;
uint8_t read_cnt;
uint8_t i;
iot_pkt_t *read_result = NULL;
uint16_t total_cnt = 0;
uint8_t remain_len = *len_out, entry_len;
uint8_t *p_rsp = NULL;
uint8_t tmp_out_len = 0;
iot_bsrm_branch_info_entry_t *data;
proto_645_ext_br2_recv_rec_dl_t *read_info;
proto_645_ext_br2_recv_rec_entry_t *result = NULL;
proto_645_ext_br2_recv_rec_entry_zj_head_t *result2 = NULL;
proto_645_ext_br2_recv_rec_ul_t *rsp = NULL;
proto_645_ext_br2_recv_rec_ul_zj_t *rsp2 = NULL;
proto_645_ext_br2_recv_rec_dl_xiongan_t *read_info2;
proto_645_ext_br2_recv_rec_ul_xiongan_t *rsp3 = NULL;
proto_645_ext_br2_recv_rec_entry_xiongan_t *result3 = NULL;
proto_645_ext_ct_coeff_t *i_coeff;
int32_t energy;
if (in_len < PROTO_645_2007_DI_LEN) {
err_code = PROTO_645_2007_ERR_OTHER;
goto out;
}
in_len -= PROTO_645_2007_DI_LEN;
di = proto_645_2007_byte_to_di(in_data);
proto_645_2007_di_to_byte(di, out_buf);
len += PROTO_645_2007_DI_LEN;
remain_len -= PROTO_645_2007_DI_LEN;
switch (di) {
case PROTO_645_2007_DI_TIME_YMD:
{
iot_rtc_get(&tm);
t_ymd = (proto_645_time_ymd_t *)(out_buf + len);
t_ymd->week = iot_bsrm_zeller_calc_week(&tm);
t_ymd->day = iot_byte_to_bcd(tm.tm_mday);
t_ymd->month = iot_byte_to_bcd(tm.tm_mon);
t_ymd->year = iot_byte_to_bcd((uint8_t)(tm.tm_year - 2000));
len += sizeof(*t_ymd);
break;
}
case PROTO_645_2007_DI_TIME_HMS:
{
iot_rtc_get(&tm);
t_hms = (proto_645_time_hms_t *)(out_buf + len);
t_hms->second = iot_byte_to_bcd(tm.tm_sec);
t_hms->minute = iot_byte_to_bcd(tm.tm_min);
t_hms->hour = iot_byte_to_bcd(tm.tm_hour);
len += sizeof(*t_hms);
break;
}
case PROTO_645_2007_DI_TIME:
{
iot_rtc_get(&tm);
t_all = (proto_645_07_time_t *)(out_buf + len);
t_all->week = iot_bsrm_zeller_calc_week(&tm);;
t_all->day = iot_byte_to_bcd(tm.tm_mday);
t_all->month = iot_byte_to_bcd(tm.tm_mon);
t_all->year = iot_byte_to_bcd((uint8_t)(tm.tm_year - 2000));
t_all->second = iot_byte_to_bcd(tm.tm_sec);
t_all->minute = iot_byte_to_bcd(tm.tm_min);
t_all->hour = iot_byte_to_bcd(tm.tm_hour);
len += sizeof(*t_all);
break;
}
case PROTO_645_2007_DI_R_ADDR:
{
iot_mac_addr_cpy(out_buf + len, p_bsrm_glb->addr);
len += IOT_MAC_ADDR_LEN;
break;
}
case PROTO_645_FJ_DI_UPGRADE_SEND_FILE:
{
err_code = iot_bsrm_handle_upgrade(in_data + PROTO_645_2007_DI_LEN,
in_len - PROTO_645_2007_DI_LEN, out_buf + len, &tmp_out_len);
len += tmp_out_len;
break;
}
case PROTO_645_FJ_DI_UPGRADE_REQ_FILE:
{
iot_bsrm_handle_upgrade_query_bitmap(out_buf + len, &tmp_out_len);
len += tmp_out_len;
break;
}
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD:
{
if (in_len < sizeof(*read_info)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
rsp = (proto_645_ext_br2_recv_rec_ul_t *)(out_buf + len);
read_info = (proto_645_ext_br2_recv_rec_dl_t *)(in_data +
PROTO_645_2007_DI_LEN);
tm.tm_year = read_info->start_time.year + 2000;
tm.tm_mon = read_info->start_time.month;
tm.tm_mday = read_info->start_time.day;
tm.tm_hour = read_info->start_time.hour;
tm.tm_min = read_info->start_time.minute;
tm.tm_sec = read_info->start_time.second;
ts = iot_bsrm_rtctime_to_time(&tm);
read_cnt = read_info->cnt;
iot_bsrm_printf("read info time %lu-%lu-%lu %lu:%lu:%lu, "
"recv cnt = %lu, recv idx = %lu DI:%08x \n", tm.tm_year, tm.tm_mon,
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
read_cnt, read_info->start_index, di);
ret = iot_bsrm_info_rec_read(&ts, &total_cnt, &read_cnt,
&read_result, read_info->start_index);
iot_bsrm_printf("record info total_cnt = %lu, read_cnt = %lu\n",
total_cnt, read_cnt);
data = (iot_bsrm_branch_info_entry_t *)iot_pkt_data(read_result);
rsp->total_cnt = total_cnt;
rsp->count = 0;
rsp->start_index = read_info->start_index;
iot_bsrm_time_to_rtctime(ts, &tm);
rsp->start_time.year = (uint8_t)(tm.tm_year - 2000);
rsp->start_time.month = tm.tm_mon;
rsp->start_time.day = tm.tm_mday;
rsp->start_time.hour = tm.tm_hour;
rsp->start_time.minute = tm.tm_min;
rsp->start_time.second = tm.tm_sec;
len += sizeof(*rsp);
if (ret != ERR_OK) {
break;
}
remain_len -= sizeof(*rsp);
result = rsp ->result;
for (i = 0; i < read_cnt; i++) {
if (remain_len < sizeof(*result)) {
break;
}
iot_bsrm_time_to_rtctime(data[i].ts, &tm);
result[i].signal_time.year = (uint8_t)(tm.tm_year - 2000);
result[i].signal_time.month = tm.tm_mon;
result[i].signal_time.day = tm.tm_mday;
result[i].signal_time.hour = tm.tm_hour;
result[i].signal_time.minute = tm.tm_min;
result[i].signal_time.second = tm.tm_sec;
result[i].is_vaild = data[i].is_vaild;
result[i].phase = data[i].phase;
result[i].signal1_rssi = data[i].signal1_rssi;
result[i].signal2_rssi = data[i].signal2_rssi;
result[i].base_rssi = data[i].base_rssi;
result[i].noise = data[i].noise;
len += sizeof(*result);
remain_len -= sizeof(*result);
rsp->count += 1;
}
iot_pkt_free(read_result);
break;
}
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_ZJ:
{
if (in_len < sizeof(*read_info)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
rsp2 = (proto_645_ext_br2_recv_rec_ul_zj_t *)(out_buf + len);
read_info = (proto_645_ext_br2_recv_rec_dl_t *)(in_data +
PROTO_645_2007_DI_LEN);
tm.tm_year = read_info->start_time.year + 2000;
tm.tm_mon = read_info->start_time.month;
tm.tm_mday = read_info->start_time.day;
tm.tm_hour = read_info->start_time.hour;
tm.tm_min = read_info->start_time.minute;
tm.tm_sec = read_info->start_time.second;
ts = iot_bsrm_rtctime_to_time(&tm);
read_cnt = read_info->cnt;
iot_bsrm_printf("read info time %lu-%lu-%lu %lu:%lu:%lu, "
"recv cnt = %lu, recv idx = %lu DI:%08x \n", tm.tm_year, tm.tm_mon,
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
read_cnt, read_info->start_index, di);
ret = iot_bsrm_info_rec_read(&ts, &total_cnt, &read_cnt,
&read_result, read_info->start_index);
iot_bsrm_printf("record info total_cnt = %lu, read_cnt = %lu\n",
total_cnt, read_cnt);
data = (iot_bsrm_branch_info_entry_t *)iot_pkt_data(read_result);
rsp2->total_cnt = total_cnt;
rsp2->count = 0;
rsp2->start_index = read_info->start_index;
iot_bsrm_time_to_rtctime(ts, &tm);
rsp2->start_time.year = (uint8_t)(tm.tm_year - 2000);
rsp2->start_time.month = tm.tm_mon;
rsp2->start_time.day = tm.tm_mday;
rsp2->start_time.hour = tm.tm_hour;
rsp2->start_time.minute = tm.tm_min;
rsp2->start_time.second = tm.tm_sec;
rsp2->code_len = 0;
len += sizeof(*rsp2);
if (ret != ERR_OK) {
break;
}
for (i = 0; i < read_cnt; i++) {
if (data[i].id_code_len > rsp2->code_len) {
rsp2->code_len = data[i].id_code_len;
}
}
entry_len = rsp2->code_len + sizeof(*result2) +
sizeof(roto_645_ext_br2_recv_rec_entry_zj_tail_t);
remain_len -= sizeof(*rsp2);
p_rsp = rsp2 ->data;
for (i = 0; i < read_cnt; i++) {
if (remain_len < entry_len) {
break;
}
result2 = (proto_645_ext_br2_recv_rec_entry_zj_head_t *)p_rsp;
iot_bsrm_time_to_rtctime(data[i].ts, &tm);
result2->signal_time.year = (uint8_t)(tm.tm_year - 2000);
result2->signal_time.month = tm.tm_mon;
result2->signal_time.day = tm.tm_mday;
result2->signal_time.hour = tm.tm_hour;
result2->signal_time.minute = tm.tm_min;
result2->signal_time.second = tm.tm_sec;
result2->phase = data[i].phase;
result2->signal1_rssi = data[i].signal1_rssi;
result2->signal2_rssi = data[i].signal2_rssi;
result2->noise = data[i].noise;
p_rsp += sizeof(*result2);
os_mem_cpy(p_rsp, &data[i].id_code, data[i].id_code_len);
p_rsp += data[i].id_code_len;
os_mem_set(p_rsp, 0, rsp2->code_len - data[i].id_code_len);
p_rsp += (rsp2->code_len -data[i].id_code_len);
os_mem_set(p_rsp, 0,
sizeof(roto_645_ext_br2_recv_rec_entry_zj_tail_t));
p_rsp += sizeof(roto_645_ext_br2_recv_rec_entry_zj_tail_t);
len += entry_len;
remain_len -= entry_len;
rsp2->count++;
}
iot_pkt_free(read_result);
break;
}
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_XIONGAN:
{
if (in_len < sizeof(*read_info2)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
rsp3 = (proto_645_ext_br2_recv_rec_ul_xiongan_t *)(out_buf + len);
read_info2 = (proto_645_ext_br2_recv_rec_dl_xiongan_t *)(in_data +
PROTO_645_2007_DI_LEN);
tm.tm_year = 2000;
tm.tm_mon = 1;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
ts = iot_bsrm_rtctime_to_time(&tm);
read_cnt = min(read_info2->cnt, 10);
iot_bsrm_printf("read info time %lu-%lu-%lu %lu:%lu:%lu, "
"recv cnt = %lu, recv idx = %lu DI:%08x \n", tm.tm_year, tm.tm_mon,
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
read_cnt, read_info2->start_index, di);
ret = iot_bsrm_info_rec_read(&ts, &total_cnt, &read_cnt,
&read_result, read_info2->start_index);
iot_bsrm_printf("record info total_cnt = %lu, read_cnt = %lu\n",
total_cnt, total_cnt ? read_cnt : 0);
data = (iot_bsrm_branch_info_entry_t *)iot_pkt_data(read_result);
rsp3->total_cnt = total_cnt;
rsp3->count = 0;
len += sizeof(*rsp3);
if (ret != ERR_OK) {
break;
}
remain_len -= sizeof(*rsp3);
p_rsp = rsp3 ->data;
for (i = 0; i < read_cnt; i++) {
if (remain_len < sizeof(*result3)) {
break;
}
result3 = (proto_645_ext_br2_recv_rec_entry_xiongan_t *)p_rsp;
iot_bsrm_time_to_rtctime(data[i].ts, &tm);
proto_645_rtctime_to_YYMMDDhhmmss(&tm,
(uint8_t *)&result3->signal_time);
energy = (int32_t)((data[i].signal1_rssi +
data[i].signal2_rssi) * 1000);
proto_645_sig_to_bcd(energy , 4, result3->signal_rssi);
proto_645_sig_to_bcd((int32_t)(data[i].base_rssi * 1000),
4, result3->base_rssi);
proto_645_sig_to_bcd((int32_t)(data[i].noise * 1000),
4, result3->noise);
result3->phase = data[i].phase ? data[i].phase : 4;
p_rsp += sizeof(*result3);
len += sizeof(*result3);
remain_len -= sizeof(*result3);
rsp3->count++;
}
break;
}
case PROTO_645_2007_EXT_DI_READ_VER:
{
ver_info = (proto_645_ext_read_ver_rsp_t *)(out_buf + len);
proto_645_vendor_build_ver_info_base(ver_info);
len += sizeof(*ver_info);
break;
}
case PROTO_645_EXT_BSRM_DI_TANS_CMD:
{
/* reset di payload */
len -= PROTO_645_2007_DI_LEN;
err_code = iot_bsrm_proto_645_r_extend_data_hander(
in_data + PROTO_645_2007_DI_LEN, in_len - PROTO_645_2007_DI_LEN,
out_buf, &tmp_out_len);
len += tmp_out_len;
break;
}
case PROTO_645_2007_EXT_BRM_CURRENT_COEFF:
{
i_coeff = (proto_645_ext_ct_coeff_t *)(out_buf + len);
i_coeff->coeff = iot_bsrm_get_ct_coeff();
len += sizeof(*i_coeff);
break;
}
default:
{
err_code = iot_bsrm_branch_info_evt_req_handle(di, out_buf,
&remain_len, &len);
break;
}
}
*len_out = (uint8_t)len;
out:
return err_code;
}
static uint8_t iot_bsrm_proto_645_query_topo_data_hander(uint8_t *in_data,
uint8_t in_len, uint8_t *out_buf, uint8_t *len_out)
{
uint8_t err_code = PROTO_645_2007_ERR_OK;
uint32_t di;
proto_645_ext_br2_recv_rec_dl_hn_t *read_info;
iot_time_tm_t tm = { 0 };
uint32_t ts;
uint8_t read_cnt;
uint16_t total_cnt = 0;
iot_pkt_t *read_result = NULL;
uint32_t ret;
uint8_t remain_len = *len_out;
uint8_t len = 0;
iot_bsrm_branch_info_entry_t *rd_data;
proto_645_ext_br2_recv_rec_ul_hn_t *br_rec_rsp;
proto_645_ext_br2_recv_rec_entry_hn_t *br_rec_rsp_data;
if (in_len < PROTO_645_2007_DI_LEN) {
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
goto out;
}
di = proto_645_2007_byte_to_di(in_data);
switch (di) {
case PROTO_645_2007_EXT_DI_BR2_CLEAR_HN:
{
iot_bsrm_br_rec_clear();
break;
}
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_HN:
{
if (in_len < sizeof(*read_info)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
read_info = (proto_645_ext_br2_recv_rec_dl_hn_t *)(in_data +
PROTO_645_2007_DI_LEN);
if (read_info->start_index == 0) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
proto_645_2007_di_to_byte(di, out_buf);
len += PROTO_645_2007_DI_LEN;
remain_len -= PROTO_645_2007_DI_LEN;
br_rec_rsp = (proto_645_ext_br2_recv_rec_ul_hn_t *)(out_buf + len);
tm.tm_year = 2000;
tm.tm_mon = 1;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
ts = iot_bsrm_rtctime_to_time(&tm);
iot_bsrm_printf("read info start: %d, cnt: %d \n",
read_info->start_index, read_info->cnt);
read_cnt = read_info->cnt;
ret = iot_bsrm_info_rec_read(&ts, &total_cnt, &read_cnt,
&read_result, read_info->start_index - 1);
iot_bsrm_printf("record info total_cnt = %lu, read_cnt = %lu\n",
total_cnt, read_cnt);
rd_data = (iot_bsrm_branch_info_entry_t *)iot_pkt_data(read_result);
len += sizeof(*br_rec_rsp);
if (ret != ERR_OK) {
br_rec_rsp->count = 0;
break;
}
remain_len -= sizeof(*br_rec_rsp);
br_rec_rsp_data = br_rec_rsp ->data;
for (uint8_t i = 0; i < read_cnt; i++) {
if (remain_len < sizeof(*br_rec_rsp_data)) {
break;
}
iot_bsrm_time_to_rtctime(rd_data[i].ts, &tm);
br_rec_rsp_data->signal_time.year =
iot_byte_to_bcd((uint8_t)(tm.tm_year - 2000));
br_rec_rsp_data->signal_time.month = iot_byte_to_bcd(tm.tm_mon);
br_rec_rsp_data->signal_time.day = iot_byte_to_bcd(tm.tm_mday);
br_rec_rsp_data->signal_time.hour = iot_byte_to_bcd(tm.tm_hour);
br_rec_rsp_data->signal_time.minute = iot_byte_to_bcd(tm.tm_min);
br_rec_rsp_data->signal_time.second = iot_byte_to_bcd(tm.tm_sec);
switch (rd_data[i].phase) {
case IOT_PLC_PHASE_A:
{
br_rec_rsp_data->phase = 1;
break;
}
case IOT_PLC_PHASE_B:
{
br_rec_rsp_data->phase = 2;
break;
}
case IOT_PLC_PHASE_C:
{
br_rec_rsp_data->phase = 4;
break;
}
default:
IOT_ASSERT(0);
break;
}
uint32_t energy = (uint32_t)((rd_data[i].signal1_rssi +
rd_data[i].signal2_rssi) * 100);
proto_645_sig_to_bcd(energy, PROTO_645_EXT_BRANCH_ENERGY_BCD_LEN_HN,
br_rec_rsp_data->energy);
os_mem_cpy(br_rec_rsp_data->code, &rd_data[i].id_code,
PROTO_645_EXT_BRANCH_CODE_LEN_HN);
len += sizeof(*br_rec_rsp_data);
remain_len -= sizeof(*br_rec_rsp_data);
br_rec_rsp->count++;
br_rec_rsp_data++;
}
iot_pkt_free(read_result);
break;
}
default:
{
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
break;
}
}
*len_out = (uint8_t)len;
out:
return err_code;
}
static uint8_t iot_bsrm_proto_645_w_data_hander(uint8_t *in_data,
uint8_t in_len, uint8_t *out_buf, uint8_t *len_out)
{
uint8_t err_code = PROTO_645_2007_ERR_OK;
uint8_t req_data_len;
uint32_t di;
proto_645_ext_ct_coeff_t *i_coeff;
iot_bsrm_br_param_t br_param = { 0 };
proto_645_ext_br2_launch_zj_hdr_t *br_hdr;
proto_645_ext_br2_launch_zj_tail_t *br_tail;
proto_645_write_data_dest_t *write_data;
proto_645_time_hms_t *t_hms;
proto_645_time_ymd_t *t_ymd;
proto_645_corr_time_t *ct;
if (in_len < PROTO_645_2007_DI_LEN) {
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
goto out;
}
di = proto_645_2007_byte_to_di(in_data);
switch (di) {
case PROTO_645_2007_EXT_DI_BR2_LAUNCH_ZJ:
{
req_data_len = sizeof(*br_hdr) + PROTO_645_2007_DI_LEN +
sizeof(*br_tail);
if (in_len < req_data_len) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
br_hdr = (proto_645_ext_br2_launch_zj_hdr_t *)(in_data +
PROTO_645_2007_DI_LEN);
req_data_len += br_hdr->code_len;
if (in_len < req_data_len) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
br_tail = (proto_645_ext_br2_launch_zj_tail_t *)(br_hdr->code +
br_hdr->code_len);
br_param.fc = (br_hdr->freq[0]) | (br_hdr->freq[1] << 8) |
(br_hdr->freq[2] << 16);
br_param.chara_bit_dur = br_hdr->chara_bit_dur;
br_param.pulse_high_dur = br_tail->pulse_high_dur;
br_param.pulse_low_dur = br_tail->pulse_low_dur;
br_param.id_code_len = min(br_hdr->code_len,
IOT_BSRM_BRANCH_ID_CODE_MAX);
os_mem_cpy(br_param.id_code, br_hdr->code, br_param.id_code_len);
iot_bsrm_set_br_recv_param(&br_param);
*len_out = 0;
break;
}
case PROTO_645_2007_EXT_BRM_CURRENT_COEFF:
{
req_data_len = sizeof(*i_coeff) + PROTO_645_2007_DI_LEN;
if (in_len < req_data_len) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
i_coeff = (proto_645_ext_ct_coeff_t *)(in_data +
PROTO_645_2007_DI_LEN);
iot_bsrm_set_ct_coeff(i_coeff->coeff);
*len_out = 0;
break;
}
case PROTO_645_2007_DI_TIME:
{
if (p_bsrm_glb->session_mode != IOT_BSRM_SESSION_MODE_DEFAULT) {
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
break;
}
req_data_len = sizeof(*write_data) + sizeof(*ct);
if (in_len < req_data_len) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
write_data = (proto_645_write_data_dest_t *)in_data;
ct = (proto_645_corr_time_t *)(write_data->data);
p_bsrm_glb->correct_tm.tm_sec = iot_bcd_to_byte(ct->second);
p_bsrm_glb->correct_tm.tm_min = iot_bcd_to_byte(ct->minute);
p_bsrm_glb->correct_tm.tm_hour = iot_bcd_to_byte(ct->hour);
p_bsrm_glb->correct_tm.tm_mday = iot_bcd_to_byte(ct->day);
p_bsrm_glb->correct_tm.tm_mon = iot_bcd_to_byte(ct->month);
p_bsrm_glb->correct_tm.tm_year = iot_bcd_to_byte(ct->year) + 2000;
iot_bsrm_printf("correct time success\n");
iot_bsrm_set_correct_tm(1);
*len_out = 0;
break;
}
case PROTO_645_2007_DI_TIME_YMD:
{
if (p_bsrm_glb->session_mode != IOT_BSRM_SESSION_MODE_DEFAULT) {
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
break;
}
req_data_len = sizeof(*write_data) + sizeof(*t_ymd);
if (in_len < req_data_len) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
write_data = (proto_645_write_data_dest_t *)in_data;
t_ymd = (proto_645_time_ymd_t *)(write_data->data);
p_bsrm_glb->correct_tm.tm_mday = iot_bcd_to_byte(t_ymd->day);
p_bsrm_glb->correct_tm.tm_mon = iot_bcd_to_byte(t_ymd->month);
p_bsrm_glb->correct_tm.tm_year = iot_bcd_to_byte(t_ymd->year) +
2000;
iot_bsrm_printf("correct ymd success\n");
iot_bsrm_set_correct_tm(1);
*len_out = 0;
break;
}
case PROTO_645_2007_DI_TIME_HMS:
{
if (p_bsrm_glb->session_mode != IOT_BSRM_SESSION_MODE_DEFAULT) {
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
break;
}
req_data_len = sizeof(*write_data) + sizeof(*t_hms);
if (in_len < req_data_len) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
write_data = (proto_645_write_data_dest_t *)in_data;
t_hms = (proto_645_time_hms_t *)(write_data->data);
p_bsrm_glb->correct_tm.tm_hour = iot_bcd_to_byte(t_hms->hour);
p_bsrm_glb->correct_tm.tm_min = iot_bcd_to_byte(t_hms->minute);
p_bsrm_glb->correct_tm.tm_sec = iot_bcd_to_byte(t_hms->second);
iot_bsrm_printf("correct hms success\n");
iot_bsrm_set_correct_tm(1);
*len_out = 0;
break;
}
case PROTO_645_2007_EXT_DI_BR2_CLEAR_HN:
{
iot_bsrm_br_rec_clear();
*len_out = 0;
break;
}
default:
{
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
break;
}
}
out:
return err_code;
}
static uint8_t iot_bsrm_check_get_zc_phase(uint8_t index)
{
const uint8_t phase_buf[] = {GPIO_PA_ZC, GPIO_PB_ZC, GPIO_PC_ZC,
GPIO_PA_ZC_EXT, GPIO_PB_ZC_EXT, GPIO_PC_ZC_EXT};
if (index >= sizeof(phase_buf)) {
return GPIO_NO_VALID;
}
return phase_buf[index];
}
static void iot_bsrm_check_timeout_event()
{
iot_bsrm_check_event_ctrl_t *event_check = &p_bsrm_glb->check_crtl.event;
uint8_t event_gpio_num;
if (event_check->status != IOT_BSRM_CHECK_EVENT_STATUS_DOING) {
return;
}
event_check->times++;
if (event_check->times >= IOT_BSRM_EVENT_CHECK_TIMES) {
event_gpio_num = iot_board_get_gpio(GPIO_PLC_EVENT);
iot_gpio_close(event_gpio_num);
event_check->status = IOT_BSRM_CHECK_EVENT_STATUS_DONE;
}
}
static void iot_bsrm_check_timeout_handle()
{
iot_bsrm_check_zc_ctrl_t *check_ctrl = &p_bsrm_glb->check_crtl.zc_ctrl;
uint32_t temp, cost_time;
uint8_t index, zc_phase, tmp_gpio;
if (check_ctrl->status == IOT_BSRM_CHECK_ZC_STATUS_GOING) {
cost_time = (uint32_t)(os_boot_time32() - check_ctrl->start_ts);
if (cost_time > IOT_BSRM_CHECK_ZC_TIMEOUT) {
while (1) {
index = iot_bitmap_ffs_and_c(&check_ctrl->started_zc_bm,
sizeof(check_ctrl->started_zc_bm));
if (!index) {
break;
}
index--;
if (index >= 2 * IOT_PLC_PHASE_CNT) {
IOT_ASSERT(0);
break;
}
if (check_ctrl->period[index]) {
continue;
}
if (!check_ctrl->trig_cnt[index]) {
temp = 0;
} else {
temp = check_ctrl->total_time[index] /
check_ctrl->trig_cnt[index];
}
check_ctrl->period[index] = temp;
zc_phase = iot_bsrm_check_get_zc_phase(index);
tmp_gpio = iot_board_get_gpio(zc_phase);
iot_gpio_interrupt_enable(tmp_gpio, 0);
iot_bsrm_printf("%s index %d, time %lu, trig %lu, period %lu\n",
__FUNCTION__, index, check_ctrl->total_time[index],
check_ctrl->trig_cnt[index], temp);
};
check_ctrl->status = IOT_BSRM_CHECK_ZC_STATUS_DONE;
}
}
}
static void iot_bsrm_check_zc_gpio_handler(int arg)
{
uint32_t cur_counter;
uint8_t index, zc_phase, tmp_gpio;
iot_bsrm_check_zc_ctrl_t *check_ctrl = &p_bsrm_glb->check_crtl.zc_ctrl;
if (arg >= 2 * IOT_PLC_PHASE_CNT) {
IOT_ASSERT(0);
goto err;
}
index = arg;
zc_phase = iot_bsrm_check_get_zc_phase(index);
tmp_gpio = iot_board_get_gpio(zc_phase);
cur_counter = iot_gpio_get_trigger_ticks(tmp_gpio);
if (!(check_ctrl->started_zc_bm & (1 << index))) {
check_ctrl->started_zc_bm |= 1 << index;
goto out;
}
check_ctrl->total_time[index] += (uint32_t)(cur_counter -
check_ctrl->pre_tick[index]);
check_ctrl->trig_cnt[index]++;
out:
check_ctrl->pre_tick[index] = cur_counter;
err:
return;
}
static void iot_bsrm_check_zc_start(uint8_t zc_bm)
{
iot_bsrm_check_zc_ctrl_t *check_ctrl = &p_bsrm_glb->check_crtl.zc_ctrl;
uint8_t index, tmp_gpio, zc_phase;
uint8_t reason;
if (check_ctrl->status == IOT_BSRM_CHECK_ZC_STATUS_GOING) {
goto out;
}
os_mem_set(check_ctrl, 0, sizeof(*check_ctrl));
while (1) {
reason = 0;
index = iot_bitmap_ffs_and_c(&zc_bm, sizeof(zc_bm));
if (!index || index > 2 * IOT_PLC_PHASE_CNT) {
break;
}
index--;
zc_phase = iot_bsrm_check_get_zc_phase(index);
tmp_gpio = iot_board_get_gpio(zc_phase);
if (tmp_gpio == GPIO_NO_VALID) {
reason = 1;
goto next;
}
iot_gpio_close(tmp_gpio);
if (iot_gpio_open_as_interrupt(tmp_gpio)) {
reason = 2;
goto next;
}
if (iot_gpio_interrupt_config(tmp_gpio, GPIO_INT_EDGE_RAISING,
iot_bsrm_check_zc_gpio_handler, index,
GPIO_INT_FUNC_GET_TICKS)) {
reason = 3;
goto next;
}
check_ctrl->zc_bm |= 1 << index;
if (iot_gpio_interrupt_enable(tmp_gpio, 1)) {
reason = 4;
goto next;
}
next:
if (reason) {
iot_bsrm_printf("%s index %d, zc_phase:%d, zc_gpio:%d, reason %d\n",
__FUNCTION__, index, zc_phase, tmp_gpio, reason);
}
}
check_ctrl->status = IOT_BSRM_CHECK_ZC_STATUS_GOING;
check_ctrl->start_ts = os_boot_time32();
iot_bsrm_printf("%s zc_bm %02x\n", __FUNCTION__, check_ctrl->zc_bm);
out:
return;
}
static void iot_bsrm_check_zc_quary_data_fill(uint8_t zc_bm,
proto_645_ext_check_zc_data_t *zc_data)
{
iot_bsrm_check_zc_ctrl_t *check_ctrl = &p_bsrm_glb->check_crtl.zc_ctrl;
uint8_t index, temp_bm;
temp_bm = check_ctrl->zc_bm & zc_bm;
zc_data->zc_bm = temp_bm;
iot_bsrm_printf("%s check_bm %02x, req_bm %02x, rsp_bm%02x\n", __FUNCTION__,
check_ctrl->zc_bm, zc_bm, temp_bm);
while (1) {
index = iot_bitmap_ffs_and_c(&temp_bm, sizeof(temp_bm));
if (!index || index > 2 * IOT_PLC_PHASE_CNT) {
break;
}
index--;
zc_data->period[index] = check_ctrl->period[index];
}
}
static void iot_bsrm_evt_intr_func(int arg)
{
(void)arg;
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_INTERNAL,
IOT_BSRM_MSG_ID_INTERNAL_EVENT_INTERRUPT, IOT_BSRM_MSG_QUEUE_LP, NULL,
0);
return;
}
static uint32_t iot_bsrm_evt_gpio_intr_init()
{
uint32_t ret = ERR_FAIL;
uint8_t event_gpio_num = iot_board_get_gpio(GPIO_PLC_EVENT);
if (GPIO_NO_VALID == event_gpio_num) {
goto out;
}
iot_gpio_close(event_gpio_num);
if (iot_gpio_open_as_interrupt(event_gpio_num)) {
goto out;
}
if (iot_gpio_interrupt_config(event_gpio_num, GPIO_INT_EDGE_RAISING,
iot_bsrm_evt_intr_func, 0, GPIO_INT_FUNC_DISABLE_AUTOSTOP)) {
goto out;
}
iot_gpio_interrupt_enable(event_gpio_num, 1);
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_bsrm_check_event_start()
{
iot_bsrm_check_event_ctrl_t *event_check = &p_bsrm_glb->check_crtl.event;
uint32_t ret = ERR_OK;
if (event_check->status == IOT_BSRM_CHECK_EVENT_STATUS_DOING) {
goto out;
}
if (iot_bsrm_evt_gpio_intr_init() != ERR_OK) {
ret = ERR_FAIL;
goto out;
}
event_check->count = 0;
event_check->times = 0;
event_check->status = IOT_BSRM_CHECK_EVENT_STATUS_DOING;
out:
return ret;
}
static uint8_t iot_bsrm_proto_645_br_data_hander(uint8_t *in_data,
uint8_t in_len, uint8_t *out_buf, uint8_t *len_out)
{
uint32_t di;
proto_645_ext_i_ms_ul_t *rsp_i_ms;
proto_645_ext_check_zc_dl_t *req_check_zc;
proto_645_ext_check_zc_ul_t *rsp_check_zc;
proto_645_ext_bsrm_evt_check_dl_t *req_check_event;
proto_645_ext_bsrm_evt_check_ul_t *rsp_check_event;
iot_bsrm_check_ctrl_t *check_ctrl = &p_bsrm_glb->check_crtl;
uint8_t err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
if (in_len < PROTO_645_2007_DI_LEN) {
goto out;
}
in_len -= PROTO_645_2007_DI_LEN;
di = proto_645_2007_byte_to_di(in_data);
in_data += PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, out_buf);
*len_out = PROTO_645_2007_DI_LEN;
out_buf += PROTO_645_2007_DI_LEN;
switch (di) {
case PROTO_645_2007_EXT_DI_I_MS:
{
rsp_i_ms = (proto_645_ext_i_ms_ul_t *)out_buf;
*len_out += sizeof(*rsp_i_ms);
rsp_i_ms->ms_i[0] = iot_plc_hw_topo_rms2_get(IOT_PLC_PHASE_A);
rsp_i_ms->ms_i[1] = iot_plc_hw_topo_rms2_get(IOT_PLC_PHASE_B);
rsp_i_ms->ms_i[2] = iot_plc_hw_topo_rms2_get(IOT_PLC_PHASE_C);
err_code = PROTO_645_2007_ERR_OK;
break;
}
case PROTO_645_2007_EXT_DI_CHECK_ZC:
{
if (in_len < sizeof(*req_check_zc)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
err_code = PROTO_645_2007_ERR_OK;
req_check_zc = (proto_645_ext_check_zc_dl_t *)in_data;
rsp_check_zc = (proto_645_ext_check_zc_ul_t *)out_buf;
*len_out += sizeof(*rsp_check_zc);
rsp_check_zc->fn = req_check_zc->fn;
iot_bsrm_printf("%s fn %d, bm %02x\n", __FUNCTION__, req_check_zc->fn,
req_check_zc->zc_bm);
switch (req_check_zc->fn) {
case PROTO_645_EXT_CHECK_FN_REQ:
{
iot_bsrm_check_zc_start(req_check_zc->zc_bm);
break;
}
case PROTO_645_EXT_CHECK_FN_QUERY:
{
iot_bsrm_check_zc_quary_data_fill(req_check_zc->zc_bm,
(proto_645_ext_check_zc_data_t *)rsp_check_zc->data);
*len_out += sizeof(proto_645_ext_check_zc_data_t);
break;
}
default:
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
rsp_check_zc->status = check_ctrl->zc_ctrl.status;
break;
}
case PROTO_645_2007_EXT_DI_CHECK_EVENT_INTERRUPT:
{
if (in_len < sizeof(*req_check_event)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
err_code = PROTO_645_2007_ERR_OK;
req_check_event = (proto_645_ext_bsrm_evt_check_dl_t *)in_data;
rsp_check_event = (proto_645_ext_bsrm_evt_check_ul_t *)out_buf;
*len_out += sizeof(*rsp_check_event);
rsp_check_event->fn = req_check_event->fn;
rsp_check_event->count = 0;
switch (req_check_event->fn) {
case PROTO_645_EXT_CHECK_FN_REQ:
{
if (iot_bsrm_check_event_start() != ERR_OK) {
/* not support */
rsp_check_event->result = PROTO_645_EXT_CHECK_EVENT_NOSUPPORT;
} else {
/* fwd data */
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
}
break;
}
case PROTO_645_EXT_CHECK_FN_QUERY:
{
if (p_bsrm_glb->check_crtl.event.status ==
IOT_BSRM_CHECK_EVENT_STATUS_DONE) {
rsp_check_event->result = PROTO_645_EXT_CHECK_EVENT_SUCCESS;
rsp_check_event->count = p_bsrm_glb->check_crtl.event.count;
} else if (p_bsrm_glb->check_crtl.event.status ==
IOT_BSRM_CHECK_EVENT_STATUS_DOING) {
rsp_check_event->result = PROTO_645_EXT_CHECK_EVENT_RUNNING;
} else {
rsp_check_event->result = PROTO_645_EXT_CHECK_EVENT_FAIL;
}
break;
}
default:
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
break;
}
default:
break;
}
out:
return err_code;
}
static uint32_t iot_bsrm_handle_master_645_data(
proto_645_header_t *hdr_645)
{
uint8_t ret = ERR_FAIL;
uint8_t fn;
uint8_t err_code = 0;
uint8_t *out_buf;
uint8_t out_len;
uint8_t *out_ds = p_bsrm_glb->proto_buff;
uint8_t follow = PROTO_645_FOLLOW_INVALID;
uint32_t len = 0;
iot_pkt_t *rsp_pkt;
uint32_t di;
uint8_t bcast = 0;
proto_645_07_dingxin_address_t *new_addr;
if (iot_mac_addr_cmp(hdr_645->addr, proto_645_bcast_addr)) {
bcast = 1;
}
proto_645_sub33_handle(hdr_645->data, hdr_645->len);
os_mem_set(out_ds, 0, PROTO_645_MAX_PKT_LEN);
out_buf = out_ds + sizeof(*hdr_645);
out_len = PROTO_645_MAX_DATA_LEN;
fn = (uint8_t)hdr_645->control.fn;
di = proto_645_2007_byte_to_di(hdr_645->data);
switch (fn) {
case PROTO_645_2007_FN_BSRM_DX_WRITE_ADDR:
{
new_addr = (proto_645_07_dingxin_address_t *)hdr_645->data;
if (new_addr->ident == PROTO_645_2007_BSRM_DX_SET_ADDR_IDENT) {
iot_bsrm_check_renew_addr(new_addr->addr);
out_len = 0;
err_code = PROTO_645_2007_ERR_OK;
} else {
err_code = PROTO_645_2007_ERR_OTHER;
}
break;
}
case PROTO_645_2007_FN_READ_DATA:
{
err_code = iot_bsrm_proto_645_r_data_hander(hdr_645->data,
hdr_645->len, out_buf, &out_len);
if (bcast && (di == PROTO_645_FJ_DI_UPGRADE_SEND_FILE)) {
ret = ERR_OK;
goto out;
}
break;
}
case PROTO_645_2007_FN_WRITE_DATA:
{
err_code = iot_bsrm_proto_645_w_data_hander(hdr_645->data, hdr_645->len,
out_buf, &out_len);
break;
}
case PROTO_645_2007_FN_CORRECT_TIME:
{
/* synchro time from 645 correct time data */
proto_645_corr_time_t *ct = (proto_645_corr_time_t *)hdr_645->data;
p_bsrm_glb->correct_tm.tm_sec = iot_bcd_to_byte(ct->second);
p_bsrm_glb->correct_tm.tm_min = iot_bcd_to_byte(ct->minute);
p_bsrm_glb->correct_tm.tm_hour = iot_bcd_to_byte(ct->hour);
p_bsrm_glb->correct_tm.tm_mday = iot_bcd_to_byte(ct->day);
p_bsrm_glb->correct_tm.tm_mon = iot_bcd_to_byte(ct->month);
p_bsrm_glb->correct_tm.tm_year = iot_bcd_to_byte(ct->year) + 2000;
iot_bsrm_set_correct_tm(1);
ret = ERR_OK;
goto out;
}
default:
{
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
}
if (err_code) {
len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
p_bsrm_glb->addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_ABNORMAL,
follow, fn, PROTO_645_INVALID_DI, 1, &err_code);
} else {
len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
p_bsrm_glb->addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
follow, fn, PROTO_645_INVALID_DI, out_len, out_buf);
}
rsp_pkt = iot_pkt_alloc(len, IOT_BSRM_MID);
IOT_ASSERT(rsp_pkt);
os_mem_cpy(iot_pkt_put(rsp_pkt, len), out_ds, len);
iot_bsrm_uart_send(rsp_pkt);
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_bsrm_sg_check_698_req(proto_69845_app_req_resp_t *req_data)
{
(void)req_data;
uint8_t ret = ERR_OK;
if (p_bsrm_glb->session_mode == IOT_BSRM_SESSION_MODE_DEFAULT) {
goto out;
}
if (false == iot_board_support_topo_rx()) {
ret = ERR_FAIL;
}
out:
return ret;
}
static uint16_t iot_bsrm_698_br2_record_info_fill(uint8_t *resp_data,
uint16_t len_limit, uint8_t sn, uint8_t priority,
uint8_t first, uint16_t oi, uint8_t is_retry, uint8_t *is_frag)
{
uint32_t ret, ts, tmp_value;
uint16_t total_cnt = 0, i;
uint16_t fill_len = 0, uint_len;
uint8_t read_cnt = 0xff, *fill_data;
iot_pkt_t *read_result = NULL;
proto_69845_app_ele_data_t * else_data;
proto_69845_br2_record_info_uint_t *record_uint;
proto_69845_br2_code_id_t *code_id;
proto_69845_br2_ext_info_t *ext_info;
iot_bsrm_branch_info_entry_t *data = NULL;
proto_69845_app_get_resp_next_t *rsp_next;
proto_69845_app_get_resp_next_fail_t *rsp_next_fail;
proto_69845_app_get_resp_normal_t *rsp_nor;
proto_69845_app_result_normal_t *normal_resp;
iot_bsrm_br_rec_frag_ctrl_t *frag_ctrl = &p_bsrm_glb->br_rec_frag_ctrl;
uint8_t frag = 1, end_flag = 0, fill_cnt = 0;
iot_time_tm_t tm = { 0 }, end_tm = { 0 };
if (first) {
frag_ctrl->start_tm.tm_year = 2000;
frag_ctrl->start_tm.tm_mon = 1;
frag_ctrl->start_tm.tm_mday = 1;
frag_ctrl->start_tm.tm_hour = 0;
frag_ctrl->start_tm.tm_min = 0;
frag_ctrl->start_tm.tm_sec = 0;
} else if (!is_retry) {
if (frag_ctrl->start_up != 1) {
IOT_ASSERT(0);
}
frag_ctrl->start_tm = frag_ctrl->end_tm;
iot_rtc_delta_add(1, &frag_ctrl->start_tm);
}
ts = iot_bsrm_rtctime_to_time(&frag_ctrl->start_tm);
ret = iot_bsrm_info_rec_read(&ts, &total_cnt, &read_cnt,
&read_result, 0);
if (first) {
if (ret == ERR_OK && total_cnt > IOT_BSRM_BR_REC_MAX_RESP_CNT) {
/* use framing transmission */
frag_ctrl->seq = 1;
frag_ctrl->start_up = 1;
frag_ctrl->oi = oi;
} else {
/* if one frame of message can carry all records, it will respond in
* the format of "GetResponseNormal".
*/
fill_len = sizeof(*rsp_nor);
frag = 0;
rsp_nor = (proto_69845_app_get_resp_normal_t *)resp_data;
rsp_nor->piid_acd.sn = sn;
rsp_nor->piid_acd.priority = priority;
rsp_nor->piid_acd.acd = 0;
proto_69845_oi_to_byte(oi, (uint8_t*)&rsp_nor->oad.oi);
rsp_nor->oad.attribute_id = 2;
rsp_nor->oad.attribute_char = 0;
rsp_nor->oad.element_index = 0;
if (ret == ERR_OK) {
rsp_nor->result_type = PROTO_69845_APP_GET_RESULT_DATA;
fill_data = rsp_nor->result;
fill_cnt = total_cnt;
data = (iot_bsrm_branch_info_entry_t *)
iot_pkt_data(read_result);
goto fill_rec;
} else {
rsp_nor->result_type = PROTO_69845_APP_GET_RESULT_DATA;
else_data = (proto_69845_app_ele_data_t *)rsp_nor->result;
else_data->data_type = PROTO_69845_APP_DATA_ARRAY;
else_data->num_of_data = 0;
fill_len += sizeof(*else_data);
goto out;
}
}
}
rsp_next_fail = (proto_69845_app_get_resp_next_fail_t *)resp_data;
if (ret != ERR_OK) {
/* when an error occurs during frame division transmission, reply
* the error code and terminate the transmission.
*/
rsp_next_fail->piid_acd.sn = sn;
rsp_next_fail->piid_acd.priority = priority;
rsp_next_fail->end_flag = 1;
iot_uint16_to_bytes(frag_ctrl->seq, (uint8_t *)&rsp_next_fail->seq, 1);
rsp_next_fail->data_type = PROTO_69845_GET_RESP_NEXT_ERR;
rsp_next_fail->err_code = PROTO_69845_APP_DAR_OTHER;
fill_len = sizeof(*rsp_next_fail);
goto out;
}
len_limit -= sizeof(*rsp_next) + sizeof(*normal_resp) + sizeof(*else_data);
data = (iot_bsrm_branch_info_entry_t *)iot_pkt_data(read_result);
/* calculate 698 apud max response len */
for (i = 0; i < read_cnt &&
fill_cnt < IOT_BSRM_BR_REC_MAX_RESP_CNT; i++) {
uint_len = sizeof(*record_uint) + sizeof(*code_id) +
data[i].id_code_len + sizeof(*ext_info) + 1;
if (len_limit < uint_len) {
break;
}
fill_cnt++;
len_limit -= uint_len;
}
if (fill_cnt == total_cnt) {
end_flag = 1;
}
rsp_next = (proto_69845_app_get_resp_next_t *)resp_data;
rsp_next->piid_acd.sn = sn;
rsp_next->piid_acd.priority = priority;
rsp_next->end_flag = end_flag;
iot_uint16_to_bytes(frag_ctrl->seq, (uint8_t *)&rsp_next->seq, 1);
rsp_next->data_type = PROTO_69845_GET_RESP_NEXT_NORMAL;
rsp_next->num_of_data = 1;
fill_len += sizeof(*rsp_next);
normal_resp = (proto_69845_app_result_normal_t *)rsp_next->data;
proto_69845_oi_to_byte(frag_ctrl->oi, (uint8_t*)&normal_resp->oad.oi);
normal_resp->oad.attribute_id = 2;
normal_resp->oad.attribute_char = 0;
normal_resp->oad.element_index = 0;
normal_resp->get_result.result_type = PROTO_69845_APP_GET_RESULT_DATA;
fill_data = normal_resp->get_result.result;
fill_len += sizeof(*normal_resp);
fill_rec:
else_data = (proto_69845_app_ele_data_t *)fill_data;
else_data->data_type = PROTO_69845_APP_DATA_ARRAY;
else_data->num_of_data = fill_cnt;
fill_data += sizeof(*else_data);
fill_len += sizeof(*else_data);
for (i = 0; i < fill_cnt; i++) {
record_uint = (proto_69845_br2_record_info_uint_t *)fill_data;
record_uint->data0_type = PROTO_69845_APP_DATA_STRUCTURE;
record_uint->cnt = 7;
record_uint->data1_type = PROTO_69845_APP_DATA_TIME_S;
iot_bsrm_time_to_rtctime(data[i].ts, &tm);
end_tm = tm;
iot_uint16_to_bytes(tm.tm_year,
(uint8_t *)&record_uint->suc_time.year, 1);
record_uint->suc_time.month = tm.tm_mon;
record_uint->suc_time.day = tm.tm_mday;
record_uint->suc_time.hour = tm.tm_hour;
record_uint->suc_time.minute = tm.tm_min;
record_uint->suc_time.second = tm.tm_sec;
record_uint->data2_type = PROTO_69845_APP_DATA_ENUM;
record_uint->phase = iot_bsrm_plc_phase_to_br2_phase(data[i].phase);
record_uint->data3_type = PROTO_69845_APP_DATA_DOUBLE_LONG;
tmp_value = (uint32_t)(data[i].signal1_rssi * 1000);
iot_uint32_to_bytes(tmp_value, record_uint->signal1_rssi, 1);
record_uint->data4_type = PROTO_69845_APP_DATA_DOUBLE_LONG;
tmp_value = (uint32_t)(data[i].signal2_rssi * 1000);
iot_uint32_to_bytes(tmp_value, record_uint->signal2_rssi, 1);
record_uint->data5_type = PROTO_69845_APP_DATA_DOUBLE_LONG;
tmp_value = (uint32_t)(data[i].noise * 1000);
iot_uint32_to_bytes(tmp_value, record_uint->noise, 1);
fill_data += sizeof(*record_uint);
fill_len += sizeof(*record_uint);
code_id = (proto_69845_br2_code_id_t *)fill_data;
code_id->data_type = PROTO_69845_APP_DATA_BIT_STRING;
code_id->bit_len = data[i].id_code_len * 8;
fill_data += sizeof(*code_id);
fill_len += sizeof(*code_id);
os_mem_cpy(fill_data, data[i].id_code, data[i].id_code_len);
fill_data += data[i].id_code_len;
fill_len += data[i].id_code_len;
ext_info = (proto_69845_br2_ext_info_t *)fill_data;
ext_info->data_type = PROTO_69845_APP_DATA_OCTET_STRING;
ext_info->byte_len = 1;
ext_info->data[0] = 0;
fill_data += (sizeof(*ext_info) + 1);
fill_len += (sizeof(*ext_info) + 1);
}
if (frag) {
IOT_ASSERT(frag_ctrl->start_up == 1);
frag_ctrl->life_cd = IOT_BSRM_BR_REC_FRAG_WIN_DUR;
frag_ctrl->end_tm = end_tm;
}
out:
if (read_result) {
iot_pkt_free(read_result);
}
*is_frag = frag;
return fill_len;
}
static uint16_t iot_bsrm_69845_br2_launch_para_fill(uint8_t *result_type,
uint8_t *result, uint16_t len_limit)
{
uint8_t reason = 0;
uint16_t result_len;
uint32_t temp;
proto_69845_br2_launch_para_t *launch_para;
proto_69845_app_data_t *fc_data;
proto_69845_app_ele_data_t *ext_info;
iot_bsrm_nv_param_t *param =
(iot_bsrm_nv_param_t *)iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
iot_bsrm_br_param_t *br_param = &param->br_param;
result_len = sizeof(*launch_para) + br_param->id_code_len;
if (len_limit < result_len) {
reason = 1;
goto out;
}
*result_type = PROTO_69845_APP_GET_RESULT_DATA;
launch_para = (proto_69845_br2_launch_para_t *)result;
launch_para->type = PROTO_69845_APP_DATA_STRUCTURE;
launch_para->cnt = 6;
launch_para->data0_type = PROTO_69845_APP_DATA_LONG_UNSIGNED;
iot_uint16_to_bytes(br_param->chara_bit_dur,
(uint8_t *)&launch_para->chara_bit_dur, 1);
launch_para->data1_type = PROTO_69845_APP_DATA_LONG_UNSIGNED;
iot_uint16_to_bytes(br_param->pulse_high_dur,
(uint8_t *)&launch_para->pulse_high_dur, 1);
launch_para->data2_type = PROTO_69845_APP_DATA_LONG_UNSIGNED;
iot_uint16_to_bytes(br_param->pulse_low_dur,
(uint8_t *)&launch_para->pulse_low_dur, 1);
launch_para->data3_type = PROTO_69845_APP_DATA_BIT_STRING;
launch_para->bit_len.mub_flag = 0;
launch_para->bit_len.byte_num = br_param->id_code_len << 3;
os_mem_cpy(launch_para->code, br_param->id_code, br_param->id_code_len);
/* load hw tsfm mode encode frequncy, double-long-unsigned, unit: 0.01Hz */
if (len_limit < result_len + sizeof(*fc_data)) {
reason = 2;
goto out;
}
fc_data = (proto_69845_app_data_t *)(result + result_len);
fc_data->data_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
if (proto_69845_get_data_len(fc_data, len_limit - result_len, &temp)) {
reason = 3;
goto out;
}
result_len += temp;
iot_uint32_to_bytes(br_param->fc, fc_data->data, 1);
/* extend information */
if (len_limit < result_len + sizeof(*ext_info)) {
reason = 4;
goto out;
}
ext_info = (proto_69845_app_ele_data_t *)(result + result_len);
ext_info->data_type = PROTO_69845_APP_DATA_OCTET_STRING;
ext_info->num_of_data = 12;
if (proto_69845_get_data_len((proto_69845_app_data_t *)ext_info,
len_limit - result_len, &temp)) {
reason = 5;
goto out;
}
result_len += temp;
os_mem_set(ext_info->data, 0, 12);
out:
if (reason) {
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
result_len = 0;
}
return result_len;
}
iot_pkt_t *iot_bsrm_69845_get_normal_handle(uint8_t *data, uint32_t len)
{
uint16_t oi;
uint16_t total_len, head_len, apdu_len = 0, tail_len, apdu_limit_len;
uint16_t result_len = 0;
uint8_t reason = 0, is_frag = 0;
iot_pkt_t *resp_pkt = NULL;
uint8_t *resp_data;
addr_info_t addr_info = { 0 };
proto_69845_app_get_req_normal_t *req;
proto_69845_frame_head_info_t *hdr_698_resp;
proto_69845_app_req_resp_t *server_apdu;
proto_69845_app_get_resp_t *get_resp;
proto_69845_app_get_resp_normal_t *result_normal;
uint8_t fragment_type = PROTO_69845_APDU_WHOLE;
if (len < sizeof(*req)) {
reason = 1;
goto drop;
}
req = (proto_69845_app_get_req_normal_t *)data;
oi = proto_69845_byte_to_oi((uint8_t *)&req->oad.oi);
len -= sizeof(*req);
head_len = sizeof(*hdr_698_resp) + IOT_MAC_ADDR_LEN
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
apdu_limit_len = PROTO_69845_PREDICT_APDU_MAX_LEN;
tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN +
sizeof(proto_69845_tailer_t);
resp_pkt = iot_pkt_alloc(head_len + apdu_limit_len + tail_len,
IOT_SMART_GRID_MID);
if (!resp_pkt) {
reason = 2;
goto drop;
}
resp_data = iot_pkt_data(resp_pkt);
hdr_698_resp = (proto_69845_frame_head_info_t *)resp_data;
resp_data += head_len;
server_apdu = (proto_69845_app_req_resp_t *)resp_data;
apdu_len += sizeof(*server_apdu);
get_resp = (proto_69845_app_get_resp_t *)server_apdu->data;
apdu_len += sizeof(*get_resp);
switch (oi) {
case PROTO_69845_APP_OI_BR2_INFO:
case PROTO_69845_APP_OI_EXT_BR2_INFO:
{
apdu_limit_len -= apdu_len;
result_len = iot_bsrm_698_br2_record_info_fill(get_resp->data,
apdu_limit_len, req->piid.sn, req->piid.priority, 1, oi, 0,
&is_frag);
if (!result_len) {
reason = 3;
goto drop;
}
if (is_frag) {
fragment_type = PROTO_69845_APDU_PART;
}
break;
}
case PROTO_69845_APP_OI_EXT_BR2_LAUNCH:
case PROTO_69845_APP_OI_BR2_LAUNCH:
{
if (req->oad.attribute_id != 4) {
reason = 4;
goto drop;
}
result_normal = (proto_69845_app_get_resp_normal_t *)get_resp->data;
result_normal->oad = req->oad;
result_normal->piid_acd.sn = req->piid.sn;
result_normal->piid_acd.priority = req->piid.priority;
apdu_len += sizeof(*result_normal);
apdu_limit_len -= apdu_len;
result_len = iot_bsrm_69845_br2_launch_para_fill(
&result_normal->result_type, result_normal->result, apdu_limit_len);
if (!result_len) {
reason = 5;
goto drop;
}
break;
}
default:
reason = 6;
goto drop;
}
apdu_len += result_len;
total_len = head_len + apdu_len + tail_len;
resp_data += apdu_len;
iot_pkt_put(resp_pkt, total_len);
iot_mac_addr_cpy(addr_info.ser_info.addr, p_bsrm_glb->addr);
addr_info.ser_info.len = IOT_MAC_ADDR_LEN;
proto_69845_head_fill(hdr_698_resp, head_len, total_len, &addr_info,
PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
PROTO_69845_D_P_SERVER_RESPONSE);
server_apdu->type = PROTO_69845_S_APP_GET_RESP;
if (fragment_type == PROTO_69845_APDU_PART) {
get_resp->data_type = PROTO_69845_APP_GET_NEXT;
} else {
get_resp->data_type = PROTO_69845_APP_GET_NORMAL;
}
proto_69845_tail_fill_without_ts_fl(hdr_698_resp, resp_data, tail_len);
goto out;
drop:
if (resp_pkt) {
iot_pkt_free(resp_pkt);
resp_pkt = NULL;
}
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return resp_pkt;
}
iot_pkt_t *iot_bsrm_69845_get_next_handle(uint8_t *data, uint32_t len)
{
uint16_t total_len, head_len, apdu_len = 0, tail_len, apdu_limit_len;
uint16_t result_len = 0, next_seq, ack_seq;
uint8_t reason = 0, retry_flag = 0, fail_flag = 0;
iot_pkt_t *resp_pkt = NULL;
uint8_t *resp_data;
addr_info_t addr_info = { 0 };
proto_69845_app_get_req_next_t *req;
proto_69845_frame_head_info_t *hdr_698_resp;
proto_69845_app_req_resp_t *server_apdu;
proto_69845_app_get_resp_t *get_resp;
proto_69845_app_get_resp_next_fail_t *next_fail;
uint8_t is_frag;
iot_bsrm_br_rec_frag_ctrl_t *frag_ctrl = &p_bsrm_glb->br_rec_frag_ctrl;
if (len < sizeof(*req)) {
reason = 1;
goto drop;
}
if (frag_ctrl->start_up == 0) {
/* If the fragment transmission is not started, the message is
* discarded.
*/
reason = 2;
goto drop;
}
req = (proto_69845_app_get_req_next_t *)data;
len -= sizeof(*req);
ack_seq = iot_bytes_to_uint16((uint8_t *)&req->last_seq, 1);
next_seq = ack_seq + 1;
if (!next_seq) {
next_seq = 1;
}
if (ack_seq == frag_ctrl->seq) {
/* last response is succeed */
frag_ctrl->seq = next_seq;
} else if (next_seq == frag_ctrl->seq) {
/* last response is losted */
retry_flag = 1;
} else {
/* msg seq is unkown */
fail_flag = 1;
}
head_len = sizeof(*hdr_698_resp) + IOT_MAC_ADDR_LEN
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
apdu_limit_len = PROTO_69845_PREDICT_APDU_MAX_LEN;
tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN +
sizeof(proto_69845_tailer_t);
resp_pkt = iot_pkt_alloc(head_len + apdu_limit_len + tail_len,
IOT_SMART_GRID_MID);
if (!resp_pkt) {
reason = 3;
goto drop;
}
resp_data = iot_pkt_data(resp_pkt);
hdr_698_resp = (proto_69845_frame_head_info_t *)resp_data;
resp_data += head_len;
server_apdu = (proto_69845_app_req_resp_t *)resp_data;
apdu_len += sizeof(*server_apdu);
get_resp = (proto_69845_app_get_resp_t *)server_apdu->data;
apdu_len += sizeof(*get_resp);
apdu_limit_len -= apdu_len;
if (fail_flag) {
next_fail = (proto_69845_app_get_resp_next_fail_t *)get_resp->data;
next_fail->piid_acd.sn = req->piid.sn;
next_fail->piid_acd.priority = req->piid.priority;
next_fail->end_flag = 1;
iot_uint16_to_bytes(next_seq, (uint8_t *)&next_fail->seq, 1);
next_fail->data_type = PROTO_69845_GET_RESP_NEXT_ERR;
next_fail->err_code = PROTO_69845_APP_DAR_OTHER;
result_len = sizeof(*next_fail);
} else {
result_len = iot_bsrm_698_br2_record_info_fill(get_resp->data,
apdu_limit_len, req->piid.sn, req->piid.priority, 0, 0,
retry_flag, &is_frag);
}
if (!result_len) {
reason = 4;
goto drop;
}
apdu_len += result_len;
total_len = head_len + apdu_len + tail_len;
resp_data += apdu_len;
iot_pkt_put(resp_pkt, total_len);
iot_mac_addr_cpy(addr_info.ser_info.addr, p_bsrm_glb->addr);
addr_info.ser_info.len = IOT_MAC_ADDR_LEN;
proto_69845_head_fill(hdr_698_resp, head_len, total_len, &addr_info,
PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
PROTO_69845_D_P_SERVER_RESPONSE);
server_apdu->type = PROTO_69845_S_APP_GET_RESP;
get_resp->data_type = PROTO_69845_APP_GET_NEXT;
proto_69845_tail_fill_without_ts_fl(hdr_698_resp, resp_data, tail_len);
goto out;
drop:
if (resp_pkt) {
iot_pkt_free(resp_pkt);
resp_pkt = NULL;
}
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return resp_pkt;
}
static void iot_bsrm_br_rec_frag_ctrl_ageing(void)
{
iot_bsrm_br_rec_frag_ctrl_t *frag_ctrl = &p_bsrm_glb->br_rec_frag_ctrl;
if (frag_ctrl->start_up == 1) {
if (frag_ctrl->life_cd) {
frag_ctrl->life_cd--;
if (!frag_ctrl->life_cd) {
iot_printf("iot_bsrm_br_rec_frag_ctrl_ageing reach\n");
os_mem_set(frag_ctrl, 0, sizeof(*frag_ctrl));
}
} else {
IOT_ASSERT(0);
}
}
}
static iot_pkt_t *iot_bsrm_handle_698_get_req(uint8_t *apdu,
uint32_t len)
{
uint8_t reason = 0;
iot_pkt_t *resp_pkt = NULL;
uint8_t *data_ptr = apdu;
uint32_t data_len = len;
proto_69845_app_get_req_t *req;
if (len < sizeof(*req)) {
reason = 1;
goto out;
}
req = (proto_69845_app_get_req_t *)data_ptr;
data_ptr += sizeof(*req);
data_len -= sizeof(*req);
switch (req->data_type) {
case PROTO_69845_APP_GET_NORMAL:
{
resp_pkt = iot_bsrm_69845_get_normal_handle(data_ptr, data_len);
break;
}
case PROTO_69845_APP_GET_NEXT:
{
resp_pkt = iot_bsrm_69845_get_next_handle(data_ptr, data_len);
break;
}
default:
reason = 2;
break;
}
out:
if (reason) {
iot_bsrm_printf("%s err reason %d\n", __FUNCTION__, reason);
}
return resp_pkt;
}
static uint8_t iot_bsrm_69845_handle_br2_launch_para(
proto_69845_br2_launch_para_t *launch_para, uint32_t para_len)
{
uint8_t reason = 0, launch_code_len, *launch_code;
proto_69845_app_data_t *fc_data;
uint32_t len;
iot_bsrm_br_param_t br_param = { 0 };
if (!launch_para->bit_len.mub_flag) {
launch_code_len = launch_para->bit_len.byte_num / 8;
launch_code = launch_para->code;
} else {
reason = 1;
goto out;
}
/* load hw tsfm mode encode frequncy, double-long-unsigned, unit: 0.01Hz */
fc_data = (proto_69845_app_data_t *)(launch_para->code + launch_code_len);
para_len -= sizeof(*launch_para) + launch_code_len;
if (para_len < sizeof(*fc_data) ||
fc_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED ||
proto_69845_get_data_len(fc_data, para_len, &len)) {
reason = 2;
goto out;
}
br_param.fc = iot_bytes_to_uint32(fc_data->data, 1);
br_param.chara_bit_dur = iot_bytes_to_uint16(
(uint8_t *)&launch_para->chara_bit_dur ,1);
br_param.pulse_high_dur = iot_bytes_to_uint16(
(uint8_t *)&launch_para->pulse_high_dur, 1);
br_param.pulse_low_dur = iot_bytes_to_uint16(
(uint8_t *)&launch_para->pulse_low_dur, 1);
br_param.id_code_len = launch_code_len;
os_mem_cpy(br_param.id_code, launch_code, launch_code_len);
iot_bsrm_set_br_recv_param(&br_param);
out:
if (reason) {
iot_bsrm_printf("%s err reason %d\n", __FUNCTION__, reason);
return ERR_FAIL;
}
return ERR_OK;
}
static uint8_t iot_bsrm_69845_handle_br2_launch_req(proto_69845_app_omd_t *omd,
proto_69845_data_cache_desc_t *action_desc)
{
uint8_t ele_cnt, reason;
uint32_t ret, total_len, para_len;
proto_69845_app_ele_data_t *desc;
proto_69845_rpt_data_time_s_t *start_time;
proto_69845_br2_launch_para_t *launch_para;
if (omd->method_id != PROTO_OI_BR2_LAUNCH_METHOD_LAUNCH &&
omd->method_id != PROTO_OI_BR2_LAUNCH_METHOD_TIME_LAUNCH) {
reason = 1;
goto drop;
}
total_len = sizeof(*desc);
if (action_desc->len < total_len) {
reason = 2;
goto drop;
}
desc = (proto_69845_app_ele_data_t *)action_desc->data;
if (desc->data_type != PROTO_69845_APP_DATA_STRUCTURE) {
reason = 3;
goto drop;
}
if (omd->method_id == PROTO_OI_BR2_LAUNCH_METHOD_TIME_LAUNCH) {
ele_cnt = 2;
total_len = sizeof(*desc) + sizeof(*launch_para) + sizeof(*start_time);
} else {
ele_cnt = 6;
total_len = sizeof(*launch_para);
}
if (ele_cnt != desc->num_of_data || (action_desc->len < total_len)) {
reason = 4;
goto drop;
}
if (omd->method_id == PROTO_OI_BR2_LAUNCH_METHOD_TIME_LAUNCH) {
launch_para = (proto_69845_br2_launch_para_t *)&desc->data;
total_len = action_desc->len - sizeof(*desc);
ret = proto_69845_get_data_len((proto_69845_app_data_t *)launch_para,
total_len, &para_len);
if (ret) {
reason = 5;
goto drop;
}
start_time = (proto_69845_rpt_data_time_s_t *)(desc->data + para_len);
} else {
launch_para = (proto_69845_br2_launch_para_t *)action_desc->data;
start_time = NULL;
}
if (iot_bsrm_69845_handle_br2_launch_para(launch_para, para_len) != ERR_OK) {
reason = 6;
goto drop;
}
goto out;
drop:
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
return ERR_FAIL;
out:
return ERR_OK;
}
static iot_pkt_t *iot_bsrm_handle_698_action_normal_req(uint8_t *data,
uint32_t len)
{
uint16_t oi;
uint8_t reason = 0;
iot_pkt_t *resp_pkt = NULL;
addr_info_t addr_info = {0};
proto_69845_app_action_req_single_t *req;
proto_69845_data_cache_desc_t action_desc = {0};
if (len < sizeof(*req)) {
reason = 1;
goto drop;
}
req = (proto_69845_app_action_req_single_t*)data;
oi = proto_69845_byte_to_oi((uint8_t *)&req->omd.oi);
len -= sizeof(*req);
if (proto_69845_get_data_len(&req->data, len, &action_desc.len)) {
reason = 2;
goto drop;
}
if (len < action_desc.len) {
reason = 3;
goto drop;
}
action_desc.data = (uint8_t *)&req->data;
switch (oi) {
case PROTO_69845_APP_OI_BR2_INFO:
case PROTO_69845_APP_OI_EXT_BR2_INFO:
{
if (req->omd.method_id != PROTO_OI_BR2_REC_METHOD_CLEAR) {
reason = 4;
goto drop;
}
iot_bsrm_br_rec_clear();
break;
}
case PROTO_69845_APP_OI_EXT_BR2_LAUNCH:
case PROTO_69845_APP_OI_BR2_LAUNCH:
{
if (iot_bsrm_69845_handle_br2_launch_req(&req->omd, &action_desc) !=
ERR_OK) {
reason = 5;
goto drop;
}
break;
}
default:
goto drop;
}
addr_info.ser_info.type = PROTO_69845_SA_TYPE_SIG;
addr_info.ser_info.len = IOT_MAC_ADDR_LEN;
addr_info.ser_info.logical_addr = 0;
iot_mac_addr_cpy(addr_info.ser_info.addr, p_bsrm_glb->addr);
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
req->omd.oi = oi;
resp_pkt = proto_69845_action_single_ack(&addr_info, &req->piid, &req->omd,
PROTO_69845_APP_DAR_SUCCESS);
goto out;
drop:
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return resp_pkt;
}
static iot_pkt_t *iot_bsrm_handle_698_action_req(uint8_t *data,
uint32_t len)
{
uint8_t *data_ptr = data;
uint32_t data_len = len;
iot_pkt_t *resp_pkt = NULL;
proto_69845_app_action_req_t *req;
if (len < sizeof(*req)) {
goto out;
}
req = (proto_69845_app_action_req_t*)data;
data_ptr += sizeof(*req);
data_len -= sizeof(*req);
switch (req->data_type) {
case PROTO_69845_APP_ACTION_NORMAL:
{
resp_pkt = iot_bsrm_handle_698_action_normal_req(data_ptr, data_len);
break;
}
default:
break;
}
out:
return resp_pkt;
}
iot_pkt_t *iot_bsrm_69845_set_normal_handle(uint8_t *data, uint32_t len)
{
uint16_t oi;
uint8_t reason = 0;
iot_pkt_t *resp_pkt = NULL;
addr_info_t addr_info = {0};
proto_69845_app_set_req_normal_t *req;
proto_69845_data_cache_desc_t data_desc = {0};
proto_69845_br2_launch_para_t *launch_para;
if (len < sizeof(*req)) {
reason = 1;
goto drop;
}
req = (proto_69845_app_set_req_normal_t *)data;
oi = proto_69845_byte_to_oi((uint8_t *)&req->oad.oi);
len -= sizeof(*req);
if (proto_69845_get_data_len(&req->data, len, &data_desc.len)) {
reason = 2;
goto drop;
}
if (len < data_desc.len) {
reason = 3;
goto drop;
}
data_desc.data = (uint8_t *)&req->data;
switch (oi) {
case PROTO_69845_APP_OI_EXT_BR2_LAUNCH:
case PROTO_69845_APP_OI_BR2_LAUNCH:
{
if (req->oad.attribute_id != 4) {
reason = 4;
goto drop;
}
launch_para = (proto_69845_br2_launch_para_t *)data_desc.data;
if (iot_bsrm_69845_handle_br2_launch_para(launch_para, data_desc.len) !=
ERR_OK) {
reason = 5;
goto drop;
}
break;
}
default:
goto out;
}
addr_info.ser_info.type = PROTO_69845_SA_TYPE_SIG;
addr_info.ser_info.len = IOT_MAC_ADDR_LEN;
addr_info.ser_info.logical_addr = 0;
iot_mac_addr_cpy(addr_info.ser_info.addr, p_bsrm_glb->addr);
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
req->oad.oi = oi;
resp_pkt = proto_69845_set_normal_ack(&addr_info, &req->piid, &req->oad,
PROTO_69845_APP_DAR_SUCCESS);
goto out;
drop:
iot_bsrm_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return resp_pkt;
}
static iot_pkt_t *iot_bsrm_handle_69845_set_req(uint8_t *data, uint32_t len)
{
iot_pkt_t *pkt = NULL;
uint8_t *data_ptr = data;
uint32_t data_len = len;
proto_69845_app_set_req_t *req;
if (len < sizeof(*req)) {
goto out;
}
req = (proto_69845_app_set_req_t *)data;
data_ptr += sizeof(*req);
data_len -= sizeof(*req);
switch (req->data_type) {
case PROTO_69845_APP_SET_NORMAL:
{
pkt = iot_bsrm_69845_set_normal_handle(data_ptr, data_len);
break;
}
default:
break;
}
out:
return pkt;
}
static iot_pkt_t *iot_bsrm_handle_698_req(
uint8_t *data, uint32_t len, uint8_t *fwd)
{
uint8_t *data_ptr = data, reason = 0, sub33;
uint32_t data_len = len;
proto_69845_frame_head_info_t *hdr = NULL;
proto_69845_app_req_resp_t *req;
apdu_info_t apdu_desc = {0};
iot_pkt_t *resp_pkt = NULL;
addr_info_t addr_info = {0};
(void)fwd;
if (proto_69845_parse(&data_ptr, &data_len, &hdr, &apdu_desc)) {
reason = 1;
goto out;
}
sub33 = 1;
proto_69845_get_addr_info(hdr, &addr_info);
if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_GROUP
|| addr_info.ser_info.type == PROTO_69845_SA_TYPE_BROADCAST
|| !iot_bsrm_addr_check(addr_info.ser_info.addr)) {
goto out;
}
if (proto_69845_apdu_sec_ciphertext_check(apdu_desc.ptr, apdu_desc.len)
== ERR_OK) {
reason = 2;
goto out;
}
req = (proto_69845_app_req_resp_t*)data_ptr;
data_ptr += sizeof(*req);
data_len -= sizeof(*req);
if (ERR_OK != iot_bsrm_sg_check_698_req(req)) {
reason = 3;
goto out;
}
switch (req->type) {
case PROTO_69845_C_APP_GET_REQ:
{
resp_pkt = iot_bsrm_handle_698_get_req(data_ptr, data_len);
break;
}
case PROTO_69845_C_APP_ACTION_REQ:
{
resp_pkt = iot_bsrm_handle_698_action_req(data_ptr, data_len);
break;
}
case PROTO_69845_C_APP_SET_REQ:
{
resp_pkt = iot_bsrm_handle_69845_set_req(data_ptr, data_len);
break;
}
default:
reason = 4;
break;
}
out:
if (reason) {
iot_bsrm_printf("handle 698 data err %lu\n", reason);
}
if (sub33 && hdr && hdr->ctrl.flag_scramble) {
proto_69845_add33_handle(apdu_desc.ptr, apdu_desc.len);
}
return resp_pkt;
}
static uint32_t iot_bsrm_handle_master_698_data(
uint8_t *data, uint32_t len)
{
uint32_t ret = ERR_FAIL;
iot_pkt_t *resp_pkt = NULL;
resp_pkt = iot_bsrm_handle_698_req(data, len, NULL);
if (resp_pkt) {
iot_bsrm_uart_send(resp_pkt);
ret = ERR_OK;
}
return ret;
}
static uint32_t iot_bsrm_handle_master_data(iot_pkt_t *pkt)
{
uint8_t ret = ERR_FAIL, *data;
uint32_t len = 0;
proto_645_header_t *hdr_645;
proto_69845_frame_head_info_t *hdr_698;
data = iot_pkt_data(pkt);
len = iot_pkt_data_len(pkt);
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
if (hdr_645) {
iot_bsrm_check_renew_addr(hdr_645->addr);
ret = iot_bsrm_handle_master_645_data(hdr_645);
} else {
hdr_698 = proto_69845_sanity_check(data, len);
if (hdr_698) {
iot_bsrm_check_renew_addr(proto_69845_get_ser_addr(hdr_698));
ret = iot_bsrm_handle_master_698_data(data, len);
} else {
iot_bsrm_printf("uart rec invalid data\n");
ret = ERR_INVAL;
}
}
return ret;
}
static uint32_t iot_bsrm_sg_check_proto_di_r(uint32_t di)
{
uint32_t ret = ERR_OK;
if (p_bsrm_glb->session_mode == IOT_BSRM_SESSION_MODE_DEFAULT) {
IOT_ASSERT(0);
}
if (false == iot_board_support_topo_rx()) {
switch (di) {
case PROTO_645_FJ_DI_UPGRADE_SEND_FILE:
case PROTO_645_FJ_DI_UPGRADE_REQ_FILE:
case PROTO_645_2007_EXT_DI_READ_VER:
break;
default:
ret = ERR_FAIL;
break;
}
} else {
switch (di) {
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD:
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_ZJ:
case PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_XIONGAN:
case PROTO_645_2007_EXT_BRM_CURRENT_COEFF:
{
break;
}
default:
if ((di & 0xFFFFFF00) != PROTO_645_2007_EXT_DI_BR2_EVT_RECORD_ZJ) {
ret = ERR_FAIL;
}
break;
}
}
return ret;
}
static uint32_t iot_bsrm_sg_check_proto_di_w(uint32_t di)
{
uint32_t ret = ERR_OK;
if (p_bsrm_glb->session_mode == IOT_BSRM_SESSION_MODE_DEFAULT) {
IOT_ASSERT(0);
}
if (false == iot_board_support_topo_rx()) {
ret = ERR_FAIL;
}
return ret;
}
static void iot_bsrm_sg_645_data_handler(iot_pkt_t *pkt,
proto_645_header_t *hdr_645)
{
uint8_t fn;
uint8_t err_code = 0;
uint8_t *out_buf;
uint8_t out_len;
uint8_t *out_ds = p_bsrm_glb->proto_buff;
uint8_t follow = PROTO_645_FOLLOW_INVALID;
uint32_t len = 0;
uint32_t di;
uint8_t fwd = 1;
uint8_t sub33 = 0;
if (!iot_bsrm_addr_check(hdr_645->addr)) {
goto out;
}
proto_645_sub33_handle(hdr_645->data, hdr_645->len);
sub33 = 1;
fn = (uint8_t)hdr_645->control.fn;
os_mem_set(out_ds, 0, PROTO_645_MAX_PKT_LEN);
out_buf = out_ds + sizeof(*hdr_645);
out_len = PROTO_645_MAX_DATA_LEN;
switch (fn) {
case PROTO_645_2007_EXT_FN_BR:
{
err_code = iot_bsrm_proto_645_br_data_hander(hdr_645->data,
hdr_645->len, out_buf, &out_len);
if (err_code == PROTO_645_2007_ERR_NO_REQ_DATA) {
goto out;
}
fwd = 0;
break;
}
case PROTO_645_2007_FN_READ_DATA:
{
if (hdr_645->len < PROTO_645_2007_DI_LEN) {
goto out;
}
di = proto_645_2007_byte_to_di(hdr_645->data);
if (iot_bsrm_sg_check_proto_di_r(di) != ERR_OK) {
goto out;
}
fwd = 0;
err_code = iot_bsrm_proto_645_r_data_hander(hdr_645->data,
hdr_645->len, out_buf, &out_len);
break;
}
case PROTO_645_2007_FN_QUERY_TOPO:
{
if (false == iot_board_support_topo_rx()) {
goto out;
}
err_code = iot_bsrm_proto_645_query_topo_data_hander(hdr_645->data,
hdr_645->len, out_buf, &out_len);
if (err_code == PROTO_645_2007_ERR_NO_REQ_DATA) {
goto out;
}
fwd = 0;
break;
}
case PROTO_645_2007_FN_WRITE_DATA:
{
if (hdr_645->len < PROTO_645_2007_DI_LEN) {
goto out;
}
di = proto_645_2007_byte_to_di(hdr_645->data);
if (iot_bsrm_sg_check_proto_di_w(di) != ERR_OK) {
goto out;
}
err_code = iot_bsrm_proto_645_w_data_hander(hdr_645->data, hdr_645->len,
out_buf, &out_len);
if (err_code == PROTO_645_2007_ERR_NO_REQ_DATA) {
goto out;
}
fwd = 0;
break;
}
default:
{
goto out;
}
}
if (err_code) {
len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
p_bsrm_glb->addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_ABNORMAL,
follow, fn, PROTO_645_INVALID_DI, 1, &err_code);
} else {
len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
p_bsrm_glb->addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
follow, fn, PROTO_645_INVALID_DI, out_len, out_buf);
}
iot_bsrm_send_data_to_sg_app(out_ds, len);
out:
if (fwd) {
if (sub33) {
proto_645_add33_handle(hdr_645->data, hdr_645->len);
}
iot_bsrm_fwd_data(pkt);
} else {
iot_pkt_free(pkt);
}
}
static void iot_bsrm_sg_698_data_handler(iot_pkt_t *pkt)
{
uint8_t *data = iot_pkt_data(pkt), fwd = 1;
uint32_t len = iot_pkt_data_len(pkt);
iot_pkt_t *resp_pkt = NULL;
resp_pkt = iot_bsrm_handle_698_req(data, len, &fwd);
if (resp_pkt) {
fwd = 0;
data = iot_pkt_data(resp_pkt);
len = iot_pkt_data_len(resp_pkt);
iot_bsrm_send_data_to_sg_app(data, len);
iot_pkt_free(resp_pkt);
}
if (fwd) {
iot_bsrm_fwd_data(pkt);
} else {
iot_pkt_free(pkt);
}
}
static void iot_bsrm_sg_data_handler(iot_pkt_t *pkt)
{
uint8_t *data;
uint32_t len;
proto_645_header_t *hdr_645;
proto_69845_frame_head_info_t *hdr_698;
data = iot_pkt_data(pkt);
len = iot_pkt_data_len(pkt);
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
if (hdr_645) {
iot_bsrm_sg_645_data_handler(pkt, hdr_645);
} else {
hdr_698 = proto_69845_sanity_check(data, len);
if (hdr_698) {
iot_bsrm_sg_698_data_handler(pkt);
} else {
iot_bsrm_fwd_data(pkt);
}
}
}
static void iot_bsrm_evt_set_pend(void)
{
if (p_bsrm_glb->session_mode != IOT_BSRM_SESSION_MODE_TRANS) {
return;
}
p_bsrm_glb->evt_nodify_pend = 1;
iot_bsrm_cmd_guard(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
}
static void iot_bsrm_evt_clear_pend(void)
{
if (p_bsrm_glb->session_mode != IOT_BSRM_SESSION_MODE_TRANS) {
return;
}
p_bsrm_glb->evt_nodify_pend = 0;
p_bsrm_glb->evt_nodify_try_cnt = 0;
}
static uint8_t iot_bsrm_handle_evt_nodify_resp(iot_pkt_t *pkt)
{
uint8_t *data;
uint32_t len;
uint8_t done = 0;
proto_645_header_t *hdr = NULL;
if (pkt == NULL) {
p_bsrm_glb->evt_nodify_try_cnt++;
if (p_bsrm_glb->evt_nodify_try_cnt >= IOT_BSRM_EVT_NODIFY_TRY_MAX) {
iot_bsrm_evt_clear_pend();
}
goto out;
}
data = iot_pkt_data(pkt);
len = iot_pkt_data_len(pkt);
hdr = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
if (hdr != NULL
&& hdr->control.fn == PROTO_645_2007_FN_WRITE_DATA
&& hdr->control.ack == PROTO_645_ACK_NORMAL) {
iot_bsrm_evt_clear_pend();
done = 1;
}
iot_pkt_free(pkt);
out:
return done;
}
static uint32_t iot_bsrm_rating_cur_to_cur_coeff(
proto_645_07_rating_current_t *rating_cur)
{
uint32_t cur_coeff;
float ratio = 0;
uint32_t in_cur;
float res = 1.0;
in_cur = (uint32_t)proto_645_ascii_to_integer(rating_cur->value,
PROTO_645_2007_RATING_CUR_LEN);
uint8_t n = IOT_ARRAY_CNT(rating_cur_tab);
for (uint8_t i = 0; i < n; i++) {
if (rating_cur_tab[i].rating_current == in_cur) {
ratio = rating_cur_tab[i].ratio;
res = rating_cur_tab[i].resistance;
break;
}
}
/*
* cur ration coeff = (k1 / r1) / (k0 / r0), unit: 0.0001.
* k1: current transformer ratio. r1: Sampling resistance;
* k0 = 4000 base current transformer,
* r0 = 4.4ohm base Sampling resistance.
*/
cur_coeff = (uint32_t)(ratio * 11.0 / res);
iot_bsrm_printf("%s input: %lu A,cur_coeff: %d\n", __FUNCTION__, in_cur,
cur_coeff);
return cur_coeff;
}
static uint8_t iot_bsrm_handle_cur_coeff_resp(iot_pkt_t *pkt)
{
uint8_t *data;
uint32_t len;
proto_645_header_t *hdr = NULL;
proto_645_07_rating_current_t *rating_cur;
uint8_t done = 0;
uint32_t i_coeff;
uint32_t di;
if (NULL == pkt) {
if (p_bsrm_glb->coeff_sync_cnt++ > IOT_BSRM_SYNC_CUR_COEFF_MAX_CNT) {
p_bsrm_glb->cur_coeff_sync_sts = IOT_BSRM_SYNC_CUR_COEFF_DONE;
}
iot_printf("%s timeout\n", __FUNCTION__);
goto out;
}
data = iot_pkt_data(pkt);
len = iot_pkt_data_len(pkt);
hdr = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
if (NULL == hdr) {
goto out;
}
if (hdr->len < PROTO_645_2007_DI_LEN + sizeof(*rating_cur)) {
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
di = proto_645_2007_byte_to_di(hdr->data);
if (PROTO_645_2007_DI_RATING_CURRENT == di) {
rating_cur = (proto_645_07_rating_current_t *)
(hdr->data + PROTO_645_2007_DI_LEN);
i_coeff = iot_bsrm_rating_cur_to_cur_coeff(rating_cur);
iot_bsrm_set_ct_coeff(i_coeff);
p_bsrm_glb->cur_coeff_sync_sts = IOT_BSRM_SYNC_CUR_COEFF_DONE;
done = 1;
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
iot_printf("%s, cur_coeff_sync_sts: %d \n", __FUNCTION__,
p_bsrm_glb->cur_coeff_sync_sts);
return done;
}
static iot_pkt_t *iot_bsrm_w_cmd_from_cus_handle(uint8_t *data,
uint32_t len)
{
uint32_t di;
iot_pkt_t *pkt = NULL;
uint8_t err_code = PROTO_645_2007_ERR_OK;
uint8_t handle = 0;
proto_645_ext_ct_coeff_t *ct_coeff;
if (len < PROTO_645_2007_DI_LEN) {
goto out;
}
di = proto_645_2007_byte_to_di(data);
data += PROTO_645_2007_DI_LEN;
len -= PROTO_645_2007_DI_LEN;
switch (di) {
case PROTO_645_2007_EXT_BRM_CURRENT_COEFF:
{
handle = 1;
if (len < sizeof(*ct_coeff)) {
err_code = PROTO_645_2007_ERR_OTHER;
break;
}
ct_coeff = (proto_645_ext_ct_coeff_t *)data;
iot_bsrm_set_ct_coeff(ct_coeff->coeff);
break;
}
default:
break;
}
if (handle) {
if (err_code != PROTO_645_2007_ERR_OK) {
pkt = proto_645_build_msg(p_bsrm_glb->addr, &err_code, 1,
PROTO_645_INVALID_DI,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_ABNORMAL,
PROTO_645_2007_FN_WRITE_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
} else {
pkt = proto_645_build_msg(p_bsrm_glb->addr, NULL, 0,
PROTO_645_INVALID_DI,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_2007_FN_WRITE_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
}
}
out:
return pkt;
}
static iot_pkt_t *iot_bsrm_r_cmd_from_cus_handle(uint8_t *data,
uint32_t len)
{
uint32_t di;
iot_pkt_t *pkt = NULL;
uint8_t err_code = PROTO_645_2007_ERR_OK;
uint8_t handle = 0, out_len = 0;
uint8_t *out_ds = p_bsrm_glb->proto_buff;
proto_645_ext_ct_coeff_t *ct_coeff;
if (len < PROTO_645_2007_DI_LEN) {
goto out;
}
di = proto_645_2007_byte_to_di(data);
data += PROTO_645_2007_DI_LEN;
len -= PROTO_645_2007_DI_LEN;
switch (di) {
case PROTO_645_2007_EXT_BRM_CURRENT_COEFF:
{
handle = 1;
ct_coeff = (proto_645_ext_ct_coeff_t *)out_ds;
out_len += sizeof(*ct_coeff);
ct_coeff->coeff = iot_bsrm_get_ct_coeff();
break;
}
default:
break;
}
if (handle) {
if (err_code != PROTO_645_2007_ERR_OK) {
pkt = proto_645_build_msg(p_bsrm_glb->addr, &err_code, 1,
PROTO_645_INVALID_DI, PROTO_645_DIR_SLAVE,
PROTO_645_ACK_ABNORMAL, PROTO_645_2007_FN_READ_DATA,
PROTO_645_2007_ID, PROTO_645_FOLLOW_INVALID);
} else {
pkt = proto_645_build_msg(p_bsrm_glb->addr, out_ds, out_len, di,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_2007_FN_READ_DATA, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
}
}
out:
return pkt;
}
static uint8_t iot_bsrm_cmd_from_cus_handle(uint8_t *data,
uint32_t len)
{
uint8_t handle = 0;
uint8_t sub33 = 0;
uint8_t *ds;
uint32_t in_len;
proto_645_header_t *hdr;
iot_pkt_t *pkt = NULL;
hdr = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
if (!hdr) {
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
sub33 = 1;
ds = hdr->data;
in_len = hdr->len;
switch (hdr->control.fn) {
case PROTO_645_2007_FN_WRITE_DATA:
{
pkt = iot_bsrm_w_cmd_from_cus_handle(ds, in_len);
break;
}
case PROTO_645_2007_FN_READ_DATA:
{
pkt = iot_bsrm_r_cmd_from_cus_handle(ds, in_len);
break;
}
default:
break;
}
if (pkt) {
iot_bsrm_uart_send(pkt);
handle = 1;
}
out:
if (sub33) {
proto_645_add33_handle(hdr->data, hdr->len);
}
return handle;
}
static void iot_bsrm_handle_resp_in_tans_mode(iot_pkt_t *pkt)
{
uint8_t done = 0;
uint8_t *data;
uint32_t len;
data = iot_pkt_data(pkt);
len = iot_pkt_data_len(pkt);
if (iot_bsrm_cmd_from_cus_handle(data, len)) {
iot_pkt_free(pkt);
return;
}
switch (p_bsrm_glb->mr_status) {
case IOT_BSRM_MR_STATE_FWD:
{
iot_bsrm_send_data_to_sg_app(data, len);
iot_pkt_free(pkt);
break;
}
case IOT_BSRM_MR_STATE_EVT_NODIF:
{
done = iot_bsrm_handle_evt_nodify_resp(pkt);
break;
}
case IOT_BSRM_MR_STATE_SYNC_CUR_RATIO_COEFF:
{
done = iot_bsrm_handle_cur_coeff_resp(pkt);
break;
}
case IOT_BSRM_MR_STATE_PM_UPGRADE:
{
done = iot_bsrm_handle_pm_upgrade_resp(pkt);
break;
}
case IOT_BSRM_MR_STATE_READY:
case IOT_BSRM_MR_STATE_IDLE:
{
iot_bsrm_send_data_to_sg_app(data, len);
}
default:
{
iot_pkt_free(pkt);
break;
}
}
if (done) {
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_READY;
iot_bsrm_restart_mr_timer(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
}
}
static uint32_t iot_brm_evt_nodify_issue(void)
{
proto_645_header_t *hdr;
proto_645_write_data_dest_t *w;
proto_645_ext_bsrm_evt_nodify_t *nodify;
uint8_t *data;
iot_pkt_t *pkt;
if (!p_bsrm_glb->evt_nodify_pend) {
return ERR_NOT_EXIST;
}
pkt = iot_pkt_alloc(PROTO_645_PREAMBLE_LEN + sizeof(*hdr) + sizeof(*w) \
+ sizeof(*nodify) + sizeof(proto_645_tailer_t), IOT_BSRM_MID);
if (pkt == NULL) {
return ERR_NOMEM;
}
data = iot_pkt_data(pkt);
os_mem_cpy(data, proto_645_preamble, sizeof(proto_645_preamble));
data += sizeof(proto_645_preamble);
iot_pkt_put(pkt, sizeof(proto_645_preamble));
hdr = (proto_645_header_t *)data;
proto_645_header_init(hdr, p_bsrm_glb->addr, PROTO_645_2007_FN_WRITE_DATA,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
data += sizeof(*hdr);
iot_pkt_put(pkt, sizeof(*hdr));
w = (proto_645_write_data_dest_t *)data;
proto_645_2007_di_to_byte(PROTO_645_2007_EXT_BSRM_DI_EVT_NODIFY, w->di);
os_mem_set(w->operator, 0x0, sizeof(w->operator));
os_mem_set(w->password, 0x0, sizeof(w->password));
data += sizeof(*w);
hdr->len += sizeof(*w);
nodify = (proto_645_ext_bsrm_evt_nodify_t *)data;
nodify->flag = 1;
os_mem_set(nodify->rsvd, 0x0, sizeof(nodify->rsvd));
hdr->len += sizeof(*nodify);
proto_645_add33_handle(hdr->data, hdr->len);
proto_645_tail_init(hdr);
iot_pkt_put(pkt, hdr->len + sizeof(proto_645_tailer_t));
iot_bsrm_uart_send(pkt);
return ERR_OK;
}
static uint32_t iot_brm_sync_cur_coeff(void)
{
iot_pkt_t *pkt;
if (p_bsrm_glb->cur_coeff_sync_sts != IOT_BSRM_SYNC_CUR_COEFF_DOING) {
return ERR_EXIST;
}
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID, proto_645_any_addr,
PROTO_645_2007_DI_RATING_CURRENT);
IOT_ASSERT(pkt);
iot_bsrm_uart_send(pkt);
return ERR_OK;
}
static void iot_bsrm_mr_timeout_in_tans_mode(void)
{
uint32_t ret;
uint32_t timeout;
switch (p_bsrm_glb->mr_status) {
case IOT_BSRM_MR_STATE_READY:
{
if (p_bsrm_glb->fwd_pkt) {
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_FWD;
iot_bsrm_uart_send(p_bsrm_glb->fwd_pkt);
p_bsrm_glb->fwd_pkt = NULL;
iot_bsrm_restart_mr_timer(3000);
goto out;
}
ret = iot_brm_sync_cur_coeff();
if (ret == ERR_OK) {
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_SYNC_CUR_RATIO_COEFF;
iot_bsrm_restart_mr_timer(IOT_BSRM_MR_TIMER_RSP_TIMEOUT);
goto out;
}
ret = iot_brm_evt_nodify_issue();
if (ret == ERR_OK) {
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_EVT_NODIF;
iot_bsrm_restart_mr_timer(IOT_BSRM_MR_EVT_NODIFY_TIMEOUT);
goto out;
} else if (ret != ERR_NOT_EXIST) {
/* the execution failed, but the task was not finished yet. */
break;
}
ret = iot_bsrm_handle_pm_upgrade_req(&timeout);
if (ret == ERR_OK) {
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_PM_UPGRADE;
iot_bsrm_restart_mr_timer(timeout);
goto out;
} else if (ret == ERR_NOMEM) {
/* malloc fail, retry again upgrade */
break;
}
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_IDLE;
break;
}
case IOT_BSRM_MR_STATE_FWD:
{
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_READY;
break;
}
case IOT_BSRM_MR_STATE_SYNC_CUR_RATIO_COEFF:
{
iot_bsrm_handle_cur_coeff_resp(NULL);
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_READY;
break;
}
case IOT_BSRM_MR_STATE_EVT_NODIF:
{
iot_bsrm_handle_evt_nodify_resp(NULL);
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_READY;
break;
}
case IOT_BSRM_MR_STATE_PM_UPGRADE:
{
iot_bsrm_handle_pm_upgrade_resp(NULL);
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_READY;
break;
}
case IOT_BSRM_MR_STATE_IDLE:
default:
IOT_ASSERT(0);
break;
}
if (p_bsrm_glb->mr_status == IOT_BSRM_MR_STATE_READY) {
iot_bsrm_restart_mr_timer(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
}
out:
return;
}
static void iot_bsrm_handle_uart_msg(iot_bsrm_msg_t *sg_msg)
{
iot_pkt_t *pkt = (iot_pkt_t *)sg_msg->data;
IOT_ASSERT(sg_msg->task_msg.id == IOT_BSRM_MSG_ID_UART_DATA);
if (p_bsrm_glb->session_mode == IOT_BSRM_SESSION_MODE_DEFAULT) {
/* handle bsrm uart 645 proto data */
if (ERR_OK != iot_bsrm_handle_slave_data(pkt)) {
iot_bsrm_handle_master_data(pkt);
}
iot_pkt_free(pkt);
} else {
iot_bsrm_handle_resp_in_tans_mode(pkt);
}
}
static uint32_t iot_bsrm_sync_tm_cmd_issue()
{
iot_pkt_t *pkt = NULL;
uint32_t di = PROTO_645_2007_DI_TIME_HMS;
uint32_t ret = ERR_FAIL;
if (p_bsrm_glb->sync_tm_state == IOT_BSRM_SYNC_TIME_STATE_YMD) {
/* get time ymd cmd */
di = PROTO_645_2007_DI_TIME_YMD;
}
pkt = proto_645_build_msg(p_bsrm_glb->addr, NULL, 0, di,
PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL, 0x11, PROTO_645_2007_ID,
PROTO_645_FOLLOW_INVALID);
if (pkt) {
iot_bsrm_uart_send(pkt);
ret = ERR_OK;
}
return ret;
}
/* handle pending communication commands */
static uint32_t iot_bsrm_pend_comm_handle(void)
{
iot_pkt_t *pkt;
uint32_t ret = ERR_FAIL;
if (p_bsrm_glb->mr_addr_pend) {
/* send get addr 645 cmd */
pkt = proto_645_2007_build_ra_msg();
if (pkt) {
p_bsrm_glb->mr_addr_pend = 0;
p_bsrm_glb->req_cnt++;
iot_bsrm_uart_send(pkt);
os_start_timer(p_bsrm_glb->mr_timer, IOT_BSRM_MR_TIMER_RSP_TIMEOUT);
p_bsrm_glb->mr_status = IOT_BSRM_MR_GET_ADDR;
ret = ERR_OK;
}
} else if (p_bsrm_glb->sync_tm_state != IOT_BSRM_SYNC_TIME_STATE_IDLE) {
/* sync tm */
ret = iot_bsrm_sync_tm_cmd_issue();
if (ret == ERR_OK) {
if (!p_bsrm_glb->sync_tm_done) {
p_bsrm_glb->req_cnt++;
}
os_start_timer(p_bsrm_glb->mr_timer, IOT_BSRM_MR_TIMER_RSP_TIMEOUT);
p_bsrm_glb->mr_status = IOT_BSRM_MR_STATE_SYNC_TIME;
}
}
return ret;
}
static void iot_bsrm_mr_timeout_default()
{
uint32_t ret = ERR_FAIL;
switch (p_bsrm_glb->mr_status) {
case IOT_BSRM_MR_STATE_READY:
{
ret = iot_bsrm_pend_comm_handle();
break;
}
case IOT_BSRM_MR_GET_ADDR:
{
iot_bsrm_printf("bsrm get addr timeout\n");
break;
}
case IOT_BSRM_MR_STATE_SYNC_TIME:
{
p_bsrm_glb->sync_tm_state = IOT_BSRM_SYNC_TIME_STATE_IDLE;
iot_bsrm_printf("bsrm correct time timeout\n");
break;
}
default:
IOT_ASSERT(0);
break;
}
if (ret != ERR_OK) {
iot_bsrm_check_done_handle();
}
}
static void iot_bsrm_mr_timeout()
{
if (p_bsrm_glb->session_mode == IOT_BSRM_SESSION_MODE_TRANS) {
iot_bsrm_mr_timeout_in_tans_mode();
} else {
iot_bsrm_mr_timeout_default();
}
}
static void iot_bsrm_branch_info_rec(void)
{
iot_bsrm_nv_info_t *nv_info;
iot_bsrm_branch_evt_rec_entry_t *evt_buf =
(iot_bsrm_branch_evt_rec_entry_t *)p_bsrm_glb->evt_buf;
evt_buf->data_cnt = p_bsrm_glb->data_cnt;
iot_bsrm_evt_rec_write(p_bsrm_glb->evt_buf);
p_bsrm_glb->data_cnt = 0;
p_bsrm_glb->evt_trig_cd = 0;
os_mem_set(p_bsrm_glb->evt_buf, 0, sizeof(*evt_buf));
nv_info = (iot_bsrm_nv_info_t *)iot_bsrm_nv_get_section(
iot_bsrm_nv_id_info);
nv_info->evt_occur_cnt++;
iot_bsrm_printf("%s...event cnt %lu\n", __FUNCTION__,
nv_info->evt_occur_cnt);
iot_bsrm_nv_update_section(iot_bsrm_nv_id_info);
iot_bsrm_evt_set_pend();
}
static void iot_bsrm_branch_info_timeout_handle(void)
{
iot_bsrm_branch_evt_rec_entry_t *evt_buf =
(iot_bsrm_branch_evt_rec_entry_t *)p_bsrm_glb->evt_buf;
iot_bsrm_branch_info_entry_t *rec_buf = &p_bsrm_glb->br_rec_buf;
if (p_bsrm_glb->br_rec_cd) {
p_bsrm_glb->br_rec_cd--;
if (!p_bsrm_glb->br_rec_cd) {
iot_bsrm_info_rec(rec_buf->ts, sizeof(*rec_buf),
(uint8_t *)rec_buf);
os_mem_cpy(&evt_buf->record_data[p_bsrm_glb->data_cnt],
(uint8_t *)rec_buf, sizeof(*rec_buf));
p_bsrm_glb->data_cnt++;
if (!p_bsrm_glb->evt_trig_cd) {
p_bsrm_glb->evt_trig_cd = IOT_BSRM_BRANCH_EVT_TIMEOUT;
}
if (p_bsrm_glb->data_cnt == IOT_BSRM_BRANCH_EVT_ENTRY_INFO_NUM) {
iot_bsrm_branch_info_rec();
}
}
}
if (p_bsrm_glb->evt_trig_cd) {
p_bsrm_glb->evt_trig_cd--;
if (!p_bsrm_glb->evt_trig_cd) {
iot_bsrm_branch_info_rec();
}
}
}
static void iot_bsrm_session_mode_main_check()
{
uint32_t interval_tm = IOT_BSRM_REQ_TIMER_TIMEOUT;
if (p_bsrm_glb->session_mode != IOT_BSRM_SESSION_MODE_DEFAULT) {
goto out;
}
if (p_bsrm_glb->req_cnt >= IOT_BSRM_REQ_MAX_CNT) {
goto out;
}
if (!p_bsrm_glb->addr_valid) {
if (p_bsrm_glb->mr_tm_interval < interval_tm) {
p_bsrm_glb->mr_tm_interval++;
} else {
if (!p_bsrm_glb->mr_addr_pend) {
p_bsrm_glb->mr_addr_pend = 1;
}
p_bsrm_glb->mr_tm_interval = 0;
iot_bsrm_cmd_guard(IOT_BSRM_MR_TIMER_HANDLE_PERIOD);
iot_bsrm_printf("bsrm start request address\n");
}
goto out;
}
if (p_bsrm_glb->sync_tm_done) {
interval_tm = IOT_BSRM_AUTO_CORRECT_TM_INTERVAL;
}
if (p_bsrm_glb->mr_tm_interval < interval_tm) {
p_bsrm_glb->mr_tm_interval++;
} else {
iot_bsrm_set_correct_tm(0);
}
out:
return;
}
static void iot_bsrm_handle_timer_msg(iot_bsrm_msg_t *msg)
{
switch (msg->task_msg.id) {
case IOT_BSRM_MSG_ID_TIMER_PERIOD:
{
iot_bsrm_branch_info_timeout_handle();
iot_bsrm_upgrade_windows();
iot_bsrm_session_mode_main_check();
iot_bsrm_check_timeout_handle();
iot_bsrm_check_timeout_event();
iot_bsrm_br_rec_frag_ctrl_ageing();
break;
}
case IOT_BSRM_MSG_ID_TIMER_CHECK_MR:
{
iot_bsrm_mr_timeout();
break;
}
default:
break;
}
}
static void iot_bsrm_branch_recv_init(void)
{
iot_bsrm_nv_param_t *param = (iot_bsrm_nv_param_t *)iot_bsrm_nv_get_section(
iot_bsrm_nv_id_param);
iot_bsrm_br_param_t *br_param = &param->br_param;
hw_topo_rcv_cfg_t cfg = { 0 };
static const uint8_t id_code_def[] = { 0xAA, 0xE9 };
if (!br_param->fc) {
br_param->fc = IOT_BSRM_BRANCH_LOAD_FREQ_DEF;
br_param->pulse_high_dur = 400;
br_param->pulse_low_dur = 800;
br_param->chara_bit_dur = 600;
br_param->id_code_len = sizeof(id_code_def);
os_mem_cpy(br_param->id_code, id_code_def, sizeof(id_code_def));
iot_bsrm_nv_update_section(iot_bsrm_nv_id_param);
}
iot_bsrm_printf("%s fc %lu, bit_dur = %lu\n", __FUNCTION__, br_param->fc,
br_param->chara_bit_dur);
iot_bsrm_data_print("code", br_param->id_code, br_param->id_code_len);
cfg.fc = br_param->fc;
cfg.fc_valid = 1;
cfg.chara_bit_dur = br_param->chara_bit_dur;
cfg.dur_valid = 1;
cfg.data_len = sizeof(id_code_def);
os_mem_cpy(cfg.data, id_code_def, cfg.data_len);
cfg.phase = IOT_PLC_PHASE_ALL;
iot_plc_hw_topo_rcv_cfg(&cfg);
}
static void iot_bsrm_branch_info_handle(iot_pkt_t *pkt)
{
uint32_t ts;
iot_time_tm_t tm;
uint8_t update = 0, *data, i, id_code_len;
float rssi1, rssi2;
hw_tsfm_rx_info_t *rx_info;
iot_bsrm_branch_info_entry_t *rec_buf;
uint8_t err_bit_mask, err_bit_cnt = 0;
iot_bsrm_nv_param_t *nv_param = (iot_bsrm_nv_param_t *)
iot_bsrm_nv_get_section(iot_bsrm_nv_id_param);
iot_bsrm_br_param_t *br_param = &nv_param->br_param;
rec_buf = &p_bsrm_glb->br_rec_buf;
data = iot_pkt_data(pkt);
rx_info = (hw_tsfm_rx_info_t *)data;
data += sizeof(*rx_info);
id_code_len = (uint8_t)(iot_pkt_data_len(pkt) - sizeof(*rx_info));
if (id_code_len != br_param->id_code_len) {
goto out;
}
for (i = 0; i < id_code_len; i++) {
err_bit_mask = data[i] ^ br_param->id_code[i];
err_bit_cnt += iot_bitops_cbs(err_bit_mask);
}
if (err_bit_cnt > 1) {
goto out;
}
if (!p_bsrm_glb->br_rec_cd) {
p_bsrm_glb->br_rec_cd = IOT_BSRM_BR_REC_CD;
update = 1;
} else {
rssi1 = (float)(rx_info->sub_sig_info[0].energy * 0.001);
rssi2 = (float)(rx_info->sub_sig_info[1].energy * 0.001);
if ((rssi1 + rssi2) >
(rec_buf->signal1_rssi + rec_buf->signal2_rssi)) {
update = 1;
}
}
if (update) {
iot_rtc_get(&tm);
ts = iot_bsrm_rtctime_to_time(&tm);
rec_buf->base_rssi = 0;
rec_buf->is_vaild = 1;
rec_buf->phase = rx_info->phase;
rec_buf->reserved1 = 0;
rec_buf->ts = ts;
rec_buf->signal1_rssi = (float)(rx_info->sub_sig_info[0].energy
* 0.001);
rec_buf->signal2_rssi = (float)(rx_info->sub_sig_info[1].energy
* 0.001);
rec_buf->noise = (float)(rx_info->noise * 0.001);
if (rec_buf->noise < 0.002) {
rec_buf->noise = 0.002;
}
rec_buf->id_code_len = id_code_len;
os_mem_cpy(rec_buf->id_code, br_param->id_code, id_code_len);
os_mem_set(rec_buf->reserved2, 0 ,sizeof(rec_buf->reserved2));
iot_printf("br info rx ts: %lu-%lu-%lu %lu:%lu:%lu, "
"phase:%lu, rssi1:%lu, rssi2:%lu, noise:%lu\n",
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
rec_buf->phase, (uint32_t)(rec_buf->signal1_rssi * 1000.0),
(uint32_t)(rec_buf->signal2_rssi * 1000.0),
(uint32_t)(rec_buf->noise * 1000.0));
}
out:
iot_pkt_free(pkt);
return;
}
static void iot_bsrm_handle_internal_msg(iot_bsrm_msg_t *msg)
{
iot_pkt_t *pkt;
iot_bsrm_nv_info_t *nv_info;
switch (msg->task_msg.id) {
case IOT_BSRM_MSG_ID_INTERNAL_HW_TSFM:
{
pkt = (iot_pkt_t *)msg->data;
if (iot_rtc_data_is_revised()) {
iot_bsrm_branch_info_handle(pkt);
} else {
iot_bsrm_printf("%s drop tsfm data, sync tm not done\n",
__FUNCTION__);
iot_pkt_free(pkt);
}
break;
}
case IOT_BSRM_MSG_ID_INTERNAL_EVENT_INTERRUPT:
{
p_bsrm_glb->check_crtl.event.count++;
break;
}
case IOT_BSRM_MSG_ID_INTERNAL_BR_REC_CLEAR:
{
iot_bsrm_rec_info_clear();
iot_bsrm_rec_evt_clear();
nv_info = (iot_bsrm_nv_info_t *)iot_bsrm_nv_get_section(
iot_bsrm_nv_id_info);
nv_info->evt_occur_cnt = 0;
iot_bsrm_nv_update_section(iot_bsrm_nv_id_info);
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void iot_bsrm_config_uart(iot_uart_h uart_h,
uint32_t baud, uint8_t parity, uint8_t data, uint8_t stop,
iot_frame_fmt *fmt, uint32_t thrd)
{
IOT_ASSERT(uart_h);
iot_uart_set_config(uart_h, baud, parity, data, stop);
if (fmt) {
iot_uart_set_frame(uart_h, fmt);
}
iot_uart_set_threshold(uart_h, UART_THR_RXTIMEOUT, thrd);
iot_bsrm_printf("%s buad %lu, parity %lu\n", __FUNCTION__, baud, parity);
}
static void iot_bsrm_uart_config_ext(iot_sg_ext_uart_t *cfg)
{
iot_bsrm_printf("%s baudrate: %d, parity: %d, data: %d, stop: %d \n",
__FUNCTION__, cfg->baudrate, cfg->parity, cfg->data, cfg->stop);
iot_bsrm_config_uart(p_bsrm_glb->handle, cfg->baudrate, cfg->parity,
cfg->data, cfg->stop, cfg->fmt_valid ? &(cfg->fmt) : NULL,
cfg->thd_rx_tm);
}
static void iot_bsrm_handle_sg_app_msg(iot_bsrm_msg_t *sg_msg)
{
iot_pkt_t *pkt = (iot_pkt_t *)sg_msg->data;
iot_sg_ext_header_t *hdr;
iot_bsrm_br_param_t br_param;
iot_sg_ext_cus_topo_rcv_cfg_t *cfg;
iot_sg_ext_dev_info_t *dev_info;
hdr = (iot_sg_ext_header_t *)iot_pkt_data(pkt);
switch (hdr->mid) {
case IOT_SG_EXT_MID_UART_DATA_FROM_SG:
{
iot_pkt_set_data(pkt, hdr->data);
iot_bsrm_data_print("sg app to bsrm: ", iot_pkt_data(pkt),
iot_pkt_data_len(pkt));
iot_bsrm_sg_data_handler(pkt);
break;
}
case IOT_SG_EXT_MID_COMMAND:
{
switch (hdr->arg) {
case IOT_SG_EXT_SID_UART_CFG:
{
iot_bsrm_uart_config_ext((iot_sg_ext_uart_t *)hdr->data);
break;
}
case IOT_SG_EXT_SID_TOPO_RCV_CFG:
{
cfg = (iot_sg_ext_cus_topo_rcv_cfg_t*)hdr->data;
br_param.fc = cfg->fc;
br_param.chara_bit_dur = cfg->chara_bit_dur;
br_param.pulse_high_dur = cfg->pulse_high_dur;
br_param.pulse_low_dur = cfg->pulse_low_dur;
os_mem_cpy(br_param.id_code, cfg->fr_code, cfg->fr_code_len);
br_param.id_code_len = cfg->fr_code_len;
iot_bsrm_set_br_recv_param(&br_param);
break;
}
case IOT_SG_EXT_SID_DEV_INFO_SYNC:
{
dev_info = (iot_sg_ext_dev_info_t*)hdr->data;
iot_bsrm_check_renew_addr(dev_info->addr);
break;
}
default:
break;
}
iot_pkt_free(pkt);
break;
}
default:
iot_pkt_free(pkt);
break;
}
}
static void iot_bsrm_msg_exe_func(iot_task_h task_h, iot_task_msg_t *msg)
{
(void)task_h;
iot_bsrm_msg_t *bsrm_msg = (iot_bsrm_msg_t *)msg;
switch (bsrm_msg->task_msg.type) {
case IOT_BSRM_MSG_TYPE_UART:
{
iot_bsrm_handle_uart_msg(bsrm_msg);
break;
}
case IOT_BSRM_MSG_TYPE_TIMER:
{
iot_bsrm_handle_timer_msg(bsrm_msg);
break;
}
case IOT_BSRM_MSG_TYPE_INTERNAL:
{
iot_bsrm_handle_internal_msg(bsrm_msg);
break;
}
case IOT_BSRM_MSG_TYPE_SG_APP:
{
iot_bsrm_handle_sg_app_msg(bsrm_msg);
break;
}
default:
IOT_ASSERT(0);
break;
}
iot_task_free_msg(task_h, &bsrm_msg->task_msg);
}
static void iot_bsrm_msg_cancel_func(iot_task_h task_h, iot_task_msg_t *msg)
{
iot_pkt_t *pkt = NULL;
iot_bsrm_msg_t *bsrm_msg = (iot_bsrm_msg_t *)msg;
switch (bsrm_msg->task_msg.type) {
case IOT_BSRM_MSG_TYPE_UART:
{
pkt = (iot_pkt_t *)bsrm_msg->data;
iot_pkt_free(pkt);
break;
}
case IOT_BSRM_MSG_TYPE_TIMER:
{
break;
}
case IOT_BSRM_MSG_TYPE_INTERNAL:
{
pkt = (iot_pkt_t *)bsrm_msg->data;
iot_pkt_free(pkt);
break;
}
default:
IOT_ASSERT(0);
break;
}
iot_task_free_msg(task_h, &bsrm_msg->task_msg);
}
static void iot_bsrm_period_timer_func(timer_id_t timer_id, void *arg)
{
(void)timer_id;
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_TIMER,
IOT_BSRM_MSG_ID_TIMER_PERIOD, IOT_BSRM_MSG_QUEUE_LP, arg, 0);
}
uint32_t iot_bsrm_rtctime_to_time(iot_time_tm_t *tm)
{
int64_t diff;
iot_time_tm_t tm_base;
tm_base.tm_year = 1970;
tm_base.tm_mon = 1;
tm_base.tm_mday = 1;
tm_base.tm_hour = 0;
tm_base.tm_min = 0;
tm_base.tm_sec = 0;
diff = iot_rtc_delta_calc(&tm_base, tm);
IOT_ASSERT(diff >= 0);
return (uint32_t)diff;
}
void iot_bsrm_time_to_rtctime(uint32_t time, iot_time_tm_t *tm)
{
iot_time_tm_t tm_base;
tm_base.tm_year = 1970;
tm_base.tm_mon = 1;
tm_base.tm_mday = 1;
tm_base.tm_hour = 0;
tm_base.tm_min = 0;
tm_base.tm_sec = 0;
iot_rtc_delta_add((int64_t)time, &tm_base);
*tm = tm_base;
}
/* this callback function receives the hw tsfm info from PLC LIB */
static void iot_bsrm_hw_tsfm_plc_recv(
uint8_t data_type, uint8_t *data, uint8_t len,
hw_tsfm_rx_info_t *rx_info)
{
iot_pkt_t *pkt = NULL;
uint8_t *ds;
switch (data_type) {
case PROTO_HW_TSFM_ID_TOPO_RAW:
{
pkt = iot_pkt_alloc(sizeof(*rx_info) + len, IOT_BSRM_MID);
if (!pkt) {
iot_printf("%s pkt alloc failed\n", __FUNCTION__);
return;
}
ds = iot_pkt_put(pkt, sizeof(*rx_info) + len);
os_mem_cpy(ds, rx_info, sizeof(*rx_info));
ds += sizeof(*rx_info);
os_mem_cpy(ds, data, len);
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_INTERNAL,
IOT_BSRM_MSG_ID_INTERNAL_HW_TSFM, IOT_BSRM_MSG_QUEUE_LP,
pkt, 0);
break;
}
default:
break;
}
}
static void iot_bsrm_uart_setting(iot_uart_h handle)
{
iot_frame_fmt fmt = {0};
/* set 485 config */
fmt.preamble_code[0] = PROTO_645_START_CHAR;
fmt.preamble_codelen = 1;
fmt.datalen_offset = 8;
fmt.datalen_size = 1;
fmt.backcode_offset = 1;
fmt.backcode_len = 1;
fmt.datalen_fix = 0;
fmt.backcode[0] = PROTO_645_END_CHAR;
fmt.frame_timeout = 30;
fmt.timeout_mode = TIMEOUT_PERDATA;
fmt.check_frame_func = proto_645_check_frame_handler;
iot_bsrm_config_uart(handle, 9600, IOT_UART_PARITY_EVEN, 8, 1, &fmt, 3);
}
void iot_bsrm_ipc_recv(void *param, iot_ipc_addr_t *addr, iot_pkt_t *pkt)
{
(void)param;
iot_bsrm_post_msg(IOT_BSRM_MSG_TYPE_SG_APP, IOT_BSRM_MSG_ID_SG_APP,
IOT_BSRM_MSG_QUEUE_LP, pkt, (addr->c_id << 4) + addr->f_id);
}
uint32_t iot_bsrm_init(void)
{
uint32_t ret = ERR_OK;
if (p_bsrm_glb) {
goto out;
}
p_bsrm_glb = os_mem_malloc(IOT_BSRM_MID, sizeof(*p_bsrm_glb));
if (p_bsrm_glb == NULL) {
ret = ERR_NOMEM;
goto out;
}
/* init bsrm glb param */
os_mem_set(p_bsrm_glb, 0, sizeof(*p_bsrm_glb));
p_bsrm_glb->evt_trig_cd = 0;
p_bsrm_glb->evt_buf = os_mem_malloc(IOT_BSRM_MID,
sizeof(iot_bsrm_branch_evt_rec_entry_t));
if (p_bsrm_glb->evt_buf == NULL) {
ret = ERR_NOMEM;
goto err_task;
}
/* create extend bsrm task */
p_bsrm_glb->task_cfg.stack_size = IOT_BSRM_TASK_STACK_SZIE;
p_bsrm_glb->task_cfg.task_prio = IOT_BSRM_TASK_PRIO;
p_bsrm_glb->task_cfg.msg_size = sizeof(iot_bsrm_msg_t);
p_bsrm_glb->task_cfg.msg_cnt = IOT_BSRM_MSG_POOL_SIZE;
p_bsrm_glb->task_cfg.queue_cnt = IOT_BSRM_MSG_QUEUE_MAX_PRIO;
p_bsrm_glb->task_cfg.queue_cfg[IOT_BSRM_MSG_QUEUE_HP].quota = 0;
p_bsrm_glb->task_cfg.queue_cfg[IOT_BSRM_MSG_QUEUE_LP].quota = 0;
p_bsrm_glb->task_cfg.msg_exe_func = iot_bsrm_msg_exe_func;
p_bsrm_glb->task_cfg.msg_cancel_func = iot_bsrm_msg_cancel_func;
p_bsrm_glb->task_h = iot_task_create(IOT_BSRM_MID,
&p_bsrm_glb->task_cfg);
if (p_bsrm_glb->task_h == NULL) {
ret = ERR_NOMEM;
goto err_task;
}
p_bsrm_glb->periodic_timer = os_create_timer(IOT_BSRM_MID, true,
iot_bsrm_period_timer_func, NULL);
if (p_bsrm_glb->periodic_timer == 0) {
ret = ERR_NOMEM;
goto err_periodic_timer;
}
p_bsrm_glb->mr_timer = os_create_timer(IOT_BSRM_MID, false,
iot_bsrm_mr_timer_func, NULL);
if (p_bsrm_glb->mr_timer == 0) {
ret = ERR_NOMEM;
goto err_mr_timer;
}
/* open extend bsrm interface (UART) for bsrm app */
p_bsrm_glb->handle = iot_uart_open(
iot_board_get_uart(UART_METER_PORT), iot_bsrm_uart_recv,
IOT_BSRM_UART_BUF_SIZE, NULL);
if (p_bsrm_glb->handle == NULL) {
ret = ERR_BUSY;
goto err_uart_fail;
}
iot_bsrm_uart_setting(p_bsrm_glb->handle);
ret = iot_bsrm_flash_init();
if (ret) {
ret = ERR_BUSY;
goto flash_init_err;
}
ret = iot_plc_hw_tsfm_register_listener(iot_bsrm_hw_tsfm_plc_recv);
if (ret) {
ret = ERR_NOSUPP;
goto err_pm_init;
}
ret = iot_bsrm_nv_init();
if (ret) {
IOT_ASSERT(0);
ret = ERR_NOSUPP;
goto err_nv_init;
}
ret = iot_bsrm_rec_init();
if (ret) {
ret = ERR_NOMEM;
goto err_rec_init;
}
/* load nonvolatile information */
iot_bsrm_load_nv();
iot_bsrm_branch_recv_init();
/* init psrm upgrade info*/
if (iot_bsrm_upgrade_init() != ERR_OK) {
ret = ERR_NOMEM;
goto err_upgrade;
}
/* upgrade success, set pm upgrade flag */
if (IOT_PLC_UPGRADE_SWITCH_SUCC == iot_upgrade_get_switch_part_info()) {
iot_bsrm_set_pm_upgrade_guard_code(IOT_BSRM_PM_UPGRADE_GUARD_CODE);
}
/* init psrm pm upgrade info */
if(iot_bsrm_pm_upgrade_init() != ERR_OK) {
ret = ERR_NOMEM;
goto err_pm_upgrade;
}
#if (IOT_BSRM_MODE == IOT_BSRM_MODE_DEFAULT)
p_bsrm_glb->session_mode = IOT_BSRM_SESSION_MODE_DEFAULT;
p_bsrm_glb->cur_coeff_sync_sts = IOT_BSRM_SYNC_CUR_COEFF_DONE;
#else
iot_ipc_client_t client;
/* register IPC for iot_bsrm */
client.addr.f_id = IOT_IPC_FID_SG_EXT_SDK;
client.addr.c_id = IOT_IPC_CID_SG_EXT_CUS_APP;
client.recv = iot_bsrm_ipc_recv;
client.param = NULL;
p_bsrm_glb->ipc_h = iot_ipc_register_client(&client);
if (p_bsrm_glb->ipc_h == NULL) {
ret = ERR_BUSY;
goto err_ipc;
}
p_bsrm_glb->session_mode = IOT_BSRM_SESSION_MODE_TRANS;
if (false == iot_board_support_topo_rx()) {
p_bsrm_glb->cur_coeff_sync_sts = IOT_BSRM_SYNC_CUR_COEFF_DONE;
} else {
p_bsrm_glb->cur_coeff_sync_sts = IOT_BSRM_SYNC_CUR_COEFF_IDLE;
}
p_bsrm_glb->coeff_sync_cnt = 0;
#endif
p_bsrm_glb->check_crtl.event.status = IOT_BSRM_CHECK_EVENT_STATUS_IDLE;
os_start_timer(p_bsrm_glb->periodic_timer,
IOT_BSRM_PERIOND_TIMER_INTERVAL);
iot_bsrm_printf("%s init successful\n", __FUNCTION__);
goto out;
#if (IOT_BSRM_MODE == IOT_BSRM_MODE_CUS_APP)
err_ipc:
iot_bsrm_pm_upgrade_deinit();
#endif
err_pm_upgrade:
iot_bsrm_upgrade_deinit();
err_upgrade:
err_rec_init:
err_nv_init:
err_pm_init:
flash_init_err:
iot_uart_close(p_bsrm_glb->handle);
p_bsrm_glb->handle = NULL;
err_uart_fail:
os_delete_timer(p_bsrm_glb->mr_timer);
p_bsrm_glb->mr_timer = 0;
err_mr_timer:
os_delete_timer(p_bsrm_glb->periodic_timer);
p_bsrm_glb->periodic_timer = 0;
err_periodic_timer:
iot_task_delete(p_bsrm_glb->task_h);
p_bsrm_glb->task_h = NULL;
err_task:
os_mem_free(p_bsrm_glb);
p_bsrm_glb = NULL;
out:
return ret;
}
/*
* app_bsrm_entry: entry for bsrm app
*/
uint32_t app_bsrm_entry()
{
uint32_t ret = ERR_PENDING;
if (iot_bsrm_init()) {
ret = ERR_OK;
}
return ret;
}
#endif /* IOT_BSRM_MODE */