OBD-II signals renamed obd_*, plus timing, trims, O2; GNSS signals; elm_connected; reboot command
Decision 30: CAN feeds displays, OBD-II (K-line via the ELM) calibrates, so every obd2 signal carries the obd_ prefix and the plain names are left for decoded ones. yukart/gnss/<signal> gives displays the fix as single values; gnss/fix stays for navigation. Boundary: reboot beside poweroff, same guards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
This commit is contained in:
+9
-7
@@ -37,7 +37,7 @@ The two channels from decision 24 share the socket but keep different guarantees
|
|||||||
| `ack` | reply to a `cmd` | `id`, `ok`, `detail`, `dup` (true when answered from the cache) |
|
| `ack` | reply to a `cmd` | `id`, `ok`, `detail`, `dup` (true when answered from the cache) |
|
||||||
|
|
||||||
With `source: bus`, `signals` is the newest envelope of every signal svc-gw has
|
With `source: bus`, `signals` is the newest envelope of every signal svc-gw has
|
||||||
seen on `yukart/vehicle/+` and `yukart/host/+`. svc-gw marks one
|
seen on `yukart/vehicle/+`, `yukart/host/+` and `yukart/gnss/+`. svc-gw marks one
|
||||||
`quality: "stale"` when it has not been refreshed for 5 s, or is known only from
|
`quality: "stale"` when it has not been refreshed for 5 s, or is known only from
|
||||||
the broker's retained copy (which may predate a reboot). A signal once seen is
|
the broker's retained copy (which may predate a reboot). A signal once seen is
|
||||||
never removed.
|
never removed.
|
||||||
@@ -66,18 +66,20 @@ tablet, or an Orin behind a replugged hub, looks connected at the link layer.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `ping` | — | `ack` with `detail: "pong"` |
|
| `ping` | — | `ack` with `detail: "pong"` |
|
||||||
| `mark` | `text`, `delay_ms` (optional: how long the command waited before this send) | stamped into the open recording; fails with no session open |
|
| `mark` | `text`, `delay_ms` (optional: how long the command waited before this send) | stamped into the open recording; fails with no session open |
|
||||||
| `poweroff` | `confirm: "poweroff"`, `boot_id` (from this connection's `hello`) | acks, then shuts the host down cleanly (`systemctl poweroff`) about 2 s later. Refused unless svc-gw runs with `--allow-poweroff` (the Orin's unit only), and when `boot_id` is not the current boot's |
|
| `poweroff` | `confirm: "poweroff"`, `boot_id` (from this connection's `hello`) | acks, then shuts the host down cleanly (`systemctl poweroff`) about 2 s later. Refused unless svc-gw runs with `--allow-power` (the Orin's unit only), and when `boot_id` is not the current boot's |
|
||||||
|
| `reboot` | `confirm: "reboot"`, `boot_id` | the same, with `systemctl reboot`; the same flag and refusals |
|
||||||
|
|
||||||
A repeated `id` returns the original `ack` (last 256 kept, shared across
|
A repeated `id` returns the original `ack` (last 256 kept, shared across
|
||||||
connections) and never re-runs the command.
|
connections) and never re-runs the command.
|
||||||
|
|
||||||
`poweroff` is the exception to retry-until-acked: the ack cache does not survive
|
`poweroff` and `reboot` are the exception to retry-until-acked: the ack cache does
|
||||||
the reboot it causes, so a resend could shut the next boot down too. The client
|
not survive the restart they cause, so a resend could shut the next boot down (or
|
||||||
sends it once and does not resend it; `boot_id` makes svc-gw refuse one from a
|
reboot it again). The client sends them once and does not resend; `boot_id` makes
|
||||||
previous boot regardless.
|
svc-gw refuse one from a previous boot regardless.
|
||||||
|
|
||||||
## Not yet
|
## Not yet
|
||||||
|
|
||||||
- TTS utterances (id, chunk sequence, terminator, expiry) — when there is a TTS.
|
- TTS utterances (id, chunk sequence, terminator, expiry) — when there is a TTS.
|
||||||
- `gnss`: its fix is an object, which the envelope's `value` does not allow yet.
|
- `gnss/fix` as one object (navigation's input): the envelope's `value` does not allow
|
||||||
|
one yet. Displays get the fix as single values on `yukart/gnss/<signal>` instead.
|
||||||
- Any version beyond `proto: 0`. A breaking change bumps it; the client checks it.
|
- Any version beyond `proto: 0`. A breaking change bumps it; the client checks it.
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ type: guidelines
|
|||||||
- ⚠ **The unit appears in both the topic name and the payload, so they can
|
- ⚠ **The unit appears in both the topic name and the payload, so they can
|
||||||
contradict each other.** Generating both from one entry is what stops that; a
|
contradict each other.** Generating both from one entry is what stops that; a
|
||||||
hand-written `"unit"` reintroduces the failure it was meant to prevent.
|
hand-written `"unit"` reintroduces the failure it was meant to prevent.
|
||||||
- Signal names carry their unit (`vehicle_speed_kph`, `coolant_temp_c`), so a unit
|
- Signal names carry their unit (`gnss_speed_kph`, `obd_coolant_temp_c`), so a unit
|
||||||
mismatch is visible at the call site rather than one registry lookup away.
|
mismatch is visible at the call site rather than one registry lookup away.
|
||||||
|
|
||||||
## 2. Two clocks, and they answer different questions
|
## 2. Two clocks, and they answer different questions
|
||||||
|
|||||||
+203
-81
@@ -1,6 +1,136 @@
|
|||||||
{
|
{
|
||||||
"$comment": "Single source for signal identity. Topic name and envelope unit are both derived from these entries and are never authored separately. source=obd2 is standardised; source=host is the Orin itself (orin-status), not the car. source=z27ag is reverse-engineered from the car's own broadcast frames, and its 'can' block is the only place its layout is written down: id (11-bit, hex string), byte (first data byte, 0-7), length in bits (1, 8 or 16), bit (length 1 only: 0 = LSB of that byte), order (length 16: big = byte first is most significant, little = the reverse), scale and offset (value = raw * scale + offset; booleans are raw != 0). 'evidence' names the contracts report that found it.",
|
"$comment": "Single source for signal identity. Topic name and envelope unit are both derived from these entries and are never authored separately. source=obd2 is standardised (OBD-II mode 01 over the K-line, through the ELM327): calibration references, every name prefixed obd_ (project-yukart decision 30); source=host is the Orin itself (orin-status), not the car. source=gnss is the receiver (svc-core gnss), on yukart/gnss/<signal>. source=z27ag is reverse-engineered from the car's own broadcast frames, and its 'can' block is the only place its layout is written down: id (11-bit, hex string), byte (first data byte, 0-7), length in bits (1, 8 or 16), bit (length 1 only: 0 = LSB of that byte), order (length 16: big = byte first is most significant, little = the reverse), scale and offset (value = raw * scale + offset; booleans are raw != 0). 'evidence' names the contracts report that found it.",
|
||||||
"signals": {
|
"signals": {
|
||||||
|
"obd_vehicle_speed_kph": {
|
||||||
|
"unit": "kph",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Road speed",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
255
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_coolant_temp_c": {
|
||||||
|
"unit": "celsius",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Engine coolant temperature",
|
||||||
|
"range": [
|
||||||
|
-40,
|
||||||
|
215
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_intake_air_temp_c": {
|
||||||
|
"unit": "celsius",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Intake air temperature",
|
||||||
|
"range": [
|
||||||
|
-40,
|
||||||
|
215
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_throttle_pct": {
|
||||||
|
"unit": "percent",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Throttle position",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_engine_load_pct": {
|
||||||
|
"unit": "percent",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Calculated engine load",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_fuel_level_pct": {
|
||||||
|
"unit": "percent",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Fuel tank level",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_intake_pressure_kpa": {
|
||||||
|
"unit": "kpa",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Intake manifold absolute pressure",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
255
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_maf_gps": {
|
||||||
|
"unit": "g/s",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Mass air flow rate",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
656
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_engine_rpm": {
|
||||||
|
"unit": "rpm",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Engine speed (OBD-II 0C): the reference for the decoded engine_rpm",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
8000
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_timing_advance_deg": {
|
||||||
|
"unit": "degree",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Ignition timing advance before TDC, cylinder 1",
|
||||||
|
"range": [
|
||||||
|
-64,
|
||||||
|
64
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_stft_pct": {
|
||||||
|
"unit": "percent",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Short-term fuel trim, bank 1: positive adds fuel",
|
||||||
|
"range": [
|
||||||
|
-100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_ltft_pct": {
|
||||||
|
"unit": "percent",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Long-term fuel trim, bank 1: positive adds fuel",
|
||||||
|
"range": [
|
||||||
|
-100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"obd_o2_b1s1_v": {
|
||||||
|
"unit": "V",
|
||||||
|
"type": "number",
|
||||||
|
"source": "obd2",
|
||||||
|
"description": "Upstream oxygen sensor voltage (narrowband: ~0.1 lean … ~0.9 rich)",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
1.275
|
||||||
|
]
|
||||||
|
},
|
||||||
"engine_rpm": {
|
"engine_rpm": {
|
||||||
"unit": "rpm",
|
"unit": "rpm",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@@ -20,86 +150,6 @@
|
|||||||
"evidence": "Z27AG-DECODE-1"
|
"evidence": "Z27AG-DECODE-1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicle_speed_kph": {
|
|
||||||
"unit": "kph",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Road speed",
|
|
||||||
"range": [
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"coolant_temp_c": {
|
|
||||||
"unit": "celsius",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Engine coolant temperature",
|
|
||||||
"range": [
|
|
||||||
-40,
|
|
||||||
215
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"intake_air_temp_c": {
|
|
||||||
"unit": "celsius",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Intake air temperature",
|
|
||||||
"range": [
|
|
||||||
-40,
|
|
||||||
215
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"throttle_pct": {
|
|
||||||
"unit": "percent",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Throttle position",
|
|
||||||
"range": [
|
|
||||||
0,
|
|
||||||
100
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"engine_load_pct": {
|
|
||||||
"unit": "percent",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Calculated engine load",
|
|
||||||
"range": [
|
|
||||||
0,
|
|
||||||
100
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"fuel_level_pct": {
|
|
||||||
"unit": "percent",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Fuel tank level",
|
|
||||||
"range": [
|
|
||||||
0,
|
|
||||||
100
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"intake_pressure_kpa": {
|
|
||||||
"unit": "kpa",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Intake manifold absolute pressure",
|
|
||||||
"range": [
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"maf_gps": {
|
|
||||||
"unit": "g/s",
|
|
||||||
"type": "number",
|
|
||||||
"source": "obd2",
|
|
||||||
"description": "Mass air flow rate",
|
|
||||||
"range": [
|
|
||||||
0,
|
|
||||||
656
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"accel_pedal_pct": {
|
"accel_pedal_pct": {
|
||||||
"unit": "percent",
|
"unit": "percent",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@@ -477,6 +527,12 @@
|
|||||||
10000
|
10000
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"elm_connected": {
|
||||||
|
"unit": "",
|
||||||
|
"type": "boolean",
|
||||||
|
"source": "host",
|
||||||
|
"description": "Bluetooth link to the OBD-II adapter (the ELM327 on the K-line) is up: obd-poller holds it while the ECU answers"
|
||||||
|
},
|
||||||
"ups_battery_v": {
|
"ups_battery_v": {
|
||||||
"unit": "V",
|
"unit": "V",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@@ -512,6 +568,72 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"source": "host",
|
"source": "host",
|
||||||
"description": "charging, discharging (running on battery) or idle (on input power, not charging)"
|
"description": "charging, discharging (running on battery) or idle (on input power, not charging)"
|
||||||
|
},
|
||||||
|
"gnss_fix": {
|
||||||
|
"unit": "",
|
||||||
|
"type": "string",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Fix quality: none, 2d or 3d (gpsd TPV mode)"
|
||||||
|
},
|
||||||
|
"gnss_speed_kph": {
|
||||||
|
"unit": "kph",
|
||||||
|
"type": "number",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Speed over ground; null without a fix",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
300
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gnss_heading_deg": {
|
||||||
|
"unit": "degree",
|
||||||
|
"type": "number",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Course over ground, true north; null without a fix or at a standstill",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
360
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gnss_lat": {
|
||||||
|
"unit": "degree",
|
||||||
|
"type": "number",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Latitude, WGS84",
|
||||||
|
"range": [
|
||||||
|
-90,
|
||||||
|
90
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gnss_lon": {
|
||||||
|
"unit": "degree",
|
||||||
|
"type": "number",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Longitude, WGS84",
|
||||||
|
"range": [
|
||||||
|
-180,
|
||||||
|
180
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gnss_alt_m": {
|
||||||
|
"unit": "m",
|
||||||
|
"type": "number",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Altitude above mean sea level; null without a 3D fix",
|
||||||
|
"range": [
|
||||||
|
-500,
|
||||||
|
9000
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gnss_satellites": {
|
||||||
|
"unit": "",
|
||||||
|
"type": "number",
|
||||||
|
"source": "gnss",
|
||||||
|
"description": "Satellites used in the fix",
|
||||||
|
"range": [
|
||||||
|
0,
|
||||||
|
64
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -12,7 +12,7 @@
|
|||||||
"payload": "envelope",
|
"payload": "envelope",
|
||||||
"retained": true,
|
"retained": true,
|
||||||
"rate": "1-50/s",
|
"rate": "1-50/s",
|
||||||
"publisher": "decoder, obd-poller",
|
"publisher": "decoder (source z27ag), obd-poller (source obd2)",
|
||||||
"description": "One topic per signal, named exactly as in signals.json."
|
"description": "One topic per signal, named exactly as in signals.json."
|
||||||
},
|
},
|
||||||
"yukart/gnss/fix": {
|
"yukart/gnss/fix": {
|
||||||
@@ -22,6 +22,13 @@
|
|||||||
"publisher": "gnss",
|
"publisher": "gnss",
|
||||||
"description": "value is an object: lat, lon, alt_m, speed_kph, heading_deg, fix, satellites."
|
"description": "value is an object: lat, lon, alt_m, speed_kph, heading_deg, fix, satellites."
|
||||||
},
|
},
|
||||||
|
"yukart/gnss/<signal>": {
|
||||||
|
"payload": "envelope",
|
||||||
|
"retained": true,
|
||||||
|
"rate": "1-10/s",
|
||||||
|
"publisher": "gnss",
|
||||||
|
"description": "The receiver's fix as single values, one topic per signal, named exactly as in signals.json (source=gnss). For displays; yukart/gnss/fix stays the composite for navigation."
|
||||||
|
},
|
||||||
"yukart/host/<signal>": {
|
"yukart/host/<signal>": {
|
||||||
"payload": "envelope",
|
"payload": "envelope",
|
||||||
"retained": true,
|
"retained": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user