Files
kunlun/app/iot_dlt645_app/proto/app_proto_dlt645.c
2024-09-28 14:24:04 +08:00

272 lines
9.2 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
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.
****************************************************************************/
#include "app_main_task.h"
#include "app_uart.h"
#include "app_common.h"
#include "app_proto_dlt645.h"
#include "app_cus_task.h"
#include "iot_app_pib_sta_api.h"
#include "iot_plc_sync_api.h"
#include "proto_645.h"
#include "proto_645_vendor.h"
typedef struct {
/* handle list base. */
proto_dlt645_proc_func_pair *base;
/* handle list item count. */
uint16_t count;
} app_dlt645_handle_list_t;
/* app dlt645 handle list for customer task and main task. */
app_dlt645_handle_list_t g_app_dlt645_handle_list[APP_TASK_MAX];
/* get dlt645 frame di from buffer. */
static inline uint32_t get_di(uint8_t *ptr)
{
return (((((uint8_t *)(ptr))[3] - 0x33)<<24)
|((((uint8_t *)(ptr))[2] - 0x33)<<16)
|((((uint8_t *)(ptr))[1] - 0x33)<<8)
|(((uint8_t *)(ptr))[0] - 0x33));
}
uint32_t app_dlt645_local_handle(app_task_e task, proto_645_header_t *frame,
uint16_t frame_len, iot_pkt_t **pkt_ack)
{
uint8_t local_addr[IOT_MAC_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t frm_addr[IOT_MAC_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
int i = 0;
uint32_t di = 0;
uint8_t fn = 0;
uint8_t err_code = 0;
uint16_t out_len = 0;
uint16_t frm_len = 0;
uint8_t *proto_buf = NULL;
uint8_t *out_buf = NULL;
app_dlt645_handle_list_t *list = NULL;
iot_pkt_t *pkt = NULL;
if (task >= APP_TASK_MAX || NULL == frame) {
APP_PRINTF("%s error parameter!", __FUNCTION__);
goto dispatch;
}
if (APP_TASK_MAIN == task) {
APP_PRINT_BUF("main task app_dlt645_local_handle: ", (uint8_t *)frame,
frame_len);
} else {
APP_PRINT_BUF("cus task app_dlt645_local_handle: ", (uint8_t *)frame,
frame_len);
}
iot_mac_addr_cpy(frm_addr, frame->addr);
iot_mac_addr_reverse(frm_addr);
if (iot_plc_is_client_mode()) {
iot_mac_addr_cpy(local_addr, app_get_mac_addr());
if (!iot_mac_addr_cmp(frm_addr, proto_645_any_addr) &&
!iot_mac_addr_cmp(frm_addr, proto_645_bcast_addr) &&
!iot_mac_addr_cmp(frm_addr, local_addr)) {
/* mac addr mismatch */
APP_PRINT_BUF("frm mac", frm_addr, IOT_MAC_ADDR_LEN);
APP_PRINT_BUF("local mac", local_addr, IOT_MAC_ADDR_LEN);
APP_PRINTF("%s sta mac addr mismatch", __FUNCTION__);
goto dispatch;
}
} else {
iot_mac_addr_cpy(local_addr, app_get_cco_mac_addr());
if (!iot_mac_addr_cmp(frm_addr, local_addr)) {
/* mac addr mismatch */
APP_PRINT_BUF("frm mac", frm_addr, IOT_MAC_ADDR_LEN);
APP_PRINT_BUF("local mac", local_addr, IOT_MAC_ADDR_LEN);
APP_PRINTF("%s cco mac addr mismatch", __FUNCTION__);
goto dispatch;
}
}
list = &g_app_dlt645_handle_list[task];
if ( NULL == list->base || 0 == list->count) {
/* no valid handle */
APP_PRINTF("%s no valid handle", __FUNCTION__);
goto dispatch;
}
fn = frame->control.fn;
if (frame->len >= PROTO_645_2007_DI_LEN) {
di = get_di(frame->data);
}
for (i = 0; i < list->count; i++) {
if ((fn == list->base[i].fn) && (di == list->base[i].di)
&& (NULL != list->base[i].func)) {
break;
}
}
if (i >= list->count) {
/* no matching handle */
APP_PRINTF("%s no matching handle", __FUNCTION__);
goto dispatch;
}
pkt = iot_pkt_alloc(MAX_RSP_DATA_LEN, IOT_APP_DL645_MID);
if (pkt == NULL) {
APP_PRINTF("[ERR] %s Out Packet Alloc Failed !!", __FUNCTION__);
goto dispatch;
}
proto_buf = iot_pkt_data(pkt);
out_buf = proto_buf + sizeof(proto_645_header_t);
/* call the matched handle */
err_code = list->base[i].func(frame, out_buf, &out_len);
if (ERR_OK == err_code) {
frm_len = proto_645_fill_frame(proto_buf, PROTO_645_2007_ID,
frame->addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID, fn, PROTO_645_INVALID_DI, out_len,
out_buf);
} else {
frm_len = proto_645_fill_frame(proto_buf, PROTO_645_2007_ID,
frame->addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_ABNORMAL,
PROTO_645_FOLLOW_INVALID, fn, PROTO_645_INVALID_DI, 1, &err_code);
}
iot_pkt_put(pkt, frm_len);
*pkt_ack = pkt;
return ERR_OK;
dispatch:
return ERR_FAIL;
}
uint32_t app_dlt645_uart_data_parse(uint8_t *data, uint16_t data_length)
{
uint8_t *pdata;
uint16_t total_len;
uint16_t i = 0;
uint16_t frame_length;
proto_645_header_t *frame;
uint16_t hd_index = 0xFFFF;
uart_handle_buffer *uart_buffer;
iot_pkt_t * pkt_645 = NULL;
bool_t is_frame = false;
uart_buffer = app_get_uart_buf_info();
/* 断帧数据清除 */
app_uart_buf_clear();
total_len = uart_buffer->buff_len + data_length;
iot_pkt_t *pkt = iot_pkt_alloc(total_len, IOT_APP_DL645_MID);
if (NULL == pkt) {
APP_PRINTF("[ERR] %s Packet Alloc Failed !!", __FUNCTION__);
return ERR_FAIL;
}
APP_PRINT_BUF("[app_dlt645_uart_data_parse]: ", data, data_length);
pdata = (uint8_t *)iot_pkt_put(pkt, total_len);
/* 合并存储的半帧数据和串口新输入的数据到一个pkt中 */
if (uart_buffer->buff_len > 0) {
os_mem_cpy(pdata, uart_buffer->buff_tmp, uart_buffer->buff_len);
os_mem_set(uart_buffer->buff_tmp, 0, uart_buffer->buff_len);
}
os_mem_cpy(pdata + uart_buffer->buff_len, data, data_length);
for (i = 0; i < total_len; i++) {
if (PROTO_645_START_CHAR == pdata[i]) {
/* 记录帧头位置 */
hd_index = i;
/* 剩余长度小于帧的最小长度,判断为半帧 */
if ((i + (PROTO_645_HEADER_LEN + PROTO_645_END_LEN)) > total_len) {
goto half_frame;
}
frame = (proto_645_header_t *)&pdata[i];
frame_length = PROTO_645_HEADER_LEN + frame->len
+ PROTO_645_END_LEN;
/* 帧长度大于剩余长度并且小于帧的最大长度,判断为半帧 */
if (frame_length > (total_len - i)) {
if (frame_length < PROTO_645_MAX_PKT_LEN) {
goto half_frame;
} else {
continue;
}
}
/* 验证帧格式 */
proto_645_check_frame_handler((uint8_t *)frame, frame_length,
&is_frame);
if (!is_frame) {
hd_index = 0xFFFF;
continue;
}
/* 收到正确的645帧 */
pkt_645 = iot_pkt_alloc(data_length, IOT_APP_DL645_MID);
if (NULL == pkt_645) {
APP_PRINTF("[ERR] %s Packet Alloc Failed !!", __FUNCTION__);
} else {
os_mem_cpy(iot_pkt_put(pkt_645, frame_length), (void *)frame,
frame_length);
/* 仅会收到uart的帧发送给cus_task处理 */
iot_cus_task_msg_post(E_CUS_MSG_FROM_UART,
E_CUS_MSG_ID_645PKT_RECV, pkt_645);
}
/* 帧长度等于剩余长度,则判断为没有半帧 */
if (frame_length == total_len - i) {
hd_index = 0xFFFF;
}
i += (frame_length - 1);
}
}
/* 分析结束,判断是否有半帧 */
if (total_len > hd_index) {
if ((total_len - hd_index) < PROTO_645_MAX_PKT_LEN) {
goto half_frame;
}
}
iot_pkt_free(pkt);
return ERR_OK;
/* 存储半帧到全局buffer */
half_frame:
uart_buffer->buff_len = total_len - hd_index;
os_mem_cpy(uart_buffer->buff_tmp, &pdata[hd_index], uart_buffer->buff_len);
APP_PRINTF(" half frame, buff len=%d\n", uart_buffer->buff_len);
iot_pkt_free(pkt);
return ERR_OK;
}
uint32_t app_dlt645_local_handle_list_register(app_task_e task,
proto_dlt645_proc_func_pair *list_base, uint16_t list_count)
{
if (task >= APP_TASK_MAX || NULL == list_base) {
return ERR_FAIL;
}
g_app_dlt645_handle_list[task].base = list_base;
g_app_dlt645_handle_list[task].count = list_count;
return ERR_OK;
}
uint32_t app_dlt645_init(void)
{
int i = 0;
for (i = 0; i < APP_TASK_MAX; i++) {
g_app_dlt645_handle_list[i].base = NULL;
g_app_dlt645_handle_list[i].count = 0;
}
return ERR_OK;
}