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

3080 lines
102 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"
/* smart grid internal header files */
#include "iot_sg_fr.h"
#include "iot_sg.h"
#include "iot_sg_sta.h"
#include "proto_645.h"
#include "proto_69845.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_AI_FUNC_ENABLE)
/* sta ai management module topo data collection default interval
* unit is 1s.
*/
#define IOT_SG_STA_AI_MOD_TOPO_INTER_DEF (60)
/* sta ai management module topo data collection min interval
* unit is 1s.
*/
#define IOT_SG_STA_AI_MOD_TOPO_INTER_MIN (10)
/* sta ai management module topo data collection cycle time
* unit is 1s.
*/
#define IOT_SG_STA_AI_MOD_TOPO_CYCLE_DUR (60 * 70)
/* sta ai management module topo data collection state */
#define IOT_SG_STA_AI_MOD_TOPO_SM_IDLE (0)
#define IOT_SG_STA_AI_MOD_TOPO_SM_SEND (1)
#define IOT_SG_STA_AI_MOD_TOPO_SM_WAIT (2)
/* define 69845 meter data frame max oi number */
#define IOT_SG_STA_AI_MOD_698_FRAME_MAX_OI_NUM (6)
/* sta ai management module topo query cmd response data max length.
*/
#define IOT_SG_STA_AI_MOD_TOPO_DATA_RESP_LEN_MAX (0xff - \
sizeof(proto_645_header_t) - sizeof(proto_645_tailer_t) - \
PROTO_645_2007_DI_LEN - sizeof(proto_645_07_ai_topo_query_ul_t))
/* sta ai management module line loss data collection interval
* unit is 1s.
*/
#define IOT_SG_STA_AI_MOD_LL_INTER_1MIN (60)
#define IOT_SG_STA_AI_MOD_LL_INTER_5MIN (60 * 5)
#define IOT_SG_STA_AI_MOD_LL_INTER_15MIN (60 * 15)
#define IOT_SG_STA_AI_MOD_LL_INTER_30MIN (60 * 30)
#define IOT_SG_STA_AI_MOD_LL_INTER_60MIN (60 * 60)
/* sta ai management module line lose data collection times in cycle */
#define IOT_SG_STA_AI_MOD_LL_TIMES_IN_CYC (96)
/* sta ai management module line lose data collection state */
#define IOT_SG_STA_AI_MOD_LL_SM_IDLE (0)
#define IOT_SG_STA_AI_MOD_LL_SM_SEND (1)
#define IOT_SG_STA_AI_MOD_LL_SM_WAIT (2)
/* sta ai management module meter response data type */
#define IOT_SG_STA_AI_MOD_METER_RSP_TYPE_TOPO (0)
#define IOT_SG_STA_AI_MOD_METER_RSP_TYPE_LL (1)
/* max delta between meter clock and AI module clock, unit is 1s */
#define IOT_SG_STA_AI_MOD_TO_METER_TIME_MAX_DELTA (60 * 60 * 24 * 365)
#define IOT_SG_STA_AI_MOD_LL_DATA_RESP_LEN_MAX (0xff - \
sizeof(proto_645_header_t) - sizeof(proto_645_tailer_t) - \
PROTO_645_2007_DI_LEN - sizeof(proto_645_07_ai_ll_query_ul_t))
/* line lose data response cache info */
typedef struct _iot_sg_sta_ext_ai_ll_rsp_info {
/* flag of collection data */
uint8_t flag_p : 1,
flag_i : 1,
flag_gi : 1,
flag_v : 1,
flag_pf : 1,
flag_pos : 1,
flag_neg : 1,
flag_qtr : 1;
/* collection interval, unit is 1s */
uint16_t interval;
/* response cnt */
uint16_t rsp_cnt;
/* response first tm */
iot_time_tm_t first_tm;
/* start index in flash */
uint16_t start_idx;
/* end index in flash */
uint16_t end_idx;
} iot_sg_sta_ext_ai_ll_rsp_info_t;
static void iot_sg_sta_ext_ai_time_set(iot_time_tm_t *tm)
{
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_ai_time_t *time;
if (ext_info->ai_module_info) {
time = &ext_info->ai_module_info->time;
time->sys_time = *tm;
time->sys_ts = (uint32_t)(os_boot_time32() / 1000);
iot_sg_printf("%s set time %02d-%02d-%02d %02d:%02d:%02d\n",
__FUNCTION__, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
}
static uint32_t iot_sg_sta_ext_ai_time_get(iot_time_tm_t *tm)
{
int64_t dur;
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_ai_time_t *time;
if (ext_info->ai_module_info) {
time = &ext_info->ai_module_info->time;
if (time->sys_ts) {
dur = (int64_t)((os_boot_time32() / 1000) - time->sys_ts);
*tm = time->sys_time;
iot_rtc_delta_add(dur, tm);
return ERR_OK;
}
}
return ERR_FAIL;
}
uint32_t iot_sg_sta_ext_ai_module_init(void)
{
uint32_t ret = ERR_FAIL;
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->ai_module_info = os_mem_malloc(IOT_SMART_GRID_MID,
sizeof(iot_sg_sta_ext_ai_module_t));
if (ext_info->ai_module_info) {
os_mem_set(ext_info->ai_module_info, 0,
sizeof(iot_sg_sta_ext_ai_module_t));
iot_sg_printf("%s\n", __FUNCTION__);
ret = ERR_OK;
}
return ret;
}
void iot_sg_sta_ext_ai_module_deinit(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;
if (ext_info->ai_module_info) {
os_mem_free(ext_info->ai_module_info);
ext_info->ai_module_info = NULL;
iot_sg_printf("%s\n", __FUNCTION__);
}
}
static uint32_t iot_sg_sta_ext_ai_module_check(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;
if (ext_info->ai_module_info) {
return ERR_OK;
} else {
return ERR_NOSUPP;
}
}
static void iot_sg_sta_ext_ai_topo_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;
if (ext_info->ai_module_info) {
os_mem_set(&ext_info->ai_module_info->topo_info, 0,
sizeof(iot_sg_sta_ext_ai_topo_info_t));
}
}
static void iot_sg_sta_ext_ai_topo_di_init(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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
topo_info->di_idx = 0;
topo_info->di_cnt = 0;
os_mem_set(&topo_info->resp_data, 0xff, sizeof(topo_info->resp_data));
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
if (topo_info->curr_cfg.flag_v) {
topo_info->di_list[topo_info->di_cnt] = PROTO_69845_APP_OAD_VOLTAGE;
topo_info->di_cnt++;
}
if (topo_info->curr_cfg.flag_i) {
topo_info->di_list[topo_info->di_cnt] = PROTO_69845_APP_OAD_CURRENT;
topo_info->di_cnt++;
}
if (topo_info->curr_cfg.flag_pf) {
topo_info->di_list[topo_info->di_cnt] = PROTO_69845_APP_OAD_PF;
topo_info->di_cnt++;
}
} else if (node->is_three_phase) {
if (topo_info->curr_cfg.flag_v) {
topo_info->di_list[topo_info->di_cnt] = PROTO_645_2007_DI_V_ALL;
topo_info->di_cnt++;
}
if (topo_info->curr_cfg.flag_i) {
topo_info->di_list[topo_info->di_cnt] = PROTO_645_2007_DI_I_ALL;
topo_info->di_cnt++;
}
if (topo_info->curr_cfg.flag_pf) {
topo_info->di_list[topo_info->di_cnt] = PROTO_645_2007_DI_PF_ALL;
topo_info->di_cnt++;
}
} else {
if (topo_info->curr_cfg.flag_v) {
topo_info->di_list[topo_info->di_cnt] = PROTO_645_2007_DI_V_A;
topo_info->di_cnt++;
}
if (topo_info->curr_cfg.flag_i) {
topo_info->di_list[topo_info->di_cnt] = PROTO_645_2007_DI_I_A;
topo_info->di_cnt++;
}
if (topo_info->curr_cfg.flag_pf) {
topo_info->di_list[topo_info->di_cnt] = PROTO_645_2007_DI_PF_T;
topo_info->di_cnt++;
}
}
}
static iot_pkt_t * iot_sg_sta_ext_ai_topo_698_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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
proto_69845_app_get_list_req_info_t *req = NULL;
server_addr_info_t server = {0};
if (topo_info->di_idx >= topo_info->di_cnt) {
goto out;
}
topo_info->last_idx = topo_info->di_idx;
di_cnt = topo_info->di_cnt - topo_info->di_idx;
if (di_cnt > IOT_SG_STA_AI_MOD_698_FRAME_MAX_OI_NUM) {
di_cnt = IOT_SG_STA_AI_MOD_698_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 = 0;
/* fill di from di_buff */
for (i = 0; i < di_cnt; i++) {
if (topo_info->di_idx + i >= IOT_SG_STA_EXT_AI_TOPO_DI_MAX) {
break;
}
oad = topo_info->di_list[topo_info->di_idx + i];
cur_index = topo_info->di_idx + 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++;
}
}
topo_info->di_idx = 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_sta_ext_ai_topo_645_data_handle(uint32_t rsp_di,
proto_645_header_t *resp_hdr)
{
uint8_t reason = 0, len;
uint32_t ret = ERR_INVAL;
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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
iot_sg_sta_ext_ai_topo_data_unit_t *meter = &topo_info->resp_data;
iot_sg_printf("%s resp id %08x\n", __FUNCTION__, rsp_di);
switch (rsp_di) {
case PROTO_645_2007_DI_V_A:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_V_LEN) {
reason = 1;
goto drop;
}
os_mem_cpy(meter->v.a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_V_LEN);
break;
}
case PROTO_645_2007_DI_I_A:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_07_A_LEN) {
reason = 2;
goto drop;
}
os_mem_cpy(meter->i.a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_A_LEN);
break;
}
case PROTO_645_2007_DI_PF_T:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_07_PF_LEN) {
reason = 3;
goto drop;
}
os_mem_cpy(meter->pf.total, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_PF_LEN);
break;
}
case PROTO_645_2007_DI_V_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->v.a)) {
reason = 4;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->v),
sizeof(meter->v.a));
os_mem_cpy(&meter->v, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
case PROTO_645_2007_DI_I_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->i.a)) {
reason = 5;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->i),
sizeof(meter->i.a));
os_mem_cpy(&meter->i, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
case PROTO_645_2007_DI_PF_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->pf.total)) {
reason = 6;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->pf),
sizeof(meter->pf.total));
os_mem_cpy(&meter->pf, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
default:
reason = 7;
goto drop;
}
ret = ERR_OK;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static void iot_sg_sta_ext_ai_topo_698_oad_data_handle(
proto_69845_app_oad_resp_hdr_t *oad_data, uint32_t data_len)
{
uint8_t reason = 0;
uint32_t oad_value;
proto_69845_app_ele_data_t *ele_data;
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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
iot_sg_sta_ext_ai_topo_data_unit_t *meter = &topo_info->resp_data;
oad_value = iot_bytes_to_uint32((uint8_t*)&oad_data->oad.oi, 1);
if (data_len < sizeof(*ele_data)) {
reason = 1;
goto drop;
}
data_len -= sizeof(*ele_data);
ele_data = (proto_69845_app_ele_data_t *)oad_data->result;
if (ele_data->data_type != PROTO_69845_APP_DATA_ARRAY) {
reason = 2;
goto drop;
}
if (!ele_data->num_of_data) {
reason = 3;
goto drop;
}
switch (oad_value) {
case PROTO_69845_APP_OAD_VOLTAGE:
{
proto_69845_v_data_handle(&meter->v, ele_data, data_len);
break;
}
case PROTO_69845_APP_OAD_CURRENT:
{
proto_69845_a_data_handle(&meter->i, ele_data, data_len);
break;
}
case PROTO_69845_APP_OAD_PF:
{
proto_69845_pf_ele_data_handle(&meter->pf, ele_data, data_len);
break;
}
default:
reason = 4;
break;
}
return;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
static void iot_sg_sta_ext_ai_topo_save(uint8_t *addr, iot_time_tm_t *tm)
{
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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
iot_sg_sta_ext_ai_topo_data_t *topo_data = &topo_info->topo_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);
if (!topo_data->first_tm.tm_year && !topo_data->first_tm.tm_mon
&& !topo_data->first_tm.tm_mday && !topo_data->first_tm.tm_hour
&& !topo_data->first_tm.tm_min && !topo_data->first_tm.tm_sec) {
topo_data->first_tm = *tm;
topo_data->start_idx = 0;
topo_data->end_idx = 0;
}
topo_data->list[topo_data->end_idx] = topo_info->resp_data;
topo_data->end_idx++;
if (topo_data->end_idx >= IOT_SG_STA_EXT_AI_TOPO_DATA_MAX) {
topo_data->end_idx = 0;
}
if (topo_data->start_idx == topo_data->end_idx) {
topo_data->start_idx++;
if (topo_data->start_idx >= IOT_SG_STA_EXT_AI_TOPO_DATA_MAX) {
topo_data->start_idx = 0;
}
iot_rtc_delta_add(topo_info->curr_cfg.interval, &topo_data->first_tm);
}
}
void iot_sg_sta_ext_ai_topo_func(void)
{
iot_pkt_t *pkt = NULL;
uint8_t addr[IOT_MAC_ADDR_LEN], flag_new = 0;
uint32_t ret;
iot_sg_sta_node_desc_t *node;
iot_time_tm_t curr_tm;
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_ai_topo_info_t *topo_info;
if (iot_sg_sta_ext_ai_module_check()) {
goto out;
}
topo_info = &ext_info->ai_module_info->topo_info;
if (!topo_info->flag_enable) {
goto out;
}
p_sg_glb->desc.sta->drv->get_login_addr(addr);
node = iot_sg_sta_node_find_by_addr(addr);
if (node == NULL) {
goto out;
}
iot_sg_sta_ext_ai_time_get(&curr_tm);
switch (topo_info->state) {
case IOT_SG_STA_AI_MOD_TOPO_SM_IDLE:
{
if (topo_info->cnt >= topo_info->curr_cfg.collected_cnt) {
topo_info->flag_enable = 0;
iot_sg_printf("%s collect over time %lu-%lu-%lu %lu:%lu:%lu\n",
__FUNCTION__, curr_tm.tm_year, curr_tm.tm_mon, curr_tm.tm_mday,
curr_tm.tm_hour, curr_tm.tm_min, curr_tm.tm_sec);
} else {
if (!topo_info->collect_tm.tm_year && !topo_info->collect_tm.tm_mon
&& !topo_info->collect_tm.tm_mday
&& !topo_info->collect_tm.tm_hour
&& !topo_info->collect_tm.tm_min
&& !topo_info->collect_tm.tm_sec) {
if (iot_rtc_delta_calc(&curr_tm, &topo_info->curr_cfg.start_tm)
>= 0) {
topo_info->collect_tm = topo_info->curr_cfg.start_tm;
} else {
topo_info->collect_tm = iot_sg_ext_get_next_lr_ts(
topo_info->curr_cfg.start_tm,
topo_info->curr_cfg.interval, curr_tm);
}
} else if (iot_rtc_delta_calc(&topo_info->collect_tm,
&curr_tm) >= 0) {
/* when current tm is greater than or equal to next tm of
* reading load curve data, start read load curve data.
*/
topo_info->state = IOT_SG_STA_AI_MOD_TOPO_SM_SEND;
iot_sg_sta_ext_ai_topo_di_init(node);
flag_new = 1;
goto send;
}
}
break;
}
case IOT_SG_STA_AI_MOD_TOPO_SM_WAIT:
{
if (!topo_info->timeout) {
if (!topo_info->repeat_cnt || topo_info->flag_resp) {
topo_info->di_idx++;
topo_info->repeat_cnt = 0;
flag_new = 1;
}
if (topo_info->di_idx >= topo_info->di_cnt) {
iot_sg_sta_ext_ai_topo_save(node->entry.addr,
&topo_info->collect_tm);
topo_info->cnt++;
topo_info->state = IOT_SG_STA_AI_MOD_TOPO_SM_IDLE;
topo_info->collect_tm = iot_sg_ext_get_next_lr_ts(
topo_info->collect_tm, topo_info->curr_cfg.interval,
curr_tm);
iot_sg_printf("%s curr collect cnt %lu "
"next collect time %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
topo_info->cnt, topo_info->collect_tm.tm_year,
topo_info->collect_tm.tm_mon, topo_info->collect_tm.tm_mday,
topo_info->collect_tm.tm_hour, topo_info->collect_tm.tm_min,
topo_info->collect_tm.tm_sec);
goto out;
}
if (topo_info->repeat_cnt) {
topo_info->repeat_cnt--;
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
topo_info->di_idx = topo_info->last_idx;
}
}
topo_info->state = IOT_SG_STA_AI_MOD_TOPO_SM_SEND;
} else {
topo_info->timeout--;
break;
}
}
case IOT_SG_STA_AI_MOD_TOPO_SM_SEND:
{
send:
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
pkt = iot_sg_sta_ext_ai_topo_698_msg_build(addr);
} else {
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID, addr,
topo_info->di_list[topo_info->di_idx]);
}
if (pkt) {
if (!topo_info->seq) {
topo_info->seq = (uint16_t)os_rand();
} else {
topo_info->seq++;
}
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_EXT_AI_TOPO,
addr, topo_info->seq, node->data_type, iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt),
IOT_SG_STA_EXT_DRV_READ_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],
topo_info->di_list[topo_info->di_idx], topo_info->di_idx);
topo_info->state = IOT_SG_STA_AI_MOD_TOPO_SM_WAIT;
topo_info->timeout = IOT_SG_STA_EXT_READ_DATA_TIMEOUT;
if (flag_new) {
topo_info->repeat_cnt = 1;
}
topo_info->flag_resp = 0;
} else if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
topo_info->di_idx = topo_info->last_idx;
}
iot_pkt_free(pkt);
}
break;
}
default:
break;
}
out:
return;
}
static void iot_sg_sta_ext_ai_topo_start(iot_sg_sta_ext_ai_topo_cfg_t *cfg)
{
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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
iot_sg_printf("%s collected cnt %lu, dur %lu, "
"flag_v %lu, flag_i %lu, flag_pf %lu, curr_state %lu\n",
__FUNCTION__, cfg->collected_cnt, cfg->interval,
cfg->flag_v, cfg->flag_i, cfg->flag_pf, topo_info->flag_enable);
iot_sg_printf("%s time %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
cfg->start_tm.tm_year, cfg->start_tm.tm_mon, cfg->start_tm.tm_mday,
cfg->start_tm.tm_hour, cfg->start_tm.tm_min, cfg->start_tm.tm_sec);
iot_sg_sta_ext_ai_topo_reset();
topo_info->curr_cfg = *cfg;
topo_info->flag_enable = 1;
}
static void iot_sg_sta_ext_ai_ll_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;
if (ext_info->ai_module_info) {
os_mem_set(&ext_info->ai_module_info->ll_info.collect_info, 0,
sizeof(iot_sg_sta_ext_ai_ll_collect_info_t));
}
}
static void iot_sg_sta_ext_ai_ll_di_init(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_ai_ll_collect_info_t *ll_info =
&ext_info->ai_module_info->ll_info.collect_info;
iot_sg_sta_ext_ai_ll_cfg_t *cfg =
&ext_info->ai_module_info->ll_info.cfg;
ll_info->di_idx = 0;
ll_info->di_cnt = 0;
os_mem_set(&ll_info->resp_data, 0xff, sizeof(ll_info->resp_data));
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
if (cfg->flag_p) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_P;
ll_info->di_cnt++;
}
if (cfg->flag_i) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_CURRENT;
ll_info->di_cnt++;
}
if (cfg->flag_gi) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_GND_CURRENT;
ll_info->di_cnt++;
}
if (cfg->flag_v) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_VOLTAGE;
ll_info->di_cnt++;
}
if (cfg->flag_pf) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_PF;
ll_info->di_cnt++;
}
if (cfg->flag_pos) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_EPT_POS_SIG;
ll_info->di_cnt++;
}
if (cfg->flag_neg) {
ll_info->di_list[ll_info->di_cnt] = PROTO_69845_APP_OAD_EPT_NEG_SIG;
ll_info->di_cnt++;
}
if (node->is_three_phase) {
if (cfg->flag_pos) {
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EPT_POS_A_SIG;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EPT_POS_B_SIG;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EPT_POS_C_SIG;
ll_info->di_cnt++;
}
if (cfg->flag_neg) {
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EPT_NEG_A_SIG;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EPT_NEG_B_SIG;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EPT_NEG_C_SIG;
ll_info->di_cnt++;
}
if (cfg->flag_qtr) {
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EQT_QRT1_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EQT_QRT2_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EQT_QRT3_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] =
PROTO_69845_APP_OAD_EQT_QRT4_SUM;
ll_info->di_cnt++;
}
}
} else if (node->is_three_phase) {
if (cfg->flag_p) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_P_ALL;
ll_info->di_cnt++;
}
if (cfg->flag_i) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_I_ALL;
ll_info->di_cnt++;
}
if (cfg->flag_gi) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_I_N;
ll_info->di_cnt++;
}
if (cfg->flag_v) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_V_ALL;
ll_info->di_cnt++;
}
if (cfg->flag_pf) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_PF_ALL;
ll_info->di_cnt++;
}
if (cfg->flag_pos) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_POS_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_POS_A;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_POS_B;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_POS_C;
ll_info->di_cnt++;
}
if (cfg->flag_neg) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_NEG_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_NEG_A;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_NEG_B;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_NEG_C;
ll_info->di_cnt++;
}
if (cfg->flag_qtr) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EQT_QRT1_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EQT_QRT2_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EQT_QRT3_SUM;
ll_info->di_cnt++;
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EQT_QRT4_SUM;
ll_info->di_cnt++;
}
} else {
if (cfg->flag_p) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_P_T;
ll_info->di_cnt++;
}
if (cfg->flag_i) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_I_A;
ll_info->di_cnt++;
}
if (cfg->flag_gi) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_I_N;
ll_info->di_cnt++;
}
if (cfg->flag_v) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_V_A;
ll_info->di_cnt++;
}
if (cfg->flag_pf) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_PF_T;
ll_info->di_cnt++;
}
if (cfg->flag_pos) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_POS_SUM;
ll_info->di_cnt++;
}
if (cfg->flag_neg) {
ll_info->di_list[ll_info->di_cnt] = PROTO_645_2007_DI_EPT_NEG_SUM;
ll_info->di_cnt++;
}
}
}
static iot_pkt_t * iot_sg_sta_ext_ai_ll_698_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_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_collect_info_t *collect_info =
&ext_info->ai_module_info->ll_info.collect_info;
proto_69845_app_get_list_req_info_t *req = NULL;
server_addr_info_t server = {0};
if (collect_info->di_idx >= collect_info->di_cnt) {
goto out;
}
collect_info->last_idx = collect_info->di_idx;
di_cnt = collect_info->di_cnt - collect_info->di_idx;
if (di_cnt > IOT_SG_STA_AI_MOD_698_FRAME_MAX_OI_NUM) {
di_cnt = IOT_SG_STA_AI_MOD_698_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 = 0;
/* fill di from di_buff */
for (i = 0; i < di_cnt; i++) {
if (collect_info->di_idx + i >= IOT_SG_STA_EXT_AI_LL_DI_MAX) {
break;
}
oad = collect_info->di_list[collect_info->di_idx + i];
cur_index = collect_info->di_idx + 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++;
}
}
collect_info->di_idx = 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_sta_ext_ai_ll_645_data_handle(uint32_t rsp_di,
proto_645_header_t *resp_hdr)
{
uint8_t reason = 0, len;
uint32_t ret = ERR_INVAL;
iot_sg_sta_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_collect_info_t *collect_info =
&ext_info->ai_module_info->ll_info.collect_info;
iot_sg_sta_ext_ai_ll_cache_data_t *meter = &collect_info->resp_data;
iot_sg_printf("%s resp id %08x\n", __FUNCTION__, rsp_di);
switch (rsp_di) {
case PROTO_645_2007_DI_V_A:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_V_LEN) {
reason = 1;
goto drop;
}
os_mem_cpy(meter->v.a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_V_LEN);
break;
}
case PROTO_645_2007_DI_I_A:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_07_A_LEN) {
reason = 2;
goto drop;
}
os_mem_cpy(meter->i.a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_A_LEN);
break;
}
case PROTO_645_2007_DI_I_N:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_07_A_LEN) {
reason = 3;
goto drop;
}
os_mem_cpy(meter->gnd_a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_A_LEN);
break;
}
case PROTO_645_2007_DI_PF_T:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_07_PF_LEN) {
reason = 4;
goto drop;
}
os_mem_cpy(meter->pf.total, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_PF_LEN);
break;
}
case PROTO_645_2007_DI_P_T:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) < PROTO_645_07_P_LEN) {
reason = 5;
goto drop;
}
os_mem_cpy(meter->ap.total, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_P_LEN);
break;
}
case PROTO_645_2007_DI_EPT_POS_SUM:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 6;
goto drop;
}
os_mem_cpy(meter->pos_total, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_POS_A:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 7;
goto drop;
}
os_mem_cpy(meter->pos_a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_POS_B:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 8;
goto drop;
}
os_mem_cpy(meter->pos_b, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_POS_C:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 9;
goto drop;
}
os_mem_cpy(meter->pos_c, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_NEG_SUM:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 10;
goto drop;
}
os_mem_cpy(meter->neg_total, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_NEG_A:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 11;
goto drop;
}
os_mem_cpy(meter->neg_a, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_NEG_B:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 12;
goto drop;
}
os_mem_cpy(meter->neg_b, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EPT_NEG_C:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 13;
goto drop;
}
os_mem_cpy(meter->neg_c, &resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EQT_QRT1_SUM:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 14;
goto drop;
}
os_mem_cpy(meter->re_1st_total,
&resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EQT_QRT2_SUM:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 15;
goto drop;
}
os_mem_cpy(meter->re_2st_total,
&resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EQT_QRT3_SUM:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 16;
goto drop;
}
os_mem_cpy(meter->re_3st_total,
&resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_EQT_QRT4_SUM:
{
if ((resp_hdr->len - PROTO_645_2007_DI_LEN) <
PROTO_645_07_ENERGY_DATA_LEN) {
reason = 17;
goto drop;
}
os_mem_cpy(meter->re_4st_total,
&resp_hdr->data[PROTO_645_2007_DI_LEN],
PROTO_645_07_ENERGY_DATA_LEN);
break;
}
case PROTO_645_2007_DI_V_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->v.a)) {
reason = 18;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->v),
sizeof(meter->v.a));
os_mem_cpy(&meter->v, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
case PROTO_645_2007_DI_I_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->i.a)) {
reason = 19;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->i),
sizeof(meter->i.a));
os_mem_cpy(&meter->i, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
case PROTO_645_2007_DI_PF_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->pf.total)) {
reason = 20;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->pf),
sizeof(meter->pf.total));
os_mem_cpy(&meter->pf, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
case PROTO_645_2007_DI_P_ALL:
{
len = resp_hdr->len - PROTO_645_2007_DI_LEN;
if (len < sizeof(meter->ap.total)) {
reason = 21;
goto drop;
}
len = iot_sg_ext_get_min_data_len(len, sizeof(meter->ap),
sizeof(meter->ap.total));
os_mem_cpy(&meter->ap, &resp_hdr->data[PROTO_645_2007_DI_LEN], len);
break;
}
default:
reason = 22;
goto drop;
}
ret = ERR_OK;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static void iot_sg_sta_ext_ai_ll_698_oad_data_handle(
proto_69845_app_oad_resp_hdr_t *oad_data, uint32_t data_len)
{
uint8_t reason = 0;
uint32_t oad_value;
proto_69845_app_ele_data_t *ele_data;
iot_sg_sta_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_cache_data_t *meter =
&ext_info->ai_module_info->ll_info.collect_info.resp_data;
oad_value = iot_bytes_to_uint32((uint8_t*)&oad_data->oad.oi, 1);
switch (oad_value) {
case PROTO_69845_APP_OAD_GND_CURRENT:
{
proto_69845_gnd_a_data_handle(meter->gnd_a, IOT_SG_STA_METER_A_LEN,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_POS_SIG:
{
proto_69845_energy_sum_data_handle(meter->pos_total,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_POS_A_SIG:
{
proto_69845_energy_sum_data_handle(meter->pos_a,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_POS_B_SIG:
{
proto_69845_energy_sum_data_handle(meter->pos_b,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_POS_C_SIG:
{
proto_69845_energy_sum_data_handle(meter->pos_c,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_NEG_SIG:
{
proto_69845_energy_sum_data_handle(meter->neg_total,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_NEG_A_SIG:
{
proto_69845_energy_sum_data_handle(meter->neg_a,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_NEG_B_SIG:
{
proto_69845_energy_sum_data_handle(meter->neg_b,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EPT_NEG_C_SIG:
{
proto_69845_energy_sum_data_handle(meter->neg_c,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EQT_QRT1_SUM:
{
proto_69845_energy_sum_data_handle(meter->re_1st_total,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EQT_QRT2_SUM:
{
proto_69845_energy_sum_data_handle(meter->re_2st_total,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EQT_QRT3_SUM:
{
proto_69845_energy_sum_data_handle(meter->re_3st_total,
oad_data->result, data_len);
break;
}
case PROTO_69845_APP_OAD_EQT_QRT4_SUM:
{
proto_69845_energy_sum_data_handle(meter->re_4st_total,
oad_data->result, data_len);
break;
}
default:
{
if (data_len < sizeof(*ele_data)) {
reason = 1;
goto drop;
}
data_len -= sizeof(*ele_data);
ele_data = (proto_69845_app_ele_data_t *)oad_data->result;
if (ele_data->data_type != PROTO_69845_APP_DATA_ARRAY) {
reason = 2;
goto drop;
}
if (!ele_data->num_of_data) {
reason = 3;
goto drop;
}
switch (oad_value) {
case PROTO_69845_APP_OAD_VOLTAGE:
{
proto_69845_v_data_handle(&meter->v, ele_data, data_len);
break;
}
case PROTO_69845_APP_OAD_CURRENT:
{
proto_69845_a_data_handle(&meter->i, ele_data, data_len);
break;
}
case PROTO_69845_APP_OAD_PF:
{
proto_69845_pf_ele_data_handle(&meter->pf, ele_data, data_len);
break;
}
case PROTO_69845_APP_OAD_P:
{
proto_69845_p_data_handle(&meter->ap, ele_data, data_len);
break;
}
default:
reason = 4;
break;
}
break;
}
}
return;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
static void iot_sg_sta_ext_ai_ll_save(uint8_t *addr, iot_time_tm_t *tm,
uint8_t flag_data)
{
uint16_t index = 0, unit_len;
uint32_t ret;
iot_pkt_t *pkt;
iot_time_tm_t cache_tm = { 0 };
iot_sg_sta_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_cfg_t *cfg = &ext_info->ai_module_info->ll_info.cfg;
iot_sg_sta_ext_ai_ll_cache_data_t *meter =
&ext_info->ai_module_info->ll_info.collect_info.resp_data;
iot_sg_meter_ai_ll_unit_data_t *ll_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);
if (iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_AI_LL, &unit_len, NULL)) {
return;
}
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
iot_sg_printf("%s pkt err\n", __FUNCTION__);
return;
}
ll_data = (iot_sg_meter_ai_ll_unit_data_t *)iot_pkt_put(pkt, unit_len);
ret = iot_sg_sta_flash_unit_data_find_by_time(addr,
&index, tm, (uint8_t*)ll_data, unit_len,
IOT_SG_STA_METER_DATA_TYPE_AI_LL, 1);
if (ret == ERR_OK) {
cache_tm.tm_year = (uint16_t)(ll_data->unit_tm.year + 2000);
cache_tm.tm_mon = (uint8_t)ll_data->unit_tm.month;
cache_tm.tm_mday = (uint8_t)ll_data->unit_tm.day;
cache_tm.tm_hour = (uint8_t)ll_data->unit_tm.hour;
cache_tm.tm_min = (uint8_t)ll_data->unit_tm.minute;
cache_tm.tm_sec = ll_data->unit_tm.second;
if (iot_rtc_delta_calc(&cache_tm, tm) != 0) {
index++;
}
}
if (index >= IOT_SG_STA_METER_AI_LL_CNT) {
index = 0;
}
ll_data->unit_tm.year = (uint32_t)(tm->tm_year % 100);
ll_data->unit_tm.month = (uint32_t)(tm->tm_mon);
ll_data->unit_tm.day = (uint32_t)(tm->tm_mday);
ll_data->unit_tm.hour = (uint32_t)(tm->tm_hour);
ll_data->unit_tm.minute = (uint32_t)(tm->tm_min);
ll_data->unit_tm.second = tm->tm_sec;
ll_data->interval = (uint8_t)(cfg->interval / 60);
ll_data->flag_p = cfg->flag_p;
ll_data->flag_i = cfg->flag_i;
ll_data->flag_gi = cfg->flag_gi;
ll_data->flag_v = cfg->flag_v;
ll_data->flag_pf = cfg->flag_pf;
ll_data->flag_pos = cfg->flag_pos;
ll_data->flag_neg = cfg->flag_neg;
ll_data->flag_qtr = cfg->flag_qtr;
ll_data->start_year = (uint32_t)(cfg->start_tm.tm_year % 100);
ll_data->start_month = (uint32_t)(cfg->start_tm.tm_mon);
ll_data->start_day = (uint32_t)(cfg->start_tm.tm_mday);
ll_data->start_hour = (uint32_t)(cfg->start_tm.tm_hour);
ll_data->start_minute = (uint32_t)(cfg->start_tm.tm_min);
ll_data->start_sec = cfg->start_tm.tm_sec;
ll_data->cycle = cfg->collected_cnt / IOT_SG_STA_AI_MOD_LL_TIMES_IN_CYC;
ll_data->valid = cfg->valid;
ll_data->neg_delta = cfg->neg_delta;
ll_data->delta = cfg->delta;
ll_data->flag_data = flag_data;
os_mem_cpy(&ll_data->v, &meter->v, sizeof(meter->v));
os_mem_cpy(&ll_data->i, &meter->i, sizeof(meter->i));
os_mem_cpy(ll_data->gnd_a, meter->gnd_a, sizeof(meter->gnd_a));
os_mem_cpy(&ll_data->ap, &meter->ap, sizeof(meter->ap));
os_mem_cpy(&ll_data->pf, &meter->pf, sizeof(meter->pf));
os_mem_cpy(ll_data->pos_total, meter->pos_total, sizeof(meter->pos_total));
os_mem_cpy(ll_data->pos_a, meter->pos_a, sizeof(meter->pos_a));
os_mem_cpy(ll_data->pos_b, meter->pos_b, sizeof(meter->pos_b));
os_mem_cpy(ll_data->pos_c, meter->pos_c, sizeof(meter->pos_c));
os_mem_cpy(ll_data->neg_total, meter->neg_total, sizeof(meter->neg_total));
os_mem_cpy(ll_data->neg_a, meter->neg_a, sizeof(meter->neg_a));
os_mem_cpy(ll_data->neg_b, meter->neg_b, sizeof(meter->neg_b));
os_mem_cpy(ll_data->neg_c, meter->neg_c, sizeof(meter->neg_c));
os_mem_cpy(ll_data->re_1st_total, meter->re_1st_total,
sizeof(meter->re_1st_total));
os_mem_cpy(ll_data->re_2st_total, meter->re_2st_total,
sizeof(meter->re_2st_total));
os_mem_cpy(ll_data->re_3st_total, meter->re_3st_total,
sizeof(meter->re_3st_total));
os_mem_cpy(ll_data->re_4st_total, meter->re_4st_total,
sizeof(meter->re_4st_total));
iot_sg_sta_flash_unit_data_save(addr, index, (uint8_t*)ll_data,
unit_len, IOT_SG_STA_METER_DATA_TYPE_AI_LL);
iot_sg_sta_flash_unit_data_check(addr, index, tm,
IOT_SG_STA_METER_DATA_TYPE_AI_LL);
iot_pkt_free(pkt);
}
void iot_sg_sta_ext_ai_ll_func(void)
{
iot_pkt_t *pkt = NULL;
uint8_t addr[IOT_MAC_ADDR_LEN], flag_new = 0;
uint32_t ret;
iot_sg_sta_node_desc_t *node;
iot_time_tm_t curr_tm;
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_ai_ll_cfg_t *cfg;
iot_sg_sta_ext_ai_ll_collect_info_t *collect_info;
if (iot_sg_sta_ext_ai_module_check()) {
goto out;
}
collect_info = &ext_info->ai_module_info->ll_info.collect_info;
cfg = &ext_info->ai_module_info->ll_info.cfg;
if (!collect_info->flag_enable) {
goto out;
}
p_sg_glb->desc.sta->drv->get_login_addr(addr);
node = iot_sg_sta_node_find_by_addr(addr);
if (node == NULL) {
goto out;
}
iot_sg_sta_ext_ai_time_get(&curr_tm);
switch (collect_info->state) {
case IOT_SG_STA_AI_MOD_LL_SM_IDLE:
{
if (collect_info->cnt >= cfg->collected_cnt) {
collect_info->flag_enable = 0;
iot_sg_printf("%s collect over time %lu-%lu-%lu %lu:%lu:%lu\n",
__FUNCTION__, curr_tm.tm_year, curr_tm.tm_mon, curr_tm.tm_mday,
curr_tm.tm_hour, curr_tm.tm_min, curr_tm.tm_sec);
} else {
if (iot_rtc_delta_calc(&collect_info->collect_tm, &curr_tm) >= 0) {
/* when current tm is greater than or equal to next tm of
* reading load curve data, start read load curve data.
*/
collect_info->state = IOT_SG_STA_AI_MOD_LL_SM_SEND;
iot_sg_sta_ext_ai_ll_di_init(node);
flag_new = 1;
goto send;
}
}
break;
}
case IOT_SG_STA_AI_MOD_LL_SM_WAIT:
{
if (!collect_info->timeout) {
if (!collect_info->repeat_cnt || collect_info->flag_resp) {
collect_info->di_idx++;
collect_info->repeat_cnt = 0;
flag_new = 1;
}
if (collect_info->di_idx >= collect_info->di_cnt) {
iot_sg_sta_ext_ai_ll_save(node->entry.addr,
&collect_info->collect_tm, 1);
collect_info->cnt++;
collect_info->state = IOT_SG_STA_AI_MOD_LL_SM_IDLE;
collect_info->collect_tm = iot_sg_ext_get_next_lr_ts(
collect_info->collect_tm, cfg->interval,
curr_tm);
iot_sg_printf("%s curr collect cnt %lu "
"next collect time %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
collect_info->cnt, collect_info->collect_tm.tm_year,
collect_info->collect_tm.tm_mon,
collect_info->collect_tm.tm_mday,
collect_info->collect_tm.tm_hour,
collect_info->collect_tm.tm_min,
collect_info->collect_tm.tm_sec);
goto out;
}
if (collect_info->repeat_cnt) {
collect_info->repeat_cnt--;
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
collect_info->di_idx = collect_info->last_idx;
}
}
collect_info->state = IOT_SG_STA_AI_MOD_LL_SM_SEND;
} else {
collect_info->timeout--;
break;
}
}
case IOT_SG_STA_AI_MOD_LL_SM_SEND:
{
send:
if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
pkt = iot_sg_sta_ext_ai_ll_698_msg_build(addr);
} else {
pkt = proto_645_build_mr_msg(PROTO_645_2007_ID, addr,
collect_info->di_list[collect_info->di_idx]);
}
if (pkt) {
if (!collect_info->seq) {
collect_info->seq = (uint16_t)os_rand();
} else {
collect_info->seq++;
}
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_EXT_AI_LL,
addr, collect_info->seq, node->data_type, iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt),
IOT_SG_STA_EXT_DRV_READ_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],
collect_info->di_list[collect_info->di_idx],
collect_info->di_idx);
collect_info->state = IOT_SG_STA_AI_MOD_LL_SM_WAIT;
collect_info->timeout = IOT_SG_STA_EXT_READ_DATA_TIMEOUT;
if (flag_new) {
collect_info->repeat_cnt = 1;
}
collect_info->flag_resp = 0;
} else if (node->data_type == IOT_SG_STA_DATA_TYPE_69845) {
collect_info->di_idx = collect_info->last_idx;
}
iot_pkt_free(pkt);
}
break;
}
default:
break;
}
out:
return;
}
static uint8_t iot_sg_sta_ext_ai_ll_run_check(void)
{
iot_sg_sta_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_collect_info_t *ll_info =
&ext_info->ai_module_info->ll_info.collect_info;
return ll_info->flag_enable;
}
static void iot_sg_sta_ext_ai_ll_start(iot_sg_sta_ext_ai_ll_cfg_t *cfg,
uint8_t flag_recover, uint16_t collected_cnt)
{
iot_time_tm_t curr_tm;
uint8_t addr[IOT_MAC_ADDR_LEN] = {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_ai_ll_info_t *ll_info =
&ext_info->ai_module_info->ll_info;
if (iot_sg_sta_ext_ai_ll_run_check()) {
return;
}
iot_sg_printf("%s cfg : collect cnt %lu, dur %lu. flag_recover %lu, "
"collected cnt %lu\n", __FUNCTION__, cfg->collected_cnt, cfg->interval,
flag_recover, collected_cnt);
iot_sg_printf("%s flag_p %lu, flag_i %lu, flag_gi %lu, flag_v %lu, "
"flag_pt %lu, flag_pos %lu, flag_neg %lu, flag_qtr %lu\n",
__FUNCTION__, cfg->flag_p, cfg->flag_i, cfg->flag_gi, cfg->flag_v,
cfg->flag_pf, cfg->flag_pos, cfg->flag_neg, cfg->flag_qtr);
iot_sg_printf("%s time %lu-%lu-%lu %lu:%lu:%lu\n", __FUNCTION__,
cfg->start_tm.tm_year, cfg->start_tm.tm_mon, cfg->start_tm.tm_mday,
cfg->start_tm.tm_hour, cfg->start_tm.tm_min, cfg->start_tm.tm_sec);
iot_sg_sta_ext_ai_ll_reset();
ll_info->cfg = *cfg;
ll_info->collect_info.flag_enable = 1;
ll_info->flag_recover = 1;
iot_sg_sta_ext_ai_time_get(&curr_tm);
if (iot_rtc_delta_calc(&curr_tm, &cfg->start_tm) >= 0) {
ll_info->collect_info.collect_tm = cfg->start_tm;
} else {
ll_info->collect_info.collect_tm = iot_sg_ext_get_next_lr_ts(
cfg->start_tm, cfg->interval, curr_tm);
}
if (flag_recover) {
/* recover the collection status after power off or restart */
ll_info->collect_info.cnt = collected_cnt;
} else {
/* save cfg */
p_sg_glb->desc.sta->drv->get_login_addr(addr);
iot_sg_sta_ext_ai_ll_save(addr, &ll_info->collect_info.collect_tm, 0);
}
}
void iot_sg_sta_ext_ai_ll_recover(iot_time_tm_t *tm)
{
uint8_t addr[IOT_MAC_ADDR_LEN] = {0};
uint16_t latest_idx, collected_cnt, unit_len;
uint32_t ret;
int64_t delta;
iot_pkt_t *pkt = NULL;
iot_time_tm_t curr_tm;
iot_sg_sta_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_cfg_t cfg = {0};
iot_sg_meter_ai_ll_unit_data_t *ll_data;
if (iot_sg_sta_ext_ai_module_check()) {
goto out;
}
if (ext_info->ai_module_info->ll_info.flag_recover) {
goto out;
}
if (iot_sg_sta_flash_unit_get_data_info(IOT_SG_STA_METER_DATA_TYPE_AI_LL,
&unit_len, NULL)) {
goto out;
}
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
iot_sg_printf("%s pkt err\n", __FUNCTION__);
goto out;
}
ext_info->ai_module_info->ll_info.flag_recover = 1;
p_sg_glb->desc.sta->drv->get_login_addr(addr);
ll_data = (iot_sg_meter_ai_ll_unit_data_t *)iot_pkt_put(pkt, unit_len);
ret = iot_sg_sta_flash_unit_data_find_latest(addr, &latest_idx,
(uint8_t *)ll_data, unit_len, IOT_SG_STA_METER_DATA_TYPE_AI_LL);
if (ret) {
goto out;
}
/* recover ai management module time */
if (iot_sg_sta_ext_ai_time_get(&curr_tm)) {
curr_tm = *tm;
if (!ll_data->valid) {
goto out;
}
delta = (int64_t)ll_data->delta;
if (ll_data->neg_delta) {
delta = 0 - delta;
}
iot_rtc_delta_add(delta, &curr_tm);
iot_sg_sta_ext_ai_time_set(&curr_tm);
}
/* recover line lose cfg */
cfg.flag_p = ll_data->flag_p;
cfg.flag_i = ll_data->flag_i;
cfg.flag_gi = ll_data->flag_gi;
cfg.flag_v = ll_data->flag_v;
cfg.flag_pf = ll_data->flag_pf;
cfg.flag_pos = ll_data->flag_pos;
cfg.flag_neg = ll_data->flag_neg;
cfg.flag_qtr = ll_data->flag_qtr;
cfg.interval = ll_data->interval * 60;
cfg.collected_cnt = (uint16_t)(IOT_SG_STA_AI_MOD_LL_TIMES_IN_CYC *
ll_data->cycle);
cfg.start_tm.tm_year = (uint16_t)ll_data->start_year + 2000;
cfg.start_tm.tm_mon = (uint8_t)ll_data->start_month;
cfg.start_tm.tm_mday = (uint8_t)ll_data->start_day;
cfg.start_tm.tm_hour = (uint8_t)ll_data->start_hour;
cfg.start_tm.tm_min = (uint8_t)ll_data->start_minute;
cfg.start_tm.tm_sec = ll_data->start_sec;
cfg.valid = ll_data->valid;
cfg.neg_delta = ll_data->neg_delta;
cfg.delta = ll_data->delta;
/* recover collection cnt */
delta = iot_rtc_delta_calc(&cfg.start_tm, &curr_tm);
if (delta > (cfg.interval * cfg.collected_cnt)) {
collected_cnt = cfg.collected_cnt;
} else if (delta > 0) {
collected_cnt = (uint16_t)(delta / cfg.interval) + 1;
} else {
collected_cnt = 0;
}
iot_sg_sta_ext_ai_ll_start(&cfg, 1, collected_cnt);
out:
if (pkt) {
iot_pkt_free(pkt);
}
return;
}
static uint32_t iot_sg_sta_ext_ai_645_data_handle(uint16_t seq,
uint8_t data_type, uint8_t *resp_data, uint16_t resp_len,
uint8_t *req_data, uint16_t req_len, uint8_t *is_nack, uint8_t type)
{
uint8_t reason = 0, addr[IOT_MAC_ADDR_LEN] = {0};
uint32_t rsp_di, ret = ERR_INVAL;
proto_645_header_t *resp_hdr, *req_hdr;
(void)seq;
if (data_type != IOT_SG_STA_DATA_TYPE_645_07) {
reason = 1;
goto drop;
}
if ((req_data == NULL) || !req_len) {
reason = 2;
goto drop;
}
if ((resp_data == NULL) || !resp_len) {
ret = ERR_TIMEOVER;
reason = 3;
goto drop;
}
p_sg_glb->desc.sta->drv->get_login_addr(addr);
if (iot_sg_ext_read_645_nack_check(req_data, req_len, resp_data, resp_len,
addr) == ERR_OK) {
iot_sg_printf("%s nack\n", __FUNCTION__);
if (is_nack) {
*is_nack = 1;
}
ret = ERR_OK;
goto out;
}
if (proto_645_check_di_fn_match(req_data, req_len,
resp_data, resp_len)) {
reason = 4;
goto drop;
}
resp_hdr = (proto_645_header_t*)resp_data;
req_hdr = (proto_645_header_t*)req_data;
if (!iot_mac_addr_cmp(req_hdr->addr, resp_hdr->addr)) {
reason = 5;
goto drop;
}
if ((resp_hdr->control.ack != PROTO_645_ACK_NORMAL)
|| (resp_hdr->control.dir != PROTO_645_DIR_SLAVE)) {
reason = 6;
goto drop;
}
if (resp_hdr->len < PROTO_645_2007_DI_LEN) {
reason = 7;
goto drop;
}
proto_645_sub33_handle(resp_hdr->data, resp_hdr->len);
rsp_di = proto_645_2007_byte_to_di(resp_hdr->data);
if (type == IOT_SG_STA_AI_MOD_METER_RSP_TYPE_TOPO) {
ret = iot_sg_sta_ext_ai_topo_645_data_handle(rsp_di, resp_hdr);
} else {
ret = iot_sg_sta_ext_ai_ll_645_data_handle(rsp_di, resp_hdr);
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static uint32_t iot_sg_sta_ext_ai_698_get_nor_list_data_handle(
proto_69845_app_get_resp_t *get_resp, uint32_t data_len, uint8_t type)
{
uint8_t i, *data, reason = 0;
uint32_t oad_data_len, ret = ERR_FAIL;
proto_69845_app_oad_resp_hdr_t *oad_data;
proto_69845_app_get_resp_normal_list_t *get_normal_resp;
if (data_len < sizeof(*get_normal_resp)) {
reason = 1;
goto drop;
}
get_normal_resp = (proto_69845_app_get_resp_normal_list_t*)get_resp->data;
data_len -= sizeof(*get_normal_resp);
if (!get_normal_resp->oad_cnt) {
reason = 2;
goto drop;
}
data = get_normal_resp->oad_data;
for (i = 0; i < get_normal_resp->oad_cnt; i++) {
if (data_len < sizeof(*oad_data)) {
reason = 3;
goto drop;
}
oad_data = (proto_69845_app_oad_resp_hdr_t *)data;
data_len -= sizeof(*oad_data);
data += sizeof(*oad_data);
if (oad_data->result_type != PROTO_69845_APP_GET_RESULT_DATA) {
/* skip dar, see PROTO_69845_APP_DAR_XXX */
data_len--;
data++;
continue;
}
if (proto_69845_get_data_len((proto_69845_app_data_t *)oad_data->result,
data_len, &oad_data_len)) {
reason = 4;
goto drop;
}
if (data_len < oad_data_len) {
reason = 5;
goto drop;
}
if (type == IOT_SG_STA_AI_MOD_METER_RSP_TYPE_TOPO) {
iot_sg_sta_ext_ai_topo_698_oad_data_handle(oad_data, oad_data_len);
} else {
iot_sg_sta_ext_ai_ll_698_oad_data_handle(oad_data, oad_data_len);
}
data += oad_data_len;
data_len -= oad_data_len;
}
ret = ERR_OK;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
static uint32_t iot_sg_sta_ext_ai_698_sec_data_handle(
proto_69845_app_sec_req_resp_info_t *sec_resp, uint32_t data_len,
uint8_t type)
{
uint32_t ret = ERR_FAIL;
uint16_t sec_len;
uint8_t *data, reason = 0;
proto_69845_app_req_resp_t *resp;
proto_69845_app_get_resp_t *get_resp;
proto_69845_app_len_descript_t *len_desc;
len_desc = (proto_69845_app_len_descript_t *)((uint8_t *)sec_resp + 1);
if (!len_desc->mub_flag) {
data = sec_resp->data;
sec_len = sec_resp->len;
} else {
if (len_desc->byte_num == 1) {
sec_len = sec_resp->data[0];
data = sec_resp->data + 1;
data_len -= 1;
} else if (len_desc->byte_num == 2) {
sec_len = iot_bytes_to_uint16(sec_resp->data, 1);
data = sec_resp->data + 2;
data_len -= 2;
} else {
reason = 1;
goto out;
}
}
if (data_len < sec_len) {
reason = 2;
goto out;
}
if (sec_len < sizeof(*resp)) {
reason = 3;
goto out;
}
resp = (proto_69845_app_req_resp_t*)data;
sec_len -= sizeof(*resp);
switch (resp->type) {
case PROTO_69845_S_APP_GET_RESP:
{
if (sec_len < sizeof(*get_resp)) {
reason = 4;
goto out;
}
get_resp = (proto_69845_app_get_resp_t*)resp->data;
sec_len -= sizeof(*get_resp);
switch (get_resp->data_type) {
case PROTO_69845_APP_GET_NORMALLIST:
{
ret = iot_sg_sta_ext_ai_698_get_nor_list_data_handle(get_resp,
sec_len, type);
break;
}
default:
reason = 5;
break;
}
break;
}
default:
reason = 6;
break;
}
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_ext_ai_698_data_handle(uint16_t seq,
uint8_t data_type, uint8_t *resp_data, uint16_t resp_len,
uint8_t *req_data, uint16_t req_len, uint8_t type)
{
uint8_t reason = 0, *req_ser_addr, *resp_ser_addr;
uint32_t ret = ERR_INVAL, len;
proto_69845_frame_head_info_t *resp_hdr, *req_hdr;
proto_69845_app_req_resp_t *resp;
proto_69845_app_sec_req_resp_info_t *sec_resp;
apdu_info_t apdu;
(void)seq;
if (data_type != IOT_SG_STA_DATA_TYPE_69845) {
reason = 1;
goto drop;
}
if ((req_data == NULL) || !req_len) {
reason = 2;
goto drop;
}
if ((resp_data == NULL) || !resp_len) {
ret = ERR_TIMEOVER;
reason = 3;
goto drop;
}
req_hdr = proto_69845_sanity_check(req_data, req_len);
resp_hdr = proto_69845_sanity_check(resp_data, resp_len);
if(!req_hdr || !resp_hdr) {
reason = 4;
goto drop;
}
req_ser_addr = proto_69845_get_ser_addr(req_hdr);
resp_ser_addr = proto_69845_get_ser_addr(resp_hdr);
if (!iot_mac_addr_cmp(req_ser_addr, resp_ser_addr)) {
reason = 5;
goto drop;
}
if (resp_hdr->ctrl.dir_prm != PROTO_69845_D_P_SERVER_RESPONSE &&
resp_hdr->ctrl.dir_prm != PROTO_69845_D_P_SERVER_REPORT) {
reason = 6;
goto drop;
}
if (resp_hdr->ctrl.fragment != PROTO_69845_APDU_WHOLE) {
reason = 7;
goto drop;
}
if (proto_69845_get_apdu(resp_hdr, resp_len, &apdu)) {
reason = 8;
goto drop;
}
len = apdu.len;
if (len < sizeof(*resp)) {
reason = 9;
goto drop;
}
resp = (proto_69845_app_req_resp_t*)apdu.ptr;
len -= sizeof(*resp);
switch (resp->type) {
case PROTO_69845_S_APP_SECURITY_RESP:
{
if (len < sizeof(*sec_resp)) {
reason = 10;
goto drop;
}
sec_resp = (proto_69845_app_sec_req_resp_info_t*)resp->data;
len -= sizeof(*sec_resp);
if (iot_sg_sta_ext_ai_698_sec_data_handle(sec_resp, len, type)) {
reason = 11;
goto drop;
}
break;
}
default:
reason = 12;
goto drop;
}
ret = ERR_OK;
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
void iot_sg_sta_ext_ai_topo_data_handle(uint16_t seq,
uint8_t data_type, uint8_t *resp_data, uint16_t resp_len,
uint8_t *req_data, uint16_t req_len)
{
uint8_t flag_nack = 0;
uint32_t ret;
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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
if (seq != topo_info->seq) {
return;
}
if (data_type == IOT_SG_STA_DATA_TYPE_69845) {
ret = iot_sg_sta_ext_ai_698_data_handle(seq, data_type, resp_data,
resp_len, req_data, req_len, IOT_SG_STA_AI_MOD_METER_RSP_TYPE_TOPO);
} else {
ret = iot_sg_sta_ext_ai_645_data_handle(seq, data_type, resp_data,
resp_len, req_data, req_len, &flag_nack,
IOT_SG_STA_AI_MOD_METER_RSP_TYPE_TOPO);
}
if (ret == ERR_OK || ret == ERR_TIMEOVER) {
if (ret == ERR_OK) {
topo_info->flag_resp = !flag_nack;
topo_info->repeat_cnt = 0;
}
topo_info->timeout = 0;
}
}
void iot_sg_sta_ext_ai_ll_data_handle(uint16_t seq,
uint8_t data_type, uint8_t *resp_data, uint16_t resp_len,
uint8_t *req_data, uint16_t req_len)
{
uint8_t flag_nack = 0;
uint32_t ret;
iot_sg_sta_ext_info_t *ext_info = &p_sg_glb->desc.sta->ext_info;
iot_sg_sta_ext_ai_ll_collect_info_t *collect_info =
&ext_info->ai_module_info->ll_info.collect_info;
if (seq != collect_info->seq) {
return;
}
if (data_type == IOT_SG_STA_DATA_TYPE_69845) {
ret = iot_sg_sta_ext_ai_698_data_handle(seq, data_type, resp_data,
resp_len, req_data, req_len, IOT_SG_STA_AI_MOD_METER_RSP_TYPE_LL);
} else {
ret = iot_sg_sta_ext_ai_645_data_handle(seq, data_type, resp_data,
resp_len, req_data, req_len, &flag_nack,
IOT_SG_STA_AI_MOD_METER_RSP_TYPE_LL);
}
if (ret == ERR_OK || ret == ERR_TIMEOVER) {
if (ret == ERR_OK) {
collect_info->flag_resp = !flag_nack;
collect_info->repeat_cnt = 0;
}
collect_info->timeout = 0;
}
}
static void iot_sg_sta_ext_ai_ntb_to_tm(iot_time_tm_t *start,
uint32_t start_ntb)
{
uint32_t curr_ntb, delta;
curr_ntb = iot_plc_get_ntb(p_sg_glb->plc_app_h);
if (start_ntb > curr_ntb) {
delta = (start_ntb - curr_ntb);
} else {
delta = 0xffffffff - curr_ntb + start_ntb;
}
delta = GW_APP_NTB_TO_MS(delta) / 1000;
iot_rtc_delta_add((int64_t)delta, start);
}
static iot_pkt_t *iot_sg_sta_ext_ai_topo_start_rsp(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0;
iot_pkt_t *rsp = NULL;
iot_time_tm_t tm;
proto_645_07_ai_topo_start_t *cmd;
iot_sg_sta_ext_ai_topo_cfg_t cfg = {0};
proto_645_sub33_handle(data, len);
if (len < sizeof(*cmd)) {
reason = 1;
goto drop;
}
cmd = (proto_645_07_ai_topo_start_t*)data;
if (iot_bcd_data_check(data, 6)) {
tm.tm_year = iot_bcd_to_byte(cmd->year) + 2000;
tm.tm_mon = iot_bcd_to_byte(cmd->mon);
tm.tm_mday = iot_bcd_to_byte(cmd->day);
tm.tm_hour = iot_bcd_to_byte(cmd->hour);
tm.tm_min = iot_bcd_to_byte(cmd->min);
tm.tm_sec = iot_bcd_to_byte(cmd->sec);
} else {
reason = 2;
goto drop;
}
if (!cmd->flag_i && !cmd->flag_pf && !cmd->flag_v) {
cfg.flag_v = 1;
cfg.flag_i = 1;
cfg.flag_pf = 1;
} else {
cfg.flag_v = cmd->flag_v;
cfg.flag_i = cmd->flag_i;
cfg.flag_pf = cmd->flag_pf;
}
if (cmd->interval) {
if (cmd->interval <= IOT_SG_STA_AI_MOD_TOPO_INTER_MIN) {
cfg.interval = IOT_SG_STA_AI_MOD_TOPO_INTER_MIN;
} else {
cfg.interval = cmd->interval;
}
} else {
cfg.interval = IOT_SG_STA_AI_MOD_TOPO_INTER_DEF;
}
if (cmd->cycle_cnt) {
cfg.collected_cnt = (cmd->cycle_cnt * \
IOT_SG_STA_AI_MOD_TOPO_CYCLE_DUR) / cfg.interval;
} else {
cfg.collected_cnt = IOT_SG_STA_AI_MOD_TOPO_CYCLE_DUR / cfg.interval;
}
iot_sg_sta_ext_ai_time_set(&tm);
cfg.start_tm = tm;
iot_sg_sta_ext_ai_ntb_to_tm(&cfg.start_tm, cmd->start_ntb);
iot_sg_sta_ext_ai_topo_start(&cfg);
rsp = proto_645_build_msg(addr, NULL, 0, PROTO_645_2007_DI_AI_TOPO_START,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_AI_XIAN,
PROTO_645_2007_ID, PROTO_645_FOLLOW_INVALID);
drop:
if (reason) {
iot_sg_printf("%s fail %lu\n", __FUNCTION__, reason);
proto_645_add33_handle(data, len);
}
return rsp;
}
static iot_pkt_t *iot_sg_sta_ext_ai_topo_query_rsp(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, max_cnt, cnt, unit_len, *src, *dst, i, idx, offset;
uint32_t di, rsp_data_len;
int64_t delta;
iot_time_tm_t start_tm = {0};
iot_pkt_t *rsp_pkt = NULL, *data_pkt = NULL;
iot_sg_sta_node_desc_t *node;
proto_645_07_ai_topo_query_dl_t *query;
proto_645_07_ai_topo_query_ul_t *resp_data_hdr;
iot_sg_sta_ext_ai_topo_data_unit_t *unit_data;
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_ai_topo_info_t *topo_info =
&ext_info->ai_module_info->topo_info;
iot_sg_sta_ext_ai_topo_data_t *topo_data = &topo_info->topo_data;
proto_645_sub33_handle(data, len);
p_sg_glb->desc.sta->drv->get_login_addr(addr);
node = iot_sg_sta_node_find_by_addr(addr);
if (node == NULL) {
reason = 1;
goto drop;
}
if (len < sizeof(*query)) {
reason = 2;
goto drop;
}
query = (proto_645_07_ai_topo_query_dl_t*)data;
if (iot_bcd_check(query->offset)) {
offset = iot_bcd_to_byte(query->offset);
} else {
reason = 3;
goto drop;
}
if (topo_data->end_idx >= topo_data->start_idx) {
cnt = topo_data->end_idx - topo_data->start_idx;
} else {
cnt = IOT_SG_STA_EXT_AI_TOPO_DATA_MAX - topo_data->start_idx
+ topo_data->end_idx;
}
if (offset >= cnt) {
cnt = 0;
} else {
cnt = cnt - offset;
}
di = proto_645_2007_byte_to_di(query->di);
iot_sg_printf("%s di %08x, offset %lu, cnt %lu\n",
__FUNCTION__, di, offset, query->cnt);
switch (di) {
case PROTO_645_2007_DI_V_A:
{
if (!topo_info->curr_cfg.flag_v) {
cnt = 0;
}
unit_len = PROTO_645_V_LEN;
break;
}
case PROTO_645_2007_DI_V_ALL:
{
if (!topo_info->curr_cfg.flag_v) {
cnt = 0;
}
if (!node->is_three_phase) {
di = PROTO_645_2007_DI_V_A;
unit_len = PROTO_645_V_LEN;
} else {
unit_len = sizeof(proto_645_v_t);
}
break;
}
case PROTO_645_2007_DI_I_A:
{
if (!topo_info->curr_cfg.flag_i) {
cnt = 0;
}
unit_len = PROTO_645_07_A_LEN;
break;
}
case PROTO_645_2007_DI_I_ALL:
{
if (!topo_info->curr_cfg.flag_i) {
cnt = 0;
}
if (!node->is_three_phase) {
di = PROTO_645_2007_DI_I_A;
unit_len = PROTO_645_07_A_LEN;
} else {
unit_len = sizeof(proto_645_07_a_t);
}
break;
}
case PROTO_645_2007_DI_PF_T:
{
if (!topo_info->curr_cfg.flag_pf) {
cnt = 0;
}
unit_len = PROTO_645_07_PF_LEN;
break;
}
case PROTO_645_2007_DI_PF_ALL:
{
if (!topo_info->curr_cfg.flag_pf) {
cnt = 0;
}
if (!node->is_three_phase) {
di = PROTO_645_2007_DI_PF_T;
unit_len = PROTO_645_07_PF_LEN;
} else {
unit_len = sizeof(proto_645_07_pf_t);
}
break;
}
default:
reason = 4;
goto drop;
}
cnt = min(cnt, query->cnt);
max_cnt = IOT_SG_STA_AI_MOD_TOPO_DATA_RESP_LEN_MAX / unit_len;
cnt = min(cnt, max_cnt);
rsp_data_len = sizeof(*resp_data_hdr) + cnt * unit_len;
data_pkt = iot_pkt_alloc(rsp_data_len, IOT_SMART_GRID_MID);
if (data_pkt == NULL) {
reason = 5;
goto drop;
}
resp_data_hdr = (proto_645_07_ai_topo_query_ul_t*)iot_pkt_put(data_pkt,
rsp_data_len);
if (!cnt) {
resp_data_hdr->year = 0xff;
resp_data_hdr->mon = 0xff;
resp_data_hdr->day = 0xff;
resp_data_hdr->hour = 0xff;
resp_data_hdr->min = 0xff;
resp_data_hdr->sec = 0xff;
} else {
start_tm = topo_data->first_tm;
delta = topo_info->curr_cfg.interval * offset;
iot_rtc_delta_add(delta, &start_tm);
resp_data_hdr->year = iot_byte_to_bcd((uint8_t)(start_tm.tm_year
- 2000));
resp_data_hdr->mon = iot_byte_to_bcd(start_tm.tm_mon);
resp_data_hdr->day = iot_byte_to_bcd(start_tm.tm_mday);
resp_data_hdr->hour = iot_byte_to_bcd(start_tm.tm_hour);
resp_data_hdr->min = iot_byte_to_bcd(start_tm.tm_min);
resp_data_hdr->sec = iot_byte_to_bcd(start_tm.tm_sec);
}
proto_645_2007_di_to_byte(di, resp_data_hdr->di);
resp_data_hdr->cnt = cnt;
resp_data_hdr->phase_info = query->phase_info;
resp_data_hdr->state_topo = topo_info->flag_enable;
resp_data_hdr->state_ll = iot_sg_sta_ext_ai_ll_run_check();
resp_data_hdr->data_len = cnt * unit_len;
if (cnt) {
dst = resp_data_hdr->data;
if ((topo_data->start_idx + offset) >=
IOT_SG_STA_EXT_AI_TOPO_DATA_MAX) {
idx = topo_data->start_idx + offset -
IOT_SG_STA_EXT_AI_TOPO_DATA_MAX;
} else {
idx = topo_data->start_idx + offset;
}
for (i = 0; i < cnt; i++) {
unit_data = &topo_data->list[idx];
switch (di) {
case PROTO_645_2007_DI_V_ALL:
{
src = (uint8_t*)&unit_data->v;
break;
}
case PROTO_645_2007_DI_V_A:
{
src = unit_data->v.a;
break;
}
case PROTO_645_2007_DI_I_ALL:
{
src = (uint8_t*)&unit_data->i;
break;
}
case PROTO_645_2007_DI_I_A:
{
src = unit_data->i.a;
break;
}
case PROTO_645_2007_DI_PF_ALL:
{
src = (uint8_t*)&unit_data->pf;
break;
}
case PROTO_645_2007_DI_PF_T:
{
src = unit_data->pf.total;
break;
}
default:
reason = 6;
goto drop;
}
os_mem_cpy(dst, src, unit_len);
dst += unit_len;
idx++;
if (idx >= IOT_SG_STA_EXT_AI_TOPO_DATA_MAX) {
idx = 0;
}
}
}
iot_sg_printf("%s resp di %08x, cnt %lu, start_tm %lu-%lu-%lu %lu:%lu:"
"%lu\n", __FUNCTION__, di, cnt, start_tm.tm_year, start_tm.tm_mon,
start_tm.tm_mday, start_tm.tm_hour, start_tm.tm_min, start_tm.tm_sec);
rsp_pkt = proto_645_build_msg(addr, (uint8_t*)resp_data_hdr,
(uint8_t)rsp_data_len, PROTO_645_2007_DI_AI_TOPO_QUERY,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_AI_XIAN,
PROTO_645_2007_ID, PROTO_645_FOLLOW_INVALID);
drop:
if (reason) {
iot_sg_printf("%s fail %lu\n", __FUNCTION__, reason);
proto_645_add33_handle(data, len);
}
if (data_pkt) {
iot_pkt_free(data_pkt);
}
return rsp_pkt;
}
static iot_pkt_t *iot_sg_sta_ext_ai_ll_start_rsp(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0;
int64_t delta;
iot_pkt_t *rsp = NULL;
iot_time_tm_t tm, m_tm;
proto_645_07_ai_ll_start_t *cmd;
iot_sg_sta_ext_ai_ll_cfg_t cfg = {0};
if (iot_sg_sta_ext_ai_ll_run_check()) {
reason = 1;
goto ack;
}
proto_645_sub33_handle(data, len);
if (len < sizeof(*cmd)) {
reason = 2;
goto drop;
}
cmd = (proto_645_07_ai_ll_start_t*)data;
if (iot_bcd_data_check(data, 6)) {
tm.tm_year = iot_bcd_to_byte(cmd->year) + 2000;
tm.tm_mon = iot_bcd_to_byte(cmd->mon);
tm.tm_mday = iot_bcd_to_byte(cmd->day);
tm.tm_hour = iot_bcd_to_byte(cmd->hour);
tm.tm_min = iot_bcd_to_byte(cmd->min);
tm.tm_sec = iot_bcd_to_byte(cmd->sec);
} else {
reason = 3;
goto drop;
}
if (!cmd->flag_p && !cmd->flag_i && !cmd->flag_gi && !cmd->flag_v
&& !cmd->flag_pf && !cmd->flag_pos && !cmd->flag_neg
&& !cmd->flag_qtr) {
cfg.flag_p = 1;
cfg.flag_i = 1;
cfg.flag_gi = 1;
cfg.flag_v = 1;
cfg.flag_pf = 1;
cfg.flag_pos = 1;
cfg.flag_neg = 1;
cfg.flag_qtr = 1;
} else {
cfg.flag_p = cmd->flag_p;
cfg.flag_i = cmd->flag_i;
cfg.flag_gi = cmd->flag_gi;
cfg.flag_v = cmd->flag_v;
cfg.flag_pf = cmd->flag_pf;
cfg.flag_pos = cmd->flag_pos;
cfg.flag_neg = cmd->flag_neg;
cfg.flag_qtr = cmd->flag_qtr;
}
cfg.interval = cmd->interval * 60;
if (cfg.interval != IOT_SG_STA_AI_MOD_LL_INTER_1MIN
&& cfg.interval != IOT_SG_STA_AI_MOD_LL_INTER_5MIN
&& cfg.interval != IOT_SG_STA_AI_MOD_LL_INTER_15MIN
&& cfg.interval != IOT_SG_STA_AI_MOD_LL_INTER_30MIN
&& cfg.interval != IOT_SG_STA_AI_MOD_LL_INTER_60MIN) {
cfg.interval = IOT_SG_STA_AI_MOD_LL_INTER_15MIN;
}
if (cmd->cycle_cnt) {
cfg.collected_cnt = IOT_SG_STA_AI_MOD_LL_TIMES_IN_CYC * cmd->cycle_cnt;
} else {
cfg.collected_cnt = IOT_SG_STA_AI_MOD_LL_TIMES_IN_CYC;
}
iot_sg_sta_ext_ai_time_set(&tm);
cfg.start_tm = tm;
if (iot_sg_sta_rtc_get_m_t(&m_tm) == ERR_OK) {
delta = iot_rtc_delta_calc(&m_tm, &tm);
if (IOT_ABS(delta) <= IOT_SG_STA_AI_MOD_TO_METER_TIME_MAX_DELTA) {
cfg.delta = (uint32_t)IOT_ABS(delta);
if (delta >= 0) {
cfg.neg_delta = 0;
} else {
cfg.neg_delta = 1;
}
cfg.valid = 1;
} else {
cfg.delta = 0;
cfg.neg_delta = 0;
cfg.valid = 0;
}
} else {
cfg.delta = 0;
cfg.neg_delta = 0;
cfg.valid = 0;
}
iot_sg_sta_ext_ai_ntb_to_tm(&cfg.start_tm, cmd->start_ntb);
iot_sg_sta_ext_ai_ll_start(&cfg, 0, 0);
ack:
rsp = proto_645_build_msg(addr, NULL, 0, PROTO_645_2007_DI_AI_LL_START,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_AI_XIAN,
PROTO_645_2007_ID, PROTO_645_FOLLOW_INVALID);
drop:
if (reason) {
iot_sg_printf("%s fail %lu\n", __FUNCTION__, reason);
proto_645_add33_handle(data, len);
}
return rsp;
}
static iot_time_tm_t iot_sg_sta_ext_ai_ll_next_ts(iot_time_tm_t start_ts,
uint16_t period, iot_time_tm_t curr_tm)
{
int64_t delta_time, interval = (int64_t)period;
iot_time_tm_t tm = curr_tm, tm_start = start_ts;
delta_time = iot_rtc_delta_calc(&tm_start, &tm);
delta_time %= interval;
if (delta_time != 0) {
delta_time = interval - delta_time;
iot_rtc_delta_add(delta_time, &tm);
}
return tm;
}
static void iot_sg_sta_ext_ai_ll_get_info(uint8_t *addr, uint8_t flag_curr,
uint8_t offset, iot_sg_sta_ext_ai_ll_rsp_info_t *rsp_info)
{
uint8_t flag_up[2], reason = 0;
uint16_t index[2], unit_len;
uint32_t ret;
int64_t delta = 0;
iot_time_tm_t tm[2], curr_tm, start_tm, end_tm;
iot_pkt_t *pkt = NULL;
iot_sg_meter_ai_ll_unit_data_t *ll_data;
if (iot_sg_sta_ext_ai_time_get(&curr_tm)) {
reason = 1;
goto out;
}
if (iot_sg_sta_flash_unit_get_data_info(IOT_SG_STA_METER_DATA_TYPE_AI_LL,
&unit_len, NULL)) {
reason = 2;
goto out;
}
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 3;
goto out;
}
ll_data = (iot_sg_meter_ai_ll_unit_data_t *)iot_pkt_put(pkt, unit_len);
tm[0] = curr_tm;
tm[1] = curr_tm;
if (flag_curr) {
tm[0].tm_hour = 0;
tm[0].tm_min = 0;
tm[0].tm_sec = 0;
} else {
tm[0].tm_hour = 0;
tm[0].tm_min = 0;
tm[0].tm_sec = 0;
tm[1].tm_hour = 23;
tm[1].tm_min = 59;
tm[1].tm_sec = 59;
delta -= 60 * 60 * 24;
iot_rtc_delta_add(delta, &tm[0]);
iot_rtc_delta_add(delta, &tm[1]);
}
flag_up[0] = 0;
flag_up[1] = 1;
ret = iot_sg_sta_flash_unit_data_find_by_multiple_time(addr,
index, tm, 2, IOT_SG_STA_METER_DATA_TYPE_AI_LL, flag_up);
if (ret || index[0] == 0xffff || index[1] == 0xffff) {
reason = 4;
goto out;
}
iot_sg_sta_flash_unit_data_read(addr, index[1], (uint8_t*)ll_data,
(uint16_t)unit_len, IOT_SG_STA_METER_DATA_TYPE_AI_LL);
if (!ll_data->flag_data) {
reason = 5;
goto out;
}
rsp_info->flag_p = ll_data->flag_p;
rsp_info->flag_i = ll_data->flag_i;
rsp_info->flag_gi = ll_data->flag_gi;
rsp_info->flag_v = ll_data->flag_v;
rsp_info->flag_pf = ll_data->flag_pf;
rsp_info->flag_pos = ll_data->flag_pos;
rsp_info->flag_neg = ll_data->flag_neg;
rsp_info->flag_qtr = ll_data->flag_qtr;
rsp_info->interval = ll_data->interval * 60;
start_tm.tm_year = (uint16_t)(ll_data->start_year + 2000);
start_tm.tm_mon = (uint8_t)ll_data->start_month;
start_tm.tm_mday = (uint8_t)ll_data->start_day;
start_tm.tm_hour = (uint8_t)ll_data->start_hour;
start_tm.tm_min = (uint8_t)ll_data->start_minute;
start_tm.tm_sec = ll_data->start_sec;
delta = iot_rtc_delta_calc(&tm[0], &start_tm);
if (delta >= 0) {
tm[0] = start_tm;
} else {
tm[0] = iot_sg_sta_ext_ai_ll_next_ts(start_tm, rsp_info->interval,
tm[0]);
}
end_tm = start_tm;
delta = ll_data->interval * 60 * ll_data->cycle * 96;
iot_rtc_delta_add(delta, &end_tm);
delta = iot_rtc_delta_calc(&tm[1], &end_tm);
if (delta >= 0) {
delta = iot_rtc_delta_calc(&curr_tm, &tm[1]);
if (delta >= 0) {
tm[1].tm_year = (uint16_t)(ll_data->unit_tm.year+ 2000);
tm[1].tm_mon = (uint8_t)ll_data->unit_tm.month;
tm[1].tm_mday = (uint8_t)ll_data->unit_tm.day;
tm[1].tm_hour = (uint8_t)ll_data->unit_tm.hour;
tm[1].tm_min = (uint8_t)ll_data->unit_tm.minute;
tm[1].tm_sec = ll_data->unit_tm.second;
} else {
delta = 0 - rsp_info->interval;
iot_rtc_delta_add(delta, &tm[1]);
tm[1] = iot_sg_sta_ext_ai_ll_next_ts(start_tm, rsp_info->interval,
tm[1]);
}
} else {
delta = iot_rtc_delta_calc(&curr_tm, &end_tm);
if (delta >= 0) {
tm[1].tm_year = (uint16_t)(ll_data->unit_tm.year+ 2000);
tm[1].tm_mon = (uint8_t)ll_data->unit_tm.month;
tm[1].tm_mday = (uint8_t)ll_data->unit_tm.day;
tm[1].tm_hour = (uint8_t)ll_data->unit_tm.hour;
tm[1].tm_min = (uint8_t)ll_data->unit_tm.minute;
tm[1].tm_sec = ll_data->unit_tm.second;
} else {
delta = 0 - rsp_info->interval;
iot_rtc_delta_add(delta, &end_tm);
tm[1] = end_tm;
}
}
delta = iot_rtc_delta_calc(&tm[0], &tm[1]);
if (delta < 0) {
reason = 6;
goto out;
}
rsp_info->rsp_cnt = (uint16_t)(delta / rsp_info->interval) + 1;
if (offset) {
if (offset >= rsp_info->rsp_cnt) {
reason = 7;
goto out;
}
rsp_info->rsp_cnt -= offset;
delta = offset * rsp_info->interval;
iot_rtc_delta_add(delta, &tm[0]);
}
ret = iot_sg_sta_flash_unit_data_find_by_multiple_time(addr,
index, tm, 2, IOT_SG_STA_METER_DATA_TYPE_AI_LL, flag_up);
if (ret || index[0] == 0xffff || index[1] == 0xffff) {
reason = 8;
goto out;
}
rsp_info->first_tm = tm[0];
rsp_info->start_idx = index[0];
rsp_info->end_idx = index[1];
out:
if (reason) {
os_mem_set(rsp_info, 0, sizeof(*rsp_info));
iot_sg_printf("%s error %lu\n", __FUNCTION__, reason);
}
if (pkt) {
iot_pkt_free(pkt);
}
}
static uint32_t iot_sg_sta_ext_ai_ll_di_check(uint32_t *di, uint8_t flag_3p,
uint8_t *unit_len, iot_sg_sta_ext_ai_ll_rsp_info_t *rsp_info)
{
uint32_t ret = ERR_FAIL;
switch (*di) {
case PROTO_645_2007_DI_P_T:
{
if (!rsp_info->flag_p) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_07_P_LEN;
break;
}
case PROTO_645_2007_DI_P_ALL:
{
if (!rsp_info->flag_p) {
rsp_info->rsp_cnt = 0;
}
if (!flag_3p) {
*di = PROTO_645_2007_DI_P_T;
*unit_len = PROTO_645_07_P_LEN;
} else {
*unit_len = sizeof(proto_645_07_p_t);
}
break;
}
case PROTO_645_2007_DI_I_A:
{
if (!rsp_info->flag_i) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_07_A_LEN;
break;
}
case PROTO_645_2007_DI_I_ALL:
{
if (!rsp_info->flag_i) {
rsp_info->rsp_cnt = 0;
}
if (!flag_3p) {
*di = PROTO_645_2007_DI_I_A;
*unit_len = PROTO_645_07_A_LEN;
} else {
*unit_len = sizeof(proto_645_07_a_t);
}
break;
}
case PROTO_645_2007_DI_I_N:
{
if (!rsp_info->flag_gi) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_07_A_LEN;
break;
}
case PROTO_645_2007_DI_V_A:
{
if (!rsp_info->flag_v) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_V_LEN;
break;
}
case PROTO_645_2007_DI_V_ALL:
{
if (!rsp_info->flag_v) {
rsp_info->rsp_cnt = 0;
}
if (!flag_3p) {
*di = PROTO_645_2007_DI_V_A;
*unit_len = PROTO_645_V_LEN;
} else {
*unit_len = sizeof(proto_645_v_t);
}
break;
}
case PROTO_645_2007_DI_PF_T:
{
if (!rsp_info->flag_pf) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_07_PF_LEN;
break;
}
case PROTO_645_2007_DI_PF_ALL:
{
if (!rsp_info->flag_pf) {
rsp_info->rsp_cnt = 0;
}
if (!flag_3p) {
*di = PROTO_645_2007_DI_PF_T;
*unit_len = PROTO_645_07_PF_LEN;
} else {
*unit_len = sizeof(proto_645_07_pf_t);
}
break;
}
case PROTO_645_2007_DI_EPT_POS_SUM:
case PROTO_645_2007_DI_EPT_POS_ALL:
{
if (!rsp_info->flag_pos) {
rsp_info->rsp_cnt = 0;
}
*di = PROTO_645_2007_DI_EPT_POS_SUM;
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_EPT_NEG_SUM:
case PROTO_645_2007_DI_EPT_NEG_ALL:
{
if (!rsp_info->flag_neg) {
rsp_info->rsp_cnt = 0;
}
*di = PROTO_645_2007_DI_EPT_NEG_SUM;
*unit_len = PROTO_645_07_ENERGY_DATA_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:
{
if (!flag_3p || !rsp_info->flag_pos) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_EPT_NEG_A:
case PROTO_645_2007_DI_EPT_NEG_B:
case PROTO_645_2007_DI_EPT_NEG_C:
{
if (!flag_3p || !rsp_info->flag_pos) {
rsp_info->rsp_cnt = 0;
}
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_EQT_QRT1_SUM:
case PROTO_645_2007_DI_EQT_QRT1_ALL:
{
if (!flag_3p || !rsp_info->flag_qtr) {
rsp_info->rsp_cnt = 0;
}
*di = PROTO_645_2007_DI_EQT_QRT1_SUM;
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_EQT_QRT2_SUM:
case PROTO_645_2007_DI_EQT_QRT2_ALL:
{
if (!flag_3p || !rsp_info->flag_qtr) {
rsp_info->rsp_cnt = 0;
}
*di = PROTO_645_2007_DI_EQT_QRT2_SUM;
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_EQT_QRT3_SUM:
case PROTO_645_2007_DI_EQT_QRT3_ALL:
{
if (!flag_3p || !rsp_info->flag_qtr) {
rsp_info->rsp_cnt = 0;
}
*di = PROTO_645_2007_DI_EQT_QRT3_SUM;
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
case PROTO_645_2007_DI_EQT_QRT4_SUM:
case PROTO_645_2007_DI_EQT_QRT4_ALL:
{
if (!flag_3p || !rsp_info->flag_qtr) {
rsp_info->rsp_cnt = 0;
}
*di = PROTO_645_2007_DI_EQT_QRT4_SUM;
*unit_len = PROTO_645_07_ENERGY_DATA_LEN;
break;
}
default:
goto out;
}
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_sg_sta_ext_ai_ll_query_rsp_data_fill(uint8_t *addr,
uint32_t di, uint8_t unit_len, iot_sg_sta_ext_ai_ll_rsp_info_t *rsp_info,
proto_645_07_ai_ll_query_ul_t *resp_data_hdr, uint32_t *len)
{
uint8_t reason = 0, i, first_point = 0;
uint8_t *src, *result_data = resp_data_hdr->data;
uint16_t index_tmp, flash_cnt, write_cnt = 0, delta_cnt, node_unit_len;
uint32_t ret = ERR_OK;
int64_t delta;
iot_pkt_t *pkt = NULL;
iot_time_tm_t tm_new, tm_old;
iot_sg_meter_ai_ll_unit_data_t *ll_data;
if (iot_sg_sta_flash_unit_get_data_info(IOT_SG_STA_METER_DATA_TYPE_AI_LL,
&node_unit_len, NULL)) {
reason = 2;
goto out;
}
pkt = iot_pkt_alloc(node_unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
iot_sg_printf("%s no pkt %lu\n", __FUNCTION__, reason);
return ERR_FAIL;
}
ll_data = (iot_sg_meter_ai_ll_unit_data_t *)iot_pkt_put(pkt, node_unit_len);
if (rsp_info->end_idx >= rsp_info->start_idx) {
flash_cnt = rsp_info->end_idx - rsp_info->start_idx + 1;
} else {
flash_cnt = IOT_SG_STA_METER_AI_LL_CNT - rsp_info->end_idx +
rsp_info->start_idx + 1;
}
tm_new = rsp_info->first_tm;
index_tmp = rsp_info->start_idx;
for (i = 0; i < flash_cnt; i++) {
if (write_cnt == rsp_info->rsp_cnt) {
break;
}
ret = iot_sg_sta_flash_unit_data_read(addr, index_tmp,
(uint8_t *)ll_data, node_unit_len,
IOT_SG_STA_METER_DATA_TYPE_AI_LL);
if (ret == ERR_OK) {
tm_old = tm_new;
tm_new.tm_year = (uint16_t)ll_data->unit_tm.year + 2000;
tm_new.tm_mon = (uint8_t)ll_data->unit_tm.month;
tm_new.tm_mday = (uint8_t)ll_data->unit_tm.day;
tm_new.tm_hour = (uint8_t)ll_data->unit_tm.hour;
tm_new.tm_min = (uint8_t)ll_data->unit_tm.minute;
tm_new.tm_sec = ll_data->unit_tm.second;
delta = iot_rtc_delta_calc(&tm_old, &tm_new);
delta_cnt = (uint16_t)(delta / rsp_info->interval);
if (delta % rsp_info->interval) {
tm_new = tm_old;
goto done;
}
if (!first_point) {
first_point = 1;
if (!delta_cnt) {
goto write;
} else {
if (delta_cnt >= rsp_info->rsp_cnt) {
delta_cnt = (uint8_t)rsp_info->rsp_cnt;
os_mem_set(result_data, 0xff, unit_len * delta_cnt);
goto out;
}
/* delta_cnt contains the first invalid point */
os_mem_set(result_data, 0xff, unit_len * delta_cnt);
write_cnt += delta_cnt;
result_data += (unit_len * delta_cnt);
goto write;
}
} else {
if (!delta_cnt) {
/* load record delta time too short
* ignore current data unit.
*/
tm_new = tm_old;
goto done;
} else if (delta_cnt == 1) {
goto write;
} else {
if ((write_cnt + delta_cnt) > rsp_info->rsp_cnt) {
delta_cnt = (uint8_t)(rsp_info->rsp_cnt - write_cnt);
os_mem_set(result_data, 0xff, unit_len * delta_cnt);
goto out;
}
/* delta_cnt contains the first invalid point */
os_mem_set(result_data, 0xff, unit_len * (delta_cnt - 1));
write_cnt += (delta_cnt - 1);
result_data += (unit_len * (delta_cnt - 1));
}
}
write:
switch (di) {
case PROTO_645_2007_DI_P_T:
case PROTO_645_2007_DI_P_ALL:
{
src = ll_data->ap.total;
break;
}
case PROTO_645_2007_DI_I_A:
case PROTO_645_2007_DI_I_ALL:
{
src = ll_data->i.a;
break;
}
case PROTO_645_2007_DI_I_N:
{
src = ll_data->gnd_a;
break;
}
case PROTO_645_2007_DI_V_A:
case PROTO_645_2007_DI_V_ALL:
{
src = ll_data->v.a;
break;
}
case PROTO_645_2007_DI_PF_T:
case PROTO_645_2007_DI_PF_ALL:
{
src = ll_data->pf.total;
break;
}
case PROTO_645_2007_DI_EPT_POS_SUM:
{
src = ll_data->pos_total;
break;
}
case PROTO_645_2007_DI_EPT_NEG_SUM:
{
src = ll_data->neg_total;
break;
}
case PROTO_645_2007_DI_EPT_POS_A:
{
src = ll_data->pos_a;
break;
}
case PROTO_645_2007_DI_EPT_POS_B:
{
src = ll_data->pos_b;
break;
}
case PROTO_645_2007_DI_EPT_POS_C:
{
src = ll_data->pos_c;
break;
}
case PROTO_645_2007_DI_EPT_NEG_A:
{
src = ll_data->neg_a;
break;
}
case PROTO_645_2007_DI_EPT_NEG_B:
{
src = ll_data->neg_b;
break;
}
case PROTO_645_2007_DI_EPT_NEG_C:
{
src = ll_data->neg_c;
break;
}
case PROTO_645_2007_DI_EQT_QRT1_SUM:
{
src = ll_data->re_1st_total;
break;
}
case PROTO_645_2007_DI_EQT_QRT2_SUM:
{
src = ll_data->re_2st_total;
break;
}
case PROTO_645_2007_DI_EQT_QRT3_SUM:
{
src = ll_data->re_3st_total;
break;
}
case PROTO_645_2007_DI_EQT_QRT4_SUM:
{
src = ll_data->re_4st_total;
break;
}
default:
resp_data_hdr->cnt = 0;
resp_data_hdr->data_len = 0;
*len = sizeof(*resp_data_hdr);
goto out;
}
os_mem_cpy(result_data, src, unit_len);
write_cnt++;
result_data += unit_len;
}
done:
index_tmp++;
if (index_tmp >= IOT_SG_STA_METER_AI_LL_CNT) {
index_tmp = 0;
}
}
if (write_cnt < rsp_info->rsp_cnt) {
delta_cnt = rsp_info->rsp_cnt - write_cnt;
os_mem_set(result_data, 0xff, unit_len * delta_cnt);
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
return ERR_OK;
}
static iot_pkt_t *iot_sg_sta_ext_ai_ll_query_rsp(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, max_cnt, unit_len, offset;
uint32_t di, rsp_data_len;
iot_sg_sta_ext_ai_ll_rsp_info_t rsp_info = {0};
iot_pkt_t *rsp_pkt = NULL, *data_pkt = NULL;
iot_sg_sta_node_desc_t *node;
proto_645_07_ai_ll_query_dl_t *query;
proto_645_07_ai_ll_query_ul_t *resp_data_hdr;
iot_sg_sta_ext_ai_topo_info_t *topo_info =
&p_sg_glb->desc.sta->ext_info.ai_module_info->topo_info;
proto_645_sub33_handle(data, len);
p_sg_glb->desc.sta->drv->get_login_addr(addr);
node = iot_sg_sta_node_find_by_addr(addr);
if (node == NULL) {
reason = 1;
goto drop;
}
if (len < sizeof(*query)) {
reason = 2;
goto drop;
}
query = (proto_645_07_ai_ll_query_dl_t*)data;
di = proto_645_2007_byte_to_di(query->di);
if (iot_bcd_check(query->offset)) {
offset = iot_bcd_to_byte(query->offset);
} else {
reason = 3;
goto drop;
}
iot_sg_sta_ext_ai_ll_get_info(addr, query->flag_curr, offset, &rsp_info);
iot_sg_printf("%s di %08x, offset %lu, cnt %lu, curr_flag %lu\n",
__FUNCTION__, di, offset, query->cnt, query->flag_curr);
if (iot_sg_sta_ext_ai_ll_di_check(&di, node->is_three_phase, &unit_len,
&rsp_info)) {
reason = 4;
goto drop;
}
rsp_info.rsp_cnt = min(rsp_info.rsp_cnt, query->cnt);
max_cnt = IOT_SG_STA_AI_MOD_LL_DATA_RESP_LEN_MAX / unit_len;
rsp_info.rsp_cnt = min(rsp_info.rsp_cnt, max_cnt);
rsp_data_len = sizeof(*resp_data_hdr) + rsp_info.rsp_cnt * unit_len;
data_pkt = iot_pkt_alloc(rsp_data_len, IOT_SMART_GRID_MID);
if (data_pkt == NULL) {
reason = 5;
goto drop;
}
resp_data_hdr = (proto_645_07_ai_ll_query_ul_t*)iot_pkt_put(data_pkt,
rsp_data_len);
if (!rsp_info.rsp_cnt) {
resp_data_hdr->year = 0xff;
resp_data_hdr->mon = 0xff;
resp_data_hdr->day = 0xff;
resp_data_hdr->hour = 0xff;
resp_data_hdr->min = 0xff;
resp_data_hdr->sec = 0xff;
} else {
resp_data_hdr->year = iot_byte_to_bcd((uint8_t)(
rsp_info.first_tm.tm_year - 2000));
resp_data_hdr->mon = iot_byte_to_bcd(rsp_info.first_tm.tm_mon);
resp_data_hdr->day = iot_byte_to_bcd(rsp_info.first_tm.tm_mday);
resp_data_hdr->hour = iot_byte_to_bcd(rsp_info.first_tm.tm_hour);
resp_data_hdr->min = iot_byte_to_bcd(rsp_info.first_tm.tm_min);
resp_data_hdr->sec = iot_byte_to_bcd(rsp_info.first_tm.tm_sec);
}
proto_645_2007_di_to_byte(di, resp_data_hdr->di);
resp_data_hdr->cnt = (uint8_t)rsp_info.rsp_cnt;
resp_data_hdr->phase_info = query->phase_info;
resp_data_hdr->state_topo = topo_info->flag_enable;
resp_data_hdr->state_ll = iot_sg_sta_ext_ai_ll_run_check();
resp_data_hdr->data_len = (uint8_t)(rsp_info.rsp_cnt * unit_len);
if (rsp_info.rsp_cnt) {
if (iot_sg_sta_ext_ai_ll_query_rsp_data_fill(addr, di, unit_len,
&rsp_info, resp_data_hdr, &rsp_data_len)) {
reason = 6;
goto drop;
}
}
iot_sg_printf("%s resp di %08x, cnt %lu, start_tm %lu-%lu-%lu %lu:%lu:"
"%lu\n", __FUNCTION__, di, rsp_info.rsp_cnt, rsp_info.first_tm.tm_year,
rsp_info.first_tm.tm_mon, rsp_info.first_tm.tm_mday,
rsp_info.first_tm.tm_hour, rsp_info.first_tm.tm_min,
rsp_info.first_tm.tm_sec);
rsp_pkt = proto_645_build_msg(addr, (uint8_t*)resp_data_hdr,
(uint8_t)rsp_data_len, PROTO_645_2007_DI_AI_LL_QUERY,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_AI_XIAN,
PROTO_645_2007_ID, PROTO_645_FOLLOW_INVALID);
drop:
if (reason) {
iot_sg_printf("%s fail %lu\n", __FUNCTION__, reason);
proto_645_add33_handle(data, len);
}
if (data_pkt) {
iot_pkt_free(data_pkt);
}
return rsp_pkt;
}
iot_pkt_t *iot_sg_sta_ext_ai_rsp_handle(uint8_t *addr,
uint32_t di, uint8_t *data, uint8_t len)
{
iot_pkt_t *rsp_pkt = NULL;
uint8_t *data_ptr = data + PROTO_645_2007_DI_LEN;
uint8_t data_len = len - PROTO_645_2007_DI_LEN;
if (iot_sg_sta_ext_ai_module_check()) {
goto out;
}
switch (di) {
case PROTO_645_2007_DI_AI_TOPO_START:
{
rsp_pkt = iot_sg_sta_ext_ai_topo_start_rsp(addr, data_ptr, data_len);
break;
}
case PROTO_645_2007_DI_AI_TOPO_QUERY:
{
rsp_pkt = iot_sg_sta_ext_ai_topo_query_rsp(addr, data_ptr, data_len);
break;
}
case PROTO_645_2007_DI_AI_LL_START:
{
rsp_pkt = iot_sg_sta_ext_ai_ll_start_rsp(addr, data_ptr, data_len);
break;
}
case PROTO_645_2007_DI_AI_LL_QUERY:
{
rsp_pkt = iot_sg_sta_ext_ai_ll_query_rsp(addr, data_ptr, data_len);
break;
}
default:
break;
}
out:
return rsp_pkt;
}
#endif /* IOT_SMART_GRID_EXT_AI_FUNC_ENABLE */