Byte 0-1: Service ID (uint16) — identifies the service interface
Byte 2-3: Method/Event ID (uint16) — method call or event notification
Byte 4-7: Length (uint32) — total message size MINUS first 8 bytes
Byte 8-9: Client ID (uint16) — identifies the calling client
Byte 10-11: Session ID (uint16) — incremented per request; used for matching response
Byte 12: Protocol Version (uint8) — 0x01
Byte 13: Interface Version(uint8) — matches ServiceInterface.version in ARXML
Byte 14: Message Type (uint8):
0x00 = REQUEST (client → server, expects RESPONSE)
0x01 = REQUEST_NO_RETURN (fire-and-forget)
0x02 = NOTIFICATION (server → subscriber, one-way)
0x80 = RESPONSE (server → client, matches Client+Session ID)
0x81 = ERROR (server → client, error response)
Byte 15: Return Code (uint8):
0x00 = E_OK
0x01 = E_NOT_OK
0x22 = E_UNKNOWN_METHOD
0x23 = E_WRONG_MESSAGE_TYPEimport struct
def parse_someip_header(data: bytes) -> dict:
"""Parse SOME/IP 16-byte header (8 fixed + 8 request header)"""
if len(data) < 16:
raise ValueError(f"Too short: {len(data)} bytes")
service_id, method_id, length, client_id, session_id, proto_ver, iface_ver, msg_type, return_code = struct.unpack(">HHIBBHHBBBB", data[:16])
return {
"service_id": f"0x{service_id:04X}",
"method_id": f"0x{method_id:04X}",
"length": length,
"client_id": f"0x{client_id:04X}",
"session_id": session_id,
"msg_type": {0x00:"REQUEST",0x02:"NOTIFICATION",0x80:"RESPONSE"}.get(msg_type, f"0x{msg_type:02X}"),
"return_code": "E_OK" if return_code == 0 else f"0x{return_code:02X}",
}
# Example: parse a SOME/IP NOTIFICATION
raw = bytes([0x12,0x34, 0x80,0x01, 0x00,0x00,0x00,0x04,
0x00,0x01, 0x00,0x05, 0x01, 0x01, 0x02, 0x00,
0x00,0x00, 0x27,0x10]) # payload: VehicleSpeed = 10000 (×0.01 = 100 km/h)
hdr = parse_someip_header(raw)
print(hdr)