4366 lines
130 KiB
C
Executable File
4366 lines
130 KiB
C
Executable File
/****************************************************************************
|
|
|
|
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 ship includes */
|
|
#include "os_mem_api.h"
|
|
|
|
/* common includes */
|
|
#include "iot_config_api.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_utils_api.h"
|
|
#include "iot_io_api.h"
|
|
|
|
/* protocol includes */
|
|
#include "proto_crc16.h"
|
|
#include "proto_645.h"
|
|
#include "proto_69845.h"
|
|
|
|
/* smart grid internal header files */
|
|
#include "iot_sg_cco_drv_api.h"
|
|
#include "iot_sg_fr.h"
|
|
|
|
#define PROTO_69845_DATA_DESC_LIST_MAX 40
|
|
#define PROTO_69845_ELEMENT_DATA_RECURSION_CNT_MAX 4
|
|
#define PROTO_69845_TANS_BAUD_MAX 11
|
|
#define PORTO_645_BAUD_ID_AUTO 255
|
|
|
|
const uint8_t proto_69845_preamble[PROTO_69845_PREAMBLE_LEN] =
|
|
{ 0xFE, 0xFE, 0xFE, 0xFE };
|
|
|
|
const server_addr_info_t proto_69845_any_server_addr =
|
|
{
|
|
.len = PROTO_69845_SA_LEN,
|
|
.type = PROTO_69845_SA_TYPE_WILDCARD,
|
|
.addr = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF},
|
|
.logical_addr = 0
|
|
};
|
|
|
|
const uint8_t proto_69845_event_report_data[PROTO_69845_EVENT_DATA_LEN] = {
|
|
0x34, 0x48, 0x33, 0x37, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
|
0x33, 0x33, 0x33, 0x33, 0xdd, 0xdd};
|
|
|
|
const uint8_t proto_69845_rn[PROTO_69845_SECURITY_RN_LEN] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00};
|
|
|
|
const uint32_t proto_69845_tans_baud[PROTO_69845_TANS_BAUD_MAX] = {
|
|
300, 600, 1200, 2400, 4800, 7200, 9600, 19200, 38400, 57600, 115200};
|
|
|
|
const proto_69845_app_data_desc_t proto_69845_data_desc_list[ \
|
|
PROTO_69845_DATA_DESC_LIST_MAX] = {
|
|
{
|
|
PROTO_69845_APP_DATA_NULL,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_ARRAY,
|
|
PROTO_69845_DATA_LEN_TYPE_ELEMENT,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_STRUCTURE,
|
|
PROTO_69845_DATA_LEN_TYPE_ELEMENT,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_BOOL,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
1,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_BIT_STRING,
|
|
PROTO_69845_DATA_LEN_TYPE_DIV8,
|
|
0
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_DOUBLE_LONG,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
4,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
4,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_OCTET_STRING,
|
|
PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_VISIBLE_STRING,
|
|
PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_UTF8_SRTING,
|
|
PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_INTEGER,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
1,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_LONG,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
2,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_UNSIGNED,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
1,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_LONG_UNSIGNED,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
2,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_LONG64,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
8,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_LONG64_UNSIGNED,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
8,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_ENUM,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
1,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_FLOAT32,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
4,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_FLOAT64,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
8,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_DATE_TIME,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
10,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_DATE,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
5,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_TIME,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
3,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_TIME_S,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
7,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_OI,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
2,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_OAD,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
4,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_ROAD,
|
|
PROTO_69845_DATA_LEN_TYPE_ROAD,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_OMD,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
4,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_TI,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
3,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_TSA,
|
|
PROTO_69845_DATA_LEN_TYPE_TSA,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_MAC,
|
|
PROTO_69845_DATA_LEN_TYPE_UNKNOW,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_RN,
|
|
PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_REGION,
|
|
PROTO_69845_DATA_LEN_TYPE_UNKNOW,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_SCALER_UNIT,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
2,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_RSD,
|
|
PROTO_69845_DATA_LEN_TYPE_RSD,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_CSD,
|
|
PROTO_69845_DATA_LEN_TYPE_CSD,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_MS,
|
|
PROTO_69845_DATA_LEN_TYPE_MS,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_SID,
|
|
PROTO_69845_DATA_LEN_TYPE_UNKNOW,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_SID_MAC,
|
|
PROTO_69845_DATA_LEN_TYPE_UNKNOW,
|
|
0,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_COMDCB,
|
|
PROTO_69845_DATA_LEN_TYPE_NORMAL,
|
|
5,
|
|
},
|
|
{
|
|
PROTO_69845_APP_DATA_RCSD,
|
|
PROTO_69845_DATA_LEN_TYPE_RCSD,
|
|
0,
|
|
},
|
|
};
|
|
|
|
uint8_t proto_698_is_security_cmd(uint8_t *data, uint32_t len)
|
|
{
|
|
uint8_t ret = 0;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *resp;
|
|
apdu_info_t apdu;
|
|
|
|
if (proto_69845_parse(&data, &len, &head, &apdu) != ERR_OK) {
|
|
goto out;
|
|
}
|
|
if (apdu.len < sizeof(*resp)) {
|
|
goto out;
|
|
}
|
|
resp = (proto_69845_app_req_resp_t * )apdu.ptr;
|
|
if (resp->type == PROTO_69845_C_APP_SECURITY_REQ ||
|
|
resp->type == PROTO_69845_S_APP_SECURITY_RESP) {
|
|
ret = 1;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint8_t proto_698_interactive_cmd_check(uint8_t *data1, uint32_t len1,
|
|
uint8_t *data2, uint32_t len2)
|
|
{
|
|
uint32_t apud_len1, apdu_len2;
|
|
uint8_t ret = 0, *choice1, *choice2;
|
|
proto_69845_frame_head_info_t *head1, *head2;
|
|
proto_69845_app_req_resp_t *resp1, *resp2;
|
|
proto_69845_app_piid_t *piid1 = NULL, *piid2 = NULL;
|
|
apdu_info_t apdu1, apdu2;
|
|
|
|
if (!data1 || !len1 || !data2 || !len2) {
|
|
goto out;
|
|
}
|
|
if (proto_69845_parse(&data1, &len1, &head1, &apdu1) != ERR_OK ||
|
|
proto_69845_parse(&data2, &len2, &head2, &apdu2) != ERR_OK) {
|
|
goto out;
|
|
}
|
|
apud_len1 = apdu1.len;
|
|
apdu_len2 = apdu2.len;
|
|
if (apud_len1 < sizeof(*resp1) || apdu_len2 < sizeof(*resp2)) {
|
|
goto out;
|
|
}
|
|
apud_len1 -= sizeof(*resp1);
|
|
apdu_len2 -= sizeof(*resp2);
|
|
resp1 = (proto_69845_app_req_resp_t * )apdu1.ptr;
|
|
resp2 = (proto_69845_app_req_resp_t * )apdu2.ptr;
|
|
if (((resp1->type & 0x80) == (resp2->type & 0x80)) ||
|
|
((resp1->type & 0x7f) != (resp2->type & 0x7f))) {
|
|
goto out;
|
|
}
|
|
switch (resp1->type & 0x7f) {
|
|
case PROTO_69845_C_APP_LINK_RESP:
|
|
case PROTO_69845_C_APP_CONNECT_REQ:
|
|
case PROTO_69845_C_APP_RELEASE_REQ:
|
|
{
|
|
if (apud_len1 < sizeof(*piid1) ||
|
|
apdu_len2 < sizeof(*piid2)) {
|
|
goto out;
|
|
}
|
|
piid1 = (proto_69845_app_piid_t *)resp1->data;
|
|
piid2 = (proto_69845_app_piid_t *)resp2->data;
|
|
break;
|
|
}
|
|
case PROTO_69845_C_APP_GET_REQ:
|
|
case PROTO_69845_C_APP_SET_REQ:
|
|
case PROTO_69845_C_APP_ACTION_REQ:
|
|
case PROTO_69845_C_APP_REPORT_RESP:
|
|
case PROTO_69845_C_APP_PROXY_REQ:
|
|
{
|
|
if (apud_len1 < sizeof(*choice1) ||
|
|
apdu_len2 < sizeof(*choice2)) {
|
|
goto out;
|
|
}
|
|
apud_len1 -= sizeof(*choice1);
|
|
apdu_len2 -= sizeof(*choice2);
|
|
choice1 = resp1->data;
|
|
choice2 = resp2->data;
|
|
if (*choice1 != *choice2) {
|
|
goto out;
|
|
}
|
|
if (apud_len1 < sizeof(*piid1) ||
|
|
apdu_len2 < sizeof(*piid2)) {
|
|
goto out;
|
|
}
|
|
piid1 = (proto_69845_app_piid_t *)(choice1 + 1);
|
|
piid2 = (proto_69845_app_piid_t *)(choice2 + 1);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
if (!piid1 || !piid2) {
|
|
goto out;
|
|
}
|
|
if (piid1->sn != piid2->sn) {
|
|
goto out;
|
|
}
|
|
ret = 1;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_698_oad_to_645_di(uint32_t oad_698)
|
|
{
|
|
uint32_t di_645 = PROTO_645_INVALID_DI;
|
|
uint16_t oi_698 = oad_698 >> 16;
|
|
|
|
switch (oi_698) {
|
|
case PROTO_69845_APP_OI_VOLTAGE:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_V_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_CURRENT:
|
|
{
|
|
if (oad_698 == PROTO_69845_APP_OAD_GND_CURRENT) {
|
|
di_645 = PROTO_645_2007_DI_I_N;
|
|
} else {
|
|
di_645 = PROTO_645_2007_DI_I_ALL;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_P:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_P_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_Q:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_Q_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_PF:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_PF_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EPT_COMP:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_COMP_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EPT_POS:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_POS_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EPT_NEG:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_NEG_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_POS:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_POS_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_NEG:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_NEG_ALL;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_QRT1:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_QRT1_SUM;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_QRT2:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_QRT2_SUM;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_QRT3:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_QRT3_SUM;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_QRT4:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_QRT4_SUM;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EPT_DEMAND:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EQT_DEMAND:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EQT_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EPT_POS_DEMAND:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_POS_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OI_EPT_NEG_DEMAND:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_NEG_DEMAND;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
switch (oad_698) {
|
|
case PROTO_69845_APP_OAD_EPT_POS_A_SIG:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_POS_A;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OAD_EPT_POS_B_SIG:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_POS_B;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OAD_EPT_POS_C_SIG:
|
|
{
|
|
di_645 = PROTO_645_2007_DI_EPT_POS_C;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return di_645;
|
|
}
|
|
|
|
uint32_t proto_645_di_to_698_oad(uint32_t di)
|
|
{
|
|
uint32_t oad_698 = PROTO_69845_APP_OAD_INVALID;
|
|
switch (di) {
|
|
case PROTO_645_2007_DI_V_A:
|
|
case PROTO_645_2007_DI_V_ALL:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_VOLTAGE;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_A:
|
|
case PROTO_645_2007_DI_I_ALL:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_CURRENT;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_PF_ALL:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_PF;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_COMP_SUM:
|
|
case PROTO_645_2007_DI_EPT_COMP_ALL:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_COMP;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_ALL:
|
|
case PROTO_645_2007_DI_EPT_POS_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_POS;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_ALL:
|
|
case PROTO_645_2007_DI_EPT_NEG_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_NEG;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_POS_ALL:
|
|
case PROTO_645_2007_DI_EQT_POS_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_POS;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_NEG_ALL:
|
|
case PROTO_645_2007_DI_EQT_NEG_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_NEG;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_P_A:
|
|
case PROTO_645_2007_DI_P_T:
|
|
case PROTO_645_2007_DI_P_ALL:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_P;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_Q_ALL:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_Q;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_I_N:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_GND_CURRENT;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT1_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_QRT1_SUM;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT2_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_QRT2_SUM;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT3_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_QRT3_SUM;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_QRT4_SUM:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_QRT4_SUM;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_DEMAND:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EQT_DEMAND:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EQT_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_DEMAND:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_POS_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_NEG_DEMAND:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_NEG_DEMAND;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_TIME:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_TIME;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_A:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_POS_A_SIG;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_B:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_POS_B_SIG;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_EPT_POS_C:
|
|
{
|
|
oad_698 = PROTO_69845_APP_OAD_EPT_POS_C_SIG;
|
|
break;
|
|
}
|
|
case PROTO_645_2007_DI_RT_YMDHMS_LAST1:
|
|
case PROTO_645_2007_DI_RT_EP_POS_LAST1:
|
|
case PROTO_645_2007_DI_RT_EP_NEG_LAST1:
|
|
case PROTO_645_2007_DI_RT_VARIABLE_LAST1:
|
|
default:
|
|
break;
|
|
}
|
|
return oad_698;
|
|
}
|
|
|
|
uint32_t proto_69845_is_any_server_addr(uint8_t *server_addr)
|
|
{
|
|
uint8_t i;
|
|
for (i = 0; i < IOT_MAC_ADDR_LEN; i++) {
|
|
if (server_addr[i] == 0xAA) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t proto_69845_get_addr_info(proto_69845_frame_head_info_t* head,
|
|
addr_info_t *addr_info)
|
|
{
|
|
uint8_t total_len = 0;
|
|
|
|
if (head == NULL) {
|
|
goto out;
|
|
}
|
|
total_len = head->addr.flag.sa_len + 1;
|
|
if (addr_info) {
|
|
if (head->addr.flag.flg_ext) {
|
|
addr_info->ser_info.logical_addr = head->addr.sa_and_ca[0];
|
|
addr_info->ser_info.len = total_len -
|
|
PROTO_69845_EXT_LOGICAL_ADD_LEN;
|
|
os_mem_cpy(addr_info->ser_info.addr,
|
|
&head->addr.sa_and_ca[PROTO_69845_EXT_LOGICAL_ADD_LEN],
|
|
addr_info->ser_info.len);
|
|
} else {
|
|
addr_info->ser_info.logical_addr = head->addr.flag.logical_addr;
|
|
addr_info->ser_info.len = total_len;
|
|
os_mem_cpy(addr_info->ser_info.addr, head->addr.sa_and_ca,
|
|
addr_info->ser_info.len);
|
|
}
|
|
addr_info->ser_info.type = head->addr.flag.sa_type;
|
|
addr_info->cli_addr = head->addr.sa_and_ca[total_len];
|
|
}
|
|
total_len += PROTO_69845_CA_LEN;
|
|
out:
|
|
return total_len;
|
|
}
|
|
|
|
uint8_t *proto_69845_get_ser_addr(proto_69845_frame_head_info_t* head)
|
|
{
|
|
uint8_t *addr = NULL;
|
|
if (head) {
|
|
addr = head->addr.sa_and_ca;
|
|
if (head->addr.flag.flg_ext) {
|
|
addr += PROTO_69845_EXT_LOGICAL_ADD_LEN;
|
|
}
|
|
}
|
|
return addr;
|
|
}
|
|
|
|
static uint8_t proto_69845_server_len_calc(
|
|
const server_addr_info_t *ser_info)
|
|
{
|
|
uint8_t len;
|
|
|
|
len = ser_info->len;
|
|
if (ser_info->logical_addr >= PROTO_69845_EXT_LOGICAL_ADD_MIN) {
|
|
len += PROTO_69845_EXT_LOGICAL_ADD_LEN;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
uint32_t proto_69845_head_sanity_check(
|
|
proto_69845_frame_head_info_t* head, uint8_t* data, uint16_t len)
|
|
{
|
|
uint8_t head_len;
|
|
uint8_t *check_sum_start = data + 1;
|
|
uint32_t ret;
|
|
|
|
if ((head->addr.flag.sa_len + 1) > PROTO_69845_SA_MAX_LEN) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
head_len = sizeof(proto_69845_frame_head_info_t) + head->addr.flag.sa_len \
|
|
+ 1 + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
if (len < head_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
head_len = (head_len - sizeof(head->start_char));
|
|
/* 698.45 Head Check Sum */
|
|
ret = proto_fcs16_check(check_sum_start, head_len);
|
|
out:
|
|
/* Invalid 698.45 protocol head */
|
|
return ret;
|
|
}
|
|
|
|
proto_69845_frame_head_info_t *proto_69845_sanity_check(uint8_t* data,
|
|
uint16_t len)
|
|
{
|
|
uint16_t len_t, i = 0x0;
|
|
uint8_t *data_s = NULL;
|
|
uint16_t min_data_len = sizeof(proto_69845_frame_head_info_t);
|
|
proto_69845_frame_head_info_t* head;
|
|
|
|
for (i = 0x0, len_t = len; i < len; i++) {
|
|
if (data[i] == PROTO_69845_START_BYTE) {
|
|
data_s = data + i;
|
|
break;
|
|
}
|
|
len_t--;
|
|
}
|
|
|
|
if (len_t <= min_data_len) {
|
|
goto drop;
|
|
}
|
|
|
|
head = (proto_69845_frame_head_info_t*)data_s;
|
|
if (len_t < (head->len + PROTO_69845_START_END_LEN)) {
|
|
goto drop;
|
|
}
|
|
|
|
if (data_s[0] != PROTO_69845_START_BYTE
|
|
|| data_s[head->len + 1] != PROTO_69845_END_BYTE) {
|
|
goto drop;
|
|
}
|
|
|
|
if (proto_69845_head_sanity_check(head, data_s, len_t)) {
|
|
/* Invalid 698.45 protocol head */
|
|
goto drop;
|
|
}
|
|
|
|
/* 698.45 frame check sum */
|
|
if (proto_fcs16_check(data_s + 1, head->len)) {
|
|
goto drop;
|
|
}
|
|
goto out;
|
|
drop:
|
|
head = NULL;
|
|
out:
|
|
return head; /* checksum success */
|
|
}
|
|
|
|
proto_69845_frame_head_info_t *proto_69845_sanity_check_ext(uint8_t* data,
|
|
uint16_t len)
|
|
{
|
|
uint16_t len_t = len, curr_len, i = 0x0;
|
|
uint8_t *data_s = data;
|
|
uint16_t min_data_len = sizeof(proto_69845_frame_head_info_t);
|
|
proto_69845_frame_head_info_t* head;
|
|
|
|
again:
|
|
curr_len = len_t;
|
|
for (i = 0x0; i < curr_len; i++) {
|
|
if (data_s[i] == PROTO_69845_START_BYTE) {
|
|
data_s += i;
|
|
len_t -= i;
|
|
break;
|
|
}
|
|
}
|
|
if (i == curr_len) {
|
|
goto drop;
|
|
}
|
|
if (len_t < min_data_len) {
|
|
goto drop;
|
|
}
|
|
head = (proto_69845_frame_head_info_t*)data_s;
|
|
if (len_t < (head->len + PROTO_69845_START_END_LEN)) {
|
|
data_s++;
|
|
len_t--;
|
|
goto again;
|
|
}
|
|
|
|
if (data_s[0] != PROTO_69845_START_BYTE
|
|
|| data_s[head->len + 1] != PROTO_69845_END_BYTE) {
|
|
data_s++;
|
|
len_t--;
|
|
goto again;
|
|
}
|
|
|
|
if (proto_69845_head_sanity_check(head, data_s, len_t)) {
|
|
/* Invalid 698.45 protocol head */
|
|
data_s++;
|
|
len_t--;
|
|
goto again;
|
|
}
|
|
|
|
/* 698.45 frame check sum */
|
|
if (proto_fcs16_check(data_s + 1, head->len)) {
|
|
data_s++;
|
|
len_t--;
|
|
goto again;
|
|
}
|
|
goto out;
|
|
drop:
|
|
head = NULL;
|
|
out:
|
|
return head;
|
|
}
|
|
|
|
uint32_t proto_69845_head_fill(
|
|
proto_69845_frame_head_info_t *head, uint16_t head_len,
|
|
uint16_t total_len, addr_info_t *addr_info, uint8_t fn,
|
|
uint8_t fragment, uint8_t dir_prm)
|
|
{
|
|
uint8_t *data, ser_len;
|
|
uint16_t cs_len, cs;
|
|
uint32_t ret = ERR_FAIL;
|
|
|
|
if (!total_len || !addr_info) {
|
|
goto out;
|
|
}
|
|
if (total_len < head_len) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
|
|
if ((head_len < (sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN))
|
|
|| !ser_len) {
|
|
goto out;
|
|
}
|
|
data = (uint8_t*)head;
|
|
head->start_char = PROTO_69845_START_BYTE;
|
|
head->len = total_len - PROTO_69845_START_END_LEN;
|
|
head ->ctrl.fn = fn;
|
|
head->ctrl.fragment = fragment;
|
|
head->ctrl.dir_prm = dir_prm;
|
|
if (addr_info->ser_info.logical_addr < PROTO_69845_EXT_LOGICAL_ADD_MIN) {
|
|
head->addr.flag.logical_addr = addr_info->ser_info.logical_addr;
|
|
head->addr.flag.flg_ext = 0;
|
|
os_mem_cpy(head->addr.sa_and_ca, addr_info->ser_info.addr,
|
|
addr_info->ser_info.len);
|
|
head->addr.flag.sa_len = addr_info->ser_info.len;
|
|
} else {
|
|
head->addr.flag.logical_addr = 0;
|
|
head->addr.flag.flg_ext = 1;
|
|
head->addr.sa_and_ca[0] = addr_info->ser_info.logical_addr;
|
|
os_mem_cpy(&head->addr.sa_and_ca[PROTO_69845_EXT_LOGICAL_ADD_LEN],
|
|
addr_info->ser_info.addr, addr_info->ser_info.len);
|
|
head->addr.flag.sa_len = (addr_info->ser_info.len +
|
|
PROTO_69845_EXT_LOGICAL_ADD_LEN);
|
|
}
|
|
head->addr.flag.sa_len--;
|
|
head->addr.flag.sa_type = addr_info->ser_info.type;
|
|
head->addr.sa_and_ca[head->addr.flag.sa_len + 1] = addr_info->cli_addr;
|
|
cs_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN - PROTO_69845_START_LEN;
|
|
cs = proto_fcs16_get_check_sum(data + 1, cs_len);
|
|
data[cs_len + 1] = (cs & 0x00ff);
|
|
data[cs_len + 2] = ((cs >> 8) & 0x00ff);
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_tail_fill(proto_69845_frame_head_info_t *head,
|
|
uint8_t *tail_data, uint16_t len)
|
|
{
|
|
uint8_t *ptr = tail_data;
|
|
uint16_t cs_len, cs;
|
|
uint32_t ret = ERR_FAIL;
|
|
proto_69845_tailer_t *tail;
|
|
|
|
if (len < sizeof(*tail)) {
|
|
goto out;
|
|
}
|
|
/* fill 698.45 proto tailer */
|
|
tail = (proto_69845_tailer_t*)ptr;
|
|
cs_len = head->len - PROTO_69845_CHECKSUM_LEN;
|
|
cs = proto_fcs16_get_check_sum((uint8_t*)&head->len, cs_len);
|
|
tail->fcs[0] = (cs & 0x00ff);
|
|
tail->fcs[1] = ((cs >> 8) & 0x00ff);
|
|
tail->end_char = PROTO_69845_END_BYTE;
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_tail_fill_without_ts_fl(
|
|
proto_69845_frame_head_info_t *head,
|
|
uint8_t *tail_data, uint16_t len)
|
|
{
|
|
uint8_t *time_tag, *flw_rpt, *ptr = tail_data;
|
|
uint16_t total_len;
|
|
uint32_t ret = ERR_FAIL;
|
|
|
|
if (head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_REPORT
|
|
|| head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_RESPONSE) {
|
|
total_len = sizeof(proto_69845_tailer_t) + sizeof(*time_tag)
|
|
+ sizeof(*flw_rpt);
|
|
} else {
|
|
total_len = sizeof(proto_69845_tailer_t) + sizeof(*time_tag);
|
|
}
|
|
|
|
if (len < total_len) {
|
|
goto out;
|
|
}
|
|
/* There is no time tag field, so time_tag is 0 */
|
|
time_tag = ptr;
|
|
(*time_tag) = 0;
|
|
ptr += sizeof(*time_tag);
|
|
if (head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_REPORT
|
|
|| head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_RESPONSE) {
|
|
/* There is no follow report data field, so flw_rpt is 0 */
|
|
flw_rpt = ptr;
|
|
(*flw_rpt) = 0;
|
|
ptr += sizeof(*flw_rpt);
|
|
}
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, ptr, sizeof(proto_69845_tailer_t));
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
void proto_69845_add33_handle(uint8_t *ds, uint32_t size)
|
|
{
|
|
uint8_t *ptr = ds;
|
|
while (size--)
|
|
{
|
|
(*ptr++) += 0x33;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void proto_69845_sub33_handle(uint8_t *ds, uint32_t size)
|
|
{
|
|
uint8_t *ptr = ds;
|
|
while (size--)
|
|
{
|
|
(*ptr++) -= 0x33;
|
|
}
|
|
return;
|
|
}
|
|
|
|
uint32_t proto_69845_get_apdu(proto_69845_frame_head_info_t *hdr,
|
|
uint32_t len, apdu_info_t *apdu)
|
|
{
|
|
uint8_t *data = (uint8_t*)hdr;
|
|
uint32_t head_len, total_len, min_len;
|
|
uint32_t ret = ERR_OK;
|
|
|
|
head_len = sizeof(*hdr) + hdr->addr.flag.sa_len \
|
|
+ 1 + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
total_len = hdr->len + PROTO_69845_START_END_LEN;
|
|
min_len = head_len + sizeof(proto_69845_tailer_t);
|
|
if ((len < head_len) || (len < total_len) || (len < min_len)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (hdr->ctrl.fragment != PROTO_69845_APDU_WHOLE) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
apdu->ptr = data + head_len;
|
|
apdu->len = len - min_len;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_parse(uint8_t **data, uint32_t *len,
|
|
proto_69845_frame_head_info_t **hdr, apdu_info_t *apdu_desc)
|
|
{
|
|
uint8_t *ds = *data, *sub_data = NULL;
|
|
uint32_t len1 = *len, temp, offset, sub_len = 0;
|
|
|
|
proto_69845_frame_head_info_t *hdr_temp;
|
|
proto_69845_apdu_t *apdu;
|
|
proto_69845_app_sec_req_resp_info_t *sec;
|
|
proto_69845_app_len_descript_t *len_desc;
|
|
hdr_temp = proto_69845_sanity_check(ds, (uint16_t)len1);
|
|
if (hdr_temp == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
offset = (uint32_t)((uint8_t *)hdr_temp - ds);
|
|
len1 -= offset;
|
|
ds += offset;
|
|
|
|
temp = sizeof(*hdr_temp) + sizeof(proto_69845_addr_t) +
|
|
hdr_temp->addr.flag.sa_len + PROTO_69845_CA_LEN +
|
|
PROTO_69845_CHECKSUM_LEN;
|
|
len1 -= temp;
|
|
ds += temp;
|
|
if (len1 < sizeof(proto_69845_tailer_t)) {
|
|
goto err;
|
|
}
|
|
len1 -= sizeof(proto_69845_tailer_t);
|
|
if (hdr_temp->ctrl.flag_scramble) {
|
|
proto_69845_sub33_handle(ds, len1);
|
|
sub_data = ds;
|
|
sub_len = len1;
|
|
}
|
|
if (apdu_desc) {
|
|
apdu_desc->ptr = ds;
|
|
apdu_desc->len = len1;
|
|
}
|
|
if (len1 < sizeof(*apdu))
|
|
goto err;
|
|
apdu = (proto_69845_apdu_t *)ds;
|
|
switch (apdu->type) {
|
|
case PROTO_69845_C_APP_SECURITY_REQ:
|
|
case PROTO_69845_S_APP_SECURITY_RESP:
|
|
{
|
|
ds += sizeof(*apdu);
|
|
len1 -= sizeof(*apdu);
|
|
if (len1 < sizeof (*sec)) {
|
|
goto err;
|
|
}
|
|
sec = (proto_69845_app_sec_req_resp_info_t*)ds;
|
|
len1 -= sizeof (*sec);
|
|
ds += sizeof (*sec);
|
|
|
|
len_desc = (proto_69845_app_len_descript_t *)((uint8_t *)sec + 1);
|
|
if (!len_desc->mub_flag) {
|
|
ds = sec->data;
|
|
temp = sec->len;
|
|
} else if (len_desc->byte_num == 1) {
|
|
if (len1 < 1) {
|
|
goto err;
|
|
}
|
|
temp = sec->data[0];
|
|
ds = sec->data + 1;
|
|
len1--;
|
|
} else if (len_desc->byte_num == 2) {
|
|
if (len1 < 2) {
|
|
goto err;
|
|
}
|
|
temp = iot_bytes_to_uint16(sec->data, 1);
|
|
ds = sec->data + 2;
|
|
len1 -= 2;
|
|
} else {
|
|
goto err;
|
|
}
|
|
if (len1 < temp) {
|
|
goto err;
|
|
}
|
|
len1 = temp;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
*data = ds;
|
|
*len = len1;
|
|
*hdr = hdr_temp;
|
|
return ERR_OK;
|
|
err:
|
|
if (sub_data && sub_len) {
|
|
proto_69845_add33_handle(sub_data, sub_len);
|
|
}
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_event_msg(uint8_t *addr)
|
|
{
|
|
uint8_t *data;
|
|
uint32_t len;
|
|
iot_pkt_t *pkt;
|
|
proto_645_header_t *hdr;
|
|
|
|
len = sizeof(*hdr) + PROTO_69845_EVENT_DATA_LEN
|
|
+ sizeof(proto_645_tailer_t);
|
|
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
data = (uint8_t*)iot_pkt_data(pkt);
|
|
hdr = (proto_645_header_t*)data;
|
|
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
|
|
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
|
|
hdr->len = PROTO_69845_EVENT_DATA_LEN;
|
|
os_mem_cpy(hdr->data, proto_69845_event_report_data,
|
|
PROTO_69845_EVENT_DATA_LEN);
|
|
proto_645_tail_init(hdr);
|
|
iot_pkt_put(pkt, len);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t proto_69845_get_oad(uint8_t *data,
|
|
uint32_t data_len, proto_69845_app_oad_t *oad)
|
|
{
|
|
uint32_t ret = ERR_FAIL;
|
|
proto_69845_app_get_req_normal_t *req =
|
|
(proto_69845_app_get_req_normal_t*)data;
|
|
|
|
if (data_len < sizeof(*req)) {
|
|
goto out;
|
|
}
|
|
oad->oi = proto_69845_byte_to_oi((uint8_t*)&req->oad.oi);
|
|
oad->element_index = req->oad.element_index;
|
|
oad->attribute_id = req->oad.attribute_id;
|
|
oad->attribute_char = req->oad.attribute_char;
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_get_omd(uint8_t *data,
|
|
uint32_t data_len, proto_69845_app_omd_t *omd)
|
|
{
|
|
uint32_t ret = ERR_FAIL;
|
|
proto_69845_app_action_req_single_t *req =
|
|
(proto_69845_app_action_req_single_t*)data;
|
|
|
|
if (data_len < sizeof(*req)) {
|
|
goto out;
|
|
}
|
|
omd->oi = proto_69845_byte_to_oi((uint8_t*)&req->omd.oi);
|
|
omd->method_id = req->omd.method_id;
|
|
omd->operation_mode = req->omd.operation_mode;
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t proto_69845_get_data_len_type(uint8_t data_type)
|
|
{
|
|
uint8_t data_len_type = PROTO_69845_DATA_LEN_TYPE_UNKNOW;
|
|
|
|
for (uint8_t i = 0; i < PROTO_69845_DATA_DESC_LIST_MAX; i++) {
|
|
if (data_type == proto_69845_data_desc_list[i].type) {
|
|
data_len_type = proto_69845_data_desc_list[i].len_type;
|
|
break;
|
|
}
|
|
}
|
|
return data_len_type;
|
|
}
|
|
|
|
uint32_t proto_69845_get_normal_data_len(uint8_t data_type)
|
|
{
|
|
uint32_t data_len = 0;
|
|
|
|
for (uint8_t i = 0; i < PROTO_69845_DATA_DESC_LIST_MAX; i++) {
|
|
if (data_type == proto_69845_data_desc_list[i].type) {
|
|
data_len = proto_69845_data_desc_list[i].len;
|
|
break;
|
|
}
|
|
}
|
|
return data_len;
|
|
}
|
|
|
|
uint32_t proto_69845_get_div8_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *len_data;
|
|
uint32_t ret = ERR_OK, len, bit_len = 0;
|
|
proto_69845_app_len_descript_t *len_desc;
|
|
|
|
if (rec_data_len < sizeof(*len_desc)) {
|
|
goto drop;
|
|
}
|
|
len_desc = (proto_69845_app_len_descript_t *)data;
|
|
if (!len_desc->mub_flag) {
|
|
bit_len = data[0];
|
|
} else {
|
|
if (rec_data_len < sizeof(*len_desc) + len_desc->byte_num) {
|
|
goto drop;
|
|
}
|
|
len_data = data + sizeof(*len_desc);
|
|
if (len_desc->byte_num == 1) {
|
|
bit_len = len_data[0];
|
|
} else if (len_desc->byte_num == 2) {
|
|
bit_len = iot_bytes_to_uint16(len_data, 1);
|
|
} else {
|
|
goto drop;
|
|
}
|
|
}
|
|
len = bit_len / 8;
|
|
if ((bit_len % 8) != 0) {
|
|
len++;
|
|
}
|
|
len += sizeof(*len_desc);
|
|
if (len_desc->mub_flag) {
|
|
len += len_desc->byte_num;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_multi_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *len_data;
|
|
uint32_t ret = ERR_OK, len = 0;
|
|
proto_69845_app_len_descript_t *len_desc;
|
|
|
|
if (rec_data_len < sizeof(*len_desc)) {
|
|
goto drop;
|
|
}
|
|
len_desc = (proto_69845_app_len_descript_t *)data;
|
|
if (!len_desc->mub_flag) {
|
|
len = data[0];
|
|
} else {
|
|
if (rec_data_len < sizeof(*len_desc) + len_desc->byte_num) {
|
|
goto drop;
|
|
}
|
|
len_data = data + sizeof(*len_desc);
|
|
if (len_desc->byte_num == 1) {
|
|
len = len_data[0];
|
|
} else if (len_desc->byte_num == 2) {
|
|
len = iot_bytes_to_uint16(len_data, 1);
|
|
} else {
|
|
goto drop;
|
|
}
|
|
}
|
|
len += sizeof(*len_desc);
|
|
if (len_desc->mub_flag) {
|
|
len += len_desc->byte_num;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_get_road_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint32_t ret = ERR_OK, len;
|
|
proto_69845_app_road_t *road_hdr;
|
|
|
|
if (rec_data_len < sizeof(*road_hdr)) {
|
|
goto drop;
|
|
}
|
|
road_hdr = (proto_69845_app_road_t*)data;
|
|
len = proto_69845_get_normal_data_len(PROTO_69845_APP_DATA_OAD);
|
|
len *= road_hdr->cnt;
|
|
len += sizeof(*road_hdr);
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_get_csd_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_csd_t *csd_hdr;
|
|
|
|
if (rec_len < sizeof(*csd_hdr)) {
|
|
goto drop;
|
|
}
|
|
csd_hdr = (proto_69845_app_data_csd_t*)ptr;
|
|
len = sizeof(*csd_hdr);
|
|
ptr += sizeof(*csd_hdr);
|
|
rec_len -= sizeof(*csd_hdr);
|
|
switch (csd_hdr->type) {
|
|
case PROTO_OI_CSD_TYPE_OAD:
|
|
{
|
|
len += proto_69845_get_normal_data_len(PROTO_69845_APP_DATA_OAD);
|
|
break;
|
|
}
|
|
case PROTO_OI_CSD_TYPE_ROAD:
|
|
{
|
|
if (proto_69845_get_road_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
default:
|
|
goto drop;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_get_rcsd_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data, i;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_rcsd_t *rcsd_hdr;
|
|
|
|
if (rec_len < sizeof(*rcsd_hdr)) {
|
|
goto drop;
|
|
}
|
|
rcsd_hdr = (proto_69845_app_data_rcsd_t*)ptr;
|
|
len = sizeof(*rcsd_hdr);
|
|
ptr += sizeof(*rcsd_hdr);
|
|
rec_len -= sizeof(*rcsd_hdr);
|
|
for (i = 0; i < rcsd_hdr->cnt; i++) {
|
|
cache_len = 0;
|
|
if (proto_69845_get_csd_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
if (rec_len < cache_len) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
ptr += cache_len;
|
|
rec_len -= cache_len;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_tsa_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint32_t ret = ERR_OK, len;
|
|
proto_69845_app_data_tsa_t *tsa_hdr;
|
|
|
|
if (rec_data_len < sizeof(*tsa_hdr)) {
|
|
goto drop;
|
|
}
|
|
tsa_hdr = (proto_69845_app_data_tsa_t*)data;
|
|
len = tsa_hdr->flag.sa_len + 1;
|
|
len += sizeof(*tsa_hdr);
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_ms_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data, i;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_ms_t *ms_hdr;
|
|
proto_69845_app_data_ms_type_t *type_list_hdr;
|
|
proto_69845_app_data_tsa_seq_t *tsa_list_hdr;
|
|
|
|
if (rec_len < sizeof(*ms_hdr)) {
|
|
goto drop;
|
|
}
|
|
ms_hdr = (proto_69845_app_data_ms_t*)ptr;
|
|
len = sizeof(*ms_hdr);
|
|
ptr += sizeof(*ms_hdr);
|
|
rec_len -= sizeof(*ms_hdr);
|
|
switch (ms_hdr->type) {
|
|
case PROTO_OI_MS_TYPE_ALL_PM:
|
|
{
|
|
break;
|
|
}
|
|
case PROTO_OI_MS_TYPE_GROUP_PM_TYPE:
|
|
{
|
|
if (rec_len < sizeof(*type_list_hdr)) {
|
|
goto drop;
|
|
}
|
|
type_list_hdr = (proto_69845_app_data_ms_type_t*)ptr;
|
|
cache_len = type_list_hdr->cnt * sizeof(type_list_hdr->type_list[0])
|
|
+ sizeof(*type_list_hdr);
|
|
if (rec_len < cache_len) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_OI_MS_TYPE_GROUP_PM_ADDR:
|
|
{
|
|
if (rec_len < sizeof(*tsa_list_hdr)) {
|
|
goto drop;
|
|
}
|
|
tsa_list_hdr = (proto_69845_app_data_tsa_seq_t*)ptr;
|
|
len += sizeof(*tsa_list_hdr);
|
|
ptr += sizeof(*tsa_list_hdr);
|
|
rec_len -= sizeof(*tsa_list_hdr);
|
|
for (i = 0; i < tsa_list_hdr->cnt; i++) {
|
|
cache_len = 0;
|
|
if (proto_69845_get_tsa_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
if (rec_len < cache_len) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
ptr += cache_len;
|
|
rec_len -= cache_len;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
goto drop;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_rsd_type_2_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data, data_len_type;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_rsd_type2_t *rsd_type2_hdr;
|
|
proto_69845_app_data_t *data_hdr;
|
|
|
|
if (rec_len < sizeof(*rsd_type2_hdr)) {
|
|
goto drop;
|
|
}
|
|
rsd_type2_hdr = (proto_69845_app_data_rsd_type2_t*)ptr;
|
|
len = sizeof(*rsd_type2_hdr);
|
|
ptr += sizeof(*rsd_type2_hdr);
|
|
rec_len -= sizeof(*rsd_type2_hdr);
|
|
for (uint8_t i = 0; i < PROTO_OI_RSD_TYPE_2_DATA_CNT; i++) {
|
|
if (rec_len < sizeof(*data_hdr)) {
|
|
goto drop;
|
|
}
|
|
data_hdr = (proto_69845_app_data_t*)ptr;
|
|
len += sizeof(*data_hdr);
|
|
ptr += sizeof(*data_hdr);
|
|
rec_len -= sizeof(*data_hdr);
|
|
data_len_type = proto_69845_get_data_len_type(data_hdr->data_type);
|
|
if (data_len_type != PROTO_69845_DATA_LEN_TYPE_NORMAL) {
|
|
goto drop;
|
|
}
|
|
cache_len = proto_69845_get_normal_data_len(data_hdr->data_type);
|
|
if (rec_len < cache_len) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
ptr += cache_len;
|
|
rec_len -= cache_len;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_rsd_type_678_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_rsd_type678_t *rsd_hdr;
|
|
|
|
if (rec_len < sizeof(*rsd_hdr)) {
|
|
goto drop;
|
|
}
|
|
rsd_hdr = (proto_69845_app_data_rsd_type678_t*)ptr;
|
|
len = sizeof(rsd_hdr->start_time) + sizeof(rsd_hdr->end_time)
|
|
+ sizeof(rsd_hdr->ti);
|
|
ptr = (uint8_t*)&rsd_hdr->meter_set;
|
|
rec_len = rec_len - len;
|
|
if (proto_69845_get_ms_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_rsd_type_10_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_rsd_type10_t *rsd_hdr;
|
|
|
|
if (rec_len < sizeof(*rsd_hdr)) {
|
|
goto drop;
|
|
}
|
|
rsd_hdr = (proto_69845_app_data_rsd_type10_t*)ptr;
|
|
len = sizeof(rsd_hdr->record_num);
|
|
ptr = (uint8_t*)&rsd_hdr->meter_set;
|
|
rec_len = rec_len - len;
|
|
if (proto_69845_get_ms_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_get_rsd_data_len(uint8_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_data_rsd_t *rsd_hdr;
|
|
|
|
if (rec_len < sizeof(*rsd_hdr)) {
|
|
goto drop;
|
|
}
|
|
rsd_hdr = (proto_69845_app_data_rsd_t*)ptr;
|
|
len = sizeof(*rsd_hdr);
|
|
ptr += sizeof(*rsd_hdr);
|
|
rec_len -= sizeof(*rsd_hdr);
|
|
switch (rsd_hdr->type) {
|
|
case PROTO_OI_RSD_TYPE_2:
|
|
{
|
|
cache_len = 0;
|
|
if (proto_69845_get_rsd_type_2_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_OI_RSD_TYPE_6:
|
|
case PROTO_OI_RSD_TYPE_7:
|
|
case PROTO_OI_RSD_TYPE_8:
|
|
{
|
|
cache_len = 0;
|
|
if (proto_69845_get_rsd_type_678_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_OI_RSD_TYPE_9:
|
|
{
|
|
len += 1;
|
|
break;
|
|
}
|
|
case PROTO_OI_RSD_TYPE_10:
|
|
{
|
|
cache_len = 0;
|
|
if (proto_69845_get_rsd_type_10_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
default:
|
|
goto drop;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_base_data_len(proto_69845_app_data_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data, data_len_type;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len = 0;
|
|
|
|
if (rec_len < sizeof(*data)) {
|
|
goto drop;
|
|
}
|
|
ptr += sizeof(*data);
|
|
rec_len -= sizeof(*data);
|
|
len = sizeof(*data);
|
|
data_len_type = proto_69845_get_data_len_type(data->data_type);
|
|
switch (data_len_type){
|
|
case PROTO_69845_DATA_LEN_TYPE_NORMAL:
|
|
{
|
|
len += proto_69845_get_normal_data_len(data->data_type);
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_ROAD:
|
|
{
|
|
if (proto_69845_get_road_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_TSA:
|
|
{
|
|
if (proto_69845_get_tsa_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_RSD:
|
|
{
|
|
if (proto_69845_get_rsd_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_CSD:
|
|
{
|
|
if (proto_69845_get_csd_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_MS:
|
|
{
|
|
if (proto_69845_get_ms_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_RCSD:
|
|
{
|
|
if (proto_69845_get_rcsd_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_DIV8:
|
|
{
|
|
if (proto_69845_get_div8_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE:
|
|
{
|
|
if (proto_69845_get_multi_data_len(ptr, rec_len, &cache_len)) {
|
|
goto drop;
|
|
}
|
|
len += cache_len;
|
|
break;
|
|
}
|
|
case PROTO_69845_DATA_LEN_TYPE_UNKNOW:
|
|
default:
|
|
goto drop;
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t proto_69845_get_element_data_len(proto_69845_app_ele_data_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len, uint8_t recursion_cnt)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)data, data_len_type;
|
|
uint8_t i;
|
|
uint8_t cnt;
|
|
uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
|
|
proto_69845_app_ele_data_t *element_hdr;
|
|
proto_69845_app_data_t *base_data_hdr;
|
|
|
|
if (rec_len < sizeof(*data)) {
|
|
goto drop;
|
|
}
|
|
ptr += sizeof(*data);
|
|
rec_len -= sizeof(*data);
|
|
len = sizeof(*data);
|
|
cnt = data->num_of_data;
|
|
for (i = 0; i < cnt; i++) {
|
|
if (rec_len < sizeof(*base_data_hdr)) {
|
|
goto drop;
|
|
}
|
|
base_data_hdr = (proto_69845_app_data_t*)ptr;
|
|
data_len_type = proto_69845_get_data_len_type(base_data_hdr->data_type);
|
|
if (data_len_type == PROTO_69845_DATA_LEN_TYPE_ELEMENT) {
|
|
if (!recursion_cnt) {
|
|
goto drop;
|
|
}
|
|
if (rec_len < sizeof(*element_hdr)) {
|
|
goto drop;
|
|
}
|
|
element_hdr = (proto_69845_app_ele_data_t*)base_data_hdr;
|
|
cache_len = 0;
|
|
if (proto_69845_get_element_data_len(element_hdr, rec_len,
|
|
&cache_len, (recursion_cnt - 1))) {
|
|
goto drop;
|
|
}
|
|
if (rec_len < cache_len) {
|
|
goto drop;
|
|
}
|
|
ptr += cache_len;
|
|
rec_len -= cache_len;
|
|
len += cache_len;
|
|
} else {
|
|
cache_len = 0;
|
|
if (proto_69845_get_base_data_len(base_data_hdr, rec_data_len,
|
|
&cache_len)) {
|
|
goto drop;
|
|
}
|
|
if (rec_len < cache_len) {
|
|
goto drop;
|
|
}
|
|
ptr += cache_len;
|
|
rec_len -= cache_len;
|
|
len += cache_len;
|
|
}
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_get_data_len(proto_69845_app_data_t *data,
|
|
uint32_t rec_data_len, uint32_t *data_len)
|
|
{
|
|
uint8_t data_len_type;
|
|
uint32_t ret = ERR_OK, len = 0;
|
|
proto_69845_app_ele_data_t *element_hdr;
|
|
|
|
if (!rec_data_len || !data) {
|
|
goto drop;
|
|
}
|
|
data_len_type = proto_69845_get_data_len_type(data->data_type);
|
|
if (data_len_type == PROTO_69845_DATA_LEN_TYPE_ELEMENT) {
|
|
element_hdr = (proto_69845_app_ele_data_t*)data;
|
|
if (proto_69845_get_element_data_len(element_hdr, rec_data_len, &len,
|
|
PROTO_69845_ELEMENT_DATA_RECURSION_CNT_MAX)) {
|
|
goto drop;
|
|
}
|
|
} else {
|
|
if (proto_69845_get_base_data_len(data, rec_data_len, &len)) {
|
|
goto drop;
|
|
}
|
|
}
|
|
*data_len = len;
|
|
goto out;
|
|
drop:
|
|
ret = ERR_FAIL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_get_rpt_noti_rcsd()
|
|
{
|
|
uint8_t i = 0, *data = NULL, oad_cnt = 0;
|
|
uint16_t rcsd_len = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_69845_app_data_rcsd_t *p_rcsd;
|
|
proto_69845_app_data_csd_t *p_csd;
|
|
proto_69845_app_oad_t* p_oad;
|
|
const uint16_t evt_oi[] = {
|
|
PROTO_69845_APP_OI_EVENT_REC_SEQ, PROTO_69845_APP_OI_EVENT_START_TM,
|
|
PROTO_69845_APP_OI_EVENT_END_TM, PROTO_69845_APP_OI_EVENT_OCCUR_SOURCE,
|
|
PROTO_69845_APP_OI_EVENT_RPT_STA};
|
|
|
|
oad_cnt = sizeof(evt_oi)/sizeof(evt_oi[0]);
|
|
|
|
rcsd_len = sizeof(proto_69845_app_data_rcsd_t) +
|
|
(sizeof(proto_69845_app_data_csd_t) +
|
|
sizeof(proto_69845_app_oad_t)) * oad_cnt;
|
|
|
|
pkt = iot_pkt_alloc(rcsd_len, IOT_SMART_GRID_MID);
|
|
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
p_rcsd = (proto_69845_app_data_rcsd_t *)iot_pkt_data(pkt);
|
|
|
|
p_rcsd->cnt = oad_cnt;
|
|
|
|
data = (uint8_t*)p_rcsd->csd_list;
|
|
for (i = 0; i < p_rcsd->cnt; i++) {
|
|
p_csd = (proto_69845_app_data_csd_t*)data;
|
|
p_csd->type = 0;
|
|
p_oad = (proto_69845_app_oad_t*)(p_csd->csd_data);
|
|
proto_69845_oi_to_byte(evt_oi[i], (uint8_t*)&p_oad->oi);
|
|
p_oad->attribute_id = 2;
|
|
p_oad->attribute_char = 0;
|
|
p_oad->element_index = 0;
|
|
data += sizeof(proto_69845_app_data_csd_t) +
|
|
sizeof(proto_69845_app_oad_t);
|
|
}
|
|
iot_pkt_put(pkt, rcsd_len);
|
|
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_get_rpt_noti_ele(
|
|
proto_69845_app_data_time_s_t *evt_start_tm,
|
|
proto_69845_app_data_time_s_t *evt_end_tm, rpt_status_t *rpt_status)
|
|
{
|
|
uint16_t evt_unit_len = 0;
|
|
proto_69845_app_norm_evt_unit_t *evt_unit;
|
|
proto_69845_app_unrecover_evt_unit_t *evt_unit_ab;
|
|
iot_pkt_t *pkt = NULL;
|
|
|
|
/* there is power off and power on record */
|
|
if (rpt_status->pf_rpt && rpt_status->po_rpt) {
|
|
evt_unit_len = sizeof(proto_69845_app_norm_evt_unit_t);
|
|
pkt = iot_pkt_alloc(evt_unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
|
|
evt_unit = (proto_69845_app_norm_evt_unit_t *)
|
|
iot_pkt_put(pkt, evt_unit_len);
|
|
evt_unit->data0_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
|
|
iot_uint32_to_bytes(0x01, (uint8_t *)&evt_unit->evt_seq, 1);
|
|
|
|
evt_unit->data1_type = PROTO_69845_APP_DATA_TIME_S;
|
|
os_mem_cpy(&evt_unit->evt_start_time, (uint8_t *)evt_start_tm,
|
|
sizeof(proto_69845_app_data_time_s_t));
|
|
|
|
evt_unit->data2_type = PROTO_69845_APP_DATA_TIME_S;
|
|
os_mem_cpy(&evt_unit->evt_end_time, (uint8_t *)evt_end_tm,
|
|
sizeof(proto_69845_app_data_time_s_t));
|
|
|
|
evt_unit->data3_type = PROTO_69845_APP_DATA_ENUM;
|
|
evt_unit->evt_soc = PROTO_69845_APP_EVT_SOC_485_FALT;
|
|
|
|
evt_unit->data4_type = PROTO_69845_APP_DATA_ARRAY;
|
|
evt_unit->channel_cnt = 1;
|
|
|
|
evt_unit->data5_type = PROTO_69845_APP_DATA_STRUCTURE;
|
|
evt_unit->member_cnt = 2;
|
|
|
|
evt_unit->data6_type = PROTO_69845_APP_DATA_OAD;
|
|
proto_69845_oi_to_byte(PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE,
|
|
(uint8_t*)&evt_unit->channel_oad.oi);
|
|
evt_unit->channel_oad.attribute_id = 2;
|
|
evt_unit->channel_oad.attribute_char = 0;
|
|
evt_unit->channel_oad.element_index = 1;
|
|
|
|
evt_unit->data7_type = PROTO_69845_APP_DATA_UNSIGNED;
|
|
evt_unit->pf_rpt = rpt_status->pf_rpt;
|
|
evt_unit->pf_rpt_ok = rpt_status->pf_rpt_ok;
|
|
evt_unit->po_rpt = rpt_status->po_rpt;
|
|
evt_unit->po_rpt_ok = rpt_status->po_rpt_ok;
|
|
|
|
/* there is power off record, not power on record */
|
|
} else if (rpt_status->pf_rpt && !rpt_status->po_rpt) {
|
|
evt_unit_len = sizeof(proto_69845_app_unrecover_evt_unit_t);
|
|
pkt = iot_pkt_alloc(evt_unit_len, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
|
|
evt_unit_ab = (proto_69845_app_unrecover_evt_unit_t *)
|
|
iot_pkt_put(pkt, evt_unit_len);
|
|
evt_unit_ab->data0_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
|
|
iot_uint32_to_bytes(0x01, (uint8_t *)&evt_unit_ab->evt_seq, 1);
|
|
|
|
evt_unit_ab->data1_type = PROTO_69845_APP_DATA_TIME_S;
|
|
os_mem_cpy(&evt_unit_ab->evt_start_time, (uint8_t *)evt_start_tm,
|
|
sizeof(proto_69845_app_data_time_s_t));
|
|
|
|
evt_unit_ab->data2_type = 0;
|
|
|
|
evt_unit_ab->data3_type = PROTO_69845_APP_DATA_ENUM;
|
|
evt_unit_ab->evt_soc = PROTO_69845_APP_EVT_SOC_485_FALT;
|
|
|
|
evt_unit_ab->data4_type = PROTO_69845_APP_DATA_ARRAY;
|
|
evt_unit_ab->channel_cnt = 1;
|
|
|
|
evt_unit_ab->data5_type = PROTO_69845_APP_DATA_STRUCTURE;
|
|
evt_unit_ab->member_cnt = 2;
|
|
|
|
evt_unit_ab->data6_type = PROTO_69845_APP_DATA_OAD;
|
|
proto_69845_oi_to_byte(PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE,
|
|
(uint8_t*)&evt_unit_ab->channel_oad.oi);
|
|
evt_unit_ab->channel_oad.attribute_id = 2;
|
|
evt_unit_ab->channel_oad.attribute_char = 0;
|
|
evt_unit_ab->channel_oad.element_index = 1;
|
|
|
|
evt_unit_ab->data7_type = PROTO_69845_APP_DATA_UNSIGNED;
|
|
evt_unit_ab->pf_rpt = rpt_status->pf_rpt;
|
|
evt_unit_ab->pf_rpt_ok = rpt_status->pf_rpt_ok;
|
|
evt_unit_ab->po_rpt = rpt_status->po_rpt;
|
|
evt_unit_ab->po_rpt_ok = rpt_status->po_rpt_ok;
|
|
|
|
/* only exist last two case when actively report pof event */
|
|
}
|
|
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_rpt_noti_sus_pof_msg(
|
|
proto_69845_app_rpt_noti_info_t* noti_info,
|
|
const server_addr_info_t* server_info,
|
|
proto_69845_app_data_time_s_t *evt_start_tm,
|
|
proto_69845_app_data_time_s_t *evt_end_tm, rpt_status_t *rpt_status)
|
|
{
|
|
iot_pkt_t *pkt = NULL, *rcsd_pkt = NULL, *ele_pkt = NULL;
|
|
uint8_t *data, ser_len;
|
|
uint16_t length, rcsd_len = 0, ele_load_len = 0;
|
|
uint16_t head_len, tail_len;
|
|
addr_info_t addr_info = { 0 };
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_noti_resp_t *noti;
|
|
proto_69845_app_rpt_noti_t *rpt_noti;
|
|
proto_69845_app_rpt_record_list_t *record_list;
|
|
proto_69845_app_rpt_result_record_t *result_record;
|
|
proto_69845_app_rpt_noti_result_t *noti_result;
|
|
proto_69845_app_rpt_record_row_t *record_row;
|
|
|
|
if (noti_info == NULL || server_info == NULL) {
|
|
goto drop;
|
|
}
|
|
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if (ser_len > PROTO_69845_SA_MAX_LEN || !ser_len) {
|
|
goto drop;
|
|
}
|
|
length = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
rcsd_pkt = proto_69845_get_rpt_noti_rcsd();
|
|
if(!rcsd_pkt)
|
|
goto drop;
|
|
|
|
rcsd_len = (uint16_t)iot_pkt_data_len(rcsd_pkt);
|
|
|
|
ele_pkt = proto_69845_get_rpt_noti_ele(evt_start_tm, evt_end_tm, rpt_status);
|
|
|
|
if(!ele_pkt)
|
|
goto drop;
|
|
|
|
ele_load_len = (uint16_t)iot_pkt_data_len(ele_pkt);
|
|
|
|
switch (noti_info->type) {
|
|
case PROTO_69845_APP_REPRORT_RECORDLIST:
|
|
{
|
|
length = length + sizeof(*noti) + sizeof(*rpt_noti)
|
|
+ sizeof(*record_list) + sizeof(*result_record)
|
|
+ sizeof(*noti_result) + sizeof(*record_row)
|
|
+ rcsd_len + ele_load_len - sizeof(proto_69845_app_data_rcsd_t);
|
|
break;
|
|
}
|
|
default:
|
|
goto drop;
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt)
|
|
goto drop;
|
|
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len, length,
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_SERVER_REPORT);
|
|
data += head_len;
|
|
|
|
/* fill apdu data */
|
|
noti = (proto_69845_app_noti_resp_t*)data;
|
|
noti->type = PROTO_69845_S_APP_REPORT_NOTI;
|
|
rpt_noti = (proto_69845_app_rpt_noti_t*)noti->data;
|
|
rpt_noti->data_type = noti_info->type;
|
|
data = data + sizeof(proto_69845_app_noti_resp_t)
|
|
+ sizeof(proto_69845_app_rpt_noti_t);
|
|
switch (rpt_noti->data_type) {
|
|
case PROTO_69845_APP_REPRORT_RECORDLIST:
|
|
{
|
|
record_list =
|
|
(proto_69845_app_rpt_record_list_t*)rpt_noti->data;
|
|
record_list->piid_acd = noti_info->piid_acd;
|
|
record_list->att_cnt = 1;
|
|
|
|
data += sizeof(proto_69845_app_rpt_record_list_t);
|
|
|
|
result_record = (proto_69845_app_rpt_result_record_t*)data;
|
|
proto_69845_oi_to_byte(noti_info->oad.oi,
|
|
(uint8_t*)&result_record->oad.oi);
|
|
result_record->oad.attribute_id = noti_info->oad.attribute_id;
|
|
result_record->oad.attribute_char = noti_info->oad.attribute_char;
|
|
result_record->oad.element_index = noti_info->oad.element_index;
|
|
|
|
os_mem_cpy(&result_record->rcsd, iot_pkt_data(rcsd_pkt), rcsd_len);
|
|
|
|
data = data + sizeof(proto_69845_app_rpt_result_record_t) +
|
|
rcsd_len - sizeof(proto_69845_app_data_rcsd_t);
|
|
|
|
noti_result = (proto_69845_app_rpt_noti_result_t *)data;
|
|
noti_result->type = PROTO_69845_APP_RPT_RESULT_DATA;
|
|
data += sizeof(proto_69845_app_rpt_noti_result_t);
|
|
|
|
record_row = (proto_69845_app_rpt_record_row_t *)data;
|
|
record_row->record_num = 1;
|
|
|
|
os_mem_cpy(record_row->data, iot_pkt_data(ele_pkt), ele_load_len);
|
|
|
|
data = data + sizeof(proto_69845_app_rpt_record_row_t) + ele_load_len;
|
|
break;
|
|
}
|
|
default:
|
|
goto drop;
|
|
}
|
|
tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
goto out;
|
|
drop:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
pkt = NULL;
|
|
}
|
|
out:
|
|
if (rcsd_pkt) {
|
|
iot_pkt_free(rcsd_pkt);
|
|
}
|
|
if (ele_pkt) {
|
|
iot_pkt_free(ele_pkt);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_rpt_noti_list_msg(
|
|
uint8_t* result_list, uint16_t list_len, uint8_t list_cnt,
|
|
const server_addr_info_t* server_info, uint8_t sn)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, ser_len;
|
|
uint16_t length;
|
|
uint16_t head_len, tail_len;
|
|
addr_info_t addr_info = { 0 };
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_noti_resp_t *noti;
|
|
proto_69845_app_rpt_noti_t *rpt_noti;
|
|
proto_69845_app_rpt_nor_list_t *nor_list;
|
|
|
|
if (server_info == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if (ser_len > PROTO_69845_SA_MAX_LEN || !ser_len) {
|
|
goto out;
|
|
}
|
|
length = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t) + sizeof(*noti) + sizeof(*rpt_noti)
|
|
+ sizeof(*nor_list) + list_len;
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len, length,
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_SERVER_REPORT);
|
|
data += head_len;
|
|
|
|
/* fill apdu data */
|
|
noti = (proto_69845_app_noti_resp_t*)data;
|
|
noti->type = PROTO_69845_S_APP_REPORT_NOTI;
|
|
rpt_noti = (proto_69845_app_rpt_noti_t*)noti->data;
|
|
rpt_noti->data_type = PROTO_69845_APP_REPRORT_NORMALLIST;
|
|
nor_list = (proto_69845_app_rpt_nor_list_t*)rpt_noti->data;
|
|
nor_list->piid_acd.sn = sn;
|
|
nor_list->piid_acd.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
|
|
nor_list->piid_acd.acd = 0;
|
|
nor_list->att_cnt = list_cnt;
|
|
os_mem_cpy(nor_list->data, result_list, list_len);
|
|
data = data + sizeof(*noti) + sizeof(*rpt_noti) + sizeof(*nor_list)
|
|
+ list_len;
|
|
tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
void proto_69845_check_frame_handler(uint8_t* buffer, uint32_t buffer_len,
|
|
bool_t* is_frame)
|
|
{
|
|
proto_69845_frame_head_info_t *head;
|
|
do {
|
|
if (buffer_len < sizeof(proto_69845_frame_head_info_t)) {
|
|
*is_frame = false;
|
|
break;
|
|
}
|
|
head = (proto_69845_frame_head_info_t*)buffer;
|
|
if ((uint16_t)buffer_len != (head->len + PROTO_69845_START_END_LEN)) {
|
|
*is_frame = false;
|
|
break;
|
|
}
|
|
if (buffer[0] != PROTO_69845_START_BYTE
|
|
|| buffer[head->len + 1] != PROTO_69845_END_BYTE) {
|
|
*is_frame = false;
|
|
break;
|
|
}
|
|
/* 698.45 frame check sum */
|
|
if (proto_fcs16_check(buffer + 1, head->len)) {
|
|
*is_frame = false;
|
|
break;
|
|
}
|
|
*is_frame = true;
|
|
} while(0);
|
|
}
|
|
|
|
proto_69845_app_data_time_s_t *proto_69845_get_time_rsp_msg_handle(
|
|
uint8_t *data, uint16_t len)
|
|
{
|
|
uint32_t ret, data_len;
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_69845_app_req_resp_t *resp;
|
|
proto_69845_app_get_resp_t *get_resp;
|
|
proto_69845_app_get_resp_normal_t *resp_normal;
|
|
proto_69845_app_data_time_s_t *time = NULL;
|
|
proto_69845_app_data_t *app_data;
|
|
apdu_info_t apdu;
|
|
hdr_698 = proto_69845_sanity_check(data, len);
|
|
if (!hdr_698) {
|
|
goto out;
|
|
}
|
|
if ((hdr_698->ctrl.dir_prm != PROTO_69845_D_P_SERVER_RESPONSE) &&
|
|
(hdr_698->ctrl.dir_prm != PROTO_69845_D_P_SERVER_REPORT)) {
|
|
goto out;
|
|
}
|
|
ret = proto_69845_get_apdu(hdr_698, len, &apdu);
|
|
if (ret != ERR_OK) {
|
|
goto out;
|
|
}
|
|
data_len = sizeof(*resp) + sizeof(*get_resp) + sizeof(*resp_normal) +
|
|
sizeof(*app_data) + sizeof(*time);
|
|
if (apdu.len < data_len) {
|
|
goto out;
|
|
}
|
|
resp = (proto_69845_app_req_resp_t*)(apdu.ptr);
|
|
if (resp->type == PROTO_69845_S_APP_GET_RESP) {
|
|
get_resp = (proto_69845_app_get_resp_t *)resp->data;
|
|
if (get_resp->data_type == PROTO_69845_APP_GET_NORMAL) {
|
|
resp_normal =
|
|
(proto_69845_app_get_resp_normal_t *)get_resp->data;
|
|
if ((proto_69845_byte_to_oi((uint8_t *)&resp_normal->oad.oi)
|
|
== PROTO_69845_APP_OI_TIME) &&
|
|
(resp_normal->oad.attribute_id == 2) &&
|
|
(resp_normal->result_type ==
|
|
PROTO_69845_APP_GET_RESULT_DATA)) {
|
|
app_data = (proto_69845_app_data_t*)resp_normal->result;
|
|
if (app_data->data_type == PROTO_69845_APP_DATA_TIME_S) {
|
|
time = (proto_69845_app_data_time_s_t *)app_data->data;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
out:
|
|
return time;
|
|
}
|
|
|
|
uint64_t proto_69845_ti_data_to_sec(proto_69845_app_data_ti_t *ti)
|
|
{
|
|
uint64_t uint = 0;
|
|
|
|
switch (ti->uint) {
|
|
case PROTO_OI_TI_INTERVAL_UNIT_TYPE_SEC:
|
|
{
|
|
uint = PROTO_OI_TI_INTERVAL_UNIT_SEC;
|
|
break;
|
|
}
|
|
case PROTO_OI_TI_INTERVAL_UNIT_TYPE_MIN:
|
|
{
|
|
uint = PROTO_OI_TI_INTERVAL_UNIT_MIN;
|
|
break;
|
|
}
|
|
case PROTO_OI_TI_INTERVAL_UNIT_TYPE_HOUR:
|
|
{
|
|
uint = PROTO_OI_TI_INTERVAL_UNIT_HOUR;
|
|
break;
|
|
}
|
|
case PROTO_OI_TI_INTERVAL_UNIT_TYPE_DAY:
|
|
{
|
|
uint = PROTO_OI_TI_INTERVAL_UNIT_DAY;
|
|
break;
|
|
}
|
|
case PROTO_OI_TI_INTERVAL_UNIT_TYPE_MON:
|
|
{
|
|
uint = PROTO_OI_TI_INTERVAL_UNIT_MON;
|
|
break;
|
|
}
|
|
case PROTO_OI_TI_INTERVAL_UNIT_TYPE_YEAR:
|
|
{
|
|
uint = PROTO_OI_TI_INTERVAL_UNIT_YEAR;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return (uint * ti->value);
|
|
}
|
|
|
|
uint32_t proto_69845_apdu_sec_ciphertext_check(uint8_t *apdu,
|
|
uint32_t len)
|
|
{
|
|
uint32_t ret = ERR_FAIL;
|
|
proto_69845_app_req_resp_t *req;
|
|
proto_69845_app_sec_req_resp_info_t *req_info;
|
|
|
|
if (len < (sizeof(*req) + sizeof(*req_info))) {
|
|
goto out;
|
|
}
|
|
req = (proto_69845_app_req_resp_t*)apdu;
|
|
if (req->type != PROTO_69845_C_APP_SECURITY_REQ
|
|
&& req->type != PROTO_69845_S_APP_SECURITY_RESP) {
|
|
goto out;
|
|
}
|
|
req_info = (proto_69845_app_sec_req_resp_info_t*)req->data;
|
|
if (req_info->type != PROTO_69845_SEC_DATA_TYPE_CIPHERTEXT) {
|
|
goto out;
|
|
}
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_corr_msg_check(uint8_t *data, uint32_t len, uint8_t *addr)
|
|
{
|
|
uint32_t ret = ERR_INVAL;
|
|
uint16_t oi;
|
|
proto_69845_frame_head_info_t *hdr_698 = NULL;
|
|
proto_69845_apdu_t *apdu_hdr;
|
|
proto_69845_app_action_req_t *req_hdr;
|
|
proto_69845_app_action_req_single_t *action_hdr;
|
|
apdu_info_t apdu = { 0 };
|
|
addr_info_t addr_info = {0};
|
|
|
|
if (!data || !len || !addr) {
|
|
goto out;
|
|
}
|
|
if (proto_69845_parse(&data, &len, &hdr_698, &apdu) != ERR_OK) {
|
|
goto out;
|
|
}
|
|
if (apdu.len < (sizeof(*apdu_hdr) + sizeof(*req_hdr)
|
|
+ sizeof(*action_hdr) + sizeof(proto_69845_app_data_time_s_t))) {
|
|
goto out;
|
|
}
|
|
proto_69845_oi_to_byte(PROTO_69845_APP_OI_TIME, (uint8_t*)&oi);
|
|
apdu_hdr = (proto_69845_apdu_t*)apdu.ptr;
|
|
req_hdr = (proto_69845_app_action_req_t*)apdu_hdr->data;
|
|
action_hdr = (proto_69845_app_action_req_single_t*)req_hdr->data;
|
|
if (apdu_hdr->type != PROTO_69845_C_APP_ACTION_REQ
|
|
|| req_hdr->data_type != PROTO_69845_APP_ACTION_NORMAL
|
|
|| action_hdr->omd.oi != oi
|
|
|| action_hdr->omd.method_id != PROTO_OMD_CORRECT_TIME_METHOD_ID
|
|
|| action_hdr->data.data_type != PROTO_69845_APP_DATA_TIME_S) {
|
|
goto out;
|
|
}
|
|
proto_69845_get_addr_info(hdr_698, &addr_info);
|
|
if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_SIG) {
|
|
if (addr_info.ser_info.len != IOT_MAC_ADDR_LEN) {
|
|
goto out;
|
|
}
|
|
iot_mac_addr_cpy(addr, addr_info.ser_info.addr);
|
|
} else if (hdr_698->addr.flag.sa_type == PROTO_69845_SA_TYPE_BROADCAST) {
|
|
os_mem_set(addr, 0xAA, IOT_MAC_ADDR_LEN);
|
|
} else {
|
|
goto out;
|
|
}
|
|
ret = ERR_OK;
|
|
out:
|
|
if (hdr_698 && hdr_698->ctrl.flag_scramble) {
|
|
/* the message is forwarded after recovery */
|
|
proto_69845_add33_handle(apdu.ptr, apdu.len);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#if PLC_SUPPORT_STA_ROLE
|
|
|
|
iot_pkt_t *proto_69845_build_get_req_msg(
|
|
proto_69845_app_get_req_info_t* req_info,
|
|
const server_addr_info_t* server_info)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, ser_len;
|
|
uint16_t length, head_len, tail_len;
|
|
addr_info_t addr_info = { 0 };
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *req;
|
|
proto_69845_app_get_req_t *get_req;
|
|
proto_69845_app_get_req_normal_t *get_req_normal;
|
|
|
|
if (req_info == NULL || server_info == NULL) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
|
|
switch (req_info->type) {
|
|
case PROTO_69845_APP_GET_NORMAL:
|
|
length = length + sizeof(*req) + sizeof(*get_req)
|
|
+ sizeof(*get_req_normal);
|
|
break;
|
|
default:
|
|
goto out;
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt)
|
|
goto out;
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
length - PROTO_69845_PREAMBLE_LEN,
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_CLIENT_REQUEST);
|
|
data += head_len;
|
|
|
|
/* fill apdu data */
|
|
req = (proto_69845_app_req_resp_t*)data;
|
|
req->type = PROTO_69845_C_APP_GET_REQ;
|
|
get_req = (proto_69845_app_get_req_t*)req->data;
|
|
get_req->data_type = req_info->type;
|
|
data = data + sizeof(proto_69845_app_req_resp_t)
|
|
+ sizeof(proto_69845_app_get_req_t);
|
|
switch (get_req->data_type) {
|
|
case PROTO_69845_APP_GET_NORMAL:
|
|
get_req_normal =
|
|
(proto_69845_app_get_req_normal_t*)get_req->data;
|
|
get_req_normal->piid = req_info->piid;
|
|
proto_69845_oi_to_byte(req_info->oad.oi,
|
|
(uint8_t*)&get_req_normal->oad.oi);
|
|
get_req_normal->oad.attribute_id = req_info->oad.attribute_id;
|
|
get_req_normal->oad.attribute_char = req_info->oad.attribute_char;
|
|
get_req_normal->oad.element_index = req_info->oad.element_index;
|
|
data += sizeof(proto_69845_app_get_req_normal_t);
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
tail_len = PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
|
|
proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_get_req_msg_with_rn(
|
|
proto_69845_app_get_list_req_info_t* req_info,
|
|
const server_addr_info_t* server_info)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, *time_tag;
|
|
uint8_t plaintext_len, ser_len;
|
|
uint16_t length, head_len;
|
|
addr_info_t addr_info = { 0 };
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_sec_req_resp_info_t *sec_req;
|
|
proto_69845_app_req_resp_t *req;
|
|
proto_69845_app_get_req_t *get_req;
|
|
proto_69845_app_get_req_normal_list_t *get_req_normal;
|
|
proto_69845_app_sec_req_resp_vali_info_t *vali_data;
|
|
proto_69845_app_sec_rn_info_t *rn;
|
|
|
|
if (req_info == NULL || server_info == NULL) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ sizeof(*req) + sizeof(*sec_req) + sizeof(*vali_data)
|
|
+ sizeof(*rn) + PROTO_69845_SECURITY_RN_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
switch (req_info->type) {
|
|
case PROTO_69845_APP_GET_NORMALLIST:
|
|
plaintext_len = sizeof(*req) + sizeof(*get_req)
|
|
+ sizeof(*get_req_normal)
|
|
+ sizeof(proto_69845_app_oad_t) * req_info->oad_cnt
|
|
+ PROTO_69845_NO_TIME_TAG_LEN;
|
|
break;
|
|
default:
|
|
goto out;
|
|
}
|
|
length += plaintext_len;
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt)
|
|
goto out;
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
length - PROTO_69845_PREAMBLE_LEN,
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_CLIENT_REQUEST);
|
|
data += head_len;
|
|
|
|
/* fill security request */
|
|
req = (proto_69845_app_req_resp_t*)data;
|
|
req->type = PROTO_69845_C_APP_SECURITY_REQ;
|
|
sec_req = (proto_69845_app_sec_req_resp_info_t*)req->data;
|
|
sec_req->type = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
|
|
sec_req->len = plaintext_len;
|
|
data = data + sizeof(proto_69845_app_req_resp_t)
|
|
+ sizeof(proto_69845_app_sec_req_resp_info_t);
|
|
|
|
/* fill plaintext apdu data */
|
|
req = (proto_69845_app_req_resp_t*)sec_req->data;
|
|
req->type = PROTO_69845_C_APP_GET_REQ;
|
|
get_req = (proto_69845_app_get_req_t*)req->data;
|
|
get_req->data_type = req_info->type;
|
|
data = data + sizeof(proto_69845_app_req_resp_t)
|
|
+ sizeof(proto_69845_app_get_req_t);
|
|
switch (get_req->data_type) {
|
|
case PROTO_69845_APP_GET_NORMALLIST:
|
|
{
|
|
get_req_normal =
|
|
(proto_69845_app_get_req_normal_list_t*)get_req->data;
|
|
get_req_normal->piid = req_info->piid;
|
|
get_req_normal->oad_cnt = req_info->oad_cnt;
|
|
data += sizeof(proto_69845_app_get_req_normal_list_t);
|
|
for (uint8_t i = 0; i < req_info->oad_cnt; i++) {
|
|
proto_69845_oi_to_byte(req_info->oad[i].oi,
|
|
(uint8_t*)&get_req_normal->oad[i].oi);
|
|
get_req_normal->oad[i].attribute_id =
|
|
req_info->oad[i].attribute_id;
|
|
get_req_normal->oad[i].attribute_char =
|
|
req_info->oad[i].attribute_char;
|
|
get_req_normal->oad[i].element_index =
|
|
req_info->oad[i].element_index;
|
|
data += sizeof(proto_69845_app_oad_t);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
/* There is no time tag field, so time_tag is 0 */
|
|
time_tag = data;
|
|
(*time_tag) = 0;
|
|
data += 1;
|
|
|
|
/* fill 698.45 proto security validation data */
|
|
vali_data = (proto_69845_app_sec_req_resp_vali_info_t*)data;
|
|
vali_data->type = PROTO_69845_SEC_REQ_VALI_TYPE_RN;
|
|
rn = (proto_69845_app_sec_rn_info_t*)vali_data->data;
|
|
rn->len = PROTO_69845_SECURITY_RN_LEN;
|
|
os_mem_cpy(rn->data, proto_69845_rn, PROTO_69845_SECURITY_RN_LEN);
|
|
data = data + sizeof(proto_69845_app_sec_req_resp_vali_info_t)
|
|
+ sizeof(proto_69845_app_sec_rn_info_t) + PROTO_69845_SECURITY_RN_LEN;
|
|
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_action_req_single_msg(
|
|
const proto_69845_app_action_req_single_t *req_info, uint16_t app_data_len,
|
|
const server_addr_info_t* server_info)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *apdu_head;
|
|
proto_69845_app_action_req_single_t *src_req_info;
|
|
proto_69845_app_action_req_t *req;
|
|
uint8_t ser_len;
|
|
uint16_t length, head_len;
|
|
uint8_t *data, *time_tag;
|
|
addr_info_t addr_info = { 0 };
|
|
|
|
if (req_info == NULL || server_info == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN +
|
|
sizeof(*apdu_head) + sizeof(*req) + sizeof(*req_info) + app_data_len +
|
|
PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
|
|
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt)
|
|
goto out;
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
length - PROTO_69845_PREAMBLE_LEN,
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_CLIENT_REQUEST);
|
|
data += head_len;
|
|
|
|
/* fill apdu data */
|
|
apdu_head = (proto_69845_app_req_resp_t*)data;
|
|
apdu_head->type = PROTO_69845_C_APP_ACTION_REQ;
|
|
data += sizeof(*apdu_head);
|
|
|
|
/* fill 698.45 action req single object header */
|
|
req = (proto_69845_app_action_req_t *)data;
|
|
req->data_type = PROTO_69845_APP_ACTION_NORMAL;
|
|
data += sizeof(*req);
|
|
|
|
/* fill 698.45 action req single object info */
|
|
os_mem_cpy(data, req_info, sizeof(*req_info));
|
|
src_req_info = (proto_69845_app_action_req_single_t *)data;
|
|
proto_69845_oi_to_byte(req_info->omd.oi,
|
|
(uint8_t *)&(src_req_info->omd.oi));
|
|
data += sizeof(*req_info);
|
|
|
|
/* fill 698.45 action req single object app data */
|
|
if (app_data_len) {
|
|
os_mem_cpy(data, req_info->data.data, app_data_len);
|
|
data += app_data_len;
|
|
}
|
|
|
|
/* There is no time tag field, so time_tag is 0 */
|
|
time_tag = data;
|
|
(*time_tag) = 0;
|
|
data += 1;
|
|
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
uint8_t proto_69845_oad_cmp(proto_69845_app_oad_t *oad_1,
|
|
proto_69845_app_oad_t *oad_2)
|
|
{
|
|
if (!oad_1 || !oad_2) {
|
|
return 0;
|
|
}
|
|
if (oad_1->oi == oad_2->oi && oad_1->attribute_id == oad_2->attribute_id &&
|
|
oad_1->attribute_char == oad_2->attribute_char &&
|
|
oad_1->element_index == oad_2->element_index) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_apdu_data_with_rn_msg(uint8_t *apdu_data,
|
|
uint32_t data_len, const server_addr_info_t* server_info)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, *len, ser_len, info_len_byte = 0;
|
|
uint16_t head_len;
|
|
uint32_t length;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *req;
|
|
proto_69845_app_sec_req_resp_info_t *req_info;
|
|
proto_69845_app_sec_req_resp_vali_info_t *vali_data;
|
|
proto_69845_app_sec_rn_info_t *rn;
|
|
proto_69845_app_len_descript_t *len_desc;
|
|
addr_info_t addr_info = { 0 };
|
|
|
|
if (apdu_data == NULL || server_info == NULL) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
if (data_len > 255) {
|
|
info_len_byte = 2;
|
|
} else if (data_len > 127) {
|
|
info_len_byte = 1;
|
|
}
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ sizeof(*req) + sizeof(*req_info)
|
|
+ sizeof(*vali_data) + sizeof(*rn) + PROTO_69845_SECURITY_RN_LEN
|
|
+ sizeof(proto_69845_tailer_t) + data_len + info_len_byte;
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
(uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_CLIENT_REQUEST);
|
|
data += head_len;
|
|
/* fill app req */
|
|
req = (proto_69845_app_req_resp_t *)data;
|
|
req->type = PROTO_69845_C_APP_SECURITY_REQ;
|
|
req_info = (proto_69845_app_sec_req_resp_info_t *)req->data;
|
|
req_info->type = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
|
|
if (!info_len_byte) {
|
|
req_info->len = (uint8_t)data_len;
|
|
data += (sizeof(*req) + sizeof(*req_info));
|
|
} else {
|
|
len_desc = (proto_69845_app_len_descript_t*)&req_info->len;
|
|
len_desc->mub_flag = 1;
|
|
len_desc->byte_num = info_len_byte;
|
|
len = (uint8_t*)req_info->data;
|
|
if (info_len_byte == 2) {
|
|
*len = (uint8_t)(data_len >> 8);
|
|
len++;
|
|
}
|
|
*len = (uint8_t)data_len;
|
|
data += (sizeof(*req) + sizeof(*req_info) + info_len_byte);
|
|
}
|
|
/* fill apdu data */
|
|
os_mem_cpy(req_info->data, apdu_data, data_len);
|
|
data += data_len;
|
|
/* fill 698.45 proto security validation data */
|
|
vali_data = (proto_69845_app_sec_req_resp_vali_info_t*)data;
|
|
vali_data->type = PROTO_69845_SEC_REQ_VALI_TYPE_RN;
|
|
rn = (proto_69845_app_sec_rn_info_t*)vali_data->data;
|
|
rn->len = PROTO_69845_SECURITY_RN_LEN;
|
|
os_mem_cpy(rn->data, proto_69845_rn, PROTO_69845_SECURITY_RN_LEN);
|
|
data = data + sizeof(proto_69845_app_sec_req_resp_vali_info_t)
|
|
+ sizeof(proto_69845_app_sec_rn_info_t) + PROTO_69845_SECURITY_RN_LEN;
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
static uint8_t proto_69845_get_tans_baud_id(uint32_t baud)
|
|
{
|
|
uint8_t i = 0;
|
|
|
|
for (i = 0; i < PROTO_69845_TANS_BAUD_MAX; i++) {
|
|
if (proto_69845_tans_baud[i] == baud) {
|
|
return i;
|
|
}
|
|
}
|
|
return PORTO_645_BAUD_ID_AUTO;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_proxy_trans_data_msg(uint8_t *data,
|
|
uint32_t data_len, uint32_t baud, uint8_t port, uint8_t parity,
|
|
uint16_t timeout, const server_addr_info_t* server_info, uint8_t sn)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *time_flag, *data_in, ser_len;
|
|
uint16_t head_len;
|
|
uint32_t length;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_apdu_t *apdu_req;
|
|
proto_69845_app_data_proxy_req_t *proxy_request;
|
|
proto_69845_app_data_proxy_tans_req_t *proxy_cmd_request;
|
|
addr_info_t addr_info;
|
|
|
|
if (!data || !server_info) {
|
|
goto out;
|
|
}
|
|
if (port != PROTO_PORT_RS485_1 && port != PROTO_PORT_RS485_2) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(server_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ sizeof(*proxy_request) + sizeof(*proxy_cmd_request)
|
|
+ sizeof(*apdu_req) + sizeof(proto_69845_tailer_t)
|
|
+ sizeof(*time_flag) + data_len;
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
/* fill 698.45 proto header */
|
|
data_in = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
|
|
head = (proto_69845_frame_head_info_t *)data_in;
|
|
addr_info.ser_info = *server_info;
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
(uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
|
|
&addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_CLIENT_REQUEST);
|
|
data_in += head_len;
|
|
/* fill app req */
|
|
apdu_req = (proto_69845_apdu_t *)data_in;
|
|
apdu_req->type = PROTO_69845_C_APP_PROXY_REQ;
|
|
|
|
proxy_request = (proto_69845_app_data_proxy_req_t *)apdu_req->data;
|
|
proxy_request->proxy_type = PROTO_69845_PROXY_TRANS_COMMAND_REQUEST;
|
|
|
|
proxy_cmd_request =
|
|
(proto_69845_app_data_proxy_tans_req_t*)proxy_request->data;
|
|
proxy_cmd_request->piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
|
|
proxy_cmd_request->piid.sn = sn;
|
|
|
|
if (port == PROTO_PORT_RS485_1) {
|
|
iot_uint32_to_bytes(PROTO_69845_APP_OAD_PORT_RS485I,
|
|
(uint8_t*)&proxy_cmd_request->oad, 1);
|
|
} else {
|
|
iot_uint32_to_bytes(PROTO_69845_APP_OAD_PORT_RS485II,
|
|
(uint8_t*)&proxy_cmd_request->oad, 1);
|
|
}
|
|
|
|
proxy_cmd_request->comdcb.buad = proto_69845_get_tans_baud_id(baud);
|
|
proxy_cmd_request->comdcb.parity = parity;
|
|
proxy_cmd_request->comdcb.stop = PROTO_69845_STOP_1_BITS;
|
|
proxy_cmd_request->comdcb.data_bit = PROTO_69845_DLEN_8_BITS;
|
|
proxy_cmd_request->comdcb.flow_mode = 0;
|
|
iot_uint16_to_bytes(timeout, (uint8_t*)&proxy_cmd_request->timeout1, 1);
|
|
iot_uint16_to_bytes(30, (uint8_t*)&proxy_cmd_request->timeout2, 1);
|
|
proxy_cmd_request->data_len = (uint8_t)data_len;
|
|
/* fill trans data */
|
|
os_mem_cpy(proxy_cmd_request->data, data, data_len);
|
|
time_flag = proxy_cmd_request->data + data_len;
|
|
*time_flag = 0;
|
|
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, time_flag + sizeof(*time_flag),
|
|
sizeof(proto_69845_tailer_t));
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_get_version_msg_with_rn(
|
|
const server_addr_info_t *server_info, uint8_t sn)
|
|
{
|
|
uint8_t *data = NULL;
|
|
proto_69845_apdu_t *apdu;
|
|
proto_69845_app_get_req_t *get_req = NULL;
|
|
proto_69845_app_get_req_normal_t *normal = NULL;
|
|
uint32_t req_size = 0;
|
|
iot_pkt_t *pkt = NULL, *req = NULL;
|
|
|
|
req_size = sizeof(*apdu) + sizeof(*get_req) + sizeof(*normal)
|
|
+ PROTO_69845_NO_TIME_TAG_LEN;
|
|
req = iot_pkt_alloc(req_size, IOT_SMART_GRID_MID);
|
|
if (!req) {
|
|
goto out;
|
|
}
|
|
data = iot_pkt_put(req, req_size);
|
|
apdu = (proto_69845_apdu_t *)data;
|
|
apdu->type = PROTO_69845_C_APP_GET_REQ;
|
|
get_req = (proto_69845_app_get_req_t *)apdu->data;
|
|
get_req->data_type = PROTO_69845_APP_GET_NORMAL;
|
|
normal = (proto_69845_app_get_req_normal_t *)get_req->data;
|
|
normal->piid.sn = sn;
|
|
normal->piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
|
|
proto_69845_oi_to_byte(PROTO_69845_APP_OI_GET_VERSION,
|
|
(uint8_t *)&normal->oad.oi);
|
|
normal->oad.attribute_id = 3;
|
|
normal->oad.attribute_char = 0;
|
|
normal->oad.element_index = 1;
|
|
pkt = proto_69845_build_apdu_data_with_rn_msg(data, req_size, server_info);
|
|
iot_pkt_free(req);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_comdcb_msg(uint32_t baud,
|
|
const server_addr_info_t *server_info, uint8_t sn)
|
|
{
|
|
uint16_t data_len = 0;
|
|
iot_pkt_t *ret = NULL, *pkt = NULL;
|
|
proto_69845_app_action_req_single_t *request = NULL;
|
|
proto_69845_app_ele_data_t *app_ele_data = NULL;
|
|
proto_69845_app_oad_t *app_oad = NULL;
|
|
proto_69845_app_data_t *app_data = NULL;
|
|
proto_69845_app_data_comdcb_t *comdcb = NULL;
|
|
|
|
data_len = sizeof(*app_data) + sizeof(*app_data) + sizeof(*app_oad) +
|
|
sizeof(*app_data) + sizeof(*comdcb);
|
|
pkt = iot_pkt_alloc(data_len + sizeof(*request), IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
request = (proto_69845_app_action_req_single_t *)iot_pkt_data(pkt);
|
|
request->piid.sn = sn;
|
|
request->omd.oi = PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE;
|
|
request->omd.method_id = 0x80;
|
|
request->omd.operation_mode = 0x00;
|
|
|
|
app_ele_data = (proto_69845_app_ele_data_t *)&request->data;
|
|
app_ele_data->data_type = PROTO_69845_APP_DATA_STRUCTURE;
|
|
app_ele_data->num_of_data = 2;
|
|
app_data = (proto_69845_app_data_t *)app_ele_data->data;
|
|
app_data->data_type = PROTO_69845_APP_DATA_OAD;
|
|
|
|
app_oad = (proto_69845_app_oad_t *)app_data->data;
|
|
app_oad->oi = PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE;
|
|
proto_69845_oi_to_byte(app_oad->oi, (uint8_t *)&(app_oad->oi));
|
|
|
|
app_oad->attribute_id = 0x02;
|
|
app_oad->element_index = 0xFD;
|
|
|
|
app_data = (proto_69845_app_data_t *)(app_oad + 1);
|
|
app_data->data_type = PROTO_69845_APP_DATA_COMDCB;
|
|
|
|
comdcb = (proto_69845_app_data_comdcb_t *)app_data->data;
|
|
comdcb->buad = proto_69845_get_tans_baud_id(baud);
|
|
comdcb->parity = PROTO_69845_PARITY_EVEN;
|
|
comdcb->data_bit = PROTO_69845_DLEN_8_BITS;
|
|
comdcb->stop = PROTO_69845_STOP_1_BITS;
|
|
comdcb->flow_mode = 0;
|
|
ret = proto_69845_build_action_req_single_msg(
|
|
request, data_len, server_info);
|
|
out:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_proxy_trans_resp_parse(uint8_t **data,
|
|
uint16_t *len, uint8_t *seq)
|
|
{
|
|
uint32_t oad, apdu_len, err = ERR_OK;
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
apdu_info_t apdu_desc = { 0 };
|
|
proto_69845_apdu_t *apdu_resq;
|
|
proto_69845_app_data_proxy_req_t *proxy_resq;
|
|
proto_69845_app_data_proxy_tans_resp_t *proxy_tans_resp;
|
|
if (!data || !(*data) || !len) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
hdr_698 = proto_69845_sanity_check(*data, *len);
|
|
if (!hdr_698) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (proto_69845_get_apdu(hdr_698, *len, &apdu_desc) != ERR_OK) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (!apdu_desc.len || !apdu_desc.ptr) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
apdu_len = apdu_desc.len;
|
|
if (apdu_len < sizeof(*apdu_resq) + sizeof(*proxy_resq)
|
|
+ sizeof(*proxy_tans_resp)) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
apdu_len -= sizeof(*apdu_resq) + sizeof(*proxy_resq)
|
|
+ sizeof(*proxy_tans_resp);
|
|
apdu_resq = (proto_69845_apdu_t *)apdu_desc.ptr;
|
|
if (apdu_resq->type != PROTO_69845_S_APP_PROXY_RESP) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
proxy_resq = (proto_69845_app_data_proxy_req_t *)apdu_resq->data;
|
|
if (proxy_resq->proxy_type != PROTO_69845_PROXY_TRANS_COMMAND_REQUEST) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
proxy_tans_resp =
|
|
(proto_69845_app_data_proxy_tans_resp_t *)proxy_resq->data;
|
|
oad = iot_bytes_to_uint32((uint8_t*)&proxy_tans_resp->oad, 1);
|
|
if (oad != PROTO_69845_APP_OAD_PORT_RS485I
|
|
&& oad != PROTO_69845_APP_OAD_PORT_RS485II) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (proxy_tans_resp->data_type != PROTO_69845_APP_DATA_ARRAY
|
|
|| !proxy_tans_resp->data_len) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (apdu_len < proxy_tans_resp->data_len) {
|
|
err = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
*len = proxy_tans_resp->data_len;
|
|
*data = proxy_tans_resp->data;
|
|
*seq = proxy_tans_resp->piid.sn;
|
|
out:
|
|
return err;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_apdu_data_msg(uint8_t *apdu_data,
|
|
uint32_t data_len, addr_info_t* addr_info, uint8_t dir_and_prm)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, ser_len;
|
|
uint16_t head_len;
|
|
uint32_t length;
|
|
proto_69845_frame_head_info_t *head;
|
|
|
|
if (apdu_data == NULL || addr_info == NULL) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ data_len + sizeof(proto_69845_tailer_t);
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
(uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
|
|
addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
dir_and_prm);
|
|
data += head_len;
|
|
/* fill apdu data */
|
|
os_mem_cpy(data, apdu_data, data_len);
|
|
data += data_len;
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_apdu_data_with_security_resp_msg(uint8_t *apdu_data,
|
|
uint32_t data_len, addr_info_t* addr_info)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, *len, info_len_byte = 0, ser_len;
|
|
uint16_t head_len;
|
|
uint32_t length;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *resp;
|
|
proto_69845_app_sec_req_resp_info_t *resp_info;
|
|
proto_69845_app_sec_optinon_info_t *vali_data;
|
|
proto_69845_app_sec_mac_info_t *sec_mac;
|
|
proto_69845_app_len_descript_t *len_desc;
|
|
|
|
if (apdu_data == NULL || addr_info == NULL) {
|
|
goto out;
|
|
}
|
|
ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
if (data_len > 255) {
|
|
info_len_byte = 2;
|
|
} else if (data_len > 127) {
|
|
info_len_byte = 1;
|
|
}
|
|
length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
|
|
+ ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
|
|
+ sizeof(*resp) + sizeof(*resp_info)
|
|
+ sizeof(*vali_data) + sizeof(*sec_mac)
|
|
+ info_len_byte + PROTO_69845_SECURITY_SEQUEN_LEN
|
|
+ sizeof(proto_69845_tailer_t) + data_len;
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt) {
|
|
goto out;
|
|
}
|
|
iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
head_len = sizeof(*head) + ser_len
|
|
+ PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len,
|
|
(uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
|
|
addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_SERVER_RESPONSE);
|
|
data += head_len;
|
|
/* fill app req */
|
|
resp = (proto_69845_app_req_resp_t *)data;
|
|
resp->type = PROTO_69845_S_APP_SECURITY_RESP;
|
|
resp_info = (proto_69845_app_sec_req_resp_info_t *)resp->data;
|
|
resp_info->type = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
|
|
if (!info_len_byte) {
|
|
resp_info->len = (uint8_t)data_len;
|
|
data += (sizeof(*resp) + sizeof(*resp_info));
|
|
} else {
|
|
len_desc = (proto_69845_app_len_descript_t*)&resp_info->len;
|
|
len_desc->mub_flag = 1;
|
|
len_desc->byte_num = info_len_byte;
|
|
len = (uint8_t*)resp_info->data;
|
|
if (info_len_byte == 2) {
|
|
*len = (uint8_t)(data_len >> 8);
|
|
len++;
|
|
}
|
|
*len = (uint8_t)data_len;
|
|
data += (sizeof(*resp) + sizeof(*resp_info) + info_len_byte);
|
|
}
|
|
|
|
/* fill apdu data */
|
|
os_mem_cpy(data, apdu_data, data_len);
|
|
data += data_len;
|
|
/* fill 698.45 proto security validation data */
|
|
vali_data = (proto_69845_app_sec_optinon_info_t*)data;
|
|
vali_data->type = PROTO_69845_SEC_RESP_VALI_TYPE_MAC_RN;
|
|
vali_data->choice = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
|
|
sec_mac = (proto_69845_app_sec_mac_info_t*)vali_data->data;
|
|
sec_mac->len = PROTO_69845_SECURITY_SEQUEN_LEN;
|
|
os_mem_cpy(sec_mac->data, proto_69845_rn, PROTO_69845_SECURITY_SEQUEN_LEN);
|
|
data = data + sizeof(proto_69845_app_sec_optinon_info_t)
|
|
+ sizeof(proto_69845_app_sec_mac_info_t)
|
|
+ PROTO_69845_SECURITY_SEQUEN_LEN;
|
|
/* fill 698.45 proto tailer */
|
|
proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_set_normal_ack(addr_info_t *addr_info,
|
|
proto_69845_app_piid_t *piid, proto_69845_app_oad_t *oad,
|
|
uint8_t dar)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, ser_len;
|
|
uint16_t length, head_len, tail_len;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *resp;
|
|
proto_69845_app_set_resp_t *set_resp;
|
|
proto_69845_app_set_resp_normal_t *set_normal;
|
|
|
|
if (addr_info == NULL || piid == NULL || oad == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
|
|
length = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
|
|
+ PROTO_69845_CHECKSUM_LEN + sizeof(*resp) + sizeof(*set_resp)
|
|
+ sizeof(*set_normal) + PROTO_69845_NO_TIME_TAG_LEN
|
|
+ PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt)
|
|
goto out;
|
|
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
head_len = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
|
|
+ PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len, length,
|
|
addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_SERVER_RESPONSE);
|
|
data += head_len;
|
|
|
|
/* fill plaintext apdu data */
|
|
resp = (proto_69845_app_req_resp_t*)data;
|
|
resp->type = PROTO_69845_S_APP_SET_RESP;
|
|
set_resp = (proto_69845_app_set_resp_t*)resp->data;
|
|
set_resp->data_type = PROTO_69845_APP_SET_NORMAL;
|
|
data = data + sizeof(*resp) + sizeof(*set_resp);
|
|
set_normal = (proto_69845_app_set_resp_normal_t*)set_resp->data;
|
|
set_normal->piid_acd.sn = piid->sn;
|
|
set_normal->piid_acd.priority = piid->priority;
|
|
set_normal->piid_acd.acd = 0;
|
|
proto_69845_oi_to_byte(oad->oi, (uint8_t*)&set_normal->result.oad.oi);
|
|
set_normal->result.oad.attribute_char = oad->attribute_char;
|
|
set_normal->result.oad.attribute_id = oad->attribute_id;
|
|
set_normal->result.oad.element_index = oad->element_index;
|
|
set_normal->result.dar = dar;
|
|
data += sizeof(*set_normal);
|
|
/* There is no time tag field, so time_tag is 0 */
|
|
tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_action_single_ack(addr_info_t *addr_info,
|
|
proto_69845_app_piid_t *piid, proto_69845_app_omd_t *omd,
|
|
uint8_t dar)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t *data, ser_len;
|
|
uint16_t length, head_len, tail_len;
|
|
proto_69845_frame_head_info_t *head;
|
|
proto_69845_app_req_resp_t *resp;
|
|
proto_69845_app_action_resp_t *action_resp;
|
|
proto_69845_app_action_resp_normal_t *action_normal;
|
|
|
|
if (addr_info == NULL || piid == NULL || omd == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
|
|
if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
|
|
goto out;
|
|
}
|
|
|
|
length = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
|
|
+ PROTO_69845_CHECKSUM_LEN + sizeof(*resp) + sizeof(*action_resp)
|
|
+ sizeof(*action_normal) + PROTO_69845_NO_TIME_TAG_LEN
|
|
+ PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
|
|
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (!pkt)
|
|
goto out;
|
|
|
|
/* fill 698.45 proto header */
|
|
data = iot_pkt_data(pkt);
|
|
head = (proto_69845_frame_head_info_t *)data;
|
|
head_len = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
|
|
+ PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(head, head_len, length,
|
|
addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_SERVER_RESPONSE);
|
|
data += head_len;
|
|
|
|
/* fill plaintext apdu data */
|
|
resp = (proto_69845_app_req_resp_t*)data;
|
|
resp->type = PROTO_69845_S_APP_ACTION_RESP;
|
|
action_resp = (proto_69845_app_action_resp_t*)resp->data;
|
|
action_resp->data_type = PROTO_69845_APP_ACTION_NORMAL;
|
|
data = data + sizeof(*resp) + sizeof(*action_resp);
|
|
action_normal = (proto_69845_app_action_resp_normal_t*)action_resp->data;
|
|
action_normal->piid_acd.sn = piid->sn;
|
|
action_normal->piid_acd.priority = piid->priority;
|
|
action_normal->piid_acd.acd = 0;
|
|
proto_69845_oi_to_byte(omd->oi, (uint8_t*)&action_normal->result.omd.oi);
|
|
action_normal->result.omd.method_id = omd->method_id;
|
|
action_normal->result.omd.operation_mode = omd->operation_mode;
|
|
action_normal->result.dar = dar;
|
|
action_normal->result.optional = PROTO_69845_APP_OPTIONAL_NO_DATA;
|
|
data += sizeof(*action_normal);
|
|
/* There is no time tag field, so time_tag is 0 */
|
|
tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
|
|
+ sizeof(proto_69845_tailer_t);
|
|
proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
|
|
iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
/* create a meter correcting time message for the 69845 protocol */
|
|
iot_pkt_t *proto_69845_build_corr_msg(server_addr_info_t *server_addr,
|
|
iot_time_tm_t *tm, proto_69845_app_piid_t *piid, uint8_t with_rn)
|
|
{
|
|
uint8_t *time_tag, *data;
|
|
uint32_t action_req_size;
|
|
proto_69845_apdu_t *apdu;
|
|
proto_69845_app_action_req_t *act_req;
|
|
proto_69845_app_action_req_single_t *req_single;
|
|
proto_69845_app_data_time_s_t *time;
|
|
iot_pkt_t *pkt = NULL, *get_action_req = NULL;
|
|
addr_info_t addr_info = { 0 };
|
|
|
|
if (!tm || !piid) {
|
|
goto out;
|
|
}
|
|
action_req_size = sizeof(*apdu) + sizeof(*act_req) + sizeof(*req_single)
|
|
+ sizeof(*time) + sizeof(*time_tag);
|
|
get_action_req = iot_pkt_alloc(action_req_size, IOT_SMART_GRID_MID);
|
|
if (!get_action_req) {
|
|
goto out;
|
|
}
|
|
data = iot_pkt_put(get_action_req, action_req_size);
|
|
apdu = (proto_69845_apdu_t *)data;
|
|
apdu->type = PROTO_69845_C_APP_ACTION_REQ;
|
|
act_req = (proto_69845_app_action_req_t *)apdu->data;
|
|
act_req->data_type = PROTO_69845_APP_ACTION_NORMAL;
|
|
req_single = (proto_69845_app_action_req_single_t *)act_req->data;
|
|
req_single->piid.priority = piid->priority;
|
|
req_single->piid.sn = piid->sn;
|
|
proto_69845_oi_to_byte(PROTO_69845_APP_OI_TIME,
|
|
(uint8_t*)&req_single->omd.oi);
|
|
req_single->omd.method_id = PROTO_OMD_CORRECT_TIME_METHOD_ID;
|
|
req_single->omd.operation_mode = 0;
|
|
req_single->data.data_type = PROTO_69845_APP_DATA_TIME_S;
|
|
time = (proto_69845_app_data_time_s_t *)req_single->data.data;
|
|
time->year = iot_bytes_to_uint16((uint8_t *)&tm->tm_year, 1);
|
|
time->month = tm->tm_mon;
|
|
time->day = tm->tm_mday;
|
|
time->hour = tm->tm_hour;
|
|
time->minute = tm->tm_min;
|
|
time->second = tm->tm_sec;
|
|
time_tag = data + sizeof(*apdu) + sizeof(*act_req) + sizeof(*req_single)
|
|
+ sizeof(*time);
|
|
*time_tag = 0;
|
|
if (!server_addr) {
|
|
if (with_rn) {
|
|
pkt = proto_69845_build_apdu_data_with_rn_msg((uint8_t *)apdu,
|
|
action_req_size, &proto_69845_any_server_addr);
|
|
} else {
|
|
addr_info.ser_info = proto_69845_any_server_addr;
|
|
pkt = proto_69845_build_apdu_data_msg((uint8_t *)apdu,
|
|
action_req_size, &addr_info, PROTO_69845_D_P_CLIENT_REQUEST);
|
|
}
|
|
} else {
|
|
if (with_rn) {
|
|
pkt = proto_69845_build_apdu_data_with_rn_msg((uint8_t *)apdu,
|
|
action_req_size, server_addr);
|
|
} else {
|
|
addr_info.ser_info = *server_addr;
|
|
pkt = proto_69845_build_apdu_data_msg((uint8_t *)apdu,
|
|
action_req_size, &addr_info, PROTO_69845_D_P_CLIENT_REQUEST);
|
|
}
|
|
}
|
|
iot_pkt_free(get_action_req);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t proto_69845_dlong_unsign_data_to_meter_bcd_data(
|
|
uint8_t *dlong_data, uint8_t dlong_data_len, uint8_t *meter_bcd_data,
|
|
uint8_t bcd_len)
|
|
{
|
|
uint32_t data;
|
|
if (dlong_data == NULL
|
|
|| dlong_data_len != PROTO_69845_METER_DATA_DOUBLE_LONG_LEN
|
|
|| meter_bcd_data == NULL
|
|
|| !bcd_len) {
|
|
return ERR_FAIL;
|
|
}
|
|
data = iot_bytes_to_uint32(dlong_data, 1);
|
|
iot_uint32_to_bcd(data, bcd_len, meter_bcd_data);
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t proto_69845_long_unsign_to_meter_bcd_data(
|
|
uint8_t *long_data, uint8_t long_data_len, uint8_t *meter_bcd_data,
|
|
uint8_t bcd_len)
|
|
{
|
|
uint8_t high, low;
|
|
uint16_t data;
|
|
uint32_t ret = ERR_OK;
|
|
if (long_data == NULL
|
|
|| long_data_len != PROTO_69845_METER_DATA_LONG_LEN
|
|
|| meter_bcd_data == NULL
|
|
|| !bcd_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
data = iot_bytes_to_uint16(long_data, 1);
|
|
high = (uint8_t)(data / 100);
|
|
low = (uint8_t)(data % 100);
|
|
if (bcd_len > sizeof(data)) {
|
|
bcd_len = sizeof(data);
|
|
}
|
|
if (!bcd_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
meter_bcd_data[0] = iot_byte_to_bcd(low);
|
|
bcd_len--;
|
|
if (!bcd_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
meter_bcd_data[1] = iot_byte_to_bcd(high);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_dlong_data_to_meter_bcd_data(
|
|
uint8_t *dlong_data, uint8_t dlong_data_len, uint8_t *meter_bcd_data,
|
|
uint8_t bcd_len)
|
|
{
|
|
uint8_t flag_neg = 0;
|
|
int32_t data;
|
|
if (dlong_data == NULL
|
|
|| dlong_data_len != PROTO_69845_METER_DATA_DOUBLE_LONG_LEN
|
|
|| meter_bcd_data == NULL
|
|
|| !bcd_len) {
|
|
return ERR_FAIL;
|
|
}
|
|
data = (int32_t)iot_bytes_to_uint32(dlong_data, 1);
|
|
if (data < 0) {
|
|
flag_neg = 1;
|
|
data = 0 - data;
|
|
}
|
|
iot_uint32_to_bcd((uint32_t)data, bcd_len, meter_bcd_data);
|
|
if (flag_neg) {
|
|
meter_bcd_data[bcd_len - 1] |= 0x80;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t proto_69845_long_data_to_meter_bcd_data(
|
|
uint8_t *long_data, uint8_t long_data_len, uint8_t *meter_bcd_data,
|
|
uint8_t bcd_len)
|
|
{
|
|
uint8_t high, low, flag_neg = 0;;
|
|
int16_t data;
|
|
uint32_t ret = ERR_OK;
|
|
if (long_data == NULL
|
|
|| long_data_len != PROTO_69845_METER_DATA_LONG_LEN
|
|
|| meter_bcd_data == NULL
|
|
|| !bcd_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
data = (int16_t)iot_bytes_to_uint16(long_data, 1);
|
|
if (data < 0) {
|
|
flag_neg = 1;
|
|
data = 0 - data;
|
|
}
|
|
high = (uint8_t)(data / 100);
|
|
low = (uint8_t)(data % 100);
|
|
if (bcd_len > sizeof(data)) {
|
|
bcd_len = sizeof(data);
|
|
}
|
|
if (!bcd_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
meter_bcd_data[0] = iot_byte_to_bcd(low);
|
|
bcd_len--;
|
|
if (!bcd_len) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
meter_bcd_data[1] = iot_byte_to_bcd(high);
|
|
if (flag_neg) {
|
|
meter_bcd_data[1] |= 0x80;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_pf_ele_data_handle(proto_645_07_pf_t *meter_pf,
|
|
proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
|
|
{
|
|
uint8_t i, *meter_data, *data;
|
|
uint32_t ele_len, ret = ERR_OK;;
|
|
proto_69845_app_data_t *app_data;
|
|
|
|
ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_LONG_LEN;
|
|
if (data_len < ele_len * ele_data->num_of_data) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
data = ele_data->data;
|
|
BUILD_BUG_ON(sizeof(meter_pf->total) == PROTO_645_07_PF_LEN);
|
|
meter_data = meter_pf->total;
|
|
for (i = 0; i < ele_data->num_of_data && i < PROTO_69845_POWER_MAX_ELE_NUM;
|
|
i++) {
|
|
app_data = (proto_69845_app_data_t *)data;
|
|
if (app_data->data_type == PROTO_69845_APP_DATA_LONG) {
|
|
if (proto_69845_long_data_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_LONG_LEN,
|
|
meter_data, PROTO_645_07_PF_LEN) != ERR_OK) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
data += ele_len;
|
|
meter_data += PROTO_645_07_PF_LEN;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_v_data_handle(proto_645_v_t *meter_v,
|
|
proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
|
|
{
|
|
uint8_t i, *meter_data, *data;
|
|
uint32_t ele_len, ret = ERR_OK;
|
|
proto_69845_app_data_t *app_data;
|
|
|
|
ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_LONG_LEN;
|
|
if (data_len < ele_len * ele_data->num_of_data) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
data = ele_data->data;
|
|
meter_data = meter_v->a;
|
|
BUILD_BUG_ON(sizeof(meter_v->a) == PROTO_645_V_LEN);
|
|
for (i = 0; i < ele_data->num_of_data &&
|
|
i < PROTO_69845_SPLIT_PHASE_MAX_ELE_NUM; i++) {
|
|
app_data = (proto_69845_app_data_t *)data;
|
|
if (app_data->data_type == PROTO_69845_APP_DATA_LONG_UNSIGNED) {
|
|
if (proto_69845_long_unsign_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_LONG_LEN,
|
|
meter_data, PROTO_645_V_LEN) != ERR_OK) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
data += ele_len;
|
|
meter_data += PROTO_645_V_LEN;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_a_data_handle(proto_645_07_a_t *meter_a,
|
|
proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
|
|
{
|
|
uint8_t i, *meter_data, *data;
|
|
uint32_t ele_len, ret = ERR_OK;
|
|
proto_69845_app_data_t *app_data;
|
|
|
|
ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
|
|
if (data_len < ele_len * ele_data->num_of_data) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
data = ele_data->data;
|
|
meter_data = meter_a->a;
|
|
BUILD_BUG_ON(sizeof(meter_a->a) == PROTO_645_07_A_LEN);
|
|
for (i = 0; i < ele_data->num_of_data &&
|
|
i < PROTO_69845_SPLIT_PHASE_MAX_ELE_NUM; i++) {
|
|
app_data = (proto_69845_app_data_t *)data;
|
|
if (app_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
|
|
if (proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_DOUBLE_LONG_LEN,
|
|
meter_data, PROTO_645_07_A_LEN) != ERR_OK){
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
data += ele_len;
|
|
meter_data += PROTO_645_07_A_LEN;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_gnd_a_data_handle(uint8_t *meter_gnd_a, uint8_t gnd_a_len,
|
|
uint8_t *data, uint32_t data_len)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
proto_69845_app_data_t *app_data;
|
|
|
|
if (data_len < sizeof(*app_data) || gnd_a_len < PROTO_645_07_A_LEN) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
app_data = (proto_69845_app_data_t *)data;
|
|
data_len -= sizeof(*app_data);
|
|
if (app_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
if (data_len < PROTO_69845_METER_DATA_DOUBLE_LONG_LEN) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
ret = proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_DOUBLE_LONG_LEN, meter_gnd_a,
|
|
PROTO_645_07_A_LEN);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_power_data_handle(int32_t power[],
|
|
uint8_t **data, uint32_t *len)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
uint8_t *ds = *data, i, ele_len;
|
|
proto_69845_app_data_t *fix_data;
|
|
proto_69845_app_ele_data_t *var_data = (proto_69845_app_ele_data_t *)ds;
|
|
if (*len < sizeof(*var_data)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
*len -= sizeof(*var_data);
|
|
ds += sizeof(*var_data);
|
|
|
|
ele_len = PROTO_69845_METER_DATA_DOUBLE_LONG_LEN + sizeof(*fix_data);
|
|
|
|
for (i = 0; i < var_data->num_of_data && *len > ele_len; i++) {
|
|
fix_data = (proto_69845_app_data_t *)ds;
|
|
if (fix_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
|
|
power[i] = (int32_t)iot_bytes_to_uint32(fix_data->data, 1);
|
|
} else {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
ds += ele_len;
|
|
*len -= ele_len;
|
|
}
|
|
*data = ds;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_time_data_handle(iot_time_tm_t *meter_time,
|
|
uint8_t **data, uint32_t *len)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
proto_69845_app_data_t *app_data;
|
|
proto_69845_app_data_time_s_t *time;
|
|
app_data = (proto_69845_app_data_t*)(*data);
|
|
if (*len < sizeof(*app_data) + sizeof(*time)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
*data += sizeof(*app_data) + sizeof(*time);
|
|
*len -= sizeof(*app_data) + sizeof(*time);
|
|
if (app_data->data_type != PROTO_69845_APP_DATA_TIME_S) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
time = (proto_69845_app_data_time_s_t *)app_data->data;
|
|
meter_time->tm_year = iot_bytes_to_uint16((uint8_t *)&time->year, 1);
|
|
meter_time->tm_mon = time->month;;
|
|
meter_time->tm_mday = time->day;
|
|
meter_time->tm_hour = time->hour;
|
|
meter_time->tm_min = time->minute;
|
|
meter_time->tm_sec = time->second;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_run_state_data_handle(proto_69845_rs_word_t *rs_word,
|
|
uint8_t **data, uint32_t *len)
|
|
{
|
|
uint8_t i, *ds;
|
|
uint16_t *word;
|
|
uint32_t ele_len, ret = ERR_OK;
|
|
proto_69845_app_ele_data_t *var_data;
|
|
proto_69845_app_ele_data_t *word_data;
|
|
if (*len < sizeof(*var_data)) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
var_data = (proto_69845_app_ele_data_t *)(*data);
|
|
*len -= sizeof(*var_data);
|
|
|
|
if (var_data->num_of_data != PROTO_69845_RS_WORDS_NUM) {
|
|
ret = ERR_FAIL;
|
|
goto out;
|
|
}
|
|
ele_len = sizeof(*var_data) + PROTO_69845_METER_DATA_LONG_LEN;
|
|
|
|
ds = var_data->data;
|
|
word = (uint16_t *)rs_word;
|
|
BUILD_BUG_ON(sizeof(*rs_word) == PROTO_69845_RS_WORDS_NUM * \
|
|
PROTO_69845_METER_DATA_LONG_LEN);
|
|
for (i = 0; i < var_data->num_of_data && *len > ele_len; i++) {
|
|
word_data = (proto_69845_app_ele_data_t *)ds;
|
|
if (word_data->data_type != PROTO_69845_APP_DATA_BIT_STRING ||
|
|
word_data->num_of_data != PROTO_69845_APP_DATA_LONG) {
|
|
break;
|
|
}
|
|
*word = iot_bytes_to_uint16(word_data->data, 1);
|
|
*len -= ele_len;
|
|
ds += ele_len;
|
|
word++;
|
|
}
|
|
if (i != PROTO_69845_RS_WORDS_NUM)
|
|
ret = ERR_FAIL;
|
|
*data = ds;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t proto_69845_evt_cur_info_parse(uint32_t *occur_n, uint32_t *acc_time,
|
|
uint8_t **data, uint32_t *len)
|
|
{
|
|
uint8_t *ds = *data, evt_src_len, ele_len;
|
|
proto_69845_app_data_t *fix_data;
|
|
proto_69845_app_ele_data_t *var_data;
|
|
if (*len < sizeof (*var_data))
|
|
goto err;
|
|
|
|
var_data = (proto_69845_app_ele_data_t *)ds;
|
|
ds += sizeof (*var_data);
|
|
*len -= sizeof (*var_data);
|
|
|
|
if (var_data->data_type != PROTO_69845_APP_DATA_ARRAY)
|
|
goto err;
|
|
if (var_data->num_of_data != 1)
|
|
goto err;
|
|
if (*len < sizeof (*var_data))
|
|
goto err;
|
|
|
|
var_data = (proto_69845_app_ele_data_t *)ds;
|
|
ds += sizeof (*var_data);
|
|
*len -= sizeof (*var_data);
|
|
|
|
if (var_data->data_type != PROTO_69845_APP_DATA_STRUCTURE)
|
|
goto err;
|
|
if (var_data->num_of_data != 2)
|
|
goto err;
|
|
|
|
/* parsing the event source */
|
|
if (*len < sizeof(*fix_data)) {
|
|
goto err;
|
|
}
|
|
|
|
fix_data = (proto_69845_app_data_t *)ds;
|
|
ds += sizeof (*fix_data);
|
|
*len -= sizeof (*fix_data);
|
|
switch (fix_data->data_type) {
|
|
case PROTO_69845_APP_DATA_NULL:
|
|
evt_src_len = 0;
|
|
break;
|
|
default:
|
|
goto err;
|
|
}
|
|
if (*len < evt_src_len)
|
|
goto err;
|
|
ds += evt_src_len;
|
|
*len -= evt_src_len;
|
|
|
|
if (*len < sizeof (*var_data))
|
|
goto err;
|
|
var_data = (proto_69845_app_ele_data_t *)ds;
|
|
ds += sizeof (*var_data);
|
|
*len -= sizeof (*var_data);
|
|
if (var_data->data_type != PROTO_69845_APP_DATA_STRUCTURE) {
|
|
goto err;
|
|
}
|
|
if (var_data->num_of_data != 2) {
|
|
goto err;
|
|
}
|
|
|
|
ele_len = PROTO_69845_METER_DATA_DOUBLE_LONG_LEN + sizeof(*fix_data);
|
|
fix_data = (proto_69845_app_data_t *)ds;
|
|
if (fix_data->data_type == PROTO_69845_APP_DATA_NULL) {
|
|
ds += sizeof(*fix_data);
|
|
*len -= sizeof(*fix_data);
|
|
} else if (fix_data->data_type ==
|
|
PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
|
|
if (occur_n)
|
|
*occur_n = iot_bytes_to_uint32(fix_data->data, 1);
|
|
ds += ele_len;
|
|
*len -= ele_len;
|
|
} else {
|
|
goto err;
|
|
}
|
|
|
|
fix_data = (proto_69845_app_data_t *)ds;
|
|
if (fix_data->data_type == PROTO_69845_APP_DATA_NULL) {
|
|
ds += sizeof (*fix_data);
|
|
*len -= sizeof (*fix_data);
|
|
} else if (fix_data->data_type ==
|
|
PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
|
|
if (acc_time)
|
|
*acc_time = iot_bytes_to_uint32(fix_data->data, 1);
|
|
ds += ele_len;
|
|
*len -= ele_len;
|
|
} else {
|
|
goto err;
|
|
}
|
|
*data = ds;
|
|
return ERR_OK;
|
|
|
|
err:
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
uint32_t proto_69845_energy_data_handle(uint32_t *energy,
|
|
uint8_t **data, uint32_t *in_len)
|
|
{
|
|
uint8_t *ds = *data, i, cnt;
|
|
uint32_t len = *in_len;
|
|
proto_69845_app_data_t *fix_data;
|
|
uint32_t ele_len;
|
|
if (len < sizeof(proto_69845_app_ele_data_t)) {
|
|
return ERR_FAIL;
|
|
}
|
|
switch (ds[0]) {
|
|
case PROTO_69845_APP_DATA_DOUBLE_LONG:
|
|
case PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED:
|
|
{
|
|
cnt = 1;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_DATA_ARRAY:
|
|
{
|
|
cnt = ds[1];
|
|
ds += sizeof(proto_69845_app_ele_data_t);
|
|
len -= sizeof(proto_69845_app_ele_data_t);
|
|
break;
|
|
}
|
|
default:
|
|
return ERR_FAIL;
|
|
}
|
|
ele_len = sizeof(*fix_data) + PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
|
|
for (i = 0; i < cnt && len > ele_len ; i++) {
|
|
fix_data = (proto_69845_app_data_t *)ds;
|
|
if (fix_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG &&
|
|
fix_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
|
|
return ERR_FAIL;
|
|
}
|
|
energy[i] = iot_bytes_to_uint32(fix_data->data, 1);
|
|
ds += ele_len;
|
|
len -= ele_len;
|
|
}
|
|
*data = ds;
|
|
*in_len = len;
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t proto_69845_energy_sum_data_handle(uint8_t *energy_sum,
|
|
uint8_t *data, uint32_t data_len)
|
|
{
|
|
proto_69845_app_data_t *app_data;
|
|
|
|
if (data_len < sizeof(*app_data)) {
|
|
goto drop;
|
|
}
|
|
app_data = (proto_69845_app_data_t *)data;
|
|
data_len -= sizeof(*app_data);
|
|
if (app_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG &&
|
|
app_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
|
|
goto drop;
|
|
}
|
|
if (data_len < PROTO_69845_METER_DATA_DOUBLE_LONG_LEN) {
|
|
goto drop;
|
|
}
|
|
BUILD_BUG_ON(PROTO_645_07_ENERGY_DATA_LEN ==
|
|
PROTO_69845_METER_DATA_DOUBLE_LONG_LEN);
|
|
if (app_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
|
|
proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_DOUBLE_LONG_LEN, energy_sum,
|
|
PROTO_645_07_ENERGY_DATA_LEN);
|
|
} else {
|
|
proto_69845_dlong_unsign_data_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_DOUBLE_LONG_LEN, energy_sum,
|
|
PROTO_645_07_ENERGY_DATA_LEN);
|
|
}
|
|
return ERR_OK;
|
|
drop:
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
uint32_t proto_69845_pf_data_handle(int16_t *pf,
|
|
uint8_t **data, uint32_t *in_len)
|
|
{
|
|
uint8_t *ds = *data, i, cnt;
|
|
uint32_t len = *in_len;
|
|
proto_69845_app_data_t *fix_data;
|
|
uint32_t ele_len;
|
|
if (len < sizeof(proto_69845_app_ele_data_t)) {
|
|
return ERR_FAIL;
|
|
}
|
|
switch (ds[0]) {
|
|
case PROTO_69845_APP_DATA_LONG:
|
|
{
|
|
cnt = 1;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_DATA_ARRAY:
|
|
{
|
|
cnt = ds[1];
|
|
ds += sizeof(proto_69845_app_ele_data_t);
|
|
len -= sizeof(proto_69845_app_ele_data_t);
|
|
break;
|
|
}
|
|
default:
|
|
return ERR_FAIL;
|
|
}
|
|
ele_len = sizeof(*fix_data) + PROTO_69845_METER_DATA_LONG_LEN;
|
|
for (i = 0; i < cnt && len > ele_len ; i++) {
|
|
fix_data = (proto_69845_app_data_t *)ds;
|
|
if (fix_data->data_type != PROTO_69845_APP_DATA_LONG) {
|
|
return ERR_FAIL;
|
|
}
|
|
pf[i] = (int16_t)iot_bytes_to_uint16(fix_data->data, 1);
|
|
ds += ele_len;
|
|
len -= ele_len;
|
|
}
|
|
*data = ds;
|
|
*in_len = len;
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t proto_69845_p_data_handle(proto_645_07_p_t *meter_p,
|
|
proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
|
|
{
|
|
uint8_t i, *meter_data, *data;
|
|
uint32_t ele_len;
|
|
proto_69845_app_data_t *app_data;
|
|
|
|
ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
|
|
if (data_len < ele_len * ele_data->num_of_data) {
|
|
return ERR_FAIL;
|
|
}
|
|
data = ele_data->data;
|
|
BUILD_BUG_ON(sizeof(meter_p->total) == PROTO_645_07_P_LEN);
|
|
meter_data = meter_p->total;
|
|
for (i = 0; i < ele_data->num_of_data && i < PROTO_69845_POWER_MAX_ELE_NUM;
|
|
i++) {
|
|
app_data = (proto_69845_app_data_t *)data;
|
|
if (app_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
|
|
proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
|
|
PROTO_69845_METER_DATA_DOUBLE_LONG_LEN,
|
|
meter_data, PROTO_645_07_P_LEN);
|
|
}
|
|
data += ele_len;
|
|
meter_data += PROTO_645_07_P_LEN;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
iot_pkt_t * proto_69845_build_file_info_msg(uint32_t file_size,
|
|
uint16_t file_crc, uint16_t block_size, uint32_t hw_ver, uint32_t sw_ver,
|
|
uint32_t loader_id, uint8_t *server_addr) {
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_pkt_t *tmp_pkt = NULL;
|
|
proto_69845_app_action_req_single_t *req_info;
|
|
uint8_t *app_data;
|
|
uint16_t i;
|
|
server_addr_info_t server_info = {0};
|
|
char ver_string[16];
|
|
|
|
server_info.len = PROTO_69845_SA_LEN;
|
|
server_info.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server_info.addr, server_addr);
|
|
|
|
tmp_pkt = iot_pkt_alloc(PROTO_69845_ACTION_REQUEST_COMMON_LEN,
|
|
IOT_SMART_GRID_MID);
|
|
if (tmp_pkt == NULL) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
req_info = (proto_69845_app_action_req_single_t *)iot_pkt_data(tmp_pkt);
|
|
req_info->omd.method_id = PROTO_OMD_TRANSFILE_INFO_START_METHOD_ID;
|
|
req_info->omd.oi = PROTO_69845_APP_OI_FILETRANS_BLOCK;
|
|
req_info->omd.operation_mode = 0;
|
|
|
|
req_info->data.data_type = PROTO_69845_APP_DATA_STRUCTURE;
|
|
app_data = (iot_pkt_data(tmp_pkt) + sizeof(*req_info));
|
|
i = 0;
|
|
app_data[i++] = 6;
|
|
/* file info, type is struct */
|
|
app_data[i++] = PROTO_69845_APP_DATA_STRUCTURE;
|
|
app_data[i++] = 6;
|
|
/* src file path, type is visible string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i++] = 1;
|
|
/* src file is null */
|
|
app_data[i++] = 0x30;
|
|
/* destination file path, type is visible string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i++] = 1;
|
|
/* destination file is null */
|
|
app_data[i++] = 0x30;
|
|
/* file size type is double long unsigned */
|
|
app_data[i++] = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
|
|
iot_uint32_to_bytes(file_size, app_data + i, 1);
|
|
i += PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
|
|
/* file attribute, type is bit-string size 3, bit0 - 1 read, 0 not read;
|
|
bit1 - 1 write, 0 not write; bit2 - 1 exe, 0 not exe.
|
|
*/
|
|
app_data[i++] = PROTO_69845_APP_DATA_BIT_STRING;
|
|
app_data[i++] = 3;
|
|
app_data[i++] = 0x07;
|
|
/* file version, type is visible string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i++] = 1;
|
|
app_data[i++] = 0x30;
|
|
/* file type, type is enum, 0 - local file, 1 - other file */
|
|
app_data[i++] = PROTO_69845_APP_DATA_ENUM;
|
|
app_data[i++] = 1;
|
|
/* translate block size, type is long unsigned */
|
|
app_data[i++] = PROTO_69845_APP_DATA_LONG_UNSIGNED;
|
|
iot_uint16_to_bytes(block_size, app_data + i, 1);
|
|
i += PROTO_69845_METER_DATA_LONG_LEN;
|
|
/* check type, type is struct */
|
|
app_data[i++] = PROTO_69845_APP_DATA_STRUCTURE;
|
|
app_data[i++] = 2;
|
|
/* check mode, type is enum, 0 - crc, 1 -mdt, 2 - sha1, 255 - other */
|
|
app_data[i++] = PROTO_69845_APP_DATA_ENUM;
|
|
app_data[i++] = 0;
|
|
/* check value, type is octet-string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_OCTET_STRING;
|
|
app_data[i++] = sizeof(file_crc);
|
|
iot_uint16_to_bytes(file_crc, app_data + i, 1);
|
|
i += sizeof(file_crc);
|
|
/* compatible soft version, type is array visible string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_ARRAY;
|
|
app_data[i++] = 2;
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", sw_ver);
|
|
os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
|
|
i += app_data[i] + 1;
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", sw_ver);
|
|
os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
|
|
i += app_data[i] + 1;
|
|
|
|
/* compatible hardware version, type is array visible string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_ARRAY;
|
|
app_data[i++] = 2;
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", hw_ver);
|
|
os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
|
|
i += app_data[i] + 1;
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", hw_ver);
|
|
os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
|
|
i += app_data[i] + 1;
|
|
|
|
/* loader id type is visible string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
|
|
app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", loader_id);
|
|
os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
|
|
i += app_data[i] + 1;
|
|
|
|
pkt = proto_69845_build_action_req_single_msg(req_info, i, &server_info);
|
|
|
|
if (tmp_pkt) {
|
|
iot_pkt_free(tmp_pkt);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_file_info_rsp(uint8_t *data, uint32_t data_len)
|
|
{
|
|
uint8_t reason = 0;
|
|
uint32_t oad_value;
|
|
apdu_info_t apdu_desc = { 0 };
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_69845_apdu_t *apdu;
|
|
proto_69845_app_action_resp_t *act_resp;
|
|
proto_69845_app_action_resp_normal_t *act_resp_single;
|
|
|
|
if (ERR_OK != proto_69845_parse(&data, &data_len, &hdr_698, &apdu_desc)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
|
|
apdu = (proto_69845_apdu_t *)apdu_desc.ptr;
|
|
if (apdu_desc.len < (sizeof(*apdu) + sizeof(*act_resp) +
|
|
sizeof(*act_resp_single))) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
if (apdu->type != PROTO_69845_S_APP_ACTION_RESP) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
|
|
act_resp = (proto_69845_app_action_resp_t*)apdu->data;
|
|
if (act_resp->data_type != PROTO_69845_APP_ACTION_NORMAL) {
|
|
reason = 4;
|
|
goto out;
|
|
}
|
|
|
|
act_resp_single = (proto_69845_app_action_resp_normal_t*)act_resp->data;
|
|
oad_value = iot_bytes_to_uint32((uint8_t*)&act_resp_single->result.omd.oi,
|
|
1);
|
|
if (oad_value != PROTO_69845_APP_OAD_TRANSFILE_START) {
|
|
reason = 5;
|
|
goto out;
|
|
}
|
|
if (act_resp_single->result.dar != PROTO_69845_APP_DAR_SUCCESS) {
|
|
reason = 6;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (reason) {
|
|
return ERR_FAIL;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_file_data_msg(uint8_t *file_data,
|
|
uint16_t data_len, uint16_t block_index, uint8_t *server_addr)
|
|
{
|
|
uint16_t i = 0;
|
|
uint16_t len;
|
|
uint8_t *data;
|
|
uint8_t info_len_byte = 0;
|
|
uint8_t *app_data;
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_pkt_t *tmp_pkt = NULL;
|
|
server_addr_info_t server_info = { 0 };
|
|
proto_69845_app_action_req_single_t *req_info;
|
|
|
|
server_info.len = PROTO_69845_SA_LEN;
|
|
server_info.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server_info.addr, server_addr);
|
|
|
|
len = sizeof(*req_info) + data_len;
|
|
if (data_len > 255) {
|
|
info_len_byte = 2;
|
|
} else if (data_len > 127) {
|
|
info_len_byte = 1;
|
|
}
|
|
|
|
tmp_pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
|
|
if (tmp_pkt == NULL) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
data = iot_pkt_data(tmp_pkt);
|
|
|
|
req_info = (proto_69845_app_action_req_single_t *)data;
|
|
req_info->omd.method_id = PROTO_OMD_TRANSFILE_DATA_METHOD_ID;
|
|
req_info->omd.oi = PROTO_69845_APP_OI_FILETRANS_BLOCK;
|
|
req_info->omd.operation_mode = 0;
|
|
|
|
req_info->data.data_type = PROTO_69845_APP_DATA_STRUCTURE;
|
|
app_data = data + sizeof(*req_info);
|
|
/* element cnt in structure, it's always 2 */
|
|
app_data[i++] = 2;
|
|
/* element1, block number, type is long-unsigned */
|
|
app_data[i++] = PROTO_69845_APP_DATA_LONG_UNSIGNED;
|
|
/* long-unsigned size, 2 bytes */
|
|
iot_uint16_to_bytes(block_index, app_data + i, 1);
|
|
i += PROTO_69845_METER_DATA_LONG_LEN;
|
|
/* element2, block data, type is octet-string */
|
|
app_data[i++] = PROTO_69845_APP_DATA_OCTET_STRING;
|
|
if (info_len_byte == 0) {
|
|
app_data[i++] = (uint8_t)data_len;
|
|
} else if (info_len_byte == 1) {
|
|
app_data[i++] = 0x80 | info_len_byte;
|
|
app_data[i++] = (uint8_t)data_len;
|
|
} else if (info_len_byte == 2) {
|
|
app_data[i++] = 0x80 | info_len_byte;
|
|
iot_uint16_to_bytes(data_len, app_data + i, 1);
|
|
i += PROTO_69845_METER_DATA_LONG_LEN;
|
|
}
|
|
|
|
os_mem_cpy(app_data + i, file_data, data_len);
|
|
i += data_len;
|
|
pkt = proto_69845_build_action_req_single_msg(req_info, i, &server_info);
|
|
|
|
if (tmp_pkt) {
|
|
iot_pkt_free(tmp_pkt);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_file_data_rsp(uint8_t *data, uint32_t data_len)
|
|
{
|
|
uint8_t reason = 0;
|
|
uint32_t oad_value;
|
|
apdu_info_t apdu_desc = { 0 };
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_69845_apdu_t *apdu;
|
|
proto_69845_app_action_resp_t *act_resp;
|
|
proto_69845_app_action_resp_normal_t *act_resp_single;
|
|
|
|
if (ERR_OK != proto_69845_parse(&data, &data_len, &hdr_698, &apdu_desc)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
|
|
apdu = (proto_69845_apdu_t *)apdu_desc.ptr;
|
|
if (apdu_desc.len < (sizeof(*apdu) + sizeof(*act_resp) +
|
|
sizeof(*act_resp_single))) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
if (apdu->type != PROTO_69845_S_APP_ACTION_RESP) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
|
|
act_resp = (proto_69845_app_action_resp_t*)apdu->data;
|
|
if (act_resp->data_type != PROTO_69845_APP_ACTION_NORMAL) {
|
|
reason = 4;
|
|
goto out;
|
|
}
|
|
|
|
act_resp_single = (proto_69845_app_action_resp_normal_t*)act_resp->data;
|
|
oad_value = iot_bytes_to_uint32((uint8_t*)&act_resp_single->result.omd.oi,
|
|
1);
|
|
if (oad_value != PROTO_69845_APP_OAD_TRANSFILE_DATA) {
|
|
reason = 5;
|
|
goto out;
|
|
}
|
|
if (act_resp_single->result.dar != PROTO_69845_APP_DAR_SUCCESS) {
|
|
reason = 6;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (reason) {
|
|
return ERR_FAIL;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_file_exe_msg(iot_time_tm_t *time,
|
|
uint8_t *server_addr)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
iot_pkt_t *tmp_pkt = NULL;
|
|
uint16_t i = 0;
|
|
uint8_t *app_data;
|
|
proto_69845_app_action_req_single_t *req_info;
|
|
proto_69845_app_data_time_s_t *times;
|
|
server_addr_info_t server_info = {0};
|
|
|
|
server_info.len = PROTO_69845_SA_LEN;
|
|
server_info.type = PROTO_69845_SA_TYPE_SIG;
|
|
iot_mac_addr_cpy(server_info.addr, server_addr);
|
|
|
|
tmp_pkt = iot_pkt_alloc(PROTO_69845_ACTION_REQUEST_COMMON_LEN,
|
|
IOT_SMART_GRID_MID);
|
|
if (tmp_pkt == NULL) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
req_info = (proto_69845_app_action_req_single_t *)iot_pkt_data(tmp_pkt);
|
|
req_info->omd.method_id = PROTO_OMD_TRANSFILE_INFO_EXE_METHOD_ID;
|
|
req_info->omd.oi = PROTO_69845_APP_OI_FILETRANS_BLOCK;
|
|
req_info->omd.operation_mode = 0;
|
|
|
|
req_info->data.data_type = PROTO_69845_APP_DATA_STRUCTURE;
|
|
app_data = (iot_pkt_data(tmp_pkt) + sizeof(*req_info));
|
|
app_data[i++] = 2;
|
|
app_data[i++] = PROTO_69845_APP_DATA_TIME_S;
|
|
times = (proto_69845_app_data_time_s_t*)(app_data + i);
|
|
times->year = time->tm_year;
|
|
times->month = time->tm_mon;
|
|
times->day = time->tm_mday;
|
|
times->hour = time->tm_hour;
|
|
times->minute = time->tm_min;
|
|
times->second = time->tm_sec;
|
|
i += sizeof(proto_69845_app_data_time_s_t);
|
|
app_data[i++] = PROTO_69845_APP_DATA_NULL;
|
|
pkt = proto_69845_build_action_req_single_msg(req_info, i, &server_info);
|
|
|
|
if (tmp_pkt) {
|
|
iot_pkt_free(tmp_pkt);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_file_exe_rsp(uint8_t *data, uint32_t data_len)
|
|
{
|
|
uint8_t reason = 0;
|
|
uint32_t oad_value;
|
|
apdu_info_t apdu_desc = { 0 };
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_69845_apdu_t *apdu;
|
|
proto_69845_app_action_resp_t *act_resp;
|
|
proto_69845_app_action_resp_normal_t *act_resp_single;
|
|
|
|
if (ERR_OK != proto_69845_parse(&data, &data_len, &hdr_698, &apdu_desc)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
|
|
apdu = (proto_69845_apdu_t *)apdu_desc.ptr;
|
|
if (apdu_desc.len < (sizeof(*apdu) + sizeof(*act_resp) +
|
|
sizeof(*act_resp_single))) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
if (apdu->type != PROTO_69845_S_APP_ACTION_RESP) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
|
|
act_resp = (proto_69845_app_action_resp_t*)apdu->data;
|
|
if (act_resp->data_type != PROTO_69845_APP_ACTION_NORMAL) {
|
|
reason = 4;
|
|
goto out;
|
|
}
|
|
|
|
act_resp_single = (proto_69845_app_action_resp_normal_t*)act_resp->data;
|
|
oad_value = iot_bytes_to_uint32((uint8_t*)&act_resp_single->result.omd.oi,
|
|
1);
|
|
if (oad_value != PROTO_69845_APP_OAD_TRANSFILE_EXE) {
|
|
reason = 5;
|
|
goto out;
|
|
}
|
|
if (act_resp_single->result.dar != PROTO_69845_APP_DAR_SUCCESS) {
|
|
reason = 6;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (reason) {
|
|
return ERR_FAIL;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
#else /* PLC_SUPPORT_STA_ROLE */
|
|
|
|
iot_pkt_t *proto_69845_build_get_req_msg(
|
|
proto_69845_app_get_req_info_t* req_info,
|
|
const server_addr_info_t* server_info)
|
|
{
|
|
(void)req_info;
|
|
(void)server_info;
|
|
return NULL;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_comdcb_msg(uint32_t baud,
|
|
const server_addr_info_t *server_info, uint8_t sn)
|
|
{
|
|
(void)baud;
|
|
(void)server_info;
|
|
(void)sn;
|
|
return NULL;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_get_req_msg_with_rn(
|
|
proto_69845_app_get_list_req_info_t* req_info,
|
|
const server_addr_info_t* server_info)
|
|
{
|
|
(void)req_info;
|
|
(void)server_info;
|
|
return NULL;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_get_version_msg_with_rn(
|
|
const server_addr_info_t *server_info, uint8_t sn)
|
|
{
|
|
(void)server_info;
|
|
(void)sn;
|
|
return NULL;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_apdu_data_with_rn_msg(uint8_t *apdu_data,
|
|
uint32_t data_len, const server_addr_info_t* server_info)
|
|
{
|
|
(void)apdu_data;
|
|
(void)data_len;
|
|
(void)server_info;
|
|
return NULL;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_action_single_ack(addr_info_t *addr_info,
|
|
proto_69845_app_piid_t *piid, proto_69845_app_omd_t *omd,
|
|
uint8_t dar)
|
|
{
|
|
(void)addr_info;
|
|
(void)piid;
|
|
(void)omd;
|
|
(void)dar;
|
|
return NULL;
|
|
}
|
|
|
|
iot_pkt_t * proto_69845_build_file_info_msg(uint32_t file_size,
|
|
uint16_t file_crc, uint16_t block_size, uint32_t hw_ver, uint32_t sw_ver,
|
|
uint32_t loader_id, uint8_t *server_addr)
|
|
{
|
|
(void)file_size;
|
|
(void)file_crc;
|
|
(void)block_size;
|
|
(void)hw_ver;
|
|
(void)sw_ver;
|
|
(void)loader_id;
|
|
(void)server_addr;
|
|
return NULL;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_file_info_rsp(uint8_t *data, uint32_t data_len)
|
|
{
|
|
(void)data;
|
|
(void)data_len;
|
|
return ERR_OK;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_file_data_msg(uint8_t *data,
|
|
uint16_t data_len, uint16_t block_index, uint8_t *server_addr)
|
|
{
|
|
(void)data;
|
|
(void)data_len;
|
|
(void)block_index;
|
|
(void)server_addr;
|
|
return NULL;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_file_data_rsp(uint8_t *data, uint32_t data_len)
|
|
{
|
|
(void)data;
|
|
(void)data_len;
|
|
return ERR_OK;
|
|
}
|
|
|
|
iot_pkt_t *proto_69845_build_file_exe_msg(iot_time_tm_t *time,
|
|
uint8_t *server_addr)
|
|
{
|
|
(void)time;
|
|
(void)server_addr;
|
|
return NULL;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_file_exe_rsp(uint8_t *data, uint32_t data_len)
|
|
{
|
|
(void)data;
|
|
(void)data_len;
|
|
return ERR_OK;
|
|
}
|
|
|
|
#endif /* PLC_SUPPORT_STA_ROLE */
|