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

9319 lines
317 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os_shim header files */
#include "os_utils_api.h"
/* iot common header files */
#include "iot_io_api.h"
#include "iot_oem_api.h"
#include "iot_version_api.h"
#include "iot_bitmap_api.h"
#include "iot_plc_led_api.h"
/* smart grid internal header files */
#include "iot_sg_fr.h"
#include "iot_sg.h"
#include "iot_sg_sta.h"
#include "iot_sg_sta_ext.h"
#include "iot_sg_sta_flash.h"
#include "iot_sg_sta_cfg_flash.h"
#include "proto_645_fj.h"
#include "iot_sg_sta_upgrade.h"
#include "iot_board_api.h"
#if (IOT_SMART_GRID_EXT_FJ_FUNC_ENABLE)
/* define data freeze state */
#define IOT_SG_STA_EXT_FREEZR_STATE_IDLE (0)
#define IOT_SG_STA_EXT_FREEZR_STATE_SEND (1)
#define IOT_SG_STA_EXT_FREEZR_STATE_WAIT (2)
/* define data freeze function */
#define IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_1 (0)
#define IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_0 (1)
#define IOT_SG_STA_EXT_FREEZR_FUNC_RPT (2)
#define IOT_SG_STA_EXT_FREEZR_FUNC_CNT (3)
/* freeze task data default random report time max value, uint is 1% */
#define IOT_SG_STA_EXT_TASK_RANDOM_RPT_PERCENT_MAX (90)
/* freeze task data default random report time, uint is 1% */
#define IOT_SG_STA_EXT_TASK_RANDON_RPT_PERCENT_DEF (50)
/* freeze task data default random report time min percent of task cycle, uint is 1% */
#define IOT_SG_STA_EXT_TASK_RANDON_RPT_PERCENT_MIN (10)
/* freeze task data default random report time max value, uint is 1s */
#define IOT_SG_STA_EXT_TASK_RANDOM_RPT_TIME_MAX (300)
/* freeze task data default random report time min value, uint is 1s */
#define IOT_SG_STA_EXT_TASK_RANDON_RPT_TIME_MIN (1)
/* freeze task data record unit default lengtht */
#define IOT_SG_STA_EXT_TASK_REC_UNIT_LEN_DEF (200)
/* freeze task data report default cnt within 24H */
#define IOT_SG_STA_EXT_TASK_RPT_CNT_DEF (100)
/* freeze task data repeat reporting dur, uint is 1s */
#define IOT_SG_STA_EXT_TASK_RE_RPT_DUR (15)
/* freeze task response data cache len */
#define IOT_SG_STA_EXT_FREEZR_CACHE_LEN (1024)
/* freeze task response data cache len for simple 698 */
#define IOT_SG_STA_EXT_FREEZR_698_CACHE_LEN (2048)
/* collect last day freeze data min interval time, uint is 1s */
#define IOT_SG_STA_EXT_FREEZE_LAST_DF_MIN_TIME (60 * 30)
/* chg task cache di list max len */
#define IOT_SG_STA_EXT_CACHE_DI_LIST_MAX_LEN (128)
/* write meter multiple data item flag enable */
#define IOT_SG_STA_EXT_WRITE_MULT_FLAG_EN (0)
/* define led blink enable counter, unit is 1s refresh interval */
#define IOT_SG_STA_EXT_LED_BLINK_EN_CNT (2)
/* define freeze data build msg type */
#define IOT_SG_STA_EXT_FREEZE_BUILD_MSG_645 (0)
#define IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698 (1)
/* define simple 698 max len desc byte number */
#define IOT_SG_STA_EXT_698_LEN_BYTE_MAX_NUM (2)
/* pack for the structures in the whole file */
#pragma pack(push) /* save the pack status */
#pragma pack(1) /* 1 byte align */
/* freeze task response data cache infomation */
typedef struct _iot_sg_sta_ext_freeze_resp_cache_data {
/* record time */
iot_sg_meter_unit_time_with_sec_t rec_time;
/* cache di count */
uint8_t di_cnt;
/* unit data len */
uint16_t unit_len;
/* iot_sg_sta_drv_meter_fj_unit_data_t */
uint8_t unit_data[0];
} iot_sg_sta_ext_freeze_resp_cache_data_t;
/* freeze task response data cache di infomation */
typedef struct _iot_sg_sta_ext_freeze_resp_cache_di_info {
/* di */
uint32_t di;
/* resp len */
uint8_t resp_len;
/* resp data first byte */
uint8_t resp_first_byte;
} iot_sg_sta_ext_freeze_resp_cache_di_info_t;
/* freeze task response data cache */
typedef struct _iot_sg_sta_ext_freeze_resp_cache_hdr {
/* task type, see PROTO_645_FJ_TASK_TYPE_XXX */
uint8_t type;
/* freeze data start time */
iot_time_tm_t start_tm;
/* freeze data cache end time */
iot_time_tm_t cache_end_tm;
/* freeze data cache end time index */
uint16_t cache_end_tm_idx;
/* task cycle*/
proto_645_fj_task_cycle_t cycle;
/* storage times to task response */
uint16_t storage_times;
/* query count */
uint8_t query_cnt;
/* response count */
uint8_t rsp_cnt;
/* di count*/
uint8_t di_cnt;
/* di */
iot_sg_sta_ext_freeze_resp_cache_di_info_t di_info[0];
/* iot_sg_sta_ext_freeze_resp_cache_data_t */
} iot_sg_sta_ext_freeze_resp_cache_hdr_t;
#pragma pack(pop) /* restore the pack status */
static uint32_t iot_sg_sta_ext_freeze_task_comm_cfg_save(
iot_sg_sta_ext_freeze_task_comm_cfg_t *cfg_comm);
static void iot_sg_sta_ext_fj_rpt_count(uint8_t task_id,
uint8_t flag_total_cnt, uint8_t count);
static uint8_t iot_sg_sta_ext_fj_task_group_get(uint8_t id)
{
uint8_t group = PROTO_645_FJ_TASK_GROUP_UNKNOWN;
if (id >= PROTO_FJ_FREEZE_645_TASK_ID_MIN &&
id <= PROTO_FJ_FREEZE_645_TASK_ID_MAX) {
group = PROTO_645_FJ_TASK_GROUP_645;
} else if (id >= PROTO_FJ_FREEZE_698_TASK_ID_MIN &&
id <= PROTO_FJ_FREEZE_698_TASK_ID_MAX) {
group = PROTO_645_FJ_TASK_GROUP_698;
}
return group;
}
static iot_sg_sta_drv_meter_fj_unit_data_t *iot_sg_ext_freeze_di_unit_data_get(
uint32_t di, uint8_t *data, uint16_t len, uint8_t unit_cnt)
{
uint8_t i;
uint16_t offset = 0;
uint32_t ret = ERR_FAIL;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data = NULL;
if (!data || !len || !unit_cnt) {
goto out;
}
for (i = 0; i < unit_cnt; i++) {
if (len < sizeof(*unit_data)) {
goto out;
}
len -= sizeof(*unit_data);
unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)(data + offset);
if (len < unit_data->len) {
goto out;
}
len -= unit_data->len;
offset += (sizeof(*unit_data) + unit_data->len);
if (unit_data->len < PROTO_645_2007_DI_LEN) {
continue;
}
if (di == proto_645_2007_byte_to_di(unit_data->data)) {
ret = ERR_OK;
break;
}
}
out:
if (ret != ERR_OK) {
unit_data = NULL;
}
return unit_data;
}
static uint8_t iot_sg_sta_ext_fj_task_chg_unit_di_list_get(
iot_sg_sta_drv_meter_fj_task_unit_t *cur_data,
iot_sg_sta_drv_meter_fj_task_unit_t *last_data,
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
uint32_t *di_list, uint8_t len)
{
uint8_t reason = 0, j, skip, di_full = 0, last_di_fill = 0;
uint8_t di_cnt = 0, i, tmp_offset, valid_len, *unit_data_tmp, resp_data_cnt;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data;
if (!cur_data || !last_data || !di_list || !len) {
reason = 1;
goto out;
}
if (cache_hdr) {
for (i = 0; i < cache_hdr->di_cnt; i++) {
di_list[i] = cache_hdr->di_info[i].di;
di_cnt++;
if (di_cnt >= len / PROTO_645_2007_DI_LEN) {
break;
}
}
goto out;
}
valid_len = cur_data->valid_len;
unit_data_tmp = cur_data->uint_data;
resp_data_cnt = cur_data->resp_data_cnt;
tmp_offset = 0;
di_fill:
for (i = 0; i < resp_data_cnt; i++) {
if (valid_len < sizeof(*unit_data)) {
reason = 2;
goto out;
}
unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)
(unit_data_tmp + tmp_offset);
valid_len -= sizeof(*unit_data);
if (valid_len < unit_data->len) {
reason = 3;
goto out;
}
valid_len -= unit_data->len;
tmp_offset += sizeof(*unit_data) + unit_data->len;
if (unit_data->len <= PROTO_645_2007_DI_LEN) {
continue;
}
skip = 0;
for (j = 0; j < di_cnt; j++) {
if (!os_mem_cmp((uint8_t *)&di_list[i], unit_data->data,
PROTO_645_2007_DI_LEN)) {
skip = 1;
break;
}
}
if (skip) {
continue;
}
os_mem_cpy((uint8_t *)&di_list[di_cnt], unit_data->data,
PROTO_645_2007_DI_LEN);
di_cnt++;
if (di_cnt >= len / PROTO_645_2007_DI_LEN) {
di_full = 1;
break;
}
}
if (di_full) {
reason = 4;
goto out;
}
if (!last_di_fill) {
last_di_fill = 1;
valid_len = last_data->valid_len;
unit_data_tmp = last_data->uint_data;
resp_data_cnt = last_data->resp_data_cnt;
tmp_offset = 0;
goto di_fill;
}
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return di_cnt;
}
static uint8_t iot_sg_sta_ext_fj_645_di_ff_unit_min_len_get(uint32_t di)
{
uint8_t unit_data_len = 0;
switch (di) {
case PROTO_645_2007_DI_V_ALL:
{
unit_data_len = PROTO_645_V_LEN;
break;
}
case PROTO_645_2007_DI_I_ALL:
{
unit_data_len = PROTO_645_07_A_LEN;
break;
}
case PROTO_645_2007_DI_P_ALL:
case PROTO_645_2007_DI_PF_ALL:
case PROTO_645_2007_DI_Q_ALL:
{
unit_data_len = PROTO_645_07_P_LEN;
break;
}
case PROTO_645_2007_DI_EPT_POS_ALL:
case PROTO_645_2007_DI_EPT_NEG_ALL:
case PROTO_645_2007_DI_EPT_COMP_ALL:
{
unit_data_len= PROTO_645_07_ENERGY_DATA_LEN;
break;
}
default:
break;
}
return unit_data_len;
}
static void iot_sg_sta_ext_fj_645_unit_to_698_unit(uint32_t di,
uint8_t *data, uint8_t len)
{
uint8_t unit_len, i, *data_tmp;
iot_sg_meter_max_demand_and_ht_t *pos_demand, *neg_demand;
if ((di | 0xFFFF00FF) == 0xFFFFFFFF) {
unit_len = iot_sg_sta_ext_fj_645_di_ff_unit_min_len_get(di);
if (!unit_len || (len % unit_len )) {
iot_data_reverse(data, len);
goto out;
}
data_tmp = data;
for (i = 0; i < (len / unit_len); i++) {
iot_data_reverse(data_tmp, unit_len);
data_tmp += unit_len;
}
} else {
switch (di) {
case PROTO_645_2007_DI_EPT_POS_DEMAND:
{
if (len != sizeof(*pos_demand)) {
break;
}
pos_demand = (iot_sg_meter_max_demand_and_ht_t *)data;
iot_data_reverse(pos_demand->max_demand,
IOT_SG_STA_METER_POWER_LEN);
iot_data_reverse(pos_demand->max_demand +
IOT_SG_STA_METER_POWER_LEN,
sizeof(*pos_demand) - IOT_SG_STA_METER_POWER_LEN);
goto out;
}
case PROTO_645_2007_DI_EPT_NEG_DEMAND:
{
if (len != sizeof(*neg_demand)) {
break;
}
neg_demand = (iot_sg_meter_max_demand_and_ht_t *)data;
iot_data_reverse(neg_demand->max_demand,
IOT_SG_STA_METER_POWER_LEN);
iot_data_reverse(neg_demand->max_demand +
IOT_SG_STA_METER_POWER_LEN,
sizeof(*neg_demand) - IOT_SG_STA_METER_POWER_LEN);
goto out;
}
default:
break;
}
iot_data_reverse(data, len);
}
out:
return;
}
static uint8_t iot_sg_sta_ext_fj_task_chg_data_to_resp(
iot_sg_sta_drv_meter_fj_task_unit_t *cur_data,
iot_sg_sta_drv_meter_fj_task_unit_t *last_data,
proto_645_fj_task_data_query_hdr_ul_t *resp_data, uint16_t max_len,
uint8_t type, proto_645_fj_task_cycle_t cycle,
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
uint8_t msg_type, uint8_t task_id)
{
iot_pkt_t *di_list_pkt = NULL;
uint32_t *di_list;
uint8_t resp_first_byte;
uint8_t resp_len = 0, i, unit_len, reason = 0, di_cnt, group_type;
iot_sg_sta_drv_meter_fj_unit_data_t *cur_unit_data, *last_unit_data;
iot_sg_sta_drv_meter_fj_unit_data_t *chg_unit_data;
proto_645_fj_task_data_query_di_unit_t *di_unit;
if (!cur_data || !last_data || !resp_data || !max_len) {
reason = 1;
goto drop;
}
if (max_len < sizeof(*resp_data)) {
reason = 2;
goto drop;
}
max_len -= sizeof(*resp_data);
resp_data->type = type;
resp_data->start.year =
iot_byte_to_bcd((uint8_t)last_data->uint_time.year);
resp_data->start.month =
iot_byte_to_bcd((uint8_t)last_data->uint_time.month);
resp_data->start.day =
iot_byte_to_bcd((uint8_t)last_data->uint_time.day);
resp_data->start.hour =
iot_byte_to_bcd((uint8_t)last_data->uint_time.hour);
resp_data->start.minute =
iot_byte_to_bcd((uint8_t)last_data->uint_time.minute);
resp_data->start.second =
iot_byte_to_bcd((uint8_t)last_data->uint_time.second);
if (last_data->storage_times) {
resp_data->storage_times = last_data->storage_times - 1;
} else {
resp_data->storage_times = last_data->storage_times;
}
resp_data->task_cycle = cycle;
resp_data->frozen_point_cnt = 2;
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698) {
resp_data->start.year = (uint8_t)last_data->uint_time.year;
resp_data->start.month = (uint8_t)last_data->uint_time.month;
resp_data->start.day = (uint8_t)last_data->uint_time.day;
resp_data->start.hour = (uint8_t)last_data->uint_time.hour;
resp_data->start.minute = (uint8_t)last_data->uint_time.minute;
resp_data->start.second = (uint8_t)last_data->uint_time.second;
iot_data_reverse((uint8_t *)&resp_data->start,
sizeof(resp_data->start));
iot_data_reverse((uint8_t *)&resp_data->storage_times,
sizeof(resp_data->storage_times));
iot_data_reverse((uint8_t *)&resp_data->task_cycle,
sizeof(resp_data->task_cycle));
}
resp_data->di_cnt = 0;
di_list_pkt = iot_pkt_alloc(IOT_SG_STA_EXT_CACHE_DI_LIST_MAX_LEN,
IOT_SMART_GRID_MID);
if (!di_list_pkt) {
reason = 3;
goto drop;
}
di_list = (uint32_t *)iot_pkt_put(di_list_pkt,
IOT_SG_STA_EXT_CACHE_DI_LIST_MAX_LEN);
di_cnt = iot_sg_sta_ext_fj_task_chg_unit_di_list_get(cur_data, last_data,
cache_hdr, di_list, IOT_SG_STA_EXT_CACHE_DI_LIST_MAX_LEN);
if (!di_cnt) {
reason = 4;
goto drop;
}
group_type = iot_sg_sta_ext_fj_task_group_get(task_id);
for (i = 0; i < di_cnt; i++) {
last_unit_data = iot_sg_ext_freeze_di_unit_data_get(di_list[i],
last_data->uint_data, last_data->valid_len,
last_data->resp_data_cnt);
cur_unit_data = iot_sg_ext_freeze_di_unit_data_get(di_list[i],
cur_data->uint_data, cur_data->valid_len, cur_data->resp_data_cnt);
if (!last_unit_data && !cur_unit_data) {
continue;
}
if (last_unit_data) {
chg_unit_data = last_unit_data;
} else {
chg_unit_data = cur_unit_data;
}
unit_len = sizeof(*di_unit) + (chg_unit_data->len -
PROTO_645_2007_DI_LEN) * resp_data->frozen_point_cnt;
/* check response msg max len */
if ((resp_len + unit_len) > max_len) {
resp_data->result = PROTO_645_FJ_READ_RESP_DATA_OVERFLOW;
break;
}
di_unit = (proto_645_fj_task_data_query_di_unit_t *)
(resp_data->di_data + resp_len);
di_unit->length = chg_unit_data->len - PROTO_645_2007_DI_LEN;
os_mem_cpy((uint8_t *)&di_unit->di, chg_unit_data->data,
PROTO_645_2007_DI_LEN);
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698) {
iot_data_reverse((uint8_t *)&di_unit->di, sizeof(di_unit->di));
}
resp_first_byte = 0xff;
if (last_unit_data) {
os_mem_cpy(di_unit->di_data, last_unit_data->data +
PROTO_645_2007_DI_LEN, di_unit->length);
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698 &&
group_type == PROTO_645_FJ_TASK_GROUP_645) {
iot_sg_sta_ext_fj_645_unit_to_698_unit(di_unit->di,
di_unit->di_data, di_unit->length);
}
if (di_unit->length) {
resp_first_byte = di_unit->di_data[0];
}
} else {
os_mem_set(di_unit->di_data, 0xFF, di_unit->length);
}
if (cur_unit_data) {
os_mem_cpy(di_unit->di_data + di_unit->length,
cur_unit_data->data + PROTO_645_2007_DI_LEN, di_unit->length);
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698 &&
group_type == PROTO_645_FJ_TASK_GROUP_645) {
iot_sg_sta_ext_fj_645_unit_to_698_unit(di_unit->di,
di_unit->di_data + di_unit->length, di_unit->length);
}
if (di_unit->length) {
resp_first_byte = di_unit->di_data[di_unit->length];
}
} else {
os_mem_set(di_unit->di_data + di_unit->length, 0xFF,
di_unit->length);
}
if (group_type == PROTO_645_FJ_TASK_GROUP_698 &&
resp_first_byte != 0xff) {
di_unit->di_data[0] = resp_first_byte;
di_unit->di_data[di_unit->length] = resp_first_byte;
}
resp_len += unit_len;
resp_data->di_cnt++;
}
if (resp_data->result != PROTO_645_FJ_READ_RESP_DATA_OVERFLOW) {
resp_data->result = PROTO_645_FJ_READ_RESP_DATA_OK;
}
resp_len += sizeof(*resp_data);
goto out;
drop:
iot_sg_printf("%s drop %lu\n", __FUNCTION__, reason);
out:
if (di_list_pkt) {
iot_pkt_free(di_list_pkt);
}
return resp_len;
}
static uint8_t iot_sg_sta_ext_fj_task_single_data_to_resp(
iot_sg_sta_drv_meter_fj_task_unit_t *task_data,
proto_645_fj_task_data_query_hdr_ul_t *resp_data, uint8_t max_len,
iot_sg_sta_drv_meter_fj_task_info_t *cfg_info, uint8_t msg_type,
uint8_t task_id)
{
uint8_t group_type;
uint8_t resp_len = 0, i, offset = 0, unit_len, valid_len, reason = 0;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data;
proto_645_fj_task_data_query_di_unit_t *di_unit;
if (!task_data || !resp_data || !max_len || !cfg_info) {
reason = 1;
goto drop;
}
if (max_len < sizeof(*resp_data)) {
reason = 2;
goto drop;
}
max_len -= sizeof(*resp_data);
resp_data->type = cfg_info->type;
resp_data->start.year =
iot_byte_to_bcd((uint8_t)task_data->uint_time.year);
resp_data->start.month =
iot_byte_to_bcd((uint8_t)task_data->uint_time.month);
resp_data->start.day =
iot_byte_to_bcd((uint8_t)task_data->uint_time.day);
resp_data->start.hour =
iot_byte_to_bcd((uint8_t)task_data->uint_time.hour);
resp_data->start.minute =
iot_byte_to_bcd((uint8_t)task_data->uint_time.minute);
resp_data->start.second =
iot_byte_to_bcd((uint8_t)task_data->uint_time.second);
if (task_data->storage_times) {
resp_data->storage_times = task_data->storage_times - 1;
} else {
resp_data->storage_times = task_data->storage_times;
}
resp_data->task_cycle.value = cfg_info->value;
resp_data->task_cycle.unit = cfg_info->unit;
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698) {
resp_data->start.year = (uint8_t)task_data->uint_time.year;
resp_data->start.month = (uint8_t)task_data->uint_time.month;
resp_data->start.day = (uint8_t)task_data->uint_time.day;
resp_data->start.hour = (uint8_t)task_data->uint_time.hour;
resp_data->start.minute = (uint8_t)task_data->uint_time.minute;
resp_data->start.second = (uint8_t)task_data->uint_time.second;
iot_data_reverse((uint8_t *)&resp_data->start,
sizeof(resp_data->start));
iot_data_reverse((uint8_t *)&resp_data->storage_times,
sizeof(resp_data->storage_times));
iot_data_reverse((uint8_t *)&resp_data->task_cycle,
sizeof(resp_data->task_cycle));
}
resp_data->frozen_point_cnt = 1;
resp_data->di_cnt = 0;
valid_len = task_data->valid_len;
group_type = iot_sg_sta_ext_fj_task_group_get(task_id);
for (i = 0; i < task_data->resp_data_cnt; i++) {
if (valid_len < sizeof(*unit_data)) {
reason = 3;
goto drop;
}
unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)
(task_data->uint_data + offset);
valid_len -= sizeof(*unit_data);
if (valid_len < unit_data->len) {
reason = 4;
goto drop;
}
valid_len -= unit_data->len;
unit_len = sizeof(*unit_data) + unit_data->len;
offset += unit_len;
if (unit_data->len <= PROTO_645_2007_DI_LEN) {
continue;
}
/* check response msg max len */
if ((resp_len + unit_len) > max_len) {
resp_data->result = PROTO_645_FJ_READ_RESP_DATA_OVERFLOW;
break;
}
di_unit = (proto_645_fj_task_data_query_di_unit_t *)
(resp_data->di_data + resp_len);
di_unit->length = unit_data->len - PROTO_645_2007_DI_LEN;
os_mem_cpy((uint8_t *)&di_unit->di, unit_data->data,
PROTO_645_2007_DI_LEN);
os_mem_cpy(di_unit->di_data, unit_data->data + PROTO_645_2007_DI_LEN,
di_unit->length);
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698) {
iot_data_reverse((uint8_t *)&di_unit->di, sizeof(di_unit->di));
if (group_type == PROTO_645_FJ_TASK_GROUP_645) {
iot_sg_sta_ext_fj_645_unit_to_698_unit(di_unit->di,
di_unit->di_data, di_unit->length);
}
}
resp_len += unit_len;
resp_data->di_cnt++;
}
if (resp_data->result != PROTO_645_FJ_READ_RESP_DATA_OVERFLOW) {
resp_data->result = PROTO_645_FJ_READ_RESP_DATA_OK;
}
resp_len += sizeof(*resp_data);
goto out;
drop:
iot_sg_printf("%s drop %lu\n", __FUNCTION__, reason);
out:
return resp_len;
}
static void iot_sg_sta_ext_fj_rpt_reset(
iot_sg_sta_ext_freeze_task_rpt_uint_t *rpt_info)
{
if (rpt_info->rpt_pkt) {
iot_pkt_free(rpt_info->rpt_pkt);
}
os_mem_set(rpt_info, 0, sizeof(*rpt_info));
}
static uint8_t iot_sg_sta_ext_fj_rpt_msg_data_fill(
iot_sg_sta_drv_meter_fj_task_unit_t *task_unit,
iot_sg_sta_drv_meter_fj_task_unit_t *last_task_unit,
iot_sg_sta_drv_meter_fj_task_info_t *cfg_info,
proto_645_fj_task_data_query_hdr_ul_t *resp_data,
uint8_t max_len, uint8_t msg_type, uint8_t task_id)
{
uint8_t len;
proto_645_fj_task_cycle_t cycle = { 0 };
if (last_task_unit && cfg_info->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
cycle.value = cfg_info->value;
cycle.unit = cfg_info->unit;
len = iot_sg_sta_ext_fj_task_chg_data_to_resp(task_unit, last_task_unit,
resp_data, max_len, cfg_info->type, cycle, NULL, msg_type, task_id);
} else {
len = iot_sg_sta_ext_fj_task_single_data_to_resp(task_unit, resp_data,
max_len, cfg_info, msg_type, task_id);
}
if (!len) {
resp_data->type = cfg_info->type;
resp_data->result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
len = sizeof(resp_data->result) + sizeof(resp_data->type);
}
return len;
}
static iot_pkt_t *iot_sg_sta_ext_fj_rpt_msg_build(
iot_sg_sta_drv_meter_fj_task_unit_t *task_unit,
iot_sg_sta_drv_meter_fj_task_unit_t *last_task_unit,
iot_sg_sta_drv_meter_fj_task_info_t *cfg_info,
uint8_t task_id, uint8_t mode)
{
uint8_t max_len = PROTO_645_FJ_RESP_DATA_MAX_LEN, len, cache_len, msg_type;
uint32_t di = PROTO_645_FJ_DI_QR_TASK_DATA + task_id;
iot_pkt_t *pkt = NULL;
proto_69845_app_result_normal_t *result;
proto_69845_octet_string_uint_t *oct_hdr;
proto_645_fj_task_data_query_hdr_ul_t *resp_data;
pkt = iot_pkt_alloc(max_len, IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
if (mode == PROTO_645_FJ_REPORT_MODE_645) {
resp_data = (proto_645_fj_task_data_query_hdr_ul_t *)iot_pkt_data(pkt);
msg_type = IOT_SG_STA_EXT_FREEZE_BUILD_MSG_645;
} else {
len = sizeof(*result) + sizeof(*oct_hdr) + 1;
iot_pkt_reserve(pkt, len);
resp_data = (proto_645_fj_task_data_query_hdr_ul_t *)iot_pkt_data(pkt);
max_len -= len;
msg_type = IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698;
}
len = iot_sg_sta_ext_fj_rpt_msg_data_fill(task_unit, last_task_unit,
cfg_info, resp_data, max_len, msg_type, task_id);
iot_pkt_put(pkt, len);
if (mode == PROTO_645_FJ_REPORT_MODE_698) {
if (len < 128) {
cache_len = 0;
} else {
cache_len = 1;
}
cache_len = sizeof(*result) + sizeof(*oct_hdr) + cache_len;
result = (proto_69845_app_result_normal_t*)iot_pkt_push(pkt, cache_len);
iot_uint32_to_bytes(di, (uint8_t*)(&result->oad), 1);
result->get_result.result_type = PROTO_69845_APP_GET_RESULT_DATA;
oct_hdr = (proto_69845_octet_string_uint_t*)result->get_result.result;
oct_hdr->data_type = PROTO_69845_APP_DATA_OCTET_STRING;
if (len < 128) {
oct_hdr->len_info.mub_flag = 0;
oct_hdr->len_info.byte_num = len;
} else {
oct_hdr->len_info.mub_flag = 1;
oct_hdr->len_info.byte_num = 1;
oct_hdr->len_and_data[0] = len;
}
}
out:
return pkt;
}
static uint16_t iot_sg_sta_ext_fj_random_rpt_tm_get(
iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint8_t random_rpt_time)
{
uint16_t time = 0;
uint32_t field = 0;
proto_645_fj_task_cycle_t cycle = { 0 };
cycle.value = cfg->value;
cycle.unit = cfg->unit;
field = proto_645_fj_task_cycle_to_sec(&cycle);
field = (field * random_rpt_time) / 100;
if (field > IOT_SG_STA_EXT_TASK_RANDOM_RPT_TIME_MAX) {
field = IOT_SG_STA_EXT_TASK_RANDOM_RPT_TIME_MAX;
} else if (field < IOT_SG_STA_EXT_TASK_RANDON_RPT_TIME_MIN) {
field = IOT_SG_STA_EXT_TASK_RANDON_RPT_TIME_MIN;
}
time = (uint16_t)(os_rand() % field);
iot_sg_printf("random rpt time %lu in [0, %lu]\n", time, field);
return time;
}
static uint8_t iot_sg_ext_data_rpt_msg_merge_cnt_get(
iot_sg_sta_ext_freeze_task_comm_cfg_t *comm_cfg, uint8_t task_id)
{
uint8_t merge_cnt = 0, i;
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (comm_cfg->task_rpt[i].id == task_id) {
merge_cnt = comm_cfg->task_rpt[i].cnt;
break;
}
}
return merge_cnt;
}
static uint32_t iot_sg_ext_data_rpt_645_msg_check(
proto_645_fj_task_data_query_hdr_ul_t *src_hdr,
proto_645_fj_task_data_query_hdr_ul_t *merge_hdr)
{
uint8_t *src_ptr, *merge_ptr, i;
uint32_t ret = ERR_FAIL;
int64_t interval;
iot_time_tm_t src_tm = {0}, merge_tm = {0};
proto_645_fj_task_data_query_di_unit_t *src_unit, *merge_unit;
if (merge_hdr->type != PROTO_645_FJ_TASK_TYPE_FREEZE
|| src_hdr->type != merge_hdr->type
|| src_hdr->task_cycle.value != merge_hdr->task_cycle.value
|| src_hdr->task_cycle.unit != merge_hdr->task_cycle.unit
|| src_hdr->di_cnt != merge_hdr->di_cnt) {
goto out;
}
src_tm.tm_year = iot_bcd_to_byte(src_hdr->start.year) + 2000;
src_tm.tm_mon = iot_bcd_to_byte(src_hdr->start.month);
src_tm.tm_mday = iot_bcd_to_byte(src_hdr->start.day);
src_tm.tm_hour = iot_bcd_to_byte(src_hdr->start.hour);
src_tm.tm_min = iot_bcd_to_byte(src_hdr->start.minute);
src_tm.tm_sec = iot_bcd_to_byte(src_hdr->start.second);
merge_tm.tm_year = iot_bcd_to_byte(merge_hdr->start.year) + 2000;
merge_tm.tm_mon = iot_bcd_to_byte(merge_hdr->start.month);
merge_tm.tm_mday = iot_bcd_to_byte(merge_hdr->start.day);
merge_tm.tm_hour = iot_bcd_to_byte(merge_hdr->start.hour);
merge_tm.tm_min = iot_bcd_to_byte(merge_hdr->start.minute);
merge_tm.tm_sec = iot_bcd_to_byte(merge_hdr->start.second);
interval = (int64_t)proto_645_fj_task_cycle_to_sec(&src_hdr->task_cycle);
interval = interval * src_hdr->frozen_point_cnt;
iot_rtc_delta_add(interval, &src_tm);
if (iot_rtc_delta_calc(&src_tm, &merge_tm) != 0) {
goto out;
}
src_ptr = src_hdr->di_data;
merge_ptr = merge_hdr->di_data;
for (i = 0; i < src_hdr->di_cnt; i++) {
src_unit = (proto_645_fj_task_data_query_di_unit_t*)src_ptr;
merge_unit = (proto_645_fj_task_data_query_di_unit_t*)merge_ptr;
if ((src_unit->di != merge_unit->di)
|| (src_unit->length != merge_unit->length)) {
goto out;
}
src_ptr += (sizeof(*src_unit) +
src_unit->length * src_hdr->frozen_point_cnt);
merge_ptr += (sizeof(*merge_unit) +
merge_unit->length * merge_hdr->frozen_point_cnt);
}
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_sg_ext_data_rpt_645_msg_total_len_get(
proto_645_fj_task_data_query_hdr_ul_t *src_hdr, uint32_t len,
uint8_t merge_cnt)
{
uint8_t *src_ptr, i;
uint32_t total_len = len;
proto_645_fj_task_data_query_di_unit_t *src_unit;
src_ptr = src_hdr->di_data;
for (i = 0; i < src_hdr->di_cnt; i++) {
src_unit = (proto_645_fj_task_data_query_di_unit_t*)src_ptr;
total_len += (src_unit->length * merge_cnt);
src_ptr += (sizeof(*src_unit) +
src_unit->length * src_hdr->frozen_point_cnt);
}
return total_len;
}
static iot_pkt_t *iot_sg_ext_data_rpt_645_msg_merge(uint8_t *src_data,
uint32_t src_len, uint8_t *merge_data, uint32_t merge_len)
{
uint8_t *src_ptr, *merge_ptr, *total_ptr, *ptr,i;
uint32_t total_len;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_data_query_hdr_ul_t *src_hdr, *merge_hdr, *total_hdr;
proto_645_fj_task_data_query_di_unit_t *src_unit, *merge_unit, *total_unit;
(void)merge_len;
src_hdr = (proto_645_fj_task_data_query_hdr_ul_t*)src_data;
merge_hdr = (proto_645_fj_task_data_query_hdr_ul_t*)merge_data;
if (iot_sg_ext_data_rpt_645_msg_check(src_hdr, merge_hdr)) {
goto out;
}
total_len = iot_sg_ext_data_rpt_645_msg_total_len_get(src_hdr, src_len,
merge_hdr->frozen_point_cnt);
if (total_len > PROTO_645_FJ_RESP_DATA_MAX_LEN) {
src_hdr->result = PROTO_645_FJ_READ_RESP_DATA_OVERFLOW;
goto out;
}
pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
total_hdr = (proto_645_fj_task_data_query_hdr_ul_t*)iot_pkt_put(pkt,
total_len);
os_mem_cpy(total_hdr, src_hdr, sizeof(*src_hdr));
total_hdr->frozen_point_cnt += merge_hdr->frozen_point_cnt;
src_ptr = src_hdr->di_data;
merge_ptr = merge_hdr->di_data;
total_ptr = total_hdr->di_data;
for (i = 0; i < total_hdr->di_cnt; i++) {
src_unit = (proto_645_fj_task_data_query_di_unit_t*)src_ptr;
merge_unit = (proto_645_fj_task_data_query_di_unit_t*)merge_ptr;
total_unit = (proto_645_fj_task_data_query_di_unit_t*)total_ptr;
os_mem_cpy(total_unit, src_unit, sizeof(*src_unit));
total_len = src_unit->length * src_hdr->frozen_point_cnt;
os_mem_cpy(total_unit->di_data, src_unit->di_data, total_len);
ptr = total_unit->di_data + total_len;
total_len = merge_unit->length * merge_hdr->frozen_point_cnt;
os_mem_cpy(ptr, merge_unit->di_data, total_len);
src_ptr += (sizeof(*src_unit) +
src_unit->length * src_hdr->frozen_point_cnt);
merge_ptr += (sizeof(*merge_unit) +
merge_unit->length * merge_hdr->frozen_point_cnt);
total_ptr += (sizeof(*total_unit) +
total_unit->length * total_hdr->frozen_point_cnt);
}
out:
return pkt;
}
static iot_pkt_t *iot_sg_ext_data_rpt_698_msg_merge(uint8_t *src_data,
uint32_t src_len, uint8_t *merge_data, uint32_t merge_len)
{
uint8_t *ptr;
uint32_t len = src_len + merge_len;
iot_pkt_t *pkt = NULL;
if (len < IOT_SG_STA_EXT_FREEZR_CACHE_LEN) {
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (pkt) {
ptr = iot_pkt_put(pkt, len);
os_mem_cpy(ptr, src_data, src_len);
ptr += src_len;
os_mem_cpy(ptr, merge_data, merge_len);
}
}
return pkt;
}
static iot_pkt_t *iot_sg_ext_data_rpt_msg_merge(uint8_t *addr,
uint8_t task_id, uint8_t *merge_cnt, uint8_t rpt_mode, uint8_t msg_type,
iot_pkt_t *unit_pkt)
{
uint8_t i, idx = 0xff;
uint16_t max_cnt = *merge_cnt + 1;
iot_pkt_t *rpt_pkt = unit_pkt;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_merge_uint_t *merge_info;
*merge_cnt = 1;
if ((rpt_mode == PROTO_645_FJ_REPORT_MODE_645)
&& (msg_type != PROTO_645_FJ_TASK_TYPE_FREEZE)) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
merge_info = &freeze_task->merge_list[i];
if (merge_info->merge_pkt) {
if (iot_mac_addr_cmp(addr, merge_info->addr)
&& task_id == merge_info->task_id) {
idx = i;
goto handle;
}
} else if (idx == 0xff) {
idx = i;
}
}
if (i == 0xff) {
goto out;
}
handle:
merge_info = &freeze_task->merge_list[idx];
if (merge_info->merge_pkt && (merge_info->mode == rpt_mode)) {
if (rpt_mode == PROTO_645_FJ_REPORT_MODE_645) {
rpt_pkt = iot_sg_ext_data_rpt_645_msg_merge(
iot_pkt_data(merge_info->merge_pkt),
iot_pkt_data_len(merge_info->merge_pkt),
iot_pkt_data(unit_pkt), iot_pkt_data_len(unit_pkt));
} else {
rpt_pkt = iot_sg_ext_data_rpt_698_msg_merge(
iot_pkt_data(merge_info->merge_pkt),
iot_pkt_data_len(merge_info->merge_pkt),
iot_pkt_data(unit_pkt), iot_pkt_data_len(unit_pkt));
}
if (rpt_pkt) {
iot_pkt_free(merge_info->merge_pkt);
iot_pkt_free(unit_pkt);
merge_info->msg_cnt++;
if (merge_info->msg_cnt >= max_cnt) {
*merge_cnt = merge_info->msg_cnt;
os_mem_set(merge_info, 0, sizeof(*merge_info));
} else {
merge_info->merge_pkt = rpt_pkt;
rpt_pkt = NULL;
*merge_cnt = 0;
}
} else {
rpt_pkt = merge_info->merge_pkt;
*merge_cnt = merge_info->msg_cnt;
merge_info->merge_pkt = unit_pkt;
merge_info->msg_cnt = 1;
}
} else {
if (merge_info->merge_pkt) {
iot_pkt_free(merge_info->merge_pkt);
}
merge_info->merge_pkt = rpt_pkt;
merge_info->mode = rpt_mode;
merge_info->task_id = task_id;
merge_info->msg_cnt = 1;
iot_mac_addr_cpy(merge_info->addr, addr);
rpt_pkt = NULL;
*merge_cnt = 0;
}
out:
return rpt_pkt;
}
static void iot_sg_ext_data_rpt_msg_merge_del(uint8_t *addr,
uint8_t task_id)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_merge_uint_t *merge_info;
if (freeze_task == NULL) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
merge_info = &freeze_task->merge_list[i];
if (iot_mac_addr_cmp(addr, merge_info->addr)
&& task_id == merge_info->task_id) {
if (merge_info->merge_pkt) {
iot_pkt_free(merge_info->merge_pkt);
os_mem_set(merge_info, 0, sizeof(*merge_info));
}
}
}
out:
return;
}
static void iot_sg_ext_data_rpt_msg_merge_del_by_mode(
uint8_t mode)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_merge_uint_t *merge_info;
if (freeze_task == NULL) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
merge_info = &freeze_task->merge_list[i];
if (merge_info->mode == mode && merge_info->merge_pkt
&& (iot_sg_sta_ext_fj_task_group_get(merge_info->task_id)
== PROTO_645_FJ_TASK_GROUP_645)) {
iot_pkt_free(merge_info->merge_pkt);
os_mem_set(merge_info, 0, sizeof(*merge_info));
}
}
out:
return;
}
static void iot_sg_sta_ext_fj_rpt_add(iot_pkt_t *rpt_pkt, uint8_t *addr,
uint8_t task_id, iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint8_t mode,
uint8_t msg_cnt)
{
uint8_t i, old_idx = 0;
uint32_t tm = 0;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_rpt_uint_t *rpt_info;
if (freeze_task == NULL) {
goto out;
}
if (!rpt_pkt || !addr || !task_id || (task_id >
PROTO_FJ_FREEZE_TASK_ID_MAX) || !msg_cnt || !cfg) {
goto out;
}
if (iot_sg_sta_power_off_check()) {
iot_pkt_free(rpt_pkt);
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
rpt_info = &freeze_task->rpt_list[i];
if (rpt_info->rpt_pkt == NULL) {
goto handle;
}
if (!tm) {
old_idx = i;
tm = rpt_info->tm;
} else if (rpt_info->tm < tm) {
old_idx = i;
tm = rpt_info->tm;
}
}
rpt_info = &freeze_task->rpt_list[old_idx];
handle:
iot_sg_sta_ext_fj_rpt_reset(rpt_info);
rpt_info->rpt_pkt = rpt_pkt;
rpt_info->seq = iot_sg_sta_get_event_rpt_seq();
rpt_info->rpt_cnt = 0;
rpt_info->task_id = task_id;
rpt_info->mode = !!mode;
rpt_info->msg_cnt = msg_cnt;
iot_mac_addr_cpy(rpt_info->addr, addr);
rpt_info->tm = (uint32_t)(os_boot_time64() / 1000);
rpt_info->random_rpt_tm = iot_sg_sta_ext_fj_random_rpt_tm_get(cfg,
freeze_task->comm_cfg.random_rpt_time);
rpt_info->rpt_tm = rpt_info->tm + rpt_info->random_rpt_tm;
out:
return;
}
static void iot_sg_sta_ext_fj_rpt_del(uint8_t *addr,
uint8_t task_id)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_rpt_uint_t *rpt_info;
if (freeze_task == NULL) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
rpt_info = &freeze_task->rpt_list[i];
if (rpt_info->rpt_pkt && iot_mac_addr_cmp(rpt_info->addr, addr)
&& (rpt_info->task_id == task_id)) {
iot_sg_sta_ext_fj_rpt_reset(rpt_info);
}
}
out:
return;
}
static void iot_sg_sta_ext_fj_rpt_del_by_mode(uint8_t mode)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_rpt_uint_t *rpt_info;
if (freeze_task == NULL) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
rpt_info = &freeze_task->rpt_list[i];
if (rpt_info->rpt_pkt && (mode == rpt_info->mode)
&& (iot_sg_sta_ext_fj_task_group_get(rpt_info->task_id)
== PROTO_645_FJ_TASK_GROUP_645)) {
iot_sg_sta_ext_fj_rpt_reset(rpt_info);
}
}
out:
return;
}
uint8_t iot_sg_sta_ext_fj_rpt_seq_check(uint16_t seq)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_rpt_uint_t *rpt_info;
if (freeze_task == NULL) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
rpt_info = &freeze_task->rpt_list[i];
if (rpt_info->rpt_pkt && rpt_info->seq == seq) {
return 1;
}
}
out:
return 0;
}
void iot_sg_sta_ext_fj_rpt_ack_handle(uint16_t seq)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_rpt_uint_t *rpt_info;
if (freeze_task == NULL) {
return;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
rpt_info = &freeze_task->rpt_list[i];
if (rpt_info->rpt_pkt && rpt_info->seq == seq) {
iot_sg_sta_ext_fj_rpt_count(rpt_info->task_id, 0,
rpt_info->msg_cnt);
iot_sg_sta_ext_fj_rpt_reset(rpt_info);
break;
}
}
}
static void iot_sg_ext_data_rpt_task_finish_handle(uint8_t *addr,
uint8_t task_id, iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_merge_uint_t *merge_info;
if (iot_sg_ext_data_task_finish_check(addr, task_id)) {
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
merge_info = &freeze_task->merge_list[i];
if (merge_info->merge_pkt && (task_id == merge_info->task_id)
&& iot_mac_addr_cmp(addr, merge_info->addr)) {
iot_sg_sta_ext_fj_rpt_add(merge_info->merge_pkt, addr, task_id,
cfg, merge_info->mode, merge_info->msg_cnt);
os_mem_set(merge_info, 0, sizeof(*merge_info));
}
}
}
}
static void iot_sg_sta_ext_freeze_flash_cfg_valid_set(uint8_t task_id,
uint8_t flag_valid)
{
uint8_t i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
if (!freeze_task) {
goto out;
}
if (!task_id || task_id > PROTO_FJ_FREEZE_TASK_ID_MAX) {
goto out;
}
if (flag_valid) {
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (freeze_task->valid_id[i]
&& freeze_task->valid_id[i] == task_id) {
goto out;
}
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (!freeze_task->valid_id[i]) {
freeze_task->valid_id[i] = task_id;
goto out;
}
}
} else {
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (freeze_task->valid_id[i]
&& freeze_task->valid_id[i] == task_id) {
freeze_task->valid_id[i] = 0;
goto out;
}
}
}
out:
return;
}
static uint8_t iot_sg_sta_ext_freeze_flash_cfg_valid_check(uint8_t task_id,
uint8_t *idx)
{
uint8_t flag_valid = 0, i;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
if (!freeze_task) {
goto out;
}
if (!task_id || task_id > PROTO_FJ_FREEZE_TASK_ID_MAX) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (freeze_task->valid_id[i] && freeze_task->valid_id[i] == task_id) {
if (idx) {
*idx = i;
}
flag_valid = 1;
break;
}
}
out:
return flag_valid;
}
static iot_time_tm_t *iot_sg_ext_data_freeze_get_node_tm(
iot_sg_sta_node_desc_t *node, uint8_t task_id)
{
uint8_t idx = 0;
iot_time_tm_t *tm = NULL;
if (!node || !iot_sg_sta_ext_freeze_flash_cfg_valid_check(task_id, &idx)) {
goto out;
}
tm = &node->ext.freeze_info.task_tm[idx];
out:
return tm;
}
static uint32_t iot_sg_ext_freeze_exe_cnt_set(uint8_t task_id,
uint16_t exe_cnt, uint16_t triger_cnt, uint8_t flag_first)
{
uint8_t i = 0, idle = 0xFF;
uint32_t ret = ERR_NOMEM;
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_freeze_task_t* task_info = ext_info->freeze_task_info;
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (task_info->exe_cnt_remain[i].task_id == task_id) {
task_info->exe_cnt_remain[i].count = exe_cnt;
task_info->exe_cnt_remain[i].trigger_cnt = triger_cnt;
if (flag_first) {
task_info->exe_cnt_remain[i].data_cnt = 0;
task_info->exe_cnt_remain[i].valid_len = 0;
os_mem_set(task_info->exe_cnt_remain[i].last_data, 0,
sizeof(task_info->exe_cnt_remain[i].last_data));
}
ret = ERR_OK;
goto out;
}
if (task_info->exe_cnt_remain[i].task_id == 0 && idle == 0xFF) {
idle = i;
}
}
if (idle != 0xFF) {
task_info->exe_cnt_remain[idle].count = exe_cnt;
task_info->exe_cnt_remain[idle].task_id = task_id;
task_info->exe_cnt_remain[idle].trigger_cnt = triger_cnt;
task_info->exe_cnt_remain[idle].data_cnt = 0;
task_info->exe_cnt_remain[idle].valid_len = 0;
task_info->exe_cnt_remain[idle].rpt_total_cnt = 0;
task_info->exe_cnt_remain[idle].rpt_cnt = 0;
os_mem_set(task_info->exe_cnt_remain[idle].last_data, 0,
sizeof(task_info->exe_cnt_remain[idle].last_data));
ret = ERR_OK;
}
out:
return ret;
}
static uint32_t iot_sg_ext_freeze_exe_cnt_get(uint8_t task_id,
uint16_t* exe_cnt, uint16_t* trigger_cnt)
{
uint8_t i = 0;
uint32_t ret = ERR_NOT_EXIST;
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_freeze_task_t* task_info = ext_info->freeze_task_info;
IOT_ASSERT(exe_cnt);
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (task_info->exe_cnt_remain[i].task_id == task_id) {
*exe_cnt = task_info->exe_cnt_remain[i].count;
*trigger_cnt = task_info->exe_cnt_remain[i].trigger_cnt;
ret = ERR_OK;
break;
}
}
return ret;
}
static void iot_sg_ext_freeze_exe_cnt_del(uint8_t task_id)
{
uint8_t i = 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_freeze_task_t* task_info = ext_info->freeze_task_info;
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (task_info->exe_cnt_remain[i].task_id == task_id) {
task_info->exe_cnt_remain[i].task_id = 0;
task_info->exe_cnt_remain[i].count = 0;
task_info->exe_cnt_remain[i].trigger_cnt = 0;
task_info->exe_cnt_remain[i].data_cnt = 0;
task_info->exe_cnt_remain[i].valid_len = 0;
os_mem_set(task_info->exe_cnt_remain[i].last_data, 0,
sizeof(task_info->exe_cnt_remain[i].last_data));
break;
}
}
}
static iot_sg_sta_ext_freeze_task_exe_cnt_t*
iot_sg_ext_freeze_last_data_get(uint8_t task_id)
{
uint8_t i = 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_freeze_task_t* task_info = ext_info->freeze_task_info;
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (task_info->exe_cnt_remain[i].task_id == task_id) {
return &task_info->exe_cnt_remain[i];
}
}
return NULL;
}
static uint32_t iot_sg_sta_ext_freeze_flash_cfg_get(uint8_t *addr,
uint8_t task_id, iot_sg_sta_drv_meter_fj_task_info_t *task_info)
{
uint32_t ret = ERR_FAIL;
if (!iot_sg_sta_ext_freeze_flash_cfg_valid_check(task_id, NULL)) {
goto out;
}
if (iot_sg_sta_flash_clct_task_info_get(addr, task_id, (uint8_t *)task_info,
sizeof(*task_info), IOT_SG_STA_METER_DATA_TYPE_FJ_TASK)) {
goto out;
}
ret = ERR_OK;
out:
return ret;
}
static uint8_t iot_sg_sta_ext_fj_rpt_retry_cnt_get(uint8_t* addr, uint8_t task_id)
{
uint8_t reason = 0, count = PROTO_645_FJ_FREEZE_TASK_RERPT_CNT_DEF;
iot_pkt_t* pkt = NULL;
uint32_t time = 0;
proto_645_fj_task_cycle_t cycle = { 0 };
iot_sg_sta_drv_meter_fj_task_info_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_freeze_task_t* freeze_task = ext_info->freeze_task_info;
pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!pkt) {
reason = 1;
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t*)iot_pkt_put(pkt, sizeof(*cfg));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg) != ERR_OK) {
reason = 2;
goto out;
}
cycle.value = cfg->value;
cycle.unit = cfg->unit;
time = proto_645_fj_task_cycle_to_sec(&cycle);
if (cfg->type == PROTO_645_FJ_TASK_TYPE_FREEZE && time < 300) {
/* For frozen data tasks with a cycle of less than 5 minutes */
count = freeze_task->comm_cfg.retry_freeze;
} else {
count = freeze_task->comm_cfg.retry_nonfreeze;
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return count;
}
static void iot_sg_sta_ext_fj_led_blink_disable(
iot_sg_sta_ext_freeze_task_t *task)
{
if (!task->led_blink_en_cnt) {
iot_plc_led_request(IOT_PLC_LED_SEARCH_METER_END);
}
task->led_blink_en_cnt = IOT_SG_STA_EXT_LED_BLINK_EN_CNT;
}
static void iot_sg_sta_ext_fj_led_blink_timeout_enable(
iot_sg_sta_ext_freeze_task_t *task)
{
if (task->led_blink_en_cnt) {
task->led_blink_en_cnt--;
if (!task->led_blink_en_cnt) {
iot_plc_led_request(IOT_PLC_LED_SEARCH_METER_START);
}
}
}
static void iot_sg_sta_ext_fj_rpt_count(uint8_t task_id,
uint8_t flag_total_cnt, uint8_t count)
{
iot_sg_sta_ext_freeze_task_exe_cnt_t *exe_info;
exe_info = iot_sg_ext_freeze_last_data_get(task_id);
if (exe_info) {
if (flag_total_cnt) {
exe_info->rpt_total_cnt += count;
} else {
exe_info->rpt_cnt += count;
}
}
}
static void iot_sg_sta_ext_fj_rpt_handle(void)
{
uint8_t i, *data, retry_cnt;
uint32_t len, ret, curr_tm, wait, di = PROTO_645_FJ_DI_QR_TASK_DATA;
server_addr_info_t server_info = {0};
iot_pkt_t *msg_pkt = 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_freeze_task_t* freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_rpt_uint_t* rpt_info;
if (freeze_task == NULL) {
return;
}
curr_tm = (uint32_t)(os_boot_time64() / 1000);
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
rpt_info = &freeze_task->rpt_list[i];
if (rpt_info->rpt_pkt) {
retry_cnt = iot_sg_sta_ext_fj_rpt_retry_cnt_get(rpt_info->addr,
rpt_info->task_id);
retry_cnt++;
if (rpt_info->rpt_cnt >= retry_cnt
|| iot_sg_sta_power_off_check()) {
iot_sg_sta_ext_fj_rpt_reset(rpt_info);
continue;
}
if (curr_tm < rpt_info->rpt_tm) {
continue;
}
di += rpt_info->task_id;
if (rpt_info->mode == PROTO_645_FJ_REPORT_MODE_645) {
msg_pkt = proto_645_fj_build_msg(rpt_info->addr,
iot_pkt_data(rpt_info->rpt_pkt),
(uint8_t)iot_pkt_data_len(rpt_info->rpt_pkt),
di, PROTO_645_FJ_FN_ACTIVE_RPT);
} else {
server_info.len = IOT_MAC_ADDR_LEN;
server_info.type = PROTO_69845_SA_TYPE_SIG;
iot_mac_addr_cpy(server_info.addr, rpt_info->addr);
msg_pkt = proto_69845_build_rpt_noti_list_msg(
iot_pkt_data(rpt_info->rpt_pkt),
(uint16_t)iot_pkt_data_len(rpt_info->rpt_pkt),
rpt_info->msg_cnt, &server_info, (uint8_t)rpt_info->seq);
}
if (msg_pkt == NULL) {
continue;
}
data = iot_pkt_data(msg_pkt);
len = iot_pkt_data_len(msg_pkt);
ret = iot_sg_sta_report_event_with_seq(rpt_info->addr, data, len,
rpt_info->seq);
if (ret == ERR_OK) {
iot_sg_sta_ext_fj_led_blink_disable(freeze_task);
rpt_info->rpt_cnt++;
wait = rpt_info->random_rpt_tm > IOT_SG_STA_EXT_TASK_RE_RPT_DUR
? rpt_info->random_rpt_tm : IOT_SG_STA_EXT_TASK_RE_RPT_DUR;
rpt_info->rpt_tm = curr_tm + wait;
iot_sg_printf("%s task_id %lu report %luth\n",
__FUNCTION__, rpt_info->task_id, rpt_info->rpt_cnt);
}
iot_pkt_free(msg_pkt);
}
}
}
void iot_sg_sta_ext_freeze_node_tm_update(iot_sg_sta_node_desc_t *node)
{
uint8_t idx, task_id;
int64_t delta;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_drv_meter_fj_task_info_t *task_info;
proto_645_fj_task_cycle_t cycle = { 0 };
iot_pkt_t *task_pkt = NULL;
if (!freeze_task) {
goto out;
}
task_pkt = iot_pkt_alloc(sizeof(*task_info), IOT_SMART_GRID_MID);
if (!task_pkt) {
goto out;
}
task_info = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*task_info));
for (idx = 0; idx < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; idx++) {
task_id = freeze_task->valid_id[idx];
if (iot_sg_sta_ext_freeze_flash_cfg_get(node->entry.addr,
task_id, task_info) != ERR_OK) {
continue;
}
cycle.value = task_info->value;
cycle.unit = task_info->unit;
delta = (int64_t)proto_645_fj_task_cycle_to_sec(&cycle);
if (cycle.unit == PROTO_645_FJ_TASK_CYCLE_UNIT_TYPE_DAY ||
iot_sg_sta_ext_node_tm_check(&node->ext.freeze_info.task_tm[idx],
delta)) {
os_mem_set(&node->ext.freeze_info.task_tm[idx], 0x0,
sizeof(iot_time_tm_t));
}
}
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
}
static void iot_sg_ext_data_freeze_cur_info_clear(
iot_sg_sta_ext_freeze_task_t *freeze_task)
{
if (!freeze_task) {
return;
}
freeze_task->cur_state = IOT_SG_STA_EXT_FREEZR_STATE_IDLE;
freeze_task->cur_task_id = 0;
freeze_task->task_end = 0;
freeze_task->cur_di_idx = 0;
freeze_task->cur_mr_di_cnt = 0;
freeze_task->flag_resp = 0;
freeze_task->flag_nack_resp = 0;
freeze_task->flag_rpt = 0;
freeze_task->repeat_cnt = 0;
freeze_task->timeout_cnt = 0;
if (freeze_task->resp_pkt) {
iot_pkt_free(freeze_task->resp_pkt);
freeze_task->resp_pkt = NULL;
}
}
void iot_sg_ext_data_freeze_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;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
if (freeze_task) {
iot_sg_ext_data_freeze_cur_info_clear(freeze_task);
freeze_task->task_bm = 0;
}
}
static uint32_t iot_sg_ext_freeze_unit_data_offset_get(uint8_t *data_offset,
uint8_t max_len, uint8_t resp_data_cnt, uint8_t *data)
{
uint32_t ret = ERR_OK;
uint8_t offset = 0, i;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data;
for (i = 0; i < resp_data_cnt; i++) {
if (offset >= max_len) {
ret = ERR_FAIL;
goto out;
}
unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)(data + offset);
offset += sizeof(*unit_data) + unit_data->len;
}
*data_offset = offset;
out:
return ret;
}
static uint64_t iot_sg_ext_freeze_rpt_value_get(uint8_t *data, uint8_t len,
uint8_t group_type, uint8_t is_big_endian)
{
uint8_t i;
uint64_t cross_value = 0;
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
for (i = 0; i < len; i++) {
if (is_big_endian) {
cross_value |= (data[len - i - 1] << (i * 8));
} else {
cross_value |= (data[i] << (i * 8));
}
}
} else {
for (i = len; i != 0; i--) {
cross_value += iot_bcd_to_byte(data[i - 1]);
if ((i - 1) != 0) {
cross_value *= 100;
}
}
}
return cross_value;
}
static uint8_t iot_sg_ext_freeze_cross_grads_get(uint64_t value,
proto_645_fj_task_set_cross_rpt_t *cross, uint8_t group_type)
{
uint8_t grads = 0, *cross_data, cross_data_len;
uint64_t cross_value1, cross_value2;
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
cross_data = cross->value_list + sizeof(proto_69845_app_data_t);
cross_data_len = cross->value_len - sizeof(proto_69845_app_data_t);
} else {
cross_data = cross->value_list;
cross_data_len = cross->value_len;
}
cross_value1 = iot_sg_ext_freeze_rpt_value_get(cross_data, cross_data_len,
group_type, 0);
if (value <= cross_value1) {
goto out;
}
cross_data += cross_data_len;
for (grads = 1; grads < cross->cnt; grads++) {
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
cross_data += sizeof(proto_69845_app_data_t);
}
cross_value2 = iot_sg_ext_freeze_rpt_value_get(cross_data,
cross_data_len, group_type, 0);
if (value > cross_value1 && value <= cross_value2) {
goto out;
}
cross_value1 = cross_value2;
cross_data += cross_data_len;
}
/* running to here value >= end crossing value */
out:
return grads;
}
static uint8_t iot_sg_ext_freeze_cross_rpt_check(
iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint8_t *data, uint8_t len,
uint8_t *save_data, uint8_t save_len, uint8_t group_type)
{
uint64_t rsp_value, save_value;
uint8_t flag_rpt = 0, desc_len = cfg->desc_len;
uint8_t rsp_grads, save_grads, reason = 0, is_big_endian = 0;
proto_645_fj_task_set_cross_rpt_t *cross;
proto_69845_app_data_t *save_app_data, *resp_app_data, *set_app_data;
if (!cfg || !data || !len || !save_data || !save_len) {
reason = 1;
goto out;
}
cross = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
if (desc_len < sizeof(*cross)) {
reason = 2;
goto out;
}
desc_len -= sizeof(*cross);
if (desc_len < cross->cnt * cross->value_len) {
reason = 3;
goto out;
}
if (cross->value_len > PROTO_645_FJ_TASK_DESC_CROSS_VALUE_MAX_LEN) {
reason = 4;
goto out;
}
if (save_len != cross->value_len || len != cross->value_len) {
reason = 5;
goto out;
}
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
if (len < sizeof(*resp_app_data)) {
reason = 6;
goto out;
}
resp_app_data = (proto_69845_app_data_t *)data;
save_app_data = (proto_69845_app_data_t *)save_data;
set_app_data = (proto_69845_app_data_t *)cross->value_list;
if (resp_app_data->data_type != set_app_data->data_type ||
save_app_data->data_type != set_app_data->data_type) {
reason = 7;
goto out;
}
len -= sizeof(*resp_app_data);
data += sizeof(*resp_app_data);
save_len -= sizeof(*save_app_data);
save_data += sizeof(*save_app_data);
is_big_endian = 1;
}
if (!cross->cnt) {
reason = 8;
goto out;
}
rsp_value = iot_sg_ext_freeze_rpt_value_get(data, len, group_type,
is_big_endian);
save_value = iot_sg_ext_freeze_rpt_value_get(save_data, save_len,
group_type, is_big_endian);
rsp_grads = iot_sg_ext_freeze_cross_grads_get(rsp_value, cross, group_type);
save_grads = iot_sg_ext_freeze_cross_grads_get(save_value, cross,
group_type);
iot_sg_printf("%s rsp_value %lu grads %lu save_value %lu grads %lu\n",
__FUNCTION__, (uint32_t)rsp_value, rsp_grads, (uint32_t)save_value,
save_grads);
if (rsp_grads != save_grads) {
flag_rpt = 1;
}
out:
if (reason) {
iot_sg_printf("%s fail reason %lu\n", __FUNCTION__, reason);
}
return flag_rpt;
}
static uint8_t iot_sg_ext_freeze_chg_rpt_check(
iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint8_t *data, uint8_t len,
uint8_t *save_data, uint8_t save_len, uint8_t debug_flag,
uint8_t group_type)
{
uint64_t rsp_value, save_value, change_value, max_value;
uint8_t flag_rpt = 0, desc_len = cfg->desc_len, *chg_data, chg_data_len;
uint8_t reason = 0, is_big_endian = 0;
proto_645_fj_task_set_change_rpt_hdr_t *chg;
proto_69845_app_data_t *save_app_data, *resp_app_data, *set_app_data;
if (!cfg || !data || !len || !save_data || !save_len) {
reason = 1;
goto out;
}
chg = (proto_645_fj_task_set_change_rpt_hdr_t*)cfg->desc;
if (desc_len < sizeof(*chg )) {
reason = 2;
goto out;
}
desc_len -= sizeof(*chg);
if (desc_len < chg->value_len) {
reason = 3;
goto out;
}
if (chg->value_len > PROTO_645_FJ_TASK_DESC_CHANGE_VALUE_MAX_LEN) {
reason = 4;
goto out;
}
if (save_len != chg->value_len || len != chg->value_len) {
reason = 5;
goto out;
}
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
if (len < sizeof(*save_app_data)) {
reason = 6;
goto out;
}
resp_app_data = (proto_69845_app_data_t *)data;
save_app_data = (proto_69845_app_data_t *)save_data;
set_app_data = (proto_69845_app_data_t *)chg->value_list;
if (resp_app_data->data_type != set_app_data->data_type ||
save_app_data->data_type != set_app_data->data_type) {
reason = 7;
goto out;
}
len -= sizeof(*resp_app_data);
data += sizeof(*resp_app_data);
save_len -= sizeof(*save_app_data);
save_data += sizeof(*save_app_data);
chg_data_len = chg->value_len - sizeof(*set_app_data);
chg_data = chg->value_list + sizeof(*set_app_data);
is_big_endian = 1;
} else {
chg_data_len = chg->value_len;
chg_data = chg->value_list;
}
rsp_value = iot_sg_ext_freeze_rpt_value_get(data, len, group_type,
is_big_endian);
save_value = iot_sg_ext_freeze_rpt_value_get(save_data, save_len,
group_type, is_big_endian);
max_value = iot_sg_ext_freeze_rpt_value_get(chg_data, chg_data_len,
group_type, 0);
if (debug_flag) {
iot_sg_printf("%s rsp_value %lu, save_value %lu, change value %lu\n",
__FUNCTION__, (uint32_t)rsp_value, (uint32_t)save_value,
(uint32_t)max_value);
}
if (rsp_value >= save_value) {
change_value = rsp_value - save_value;
} else {
change_value = save_value - rsp_value;
}
if (change_value >= max_value) {
flag_rpt = 1;
}
out:
if (reason) {
iot_sg_printf("%s fail reason %lu\n", __FUNCTION__, reason);
}
return flag_rpt;
}
static uint32_t iot_sg_ext_freeze_rpt_di_check(uint32_t rsp_di,
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t idx;
uint32_t ret = ERR_FAIL, di;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_rpt;
proto_645_fj_task_set_cross_rpt_t *cross_rpt;
proto_645_fj_task_set_change_rpt_hdr_t *chg_rpt;
switch (cfg->type) {
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_rpt = (proto_645_fj_task_set_incon_rpt_hdr_t *)cfg->desc;
for (idx = 0; idx < incon_rpt->di_cnt; idx++) {
di = proto_645_2007_byte_to_di((uint8_t *)&incon_rpt->di[idx]);
if (di == rsp_di) {
ret = ERR_OK;
break;
}
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_rpt = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
di = proto_645_2007_byte_to_di((uint8_t *)&cross_rpt->di);
if (di == rsp_di) {
ret = ERR_OK;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_rpt = (proto_645_fj_task_set_change_rpt_hdr_t *)cfg->desc;
di = proto_645_2007_byte_to_di((uint8_t *)&chg_rpt->di);
if (di == rsp_di) {
ret = ERR_OK;
}
break;
}
default:
break;
}
return ret;
}
static uint8_t iot_sg_ext_freeze_rpt_check(uint8_t *addr, uint8_t *data,
uint8_t len, iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint8_t task_id,
uint8_t *first_rpt_task)
{
uint8_t *save_data, save_len, reason = 0, group_type;
uint8_t flag_rpt = 0, rsp_len, *rsp_data;
uint16_t latest_idx = 0, unit_len = 0;
uint32_t rsp_di;
int64_t delta;
proto_645_fj_task_cycle_t cycle = { 0 };
iot_time_tm_t *node_tm = NULL, last_tm = {0};
iot_sg_sta_node_desc_t *node = iot_sg_sta_node_find_by_addr(addr);
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data;
iot_sg_sta_drv_meter_fj_task_unit_t *task_data;
iot_sg_sta_ext_freeze_task_exe_cnt_t *last_info;
iot_pkt_t *task_pkt = NULL;
if (!cfg || !addr || !data || !task_id || !first_rpt_task) {
reason = 1;
goto out;
}
if (len < PROTO_645_2007_DI_LEN) {
reason = 2;
goto out;
}
group_type = iot_sg_sta_ext_fj_task_group_get(task_id);
rsp_di = proto_645_2007_byte_to_di(data);
if (iot_sg_ext_freeze_rpt_di_check(rsp_di, cfg)) {
reason = 3;
goto out;
}
rsp_len = len - PROTO_645_2007_DI_LEN;
rsp_data = data + PROTO_645_2007_DI_LEN;
last_info = iot_sg_ext_freeze_last_data_get(task_id);
if (!last_info || !last_info->valid_len || !last_info->data_cnt) {
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
task_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!task_pkt) {
reason = 4;
goto out;
}
task_data = (iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(
task_pkt, unit_len);
if (iot_sg_sta_flash_ct_unit_data_find_latest(addr, &latest_idx,
(uint8_t *)task_data, unit_len, task_id,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) != ERR_OK) {
if (cfg->type != PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
*first_rpt_task = 1;
}
reason = 5;
goto out;
}
if (cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
node_tm = iot_sg_ext_data_freeze_get_node_tm(node, task_id);
last_tm.tm_year = (uint16_t)(task_data->uint_time.year + 2000);
last_tm.tm_mon = (uint8_t)task_data->uint_time.month;
last_tm.tm_mday = (uint8_t)task_data->uint_time.day;
last_tm.tm_hour = (uint8_t)task_data->uint_time.hour;
last_tm.tm_min = (uint8_t)task_data->uint_time.minute;
cycle.value = cfg->value;
cycle.unit = cfg->unit;
delta = (int64_t)proto_645_fj_task_cycle_to_sec(&cycle);
if (!node_tm || iot_rtc_delta_calc(&last_tm, node_tm) != delta) {
reason = 6;
goto out;
}
if (!last_info) {
reason = 7;
goto out;
}
last_info->data_cnt = task_data->resp_data_cnt;
last_info->valid_len = task_data->valid_len;
os_mem_cpy(last_info->last_data, task_data->uint_data,
last_info->valid_len);
}
unit_data = iot_sg_ext_freeze_di_unit_data_get(rsp_di,
task_data->uint_data, task_data->valid_len,
task_data->resp_data_cnt);
} else {
unit_data = iot_sg_ext_freeze_di_unit_data_get(rsp_di,
last_info->last_data, last_info->valid_len,
last_info->data_cnt);
}
if (!unit_data) {
reason = 8;
goto out;
}
if (unit_data->len <= PROTO_645_2007_DI_LEN) {
reason = 9;
goto out;
}
save_len = unit_data->len - PROTO_645_2007_DI_LEN;
save_data = unit_data->data + PROTO_645_2007_DI_LEN;
if (cfg->type == PROTO_645_FJ_TASK_TYPE_CROSS_RPT) {
flag_rpt = iot_sg_ext_freeze_cross_rpt_check(cfg, rsp_data,
rsp_len, save_data, save_len, group_type);
} else if (cfg->type == PROTO_645_FJ_TASK_TYPE_INCON_RPT) {
if (rsp_len != save_len) {
reason = 10;
goto out;
}
if (os_mem_cmp(rsp_data, save_data, save_len) != 0) {
flag_rpt = 1;
goto out;
}
} else if (cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
flag_rpt = iot_sg_ext_freeze_chg_rpt_check(cfg, rsp_data,
rsp_len, save_data, save_len, 1, group_type);
}
out:
iot_sg_printf("%s err %d\n", __FUNCTION__, reason);
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return flag_rpt;
}
static void iot_sg_ext_freeze_cur_task_resp_handle(uint8_t *addr, uint8_t *data,
uint8_t len)
{
uint8_t max_len, offset, ret = 0, first_rpt_task = 0;
uint16_t unit_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_freeze_task_t *freeze = ext_info->freeze_task_info;
iot_sg_sta_drv_meter_fj_task_info_t *cfg;
iot_sg_sta_drv_meter_fj_task_unit_t *resp_data;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data;
iot_pkt_t *task_pkt = NULL;
if (!addr || !data || !len) {
ret = 1;
goto out;
}
task_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!task_pkt) {
ret = 2;
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*cfg));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, freeze->cur_task_id, cfg)) {
ret = 3;
goto out;
}
if (!freeze->resp_pkt) {
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
freeze->resp_pkt =
iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!freeze->resp_pkt) {
ret = 4;
goto out;
}
iot_pkt_put(freeze->resp_pkt, unit_len);
}
resp_data = (iot_sg_sta_drv_meter_fj_task_unit_t *)
iot_pkt_data(freeze->resp_pkt);
max_len = IOT_SG_STA_METER_FJ_TASK_RECORD_UINT_LEN;
if (len + sizeof(*unit_data) + resp_data->valid_len > max_len) {
freeze->task_end = 1;
ret = 5;
goto out;
}
if (iot_sg_ext_freeze_unit_data_offset_get(&offset, max_len,
resp_data->resp_data_cnt, resp_data->uint_data)) {
ret = 6;
goto out;
}
unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)
(resp_data->uint_data + offset);
unit_data->len = len;
os_mem_cpy(unit_data->data, data, len);
resp_data->resp_data_cnt++;
resp_data->valid_len += (len + sizeof(*unit_data));
if ((cfg->type == PROTO_645_FJ_TASK_TYPE_CROSS_RPT ||
cfg->type == PROTO_645_FJ_TASK_TYPE_INCON_RPT ||
cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) && !freeze->flag_rpt) {
if (iot_sg_ext_freeze_rpt_check(addr, data, len, cfg,
freeze->cur_task_id, &first_rpt_task)) {
freeze->flag_rpt = 1;
}
freeze->first_rpt_task = first_rpt_task;
} else if (cfg->type == PROTO_645_FJ_TASK_TYPE_FREEZE) {
freeze->flag_rpt = 1;
}
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
iot_sg_printf("%s ret %lu\n", __FUNCTION__, ret);
return;
}
static uint32_t iot_sg_ext_data_freeze_handle_645(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 reason = 0, di_cnt, i, multi_data_len, *multi_data;
uint32_t ret = ERR_INVAL, di;
proto_645_header_t *resp_hdr, *req_hdr;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
proto_645_fj_multi_resp_data_t *multi_resp;
iot_sg_sta_ext_freeze_task_t *freeze = ext_info->freeze_task_info;
(void)seq;
if (ext_info->freeze_task_info->cur_state !=
IOT_SG_STA_EXT_FREEZR_STATE_WAIT) {
reason = 1;
goto out;
}
if (data_type != IOT_SG_STA_DATA_TYPE_645_07) {
reason = 2;
goto out;
}
if ((req_data == NULL) || !req_len) {
reason = 3;
goto out;
}
if ((resp_data == NULL) || !resp_len) {
ret = ERR_TIMEOVER;
reason = 4;
goto out;
}
if (iot_sg_ext_read_645_nack_check(req_data, req_len, resp_data, resp_len,
ext_info->addr) == ERR_OK) {
iot_sg_printf("%s nack\n", __FUNCTION__);
freeze->flag_nack_resp = 1;
reason = 5;
ret = ERR_OK;
goto out;
}
if (proto_645_check_di_fn_match(req_data, req_len,
resp_data, resp_len)) {
reason = 6;
goto out;
}
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 = 7;
goto out;
}
if ((resp_hdr->control.ack != PROTO_645_ACK_NORMAL)
|| (resp_hdr->control.dir != PROTO_645_DIR_SLAVE)) {
reason = 8;
goto out;
}
if (!iot_mac_addr_cmp(ext_info->addr, resp_hdr->addr)) {
reason = 9;
goto out;
}
if (resp_hdr->len < PROTO_645_2007_DI_LEN) {
reason = 10;
goto out;
}
proto_645_sub33_handle(resp_hdr->data, resp_hdr->len);
di = proto_645_2007_byte_to_di(resp_hdr->data);
if ((di & 0xffffff00) == PROTO_645_FJ_METER_MULTI_DI_READ &&
freeze->cur_mr_di_cnt > 1) {
multi_data_len = resp_hdr->len - PROTO_645_2007_DI_LEN;
multi_data = resp_hdr->data + PROTO_645_2007_DI_LEN;
di_cnt = (uint8_t)(di & 0x000000ff);
for (i = 0; i < di_cnt; i++) {
if (multi_data_len < sizeof(*multi_resp)) {
reason = 11;
goto out;
}
multi_data_len -= sizeof(*multi_resp);
multi_resp = (proto_645_fj_multi_resp_data_t *)multi_data;
if (multi_data_len < multi_resp->data_len) {
reason = 12;
goto out;
}
multi_data_len -= multi_resp->data_len;
iot_sg_ext_freeze_cur_task_resp_handle(ext_info->addr,
multi_resp->data, multi_resp->data_len);
ret = ERR_OK;
multi_data += (sizeof(*multi_resp) + multi_resp->data_len);
if (i < di_cnt -1) {
if (!multi_data_len) {
reason = 13;
goto out;
}
/* skip the separator */
if (*multi_data != 0xbb) {
reason = 14;
goto out;
}
multi_data_len -= 1;
multi_data += 1;
}
}
} else {
iot_sg_ext_freeze_cur_task_resp_handle(ext_info->addr, resp_hdr->data,
resp_hdr->len);
ret = ERR_OK;
}
out:
iot_sg_printf("%s reason %d\n", __FUNCTION__, reason);
return ret;
}
void iot_sg_sta_ext_fj_698_oad_data_handle(
proto_69845_app_oad_resp_hdr_t *oad_data, uint32_t oad_data_len)
{
uint8_t *data, buff_len;
iot_pkt_t *buff_pkt = 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;
if (!oad_data_len) {
goto out;
}
buff_len = (uint8_t)(sizeof(proto_69845_app_oad_t) + oad_data_len);
buff_pkt = iot_pkt_alloc(buff_len, IOT_SMART_GRID_MID);
if (!buff_pkt) {
goto out;
}
data = iot_pkt_put(buff_pkt, buff_len);
os_mem_cpy(data, &oad_data->oad, sizeof(proto_69845_app_oad_t));
iot_data_reverse(data, sizeof(proto_69845_app_oad_t));
data += sizeof(proto_69845_app_oad_t);
os_mem_cpy(data, oad_data->result, oad_data_len);
iot_sg_ext_freeze_cur_task_resp_handle(ext_info->addr,
iot_pkt_data(buff_pkt), buff_len);
out:
if (buff_pkt) {
iot_pkt_free(buff_pkt);
}
return;
}
void iot_sg_ext_data_freeze_handle(uint16_t seq,
uint8_t data_type, uint8_t *resp_data, uint16_t resp_len,
uint8_t *req_data, uint16_t req_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;
if (data_type == IOT_SG_STA_DATA_TYPE_645_07) {
ret = iot_sg_ext_data_freeze_handle_645(seq, data_type, resp_data,
resp_len, req_data, req_len);
} else if (data_type == IOT_SG_STA_DATA_TYPE_69845) {
ret = iot_sg_ext_read_698_data_handle(seq, data_type, resp_data,
resp_len, req_data, req_len);
}
if (ret == ERR_OK || ret == ERR_TIMEOVER) {
if (ret == ERR_OK) {
ext_info->freeze_task_info->flag_resp = 1;
}
ext_info->freeze_task_info->timeout_cnt = 0;
iot_sg_sta_ext_sm_stop_action();
iot_sg_sta_ext_sm_next_action(IOT_SG_STA_EXT_SM_MIN_DELAY);
}
}
static void iot_sg_sta_ext_freeze_cur_task_reset(uint8_t *addr, uint8_t task_id)
{
uint8_t idx = 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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_node_desc_t *node;
node = iot_sg_sta_node_find_by_addr(addr);
if (!iot_sg_sta_ext_freeze_flash_cfg_valid_check(task_id, &idx)
|| !node || !freeze_task) {
return;
}
os_mem_set(&node->ext.freeze_info.task_tm[idx], 0x0,
sizeof(iot_time_tm_t));
if (task_id == freeze_task->cur_task_id) {
iot_sg_ext_data_freeze_cur_info_clear(freeze_task);
freeze_task->task_bm &= ~(1 << idx);
}
iot_sg_printf("%s id %lu\n", __FUNCTION__, task_id);
}
static uint8_t iot_sg_sta_ext_freeze_task_same_check(
iot_sg_sta_drv_meter_fj_task_info_t *local_cfg,
iot_sg_sta_drv_meter_fj_task_info_t *add_cfg)
{
uint8_t same_flag = 0;
if (!local_cfg || !add_cfg) {
goto out;
}
if (local_cfg->type == add_cfg->type &&
local_cfg->value == add_cfg->value &&
local_cfg->unit == add_cfg->unit &&
local_cfg->delay == add_cfg->delay &&
local_cfg->save_cnt == add_cfg->save_cnt &&
local_cfg->rec_total_len == add_cfg->rec_total_len &&
local_cfg->prio == add_cfg->prio &&
local_cfg->storage_mode == add_cfg->storage_mode &&
local_cfg->exe_cnt == add_cfg->exe_cnt &&
local_cfg->desc_len == add_cfg->desc_len &&
local_cfg->flag_rpt == add_cfg->flag_rpt &&
!os_mem_cmp(local_cfg->desc, add_cfg->desc, add_cfg->desc_len)) {
same_flag = 1;
}
out:
return same_flag;
}
static uint32_t iot_sg_sta_ext_freeze_task_cnt_check(uint8_t *addr,
uint8_t task_id)
{
uint8_t i, cnt = 0;
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;
iot_sg_sta_ext_freeze_task_t *task_cfg = ext_info->freeze_task_info;
iot_sg_sta_node_desc_t *node = iot_sg_sta_node_find_by_addr(addr);
if (!node || !task_cfg) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (task_cfg->valid_id[i]) {
if (task_cfg->valid_id[i] == task_id) {
ret = ERR_OK;
goto out;
}
cnt++;
}
}
if (cnt != IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT) {
ret = ERR_OK;
}
out:
return ret;
}
static uint32_t iot_sg_ext_flash_freeze_task_exe_cnt_set(uint8_t* addr,
uint8_t task_id, uint16_t exe_cnt_remain, uint16_t trigger_cnt,
uint8_t rpt_cnt)
{
uint8_t reason = 0;
uint16_t index = 0, unit_len = 0;
uint32_t ret = ERR_OK;
iot_pkt_t* pkt = NULL;
iot_sg_sta_drv_meter_fj_task_unit_t* unit;
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 1;
goto out;
}
unit = (iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(pkt, unit_len);
if (iot_sg_sta_flash_ct_unit_data_find_latest(addr, &index, (uint8_t *)unit,
unit_len, task_id, IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) == ERR_OK) {
unit->exe_cnt_remain = exe_cnt_remain;
unit->save_cnt = trigger_cnt;
unit->rpt_cnt = rpt_cnt;
ret = iot_sg_sta_flash_ct_unit_data_save(
addr, index, (uint8_t *)unit, unit_len, task_id);
if (ret != ERR_OK) {
reason = 2;
}
}
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
void iot_sg_sta_ext_fj_task_restart(void)
{
uint8_t i, task_id, addr[IOT_MAC_ADDR_LEN], reason = 0;
iot_pkt_t* task_pkt = 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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_ext_freeze_task_reset_t *reset = &freeze_task->reset;
iot_sg_sta_drv_meter_fj_task_info_t *task_info;
if (!freeze_task) {
reason = 1;
goto out;
}
if (!reset->cnt) {
goto out;
}
iot_mac_addr_cpy(addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(addr);
task_pkt = iot_pkt_alloc(sizeof(*task_info), IOT_SMART_GRID_MID);
if (!task_pkt) {
reason = 2;
goto out;
}
task_info = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*task_info));
for (i = reset->cur_idx; i < reset->cnt; i++) {
task_id = reset->task_id[i];
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, task_info)
== ERR_OK) {
iot_sg_ext_freeze_exe_cnt_set(task_id, task_info->exe_cnt, 0, 1);
iot_sg_ext_flash_freeze_task_exe_cnt_set(addr, task_id,
task_info->exe_cnt, 0, 0);
break;
}
}
reset->cur_idx = ++i;
if (reset->cur_idx >= reset->cnt) {
os_mem_set(reset, 0x0, sizeof(*reset));
}
out:
if (reason) {
iot_sg_printf("%s fail reason %d\n", __FUNCTION__, reason);
}
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return;
}
uint32_t iot_sg_sta_ext_freeze_task_add(uint8_t *addr, uint8_t task_id,
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t reason = 0;
uint32_t ret = ERR_FAIL;
iot_pkt_t *task_pkt = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *task_info;
if (!cfg) {
reason = 1;
goto out;
}
task_pkt = iot_pkt_alloc(sizeof(*task_info), IOT_SMART_GRID_MID);
if (!task_pkt) {
reason = 2;
goto out;
}
if (iot_sg_sta_ext_freeze_task_cnt_check(addr, task_id)) {
reason = 3;
goto out;
}
task_info = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*task_info));
if (!iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, task_info)) {
if (iot_sg_sta_ext_freeze_task_same_check(task_info, cfg)) {
ret = ERR_OK;
goto out;
}
}
if (iot_sg_sta_flash_clct_task_add(addr, (uint8_t *)cfg,
sizeof(*cfg), IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) != ERR_OK) {
reason = 4;
goto out;
}
iot_sg_sta_ext_freeze_cur_task_reset(addr, task_id);
iot_sg_sta_ext_fj_rpt_del(addr, task_id);
iot_sg_ext_data_rpt_msg_merge_del(addr, task_id);
iot_sg_sta_ext_freeze_flash_cfg_valid_set(task_id, 1);
iot_sg_ext_freeze_exe_cnt_set(task_id, cfg->exe_cnt, 0, 1);
ret = ERR_OK;
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return ret;
}
static uint32_t iot_sg_sta_ext_freeze_task_del(uint8_t *addr,
uint8_t task_id)
{
uint8_t reason = 0;
uint32_t ret = ERR_FAIL;
if (!iot_sg_sta_ext_freeze_flash_cfg_valid_check(task_id, NULL)) {
reason = 1;
goto out;
}
ret = iot_sg_sta_flash_clct_task_del(addr, task_id, 1,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret != ERR_OK) {
reason = 2;
goto out;
}
iot_sg_sta_ext_freeze_cur_task_reset(addr, task_id);
iot_sg_sta_ext_fj_rpt_del(addr, task_id);
iot_sg_ext_data_rpt_msg_merge_del(addr, task_id);
iot_sg_ext_freeze_exe_cnt_del(task_id);
iot_sg_sta_ext_freeze_flash_cfg_valid_set(task_id, 0);
ret = ERR_OK;
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint32_t iot_sg_sta_ext_freeze_task_del_all(uint8_t *addr)
{
uint8_t i;
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;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_node_desc_t *node = iot_sg_sta_node_find_by_addr(addr);
if (!freeze_task || !node) {
goto out;
}
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (freeze_task->valid_id[i]) {
ret = iot_sg_sta_ext_freeze_task_del(addr,
freeze_task->valid_id[i]);
if (ret != ERR_OK) {
goto out;
}
}
}
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_sg_sta_ext_freeze_task_get(uint8_t *addr,
uint8_t task_id, iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint32_t ret = ERR_FAIL;
if (!cfg) {
goto out;
}
ret = iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg);
out:
return ret;
}
static void iot_sg_sta_ext_freeze_task_id_get(iot_sg_sta_ext_fj_task_id_t *task)
{
uint8_t i, m = 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_freeze_task_t *task_cfg = ext_info->freeze_task_info;
if (task_cfg) {
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (task_cfg->valid_id[i]) {
task->task_list[m] = task_cfg->valid_id[i];
m++;
}
}
task->task_cnt = m;
} else {
task->task_cnt = 0;
}
}
static iot_time_tm_t iot_sg_ext_get_next_data_freeze_ts(iot_time_tm_t *curr_tm,
iot_time_tm_t *node_tm, iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
int64_t interval;
iot_time_tm_t tm = { 0 };
proto_645_fj_task_cycle_t cycle = { 0 };
if (!cfg || !curr_tm || !node_tm) {
goto out;
}
cycle.value = cfg->value;
cycle.unit = cfg->unit;
interval = (int64_t)proto_645_fj_task_cycle_to_sec(&cycle);
tm = *curr_tm;
iot_sg_ext_set_integral_point(&tm, interval, 1);
if (tm.tm_year == node_tm->tm_year && tm.tm_mon == node_tm->tm_mon &&
tm.tm_mday == node_tm->tm_mday && tm.tm_hour == node_tm->tm_hour &&
tm.tm_min == node_tm->tm_min && tm.tm_sec == node_tm->tm_sec) {
iot_rtc_delta_add(1, &tm);
iot_sg_ext_set_integral_point(&tm, interval, 1);
}
if (cfg->delay) {
iot_rtc_delta_add(cfg->delay, &tm);
}
out:
return tm;
}
static void iot_sg_ext_data_freeze_cur_task_done(void)
{
uint8_t idx = 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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
if (!iot_sg_sta_ext_freeze_flash_cfg_valid_check(freeze_task->cur_task_id,
&idx)) {
return;
}
freeze_task->task_bm |= (1 << idx);
iot_sg_ext_data_freeze_cur_info_clear(freeze_task);
}
static uint8_t iot_sg_ext_data_freeze_task_id_get_by_func(uint8_t *addr,
uint8_t func)
{
uint8_t task_id = 0, idx = 0;
iot_pkt_t *task_pkt;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_drv_meter_fj_task_info_t *local_cfg;
task_pkt = iot_pkt_alloc(sizeof(*local_cfg), IOT_SMART_GRID_MID);
if (!task_pkt) {
goto out;
}
local_cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*local_cfg));
for (task_id = PROTO_FJ_FREEZE_TASK_ID_MIN;
task_id <= PROTO_FJ_FREEZE_TASK_ID_MAX;
task_id++) {
if (!iot_sg_sta_ext_freeze_flash_cfg_valid_check(task_id, &idx)) {
continue;
}
if (freeze_task->task_bm & (1 << idx)) {
continue;
}
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, local_cfg)
!= ERR_OK) {
continue;
}
if (func == IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_1) {
if (local_cfg->type == PROTO_645_FJ_TASK_TYPE_FREEZE
&& local_cfg->prio) {
goto out;
}
} else if (func == IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_0) {
if (local_cfg->type == PROTO_645_FJ_TASK_TYPE_FREEZE
&& !local_cfg->prio) {
goto out;
}
} else if (func == IOT_SG_STA_EXT_FREEZR_FUNC_RPT) {
if (local_cfg->type == PROTO_645_FJ_TASK_TYPE_INCON_RPT ||
local_cfg->type == PROTO_645_FJ_TASK_TYPE_CROSS_RPT ||
local_cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
goto out;
}
}
}
task_id = 0;
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return task_id;
}
static uint32_t iot_sg_ext_data_freeze_tm_check(uint8_t type)
{
uint8_t reason = 0;
uint32_t ret = ERR_OK;
if (iot_sg_sta_rtc_valid_check(0)) {
reason = 1;
ret = ERR_INVAL;
goto out;
}
if (type == PROTO_645_FJ_TASK_TYPE_FREEZE) {
if (iot_sg_sta_rtc_valid_check(1)) {
reason = 2;
ret = ERR_INVAL;
goto out;
}
}
out:
if (ret != ERR_OK) {
iot_sg_printf("%s fail %d type %lu\n", __FUNCTION__, reason, type);
}
return ret;
}
static uint32_t iot_sg_ext_data_freeze_tm_check_by_prio(uint8_t prio)
{
uint8_t reason = 0;
uint32_t ret = ERR_OK;
if (iot_sg_sta_rtc_valid_check(0)) {
reason = 1;
ret = ERR_INVAL;
goto out;
}
if (prio == IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_1 ||
prio == IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_0) {
if (iot_sg_sta_rtc_valid_check(1)) {
reason = 2;
ret = ERR_INVAL;
goto out;
}
}
out:
if (ret != ERR_OK) {
iot_sg_printf("%s fail %d prio %lu\n", __FUNCTION__, reason, prio);
}
return ret;
}
static uint32_t iot_sg_ext_data_freeze_cur_task_update(uint8_t *addr)
{
uint8_t func, task_id;
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;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
/* func execution priority:
* IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_1 > IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_0 >
* IOT_SG_STA_EXT_FREEZR_FUNC_RPT
*/
for (func = IOT_SG_STA_EXT_FREEZR_FUNC_PRIO_1;
func < IOT_SG_STA_EXT_FREEZR_FUNC_CNT; func++) {
if (iot_sg_ext_data_freeze_tm_check_by_prio(func) != ERR_OK) {
continue;
}
task_id = iot_sg_ext_data_freeze_task_id_get_by_func(addr, func);
if (task_id) {
freeze_task->cur_task_id = task_id;
ret = ERR_OK;
iot_sg_printf("%s to %lu\n", __FUNCTION__, task_id);
break;
}
}
return ret;
}
static uint32_t iot_sg_ext_cur_freeze_di_update(
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t di_cnt = 0;
uint32_t ret = ERR_OK;;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_rpt;
proto_645_fj_task_set_flw_rpt_hdr_t *flw_rpt;
proto_645_fj_task_set_cross_rpt_t *cross_rpt;
proto_645_fj_task_set_change_rpt_hdr_t *chg_rpt;
if (!cfg || freeze_task->task_end) {
ret = ERR_FAIL;
goto out;
}
freeze_task->cur_di_idx += freeze_task->cur_mr_di_cnt;
switch (cfg->type) {
case PROTO_645_FJ_TASK_TYPE_FREEZE:
{
freeze_hdr = (proto_645_fj_task_set_freeze_hdr_t *)cfg->desc;
if (freeze_task->cur_di_idx >= freeze_hdr->data_cnt) {
ret = ERR_FAIL;
goto out;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_rpt = (proto_645_fj_task_set_incon_rpt_hdr_t *)cfg->desc;
di_cnt = incon_rpt->di_cnt;
if (freeze_task->flag_rpt) {
/* freeze data report, meter read follow di */
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)
(incon_rpt->di + incon_rpt->di_cnt);
di_cnt += flw_rpt->follow_di_cnt;
}
if (freeze_task->cur_di_idx >= di_cnt) {
ret = ERR_FAIL;
goto out;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_rpt = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
di_cnt++;
if (freeze_task->flag_rpt) {
/* freeze data report, meter read follow di */
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)
(cross_rpt->value_list + cross_rpt->cnt * cross_rpt->value_len);
di_cnt += flw_rpt->follow_di_cnt;
}
if (freeze_task->cur_di_idx >= di_cnt) {
ret = ERR_FAIL;
goto out;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_rpt = (proto_645_fj_task_set_change_rpt_hdr_t*)cfg->desc;
di_cnt++;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)
(chg_rpt->value_list + chg_rpt->value_len);
di_cnt += flw_rpt->follow_di_cnt;
if (freeze_task->cur_di_idx >= di_cnt) {
ret = ERR_FAIL;
goto out;
}
break;
}
default:
ret = ERR_FAIL;
break;
}
out:
return ret;
}
static void iot_sg_ext_chg_to_data_freeze_ts(
iot_time_tm_t *node_tm, iot_sg_sta_drv_meter_fj_task_info_t *cfg,
uint8_t flag_last)
{
int64_t interval;
proto_645_fj_task_cycle_t cycle = { 0 };
cycle.value = cfg->value;
cycle.unit = cfg->unit;
interval = (int64_t)proto_645_fj_task_cycle_to_sec(&cycle);
if (flag_last) {
interval = 0 - interval;
}
iot_rtc_delta_add(interval, node_tm);
}
static void iot_sg_ext_data_freeze_save(uint8_t *addr, uint8_t task_id,
iot_time_tm_t *tm)
{
uint8_t valid_rpt_cnt = 1;
uint8_t merge_cnt, rpt_mode = PROTO_645_FJ_REPORT_MODE_698;
uint32_t ret, reason = 0;
uint16_t max_cnt = 0, index = 0, exe_cnt = 0, trigger_cnt = 0, unit_len = 0;
iot_pkt_t *pkt = NULL, *rpt_pkt = NULL, *task_pkt = NULL;
iot_time_tm_t cache_tm = { 0 }, node_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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_drv_meter_fj_task_unit_t *resp_data = NULL, *flash_data = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *cfg;
iot_sg_sta_ext_freeze_task_exe_cnt_t *last_data =
iot_sg_ext_freeze_last_data_get(task_id);
if (!freeze_task->resp_pkt || !addr || !tm) {
reason = 1;
goto out;
}
task_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!task_pkt) {
reason = 2;
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*cfg));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg) != ERR_OK) {
reason = 3;
goto out;
}
resp_data = (iot_sg_sta_drv_meter_fj_task_unit_t *)
iot_pkt_data(freeze_task->resp_pkt);
if (cfg->type != PROTO_645_FJ_TASK_TYPE_FREEZE &&
!freeze_task->first_rpt_task && !freeze_task->flag_rpt) {
ret = iot_sg_ext_freeze_exe_cnt_get(task_id, &exe_cnt, &trigger_cnt);
if(ret || 0 == exe_cnt) {
reason = 4;
goto out;
}
if (exe_cnt != (uint16_t)~0) {
exe_cnt--;
iot_sg_ext_freeze_exe_cnt_set(task_id, exe_cnt, trigger_cnt, 0);
}
goto out;
}
node_tm = *tm;
if (cfg->delay) {
iot_rtc_delta_add(0 - cfg->delay, &node_tm);
}
resp_data->uint_time.year = node_tm.tm_year - 2000;
resp_data->uint_time.month = node_tm.tm_mon;
resp_data->uint_time.day = node_tm.tm_mday;
resp_data->uint_time.hour = node_tm.tm_hour;
resp_data->uint_time.minute = node_tm.tm_min;
resp_data->uint_time.second = node_tm.tm_sec;
resp_data->rpt_cnt = 0;
max_cnt = iot_sg_sta_flash_ct_unit_cnt_get(addr, task_id);
if (!max_cnt) {
reason = 5;
goto out;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 6;
goto out;
}
flash_data =
(iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(pkt, unit_len);
if (cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
iot_sg_ext_chg_to_data_freeze_ts(&node_tm, cfg, 1);
}
ret = iot_sg_sta_flash_ct_unit_data_find_by_time(addr, &index, &node_tm,
(uint8_t *)flash_data, unit_len, task_id, 1,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret == ERR_OK) {
cache_tm.tm_year = (uint16_t)(flash_data->uint_time.year + 2000);
cache_tm.tm_mon = (uint8_t)flash_data->uint_time.month;
cache_tm.tm_mday = (uint8_t)flash_data->uint_time.day;
cache_tm.tm_hour = (uint8_t)flash_data->uint_time.hour;
cache_tm.tm_min = (uint8_t)flash_data->uint_time.minute;
cache_tm.tm_sec = flash_data->uint_time.second;
if (iot_rtc_delta_calc(&cache_tm, &node_tm) != 0) {
index++;
}
resp_data->save_cnt = flash_data->save_cnt;
resp_data->save_cnt++;
resp_data->storage_times = flash_data->storage_times;
resp_data->storage_times++;
if (resp_data->uint_time.year == flash_data->uint_time.year &&
resp_data->uint_time.month == flash_data->uint_time.month &&
resp_data->uint_time.day == flash_data->uint_time.day) {
resp_data->rpt_cnt = flash_data->rpt_cnt;
}
} else {
if ((cfg->type == PROTO_645_FJ_TASK_TYPE_INCON_RPT
|| cfg->type == PROTO_645_FJ_TASK_TYPE_CROSS_RPT)
&& freeze_task->first_rpt_task) {
resp_data->save_cnt = 0;
resp_data->storage_times = 0;
/* for current report state count */
valid_rpt_cnt = 0;
} else {
resp_data->save_cnt = 1;
resp_data->storage_times = 1;
}
}
ret = iot_sg_ext_freeze_exe_cnt_get(task_id, &exe_cnt, &trigger_cnt);
if(ret || 0 == exe_cnt) {
reason = 7;
goto out;
}
if (exe_cnt != (uint16_t)~0) {
exe_cnt--;
}
resp_data->exe_cnt_remain = exe_cnt;
iot_sg_ext_freeze_exe_cnt_set(task_id, exe_cnt, resp_data->save_cnt, 0);
if (index >= max_cnt) {
index = 0;
}
if (cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
if (!last_data || !last_data->valid_len || !last_data->data_cnt) {
reason = 8;
goto out;
}
os_mem_set(flash_data, 0, sizeof(*flash_data));
flash_data->uint_time.year = node_tm.tm_year - 2000;
flash_data->uint_time.month = node_tm.tm_mon;
flash_data->uint_time.day = node_tm.tm_mday;
flash_data->uint_time.hour = node_tm.tm_hour;
flash_data->uint_time.minute = node_tm.tm_min;
flash_data->uint_time.second = node_tm.tm_sec;
flash_data->save_cnt = resp_data->save_cnt;
flash_data->storage_times = resp_data->storage_times;
flash_data->exe_cnt_remain = resp_data->exe_cnt_remain;
flash_data->resp_data_cnt = last_data->data_cnt;
flash_data->valid_len = last_data->valid_len;
os_mem_cpy(flash_data->uint_data, last_data->last_data,
flash_data->valid_len);
iot_sg_ext_chg_to_data_freeze_ts(&node_tm, cfg, 0);
}
if (freeze_task->flag_rpt && cfg->flag_rpt) {
if (!freeze_task->comm_cfg.report_max_cnt) {
resp_data->rpt_cnt = 0;
goto save;
}
if (freeze_task->comm_cfg.report_max_cnt != 0xff &&
resp_data->rpt_cnt >= freeze_task->comm_cfg.report_max_cnt) {
goto save;
}
if (iot_sg_sta_ext_fj_task_group_get(task_id)
== PROTO_645_FJ_TASK_GROUP_645) {
rpt_mode = freeze_task->comm_cfg.rpt_mode;
}
rpt_pkt = iot_sg_sta_ext_fj_rpt_msg_build(resp_data, flash_data,
cfg, task_id, rpt_mode);
merge_cnt = iot_sg_ext_data_rpt_msg_merge_cnt_get(
&freeze_task->comm_cfg, task_id);
if (merge_cnt) {
rpt_pkt = iot_sg_ext_data_rpt_msg_merge(addr, task_id, &merge_cnt,
rpt_mode, cfg->type, rpt_pkt);
} else {
merge_cnt = 1;
}
if (rpt_pkt) {
resp_data->rpt_cnt++;
iot_sg_sta_ext_fj_rpt_add(rpt_pkt, addr, task_id, cfg,
rpt_mode, merge_cnt);
}
iot_sg_ext_data_rpt_task_finish_handle(addr, task_id, cfg);
}
save:
if (cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
flash_data->rpt_cnt = resp_data->rpt_cnt;
ret = iot_sg_sta_flash_ct_unit_data_save(
addr, index, (uint8_t *)flash_data, unit_len, task_id);
if (ret != ERR_OK) {
reason = 9;
goto out;
}
index++;
if (index >= max_cnt) {
index = 0;
}
}
ret = iot_sg_sta_flash_ct_unit_data_save(
addr, index, (uint8_t *)resp_data, unit_len, task_id);
if (ret != ERR_OK) {
reason = 10;
goto out;
}
if (cfg->flag_rpt && valid_rpt_cnt) {
iot_sg_sta_ext_fj_rpt_count(task_id, 1, valid_rpt_cnt);
}
iot_sg_sta_flash_ct_unit_data_check(addr, index, &node_tm,
task_id, IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
iot_sg_printf("%s addr %02x:%02x:%02x:%02x:%02x:%02x task id %lu idx %lu\n",
__FUNCTION__, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
task_id, index);
iot_sg_printf("%s time %lu-%lu-%lu %lu:%lu:%lu rpt_cnt %lu\n", __FUNCTION__,
node_tm.tm_year, node_tm.tm_mon, node_tm.tm_mday, node_tm.tm_hour,
node_tm.tm_min, node_tm.tm_sec, resp_data->rpt_cnt);
out:
if (last_data && resp_data) {
last_data->data_cnt = resp_data->resp_data_cnt;
last_data->valid_len = resp_data->valid_len;
os_mem_cpy(last_data->last_data, resp_data->uint_data,
resp_data->valid_len);
}
if (pkt) {
iot_pkt_free(pkt);
}
if (task_pkt) {
iot_pkt_free(task_pkt);
}
if (reason) {
iot_sg_printf("%s err %d\n", __FUNCTION__, reason);
}
return;
}
static void iot_sg_ext_freeze_tail_time_fill(
proto_645_fj_freeze_data_desc_tail_t *tail, iot_time_tm_t *tm)
{
iot_time_tm_t new_tm = { 0 };
int64_t delta = 0;
if (!tail || !tm) {
return;
}
if (tail->ts.year == 0x99) {
new_tm.tm_year = tm->tm_year;
} else {
new_tm.tm_year = iot_bcd_to_byte(tail->ts.year) + 2000;
}
if (tail->ts.month == 0x99) {
new_tm.tm_mon = tm->tm_mon;
} else {
new_tm.tm_mon = iot_bcd_to_byte(tail->ts.month);
}
if (tail->ts.day == 0x99) {
new_tm.tm_mday = tm->tm_mday;
} else {
new_tm.tm_mday = iot_bcd_to_byte(tail->ts.day);
}
if (tail->ts.hour == 0x99) {
new_tm.tm_hour = tm->tm_hour;
} else {
new_tm.tm_hour = iot_bcd_to_byte(tail->ts.hour);
}
if (tail->ts.minute == 0x99) {
new_tm.tm_min = tm->tm_min;
} else {
new_tm.tm_min = iot_bcd_to_byte(tail->ts.minute);
}
switch (tail->ts_desc.unit) {
case PROTO_645_FJ_TASK_CYCLE_UNIT_TYPE_DAY:
{
delta = tail->ts_desc.value * 60 * 60 * 24;
break;
}
case PROTO_645_FJ_TASK_CYCLE_UNIT_TYPE_HOUR:
{
delta = tail->ts_desc.value * 60 * 60;
break;
}
case PROTO_645_FJ_TASK_CYCLE_UNIT_TYPE_MIN:
{
delta = tail->ts_desc.value * 60;
break;
}
case PROTO_645_FJ_TASK_CYCLE_UNIT_TYPE_SEC:
{
delta = tail->ts_desc.value;
break;
}
default:
iot_sg_printf("%s delta invalid\n");
break;
}
if (!tail->ts_desc.flag) {
iot_rtc_delta_add(delta, &new_tm);
} else {
iot_rtc_delta_add(0 - delta, &new_tm);
}
tail->ts.year = iot_byte_to_bcd((uint8_t)(new_tm.tm_year - 2000));
tail->ts.month = iot_byte_to_bcd(new_tm.tm_mon);
tail->ts.day = iot_byte_to_bcd(new_tm.tm_mday);
tail->ts.hour = iot_byte_to_bcd(new_tm.tm_hour);
tail->ts.minute = iot_byte_to_bcd(new_tm.tm_min);
}
static uint32_t iot_sg_ext_freeze_data_desc_offset_get(uint8_t *desc_offser,
uint8_t desc_len, uint8_t *data, uint8_t idx)
{
uint32_t ret = ERR_OK;
uint8_t i, offset_len = 0;
proto_645_fj_freeze_data_desc_hdr_t *freeze_des;
for (i = 0; i < idx; i++) {
if (offset_len >= desc_len) {
ret = ERR_FAIL;
goto out;
}
freeze_des = (proto_645_fj_freeze_data_desc_hdr_t *)(data + offset_len);
offset_len += sizeof(*freeze_des) + freeze_des->data_len;
}
*desc_offser = offset_len;
out:
return ret;
}
static uint8_t iot_sg_sta_ext_fj_task_freeze_di_list_get(uint8_t cur_idx,
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr,
iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint32_t *di_list, uint8_t max_cnt)
{
uint8_t di_cnt = 0, offset_len = 0, i;
proto_645_fj_freeze_data_desc_hdr_t *freeze_des;
if (!freeze_hdr || !cfg || !di_list) {
goto out;
}
for (i = cur_idx; i < freeze_hdr->data_cnt; i++) {
if (iot_sg_ext_freeze_data_desc_offset_get(&offset_len, cfg->desc_len,
freeze_hdr->data_desc, i) != ERR_OK) {
goto out;
}
freeze_des = (proto_645_fj_freeze_data_desc_hdr_t *)(
freeze_hdr->data_desc + offset_len);
if (freeze_des->format_type != PROTO_645_FJ_FREEZE_DATA_FORMAT_NO_TS ||
freeze_des->data_len != PROTO_645_2007_DI_LEN) {
goto out;
}
di_list[di_cnt] = proto_645_2007_byte_to_di(freeze_des->data);
di_cnt++;
if (di_cnt >= max_cnt) {
goto out;
}
}
out:
return di_cnt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_task_freeze_muilt_msg_build(uint8_t *addr,
uint8_t cur_idx, proto_645_fj_task_set_freeze_hdr_t *freeze_hdr,
iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint8_t *cur_mr_di_cnt)
{
uint8_t di_list_cnt, di_list_pkt_len;
uint32_t *di_list = NULL;
iot_pkt_t *di_list_pkt = NULL, *pkt = NULL;
di_list_pkt_len = PROTO_645_FJ_METER_MULTI_DI_CNT_MAX *
PROTO_645_2007_DI_LEN;
di_list_pkt = iot_pkt_alloc(di_list_pkt_len, IOT_SMART_GRID_MID);
if (!di_list_pkt) {
goto out;
}
di_list = (uint32_t *)iot_pkt_put(di_list_pkt,
di_list_pkt_len);
di_list_cnt = iot_sg_sta_ext_fj_task_freeze_di_list_get(cur_idx, freeze_hdr,
cfg, di_list, PROTO_645_FJ_METER_MULTI_DI_CNT_MAX);
if (di_list_cnt > 1) {
pkt = proto_645_fj_build_muilt_mr_msg(addr, di_list,
di_list_cnt);
if (pkt) {
*cur_mr_di_cnt = di_list_cnt;
}
}
out:
if (di_list_pkt) {
iot_pkt_free(di_list_pkt);
}
return pkt;
}
static uint32_t iot_sg_sta_ext_freeze_task_comm_cfg_get(
iot_sg_sta_ext_freeze_task_comm_cfg_t *cfg_comm)
{
uint8_t i;
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;
iot_sg_sta_ext_freeze_task_t *task_info = ext_info->freeze_task_info;
if (task_info) {
cfg_comm->report_max_cnt = task_info->comm_cfg.report_max_cnt;
cfg_comm->unit_max_len = task_info->comm_cfg.unit_max_len;
cfg_comm->random_rpt_time = task_info->comm_cfg.random_rpt_time;
cfg_comm->retry_freeze = task_info->comm_cfg.retry_freeze;
cfg_comm->retry_nonfreeze = task_info->comm_cfg.retry_nonfreeze;
cfg_comm->mult_data_item = task_info->comm_cfg.mult_data_item;
cfg_comm->rpt_mode = task_info->comm_cfg.rpt_mode;
cfg_comm->cnt = task_info->comm_cfg.cnt;
for (i = 0; i < cfg_comm->cnt; i++) {
cfg_comm->task_rpt[i].id = task_info->comm_cfg.task_rpt[i].id;
cfg_comm->task_rpt[i].cnt = task_info->comm_cfg.task_rpt[i].cnt;
}
ret = ERR_OK;
}
return ret;
}
static iot_pkt_t * iot_sg_ext_69845_mr_msg_build(uint8_t *addr,
uint32_t *oad_list, uint8_t oad_cnt)
{
uint32_t get_list_req_size, oad;
uint8_t i, oad_idx = 0, attribute;
iot_pkt_t *pkt = NULL, *get_list_req = NULL;
proto_69845_app_get_list_req_info_t *req = NULL;
server_addr_info_t server = {0};
get_list_req_size = sizeof(proto_69845_app_oad_t) * oad_cnt + sizeof(*req);
get_list_req = iot_pkt_alloc(get_list_req_size, IOT_SMART_GRID_MID);
if (!get_list_req) {
goto out;
}
req = (proto_69845_app_get_list_req_info_t *)iot_pkt_put(get_list_req,
get_list_req_size);
req->type = PROTO_69845_APP_GET_NORMALLIST;
req->piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
req->piid.sn = iot_sg_sta_ext_get_69845_apdu_sn();
/* fill di from di_buff */
for (i = 0; i < oad_cnt; i++) {
os_mem_cpy(&oad, (oad_list + i), sizeof(oad));
iot_data_reverse((uint8_t *)&oad, sizeof(proto_69845_app_oad_t));
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++;
}
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 iot_pkt_t *iot_sg_ext_meter_freeze_msg_build_698(uint8_t *addr,
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t idx, *data, reason = 0;
uint8_t di_list_cnt = 0, di_list_pkt_len;
uint32_t *di_list = NULL;
iot_pkt_t *pkt = NULL, *pkt_tmp = NULL, *di_list_pkt = 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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_rpt;
proto_645_fj_task_set_flw_rpt_hdr_t *flw_rpt;
proto_645_fj_task_set_cross_rpt_t *cross_rpt;
proto_645_fj_task_set_change_rpt_hdr_t *chg_rpt;
if (!addr || !cfg) {
reason = 1;
goto out;
}
idx = freeze_task->cur_di_idx;
switch (cfg->type) {
case PROTO_645_FJ_TASK_TYPE_FREEZE:
{
freeze_hdr = (proto_645_fj_task_set_freeze_hdr_t *)cfg->desc;
if (idx >= freeze_hdr->data_cnt) {
reason = 2;
goto out;
}
di_list_pkt_len = PROTO_645_FJ_METER_MULTI_DI_CNT_MAX *
PROTO_645_2007_DI_LEN;
di_list_pkt = iot_pkt_alloc(di_list_pkt_len, IOT_SMART_GRID_MID);
if (!di_list_pkt) {
reason = 3;
goto out;
}
di_list = (uint32_t *)iot_pkt_put(di_list_pkt, di_list_pkt_len);
di_list_cnt = iot_sg_sta_ext_fj_task_freeze_di_list_get(idx,
freeze_hdr, cfg, di_list, PROTO_645_FJ_METER_MULTI_DI_CNT_MAX);
break;
}
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_rpt = (proto_645_fj_task_set_incon_rpt_hdr_t *)cfg->desc;
if (idx < incon_rpt->di_cnt) {
di_list_cnt = incon_rpt->di_cnt - idx;
di_list = &incon_rpt->di[idx];
} else {
/* freeze data report, meter read follow di */
idx -= incon_rpt->di_cnt;
data = (uint8_t *)incon_rpt->di +
incon_rpt->di_cnt * PROTO_645_2007_DI_LEN;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
if (idx < flw_rpt->follow_di_cnt) {
di_list_cnt = flw_rpt->follow_di_cnt - idx;
di_list = &flw_rpt->di[idx];
} else {
reason = 4;
goto out;
}
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_rpt = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
if (idx < PROTO_645_FJ_CROSS_RPT_CMP_DI_CNT) {
di_list = &cross_rpt->di;
di_list_cnt = 1;
} else {
/* freeze data report, meter read follow di */
idx -= PROTO_645_FJ_CROSS_RPT_CMP_DI_CNT;
data = cross_rpt->value_list + cross_rpt->cnt * cross_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
if (idx < flw_rpt->follow_di_cnt) {
di_list_cnt = flw_rpt->follow_di_cnt - idx;
di_list = &flw_rpt->di[idx];
} else {
reason = 5;
goto out;
}
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_rpt = (proto_645_fj_task_set_change_rpt_hdr_t *)cfg->desc;
if (idx < PROTO_645_FJ_CHANGE_RPT_CMP_DI_CNT) {
di_list = &chg_rpt->di;
di_list_cnt = 1;
} else {
/* meter read follow di */
idx -= PROTO_645_FJ_CHANGE_RPT_CMP_DI_CNT;
data = chg_rpt->value_list + chg_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
if (idx < flw_rpt->follow_di_cnt) {
di_list_cnt = flw_rpt->follow_di_cnt - idx;
di_list = &flw_rpt->di[idx];
} else {
reason = 6;
goto out;
}
}
break;
}
default:
break;
}
pkt = iot_sg_ext_69845_mr_msg_build(addr, di_list, di_list_cnt);
freeze_task->cur_mr_di_cnt = di_list_cnt;
out:
if (pkt_tmp) {
iot_pkt_free(pkt_tmp);
}
if (di_list_pkt) {
iot_pkt_free(di_list_pkt);
}
if (reason) {
iot_sg_printf("%s reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_ext_meter_freeze_msg_build_645(uint8_t *addr,
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t idx, offset_len = 0, *data_tmp,*data, data_len, reason = 0;
uint8_t di_list_cnt = 0, mult_data_item;
uint32_t di = PROTO_645_INVALID_DI, delta = 0, *di_list = NULL;
iot_pkt_t *pkt = NULL, *pkt_tmp = NULL;
iot_time_tm_t tm = { 0 };
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_ext_info_t *ext_info = &sta_glb->ext_info;
iot_sg_sta_ext_freeze_task_t *freeze_task = ext_info->freeze_task_info;
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr;
proto_645_fj_freeze_data_desc_hdr_t *freeze_des;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_rpt;
proto_645_fj_task_set_flw_rpt_hdr_t *flw_rpt;
proto_645_fj_task_set_cross_rpt_t *cross_rpt;
proto_645_fj_task_set_change_rpt_hdr_t *chg_rpt;
proto_645_fj_freeze_data_desc_tail_t *tail;
proto_645_fj_task_time_domain_t *time_domain;
if (!addr || !cfg) {
reason = 1;
goto out;
}
if (iot_sg_ext_data_freeze_tm_check(cfg->type) != ERR_OK) {
reason = 2;
goto out;
}
if (iot_mac_addr_valid(freeze_task->comm_cfg.mult_di_addr)) {
mult_data_item = freeze_task->comm_cfg.mult_data_item;
} else {
mult_data_item = PROTO_645_FJ_METET_MULT_DATA_ITEM_DEF;
}
iot_sg_sta_rtc_get(&tm, 0);
idx = freeze_task->cur_di_idx;
switch (cfg->type) {
case PROTO_645_FJ_TASK_TYPE_FREEZE:
{
freeze_hdr = (proto_645_fj_task_set_freeze_hdr_t *)cfg->desc;
if (idx >= freeze_hdr->data_cnt) {
reason = 3;
goto out;
}
if (iot_sg_ext_freeze_data_desc_offset_get(&offset_len, cfg->desc_len,
freeze_hdr->data_desc, idx)) {
reason = 4;
goto out;
}
freeze_des = (proto_645_fj_freeze_data_desc_hdr_t *)(
freeze_hdr->data_desc + offset_len);
if (!freeze_des) {
reason = 5;
goto out;
}
di = proto_645_2007_byte_to_di(freeze_des->data);
data = freeze_des->data + PROTO_645_2007_DI_LEN;
data_len = freeze_des->data_len - PROTO_645_2007_DI_LEN;
if (freeze_des->format_type == PROTO_645_FJ_FREEZE_DATA_FORMAT_WITH_TS
|| freeze_des->format_type ==
PROTO_645_FJ_FREEZE_DATA_FORMAT_WITH_TSR) {
pkt_tmp = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
if (!pkt_tmp) {
reason = 6;
goto out;
}
data_tmp = iot_pkt_put(pkt_tmp, data_len);
os_mem_cpy(data_tmp, data, data_len);
if (data_len < sizeof(*tail)) {
reason = 7;
goto out;
}
if (freeze_des->format_type ==
PROTO_645_FJ_FREEZE_DATA_FORMAT_WITH_TSR) {
if (data_len < (sizeof(*tail) + sizeof(*time_domain))) {
reason = 8;
goto out;
}
time_domain = (proto_645_fj_task_time_domain_t*)
(data_tmp + (data_len - sizeof(*time_domain)));
data_len -= sizeof(*time_domain);
if (proto_645_fj_task_time_domain_to_sec(time_domain,
&delta) == ERR_OK) {
if (delta) {
iot_sg_ext_set_integral_point(&tm, (int64_t)delta, 0);
}
} else {
reason = 9;
goto out;
}
}
tail = (proto_645_fj_freeze_data_desc_tail_t *)
(data_tmp + (data_len - sizeof(*tail)));
/* fill current time to msg */
iot_sg_ext_freeze_tail_time_fill(tail, &tm);
pkt = proto_645_fj_build_mr_msg(addr, data_tmp, data_len -
sizeof(tail->ts_desc), di, PROTO_645_2007_FN_READ_DATA);
freeze_task->cur_mr_di_cnt = 1;
} else {
if (mult_data_item) {
pkt = iot_sg_sta_ext_fj_task_freeze_muilt_msg_build(addr,
idx, freeze_hdr, cfg, &freeze_task->cur_mr_di_cnt);
if (pkt) {
goto out;
}
/* muilt di msg pkt is NULL go to build single di msg */
}
pkt = proto_645_fj_build_mr_msg(addr, data, data_len, di,
PROTO_645_2007_FN_READ_DATA);
freeze_task->cur_mr_di_cnt = 1;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_rpt = (proto_645_fj_task_set_incon_rpt_hdr_t *)cfg->desc;
if (idx < incon_rpt->di_cnt) {
di_list_cnt = incon_rpt->di_cnt - idx;
if (mult_data_item && di_list_cnt > 1) {
di_list = &incon_rpt->di[idx];
} else {
di = proto_645_2007_byte_to_di((uint8_t *)&incon_rpt->di[idx]);
}
} else {
/* freeze data report, meter read follow di */
idx -= incon_rpt->di_cnt;
data = (uint8_t *)incon_rpt->di +
incon_rpt->di_cnt * PROTO_645_2007_DI_LEN;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
if (idx < flw_rpt->follow_di_cnt) {
di_list_cnt = flw_rpt->follow_di_cnt - idx;
if (mult_data_item && di_list_cnt > 1) {
di_list = &flw_rpt->di[idx];
} else {
di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
}
} else {
reason = 10;
goto out;
}
}
if (di_list) {
if (di_list_cnt > PROTO_645_FJ_METER_MULTI_DI_CNT_MAX) {
di_list_cnt = PROTO_645_FJ_METER_MULTI_DI_CNT_MAX;
}
pkt = proto_645_fj_build_muilt_mr_msg(addr, di_list, di_list_cnt);
freeze_task->cur_mr_di_cnt = di_list_cnt;
} else {
pkt = proto_645_fj_build_mr_msg(addr, NULL, 0, di,
PROTO_645_2007_FN_READ_DATA);
freeze_task->cur_mr_di_cnt = 1;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_rpt = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
if (idx < PROTO_645_FJ_CROSS_RPT_CMP_DI_CNT) {
di = proto_645_2007_byte_to_di((uint8_t *)&cross_rpt->di);
} else {
/* freeze data report, meter read follow di */
idx -= PROTO_645_FJ_CROSS_RPT_CMP_DI_CNT;
data = cross_rpt->value_list + cross_rpt->cnt * cross_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
if (idx < flw_rpt->follow_di_cnt) {
di_list_cnt = flw_rpt->follow_di_cnt - idx;
if (mult_data_item && di_list_cnt > 1) {
di_list = &flw_rpt->di[idx];
} else {
di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
}
} else {
reason = 11;
goto out;
}
}
if (di_list) {
if (di_list_cnt > PROTO_645_FJ_METER_MULTI_DI_CNT_MAX) {
di_list_cnt = PROTO_645_FJ_METER_MULTI_DI_CNT_MAX;
}
pkt = proto_645_fj_build_muilt_mr_msg(addr, di_list, di_list_cnt);
freeze_task->cur_mr_di_cnt = di_list_cnt;
} else {
pkt = proto_645_fj_build_mr_msg(addr, NULL, 0, di,
PROTO_645_2007_FN_READ_DATA);
freeze_task->cur_mr_di_cnt = 1;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_rpt = (proto_645_fj_task_set_change_rpt_hdr_t *)cfg->desc;
if (idx < PROTO_645_FJ_CHANGE_RPT_CMP_DI_CNT) {
di = proto_645_2007_byte_to_di((uint8_t *)&chg_rpt->di);
} else {
/* meter read follow di */
idx -= PROTO_645_FJ_CHANGE_RPT_CMP_DI_CNT;
data = chg_rpt->value_list + chg_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
if (idx < flw_rpt->follow_di_cnt) {
di_list_cnt = flw_rpt->follow_di_cnt - idx;
if (mult_data_item && di_list_cnt > 1) {
di_list = &flw_rpt->di[idx];
} else {
di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
}
} else {
reason = 12;
goto out;
}
}
if (di_list) {
if (di_list_cnt > PROTO_645_FJ_METER_MULTI_DI_CNT_MAX) {
di_list_cnt = PROTO_645_FJ_METER_MULTI_DI_CNT_MAX;
}
pkt = proto_645_fj_build_muilt_mr_msg(addr, di_list, di_list_cnt);
freeze_task->cur_mr_di_cnt = di_list_cnt;
} else {
pkt = proto_645_fj_build_mr_msg(addr, NULL, 0, di,
PROTO_645_2007_FN_READ_DATA);
freeze_task->cur_mr_di_cnt = 1;
}
break;
}
default:
break;
}
out:
if (pkt_tmp) {
iot_pkt_free(pkt_tmp);
}
if (reason) {
iot_sg_printf("%s reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static void iot_sg_ext_day_freeze_task_last_check(uint8_t *addr,
iot_time_tm_t *node_tm, iot_time_tm_t *cur_tm,
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint16_t flash_idx = 0, unit_len = 0;
uint32_t ret;
int64_t delta;
iot_time_tm_t last_tm;
iot_pkt_t *pkt = NULL;
iot_sg_sta_drv_meter_fj_task_unit_t *task_unit;
if (!addr || !node_tm || !cur_tm || !cfg) {
goto out;
}
if (cfg->type != PROTO_645_FJ_TASK_TYPE_FREEZE ||
cfg->unit != PROTO_645_FJ_TASK_CYCLE_UNIT_TYPE_DAY) {
goto out;
}
delta = iot_rtc_delta_calc(cur_tm, node_tm);
if (delta <= IOT_SG_STA_EXT_FREEZE_LAST_DF_MIN_TIME) {
/* next freeze data will be collected soon,
* do not collect last freeze data.
*/
goto out;
}
last_tm = *cur_tm;
last_tm.tm_hour = 0;
last_tm.tm_min = 0;
last_tm.tm_sec = 0;
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
task_unit = (iot_sg_sta_drv_meter_fj_task_unit_t *)
iot_pkt_put(pkt, unit_len);
ret = iot_sg_sta_flash_ct_unit_data_find_by_time(addr, &flash_idx,
&last_tm, (uint8_t *)task_unit, unit_len, cfg->id, 0,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret != ERR_OK) {
*node_tm = last_tm;
if (cfg->delay) {
iot_rtc_delta_add(cfg->delay, node_tm);
}
goto out;
}
if (last_tm.tm_year != (uint16_t)task_unit->uint_time.year + 2000 ||
last_tm.tm_mon != (uint8_t)task_unit->uint_time.month ||
last_tm.tm_mday != (uint8_t)task_unit->uint_time.day) {
*node_tm = last_tm;
if (cfg->delay) {
iot_rtc_delta_add(cfg->delay, node_tm);
}
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
return;
}
static uint8_t iot_sg_ext_data_freeze_task_trigger_cnt_check(
uint8_t task_type, uint8_t *desc, uint16_t trigger_cnt)
{
uint8_t done = 0;
uint16_t max_cnt;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_hdr;
proto_645_fj_task_set_cross_rpt_t *cross_hdr;
proto_645_fj_task_set_change_rpt_hdr_t *chg_hdr;
switch (task_type) {
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_hdr = (proto_645_fj_task_set_incon_rpt_hdr_t*)desc;
max_cnt = incon_hdr->triger_cnt;
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_hdr = (proto_645_fj_task_set_cross_rpt_t*)desc;
max_cnt = cross_hdr->triger_cnt;
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_hdr = (proto_645_fj_task_set_change_rpt_hdr_t*)desc;
max_cnt = chg_hdr->triger_cnt;
break;
}
default:
goto out;
}
if (trigger_cnt >= max_cnt) {
done = 1;
}
out:
return done;
}
static uint8_t iot_sg_ext_task_is_runing(uint8_t task_id,
iot_sg_sta_drv_meter_fj_task_info_t *local_cfg)
{
uint8_t ret = 0;
uint16_t exe_cnt = 0, trigger_cnt = 0;
if (iot_sg_ext_freeze_exe_cnt_get(task_id, &exe_cnt, &trigger_cnt)) {
goto out;
}
if (exe_cnt == 0 || iot_sg_ext_data_freeze_task_trigger_cnt_check(
local_cfg->type, local_cfg->desc, trigger_cnt)) {
goto out;
}
ret = 1;
out:
return ret;
}
static uint32_t iot_sg_sta_ext_fj_task_cfg_desc_reverse(uint8_t task_type,
uint8_t *desc, uint8_t desc_len, uint8_t desc_is_big_endian,
uint8_t group_type)
{
uint8_t other_len;
uint8_t reason = 0, *data, len, i, j, di_cnt, des_len, *des_data;
uint32_t ret = ERR_FAIL, di;
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr;
proto_645_fj_freeze_data_desc_hdr_t *freeze_des_hdr;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_hdr;
proto_645_fj_task_set_flw_rpt_hdr_t *flw_tail;
proto_645_fj_task_set_cross_rpt_t *cross_hdr;
proto_645_fj_task_set_change_rpt_hdr_t *change_hdr;
switch (task_type) {
case PROTO_645_FJ_TASK_TYPE_FREEZE:
{
if (desc_len < sizeof(*freeze_hdr)) {
reason = 1;
goto out;
}
freeze_hdr = (proto_645_fj_task_set_freeze_hdr_t*)desc;
if ((freeze_hdr->data_cnt > PROTO_645_FJ_TASK_DESC_FREEZE_MAX_CNT)
|| !freeze_hdr->data_cnt) {
reason = 2;
goto out;
}
data = freeze_hdr->data_desc;
len = desc_len - sizeof(*freeze_hdr);
for (i = 0; i < freeze_hdr->data_cnt; i++) {
if (len < sizeof(*freeze_des_hdr)) {
reason = 3;
goto out;
}
freeze_des_hdr = (proto_645_fj_freeze_data_desc_hdr_t*)data;
len -= sizeof(*freeze_des_hdr);
data += sizeof(*freeze_des_hdr);
if (len < freeze_des_hdr->data_len) {
reason = 4;
goto out;
}
len -= freeze_des_hdr->data_len;
data += freeze_des_hdr->data_len;
des_len = freeze_des_hdr->data_len;
des_data = freeze_des_hdr->data;
switch (freeze_des_hdr->format_type) {
case PROTO_645_FJ_FREEZE_DATA_FORMAT_NO_TS:
{
if ((des_len < PROTO_645_2007_DI_LEN) ||
(des_len > PROTO_645_FJ_TASK_DESC_FREEZE_MAX_LEN)) {
reason = 5;
goto out;
}
di = iot_bytes_to_uint32(des_data, desc_is_big_endian);
iot_data_reverse(des_data, PROTO_645_2007_DI_LEN);
des_len -= PROTO_645_2007_DI_LEN;
des_data += PROTO_645_2007_DI_LEN;
if ((di & 0xffffff00) == PROTO_645_FJ_METER_MULTI_DI_READ) {
di_cnt = (uint8_t)(di & 0x000000ff);
if (!di_cnt) {
break;
}
if (di_cnt * PROTO_645_2007_DI_LEN + di_cnt - 1 > des_len) {
reason = 6;
goto out;
}
for (j = 0; j < di_cnt; j++) {
iot_data_reverse(des_data, PROTO_645_2007_DI_LEN);
des_data += PROTO_645_2007_DI_LEN;
if (j < di_cnt - 1) {
des_data++;
}
}
} else {
if (des_len > 1) {
iot_data_reverse(des_data, des_len);
}
}
break;
}
case PROTO_645_FJ_FREEZE_DATA_FORMAT_WITH_TS:
{
if (des_len < (PROTO_645_2007_DI_LEN +
sizeof(proto_645_fj_freeze_data_desc_tail_t))
|| (des_len > PROTO_645_FJ_TASK_DESC_FREEZE_MAX_LEN)) {
reason = 7;
goto out;
}
iot_data_reverse(des_data, PROTO_645_2007_DI_LEN);
des_len -= PROTO_645_2007_DI_LEN;
des_data += PROTO_645_2007_DI_LEN;
other_len = des_len -
sizeof(proto_645_fj_freeze_data_desc_tail_t);
if (other_len > 1) {
iot_data_reverse(des_data, other_len);
}
des_data += other_len;
iot_data_reverse(des_data, sizeof(proto_645_fj_time_ymdhm_t));
des_data += sizeof(proto_645_fj_time_ymdhm_t);
iot_data_reverse(des_data, sizeof(proto_645_fj_task_cycle_t));
break;
}
case PROTO_645_FJ_FREEZE_DATA_FORMAT_WITH_TSR:
{
if ((des_len < (PROTO_645_2007_DI_LEN +
sizeof(proto_645_fj_freeze_data_desc_tail_t) +
sizeof(proto_645_fj_task_time_domain_t)))
|| (des_len > PROTO_645_FJ_TASK_DESC_FREEZE_MAX_LEN)) {
reason = 8;
goto out;
}
iot_data_reverse(des_data, PROTO_645_2007_DI_LEN);
des_len -= PROTO_645_2007_DI_LEN;
des_data += PROTO_645_2007_DI_LEN;
other_len = des_len -
(sizeof(proto_645_fj_freeze_data_desc_tail_t) +
sizeof(proto_645_fj_task_time_domain_t));
if (other_len > 1) {
iot_data_reverse(des_data, other_len);
}
des_data += other_len;
iot_data_reverse(des_data, sizeof(proto_645_fj_time_ymdhm_t));
des_data += sizeof(proto_645_fj_time_ymdhm_t);
iot_data_reverse(des_data, sizeof(proto_645_fj_task_cycle_t));
break;
}
default:
reason = 9;
goto out;
}
}
ret = ERR_OK;
break;
}
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
if (desc_len < sizeof(*incon_hdr)) {
reason = 10;
goto out;
}
incon_hdr = (proto_645_fj_task_set_incon_rpt_hdr_t*)desc;
iot_data_reverse((uint8_t *)&incon_hdr->triger_cnt,
sizeof(incon_hdr->triger_cnt));
if (!incon_hdr->di_cnt) {
reason = 11;
goto out;
}
data = (uint8_t*)incon_hdr->di;
len = desc_len - sizeof(*incon_hdr);
if (len < (incon_hdr->di_cnt * PROTO_645_2007_DI_LEN)) {
reason = 12;
goto out;
}
for (j = 0; j < incon_hdr->di_cnt; j++) {
iot_data_reverse((uint8_t *)&incon_hdr->di[j],
PROTO_645_2007_DI_LEN);
}
len = len - incon_hdr->di_cnt * PROTO_645_2007_DI_LEN;
data = data + incon_hdr->di_cnt * PROTO_645_2007_DI_LEN;
if (len < sizeof(*flw_tail)) {
reason = 13;
goto out;
}
len = len - sizeof(*flw_tail);
flw_tail = (proto_645_fj_task_set_flw_rpt_hdr_t*)data;
if (((flw_tail->follow_di_cnt * PROTO_645_2007_DI_LEN) > len)
&& flw_tail->follow_di_cnt) {
reason = 14;
goto out;
}
for (j = 0; j < flw_tail->follow_di_cnt; j++) {
iot_data_reverse((uint8_t *)&flw_tail->di[j],
PROTO_645_2007_DI_LEN);
}
ret = ERR_OK;
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
if (desc_len < sizeof(*cross_hdr)) {
reason = 15;
goto out;
}
cross_hdr = (proto_645_fj_task_set_cross_rpt_t*)desc;
iot_data_reverse((uint8_t *)&cross_hdr->triger_cnt,
sizeof(cross_hdr->triger_cnt));
iot_data_reverse((uint8_t *)&cross_hdr->di, sizeof(cross_hdr->di));
if (cross_hdr->value_len > PROTO_645_FJ_TASK_DESC_CROSS_VALUE_MAX_LEN
|| !cross_hdr->value_len) {
reason = 16;
goto out;
}
if (cross_hdr->cnt < PROTO_645_FJ_TASK_DESC_CROSS_VALUE_MIN_CNT
|| cross_hdr->cnt > PROTO_645_FJ_TASK_DESC_CROSS_VALUE_MAX_CNT) {
reason = 17;
goto out;
}
data = cross_hdr->value_list;
len = desc_len - sizeof(*cross_hdr);
if (len < cross_hdr->value_len * cross_hdr->cnt) {
reason = 18;
goto out;
}
for (j = 0; j < cross_hdr->cnt; j++) {
if (group_type == PROTO_645_FJ_TASK_GROUP_698 &&
cross_hdr->value_len > 2) {
/* skip data type */
data++;
len--;
iot_data_reverse(data, cross_hdr->value_len - 1);
len -= (cross_hdr->value_len - 1);
data += (cross_hdr->value_len - 1);
} else if (group_type == PROTO_645_FJ_TASK_GROUP_645 &&
cross_hdr->value_len > 1) {
iot_data_reverse(data, cross_hdr->value_len);
len -= cross_hdr->value_len;
data += cross_hdr->value_len;
} else {
len -= cross_hdr->value_len;
data += cross_hdr->value_len;
}
}
if (len < sizeof(*flw_tail)) {
reason = 19;
goto out;
}
len = len - sizeof(*flw_tail);
flw_tail = (proto_645_fj_task_set_flw_rpt_hdr_t*)data;
if (((flw_tail->follow_di_cnt * PROTO_645_2007_DI_LEN) > len)
&& flw_tail->follow_di_cnt) {
reason = 20;
goto out;
}
for (j = 0; j < flw_tail->follow_di_cnt; j++) {
iot_data_reverse((uint8_t *)&flw_tail->di[j],
PROTO_645_2007_DI_LEN);
}
ret = ERR_OK;
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
if (desc_len < sizeof(*change_hdr)) {
reason = 21;
goto out;
}
change_hdr = (proto_645_fj_task_set_change_rpt_hdr_t*)desc;
iot_data_reverse((uint8_t *)&change_hdr->triger_cnt,
sizeof(change_hdr->triger_cnt));
iot_data_reverse((uint8_t *)&change_hdr->di, sizeof(change_hdr->di));
if (change_hdr->value_len > PROTO_645_FJ_TASK_DESC_CHANGE_VALUE_MAX_LEN
|| !change_hdr->value_len) {
reason = 22;
goto out;
}
data = change_hdr->value_list;
len = desc_len - sizeof(*change_hdr);
if (len < change_hdr->value_len) {
reason = 23;
goto out;
}
if (group_type == PROTO_645_FJ_TASK_GROUP_698 &&
change_hdr->value_len > 2) {
/* skip data type */
data++;
len--;
iot_data_reverse(data, change_hdr->value_len - 1);
len -= (change_hdr->value_len - 1);
data += (change_hdr->value_len - 1);
} else if (group_type == PROTO_645_FJ_TASK_GROUP_645 &&
change_hdr->value_len > 1) {
iot_data_reverse(data, change_hdr->value_len);
len -= change_hdr->value_len;
data += change_hdr->value_len;
} else {
len -= change_hdr->value_len;
data += change_hdr->value_len;
}
if (len < sizeof(*flw_tail)) {
reason = 24;
goto out;
}
len = len - sizeof(*flw_tail);
flw_tail = (proto_645_fj_task_set_flw_rpt_hdr_t*)data;
if (((flw_tail->follow_di_cnt * PROTO_645_2007_DI_LEN) > len)
&& flw_tail->follow_di_cnt) {
reason = 25;
goto out;
}
for (j = 0; j < flw_tail->follow_di_cnt; j++) {
iot_data_reverse((uint8_t *)&flw_tail->di[j],
PROTO_645_2007_DI_LEN);
}
ret = ERR_OK;
break;
}
default:
break;
}
out:
if (reason) {
iot_sg_printf("%s reason %d\n", __FUNCTION__, reason);
}
return ret;
}
uint8_t iot_sg_ext_data_task_finish_check(uint8_t *addr,
uint8_t task_id)
{
uint8_t complete = 0;
uint32_t ret;
iot_pkt_t *task_pkt = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *cfg;
task_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!task_pkt) {
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)iot_pkt_put(task_pkt,
sizeof(*cfg));
ret = iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg);
if (ret != ERR_OK) {
goto out;
}
if (iot_sg_ext_task_is_runing(task_id, cfg)) {
goto out;
}
complete = 1;
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return complete;
}
static void iot_sg_sta_ext_fj_muilt_flag_to_save(uint8_t mult_data_item)
{
uint8_t addr[IOT_MAC_ADDR_LEN] = { 0 };
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
sta_glb->drv->get_login_addr(addr);
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
goto out;
}
iot_mac_addr_cpy(comm_cfg.mult_di_addr, addr);
comm_cfg.mult_data_item = mult_data_item;
iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg);
out:
return;
}
static uint8_t iot_sg_ext_data_freeze_task_handle(iot_sg_sta_node_desc_t *node,
iot_time_tm_t curr_tm)
{
uint32_t ret;
uint16_t *triger_cnt;
uint8_t task_done = 0, flag_new = 0, timeout, group_type, data_type;
iot_pkt_t *pkt = NULL, *task_pkt = NULL;
iot_time_tm_t tm = curr_tm, *node_tm = 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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
iot_sg_sta_drv_meter_fj_task_info_t *local_cfg;
if (!freeze_task->cur_task_id) {
goto done;
}
task_pkt = iot_pkt_alloc(sizeof(*local_cfg), IOT_SMART_GRID_MID);
if (!task_pkt) {
goto done;
}
local_cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(task_pkt, sizeof(*local_cfg));
ret = iot_sg_sta_ext_freeze_flash_cfg_get(node->entry.addr,
freeze_task->cur_task_id, local_cfg);
if (ret != ERR_OK) {
goto done;
}
group_type = iot_sg_sta_ext_fj_task_group_get(local_cfg->id);
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
/* 698 group meter read msg is big endian */
iot_sg_sta_ext_fj_task_cfg_desc_reverse(local_cfg->type,
local_cfg->desc, local_cfg->desc_len, 0, group_type);
/* triger count check is little endian */
if (local_cfg->type == PROTO_645_FJ_TASK_TYPE_INCON_RPT ||
local_cfg->type == PROTO_645_FJ_TASK_TYPE_CROSS_RPT ||
local_cfg->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
triger_cnt = (uint16_t *)local_cfg->desc;
iot_data_reverse((uint8_t *)triger_cnt, sizeof(*triger_cnt));
}
}
if (!iot_sg_ext_task_is_runing(freeze_task->cur_task_id, local_cfg)) {
goto done;
}
if (iot_sg_ext_data_freeze_tm_check(local_cfg->type) != ERR_OK) {
goto done;
}
node_tm = iot_sg_ext_data_freeze_get_node_tm(node,
freeze_task->cur_task_id);
if (!node_tm) {
goto done;
}
switch (freeze_task->cur_state) {
case IOT_SG_STA_EXT_FREEZR_STATE_IDLE:
{
if (!node_tm->tm_year && !node_tm->tm_mon && !node_tm->tm_mday &&
!node_tm->tm_hour && !node_tm->tm_min && !node_tm->tm_sec) {
*node_tm = iot_sg_ext_get_next_data_freeze_ts(&tm, node_tm,
local_cfg);
/* check day freeze task */
iot_sg_ext_day_freeze_task_last_check(node->entry.addr, node_tm, &tm,
local_cfg);
} else if (iot_rtc_delta_calc(node_tm, &tm) >= 0) {
freeze_task->cur_state = IOT_SG_STA_EXT_FREEZR_STATE_SEND;
flag_new = 1;
goto send;
}
goto done;
}
case IOT_SG_STA_EXT_FREEZR_STATE_WAIT:
{
if (!freeze_task->timeout_cnt) {
if (freeze_task->flag_resp) {
freeze_task->repeat_cnt = 0;
}
if (!freeze_task->repeat_cnt) {
if (group_type == PROTO_645_FJ_TASK_GROUP_645 &&
!iot_mac_addr_valid(freeze_task->comm_cfg.mult_di_addr) &&
freeze_task->cur_mr_di_cnt > 1) {
if (freeze_task->flag_resp &&
!freeze_task->flag_nack_resp) {
iot_sg_sta_ext_fj_muilt_flag_to_save(1);
} else {
iot_sg_sta_ext_fj_muilt_flag_to_save(0);
flag_new = 1;
freeze_task->cur_state =
IOT_SG_STA_EXT_FREEZR_STATE_SEND;
goto send;
}
}
if (iot_sg_ext_cur_freeze_di_update(local_cfg)) {
iot_sg_ext_data_freeze_save(node->entry.addr,
freeze_task->cur_task_id, node_tm);
if (iot_sg_ext_task_is_runing(
freeze_task->cur_task_id, local_cfg)) {
*node_tm = iot_sg_ext_get_next_data_freeze_ts(
&tm, node_tm, local_cfg);
} else {
os_mem_set(node_tm, 0, sizeof(*node_tm));
}
goto done;
} else {
flag_new = 1;
}
} else {
freeze_task->repeat_cnt--;
}
freeze_task->cur_state = IOT_SG_STA_EXT_FREEZR_STATE_SEND;
goto send;
} else {
freeze_task->timeout_cnt--;
}
break;
}
case IOT_SG_STA_EXT_FREEZR_STATE_SEND:
{
send:
if (group_type == PROTO_645_FJ_TASK_GROUP_698) {
data_type = IOT_SG_STA_DATA_TYPE_69845;
pkt = iot_sg_ext_meter_freeze_msg_build_698(node->entry.addr,
local_cfg);
} else {
pkt = iot_sg_ext_meter_freeze_msg_build_645(node->entry.addr,
local_cfg);
data_type = IOT_SG_STA_DATA_TYPE_645_07;
}
if (pkt) {
timeout = (IOT_SG_STA_EXT_READ_DATA_TIMEOUT *
IOT_SG_STA_EXT_SM_DELAY / 100);
timeout = min(timeout, IOT_SG_STA_EXT_DRV_READ_TIMEOUT);
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_DATA_FREEZE,
node->entry.addr, 0, data_type, iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt), timeout);
if (ret == ERR_OK) {
iot_sg_printf("%s addr %02x:%02x:%02x:%02x:%02x:%02x task %lu "
"di idx %lu\n", __FUNCTION__, node->entry.addr[0],
node->entry.addr[1], node->entry.addr[2],node->entry.addr[3],
node->entry.addr[4], node->entry.addr[5],
freeze_task->cur_task_id, freeze_task->cur_di_idx);
freeze_task->cur_state = IOT_SG_STA_EXT_FREEZR_STATE_WAIT;
freeze_task->timeout_cnt = IOT_SG_STA_EXT_READ_DATA_TIMEOUT;
freeze_task->flag_resp = 0;
freeze_task->flag_nack_resp = 0;
if (flag_new) {
freeze_task->repeat_cnt = 1;
}
}
iot_pkt_free(pkt);
} else {
if (iot_sg_ext_cur_freeze_di_update(local_cfg)) {
iot_sg_ext_data_freeze_save(node->entry.addr,
freeze_task->cur_task_id, node_tm);
if (iot_sg_ext_task_is_runing(
freeze_task->cur_task_id, local_cfg)) {
*node_tm = iot_sg_ext_get_next_data_freeze_ts(
&tm, node_tm, local_cfg);
} else {
os_mem_set(node_tm, 0, sizeof(*node_tm));
}
goto done;
} else {
flag_new = 1;
goto send;
}
}
break;
}
default:
IOT_ASSERT(0);
break;
}
goto out;
done:
task_done = 1;
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return task_done;
}
static uint32_t iot_sg_ext_task_info_check(
iot_sg_sta_drv_meter_fj_task_info_t* info)
{
uint32_t ret = ERR_INVAL, cycle_sec;
uint8_t reason = 0, group;
proto_645_fj_task_cycle_t cycle = { 0 };
group = iot_sg_sta_ext_fj_task_group_get(info->id);
if (group == PROTO_645_FJ_TASK_GROUP_UNKNOWN) {
reason = 1;
goto out;
}
if (info->type != PROTO_645_FJ_TASK_TYPE_FREEZE
&& info->type != PROTO_645_FJ_TASK_TYPE_CROSS_RPT
&& info->type != PROTO_645_FJ_TASK_TYPE_INCON_RPT
&& info->type != PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
reason = 2;
goto out;
}
cycle.unit = info->unit;
cycle.value = info->value;
cycle_sec = proto_645_fj_task_cycle_to_sec(&cycle);
if (cycle_sec == 0) {
reason = 3;
goto out;
}
if (info->delay >= cycle_sec) {
reason = 4;
goto out;
}
if (!info->save_cnt) {
reason = 5;
goto out;
}
if (!info->exe_cnt) {
reason = 6;
goto out;
}
if (!info->desc_len) {
reason = 7;
goto out;
}
if (proto_645_fj_task_info_desc_check(info->type,
info->desc, info->desc_len, group)) {
reason = 8;
goto out;
}
ret = ERR_OK;
out:
if (reason) {
iot_sg_printf("%s reason %lu\n", __FUNCTION__, reason);
}
return ret;
}
static uint8_t iot_sg_ext_data_freeze_cfg_init(uint8_t task_init, uint8_t *addr)
{
uint8_t task_id = task_init;
uint16_t index, exe_cnt, triger_cnt, unit_len = 0;
iot_pkt_t *flash_pkt = NULL, *pkt_unit = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *flash_cfg;
iot_sg_sta_drv_meter_fj_task_unit_t* unit;
if (task_id > PROTO_FJ_FREEZE_TASK_ID_MAX) {
goto out;
}
flash_pkt = iot_pkt_alloc(sizeof(*flash_cfg), IOT_SMART_GRID_MID);
if (!flash_pkt) {
goto out;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
pkt_unit = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!pkt_unit) {
iot_pkt_free(flash_pkt);
goto out;
}
flash_cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)iot_pkt_put(flash_pkt,
sizeof(*flash_cfg));
unit = (iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(pkt_unit,
unit_len);
for (; task_id <= PROTO_FJ_FREEZE_TASK_ID_MAX; task_id++) {
if (iot_sg_sta_flash_clct_task_info_get(addr, task_id,
(uint8_t *)flash_cfg, sizeof(*flash_cfg),
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) == ERR_OK) {
if (iot_sg_ext_task_info_check(flash_cfg) != ERR_OK) {
iot_sg_sta_flash_clct_task_del(addr, task_id, 1,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
continue;
}
os_delay(10);
if (!flash_cfg->storage_mode) {
iot_sg_sta_ext_freeze_flash_cfg_valid_set(task_id, 1);
if (iot_sg_sta_flash_ct_unit_data_find_latest(addr, &index,
(uint8_t *)unit, unit_len, task_id,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) == ERR_OK) {
exe_cnt = unit->exe_cnt_remain;
triger_cnt = unit->save_cnt;
} else {
exe_cnt = flash_cfg->exe_cnt;
triger_cnt = 0;
}
iot_sg_ext_freeze_exe_cnt_set(task_id, exe_cnt, triger_cnt, 0);
iot_sg_printf("%s id %lu success\n", __FUNCTION__, task_id);
} else {
iot_sg_sta_flash_clct_task_del(addr, task_id, 1,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
}
task_id++;
break;
}
}
iot_pkt_free(flash_pkt);
iot_pkt_free(pkt_unit);
out:
return task_id;
}
uint8_t iot_sg_ext_data_freeze_func(uint8_t *addr)
{
uint8_t complete = 0;
iot_time_tm_t tm = {0};
iot_sg_sta_node_desc_t *node = iot_sg_sta_node_find_by_addr(addr);
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_freeze_task_t *task_info;
if (!node || !ext_info->freeze_task_info) {
complete = 1;
goto out;
}
task_info = ext_info->freeze_task_info;
task_info->init_task_id =
iot_sg_ext_data_freeze_cfg_init((uint8_t)task_info->init_task_id, addr);
if (task_info->init_task_id <= PROTO_FJ_FREEZE_TASK_ID_MAX) {
complete = 1;
goto out;
}
if (task_info->stop_dur) {
complete = 1;
goto out;
}
iot_sg_sta_rtc_get(&tm, 0);
next_task:
if (task_info->cur_state == IOT_SG_STA_EXT_FREEZR_STATE_IDLE) {
if (iot_sg_ext_data_freeze_cur_task_update(addr) != ERR_OK) {
complete = 1;
goto out;
}
}
if (iot_sg_ext_data_freeze_task_handle(node, tm)) {
iot_sg_ext_data_freeze_cur_task_done();
goto next_task;
}
out:
return complete;
}
static void iot_sg_sta_ext_freeze_task_comm_cfg_init(
iot_sg_sta_ext_freeze_task_comm_cfg_t *cfg_comm)
{
uint8_t need_save = 0, i, addr[IOT_MAC_ADDR_LEN];
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_pkt_t *pkt = NULL;
iot_sg_sta_flash_fj_task_comm_cfg_t *cfg = NULL;
pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (pkt == NULL) {
goto def;
}
BUILD_BUG_ON(IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT ==
IOT_SG_STA_FLASH_FJ_TASK_RPT_CFG_CNT);
cfg = (iot_sg_sta_flash_fj_task_comm_cfg_t*)iot_pkt_put(pkt, sizeof(*cfg));
if (iot_sg_sta_flash_fj_task_comm_cfg_get(cfg) == ERR_OK) {
cfg_comm->report_max_cnt = cfg->report_max_cnt;
cfg_comm->unit_max_len = cfg->unit_max_len;
cfg_comm->random_rpt_time = cfg->random_rpt_time;
cfg_comm->retry_freeze = cfg->retry_freeze;
cfg_comm->retry_nonfreeze = cfg->retry_nonfreeze;
sta_glb->drv->get_login_addr(addr);
if (iot_mac_addr_cmp(cfg->mult_di_addr, addr)) {
cfg_comm->mult_data_item = cfg->mult_data_item;
iot_mac_addr_cpy(cfg_comm->mult_di_addr, addr);
} else {
cfg_comm->mult_data_item = PROTO_645_FJ_METET_MULT_DATA_ITEM_DEF;
os_mem_set(cfg_comm->mult_di_addr, 0x0, IOT_MAC_ADDR_LEN);
}
cfg_comm->rpt_mode = cfg->rpt_mode;
cfg_comm->cnt = cfg->cnt;
for (i = 0; i < cfg_comm->cnt; i++) {
cfg_comm->task_rpt[i].id = cfg->task_rpt[i].id;
cfg_comm->task_rpt[i].cnt = cfg->task_rpt[i].cnt;
}
} else {
def:
cfg_comm->report_max_cnt = IOT_SG_STA_EXT_TASK_RPT_CNT_DEF;
cfg_comm->unit_max_len = IOT_SG_STA_EXT_TASK_REC_UNIT_LEN_DEF;
cfg_comm->random_rpt_time = IOT_SG_STA_EXT_TASK_RANDON_RPT_PERCENT_DEF;
cfg_comm->retry_freeze = PROTO_645_FJ_FREEZE_TASK_RERPT_CNT_DEF;
cfg_comm->retry_nonfreeze = PROTO_645_FJ_NON_FREEZE_TASK_RERPT_CNT_DEF;
cfg_comm->mult_data_item = PROTO_645_FJ_METET_MULT_DATA_ITEM_DEF;
os_mem_set(cfg_comm->mult_di_addr, 0x0, IOT_MAC_ADDR_LEN);
cfg_comm->rpt_mode = PROTO_645_FJ_REPORT_MODE_645;
cfg_comm->cnt = 0;
os_mem_set(cfg_comm->task_rpt, 0, sizeof(cfg_comm->task_rpt));
goto save;
}
if (cfg_comm->retry_freeze > PROTO_645_FJ_FREEZE_TASK_RERPT_CNT_MAX) {
cfg_comm->retry_freeze = PROTO_645_FJ_FREEZE_TASK_RERPT_CNT_DEF;
need_save = 1;
}
if (cfg_comm->retry_nonfreeze >
PROTO_645_FJ_NON_FREEZE_TASK_RERPT_CNT_MAX) {
cfg_comm->retry_nonfreeze = PROTO_645_FJ_NON_FREEZE_TASK_RERPT_CNT_DEF;
need_save = 1;
}
if (cfg_comm->random_rpt_time > IOT_SG_STA_EXT_TASK_RANDOM_RPT_PERCENT_MAX
|| cfg_comm->random_rpt_time <
IOT_SG_STA_EXT_TASK_RANDON_RPT_PERCENT_MIN) {
cfg_comm->random_rpt_time = IOT_SG_STA_EXT_TASK_RANDON_RPT_PERCENT_DEF;
need_save = 1;
}
if (cfg_comm->mult_data_item > PROTO_645_FJ_METET_MULT_DATA_ITEM_MAX) {
cfg_comm->mult_data_item = PROTO_645_FJ_METET_MULT_DATA_ITEM_DEF;
need_save = 1;
}
if (cfg_comm->rpt_mode > PROTO_645_FJ_REPORT_MODE_698) {
cfg_comm->rpt_mode = PROTO_645_FJ_REPORT_MODE_645;
need_save = 1;
}
if (cfg_comm->cnt > IOT_SG_STA_FLASH_FJ_TASK_RPT_CFG_CNT) {
cfg_comm->cnt = 0;
os_mem_set(cfg_comm->task_rpt, 0, sizeof(cfg_comm->task_rpt));
need_save = 1;
}
if (!need_save) {
goto out;
}
save:
if (cfg) {
cfg->unit_max_len = cfg_comm->unit_max_len;
cfg->report_max_cnt = cfg_comm->report_max_cnt;
cfg->random_rpt_time = cfg_comm->random_rpt_time;
cfg->retry_freeze = cfg_comm->retry_freeze;
cfg->retry_nonfreeze = cfg_comm->retry_nonfreeze;
cfg->mult_data_item = cfg_comm->mult_data_item;
iot_mac_addr_cpy(cfg->mult_di_addr, cfg_comm->mult_di_addr);
cfg->rpt_mode = cfg_comm->rpt_mode;
cfg->cnt = cfg_comm->cnt;
for (i = 0; i < cfg->cnt; i++) {
cfg->task_rpt[i].id = cfg_comm->task_rpt[i].id;
cfg->task_rpt[i].cnt = cfg_comm->task_rpt[i].cnt;
}
iot_sg_sta_flash_fj_task_comm_cfg_save(cfg);
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
}
static uint32_t iot_sg_sta_ext_freeze_task_comm_same_check(
iot_sg_sta_ext_freeze_task_comm_cfg_t *cfg_comm,
iot_sg_sta_ext_freeze_task_comm_cfg_t *task_cfg)
{
uint8_t i;
uint32_t ret = ERR_FAIL;
if ((task_cfg->report_max_cnt != cfg_comm->report_max_cnt)
|| (task_cfg->unit_max_len != cfg_comm->unit_max_len)
|| (task_cfg->random_rpt_time != cfg_comm->random_rpt_time)
|| (task_cfg->retry_freeze != cfg_comm->retry_freeze)
|| (task_cfg->retry_nonfreeze != cfg_comm->retry_nonfreeze)
|| (task_cfg->mult_data_item != cfg_comm->mult_data_item)
|| (!iot_mac_addr_cmp(task_cfg->mult_di_addr, cfg_comm->mult_di_addr))
|| (task_cfg->rpt_mode != cfg_comm->rpt_mode)
|| (task_cfg->cnt != cfg_comm->cnt)) {
goto out;
}
for (i = 0; i < cfg_comm->cnt; i++) {
if ((task_cfg->task_rpt[i].id != cfg_comm->task_rpt[i].id)
|| (task_cfg->task_rpt[i].cnt != cfg_comm->task_rpt[i].cnt)) {
goto out;
}
}
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_sg_sta_ext_freeze_task_comm_cfg_save(
iot_sg_sta_ext_freeze_task_comm_cfg_t *cfg_comm)
{
uint8_t reason = 0, i;
uint32_t ret = ERR_FAIL;
iot_pkt_t *pkt_buf = NULL;
iot_sg_sta_flash_fj_task_comm_cfg_t *flash_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_freeze_task_t *task_info = ext_info->freeze_task_info;
if (!task_info) {
reason = 1;
goto drop;
}
if (iot_sg_sta_ext_freeze_task_comm_same_check(&task_info->comm_cfg,
cfg_comm) == ERR_OK) {
ret = ERR_OK;
goto out;
}
pkt_buf = iot_pkt_alloc(sizeof(*flash_cfg), IOT_SMART_GRID_MID);
if (!pkt_buf) {
reason = 2;
goto drop;
}
flash_cfg = (iot_sg_sta_flash_fj_task_comm_cfg_t*)iot_pkt_put(pkt_buf,
sizeof(*flash_cfg));
flash_cfg->unit_max_len = cfg_comm->unit_max_len;
flash_cfg->report_max_cnt = cfg_comm->report_max_cnt;
flash_cfg->random_rpt_time = cfg_comm->random_rpt_time;
flash_cfg->retry_freeze = cfg_comm->retry_freeze;
flash_cfg->retry_nonfreeze = cfg_comm->retry_nonfreeze;
flash_cfg->mult_data_item = cfg_comm->mult_data_item;
iot_mac_addr_cpy(flash_cfg->mult_di_addr, cfg_comm->mult_di_addr);
flash_cfg->rpt_mode = cfg_comm->rpt_mode;
flash_cfg->cnt = cfg_comm->cnt;
for (i = 0; i < flash_cfg->cnt; i++) {
flash_cfg->task_rpt[i].id = cfg_comm->task_rpt[i].id;
flash_cfg->task_rpt[i].cnt = cfg_comm->task_rpt[i].cnt;
}
ret = iot_sg_sta_flash_fj_task_comm_cfg_save(flash_cfg);
if (ret) {
reason = 3;
goto drop;
}
task_info->comm_cfg.report_max_cnt = cfg_comm->report_max_cnt;
task_info->comm_cfg.unit_max_len = cfg_comm->unit_max_len;
task_info->comm_cfg.random_rpt_time = cfg_comm->random_rpt_time;
task_info->comm_cfg.retry_freeze = cfg_comm->retry_freeze;
task_info->comm_cfg.retry_nonfreeze = cfg_comm->retry_nonfreeze;
task_info->comm_cfg.mult_data_item = cfg_comm->mult_data_item;
iot_mac_addr_cpy(task_info->comm_cfg.mult_di_addr, cfg_comm->mult_di_addr);
task_info->comm_cfg.rpt_mode = cfg_comm->rpt_mode;
task_info->comm_cfg.cnt = cfg_comm->cnt;
for (i = 0; i < task_info->comm_cfg.cnt; i++) {
task_info->comm_cfg.task_rpt[i].id = cfg_comm->task_rpt[i].id;
task_info->comm_cfg.task_rpt[i].cnt = cfg_comm->task_rpt[i].cnt;
}
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (pkt_buf) {
iot_pkt_free(pkt_buf);
}
return ret;
}
static uint16_t iot_sg_sta_ext_freeze_stop_dur_get(void)
{
uint16_t stop_dur = 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;
if (ext_info->freeze_task_info) {
stop_dur = (uint16_t)(ext_info->freeze_task_info->stop_dur / 60);
if (ext_info->freeze_task_info->stop_dur % 60) {
stop_dur++;
}
}
return stop_dur;
}
static void iot_sg_sta_ext_freeze_stop_dur_node_tm_check(uint16_t stop_dur)
{
uint8_t i;
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_node_desc_t *node;
iot_time_tm_t tm = { 0 };
node = iot_sg_sta_node_find_by_addr(ext_info->addr);
if (!node) {
return;
}
iot_sg_sta_rtc_get(&tm, 0);
iot_rtc_delta_add(stop_dur * 60, &tm);
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (iot_rtc_delta_calc(&tm, &node->ext.freeze_info.task_tm[i]) < 0) {
os_mem_set(&node->ext.freeze_info.task_tm[i], 0x0,
sizeof(iot_time_tm_t));
}
}
}
static uint32_t iot_sg_sta_ext_freeze_stop_dur_set(uint16_t stop_dur)
{
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;
if (ext_info->freeze_task_info) {
ext_info->freeze_task_info->stop_dur = stop_dur * 60;
iot_sg_sta_ext_freeze_stop_dur_node_tm_check(stop_dur);
iot_sg_ext_data_freeze_reset();
ret = ERR_OK;
}
return ret;
}
void iot_sg_sta_ext_fj_freeze_refresh(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;
iot_sg_sta_ext_freeze_task_t *task = ext_info->freeze_task_info;
if (task) {
iot_sg_sta_ext_fj_led_blink_timeout_enable(task);
iot_sg_sta_ext_fj_rpt_handle();
if (task->stop_dur) {
task->stop_dur--;
}
}
}
uint32_t iot_sg_sta_ext_freeze_task_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->freeze_task_info = os_mem_malloc(IOT_SMART_GRID_MID,
sizeof(iot_sg_sta_ext_freeze_task_t));
os_mem_set(ext_info->freeze_task_info, 0,
sizeof(iot_sg_sta_ext_freeze_task_t));
if (ext_info->freeze_task_info) {
iot_sg_sta_ext_freeze_task_comm_cfg_init(
&ext_info->freeze_task_info->comm_cfg);
ext_info->freeze_task_info->init_task_id =
PROTO_FJ_FREEZE_TASK_ID_MIN;
ret = ERR_OK;
}
return ret;
}
void iot_sg_sta_ext_freeze_task_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->freeze_task_info) {
os_mem_free(ext_info->freeze_task_info);
ext_info->freeze_task_info = NULL;
}
}
static iot_pkt_t *iot_sg_sta_ext_fj_qr_chip_id(uint8_t *addr)
{
iot_pkt_t *pkt = NULL;
proto_645_fj_chip_id_t chip_id = { 0 };
BUILD_BUG_ON(sizeof(proto_645_fj_chip_id_t) == IOT_CHIP_MMID_LEN);
iot_oem_get_chip_mmid((uint8_t *)&chip_id, sizeof(chip_id));
pkt = proto_645_fj_build_query_chip_id(addr, (uint8_t *)&chip_id,
sizeof(chip_id));
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_qr_mod_id(uint8_t *addr)
{
iot_oem_base_cfg_t *base_cfg;
uint8_t mod_id[PROTO_645_FJ_MOD_ID_SIZE] = { 0 }, i;
if (iot_oem_get_base_cfg(&base_cfg) != ERR_OK) {
return proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
}
BUILD_BUG_ON(IOT_OEM_DEVICE_ID_LEN * 2 <= PROTO_645_FJ_MOD_ID_SIZE);
for (i = 0; i < IOT_OEM_DEVICE_ID_LEN; i++) {
mod_id[i * 2] = (base_cfg->dev_id[i] & 0x0F) + 0x30;
mod_id[i * 2 + 1] = ((base_cfg->dev_id[i] >> 4) & 0x0F) + 0x30;
}
iot_data_reverse(mod_id, PROTO_645_FJ_MOD_ID_SIZE);
return proto_645_fj_build_query_mod_id(addr, mod_id, sizeof(mod_id));
}
static void iot_sg_sta_ext_fj_get_mod_ver(proto_645_fj_mod_ver_info_t *ver_info)
{
uint16_t vendor_id, chip_code;
iot_build_info_t ts_info;
vendor_id = iot_sg_get_vendor_id();
ver_info->vendor_id = (vendor_id << 8) | ((vendor_id & 0xFF00) >> 8);
chip_code = iot_sg_get_chip_code();
ver_info->chip_code = (chip_code << 8) | ((chip_code & 0xFF00) >> 8);
iot_version_get_user_build_info(&ts_info);
ver_info->day = iot_byte_to_bcd(ts_info.day);
ver_info->month = iot_byte_to_bcd(ts_info.month);
ver_info->year = iot_byte_to_bcd(ts_info.year);
ver_info->version[0] = (ts_info.sw_ver & 0xFF);
ver_info->version[1] = (ts_info.sw_ver >> 8);
}
static iot_pkt_t *iot_sg_sta_ext_fj_qr_mod_ver(uint8_t *addr)
{
proto_645_fj_mod_ver_info_t ver_info = { 0 };
iot_sg_sta_ext_fj_get_mod_ver(&ver_info);
return proto_645_fj_build_query_mod_ver(addr, (uint8_t *)&ver_info,
sizeof(ver_info));
}
static iot_pkt_t * iot_sg_sta_ext_fj_write_tm_soc(uint8_t *addr, uint8_t fn,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, req_tm_soc;
iot_pkt_t *rsp_pkt = NULL, *ct_cfg_pkt = NULL;
iot_time_tm_t curr_tm = {0};
iot_sg_sta_flash_fj_ct_cfg_t *ct_cfg;
iot_sg_sta_flash_fj_ct_rec_t ct_rec;
proto_645_fj_mod_tm_soc_t *mod_tm_soc;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (len < sizeof(proto_645_write_data_dest_t) + sizeof(*mod_tm_soc)) {
reason = 1;
goto nack;
}
proto_645_sub33_handle(data, len);
mod_tm_soc = (proto_645_fj_mod_tm_soc_t *)
(data + sizeof(proto_645_write_data_dest_t));
req_tm_soc = iot_bcd_to_byte(mod_tm_soc->tm_soc);
/* only support two time source for FJ, other values is invalid */
if ((req_tm_soc != PROTO_645_FJ_MOD_TM_SOC_NET) &&
(req_tm_soc != PROTO_645_FJ_MOD_TM_SOC_PM)) {
reason = 2;
goto nack;
}
/* save correct time record to flash when receive module correct time
* command or setting command of timer management class according to FJ
*/
if (iot_sg_sta_rtc_get(&curr_tm, 0) == ERR_OK) {
ct_rec.ntb_delta = 0;
ct_rec.second = curr_tm.tm_sec;
ct_rec.minute = curr_tm.tm_min;
ct_rec.hour = curr_tm.tm_hour;
ct_rec.day = curr_tm.tm_mday;
ct_rec.month = curr_tm.tm_mon;
ct_rec.year = (uint8_t)(curr_tm.tm_year - 2000);
iot_sg_sta_flash_fj_ct_rec_save(&ct_rec);
}
ct_cfg_pkt =
iot_pkt_alloc(sizeof(iot_sg_sta_flash_fj_ct_cfg_t), IOT_SMART_GRID_MID);
if (ct_cfg_pkt) {
ct_cfg = (iot_sg_sta_flash_fj_ct_cfg_t *)iot_pkt_data(ct_cfg_pkt);
if (sta_glb->tm_soc != req_tm_soc) {
iot_sg_sta_rtc_clear(1);
sta_glb->tm_soc = req_tm_soc;
ct_cfg->tm_soc = sta_glb->tm_soc;
ct_cfg->ct_dur = sta_glb->ct_dur;
iot_sg_sta_flash_fj_ct_cfg_save(ct_cfg);
if (sta_glb->tm_soc == PROTO_645_FJ_MOD_TM_SOC_PM){
iot_sg_sta_rtc_clear(0);
iot_sg_sta_start_get_time();
}
}
} else {
if (sta_glb->tm_soc != req_tm_soc) {
iot_sg_sta_rtc_clear(1);
sta_glb->tm_soc = req_tm_soc;
if (sta_glb->tm_soc == PROTO_645_FJ_MOD_TM_SOC_PM) {
iot_sg_sta_rtc_clear(0);
iot_sg_sta_start_get_time();
}
}
}
iot_sg_printf("%s tm_soc %lu\n", __FUNCTION__, sta_glb->tm_soc);
rsp_pkt = proto_645_2007_build_ack_msg(addr, fn);
goto out;
nack:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
rsp_pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr, fn);
out:
if (ct_cfg_pkt) {
iot_pkt_free(ct_cfg_pkt);
}
return rsp_pkt;
}
static iot_pkt_t * iot_sg_sta_ext_fj_write_ct_dur(uint8_t *addr, uint8_t fn,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0;
uint16_t req_ct_dur = 0;
uint32_t tmp_dur;
iot_pkt_t *rsp_pkt = NULL, *ct_cfg_pkt = NULL;
iot_time_tm_t curr_tm = {0};
iot_sg_sta_flash_fj_ct_cfg_t *ct_cfg;
iot_sg_sta_flash_fj_ct_rec_t ct_rec;
proto_645_fj_mod_ct_dur_t *mod_ct_dur;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (len < sizeof(proto_645_write_data_dest_t) + sizeof(*mod_ct_dur)) {
reason = 1;
goto nack;
}
proto_645_sub33_handle(data, len);
mod_ct_dur = (proto_645_fj_mod_ct_dur_t *)
(data + sizeof(proto_645_write_data_dest_t));
iot_bcd_to_uint32((uint8_t *)&(mod_ct_dur->ct_dur),
sizeof(mod_ct_dur->ct_dur), 0, &tmp_dur);
req_ct_dur = (uint16_t)tmp_dur;
if (req_ct_dur < PROTO_645_FJ_MOD_CT_DUR_MIN) {
reason = 2;
goto nack;
}
ct_cfg_pkt =
iot_pkt_alloc(sizeof(iot_sg_sta_flash_fj_ct_cfg_t), IOT_SMART_GRID_MID);
if(ct_cfg_pkt) {
ct_cfg = (iot_sg_sta_flash_fj_ct_cfg_t *)iot_pkt_data(ct_cfg_pkt);
if (sta_glb->ct_dur != req_ct_dur) {
sta_glb->ct_dur = req_ct_dur;
ct_cfg->ct_dur = sta_glb->ct_dur;
ct_cfg->tm_soc = sta_glb->tm_soc;
iot_sg_sta_flash_fj_ct_cfg_save(ct_cfg);
}
} else {
sta_glb->ct_dur = req_ct_dur;
}
/* save correct time record to flash when receive module correct time
* command or setting command of timer management class according to FJ
*/
if (iot_sg_sta_rtc_get(&curr_tm, 0) == ERR_OK) {
ct_rec.ntb_delta = 0;
ct_rec.second = curr_tm.tm_sec;
ct_rec.minute = curr_tm.tm_min;
ct_rec.hour = curr_tm.tm_hour;
ct_rec.day = curr_tm.tm_mday;
ct_rec.month = curr_tm.tm_mon;
ct_rec.year = (uint8_t)(curr_tm.tm_year - 2000);
iot_sg_sta_flash_fj_ct_rec_save(&ct_rec);
}
iot_sg_printf("%s ct_dur %lu\n", __FUNCTION__, sta_glb->ct_dur);
rsp_pkt = proto_645_2007_build_ack_msg(addr, fn);
goto out;
nack:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
rsp_pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr, fn);
out:
if (ct_cfg_pkt) {
iot_pkt_free(ct_cfg_pkt);
}
return rsp_pkt;
}
static iot_pkt_t * iot_sg_sta_ext_fj_write_mod_tm(uint8_t *addr, uint8_t fn,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0;
uint32_t curr_ts;
iot_pkt_t *rsp_pkt = NULL;
iot_time_tm_t drv_tm;
iot_sg_sta_flash_fj_ct_rec_t ct_rec;
proto_645_07_time_ymdhms_t *mod_tm;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
curr_ts = (uint32_t)(os_boot_time64() / 1000);
if (sta_glb->last_gen_ct_ts &&
(((curr_ts - sta_glb->last_gen_ct_ts) / 60) < sta_glb->ct_dur)) {
reason = 1;
goto nack;
}
if (sta_glb->tm_soc != PROTO_645_FJ_MOD_TM_SOC_NET) {
reason = 2;
goto nack;
}
if (len < sizeof(proto_645_write_data_dest_t) + sizeof(*mod_tm)) {
reason = 3;
goto nack;
}
proto_645_sub33_handle(data, len);
mod_tm = (proto_645_07_time_ymdhms_t *)
(data + sizeof(proto_645_write_data_dest_t));
drv_tm.tm_year = iot_bcd_to_byte(mod_tm->year) + 2000;
drv_tm.tm_mon = iot_bcd_to_byte(mod_tm->month);
drv_tm.tm_mday = iot_bcd_to_byte(mod_tm->day);
drv_tm.tm_hour = iot_bcd_to_byte(mod_tm->hour);
drv_tm.tm_min = iot_bcd_to_byte(mod_tm->minute);
drv_tm.tm_sec = iot_bcd_to_byte(mod_tm->second);
iot_sg_sta_rtc_set(&drv_tm, 1);
/* reset next read data time */
iot_sg_sta_ext_tm_reset();
iot_sg_sta_ext_fj_power_up_down_record_handle(IOT_SG_STA_POWER_REC_TYPE_UP);
sta_glb->last_gen_ct_ts = (uint32_t)(os_boot_time64() / 1000);
ct_rec.ntb_delta = 0;
ct_rec.second = drv_tm.tm_sec;
ct_rec.minute = drv_tm.tm_min;
ct_rec.hour = drv_tm.tm_hour;
ct_rec.day = drv_tm.tm_mday;
ct_rec.month = drv_tm.tm_mon;
ct_rec.year = (uint8_t)(drv_tm.tm_year - 2000);
iot_sg_sta_flash_fj_ct_rec_save(&ct_rec);
rsp_pkt = proto_645_2007_build_ack_msg(addr, fn);
goto out;
nack:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
rsp_pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr, fn);
out:
return rsp_pkt;
}
static iot_pkt_t * iot_sg_sta_ext_fj_ntb_ct(uint8_t *addr, uint8_t fn,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0;
uint32_t curr_ts, curr_ntb, ret;
iot_pkt_t *rsp_pkt = NULL, *ct_pkt = NULL;
iot_time_tm_t req_tm;
iot_sg_sta_flash_fj_ct_rec_t ct_rec;
proto_645_fj_ntb_corr_time_t *ntb_ct;
proto_645_corr_time_t corr_tm;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
curr_ts = (uint32_t)(os_boot_time64() / 1000);
if (sta_glb->last_ntb_ct_ts &&
(((curr_ts - sta_glb->last_ntb_ct_ts) / 60) < sta_glb->ct_dur)) {
reason = 1;
goto nack;
}
if (sta_glb->tm_soc != PROTO_645_FJ_MOD_TM_SOC_NET) {
reason = 2;
goto nack;
}
if (len < sizeof(proto_645_write_data_dest_t) + sizeof(*ntb_ct)) {
reason = 3;
goto nack;
}
proto_645_sub33_handle(data, len);
ntb_ct = (proto_645_fj_ntb_corr_time_t *)
(data + sizeof(proto_645_write_data_dest_t));
if (!ntb_ct->ntb) {
reason = 4;
goto nack;
}
/* module correct time */
req_tm.tm_year = iot_bcd_to_byte(ntb_ct->year) + 2000;
req_tm.tm_mon = iot_bcd_to_byte(ntb_ct->mon);
req_tm.tm_mday = iot_bcd_to_byte(ntb_ct->day);
req_tm.tm_hour = iot_bcd_to_byte(ntb_ct->hour);
req_tm.tm_min = iot_bcd_to_byte(ntb_ct->min);
req_tm.tm_sec = iot_bcd_to_byte(ntb_ct->sec);
iot_sg_sta_cur_ntb_correct_ts(ntb_ct->ntb, &req_tm);
iot_sg_sta_rtc_set(&req_tm, 1);
/* reset next read data time */
iot_sg_sta_ext_tm_reset();
iot_sg_sta_ext_fj_power_up_down_record_handle(IOT_SG_STA_POWER_REC_TYPE_UP);
sta_glb->last_ntb_ct_ts = (uint32_t)(os_boot_time64() / 1000);
/* save correct time record to flash */
curr_ntb = iot_plc_get_ntb(p_sg_glb->plc_app_h);
curr_ntb = curr_ntb - ntb_ct->ntb;
ct_rec.ntb_delta = IOT_SG_STA_NTB_TO_MS(curr_ntb) * 1000;
ct_rec.second = req_tm.tm_sec;
ct_rec.minute = req_tm.tm_min;
ct_rec.hour = req_tm.tm_hour;
ct_rec.day = req_tm.tm_mday;
ct_rec.month = req_tm.tm_mon;
ct_rec.year = (uint8_t)(req_tm.tm_year - 2000);
iot_sg_sta_flash_fj_ct_rec_save(&ct_rec);
corr_tm.year = iot_byte_to_bcd((uint8_t)(req_tm.tm_year - 2000));
corr_tm.month = iot_byte_to_bcd(req_tm.tm_mon);
corr_tm.day = iot_byte_to_bcd(req_tm.tm_mday);
corr_tm.hour = iot_byte_to_bcd(req_tm.tm_hour);
corr_tm.minute = iot_byte_to_bcd(req_tm.tm_min);
corr_tm.second = iot_byte_to_bcd(req_tm.tm_sec);
ct_pkt = proto_645_build_corr_msg(NULL, &corr_tm);
if (ct_pkt == NULL) {
reason = 5;
goto nack;
}
ret = sta_glb->drv->correct_time(ct_pkt, 1);
if (ret) {
reason = 6;
goto nack;
}
rsp_pkt = proto_645_2007_build_ack_msg(addr, fn);
goto out;
nack:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
rsp_pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr, fn);
out:
return rsp_pkt;
}
/* get module time
* return ERR_OK for success case, ERR_FAIL for fail case
*/
static uint32_t iot_sg_sta_ext_fj_get_mod_tm(proto_645_07_time_ymdhms_t *mod_tm)
{
uint32_t ret = ERR_OK;
iot_time_tm_t curr_tm;
if (iot_sg_sta_rtc_get(&curr_tm, 0)) {
ret = ERR_FAIL;
goto out;
}
mod_tm->year = iot_byte_to_bcd((uint8_t)(curr_tm.tm_year - 2000));
mod_tm->month = iot_byte_to_bcd(curr_tm.tm_mon);
mod_tm->day = iot_byte_to_bcd(curr_tm.tm_mday);
mod_tm->hour = iot_byte_to_bcd(curr_tm.tm_hour);
mod_tm->minute = iot_byte_to_bcd(curr_tm.tm_min);
mod_tm->second = iot_byte_to_bcd(curr_tm.tm_sec);
out:
return ret;
}
static uint32_t iot_sg_sta_ext_fj_get_latest_ct_rec(
proto_645_fj_mod_ct_rec_t *ct_rec)
{
uint8_t reason = 0;;
uint32_t ret = ERR_OK;
iot_sg_sta_flash_fj_ct_rec_t ct_rec_flash;
if (iot_sg_sta_flash_fj_latest_ct_rec_get(&ct_rec_flash) != ERR_OK) {
reason = 1;
ret = ERR_FAIL;
goto out;
}
ct_rec->ntb_delta = ct_rec_flash.ntb_delta;
ct_rec->second = iot_byte_to_bcd((uint8_t)ct_rec_flash.second);
ct_rec->minute = iot_byte_to_bcd((uint8_t)ct_rec_flash.minute);
ct_rec->hour = iot_byte_to_bcd((uint8_t)ct_rec_flash.hour);
ct_rec->day = iot_byte_to_bcd((uint8_t)ct_rec_flash.day);
ct_rec->month = iot_byte_to_bcd((uint8_t)ct_rec_flash.month);
ct_rec->year = iot_byte_to_bcd((uint8_t)ct_rec_flash.year);
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return ret;
}
static void iot_sg_sta_ext_fj_get_evt_rpt_cfg(proto_645_fj_evt_rpt_cfg_t *cfg)
{
iot_sg_sta_evt_global_t *evt_glb = &p_sg_glb->desc.sta->evt;
cfg->mode = evt_glb->fj_evt_rpt_mode;
cfg->rpt_pin_type = evt_glb->fj_evt_rpt_type;
cfg->rpt_pin_en = evt_glb->fj_evt_rpt_en;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_evt_rpt_cfg(
uint8_t *addr, uint8_t *data, uint8_t len)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_evt_global_t *evt_glb = &sta_glb->evt;
proto_645_fj_evt_rpt_cfg_t *cfg_in;
iot_sg_sta_flash_fj_evt_rpt_cfg_t *cfg_flash;
iot_pkt_t *pkt, *buff_pkt = NULL;
uint8_t write_valid = 0, change_valid = 0, err_code, reason;
if (len < sizeof(proto_645_write_data_dest_t) + sizeof(*cfg_in)) {
err_code = PROTO_645_FJ_ERR_LEN;
reason = 1;
goto nack;
}
proto_645_sub33_handle(data, len);
cfg_in = (proto_645_fj_evt_rpt_cfg_t *)
(data + sizeof(proto_645_write_data_dest_t));
if (cfg_in->mode >= PROTO_645_FJ_EVT_RPT_MODE_MAX) {
err_code = PROTO_645_FJ_ERR_OTHER;
reason = 2;
goto nack;
}
buff_pkt = iot_pkt_alloc(sizeof(*cfg_flash), IOT_SMART_GRID_MID);
if (!buff_pkt) {
err_code = PROTO_645_FJ_ERR_OTHER;
reason = 3;
goto nack;
}
cfg_flash = (iot_sg_sta_flash_fj_evt_rpt_cfg_t *)iot_pkt_put(
buff_pkt, sizeof(*cfg_flash));
if (iot_sg_sta_flash_fj_evt_rpt_cfg_get(cfg_flash) != ERR_OK) {
write_valid = 1;
change_valid = 1;
} else {
/* if parameter change, write it into flash */
if (cfg_in->mode != cfg_flash->fj_evt_rpt_mode ||
cfg_in->rpt_pin_type != cfg_flash->fj_evt_rpt_type ||
cfg_in->rpt_pin_en != cfg_flash->fj_evt_rpt_en) {
write_valid = 1;
}
/* if parameter change, need to re-enable event report to update report
* parameter in the following two cases:
* 1. report mode change;
* 2. report mode not change, but current mode is fujian external mode.
*/
if (write_valid && (cfg_in->mode != cfg_flash->fj_evt_rpt_mode ||
cfg_in->mode == PROTO_645_FJ_EVT_RPT_MODE_EXT_FJ)) {
change_valid = 1;
}
}
if (write_valid) {
iot_sg_printf("%s param change mode %lu -> %lu, type %lu -> %lu, en_fj "
"%lu -> %lu\n", __FUNCTION__, cfg_flash->fj_evt_rpt_mode,
cfg_in->mode, cfg_flash->fj_evt_rpt_type, cfg_in->rpt_pin_type,
cfg_flash->fj_evt_rpt_en, cfg_in->rpt_pin_en);
cfg_flash->fj_evt_rpt_mode = cfg_in->mode;
cfg_flash->fj_evt_rpt_type = cfg_in->rpt_pin_type;
cfg_flash->fj_evt_rpt_en = cfg_in->rpt_pin_en;
if (iot_sg_sta_flash_fj_evt_rpt_cfg_save(cfg_flash)) {
err_code = PROTO_645_FJ_ERR_OTHER;
reason = 3;
goto nack;
}
evt_glb->fj_evt_rpt_mode = cfg_flash->fj_evt_rpt_mode;
evt_glb->fj_evt_rpt_type = cfg_flash->fj_evt_rpt_type;
evt_glb->fj_evt_rpt_en = cfg_flash->fj_evt_rpt_en;
}
if (change_valid) {
iot_sg_sta_module_report_re_enable();
}
pkt = proto_645_2007_build_w_rsp(addr);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(err_code, addr,
PROTO_645_2007_FN_WRITE_DATA);
iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
out:
if (buff_pkt) {
iot_pkt_free(buff_pkt);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_evt_rpt_cfg(uint8_t *addr)
{
proto_645_fj_evt_rpt_cfg_t cfg = { 0 };
iot_sg_sta_ext_fj_get_evt_rpt_cfg(&cfg);
return proto_645_fj_build_qr_evt_rpt_cfg(addr, (uint8_t *)&cfg,
sizeof(cfg));
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_tm_soc(uint8_t *addr)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
proto_645_fj_mod_tm_soc_t mod_tm_soc;
mod_tm_soc.tm_soc = iot_byte_to_bcd(sta_glb->tm_soc);
return proto_645_fj_build_qr_tm_soc(addr, (uint8_t *)&mod_tm_soc,
sizeof(mod_tm_soc));
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_ct_rec(uint8_t *addr, uint8_t fn)
{
proto_645_fj_mod_ct_rec_t mod_ct_rec;
if (iot_sg_sta_ext_fj_get_latest_ct_rec(&mod_ct_rec) != ERR_OK) {
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr, fn);
}
return proto_645_fj_build_query_ct_rec(addr, (uint8_t *)&mod_ct_rec,
sizeof(mod_ct_rec));
}
static iot_pkt_t * iot_sg_sta_ext_fj_read_ct_dur(uint8_t *addr)
{
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
proto_645_fj_mod_ct_dur_t mod_ct_dur;
iot_uint32_to_bcd(sta_glb->ct_dur, sizeof(mod_ct_dur.ct_dur),
(uint8_t *)&(mod_ct_dur.ct_dur));
return proto_645_fj_build_query_ct_dur(addr, (uint8_t *)&mod_ct_dur,
sizeof(mod_ct_dur));
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_mod_tm(uint8_t *addr, uint8_t fn)
{
proto_645_07_time_ymdhms_t mod_tm;
if (iot_sg_sta_ext_fj_get_mod_tm(&mod_tm) != ERR_OK) {
return proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr, fn);
}
return proto_645_fj_build_query_mod_tm(addr, (uint8_t *)&mod_tm,
sizeof(mod_tm));
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_task(uint8_t *addr,
uint32_t di, uint8_t is_simple_698)
{
uint8_t reason = 0, local_addr[IOT_MAC_ADDR_LEN], group;
iot_pkt_t *pkt = NULL, *pkt_buf1 = NULL, *pkt_buf2 = NULL;
uint8_t task_id = (uint8_t)(di & 0x000000ff), data_len, *data;
iot_sg_sta_drv_meter_fj_task_info_t *task_cfg;
proto_645_fj_task_set_hdr_t *qr_task_info;
if (task_id > PROTO_FJ_FREEZE_TASK_ID_MAX || !task_id) {
reason = 1;
goto nack;
}
pkt_buf1 = iot_pkt_alloc(sizeof(*task_cfg), IOT_SMART_GRID_MID);
if (!pkt_buf1) {
reason = 2;
goto nack;
}
data = iot_pkt_put(pkt_buf1, sizeof(*task_cfg));
task_cfg = (iot_sg_sta_drv_meter_fj_task_info_t*)data;
if (iot_mac_addr_cmp(addr, proto_645_bcast_addr)) {
iot_mac_addr_cpy(local_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(local_addr);
} else {
iot_mac_addr_cpy(local_addr, addr);
}
if (iot_sg_sta_ext_freeze_task_get(local_addr, task_id, task_cfg)) {
reason = 3;
goto nack;
}
data_len = sizeof(*qr_task_info) + task_cfg->desc_len;
pkt_buf2 = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
if (!pkt_buf2) {
reason = 4;
goto nack;
}
data = iot_pkt_put(pkt_buf2, data_len);
qr_task_info = (proto_645_fj_task_set_hdr_t*)data;
qr_task_info->type = task_cfg->type;
qr_task_info->cycle.value = task_cfg->value;
qr_task_info->cycle.unit = task_cfg->unit;
qr_task_info->cycle.flag = 0;
qr_task_info->cycle.rsvd = 0;
qr_task_info->delay = task_cfg->delay;
qr_task_info->save_cnt = task_cfg->save_cnt;
qr_task_info->rec_total_len = task_cfg->rec_total_len;
qr_task_info->prio_desc.prio = task_cfg->prio;
qr_task_info->prio_desc.storage_mode = task_cfg->storage_mode;
qr_task_info->prio_desc.rsvd_1 = 0;
qr_task_info->prio_desc.flag_rpt = task_cfg->flag_rpt;
qr_task_info->prio_desc.rsvd_2 = 0;
qr_task_info->exe_cnt = task_cfg->exe_cnt;
os_mem_cpy(qr_task_info->task_info_desc, task_cfg->desc,
task_cfg->desc_len);
group = iot_sg_sta_ext_fj_task_group_get(task_id);
if (is_simple_698) {
iot_data_reverse((uint8_t *)&qr_task_info->cycle,
sizeof(qr_task_info->cycle));
iot_data_reverse((uint8_t *)&qr_task_info->save_cnt,
sizeof(qr_task_info->save_cnt));
iot_data_reverse((uint8_t *)&qr_task_info->exe_cnt,
sizeof(qr_task_info->exe_cnt));
iot_sg_sta_ext_fj_task_cfg_desc_reverse(qr_task_info->type,
qr_task_info->task_info_desc, task_cfg->desc_len, 0, group);
}
pkt = proto_645_fj_build_msg(addr, data, data_len, di,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
if (pkt_buf1) {
iot_pkt_free(pkt_buf1);
}
if (pkt_buf2) {
iot_pkt_free(pkt_buf2);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_reset_cnt(uint8_t *addr)
{
proto_645_fj_module_reset_cnt_t reset_count = { 0 };
reset_count.reset_cnt = (uint16_t)(
iot_board_get_reset_count(SYSTEM_RESET_SOFT) +
iot_board_get_reset_count(SYSTEM_RESET_WDT) +
iot_board_get_reset_count(SYSTEM_RESET_PWR));
return proto_645_fj_build_qr_rst_cnt(addr, (uint8_t *)&reset_count,
sizeof(reset_count));
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_pd_cnt(uint8_t *addr)
{
proto_645_fj_pd_cnt_t pd_count = { 0 };
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
iot_sg_sta_flash_fj_pwr_rec_t *record;
pkt_buff = iot_pkt_alloc(sizeof(*record), IOT_SMART_GRID_MID);
if (!pkt_buff) {
goto nack;
}
record = (iot_sg_sta_flash_fj_pwr_rec_t *)iot_pkt_put(pkt_buff,
sizeof(*record));
/* the power down count save in the latest record */
if (iot_sg_sta_flash_fj_pwr_record_get(record, 1) == ERR_OK) {
pd_count.pd_cnt = record->power_down_cnt;
}
pkt = proto_645_fj_build_qr_pd_cnt(addr, (uint8_t *)&pd_count,
sizeof(pd_count));
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_rpt_status(uint8_t *addr,
uint8_t is_simple_698)
{
uint8_t reason = 0, len, i;
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
proto_645_fj_rpt_status_t *rpt;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
if (!freeze_task) {
reason = 1;
goto nack;
}
len = sizeof(*rpt) + IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT *
sizeof(proto_645_fj_task_rpt_status_t);
pkt_buff = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (!pkt_buff) {
reason = 2;
goto nack;
}
rpt = (proto_645_fj_rpt_status_t *)iot_pkt_put(pkt_buff, sizeof(*rpt));
for (i = 0; i < IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT; i++) {
if (!freeze_task->exe_cnt_remain[i].task_id) {
continue;
}
rpt->task_status[rpt->cnt].id = freeze_task->exe_cnt_remain[i].task_id;
if (freeze_task->exe_cnt_remain[i].rpt_total_cnt >=
freeze_task->exe_cnt_remain[i].rpt_cnt) {
rpt->task_status[rpt->cnt].fail_cnt =
freeze_task->exe_cnt_remain[i].rpt_total_cnt -
freeze_task->exe_cnt_remain[i].rpt_cnt;
} else {
rpt->task_status[rpt->cnt].fail_cnt = 0 -
freeze_task->exe_cnt_remain[i].rpt_cnt +
freeze_task->exe_cnt_remain[i].rpt_total_cnt;
}
rpt->task_status[rpt->cnt].rpt_cnt =
freeze_task->exe_cnt_remain[i].rpt_cnt;
if (is_simple_698) {
iot_data_reverse((uint8_t *)&rpt->task_status[rpt->cnt].fail_cnt,
sizeof(rpt->task_status[rpt->cnt].fail_cnt));
iot_data_reverse((uint8_t *)&rpt->task_status[rpt->cnt].rpt_cnt,
sizeof(rpt->task_status[rpt->cnt].rpt_cnt));
}
rpt->cnt++;
iot_pkt_put(pkt_buff, sizeof(proto_645_fj_task_rpt_status_t));
}
pkt = proto_645_fj_build_msg(addr, iot_pkt_data(pkt_buff),
(uint8_t)iot_pkt_data_len(pkt_buff), PROTO_645_FJ_DI_RPT_STATUS,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_multi_rpt(uint8_t *addr)
{
uint8_t reason = 0, len, i;
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_fj_multi_rpt_t *rpt;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 1;
goto nack;
}
len = sizeof(*rpt) + comm_cfg.cnt * sizeof(proto_645_fj_multi_rpt_param_t);
pkt_buff = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (!pkt_buff) {
reason = 2;
goto nack;
}
rpt = (proto_645_fj_multi_rpt_t *)iot_pkt_put(pkt_buff, len);
rpt->cnt = comm_cfg.cnt;
for (i = 0; i < rpt->cnt; i++) {
rpt->task_param[i].id = comm_cfg.task_rpt[i].id;
rpt->task_param[i].cnt = comm_cfg.task_rpt[i].cnt;
}
pkt = proto_645_fj_build_msg(addr, (uint8_t *)rpt, len,
PROTO_645_FJ_DI_MULTI_RPT, PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_rpt_mode(uint8_t *addr)
{
uint8_t reason = 0, rpt_mode;
iot_pkt_t *pkt = NULL;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 1;
goto nack;
}
rpt_mode = comm_cfg.rpt_mode;
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&rpt_mode,
sizeof(rpt_mode), PROTO_645_FJ_DI_RPT_MODE,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_pd_valid_time(uint8_t *addr)
{
proto_645_fj_pd_valid_time_t pd_valid_time = { 0 };
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
iot_sg_sta_flash_fj_pwr_rpt_cfg_t *rpt_cfg;
pkt_buff = iot_pkt_alloc(sizeof(*rpt_cfg), IOT_SMART_GRID_MID);
if (!pkt_buff) {
goto nack;
}
rpt_cfg = (iot_sg_sta_flash_fj_pwr_rpt_cfg_t *)iot_pkt_put(
pkt_buff, sizeof(*rpt_cfg));
if (iot_sg_sta_flash_fj_pwr_rpt_cfg_get(rpt_cfg) == ERR_OK) {
pd_valid_time.pd_valid_time = rpt_cfg->pd_valid_time;
} else {
goto nack;
}
pkt = proto_645_fj_build_pd_valid_time(addr, pd_valid_time.pd_valid_time);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(
PROTO_645_FJ_ERR_OTHER, addr, PROTO_645_2007_FN_READ_DATA);
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_pd_rec(uint8_t *addr, uint32_t di)
{
proto_645_fj_pd_rec_t pd_record = { 0 };
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
iot_sg_sta_flash_fj_pwr_rec_t *record;
pkt_buff = iot_pkt_alloc(sizeof(*record), IOT_SMART_GRID_MID);
if (!pkt_buff) {
goto nack;
}
record =(iot_sg_sta_flash_fj_pwr_rec_t *)iot_pkt_put(pkt_buff,
sizeof(*record));
if (iot_sg_sta_flash_fj_pwr_record_get(record, di & 0x0000000f) == ERR_OK) {
if (record->flag_valid_power_off) {
pd_record.power_down_time.year =
iot_byte_to_bcd(record->power_off_year);
pd_record.power_down_time.month =
iot_byte_to_bcd((uint8_t)record->power_off_month);
pd_record.power_down_time.day =
iot_byte_to_bcd((uint8_t)record->power_off_day);
pd_record.power_down_time.hour =
iot_byte_to_bcd((uint8_t)record->power_off_hour);
pd_record.power_down_time.minute =
iot_byte_to_bcd((uint8_t)record->power_off_minute);
pd_record.power_down_time.second =
iot_byte_to_bcd((uint8_t)record->power_off_second);
} else {
iot_sg_printf("%s Invalid power down record last %lu\n",
__FUNCTION__, (di & 0x0000000f));
goto nack;
}
if ( record->flag_valid_power_on) {
pd_record.power_on_time.year =
iot_byte_to_bcd(record->power_on_year);
pd_record.power_on_time.month =
iot_byte_to_bcd((uint8_t)record->power_on_month);
pd_record.power_on_time.day =
iot_byte_to_bcd((uint8_t)record->power_on_day);
pd_record.power_on_time.hour =
iot_byte_to_bcd((uint8_t)record->power_on_hour);
pd_record.power_on_time.minute =
iot_byte_to_bcd((uint8_t)record->power_on_minute);
pd_record.power_on_time.second =
iot_byte_to_bcd((uint8_t)record->power_on_second);
} else {
/**
* When the power on time is invalid,
* default 2000-1-1 0:0:0,BCD.
*/
os_mem_set(&pd_record.power_on_time, 0,
sizeof(pd_record.power_on_time));
pd_record.power_on_time.month = 1;
pd_record.power_on_time.day = 1;
}
} else {
goto nack;
}
pkt = proto_645_fj_build_msg(addr, (uint8_t *)&pd_record, sizeof(pd_record),
di, PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(
PROTO_645_FJ_ERR_OTHER, addr, PROTO_645_2007_FN_READ_DATA);
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_task(uint8_t *addr,
uint32_t di, uint8_t *data, uint8_t len, uint8_t is_simple_698)
{
uint8_t reason = 0, local_addr[IOT_MAC_ADDR_LEN], group;
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
uint8_t task_id = (uint8_t)(di & 0x000000ff), *req_data = data;
uint8_t req_len = len;
iot_sg_sta_drv_meter_fj_task_info_t *task_cfg;
proto_645_fj_task_set_hdr_t *set_task_info;
group = iot_sg_sta_ext_fj_task_group_get(task_id);
if (group == PROTO_645_FJ_TASK_GROUP_UNKNOWN) {
reason = 1;
goto nack;
}
if (!is_simple_698 && group == PROTO_645_FJ_TASK_GROUP_698) {
reason = 2;
goto nack;
}
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 3;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*set_task_info)) {
reason = 4;
goto nack;
}
set_task_info = (proto_645_fj_task_set_hdr_t*)req_data;
if (is_simple_698) {
iot_data_reverse((uint8_t *)&set_task_info->cycle,
sizeof(set_task_info->cycle));
iot_data_reverse((uint8_t *)&set_task_info->save_cnt,
sizeof(set_task_info->save_cnt));
iot_data_reverse((uint8_t *)&set_task_info->exe_cnt,
sizeof(set_task_info->exe_cnt));
iot_sg_sta_ext_fj_task_cfg_desc_reverse(set_task_info->type,
set_task_info->task_info_desc, req_len - sizeof(*set_task_info),
1, group);
}
if (proto_645_fj_task_set_msg_check(set_task_info, req_len, group)) {
reason = 5;
goto nack;
}
BUILD_BUG_ON(IOT_SG_STA_EXT_FJ_FREEZE_TASK_CFG_MAX_LEN ==
PROTO_645_FJ_FREEZE_TASK_CFG_MAX_LEN);
if (req_len - sizeof(*set_task_info) >
IOT_SG_STA_EXT_FJ_FREEZE_TASK_CFG_MAX_LEN) {
reason = 6;
goto nack;
}
pkt_buff = iot_pkt_alloc(sizeof(*task_cfg), IOT_SMART_GRID_MID);
if (!pkt_buff) {
reason = 7;
goto nack;
}
task_cfg = (iot_sg_sta_drv_meter_fj_task_info_t*)iot_pkt_put(pkt_buff,
sizeof(*task_cfg));
task_cfg->id = task_id;
task_cfg->type = set_task_info->type;
task_cfg->value = set_task_info->cycle.value;
task_cfg->unit = set_task_info->cycle.unit;
task_cfg->delay = set_task_info->delay;
task_cfg->save_cnt = set_task_info->save_cnt;
task_cfg->rec_total_len = set_task_info->rec_total_len;
task_cfg->prio = set_task_info->prio_desc.prio;
task_cfg->exe_cnt = set_task_info->exe_cnt;
task_cfg->storage_mode = set_task_info->prio_desc.storage_mode;
task_cfg->flag_rpt = set_task_info->prio_desc.flag_rpt;
task_cfg->desc_len = req_len - sizeof(*set_task_info);
os_mem_cpy(task_cfg->desc, set_task_info->task_info_desc,
task_cfg->desc_len);
if (iot_mac_addr_cmp(addr, proto_645_bcast_addr)) {
iot_mac_addr_cpy(local_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(local_addr);
} else {
iot_mac_addr_cpy(local_addr, addr);
}
if (iot_sg_sta_ext_freeze_task_add(local_addr, task_id, task_cfg)) {
reason = 8;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_del_task(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, i, task_id, req_len = len, *req_data = data;
uint8_t local_addr[IOT_MAC_ADDR_LEN];
iot_pkt_t *pkt;
proto_645_fj_task_del_dl_t *del_info;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*del_info)) {
reason = 2;
goto nack;
}
del_info = (proto_645_fj_task_del_dl_t*)req_data;
if (!del_info->del_cnt) {
reason = 3;
goto nack;
}
if (iot_mac_addr_cmp(addr, proto_645_bcast_addr)) {
iot_mac_addr_cpy(local_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(local_addr);
} else {
iot_mac_addr_cpy(local_addr, addr);
}
if (del_info->del_cnt == PROTO_645_FJ_TASK_DEL_ALL) {
iot_sg_sta_ext_freeze_task_del_all(local_addr);
} else {
if (req_len < (sizeof(*del_info) + del_info->del_cnt)) {
reason = 4;
goto nack;
}
for (i = 0; i < del_info->del_cnt; i++) {
task_id = del_info->task_num[i];
iot_sg_sta_ext_freeze_task_del(local_addr, task_id);
}
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_rec_max_len(uint8_t *addr)
{
uint8_t reason = 0;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_rec_max_t cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 1;
goto nack;
}
cfg.rec_max_len = comm_cfg.unit_max_len;
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&cfg,
sizeof(cfg), PROTO_645_FJ_DI_SET_TASK_REC_MAX_LEN,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_rec_max_len(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, req_len = len, *req_data = data;
uint8_t local_addr[IOT_MAC_ADDR_LEN] = {0};
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_rec_max_t *cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*cfg)) {
reason = 2;
goto nack;
}
cfg = (proto_645_fj_task_set_rec_max_t*)req_data;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 3;
goto nack;
}
if (comm_cfg.unit_max_len != cfg->rec_max_len) {
comm_cfg.unit_max_len = cfg->rec_max_len;
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 4;
goto nack;
}
if (iot_mac_addr_cmp(addr, proto_645_bcast_addr)) {
iot_mac_addr_cpy(local_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(local_addr);
} else {
iot_mac_addr_cpy(local_addr, addr);
}
iot_sg_sta_ext_freeze_task_del_all(local_addr);
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_meter_multi_data_flag(uint8_t *addr)
{
uint8_t reason = 0;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_meter_muilt_data_item_t cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 1;
goto nack;
}
cfg.mult_data_item = comm_cfg.mult_data_item;
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&cfg,
sizeof(cfg), PROTO_645_FJ_DI_METER_MULTI_DATA_ITEM,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_meter_multi_data_flag(uint8_t *addr,
uint8_t *data, uint8_t len)
{
#if IOT_SG_STA_EXT_WRITE_MULT_FLAG_EN
uint8_t reason = 0, req_len = len, *req_data = data;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_meter_muilt_data_item_t *cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*cfg)) {
reason = 2;
goto nack;
}
cfg = (proto_645_fj_task_meter_muilt_data_item_t*)req_data;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 3;
goto nack;
}
if (cfg->mult_data_item > PROTO_645_FJ_METET_MULT_DATA_ITEM_MAX) {
comm_cfg.mult_data_item = PROTO_645_FJ_METET_MULT_DATA_ITEM_DEF;
} else {
comm_cfg.mult_data_item = cfg->mult_data_item;
}
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 4;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
#else
iot_pkt_t *pkt = NULL;
(void)data;
(void)len;
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
#endif
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_rpt_max_cnt(uint8_t *addr)
{
uint8_t reason = 0;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_rpt_max_t cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 1;
goto nack;
}
cfg.rpt_cnt = comm_cfg.report_max_cnt;
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&cfg,
sizeof(cfg), PROTO_645_FJ_DI_SET_RPT_MAX_CNT,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_random_rpt_time(uint8_t *addr)
{
uint8_t reason = 0;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_random_rpt_t random_rpt;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 1;
goto nack;
}
random_rpt.time = comm_cfg.random_rpt_time;
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&random_rpt,
sizeof(random_rpt), PROTO_645_FJ_DI_SET_RPT_MAX_CNT,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t* iot_sg_sta_ext_fj_read_rpt_retry_count(uint8_t* addr)
{
uint8_t reason = 0;
iot_pkt_t *pkt = NULL;
proto_645_fj_rpt_retry_t data;
iot_sg_sta_ext_freeze_task_comm_cfg_t cfg;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&cfg)) {
reason = 1;
goto nack;
}
data.retry_freeze = cfg.retry_freeze;
data.retry_nonfreeze = cfg.retry_nonfreeze;
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&data, sizeof(data),
PROTO_645_FJ_DI_SET_RPT_RETRY_COUNT, PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_multi_rpt(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, req_len = len, *req_data = data, rpt_cnt, i, idx = 0;
iot_pkt_t *pkt = NULL;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_fj_multi_rpt_t *rpt;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*rpt)) {
reason = 2;
goto nack;
}
rpt = (proto_645_fj_multi_rpt_t *)req_data;
rpt_cnt = rpt->cnt;
if (!rpt_cnt) {
reason = 3;
goto nack;
}
if (rpt_cnt > IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT) {
rpt_cnt = IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT;
}
req_len -= sizeof(*rpt);
if (req_len < sizeof(proto_645_fj_multi_rpt_param_t) * rpt_cnt) {
reason = 4;
goto nack;
}
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 5;
goto nack;
}
comm_cfg.cnt = rpt_cnt;
for (i = 0; i < rpt_cnt; i++) {
if ((rpt->task_param[i].id > PROTO_FJ_FREEZE_645_TASK_ID_MAX &&
rpt->task_param[i].id < PROTO_FJ_FREEZE_698_TASK_ID_MIN ) ||
rpt->task_param[i].id > PROTO_FJ_FREEZE_698_TASK_ID_MAX) {
continue;
}
comm_cfg.task_rpt[idx].id = rpt->task_param[i].id;
comm_cfg.task_rpt[idx].cnt = rpt->task_param[i].cnt;
idx++;
}
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 6;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_report_mode(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, req_len = len, *req_data = data, src_mode;
iot_pkt_t *pkt = NULL;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (!req_len) {
reason = 2;
goto nack;
}
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 3;
goto nack;
}
src_mode = comm_cfg.rpt_mode;
comm_cfg.rpt_mode = !!req_data[0];
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 4;
goto nack;
}
if (src_mode != comm_cfg.rpt_mode) {
iot_sg_ext_data_rpt_msg_merge_del_by_mode(src_mode);
iot_sg_sta_ext_fj_rpt_del_by_mode(src_mode);
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_task_restart(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t task_id[IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT] = { 0 };
uint8_t reason = 0, req_len = len, *req_data = data, task_cnt;
iot_pkt_t *pkt = NULL;
proto_645_fj_freeze_task_reset_t *restart;
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_freeze_task_t *freeze_task = ext_info->freeze_task_info;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*restart)) {
reason = 2;
goto nack;
}
req_len -= sizeof(*restart);
restart = (proto_645_fj_freeze_task_reset_t *)req_data;
task_cnt = restart->cnt;
if (task_cnt != 0xFF) {
if (!task_cnt || task_cnt > req_len) {
reason = 3;
goto nack;
}
if (task_cnt > IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT) {
task_cnt = IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT;
}
os_mem_cpy(task_id, restart->task_id, task_cnt);
} else {
task_cnt = IOT_SG_STA_EXT_FJ_FREEZE_TASK_MAX_CNT;
os_mem_cpy(task_id, freeze_task->valid_id, task_cnt);
}
if (freeze_task) {
if ((freeze_task->reset.cnt != task_cnt) ||
(os_mem_cmp(freeze_task->reset.task_id, task_id,
task_cnt) != 0)) {
freeze_task->reset.cnt = task_cnt;
freeze_task->reset.cur_idx = 0;
os_mem_cpy(freeze_task->reset.task_id, task_id,
task_cnt);
}
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_rpt_max_cnt(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, req_len = len, *req_data = data;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_rpt_max_t *cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*cfg)) {
reason = 2;
goto nack;
}
cfg = (proto_645_fj_task_set_rpt_max_t*)req_data;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 3;
goto nack;
}
comm_cfg.report_max_cnt = cfg->rpt_cnt;
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 4;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_random_rpt_time(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0, req_len = len, *req_data = data;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_random_rpt_t *random_rpt;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*random_rpt)) {
reason = 2;
goto nack;
}
random_rpt = (proto_645_fj_task_set_random_rpt_t*)req_data;
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 3;
goto nack;
}
comm_cfg.random_rpt_time = random_rpt->time;
if (comm_cfg.random_rpt_time > IOT_SG_STA_EXT_TASK_RANDOM_RPT_PERCENT_MAX ||
comm_cfg.random_rpt_time < IOT_SG_STA_EXT_TASK_RANDON_RPT_PERCENT_MIN) {
reason = 4;
goto nack;
}
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 5;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t* iot_sg_sta_ext_fj_write_rpt_retry_count(uint8_t* addr,
uint8_t* data, uint8_t len)
{
uint8_t reason = 0, req_len = len, * req_data = data;
iot_pkt_t* pkt = NULL;
proto_645_fj_rpt_retry_t* cfg;
iot_sg_sta_ext_freeze_task_comm_cfg_t comm_cfg;
proto_645_sub33_handle(data, len);
if (req_len <= sizeof(proto_645_write_data_dest_t)) {
reason = 1;
goto nack;
}
req_len -= sizeof(proto_645_write_data_dest_t);
req_data += sizeof(proto_645_write_data_dest_t);
if (req_len < sizeof(*cfg)) {
reason = 2;
goto nack;
}
cfg = (proto_645_fj_rpt_retry_t*)req_data;
if (cfg->retry_freeze > PROTO_645_FJ_FREEZE_TASK_RERPT_CNT_MAX
|| cfg->retry_nonfreeze > PROTO_645_FJ_NON_FREEZE_TASK_RERPT_CNT_MAX) {
reason = 3;
goto nack;
}
if (iot_sg_sta_ext_freeze_task_comm_cfg_get(&comm_cfg)) {
reason = 4;
goto nack;
}
comm_cfg.retry_freeze = cfg->retry_freeze;
comm_cfg.retry_nonfreeze = cfg->retry_nonfreeze;
if (iot_sg_sta_ext_freeze_task_comm_cfg_save(&comm_cfg)) {
reason = 5;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_task_state(uint8_t *addr)
{
uint8_t reason = 0, len, i;
iot_pkt_t *pkt = NULL, *pkt_buf = NULL;
iot_sg_sta_ext_fj_task_id_t task = {0};
proto_645_fj_task_qr_state_t *task_state;
iot_sg_sta_ext_freeze_task_id_get(&task);
len = sizeof(*task_state) + task.task_cnt;
pkt_buf = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (pkt_buf == NULL) {
reason = 1;
goto nack;
}
task_state = (proto_645_fj_task_qr_state_t*)iot_pkt_put(pkt_buf, len);
task_state->task_cnt = task.task_cnt;
for (i = 0; i < task_state->task_cnt; i++) {
task_state->task_num[i] = task.task_list[i];
}
pkt = proto_645_fj_build_msg(addr, (uint8_t*)task_state,
len, PROTO_645_FJ_DI_QR_TASK_STATE,
PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_stop_dur(uint8_t *addr,
uint8_t is_simple_698)
{
uint16_t curr_dur;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_task_stop_dur_t resp;
curr_dur = iot_sg_sta_ext_freeze_stop_dur_get();
if (is_simple_698) {
iot_uint16_to_bytes(curr_dur, (uint8_t *)&resp.stop_dur, 1);
} else {
iot_uint32_to_bcd(curr_dur, sizeof(resp.stop_dur), resp.stop_dur);
}
pkt = proto_645_fj_build_msg(addr, (uint8_t*)&resp,
sizeof(resp), PROTO_645_FJ_DI_SET_TASK_STOP_DUR,
PROTO_645_2007_FN_READ_DATA);
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_stop_dur(uint8_t *addr, uint8_t *data,
uint8_t len, uint8_t is_simple_698)
{
uint8_t reason = 0;
uint32_t stop_dur, curr_stop_dur;
iot_pkt_t *pkt = NULL;
proto_645_fj_task_set_task_stop_dur_t *req;
proto_645_sub33_handle(data, len);
if (len < (sizeof(proto_645_write_data_dest_t) + sizeof(*req))) {
reason = 1;
goto nack;
}
req = (proto_645_fj_task_set_task_stop_dur_t*)(data +
sizeof(proto_645_write_data_dest_t));
if (is_simple_698) {
stop_dur = iot_bytes_to_uint16((uint8_t *)&req->stop_dur, 1);
} else {
if (!iot_bcd_to_uint32(req->stop_dur, sizeof(req->stop_dur),
0, &stop_dur)) {
reason = 2;
goto nack;
}
}
curr_stop_dur = iot_sg_sta_ext_freeze_stop_dur_get();
if (stop_dur > PROTO_645_FJ_TASK_STOP_DUR_MAX || stop_dur < curr_stop_dur) {
reason = 3;
goto nack;
}
if (iot_sg_sta_ext_freeze_stop_dur_set((uint16_t)stop_dur)) {
reason = 4;
goto nack;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
out:
if (reason) {
iot_sg_printf("%s resp nack, reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_mod_work_v(uint8_t *addr)
{
uint8_t v[PROTO_645_V_LEN];
iot_pkt_t *pkt;
v[0] = 0x20;
v[1] = 0x01;
pkt = proto_645_fj_build_msg(addr, v, sizeof(v),
PROTO_645_FJ_DI_QR_MOD_WORK_V, PROTO_645_2007_FN_READ_DATA);
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_handle_send_file(uint8_t *addr,
uint8_t *data, uint8_t len)
{
iot_pkt_t *pkt_645 = NULL;
uint8_t bcast = 0;
proto_645_fj_send_file_dl_t *req;
uint32_t ack_no;
if (!addr) {
goto err;
}
if (iot_mac_addr_cmp(addr, proto_645_bcast_addr)) {
bcast = 1;
}
if (!data || len <= PROTO_645_2007_DI_LEN) {
goto err;
}
if (len < (sizeof(*req) + PROTO_645_2007_DI_LEN)) {
goto err;
}
proto_645_sub33_handle(data, len);
req = (proto_645_fj_send_file_dl_t*)(data + PROTO_645_2007_DI_LEN);
ack_no = req->seg_index;
iot_sg_printf("sg_upgrade: action = %d, seg_len = %d, file_cmd = %d, "
"is_last = %d, seg_index/total_set_cnt = %d/%d. sn = %d\n",
req->action, req->cur_seg_len, req->file_cmd,
req->is_last_seg, req->seg_index, req->total_seg_cnt, 0);
switch (req->action) {
case PROTO_645_FJ_UPGRADE_CLEAR_FILE:
{
iot_sg_sta_upgrade_handle_file_segment(
IOT_SG_STA_SEG_UPGRADE_ACTION_STOP,
IOT_SG_STA_UPGRADE_SESSION_TYPE_645, (uint16_t)req->seg_index,
req->total_seg_cnt, NULL, 0, 1, PROTO_645_FJ_UPGRADE_WINDOWS * 60);
break;
}
case PROTO_645_FJ_UPGRADE_CCO_STA_MODULE:
case PROTO_645_FJ_UPGRADE_LOCAL_MODULE:
{
/* reject invalid data packet. */
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
break;
}
case PROTO_645_FJ_UPGRADE_STA_MODULE:
{
if (iot_sg_sta_upgrade_handle_file_segment(
IOT_SG_STA_SEG_UPGRADE_ACTION_UPGRADE,
IOT_SG_STA_UPGRADE_SESSION_TYPE_645, (uint16_t)req->seg_index,
req->total_seg_cnt, req->data, req->cur_seg_len, 1,
PROTO_645_FJ_UPGRADE_WINDOWS * 60) != ERR_OK) {
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
}
break;
}
default:
ack_no = PROTO_645_FJ_INVALID_SEG_INDEX;
break;
}
if (!bcast) {
pkt_645 = proto_645_fj_build_upgrade_send_file_ack(addr, ack_no);
}
goto out;
err:
if (!bcast) {
pkt_645 = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_LEN, addr,
PROTO_645_2007_FN_READ_DATA);
}
out:
return pkt_645;
}
static iot_pkt_t *iot_sg_sta_ext_fj_handle_query_file(uint8_t *addr)
{
iot_pkt_t *pkt_645 = NULL;
iot_pkt_t *bitmap_pkt = NULL, *allbitmap_pkt = NULL;
iot_sg_sta_upgrade_info_t *upgrade_info =
&p_sg_glb->desc.sta->upgrade_info;
uint8_t *bitmap_data = NULL, *allbitmap;
uint32_t bitmap_size;
uint32_t i, len;
uint8_t array_index = 0;
uint8_t done = 0;
if (!addr || iot_mac_addr_cmp(addr, proto_645_bcast_addr)) {
goto out;
}
bitmap_pkt = iot_pkt_alloc(PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN,
IOT_SMART_GRID_MID);
if (!bitmap_pkt) {
goto out;
}
bitmap_data = iot_pkt_data(bitmap_pkt);
if ((upgrade_info->state == IOT_SG_STA_UPGRADE_ST_IDLE) ||
(upgrade_info->session_type != IOT_SG_STA_UPGRADE_SESSION_TYPE_645)) {
/* not recv upgrade data */
done = 0;
goto done;
}
if (upgrade_info->skip) {
/* recv done */
done = 1;
goto done;
}
allbitmap_pkt = iot_sg_sta_get_recv_bitmap(0, IOT_SG_STA_QUERY_ALL_BLOCK);
if (!allbitmap_pkt) {
/* not recv upgrade data */
done = 0;
goto done;
}
allbitmap = iot_pkt_data(allbitmap_pkt);
bitmap_size = iot_pkt_data_len(allbitmap_pkt);
if (iot_bitmap_cbs(allbitmap, (uint16_t)bitmap_size) >=
upgrade_info->block_cnt) {
/* recv done */
done = 1;
goto done;
}
for (i = 0, array_index = 0; i < bitmap_size; i += len, array_index++) {
if (i + PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN <= bitmap_size) {
len = PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN;
} else {
len = bitmap_size - i;
os_mem_set(bitmap_data, 0,
PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN - len);
}
if ((len << 3) != iot_bitmap_cbs(allbitmap + i, (uint16_t)len)) {
os_mem_cpy(bitmap_data, allbitmap + i, len);
break;
}
}
iot_bitmap_reverse(bitmap_data, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
goto out;
done:
if (done == 0) {
os_mem_set(bitmap_data, 0xFF, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
} else {
os_mem_set(bitmap_data, 0, PROTO_645_FJ_FILE_SEGMENT_ARRAY_LEN);
}
out:
if (bitmap_pkt) {
pkt_645 = proto_645_fj_build_upgrade_query_file_ack(addr, array_index,
bitmap_data);
iot_pkt_free(bitmap_pkt);
}
if (allbitmap_pkt) {
iot_pkt_free(allbitmap_pkt);
}
iot_sg_printf("sg_upgrade: fj645 query bitmap, done: %d, array_index: %d\n",
done, array_index);
return pkt_645;
}
static iot_pkt_t *iot_sg_sta_ext_fj_write_pd_valid_time(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t reason = 0;
iot_sg_sta_evt_global_t *evt_glb = &p_sg_glb->desc.sta->evt;
iot_pkt_t *pkt, *pkt_buff = NULL;
proto_645_fj_pd_valid_time_t *pd_valid_time;
iot_sg_sta_flash_fj_pwr_rpt_cfg_t *rpt_cfg;
uint8_t write_valid = 0;
if (len < sizeof(proto_645_write_data_dest_t) + sizeof(*pd_valid_time)) {
reason = 1;
goto nack;
}
proto_645_sub33_handle(data, len);
pd_valid_time = (proto_645_fj_pd_valid_time_t *)(data +
sizeof(proto_645_write_data_dest_t));
if (pd_valid_time->pd_valid_time < IOT_SG_STA_FJ_PD_EVT_VALID_TIME_MIN ||
pd_valid_time->pd_valid_time > IOT_SG_STA_FJ_PD_EVT_VALID_TIME_MAX) {
reason = 2;
goto nack;
}
pkt_buff = iot_pkt_alloc(sizeof(*rpt_cfg), IOT_SMART_GRID_MID);
if (!pkt_buff) {
reason = 3;
goto nack;
}
rpt_cfg = (iot_sg_sta_flash_fj_pwr_rpt_cfg_t *)iot_pkt_put(pkt_buff,
sizeof(*rpt_cfg));
if (iot_sg_sta_flash_fj_pwr_rpt_cfg_get(rpt_cfg) != ERR_OK) {
write_valid = 1;
} else if (rpt_cfg->pd_valid_time != pd_valid_time->pd_valid_time) {
write_valid = 1;
}
if (write_valid) {
iot_sg_printf("%s pd valid time %lus->%lus\n", __FUNCTION__,
rpt_cfg->pd_valid_time, pd_valid_time->pd_valid_time);
rpt_cfg->pd_valid_time = pd_valid_time->pd_valid_time;
if (iot_sg_sta_flash_fj_pwr_rpt_cfg_save(rpt_cfg) != ERR_OK) {
reason = 4;
goto nack;
}
evt_glb->fj_pd_valid_time = pd_valid_time->pd_valid_time;
}
pkt = proto_645_2007_build_ack_msg(addr, PROTO_645_2007_FN_WRITE_DATA);
goto out;
nack:
pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
if (reason) {
iot_sg_printf("%s resp nack, reason\n", __FUNCTION__, reason);
}
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return pkt;
}
static uint8_t iot_sg_sta_ext_fj_task_chg_flag_get(uint8_t *addr,
uint8_t task_id, iot_sg_sta_drv_meter_fj_task_unit_t *cur_data,
iot_sg_sta_drv_meter_fj_task_unit_t *last_data)
{
uint32_t chg_di;
uint8_t chg_flag = 0, reason = 0;
iot_pkt_t *cfg_pkt = NULL;
iot_sg_sta_drv_meter_fj_unit_data_t *last_unit_data, *cur_unit_data;
iot_sg_sta_drv_meter_fj_task_info_t *cfg;
if (!addr || !cur_data || !last_data) {
reason = 1;
goto out;
}
if (cur_data->valid_len < sizeof(*cur_unit_data)) {
reason = 2;
goto out;
}
cur_unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)cur_data->uint_data;
if (cur_data->valid_len - sizeof(*cur_unit_data) < cur_unit_data->len) {
reason = 3;
goto out;
}
if (cur_unit_data->len <= PROTO_645_2007_DI_LEN) {
reason = 4;
goto out;
}
chg_di = proto_645_2007_byte_to_di(cur_unit_data->data);
last_unit_data = iot_sg_ext_freeze_di_unit_data_get(chg_di,
last_data->uint_data, last_data->valid_len, last_data->resp_data_cnt);
if (!last_unit_data) {
reason = 5;
goto out;
}
if (last_unit_data->len <= PROTO_645_2007_DI_LEN) {
reason = 6;
goto out;
}
cfg_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!cfg_pkt) {
reason = 7;
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(cfg_pkt, sizeof(*cfg));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg) != ERR_OK) {
reason = 8;
goto out;
}
chg_flag = iot_sg_ext_freeze_chg_rpt_check(cfg,
cur_unit_data->data + PROTO_645_2007_DI_LEN,
cur_unit_data->len - PROTO_645_2007_DI_LEN,
last_unit_data->data + PROTO_645_2007_DI_LEN,
last_unit_data->len - PROTO_645_2007_DI_LEN, 0,
iot_sg_sta_ext_fj_task_group_get(task_id));
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
if (cfg_pkt) {
iot_pkt_free(cfg_pkt);
}
return chg_flag;
}
static uint8_t iot_sg_sta_ext_fj_task_chg_data_resp_by_time(uint8_t *addr,
proto_645_fj_task_data_query_hdr_ul_t *resp_data, uint16_t max_len,
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
uint8_t msg_type, uint8_t task_id)
{
uint8_t data_len = 0, reason = 0, i;
uint16_t idx = 0, unit_len = 0;
uint32_t ret, task_cycle;
iot_pkt_t *start_pkt = NULL, *end_pkt = NULL;
iot_sg_sta_drv_meter_fj_task_unit_t *start_task_unit, *end_task_unit;
iot_time_tm_t end_tm = { 0 }, start_tm = { 0 };
if (!resp_data || !cache_hdr) {
reason = 1;
goto out;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
start_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!start_pkt) {
reason = 2;
goto out;
}
start_task_unit = (iot_sg_sta_drv_meter_fj_task_unit_t *)
iot_pkt_put(start_pkt, unit_len);
end_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!end_pkt) {
reason = 3;
goto out;
}
end_task_unit =
(iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(end_pkt, unit_len);
start_tm = cache_hdr->start_tm;
ret = iot_sg_sta_flash_ct_unit_data_find_by_time(addr, &idx, &start_tm,
(uint8_t *)start_task_unit, unit_len, task_id, 0,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret != ERR_OK) {
reason = 4;
goto out;
}
start_tm.tm_year = (uint16_t)(start_task_unit->uint_time.year + 2000);
start_tm.tm_mon = (uint8_t)start_task_unit->uint_time.month;
start_tm.tm_mday = (uint8_t)start_task_unit->uint_time.day;
start_tm.tm_hour = (uint8_t)start_task_unit->uint_time.hour;
start_tm.tm_min = (uint8_t)start_task_unit->uint_time.minute;
start_tm.tm_sec = (uint8_t)start_task_unit->uint_time.second;
task_cycle = proto_645_fj_task_cycle_to_sec(&cache_hdr->cycle);
for (i = 0; i < IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT; i++) {
if (idx == IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT - 1) {
idx = 0;
} else {
idx++;
}
ret = iot_sg_sta_flash_ct_unit_data_read(addr, idx,
(uint8_t *)end_task_unit, unit_len, task_id);
if (ret != ERR_OK) {
reason = 5;
goto out;
}
end_tm.tm_year = (uint16_t)(end_task_unit->uint_time.year + 2000);
end_tm.tm_mon = (uint8_t)end_task_unit->uint_time.month;
end_tm.tm_mday = (uint8_t)end_task_unit->uint_time.day;
end_tm.tm_hour = (uint8_t)end_task_unit->uint_time.hour;
end_tm.tm_min = (uint8_t)end_task_unit->uint_time.minute;
end_tm.tm_sec = (uint8_t)end_task_unit->uint_time.second;
if (iot_rtc_delta_calc(&start_tm, &end_tm) == task_cycle &&
iot_sg_sta_ext_fj_task_chg_flag_get(addr, task_id, end_task_unit,
start_task_unit)) {
data_len = iot_sg_sta_ext_fj_task_chg_data_to_resp(end_task_unit,
start_task_unit, resp_data, max_len, cache_hdr->type,
cache_hdr->cycle, cache_hdr, msg_type, task_id);
goto out;
}
os_mem_cpy(&start_tm, &end_tm, sizeof(end_tm));
os_mem_cpy(start_task_unit, end_task_unit, sizeof(*end_task_unit));
}
out:
if (start_pkt) {
iot_pkt_free(start_pkt);
}
if (end_pkt) {
iot_pkt_free(end_pkt);
}
if (reason) {
iot_sg_printf("%s err %d\n", __FUNCTION__, reason);
}
return data_len;
}
static uint8_t iot_sg_sta_ext_fj_task_chg_data_resp_by_idx(uint8_t *addr,
uint16_t index_ptr, iot_sg_sta_drv_meter_fj_task_unit_t *cur_task_unit,
uint8_t task_id, iot_sg_sta_drv_meter_fj_task_info_t *task_info,
proto_645_fj_task_data_query_hdr_ul_t *resp_data, uint8_t max_len,
uint8_t idx, uint8_t msg_type)
{
uint8_t data_len = 0, reason = 0;
uint16_t i, flash_idx = index_ptr, chg_idx = 0, old_start_idx = 0;
uint16_t unit_len = 0;
uint32_t ret, task_cycle;
iot_sg_sta_drv_meter_fj_task_unit_t *last_task_unit;
iot_pkt_t *task_pkt = NULL;
iot_time_tm_t end_time = { 0 }, start_time = { 0 };
proto_645_fj_task_cycle_t cycle = { 0 };
if (!cur_task_unit) {
reason = 1;
goto out;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
task_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!task_pkt) {
reason = 2;
goto out;
}
last_task_unit =
(iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(task_pkt, unit_len);
end_time.tm_year = (uint16_t)(cur_task_unit->uint_time.year + 2000);
end_time.tm_mon = (uint8_t)cur_task_unit->uint_time.month;
end_time.tm_mday = (uint8_t)cur_task_unit->uint_time.day;
end_time.tm_hour = (uint8_t)cur_task_unit->uint_time.hour;
end_time.tm_min = (uint8_t)cur_task_unit->uint_time.minute;
end_time.tm_sec = (uint8_t)cur_task_unit->uint_time.second;
cycle.value = task_info->value;
cycle.unit = task_info->unit;
task_cycle = proto_645_fj_task_cycle_to_sec(&cycle);
for (i = 0; i < IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT; i++) {
if (flash_idx == 0) {
flash_idx = IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT - 1;
} else {
flash_idx--;
}
ret = iot_sg_sta_flash_ct_unit_data_read(addr, flash_idx,
(uint8_t *)last_task_unit, unit_len, task_id);
if (ret != ERR_OK) {
break;
}
start_time.tm_year = (uint16_t)(last_task_unit->uint_time.year + 2000);
start_time.tm_mon = (uint8_t)last_task_unit->uint_time.month;
start_time.tm_mday = (uint8_t)last_task_unit->uint_time.day;
start_time.tm_hour = (uint8_t)last_task_unit->uint_time.hour;
start_time.tm_min = (uint8_t)last_task_unit->uint_time.minute;
start_time.tm_sec = (uint8_t)last_task_unit->uint_time.second;
if (iot_rtc_delta_calc(&start_time, &end_time) == task_cycle &&
iot_sg_sta_ext_fj_task_chg_flag_get(addr, task_id, cur_task_unit,
last_task_unit)) {
chg_idx++;
old_start_idx = flash_idx;
if (chg_idx >= idx) {
data_len = iot_sg_sta_ext_fj_task_chg_data_to_resp(cur_task_unit,
last_task_unit, resp_data, max_len, task_info->type, cycle,
NULL, msg_type, task_id);
goto out;
}
}
os_mem_cpy(&end_time, &start_time, sizeof(start_time));
os_mem_cpy(cur_task_unit, last_task_unit, sizeof(*cur_task_unit));
}
if (chg_idx) {
flash_idx = old_start_idx;
ret = iot_sg_sta_flash_ct_unit_data_read(addr, flash_idx,
(uint8_t *)last_task_unit, unit_len, task_id);
if (ret != ERR_OK) {
reason = 3;
goto out;
}
if (flash_idx >= IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT - 1) {
flash_idx = 0;
} else {
flash_idx++;
}
ret = iot_sg_sta_flash_ct_unit_data_read(addr, flash_idx,
(uint8_t *)cur_task_unit, unit_len, task_id);
if (ret != ERR_OK) {
reason = 4;
goto out;
}
data_len = iot_sg_sta_ext_fj_task_chg_data_to_resp(cur_task_unit,
last_task_unit, resp_data, max_len, task_info->type, cycle, NULL,
msg_type, task_id);
} else {
reason = 5;
}
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
if (reason) {
iot_sg_printf("%s err %d\n", __FUNCTION__, reason);
}
return data_len;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_freeze_data_by_idx(uint8_t *addr,
uint32_t di, uint8_t idx, uint8_t msg_type)
{
uint32_t ret;
uint16_t latest_idx, flash_idx, task_unit_len = 0;
uint8_t task_id, data_len = 0, max_len;
uint8_t result = PROTO_645_FJ_READ_RESP_DATA_OK;
iot_pkt_t *resp_pkt = NULL, *pkt = NULL, *task_pkt = NULL, *cfg_pkt;
iot_sg_sta_drv_meter_fj_task_info_t *task_info;
proto_645_fj_task_data_query_hdr_ul_t *resp_data;
iot_sg_sta_drv_meter_fj_task_unit_t *task_unit;
iot_time_tm_t tm = { 0 };
task_id = (uint8_t)(di & 0x000000FF);
cfg_pkt = iot_pkt_alloc(sizeof(*task_info), IOT_SMART_GRID_MID);
if (!cfg_pkt) {
goto out;
}
task_info = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(cfg_pkt, sizeof(*task_info));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, task_info)
!= ERR_OK) {
goto out;
}
max_len = PROTO_645_FJ_RESP_DATA_MAX_LEN - PROTO_645_2007_DI_LEN;
pkt = iot_pkt_alloc(max_len, IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
resp_data = (proto_645_fj_task_data_query_hdr_ul_t *)
iot_pkt_put(pkt, max_len);
if (!idx) {
goto out;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &task_unit_len, NULL);
task_pkt = iot_pkt_alloc(task_unit_len, IOT_SMART_GRID_MID);
if (!task_pkt) {
goto out;
}
task_unit = (iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(task_pkt,
task_unit_len);
ret = iot_sg_sta_flash_ct_unit_data_find_latest(addr, &latest_idx,
(uint8_t *)task_unit, task_unit_len, task_id,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret != ERR_OK) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
goto build;
}
if (task_info->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
data_len = iot_sg_sta_ext_fj_task_chg_data_resp_by_idx(addr, latest_idx,
task_unit, task_id, task_info, resp_data, max_len, idx, msg_type);
if (!data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
goto build;
}
/* read index >= 1 */
if (latest_idx >= idx) {
flash_idx = latest_idx - idx + 1;
} else {
flash_idx = IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT -
(idx - latest_idx) + 1;
}
ret = iot_sg_sta_flash_ct_unit_data_read(addr, flash_idx,
(uint8_t *)task_unit, task_unit_len, task_id);
if (ret == ERR_OK) {
data_len = iot_sg_sta_ext_fj_task_single_data_to_resp(task_unit,
resp_data, max_len, task_info, msg_type, task_id);
if (!data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
} else {
tm.tm_year = 1970;
tm.tm_mon = 1;
tm.tm_mday = 1;
ret = iot_sg_sta_flash_ct_unit_data_find_by_time(addr, &flash_idx,
&tm, (uint8_t *)task_unit, task_unit_len, task_id, 0,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret != ERR_OK) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
goto build;
}
data_len = iot_sg_sta_ext_fj_task_single_data_to_resp(task_unit,
resp_data, max_len, task_info, msg_type, task_id);
if (!data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
}
build:
if (result == PROTO_645_FJ_READ_RESP_DATA_INVALID) {
resp_data->type = task_info->type;
resp_data->result = result;
data_len = sizeof(resp_data->result) + sizeof(resp_data->type);
}
resp_pkt = proto_645_fj_build_msg(addr, (uint8_t *)resp_data, data_len,
di, PROTO_645_2007_FN_READ_DATA);
out:
if (pkt) {
iot_pkt_free(pkt);
}
if (task_pkt) {
iot_pkt_free(task_pkt);
}
if (cfg_pkt) {
iot_pkt_free(cfg_pkt);
}
return resp_pkt;
}
static uint16_t iot_sg_sta_ext_fj_freeze_unit_data_to_cache(
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
iot_sg_sta_ext_freeze_resp_cache_data_t *cache_data, uint16_t cache_len,
iot_sg_sta_drv_meter_fj_task_unit_t *task_data, uint16_t task_data_idx)
{
uint8_t i, reason = 0;
uint16_t len = 0;
iot_sg_sta_drv_meter_fj_unit_data_t *local_unit_data, *cache_unit_data;
if (!cache_hdr || !cache_data || !cache_len || !task_data) {
reason = 1;
goto out;
}
if (sizeof(*cache_data) > cache_len) {
reason = 2;
goto out;
}
cache_len -= sizeof(*cache_data);
for (i = 0; i < cache_hdr->di_cnt; i++) {
local_unit_data = iot_sg_ext_freeze_di_unit_data_get(
cache_hdr->di_info[i].di, task_data->uint_data, task_data->valid_len,
task_data->resp_data_cnt);
if (!local_unit_data) {
continue;
}
if (local_unit_data->len + sizeof(*cache_unit_data) > cache_len) {
reason = 3;
goto out;
}
cache_unit_data = (iot_sg_sta_drv_meter_fj_unit_data_t *)
(cache_data->unit_data + len);
cache_unit_data->len = local_unit_data->len;
os_mem_cpy(cache_unit_data->data, local_unit_data->data,
local_unit_data->len);
cache_hdr->di_info[i].resp_len = local_unit_data->len;
if (local_unit_data->len > PROTO_645_2007_DI_LEN) {
cache_hdr->di_info[i].resp_first_byte =
local_unit_data->data[PROTO_645_2007_DI_LEN];
} else {
cache_hdr->di_info[i].resp_first_byte = 0xff;
}
cache_data->di_cnt++;
cache_len -= local_unit_data->len + sizeof(*cache_unit_data);
len += local_unit_data->len + sizeof(*cache_unit_data);
}
out:
if (len) {
cache_data->rec_time = task_data->uint_time;
cache_data->unit_len = len;
cache_hdr->rsp_cnt++;
cache_hdr->cache_end_tm.tm_year =
(uint16_t)(task_data->uint_time.year + 2000);
cache_hdr->cache_end_tm.tm_mon = (uint8_t)task_data->uint_time.month;
cache_hdr->cache_end_tm.tm_mday = (uint8_t)task_data->uint_time.day;
cache_hdr->cache_end_tm.tm_hour = (uint8_t)task_data->uint_time.hour;
cache_hdr->cache_end_tm.tm_min = (uint8_t)task_data->uint_time.minute;
cache_hdr->cache_end_tm.tm_sec = task_data->uint_time.second;
cache_hdr->cache_end_tm_idx = task_data_idx;
len += sizeof(*cache_data);
}
if (reason) {
iot_sg_printf("%s err %d\n", __FUNCTION__, reason);
}
return len;
}
static uint16_t iot_sg_sta_ext_fj_freeze_flash_data_to_cache(uint8_t *addr,
uint8_t task_id, iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
uint16_t cache_max_len)
{
uint8_t i, reason = 0, first_unit = 0;
uint16_t len = cache_max_len, idx = 0, cache_len, unit_len;
uint32_t ret;
int64_t delta;
iot_sg_sta_drv_meter_fj_task_unit_t *task_unit;
iot_sg_sta_ext_freeze_resp_cache_data_t *cache_data;
proto_645_fj_task_cycle_t cycle = { 0 };
iot_pkt_t *task_pkt = NULL;
iot_time_tm_t unit_tm = { 0 }, end_tm = { 0 }, start_tm = { 0 };
if (!cache_hdr || !cache_max_len || !addr) {
goto out;
}
if (!cache_hdr->query_cnt) {
reason = 1;
goto out;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
task_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!task_pkt) {
reason = 2;
goto out;
}
task_unit =
(iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(task_pkt, unit_len);
start_tm = cache_hdr->start_tm;
ret = iot_sg_sta_flash_ct_unit_data_find_by_time(addr, &idx, &start_tm,
(uint8_t *)task_unit, unit_len, task_id, 0,
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK);
if (ret != ERR_OK) {
reason = 3;
goto out;
}
unit_tm.tm_year = (uint16_t)(task_unit->uint_time.year + 2000);
unit_tm.tm_mon = (uint8_t)task_unit->uint_time.month;
unit_tm.tm_mday = (uint8_t)task_unit->uint_time.day;
unit_tm.tm_hour = (uint8_t)task_unit->uint_time.hour;
unit_tm.tm_min = (uint8_t)task_unit->uint_time.minute;
unit_tm.tm_sec = (uint8_t)task_unit->uint_time.second;
cycle.value = cache_hdr->cycle.value;
cycle.unit = cache_hdr->cycle.unit;
delta = proto_645_fj_task_cycle_to_sec(&cycle) * (cache_hdr->query_cnt - 1);
end_tm = cache_hdr->start_tm;
iot_rtc_delta_add(delta, &end_tm);
if (cache_hdr->type == PROTO_645_FJ_TASK_TYPE_FREEZE &&
iot_rtc_delta_calc(&end_tm, &unit_tm) > 0) {
reason = 4;
goto out;
}
cache_data = (iot_sg_sta_ext_freeze_resp_cache_data_t *)
(cache_hdr->di_info + cache_hdr->di_cnt);
cache_len = iot_sg_sta_ext_fj_freeze_unit_data_to_cache(cache_hdr,
cache_data, len, task_unit, idx);
if (len < cache_len) {
reason = 5;
goto out;
}
if (!first_unit && cache_len) {
cache_hdr->storage_times = task_unit->storage_times;
first_unit = 1;
}
len -= cache_len;
cache_data = (iot_sg_sta_ext_freeze_resp_cache_data_t *)(
(uint8_t *)cache_data + cache_len);
for (i = 0; i < cache_hdr->query_cnt - 1; i++) {
if (len < sizeof(*cache_data)) {
reason = 6;
goto out;
}
idx++;
if (idx >= IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT) {
idx = 0;
}
ret = iot_sg_sta_flash_ct_unit_data_read(addr, idx, (uint8_t *)task_unit,
unit_len, task_id);
if (ret != ERR_OK) {
continue;
}
unit_tm.tm_year = (uint16_t)(task_unit->uint_time.year + 2000);
unit_tm.tm_mon = (uint8_t)task_unit->uint_time.month;
unit_tm.tm_mday = (uint8_t)task_unit->uint_time.day;
unit_tm.tm_hour = (uint8_t)task_unit->uint_time.hour;
unit_tm.tm_min = (uint8_t)task_unit->uint_time.minute;
unit_tm.tm_sec = (uint8_t)task_unit->uint_time.second;
if (iot_rtc_delta_calc(&end_tm, &unit_tm) > 0) {
reason = 7;
goto out;
}
cache_len = iot_sg_sta_ext_fj_freeze_unit_data_to_cache(cache_hdr,
cache_data, len, task_unit, idx);
if (len < cache_len) {
reason = 8;
goto out;
}
if (!first_unit && cache_len) {
first_unit = 1;
cache_hdr->storage_times = task_unit->storage_times;
}
len -= cache_len;
cache_data = (iot_sg_sta_ext_freeze_resp_cache_data_t *)(
(uint8_t *)cache_data + cache_len);
}
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
if (reason) {
iot_sg_printf("%s err %d\n", __FUNCTION__, reason);
}
return cache_max_len - len;
}
static iot_sg_sta_drv_meter_fj_unit_data_t *iot_sg_sta_ext_fj_cache_di_data_find(
iot_sg_sta_ext_freeze_resp_cache_data_t *cache_data, uint16_t cache_len,
uint8_t cache_cnt, uint32_t di, iot_time_tm_t *tm, uint8_t task_type)
{
uint8_t i;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data = NULL;
iot_time_tm_t rec_tm;
if (!cache_data || !cache_len || !cache_cnt || !tm) {
goto out;
}
for (i = 0; i < cache_cnt; i++) {
if (cache_len < sizeof(*cache_data)) {
goto out;
}
cache_len -= sizeof(*cache_data);
if (cache_len < cache_data->unit_len) {
goto out;
}
cache_len -= cache_data->unit_len;
rec_tm.tm_year = (uint16_t)(cache_data->rec_time.year + 2000);
rec_tm.tm_mon = (uint8_t)cache_data->rec_time.month;
rec_tm.tm_mday = (uint8_t)cache_data->rec_time.day;
rec_tm.tm_hour = (uint8_t)cache_data->rec_time.hour;
rec_tm.tm_min = (uint8_t)cache_data->rec_time.minute;
rec_tm.tm_sec = cache_data->rec_time.second;
if (!iot_rtc_delta_calc(&rec_tm, tm) ||
task_type != PROTO_645_FJ_TASK_TYPE_FREEZE) {
unit_data = iot_sg_ext_freeze_di_unit_data_get(di,
cache_data->unit_data, cache_data->unit_len, cache_data->di_cnt);
if (unit_data) {
goto out;
}
}
cache_data = (iot_sg_sta_ext_freeze_resp_cache_data_t *)
(cache_data->unit_data + cache_data->unit_len);
}
out:
return unit_data;
}
static uint32_t iot_sg_sta_ext_fj_freeze_resp_overflow_check(uint8_t *addr,
uint8_t task_id, iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
iot_time_tm_t *last_tm, int64_t delta, uint16_t fill_time_cnt)
{
iot_sg_sta_drv_meter_fj_task_unit_t *task_unit;
uint32_t ret = ERR_FAIL;
uint16_t flash_idx = cache_hdr->cache_end_tm_idx, unit_len = 0;
iot_pkt_t *task_pkt = NULL;
iot_time_tm_t tm, end_tm;
if (fill_time_cnt >= cache_hdr->query_cnt) {
goto out;
}
if (flash_idx >= IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT - 1) {
flash_idx = 0;
} else {
flash_idx++;
}
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, NULL);
task_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!task_pkt) {
goto out;
}
task_unit =
(iot_sg_sta_drv_meter_fj_task_unit_t *)iot_pkt_put(task_pkt, unit_len);
ret = iot_sg_sta_flash_ct_unit_data_read(addr, flash_idx,
(uint8_t *)task_unit, unit_len, task_id);
if (ret != ERR_OK) {
goto out;
}
tm.tm_year = (uint16_t)(task_unit->uint_time.year + 2000);
tm.tm_mon = (uint8_t)task_unit->uint_time.month;
tm.tm_mday = (uint8_t)task_unit->uint_time.day;
tm.tm_hour = (uint8_t)task_unit->uint_time.hour;
tm.tm_min = (uint8_t)task_unit->uint_time.minute;
tm.tm_sec = (uint8_t)task_unit->uint_time.second;
end_tm = cache_hdr->start_tm;
iot_rtc_delta_add(delta * (cache_hdr->query_cnt - 1), &end_tm);
if ((iot_rtc_delta_calc(last_tm, &tm) > 0 ) &&
(iot_rtc_delta_calc(&tm, &end_tm) >= 0 )) {
/* last_tm < tm <= end_tm */
ret = ERR_OK;
}
out:
if (task_pkt) {
iot_pkt_free(task_pkt);
}
return ret;
}
static uint16_t iot_sg_sta_ext_fj_freeze_cache_to_resp(uint8_t *addr,
proto_645_fj_task_data_query_hdr_ul_t *resp, uint16_t resp_max_len,
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr, uint16_t cache_len,
uint8_t msg_type, uint8_t task_id)
{
int64_t delta;
uint16_t len = resp_max_len, fill_time_cnt;
uint8_t frozen_point_cnt = 0, frozen_point_cnt_last = 0, group_type;
uint8_t di_info_len, *di_data, resp_len, reason = 0;
uint8_t i, j, unit_len = 0, valid_di_cnt = 0;
iot_sg_sta_ext_freeze_resp_cache_data_t *cache_data;
iot_sg_sta_drv_meter_fj_unit_data_t *unit_data;
proto_645_fj_task_data_query_di_unit_t *di_unit;
iot_time_tm_t tm = { 0 }, last_tm = { 0 }, cache_end_tm;
if (!resp || !len || !cache_hdr || !cache_len) {
reason = 1;
goto drop;
}
if (cache_len < sizeof(*cache_hdr)) {
reason = 2;
goto drop;
}
cache_len -= sizeof(*cache_hdr);
if (!cache_hdr->di_cnt) {
reason = 4;
goto drop;
}
di_info_len = cache_hdr->di_cnt *
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
if (cache_len < di_info_len) {
reason = 5;
goto drop;
}
cache_len -= di_info_len;
if (cache_len < sizeof(*cache_data)) {
reason = 6;
goto drop;
}
cache_end_tm = cache_hdr->cache_end_tm;
cache_data = (iot_sg_sta_ext_freeze_resp_cache_data_t *)(
(uint8_t *)cache_hdr->di_info + di_info_len);
for (i = 0 ; i < cache_hdr->di_cnt; i++) {
if (!cache_hdr->di_info[i].resp_len ||
cache_hdr->di_info[i].resp_len <= PROTO_645_2007_DI_LEN) {
continue;
}
unit_len += (cache_hdr->di_info[i].resp_len - PROTO_645_2007_DI_LEN);
valid_di_cnt++;
}
if (!unit_len) {
reason = 7;
goto drop;
}
delta = proto_645_fj_task_cycle_to_sec(&cache_hdr->cycle);
if (!delta) {
reason = 8;
goto drop;
}
if (len < sizeof(*resp)) {
reason = 9;
goto drop;
}
len -= sizeof(*resp);
if (len < valid_di_cnt * sizeof(*di_unit)) {
reason = 10;
goto drop;
}
if (unit_len >= (len - valid_di_cnt * sizeof(*di_unit))) {
fill_time_cnt = 1;
} else {
fill_time_cnt = (len - valid_di_cnt * sizeof(*di_unit)) / unit_len;
}
if (fill_time_cnt > cache_hdr->query_cnt) {
fill_time_cnt = cache_hdr->query_cnt;
}
resp->type = cache_hdr->type;
resp->result = PROTO_645_FJ_READ_RESP_DATA_OK;
resp->start.year = iot_byte_to_bcd((uint8_t)cache_data->rec_time.year);
resp->start.month = iot_byte_to_bcd((uint8_t)cache_data->rec_time.month);
resp->start.day = iot_byte_to_bcd((uint8_t)cache_data->rec_time.day);
resp->start.hour = iot_byte_to_bcd((uint8_t)cache_data->rec_time.hour);
resp->start.minute = iot_byte_to_bcd((uint8_t)cache_data->rec_time.minute);
resp->start.second = iot_byte_to_bcd(cache_data->rec_time.second);
if (cache_hdr->storage_times) {
resp->storage_times = cache_hdr->storage_times - 1;
} else {
resp->storage_times = cache_hdr->storage_times;
}
resp->task_cycle = cache_hdr->cycle;
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698) {
resp->start.year = (uint8_t)cache_data->rec_time.year;
resp->start.month = (uint8_t)cache_data->rec_time.month;
resp->start.day = (uint8_t)cache_data->rec_time.day;
resp->start.hour = (uint8_t)cache_data->rec_time.hour;
resp->start.minute = (uint8_t)cache_data->rec_time.minute;
resp->start.second = (uint8_t)cache_data->rec_time.second;
iot_data_reverse((uint8_t *)&resp->start, sizeof(resp->start));
iot_data_reverse((uint8_t *)&resp->storage_times,
sizeof(resp->storage_times));
iot_data_reverse((uint8_t *)&resp->task_cycle,
sizeof(resp->task_cycle));
}
di_unit = (proto_645_fj_task_data_query_di_unit_t *)resp->di_data;
group_type = iot_sg_sta_ext_fj_task_group_get(task_id);
for (i = 0 ; i < cache_hdr->di_cnt; i++) {
if (!cache_hdr->di_info[i].resp_len ||
cache_hdr->di_info[i].resp_len <= PROTO_645_2007_DI_LEN) {
continue;
}
resp_len = cache_hdr->di_info[i].resp_len - PROTO_645_2007_DI_LEN;
if (len < sizeof(*di_unit) + resp_len * fill_time_cnt) {
resp->result = PROTO_645_FJ_READ_RESP_DATA_OVERFLOW;
reason = 11;
goto out;
}
resp->di_cnt++;
di_unit->di = cache_hdr->di_info[i].di;
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698) {
iot_data_reverse((uint8_t *)&di_unit->di, sizeof(di_unit->di));
}
di_unit->length = resp_len;
len -= sizeof(*di_unit);
di_data = di_unit->di_data;
tm.tm_year = (uint16_t)(cache_data->rec_time.year + 2000);
tm.tm_mon = (uint8_t)cache_data->rec_time.month;
tm.tm_mday = (uint8_t)cache_data->rec_time.day;
tm.tm_hour = (uint8_t)cache_data->rec_time.hour;
tm.tm_min = (uint8_t)cache_data->rec_time.minute;
tm.tm_sec = (uint8_t)cache_data->rec_time.second;
frozen_point_cnt = 0;
for (j = 0; j < fill_time_cnt; j++) {
unit_data = iot_sg_sta_ext_fj_cache_di_data_find(cache_data,
cache_len, cache_hdr->rsp_cnt, cache_hdr->di_info[i].di, &tm,
cache_hdr->type);
if (unit_data) {
if (unit_data->len == resp_len + PROTO_645_2007_DI_LEN) {
os_mem_cpy(di_data, unit_data->data + PROTO_645_2007_DI_LEN,
resp_len);
if (msg_type == IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698 &&
group_type == PROTO_645_FJ_TASK_GROUP_645) {
iot_sg_sta_ext_fj_645_unit_to_698_unit(di_unit->di,
unit_data->data, unit_data->len);
}
} else {
if (group_type == PROTO_645_FJ_TASK_GROUP_698 && resp_len) {
di_data[0] = cache_hdr->di_info[i].resp_first_byte;
os_mem_set(di_data + 1, 0xff, resp_len - 1);
} else {
os_mem_set(di_data, 0xff, resp_len);
}
}
} else {
if (group_type == PROTO_645_FJ_TASK_GROUP_698 && resp_len) {
di_data[0] = cache_hdr->di_info[i].resp_first_byte;
os_mem_set(di_data + 1, 0xff, resp_len - 1);
} else {
os_mem_set(di_data, 0xff, resp_len);
}
}
di_data += resp_len;
len -= resp_len;
frozen_point_cnt++;
last_tm = tm;
if (iot_rtc_delta_calc(&tm, &cache_end_tm) <= 0) {
break;
}
iot_rtc_delta_add(delta, &tm);
}
if (!frozen_point_cnt_last) {
frozen_point_cnt_last = frozen_point_cnt;
} else if (frozen_point_cnt_last != frozen_point_cnt) {
/* must be the same to all di frozen point count */
reason = 12;
goto drop;
}
di_unit = (proto_645_fj_task_data_query_di_unit_t *)di_data;
}
resp->frozen_point_cnt = frozen_point_cnt;
if (iot_sg_sta_ext_fj_freeze_resp_overflow_check(addr, task_id, cache_hdr,
&last_tm, delta, fill_time_cnt) == ERR_OK) {
resp->result = PROTO_645_FJ_READ_RESP_DATA_OVERFLOW;
}
goto out;
drop:
len = resp_max_len;
iot_sg_printf("%s drop %d\n",__FUNCTION__, reason);
out:
return resp_max_len - len;
}
static uint32_t iot_sg_ext_fj_cfg_di_check(uint32_t di,
iot_sg_sta_drv_meter_fj_task_info_t *cfg)
{
uint8_t idx, offset_len = 0, *data;
uint32_t ret = ERR_INVAL, cfg_di;
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr;
proto_645_fj_freeze_data_desc_hdr_t *freeze_des;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_rpt;
proto_645_fj_task_set_flw_rpt_hdr_t *flw_rpt;
proto_645_fj_task_set_cross_rpt_t *cross_rpt;
proto_645_fj_task_set_change_rpt_hdr_t *chg_rpt;
switch (cfg->type) {
case PROTO_645_FJ_TASK_TYPE_FREEZE:
{
freeze_hdr = (proto_645_fj_task_set_freeze_hdr_t *)cfg->desc;
for (idx = 0; idx < freeze_hdr->data_cnt; idx++) {
if (iot_sg_ext_freeze_data_desc_offset_get(&offset_len,
cfg->desc_len, freeze_hdr->data_desc, idx)) {
goto out;
}
freeze_des = (proto_645_fj_freeze_data_desc_hdr_t *)(
freeze_hdr->data_desc + offset_len);
cfg_di = proto_645_2007_byte_to_di(freeze_des->data);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
}
break;
}
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_rpt = (proto_645_fj_task_set_incon_rpt_hdr_t *)cfg->desc;
if (!incon_rpt->di_cnt) {
goto out;
}
for (idx = 0; idx < incon_rpt->di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&incon_rpt->di[idx]);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
}
data = (uint8_t *)incon_rpt->di +
incon_rpt->di_cnt * PROTO_645_2007_DI_LEN;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
for (idx = 0; idx < flw_rpt->follow_di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_rpt = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&cross_rpt->di);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
data = cross_rpt->value_list + cross_rpt->cnt * cross_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
for (idx = 0; idx < flw_rpt->follow_di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_rpt = (proto_645_fj_task_set_change_rpt_hdr_t*)cfg->desc;
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&chg_rpt->di);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
data = chg_rpt->value_list + chg_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
for (idx = 0; idx < flw_rpt->follow_di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
if (di == cfg_di) {
ret = ERR_OK;
goto out;
}
}
break;
}
default:
break;
}
out:
return ret;
}
static void iot_sg_ext_fj_cfg_di_fill_to_cache_hdr(
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr,
iot_sg_sta_drv_meter_fj_task_info_t *cfg, uint16_t cache_max_len)
{
uint8_t idx, offset_len = 0, *data;
uint32_t cfg_di;
proto_645_fj_task_set_freeze_hdr_t *freeze_hdr;
proto_645_fj_freeze_data_desc_hdr_t *freeze_des;
proto_645_fj_task_set_incon_rpt_hdr_t *incon_rpt;
proto_645_fj_task_set_flw_rpt_hdr_t *flw_rpt;
proto_645_fj_task_set_cross_rpt_t *cross_rpt;
proto_645_fj_task_set_change_rpt_hdr_t *chg_rpt;
if (!cache_hdr || !cfg || !cache_max_len) {
goto out;
}
switch (cfg->type) {
case PROTO_645_FJ_TASK_TYPE_FREEZE:
{
freeze_hdr = (proto_645_fj_task_set_freeze_hdr_t *)cfg->desc;
for (idx = 0; idx < freeze_hdr->data_cnt; idx++) {
if (iot_sg_ext_freeze_data_desc_offset_get(&offset_len,
cfg->desc_len, freeze_hdr->data_desc, idx)) {
goto out;
}
freeze_des = (proto_645_fj_freeze_data_desc_hdr_t *)(
freeze_hdr->data_desc + offset_len);
cfg_di = proto_645_2007_byte_to_di(freeze_des->data);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_INCON_RPT:
{
incon_rpt = (proto_645_fj_task_set_incon_rpt_hdr_t *)cfg->desc;
if (!incon_rpt->di_cnt) {
goto out;
}
for (idx = 0; idx < incon_rpt->di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&incon_rpt->di[idx]);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
}
data = (uint8_t *)incon_rpt->di +
incon_rpt->di_cnt * PROTO_645_2007_DI_LEN;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
for (idx = 0; idx < flw_rpt->follow_di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CROSS_RPT:
{
cross_rpt = (proto_645_fj_task_set_cross_rpt_t *)cfg->desc;
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&cross_rpt->di);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
data = cross_rpt->value_list + cross_rpt->cnt * cross_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
for (idx = 0; idx < flw_rpt->follow_di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
}
break;
}
case PROTO_645_FJ_TASK_TYPE_CHG_RPT:
{
chg_rpt = (proto_645_fj_task_set_change_rpt_hdr_t*)cfg->desc;
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&chg_rpt->di);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
data = chg_rpt->value_list + chg_rpt->value_len;
flw_rpt = (proto_645_fj_task_set_flw_rpt_hdr_t *)data;
for (idx = 0; idx < flw_rpt->follow_di_cnt; idx++) {
cfg_di = proto_645_2007_byte_to_di((uint8_t *)&flw_rpt->di[idx]);
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
goto out;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = cfg_di;
cache_hdr->di_cnt++;
}
break;
}
default:
break;
}
out:
return;
}
static uint16_t iot_sg_sta_ext_fj_read_freeze_query_info_to_cache_hdr(
uint8_t *addr, uint8_t task_id, uint8_t *data, uint8_t len,
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr, uint16_t cache_max_len)
{
int64_t delta;
uint32_t query_di;
uint16_t cache_hdr_len = 0;
uint8_t i, reason = 0;
iot_pkt_t *cfg_pkt = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *cfg;
iot_time_tm_t start_tm = { 0 };
proto_645_fj_task_data_query_hdr_dl_t *query_hdr;
proto_645_fj_task_data_query_tail_dl_t *query_tail;
if (!addr || !data || !len || !cache_hdr || !cache_max_len) {
goto out;
}
cfg_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!cfg_pkt) {
reason = 1;
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(cfg_pkt, sizeof(*cfg));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg) != ERR_OK) {
reason = 2;
goto out;
}
if (cache_max_len < sizeof(*cache_hdr)) {
reason = 3;
goto out;
}
cache_max_len -= sizeof(*cache_hdr);
cache_hdr->type = cfg->type;
cache_hdr->cycle.value = cfg->value;
cache_hdr->cycle.unit = cfg->unit;
if (len < sizeof(*query_hdr)) {
reason = 4;
goto out;
}
len -= sizeof(*query_hdr);
query_hdr = (proto_645_fj_task_data_query_hdr_dl_t *)data;
if (query_hdr->type != PROTO_645_FJ_TASK_QR_TYPE_WITH_TIME) {
reason = 5;
goto out;
}
if (len < PROTO_645_2007_DI_LEN * query_hdr->di_cnt) {
reason = 6;
goto out;
}
len -= PROTO_645_2007_DI_LEN * query_hdr->di_cnt;
/* cache request info */
if (query_hdr->di_cnt) {
for (i = 0; i < query_hdr->di_cnt; i++) {
query_di = proto_645_2007_byte_to_di(
(uint8_t *)&query_hdr->di_list[i]);
if (iot_sg_ext_fj_cfg_di_check(query_di, cfg)) {
continue;
}
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
break;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = query_di;
cache_hdr->di_cnt++;
}
} else {
iot_sg_ext_fj_cfg_di_fill_to_cache_hdr(cache_hdr, cfg, cache_max_len);
}
if (len < sizeof(*query_tail)) {
reason = 8;
goto out;
}
query_tail = (proto_645_fj_task_data_query_tail_dl_t *)(query_hdr->di_list +
query_hdr->di_cnt);
start_tm.tm_year = iot_bcd_to_byte(query_tail->start.year) + 2000;
start_tm.tm_mon = iot_bcd_to_byte(query_tail->start.month);
start_tm.tm_mday = iot_bcd_to_byte(query_tail->start.day);
start_tm.tm_hour = iot_bcd_to_byte(query_tail->start.hour);
start_tm.tm_min = iot_bcd_to_byte(query_tail->start.minute);
start_tm.tm_sec = iot_bcd_to_byte(query_tail->start.second);
delta = proto_645_fj_task_cycle_to_sec(&cache_hdr->cycle);
iot_sg_ext_set_integral_point(&start_tm, delta, 1);
cache_hdr->start_tm.tm_year = start_tm.tm_year;
cache_hdr->start_tm.tm_mon = start_tm.tm_mon;
cache_hdr->start_tm.tm_mday = start_tm.tm_mday;
cache_hdr->start_tm.tm_hour = start_tm.tm_hour;
cache_hdr->start_tm.tm_min = start_tm.tm_min;
cache_hdr->start_tm.tm_sec = start_tm.tm_sec;
if (cfg->type == PROTO_645_FJ_TASK_TYPE_FREEZE) {
cache_hdr->query_cnt = query_tail->cnt;
} else {
cache_hdr->query_cnt = 1;
}
cache_hdr_len = sizeof(*cache_hdr) + cache_hdr->di_cnt *
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
out:
if (cfg_pkt) {
iot_pkt_free(cfg_pkt);
}
if (reason) {
iot_sg_printf("%s err %d\n",__FUNCTION__,reason);
}
return cache_hdr_len;
}
static uint16_t iot_sg_sta_ext_fj_read_freeze_query_info_to_cache_hdr2(
uint8_t *addr, uint8_t task_id, uint8_t *data, uint8_t len,
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr, uint16_t cache_max_len)
{
int64_t delta;
uint32_t query_di;
uint16_t cache_hdr_len = 0;
uint8_t i, reason = 0;
iot_pkt_t *cfg_pkt = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *cfg;
iot_time_tm_t start_tm = { 0 };
proto_645_fj_task_data_query_hdr2_dl_t *query_hdr;
proto_645_fj_task_data_query_tail2_dl_t *query_tail;
if (!addr || !data || !len || !cache_hdr || !cache_max_len) {
goto out;
}
cfg_pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!cfg_pkt) {
reason = 1;
goto out;
}
cfg = (iot_sg_sta_drv_meter_fj_task_info_t *)
iot_pkt_put(cfg_pkt, sizeof(*cfg));
if (iot_sg_sta_ext_freeze_flash_cfg_get(addr, task_id, cfg) != ERR_OK) {
reason = 2;
goto out;
}
if (cache_max_len < sizeof(*cache_hdr)) {
reason = 3;
goto out;
}
cache_max_len -= sizeof(*cache_hdr);
cache_hdr->type = cfg->type;
cache_hdr->cycle.value = cfg->value;
cache_hdr->cycle.unit = cfg->unit;
if (len < sizeof(*query_hdr)) {
reason = 4;
goto out;
}
len -= sizeof(*query_hdr);
query_hdr = (proto_645_fj_task_data_query_hdr2_dl_t *)data;
if (query_hdr->type != PROTO_645_FJ_TASK_QR_TYPE_WITH_TIME2) {
reason = 5;
goto out;
}
if (len < PROTO_645_2007_DI_LEN * query_hdr->oad_cnt) {
reason = 6;
goto out;
}
len -= PROTO_645_2007_DI_LEN * query_hdr->oad_cnt;
/* cache request info */
if (query_hdr->oad_cnt) {
for (i = 0; i < query_hdr->oad_cnt; i++) {
query_di = iot_bytes_to_uint32(
(uint8_t *)&query_hdr->oad_list[i], 1);
if (iot_sg_ext_fj_cfg_di_check(query_di, cfg)) {
continue;
}
if (cache_max_len <
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t)) {
break;
}
cache_max_len -= sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
cache_hdr->di_info[cache_hdr->di_cnt].di = query_di;
cache_hdr->di_cnt++;
}
} else {
iot_sg_ext_fj_cfg_di_fill_to_cache_hdr(cache_hdr, cfg, cache_max_len);
}
if (len < sizeof(*query_tail)) {
reason = 8;
goto out;
}
query_tail = (proto_645_fj_task_data_query_tail2_dl_t *)
(query_hdr->oad_list + query_hdr->oad_cnt);
if (query_tail->data_type != PROTO_69845_APP_DATA_TIME_S) {
reason = 9;
goto out;
}
start_tm.tm_year = iot_bytes_to_uint16((uint8_t *)&query_tail->year, 1);
start_tm.tm_mon = query_tail->month;
start_tm.tm_mday = query_tail->day;
start_tm.tm_hour = query_tail->hour;
start_tm.tm_min = query_tail->minute;
start_tm.tm_sec = query_tail->second;
delta = proto_645_fj_task_cycle_to_sec(&cache_hdr->cycle);
iot_sg_ext_set_integral_point(&start_tm, delta, 1);
cache_hdr->start_tm.tm_year = start_tm.tm_year;
cache_hdr->start_tm.tm_mon = start_tm.tm_mon;
cache_hdr->start_tm.tm_mday = start_tm.tm_mday;
cache_hdr->start_tm.tm_hour = start_tm.tm_hour;
cache_hdr->start_tm.tm_min = start_tm.tm_min;
cache_hdr->start_tm.tm_sec = start_tm.tm_sec;
if (cfg->type == PROTO_645_FJ_TASK_TYPE_FREEZE) {
cache_hdr->query_cnt = query_tail->cnt;
} else {
cache_hdr->query_cnt = 1;
}
cache_hdr_len = sizeof(*cache_hdr) + cache_hdr->di_cnt *
sizeof(iot_sg_sta_ext_freeze_resp_cache_di_info_t);
out:
if (cfg_pkt) {
iot_pkt_free(cfg_pkt);
}
if (reason) {
iot_sg_printf("%s err %d\n",__FUNCTION__,reason);
}
return cache_hdr_len;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_freeze_data_by_time2(uint8_t *addr,
uint32_t di, uint8_t *data, uint8_t len, uint8_t msg_type,
uint32_t valid_len)
{
uint8_t result = PROTO_645_FJ_READ_RESP_DATA_OK, task_id;
uint16_t cache_max_len, cache_data_len, cache_hdr_len, max_len, data_len = 0;
iot_pkt_t *pkt = NULL, *cache_pkt = NULL;
proto_645_fj_task_data_query_hdr_ul_t *query_ul;
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr;
cache_max_len = IOT_SG_STA_EXT_FREEZR_698_CACHE_LEN;
cache_pkt = iot_pkt_alloc(cache_max_len, IOT_SMART_GRID_MID);
if (!cache_pkt) {
goto out;
}
cache_hdr = (iot_sg_sta_ext_freeze_resp_cache_hdr_t *)iot_pkt_put(cache_pkt,
cache_max_len);
task_id = (uint8_t)(di & 0x000000FF);
cache_hdr_len = iot_sg_sta_ext_fj_read_freeze_query_info_to_cache_hdr2(addr,
task_id, data, len, cache_hdr, cache_max_len);
if (!cache_hdr_len || cache_max_len < cache_hdr_len) {
goto out;
}
cache_max_len -= cache_hdr_len;
max_len = (uint16_t)valid_len;
pkt = iot_pkt_alloc(max_len, IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
query_ul = (proto_645_fj_task_data_query_hdr_ul_t *)iot_pkt_data(pkt);
if (cache_hdr->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
data_len = iot_sg_sta_ext_fj_task_chg_data_resp_by_time(addr, query_ul,
max_len, cache_hdr, msg_type, task_id);
if (!data_len || max_len < data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
goto build;
}
cache_data_len = iot_sg_sta_ext_fj_freeze_flash_data_to_cache(addr,
task_id, cache_hdr, cache_max_len);
if (!cache_data_len || cache_max_len < cache_data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
goto build;
}
cache_max_len -= cache_data_len;
data_len = iot_sg_sta_ext_fj_freeze_cache_to_resp(addr, query_ul, max_len,
cache_hdr, IOT_SG_STA_EXT_FREEZR_698_CACHE_LEN - cache_max_len,
msg_type, task_id);
if (!data_len || max_len < data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
build:
if (result == PROTO_645_FJ_READ_RESP_DATA_INVALID) {
query_ul->type = cache_hdr->type;
query_ul->result = result;
data_len = sizeof(query_ul->result) + sizeof(query_ul->type);
}
iot_pkt_put(pkt, data_len);
out:
if (cache_pkt) {
iot_pkt_free(cache_pkt);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_freeze_data_by_time(uint8_t *addr,
uint32_t di, uint8_t *data, uint8_t len, uint8_t msg_type)
{
uint8_t task_id, max_len, data_len = 0;
uint8_t result = PROTO_645_FJ_READ_RESP_DATA_OK;
uint16_t cache_max_len, cache_data_len, cache_hdr_len;
iot_pkt_t *resp_pkt = NULL, *pkt = NULL, *cache_pkt = NULL;
proto_645_fj_task_data_query_hdr_ul_t *query_ul;
iot_sg_sta_ext_freeze_resp_cache_hdr_t *cache_hdr;
cache_max_len = IOT_SG_STA_EXT_FREEZR_CACHE_LEN;
cache_pkt = iot_pkt_alloc(cache_max_len, IOT_SMART_GRID_MID);
if (!cache_pkt) {
goto out;
}
cache_hdr = (iot_sg_sta_ext_freeze_resp_cache_hdr_t *)iot_pkt_put(cache_pkt,
cache_max_len);
task_id = (uint8_t)(di & 0x000000FF);
cache_hdr_len = iot_sg_sta_ext_fj_read_freeze_query_info_to_cache_hdr(addr,
task_id, data, len, cache_hdr, cache_max_len);
if (!cache_hdr_len || cache_max_len < cache_hdr_len) {
goto out;
}
cache_max_len -= cache_hdr_len;
max_len = PROTO_645_FJ_RESP_DATA_MAX_LEN - PROTO_645_2007_DI_LEN;
pkt = iot_pkt_alloc(max_len, IOT_SMART_GRID_MID);
if (!pkt) {
goto out;
}
query_ul = (proto_645_fj_task_data_query_hdr_ul_t *)
iot_pkt_put(pkt, max_len);
if (cache_hdr->type == PROTO_645_FJ_TASK_TYPE_CHG_RPT) {
data_len = iot_sg_sta_ext_fj_task_chg_data_resp_by_time(addr, query_ul,
max_len, cache_hdr, msg_type, task_id);
if (!data_len || max_len < data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
goto build;
}
cache_data_len = iot_sg_sta_ext_fj_freeze_flash_data_to_cache(addr,
task_id, cache_hdr, cache_max_len);
if (!cache_data_len || cache_max_len < cache_data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
goto build;
}
cache_max_len -= cache_data_len;
data_len = (uint8_t)iot_sg_sta_ext_fj_freeze_cache_to_resp(addr, query_ul,
max_len, cache_hdr, IOT_SG_STA_EXT_FREEZR_CACHE_LEN - cache_max_len,
msg_type, task_id);
if (!data_len || max_len < data_len) {
result = PROTO_645_FJ_READ_RESP_DATA_INVALID;
}
build:
if (result == PROTO_645_FJ_READ_RESP_DATA_INVALID) {
query_ul->type = cache_hdr->type;
query_ul->result = result;
data_len = sizeof(query_ul->result) + sizeof(query_ul->type);
}
resp_pkt = proto_645_fj_build_msg(addr, (uint8_t *)query_ul, data_len,
di, PROTO_645_2007_FN_READ_DATA);
out:
if (pkt) {
iot_pkt_free(pkt);
}
if (cache_pkt) {
iot_pkt_free(cache_pkt);
}
return resp_pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_read_freeze_data(uint8_t *addr, uint32_t di,
uint8_t *data, uint8_t len, uint8_t is_simple_698, uint32_t valid_len)
{
iot_pkt_t *resp_pkt = NULL;
uint8_t *read_type, msg_type;
proto_645_fj_task_data_query_no_time_dl_t *query_no_timw;
if (!addr || !data || len <= PROTO_645_2007_DI_LEN) {
goto nack;
}
proto_645_sub33_handle(data, len);
len -= PROTO_645_2007_DI_LEN;
if (len < sizeof(*read_type)) {
goto nack;
}
read_type = data + PROTO_645_2007_DI_LEN;
if (is_simple_698) {
msg_type = IOT_SG_STA_EXT_FREEZE_BUILD_MSG_698;
} else {
msg_type = IOT_SG_STA_EXT_FREEZE_BUILD_MSG_645;
}
if (read_type[0] == PROTO_645_FJ_TASK_QR_TYPE_NOTIME) {
if (len < sizeof(*query_no_timw)) {
goto nack;
}
query_no_timw = (proto_645_fj_task_data_query_no_time_dl_t *)read_type;
resp_pkt = iot_sg_sta_ext_fj_read_freeze_data_by_idx(addr, di,
query_no_timw->last_num, msg_type);
} else if (!is_simple_698 &&
read_type[0] == PROTO_645_FJ_TASK_QR_TYPE_WITH_TIME) {
resp_pkt = iot_sg_sta_ext_fj_read_freeze_data_by_time(addr, di,
read_type, len, msg_type);
} else if (is_simple_698 &&
read_type[0] == PROTO_645_FJ_TASK_QR_TYPE_WITH_TIME2) {
resp_pkt = iot_sg_sta_ext_fj_read_freeze_data_by_time2(addr, di,
read_type, len, msg_type, valid_len);
}
if (resp_pkt) {
goto out;
}
nack:
resp_pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
out:
return resp_pkt;
}
iot_pkt_t *iot_sg_sta_ext_fj_build_single_di_read_resp(uint8_t *addr,
uint8_t *data, uint8_t len, uint32_t di, uint8_t nack)
{
iot_pkt_t *pkt = NULL;
switch (di) {
case PROTO_645_FJ_DI_QR_CHIP_ID:
{
pkt = iot_sg_sta_ext_fj_qr_chip_id(addr);
break;
}
case PROTO_645_FJ_DI_QR_MOD_ID:
{
pkt = iot_sg_sta_ext_fj_qr_mod_id(addr);
break;
}
case PROTO_645_FJ_DI_QR_MOD_VER:
{
pkt = iot_sg_sta_ext_fj_qr_mod_ver(addr);
break;
}
case PROTO_645_FJ_DI_MOD_TM:
{
pkt = iot_sg_sta_ext_fj_read_mod_tm(addr, PROTO_645_2007_FN_READ_DATA);
break;
}
case PROTO_645_FJ_DI_MOD_CT_DUR:
{
pkt = iot_sg_sta_ext_fj_read_ct_dur(addr);
break;
}
case PROTO_645_FJ_DI_MOD_LAST_CT_REC:
{
pkt = iot_sg_sta_ext_fj_read_ct_rec(addr, PROTO_645_2007_FN_READ_DATA);
break;
}
case PROTO_645_FJ_DI_MOD_TM_SOC:
{
pkt = iot_sg_sta_ext_fj_read_tm_soc(addr);
break;
}
case PROTO_645_FJ_DI_EVT_RPT_CFG:
{
pkt = iot_sg_sta_ext_fj_read_evt_rpt_cfg(addr);
break;
}
case PROTO_645_FJ_DI_QR_MOD_WORK_V:
{
pkt = iot_sg_sta_ext_fj_read_mod_work_v(addr);
break;
}
case PROTO_645_FJ_DI_SET_TASK_REC_MAX_LEN:
{
pkt = iot_sg_sta_ext_fj_read_rec_max_len(addr);
break;
}
case PROTO_645_FJ_DI_SET_RPT_MAX_CNT:
{
pkt = iot_sg_sta_ext_fj_read_rpt_max_cnt(addr);
break;
}
case PROTO_645_FJ_DI_SET_RANDOM_RPT_TIME:
{
pkt = iot_sg_sta_ext_fj_read_random_rpt_time(addr);
break;
}
case PROTO_645_FJ_DI_SET_RPT_RETRY_COUNT:
{
pkt = iot_sg_sta_ext_fj_read_rpt_retry_count(addr);
break;
}
case PROTO_645_FJ_DI_METER_MULTI_DATA_ITEM:
{
pkt = iot_sg_sta_ext_fj_read_meter_multi_data_flag(addr);
break;
}
case PROTO_645_FJ_DI_QR_TASK_STATE:
{
pkt = iot_sg_sta_ext_fj_read_task_state(addr);
break;
}
case PROTO_645_FJ_DI_SET_TASK_STOP_DUR:
{
pkt = iot_sg_sta_ext_fj_read_stop_dur(addr, 0);
break;
}
case PROTO_645_FJ_DI_UPGRADE_SEND_FILE:
{
pkt = iot_sg_sta_ext_fj_handle_send_file(addr, data, len);
break;
}
case PROTO_645_FJ_DI_UPGRADE_REQ_FILE:
{
pkt = iot_sg_sta_ext_fj_handle_query_file(addr);
break;
}
case PROTO_645_FJ_DI_QR_MODULE_RESET_CNT:
{
pkt = iot_sg_sta_ext_fj_read_reset_cnt(addr);
break;
}
case PROTO_645_FJ_DI_QR_PD_CNT:
{
pkt = iot_sg_sta_ext_fj_read_pd_cnt(addr);
break;
}
case PROTO_645_FJ_DI_PD_EVT_VALID_TIME:
{
pkt = iot_sg_sta_ext_fj_read_pd_valid_time(addr);
break;
}
case PROTO_645_FJ_DI_RPT_MODE:
{
pkt = iot_sg_sta_ext_fj_read_rpt_mode(addr);
break;
}
case PROTO_645_FJ_DI_MULTI_RPT:
{
pkt = iot_sg_sta_ext_fj_read_multi_rpt(addr);
break;
}
case PROTO_645_FJ_DI_RPT_STATUS:
{
pkt = iot_sg_sta_ext_fj_read_rpt_status(addr, 0);
break;
}
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST1:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST2:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST3:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST4:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST5:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST6:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST7:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST8:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST9:
case PROTO_645_FJ_DI_QR_POWER_RECORD_LAST10:
{
pkt = iot_sg_sta_ext_fj_read_pd_rec(addr, di);
break;
}
default:
if ((di & 0xffffff00) == PROTO_645_FJ_DI_SET_TASK) {
pkt = iot_sg_sta_ext_fj_read_task(addr, di, 0);
} else if ((di & 0xffffff00) == PROTO_645_FJ_DI_QR_TASK_DATA) {
pkt = iot_sg_sta_ext_fj_read_freeze_data(addr, di, data, len, 0, 0);
} else if (nack && ((di & 0xffff0000) == PROTO_645_FJ_DI_QR_TASK_DATA)) {
/* EBE0xxxx not support, response nack */
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
}
/* no relevant DI, forward to meter */
break;
}
return pkt;
}
static uint8_t iot_sg_sta_ext_set_data_result_check(uint8_t *data, uint32_t len)
{
uint8_t dar = PROTO_69845_APP_DAR_OTHER;
proto_645_header_t *hdr;
hdr = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
if (!hdr) {
goto out;
}
if (!hdr->control.ack) {
dar = PROTO_69845_APP_DAR_SUCCESS;
}
out:
return dar;
}
static uint8_t iot_sg_sta_ext_fj_set_data_handle(uint8_t *addr, uint32_t di,
uint8_t *data, uint8_t len)
{
uint8_t dar, buff_len, *buff_data;
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
buff_len = len + sizeof(di);
pkt_buff = iot_pkt_alloc(buff_len, IOT_SMART_GRID_MID);
if (!pkt_buff) {
goto out;
}
buff_data = iot_pkt_put(pkt_buff, buff_len);
proto_645_2007_di_to_byte(di, buff_data);
os_mem_cpy(buff_data + PROTO_645_2007_DI_LEN, data, len);
proto_645_add33_handle(buff_data, buff_len);
switch (di) {
case PROTO_645_FJ_DI_DEL_TASK:
{
pkt = iot_sg_sta_ext_fj_del_task(addr, buff_data, buff_len);
break;
}
case PROTO_645_FJ_DI_SET_TASK_REC_MAX_LEN:
{
pkt = iot_sg_sta_ext_fj_write_rec_max_len(addr, buff_data, buff_len);
break;
}
case PROTO_645_FJ_DI_SET_RPT_MAX_CNT:
{
pkt = iot_sg_sta_ext_fj_write_rpt_max_cnt(addr, buff_data, buff_len);
break;
}
case PROTO_645_FJ_DI_SET_TASK_STOP_DUR:
{
pkt = iot_sg_sta_ext_fj_write_stop_dur(addr, buff_data, buff_len, 1);
break;
}
case PROTO_645_FJ_DI_SET_RANDOM_RPT_TIME:
{
pkt = iot_sg_sta_ext_fj_write_random_rpt_time(addr, buff_data, buff_len);
break;
}
case PROTO_645_FJ_DI_SET_RPT_RETRY_COUNT:
{
pkt = iot_sg_sta_ext_fj_write_rpt_retry_count(addr, buff_data,buff_len);
break;
}
case PROTO_645_FJ_DI_TAST_RESET:
{
pkt = iot_sg_sta_ext_fj_write_task_restart(addr, buff_data, buff_len);
break;
}
case PROTO_645_FJ_DI_RPT_MODE:
{
pkt = iot_sg_sta_ext_fj_write_report_mode(addr, buff_data, buff_len);
break;
}
case PROTO_645_FJ_DI_MULTI_RPT:
{
pkt = iot_sg_sta_ext_fj_write_multi_rpt(addr, buff_data, buff_len);
break;
}
default:
if ((di & 0xffffff00) == PROTO_645_FJ_DI_SET_TASK) {
pkt = iot_sg_sta_ext_fj_write_task(addr, di, buff_data,
buff_len, 1);
}
break;
}
out:
if (pkt) {
dar = iot_sg_sta_ext_set_data_result_check(iot_pkt_data(pkt),
iot_pkt_data_len(pkt));
iot_pkt_free(pkt);
} else {
dar = PROTO_69845_APP_DAR_OTHER;
}
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return dar;
}
static iot_pkt_t *iot_iot_sg_sta_ext_set_data_resp(addr_info_t *addr_info,
proto_69845_app_piid_t *piid, proto_69845_app_oad_with_dar_t *oad_with_dar,
uint8_t oad_cnt, uint8_t is_security)
{
uint32_t len;
iot_pkt_t *pkt = NULL, *apdu_pkt = NULL;
proto_69845_apdu_t *apdu;
proto_69845_app_set_resp_t *set;
proto_69845_app_set_resp_normal_list_t *normal_list;
len = sizeof(*apdu) + sizeof(*set) + sizeof(*normal_list) +
sizeof(*oad_with_dar) * oad_cnt + PROTO_69845_NO_TIME_TAG_LEN +
PROTO_69845_NO_FLW_DATA_LEN;
apdu_pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (!apdu_pkt) {
goto out;
}
apdu = (proto_69845_apdu_t *)iot_pkt_put(apdu_pkt, len);
apdu->type = PROTO_69845_S_APP_SET_RESP;
set = (proto_69845_app_set_resp_t *)apdu->data;
set->data_type = PROTO_69845_APP_SET_NORMALLIST;
normal_list = (proto_69845_app_set_resp_normal_list_t *)set->data;
normal_list->piid_acd.sn = piid->sn;
normal_list->piid_acd.priority = piid->priority;
normal_list->oad_cnt = oad_cnt;
os_mem_cpy(normal_list->result, oad_with_dar,
sizeof(*oad_with_dar) * oad_cnt);
if (is_security) {
pkt = proto_69845_build_apdu_data_with_security_resp_msg(
(uint8_t *)apdu, len, addr_info);
} else {
pkt = proto_69845_build_apdu_data_msg((uint8_t *)apdu, len,
addr_info, PROTO_69845_D_P_SERVER_RESPONSE);
}
out:
return pkt;
}
static uint32_t iot_sg_sta_ext_fj_action_data_fill(uint8_t *data, uint32_t len,
uint8_t *fill_data, uint32_t *fill_len, uint8_t *optional,
uint32_t valid_len)
{
proto_645_header_t *hdr = NULL;
uint8_t byte_num = 0, *octet_string_len;
uint8_t *octet_string_data = 0, *data_tmp = NULL;
uint16_t data_len;
uint32_t ret = ERR_FAIL, app_data_len;
proto_69845_app_len_descript_t *len_desc;
proto_69845_app_data_t *app_data;
hdr = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
if (hdr) {
if (hdr->control.ack) {
goto out;
}
if (hdr->len < PROTO_645_2007_DI_LEN) {
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
data_len = (uint16_t)(hdr->len - PROTO_645_2007_DI_LEN);
data_tmp = hdr->data + PROTO_645_2007_DI_LEN;
} else {
data_len = (uint16_t)len;
data_tmp = data;
}
if (data_len) {
*optional = PROTO_69845_APP_OPTIONAL_DATA;
} else {
*optional = PROTO_69845_APP_OPTIONAL_NO_DATA;
ret = ERR_OK;
goto out;
}
if (data_len > 255) {
byte_num = 2;
} else if (data_len > 127) {
byte_num = 1;
} else {
byte_num = 0;
}
app_data_len = data_len + sizeof(*app_data) + sizeof(*len_desc) + byte_num;
if (valid_len < app_data_len) {
goto out;
}
(*fill_len) += app_data_len;
app_data = (proto_69845_app_data_t *)fill_data;
app_data->data_type = PROTO_69845_APP_DATA_OCTET_STRING;
len_desc = (proto_69845_app_len_descript_t *)app_data->data;
if (byte_num == 1) {
len_desc->mub_flag = 1;
len_desc->byte_num = 1;
octet_string_len = (uint8_t *)len_desc + 1;
*octet_string_len = (uint8_t)data_len;
octet_string_data = octet_string_len + byte_num;
} else if (byte_num == 2) {
len_desc->mub_flag = 1;
len_desc->byte_num = 2;
octet_string_len = (uint8_t *)len_desc + 1;
iot_uint16_to_bytes(data_len, octet_string_len, 1);
octet_string_data = octet_string_len + byte_num;
} else {
len_desc->mub_flag = 0;
len_desc->byte_num = (uint8_t)data_len;
octet_string_data = (uint8_t *)len_desc + 1;
}
os_mem_cpy(octet_string_data, data_tmp, data_len);
ret = ERR_OK;
out:
return ret;
}
static uint8_t iot_sg_sta_ext_fj_action_data_handle(uint8_t *addr, uint32_t di,
uint8_t *data, uint8_t len, uint8_t *fill_data, uint32_t *fill_len,
uint8_t *optional, uint32_t valid_len)
{
uint32_t valid_len_tmp;
uint8_t dar = PROTO_69845_APP_DAR_OTHER, buff_len, *buff_data;
iot_pkt_t *pkt = NULL, *pkt_buff = NULL;
buff_len = len + sizeof(di);
pkt_buff = iot_pkt_alloc(buff_len, IOT_SMART_GRID_MID);
if (!pkt_buff) {
goto out;
}
buff_data = iot_pkt_put(pkt_buff, buff_len);
proto_645_2007_di_to_byte(di, buff_data);
os_mem_cpy(buff_data + PROTO_645_2007_DI_LEN, data, len);
proto_645_add33_handle(buff_data, buff_len);
switch (di) {
case PROTO_645_FJ_DI_SET_TASK_REC_MAX_LEN:
{
pkt = iot_sg_sta_ext_fj_read_rec_max_len(addr);
break;
}
case PROTO_645_FJ_DI_SET_RPT_MAX_CNT:
{
pkt = iot_sg_sta_ext_fj_read_rpt_max_cnt(addr);
break;
}
case PROTO_645_FJ_DI_QR_TASK_STATE:
{
pkt = iot_sg_sta_ext_fj_read_task_state(addr);
break;
}
case PROTO_645_FJ_DI_SET_TASK_STOP_DUR:
{
pkt = iot_sg_sta_ext_fj_read_stop_dur(addr, 1);
break;
}
case PROTO_645_FJ_DI_SET_RANDOM_RPT_TIME:
{
pkt = iot_sg_sta_ext_fj_read_random_rpt_time(addr);
break;
}
case PROTO_645_FJ_DI_SET_RPT_RETRY_COUNT:
{
pkt = iot_sg_sta_ext_fj_read_rpt_retry_count(addr);
break;
}
case PROTO_645_FJ_DI_METER_MULTI_DATA_ITEM:
{
pkt = iot_sg_sta_ext_fj_read_meter_multi_data_flag(addr);
break;
}
case PROTO_645_FJ_DI_RPT_MODE:
{
pkt = iot_sg_sta_ext_fj_read_rpt_mode(addr);
break;
}
case PROTO_645_FJ_DI_MULTI_RPT:
{
pkt = iot_sg_sta_ext_fj_read_multi_rpt(addr);
break;
}
case PROTO_645_FJ_DI_RPT_STATUS:
{
pkt = iot_sg_sta_ext_fj_read_rpt_status(addr, 1);
break;
}
default:
if ((di & 0xffffff00) == PROTO_645_FJ_DI_SET_TASK) {
pkt = iot_sg_sta_ext_fj_read_task(addr, di, 1);
} else if ((di & 0xffffff00) == PROTO_645_FJ_DI_QR_TASK_DATA) {
valid_len_tmp = valid_len - sizeof(proto_69845_app_data_t) -
sizeof(proto_69845_app_len_descript_t) -
IOT_SG_STA_EXT_698_LEN_BYTE_MAX_NUM;
pkt = iot_sg_sta_ext_fj_read_freeze_data(addr, di, buff_data,
buff_len, 1, valid_len_tmp);
}
break;
}
if (!pkt) {
goto out;
}
if (iot_sg_sta_ext_fj_action_data_fill(iot_pkt_data(pkt),
iot_pkt_data_len(pkt), fill_data, fill_len, optional,
valid_len) == ERR_OK) {
dar = PROTO_69845_APP_DAR_SUCCESS;
}
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
if (pkt) {
iot_pkt_free(pkt);
}
return dar;
}
iot_pkt_t *iot_sg_sta_ext_fj_security_handle(
proto_69845_frame_head_info_t *hdr_698, uint8_t *data, uint32_t data_len)
{
uint8_t *data_tmp;
uint16_t sec_len;
iot_pkt_t *resp_pkt = NULL;
proto_69845_app_sec_req_resp_info_t *sec_req;
proto_69845_app_len_descript_t *len_desc;
proto_69845_app_req_resp_t *req;
if (data_len < sizeof(*sec_req)) {
goto out;
}
data_len -= sizeof(*sec_req);
sec_req = (proto_69845_app_sec_req_resp_info_t*)data;
if (sec_req->type != PROTO_69845_SEC_DATA_TYPE_PLAINTEXT) {
goto out;
}
len_desc = (proto_69845_app_len_descript_t *)((uint8_t *)sec_req + 1);
if (!len_desc->mub_flag) {
data_tmp = sec_req->data;
sec_len = sec_req->len;
} else {
if (len_desc->byte_num == 1) {
sec_len = sec_req->data[0];
data_tmp = sec_req->data + 1;
data_len -= 1;
} else if (len_desc->byte_num == 2) {
sec_len = iot_bytes_to_uint16(sec_req->data, 1);
data_tmp = sec_req->data + 2;
data_len -= 2;
} else {
goto out;
}
}
if (data_len < sec_len) {
goto out;
}
if (sec_len < sizeof(*req)) {
goto out;
}
sec_len -= sizeof(*req);
req = (proto_69845_app_req_resp_t*)data_tmp;
switch (req->type) {
case PROTO_69845_C_APP_SET_REQ:
{
resp_pkt = iot_sg_sta_ext_fj_set_handle(hdr_698, req->data,
sec_len, 1);
break;
}
case PROTO_69845_C_APP_ACTION_REQ:
{
resp_pkt = iot_sg_sta_ext_fj_action_handle(hdr_698, req->data,
sec_len, 1);
break;
}
default:
break;
}
out:
return resp_pkt;
}
iot_pkt_t *iot_sg_sta_ext_fj_action_handle(proto_69845_frame_head_info_t *hdr_698,
uint8_t *data, uint32_t data_len, uint8_t is_security)
{
iot_pkt_t *pkt = NULL, *pkt_result = NULL;
uint8_t *ptr = data, i, *oad_data;
uint16_t pkt_result_len = IOT_SG_STA_EXT_FREEZR_CACHE_LEN;
uint32_t len = data_len, di, oad_data_len = 0, fill_len = 0;
proto_69845_app_action_req_t *req;
proto_69845_app_action_resp_t *resp;
proto_69845_app_action_req_list_t *req_lis;
proto_69845_app_action_resp_normal_list_t *resp_list = NULL;
proto_69845_app_omd_with_data_t *omd_with_data;
proto_69845_app_omd_with_dar_t *omd_with_dar;
proto_69845_app_len_descript_t *len_desc;
proto_69845_apdu_t *apdu = NULL;
addr_info_t addr_info = { 0 };
proto_69845_get_addr_info(hdr_698, &addr_info);
if (iot_mac_addr_cmp(addr_info.ser_info.addr, proto_645_bcast_addr)
|| ((addr_info.ser_info.type == PROTO_69845_SA_TYPE_BROADCAST)
&& (addr_info.ser_info.addr[0] == PROTO_69845_SA_BROADCAST_ADD))) {
/* broadcast command not supported */
goto out;
}
if (len < sizeof(*req)) {
iot_sg_printf("%s err\n", __FUNCTION__);
goto out;
}
ptr += sizeof(*req);
len -= sizeof(*req);
req = (proto_69845_app_action_req_t*)data;
if (req->data_type != PROTO_69845_APP_ACTION_NORMALLIST) {
goto out;
}
if (len < sizeof(*req_lis)) {
goto out;
}
ptr += sizeof(*req_lis);
len -= sizeof(*req_lis);
req_lis = (proto_69845_app_action_req_list_t *)req->data;
if (!req_lis->omd_cnt) {
goto out;
}
for (i = 0; i < req_lis->omd_cnt; i++) {
if (fill_len + sizeof(*omd_with_dar) > pkt_result_len) {
break;
}
omd_with_data = (proto_69845_app_omd_with_data_t *)ptr;
if (len < sizeof(*omd_with_data)) {
goto out;
}
ptr += sizeof(*omd_with_data);
len -= sizeof(*omd_with_data);
di = iot_bytes_to_uint32((uint8_t*)&omd_with_data->omd, 1);
if (i == 0 && ((di & 0XFF000000) != PROTO_645_FJ_DI_FREEZE_TASK)) {
goto out;
}
if (!pkt_result) {
pkt_result = iot_pkt_alloc(pkt_result_len, IOT_SMART_GRID_MID);
if (!pkt_result) {
goto out;
}
apdu = (proto_69845_apdu_t *)iot_pkt_put(pkt_result, pkt_result_len);
apdu->type = PROTO_69845_S_APP_ACTION_RESP;
resp = (proto_69845_app_action_resp_t *)apdu->data;
resp->data_type = PROTO_69845_APP_ACTION_NORMALLIST;
resp_list = (proto_69845_app_action_resp_normal_list_t *)resp->data;
resp_list->piid_acd.sn = req_lis->piid.sn;
resp_list->piid_acd.priority = req_lis->piid.priority;
fill_len += (sizeof(*apdu) + sizeof(*resp) + sizeof(*resp_list));
pkt_result_len -= (PROTO_69845_NO_FLW_DATA_LEN +
PROTO_69845_NO_TIME_TAG_LEN);
}
omd_with_dar = (proto_69845_app_omd_with_dar_t *)
(iot_pkt_data(pkt_result) + fill_len);
omd_with_dar->omd = omd_with_data->omd;
if (omd_with_data->data.data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
goto out;
}
if (len < sizeof(*len_desc)) {
goto out;
}
if (proto_69845_get_data_len(&omd_with_data->data,
len, &oad_data_len) != ERR_OK) {
goto out;
}
ptr += sizeof(*len_desc);
len -= sizeof(*len_desc);
len_desc = (proto_69845_app_len_descript_t *)omd_with_data->data.data;
oad_data = omd_with_data->data.data;
oad_data += sizeof(*len_desc);
oad_data_len -= (sizeof(omd_with_data->data) + sizeof(*len_desc));
if (len_desc->mub_flag) {
len -= len_desc->byte_num;
ptr += len_desc->byte_num;
oad_data += len_desc->byte_num;
oad_data_len -= len_desc->byte_num;
}
if (len < oad_data_len) {
goto out;
}
len -= oad_data_len;
ptr += oad_data_len;
fill_len += sizeof(*omd_with_dar);
resp_list->omd_cnt++;
omd_with_dar->dar = iot_sg_sta_ext_fj_action_data_handle(
addr_info.ser_info.addr, di, oad_data, (uint8_t)oad_data_len,
omd_with_dar->data, &fill_len, &omd_with_dar->optional,
pkt_result_len - fill_len);
}
fill_len += (PROTO_69845_NO_FLW_DATA_LEN + PROTO_69845_NO_TIME_TAG_LEN);
if (is_security) {
pkt = proto_69845_build_apdu_data_with_security_resp_msg(
(uint8_t *)apdu, fill_len, &addr_info);
} else {
pkt = proto_69845_build_apdu_data_msg((uint8_t *)apdu, fill_len,
&addr_info, PROTO_69845_D_P_SERVER_RESPONSE);
}
out:
if (pkt_result) {
iot_pkt_free(pkt_result);
}
return pkt;
}
iot_pkt_t *iot_sg_sta_ext_fj_set_handle(proto_69845_frame_head_info_t *hdr_698,
uint8_t *data, uint32_t data_len, uint8_t is_security)
{
iot_pkt_t *pkt = NULL, *pkt_result = NULL;
uint8_t *ptr = data, i, pkt_result_len, *oad_data, addr[IOT_MAC_ADDR_LEN];
uint32_t len = data_len, di, oad_data_len = 0;
proto_69845_app_set_req_t *set;
proto_69845_app_set_req_normal_list_t *normal_list;
proto_69845_app_oad_with_data_t *oad_with_data;
proto_69845_app_oad_with_dar_t *oad_with_dar = NULL;
proto_69845_app_len_descript_t *len_desc;
addr_info_t addr_info = { 0 };
proto_69845_get_addr_info(hdr_698, &addr_info);
if ((addr_info.ser_info.type == PROTO_69845_SA_TYPE_BROADCAST)
&& (addr_info.ser_info.addr[0] == PROTO_69845_SA_BROADCAST_ADD)) {
iot_mac_addr_cpy(addr, proto_645_bcast_addr);
} else {
iot_mac_addr_cpy(addr, addr_info.ser_info.addr);
}
if (len < sizeof(*set)) {
iot_sg_printf("%s err\n", __FUNCTION__);
goto out;
}
ptr += sizeof(*set);
len -= sizeof(*set);
set = (proto_69845_app_set_req_t*)data;
if (set->data_type != PROTO_69845_APP_SET_NORMALLIST) {
goto out;
}
if (len < sizeof(*normal_list)) {
goto out;
}
ptr += sizeof(*normal_list);
len -= sizeof(*normal_list);
normal_list = (proto_69845_app_set_req_normal_list_t *)set->data;
if (!normal_list->oad_cnt) {
goto out;
}
for (i = 0; i < normal_list->oad_cnt; i++) {
oad_with_data = (proto_69845_app_oad_with_data_t *)ptr;
if (len < sizeof(*oad_with_data)) {
goto out;
}
ptr += sizeof(*oad_with_data);
len -= sizeof(*oad_with_data);
di = iot_bytes_to_uint32((uint8_t*)&oad_with_data->oad, 1);
if (i == 0 && ((di & 0XFF000000) != PROTO_645_FJ_DI_FREEZE_TASK)) {
goto out;
}
if (!pkt_result) {
pkt_result_len = normal_list->oad_cnt * sizeof(*oad_with_dar);
pkt_result = iot_pkt_alloc(pkt_result_len, IOT_SMART_GRID_MID);
if (!pkt_result) {
goto out;
}
oad_with_dar = (proto_69845_app_oad_with_dar_t *)
iot_pkt_put(pkt_result, pkt_result_len);
}
oad_with_dar[i].oad = oad_with_data->oad;
if (oad_with_data->data.data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
goto out;
}
if (len < sizeof(*len_desc)) {
goto out;
}
if (proto_69845_get_data_len(&oad_with_data->data,
len, &oad_data_len) != ERR_OK) {
goto out;
}
ptr += sizeof(*len_desc);
len -= sizeof(*len_desc);
len_desc = (proto_69845_app_len_descript_t *)oad_with_data->data.data;
oad_data = oad_with_data->data.data;
oad_data += sizeof(*len_desc);
oad_data_len -= (sizeof(oad_with_data->data) + sizeof(*len_desc));
if (len_desc->mub_flag) {
len -= len_desc->byte_num;
ptr += len_desc->byte_num;
oad_data += len_desc->byte_num;
oad_data_len -= len_desc->byte_num;
}
if (len < oad_data_len) {
goto out;
}
len -= oad_data_len;
ptr += oad_data_len;
oad_with_dar[i].dar = iot_sg_sta_ext_fj_set_data_handle(
addr, di, oad_data, (uint8_t)oad_data_len);
}
pkt = iot_iot_sg_sta_ext_set_data_resp(&addr_info, &normal_list->piid,
oad_with_dar, normal_list->oad_cnt, is_security);
out:
if (pkt_result) {
iot_pkt_free(pkt_result);
}
return pkt;
}
static iot_pkt_t *iot_sg_sta_ext_fj_build_multi_di_read_resp(uint8_t *addr,
uint8_t *data, uint8_t len)
{
uint8_t i, resp_data_len = 0, fill_len, req_di[PROTO_645_2007_DI_LEN];
uint8_t *req_list_data, *fill_data, reason = 0;
iot_pkt_t *pkt = NULL, *resp_pkt = NULL, *single_di_pkt;
proto_645_fj_multi_di_read_t *req_read, *resp_read;
proto_645_fj_multi_di_list_t *req_list, *resp_list;
proto_645_header_t *hdr;
if (!addr || !data || len <= PROTO_645_2007_DI_LEN) {
reason = 1;
goto nack;
}
proto_645_sub33_handle(data, len);
len -= PROTO_645_2007_DI_LEN;
if (len < sizeof(*req_read)) {
reason = 2;
goto nack;
}
len -= sizeof(*req_read);
req_read = (proto_645_fj_multi_di_read_t *)(data + PROTO_645_2007_DI_LEN);
if (req_read->di_cnt < PROTO_645_FJ_MULTI_DI_MIN_CNT ||
req_read->di_cnt > PROTO_645_FJ_MULTI_DI_MAX_CNT) {
reason = 3;
goto nack;
}
req_list_data = req_read->di_list;
pkt = iot_pkt_alloc(PROTO_645_FJ_MULTI_DI_RESP_MAX_LEN,
IOT_SMART_GRID_MID);
if (!pkt) {
reason = 4;
goto nack;
}
resp_read = (proto_645_fj_multi_di_read_t *)iot_pkt_data(pkt);
resp_data_len += sizeof(*resp_read);
for (i = 0; i < req_read->di_cnt; i++) {
if (len < sizeof(*req_list)) {
reason = 5;
goto nack;
}
req_list = (proto_645_fj_multi_di_list_t *)req_list_data;
if (req_list->len < PROTO_645_FJ_MULTI_DI_DATA_MIN_LEN ||
req_list->len > PROTO_645_FJ_MULTI_DI_DATA_MAX_LEN) {
reason = 6;
goto nack;
}
len -= sizeof(*req_list);
if (req_list->len > len) {
reason = 7;
goto nack;
}
len -= req_list->len;
req_list_data += (req_list->len + sizeof(*req_list));
os_mem_cpy(req_di, req_list->data, PROTO_645_2007_DI_LEN);
proto_645_add33_handle(req_list->data, req_list->len);
single_di_pkt = iot_sg_sta_ext_fj_build_single_di_read_resp(addr,
req_list->data, req_list->len, proto_645_2007_byte_to_di(req_di), 0);
if (single_di_pkt) {
hdr = proto_645_format_check(iot_pkt_data(single_di_pkt),
iot_pkt_data_len(single_di_pkt), PROTO_645_DIR_SLAVE);
if (hdr && hdr->control.ack == PROTO_645_ACK_NORMAL) {
fill_data = hdr->data;
fill_len = hdr->len;
proto_645_sub33_handle(fill_data, fill_len);
} else {
fill_data = req_di;
fill_len = PROTO_645_2007_DI_LEN;
}
} else {
fill_data = req_di;
fill_len = PROTO_645_2007_DI_LEN;
}
if (sizeof(*resp_list) + fill_len + resp_data_len >
PROTO_645_FJ_MULTI_DI_RESP_MAX_LEN) {
if (single_di_pkt) {
iot_pkt_free(single_di_pkt);
}
break;
}
resp_list = (proto_645_fj_multi_di_list_t *)((uint8_t *)resp_read +
resp_data_len);
resp_list->len = fill_len;
resp_data_len += sizeof(resp_list->len);
os_mem_cpy(resp_list->data, fill_data, fill_len);
resp_data_len += fill_len;
resp_read->di_cnt++;
if (single_di_pkt) {
iot_pkt_free(single_di_pkt);
}
}
resp_pkt = proto_645_fj_build_msg(addr, (uint8_t *)resp_read,
resp_data_len, PROTO_645_FJ_MULTI_DI_READ, PROTO_645_2007_FN_READ_DATA);
goto out;
nack:
resp_pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
PROTO_645_2007_FN_READ_DATA);
iot_sg_printf("%s nack reason %d\n", __FUNCTION__, reason);
out:
if (pkt) {
iot_pkt_free(pkt);
}
return resp_pkt;
}
void iot_sg_sta_ext_fj_power_up_down_record_handle(uint8_t type)
{
uint8_t is_overlast = 0;
uint32_t ret, reason = 0;
int64_t run_time, delay_time;
uint16_t power_down_cnt = 0;
iot_time_tm_t tm, tm_power_down;
iot_sg_sta_flash_fj_pwr_rec_t record = {0};
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (iot_sg_sta_get_user_type() != USER_TYPE_STATE_GRID_FUJIAN) {
goto out;
}
if (type == IOT_SG_STA_POWER_REC_TYPE_CLEAR) {
iot_sg_sta_flash_fj_pwr_record_clear();
goto out;
}
ret = iot_sg_sta_flash_fj_pwr_record_get(&record, 1);
if (type == IOT_SG_STA_POWER_REC_TYPE_UP) {
/* power on event */
if (ret || record.flag_valid_power_on == 1) {
/**
* if there is no power off record or power on record already
* exists, the power on record will not be modify.
*/
reason = 1;
goto drop;
}
if(sta_glb->tm_soc == PROTO_645_FJ_MOD_TM_SOC_NET)
{
if (iot_sg_sta_rtc_get(&tm, 1) != ERR_OK) {
reason = 2;
goto drop;
}
} else {
if (iot_sg_sta_rtc_get(&tm, 0) != ERR_OK) {
reason = 3;
goto drop;
}
}
iot_sg_printf("%s record 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_power_off_check()) {
/**
* While power in normal,
* Set the system startup time as power on time.
*/
run_time = os_boot_time64() / 1000;
/**
* The time interval between the power on of the processing module
* and the start of the program.
*/
run_time += IOT_SG_STA_POWER_UP_CHARGING_TIME;
iot_rtc_delta_add(-run_time, &tm);
}
tm_power_down.tm_year = record.power_off_year + 2000;
tm_power_down.tm_mon = (uint8_t)record.power_off_month;
tm_power_down.tm_mday = (uint8_t)record.power_off_day;
tm_power_down.tm_hour = (uint8_t)record.power_off_hour;
tm_power_down.tm_min = (uint8_t)record.power_off_minute;
tm_power_down.tm_sec = (uint8_t)record.power_off_second;
if (iot_rtc_delta_calc(&tm_power_down, &tm) < 0) {
os_mem_set(&tm, 0, sizeof(tm));
tm.tm_year = 2000;
tm.tm_mon = 1;
tm.tm_mday = 1;
}
record.power_on_year = (uint8_t)(tm.tm_year - 2000);
record.power_on_month = tm.tm_mon;
record.power_on_day = tm.tm_mday;
record.power_on_hour = tm.tm_hour;
record.power_on_minute = tm.tm_min;
record.power_on_second = tm.tm_sec;
record.flag_valid_power_on = 1;
is_overlast = 1;
iot_sg_printf("%s power up[%lu] %lu-%lu-%lu %lu:%lu:%lu\n",
__FUNCTION__, sta_glb->tm_soc, tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
} else if (type == IOT_SG_STA_POWER_REC_TYPE_DOWN) {
if (ret == ERR_OK) {
power_down_cnt = record.power_down_cnt;
}
os_mem_set((uint8_t *)&record, 0x0, sizeof(record));
if (sta_glb->tm_soc == PROTO_645_FJ_MOD_TM_SOC_NET) {
ret = iot_sg_sta_rtc_get(&tm, 1);
} else {
ret = iot_sg_sta_rtc_get(&tm, 0);
}
if (ret == ERR_OK) {
/* Calculate the time when the power down occurred */
delay_time = sta_glb->evt.fj_pd_valid_time +
IOT_SG_STA_POWER_DOWN_DETECTED_LAG_TIME;
iot_rtc_delta_add(-delay_time, &tm);
} else {
os_mem_set(&tm, 0, sizeof(tm));
tm.tm_year = 2000;
tm.tm_mon = 1;
tm.tm_mday = 1;
}
record.power_off_year = (uint8_t)(tm.tm_year - 2000);
record.power_off_month = tm.tm_mon;
record.power_off_day = tm.tm_mday;
record.power_off_hour = tm.tm_hour;
record.power_off_minute = tm.tm_min;
record.power_off_second = tm.tm_sec;
record.flag_valid_power_off = 1;
record.flag_valid_power_on = 0;
record.power_down_cnt = power_down_cnt + 1;
iot_sg_printf("%s power down[%lu] %lu-%lu-%lu %lu:%lu:%lu\n",
__FUNCTION__, sta_glb->tm_soc, tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
} else {
reason = 6;
goto drop;
}
iot_sg_sta_flash_fj_pwr_record_save(&record, is_overlast);
goto out;
drop:
iot_sg_printf("%s drop %lu\n", __FUNCTION__, reason);
out:
return;
}
iot_pkt_t *iot_sg_sta_ext_fj_func(uint8_t *addr, uint8_t fn,
uint32_t di, uint8_t *data, uint8_t len)
{
iot_pkt_t *pkt = NULL;
iot_sg_printf("%s fn:%02x di:%08x\n", __FUNCTION__, fn, di);
switch (fn) {
case PROTO_645_2007_FN_READ_DATA:
{
if (di == PROTO_645_FJ_MULTI_DI_READ) {
pkt = iot_sg_sta_ext_fj_build_multi_di_read_resp(addr, data, len);
} else {
pkt = iot_sg_sta_ext_fj_build_single_di_read_resp(addr, data, len,
di, 1);
}
break;
}
case PROTO_645_2007_FN_WRITE_DATA:
{
switch (di) {
case PROTO_645_FJ_DI_MOD_TM:
{
pkt = iot_sg_sta_ext_fj_write_mod_tm(addr, fn, data, len);
break;
}
case PROTO_645_FJ_DI_MOD_CT_DUR:
{
pkt = iot_sg_sta_ext_fj_write_ct_dur(addr, fn, data, len);
break;
}
case PROTO_645_FJ_DI_MOD_CT_NTB:
{
pkt = iot_sg_sta_ext_fj_ntb_ct(addr, fn, data, len);
break;
}
case PROTO_645_FJ_DI_MOD_TM_SOC:
{
pkt = iot_sg_sta_ext_fj_write_tm_soc(addr, fn, data, len);
break;
}
case PROTO_645_FJ_DI_EVT_RPT_CFG:
{
pkt = iot_sg_sta_ext_fj_write_evt_rpt_cfg(addr, data, len);
break;
}
case PROTO_645_FJ_DI_DEL_TASK:
{
pkt = iot_sg_sta_ext_fj_del_task(addr, data, len);
break;
}
case PROTO_645_FJ_DI_SET_TASK_REC_MAX_LEN:
{
pkt = iot_sg_sta_ext_fj_write_rec_max_len(addr, data, len);
break;
}
case PROTO_645_FJ_DI_SET_RPT_MAX_CNT:
{
pkt = iot_sg_sta_ext_fj_write_rpt_max_cnt(addr, data, len);
break;
}
case PROTO_645_FJ_DI_SET_RANDOM_RPT_TIME:
{
pkt = iot_sg_sta_ext_fj_write_random_rpt_time(addr, data, len);
break;
}
case PROTO_645_FJ_DI_TAST_RESET:
{
pkt = iot_sg_sta_ext_fj_write_task_restart(addr, data, len);
break;
}
case PROTO_645_FJ_DI_RPT_MODE:
{
pkt = iot_sg_sta_ext_fj_write_report_mode(addr, data, len);
break;
}
case PROTO_645_FJ_DI_MULTI_RPT:
{
pkt = iot_sg_sta_ext_fj_write_multi_rpt(addr, data, len);
break;
}
case PROTO_645_FJ_DI_SET_RPT_RETRY_COUNT:
{
pkt = iot_sg_sta_ext_fj_write_rpt_retry_count(addr, data,len);
break;
}
case PROTO_645_FJ_DI_METER_MULTI_DATA_ITEM:
{
pkt = iot_sg_sta_ext_fj_write_meter_multi_data_flag(addr, data, len);
break;
}
case PROTO_645_FJ_DI_SET_TASK_STOP_DUR:
{
pkt = iot_sg_sta_ext_fj_write_stop_dur(addr, data, len, 0);
break;
}
case PROTO_645_FJ_DI_PD_EVT_VALID_TIME:
{
pkt = iot_sg_sta_ext_fj_write_pd_valid_time(addr, data, len);
break;
}
default:
if ((di & 0xffffff00) == PROTO_645_FJ_DI_SET_TASK) {
pkt = iot_sg_sta_ext_fj_write_task(addr, di, data, len, 0);
} else if ((di & 0xffff0000) == PROTO_645_FJ_DI_QR_TASK_DATA) {
/* EBE0xxxx not support, response nack */
pkt = proto_645_2007_build_nack_msg(PROTO_645_FJ_ERR_OTHER, addr,
PROTO_645_2007_FN_WRITE_DATA);
}
/* no relevant DI, forward to meter */
break;
}
break;
}
case PROTO_645_2007_FN_READ_DATA_C:
{
/* todo */
break;
}
default:
/* no relevant FN, forward to meter */
break;
}
return pkt;
}
void iot_sg_sta_fj_tm_cfg_init(void)
{
iot_pkt_t *ct_cfg_pkt = NULL;
iot_sg_sta_flash_fj_ct_cfg_t *ct_cfg;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
ct_cfg_pkt =
iot_pkt_alloc(sizeof(iot_sg_sta_flash_fj_ct_cfg_t), IOT_SMART_GRID_MID);
if (ct_cfg_pkt == NULL) {
/* native use default value */
sta_glb->tm_soc = PROTO_645_FJ_MOD_TM_SOC_NET;
sta_glb->ct_dur = PROTO_645_FJ_MOD_CT_DUR_DEFAULT;
goto out;
}
ct_cfg = (iot_sg_sta_flash_fj_ct_cfg_t *)iot_pkt_data(ct_cfg_pkt);
if (iot_sg_sta_flash_fj_ct_cfg_get(ct_cfg) != ERR_OK) {
goto def;
}
sta_glb->tm_soc = ct_cfg->tm_soc;
sta_glb->ct_dur = ct_cfg->ct_dur;
goto out;
def:
/* native use default value */
sta_glb->tm_soc = PROTO_645_FJ_MOD_TM_SOC_NET;
sta_glb->ct_dur = PROTO_645_FJ_MOD_CT_DUR_DEFAULT;
/* save default value to flash */
ct_cfg->tm_soc = PROTO_645_FJ_MOD_TM_SOC_NET;
ct_cfg->ct_dur = PROTO_645_FJ_MOD_CT_DUR_DEFAULT;
iot_sg_sta_flash_fj_ct_cfg_save(ct_cfg);
out:
if (ct_cfg_pkt) {
iot_pkt_free(ct_cfg_pkt);
}
return;
}
void iot_sg_sta_fj_evt_rpt_init(void)
{
iot_sg_sta_evt_global_t *evt_glb = &p_sg_glb->desc.sta->evt;
iot_sg_sta_flash_fj_evt_rpt_cfg_t *fj_evt_cfg;
iot_pkt_t *pkt = NULL;
pkt = iot_pkt_alloc(sizeof(*fj_evt_cfg), IOT_SMART_GRID_MID);
if (!pkt) {
return;
};
fj_evt_cfg = (iot_sg_sta_flash_fj_evt_rpt_cfg_t *)iot_pkt_put(
pkt, sizeof(*fj_evt_cfg));
if (iot_sg_sta_flash_fj_evt_rpt_cfg_get(fj_evt_cfg) == ERR_OK) {
evt_glb->fj_evt_rpt_mode = fj_evt_cfg->fj_evt_rpt_mode;
evt_glb->fj_evt_rpt_type = fj_evt_cfg->fj_evt_rpt_type;
evt_glb->fj_evt_rpt_en = fj_evt_cfg->fj_evt_rpt_en;
} else {
/* default is IOT_SG_STA_FJ_EVT_RPT_TYPE_OCCUR */
evt_glb->fj_evt_rpt_type = IOT_SG_STA_FJ_EVT_RPT_TYPE_OCCUR;
/* default is IOT_SG_STA_FJ_EVT_RPT_MODE_EXT */
evt_glb->fj_evt_rpt_mode = IOT_SG_STA_FJ_EVT_RPT_MODE_EXT;
/* default is 1, event report enable when report mode is fujian ext */
evt_glb->fj_evt_rpt_en = 1;
fj_evt_cfg->fj_evt_rpt_mode = evt_glb->fj_evt_rpt_mode;
fj_evt_cfg->fj_evt_rpt_type = evt_glb->fj_evt_rpt_type;
fj_evt_cfg->fj_evt_rpt_en = evt_glb->fj_evt_rpt_en;
iot_sg_sta_flash_fj_evt_rpt_cfg_save(fj_evt_cfg);
}
iot_printf("%s - mode %lu, type %lu, enable %lu\n", __FUNCTION__,
evt_glb->fj_evt_rpt_mode, evt_glb->fj_evt_rpt_type,
evt_glb->fj_evt_rpt_en);
iot_pkt_free(pkt);
return;
}
void iot_sg_sta_fj_pd_cfg_init(void)
{
iot_sg_sta_evt_global_t *evt_glb = &p_sg_glb->desc.sta->evt;
iot_sg_sta_flash_fj_pwr_rpt_cfg_t *cfg;
iot_pkt_t *pkt;
pkt = iot_pkt_alloc(sizeof(*cfg), IOT_SMART_GRID_MID);
if (!pkt) {
evt_glb->fj_pd_valid_time = IOT_SG_STA_FJ_PD_EVT_VALID_TIME_DFT;
return;
}
cfg = (iot_sg_sta_flash_fj_pwr_rpt_cfg_t *)iot_pkt_put(pkt, sizeof(*cfg));
if (iot_sg_sta_flash_fj_pwr_rpt_cfg_get(cfg) == ERR_OK) {
evt_glb->fj_pd_valid_time = cfg->pd_valid_time;
} else {
/* default is 5, IOT_SG_STA_FJ_PD_EVT_VALID_TIME_DFT */
evt_glb->fj_pd_valid_time = IOT_SG_STA_FJ_PD_EVT_VALID_TIME_DFT;
cfg->pd_valid_time = evt_glb->fj_pd_valid_time;
iot_sg_sta_flash_fj_pwr_rpt_cfg_save(cfg);
}
iot_pkt_free(pkt);
}
#endif /* IOT_SMART_GRID_EXT_FJ_FUNC_ENABLE */