2161 lines
75 KiB
C
2161 lines
75 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_utils_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_io_api.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
/* smart grid internal header files */
|
|
#include "iot_sg_fr.h"
|
|
#include "iot_sg.h"
|
|
#include "proto_645.h"
|
|
#include "proto_69845.h"
|
|
#include "iot_sg_sta.h"
|
|
#include "iot_sg_sta_ext.h"
|
|
#include "iot_sg_sta_flash.h"
|
|
#include "iot_sg_sta_cfg_flash.h"
|
|
|
|
#if (IOT_SMART_GRID_EXT_LR_FUNC_ENABLE)
|
|
|
|
/* define cnt of load curve configuration */
|
|
#define IOT_SG_STA_EXT_LC_CFG_CNT (IOT_SG_STA_EXT_LC_PEIWANG + 1)
|
|
|
|
/* define extend function read load data default interval time, uint is 1s */
|
|
#define IOT_SG_STA_EXT_LC_INTER IOT_SG_STA_EXT_LC_CFG_PRD_15MIN
|
|
|
|
/* define 69845 meter data lr frame max oi number */
|
|
#define IOT_SG_STA_EXT_LR_FRAME_MAX_OI_NUM (6)
|
|
|
|
static uint32_t iot_sg_ext_lr_other_handle(void);
|
|
|
|
static const iot_sg_sta_ext_lc_cfg_t lc_cfg[IOT_SG_STA_EXT_LC_CFG_CNT] = {
|
|
{
|
|
.tm = {
|
|
.tm_year = 2000,
|
|
.tm_mon = 1,
|
|
.tm_mday = 1,
|
|
.tm_hour = 0,
|
|
.tm_min = 0,
|
|
.tm_sec = 0,
|
|
},
|
|
.interval = IOT_SG_STA_EXT_LC_INTER,
|
|
.cnt = 1,
|
|
.di_buf = {
|
|
PROTO_645_2007_DI_V_A,
|
|
},
|
|
},
|
|
{
|
|
.tm = {
|
|
.tm_year = 2000,
|
|
.tm_mon = 1,
|
|
.tm_mday = 1,
|
|
.tm_hour = 0,
|
|
.tm_min = 0,
|
|
.tm_sec = 0,
|
|
},
|
|
.interval = IOT_SG_STA_EXT_LC_INTER,
|
|
.cnt = 7,
|
|
.di_buf = {
|
|
PROTO_645_2007_DI_V_A,
|
|
PROTO_645_2007_DI_I_A,
|
|
PROTO_645_2007_DI_I_N,
|
|
PROTO_645_2007_DI_P_A,
|
|
PROTO_645_2007_DI_EPT_COMP_ALL,
|
|
PROTO_645_2007_DI_EPT_POS_ALL,
|
|
PROTO_645_2007_DI_EPT_NEG_ALL,
|
|
},
|
|
},
|
|
{
|
|
.tm = {
|
|
.tm_year = 2000,
|
|
.tm_mon = 1,
|
|
.tm_mday = 1,
|
|
.tm_hour = 0,
|
|
.tm_min = 0,
|
|
.tm_sec = 0,
|
|
},
|
|
.interval = IOT_SG_STA_EXT_LC_INTER,
|
|
.cnt = 22,
|
|
.di_buf = {
|
|
PROTO_645_2007_DI_V_ALL,
|
|
PROTO_645_2007_DI_I_ALL,
|
|
PROTO_645_2007_DI_I_N,
|
|
PROTO_645_2007_DI_P_ALL,
|
|
PROTO_645_2007_DI_Q_ALL,
|
|
PROTO_645_2007_DI_PF_ALL,
|
|
PROTO_645_2007_DI_EPT_COMP_ALL,
|
|
PROTO_645_2007_DI_EPT_POS_SUM,
|
|
PROTO_645_2007_DI_EPT_NEG_SUM,
|
|
PROTO_645_2007_DI_EQT_POS_SUM,
|
|
PROTO_645_2007_DI_EQT_NEG_SUM,
|
|
PROTO_645_2007_DI_EQT_QRT1_SUM,
|
|
PROTO_645_2007_DI_EQT_QRT2_SUM,
|
|
PROTO_645_2007_DI_EQT_QRT3_SUM,
|
|
PROTO_645_2007_DI_EQT_QRT4_SUM,
|
|
PROTO_645_2007_DI_EPT_DEMAND,
|
|
PROTO_645_2007_DI_EQT_DEMAND,
|
|
PROTO_645_2007_DI_EPT_POS_DEMAND,
|
|
PROTO_645_2007_DI_EPT_NEG_DEMAND,
|
|
PROTO_645_2007_DI_EPT_POS_A,
|
|
PROTO_645_2007_DI_EPT_POS_B,
|
|
PROTO_645_2007_DI_EPT_POS_C
|
|
},
|
|
},
|
|
{
|
|
.tm = {
|
|
.tm_year = 2000,
|
|
.tm_mon = 1,
|
|
.tm_mday = 1,
|
|
.tm_hour = 0,
|
|
.tm_min = 0,
|
|
.tm_sec = 0,
|
|
},
|
|
.interval = IOT_SG_STA_EXT_LC_INTER,
|
|
.cnt = 11,
|
|
.di_buf = {
|
|
PROTO_645_2007_DI_V_ALL,
|
|
PROTO_645_2007_DI_I_ALL,
|
|
PROTO_645_2007_DI_PF_ALL,
|
|
/* if sta can't read last frozen time,
|
|
* sta don't read frozen data. sta read
|
|
* current data from PROTO_645_2007_DI_EPT_POS_SUM
|
|
* to PROTO_645_2007_DI_Q_ALL.
|
|
*/
|
|
PROTO_645_2007_DI_RT_YMDHMS_LAST1,
|
|
PROTO_645_2007_DI_RT_EP_POS_LAST1,
|
|
PROTO_645_2007_DI_RT_EP_NEG_LAST1,
|
|
PROTO_645_2007_DI_RT_VARIABLE_LAST1,
|
|
/* current data */
|
|
PROTO_645_2007_DI_EPT_POS_SUM,
|
|
PROTO_645_2007_DI_EPT_NEG_SUM,
|
|
PROTO_645_2007_DI_P_ALL,
|
|
PROTO_645_2007_DI_Q_ALL,
|
|
},
|
|
},
|
|
};
|
|
|
|
static uint32_t iot_sg_ext_get_lr_di_idx(uint32_t di, uint8_t *idx)
|
|
{
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_lc_info_t *lr_info = &ext_info->lc_info;
|
|
|
|
for (uint8_t i = 0; i < lr_info->cfg->cnt; i++) {
|
|
if (lr_info->cfg->di_buf[i] == di) {
|
|
*idx = i;
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
static void iot_sg_ext_lr_cfg_pib_save(void)
|
|
{
|
|
uint8_t ref, period;
|
|
uint16_t ticket;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_clct_param *clct_param = &ext_info->clct_param;
|
|
iot_sg_sta_app_info_t *sta_pib = iot_sg_sta_get_rw_pib();
|
|
|
|
if (!sta_pib) {
|
|
goto drop;
|
|
}
|
|
if ((clct_param->cfg.interval != clct_param->cfg_cache.interval)
|
|
&& (sta_pib->ext_lr_period != clct_param->cfg_cache.interval)) {
|
|
period = (uint8_t)(clct_param->cfg_cache.interval / 60);
|
|
iot_sg_printf("%s period %lumin -> %lumin\n", __FUNCTION__,
|
|
sta_pib->ext_lr_period, period);
|
|
if (clct_param->cfg_cache.interval != IOT_SG_STA_EXT_LC_CFG_PRD_1MIN
|
|
&& clct_param->cfg_cache.interval != IOT_SG_STA_EXT_LC_CFG_PRD_5MIN
|
|
&& clct_param->cfg_cache.interval != IOT_SG_STA_EXT_LC_CFG_PRD_15MIN
|
|
&& clct_param->cfg_cache.interval != IOT_SG_STA_EXT_LC_CFG_PRD_30MIN
|
|
&& clct_param->cfg_cache.interval !=
|
|
IOT_SG_STA_EXT_LC_CFG_PRD_60MIN) {
|
|
period = IOT_SG_STA_EXT_LC_CFG_PRD_15MIN / 60;
|
|
}
|
|
iot_pib_acquire_app_commit_ref(&ref);
|
|
sta_pib->ext_lr_period = period;
|
|
iot_pib_release_app_commit_ref(&ref);
|
|
iot_pib_app_commit(&ticket);
|
|
}
|
|
return;
|
|
drop:
|
|
iot_sg_printf("%s err\n", __FUNCTION__);
|
|
}
|
|
|
|
static void iot_sg_ext_lr_get_pib_cfg(iot_sg_sta_ext_lc_cfg_t *cfg)
|
|
{
|
|
iot_sg_sta_app_info_t *sta_pib = iot_sg_sta_get_rw_pib();
|
|
|
|
if (!sta_pib) {
|
|
goto drop;
|
|
}
|
|
cfg->interval = sta_pib->ext_lr_period;
|
|
cfg->interval *= 60;
|
|
iot_sg_printf("%s pib period %lus\n", __FUNCTION__,
|
|
cfg->interval);
|
|
if (cfg->interval != IOT_SG_STA_EXT_LC_CFG_PRD_1MIN
|
|
&& cfg->interval != IOT_SG_STA_EXT_LC_CFG_PRD_5MIN
|
|
&& cfg->interval != IOT_SG_STA_EXT_LC_CFG_PRD_15MIN
|
|
&& cfg->interval != IOT_SG_STA_EXT_LC_CFG_PRD_30MIN
|
|
&& cfg->interval != IOT_SG_STA_EXT_LC_CFG_PRD_60MIN) {
|
|
cfg->interval = IOT_SG_STA_EXT_LC_CFG_PRD_15MIN;
|
|
}
|
|
iot_sg_printf("%s cfg period %lus\n", __FUNCTION__,
|
|
sta_pib->ext_lr_period);
|
|
return;
|
|
drop:
|
|
iot_sg_printf("%s err\n", __FUNCTION__);
|
|
}
|
|
|
|
static uint32_t iot_sg_ext_lr_cfg_reset(uint8_t cfg_id)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
|
|
if (cfg_id >= IOT_SG_STA_EXT_LC_CFG_CNT) {
|
|
ret = ERR_NOSUPP;
|
|
goto out;
|
|
}
|
|
ext_info->lc_info.cfg_index = cfg_id;
|
|
ext_info->clct_param.enabled = 1;
|
|
os_mem_set(&ext_info->lc_info.last_froze_tm, 0,
|
|
sizeof(ext_info->lc_info.last_froze_tm));
|
|
os_mem_set(&ext_info->lc_info.froze_tm, 0,
|
|
sizeof(ext_info->lc_info.froze_tm));
|
|
os_mem_cpy(&ext_info->clct_param.cfg, &lc_cfg[cfg_id],
|
|
sizeof(iot_sg_sta_ext_lc_cfg_t));
|
|
if (cfg_id == IOT_SG_STA_EXT_LC_XIAN_3P_CFG
|
|
|| cfg_id == IOT_SG_STA_EXT_LC_XIAN_CFG) {
|
|
iot_sg_ext_lr_get_pib_cfg(&ext_info->clct_param.cfg);
|
|
}
|
|
ext_info->lc_info.cfg = &ext_info->clct_param.cfg;
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
void iot_sg_ext_lr_cfg_update(void)
|
|
{
|
|
uint8_t flag_tm_reset = 0;
|
|
uint32_t idx;
|
|
iot_sg_sta_node_desc_t *node;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_clct_param *clct_param = &ext_info->clct_param;
|
|
|
|
if (clct_param->flag_update) {
|
|
clct_param->flag_update = 0;
|
|
if (clct_param->enabled) {
|
|
iot_sg_ext_lr_cfg_pib_save();
|
|
os_mem_cpy(&clct_param->cfg, &clct_param->cfg_cache,
|
|
sizeof(clct_param->cfg));
|
|
ext_info->lc_info.cfg = &clct_param->cfg;
|
|
flag_tm_reset = 1;
|
|
} else {
|
|
ext_info->lc_info.cfg = NULL;
|
|
}
|
|
iot_sg_printf("%s enable:%lu\n", __FUNCTION__, clct_param->enabled);
|
|
if (ext_info->lc_info.cfg) {
|
|
iot_sg_printf("%s interval %lu di cnt %lu\n", __FUNCTION__,
|
|
ext_info->lc_info.cfg->interval, ext_info->lc_info.cfg->cnt);
|
|
}
|
|
}
|
|
if (!clct_param->enabled && !p_sg_glb->dev_is_ready) {
|
|
iot_sg_ext_lr_cfg_reset(ext_info->lc_info.cfg_index);
|
|
flag_tm_reset = 1;
|
|
}
|
|
if (flag_tm_reset) {
|
|
os_mem_set(&ext_info->lc_info.last_froze_tm, 0,
|
|
sizeof(ext_info->lc_info.last_froze_tm));
|
|
os_mem_set(&ext_info->lc_info.froze_tm, 0,
|
|
sizeof(ext_info->lc_info.froze_tm));
|
|
for (idx = 0; idx < IOT_SG_STA_SEC_NODE_MAX; idx++) {
|
|
if (sta_glb->node_list[idx] != NULL) {
|
|
node = sta_glb->node_list[idx];
|
|
os_mem_set(&node->ext.lr_info.tm, 0x0,
|
|
sizeof(iot_time_tm_t));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void iot_sg_ext_lr_reset(void)
|
|
{
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
|
|
ext_info->lc_info.index = 0;
|
|
ext_info->lc_info.timeout_cnt = 0;
|
|
ext_info->lc_info.repeat_cnt = 0;
|
|
ext_info->lc_info.flag_resp = 0;
|
|
ext_info->lc_info.state = IOT_SG_STA_EXT_LC_STATE_IDLE;
|
|
}
|
|
|
|
uint32_t iot_sg_ext_lr_init(uint8_t cfg_id)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
|
|
if (ext_info->lc_info.cfg) {
|
|
goto out;
|
|
}
|
|
if (cfg_id >= IOT_SG_STA_EXT_LC_CFG_CNT) {
|
|
ret = ERR_NOSUPP;
|
|
goto out;
|
|
}
|
|
iot_sg_ext_lr_cfg_reset(cfg_id);
|
|
iot_sg_ext_lr_reset();
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void iot_sg_ext_lr_data_save(uint8_t *addr, iot_time_tm_t *tm)
|
|
{
|
|
uint8_t reason = 0;
|
|
uint16_t index = 0, max_cnt = 0, len = 0;
|
|
uint32_t ret;
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_time_tm_t cache_tm = { 0 };
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_meter_data_t *meter = &ext_info->meter_data;
|
|
iot_sg_meter_gx_lc_uint_data_t *flash_gx_data;
|
|
iot_sg_meter_lc_uint_xian_data_t *flash_xian_data;
|
|
iot_sg_meter_pw_lc_uint_data_t *flash_pw_data;
|
|
|
|
iot_sg_printf("%s addr %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,
|
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
|
iot_sg_printf("%s time %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
|
|
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
|
tm->tm_sec);
|
|
switch (iot_sg_sta_get_user_type()) {
|
|
case USER_TYPE_SOUTHEN_POWER_GRID_GX:
|
|
{
|
|
if (iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_GX_LC, &len, &max_cnt)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
flash_gx_data = (iot_sg_meter_gx_lc_uint_data_t *)iot_pkt_put(
|
|
pkt, len);
|
|
ret = iot_sg_sta_flash_unit_data_find_by_time(
|
|
addr, &index, tm,(uint8_t *)flash_gx_data, len,
|
|
IOT_SG_STA_METER_DATA_TYPE_GX_LC, 1);
|
|
if (ret == ERR_OK) {
|
|
cache_tm.tm_year = (uint16_t)(flash_gx_data->year + 2000);
|
|
cache_tm.tm_mon = (uint8_t)flash_gx_data->month;
|
|
cache_tm.tm_mday = (uint8_t)flash_gx_data->day;
|
|
cache_tm.tm_hour = (uint8_t)flash_gx_data->hour;
|
|
cache_tm.tm_min = (uint8_t)flash_gx_data->minute;
|
|
if (iot_rtc_delta_calc(&cache_tm, tm) != 0) {
|
|
index++;
|
|
}
|
|
}
|
|
if (index >= max_cnt) {
|
|
index = 0;
|
|
}
|
|
flash_gx_data->year = (uint32_t)(tm->tm_year % 100);
|
|
flash_gx_data->month = (uint32_t)(tm->tm_mon);
|
|
flash_gx_data->day = (uint32_t)(tm->tm_mday);
|
|
flash_gx_data->hour = (uint32_t)(tm->tm_hour);
|
|
flash_gx_data->minute = (uint32_t)(tm->tm_min);
|
|
os_mem_cpy(flash_gx_data->v, meter->v.a, PROTO_645_V_LEN);
|
|
iot_sg_sta_flash_unit_data_save(addr, index, (uint8_t *)flash_gx_data,
|
|
len, IOT_SG_STA_METER_DATA_TYPE_GX_LC);
|
|
iot_sg_sta_flash_unit_data_check(addr, index, tm,
|
|
IOT_SG_STA_METER_DATA_TYPE_GX_LC);
|
|
break;
|
|
}
|
|
case USER_TYPE_STATE_GRID_XIAN:
|
|
case USER_TYPE_STATE_GRID_HEBEI:
|
|
case USER_TYPE_STATE_GRID_HUNAN:
|
|
case USER_TYPE_STATE_GRID_MENGDONG_LC:
|
|
{
|
|
if (iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_XIAN_LC, &len, &max_cnt)) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
reason = 4;
|
|
goto out;
|
|
}
|
|
flash_xian_data = (iot_sg_meter_lc_uint_xian_data_t*)iot_pkt_put(
|
|
pkt, len);
|
|
ret = iot_sg_sta_flash_unit_data_find_by_time(
|
|
addr, &index, tm, (uint8_t *)flash_xian_data, len,
|
|
IOT_SG_STA_METER_DATA_TYPE_XIAN_LC, 1);
|
|
if (ret == ERR_OK) {
|
|
cache_tm.tm_year = (uint16_t)(flash_xian_data->year + 2000);
|
|
cache_tm.tm_mon = (uint8_t)flash_xian_data->month;
|
|
cache_tm.tm_mday = (uint8_t)flash_xian_data->day;
|
|
cache_tm.tm_hour = (uint8_t)flash_xian_data->hour;
|
|
cache_tm.tm_min = (uint8_t)flash_xian_data->minute;
|
|
if (iot_rtc_delta_calc(&cache_tm, tm) != 0) {
|
|
index++;
|
|
}
|
|
}
|
|
if (index >= max_cnt) {
|
|
index = 0;
|
|
}
|
|
flash_xian_data->year = (uint32_t)(tm->tm_year % 100);
|
|
flash_xian_data->month = (uint32_t)(tm->tm_mon);
|
|
flash_xian_data->day = (uint32_t)(tm->tm_mday);
|
|
flash_xian_data->hour = (uint32_t)(tm->tm_hour);
|
|
flash_xian_data->minute = (uint32_t)(tm->tm_min);
|
|
os_mem_cpy(&flash_xian_data->v, &meter->v, sizeof(meter->v));
|
|
os_mem_cpy(&flash_xian_data->i, &meter->a, sizeof(meter->a));
|
|
os_mem_cpy(flash_xian_data->n, meter->gnd_a, sizeof(meter->gnd_a));
|
|
os_mem_cpy(&flash_xian_data->active_power, &meter->ap,
|
|
sizeof(meter->ap));
|
|
os_mem_cpy(&flash_xian_data->reactive_power, &meter->rp,
|
|
sizeof(meter->rp));
|
|
os_mem_cpy(&flash_xian_data->power_factor, &meter->pf,
|
|
sizeof(meter->pf));
|
|
os_mem_cpy(&flash_xian_data->ca_power, &meter->cae,
|
|
sizeof(meter->cae));
|
|
os_mem_cpy(&flash_xian_data->fda_power, &meter->pae,
|
|
sizeof(meter->pae));
|
|
os_mem_cpy(&flash_xian_data->bda_power, &meter->nae,
|
|
sizeof(meter->nae));
|
|
os_mem_cpy(flash_xian_data->cr_power1, meter->cre1.total,
|
|
sizeof(meter->cre1.total));
|
|
os_mem_cpy(flash_xian_data->cr_power2, meter->cre2.total,
|
|
sizeof(meter->cre2.total));
|
|
os_mem_cpy(flash_xian_data->re_1st_power, meter->re_1st.total,
|
|
sizeof(meter->re_1st));
|
|
os_mem_cpy(flash_xian_data->re_2nd_power, meter->re_2st.total,
|
|
sizeof(meter->re_2st));
|
|
os_mem_cpy(flash_xian_data->re_3rd_power, meter->re_3st.total,
|
|
sizeof(meter->re_3st));
|
|
os_mem_cpy(flash_xian_data->re_4th_power, meter->re_4st.total,
|
|
sizeof(meter->re_4st));
|
|
os_mem_cpy(flash_xian_data->ap_demand, meter->ept_demand,
|
|
sizeof(meter->ept_demand));
|
|
os_mem_cpy(flash_xian_data->rp_demand, meter->eqt_demand,
|
|
sizeof(meter->eqt_demand));
|
|
os_mem_cpy(flash_xian_data->pos_ap_demand, &meter->pos_ap_demand,
|
|
sizeof(meter->pos_ap_demand));
|
|
os_mem_cpy(flash_xian_data->neg_ap_demand, &meter->neg_ap_demand,
|
|
sizeof(meter->neg_ap_demand));
|
|
os_mem_cpy(flash_xian_data->pos_a, meter->pos_a, sizeof(meter->pos_a));
|
|
os_mem_cpy(flash_xian_data->pos_b, meter->pos_b, sizeof(meter->pos_b));
|
|
os_mem_cpy(flash_xian_data->pos_c, meter->pos_c, sizeof(meter->pos_c));
|
|
iot_sg_sta_flash_unit_data_save(addr, index, (uint8_t *)flash_xian_data,
|
|
len, IOT_SG_STA_METER_DATA_TYPE_XIAN_LC);
|
|
iot_sg_sta_flash_unit_data_check(addr, index, tm,
|
|
IOT_SG_STA_METER_DATA_TYPE_XIAN_LC);
|
|
break;
|
|
}
|
|
case USER_TYPE_BRM_PEIWANG:
|
|
case USER_TYPE_BRM_PEIWANG_DUAL_NET:
|
|
{
|
|
if (iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC, &len, &max_cnt)) {
|
|
reason = 5;
|
|
goto out;
|
|
}
|
|
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
reason = 6;
|
|
goto out;
|
|
}
|
|
flash_pw_data = (iot_sg_meter_pw_lc_uint_data_t*)iot_pkt_put(
|
|
pkt, len);
|
|
ret = iot_sg_sta_flash_unit_data_find_by_time(
|
|
addr, &index, tm, (uint8_t *)flash_pw_data, len,
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC, 1);
|
|
if (ret == ERR_OK) {
|
|
cache_tm.tm_year = (uint16_t)(flash_pw_data->year + 2000);
|
|
cache_tm.tm_mon = (uint8_t)flash_pw_data->month;
|
|
cache_tm.tm_mday = (uint8_t)flash_pw_data->day;
|
|
cache_tm.tm_hour = (uint8_t)flash_pw_data->hour;
|
|
cache_tm.tm_min = (uint8_t)flash_pw_data->minute;
|
|
if (iot_rtc_delta_calc(&cache_tm, tm) != 0) {
|
|
index++;
|
|
}
|
|
}
|
|
if (index >= max_cnt) {
|
|
index = 0;
|
|
}
|
|
flash_pw_data->year = (uint32_t)(tm->tm_year % 100);
|
|
flash_pw_data->month = (uint32_t)(tm->tm_mon);
|
|
flash_pw_data->day = (uint32_t)(tm->tm_mday);
|
|
flash_pw_data->hour = (uint32_t)(tm->tm_hour);
|
|
flash_pw_data->minute = (uint32_t)(tm->tm_min);
|
|
os_mem_cpy(&flash_pw_data->v, &meter->v, sizeof(meter->v));
|
|
os_mem_cpy(&flash_pw_data->i, &meter->a, sizeof(meter->a));
|
|
os_mem_cpy(&flash_pw_data->active_power, &meter->ap,
|
|
sizeof(meter->ap));
|
|
os_mem_cpy(&flash_pw_data->reactive_power, &meter->rp,
|
|
sizeof(meter->rp));
|
|
os_mem_cpy(&flash_pw_data->power_factor, &meter->pf,
|
|
sizeof(meter->pf));
|
|
os_mem_cpy(&flash_pw_data->ept_pos, &meter->pae.total,
|
|
sizeof(meter->pae.total));
|
|
os_mem_cpy(&flash_pw_data->ept_neg, &meter->nae.total,
|
|
sizeof(meter->nae.total));
|
|
iot_sg_sta_flash_unit_data_save(addr, index, (uint8_t *)flash_pw_data,
|
|
len, IOT_SG_STA_METER_DATA_TYPE_PW_LC);
|
|
iot_sg_sta_flash_unit_data_check(addr, index, tm,
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
out:
|
|
if (reason) {
|
|
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
|
|
}
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
static uint32_t iot_sg_ext_get_lr_time(iot_time_tm_t *tm)
|
|
{
|
|
uint32_t ret = ERR_FAIL;
|
|
|
|
switch (iot_sg_sta_get_user_type()) {
|
|
case USER_TYPE_BRM_PEIWANG:
|
|
case USER_TYPE_SOUTHEN_POWER_GRID_GX:
|
|
{
|
|
ret = iot_sg_sta_rtc_get(tm, 0);
|
|
break;
|
|
}
|
|
case USER_TYPE_BRM_PEIWANG_DUAL_NET:
|
|
case USER_TYPE_STATE_GRID_XIAN:
|
|
case USER_TYPE_STATE_GRID_HEBEI:
|
|
case USER_TYPE_STATE_GRID_HUNAN:
|
|
case USER_TYPE_STATE_GRID_MENGDONG_LC:
|
|
{
|
|
ret = iot_sg_sta_rtc_get(tm, 1);
|
|
break;
|
|
}
|
|
default:
|
|
ret = ERR_NOSUPP;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t iot_sg_ext_lr_other_handle(void)
|
|
{
|
|
uint32_t ret = ERR_FAIL;
|
|
iot_pkt_t *pkt;
|
|
iot_time_tm_t tm;
|
|
proto_645_07_frozen_mdhm_t time;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_lc_info_t *lr_info = &ext_info->lc_info;
|
|
iot_sg_sta_ext_clct_param *clct_param = &ext_info->clct_param;
|
|
|
|
if (clct_param->enabled) {
|
|
switch (iot_sg_sta_get_user_type()) {
|
|
case USER_TYPE_BRM_PEIWANG:
|
|
case USER_TYPE_BRM_PEIWANG_DUAL_NET:
|
|
{
|
|
if (iot_sg_ext_get_lr_time(&tm)) {
|
|
goto out;
|
|
}
|
|
if (!ext_info->lc_info.froze_tm.tm_year
|
|
&& !ext_info->lc_info.froze_tm.tm_mon
|
|
&& !ext_info->lc_info.froze_tm.tm_mday
|
|
&& !ext_info->lc_info.froze_tm.tm_hour
|
|
&& !ext_info->lc_info.froze_tm.tm_min
|
|
&& !ext_info->lc_info.froze_tm.tm_sec) {
|
|
/* load read load curve data time stamp */
|
|
ext_info->lc_info.froze_tm = iot_sg_ext_get_next_lr_ts(
|
|
lr_info->cfg->tm, lr_info->cfg->interval, tm);
|
|
goto out;
|
|
} else if (iot_rtc_delta_calc(&ext_info->lc_info.froze_tm, &tm)
|
|
< 0) {
|
|
goto out;
|
|
}
|
|
time.month = 0x99;
|
|
time.day = 0x99;
|
|
time.hour = 0x99;
|
|
time.minute = 0x99;
|
|
pkt = proto_645_2007_build_frozen_msg(proto_645_bcast_addr, &time);
|
|
if (pkt) {
|
|
ret = iot_sg_sta_add_corr_req(iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt));
|
|
if (ret == ERR_OK) {
|
|
iot_sg_printf("%s frozen send\n", __FUNCTION__);
|
|
ext_info->lc_info.last_froze_tm =
|
|
ext_info->lc_info.froze_tm;
|
|
ext_info->lc_info.froze_tm = iot_sg_ext_get_next_lr_ts(
|
|
lr_info->cfg->tm, lr_info->cfg->interval, tm);
|
|
}
|
|
iot_pkt_free(pkt);
|
|
}
|
|
break;
|
|
}
|
|
case USER_TYPE_SOUTHEN_POWER_GRID_GX:
|
|
case USER_TYPE_STATE_GRID_XIAN:
|
|
case USER_TYPE_STATE_GRID_HEBEI:
|
|
case USER_TYPE_STATE_GRID_HUNAN:
|
|
case USER_TYPE_STATE_GRID_MENGDONG_LC:
|
|
case USER_TYPE_STATE_GRID:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t iot_sg_ext_lr_idx_handle(uint8_t index, uint8_t flag_resp)
|
|
{
|
|
uint8_t idx = index;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_lc_info_t *lr_info = &ext_info->lc_info;
|
|
|
|
switch (lr_info->cfg_index) {
|
|
case IOT_SG_STA_EXT_LC_PEIWANG:
|
|
{
|
|
if ((idx < lr_info->cfg->cnt) && (lr_info->cfg->di_buf[idx] ==
|
|
PROTO_645_2007_DI_RT_YMDHMS_LAST1) && !flag_resp) {
|
|
if (iot_sg_ext_get_lr_di_idx(PROTO_645_2007_DI_EPT_POS_SUM,
|
|
&idx) == ERR_OK) {
|
|
/* if sta can't read the last freezing time,
|
|
* sta don't read frozen data. sta read current data.
|
|
*/
|
|
goto out;
|
|
} else {
|
|
/* if sta can't read the last freezing time and current data,
|
|
* lr function is finish.
|
|
*/
|
|
idx = lr_info->cfg->cnt;
|
|
}
|
|
}
|
|
next:
|
|
idx++;
|
|
if (idx < lr_info->cfg->cnt) {
|
|
switch (lr_info->cfg->di_buf[idx]) {
|
|
case PROTO_645_2007_DI_EPT_POS_SUM:
|
|
{
|
|
if (iot_bcd_data_check(ext_info->meter_data.pae.total,
|
|
sizeof(ext_info->meter_data.pae.total))) {
|
|
goto next;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_SUM:
|
|
{
|
|
if (iot_bcd_data_check(ext_info->meter_data.nae.total,
|
|
sizeof(ext_info->meter_data.nae.total))) {
|
|
goto next;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_ALL:
|
|
{
|
|
if (iot_bcd_data_check(ext_info->meter_data.ap.a,
|
|
sizeof(ext_info->meter_data.ap.a))) {
|
|
goto next;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_Q_ALL:
|
|
{
|
|
if (iot_bcd_data_check(ext_info->meter_data.rp.a,
|
|
sizeof(ext_info->meter_data.rp.a))) {
|
|
goto next;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IOT_SG_STA_EXT_LC_GX_CFG:
|
|
case IOT_SG_STA_EXT_LC_XIAN_CFG:
|
|
case IOT_SG_STA_EXT_LC_XIAN_3P_CFG:
|
|
default:
|
|
idx++;
|
|
break;
|
|
}
|
|
out:
|
|
return idx;
|
|
}
|
|
|
|
static iot_pkt_t * iot_sg_ext_69845_lr_mr_msg_build(uint8_t *addr)
|
|
{
|
|
uint32_t get_list_req_size, oad;
|
|
uint8_t di_cnt, i, oad_idx = 0, attribute, cur_index = 0;
|
|
iot_pkt_t *pkt = NULL, *get_list_req = NULL;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_lc_info_t *lr_info = &ext_info->lc_info;
|
|
proto_69845_app_get_list_req_info_t *req = NULL;
|
|
server_addr_info_t server = {0};
|
|
|
|
if (lr_info->index >= lr_info->cfg->cnt) {
|
|
goto out;
|
|
}
|
|
di_cnt = lr_info->cfg->cnt - lr_info->index;
|
|
if (di_cnt > IOT_SG_STA_EXT_LR_FRAME_MAX_OI_NUM) {
|
|
di_cnt = IOT_SG_STA_EXT_LR_FRAME_MAX_OI_NUM;
|
|
}
|
|
get_list_req_size = sizeof(proto_69845_app_oad_t) * di_cnt + sizeof(*req);
|
|
get_list_req = iot_pkt_alloc(get_list_req_size, IOT_SMART_GRID_MID);
|
|
if (!get_list_req) {
|
|
goto out;
|
|
}
|
|
req = (proto_69845_app_get_list_req_info_t *)iot_pkt_put(get_list_req,
|
|
get_list_req_size);
|
|
req->type = PROTO_69845_APP_GET_NORMALLIST;
|
|
req->piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
|
|
req->piid.sn = iot_sg_sta_ext_get_69845_apdu_sn();
|
|
/* fill di from di_buff */
|
|
for (i = 0; i < di_cnt; i++) {
|
|
if (lr_info->index + i >= IOT_SG_STA_EXT_LR_DI_CNT_MAX) {
|
|
break;
|
|
}
|
|
oad = proto_645_di_to_698_oad(lr_info->cfg->di_buf[lr_info->index + i]);
|
|
cur_index = lr_info->index + i;
|
|
if (oad != PROTO_69845_APP_OAD_INVALID) {
|
|
req->oad[oad_idx].oi = (uint16_t)(oad >> 16);
|
|
attribute = (oad >> 8) & 0xff;
|
|
req->oad[oad_idx].attribute_id = attribute & 0x1f;
|
|
req->oad[oad_idx].attribute_char = attribute >> 5;
|
|
req->oad[oad_idx].element_index = oad & 0xff;
|
|
oad_idx++;
|
|
}
|
|
}
|
|
lr_info->index = cur_index;
|
|
req->oad_cnt = oad_idx;
|
|
server.len = PROTO_69845_SA_LEN;
|
|
server.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server.addr, addr);
|
|
pkt = proto_69845_build_get_req_msg_with_rn(req, &server);
|
|
iot_pkt_free(get_list_req);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
static uint32_t iot_sg_ext_di_07_to_97(uint8_t *index, uint32_t di,
|
|
uint8_t flag_3p)
|
|
{
|
|
uint32_t di_97 = 0, di_07 = di;
|
|
|
|
if (di_07 == PROTO_645_2007_DI_RT_YMDHMS_LAST1) {
|
|
iot_sg_ext_get_lr_di_idx(PROTO_645_2007_DI_EPT_POS_SUM, index);
|
|
di_07 = PROTO_645_2007_DI_EPT_POS_SUM;
|
|
}
|
|
|
|
switch (di_07) {
|
|
case PROTO_645_2007_DI_V_ALL:
|
|
{
|
|
if (flag_3p) {
|
|
di_97 = PROTO_645_1997_DI_V_ALL;
|
|
} else {
|
|
di_97 = PROTO_645_1997_DI_V_A;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_ALL:
|
|
{
|
|
if (flag_3p) {
|
|
di_97 = PROTO_645_1997_DI_I_ALL;
|
|
} else {
|
|
di_97 = PROTO_645_1997_DI_I_A;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_PF_ALL:
|
|
{
|
|
if (flag_3p) {
|
|
di_97 = PROTO_645_1997_DI_PF_ALL;
|
|
} else {
|
|
di_97 = PROTO_645_1997_DI_PF_A;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_SUM:
|
|
{
|
|
di_97 = PROTO_645_1997_DI_EPT_POS_SUM;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_SUM:
|
|
{
|
|
di_97 = PROTO_645_1997_DI_EPT_NEG_SUM;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_ALL:
|
|
{
|
|
if (flag_3p) {
|
|
di_97 = PROTO_645_1997_DI_P_ALL;
|
|
} else {
|
|
di_97 = PROTO_645_1997_DI_P_A;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_Q_ALL:
|
|
{
|
|
if (flag_3p) {
|
|
di_97 = PROTO_645_1997_DI_Q_ALL;
|
|
} else {
|
|
di_97 = PROTO_645_1997_DI_Q_A;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return di_97;
|
|
}
|
|
|
|
uint8_t iot_sg_ext_lr_func(uint8_t *addr)
|
|
{
|
|
uint8_t complete = 0, last_state = 0, flag_new = 0;
|
|
uint16_t timeout;
|
|
uint32_t ret, di_97;
|
|
iot_pkt_t *pkt;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_lc_info_t *lr_info = &ext_info->lc_info;
|
|
iot_sg_sta_node_desc_t *node = iot_sg_sta_node_find_by_addr(addr);
|
|
iot_time_tm_t tm;
|
|
|
|
if (!lr_info->cfg) {
|
|
goto done;
|
|
}
|
|
IOT_ASSERT(node);
|
|
last_state = lr_info->state;
|
|
switch (lr_info->state) {
|
|
case IOT_SG_STA_EXT_LC_STATE_IDLE:
|
|
{
|
|
if (iot_sg_ext_get_lr_time(&tm)) {
|
|
/* get time fail, stop lr function */
|
|
iot_sg_printf("%s get time err\n", __FUNCTION__);
|
|
goto done;
|
|
}
|
|
if (iot_sg_ext_lr_other_handle() == ERR_OK)
|
|
goto out;
|
|
|
|
if (!node->ext.lr_info.tm.tm_year && !node->ext.lr_info.tm.tm_mon
|
|
&& !node->ext.lr_info.tm.tm_mday && !node->ext.lr_info.tm.tm_hour
|
|
&& !node->ext.lr_info.tm.tm_min && !node->ext.lr_info.tm.tm_sec) {
|
|
/* load read load curve data time stamp */
|
|
node->ext.lr_info.tm = iot_sg_ext_get_next_lr_ts(lr_info->cfg->tm,
|
|
lr_info->cfg->interval, tm);
|
|
goto done;
|
|
} else if (iot_rtc_delta_calc(&node->ext.lr_info.tm, &tm) >= 0) {
|
|
/* when current tm is greater than or equal to next tm of
|
|
* reading load curve data, start read load curve data.
|
|
*/
|
|
lr_info->state = IOT_SG_STA_EXT_LC_STATE_SEND;
|
|
lr_info->index = 0;
|
|
flag_new = 1;
|
|
goto send;
|
|
} else {
|
|
goto done;
|
|
}
|
|
break;
|
|
}
|
|
case IOT_SG_STA_EXT_LC_STATE_WAIT:
|
|
{
|
|
if (!lr_info->timeout_cnt) {
|
|
if (!lr_info->repeat_cnt || lr_info->flag_resp) {
|
|
lr_info->index = iot_sg_ext_lr_idx_handle(lr_info->index,
|
|
lr_info->flag_resp);
|
|
lr_info->repeat_cnt = 0;
|
|
flag_new = 1;
|
|
}
|
|
if (lr_info->index >= lr_info->cfg->cnt) {
|
|
iot_sg_ext_lr_data_save(addr, &node->ext.lr_info.tm);
|
|
lr_info->state = IOT_SG_STA_EXT_LC_STATE_END;
|
|
if (iot_sg_ext_get_lr_time(&tm)) {
|
|
/* get time fail, load read load curve data next time
|
|
* stamp base on last time
|
|
*/
|
|
node->ext.lr_info.tm = iot_sg_ext_get_next_lr_ts(
|
|
lr_info->cfg->tm, lr_info->cfg->interval,
|
|
node->ext.lr_info.tm);
|
|
} else {
|
|
/* load read load curve data next time stamp base on
|
|
* current time
|
|
*/
|
|
node->ext.lr_info.tm = iot_sg_ext_get_next_lr_ts(
|
|
lr_info->cfg->tm, lr_info->cfg->interval, tm);
|
|
}
|
|
goto done;
|
|
}
|
|
if (lr_info->repeat_cnt) {
|
|
lr_info->repeat_cnt--;
|
|
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
|
|
lr_info->index = lr_info->last_index_698;
|
|
}
|
|
}
|
|
lr_info->state = IOT_SG_STA_EXT_LC_STATE_SEND;
|
|
} else {
|
|
lr_info->timeout_cnt--;
|
|
break;
|
|
}
|
|
}
|
|
case IOT_SG_STA_EXT_LC_STATE_SEND:
|
|
{
|
|
send:
|
|
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
|
|
lr_info->last_index_698 = lr_info->index;
|
|
pkt = iot_sg_ext_69845_lr_mr_msg_build(addr);
|
|
} else if (node->data_type == IOT_SG_STA_DATA_TYPE_645_97) {
|
|
di_97 = iot_sg_ext_di_07_to_97(&lr_info->index,
|
|
lr_info->cfg->di_buf[lr_info->index], node->is_three_phase);
|
|
pkt = proto_645_build_mr_msg(PROTO_645_1997_ID, addr,
|
|
di_97);
|
|
} else {
|
|
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID, addr,
|
|
lr_info->cfg->di_buf[lr_info->index]);
|
|
}
|
|
if (pkt) {
|
|
timeout = (IOT_SG_STA_EXT_READ_DATA_TIMEOUT *
|
|
IOT_SG_STA_EXT_SM_DELAY / 100);
|
|
timeout = min(timeout, IOT_SG_STA_EXT_DRV_READ_TIMEOUT);
|
|
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_EXT_READ,
|
|
addr, 0, node->data_type, iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt), timeout);
|
|
if (ret == ERR_OK) {
|
|
iot_sg_printf("%s addr %02x:%02x:%02x:%02x:%02x:%02x read id "
|
|
"%08x idx %lu\n", __FUNCTION__, addr[0], addr[1], addr[2],
|
|
addr[3], addr[4], addr[5],
|
|
lr_info->cfg->di_buf[lr_info->index], lr_info->index);
|
|
lr_info->state = IOT_SG_STA_EXT_LC_STATE_WAIT;
|
|
lr_info->timeout_cnt = IOT_SG_STA_EXT_READ_DATA_TIMEOUT;
|
|
if (flag_new) {
|
|
lr_info->repeat_cnt = 1;
|
|
}
|
|
lr_info->flag_resp = 0;
|
|
}
|
|
iot_pkt_free(pkt);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_SG_STA_EXT_LC_STATE_END:
|
|
{
|
|
goto done;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
goto out;
|
|
done:
|
|
complete = 1;
|
|
out:
|
|
if (last_state != lr_info->state) {
|
|
iot_sg_printf("%s addr %02x:%02x:%02x:%02x:%02x:%02x state %lu to %lu\n"
|
|
, __FUNCTION__, addr[0], addr[1], addr[2], addr[3], addr[4],
|
|
addr[5], last_state, lr_info->state);
|
|
}
|
|
return complete;
|
|
}
|
|
|
|
uint32_t iot_sg_ext_get_lr_interval(void)
|
|
{
|
|
uint32_t interval;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
|
|
iot_sg_sta_ext_lc_info_t *lr_info = &ext_info->lc_info;
|
|
|
|
if (!lr_info->cfg) {
|
|
interval = IOT_SG_STA_EXT_LC_INTER;
|
|
} else {
|
|
interval = lr_info->cfg->interval;
|
|
}
|
|
return interval;
|
|
}
|
|
|
|
iot_pkt_t *iot_sg_sta_ext_load_record_pw_func_1(uint8_t *addr, uint32_t di,
|
|
uint8_t *in_data)
|
|
{
|
|
uint8_t *cnt, block_len, sum, i, j, *data, re_len;
|
|
uint16_t next_whole_t, start_idx = 0, latest_idx = 0, n, unit_len, max_cnt;
|
|
uint16_t inter_time = (uint16_t)(iot_sg_ext_get_lr_interval() / 60);
|
|
uint32_t ret;
|
|
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
|
|
iot_time_tm_t tm = { 0 }, start_tm = { 0 };
|
|
proto_645_07_curve_dl_t *curve_dl;
|
|
iot_sg_meter_pw_lc_uint_data_t *lc_cache;
|
|
proto_645_header_t *hdr = NULL;
|
|
int32_t delta;
|
|
|
|
pkt = iot_pkt_alloc(PROTO_645_MAX_DATA_LEN +
|
|
sizeof(*hdr) + sizeof(proto_645_tailer_t), IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
data = iot_pkt_data(pkt);
|
|
hdr = (proto_645_header_t *)data;
|
|
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
|
|
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
|
|
iot_pkt_put(pkt, sizeof(*hdr));
|
|
data += sizeof(*hdr);
|
|
|
|
proto_645_2007_di_to_byte(di, data);
|
|
hdr->len += PROTO_645_2007_DI_LEN;
|
|
data += PROTO_645_2007_DI_LEN;
|
|
|
|
proto_645_sub33_handle(in_data + PROTO_645_2007_DI_LEN, sizeof(*curve_dl));
|
|
curve_dl = (proto_645_07_curve_dl_t *)(in_data + PROTO_645_2007_DI_LEN);
|
|
|
|
start_tm.tm_year = iot_bcd_to_byte(curve_dl->year) + 2000;
|
|
start_tm.tm_mon = iot_bcd_to_byte(curve_dl->mon);
|
|
start_tm.tm_mday = iot_bcd_to_byte(curve_dl->mday);
|
|
start_tm.tm_hour = iot_bcd_to_byte(curve_dl->hour);
|
|
start_tm.tm_min = iot_bcd_to_byte(curve_dl->min);
|
|
/* calculate the time of the next whole point */
|
|
next_whole_t = start_tm.tm_min % inter_time;
|
|
if (next_whole_t) {
|
|
next_whole_t = inter_time - next_whole_t;
|
|
next_whole_t *= 60;
|
|
iot_rtc_delta_add((int64_t)next_whole_t, &start_tm);
|
|
}
|
|
|
|
iot_sg_printf("%s id %08x time %lu-%lu-%lu %lu:%lu:%lu, n %lu\n",
|
|
__FUNCTION__, di, start_tm.tm_year, start_tm.tm_mon,
|
|
start_tm.tm_mday, start_tm.tm_hour, start_tm.tm_min,
|
|
start_tm.tm_sec, curve_dl->n);
|
|
|
|
re_len = PROTO_645_MAX_DATA_LEN;
|
|
iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC, &unit_len, &max_cnt);
|
|
pkt_buff = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt_buff) {
|
|
iot_sg_printf("%s pkt err\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
lc_cache = (iot_sg_meter_pw_lc_uint_data_t *)iot_pkt_put(pkt_buff,
|
|
unit_len);
|
|
if (iot_sg_sta_flash_unit_data_find_by_time(addr, &start_idx, &start_tm,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_PW_LC,
|
|
0)) {
|
|
goto tail;
|
|
}
|
|
ret = iot_sg_sta_flash_unit_data_find_latest(addr, &latest_idx,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_PW_LC);
|
|
if (ret != ERR_OK) {
|
|
goto tail;
|
|
}
|
|
iot_sg_printf("%s start idx:%d latest idx:%d\n", __FUNCTION__,
|
|
start_idx, latest_idx);
|
|
if (latest_idx >= start_idx) {
|
|
n = latest_idx - start_idx + 1;
|
|
} else {
|
|
n = max_cnt - (start_idx - latest_idx) + 1;
|
|
}
|
|
for (i = 0; i < n; i++) {
|
|
block_len = 0;
|
|
ret = iot_sg_sta_flash_unit_data_read(addr, start_idx,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_PW_LC);
|
|
if (ret != ERR_OK) {
|
|
break;
|
|
}
|
|
tm.tm_year = (uint16_t)lc_cache->year + 2000;
|
|
tm.tm_mon = (uint8_t)lc_cache->month;
|
|
tm.tm_mday = (uint8_t)lc_cache->day;
|
|
tm.tm_hour = (uint8_t)lc_cache->hour;
|
|
tm.tm_min = (uint8_t)lc_cache->minute;
|
|
delta = (int32_t)iot_rtc_delta_calc(&start_tm, &tm);
|
|
if (delta < 0 || delta >= (int32_t)(curve_dl->n * inter_time * 60))
|
|
break;
|
|
if (delta % (inter_time * 60) != 0) {
|
|
goto next;
|
|
}
|
|
data[block_len++] = 0xA0;
|
|
data[block_len++] = 0xA0;
|
|
cnt = data + block_len;
|
|
block_len++;
|
|
block_len += proto_645_rtctime_to_YYMMDDhhmm(&tm, data + block_len);
|
|
os_mem_cpy(data + block_len, &lc_cache->v, sizeof(lc_cache->v));
|
|
block_len += sizeof(lc_cache->v);
|
|
os_mem_cpy(data + block_len, &lc_cache->i, sizeof(lc_cache->i));
|
|
block_len += sizeof(lc_cache->i);
|
|
os_mem_set(data + block_len, 0xFF, PROTO_645_07_FREQ_LEN);
|
|
block_len += PROTO_645_07_FREQ_LEN;
|
|
data[block_len++] = PROTO_645_DB_SEPARATE_CHAR;
|
|
|
|
os_mem_cpy(data + block_len, &lc_cache->active_power,
|
|
sizeof(lc_cache->active_power));
|
|
block_len += sizeof(lc_cache->active_power);
|
|
os_mem_cpy(data + block_len, &lc_cache->reactive_power,
|
|
sizeof(lc_cache->reactive_power));
|
|
block_len += sizeof(lc_cache->reactive_power);
|
|
data[block_len++] = PROTO_645_DB_SEPARATE_CHAR;
|
|
|
|
os_mem_cpy(data + block_len, &lc_cache->power_factor,
|
|
sizeof(lc_cache->power_factor));
|
|
block_len += sizeof(lc_cache->power_factor);
|
|
data[block_len++] = PROTO_645_DB_SEPARATE_CHAR;
|
|
|
|
os_mem_cpy(data + block_len, lc_cache->ept_pos,
|
|
sizeof(lc_cache->ept_pos));
|
|
block_len += sizeof(lc_cache->ept_pos);
|
|
os_mem_cpy(data + block_len, lc_cache->ept_neg,
|
|
sizeof(lc_cache->ept_neg));
|
|
block_len += sizeof(lc_cache->ept_neg);
|
|
os_mem_set(data + block_len, 0xFF, PROTO_645_07_ENERGY_DATA_LEN);
|
|
block_len += PROTO_645_07_ENERGY_DATA_LEN;
|
|
os_mem_set(data + block_len, 0xFF, PROTO_645_07_ENERGY_DATA_LEN);
|
|
block_len += PROTO_645_07_ENERGY_DATA_LEN;
|
|
|
|
data[block_len++] = PROTO_645_DB_SEPARATE_CHAR;
|
|
data[block_len++] = PROTO_645_DB_SEPARATE_CHAR;
|
|
data[block_len++] = PROTO_645_DB_SEPARATE_CHAR;
|
|
*cnt = block_len - 3;
|
|
for (sum = 0, j = 0; j < block_len; j++)
|
|
sum += data[j];
|
|
data[block_len++] = sum;
|
|
data[block_len++] = 0xE5;
|
|
hdr->len += block_len;
|
|
IOT_ASSERT(block_len <= PROTO_645_07_CURVE_REC_MAX_SIZE);
|
|
re_len -= block_len;
|
|
if (re_len < block_len) {
|
|
break;
|
|
}
|
|
next:
|
|
start_idx++;
|
|
if (start_idx >= max_cnt)
|
|
start_idx = 0;
|
|
}
|
|
tail:
|
|
proto_645_add33_handle(hdr->data, hdr->len);
|
|
proto_645_tail_init(hdr);
|
|
iot_pkt_put(pkt, hdr->len + sizeof(proto_645_tailer_t));
|
|
out:
|
|
if (pkt_buff) {
|
|
iot_pkt_free(pkt_buff);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
static void iot_sg_sta_ext_load_record_pw_uint_data_write(uint32_t di,
|
|
uint8_t *data, uint8_t len, iot_sg_meter_pw_lc_uint_data_t *lc_cache)
|
|
{
|
|
switch(di) {
|
|
case PROTO_645_2007_DI_CR_V_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->v.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_V_B:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->v.b, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_V_C:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->v.c, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_V_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->v, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_I_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->i.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_I_B:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->i.b, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_I_C:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->i.c, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_I_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->i, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_P_T:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power.total, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_P_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_P_B:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power.b, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_P_C:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power.c, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_Q_T:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->reactive_power.total, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_Q_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->reactive_power.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_Q_B:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->reactive_power.b, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_Q_C:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->reactive_power.c, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_P_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_Q_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->reactive_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_PF_T:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->power_factor.total, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_PF_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->power_factor.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_PF_B:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->power_factor.b, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_PF_C:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->power_factor.c, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_PF_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->power_factor, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_EP_POS:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->ept_pos, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_CR_EP_NEG:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->ept_neg, len);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void iot_sg_sta_ext_load_record_fill_curve_data_pw(uint8_t *data,
|
|
uint8_t cnt, uint16_t start_idx, uint8_t *addr, iot_time_tm_t *start_tm,
|
|
uint32_t di, uint8_t uint_data_len)
|
|
{
|
|
uint64_t delta;
|
|
uint32_t ret, write_cnt = 0;
|
|
uint32_t inter_time = iot_sg_ext_get_lr_interval();
|
|
uint8_t *w_data = data, first_point = 0;
|
|
uint16_t latest_idx, i, n, delta_cnt, unit_len, max_cnt;
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_time_tm_t tm_old = { 0 }, tm_new = { 0 };
|
|
iot_sg_meter_pw_lc_uint_data_t *lc_cache;
|
|
if (inter_time < 60) {
|
|
goto out;
|
|
}
|
|
iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC, &unit_len, &max_cnt);
|
|
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
iot_sg_printf("%s pkt err\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
lc_cache = (iot_sg_meter_pw_lc_uint_data_t*)iot_pkt_put(pkt,
|
|
unit_len);
|
|
ret = iot_sg_sta_flash_unit_data_find_latest(addr, &latest_idx,
|
|
(uint8_t *)lc_cache, unit_len,
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC);
|
|
if (ret != ERR_OK) {
|
|
goto out;
|
|
}
|
|
iot_sg_printf("%s start idx:%d latest idx:%d\n", __FUNCTION__,
|
|
start_idx, latest_idx);
|
|
if (latest_idx >= start_idx) {
|
|
n = latest_idx - start_idx + 1;
|
|
} else {
|
|
n = max_cnt - (start_idx - latest_idx) + 1;
|
|
}
|
|
os_mem_cpy(&tm_new, start_tm, sizeof(tm_new));
|
|
for (i = 0; i < n; i++) {
|
|
if (write_cnt == cnt) {
|
|
break;
|
|
}
|
|
ret = iot_sg_sta_flash_unit_data_read(addr, start_idx,
|
|
(uint8_t *)lc_cache, unit_len,
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC);
|
|
if (ret == ERR_OK) {
|
|
tm_old = tm_new;
|
|
tm_new.tm_year = (uint16_t)lc_cache->year + 2000;
|
|
tm_new.tm_mon = (uint8_t)lc_cache->month;
|
|
tm_new.tm_mday = (uint8_t)lc_cache->day;
|
|
tm_new.tm_hour = (uint8_t)lc_cache->hour;
|
|
tm_new.tm_min = (uint8_t)lc_cache->minute;
|
|
delta = iot_rtc_delta_calc(&tm_old, &tm_new);
|
|
if (delta >= (inter_time * max_cnt)) {
|
|
delta_cnt = max_cnt;
|
|
} else {
|
|
delta_cnt = (uint16_t)(delta / inter_time);
|
|
if (delta % inter_time) {
|
|
/* if it's not the whole point, find the next point */
|
|
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
|
|
goto done;
|
|
}
|
|
}
|
|
if (!first_point) {
|
|
first_point = 1;
|
|
if (!delta_cnt) {
|
|
goto write;
|
|
} else {
|
|
if (delta_cnt >= cnt) {
|
|
os_mem_set(w_data, 0xFF, cnt * uint_data_len);
|
|
write_cnt = cnt;
|
|
break;
|
|
}
|
|
/* delta_cnt contains the first invalid point */
|
|
os_mem_set(w_data, 0xFF, delta_cnt * uint_data_len);
|
|
write_cnt += delta_cnt;
|
|
w_data += delta_cnt * uint_data_len;
|
|
goto write;
|
|
}
|
|
} else {
|
|
if (!delta_cnt) {
|
|
/* load record delta time too short
|
|
* ignore current data unit.
|
|
*/
|
|
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
|
|
goto done;
|
|
} else if (delta_cnt == 1) {
|
|
goto write;
|
|
} else {
|
|
if ((write_cnt + delta_cnt) > cnt) {
|
|
delta_cnt = (uint8_t)(cnt - write_cnt);
|
|
os_mem_set(w_data, 0xFF, delta_cnt * uint_data_len);
|
|
write_cnt = cnt;
|
|
break;
|
|
}
|
|
os_mem_set(w_data, 0xFF, (delta_cnt - 1) * uint_data_len);
|
|
w_data += ((delta_cnt - 1) * uint_data_len);
|
|
write_cnt += (delta_cnt - 1);
|
|
}
|
|
}
|
|
write:
|
|
iot_sg_sta_ext_load_record_pw_uint_data_write(di, w_data,
|
|
uint_data_len, lc_cache);
|
|
write_cnt++;
|
|
w_data += uint_data_len;
|
|
}
|
|
done:
|
|
start_idx++;
|
|
if (start_idx >= max_cnt) {
|
|
start_idx = 0;
|
|
}
|
|
}
|
|
out:
|
|
if (write_cnt < cnt) {
|
|
os_mem_set(w_data, 0xFF, (cnt - write_cnt) * uint_data_len);
|
|
}
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
iot_pkt_t *iot_sg_sta_ext_load_record_pw_func(uint8_t *addr, uint32_t di,
|
|
uint8_t *data)
|
|
{
|
|
uint8_t curve_max_point, uint_data_len = 0, cnt;
|
|
uint16_t next_whole_t, start_idx = 0, unit_len;
|
|
uint16_t inter_time = (uint16_t)(iot_sg_ext_get_lr_interval() / 60);
|
|
uint32_t total_len, data_len;
|
|
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
|
|
iot_time_tm_t cache_ts = { 0 };
|
|
proto_645_07_curve_dl_t *curve_dl;
|
|
proto_645_07_curve_ul_t *curve_ul = NULL;
|
|
iot_sg_meter_pw_lc_uint_data_t *lc_cache;
|
|
proto_645_header_t *hdr = NULL;
|
|
|
|
if (!inter_time) {
|
|
goto out;
|
|
}
|
|
iot_sg_printf("%s read id %08x\n", __FUNCTION__, di);
|
|
uint_data_len = proto_645_07_get_curve_point_len(di);
|
|
if (!uint_data_len) {
|
|
goto out;
|
|
}
|
|
curve_max_point =(PROTO_645_MAX_DATA_LEN - PROTO_645_2007_DI_LEN -
|
|
sizeof(*curve_ul)) / uint_data_len;
|
|
proto_645_sub33_handle(data + PROTO_645_2007_DI_LEN, sizeof(*curve_dl));
|
|
curve_dl = (proto_645_07_curve_dl_t *)(data + PROTO_645_2007_DI_LEN);
|
|
cnt = min(curve_dl->n, curve_max_point);
|
|
data_len = PROTO_645_2007_DI_LEN + sizeof(*curve_ul) +
|
|
cnt * uint_data_len;
|
|
total_len = sizeof(*hdr) + sizeof(proto_645_tailer_t) + data_len;
|
|
pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
|
|
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
|
|
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
|
|
hdr->len = (uint8_t)data_len;
|
|
proto_645_2007_di_to_byte(di, hdr->data);
|
|
curve_ul = (proto_645_07_curve_ul_t *)(hdr->data +
|
|
PROTO_645_2007_DI_LEN);
|
|
cache_ts.tm_year = iot_bcd_to_byte(curve_dl->year) + 2000;
|
|
cache_ts.tm_mon = iot_bcd_to_byte(curve_dl->mon);
|
|
cache_ts.tm_mday = iot_bcd_to_byte(curve_dl->mday);
|
|
cache_ts.tm_hour = iot_bcd_to_byte(curve_dl->hour);
|
|
cache_ts.tm_min = iot_bcd_to_byte(curve_dl->min);
|
|
/* calculate the time of the next whole point */
|
|
next_whole_t = cache_ts.tm_min % inter_time;
|
|
if (next_whole_t) {
|
|
next_whole_t = inter_time - next_whole_t;
|
|
next_whole_t *= 60;
|
|
iot_rtc_delta_add((int64_t)next_whole_t, &cache_ts);
|
|
}
|
|
curve_ul->year = iot_byte_to_bcd((uint8_t)(cache_ts.tm_year - 2000));
|
|
curve_ul->mon = iot_byte_to_bcd(cache_ts.tm_mon);
|
|
curve_ul->mday = iot_byte_to_bcd(cache_ts.tm_mday);
|
|
curve_ul->hour = iot_byte_to_bcd(cache_ts.tm_hour);
|
|
curve_ul->min = iot_byte_to_bcd(cache_ts.tm_min);
|
|
iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC, &unit_len, NULL);
|
|
pkt_buff = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt_buff) {
|
|
iot_sg_printf("%s pkt err\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
lc_cache = (iot_sg_meter_pw_lc_uint_data_t *)iot_pkt_put(pkt_buff,
|
|
unit_len);
|
|
if (iot_sg_sta_flash_unit_data_find_by_time(addr, &start_idx, &cache_ts,
|
|
(uint8_t *)lc_cache, unit_len,
|
|
IOT_SG_STA_METER_DATA_TYPE_PW_LC, 0)) {
|
|
os_mem_set(curve_ul->data, 0xFF, cnt * uint_data_len);
|
|
goto tail;
|
|
}
|
|
iot_sg_sta_ext_load_record_fill_curve_data_pw(curve_ul->data, cnt,
|
|
start_idx, addr, &cache_ts, di, uint_data_len);
|
|
tail:
|
|
proto_645_add33_handle(hdr->data, hdr->len);
|
|
proto_645_tail_init(hdr);
|
|
iot_pkt_put(pkt, total_len);
|
|
out:
|
|
if (pkt_buff) {
|
|
iot_pkt_free(pkt_buff);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
static void iot_sg_sta_ext_load_record_xian_uint_data_write(uint32_t di,
|
|
uint8_t *data, uint8_t len, iot_sg_meter_lc_uint_xian_data_t *lc_cache)
|
|
{
|
|
switch (di) {
|
|
case PROTO_645_2007_DI_V_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->v.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->i.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_N:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->n, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_T:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power.total, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power.a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_DEMAND:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->ap_demand, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_DEMAND:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->rp_demand, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->fda_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->bda_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_V_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->v, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->i, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->active_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_Q_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->reactive_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_PF_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->power_factor, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_COMP_SUM:
|
|
{
|
|
os_mem_cpy(data, lc_cache->ca_power.total, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_COMP_ALL:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->ca_power, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->fda_power.total , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->bda_power.total , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_POS_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->cr_power1 , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_NEG_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->cr_power2 , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT1_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->re_1st_power , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT2_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->re_2nd_power , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT3_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->re_3rd_power , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT4_SUM:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->re_4th_power , len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_DEMAND:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->pos_ap_demand, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_DEMAND:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->neg_ap_demand, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_A:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->pos_a, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_B:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->pos_b, len);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_C:
|
|
{
|
|
os_mem_cpy(data, &lc_cache->pos_c, len);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void iot_sg_sta_ext_load_record_fill_curve_data_xian(uint8_t *data,
|
|
uint8_t cnt, uint16_t start_idx, uint8_t *addr, iot_time_tm_t *start_tm,
|
|
uint32_t di, uint8_t uint_data_len)
|
|
{
|
|
uint64_t delta;
|
|
uint32_t ret, write_cnt = 0;
|
|
uint32_t inter_time = iot_sg_ext_get_lr_interval();
|
|
uint8_t *w_data = data, first_point = 0, reason = 0;
|
|
uint16_t latest_idx, i, n, delta_cnt, unit_len, max_cnt;
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_time_tm_t tm_old = { 0 }, tm_new = { 0 };
|
|
iot_sg_meter_lc_uint_xian_data_t *lc_cache;
|
|
|
|
if (inter_time < 60) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
if (iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_XIAN_LC, &unit_len, &max_cnt)) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
lc_cache = (iot_sg_meter_lc_uint_xian_data_t *)iot_pkt_put(pkt, unit_len);
|
|
ret = iot_sg_sta_flash_unit_data_find_latest(addr, &latest_idx,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_XIAN_LC);
|
|
if (ret != ERR_OK) {
|
|
reason = 4;
|
|
goto out;
|
|
}
|
|
iot_sg_printf("%s start idx:%d latest idx:%d\n", __FUNCTION__,
|
|
start_idx, latest_idx);
|
|
if (latest_idx >= start_idx) {
|
|
n = latest_idx - start_idx + 1;
|
|
} else {
|
|
n = max_cnt - (start_idx - latest_idx) + 1;
|
|
}
|
|
os_mem_cpy(&tm_new, start_tm, sizeof(tm_new));
|
|
for (i = 0; i < n; i++) {
|
|
if (write_cnt == cnt) {
|
|
break;
|
|
}
|
|
ret = iot_sg_sta_flash_unit_data_read(addr, start_idx,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_XIAN_LC);
|
|
if (ret == ERR_OK) {
|
|
tm_old = tm_new;
|
|
tm_new.tm_year = (uint16_t)lc_cache->year + 2000;
|
|
tm_new.tm_mon = (uint8_t)lc_cache->month;
|
|
tm_new.tm_mday = (uint8_t)lc_cache->day;
|
|
tm_new.tm_hour = (uint8_t)lc_cache->hour;
|
|
tm_new.tm_min = (uint8_t)lc_cache->minute;
|
|
delta = iot_rtc_delta_calc(&tm_old, &tm_new);
|
|
if (delta >= (inter_time * max_cnt)) {
|
|
delta_cnt = max_cnt;
|
|
} else {
|
|
delta_cnt = (uint16_t)(delta / inter_time);
|
|
if (delta % inter_time) {
|
|
/* if it's not the whole point, find the next point */
|
|
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
|
|
goto done;
|
|
}
|
|
}
|
|
if (!first_point) {
|
|
first_point = 1;
|
|
if (!delta_cnt) {
|
|
goto write;
|
|
} else {
|
|
if (delta_cnt >= cnt) {
|
|
os_mem_set(w_data, 0xFF, cnt * uint_data_len);
|
|
write_cnt = cnt;
|
|
break;
|
|
}
|
|
/* delta_cnt contains the first invalid point */
|
|
os_mem_set(w_data, 0xFF, delta_cnt * uint_data_len);
|
|
write_cnt += delta_cnt;
|
|
w_data += delta_cnt * uint_data_len;
|
|
goto write;
|
|
}
|
|
} else {
|
|
if (!delta_cnt) {
|
|
/* load record delta time too short
|
|
* ignore current data unit.
|
|
*/
|
|
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
|
|
goto done;
|
|
} else if (delta_cnt == 1) {
|
|
goto write;
|
|
} else {
|
|
if ((write_cnt + delta_cnt) > cnt) {
|
|
delta_cnt = (uint8_t)(cnt - write_cnt);
|
|
os_mem_set(w_data, 0xFF, delta_cnt * uint_data_len);
|
|
write_cnt = cnt;
|
|
break;
|
|
}
|
|
os_mem_set(w_data, 0xFF, (delta_cnt - 1) * uint_data_len);
|
|
w_data += ((delta_cnt - 1) * uint_data_len);
|
|
write_cnt += (delta_cnt - 1);
|
|
}
|
|
}
|
|
write:
|
|
iot_sg_sta_ext_load_record_xian_uint_data_write(di, w_data,
|
|
uint_data_len, lc_cache);
|
|
write_cnt++;
|
|
w_data += uint_data_len;
|
|
}
|
|
done:
|
|
start_idx++;
|
|
if (start_idx >= max_cnt) {
|
|
start_idx = 0;
|
|
}
|
|
}
|
|
out:
|
|
if (reason) {
|
|
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
|
|
}
|
|
if (write_cnt < cnt) {
|
|
os_mem_set(w_data, 0xFF, (cnt - write_cnt) * uint_data_len);
|
|
}
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
iot_pkt_t *iot_sg_sta_ext_load_record_xian_func(uint8_t *addr, uint32_t di,
|
|
uint8_t *data)
|
|
{
|
|
uint8_t curve_max_point, uint_data_len = 0, cnt;
|
|
uint16_t next_whole_t, start_idx = 0, unit_len;
|
|
uint16_t inter_time = (uint16_t)(iot_sg_ext_get_lr_interval() / 60);
|
|
uint32_t total_len, data_len;
|
|
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
|
|
iot_time_tm_t cache_ts = { 0 };
|
|
proto_645_07_curve_xian_dl_t *curve_dl;
|
|
proto_645_07_curve_xian_ul_t *curve_ul = NULL;
|
|
iot_sg_meter_lc_uint_xian_data_t *lc_cache;
|
|
proto_645_header_t *hdr = NULL;
|
|
|
|
if (!inter_time) {
|
|
goto out;
|
|
}
|
|
iot_sg_printf("%s read id %08x\n", __FUNCTION__, di);
|
|
switch (di) {
|
|
case PROTO_645_2007_DI_V_A:
|
|
{
|
|
uint_data_len = PROTO_645_V_LEN;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_A:
|
|
case PROTO_645_2007_DI_I_N:
|
|
{
|
|
uint_data_len = PROTO_645_07_A_LEN;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_T:
|
|
case PROTO_645_2007_DI_P_A:
|
|
case PROTO_645_2007_DI_EQT_DEMAND:
|
|
case PROTO_645_2007_DI_EPT_DEMAND:
|
|
{
|
|
uint_data_len = PROTO_645_07_P_LEN;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_ALL:
|
|
case PROTO_645_2007_DI_EPT_NEG_ALL:
|
|
{
|
|
uint_data_len = sizeof(proto_645_07_energy_data_t);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_V_ALL:
|
|
{
|
|
uint_data_len = sizeof(proto_645_v_t);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_ALL:
|
|
{
|
|
uint_data_len = sizeof(proto_645_07_a_t);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_ALL:
|
|
case PROTO_645_2007_DI_Q_ALL:
|
|
{
|
|
uint_data_len = sizeof(proto_645_07_p_t);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_PF_ALL:
|
|
{
|
|
uint_data_len = sizeof(proto_645_07_pf_t);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_COMP_ALL:
|
|
{
|
|
uint_data_len = sizeof(proto_645_07_energy_data_t);
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_SUM:
|
|
case PROTO_645_2007_DI_EPT_NEG_SUM:
|
|
case PROTO_645_2007_DI_EQT_POS_SUM:
|
|
case PROTO_645_2007_DI_EQT_NEG_SUM:
|
|
case PROTO_645_2007_DI_EQT_QRT1_SUM:
|
|
case PROTO_645_2007_DI_EQT_QRT2_SUM:
|
|
case PROTO_645_2007_DI_EQT_QRT3_SUM:
|
|
case PROTO_645_2007_DI_EQT_QRT4_SUM:
|
|
case PROTO_645_2007_DI_EPT_COMP_SUM:
|
|
{
|
|
uint_data_len= PROTO_645_07_ENERGY_DATA_LEN;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_DEMAND:
|
|
case PROTO_645_2007_DI_EPT_NEG_DEMAND:
|
|
{
|
|
uint_data_len= PROTO_645_07_CURR_PD_LEN;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_A:
|
|
case PROTO_645_2007_DI_EPT_POS_B:
|
|
case PROTO_645_2007_DI_EPT_POS_C:
|
|
{
|
|
uint_data_len = PROTO_645_07_ENERGY_DATA_LEN;
|
|
break;
|
|
}
|
|
default:
|
|
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_NO_REQ_DATA,
|
|
addr, PROTO_645_2007_FN_READ_DATA);
|
|
goto out;
|
|
}
|
|
curve_max_point =(PROTO_645_MAX_DATA_LEN - PROTO_645_2007_DI_LEN -
|
|
sizeof(*curve_ul)) / uint_data_len;
|
|
proto_645_sub33_handle(data + PROTO_645_2007_DI_LEN, sizeof(*curve_dl));
|
|
curve_dl = (proto_645_07_curve_xian_dl_t *)(data + PROTO_645_2007_DI_LEN);
|
|
cnt = min(curve_dl->n, curve_max_point);
|
|
data_len = PROTO_645_2007_DI_LEN + sizeof(*curve_ul) +
|
|
cnt * uint_data_len;
|
|
total_len = sizeof(*hdr) + sizeof(proto_645_tailer_t) + data_len;
|
|
pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
|
|
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
|
|
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
|
|
hdr->len = (uint8_t)data_len;
|
|
proto_645_2007_di_to_byte(di, hdr->data);
|
|
curve_ul = (proto_645_07_curve_xian_ul_t *)(hdr->data +
|
|
PROTO_645_2007_DI_LEN);
|
|
cache_ts.tm_year = iot_bcd_to_byte(curve_dl->year) + 2000;
|
|
cache_ts.tm_mon = iot_bcd_to_byte(curve_dl->mon);
|
|
cache_ts.tm_mday = iot_bcd_to_byte(curve_dl->mday);
|
|
cache_ts.tm_hour = iot_bcd_to_byte(curve_dl->hour);
|
|
cache_ts.tm_min = iot_bcd_to_byte(curve_dl->min);
|
|
/* calculate the time of the next whole point */
|
|
next_whole_t = cache_ts.tm_min % inter_time;
|
|
if (next_whole_t) {
|
|
next_whole_t = inter_time - next_whole_t;
|
|
next_whole_t *= 60;
|
|
iot_rtc_delta_add((int64_t)next_whole_t, &cache_ts);
|
|
}
|
|
curve_ul->year = iot_byte_to_bcd((uint8_t)(cache_ts.tm_year - 2000));
|
|
curve_ul->mon = iot_byte_to_bcd(cache_ts.tm_mon);
|
|
curve_ul->mday = iot_byte_to_bcd(cache_ts.tm_mday);
|
|
curve_ul->hour = iot_byte_to_bcd(cache_ts.tm_hour);
|
|
curve_ul->min = iot_byte_to_bcd(cache_ts.tm_min);
|
|
if (inter_time > 55) {
|
|
curve_ul->m = PROTO_645_CURVE_FREEZ_DENSITY_60MIN;
|
|
} else if (inter_time > 25) {
|
|
curve_ul->m = PROTO_645_CURVE_FREEZ_DENSITY_30MIN;
|
|
} else if (inter_time > 10) {
|
|
curve_ul->m = PROTO_645_CURVE_FREEZ_DENSITY_15MIN;
|
|
} else if (inter_time > 3) {
|
|
curve_ul->m = PROTO_645_CURVE_FREEZ_DENSITY_5MIN;
|
|
} else if (inter_time) {
|
|
curve_ul->m = PROTO_645_CURVE_FREEZ_DENSITY_1MIN;
|
|
} else {
|
|
curve_ul->m = PROTO_645_CURVE_FREEZ_DENSITY_NO;
|
|
}
|
|
curve_ul->n = cnt;
|
|
if (iot_sg_sta_flash_unit_get_data_info(IOT_SG_STA_METER_DATA_TYPE_XIAN_LC,
|
|
&unit_len, NULL)) {
|
|
goto out;
|
|
}
|
|
pkt_buff = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt_buff) {
|
|
iot_sg_printf("%s pkt err\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
lc_cache = (iot_sg_meter_lc_uint_xian_data_t *)iot_pkt_put(pkt_buff,
|
|
unit_len);
|
|
if (iot_sg_sta_flash_unit_data_find_by_time(addr, &start_idx, &cache_ts,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_XIAN_LC,
|
|
0)) {
|
|
os_mem_set(curve_ul->data, 0xFF, cnt * uint_data_len);
|
|
goto tail;
|
|
}
|
|
iot_sg_sta_ext_load_record_fill_curve_data_xian(curve_ul->data, cnt,
|
|
start_idx, addr, &cache_ts, di, uint_data_len);
|
|
tail:
|
|
proto_645_add33_handle(hdr->data, hdr->len);
|
|
proto_645_tail_init(hdr);
|
|
iot_pkt_put(pkt, total_len);
|
|
out:
|
|
if (pkt_buff) {
|
|
iot_pkt_free(pkt_buff);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
void iot_sg_sta_ext_load_record_fill_curve_data_gx(uint8_t *data,
|
|
uint8_t cnt, uint16_t start_idx, uint8_t *addr, iot_time_tm_t *start_tm)
|
|
{
|
|
uint64_t delta;
|
|
uint16_t latest_idx, n, i, delta_cnt, max_cnt, unit_len;
|
|
uint32_t ret, write_cnt = 0;
|
|
uint32_t inter_time = iot_sg_ext_get_lr_interval();
|
|
uint8_t *w_data = data, first_point = 0;
|
|
iot_time_tm_t tm_old = { 0 }, tm_new = { 0 };
|
|
iot_sg_meter_gx_lc_uint_data_t *lc_cache;
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
if (inter_time < 60) {
|
|
os_mem_set(w_data, 0xFF, cnt * PROTO_645_V_LEN);
|
|
return;
|
|
}
|
|
iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_GX_LC, &unit_len, &max_cnt);
|
|
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
return;
|
|
}
|
|
lc_cache = (iot_sg_meter_gx_lc_uint_data_t *)iot_pkt_put(pkt, unit_len);
|
|
ret = iot_sg_sta_flash_unit_data_find_latest(addr, &latest_idx,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_GX_LC);
|
|
if (ret != ERR_OK) {
|
|
os_mem_set(w_data, 0xFF, cnt * PROTO_645_V_LEN);
|
|
return;
|
|
}
|
|
iot_sg_printf("%s start idx:%d latest idx:%d\n", __FUNCTION__, start_idx,
|
|
latest_idx);
|
|
if (latest_idx >= start_idx) {
|
|
n = latest_idx - start_idx + 1;
|
|
} else {
|
|
n = max_cnt - (start_idx - latest_idx) + 1;
|
|
}
|
|
os_mem_cpy(&tm_new, start_tm, sizeof(tm_new));
|
|
for (i = 0; i < n; i++) {
|
|
if (write_cnt == cnt) {
|
|
break;
|
|
}
|
|
ret = iot_sg_sta_flash_unit_data_read(addr, start_idx,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_GX_LC);
|
|
if (ret == ERR_OK) {
|
|
tm_old = tm_new;
|
|
tm_new.tm_year = (uint16_t)lc_cache->year + 2000;
|
|
tm_new.tm_mon = (uint8_t)lc_cache->month;
|
|
tm_new.tm_mday = (uint8_t)lc_cache->day;
|
|
tm_new.tm_hour = (uint8_t)lc_cache->hour;
|
|
tm_new.tm_min = (uint8_t)lc_cache->minute;
|
|
delta = iot_rtc_delta_calc(&tm_old, &tm_new);
|
|
if (delta >= (inter_time * max_cnt)) {
|
|
delta_cnt = max_cnt;
|
|
} else {
|
|
delta_cnt = (uint16_t)(delta / inter_time);
|
|
if (delta % inter_time) {
|
|
/* if it's not the whole point, find the next point */
|
|
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
|
|
goto done;
|
|
}
|
|
}
|
|
if (!first_point) {
|
|
first_point = 1;
|
|
if (!delta_cnt) {
|
|
goto write;
|
|
} else {
|
|
if (delta_cnt >= cnt) {
|
|
os_mem_set(w_data, 0xFF, cnt * PROTO_645_V_LEN);
|
|
write_cnt = cnt;
|
|
break;
|
|
}
|
|
/* delta_cnt contains the first invalid point */
|
|
os_mem_set(w_data, 0xFF, delta_cnt * PROTO_645_V_LEN);
|
|
write_cnt += delta_cnt;
|
|
w_data += delta_cnt * PROTO_645_V_LEN;
|
|
goto write;
|
|
}
|
|
} else {
|
|
if (!delta_cnt) {
|
|
/* load record delta time too short
|
|
* ignore current data unit.
|
|
*/
|
|
os_mem_cpy(&tm_new, &tm_old, sizeof(iot_time_tm_t));
|
|
goto done;
|
|
} else if (delta_cnt == 1) {
|
|
goto write;
|
|
} else {
|
|
if ((write_cnt + delta_cnt) > cnt) {
|
|
delta_cnt = (uint8_t)(cnt - write_cnt);
|
|
os_mem_set(w_data, 0xFF, delta_cnt * PROTO_645_V_LEN);
|
|
write_cnt = cnt;
|
|
break;
|
|
}
|
|
os_mem_set(w_data, 0xFF, (delta_cnt - 1) * PROTO_645_V_LEN);
|
|
w_data += ((delta_cnt - 1) * PROTO_645_V_LEN);
|
|
write_cnt += (delta_cnt - 1);
|
|
}
|
|
}
|
|
write:
|
|
os_mem_cpy(w_data, lc_cache->v, PROTO_645_V_LEN);
|
|
write_cnt++;
|
|
w_data += PROTO_645_V_LEN;
|
|
}
|
|
done:
|
|
start_idx++;
|
|
if (start_idx >= max_cnt) {
|
|
start_idx = 0;
|
|
}
|
|
}
|
|
if (write_cnt < cnt) {
|
|
os_mem_set(w_data, 0xFF, (cnt - write_cnt) * PROTO_645_V_LEN);
|
|
}
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
iot_pkt_t *iot_sg_sta_ext_load_record_gx_func(uint8_t *addr, uint32_t di,
|
|
uint8_t *data)
|
|
{
|
|
uint8_t cnt;
|
|
uint16_t next_whole_t, start_idx = 0,unit_len = 0;
|
|
uint16_t inter_time = (uint16_t)(iot_sg_ext_get_lr_interval() / 60);
|
|
uint32_t total_len, data_len;
|
|
iot_sg_meter_gx_lc_uint_data_t *lc_cache = NULL;
|
|
iot_pkt_t *pkt = NULL, *tmp = NULL;
|
|
iot_time_tm_t cache_ts = { 0 };
|
|
proto_645_07_curve_dl_t *curve_dl;
|
|
proto_645_07_curve_ul_t *curve_ul = NULL;
|
|
proto_645_header_t *hdr = NULL;
|
|
|
|
if (!inter_time) {
|
|
goto out;
|
|
}
|
|
if (iot_sg_sta_flash_unit_get_data_info(
|
|
IOT_SG_STA_METER_DATA_TYPE_GX_LC, &unit_len, NULL)) {
|
|
goto out;
|
|
}
|
|
tmp = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
|
|
if (!tmp) {
|
|
goto out;
|
|
}
|
|
lc_cache = (iot_sg_meter_gx_lc_uint_data_t *)iot_pkt_put(tmp, unit_len);
|
|
proto_645_sub33_handle(data + PROTO_645_2007_DI_LEN, sizeof(*curve_dl));
|
|
curve_dl = (proto_645_07_curve_dl_t *)(data + PROTO_645_2007_DI_LEN);
|
|
cnt = min(curve_dl->n, PROTO_645_07_V_LR_POINT_MAX_CNT);
|
|
data_len = PROTO_645_2007_DI_LEN + sizeof(*curve_ul) +
|
|
cnt * PROTO_645_V_LEN;
|
|
total_len = sizeof(*hdr) + sizeof(proto_645_tailer_t) + data_len;
|
|
pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
|
|
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
|
|
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
|
|
hdr->len = (uint8_t)data_len;
|
|
proto_645_2007_di_to_byte(di, hdr->data);
|
|
curve_ul = (proto_645_07_curve_ul_t *)(hdr->data + PROTO_645_2007_DI_LEN);
|
|
cache_ts.tm_year = iot_bcd_to_byte(curve_dl->year) + 2000;
|
|
cache_ts.tm_mon = iot_bcd_to_byte(curve_dl->mon);
|
|
cache_ts.tm_mday = iot_bcd_to_byte(curve_dl->mday);
|
|
cache_ts.tm_hour = iot_bcd_to_byte(curve_dl->hour);
|
|
cache_ts.tm_min = iot_bcd_to_byte(curve_dl->min);
|
|
/* calculate the time of the next whole point */
|
|
next_whole_t = cache_ts.tm_min % inter_time;
|
|
if (next_whole_t) {
|
|
next_whole_t = inter_time - next_whole_t;
|
|
next_whole_t *= 60;
|
|
iot_rtc_delta_add((int64_t)next_whole_t, &cache_ts);
|
|
}
|
|
curve_ul->year = iot_byte_to_bcd((uint8_t)(cache_ts.tm_year - 2000));
|
|
curve_ul->mon = iot_byte_to_bcd(cache_ts.tm_mon);
|
|
curve_ul->mday = iot_byte_to_bcd(cache_ts.tm_mday);
|
|
curve_ul->hour = iot_byte_to_bcd(cache_ts.tm_hour);
|
|
curve_ul->min = iot_byte_to_bcd(cache_ts.tm_min);
|
|
if (iot_sg_sta_flash_unit_data_find_by_time(addr, &start_idx, &cache_ts,
|
|
(uint8_t *)lc_cache, unit_len, IOT_SG_STA_METER_DATA_TYPE_GX_LC, 0)) {
|
|
os_mem_set(curve_ul->data, 0xFF, cnt * PROTO_645_V_LEN);
|
|
goto tail;
|
|
}
|
|
iot_sg_sta_ext_load_record_fill_curve_data_gx(curve_ul->data, cnt,
|
|
start_idx, addr, &cache_ts);
|
|
tail:
|
|
proto_645_add33_handle(hdr->data, hdr->len);
|
|
proto_645_tail_init(hdr);
|
|
iot_pkt_put(pkt, total_len);
|
|
out:
|
|
if (tmp) {
|
|
iot_pkt_free(tmp);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
#endif /* IOT_SMART_GRID_EXT_LR_FUNC_ENABLE */
|