930 lines
29 KiB
C
Executable File
930 lines
29 KiB
C
Executable File
/****************************************************************************
|
|
*
|
|
* 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_ship header files */
|
|
#include "os_task_api.h"
|
|
#include "os_timer_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_io_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_pkt_api.h"
|
|
#include "iot_crc_api.h"
|
|
#include "iot_utils_api.h"
|
|
|
|
#include "iot_energe_meter_api.h"
|
|
#include "iot_brm_common.h"
|
|
#include "iot_brm_rtc.h"
|
|
#include "iot_brm_adp.h"
|
|
#include "iot_brm_flash.h"
|
|
#include "iot_brm_rec.h"
|
|
#include "iot_brm_evt.h"
|
|
#include "iot_brm_proto_devadp_645_ext.h"
|
|
|
|
#if (IOT_BRM_ENABLE && PLC_SUPPORT_STA_ROLE)
|
|
|
|
#define BRM_ADP_MODULE_VERSION "1.0.005"
|
|
|
|
/* Max number of the energy meter adapter device state. */
|
|
#define BRM_ADP_DEV_STATE_MAX (DM_STATE_DEV_MAX)
|
|
|
|
/* define adp record event max count */
|
|
#define IOT_BRM_REC_ADP_EVT_MAX (40 * 30)
|
|
|
|
/* define adp record read buffer size */
|
|
#define IOT_BRM_ADP_REC_READ_BUF_SIZE 2048
|
|
|
|
#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
|
|
|
|
#define IOT_BRM_ADP_THRESHOLD_START \
|
|
(IOT_BRM_EVT_REGION_END + IOT_BRM_RESERVE_SIZE3)
|
|
#define IOT_BRM_ADP_THRESHOLD_SIZE (1024)
|
|
#define IOT_BRM_ADP_THRESHOLD_END \
|
|
(IOT_BRM_ADP_THRESHOLD_START + IOT_BRM_ADP_THRESHOLD_SIZE)
|
|
|
|
/* define the start, size, and end of evt recording region */
|
|
#define IOT_BRM_ADP_EVT_REGION_START IOT_BRM_ADP_THRESHOLD_END
|
|
#define IOT_BRM_ADP_EVT_REGION_SIZE (256 * 1024)
|
|
#define IOT_BRM_ADP_EVT_REGION_END \
|
|
IOT_BRM_ADP_EVT_REGION_START + IOT_BRM_ADP_EVT_REGION_SIZE
|
|
|
|
/* The energy meter adapter context. */
|
|
static brm_adp_context_t brm_adp_context;
|
|
static iot_brm_rec_region_desc_t g_adp_evt_rcd_region;
|
|
static uint8_t *g_buf;
|
|
|
|
|
|
static void iot_brm_adp_dev_fsm_state_process(
|
|
iot_brm_event_record_t *p_event_record);
|
|
|
|
static void iot_brm_adp_evt_send_at_join_in(void);
|
|
|
|
static void iot_brm_adp_plc_status_update(void);
|
|
|
|
/* check if oter request is exsiting */
|
|
static bool_t iot_brm_adp_fsm_evt_check_other_req_exsit(uint16_t new_evt)
|
|
{
|
|
bool_t is_exsit = false;
|
|
uint16_t check_val = (1 << new_evt);
|
|
if (new_evt < DM_STATE_DEV_MAX) {
|
|
if ((brm_adp_context.dev_fsm.chg_req_bitmp | check_val) != check_val) {
|
|
is_exsit = true;
|
|
}
|
|
}
|
|
return is_exsit;
|
|
}
|
|
|
|
/* set the new event request bit in bitmap */
|
|
static void iot_brm_adp_fsm_evt_set_req_bitmap(uint16_t new_evt)
|
|
{
|
|
/* only one bit could be set in bitmap */
|
|
if (new_evt < DM_STATE_DEV_MAX) {
|
|
brm_adp_context.dev_fsm.chg_req_bitmp = (1 << new_evt);
|
|
}
|
|
}
|
|
|
|
/* clear the new event request bit in bitmap */
|
|
static void iot_brm_adp_fsm_evt_clr_req_bitmap()
|
|
{
|
|
brm_adp_context.dev_fsm.chg_req_bitmp = 0;
|
|
}
|
|
|
|
static void iot_brm_adp_fsm_reset_req_cnt(void)
|
|
{
|
|
brm_adp_context.dev_fsm.chg_req_cnt = 0;
|
|
}
|
|
|
|
static bool_t iot_brm_adp_fsm_evt_req_change(
|
|
iot_brm_event_record_t *p_event, uint16_t new_evt)
|
|
{
|
|
bool_t req_cfm = false;
|
|
|
|
if (iot_brm_adp_fsm_evt_check_other_req_exsit(new_evt)) {
|
|
iot_brm_adp_fsm_reset_req_cnt();
|
|
}
|
|
brm_adp_context.dev_fsm.chg_req_cnt++;
|
|
iot_brm_adp_fsm_evt_set_req_bitmap(new_evt);
|
|
if (brm_adp_context.dev_fsm.chg_req_cnt >= IOT_BRM_FSM_REQ_CFM_CNT) {
|
|
p_event->rcd_data.event = new_evt;
|
|
req_cfm = true;
|
|
iot_brm_adp_fsm_reset_req_cnt();
|
|
iot_brm_adp_fsm_evt_clr_req_bitmap();
|
|
iot_brm_adp_dev_fsm_state_process(p_event);
|
|
iot_brm_printf("%s req event--%d confirmed\n",__FUNCTION__, new_evt);
|
|
}
|
|
return req_cfm;
|
|
}
|
|
|
|
/* Report event */
|
|
static void iot_brm_adp_event_report(iot_brm_event_record_t *p_last_adc_rec)
|
|
{
|
|
(void)p_last_adc_rec;
|
|
iot_cus_printf("%s start send request\n", __FUNCTION__);
|
|
iot_brm_evt_set(iot_brm_evt_adp_id);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Process corresponding state for device finite state machine. */
|
|
static void iot_brm_adp_dev_fsm_state_process(
|
|
iot_brm_event_record_t *p_event_record)
|
|
{
|
|
uint32_t event;
|
|
brm_adp_dev_state_e new_state;
|
|
brm_adp_dev_state_e cur_state = brm_adp_context.dev_fsm.cur_state;
|
|
char *em_adp_fsm_symbol[4] = {"OFFLINE", "STANDBY", "WORKING", "TRAPING"};
|
|
if (NULL == p_event_record) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
event = p_event_record->rcd_data.event;
|
|
iot_cus_printf("[brmadp] %s current event=%d, device fsm cur_state=%s.\n",
|
|
__FUNCTION__, event, em_adp_fsm_symbol[cur_state]);
|
|
|
|
p_event_record->state = cur_state;
|
|
|
|
/* Process current state in device fsm. */
|
|
new_state =
|
|
brm_adp_context.dev_fsm.table.handle[cur_state](event, p_event_record);
|
|
if (new_state != cur_state) {
|
|
iot_cus_printf("[brmadp] change fsm from %s to %s.\n",
|
|
em_adp_fsm_symbol[cur_state], em_adp_fsm_symbol[new_state]);
|
|
brm_adp_context.dev_fsm.prev_state = cur_state;
|
|
brm_adp_context.dev_fsm.cur_state = new_state;
|
|
iot_brm_adp_event_report(p_event_record);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void iot_brm_adp_fsm_event_process(void)
|
|
{
|
|
uint8_t week;
|
|
iot_time_tm_t tm;
|
|
iot_brm_event_record_t env_rcd = {0};
|
|
uint32_t current_phase_a, current_phase_b, current_phase_c, tt_current;
|
|
uint32_t power_phase_a, power_phase_b, power_phase_c, tt_power;
|
|
iot_brm_meter_info_t *meter_info = iot_brm_load_meter_info();
|
|
iot_brm_threshold_t *thr = &brm_adp_context.threshold;
|
|
|
|
iot_brm_adp_plc_status_update();
|
|
|
|
iot_brm_adp_evt_send_at_join_in();
|
|
|
|
env_rcd.rcd_data.w = meter_info->e_t.ept_pos[0];
|
|
os_mem_cpy(env_rcd.rcd_data.p, meter_info->var.p,
|
|
sizeof(int32_t)*IOT_BRM_PHASE_MAX);
|
|
os_mem_cpy(env_rcd.rcd_data.i, meter_info->var.i,
|
|
sizeof(int32_t)*IOT_BRM_PHASE_C);
|
|
os_mem_cpy(env_rcd.rcd_data.v, meter_info->var.v,
|
|
sizeof(uint16_t)*IOT_BRM_PHASE_C);
|
|
os_mem_cpy(env_rcd.rcd_data.f, meter_info->var.pf,
|
|
sizeof(uint16_t)*IOT_BRM_PHASE_MAX);
|
|
|
|
power_phase_a = ABS(meter_info->var.p[IOT_BRM_PHASE_A]);
|
|
power_phase_b = ABS(meter_info->var.p[IOT_BRM_PHASE_B]);
|
|
power_phase_c = ABS(meter_info->var.p[IOT_BRM_PHASE_C]);
|
|
tt_power = power_phase_a + power_phase_b + power_phase_c;
|
|
|
|
current_phase_a = ABS(meter_info->var.i[IOT_BRM_PHASE_A - 1]);
|
|
current_phase_b = ABS(meter_info->var.i[IOT_BRM_PHASE_B - 1]);
|
|
current_phase_c = ABS(meter_info->var.i[IOT_BRM_PHASE_C - 1]);
|
|
tt_current = current_phase_a + current_phase_b + current_phase_c;
|
|
|
|
iot_brm_rtc_get_time(&tm, &week);
|
|
env_rcd.time = iot_brm_rtctime_to_time(&tm);
|
|
|
|
iot_cus_printf("time=%d-%d-%d %d:%d:%d %lu\n",
|
|
tm.tm_year,tm.tm_mon,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec,
|
|
env_rcd.time);
|
|
|
|
iot_cus_printf("[brmadp] %s current=[%d %d %d], power=[%d %d %d]\n",
|
|
__FUNCTION__, meter_info->var.i[IOT_BRM_PHASE_A - 1],
|
|
meter_info->var.i[IOT_BRM_PHASE_B - 1],
|
|
meter_info->var.i[IOT_BRM_PHASE_C - 1],
|
|
meter_info->var.p[IOT_BRM_PHASE_A],
|
|
meter_info->var.p[IOT_BRM_PHASE_B],
|
|
meter_info->var.p[IOT_BRM_PHASE_C]);
|
|
iot_cus_printf("cur state--%d, p_trap--%d, i_standby--%d, i_work--%d\n",
|
|
brm_adp_context.dev_fsm.cur_state, thr->p_trap,
|
|
thr->i_standby, thr->i_work);
|
|
|
|
/* check P > P(trap). */
|
|
if (tt_power > ABS(thr->p_trap)) {
|
|
if (DM_STATE_DEV_TRAPING != brm_adp_context.dev_fsm.cur_state) {
|
|
iot_brm_adp_fsm_evt_req_change(&env_rcd, DM_EVENT_DEV_TRAP_START);
|
|
} else {
|
|
iot_brm_adp_fsm_reset_req_cnt();
|
|
}
|
|
} else {
|
|
if (DM_STATE_DEV_TRAPING == brm_adp_context.dev_fsm.cur_state) {
|
|
if (!iot_brm_adp_fsm_evt_req_change(&env_rcd,
|
|
DM_EVENT_DEV_TRAP_STOP)) {
|
|
return;
|
|
}
|
|
brm_adp_context.dev_fsm.chg_req_cnt = 2;
|
|
}
|
|
|
|
/* check I > I(work). */
|
|
if (tt_current > ABS(thr->i_work)) {
|
|
if (DM_STATE_DEV_WORKING != brm_adp_context.dev_fsm.cur_state) {
|
|
iot_brm_adp_fsm_evt_set_req_bitmap(DM_EVENT_DEV_WORK_START);
|
|
iot_brm_adp_fsm_evt_req_change(&env_rcd,
|
|
DM_EVENT_DEV_WORK_START);
|
|
} else {
|
|
iot_brm_adp_fsm_reset_req_cnt();
|
|
}
|
|
} else {
|
|
if (DM_STATE_DEV_WORKING == brm_adp_context.dev_fsm.cur_state) {
|
|
if (!iot_brm_adp_fsm_evt_req_change(&env_rcd,
|
|
DM_EVENT_DEV_WORK_STOP)) {
|
|
/* if not confirmed need wait */
|
|
return;
|
|
}
|
|
brm_adp_context.dev_fsm.chg_req_cnt = 2;
|
|
}
|
|
|
|
/* check I > I(standby). */
|
|
if (tt_current > ABS(thr->i_standby)) {
|
|
if (DM_STATE_DEV_STANDBY != brm_adp_context.dev_fsm.cur_state) {
|
|
iot_brm_adp_fsm_evt_set_req_bitmap(DM_EVENT_DEV_POWER_ON);
|
|
iot_brm_adp_fsm_evt_req_change(&env_rcd,
|
|
DM_EVENT_DEV_POWER_ON);
|
|
} else {
|
|
iot_brm_adp_fsm_reset_req_cnt();
|
|
}
|
|
} else {
|
|
if (DM_STATE_DEV_OFFLINE != brm_adp_context.dev_fsm.cur_state) {
|
|
iot_brm_adp_fsm_evt_set_req_bitmap(DM_EVENT_DEV_POWER_OFF);
|
|
iot_brm_adp_fsm_evt_req_change(&env_rcd,
|
|
DM_EVENT_DEV_POWER_OFF);
|
|
} else {
|
|
iot_brm_adp_fsm_reset_req_cnt();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* Device fsm handle used when no device plug into our brm state. */
|
|
static brm_adp_dev_state_e brm_adp_dev_fsm_handle_dev_offline(uint32_t event,
|
|
iot_brm_event_record_t *p_event_record)
|
|
{
|
|
uint8_t save_event = 0;
|
|
brm_adp_dev_state_e state = brm_adp_context.dev_fsm.cur_state;
|
|
|
|
switch (event) {
|
|
case DM_EVENT_DEV_POWER_ON:
|
|
{
|
|
/* Switch offline state to standby state. */
|
|
state = DM_STATE_DEV_STANDBY;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_WORK_START:
|
|
{
|
|
/* Switch offline state to working state. */
|
|
state = DM_STATE_DEV_WORKING;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_TRAP_START:
|
|
{
|
|
/* Switch offline state to traping state. */
|
|
state = DM_STATE_DEV_TRAPING;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
default:
|
|
iot_cus_printf("[brmadp] %s event=%d, device fsm state wrong!\n",
|
|
__FUNCTION__, event);
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if (save_event){
|
|
/* Save event record to flash. */
|
|
iot_cus_printf("[brmadp] %s write event=%d record\n",
|
|
__FUNCTION__, event);
|
|
iot_brm_adp_evt_save(p_event_record);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
/* Device fsm handle used when device plug into our brm,
|
|
* staying in standby state.
|
|
*/
|
|
static brm_adp_dev_state_e brm_adp_dev_fsm_handle_dev_standby(uint32_t event,
|
|
iot_brm_event_record_t *p_event_record)
|
|
{
|
|
uint8_t save_event = 0;
|
|
brm_adp_dev_state_e state = brm_adp_context.dev_fsm.cur_state;
|
|
|
|
switch (event) {
|
|
case DM_EVENT_DEV_POWER_OFF:
|
|
{
|
|
/* Switch standby state to offline state. */
|
|
state = DM_STATE_DEV_OFFLINE;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_WORK_START:
|
|
{
|
|
/* Switch standby state to working state. */
|
|
state = DM_STATE_DEV_WORKING;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_TRAP_START:
|
|
{
|
|
/* Switch standby state to traping state. */
|
|
state = DM_STATE_DEV_TRAPING;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
default:
|
|
iot_cus_printf("[brmadp] %s event=%d, device fsm state wrong!\n",
|
|
__FUNCTION__, event);
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if (save_event){
|
|
/* Save event record to flash. */
|
|
iot_cus_printf("[brmadp] %s write event=%d record\n",
|
|
__FUNCTION__, event);
|
|
iot_brm_adp_evt_save(p_event_record);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
/* Device fsm handle used when device plug into our brm,
|
|
* working right state.
|
|
*/
|
|
static brm_adp_dev_state_e brm_adp_dev_fsm_handle_dev_work(uint32_t event,
|
|
iot_brm_event_record_t *p_event_record)
|
|
{
|
|
uint8_t save_event = 0;
|
|
brm_adp_dev_state_e state = brm_adp_context.dev_fsm.cur_state;
|
|
|
|
switch (event) {
|
|
case DM_EVENT_DEV_POWER_ON:
|
|
{
|
|
/* Switch working state to standby state. */
|
|
state = DM_STATE_DEV_STANDBY;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_POWER_OFF:
|
|
{
|
|
/* Switch working state to offline state. */
|
|
state = DM_STATE_DEV_OFFLINE;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_WORK_STOP:
|
|
{
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_TRAP_START:
|
|
{
|
|
/* Switch working state to traping state. */
|
|
state = DM_STATE_DEV_TRAPING;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
default:
|
|
iot_cus_printf("[brmadp] %s event=%d, device fsm state wrong!\n",
|
|
__FUNCTION__, event);
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if (save_event){
|
|
/* Save event record to flash. */
|
|
iot_cus_printf("[brmadp] %s write event=%d record\n",
|
|
__FUNCTION__, event);
|
|
iot_brm_adp_evt_save(p_event_record);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
/* Device fsm handle used when device plug into our brm,
|
|
* running in trouble state.
|
|
*/
|
|
static brm_adp_dev_state_e brm_adp_dev_fsm_handle_dev_traping(uint32_t event,
|
|
iot_brm_event_record_t *p_event_record)
|
|
{
|
|
uint8_t save_event = 0;
|
|
brm_adp_dev_state_e state = brm_adp_context.dev_fsm.cur_state;
|
|
|
|
switch (event) {
|
|
case DM_EVENT_DEV_POWER_ON:
|
|
{
|
|
/* Switch traping state to standby state. */
|
|
state = DM_STATE_DEV_STANDBY;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_POWER_OFF:
|
|
{
|
|
/* Switch traping state to offline state. */
|
|
state = DM_STATE_DEV_OFFLINE;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_WORK_START:
|
|
{
|
|
/* Switch traping state to working state. */
|
|
state = DM_STATE_DEV_WORKING;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_WORK_STOP:
|
|
{
|
|
/* Switch traping state to standby state. */
|
|
state = DM_STATE_DEV_STANDBY;
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
case DM_EVENT_DEV_TRAP_STOP:
|
|
{
|
|
save_event = 1;
|
|
break;
|
|
}
|
|
default:
|
|
iot_cus_printf("[brmadp] %s event=%d, device fsm state wrong!\n",
|
|
__FUNCTION__, event);
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if (save_event){
|
|
/* Save event record to flash. */
|
|
iot_cus_printf("[brmadp] %s write event=%d record\n",
|
|
__FUNCTION__, event);
|
|
iot_brm_adp_evt_save(p_event_record);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
/* The table of device finite state machine handle */
|
|
static brm_adp_dev_fsm_handle_t dev_fsm_handle_table[BRM_ADP_DEV_STATE_MAX] =
|
|
{
|
|
brm_adp_dev_fsm_handle_dev_offline, /* DM_STATE_DEV_OFFLINE */
|
|
brm_adp_dev_fsm_handle_dev_standby, /* DM_STATE_DEV_STANDBY */
|
|
brm_adp_dev_fsm_handle_dev_work, /* DM_STATE_DEV_WORKING */
|
|
brm_adp_dev_fsm_handle_dev_traping, /* DM_STATE_DEV_TRAPING */
|
|
};
|
|
|
|
uint8_t iot_brm_adp_threshold_load(void)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
|
|
iot_cus_printf("[brmadp] read to_add=%p\n", &(brm_adp_context.threshold));
|
|
ret = iot_brm_flash_read(IOT_BRM_ADP_THRESHOLD_START,
|
|
(uint8_t*)(&(brm_adp_context.threshold)), sizeof(iot_brm_threshold_t));
|
|
if (ret) {
|
|
iot_cus_printf("[brmadp] %s err:%d\n", __FUNCTION__, ret);
|
|
} else {
|
|
iot_cus_printf("[brmadp] %s threshold:%d %d %d\n", __FUNCTION__,
|
|
brm_adp_context.threshold.i_standby,
|
|
brm_adp_context.threshold.i_work,
|
|
brm_adp_context.threshold.p_trap);
|
|
if (brm_adp_context.threshold.i_standby == 0xFFFFFFFF ||
|
|
brm_adp_context.threshold.i_work == 0xFFFFFFFF ||
|
|
brm_adp_context.threshold.p_trap == 0xFFFFFFFF) {
|
|
ret = ERR_FAIL;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
iot_brm_threshold_t *iot_brm_adp_get_threshold(void)
|
|
{
|
|
return &brm_adp_context.threshold;
|
|
}
|
|
|
|
void iot_brm_adp_threshold_save(iot_brm_threshold_t *threshold)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
|
|
if (threshold->i_standby != brm_adp_context.threshold.i_standby ||
|
|
threshold->i_work != brm_adp_context.threshold.i_work ||
|
|
threshold->p_trap != brm_adp_context.threshold.p_trap) {
|
|
brm_adp_context.threshold.i_standby = threshold->i_standby;
|
|
brm_adp_context.threshold.i_work = threshold->i_work;
|
|
brm_adp_context.threshold.p_trap = threshold->p_trap;
|
|
iot_cus_printf("[brmadp] %s threshold:%d %d %d\n", __FUNCTION__,
|
|
brm_adp_context.threshold.i_standby,
|
|
brm_adp_context.threshold.i_work,
|
|
brm_adp_context.threshold.p_trap);
|
|
ret = iot_brm_flash_write(IOT_BRM_ADP_THRESHOLD_START,
|
|
(uint8_t*)(&(brm_adp_context.threshold)), sizeof(iot_brm_threshold_t));
|
|
if (ret) {
|
|
iot_cus_printf("[brmadp] %s err:%d\n", __FUNCTION__, ret);
|
|
}
|
|
} else {
|
|
iot_cus_printf("[brmadp] %s no need to save\n", __FUNCTION__);
|
|
}
|
|
}
|
|
|
|
uint8_t iot_brm_adp_bottom_val_load(void)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
ret = iot_brm_flash_read(IOT_BRM_ADP_THRESHOLD_END,
|
|
(uint8_t*)&brm_adp_context.meter_bottom_val, sizeof(uint32_t));
|
|
if (ret) {
|
|
iot_cus_printf("[brmadp] %s err:%d\n", __FUNCTION__, ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void iot_brm_adp_bottom_val_save(uint32_t bottom_val)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
if (bottom_val != brm_adp_context.meter_bottom_val) {
|
|
iot_cus_printf("[brmadp] %s %d\n", __FUNCTION__,
|
|
brm_adp_context.meter_bottom_val);
|
|
ret = iot_brm_flash_write(IOT_BRM_ADP_THRESHOLD_END,
|
|
(uint8_t*)&brm_adp_context.meter_bottom_val, sizeof(uint32_t));
|
|
|
|
if (ret) {
|
|
iot_cus_printf("[brmadp] %s err:%d\n", __FUNCTION__, ret);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint8_t iot_brm_get_adp_evt_entry_size(void)
|
|
{
|
|
return sizeof(iot_brm_rec_head_t) + sizeof(iot_brm_load_record_t);
|
|
}
|
|
|
|
/* Save event record to flash. */
|
|
void iot_brm_adp_evt_save(iot_brm_event_record_t *p_evt_rec)
|
|
{
|
|
iot_brm_rec_head_t *hdr;
|
|
|
|
hdr = (iot_brm_rec_head_t *)g_buf;
|
|
hdr->rec_seq = g_adp_evt_rcd_region.seq;
|
|
hdr->ts = p_evt_rec->time;
|
|
os_mem_cpy(hdr->data, &p_evt_rec->rcd_data, sizeof(iot_brm_load_record_t));
|
|
|
|
iot_brm_data_print("iot_brm_adp_evt_save:", g_buf,
|
|
g_adp_evt_rcd_region.entry_size);
|
|
iot_brm_rec_write(&g_adp_evt_rcd_region,
|
|
p_evt_rec->time, g_buf, 1, 0);
|
|
return;
|
|
}
|
|
|
|
/* read event record count of daily storage. */
|
|
uint8_t iot_brm_read_adp_evt_daily_cnt(uint32_t ts)
|
|
{
|
|
uint8_t count = 0;
|
|
uint8_t ret;
|
|
uint32_t i, n_per, remain_n, read_n, pos, idx;
|
|
uint8_t *data;
|
|
uint8_t crc;
|
|
iot_brm_rec_head_t *hdr;
|
|
iot_brm_rec_region_desc_t *region = &g_adp_evt_rcd_region;
|
|
|
|
//read 1k Bytes data every time
|
|
n_per = IOT_BRM_ADP_REC_READ_BUF_SIZE / region->entry_size;
|
|
remain_n = region->rec_depth;
|
|
for (idx = 0, pos = region->start; remain_n; ) {
|
|
read_n = (remain_n >= n_per ? n_per : remain_n);
|
|
pos = region->start + idx * region->entry_size;
|
|
ret = iot_brm_flash_read(pos, g_buf, read_n * region->entry_size);
|
|
if (ret) {
|
|
break;
|
|
}
|
|
data = g_buf;
|
|
for (i = 0; i < read_n; i++) {
|
|
hdr = (iot_brm_rec_head_t *)data;
|
|
crc = iot_getcrc8(hdr->data, region->entry_size - sizeof(*hdr));
|
|
/* traverse all valid records */
|
|
if (crc == hdr->crc) {
|
|
//check
|
|
if (hdr->ts - ts > 0 && (hdr->ts - ts) < (60*60*24)){
|
|
iot_cus_printf("read rcd_ts=%lu que_ts=%lu\n",hdr->ts, ts);
|
|
count++;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
data += region->entry_size;
|
|
idx++;
|
|
}
|
|
pos += read_n * region->entry_size;
|
|
remain_n -= read_n;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/* load event record from flash. */
|
|
uint8_t iot_brm_adp_evt_load(uint32_t ts, uint8_t start_inx, uint8_t cnt,
|
|
iot_pkt_t **pkt)
|
|
{
|
|
uint8_t count = 0;
|
|
uint8_t resp_cnt = 0;
|
|
uint32_t i, n_per, remain_n, read_n, pos, idx;
|
|
uint8_t *data;
|
|
uint8_t crc;
|
|
iot_brm_rec_head_t *hdr;
|
|
iot_pkt_t *buf = NULL;
|
|
uint8_t *data_pos = NULL;
|
|
iot_brm_rec_region_desc_t *region = &g_adp_evt_rcd_region;
|
|
|
|
buf = iot_pkt_alloc(sizeof(proto_645_ext_event_record_item_t) * cnt,
|
|
IOT_BRM_MID);
|
|
if (buf == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
//read 1k Bytes data every time
|
|
n_per = IOT_BRM_ADP_REC_READ_BUF_SIZE / region->entry_size;
|
|
remain_n = region->rec_depth;
|
|
for (idx = 0, pos = region->start; remain_n; ) {
|
|
read_n = (remain_n >= n_per ? n_per : remain_n);
|
|
pos = region->start + idx * region->entry_size;
|
|
if (iot_brm_flash_read(pos, g_buf, read_n * region->entry_size)) {
|
|
goto err;
|
|
}
|
|
data = g_buf;
|
|
for (i = 0; i < read_n; i++) {
|
|
hdr = (iot_brm_rec_head_t *)data;
|
|
crc = iot_getcrc8(hdr->data, region->entry_size - sizeof(*hdr));
|
|
/* traverse all valid records */
|
|
if (crc == hdr->crc) {
|
|
//check
|
|
if (hdr->ts - ts > 0 && (hdr->ts - ts) < (60*60*24)){
|
|
count++;
|
|
if (count > start_inx && resp_cnt < cnt) {
|
|
iot_cus_printf("read rcd_ts=%lu que_ts=%lu\n",hdr->ts, ts);
|
|
data_pos = iot_pkt_data(buf) +
|
|
sizeof(proto_645_ext_event_record_item_t) * resp_cnt;
|
|
iot_brm_adp_trans_evt_to_resp((uint8_t*)hdr, data_pos);
|
|
iot_pkt_put(buf, sizeof(proto_645_ext_event_record_item_t));
|
|
resp_cnt++;
|
|
} else if (resp_cnt >= cnt) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
data += region->entry_size;
|
|
idx++;
|
|
}
|
|
pos += read_n * region->entry_size;
|
|
remain_n -= read_n;
|
|
}
|
|
|
|
iot_cus_printf("read cnt=%d\n", resp_cnt);
|
|
iot_brm_data_print("evt_load", iot_pkt_data(buf), iot_pkt_data_len(buf));
|
|
|
|
err:
|
|
|
|
if (resp_cnt == 0 && buf != NULL) {
|
|
iot_pkt_free(buf);
|
|
} else {
|
|
*pkt = buf;
|
|
}
|
|
|
|
return resp_cnt;
|
|
}
|
|
|
|
|
|
/* load the latest event record from flash. */
|
|
uint8_t iot_brm_adp_latest_evt_load(iot_pkt_t **pkt)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
uint8_t *data;
|
|
uint8_t crc;
|
|
iot_brm_rec_head_t *hdr;
|
|
iot_pkt_t *buf = NULL;
|
|
uint32_t pos = 0;
|
|
iot_brm_rec_region_desc_t *region = &g_adp_evt_rcd_region;
|
|
|
|
buf = iot_pkt_alloc(sizeof(proto_645_ext_event_record_item_t), IOT_BRM_MID);
|
|
if (buf == NULL) {
|
|
iot_cus_printf("[brmadp]alloc pkt failed!\n");
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
pos = region->start + (region->new_idx - 1) * region->entry_size;
|
|
if (iot_brm_flash_read(pos, g_buf, region->entry_size)) {
|
|
ret = ERR_FAIL;
|
|
iot_cus_printf("[brmadp]read flash ERROR!\n");
|
|
goto out;
|
|
}
|
|
|
|
data = g_buf;
|
|
|
|
hdr = (iot_brm_rec_head_t *)data;
|
|
crc = iot_getcrc8(hdr->data, region->entry_size - sizeof(*hdr));
|
|
/* traverse all valid records */
|
|
if (crc == hdr->crc) {
|
|
iot_brm_adp_trans_evt_to_resp((uint8_t *)hdr, iot_pkt_data(buf));
|
|
iot_pkt_put(buf, sizeof(proto_645_ext_event_record_item_t));
|
|
} else {
|
|
iot_cus_printf("[brmadp]Event CRC err, dropped!\n");
|
|
}
|
|
|
|
iot_brm_data_print("latest evt_load", iot_pkt_data(buf),
|
|
iot_pkt_data_len(buf));
|
|
|
|
out:
|
|
*pkt = buf;
|
|
return ret;
|
|
}
|
|
|
|
|
|
/* get load record from flash. */
|
|
uint8_t iot_brm_adp_load_data(uint32_t ts, uint8_t cnt, iot_pkt_t **pkt)
|
|
{
|
|
uint8_t resp_cnt = 0, crc;
|
|
uint8_t *data;
|
|
uint16_t resp_idx = 0;
|
|
uint32_t i, n_per, remain_n, read_n, pos, idx;
|
|
iot_brm_rec_head_t *hdr;
|
|
iot_pkt_t *buf = NULL;
|
|
uint8_t *data_pos = NULL;
|
|
iot_brm_rec_region_desc_t *region = iot_brm_get_cur_reg();
|
|
|
|
buf = iot_pkt_alloc(sizeof(proto_645_ext_load_diagram_item_t) * cnt,
|
|
IOT_BRM_MID);
|
|
if (buf == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
/* fill pkt */
|
|
iot_pkt_put(buf, sizeof(proto_645_ext_load_diagram_item_t) * cnt);
|
|
iot_brm_adp_load_resp_init(iot_pkt_data(buf), ts, cnt);
|
|
|
|
//read 1k Bytes data every time
|
|
n_per = IOT_BRM_ADP_REC_READ_BUF_SIZE / region->entry_size;
|
|
remain_n = region->rec_depth;
|
|
for (idx = 0, pos = region->start; remain_n; ) {
|
|
read_n = (remain_n >= n_per ? n_per : remain_n);
|
|
pos = region->start + idx * region->entry_size;
|
|
if (iot_brm_flash_read(pos, g_buf, read_n * region->entry_size)) {
|
|
goto err;
|
|
}
|
|
data = g_buf;
|
|
for (i = 0; i < read_n; i++) {
|
|
hdr = (iot_brm_rec_head_t *)data;
|
|
crc = iot_getcrc8(hdr->data, region->entry_size - sizeof(*hdr));
|
|
/* traverse all valid records */
|
|
if (crc == hdr->crc) {
|
|
/* check ts */
|
|
if (hdr->ts >= ts && ((hdr->ts - ts) % 15*60) == 0) {
|
|
resp_idx = (hdr->ts - ts) / 900;
|
|
if (resp_cnt >= cnt ) {
|
|
goto end;
|
|
} else if (resp_idx < cnt) {
|
|
iot_cus_printf("read ts=%lu que_ts=%lu resp_idx=%d\n",
|
|
hdr->ts, ts, resp_idx);
|
|
data_pos = iot_pkt_data(buf) +
|
|
sizeof(proto_645_ext_load_diagram_item_t) * resp_idx;
|
|
iot_brm_adp_trans_load_to_resp((uint8_t*)hdr, data_pos);
|
|
resp_cnt++;
|
|
}
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
data += region->entry_size;
|
|
idx++;
|
|
}
|
|
pos += read_n * region->entry_size;
|
|
remain_n -= read_n;
|
|
}
|
|
end:
|
|
resp_cnt = cnt;
|
|
iot_cus_printf("read cnt=%d\n", resp_cnt);
|
|
iot_brm_data_print("resp_load", iot_pkt_data(buf), iot_pkt_data_len(buf));
|
|
|
|
err:
|
|
if (resp_cnt == 0 && buf != NULL) {
|
|
iot_pkt_free(buf);
|
|
} else {
|
|
*pkt = buf;
|
|
}
|
|
|
|
return resp_cnt;
|
|
}
|
|
|
|
/* sent the latest event record once joined the network */
|
|
static void iot_brm_adp_evt_send_at_join_in(void)
|
|
{
|
|
if (brm_adp_context.evt_on_join == 0) {
|
|
/* send the latest event record once sta joins in */
|
|
if (brm_adp_context.link_ready == 1) {
|
|
iot_brm_adp_event_report(NULL);
|
|
brm_adp_context.evt_on_join = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* update plc status: joined or not */
|
|
static void iot_brm_adp_plc_status_update(void)
|
|
{
|
|
uint16_t link_ready = 0;
|
|
|
|
link_ready = iot_brm_get_plc_state();
|
|
/* clear the event flag once sta leaves */
|
|
if (link_ready == 0) {
|
|
if (brm_adp_context.link_ready == 1) {
|
|
brm_adp_context.evt_on_join = 0;
|
|
}
|
|
}
|
|
if (brm_adp_context.link_ready != link_ready) {
|
|
brm_adp_context.link_ready = link_ready;
|
|
}
|
|
}
|
|
|
|
void iot_brm_adp_evt_region_init(void)
|
|
{
|
|
uint32_t start = IOT_BRM_ADP_EVT_REGION_START;
|
|
g_adp_evt_rcd_region.start = start;
|
|
g_adp_evt_rcd_region.entry_size = iot_brm_get_adp_evt_entry_size();
|
|
g_adp_evt_rcd_region.size =
|
|
g_adp_evt_rcd_region.entry_size * IOT_BRM_REC_ADP_EVT_MAX;
|
|
g_adp_evt_rcd_region.rec_depth = IOT_BRM_REC_ADP_EVT_MAX;
|
|
start += g_adp_evt_rcd_region.size;
|
|
iot_brm_printf("%s - rec_adp_evt_region: [%08x - %08x], block %lu, "
|
|
"entry_size %lu\n", __FUNCTION__,
|
|
g_adp_evt_rcd_region.start, start - 1,
|
|
g_adp_evt_rcd_region.rec_depth,
|
|
g_adp_evt_rcd_region.entry_size);
|
|
|
|
iot_brm_rec_load(&g_adp_evt_rcd_region, 0);
|
|
IOT_ASSERT(start <= IOT_BRM_ADP_EVT_REGION_END);
|
|
}
|
|
|
|
uint32_t iot_brm_adp_init(void)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
|
|
os_mem_set(&brm_adp_context, 0x0, sizeof(brm_adp_context));
|
|
|
|
g_buf = os_mem_malloc(IOT_BRM_MID, IOT_BRM_ADP_REC_READ_BUF_SIZE);
|
|
if (g_buf == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
/* Init device finite state machine. */
|
|
brm_adp_context.dev_fsm.prev_state = DM_STATE_DEV_OFFLINE;
|
|
brm_adp_context.dev_fsm.cur_state = DM_STATE_DEV_OFFLINE;
|
|
brm_adp_context.dev_fsm.table.handle = dev_fsm_handle_table;
|
|
|
|
/* Init adp record event */
|
|
iot_brm_adp_evt_region_init();
|
|
|
|
if (ERR_OK != iot_brm_adp_threshold_load()) {
|
|
brm_adp_context.threshold.p_trap = 20000; /* mW*/
|
|
brm_adp_context.threshold.i_standby = 10; /* ma*/
|
|
brm_adp_context.threshold.i_work = 500; /* ma*/
|
|
iot_cus_printf("[brmadp][war] load threshold failed, "
|
|
"use default threshold i_standby=%d i_work=%d p_trap=%d\n",
|
|
brm_adp_context.threshold.i_standby,
|
|
brm_adp_context.threshold.i_work,
|
|
brm_adp_context.threshold.p_trap);
|
|
iot_brm_adp_threshold_save(&brm_adp_context.threshold);
|
|
}
|
|
|
|
iot_brm_evt_init(iot_brm_evt_adp_id, NULL, 1);
|
|
|
|
iot_cus_printf("[brmadp] %s module ver:%s, init successfully!\n",
|
|
__FUNCTION__, BRM_ADP_MODULE_VERSION);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
#endif /* end (IOT_BRM_ENABLE && PLC_SUPPORT_STA_ROLE) */
|
|
|