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;
 | 
						||
}
 |