Decentralized Environmental Notification (DEN) Service

The DEN Service broadcasts hazard warnings to nearby vehicles using Decentralized Environmental Notification Messages (DENMs). While CAMs say “I’m here,” DENMs say “Watch out for this!”

Note

The DEN Service implements ETSI TS 103 831 V2.2.1 (2024-04). DENMs are event-driven messages that warn about road hazards, accidents, emergency vehicles, and other dangerous situations.

What DENMs Are For

DENMs alert drivers to hazardous situations:

Use Case

Description

🚑 Emergency Vehicle

Ambulance, fire truck, or police approaching

🚧 Road Hazard

Obstacle on road, slippery conditions, road works

💥 Accident

Collision ahead, stationary vehicle

⚠️ Dangerous Situation

Wrong-way driver, traffic jam end warning

🌧️ Weather

Fog, heavy rain, ice on road

CAM vs DENM

Aspect

CAM

DENM

Purpose

“I am here”

“Watch out for this”

Trigger

Periodic (time/position based)

Event-driven (hazard detected)

Lifetime

Single transmission

Persists until terminated

BTP Port

2001

2002

Architecture

The DEN Service consists of three components:

        flowchart TB
    subgraph "Application Layer"
        EVA[Emergency Vehicle<br/>Approaching Service]
        LCRW[Longitudinal Collision<br/>Risk Warning]
        APP[Other Applications]
    end

    subgraph "DEN Service"
        DEN[DEN Service]
        TM[Transmission<br/>Management]
        RM[Reception<br/>Management]
        COD[DEN Coder]
    end

    subgraph "Transport"
        BTP[BTP Router<br/>Port 2002]
    end

    subgraph "Optional"
        LDM[(Local Dynamic Map)]
    end

    EVA --> DEN
    LCRW --> DEN
    APP --> DEN
    DEN <--> TM
    DEN <--> RM
    DEN <--> COD
    DEN <-->|"Send/Receive"| BTP
    RM -.->|"Store"| LDM

    style DEN fill:#ffebee,stroke:#c62828
    style EVA fill:#fff3e0
    style LCRW fill:#fff3e0
    

Components:

Component

Description

DEN Service

Main service handling DENM creation, management, and lifecycle

Transmission Management

Handles message triggering, updates, and termination

Reception Management

Processes incoming DENMs (automatic, no setup needed)

DEN Coder

Encodes/decodes DENM ASN.1 format


Getting Started

Prerequisites

The DEN Service requires:

  • BTP Router — for transport (port 2002)

  • Vehicle Data — your station’s information

  • Location Service — for position updates (recommended)

Optional but recommended:

  • Local Dynamic Map — for storing received DENMs

Step 1: Create DEN Service

from flexstack.facilities.decentralized_environmental_notification_service.den_service import (
    DecentralizedEnvironmentalNotificationService,
)
from flexstack.facilities.ca_basic_service.cam_transmission_management import VehicleData

# Configure vehicle data
vehicle_data = VehicleData(
    station_id=12345,
    station_type=5,  # Passenger car
    drive_direction="forward",
    vehicle_length={"vehicleLengthValue": 42, "vehicleLengthConfidenceIndication": "unavailable"},
    vehicle_width=18,
)

# Create DEN Service
den_service = DecentralizedEnvironmentalNotificationService(
    btp_router=btp_router,
    vehicle_data=vehicle_data,
)

That’s it! The DEN Service is now ready. Reception management is automatic — incoming DENMs will be processed without any additional setup.

Step 2: Use an Application Service

The DEN Service is typically used through application layer services that implement specific use cases. FlexStack provides two built-in applications:

  1. Emergency Vehicle Approaching Service — alerts about approaching emergency vehicles

  2. Longitudinal Collision Risk Warning — warns about collision risks ahead


Emergency Vehicle Approaching Service

This service broadcasts DENMs when an emergency vehicle (ambulance, fire truck, police) needs to alert nearby traffic.

from flexstack.applications.road_hazard_signalling_service.emergency_vehicle_approaching_service import (
    EmergencyVehicleApproachingService,
)
from flexstack.utils.static_location_service import generate_tpv_dict_with_current_timestamp

# Create the application service
emergency_service = EmergencyVehicleApproachingService(
    den_service=den_service,
    duration=10000,  # DENM validity duration in ms
)

# Trigger a DENM (e.g., when emergency lights are activated)
position = generate_tpv_dict_with_current_timestamp(
    latitude=41.386931,
    longitude=2.112104,
)
emergency_service.trigger_denm_sending(position)

Parameters:

Parameter

Type

Description

den_service

DENService

The DEN Service instance

duration

int

How long the DENM remains valid (milliseconds)


DENM Lifecycle

Unlike CAMs (which are fire-and-forget), DENMs have a lifecycle:

        stateDiagram-v2
    [*] --> Active: Trigger
    Active --> Active: Update
    Active --> Terminated: Cancel/Expire
    Terminated --> [*]

    note right of Active: DENM is valid and<br/>being rebroadcast
    note right of Terminated: Event is over,<br/>DENM cancelled
    

DENM Actions:

Action

Description

Trigger

Start a new DENM (hazard detected)

Update

Modify an existing DENM (situation changed)

Terminate

Cancel the DENM (hazard cleared)

Each DENM is identified by an ActionID (station ID + sequence number), allowing receivers to track updates and terminations.


DENM Message Structure

A DENM contains four containers:

        flowchart LR
    subgraph DENM[DENM Message]
        H[ITS PDU Header]
        MC[Management Container]
        SC[Situation Container]
        LC[Location Container]
        AC[À la Carte Container]
    end

    H --> MC --> SC --> LC --> AC
    

Container

Contents

Management

Action ID, detection time, reference time, event position, validity duration

Situation

Cause code, sub-cause code, severity, linked cause (optional)

Location

Event area, road type, lane position, traces

À la Carte

Additional optional data (road works, stationary vehicle, etc.)


Complete Example

Here’s a complete script demonstrating the Emergency Vehicle Approaching Service:

  1#!/usr/bin/env python3
  2"""
  3Emergency Vehicle Approaching Service Example
  4
  5Broadcasts DENMs to alert nearby vehicles about an approaching emergency vehicle.
  6Run with: sudo python emergency_vehicle_example.py
  7"""
  8
  9import logging
 10import random
 11import time
 12
 13from flexstack.linklayer.raw_link_layer import RawLinkLayer
 14from flexstack.geonet.router import Router as GNRouter
 15from flexstack.geonet.mib import MIB
 16from flexstack.geonet.gn_address import GNAddress, M, ST, MID
 17from flexstack.btp.router import Router as BTPRouter
 18from flexstack.utils.static_location_service import (
 19    ThreadStaticLocationService,
 20    generate_tpv_dict_with_current_timestamp,
 21)
 22from flexstack.facilities.ca_basic_service.cam_transmission_management import VehicleData
 23from flexstack.facilities.decentralized_environmental_notification_service.den_service import (
 24    DecentralizedEnvironmentalNotificationService,
 25)
 26from flexstack.applications.road_hazard_signalling_service.emergency_vehicle_approaching_service import (
 27    EmergencyVehicleApproachingService,
 28)
 29
 30logging.basicConfig(level=logging.INFO)
 31
 32# Configuration
 33POSITION = [41.386931, 2.112104]  # Barcelona
 34MAC_ADDRESS = bytes([random.randint(0, 255) | 0x02 for _ in range(6)])
 35STATION_ID = random.randint(1, 2147483647)
 36
 37
 38def main():
 39    # Location Service
 40    location_service = ThreadStaticLocationService(
 41        period=1,
 42        latitude=POSITION[0],
 43        longitude=POSITION[1],
 44    )
 45
 46    # GeoNetworking
 47    mib = MIB(
 48        itsGnLocalGnAddr=GNAddress(
 49            m=M.GN_MULTICAST,
 50            st=ST.SPECIAL_VEHICLE,  # Emergency vehicle
 51            mid=MID(MAC_ADDRESS),
 52        ),
 53    )
 54    gn_router = GNRouter(mib=mib, sign_service=None)
 55    location_service.add_callback(gn_router.refresh_ego_position_vector)
 56
 57    # BTP
 58    btp_router = BTPRouter(gn_router)
 59    gn_router.register_indication_callback(btp_router.btp_data_indication)
 60
 61    # Vehicle Data (emergency vehicle)
 62    vehicle_data = VehicleData(
 63        station_id=STATION_ID,
 64        station_type=10,  # Special vehicle (emergency)
 65        drive_direction="forward",
 66        vehicle_length={"vehicleLengthValue": 70, "vehicleLengthConfidenceIndication": "unavailable"},
 67        vehicle_width=25,
 68    )
 69
 70    # DEN Service
 71    den_service = DecentralizedEnvironmentalNotificationService(
 72        btp_router=btp_router,
 73        vehicle_data=vehicle_data,
 74    )
 75
 76    # Emergency Vehicle Approaching Service
 77    emergency_service = EmergencyVehicleApproachingService(
 78        den_service=den_service,
 79        duration=10000,  # 10 second validity
 80    )
 81
 82    # Trigger DENM (simulating emergency lights activation)
 83    print("🚨 Triggering Emergency Vehicle DENM...")
 84    emergency_service.trigger_denm_sending(
 85        generate_tpv_dict_with_current_timestamp(POSITION[0], POSITION[1])
 86    )
 87
 88    # Link Layer
 89    btp_router.freeze_callbacks()
 90    link_layer = RawLinkLayer(
 91        "lo",
 92        MAC_ADDRESS,
 93        receive_callback=gn_router.gn_data_indicate,
 94    )
 95    gn_router.link_layer = link_layer
 96
 97    print("✅ Emergency Vehicle Service running!")
 98    print("📡 Broadcasting DENMs...")
 99    print("Press Ctrl+C to exit\n")
100
101    try:
102        while True:
103            time.sleep(1)
104    except KeyboardInterrupt:
105        print("\n👋 Shutting down...")
106
107    location_service.stop_event.set()
108    location_service.location_service_thread.join()
109    link_layer.sock.close()
110
111
112if __name__ == "__main__":
113    main()

Cause Codes

DENMs use standardized cause codes (defined in ETSI TS 102 894-2):

Code

Cause

Example Sub-causes

1

Traffic Condition

Traffic jam, slow traffic

2

Accident

Multi-vehicle, heavy accident

3

Road Works

Construction, maintenance

6

Adverse Weather

Fog, rain, ice, wind

9

Hazardous Location

Obstacle, animal on road

12

Wrong Way Driver

Vehicle going wrong direction

14

Rescue/Recovery

Emergency vehicle, recovery in progress

15

Emergency Vehicle

Approaching ambulance/fire/police

91

Vehicle Breakdown

Stationary disabled vehicle

94

Stationary Vehicle

Stopped vehicle (various reasons)


See Also