/* * Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved. * Description: Simulate Meter handler. */ #include "mrs_sta_simu_meter.h" #include "mrs_sta_srv.h" #include "mrs_sta_plc.h" #include "mrs_sta_io.h" #include "mrs_msg.h" #include "mrs_common_uart.h" #include "mrs_common_tools.h" #include "mrs_proto_645.h" #include "mrs_dfx.h" #include "app_nv.h" #if defined(PRODUCT_CFG_PRODUCT_TYPE_STA) typedef td_void (*simu_di_proc)(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len); typedef struct { td_u32 di; simu_di_proc proc; } simu_di_pair; typedef struct { td_bool simu_flag; td_u8 simu_evt_en; td_u8 meter[EXT_METER_ADDR_LEN]; } simu_meter_ctx; /* Handlers */ td_void simu_di_05060001(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len); td_void simu_di_05060101(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len); td_void simu_di_00010000(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len); td_void simu_di_04001501(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len); td_void mrs_simu_meter_init(td_void); td_u16 mrs_simu_meter_send(td_pbyte buffer, td_u16 length); simu_meter_ctx g_simu_meter_ctx = { TD_FALSE, 0, { 0 } }; td_void mrs_simu_meter_enable(td_bool enable) { if (enable == g_simu_meter_ctx.simu_flag) { return; } g_simu_meter_ctx.simu_flag = enable; if (enable == TD_TRUE) { mrs_simu_meter_init(); } } td_bool mrs_simu_meter_flag(td_void) { return g_simu_meter_ctx.simu_flag; } td_void mrs_simu_meter_init(td_void) { mrs_sta_srv_ctx *sta = mrs_sta_get_srv_ctx(); td_u8 mac[EXT_METER_ADDR_LEN] = { 0 }; td_u32 l; td_u32 h; uapi_get_local_mac_addr(mac, sizeof(mac)); h = ((td_u32)mac[2] * 1000) + mac[3]; /* index 2*1000 add index 3 */ l = ((td_u32)mac[4] * 1000) + mac[5]; /* index 4*1000 add index 5 */ mrs_convert_int_to_bcd(h, g_simu_meter_ctx.meter + 3, 3); /* shifts 3 */ mrs_convert_int_to_bcd(l, g_simu_meter_ctx.meter, 3); /* low 3bytes */ (td_void) memcpy_s(sta->meter, sizeof(sta->meter), g_simu_meter_ctx.meter, sizeof(g_simu_meter_ctx.meter)); sta->protocol = METER_PROTO_645_2007; sta->baudrate = MRS_STA_DEFAULT_BAUDRATE; mrs_convert_meter_to_mac(sta->meter, sizeof(sta->meter), sta->mac, sizeof(sta->mac)); mrs_sta_set_mac_addr(sta->mac); mrs_uart_register_tx_callback(mrs_simu_meter_send); mrs_sta_led_offline(); mrs_simu_meter_nv_detect(); } td_void mrs_simu_meter_nv_detect(td_void) { mrs_simu_meter_inf simu = { 0, 0, 0, 0 }; if (uapi_nv_read(ID_NV_APP_SIMU_METER, &simu, sizeof(simu)) == EXT_ERR_SUCCESS) { if ((simu.simu_meter == 1) && (simu.simu_evt == 1)) { g_simu_meter_ctx.simu_evt_en = simu.simu_evt; mrs_timer_start(MRS_TIMER_ID_STA_IO_EVTOUT, simu.simu_evt_delay * 10000, /* time*10000 */ EXT_TIMER_TYPE_ONCE); } } } td_u16 mrs_simu_meter_send(td_pbyte buf, td_u16 len) { td_u32 di, i; td_u16 start_pos = 0; td_u16 frame_len = 0; td_pbyte frame; /* 0x05060001, daily-freeze clock * 0x05060101, daily-freeze positive active ennergy data * 0x00010000, total positive active ennergy * 0x04001501, report event by self */ simu_di_pair di_pair_tbl[] = { { 0x05060001, simu_di_05060001 }, { 0x05060101, simu_di_05060101 }, { 0x00010000, simu_di_00010000 }, { 0x04001501, simu_di_04001501 }, }; mrs_logbuf("[SIMU-Rx]: ", buf, len); if (mrs_proto_645_find_frame(buf, len, &start_pos, &frame_len) != EXT_ERR_SUCCESS) { return len; } frame = buf + start_pos; if (memcmp(g_simu_meter_ctx.meter, frame + MRS_645_FRAME_METERADD_OFFSET, MRS_METER_ADDR_LEN) != 0) { mrs_logbuf("meter addr: ", g_simu_meter_ctx.meter, sizeof(g_simu_meter_ctx.meter)); mrs_logbuf("frame addr: ", (frame + MRS_645_FRAME_METERADD_OFFSET), MRS_METER_ADDR_LEN); return len; } if ((frame[MRS_645_FRAME_CTRL_OFFSET] != MRS_645_CTRL_READ_DATA) || (frame[MRS_645_FRAME_LEN_OFFSET] != MRS_645_DATA_DI_SIZE)) { return len; } mrs_proto_645_data_decode(frame + MRS_645_FRAME_DATA_OFFSET, MRS_645_DATA_DI_SIZE); (td_void) memcpy_s(&di, sizeof(di), frame + MRS_645_FRAME_DATA_OFFSET, MRS_645_DATA_DI_SIZE); for (i = 0; i < ext_array_count(di_pair_tbl); i++) { if (di == di_pair_tbl[i].di) { mrs_proto_645_frame_inf param; td_pbyte out_buf = TD_NULL; td_u16 out_len = 0; if (memcpy_s(param.addr, sizeof(param.addr), frame + MRS_645_FRAME_METERADD_OFFSET, MRS_METER_ADDR_LEN) != EOK) { break; } param.ctrl = frame[MRS_645_FRAME_CTRL_OFFSET] | 0x80; di_pair_tbl[i].proc(¶m, &out_buf, &out_len); if (out_buf == TD_NULL) { break; } mrs_logbuf("[SIMU-Tx]: ", out_buf, out_len); mrs_dfx_uart_chl_rx(out_buf, out_len, TD_FALSE); if (mrs_msg_queue_send(MRS_MSG_ID_APP_FRAME_RX_645, out_len, (uintptr_t)out_buf, 0) != EXT_ERR_SUCCESS) { mrs_free(out_buf); } break; } } return len; } td_void simu_di_05060001(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len) { td_u8 data[9] = { 0x01, 0x00, 0x06, 0x05, 0x00, 0x00, 0x01, 0x03, 0x19 }; /* data 9B */ frame->data_len = sizeof(data); frame->data = data; (td_void) mrs_proto_645_create_frame(frame, out_buf, out_len); frame->data = TD_NULL; } td_void simu_di_05060101(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len) { td_u8 data[24] = { 0x01, 0x01, 0x06, 0x05 }; /* data 24B */ frame->data_len = sizeof(data); frame->data = data; (td_void) mrs_proto_645_create_frame(frame, out_buf, out_len); frame->data = TD_NULL; } td_void simu_di_00010000(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len) { td_u8 data[8] = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* data 8B */ frame->data_len = sizeof(data); frame->data = data; (td_void) mrs_proto_645_create_frame(frame, out_buf, out_len); frame->data = TD_NULL; } td_void simu_di_04001501(mrs_proto_645_frame_inf *frame, td_pbyte *out_buf, td_u16 *out_len) { td_u8 data[19] = { /* data 19B */ 0x01, 0x15, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x01, 0xaa }; if (g_simu_meter_ctx.simu_evt_en == 0) { out_buf = TD_NULL; return; } frame->data_len = sizeof(data); frame->data = data; (td_void) mrs_proto_645_create_frame(frame, out_buf, out_len); frame->data = TD_NULL; } #endif