Files
kunlun/app/smart_grid/protocol/proto_3762.c

223 lines
5.1 KiB
C
Raw Permalink Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
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"
/* protocol includes */
#include "proto_3762.h"
/* smart grid internal header files */
#include "iot_sg_cco_drv_api.h"
#if (IOT_GW_CCO_DRIVER_ENABLE || IOT_SG_CONTROLLER_ENABLE)
uint8_t proto_3762_get_checksum(uint8_t ctrl, uint8_t *data, uint32_t len)
{
uint8_t result = ctrl;
for (uint32_t i = 0; i < len; ++i) {
result += data[i];
}
return result;
}
uint8_t proto_3762_get_fn_code(uint8_t *data)
{
uint8_t result = PROTO_3762_FN_INVALID;
if (data == NULL) {
return result;
}
result = data[1] * 8;
switch (data[0]) {
case 0x1:
result += 1;
break;
case 0x2:
result += 2;
break;
case 0x4:
result += 3;
break;
case 0x8:
result += 4;
break;
case 0x10:
result += 5;
break;
case 0x20:
result += 6;
break;
case 0x40:
result += 7;
break;
case 0x80:
result += 8;
break;
default:
result = PROTO_3762_FN_INVALID;
}
return result;
}
uint32_t proto_3762_sanity_check(uint8_t* data, uint16_t len)
{
uint16_t min_data_len = PROTO_3762_FIX_FIELD_LEN;
uint16_t frame_len;
if (data[0] != PROTO_3762_SOF_BYTE) {
return INVALID_FORMAT;
}
frame_len = (uint16_t)data[2];
frame_len = (frame_len << 8) | (uint16_t)data[1];
if (len <= min_data_len) {
return INVALID_DATA;
}
if (frame_len != len) {
return INVALID_DATA_LEN;
}
if (data[len - 1] != PROTO_3762_EOF_BYTE) {
return VALIDATE_FAILED;
}
/* 376.2 version 2013 */
if (data[len - 2] == proto_3762_get_checksum(data[PROTO_3762_CTRL_OFFSET],
data + PROTO_3762_DATA_OFFSET,
len - PROTO_3762_FIX_FIELD_LEN)) {
/* check sum is correct */
return 0;
}
return VALIDATE_FAILED; /* checksum failure */
}
void proto_3762_convert_max_fn_to_bitmap(uint16_t max_fn, uint8_t *fn_buf)
{
uint8_t temp_max_fn = 0;
uint8_t idx = 0;
if (max_fn > (PROTO_3762_03F11_FNLEN_BITS - 1)) {
max_fn = (PROTO_3762_03F11_FNLEN_BITS - 1);
}
temp_max_fn = (max_fn & 0x07);
idx = (uint8_t)(max_fn >> 3);
if (idx > 0) {
os_mem_set(fn_buf, 0xff, idx);
}
while (temp_max_fn > 0) {
fn_buf[idx] |= (1 << (temp_max_fn - 1));
temp_max_fn--;
}
return;
}
void proto_3762_fn_index_add(uint8_t fn, uint8_t *fn_buf)
{
uint8_t idx = 0;
fn--;
idx = fn >> 3;
fn_buf[idx] |= (1 << (fn & 0x7));
}
void proto_3762_fn_index_del(uint8_t fn, uint8_t *fn_buf)
{
uint8_t idx = 0;
fn--;
idx = fn >> 3;
fn_buf[idx] &= ~(1 << (fn & 0x7));
}
void proto_3762_nid_to_buf(uint32_t nid, uint8_t *p_nid) {
p_nid[0] = (uint8_t)nid;
p_nid[1] = (uint8_t)(nid >> 8);
p_nid[2] = (uint8_t)(nid >> 16);
}
void proto_3762_check_frame_handler(uint8_t* buffer, uint32_t buffer_len,
bool_t* is_frame)
{
uint8_t *app_data;
uint16_t frame_len;
user_data_t *user_data;
if (buffer_len < PROTO_3762_FRAME_MIN_LEN) {
*is_frame = false;
return;
}
frame_len = (uint16_t)buffer[2];
frame_len = (frame_len << 8) | (uint16_t)buffer[1];
if (buffer[0] != PROTO_3762_SOF_BYTE
|| buffer[buffer_len - 1] != PROTO_3762_EOF_BYTE) {
*is_frame = false;
return;
}
if (frame_len != buffer_len) {
*is_frame = false;
return;
}
if (buffer[buffer_len - 2] != proto_3762_get_checksum(
buffer[PROTO_3762_CTRL_OFFSET], buffer + PROTO_3762_DATA_OFFSET,
buffer_len - PROTO_3762_FIX_FIELD_LEN)) {
/* checksum failure */
*is_frame = false;
return;
}
user_data = (user_data_t *)(buffer + PROTO_3762_DATA_OFFSET);
app_data = user_data->data;
if (user_data->res.dl_info.comm_module) {
if (buffer_len < (PROTO_3762_FRAME_MIN_LEN +
(PROTO_3762_MAC_ADDR_LEN * 2))) {
*is_frame = false;
return;
}
app_data += PROTO_3762_MAC_ADDR_LEN * 2;
}
if (proto_3762_get_fn_code(app_data + 1) == PROTO_3762_FN_INVALID) {
*is_frame = false;
return;
}
*is_frame = true;
}
#endif /* IOT_GW_CCO_DRIVER_ENABLE */