Files
kunlun/app/smart_grid/sta/iot_sg_sta_ext_lr.c
2024-09-28 14:24:04 +08:00

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