SOME/IP ↔ MQTT Gateway¶
Bidirectional bridge between SOME/IP (via OpenSOME/IP) and MQTT, aimed at fleet telemetry, remote diagnostics, cloud command-and-control, and general IoT integration.
Use case
Vehicle ECUs already speak SOME/IP on the wire; cloud backends and mobile apps typically speak MQTT. This gateway translates between the two, including topic layout, QoS, payload encoding, and optional TLS, so you can stream events and invoke RPC-style flows without rewriting in-vehicle software.
Architecture¶
flowchart LR
subgraph veh ["Vehicle"]
ECU["SOME/IP ECUs<br/>(events, RPC)"]
BUF["Offline ring buffer"]
end
subgraph gw ["Gateway"]
G["SOME/IP ↔ MQTT"]
end
subgraph cloud ["Cloud / edge"]
BRK["MQTT broker"]
DASH["Fleet / diagnostics"]
end
ECU <-->|"UDP/TCP SOME/IP"| G
G <-->|"TLS MQTT"| BRK
BUF <-->|"store & forward"| G
BRK <--> DASH
Features¶
| Area | Capability |
|---|---|
| Pub/sub | SOME/IP events to MQTT topics and reverse where configured |
| Request-response | SOME/IP RPC correlated with MQTT v5 request-response when enabled |
| Security | TLS/mTLS to the broker (mqtts://, client certs) |
| QoS | Per-event/per-method or default publish/subscribe QoS (0/½) |
| Resilience | Ring buffer for offline periods; reconnect with exponential backoff |
| LWT | Last Will and Testament for online/offline status on a dedicated topic |
| Payload encoding | RAW, JSON, or SOMEIP_FRAMED for outbound/inbound |
| Integrity | Optional SOME/IP E2E validation before forwarding |
| Multi-tenant topics | VIN-scoped namespaces: vehicle/{vin}/someip/... |
Encoding
Use JSON for human-readable cloud pipelines, RAW for minimal overhead, and SOMEIP_FRAMED when downstream tools expect a full SOME/IP-style payload wrapper.
MQTT topic structure¶
Canonical topic templates (hex IDs are formatted like 0x1000, consistent with the gateway):
| Topic pattern | Purpose |
|---|---|
vehicle/{vin}/someip/{service_id}/{instance_id}/event/{event_group_id} |
Event notifications |
vehicle/{vin}/someip/{service_id}/{instance_id}/method/{method_id}/request |
RPC request |
vehicle/{vin}/someip/{service_id}/{instance_id}/method/{method_id}/response |
RPC response |
vehicle/{vin}/someip/sd/status |
Last Will / presence (online / offline) |
Prefix and event segment
Configurable topic_prefix (default vehicle) prepends instead of the literal vehicle when set. The gateway builds the event/... segment from the SOME/IP header field that carries the event ID for notifications (often 0x8xxx); align your YAML mappings with how that ID relates to event groups in your service model.
QoS mapping¶
By SOME/IP message role¶
The gateway selects MQTT QoS from whether traffic is event-like or RPC-like, combined with per-mapping overrides and defaults:
| SOME/IP role | MQTT QoS selection | Typical default |
|---|---|---|
Notifications / events (NOTIFICATION, event routing) |
Per-event override, else defaults.publish_qos |
Often 0 for high-rate telemetry |
RPC (REQUEST, responses, errors) |
Per-method override, else RPC default (implementation uses 1 when unset) | Often 1 (at-least-once) |
Underlying helper logic treats notifications as the event path and requests as the RPC path when choosing baseline QoS before applying YAML overrides.
Operational guidelines (transport vs criticality)¶
These are recommended pairings from the gateway README; tune per service in YAML.
| Data type | SOME/IP transport | MQTT QoS | Rationale |
|---|---|---|---|
| Telemetry (periodic) | UDP events | 0 | Best-effort, high frequency |
| Control commands | RPC | 1 | At-least-once delivery |
| Diagnostic / safety-critical | TCP RPC | 2 | Stricter delivery where the broker and clients support it |
OpenSOME/IP APIs used¶
| API | Role in gateway | Documentation |
|---|---|---|
Message, Serializer, Deserializer |
MQTT payload packing and SOME/IP reconstruction | API overview, Serialization |
EventPublisher / EventSubscriber |
Event bridge toward SOME/IP | Events |
RpcClient / RpcServer |
Method call bridge | RPC |
SdClient / SdServer |
Service discovery integration | Service Discovery |
UdpTransport / Endpoint |
Optional SOME/IP UDP listener | API overview |
E2EProtection |
Optional end-to-end checks before publish | E2E Protection |
Configuration reference¶
See gateway-mqtt/examples/mqtt_config.yaml in opensomeip-gateways. Condensed example:
gateway:
name: "vehicle-telemetry-gw"
log_level: info
mqtt:
broker: "mqtts://fleet.example.com:8883"
client_id: "vehicle-${vin}"
protocol_version: 5
keepalive_seconds: 60
clean_session: true
tls:
enabled: true
ca_cert: "/etc/gateway/ca.pem"
client_cert: "/etc/gateway/client.pem"
client_key: "/etc/gateway/client.key"
reconnect:
auto: true
min_delay_ms: 1000
max_delay_ms: 60000
last_will:
enabled: true
topic: "vehicle/${vin}/someip/sd/status"
payload: "offline"
qos: 1
retain: true
defaults:
publish_qos: 1
subscribe_qos: 1
outbound_encoding: json # raw, json, someip_framed
inbound_encoding: raw
offline_buffer_capacity: 512
vin: "WBA12345678901234"
topic_prefix: "vehicle"
someip:
local_address: "0.0.0.0"
local_port: 30500
sd_multicast: "239.255.255.250"
sd_port: 30490
service_mappings:
- someip:
service_id: 0x1000
instance_id: 0x0001
event_groups: [0x0001]
mqtt:
topic_prefix: "vehicle/${vin}/telemetry/speed"
qos: 0
encoding: json
direction: someip_to_mqtt
Secrets
Keep broker URLs, VINs, and certificate paths out of public repositories; inject them at deploy time in production.
C++ usage example¶
Based on gateway-mqtt/examples/mqtt_vehicle_telemetry.cpp: configure broker and VIN, map a speed event stream and a door-lock RPC, then exercise publish and offline buffering.
#include "opensomeip/gateway/mqtt/mqtt_gateway.h"
#include "serialization/serializer.h"
#include "someip/message.h"
#include <iostream>
int main() {
using namespace opensomeip::gateway;
MqttConfig config;
config.broker_uri = "tcp://localhost:1883";
config.client_id = "vehicle-telemetry-gw";
config.topic_prefix = "vehicle";
config.vin = "WBA12345678901234";
config.default_publish_qos = 1;
config.outbound_encoding = MqttPayloadEncoding::JSON;
config.offline_buffer_capacity = 512;
config.use_mqtt_v5_request_response = true;
MqttGateway gateway(config);
ServiceMapping speed;
speed.someip_service_id = 0x1000;
speed.someip_instance_id = 0x0001;
speed.someip_event_group_ids = {0x0001};
speed.external_identifier = "telemetry/speed";
speed.direction = GatewayDirection::SOMEIP_TO_EXTERNAL;
speed.mode = TranslationMode::OPAQUE;
gateway.add_service_mapping(speed);
ServiceMapping door_lock;
door_lock.someip_service_id = 0x2000;
door_lock.someip_instance_id = 0x0001;
door_lock.someip_method_ids = {0x0001};
door_lock.external_identifier = "command/door_lock";
door_lock.direction = GatewayDirection::BIDIRECTIONAL;
gateway.add_service_mapping(door_lock);
gateway.set_someip_outbound_sink([](const someip::Message& msg) {
std::cout << "SOME/IP outbound: service=0x" << std::hex
<< msg.get_service_id() << std::dec << "\n";
});
gateway.start();
gateway.test_set_mqtt_connected(true);
someip::MessageId msg_id(0x1000, 0x8001);
someip::RequestId req_id(0x0000, 0x0001);
someip::Message notification(msg_id, req_id, someip::MessageType::NOTIFICATION);
someip::serialization::Serializer ser;
ser.serialize_float(120.5f);
notification.set_payload(ser.get_buffer());
gateway.on_someip_message(notification);
gateway.test_set_mqtt_connected(false);
gateway.on_someip_message(notification);
gateway.test_set_mqtt_connected(true);
gateway.flush_offline_buffer();
gateway.stop();
return 0;
}
Build instructions¶
Install Paho MQTT C++ when linking against a real broker (optional for stubbed tests).
Tracking¶
Feature scope and integration notes: GitHub issue #3.