-
Notifications
You must be signed in to change notification settings - Fork 72
Description
Summary V3 (Updated to incorporate comments/findings from @panaaj and @TwoCanPlugIn )
Summary
Introduce a unified notification path structure based on maritime safety categories (distress, urgency, safety) that applies consistently across all vessel contexts. This replaces the current flat top-level notification names with a categorized hierarchy and enables transport-agnostic handling of alerts from DSC, AIS Safety Messages, and future sources.
Related issues
- VHF DSC Calls #209 — VHF DSC Calls (2016, @tkurki): Requested explicit schema handling for incoming VHF DSC calls. PGN 129808 was identified as the relevant N2K message. @timmathews noted that DSC calls should create vessel entries and generate alerts.
- Add data attribute to Alarm object used in Notification messages #655 — Add data attribute to Alarm object (2023, @panaaj): Proposes an optional
dataattribute for structured alarm data (e.g. MOB position). Thenotifications.mob.<MMSI>pattern used by @bergie in signalk-mob-notifier demonstrates real-world need for per-source notification keying. - Examples for alarm notifications do not reflect the specification #668 — Examples for alarm notifications do not reflect the specification (2025, @ArjenR): Reports that the spec says
notifications.mob.<key>but examples shownotifications.mobwithout a key, causing incompatibility between FreeboardSK and KIP. - DSC Distress Alerts nmea0183-signalk#217 — DSC Distress Alerts (2022, @TwoCanPlugIn): Reports that DSC/DSE parsing is broken. Comprehensive ITU/NMEA documentation for DSC field parsing was provided. As of September 2025, users still report inability to generate Signal K paths from DSC sentences.
- Add Basic support for DSC Position and Distress Sentences nmea0183-signalk#66 — Add Basic support for DSC Position and Distress Sentences (2016, @ph1l): The original DSC codec. Notably, this implementation already writes to the vessel context of the calling MMSI, not
vessels.self.
Motivation
The ambiguity problem
The current specification defines 10 flat well-known notification paths (notifications.mob, notifications.fire, etc.) without distinguishing what kind of condition they represent or whose vessel they describe. A notifications.fire could mean:
- An onboard fire sensor detected fire on this vessel (life-threatening emergency)
- A DSC distress relay was received reporting fire on another vessel (informational)
- An NMEA ALR alarm from a connected device
These are fundamentally different situations requiring different responses.
The asymmetry problem
Signal K already stores received data from other vessels under their own context — AIS position from vessel 211457160 goes to vessels.211457160.navigation.position, not to vessels.self. Notifications should follow the same principle: a DSC distress from vessel 211457160 belongs under vessels.211457160.notifications.*, not under vessels.self.notifications.*.
But if external alerts use a categorized structure (notifications.distress.fire) while own-vessel alerts use a flat structure (notifications.fire), the notification tree is inconsistent across vessel contexts. There is no reason for this asymmetry other than backwards compatibility.
Maritime safety categories are universal
The categories distress, urgency, and safety are not DSC-specific — they are fundamental maritime safety categories defined by SOLAS and ITU, used across all maritime communication systems:
| Category | Severity | Description | Alarm State |
|---|---|---|---|
| Distress | Highest | Life-threatening emergency (fire, sinking, MOB...) | emergency |
| Urgency | High | Requires immediate attention, not life-threatening | alarm |
| Safety | Medium | Navigational or meteorological warning | warn |
These categories apply regardless of the source: a fire is a distress condition whether detected by an onboard sensor, received via DSC, reported through AIS, or relayed over LoRa. The transport is metadata ($source), not part of the path.
Current implementation issues
The nmea0183-signalk DSC parser (see #217, #66):
- Only distress calls (category 12) generate notifications — urgency (10) and safety (08) are ignored
- Notification values are incomplete — missing the required
stateandmethodfields - Parser is broken — as of 2025, DSC/DSE sentences fail to generate Signal K nodes at all
- Already uses vessel context — the existing DSC codec writes to the calling vessel's MMSI context, not
vessels.self
Proposal
Unified notification categories
Replace the flat top-level notification names with categorized branches that apply identically to all vessel contexts — own vessel (self) and others:
vessels.{any}.notifications.distress.* — Life-threatening emergencies
vessels.{any}.notifications.urgency.* — Urgent, non-life-threatening
vessels.{any}.notifications.safety.* — Navigational/meteorological warnings
The path expresses what the condition is. The vessel context expresses whose vessel is affected. The $source field expresses how the information was received (DSC, AIS, onboard sensor, NMEA ALR, LoRa, etc.).
Distress sub-paths
Distress notifications use sub-paths corresponding to the ITU nature-of-distress codes:
notifications.distress.fire — Fire/Explosion (code 00)
notifications.distress.flooding — Flooding (code 01)
notifications.distress.collision — Collision (code 02)
notifications.distress.grounding — Grounding (code 03)
notifications.distress.listing — Listing/Capsizing (code 04)
notifications.distress.sinking — Sinking (code 05)
notifications.distress.adrift — Adrift (code 06)
notifications.distress.undesignated — Undesignated (code 07)
notifications.distress.abandon — Abandon ship (code 08)
notifications.distress.piracy — Piracy/Armed attack (code 09)
notifications.distress.mob — Man overboard (code 10)
notifications.distress.epirb — EPIRB emission (code 12)
Urgency and safety use descriptive sub-paths:
notifications.urgency.{description}
notifications.safety.{description}
Full path examples
| Scenario | Path | Context | Source |
|---|---|---|---|
| Own vessel fire alarm (onboard sensor) | notifications.distress.fire |
vessels.self |
onboard sensor |
| Own vessel MOB button pressed | notifications.distress.mob |
vessels.self |
manual input |
| DSC Distress: fire from MMSI 211457160 | notifications.distress.fire |
vessels.urn:mrn:imo:mmsi:211457160 |
nmea0183.DSC |
| DSC Distress Relay: fire, orig. vessel 211457160 | notifications.distress.fire |
vessels.urn:mrn:imo:mmsi:211457160 |
nmea0183.DSC |
| DSC Urgency from MMSI 305000001 | notifications.urgency.medicalAssistance |
vessels.urn:mrn:imo:mmsi:305000001 |
nmea0183.DSC |
| AIS Safety Broadcast from MMSI 002111240 | notifications.safety.broadcast |
vessels.urn:mrn:imo:mmsi:002111240 |
nmea0183.VDM |
| AIS Addressed Safety Msg to own vessel | notifications.safety.addressed |
vessels.urn:mrn:imo:mmsi:002111240 |
nmea0183.VDM |
| NMEA ALR depth alarm on own vessel | notifications.safety.depth |
vessels.self |
nmea0183.ALR |
| Anchor drag alarm (zone-based) | notifications.navigation.anchor.currentRadius |
vessels.self |
zone monitor |
Note: zone-based operational alarms (anchor, depth via meta.zones, etc.) continue to use the existing mirrored-path convention (notifications.navigation.anchor.currentRadius). The distress/urgency/safety branches are for categorical emergency/alert conditions, not for zone-derived alarms.
Notification value format
All notifications must include the required fields per the existing spec:
{
"value": {
"message": "Distress: Fire/Explosion",
"state": "emergency",
"method": ["visual", "sound"]
},
"timestamp": "2024-01-15T14:30:00Z",
"$source": "nmea0183.DSC"
}Recommended state values per category:
- Distress:
"emergency" - Urgency:
"alarm" - Safety:
"warn"
Delta examples
Own vessel — fire detected by onboard sensor:
{
"context": "vessels.self",
"updates": [{
"source": { "label": "fire-detector", "type": "signalk" },
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.distress.fire",
"value": {
"message": "Fire detected in engine room",
"state": "emergency",
"method": ["visual", "sound"]
}
}]
}]
}DSC Distress — fire from another vessel:
{
"context": "vessels.urn:mrn:imo:mmsi:211457160",
"updates": [{
"source": {
"label": "nmea0183",
"type": "NMEA0183",
"talker": "",
"sentence": "DSC"
},
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.distress.fire",
"value": {
"message": "Distress: Fire/Explosion at 54.3000N, 10.5000E",
"state": "emergency",
"method": ["visual", "sound"]
}
}]
}]
}AIS Safety Broadcast:
{
"context": "vessels.urn:mrn:imo:mmsi:002111240",
"updates": [{
"source": {
"label": "nmea0183",
"type": "NMEA0183",
"talker": "AI",
"sentence": "VDM"
},
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.safety.broadcast",
"value": {
"message": "Uncharted rock reported at 54.12N 010.34E",
"state": "warn",
"method": ["visual"]
}
}]
}]
}DSC Urgency call:
{
"context": "vessels.urn:mrn:imo:mmsi:305000001",
"updates": [{
"source": {
"label": "nmea0183",
"type": "NMEA0183",
"talker": "",
"sentence": "DSC"
},
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.urgency.medicalAssistance",
"value": {
"message": "Urgency: Medical assistance required",
"state": "alarm",
"method": ["visual", "sound"]
}
}]
}]
}Routine calls (category 00)
Routine DSC calls do not generate notifications. They represent normal radio call requests and only update vessel position data if available.
DSC Distress vs. Distress Relay
A DSC Distress call (Format Specifier 12) is sent directly by the vessel in distress — the Category field is empty because distress is implied. A DSC Distress Relay (Format Specifier 16/All Ships, Category 12) is retransmitted by a third vessel (or coast station). Both cases produce the same Signal K path under the context of the vessel in distress. The distinction is captured in $source and is a parser-level concern, not a path-level concern.
The vessel-context model handles relays cleanly: regardless of whether a distress call is received directly or via one or more relays, it produces a single entry under the distressed vessel's context. If the same distress is received multiple times (direct call, then coast station relay, then another vessel's relay), each reception updates the same path with a new timestamp and $source. Signal K's native multi-source support means all sources are preserved, while the notification remains a single entry — no duplicates, no overwriting confusion.
| Reception | Path | Context | $source |
|---|---|---|---|
| Direct from vessel A | notifications.distress.fire |
vessels.urn:mrn:imo:mmsi:211457160 |
nmea0183.DSC |
| Relayed by coast station | notifications.distress.fire |
vessels.urn:mrn:imo:mmsi:211457160 |
nmea0183.DSC |
| Via AIS Safety Broadcast | notifications.distress.fire |
vessels.urn:mrn:imo:mmsi:211457160 |
nmea0183.VDM |
The alarm manager triggers on the first reception. Subsequent receptions confirm the distress but do not raise additional alarms.
Notification Manager integration
Signal K Server's recently released Notifications API already provides the infrastructure this RFC requires. The API introduces an Input Handler that intercepts all incoming deltas whose path starts with notifications and routes them to a centralized Notification Manager. The Notification Manager enriches notifications with a unique id and a status object before emitting them to clients.
This pipeline works naturally with the unified model: a DSC distress delta with context vessels.urn:mrn:imo:mmsi:211457160 and path notifications.distress.fire has a path starting with notifications, so the Input Handler routes it to the Notification Manager like any other notification.
Alarm lifecycle for distress/urgency/safety
The Notifications API's status attributes map directly to the semantics of received external alerts:
| Attribute | Distress (emergency) |
Urgency (alarm) |
Safety (warn) |
|---|---|---|---|
canSilence |
false (API already enforces: emergency cannot be silenced) |
true |
true |
canAcknowledge |
true (operator confirms awareness) |
true |
true |
canClear |
false (API already enforces: external notifications cannot be cleared) |
false |
false |
This means the Notification Manager already handles the two critical constraints for received alerts: distress notifications cannot be silenced, and externally received notifications cannot be cleared by the operator (the condition exists on another vessel).
Cross-vessel notification awareness
Storing notifications under each vessel's own context means the Notification Manager must process notifications from all vessel contexts, not just vessels.self. Since the Input Handler already intercepts based on path prefix (notifications), this requires extending it to trigger operator alerts (visual/sound) for state: emergency or state: alarm notifications regardless of which vessel context they belong to.
This makes the alarm system severity-aware and transport-agnostic: a state: emergency notification triggers the alarm whether it originates from an onboard sensor, a DSC call, an AIS Safety Message, or a future LoRa source. The path tells the operator what happened, the vessel context tells them who is affected, $source tells them how the information was received.
Schema changes
New dscBranch definition
The existing notificationBranch definition uses a negative-lookahead regex that excludes the well-known names (mob, fire, sinking, etc.) at all nesting levels. This means notifications.distress.fire would be rejected — fire is blocked by the regex even inside distress.
A new dscBranch definition in notifications.json explicitly lists the nature-of-distress names as properties (allowing fire, mob, etc. as sub-paths) and also permits arbitrary additional sub-paths via patternProperties.
Files modified
schemas/groups/notifications.json:- Add
distress,urgency,safetyto the negative-lookahead regex innotificationBranch - Add new
dscBranchdefinition with well-known nature-of-distress properties plusundesignatedandepirb
- Add
schemas/vessel.json— Adddistress,urgency,safetyas well-known properties referencingdscBranch, update the regexschemas/sar.json— Same as vessel.jsonschemas/aircraft.json— Add properties block withdistress,urgency,safetyreferencingdscBranch, update the regexschemas/aton.json— Same as aircraft.jsonmdbook/src/notifications.md— Document the unified model and DSC semantics
Backward compatibility
Non-breaking additions
The distress, urgency, and safety branches are new well-known names. The existing notificationBranch pattern already allows arbitrary nesting, so paths like notifications.distress.fire are valid today under the generic pattern. This RFC formalizes them as explicit schema properties.
Deprecation of flat top-level names
The existing flat paths (notifications.fire, notifications.mob, etc.) become deprecated in favour of their categorized equivalents (notifications.distress.fire, notifications.distress.mob, etc.). They should remain valid in the schema during a transition period but should no longer be used by new implementations.
The notifications.nmea.* path is currently used by n2k-signalk for NMEA2000 alarm PGNs (e.g. notifications.nmea.alarm.navigational.20.8196). This is a transport-based path — the nmea segment identifies how the alarm arrived, not what it describes. In the unified model, the same alarm would go to a category-based path (e.g. notifications.safety.navigation) with $source identifying the N2K origin. The existing notifications.nmea.* paths should remain valid during the transition period and continue to be processed by the Notification Manager.
Migration path
- New parser implementations write to
notifications.distress.*/notifications.urgency.*/notifications.safety.*under the appropriate vessel context - Existing top-level names remain valid but are marked deprecated in the spec documentation
- Server alarm managers are extended to watch
vessels.*.notifications.distress.*andvessels.*.notifications.urgency.* - A future spec version may remove the flat top-level names
Interaction with other proposals
#655 — data attribute for alarm objects
This RFC is complementary. The data attribute proposal would allow structured fields (position, MMSI) in the notification value, while this RFC addresses path structure and vessel context. Both can be adopted independently:
- Without
dataattribute: details go in themessagestring - With
dataattribute:{ "message": "Distress: Fire", "state": "emergency", "method": ["visual", "sound"], "data": { "position": { "latitude": 54.3, "longitude": 10.5 } } }
#668 — Notification path structure
The spec says notifications.mob.* but examples show notifications.mob. This RFC resolves the ambiguity: notifications.distress.mob is the leaf notification, and multiple concurrent MOBs from different vessels naturally exist as separate entries under different vessel contexts.
#378 — Notification Acknowledgements
The Notifications API already implements acknowledgement and silence actions via REST endpoints (/signalk/v2/api/notifications/{id}/acknowledge, /silence). The unified model is fully compatible: all notifications follow the same structure regardless of source, and the status attributes correctly restrict actions for external emergency notifications (cannot silence, cannot clear).
Notifications API (Signal K Server)
The recently released Notifications API introduces a Notification Manager with an Input Handler that intercepts all notification deltas. This RFC builds on that infrastructure rather than replacing it. The Notification Manager's id and status enrichment, action endpoints, and NMEA2000 alert handling all work with the categorized paths proposed here. The planned "raising specified alarms i.e. MOB" feature in the API's target state aligns with the well-known distress sub-paths (notifications.distress.mob, notifications.distress.fire, etc.).
Open questions
-
Structured data: Should the notification value object be extended with optional fields (position, nature-of-distress code) beyond the
messagestring? Or should this be deferred to thedataattribute proposal (Add data attribute to Alarm object used in Notification messages #655)? Currently, position and details are embedded in the human-readablemessagestring. A UI that wants to plot the distress position on a chart would need to parse that string. A structureddataobject would make this machine-readable, but increases the scope of this RFC. -
Cross-vessel notification awareness: The Notifications API's Input Handler currently intercepts notification deltas for processing by the Notification Manager. Should the Notification Manager be extended to trigger operator alerts for
state: emergencyandstate: alarmnotifications across all vessel contexts, not justvessels.self? This is the key enabler for the unified model — without it, received distress calls would be stored correctly but not raise alarms.
Previous Versions
Old/Original RFC
## SummaryAdd well-known notification paths for Digital Selective Calling (DSC) categories under notifications.distress.*, notifications.urgency.*, and notifications.safety.* to separate externally received DSC alerts from own-vessel alarm conditions.
Related issues
This RFC addresses several open issues across the Signal K ecosystem:
- VHF DSC Calls #209 — VHF DSC Calls (2016, @tkurki): Requested explicit schema handling for incoming VHF DSC calls. PGN 129808 was identified as the relevant N2K message. @timmathews noted that DSC calls should create vessel entries and generate alerts. This RFC provides the notification path structure that was missing.
- Add data attribute to Alarm object used in Notification messages #655 — Add data attribute to Alarm object (2023, @panaaj): Proposes an optional
dataattribute for structured alarm data (e.g. MOB position). Thenotifications.mob.<MMSI>pattern used by @bergie in signalk-mob-notifier demonstrates real-world need for per-source notification keying. This RFC'snotifications.distress.mobpath is compatible with this approach (e.g.notifications.distress.mob.<MMSI>for multiple concurrent MOBs). - Examples for alarm notifications do not reflect the specification #668 — Examples for alarm notifications do not reflect the specification (2025, @ArjenR): Reports that the spec says
notifications.mob.<key>but examples shownotifications.mobwithout a key, causing incompatibility between FreeboardSK and KIP. This RFC clarifies the path semantics and provides consistent examples. - DSC Distress Alerts nmea0183-signalk#217 — DSC Distress Alerts (2022, @TwoCanPlugIn): Reports that DSC/DSE parsing is broken. @TwoCanPlugIn provided comprehensive ITU/NMEA documentation for DSC field parsing. As of September 2025, users still report inability to generate Signal K paths from DSC sentences. This RFC provides the target paths that the parser should produce.
- Add Basic support for DSC Position and Distress Sentences nmea0183-signalk#66 — Add Basic support for DSC Position and Distress Sentences (2016, @ph1l): The original DSC codec that was merged. This is the implementation that currently writes to the top-level notification paths without
state/methodfields.
Motivation
The current Signal K specification defines 10 well-known notification paths for emergencies:
notifications.mob,notifications.fire,notifications.sinking,notifications.floodingnotifications.collision,notifications.grounding,notifications.listing,notifications.adriftnotifications.piracy,notifications.abandon
These paths are used for own-vessel conditions (e.g. an onboard fire sensor triggers notifications.fire). However, the same paths are also used by DSC implementations (e.g. signalk-parser-nmea0183) for distress calls received from other vessels.
This creates ambiguity: a notifications.fire could mean "my ship is on fire" (onboard sensor) or "I received a DSC distress relay reporting fire on another vessel". These are fundamentally different situations requiring different responses.
Current DSC implementation issues
Looking at the nmea0183-signalk DSC parser (see nmea0183-signalk#217, #66):
- Only distress calls (category 12) generate notifications — urgency (10) and safety (08) are ignored
- Notification values are incomplete — they contain a
messagebut are missing the requiredstateandmethodfields per the spec - Path collision — DSC distress relays from other vessels use the same top-level paths as own-vessel alarms
- Parser is broken — As of 2025, DSC/DSE sentences fail to generate Signal K nodes at all (nmea0183-signalk#217)
DSC categories and their semantics
| Category | Name | Description | Alarm State |
|---|---|---|---|
| 12 | Distress | Life-threatening emergency (fire, sinking, MOB...) | emergency |
| 10 | Urgency | Requires immediate attention, not life-threatening | alarm |
| 08 | Safety | Navigational or meteorological warning | warn |
| 00 | Routine | Normal radio call request | n/a |
Nature of distress codes (category 12 only)
| Code | Nature | Proposed path suffix |
|---|---|---|
| 00 | Fire/Explosion | fire |
| 01 | Flooding | flooding |
| 02 | Collision | collision |
| 03 | Grounding | grounding |
| 04 | Listing/Capsizing | listing |
| 05 | Sinking | sinking |
| 06 | Adrift | adrift |
| 07 | Undesignated | undesignated |
| 08 | Abandon ship | abandon |
| 09 | Piracy | piracy |
| 10 | Man overboard | mob |
| 12 | EPIRB emission | epirb |
Proposal
New well-known notification branches
Add three new well-known notification branches:
| Path | Type | Description |
|---|---|---|
notifications.distress.* |
branch | Distress notifications received via DSC (category 12) |
notifications.urgency.* |
branch | Urgency notifications received via DSC (category 10) |
notifications.safety.* |
branch | Safety notifications received via DSC (category 08) |
Path structure
Distress notifications use sub-paths matching the nature of distress:
notifications.distress.fire — Fire/Explosion
notifications.distress.flooding — Flooding
notifications.distress.collision — Collision
notifications.distress.grounding — Grounding
notifications.distress.listing — Listing/Capsizing
notifications.distress.sinking — Sinking
notifications.distress.adrift — Adrift
notifications.distress.undesignated — Undesignated distress
notifications.distress.abandon — Abandon ship
notifications.distress.piracy — Piracy/Armed attack
notifications.distress.mob — Man overboard
notifications.distress.epirb — EPIRB emission
Urgency and safety use a descriptive sub-path:
notifications.urgency.{description}
notifications.safety.{description}
Notification value format
All DSC notifications must include the required fields per the existing spec:
{
"value": {
"message": "Distress: Fire/Explosion from MMSI 211457160 at 54.3000N, 10.5000E",
"state": "emergency",
"method": ["visual", "sound"]
},
"timestamp": "2024-01-15T14:30:00Z",
"$source": "nmea0183.DSC"
}Recommended state values per DSC category:
- Distress (12):
"emergency" - Urgency (10):
"alarm" - Safety (08):
"warn"
Semantic separation
| Path | Meaning |
|---|---|
notifications.fire |
Own vessel: fire detected by onboard sensor |
notifications.distress.fire |
Received DSC: another vessel reports fire |
This separation allows:
- UI applications to subscribe to
notifications.distress.*and display incoming DSC calls (e.g. position on chart) - Alarm systems to use
notifications.fireetc. exclusively for own-vessel conditions - No collision between local and external alarm sources
Delta examples
DSC Distress — Fire/Explosion from another vessel:
{
"context": "vessels.urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
"updates": [{
"source": {
"label": "nmea0183",
"type": "NMEA0183",
"talker": "",
"sentence": "DSC"
},
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.distress.fire",
"value": {
"message": "Distress: Fire/Explosion from MMSI 211457160 at 54.3000N, 10.5000E",
"state": "emergency",
"method": ["visual", "sound"]
}
}]
}]
}DSC Urgency call:
{
"context": "vessels.urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
"updates": [{
"source": {
"label": "nmea0183",
"type": "NMEA0183",
"talker": "",
"sentence": "DSC"
},
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.urgency.medicalAssistance",
"value": {
"message": "Urgency: Medical assistance required, MMSI 211457160",
"state": "alarm",
"method": ["visual", "sound"]
}
}]
}]
}DSC Safety call:
{
"context": "vessels.urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
"updates": [{
"source": {
"label": "nmea0183",
"type": "NMEA0183",
"talker": "",
"sentence": "DSC"
},
"timestamp": "2024-01-15T14:30:00Z",
"values": [{
"path": "notifications.safety.navigationWarning",
"value": {
"message": "Safety: Navigational warning, MMSI 002111240",
"state": "warn",
"method": ["visual"]
}
}]
}]
}Routine calls (category 00)
Routine DSC calls do not generate notifications. They represent normal radio call requests and only update vessel position data if available.
Schema changes
New dscBranch definition
The existing notificationBranch definition uses a negative-lookahead regex that excludes the well-known names (mob, fire, sinking, etc.) at all nesting levels. This means notifications.distress.fire would be rejected — fire is blocked by the regex even inside distress.
To solve this, a new dscBranch definition is introduced in notifications.json. It explicitly lists the nature-of-distress names as properties (allowing fire, mob, etc. as sub-paths) and also permits arbitrary additional sub-paths via patternProperties.
Files modified
schemas/groups/notifications.json:- Add
distress,urgency,safetyto the negative-lookahead regex innotificationBranch - Add new
dscBranchdefinition with well-known nature-of-distress properties (fire,mob,sinking, etc.) plusundesignatedandepirb
- Add
schemas/vessel.json— Adddistress,urgency,safetyas well-known properties referencingdscBranch, update the regexschemas/sar.json— Same as vessel.jsonschemas/aircraft.json— Add properties block withdistress,urgency,safetyreferencingdscBranch, update the regexschemas/aton.json— Same as aircraft.jsonmdbook/src/notifications.md— Document the new paths and DSC semantics
Backward compatibility
- Non-breaking: The
notificationBranchpattern already allows arbitrary nesting, so paths likenotifications.distress.someCustomKeywork today. This RFC formalizes these paths as well-known and adds schema support for the nature-of-distress sub-paths. - Migration: Existing DSC implementations should transition from
notifications.fire(for received DSC) tonotifications.distress.fire. The top-level paths remain valid for own-vessel alarms.
Interaction with other proposals
#655 — data attribute for alarm objects
This RFC is complementary to #655. The data attribute proposal would allow structured fields (position, MMSI) in the notification value, while this RFC addresses the notification path structure. Both can be adopted independently:
- Without
dataattribute: MMSI and position go in themessagestring - With
dataattribute:{ "message": "Distress: Fire", "state": "emergency", "method": ["visual", "sound"], "data": { "mmsi": "211457160", "position": { "latitude": 54.3, "longitude": 10.5 } } }
#668 — Notification path structure (notifications.mob vs notifications.mob.<key>)
The spec documentation says notifications.mob.* (with wildcard), suggesting sub-keys. The dscBranch pattern used here (notifications.distress.fire) is consistent with this structure. For multiple concurrent distress calls of the same nature, an MMSI sub-key could be used: notifications.distress.fire.211457160 — similar to how @bergie uses notifications.mob.<MMSI> in signalk-mob-notifier.
#378 — Notification Acknowledgements
DSC distress notifications may need different acknowledgement semantics than own-vessel alarms (a received distress relay is informational, not a local condition to resolve). This should be considered when implementing #378.
Open questions
- MMSI in path: Should the MMSI of the calling vessel be included as a sub-key (e.g.
notifications.distress.fire.211457160) to allow multiple concurrent distress calls of the same nature? This mirrors thenotifications.mob.<MMSI>pattern from signalk-mob-notifier (Add data attribute to Alarm object used in Notification messages #655 discussion). Without MMSI sub-keys, a second distress call of the same nature would overwrite the first — only the most recent fire distress would be visible. With MMSI sub-keys, all concurrent distress calls coexist in the tree and can be subscribed to individually. - Structured data: Should the notification value object be extended with optional DSC-specific fields (MMSI, position, nature-of-distress code) beyond the
messagestring? Or should this wait for thedataattribute proposal (Add data attribute to Alarm object used in Notification messages #655)? Currently, MMSI and position are embedded in the human-readablemessagestring. A UI that wants to plot the distress position on a chart would need to parse that string. A structureddataobject would make this machine-readable, but increases the scope of this RFC. Alternatively, this could be deferred to Add data attribute to Alarm object used in Notification messages #655 which proposes the same mechanism for all notification types.