iec60870-parser
A pure-Python, zero-runtime-dependency parser and validator for IEC 60870-5-101, -103, and -104 telemetry frames. It consumes one raw byte buffer at a time and returns a structured ParseResult with VALID, INCOMPLETE, or CORRUPTED status.
Install
python -m pip install iec60870-parser
For a source checkout:
python -m pip install -e .
API
from iec60870 import FrameStatus, T104Session, parse_frame
result = parse_frame(raw_bytes, protocol="t104")
if result.status is FrameStatus.VALID:
print(result.frame_type, result.fields)
elif result.status is FrameStatus.INCOMPLETE:
# Retain the buffer and read more bytes.
pass
else:
print(result.error)
protocol accepts t101, t103, t104, or auto. Explicit protocol selection is preferred for short/incomplete buffers. T101 uses a one-byte link address by default; T103 uses two bytes. Override either with link_address_size=1 or 2.
For a stream connection, T104Session checks the receive sequence number of I-format APDUs and advances it after each valid telemetry frame:
session = T104Session()
result = session.parse(apdu_bytes)
Wire formats
T101 and T103 FT1.2
Variable frames are 68 L L 68 [control] [link address] [ASDU] [CS] 16. L is the number of bytes from control through ASDU, and CS is the sum of those bytes modulo 256. Fixed frames are 10 [control] [link address] [CS] 16; the fixed-frame helper uses the one-byte control/address layout defined by this package API.
T103 uses the same FT1.2 framing and checksum but defaults to a two-byte link address. Companion-standard ASDU variations that are not Type 1 or Type 30 remain available through raw frame fields and can be decoded with parse_asdu using the relevant address widths.
T104 APCI
An APDU is 68 L [four APCI control bytes] [ASDU]. I-format control fields expose send_sequence and receive_sequence; S-format exposes the receive sequence; U-format exposes STARTDT, STOPDT, and TESTFR activation/confirmation names. APCI integers are decoded in little-endian wire order and sequence values are 15-bit values.
ASDU schema
parse_asdu returns a dictionary containing type_id, vsq, count, sequence, cot, common_address, and information_objects. Type 1 objects decode a one-byte single-point value. Type 30 objects decode the one-byte value plus the seven raw CP56Time2a bytes. Unknown type identifiers are validated at the header/address level and leave their remaining bytes in unparsed.
The parser validates bounds before every read, rejects trailing bytes when parsing a single frame, and does not perform socket or stream I/O.
Development
python -m pip install pytest build
python -m pytest
python -m build
Release files for iec60870-parser 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| iec60870_parser-0.1.0.tar.gz | 7.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| iec60870_parser-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 14.1 kB
Release files / iec60870_parser-0.1.0.tar.gz
| Download URL | iec60870_parser-0.1.0.tar.gz |
|---|---|
| Size | 7.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3d35d80ce62bf0564ca41043c7dca264e2b7ccc7f2f96d597fcefbeb00b40874
|
|
BLAKE2b-256 checksum How to use checksums |
9f03fdb70ed4bdd0941add1ec91969480f0be1161cffa871d42f6e275ce28156
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / iec60870_parser-0.1.0-py3-none-any.whl
| Download URL | iec60870_parser-0.1.0-py3-none-any.whl |
|---|---|
| Size | 6.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a18f42a7ffbaefceaebcd471ef423f005b62d736d9a72e97250f880e723f730
|
|
BLAKE2b-256 checksum How to use checksums |
1f5c0d074da786c079f080d252504cd5f19014eb96a424c925e6b5b88676a2a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|