00 VSS nedir — COVESA sinyal standardı
VSS (Vehicle Signal Specification), COVESA (Connected Vehicle Systems Alliance) tarafından geliştirilen ve araç içindeki tüm sinyalleri standart bir ağaç yapısında tanımlayan açık standarttır.
Araç elektroniğinde aynı sinyal farklı ECU'larda, farklı CAN ID'leri ve farklı isimlendirmelerle temsil edilebilir. Örneğin motor devri:
- CAN mesaj 0x3B0 byte 0-1: RPM × 0.25
- OBD-II PID 0x0C / 256 × 4
- J1939 PGN 0xF004 SPN 190
VSS tüm bu farklılıkları tek standart isim altında soyutlar: Vehicle.Powertrain.CombustionEngine.Speed
COVESA Ekosistemi
┌──────────────────────────────────────────────────────────────┐
│ COVESA VSS Ekosistemi │
├──────────────────────────────────────────────────────────────┤
│ │
│ VSS Tree (Standart Tanım) │
│ ↓ │
│ kuksa.val (Data Broker) ←→ ECU Adapter (CAN/OBD/SOME/IP)│
│ ↓ ↑ │
│ VISS API Signal Mapper │
│ ↓ │
│ Browser / App / Cloud / Android Automotive │
└──────────────────────────────────────────────────────────────┘
Neden VSS?
01 VSS tree yapısı — node tipleri
VSS, ağaç (tree) yapısında organize edilmiş node'lardan oluşur. Her node belirli bir araç verisini veya kategorisini temsil eder.
Node Tipleri
Önemli VSS Namespace'leri
# Araç kimliği
Vehicle.VehicleIdentification.VIN (Attribute, string)
Vehicle.VehicleIdentification.Year (Attribute, uint16)
# Sürüş verisi
Vehicle.Speed (Sensor, float, km/h)
Vehicle.Acceleration.Longitudinal (Sensor, float, m/s²)
Vehicle.TraveledDistance (Sensor, float, km)
# Güç aktarma organı
Vehicle.Powertrain.CombustionEngine.Speed (Sensor, uint32, rpm)
Vehicle.Powertrain.CombustionEngine.ECT (Sensor, int16, °C)
Vehicle.Powertrain.TractionBattery.StateOfCharge.Current (Sensor, float, %)
Vehicle.Powertrain.FuelSystem.InstantConsumption (Sensor, float, l/h)
# Gövde
Vehicle.Body.Lights.IsHighBeamOn (Actuator, bool)
Vehicle.Body.Horn.IsActive (Actuator, bool)
Vehicle.Body.Windshield.Front.Wiping.Mode (Actuator, string)
# Kabin
Vehicle.Cabin.HVAC.Station.Row1.Left.Temperature (Actuator, float, °C)
Vehicle.Cabin.Door.Row1.DriverSide.IsOpen (Sensor, bool)
Vehicle.Cabin.Seat.Row1.DriverSide.Position (Actuator, uint8, mm)
# ADAS
Vehicle.ADAS.LaneDepartureDetection.IsEnabled (Actuator, bool)
Vehicle.ADAS.CruiseControl.SpeedSet (Actuator, float, km/h)
Vehicle.ADAS.ObstacleDetection.IsEnabled (Actuator, bool)
# Konum
Vehicle.CurrentLocation.Latitude (Sensor, double, degrees)
Vehicle.CurrentLocation.Longitude (Sensor, double, degrees)
Vehicle.CurrentLocation.Altitude (Sensor, float, m)
VSS vspec dosyası örneği
Vehicle.Powertrain.CombustionEngine.Speed:
datatype: uint32
type: sensor
unit: rpm
min: 0
max: 20000
description: Engine speed measured as rotations per minute.
comment: "Mapped from OBD-II PID 0x0C or CAN signal."
Vehicle.Body.Lights.IsHighBeamOn:
datatype: boolean
type: actuator
description: Indicates if the high beam switch is on.
Vehicle.VehicleIdentification.VIN:
datatype: string
type: attribute
pattern: "[A-HJ-NPR-Z0-9]{17}"
description: 17-character Vehicle Identification Number.
02 vss-tools — JSON/CSV üretimi
vss-tools, VSS ağaç tanımlarını farklı formatlara dönüştüren ve özelleştirme (overlay) desteği sunan araç setidir.
Kurulum
git clone https://github.com/COVESA/vehicle_signal_specification.git
cd vehicle_signal_specification
pip install vss-tools
Dönüştürme araçları
# JSON formatına dönüştür (kuksa.val ile uyumlu)
vspec2json \
--vspec spec/VehicleSignalSpecification.vspec \
--output vss_out.json
# CSV formatına dönüştür
vspec2csv \
--vspec spec/VehicleSignalSpecification.vspec \
--output vss_out.csv
# Belirli branch'i dönüştür
vspec2json \
--vspec spec/VehicleSignalSpecification.vspec \
--output powertrain.json \
--include-only Vehicle.Powertrain
# Overlay (özel eklentiler) ile genişlet
vspec2json \
--vspec spec/VehicleSignalSpecification.vspec \
--overlay oem_overlay.vspec \
--output vss_custom.json
Özel Overlay
Overlay, standart VSS tree'ye OEM'e özel sinyaller ekler. Mevcut signalleri override etmek veya yeni branch eklemek için kullanılır.
# OEM'e özel sinyal ekleme
Vehicle.OEM:
type: branch
description: OEM-specific signals.
Vehicle.OEM.BatteryThermalManagement.Status:
datatype: string
type: sensor
allowed: ['IDLE', 'ACTIVE', 'FAULT']
description: Battery thermal management system status.
# Standart sinyalin min/max değerini güncelle
Vehicle.Powertrain.CombustionEngine.Speed:
max: 8500 # Varsayılan 20000 yerine OEM limiti
Python API ile VSS okuma
import json
with open('vss_out.json') as f:
vss = json.load(f)
def find_sensors(tree, path=""):
"""Tüm Sensor node'larını listele"""
results = []
for name, node in tree.items():
full_path = f"{path}.{name}" if path else name
if node.get('type') == 'sensor':
results.append({
'path': full_path,
'datatype': node.get('datatype'),
'unit': node.get('unit', '')
})
if 'children' in node:
results.extend(find_sensors(node['children'], full_path))
return results
for sensor in find_sensors(vss):
print(f"{sensor['path']:60s} {sensor['datatype']:10s} {sensor['unit']}")
03 kuksa.val — araç veri broker
kuksa.val (kuksa-data-broker), Eclipse Foundation bünyesindeki açık kaynak araç veri broker'ıdır. VSS path'leri üzerinden get/set/subscribe işlemleri için gRPC API sunar.
Mimari
┌──────────────────────────────────────────────────────────────┐
│ kuksa.val Mimarisi │
├──────────────────────────────────────────────────────────────┤
│ │
│ [CAN Adapter] [OBD-II Adapter] [SOME/IP Adapter] │
│ │ │ │ │
│ └─────────────────┴────────────────────┘ │
│ │ gRPC (set_current_values) │
│ ▼ │
│ ┌──────────────────────────────────────┐ │
│ │ kuksa-data-broker │ │
│ │ VSS tree cache + gRPC server │ │
│ │ Port: 55555 │ │
│ └──────────────────────────────────────┘ │
│ │ gRPC (get/subscribe) │
│ ▼ │
│ [Dashboard App] [Cloud Agent] [Android Automotive] │
│ │
└──────────────────────────────────────────────────────────────┘
Kurulum — Docker
# Resmi Docker image ile hızlı başlangıç
docker pull ghcr.io/eclipse-kuksa/kuksa-databroker:latest
# Broker başlat
docker run -p 55555:55555 \
-e KUKSA_DATA_BROKER_METADATA_FILE=/app/vss_release_4.0.json \
ghcr.io/eclipse-kuksa/kuksa-databroker:latest
# Ya da kaynak koddan derleme
git clone https://github.com/eclipse-kuksa/kuksa-databroker.git
cd kuksa-databroker
cargo build --release
./target/release/databroker \
--metadata /path/to/vss_release_4.0.json \
--port 55555
CLI ile test
pip install kuksa-client
# Interaktif shell
kuksa-client --host localhost --port 55555
# Shell içinde:
# getValue Vehicle.Speed
# setValue Vehicle.Speed 120
# subscribe Vehicle.Speed
# Komut satırı tek işlem:
kuksa-client --host localhost \
--protocol grpc \
getValue "Vehicle.Speed"
04 kuksa Python client API
kuksa_client Python kütüphanesi, kuksa-data-broker'a gRPC üzerinden bağlanmak için yüksek seviyeli API sağlar.
Kurulum
pip install kuksa-client
Temel kullanım — get/set/subscribe
import asyncio
from kuksa_client.grpc import VSSClient
from kuksa_client.grpc import Datapoint
async def main():
async with VSSClient('127.0.0.1', 55555) as client:
# Değer oku
response = await client.get_current_values([
'Vehicle.Speed',
'Vehicle.Powertrain.CombustionEngine.Speed'
])
speed = response['Vehicle.Speed'].value
rpm = response['Vehicle.Powertrain.CombustionEngine.Speed'].value
print(f"Hız: {speed} km/h, RPM: {rpm}")
# Değer yaz (simülatörden güncelleme)
await client.set_current_values({
'Vehicle.Speed':
Datapoint(85.5),
'Vehicle.Powertrain.CombustionEngine.Speed':
Datapoint(3200),
'Vehicle.CurrentLocation.Latitude':
Datapoint(41.0082),
'Vehicle.CurrentLocation.Longitude':
Datapoint(28.9784)
})
print("Değerler güncellendi")
# Subscribe — değişiklik bildirimi al
async for updates in client.subscribe_current_values([
'Vehicle.Speed'
]):
for path, dp in updates.items():
print(f"Güncelleme: {path} = {dp.value} ({dp.timestamp})")
asyncio.run(main())
Metadata okuma
async with VSSClient('127.0.0.1', 55555) as client:
# Sinyal metadata'sını al
meta = await client.get_metadata(['Vehicle.Speed'])
entry = meta['Vehicle.Speed']
print(f"Tip: {entry.type}") # SENSOR
print(f"Veri tipi: {entry.data_type}") # FLOAT
print(f"Birim: {entry.unit}") # km/h
print(f"Min/Max: {entry.min}/{entry.max}")
kuksa.val iki transport destekler: gRPC (Python/C++ için, düşük gecikme) ve WebSocket (W3C VISS uyumlu, browser/web uygulamaları için). kuksa_client kütüphanesi her ikisini destekler: VSSClient(..., protocol='ws') ile WebSocket kullanılır.
05 SOME/IP → VSS köprüsü
SOME/IP üzerinden gelen ECU verileri, bir sinyal eşleyici (signal mapper) aracılığıyla VSS path'lerine dönüştürülüp kuksa.val'e yazılır.
Köprü Mimarisi
┌──────────────┐ SOME/IP Event ┌──────────────────┐
│ ECU │ ──────────────► │ Signal Mapper │
│ (vsomeip) │ Srv:0x5100 │ (Python Bridge) │
│ │ Evt:0x8001 │ │
└──────────────┘ payload:float └──────────────────┘
│ kuksa gRPC
▼ set_current_values
┌─────────────────┐
│ kuksa.val │
│ data broker │
└─────────────────┘
Signal Mapper yapılandırması
{
"mappings": [
{
"someip_service": "0x5100",
"someip_instance": "0x0001",
"someip_event": "0x8001",
"vss_path": "Vehicle.Speed",
"transform": "value * 3.6" // m/s → km/h
},
{
"someip_service": "0x5200",
"someip_instance": "0x0001",
"someip_event": "0x8001",
"vss_path": "Vehicle.Powertrain.CombustionEngine.Speed",
"transform": "value" // doğrudan RPM
},
{
"someip_service": "0x5300",
"someip_instance": "0x0001",
"someip_event": "0x8001",
"vss_path": "Vehicle.Powertrain.CombustionEngine.ECT",
"transform": "value - 273.15" // Kelvin → Celsius
}
]
}
Bridge implementasyonu (Python)
import asyncio, json, struct
from kuksa_client.grpc import VSSClient, Datapoint
import vsomeip # Python vsomeip binding
with open('signal_map.json') as f:
signal_map = json.load(f)['mappings']
# Servis+Event → VSS path ve transform eşlemesi
lookup = {}
for m in signal_map:
key = (int(m['someip_service'], 16),
int(m['someip_instance'], 16),
int(m['someip_event'], 16))
lookup[key] = m
kuksa_client = None
def on_message(msg):
svc = msg.get_service()
inst = msg.get_instance()
meth = msg.get_method()
payload = msg.get_payload().get_data()
key = (svc, inst, meth)
if key not in lookup:
return
mapping = lookup[key]
raw_value = struct.unpack('!f', bytes(payload[:4]))[0]
# Transform uygula
value = eval(mapping['transform'], {"value": raw_value})
asyncio.run_coroutine_threadsafe(
kuksa_client.set_current_values({
mapping['vss_path']: Datapoint(value)
}),
loop)
async def run_bridge():
global kuksa_client
async with VSSClient('127.0.0.1', 55555) as client:
kuksa_client = client
# vsomeip uygulaması başlat ve subscribe et
app = vsomeip.runtime.get().create_application("SomeipVssBridge")
app.init()
for mapping in signal_map:
svc = int(mapping['someip_service'], 16)
inst = int(mapping['someip_instance'], 16)
evt = int(mapping['someip_event'], 16)
app.request_service(svc, inst)
app.register_message_handler(svc, inst, evt, on_message)
app.start()
loop = asyncio.get_event_loop()
loop.run_until_complete(run_bridge())
06 W3C VISS — WebSocket API
W3C VISS (Vehicle Information Service Specification), araç verilerine WebSocket, REST ve GraphQL üzerinden erişimi standartlaştırır. Tarayıcıdan doğrudan araç verisine erişim mümkün olur.
VISS Protokolleri
WebSocket ile araç verisi
// kuksa.val WebSocket server: ws://localhost:8090
const ws = new WebSocket('ws://localhost:8090');
ws.onopen = () => {
// Token ile kimlik doğrulama (gerekiyorsa)
ws.send(JSON.stringify({
action: 'authorize',
tokens: 'your-jwt-token',
requestId: 'auth-1'
}));
// Araç hızına abone ol
ws.send(JSON.stringify({
action: 'subscribe',
path: 'Vehicle.Speed',
requestId: 'sub-speed'
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.action === 'subscription') {
console.log(`Hız: ${data.data.dp.value} km/h`);
document.getElementById('speed').textContent =
data.data.dp.value;
}
};
// Actuator'a yaz (yüksek ışıkları aç)
function setHighBeam(state) {
ws.send(JSON.stringify({
action: 'set',
path: 'Vehicle.Body.Lights.IsHighBeamOn',
value: state,
requestId: 'set-beam'
}));
}
REST API örneği
# GET — araç hızını oku
curl http://localhost:8090/Vehicle/Speed
# Yanıt:
# {"path":"Vehicle.Speed","value":"85.5","timestamp":"2026-04-12T..."}
# PUT — Actuator değeri yaz
curl -X PUT \
-H "Content-Type: application/json" \
-d '{"value": true}' \
http://localhost:8090/Vehicle/Body/Lights/IsHighBeamOn
# Birden fazla sinyal sorgula
curl "http://localhost:8090/Vehicle/Speed?extra=Vehicle.Powertrain.CombustionEngine.Speed"
07 Android Automotive entegrasyonu
Android Automotive OS, araç sinyallerine VHAL (Vehicle Hardware Abstraction Layer) üzerinden erişir. VSS ve VHAL arasındaki eşleme, Android ile araç donanımının entegrasyonunu sağlar.
VHAL Mimarisi
┌──────────────────────────────────────────────────────────────┐
│ Android Automotive OS Katmanları │
├──────────────────────────────────────────────────────────────┤
│ Car App (Navigation, HVAC, Media) │
│ │ CarManager API │
│ Android Car Service │
│ │ HIDL / AIDL │
│ VHAL (Vehicle Hardware Abstraction Layer) │
│ VEHICLE_PROPERTY_PERF_VEHICLE_SPEED (0x11600207) │
│ HVAC_TEMPERATURE_SET (0x15600503) │
│ │ │
│ VSS ↔ VHAL Mapper │
│ │ kuksa.val gRPC │
│ kuksa.val data broker │
└──────────────────────────────────────────────────────────────┘
VHAL Property ile VSS eşleşmesi
# VSS Path VHAL Property ID
Vehicle.Speed → PERF_VEHICLE_SPEED (0x11600207)
Vehicle.Powertrain.CombustionEngine.Speed → ENGINE_RPM (0x11600301)
Vehicle.Cabin.HVAC.Station.Row1.Left.Temperature → HVAC_TEMPERATURE_SET (0x15600503)
Vehicle.Body.Lights.IsHighBeamOn → HIGH_BEAM_LIGHTS_STATE (0x11200E01)
Vehicle.CurrentLocation.Latitude → PERF_ODOMETER (0x11600204)
Vehicle.Cabin.Door.Row1.DriverSide.IsOpen → DOOR_MOVE (0x13400B01)
Android Car Service ile hız okuma (Java)
Car mCar = Car.createCar(context);
CarPropertyManager propManager =
(CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
// Anlık hız okuma
CarPropertyValue<Float> speed = propManager.getProperty(
Float.class,
VehiclePropertyIds.PERF_VEHICLE_SPEED,
VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
Log.d("VSS", "Hız: " + speed.getValue() + " m/s");
// Subscribe — değişiklik bildirimi
propManager.registerCallback(new CarPropertyManager.CarPropertyEventCallback() {
@Override
public void onChangeEvent(CarPropertyValue value) {
if (value.getPropertyId() == VehiclePropertyIds.PERF_VEHICLE_SPEED) {
float kmh = (Float) value.getValue() * 3.6f;
runOnUiThread(() -> speedText.setText(kmh + " km/h"));
}
}
@Override
public void onErrorEvent(int propId, int zone) {}
},
VehiclePropertyIds.PERF_VEHICLE_SPEED,
0.0f); // updateRateHz: 0 = on change
08 Pratik: OBD-II → VSS → Dijital İkiz
Raspberry Pi üzerinde OBD-II dongle'dan araç verisi oku, VSS'e dönüştür, kuksa.val'e gönder ve web dashboard ile gerçek zamanlı görüntüle.
Donanım
- Raspberry Pi 4 (2 GB+)
- ELM327 OBD-II USB dongle veya Bluetooth ELM327
- Python 3.9+, python-obd kütüphanesi
OBD-II → VSS Köprüsü (Python)
import asyncio, obd, time
from kuksa_client.grpc import VSSClient, Datapoint
# OBD-II PID → VSS path eşlemesi
OBD_VSS_MAP = {
obd.commands.SPEED: 'Vehicle.Speed', # km/h
obd.commands.RPM: 'Vehicle.Powertrain.CombustionEngine.Speed',
obd.commands.COOLANT_TEMP: 'Vehicle.Powertrain.CombustionEngine.ECT',
obd.commands.THROTTLE_POS: 'Vehicle.Chassis.Accelerator.PedalPosition',
obd.commands.ENGINE_LOAD: 'Vehicle.Powertrain.CombustionEngine.EngineLoad',
obd.commands.FUEL_LEVEL: 'Vehicle.Powertrain.FuelSystem.Level',
}
async def bridge():
# OBD bağlan (USB dongle: /dev/ttyUSB0)
conn = obd.OBD('/dev/ttyUSB0')
if not conn.is_connected():
print("OBD bağlantısı kurulamadı")
return
async with VSSClient('127.0.0.1', 55555) as kuksa:
while True:
updates = {}
for cmd, vss_path in OBD_VSS_MAP.items():
try:
response = conn.query(cmd)
if not response.is_null():
value = response.value.magnitude
updates[vss_path] = Datapoint(value)
except Exception as e:
print(f"PID hatası {cmd.name}: {e}")
if updates:
await kuksa.set_current_values(updates)
print(f"{len(updates)} sinyal güncellendi")
await asyncio.sleep(0.5) # 2 Hz
asyncio.run(bridge())
Web Dashboard (WebSocket VISS)
<!DOCTYPE html>
<html>
<head>
<title>Araç Dijital İkiz</title>
<style>
body { background: #0a0a0a; color: #00ff88; font-family: monospace; }
.metric { font-size: 2em; margin: 20px; }
</style>
</head>
<body>
<div class="metric">Hız: <span id="speed">--</span> km/h</div>
<div class="metric">RPM: <span id="rpm">--</span></div>
<div class="metric">ECT: <span id="ect">--</span> °C</div>
<script>
const ws = new WebSocket('ws://raspberrypi.local:8090');
const signals = ['Vehicle.Speed',
'Vehicle.Powertrain.CombustionEngine.Speed',
'Vehicle.Powertrain.CombustionEngine.ECT'];
ws.onopen = () => signals.forEach((path, i) => {
ws.send(JSON.stringify({action:'subscribe', path, requestId:`s${i}`}));
});
const map = {
'Vehicle.Speed': 'speed',
'Vehicle.Powertrain.CombustionEngine.Speed': 'rpm',
'Vehicle.Powertrain.CombustionEngine.ECT': 'ect'
};
ws.onmessage = (e) => {
const d = JSON.parse(e.data);
if (d.action === 'subscription') {
const el = map[d.data.path];
if (el) document.getElementById(el).textContent =
parseFloat(d.data.dp.value).toFixed(1);
}
};
</script>
</body>
</html>
Sistemin çalıştırılması
# 1. kuksa.val başlat
docker run -d -p 55555:55555 -p 8090:8090 \
ghcr.io/eclipse-kuksa/kuksa-databroker:latest
# 2. OBD-VSS köprüsü başlat
python3 obd_vss_bridge.py &
# 3. Tarayıcıda dashboard aç
python3 -m http.server 8080 &
# → http://raspberrypi.local:8080/dashboard.html
# 4. CLI ile değerleri kontrol et
kuksa-client --host localhost \
getValue "Vehicle.Speed"
Aynı kuksa.val broker'a bağlanan bir simülatör, gerçek araç yerine sanal değerler gönderebilir. Test uygulamaları fiziksel araca gerek kalmadan geliştirilebilir. Bu yaklaşım araç dijital ikizi (Digital Twin) konseptinin temelidir. COVESA'nın dijital ikiz çalışma grubu VSS üzerine inşa edilmiş standart bir API geliştirmektedir.