Skip to content

py1815

A DNP3 (IEEE 1815) outstation in pure Python.

Early development

The protocol layers, the listener, controls and the event path are implemented and tested: a master reads classes 1 to 3, confirms what it was sent, and is told through the indication bits what is still waiting. Unsolicited responses, outstation-initiated traffic, are there for a session built to send them. An answer too large for one fragment is a conversation: the master confirms each fragment and the next follows. The first release is 0.1.0 and the API is not stable: while the major version is 0, a minor bump may carry a breaking change.

Why it is pure Python

There is no maintained, importable DNP3 stack for current Python. The widely used bindings wrap opendnp3, archived and declared end-of-life in September 2022, and they publish wheels only up to CPython 3.10. opendnp3 is still one of the two masters this library is tested against, and the source of two of its choices; Testing says which. Everything else in the ecosystem is a compiled extension, which means a prebuilt wheel per interpreter version and a cross-compiler for anything unusual.

This library depends on nothing outside the standard library. That is the point of it: it runs on embedded targets where no toolchain is available, and it upgrades with the interpreter rather than waiting for someone to publish a wheel.

What it does

An outstation, the side a SCADA master connects to. Subset Level 2 is the target, over TCP and TLS.

Layer Module Contents
Checksum crc CRC-16/DNP
Data link link FT3 framing, control byte, addresses, stream reader
Transport transport Segmentation and reassembly
Application application Control octet, function codes, internal indications, object headers
Objects objects Binary inputs, analog inputs and counters, static and event, with quality flags
Events events Class buffers, deadbands, overflow
Session session One master association: octets in, octets out
Listener server TCP, TLS, and which connection is allowed to be the master
DER profile profile The IEEE 1815.2 point map, and an outstation built from it

Each layer is testable without the ones above it. The session does no I/O at all, so protocol behavior is pinned against literal frames rather than against a socket.

Start here

  • How DNP3 works if the protocol is new to you, or if you need the shape of a frame in front of you.
  • Serving an outstation to get one answering a master.
  • Serving a DER to run an IEEE 1815.2 outstation, simulated or over your own device.
  • The master to read an outstation from Python, for testing one.
  • The console to watch an outstation's points, events and traffic in a browser, and The master's API to drive the same master from another process.
  • Design decisions for why the library is shaped the way it is, numbered so they can be argued with.
  • Testing for how the wire behavior is held to, and what is checked by implementations that are not this one.

Part of Project Satori

Any certified DER. Any utility program. Satori is an open-source initiative to make any certified DER a compliant participant in utility DER programs.

A device joins a program by speaking whatever protocol that program is run on, and that is not one protocol. IEEE 2030.5 is what most North American and Australian utility programs specify. DNP3 is what a great deal of existing distribution SCADA already speaks, and IEEE 1815.2 is the DER profile built on it. This library is the DNP3 half.

Project website: https://open-satori.org

License

Apache-2.0.