/**************************************************************************** * * 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) */