Encoding / Decoding#
This module implements parsing and serialization of DNP3 Application Layer objects according to section 4.2.2.7 Object Headers of the DNP3 Specification.
Object headers carry information that a bare application header cannot express. This library models each header as four pieces:
Group: which data category is being carried (binary inputs, analog outputs, etc.).
Variation: which on-the-wire layout was chosen for that data (packed, 16-bit, 32-bit, etc.).
Qualifier fields: how many objects to expect next, and which range/prefixing scheme locates them.
Objects: the decoded values themselves.
Example: Class0123 Request#
# no prefix and no range needed here
objects = DNP3Objects()
objects.add_emtpy(60, 1) # object 60, variation 1 (Class 0)
objects.add_emtpy(60, 2) # object 60, variation 2 (Class 1)
objects.add_emtpy(60, 3) # object 60, variation 3 (Class 2)
objects.add_emtpy(60, 4) # object 60, variation 4 (Class 3)
encoded = pack_objects(objects)
# ...
- class icspacket.proto.dnp3.objects.coding.ObjectHeader(group: int, variation: int, reserved: bool = 0, obj_prefix: ObjectPrefixCode = ObjectPrefixCode.NONE, range_spec: RangeSpecifierCode = RangeSpecifierCode.NONE)[source]#
Represents a DNP3 Object Header.
Each instance pins down the group and variation that the following objects belong to, along with the qualifier fields describing how many objects to expect and how they are addressed or prefixed.
- group: int#
/4.2.2.7.1 Object group Identifies the data category the following objects belong to, whether this header is part of a master request or an outstation response.
- variation: int#
/4.2.2.7.2 Object variation Selects the on-the-wire layout for objects in this group. This library uses the (group, variation) pair to look up the matching struct definition and decode the data accordingly.
- obj_prefix: ObjectPrefixCode = 0#
/4.2.2.7.3.2 Object prefix code Selects whether each following object is preceded by a small value (an index or a size) and, if so, which kind.
- range_spec: RangeSpecifierCode = 6#
/4.2.2.7.3.3 Range specifier codes
- class icspacket.proto.dnp3.objects.coding.DNP3Object(prefix: int | None, index: int, instance: Any)[source]#
Represents a single transmitted DNP3 object instance.
A DNP3 object may optionally include a prefix (such as an index), followed by its data value.
- prefix: int | None#
Parsed prefix value (if present). This may represent an index or size.
- index: int#
Sequential index of this object within its variation.
- instance: Any#
The parsed data payload for this object (actual value).
- class icspacket.proto.dnp3.objects.coding.DNP3ObjectVariations[source]#
Represents all objects of a given variation within a group.
Extends
list[DNP3Object]to hold multiple instances of the same group/variation. Additional metadata about range and prefixing is stored here for proper serialization.>>> v = DNP3ObjectVariations() # generic interface >>> v.add(DNP3ObjectG2V1(state=1))
- range_type: RangeSpecifierCode | int | None#
Indicates the range encoding used for this variation (count or start/end).
- range: tuple[int, int] | int | None#
The decoded range value. May be a tuple
(start, stop)for index ranges, an integer count, orNoneif not specified.
- prefix_type: ObjectPrefixCode | int | None#
Prefix encoding used for the objects (e.g., none, 1-byte, 2-byte index).
- get_range() tuple[int, int] | int | None[source]#
Compute the effective range of objects for this variation.
If an explicit range is already set, it is returned. Otherwise, derives the range based on the range type.
- Returns:
The start/end tuple, object count, or
None.- Return type:
tuple[int, int] | int | None
- add(value: Any, /, prefix: int | None = None, index: int | None = None) None[source]#
Add a new object instance to this variation.
- Parameters:
value (Any) – The parsed object payload.
prefix (int | None) – Optional prefix (e.g., index) associated with this object.
index (int | None) – Explicit index. Defaults to sequential numbering.
- class icspacket.proto.dnp3.objects.coding.DNP3Objects[source]#
A container for all DNP3 objects in a fragment.
Maps group numbers to variations, which then contain one or more object instances.
Structure:
DNP3Objects[group][variation] -> DNP3ObjectVariations- get_variation(group: int, variation: int, /) DNP3ObjectVariations[source]#
Retrieve or create a variation container for the given group/variation.
- Parameters:
group (int) – DNP3 object group number.
variation (int) – DNP3 object variation number.
- Returns:
A variation container if known, otherwise
None.- Return type:
DNP3ObjectVariations | None
- icspacket.proto.dnp3.objects.coding.unpack_objects(object_data: bytes) DNP3Objects[source]#
Parse raw DNP3 object data into structured representations.
Reads one or more object headers and associated objects from a byte sequence. Automatically handles range specifiers, prefix codes, and object variations.
- Parameters:
object_data (bytes) – Encoded DNP3 object data.
- Returns:
A structured mapping of groups, variations, and parsed objects.
- Return type:
- Raises:
ValueError – If an unknown object variation is encountered.
- icspacket.proto.dnp3.objects.coding.pack_objects(objects: DNP3Objects, prefix_type: ObjectPrefixCode | None = None, range_type: RangeSpecifierCode | None = None) bytes[source]#
Serialize structured DNP3 objects into raw bytes.
Iterates over all object groups and variations in the provided container, generating object headers, range/prefix encodings, and packed values.
- Parameters:
objects (DNP3Objects) – Structured DNP3 objects to serialize.
prefix_type (ObjectPrefixCode | None) – Default prefix type to apply when none is specified.
range_type (RangeSpecifierCode | None) – Default range type to apply when none is specified.
- Returns:
Encoded object data suitable for transmission.
- Return type:
bytes
- Raises:
ValueError – If an unknown object variation is encountered.