3080 lines
102 KiB
C
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 */
|