From ce7dbbd43dec02b5f3e8033333a479b49c6c2c25 Mon Sep 17 00:00:00 2001 From: dirkwa Date: Thu, 6 Aug 2026 14:34:19 +1200 Subject: [PATCH] =?UTF-8?q?feat(propulsion):=20engine=20diagnostics=20grou?= =?UTF-8?q?p=20=E2=80=94=20fault=20lamps=20and=20trouble=20codes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Engine controllers report structured diagnostics that had no home in the spec: the four standard fault lamps (malfunction, red stop, amber warning, protect) and the list of active diagnostic trouble codes identified by SPN and FMI (e.g. J1939 DM1). Engine measurements were already covered by the existing propulsion paths; this adds only the diagnostics surface, with the alerting side left to the notifications tree. --- schemas/groups/propulsion.json | 103 ++++++++++++++++++ test/data/vessel-valid/propulsion-sample.json | 90 ++++++++++----- 2 files changed, 167 insertions(+), 26 deletions(-) diff --git a/schemas/groups/propulsion.json b/schemas/groups/propulsion.json index b0770ad40..fa9a14a1a 100644 --- a/schemas/groups/propulsion.json +++ b/schemas/groups/propulsion.json @@ -220,6 +220,109 @@ "description": "Exhaust temperature", "$ref": "../definitions.json#/definitions/numberValue", "units": "K" + }, + "diagnostics": { + "type": "object", + "description": "Diagnostics reported by the engine controller: fault lamp states and active diagnostic trouble codes (e.g. J1939 DM1)", + "properties": { + "malfunctionLamp": { + "type": "object", + "description": "Malfunction indicator lamp (emissions-related fault). True when the lamp is commanded on, steady or flashing", + "allOf": [ + { + "$ref": "../definitions.json#/definitions/commonValueFields" + }, + { + "properties": { + "value": { + "type": "boolean" + } + } + } + ] + }, + "redStopLamp": { + "type": "object", + "description": "Red stop lamp (fault severe enough to stop the engine). True when the lamp is commanded on, steady or flashing", + "allOf": [ + { + "$ref": "../definitions.json#/definitions/commonValueFields" + }, + { + "properties": { + "value": { + "type": "boolean" + } + } + } + ] + }, + "amberWarningLamp": { + "type": "object", + "description": "Amber warning lamp (fault that does not require an immediate stop). True when the lamp is commanded on, steady or flashing", + "allOf": [ + { + "$ref": "../definitions.json#/definitions/commonValueFields" + }, + { + "properties": { + "value": { + "type": "boolean" + } + } + } + ] + }, + "protectLamp": { + "type": "object", + "description": "Protect lamp (problem with an engine system, e.g. high coolant temperature). True when the lamp is commanded on, steady or flashing", + "allOf": [ + { + "$ref": "../definitions.json#/definitions/commonValueFields" + }, + { + "properties": { + "value": { + "type": "boolean" + } + } + } + ] + }, + "activeCodes": { + "type": "object", + "description": "Active diagnostic trouble codes. Each entry identifies the faulting parameter (SPN), the failure mode (FMI) and how often it has occurred", + "allOf": [ + { + "$ref": "../definitions.json#/definitions/commonValueFields" + }, + { + "properties": { + "value": { + "type": "array", + "items": { + "type": "object", + "properties": { + "spn": { + "type": "number", + "description": "Suspect Parameter Number identifying the faulting parameter" + }, + "fmi": { + "type": "number", + "description": "Failure Mode Identifier describing how the parameter failed" + }, + "occurrenceCount": { + "type": "number", + "description": "How many times this fault has occurred" + } + } + } + } + } + } + ] + } + } } } } diff --git a/test/data/vessel-valid/propulsion-sample.json b/test/data/vessel-valid/propulsion-sample.json index 05ced5db9..bb0d59612 100644 --- a/test/data/vessel-valid/propulsion-sample.json +++ b/test/data/vessel-valid/propulsion-sample.json @@ -42,7 +42,6 @@ "value": 1100, "timestamp": "2014-08-15T19:00:15.402Z", "$source": "foo.bar" - } }, "state": { @@ -59,29 +58,37 @@ "units": "Hz", "displayName": "Tachometer", "shortName": "RPM", - "warnMethod": ["visual"], - "alarmMethod": ["sound"], - "zones": [{ - "upper": 8, - "state": "warn", - "message": "Engine stopped or rpm very slow!" - }, { - "lower": 50, - "upper": 58.33333333333, - "state": "warn", - "message": "Engine near maximum rpm!" - }, { - "lower": 58.33333333333, - "upper": 66.66666666666667, - "state": "alarm", - "message": "Engine exceeds maximum rpm!" - }, { - "lower": 66.66666666666667, - "state": "alarm", - "message": "Engine exceeds maximum rpm!" - }] + "warnMethod": [ + "visual" + ], + "alarmMethod": [ + "sound" + ], + "zones": [ + { + "upper": 8, + "state": "warn", + "message": "Engine stopped or rpm very slow!" + }, + { + "lower": 50, + "upper": 58.33333333333, + "state": "warn", + "message": "Engine near maximum rpm!" + }, + { + "lower": 58.33333333333, + "upper": 66.66666666666667, + "state": "alarm", + "message": "Engine exceeds maximum rpm!" + }, + { + "lower": 66.66666666666667, + "state": "alarm", + "message": "Engine exceeds maximum rpm!" + } + ] } - }, "oilPressure": { "value": 110, @@ -102,13 +109,11 @@ "value": 200, "timestamp": "2014-08-15T19:00:15.402Z", "$source": "foo.bar" - }, "engineTorque": { "value": 200, "timestamp": "2014-08-15T19:00:15.402Z", "$source": "foo.bar" - }, "oilTemperature": { "value": 345, @@ -156,7 +161,40 @@ "timestamp": "2014-08-15T19:00:15.402Z", "$source": "foo.bar" } + }, + "diagnostics": { + "malfunctionLamp": { + "value": false, + "timestamp": "2014-08-15T19:00:15.402Z", + "$source": "foo.bar" + }, + "redStopLamp": { + "value": true, + "timestamp": "2014-08-15T19:00:15.402Z", + "$source": "foo.bar" + }, + "amberWarningLamp": { + "value": false, + "timestamp": "2014-08-15T19:00:15.402Z", + "$source": "foo.bar" + }, + "protectLamp": { + "value": false, + "timestamp": "2014-08-15T19:00:15.402Z", + "$source": "foo.bar" + }, + "activeCodes": { + "value": [ + { + "spn": 100, + "fmi": 1, + "occurrenceCount": 3 + } + ], + "timestamp": "2014-08-15T19:00:15.402Z", + "$source": "foo.bar" + } } } } -} +} \ No newline at end of file