VSOA AUTOSAR 客户端

更新时间:
2023-12-28
下载文档

VSOA AUTOSAR 客户端

本节内容介绍 VSOA AUTOSAR 客户端开发方法。

开发须知

  1. VSOA AUTOSAR 客户端需以一个独立 Task 的方式运行,且因该 Task 使用到 AUTOSAR Event 资源,需配置为 Extend Task。
  2. 在 VSOA AUTOSAR 客户端运行前,需完成 VSOA 初始化流程。

开发示例

步骤 1:初始化 VSOA

参考 VSOA 初始化 建立执行 VSOA 定时器的 Task,在此例中可将该 Task 命名为 timer_task

/*
 * VSOA 初始化参数与返回值
 */
static vsoa_init_arg_t vsoa_init_arg = {
    .mem_start  = vsoa_mem,
    .mem_length = VSOA_MEM_SIZE,
    .mem_osl    = &vsoa_mem_osl,
    .timer_osl  = &vsoa_as_timer_osl,
    .event_osl  = &vsoa_as_event_osl,
    .server_osl = &vsoa_server_svc_osl,
    .client_osl = &vsoa_client_svc_osl,
    .errno_osl  = &vsoa_errno_osl
};

static vsoa_init_res_t *vsoa_init_res = NULL;

/*
 * 使用 VSOA 的任务需要定义一个 vsoa_as_task_t, 并使用 vsoa_as_task_register 注册
 */
static vsoa_as_task_t vsoa_as_timer_task = {
    .task_id     = timer_task_id,
    .alarm       = timer_task_alarm_id,
    .alarm_event = timer_task_timeout_mask
};

TASK(timer_task) {
    /*
     * 注册任务
     */
    vsoa_as_task_register(&vsoa_as_timer_task);

    /*
     * 初始化 VSOA
     */
    vsoa_init_res = vsoa_init(&vsoa_init_arg);

    while (1) {
        vsoa_init_res->timer_loop();
    }

    TerminateTask();
}

步骤 2:新建 Client Task

  1. 新建 vsoa_client_task,在该 Task 中需等待 VSOA 初始化完成。Client Task 需要与一个 Alarm 关联,该 Alarm 用于该 Task 中的信号量超时等操作。

    /*
     * 使用 VSOA 的任务需要定义一个 vsoa_as_task_t, 并使用 vsoa_as_task_register 注册
     */
    static vsoa_as_task_t vsoa_client_task = {
        .task_id     = vsoa_client_task_id,
        .alarm       = vsoa_client_task_alarm_id,
        .alarm_event = vsoa_client_task_timeout_mask,
    };
    
    TASK(vsoa_client_task) {
        /*
        * 注册任务
        */
        vsoa_as_task_register(&vsoa_client_task);
    
        /*
        * 等待 VSOA 初始化完成
        */
        while (!vsoa_init_res) {
            vsoa_as_task_sleep(ONE_MS);
        }
    
        TerminateTask();
    }
    
  2. vsoa_client_task 中创建 VSOA 客户端。与标准 VSOA 不同在于 VSOA AUTOSAR 版本的 vsoa_client_create 需要多传入一个 vsoa_client_osl_t 类型的参数,该参数中定义了 Client Task 所需的 Resource 与 Event 资源。

    /*
     * 一个 vsoa_client_osl_t 实现, 需要一个 vsoa_as_client_ctx_t,
     * vsoa_as_client_ctx_t 需要一个 Resource 和 Event 分别作 mutex 和 semaphore
     */
    static vsoa_as_client_ctx_t my_client_ctx = {
        .event = my_client_event_mask,
        .mutex = my_client_lock_id
    };
    
    static vsoa_client_osl_t my_client_osl = {
        .ctx    = &my_client_ctx,
        .lock   = vsoa_as_client_lock,
        .unlock = vsoa_as_client_unlock,
        .wait   = vsoa_as_client_wait,
        .post   = vsoa_as_client_post,
        .sleep  = vsoa_as_client_sleep
    };
    
    /* My client */
    static vsoa_client_t *my_client;
    
    /* My client password */
    #define MY_SERVER_PASSWD "123456"
    
    /*
     * 使用 VSOA 的任务需要定义一个 vsoa_as_task_t, 并使用 vsoa_as_task_register 注册
     */
    static vsoa_as_task_t vsoa_client_task = {
        .task_id     = vsoa_client_task_id,
        .alarm       = vsoa_client_task_alarm_id,
        .alarm_event = vsoa_client_task_timeout_mask,
    };
    
    TASK(vsoa_client_task) {
        /*
        * 注册任务
        */
        vsoa_as_task_register(&vsoa_client_task);
    
        /*
        * 等待 VSOA 初始化完成
        */
        while (!vsoa_init_res) {
            vsoa_as_task_sleep(ONE_MS);
        }
    
        /*
         * 创建 VSOA client
         */
        my_client = vsoa_client_create(&my_client_osl, onmessage, NULL);
    
        vsoa_client_linger(my_client, true);
    
        vsoa_client_send_timeout(my_client, 1 * ONE_S);
    
        TerminateTask();
    }
    

步骤 3:连接 VSOA 服务

vsoa_client_task 中连接 VSOA 服务端,调用 vsoa_client_connect,该接口需静态指定一个地址 ID (地址 ID 序号与具体 AUTOSAR 系统配置相关)。

/*
 * 本例中服务器的地址 ID 可以选择 0 和 1, 0 为本地回环地址, 1 为 en1 的 IP 地址
 * 本例中服务端的 IP 地址为 192.168.7.55
 */
#define CLIENT_ADDR_ID       1
#define CLIENT_SERVER_IP     IP4_ADDR_CHR_TO_UINT32(192,168,7,55)
#define CLIENT_SERVER_PORT   3001

TASK(vsoa_client_task) {

    ……

    /*
     * 连接 VSOA 服务器
     */
    char info[256];
    TcpIp_SockAddrType addr;

    addr.domain  = TCPIP_AF_INET;
    addr.port    = CLIENT_SERVER_PORT;
#if (CPU_BYTE_ORDER == LOW_BYTE_FIRST)
    addr.addr[0] = (CLIENT_SERVER_IP >>  0) & 0xff;
    addr.addr[1] = (CLIENT_SERVER_IP >>  8) & 0xff;
    addr.addr[2] = (CLIENT_SERVER_IP >> 16) & 0xff;
    addr.addr[3] = (CLIENT_SERVER_IP >> 24) & 0xff;
#else
    addr.addr[0] = (CLIENT_SERVER_IP >> 24) & 0xff;
    addr.addr[1] = (CLIENT_SERVER_IP >> 16) & 0xff;
    addr.addr[2] = (CLIENT_SERVER_IP >>  8) & 0xff;
    addr.addr[3] = (CLIENT_SERVER_IP >>  0) & 0xff;
#endif

    if (!vsoa_client_connect(my_client, CLIENT_ADDR_ID, &addr, ONE_S, MY_SERVER_PASSWD, info, sizeof(info))) {
        TerminateTask();
    }

    TerminateTask();
}

步骤 4:调用 RPC 、订阅等业务

  1. 同标准 VSOA 的使用方式,客户端可以订阅服务端发布的信息。

    TASK(vsoa_client_task) {
        ……
    
        /*
         * 创建 VSOA client
         */
        my_client = vsoa_client_create(&my_client_osl, onmessage, NULL);
    
        ……
    
        /*
         * 连接 VSOA server
         */
        if (!vsoa_client_connect(my_client, CLIENT_ADDR_ID, &addr, ONE_S, MY_SERVER_PASSWD, info, sizeof(info))) {
            TerminateTask();
        }
    
        /*
         * 订阅 URL
         */
        vsoa_url_t url;
        url.url     = "/foo";
        url.url_len = strlen(url.url);
        vsoa_client_subscribe(my_client, &url, NULL, NULL, 0);
    
        TerminateTask();
    }
    
  2. 同标准 VSOA 的使用方式,可以向 VSOA 服务端发起 RPC 调用。

    static void my_client_timer_handler(void *arg, vsoa_timer_t *timer, void *custom)
    {
        vsoa_url_t url;
    
        url.url     = "/foo";
        url.url_len = strlen(url.url);
        vsoa_client_call(my_client, VSOA_CLIENT_RPC_METHOD_GET,
                         &url, NULL, get_foo, NULL, ONE_S);
    
    }
    
    TASK(vsoa_client_task) {
        ……
    
        /*
        * 创建定时器进行 RPC 调用
        */
        vsoa_timer_t *timer = vsoa_timer_create();
        vsoa_timer_start_ms(timer, 1000, 1000, my_client_timer_handler, NULL);
    
        TerminateTask();
    }
    

步骤 5:执行 Client 事件循环

同标准 VSOA,Client Task 也需执行事件循环用于处理所有与 Client 相关的事件。在 VSOA AUTOSAR 中,该事件循环过程都已在 vsoa_client_event_loop 接口内容实现。因此只需在 Client Task 最后的循环内调用该接口即可。

TASK(vsoa_client_task) {
    ……

    /*
    * 创建定时器进行 RPC 调用
    */
    vsoa_timer_t *timer = vsoa_timer_create();
    vsoa_timer_start_ms(timer, 1000, 1000, my_client_timer_handler, NULL);

    while (1) {
        vsoa_client_event_loop(my_client);
    }

    TerminateTask();
}

验证执行

以开源的 Tramponline AUTOSARopen in new window 为例,以上 VSOA Client 运行后,结果如下:

文档内容是否对您有所帮助?
有帮助
没帮助