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

482 lines
16 KiB
C

/****************************************************************************
Copyright(c) 2016-2018 by WuQi Technologies. ALL RIGHTS RESERVED.
This Information is proprietary to WuQi Technologies and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of WuQi. This Information or any portion
thereof remains the property of WuQi. The Information contained herein
is believed to be accurate and WuQi 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 inringement.
****************************************************************************/
#include "proto_69845_vendor.h"
/* os_shim header files */
#include "os_utils_api.h"
/* iot common header files */
#include "iot_app_api.h"
#include "iot_utils_api.h"
#include "iot_upgrade_api.h"
#include "iot_oem_api.h"
#include "iot_board_api.h"
#include "iot_bitmap_api.h"
#include "iot_io_api.h"
#include "iot_system_api.h"
#include "iot_plc_hw_topo_api.h"
#include "iot_adc_api.h"
#include "iot_version_api.h"
/* smart grid internal header files */
#include "iot_sg.h"
#include "iot_sg_sta.h"
#include "proto_69845.h"
#include "iot_oem_api.h"
#if IOT_SMART_GRID_ENABLE
static uint8_t proto_69845_apdu_set_rf_param(uint8_t *data, uint16_t len)
{
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS;
proto_69845_app_ele_data_t *ele_data = NULL;
proto_69845_ext_rf_param_t *param = NULL;
if (data == NULL || len < sizeof(*ele_data) + sizeof(*param)) {
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
goto out;
}
ele_data = (proto_69845_app_ele_data_t *)data;
if (ele_data->data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
dar = PROTO_69845_APP_DAR_TYPE_MISMATCH;
goto out;
}
param = (proto_69845_ext_rf_param_t *)(ele_data->data);
if (ele_data->num_of_data != sizeof(*param)) {
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
goto out;
}
if ((param->option == IOT_PLC_RF_OPTION_1 &&
param->channel < IOT_PLC_OPTION1_CHANNEL_ID_MAX) ||
(param->option == IOT_PLC_RF_OPTION_2 &&
param->channel < IOT_PLC_OPTION2_CHANNEL_ID_MAX) ||
(param->option == IOT_PLC_RF_OPTION_3 &&
param->channel < IOT_PLC_OPTION3_CHANNEL_ID_MAX)) {
/* set rf option and channel */
iot_plc_set_rf_channel(p_sg_glb->plc_app_h,
IOT_PLC_API_REQ_ID_DEFAULT, param->option, param->channel, 0);
iot_sg_printf("%s %lu %lu\n", __FUNCTION__, param->option,
param->channel);
} else {
dar = PROTO_69845_APP_DAR_OVERFLOW;
goto out;
}
out:
return dar;
}
static uint8_t proto_69845_apdu_set_hrf_mode(uint8_t *data, uint16_t len)
{
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS;
proto_69845_app_ele_data_t *ele_data = NULL;
proto_69845_ext_work_mode_t *mode = NULL;
if (len < (sizeof(*ele_data) + sizeof(*mode))) {
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
goto out;
}
ele_data = (proto_69845_app_ele_data_t *)data;
if (ele_data->data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
dar = PROTO_69845_APP_DAR_TYPE_MISMATCH;
goto out;
}
if (ele_data->num_of_data != sizeof(*mode)) {
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
goto out;
}
mode = (proto_69845_ext_work_mode_t *)(ele_data->data);
if (mode->mode != PROTO_69845_CONTROLLER_MODE_HPLC &&
mode->mode != PROTO_69845_CONTROLLER_MODE_RF) {
dar = PROTO_69845_APP_DAR_OVERFLOW;
goto out;
}
iot_sg_printf("%s %lu\n", __FUNCTION__, mode->mode);
out:
return dar;
}
static iot_pkt_t *proto_69845_apdu_set_req_normal_handle(
proto_69845_frame_head_info_t *header, uint8_t *data, uint32_t len,
uint32_t *handle)
{
iot_pkt_t *pkt = NULL;
uint32_t oad = 0;
uint8_t dar = 0;
proto_69845_app_set_req_normal_t *normal = NULL;
addr_info_t addr_info = {0};
proto_69845_app_oad_t app_oad = {0};
if (len < sizeof(*normal)) {
goto out;
}
normal = (proto_69845_app_set_req_normal_t *)data;
len -= sizeof(*normal);
oad = iot_bytes_to_uint32((uint8_t *)&normal->oad.oi, 1);
switch (oad) {
case PROTO_69845_EXT_APP_OAD_BROADCAST_RF_PARAM:
{
dar = proto_69845_apdu_set_rf_param(
(uint8_t *)&normal->data, (uint16_t)len);
*handle = 1;
/* set rf param is broadcast, no response */
goto out;
}
case PROTO_69845_EXT_APP_OAD_HRF_MODE:
{
dar = proto_69845_apdu_set_hrf_mode(
(uint8_t *)&normal->data, (uint16_t)len);
*handle = 1;
break;
}
default:
{
goto out;
}
}
proto_69845_get_addr_info(header, &addr_info);
app_oad.oi = iot_bytes_to_uint16((uint8_t *)&normal->oad.oi, 1);
app_oad.attribute_id = normal->oad.attribute_id;
app_oad.attribute_char = normal->oad.attribute_char;
app_oad.element_index = normal->oad.element_index;
pkt = proto_69845_set_normal_ack(&addr_info, &normal->piid,
&app_oad, dar);
out:
if(*handle) {
iot_sg_printf("%s %04X-%lu\n", __FUNCTION__, oad, dar);
}
return pkt;
}
static iot_pkt_t *proto_69845_apdu_set_request_handle(
proto_69845_frame_head_info_t *hdr, uint8_t *data, uint32_t len,
uint32_t *handle)
{
uint32_t length = 0;
iot_pkt_t *pkt = NULL;
proto_69845_app_set_req_t *set_req = NULL;
set_req = (proto_69845_app_set_req_t *)data;
length = len - sizeof(*set_req);
switch (set_req->data_type) {
case PROTO_69845_APP_SET_NORMAL:
{
pkt = proto_69845_apdu_set_req_normal_handle(hdr, set_req->data,
length, handle);
break;
}
default:
break;
}
return pkt;
}
static iot_pkt_t *proto_69845_ext_build_get_resp(
proto_69845_frame_head_info_t *req_hdr,
proto_69845_app_get_req_normal_t *get_normal, uint8_t result_type,
uint8_t *data, uint32_t result_len)
{
iot_pkt_t *pkt = NULL;
uint8_t addr_len = 0, *point;
uint16_t head_len = 0;
uint32_t pkt_len = 0;
addr_info_t addr_info = {0};
proto_69845_frame_head_info_t *resp_hdr = NULL;
proto_69845_apdu_t *resp_apdu = NULL;
proto_69845_app_get_resp_t *resp_get = NULL;
proto_69845_app_get_resp_normal_t *resp_normal = NULL;
addr_len = proto_69845_get_addr_info(req_hdr, &addr_info);
pkt_len = sizeof(*resp_hdr) + addr_len + PROTO_69845_CHECKSUM_LEN +
sizeof(*resp_apdu) + sizeof(*resp_get) + sizeof(*resp_normal) +
result_len + PROTO_69845_NO_FLW_DATA_LEN +
PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
if (pkt == NULL) {
goto out;
}
point = iot_pkt_put(pkt, pkt_len);
resp_hdr = (proto_69845_frame_head_info_t *)point;
head_len = sizeof(*resp_hdr) + addr_len + PROTO_69845_CHECKSUM_LEN;
proto_69845_head_fill(
resp_hdr, head_len, (uint16_t)pkt_len, &addr_info,
PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
PROTO_69845_D_P_SERVER_RESPONSE);
point += head_len;
resp_apdu = (proto_69845_apdu_t *)point;
resp_apdu->type = PROTO_69845_S_APP_GET_RESP;
resp_get = (proto_69845_app_get_resp_t *)resp_apdu->data;
resp_get->data_type = PROTO_69845_APP_GET_NORMAL;
resp_normal = (proto_69845_app_get_resp_normal_t *)resp_get->data;
resp_normal->piid_acd.sn = get_normal->piid.sn;
resp_normal->piid_acd.priority = get_normal->piid.priority;
resp_normal->piid_acd.acd = 0;
resp_normal->oad.oi = get_normal->oad.oi;
resp_normal->oad.attribute_id = get_normal->oad.attribute_id;
resp_normal->oad.attribute_char = get_normal->oad.attribute_char;
resp_normal->oad.element_index = get_normal->oad.element_index;
resp_normal->result_type = result_type;
os_mem_cpy(resp_normal->result, data, result_len);
proto_69845_tail_fill_without_ts_fl(resp_hdr,
resp_normal->result + result_len, sizeof(proto_69845_tailer_t) +
PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN);
out:
return pkt;
}
static iot_pkt_t *proto_69845_get_chip_id(
proto_69845_frame_head_info_t *header,
proto_69845_app_get_req_normal_t *get_normal)
{
iot_pkt_t *pkt = NULL;
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS;
proto_69845_app_ele_data_t *data = NULL;
uint8_t chip_id[sizeof(*data) + PROTO_69845_EXT_CHIP_ID_LEN];
data = (proto_69845_app_ele_data_t *)chip_id;
data->data_type = PROTO_69845_APP_DATA_OCTET_STRING;
data->num_of_data = PROTO_69845_EXT_CHIP_ID_LEN;
if (iot_oem_get_chip_mmid(data->data, PROTO_69845_EXT_CHIP_ID_LEN) == 0) {
dar = PROTO_69845_APP_DAR_OTHER;
}
if (dar) {
pkt = proto_69845_ext_build_get_resp(
header, get_normal, PROTO_69845_APP_GET_RESULT_DAR, &dar,
sizeof(dar));
} else {
pkt = proto_69845_ext_build_get_resp(
header, get_normal, PROTO_69845_APP_GET_RESULT_DATA, chip_id,
PROTO_69845_EXT_CHIP_ID_LEN + sizeof(*data));
}
return pkt;
}
static iot_pkt_t *proto_69845_get_simulate_ept_pos(
proto_69845_frame_head_info_t *header,
proto_69845_app_get_req_normal_t *get_normal)
{
static uint8_t read_cnt = 1;
iot_pkt_t *pkt = NULL, *temp_pkt = NULL;
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS, i;
uint32_t pos = read_cnt;
uint32_t length = 0;
proto_69845_app_ele_data_t *data = NULL;
proto_69845_app_data_t *pos_item = NULL;
length = sizeof(*data) + (sizeof(*pos_item) +
sizeof(pos)) * PROTO_69845_ENERGY_DATA_ARRAY_COUNT;
temp_pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (temp_pkt == NULL) {
dar = PROTO_69845_APP_DAR_OTHER;
goto out;
}
iot_pkt_put(temp_pkt, length);
data = (proto_69845_app_ele_data_t *)iot_pkt_data(temp_pkt);
data->data_type = PROTO_69845_APP_DATA_ARRAY;
data->num_of_data = PROTO_69845_ENERGY_DATA_ARRAY_COUNT;
pos_item = (proto_69845_app_data_t *)data->data;
pos_item->data_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
iot_uint32_to_bytes(pos * PROTO_69845_ENERGY_DATA_ARRAY_COUNT - 1,
pos_item->data, 1);
pos_item = (proto_69845_app_data_t *)(pos_item->data + sizeof(pos));
for (i = 0; i < PROTO_69845_ENERGY_DATA_ARRAY_COUNT - 1; i++) {
pos_item->data_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
iot_uint32_to_bytes(pos, pos_item->data, 1);
pos_item = (proto_69845_app_data_t *)(pos_item->data + sizeof(pos));
}
read_cnt += 1;
out:
if (dar) {
pkt = proto_69845_ext_build_get_resp(header, get_normal,
PROTO_69845_APP_GET_RESULT_DAR, &dar, sizeof(dar));
} else {
pkt = proto_69845_ext_build_get_resp(header, get_normal,
PROTO_69845_APP_GET_RESULT_DATA, iot_pkt_data(temp_pkt),
iot_pkt_data_len(temp_pkt));
}
if (temp_pkt) {
iot_pkt_free(temp_pkt);
}
return pkt;
}
static iot_pkt_t *proto_69845_apdu_get_req_normal_handle(
proto_69845_frame_head_info_t *header, uint8_t *data, uint32_t len,
uint32_t *handle)
{
uint32_t oad = 0;
iot_pkt_t *pkt = NULL;
proto_69845_app_get_req_normal_t *normal = NULL;
IOT_ASSERT(header && data);
if (len < sizeof(*normal)) {
iot_sg_printf("69845 vendor get: undersize\n");
goto out;
}
normal = (proto_69845_app_get_req_normal_t *)data;
oad = iot_bytes_to_uint32((uint8_t *)&normal->oad.oi, 1);
switch (oad)
{
case PROTO_69845_EXT_APP_OAD_READ_CHIP_ID:
{
pkt = proto_69845_get_chip_id(header, normal);
*handle = 1;
break;
}
case PROTO_69845_APP_OAD_EPT_POS:
{
if (IOT_DEV_TEST_CCO_MODE) {
pkt = proto_69845_get_simulate_ept_pos(header, normal);
*handle = 1;
}
break;
}
default:
break;
}
if (*handle) {
iot_sg_printf("69845 vendor get oad: %08X\n", oad);
}
out:
return pkt;
}
static iot_pkt_t *proto_69845_apdu_get_request_handle(
proto_69845_frame_head_info_t *header, uint8_t *data, uint32_t len,
uint32_t *handle)
{
uint32_t length = 0;
iot_pkt_t *pkt = NULL;
proto_69845_app_get_req_t *get_req = NULL;
get_req = (proto_69845_app_get_req_t *)data;
length = len - sizeof(*get_req);
switch (get_req->data_type) {
case PROTO_69845_APP_GET_NORMAL:
{
pkt = proto_69845_apdu_get_req_normal_handle(
header, get_req->data, length, handle);
break;
}
default:
break;
}
return pkt;
}
uint32_t proto_69845_handle_vendor_proto(
uint8_t *data, uint32_t len, int8_t snr, int8_t rssi)
{
uint8_t pm_addr[IOT_MAC_ADDR_LEN] = {0};
uint32_t handle = 0, length = 0;
iot_pkt_t *pkt = NULL;
apdu_info_t apdu_info = {0};
proto_69845_apdu_t *apdu = NULL;
proto_69845_frame_head_info_t *hdr;
addr_info_t addr_info = {0};
(void)snr;
(void)rssi;
if (iot_sg_sta_get_user_type() != USER_TYPE_STATE_GRID_LIAONING) {
goto out;
}
hdr = proto_69845_sanity_check(data, (uint16_t)len);
if (!hdr) {
goto out;
}
proto_69845_get_addr_info(hdr, &addr_info);
if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_BROADCAST) {
if (addr_info.ser_info.addr[0] != PROTO_69845_SA_BROADCAST_ADD) {
goto out;
}
} else if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_SIG) {
if (p_sg_glb->desc.sta->drv) {
p_sg_glb->desc.sta->drv->get_login_addr(pm_addr);
if (!iot_mac_addr_cmp(pm_addr, addr_info.ser_info.addr)){
goto out;
}
}
} else {
goto out;
}
if (hdr->ctrl.fn != PROTO_69845_FN_USER_DATA ||
hdr->ctrl.fragment != PROTO_69845_APDU_WHOLE) {
goto out;
}
if (hdr->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_RESPONSE &&
hdr->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_REQUEST) {
goto out;
}
if (proto_69845_get_apdu(hdr, hdr->len + PROTO_69845_START_END_LEN,
&apdu_info) != ERR_OK) {
goto out;
}
if (hdr->ctrl.flag_scramble) {
proto_69845_sub33_handle(apdu_info.ptr, apdu_info.len);
}
apdu = (proto_69845_apdu_t *)apdu_info.ptr;
length = apdu_info.len - sizeof(*apdu);
switch (apdu->type)
{
case PROTO_69845_C_APP_GET_REQ:
{
pkt = proto_69845_apdu_get_request_handle(
hdr, apdu->data, length, &handle);
break;
}
case PROTO_69845_C_APP_SET_REQ:
{
pkt = proto_69845_apdu_set_request_handle(
hdr, apdu->data, length, &handle);
break;
}
default:
break;
}
out:
if (handle) {
iot_sg_sta_meter_read_done_framework(
(uint8_t)p_sg_glb->desc.sta->mr.data_type, pkt);
} else if (pkt) {
IOT_ASSERT(0);
}
return handle;
}
#else
uint32_t proto_69845_handle_vendor_proto(
uint8_t *data, uint32_t len, int8_t snr, int8_t rssi)
{
(void)data;
(void)len;
(void)snr;
(void)rssi;
return 0;
}
#endif