2. 服务接口定义与部署

任务说明

本案例目标是在AUTOSAR Adaptive Platform(AP)环境中,为一个名为VehicleSpeed的服务定义包含方法(Method)和事件(Event)的接口,并将该服务接口部署到服务进程中。最终交付物为:ara::com服务接口定义(C++头文件)、服务实现骨架、服务部署清单(JSON),以及对应的构建与运行验证方式。

1. 服务接口定义

服务接口采用AUTOSAR AP的C++绑定(ara::com)。定义两个方法:GetSpeed(获取当前车速)和SetSpeedSource(设置速度来源),以及一个事件SpeedUpdate(周期性发布车速更新)。

// vehicle_speed_service_interface.hpp
#ifndef VEHICLE_SPEED_SERVICE_INTERFACE_HPP_
#define VEHICLE_SPEED_SERVICE_INTERFACE_HPP_

#include <cstdint>
#include <string>
#include "ara/com/types.h"

namespace ara {
namespace com {

// 方法:获取当前车速
class GetSpeed {
public:
    struct Output {
        std::uint32_t speed_kph;  // 车速,单位 km/h
    };
    using Input = ara::com::Empty;
};

// 方法:设置速度来源
class SetSpeedSource {
public:
    struct Input {
        std::string source;  // 来源标识,如 "CAN" / "SIM"
    };
    struct Output {
        bool success;  // 是否设置成功
    };
};

// 事件:车速更新
class SpeedUpdate {
public:
    struct SampleType {
        std::uint32_t speed_kph;
        std::uint64_t timestamp_ms;
    };
};

// 服务接口定义
class VehicleSpeedService {
public:
    using GetSpeedMethod = ara::com::Method<GetSpeed::Output, GetSpeed::Input>;
    using SetSpeedSourceMethod = ara::com::Method<SetSpeedSource::Output, SetSpeedSource::Input>;
    using SpeedUpdateEvent = ara::com::Event<SpeedUpdate::SampleType>;

    static constexpr char const* kServiceName = "VehicleSpeed";
};

}  // namespace com
}  // namespace ara

#endif  // VEHICLE_SPEED_SERVICE_INTERFACE_HPP_

2. 服务实现骨架

以下代码实现服务进程中的核心逻辑:维护当前车速值,提供方法处理,并周期性触发事件更新。为保持最小可复现,使用一个简单线程模拟速度源。

// vehicle_speed_service_impl.cpp
#include <thread>
#include <chrono>
#include <atomic>
#include <iostream>
#include "vehicle_speed_service_interface.hpp"

using namespace ara::com;

class VehicleSpeedServiceImpl {
public:
    VehicleSpeedServiceImpl()
        : current_speed_(0), running_(true) {}

    void Init() {
        // 注册方法处理
        get_speed_handler_ = [this](const GetSpeed::Input& in, GetSpeed::Output& out) {
            (void)in;
            out.speed_kph = current_speed_.load();
        };

        set_source_handler_ = [this](const SetSpeedSource::Input& in, SetSpeedSource::Output& out) {
            if (in.source == "CAN" || in.source == "SIM") {
                source_ = in.source;
                out.success = true;
            } else {
                out.success = false;
            }
        };

        // 启动事件发布线程
        event_thread_ = std::thread([this]() {
            while (running_) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                if (source_ == "SIM") {
                    current_speed_ += 1;  // 模拟速度递增
                }
                SpeedUpdate::SampleType sample;
                sample.speed_kph = current_speed_.load();
                sample.timestamp_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                    std::chrono::system_clock::now().time_since_epoch()).count();
                // 实际部署时通过 proxy 或 skeleton 发布事件
                // 此处仅演示数据生成逻辑
                last_sample_ = sample;
            }
        });
    }

    void Stop() {
        running_ = false;
        if (event_thread_.joinable()) {
            event_thread_.join();
        }
    }

    // 供验证使用:获取最近一次事件样本
    SpeedUpdate::SampleType GetLastSample() const { return last_sample_; }

private:
    std::atomic<std::uint32_t> current_speed_;
    std::atomic<bool> running_;
    std::string source_ = "SIM";
    std::thread event_thread_;
    SpeedUpdate::SampleType last_sample_;
    std::function<void(const GetSpeed::Input&, GetSpeed::Output&)> get_speed_handler_;
    std::function<void(const SetSpeedSource::Input&, SetSpeedSource::Output&)> set_source_handler_;
};

// 主函数:演示服务生命周期
int main() {
    VehicleSpeedServiceImpl service;
    service.Init();

    // 模拟调用 GetSpeed 方法
    GetSpeed::Input in;
    GetSpeed::Output out;
    // 实际部署时通过 skeleton 的 dispatch 调用
    // 此处直接调用内部逻辑验证
    std::cout << "Service started. Press Enter to stop." << std::endl;
    std::cin.get();

    service.Stop();
    return 0;
}

3. 服务部署清单

在AP中,服务部署通过JSON清单描述服务实例与进程的绑定关系。以下为最小部署配置:

{
  "service_instances": [
    {
      "service_id": "VehicleSpeed",
      "instance_id": 1,
      "methods": [
        {
          "name": "GetSpeed",
          "type": "method"
        },
        {
          "name": "SetSpeedSource",
          "type": "method"
        }
      ],
      "events": [
        {
          "name": "SpeedUpdate",
          "type": "event"
        }
      ],
      "deployment": {
        "process": "VehicleSpeedServiceProcess",
        "communication": "someip",
        "network": "eth0"
      }
    }
  ]
}

4. 构建与运行

依赖:AUTOSAR AP实现(如Adaptive AUTOSAR官方栈或商业实现)、C++14及以上编译器、CMake。构建命令:

g++ -std=c++14 -I./ vehicle_speed_service_impl.cpp -o vehicle_speed_service -lpthread

运行:

./vehicle_speed_service

5. 验证方法与判定标准

本案例代码为教学演示,未接入完整ara::com运行时。验证分为两层:

  • 编译验证:上述命令应无错误编译通过,生成可执行文件。
  • 逻辑验证:运行程序后,观察控制台输出“Service started”,程序保持运行;按Enter后正常退出。若接入真实AP运行时,可通过ara::com proxy调用GetSpeed方法,返回值应等于当前模拟速度;订阅SpeedUpdate事件,应每100ms收到一次包含递增速度值的样本。

判定标准:编译无错误;程序能启动并响应Enter退出;若在完整AP环境中,方法调用返回有效速度值,事件订阅能周期性收到数据,即判定通过。

VehicleSpeed 服务接口 Method: GetSpeed() Method: SetSpeedSource() Event: SpeedUpdate 服务实现 (进程内) 速度数据维护 方法处理逻辑 事件发布线程 部署清单 进程绑定 通信: SOME/IP 网络: eth0 调用 调用 发布 部署 部署 部署 验证观测点 1. 编译: g++ 命令无错误通过 2. 运行: 程序启动后等待输入,Enter 退出 3. 完整AP环境: GetSpeed 返回当前速度值; SpeedUpdate 每100ms收到递增样本