272 lines
9.2 KiB
C
272 lines
9.2 KiB
C
/****************************************************************************
|
||
|
||
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||
|
||
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||
be copied by any method or incorporated into another program without
|
||
the express written consent of Aerospace C.Power. This Information or any portion
|
||
thereof remains the property of Aerospace C.Power. The Information contained herein
|
||
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||
liability for its use in any way and conveys no license or title under
|
||
any patent or copyright and makes no representation or warranty that this
|
||
Information is free from patent or copyright infringement.
|
||
|
||
****************************************************************************/
|
||
|
||
#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;
|
||
}
|