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:新建 Server Task

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

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

    /*
     * 一个 vsoa_server_osl_t 实现, 需要一个 vsoa_as_server_ctx_t,
     * vsoa_as_server_ctx_t 需要一个 Resource 和 Event 分别作 mutex 和 semaphore
     */
    static vsoa_as_server_ctx_t my_server_ctx = {
        .event = my_server_event_mask,
        .mutex = my_server_lock_id
    };
    
    static vsoa_server_osl_t my_server_osl = {
        .ctx    = &my_server_ctx,
        .lock   = vsoa_as_server_lock,
        .unlock = vsoa_as_server_unlock,
        .wait   = vsoa_as_server_wait,
        .post   = vsoa_as_server_post,
        .sleep  = vsoa_as_server_sleep
    };
    
    /* My server type */
    typedef struct {
        vsoa_server_t *server;
        struct data data;
    } my_server_t;
    
    /* My server */
    static my_server_t my_server;
    
    /* My server password */
    #define MY_SERVER_PASSWD "123456"
    
    /*
     * 使用 VSOA 的任务需要定义一个 vsoa_as_task_t, 并使用 vsoa_as_task_register 注册
     */
    static vsoa_as_task_t vsoa_server_task = {
        .task_id     = vsoa_server_task_id,
        .alarm       = vsoa_server_task_alarm_id,
        .alarm_event = vsoa_server_task_timeout_mask,
    };
    
    TASK(vsoa_server_task) {
        /*
        * 注册任务
        */
        vsoa_as_task_register(&vsoa_server_task);
    
        /*
        * 等待 VSOA 初始化完成
        */
        while (!vsoa_init_res) {
            vsoa_as_task_sleep(ONE_MS);
        }
    
        /*
         * 创建 VSOA server
         */
        my_server.server = vsoa_server_create(&my_server_osl, "{\"name\":\"C language VSOA server\"}");
    
        /*
        * 设置 VSOA server 密码
        */
    #ifdef MY_SERVER_PASSWD
        vsoa_server_passwd(my_server.server, MY_SERVER_PASSWD);
    #endif
    
        TerminateTask();
    }
    

步骤 3:增加 RPC 、发布等业务

  1. 同标准 VSOA 的使用方式,可以对客户端的连接情况进行监控,可以增加 RPC 监听。

    TASK(vsoa_server_task) {
        ……
    
        /*
        * 创建 VSOA server
        */
        my_server.server = vsoa_server_create(&my_server_osl, "{\"name\":\"C language VSOA server\"}");
    
        vsoa_server_on_cli(my_server.server, on_client, NULL);
    
        /*
        * VSOA server add listener
        */
        vsoa_url_t url;
    
        url.url     = "/foo";
        url.url_len = strlen(url.url);
        vsoa_server_add_listener(my_server.server, &url, command_foo, NULL);
    
        TerminateTask();
    }
    
  2. 同标准 VSOA 的使用方式,可以使用 VSOA Timer 定期进行 “发布” 或 “快速发布” 操作。

    static void qpub_timer_handler(void *arg, vsoa_timer_t *timer, void *custom)
    {
        vsoa_url_t url;
        vsoa_payload_t payload;
    
        url.url     = "/foo";
        url.url_len = strlen(url.url);
    
        if (!vsoa_server_is_subscribed(my_server.server, &url)) {
            return;
        }
    
        payload.data      = NULL;
        payload.data_len  = 0;
        payload.param     = "{\"foo\":0}";
        payload.param_len = strlen(payload.param);
    
        /*
        *此处调用快速发布接口
        */
        vsoa_server_quick_publish(my_server.server, &url, &payload);
    }
    
    TASK(vsoa_server_task) {
        ……
    
        /*
        * 创建定时器
        */
        vsoa_timer_t *qpub_timer = vsoa_timer_create();
        vsoa_timer_start_ms(qpub_timer, 1000, 1000, qpub_timer_handler, NULL);
    
        TerminateTask();
    }
    

步骤 4:启动 VSOA 服务

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

/*
 * 本例中服务器的地址 ID 可以选择 0 和 1, 0 为本地回环地址, 1 为 en1 的 IP 地址
 */
#define SERVER_ADDR_ID   1
#define SERVER_PORT      3001

TASK(vsoa_server_task) {

    ……

    /*
     * VSOA server add listener
     */
    ……

    url.url     = "/foo";
    url.url_len = strlen(url.url);
    vsoa_server_add_listener(my_server.server, &url, command_foo, NULL);

    /*
     * 启动 VSOA server
     */
    vsoa_server_start(my_server.server, SERVER_ADDR_ID, TCPIP_AF_INET, SERVER_PORT);

    TerminateTask();
}

步骤 5:执行 Server 事件循环

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

TASK(vsoa_server_task) {

    ……

    /*
     * VSOA server add listener
     */
    ……

    url.url     = "/foo";
    url.url_len = strlen(url.url);
    vsoa_server_add_listener(my_server.server, &url, command_foo, NULL);

    /*
     * 启动 VSOA server
     */
    vsoa_server_start(my_server.server, SERVER_ADDR_ID, TCPIP_AF_INET, SERVER_PORT);

    while (1) {
        vsoa_server_event_loop(my_server.server);
    }

    TerminateTask();
}

验证执行

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

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