IEC 60870-5 is a set of standards for telecontrol, teleprotection, and associated telecommunications for electric power systems, widely used in the European Union, the United Kingdom and other locations.
The crate provides a fully Rust-safe transport-agnostic implementation for IEC 60870-5 101/104 telegrams and common data types. The library contains almost the complete set of types and instruments required to easily write own client or server, including time conversion between Rust and IEC 60870-5 formats.
The crate IS NOT FREE for any commercial or production use. Please refer to https://github.com/roboplc/iec60870-5/blob/main/LICENSE.md for more information.
IEC 60870-5 Rust library is a part of the RoboPLC project.
MSRV: 1.68.0
use iec60870_5::telegram104::Telegram104;
let telegram = Telegram104::new_start_dt();
// The telegram is ready to be sent in any way
let mut buffer = std::io::Cursor::new(Vec::new());
telegram.write(&mut buffer).unwrap();
// A timestamp crate
use bma_ts::Timestamp;
use iec60870_5::types::datatype::{C_RC_TA_1, DataType, QU, RCO, RCS, SelectExecute};
use iec60870_5::types::COT;
use iec60870_5::telegram104::{ChatSequenceCounter, Telegram104, Telegram104_I};
// To communicate with the server, the client must have a chat sequence counter
let chat_sequence_counter = ChatSequenceCounter::new();
let mut telegram_i: Telegram104_I = Telegram104_I::new(
DataType::C_RC_TA_1, // Data type, regulating step command with CP56Time2a time tag
COT::Act, // Cause of transmission: activation
15 // ASDU address
);
telegram_i.append_iou(
11, // Information object address,
C_RC_TA_1 { // Regulating step command with CP56Time2a time tag
rco: RCO {
rcs: RCS::Increment,
se: SelectExecute::Execute,
qu: QU::Persistent,
},
time: Timestamp::now().try_into().unwrap(),
},
);
let mut telegram: Telegram104 = telegram_i.into();
telegram.chat_sequence_apply_outgoing(&chat_sequence_counter);
// The telegram is ready to be sent in any way
let mut buffer = std::io::Cursor::new(Vec::new());
telegram.write(&mut buffer).unwrap();
// A timestamp crate
use bma_ts::Timestamp;
use iec60870_5::telegram104::{ChatSequenceCounter, Telegram104};
use iec60870_5::types::datatype::{DataType, M_EP_TA_1};
// For strict servers, the client must have a chat sequence counter
let chat_sequence_counter = ChatSequenceCounter::new();
// Consider that the buffer contains a valid telegram
let mut buffer = std::io::Cursor::new(Vec::new());
let telegram = Telegram104::read(&mut buffer).unwrap();
telegram.chat_sequence_validate_incoming(&chat_sequence_counter).unwrap();
if let Telegram104::I(i) = telegram {
// This is an I-frame
if i.data_type() == DataType::M_EP_TA_1 {
// This is a M_EP_TA_1 telegram
for iou in i.iou() {
// Decode MP_EP_TA_1 information object value from the raw IOU buffer
let val: M_EP_TA_1 = iou.value().into();
// Convert the time tag to a timestamp
let dt = Timestamp::try_from(val.time).unwrap();
// Output the event state and the timestamp
dbg!(val.sep.es, dt);
}
}
}
-
As IEC 60870-5 is a complex standard, 3rd party hardware/software vendors usually do not implement it it full, some functionality may require additional development/workarounds.
-
The library has been fully tested in pair with Beckhoff TwinCAT 3 TF6500 as well as with certain embedded implementations, used in the European Union power grids.
-
The most common problem is that the majority of the IEC 60870-5 104 servers require keep-alive frames. Such can be generated either using IEC 60870-5 104 S-Frames, or test U-frames out-of-the-box:
use iec60870_5::telegram104::Telegram104;
let telegram = Telegram104::new_test();
// Write the telegram to the target
Bohemia Automation / Altertech is a group of companies with 15+ years of experience in the enterprise automation and industrial IoT. Our setups include power plants, factories and urban infrastructure. Largest of them have 1M+ sensors and controlled devices and the bar raises higher and higher every day.