目录
  • 一、准备工作
  • 二、软件设计
  • 三、编译代码
  • 四、测试

SLE UDP网关透传测试

该教程演示如何通过两块开发板实现SLE数据传输测试,A开发板通过串口接收数据,然后通过SLE传输给B开发板,B开发板将接收到的数据通过UDP协议发送到UDP服务端;B开发板接收UDP服务端发来的数据,然后通过SLE传输给A开发板,A开发板通过串口将接收到的数据打印出来。在测试中需要一块开发板做为Server端,另外一块开发板做为Client端,两块开发板配对后就可以互发消息了。注意B开发板和UDP服务器需要处于同一个局域网。

一、准备工作

  • 准备2块BearPi-HM Nano 2开发板

二、软件设计

SLE UDP网关透传客户端主要代码分析

打开device\bearpi\bearpi_hm_nano2\app\E3_sle_gateway_client_udp\sle_gateway.c,这部分的代码,首先通过 WifiConnect函数连接Wi-Fi。另外使用sle_client_init函数注册星闪数据接收回调,在sle_notification_cb回调函数中将星闪接收到的数据使用sendto函数发送到UDP服务器,在while中使用recvfrom接收UDP服务器发来的数据,并ssapc_write_req函数发送给星闪服务端设备。

void sle_notification_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
    errcode_t status)
{
    unused(client_id);
    unused(conn_id);
    unused(status);
    osal_printk("\n sle uart recived data : %s\r\n", data->data);
    uapi_uart_write(SLE_GATEWAY_BUS, (uint8_t *)(data->data), data->data_len, 0);
    sendto(g_sock_fd, (uint8_t *)(data->data), data->data_len, 0, (struct sockaddr *)&g_send_addr, g_addr_length);
}
static void *sle_client_task(const char *arg)
{
    unused(arg);
    char recvBuf[512];

    // Wifi connect
    WifiConnect(CONFIG_WIFI_SSID, CONFIG_WIFI_PWD);

    // create socket
    printf("create socket start!\r\n");
    if ((g_sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        printf("create socket failed!\r\n");
        return 0;
    }
    g_send_addr.sin_family = AF_INET;
    g_send_addr.sin_port = htons(CONFIG_SERVER_PORT);
    g_send_addr.sin_addr.s_addr = inet_addr(CONFIG_SERVER_IP);
    g_addr_length = sizeof(g_send_addr);
    printf("create socket end!\r\n");

    sle_client_init(sle_notification_cb, sle_indication_cb);
    
    while (1) {
        bzero(recvBuf, sizeof(recvBuf));
        // 接收服务端返回的字符串
        recvfrom(g_sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&g_send_addr, &g_addr_length);
        // printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);
        ssapc_write_param_t *sle_send_param = get_g_sle_send_param();
        uint16_t g_sle_conn_id = get_g_sle_conn_id();
        sle_send_param->data_len = strlen(recvBuf);
        sle_send_param->data = (uint8_t *)recvBuf;
        ssapc_write_req(0, g_sle_conn_id, sle_send_param);
    }
    return NULL;
}

SLE UDP网关透传服务端主要代码分析

打开device\bearpi\bearpi_hm_nano2\app\E4_sle_gateway_server_udp\sle_gateway.c,这部分代码为UART初始化的代码,首先要在 uart_attr_t 结构体中配置波特率、数据位、停止位、奇偶检验位,然后通过 uapi_uart_init() 函数对串口进行配置,这里默认使用是的和开发板Typec口连接的串口0作为透传串口,开发者也可改为其他串口。

static void uart_init_config(void)
{
    uart_attr_t attr = {
        .baud_rate = SLE_UART_BAUDRATE,
        .data_bits = UART_DATA_BIT_8,
        .stop_bits = UART_STOP_BIT_1,
        .parity = UART_PARITY_NONE
    };

    uart_pin_config_t pin_config = {
        // .tx_pin = CONFIG_UART_TXD_PIN,
        // .rx_pin = CONFIG_UART_RXD_PIN,
        .cts_pin = PIN_NONE,
        .rts_pin = PIN_NONE
    };
    uapi_uart_deinit(SLE_UART_BUS);
    uapi_uart_init(SLE_UART_BUS, &pin_config, &attr, NULL, &g_app_uart_buffer_config);

}

以下这部分的代码,首先通过 uapi_uart_register_rx_callback() 注册串口中断回调,在回调函数中将串口接收到的数据通过sle_server_send_report_by_handle() 函数发送出去。另外使用sle_server_init函数注册星闪数据接收回调,在ssaps_server_write_request_cbk回调函数中将星闪接收到的数据使用uapi_uart_write函数通过串口发送出来。

static void ssaps_server_write_request_cbk(uint8_t server_id, uint16_t conn_id, ssaps_req_write_cb_t *write_cb_para,
    errcode_t status)
{
    printf("%s ssaps write request callback cbk server_id:%x, conn_id:%x, handle:%x, status:%x\r\n",
        SLE_UART_SERVER_LOG, server_id, conn_id, write_cb_para->handle, status);
    if ((write_cb_para->length > 0) && write_cb_para->value) {
        printf("\n sle uart recived data : %s\r\n", write_cb_para->value);
        uapi_uart_write(SLE_UART_BUS, (uint8_t *)write_cb_para->value, write_cb_para->length, 0);
    }
}

static void sle_server_read_int_handler(const void *buffer, uint16_t length, bool error)
{
    unused(error);
    if (sle_client_is_connected()) {
        sle_server_send_report_by_handle(buffer, length);
    } else {
        printf("%s sle client is not connected! \r\n", SLE_UART_SERVER_LOG);
    }
}

static void *sle_server_task(const char *arg)
{
    unused(arg);

    sle_server_init(ssaps_server_read_request_cbk, ssaps_server_write_request_cbk);

    /* UART init config. */
    uart_init_config();

    uapi_uart_unregister_rx_callback(SLE_UART_BUS);
    errcode_t ret = uapi_uart_register_rx_callback(SLE_UART_BUS,
                                                   UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
                                                   1, sle_server_read_int_handler);
    if (ret != ERRCODE_SUCC) {
        printf("%s Register uart callback fail.[%x]\r\n", SLE_UART_SERVER_LOG, ret);
        return NULL;
    }
    while (1) {
        osDelay(SLE_UART_TASK_DURATION_MS);
    }
    return NULL;
}

三、编译代码

编译 SLE Gateway Client代码

修改 device\bearpi\bearpi_hm_nano2\app路径下 BUILD.gn 文件,指定 sle_gateway_client_udp 参与编译。

# "E1_sle_uart_client:example",
# "E2_sle_uart_server:example",
"E3_sle_gateway_client_udp:example",
# "E4_sle_gateway_server_udp:example",
# "E5_sle_gateway_client_oc:example",
# "E6_sle_gateway_server_oc:example",    

编译 SLE Gateway Server代码

修改 device\bearpi\bearpi_hm_nano2\app路径下 BUILD.gn 文件,指定 sle_gateway_server_udp 参与编译。

# "E1_sle_uart_client:example",
# "E2_sle_uart_server:example",
# "E3_sle_gateway_client_udp:example",
"E4_sle_gateway_server_udp:example",
# "E5_sle_gateway_client_oc:example",
# "E6_sle_gateway_server_oc:example",     

四、测试

使用 Socket 调试工具 创建UDP服务端用于测试。

Socket 调试工具下载地址: 点击跳转

烧录固件后先启动server设备,再启动client设备,在server端串口工具的输入框中输入数据并发送,在Socket 调试工具输入框中输入数据并发送,测试server和client设备之间的数据收发,如下图所示。

Alt text

注:如果开发板连不上这个UDP服务端,请关闭电脑所有的防火墙和杀毒软件后再尝试重新连接