Skip to content

OpenEnergyTwin/protocol-adapter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

protocol-adapter

This is a protocol adapter service for the OpenEnergyTwin Platform.

This service bridges various industrial and smart meter protocols (IEC 60870-5-104, COSEM/XML) to the OpenEnergyTwin MQTT-based messaging infrastructure. It also implements the BDEW Universal Order Process (Universalbestellprozess) for sending control commands to intelligent meter systems in Germany.

Requirements

For deployment, this service requires:

  • A running MQTT broker for communication with other services
  • Configuration for the adapters to connect (IEC 104 servers, COSEM endpoints, BDEW API servers)
Variable Description Required Default
RUST_LOG Logging level (e.g., info, debug, warn) No info

Configuration

Configuration is done via a config.toml file. The service reads this file at startup.

Basic Structure

# MQTT broker connection
mqtt_url = "mqtt://localhost:1883/?client_id=protocol_adapter"

# List of adapter configurations
[[adapters]]
# Adapter type and specific configuration...

Supported Adapters

IEC 104 Client (IEC104Client)

Connects to IEC 60870-5-104 servers to collect measurement data.

[[adapters]]
type = "IEC104Client"
server_url = "192.168.1.100:2404"

# Define measurement points to monitor
measurement_points = [
    { common_address = 1, information_object_address = 1001, type = "ActivePower", terminal = "terminal_42" },
    { common_address = 1, information_object_address = 1002, type = "ReactivePower", terminal = "terminal_42" },
    { common_address = 1, information_object_address = 2001, type = "VoltageMagnitude", topological_node = "node_123" },
]

Configuration Fields:

Field Description Required
type Must be "IEC104Client" Yes
server_url IEC 104 server address with port (e.g., "192.168.1.100:2404") Yes
measurement_points Array of measurement point definitions Yes

Measurement Point Fields:

Field Description Required
common_address IEC 104 common address (CA) of the measurement point Yes
information_object_address Information object address (IOA) Yes
type Measurement type: "ActivePower", "ReactivePower", or "VoltageMagnitude" Yes
terminal Terminal ID (required for ActivePower and ReactivePower) Conditional
topological_node Topological node ID (required for VoltageMagnitude) Conditional

COSEM Server (COSEMServer)

Exposes an HTTP server that receives COSEM/XML data from smart meters and forwards it as measurement messages.

[[adapters]]
type = "COSEMServer"
host = "0.0.0.0"
port = 3000

# Define smart meter mappings
smart_meters = [
    { device_id = "42", terminal = "terminal_42", topological_node = "node_123" },
    { device_id = "43", terminal = "terminal_43", topological_node = "node_124" },
]

Configuration Fields:

Field Description Required
type Must be "COSEMServer" Yes
host Host address to bind the HTTP server Yes
port Port to bind the HTTP server Yes
smart_meters Array of smart meter definitions Yes

Smart Meter Fields:

Field Description Required
device_id Unique device identifier (used in HTTP query parameter) Yes
terminal Terminal ID for the smart meter Yes
topological_node Topological node ID for the smart meter Yes

HTTP Endpoint:

  • Path: /cosem/ldevs?devID={device_id}
  • Method: POST
  • Content-Type: application/xml
  • Body: COSEM ProgObject XML

The server expects COSEM data in XML format containing OBIS codes for:

  • 1-0:16.7.0*255 - Active power total
  • 1-0:36.7.0*255 - Active power L1
  • 1-0:56.7.0*255 - Active power L2
  • 1-0:76.7.0*255 - Active power L3

BDEW Universalbestellprozess Client (BDEWUniversalbestellprozessClient)

Implements the BDEW Universal Order Process for sending control commands to smart meter systems (iMS) according to §14a EnWG.

[[adapters]]
type = "BDEWUniversalbestellprozessClient"
server_url = "https://api.bdew.example.com"
webhook_host = "0.0.0.0"
webhook_port = 5000

# Define location mappings
locations = [
    { location_id = "C1234848431", energy_consumer = "_caf0f2d6-3cf5-4605-8911-f36ed78bf9fb" },
]

Configuration Fields:

Field Description Required
type Must be "BDEWUniversalbestellprozessClient" Yes
server_url Base URL of the BDEW API server Yes
webhook_host Host address for the webhook callback server Yes
webhook_port Port for the webhook callback server Yes
locations Array of location mappings Yes

Location Fields:

Field Description Required
location_id BDEW location ID (SR-ID pattern C[A-Z\d]{9}\d or Nelo-ID pattern E[A-Z\d]{9}\d) Yes
energy_consumer Internal equipment ID that maps to this location Yes

Webhook Endpoints:

The service exposes the following webhook endpoints to receive responses from the BDEW API:

Endpoint Method Description
/[Post]/steuerbefehl/vorlaeufigePositiveAntwort/ POST Preliminary positive response
/[Post]/steuerbefehl/vorlaeufigeNegativeAntwort/ POST Preliminary negative response
/[Post]/steuerbefehl/positiveAntwort/ POST Final positive response
/[Post]/steuerbefehl/negativeAntwort/ POST Final negative response
/[Post]/steuerbefehl/informationAnweisung/ POST Unknown status information

Command Flow:

The BDEW Universal Order Process follows this asynchronous pattern:

  1. Platform sends a command via MQTT (Control topic) in CIM JSON-LD format with cim:ActivePowerLimit
  2. Protocol adapter parses the command and sends it to the BDEW API
  3. BDEW API responds with 202 Accepted and a transaction ID
  4. MSB (Messstellenbetreiber) sends responses via webhooks
  5. Command completion is tracked and logged

CIM Command Message Format:

{
  "@graph": [
    {
      "@id": "_977b3685-8e3b-4b1a-aa09-05941f5488f8",
      "@type": "cim:OperationalLimitType",
      "cim:IdentifiedObject.name": "§14a EnWG Congestion Limit",
      "cim:OperationalLimitType.acceptableDuration": 3600,
      "cim:OperationalLimitType.limitType": "cim:LimitTypeKind.tatl",
      "cim:OperationalLimitType.direction": "cim:OperationalLimitDirectionKind.high"
    },
    {
      "@id": "_a82c88f4-0b73-40dd-b5de-b6e014c480b2",
      "@type": "cim:OperationalLimitSet",
      "cim:IdentifiedObject.name": "§14a Limit Set",
      "cim:OperationalLimitSet.Equipment": {
        "@id": "_caf0f2d6-3cf5-4605-8911-f36ed78bf9fb"
      }
    },
    {
      "@id": "_7fa766ef-ee79-4b2d-98cf-33f6a71acd0c",
      "@type": "cim:ActivePowerLimit",
      "cim:IdentifiedObject.name": "Consumption Limit 4.2 kW",
      "cim:ActivePowerLimit.value": 4.2,
      "cim:OperationalLimit.OperationalLimitSet": {
        "@id": "_a82c88f4-0b73-40dd-b5de-b6e014c480b2"
      },
      "cim:OperationalLimit.OperationalLimitType": {
        "@id": "_977b3685-8e3b-4b1a-aa09-05941f5488f8"
      }
    }
  ]
}

MQTT Topics

Subscribed Topics

Topic QoS Description
Control 1 Receives control commands in CIM JSON-LD format

Published Topics

Topic QoS Description
Measurement.Raw 1 Publishes measurement data in CIM format

Message Formats

Outbound Measurement Messages

The service publishes measurement data in CIM format:

Active Power:

{
  "@type": "cim:SvPowerFlow",
  "cim:SvPowerFlow.Terminal": "terminal_42",
  "cim:SvPowerFlow.p": 4.2,
  "cim:SvPowerFlow.phase": 1
}

Reactive Power:

{
  "@type": "cim:SvPowerFlow",
  "cim:SvPowerFlow.Terminal": "terminal_42",
  "cim:SvPowerFlow.q": 0.5,
  "cim:SvPowerFlow.phase": null
}

Voltage Magnitude:

{
  "@type": "cim:SvVoltage",
  "cim:SvVoltage.TopologicalNode": "node_123",
  "cim:SvVoltage.v": 1.0
}

About

Protocol adapter to bridge various OT protocols into/out of OpenEnergyTwin.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors