车载终端接入指南

概述

MBE 为车载智能终端提供轻量级 HTTP REST API,支持:

  • 语音问答(知识库查询)
  • 车辆状态上报
  • 远程命令下发

API 端点

端点 方法 描述
/api/vehicle/query POST 语音问答
/api/vehicle/status POST 状态上报
/api/vehicle/command/{vid} POST 远程命令
/api/vehicle/ping GET 健康检查
/api/vehicle/debug GET 调试页面

服务地址

生产环境: https://mbe.hi-maker.com
调试页面: https://mbe.hi-maker.com/api/vehicle/debug

1. 语音问答接口

请求

POST /api/vehicle/query
Content-Type: application/json

{
  "q": "附近有加油站吗",
  "vid": "vehicle_001",
  "uid": "user_123",
  "lat": 31.2304,
  "lng": 121.4737,
  "speed": 60,
  "driving": true
}
字段 类型 必填 说明
q string 语音指令/问题
vid string 车辆ID
uid string 用户ID
lat float 纬度
lng float 经度
speed float 车速 (km/h)
driving bool 是否行驶中(默认true)

响应

{
  "ok": true,
  "a": "最近的加油站在前方500米,中石化加油站",
  "tts": "最近的加油站在前方500米",
  "e": "通用生活助手",
  "action": null
}
字段 说明
ok 是否成功
a 回答文本(用于显示)
tts 语音播报文本
e 专家名称
action 车控动作(null表示纯问答)

车控命令响应

如果识别为车控命令,返回动作指令:

{
  "ok": true,
  "a": "好的,空调已开启",
  "tts": "好的,空调已开启",
  "action": "ac_on",
  "params": {"mode": "auto"}
}

支持的车控命令

语音指令 action params
打开空调 ac_on {mode: "auto"}
关闭空调 ac_off {}
温度调到24度 ac_temp {temp: 24}
打开车窗 window_open {position: "all"}
关闭车窗 window_close {position: "all"}
打开车灯 lights_on {}
关闭车灯 lights_off {}
播放音乐 music_play {}
暂停音乐 music_pause {}
导航到... navigate {query: "..."}
查看车况 check_status {}

2. 状态上报接口

请求

POST /api/vehicle/status
Content-Type: application/json

{
  "vid": "vehicle_001",
  "ts": 1706198400000,
  "lat": 31.2304,
  "lng": 121.4737,
  "speed": 60,
  "heading": 180,
  "rpm": 2500,
  "fuel": 45,
  "temp": 90,
  "voltage": 12.6,
  "mileage": 15000,
  "engine_on": true,
  "doors_locked": true,
  "ac_on": false,
  "lights_on": false,
  "alerts": [],
  "dtc_codes": []
}
字段 类型 说明
vid string 车辆ID
ts int 时间戳 (毫秒)
lat/lng float GPS坐标
speed float 车速 (km/h)
heading float 航向角 (0-360)
rpm int 发动机转速
fuel float 油量百分比
temp float 水温 (°C)
voltage float 电池电压 (V)
mileage float 总里程 (km)
engine_on bool 发动机状态
doors_locked bool 门锁状态
ac_on bool 空调状态
lights_on bool 车灯状态
alerts array 告警列表
dtc_codes array 故障码列表

响应

{
  "ok": true,
  "cmd": "",
  "params": {},
  "notification": {
    "type": "low_fuel",
    "message": "油量较低(15%),建议及时加油"
  }
}

3. 远程命令接口

请求

POST /api/vehicle/command/{vehicle_id}
Content-Type: application/json

{
  "cmd": "lock_doors",
  "params": {}
}

支持的命令

命令 说明
lock_doors 锁车门
unlock_doors 解锁车门
start_ac 启动空调
stop_ac 关闭空调
flash_lights 闪灯寻车
honk 鸣笛
get_location 获取位置
start_engine 远程启动
stop_engine 熄火
open_trunk 打开后备箱
close_trunk 关闭后备箱

响应

{
  "ok": true,
  "queued": true,
  "cmd": "lock_doors",
  "message": "车门已锁定"
}

集成代码示例

Android (Kotlin)

import okhttp3.*
import org.json.JSONObject

class MBEVehicleClient(private val baseUrl: String = "https://mbe.hi-maker.com") {
    private val client = OkHttpClient()
    
    fun query(
        question: String,
        vehicleId: String,
        lat: Double? = null,
        lng: Double? = null,
        driving: Boolean = true,
        callback: (Result<VoiceResponse>) -> Unit
    ) {
        val json = JSONObject().apply {
            put("q", question)
            put("vid", vehicleId)
            put("driving", driving)
            lat?.let { put("lat", it) }
            lng?.let { put("lng", it) }
        }
        
        val request = Request.Builder()
            .url("$baseUrl/api/vehicle/query")
            .post(RequestBody.create(
                MediaType.parse("application/json"),
                json.toString()
            ))
            .build()
        
        client.newCall(request).enqueue(object : Callback {
            override fun onResponse(call: Call, response: Response) {
                val body = response.body()?.string() ?: ""
                val result = JSONObject(body)
                callback(Result.success(VoiceResponse(
                    ok = result.getBoolean("ok"),
                    answer = result.optString("a", ""),
                    tts = result.optString("tts", ""),
                    action = result.optString("action", null)
                )))
            }
            override fun onFailure(call: Call, e: IOException) {
                callback(Result.failure(e))
            }
        })
    }
}

data class VoiceResponse(
    val ok: Boolean,
    val answer: String,
    val tts: String,
    val action: String?
)

C/C++ (车机嵌入式)

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include "cJSON.h"

#define MBE_URL "https://mbe.hi-maker.com/api/vehicle/query"

typedef struct {
    int ok;
    char answer[512];
    char tts[256];
    char action[32];
} mbe_response_t;

// 回调函数接收响应
static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t total = size * nmemb;
    strncat((char*)userp, (char*)contents, total);
    return total;
}

int mbe_query(const char *question, const char *vehicle_id, 
              double lat, double lng, int driving,
              mbe_response_t *response) {
    CURL *curl;
    CURLcode res;
    char post_data[1024];
    char response_buf[2048] = {0};
    
    // 构建JSON请求
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "q", question);
    cJSON_AddStringToObject(root, "vid", vehicle_id);
    cJSON_AddBoolToObject(root, "driving", driving);
    if (lat != 0 && lng != 0) {
        cJSON_AddNumberToObject(root, "lat", lat);
        cJSON_AddNumberToObject(root, "lng", lng);
    }
    char *json_str = cJSON_PrintUnformatted(root);
    
    curl = curl_easy_init();
    if (curl) {
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        
        curl_easy_setopt(curl, CURLOPT_URL, MBE_URL);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, response_buf);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);  // 5秒超时
        
        res = curl_easy_perform(curl);
        
        if (res == CURLE_OK) {
            // 解析响应
            cJSON *resp = cJSON_Parse(response_buf);
            if (resp) {
                response->ok = cJSON_GetObjectItem(resp, "ok")->valueint;
                strncpy(response->answer, 
                    cJSON_GetObjectItem(resp, "a")->valuestring, 511);
                strncpy(response->tts,
                    cJSON_GetObjectItem(resp, "tts")->valuestring, 255);
                cJSON *action = cJSON_GetObjectItem(resp, "action");
                if (action && !cJSON_IsNull(action)) {
                    strncpy(response->action, action->valuestring, 31);
                } else {
                    response->action[0] = '\0';
                }
                cJSON_Delete(resp);
            }
        }
        
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    
    cJSON_Delete(root);
    free(json_str);
    
    return (res == CURLE_OK) ? 0 : -1;
}

// 使用示例
int main() {
    mbe_response_t resp;
    
    if (mbe_query("打开空调", "vehicle_001", 31.23, 121.47, 1, &resp) == 0) {
        printf("Answer: %s\n", resp.answer);
        printf("TTS: %s\n", resp.tts);
        if (resp.action[0]) {
            printf("Action: %s\n", resp.action);
            // 执行车控动作
        }
    }
    
    return 0;
}

Python (测试/原型)

import requests

class MBEVehicleClient:
    def __init__(self, base_url="https://mbe.hi-maker.com"):
        self.base_url = base_url
    
    def query(self, question, vehicle_id, lat=None, lng=None, driving=True):
        """语音问答"""
        payload = {
            "q": question,
            "vid": vehicle_id,
            "driving": driving
        }
        if lat and lng:
            payload["lat"] = lat
            payload["lng"] = lng
        
        resp = requests.post(
            f"{self.base_url}/api/vehicle/query",
            json=payload,
            timeout=5
        )
        return resp.json()
    
    def report_status(self, vehicle_id, **status):
        """上报状态"""
        payload = {"vid": vehicle_id, **status}
        resp = requests.post(
            f"{self.base_url}/api/vehicle/status",
            json=payload,
            timeout=5
        )
        return resp.json()
    
    def send_command(self, vehicle_id, cmd, params=None):
        """发送命令"""
        resp = requests.post(
            f"{self.base_url}/api/vehicle/command/{vehicle_id}",
            json={"cmd": cmd, "params": params or {}},
            timeout=5
        )
        return resp.json()

# 使用示例
client = MBEVehicleClient()

# 语音问答
result = client.query("附近有加油站吗", "my_car", lat=31.23, lng=121.47)
print(f"回答: {result['a']}")
print(f"TTS: {result['tts']}")
if result.get('action'):
    print(f"执行动作: {result['action']}")

# 上报状态
client.report_status("my_car", speed=60, fuel=45, temp=90)

# 远程锁车
client.send_command("my_car", "lock_doors")

响应时间

场景 超时设置 典型响应
行驶中 2秒 0.2-0.5秒
停车时 4秒 0.2-0.5秒
车控命令 - <0.05秒

架构说明

┌─────────────┐     HTTP/HTTPS      ┌─────────────┐
│  车载终端   │ ──────────────────→ │   MBE API   │
│  (Android/  │                     │             │
│   Linux/    │ ←────────────────── │  /api/      │
│   QNX)      │    JSON Response    │  vehicle/   │
└─────────────┘                     └─────────────┘
       │                                   │
       │                                   ▼
       │                           ┌─────────────┐
       │                           │  专家系统   │
       │                           │  知识库     │
       │                           └─────────────┘
       │
       ▼
┌─────────────┐
│  车辆CAN    │  ← 车控命令由车机本地执行
│  总线/ECU  │
└─────────────┘

注意:MBE只负责语音理解和知识问答,车控命令的实际执行由车载终端本地完成。


常见问题

1. 网络不稳定怎么办?

建议:

  • 设置合理的超时时间(行驶中2秒,停车4秒)
  • 实现请求重试机制
  • 车控命令本地缓存

2. 如何处理离线场景?

  • 车控命令(打开空调等)可以本地关键词匹配处理
  • 知识问答需要网络,可提示用户稍后再试

3. 如何保证安全性?

  • 车控命令由车机本地执行,MBE只返回动作标识
  • 远程命令需要用户认证和车辆绑定
  • 建议使用HTTPS加密传输