hat.drivers.iec60870.encodings.iec103
IEC 60870-5-103 messages
1"""IEC 60870-5-103 messages""" 2 3from hat.drivers.iec60870.encodings.iec103.common import ( 4 TimeSize, 5 Time, 6 time_from_datetime, 7 time_to_datetime, 8 AsduAddress, 9 OtherCause, 10 AsduType, 11 Cause, 12 Description, 13 OrderType, 14 Channel, 15 IoAddress, 16 Identification, 17 ValueType, 18 NoneValue, 19 TextValue, 20 BitstringValue, 21 UIntValue, 22 IntValue, 23 UFixedValue, 24 FixedValue, 25 Real32Value, 26 Real64Value, 27 DoubleValue, 28 SingleValue, 29 ExtendedDoubleValue, 30 MeasurandValue, 31 TimeValue, 32 IdentificationValue, 33 RelativeTimeValue, 34 IoAddressValue, 35 DoubleWithTimeValue, 36 DoubleWithRelativeTimeValue, 37 MeasurandWithRelativeTimeValue, 38 TextNumberValue, 39 ReplyValue, 40 ArrayValue, 41 IndexValue, 42 Value, 43 DescriptiveData, 44 IoElement_TIME_TAGGED_MESSAGE, 45 IoElement_TIME_TAGGED_MESSAGE_WITH_RELATIVE_TIME, 46 IoElement_MEASURANDS_1, 47 IoElement_TIME_TAGGED_MEASURANDS_WITH_RELATIVE_TIME, 48 IoElement_IDENTIFICATION, 49 IoElement_TIME_SYNCHRONIZATION, 50 IoElement_GENERAL_INTERROGATION, 51 IoElement_GENERAL_INTERROGATION_TERMINATION, 52 IoElement_MEASURANDS_2, 53 IoElement_GENERIC_DATA, 54 IoElement_GENERIC_IDENTIFICATION, 55 IoElement_GENERAL_COMMAND, 56 IoElement_GENERIC_COMMAND, 57 IoElement_LIST_OF_RECORDED_DISTURBANCES, 58 IoElement_ORDER_FOR_DISTURBANCE_DATA_TRANSMISSION, 59 IoElement_ACKNOWLEDGEMENT_FOR_DISTURBANCE_DATA_TRANSMISSION, 60 IoElement_READY_FOR_TRANSMISSION_OF_DISTURBANCE_DATA, 61 IoElement_READY_FOR_TRANSMISSION_OF_A_CHANNEL, 62 IoElement_READY_FOR_TRANSMISSION_OF_TAGS, 63 IoElement_TRANSMISSION_OF_TAGS, 64 IoElement_TRANSMISSION_OF_DISTURBANCE_VALUES, 65 IoElement_END_OF_TRANSMISSION, 66 IoElement, 67 IO, 68 ASDU) 69from hat.drivers.iec60870.encodings.iec103.encoder import Encoder 70 71 72__all__ = ['TimeSize', 73 'Time', 74 'time_from_datetime', 75 'time_to_datetime', 76 'AsduAddress', 77 'OtherCause', 78 'AsduType', 79 'Cause', 80 'Description', 81 'OrderType', 82 'Channel', 83 'IoAddress', 84 'Identification', 85 'ValueType', 86 'NoneValue', 87 'TextValue', 88 'BitstringValue', 89 'UIntValue', 90 'IntValue', 91 'UFixedValue', 92 'FixedValue', 93 'Real32Value', 94 'Real64Value', 95 'DoubleValue', 96 'SingleValue', 97 'ExtendedDoubleValue', 98 'MeasurandValue', 99 'TimeValue', 100 'IdentificationValue', 101 'RelativeTimeValue', 102 'IoAddressValue', 103 'DoubleWithTimeValue', 104 'DoubleWithRelativeTimeValue', 105 'MeasurandWithRelativeTimeValue', 106 'TextNumberValue', 107 'ReplyValue', 108 'ArrayValue', 109 'IndexValue', 110 'Value', 111 'DescriptiveData', 112 'IoElement_TIME_TAGGED_MESSAGE', 113 'IoElement_TIME_TAGGED_MESSAGE_WITH_RELATIVE_TIME', 114 'IoElement_MEASURANDS_1', 115 'IoElement_TIME_TAGGED_MEASURANDS_WITH_RELATIVE_TIME', 116 'IoElement_IDENTIFICATION', 117 'IoElement_TIME_SYNCHRONIZATION', 118 'IoElement_GENERAL_INTERROGATION', 119 'IoElement_GENERAL_INTERROGATION_TERMINATION', 120 'IoElement_MEASURANDS_2', 121 'IoElement_GENERIC_DATA', 122 'IoElement_GENERIC_IDENTIFICATION', 123 'IoElement_GENERAL_COMMAND', 124 'IoElement_GENERIC_COMMAND', 125 'IoElement_LIST_OF_RECORDED_DISTURBANCES', 126 'IoElement_ORDER_FOR_DISTURBANCE_DATA_TRANSMISSION', 127 'IoElement_ACKNOWLEDGEMENT_FOR_DISTURBANCE_DATA_TRANSMISSION', 128 'IoElement_READY_FOR_TRANSMISSION_OF_DISTURBANCE_DATA', 129 'IoElement_READY_FOR_TRANSMISSION_OF_A_CHANNEL', 130 'IoElement_READY_FOR_TRANSMISSION_OF_TAGS', 131 'IoElement_TRANSMISSION_OF_TAGS', 132 'IoElement_TRANSMISSION_OF_DISTURBANCE_VALUES', 133 'IoElement_END_OF_TRANSMISSION', 134 'IoElement', 135 'IO', 136 'ASDU', 137 'Encoder']
An enumeration.
31class Time(typing.NamedTuple): 32 size: TimeSize 33 milliseconds: int 34 """milliseconds in range [0, 59999]""" 35 invalid: bool | None 36 """available for size THREE, FOUR, SEVEN""" 37 minutes: int | None 38 """available for size THREE, FOUR, SEVEN (minutes in range [0, 59])""" 39 summer_time: bool | None 40 """available for size FOUR, SEVEN""" 41 hours: int | None 42 """available for size FOUR, SEVEN (hours in range [0, 23])""" 43 day_of_week: int | None 44 """available for size SEVEN (day_of_week in range [1, 7])""" 45 day_of_month: int | None 46 """available for size SEVEN (day_of_month in range [1, 31])""" 47 months: int | None 48 """available for size SEVEN (months in range [1, 12])""" 49 years: int | None 50 """available for size SEVEN (years in range [0, 99])"""
Time(size, milliseconds, invalid, minutes, summer_time, hours, day_of_week, day_of_month, months, years)
Create new instance of Time(size, milliseconds, invalid, minutes, summer_time, hours, day_of_week, day_of_month, months, years)
66def time_from_datetime(dt: datetime.datetime, 67 invalid: bool = False 68 ) -> Time: 69 """Create Time from datetime.datetime""" 70 # TODO document edge cases (local time, os implementation, ...) 71 # rounding microseconds to the nearest millisecond 72 dt_rounded = ( 73 dt.replace(microsecond=0) + 74 datetime.timedelta(milliseconds=round(dt.microsecond / 1000))) 75 local_time = time.localtime(dt_rounded.timestamp()) 76 77 return Time( 78 size=TimeSize.SEVEN, 79 milliseconds=(local_time.tm_sec * 1000 + 80 dt_rounded.microsecond // 1000), 81 invalid=invalid, 82 minutes=local_time.tm_min, 83 summer_time=bool(local_time.tm_isdst), 84 hours=local_time.tm_hour, 85 day_of_week=local_time.tm_wday + 1, 86 day_of_month=local_time.tm_mday, 87 months=local_time.tm_mon, 88 years=local_time.tm_year % 100)
Create Time from datetime.datetime
91def time_to_datetime(t: Time 92 ) -> datetime.datetime: 93 """Convert Time to datetime.datetime""" 94 # TODO document edge cases (local time, os implementation, ...) 95 # TODO maybe allow diferent time size (use now for time) 96 if t.size != TimeSize.SEVEN: 97 raise ValueError('unsupported time size') 98 99 local_dt = datetime.datetime( 100 year=2000 + t.years if t.years < 70 else 1900 + t.years, 101 month=t.months, 102 day=t.day_of_month, 103 hour=t.hours, 104 minute=t.minutes, 105 second=int(t.milliseconds / 1000), 106 microsecond=(t.milliseconds % 1000) * 1000, 107 fold=not t.summer_time) 108 109 return local_dt.astimezone(tz=datetime.timezone.utc)
Convert Time to datetime.datetime
19class AsduType(enum.Enum): 20 TIME_TAGGED_MESSAGE = 1 21 TIME_TAGGED_MESSAGE_WITH_RELATIVE_TIME = 2 22 MEASURANDS_1 = 3 23 TIME_TAGGED_MEASURANDS_WITH_RELATIVE_TIME = 4 24 IDENTIFICATION = 5 25 TIME_SYNCHRONIZATION = 6 26 GENERAL_INTERROGATION = 7 27 GENERAL_INTERROGATION_TERMINATION = 8 28 MEASURANDS_2 = 9 29 GENERIC_DATA = 10 30 GENERIC_IDENTIFICATION = 11 31 GENERAL_COMMAND = 20 32 GENERIC_COMMAND = 21 33 LIST_OF_RECORDED_DISTURBANCES = 23 34 ORDER_FOR_DISTURBANCE_DATA_TRANSMISSION = 24 35 ACKNOWLEDGEMENT_FOR_DISTURBANCE_DATA_TRANSMISSION = 25 36 READY_FOR_TRANSMISSION_OF_DISTURBANCE_DATA = 26 37 READY_FOR_TRANSMISSION_OF_A_CHANNEL = 27 38 READY_FOR_TRANSMISSION_OF_TAGS = 28 39 TRANSMISSION_OF_TAGS = 29 40 TRANSMISSION_OF_DISTURBANCE_VALUES = 30 41 END_OF_TRANSMISSION = 31
An enumeration.
44class Cause(enum.Enum): 45 SPONTANEOUS = 1 46 CYCLIC = 2 47 RESET_FRAME_COUNT_BIT = 3 48 RESET_COMMUNICATION_UNIT = 4 49 START_RESTART = 5 50 POWER_ON = 6 51 TEST_MODE = 7 52 TIME_SYNCHRONIZATION = 8 53 GENERAL_INTERROGATION = 9 54 TERMINATION_OF_GENERAL_INTERROGATION = 10 55 LOCAL_OPERATION = 11 56 REMOTE_OPERATION = 12 57 GENERAL_COMMAND = 20 58 GENERAL_COMMAND_NACK = 21 59 TRANSMISSION_OF_DISTURBANCE_DATA = 31 60 GENERIC_WRITE_COMMAND = 40 61 GENERIC_WRITE_COMMAND_NACK = 41 62 GENERIC_READ_COMMAND = 42 63 GENERIC_READ_COMMAND_NACK = 43 64 GENERIC_WRITE_CONFIRMATION = 44
An enumeration.
67class Description(enum.Enum): 68 NOT_SPECIFIED = 0 69 ACTUAL_VALUE = 1 70 DEFAULT_VALUE = 2 71 RANGE = 3 72 PRECISION = 5 73 FACTOR = 6 74 REFERENCE = 7 75 ENUMERATION = 8 76 DIMENSION = 9 77 DESCRIPTION = 10 78 PASSWORD = 12 79 READ_ONLY = 13 80 WRITE_ONLY = 14 81 IO_ADDRESS = 19 82 EVENT = 20 83 TEXT_ARRAY = 21 84 VALUE_ARRAY = 22 85 RELATED = 23
An enumeration.
88class OrderType(enum.Enum): 89 SELECTION_OF_FAULT = 1 90 REQUEST_FOR_DISTURBANCE_DATA = 2 91 ABORTION_OF_DISTURBANCE_DATA = 3 92 REQUEST_FOR_CHANNEL = 8 93 ABORTION_OF_CHANNEL = 9 94 REQUEST_FOR_TAGS = 16 95 ABORTION_OF_TAGS = 17 96 REQUEST_FOR_LIST_OF_RECORDED_DISTURBANCES = 24 97 END_OF_DISTURBANCE_DATA_TRANSMISSION_WITHOUT_ABORTION = 32 98 END_OF_DISTURBANCE_DATA_TRANSMISSION_WITH_ABORTION_BY_CONTROL_SYSTEM = 33 99 END_OF_DISTURBANCE_DATA_TRANSMISSION_WITH_ABORTION_BY_THE_PROTECTION_EQUIPMENT = 34 # NOQA 100 END_OF_CHANNEL_TRANSMISSION_WITHOUT_ABORTION = 35 101 END_OF_CHANNEL_TRANSMISSION_WITH_ABORTION_BY_CONTROL_SYSTEM = 36 102 END_OF_CHANNEL_TRANSMISSION_WITH_ABORTION_BY_THE_PROTECTION_EQUIPMENT = 37 103 END_OF_TAG_TRANSMISSION_WITHOUT_ABORTION = 38 104 END_OF_TAG_TRANSMISSION_WITH_ABORTION_BY_CONTROL_SYSTEM = 39 105 END_OF_TAG_TRANSMISSION_WITH_ABORTION_BY_THE_PROTECTION_EQUIPMENT = 40 106 DISTURBANCE_DATA_TRANSMITTED_SUCCESSFULLY = 64 107 DISTURBANCE_DATA_TRANSMITTED_NOT_SUCCESSFULLY = 65 108 CHANNEL_TRANSMITTED_SUCCESSFULLY = 66 109 CHANNEL_TRANSMITTED_NOT_SUCCESSFULLY = 67 110 TAGS_TRANSMITTED_SUCCESSFULLY = 68 111 TAGS_TRANSMITTED_NOT_SUCCESSFULLY = 69
An enumeration.
114class Channel(enum.Enum): 115 GLOBAL = 0 116 I_L1 = 1 117 I_L2 = 2 118 I_L3 = 3 119 I_N = 4 120 V_L1E = 5 121 V_L2E = 6 122 V_L3E = 7 123 V_EN = 8
An enumeration.
126class IoAddress(typing.NamedTuple): 127 function_type: int 128 """function_type is in range [0, 255]""" 129 information_number: int 130 """information_number is in range [0, 255]"""
IoAddress(function_type, information_number)
133class Identification(typing.NamedTuple): 134 group_id: int 135 """group_id in range [0, 255]""" 136 entry_id: int 137 """entry_id in range [0, 255]"""
Identification(group_id, entry_id)
140class ValueType(enum.Enum): 141 NONE = 0 142 TEXT = 1 143 BITSTRING = 2 144 UINT = 3 145 INT = 4 146 UFIXED = 5 147 FIXED = 6 148 REAL32 = 7 149 REAL64 = 8 150 DOUBLE = 9 151 SINGLE = 10 152 EXTENDED_DOUBLE = 11 153 MEASURAND = 12 154 TIME = 14 155 IDENTIFICATION = 15 156 RELATIVE_TIME = 16 157 IO_ADDRESS = 17 158 DOUBLE_WITH_TIME = 18 159 DOUBLE_WITH_RELATIVE_TIME = 19 160 MEASURAND_WITH_RELATIVE_TIME = 20 161 TEXT_NUMBER = 21 162 REPLY = 22 163 ARRAY = 23 164 INDEX = 24
An enumeration.
NoneValue()
TextValue(value,)
BitstringValue(value,)
UIntValue(value,)
IntValue(value,)
UFixedValue(value,)
FixedValue(value,)
Real32Value(value,)
Real64Value(value,)
An enumeration.
An enumeration.
An enumeration.
224class MeasurandValue(typing.NamedTuple): 225 overflow: bool 226 invalid: bool 227 value: float 228 """value in range [-1.0, 1.0)"""
MeasurandValue(overflow, invalid, value)
TimeValue(value,)
IdentificationValue(value,)
RelativeTimeValue(value,)
IoAddressValue(value,)
249class DoubleWithTimeValue(typing.NamedTuple): 250 value: DoubleValue 251 time: Time 252 """time size is FOUR""" 253 supplementary: int 254 """supplementary in range [0, 255]"""
DoubleWithTimeValue(value, time, supplementary)
Create new instance of DoubleWithTimeValue(value, time, supplementary)
257class DoubleWithRelativeTimeValue(typing.NamedTuple): 258 value: DoubleValue 259 relative_time: int 260 """relative_time in range [0, 65535]""" 261 fault_number: int 262 """fault_number in range [0, 65535]""" 263 time: Time 264 """time size is FOUR""" 265 supplementary: int 266 """supplementary in range [0, 255]"""
DoubleWithRelativeTimeValue(value, relative_time, fault_number, time, supplementary)
Create new instance of DoubleWithRelativeTimeValue(value, relative_time, fault_number, time, supplementary)
269class MeasurandWithRelativeTimeValue(typing.NamedTuple): 270 value: float 271 relative_time: int 272 """relative_time in range [0, 65535]""" 273 fault_number: int 274 """fault_number in range [0, 65535]""" 275 time: Time 276 """time size is FOUR"""
MeasurandWithRelativeTimeValue(value, relative_time, fault_number, time)
Create new instance of MeasurandWithRelativeTimeValue(value, relative_time, fault_number, time)
TextNumberValue(value,)
283class ReplyValue(enum.Enum): 284 ACK = 0 285 INVALID_IDENTIFICATION = 1 286 DATA_NOT_EXISTS = 2 287 DATA_NOT_AVAILABLE = 3 288 VERIFY_ERROR = 4 289 OUT_OF_RANGE = 5 290 ENTRY_TO_LARGE = 6 291 TOO_MANY_COMMANDS = 7 292 ENTRY_READ_ONLY = 8 293 PASSWORD_PROTECTED = 9 294 IN_PROGRESS = 10 295 FOLLOWING_DESCRIPTION = 11
An enumeration.
298class ArrayValue(typing.NamedTuple): 299 value_type: ValueType 300 more_follows: bool 301 values: typing.List['Value']
ArrayValue(value_type, more_follows, values)
Create new instance of ArrayValue(value_type, more_follows, values)
Alias for field number 2
IndexValue(value,)
DescriptiveData(description, value)
Create new instance of DescriptiveData(description, value)
IoElement_TIME_TAGGED_MESSAGE(value,)
Create new instance of IoElement_TIME_TAGGED_MESSAGE(value,)
343class IoElement_TIME_TAGGED_MESSAGE_WITH_RELATIVE_TIME(typing.NamedTuple): 344 value: DoubleWithRelativeTimeValue
IoElement_TIME_TAGGED_MESSAGE_WITH_RELATIVE_TIME(value,)
Create new instance of IoElement_TIME_TAGGED_MESSAGE_WITH_RELATIVE_TIME(value,)
IoElement_MEASURANDS_1(value,)
351class IoElement_TIME_TAGGED_MEASURANDS_WITH_RELATIVE_TIME(typing.NamedTuple): 352 value: MeasurandWithRelativeTimeValue
IoElement_TIME_TAGGED_MEASURANDS_WITH_RELATIVE_TIME(value,)
Create new instance of IoElement_TIME_TAGGED_MEASURANDS_WITH_RELATIVE_TIME(value,)
355class IoElement_IDENTIFICATION(typing.NamedTuple): 356 compatibility: int 357 """compatibility in range [0, 255]""" 358 value: util.Bytes 359 """value length is 8""" 360 software: util.Bytes 361 """software length is 4"""
IoElement_IDENTIFICATION(compatibility, value, software)
364class IoElement_TIME_SYNCHRONIZATION(typing.NamedTuple): 365 time: Time 366 """time size is SEVEN"""
IoElement_TIME_SYNCHRONIZATION(time,)
Create new instance of IoElement_TIME_SYNCHRONIZATION(time,)
369class IoElement_GENERAL_INTERROGATION(typing.NamedTuple): 370 scan_number: int 371 """scan_number in range [0, 255]"""
IoElement_GENERAL_INTERROGATION(scan_number,)
374class IoElement_GENERAL_INTERROGATION_TERMINATION(typing.NamedTuple): 375 scan_number: int 376 """scan_number in range [0, 255]"""
IoElement_GENERAL_INTERROGATION_TERMINATION(scan_number,)
IoElement_MEASURANDS_2(value,)
383class IoElement_GENERIC_DATA(typing.NamedTuple): 384 return_identifier: int 385 """return_identifier in range [0, 255]""" 386 counter: bool 387 more_follows: bool 388 data: list[tuple[Identification, DescriptiveData]]
IoElement_GENERIC_DATA(return_identifier, counter, more_follows, data)
Create new instance of IoElement_GENERIC_DATA(return_identifier, counter, more_follows, data)
391class IoElement_GENERIC_IDENTIFICATION(typing.NamedTuple): 392 return_identifier: int 393 """return_identifier in range [0, 255]""" 394 identification: Identification 395 counter: bool 396 more_follows: bool 397 data: list[DescriptiveData]
IoElement_GENERIC_IDENTIFICATION(return_identifier, identification, counter, more_follows, data)
Create new instance of IoElement_GENERIC_IDENTIFICATION(return_identifier, identification, counter, more_follows, data)
400class IoElement_GENERAL_COMMAND(typing.NamedTuple): 401 value: DoubleValue 402 return_identifier: int 403 """return_identifier in range [0, 255]"""
IoElement_GENERAL_COMMAND(value, return_identifier)
Create new instance of IoElement_GENERAL_COMMAND(value, return_identifier)
406class IoElement_GENERIC_COMMAND(typing.NamedTuple): 407 return_identifier: int 408 """return_identifier in range [0, 255]""" 409 data: list[tuple[Identification, Description]]
IoElement_GENERIC_COMMAND(return_identifier, data)
Create new instance of IoElement_GENERIC_COMMAND(return_identifier, data)
412class IoElement_LIST_OF_RECORDED_DISTURBANCES(typing.NamedTuple): 413 fault_number: int 414 """fault_number in range [0, 65535]""" 415 trip: bool 416 transmitted: bool 417 test: bool 418 other: bool 419 time: Time 420 """time size is SEVEN"""
IoElement_LIST_OF_RECORDED_DISTURBANCES(fault_number, trip, transmitted, test, other, time)
Create new instance of IoElement_LIST_OF_RECORDED_DISTURBANCES(fault_number, trip, transmitted, test, other, time)
423class IoElement_ORDER_FOR_DISTURBANCE_DATA_TRANSMISSION(typing.NamedTuple): 424 order_type: OrderType 425 fault_number: int 426 """fault_number in range [0, 65535]""" 427 channel: Channel
IoElement_ORDER_FOR_DISTURBANCE_DATA_TRANSMISSION(order_type, fault_number, channel)
430class IoElement_ACKNOWLEDGEMENT_FOR_DISTURBANCE_DATA_TRANSMISSION(typing.NamedTuple): # NOQA 431 order_type: OrderType 432 fault_number: int 433 """fault_number in range [0, 65535]""" 434 channel: Channel
IoElement_ACKNOWLEDGEMENT_FOR_DISTURBANCE_DATA_TRANSMISSION(order_type, fault_number, channel)
437class IoElement_READY_FOR_TRANSMISSION_OF_DISTURBANCE_DATA(typing.NamedTuple): 438 fault_number: int 439 """fault_number in range [0, 65535]""" 440 number_of_faults: int 441 """number_of_faults in range [0, 65535]""" 442 number_of_channels: int 443 """number_of_channels in range [0, 255]""" 444 number_of_elements: int 445 """number_of_elements in range [1, 65535]""" 446 interval: int 447 """interval in range [1, 65535]""" 448 time: Time 449 """time size is FOUR"""
IoElement_READY_FOR_TRANSMISSION_OF_DISTURBANCE_DATA(fault_number, number_of_faults, number_of_channels, number_of_elements, interval, time)
Create new instance of IoElement_READY_FOR_TRANSMISSION_OF_DISTURBANCE_DATA(fault_number, number_of_faults, number_of_channels, number_of_elements, interval, time)
452class IoElement_READY_FOR_TRANSMISSION_OF_A_CHANNEL(typing.NamedTuple): 453 fault_number: int 454 """fault_number in range [0, 65535]""" 455 channel: Channel 456 primary: Real32Value 457 secondary: Real32Value 458 reference: Real32Value
IoElement_READY_FOR_TRANSMISSION_OF_A_CHANNEL(fault_number, channel, primary, secondary, reference)
Create new instance of IoElement_READY_FOR_TRANSMISSION_OF_A_CHANNEL(fault_number, channel, primary, secondary, reference)
461class IoElement_READY_FOR_TRANSMISSION_OF_TAGS(typing.NamedTuple): 462 fault_number: int 463 """fault_number in range [0, 65535]"""
IoElement_READY_FOR_TRANSMISSION_OF_TAGS(fault_number,)
466class IoElement_TRANSMISSION_OF_TAGS(typing.NamedTuple): 467 fault_number: int 468 """fault_number in range [0, 65535]""" 469 tag_position: int 470 """tag_position in range [0, 65535]""" 471 values: list[tuple[IoAddress, DoubleValue]]
IoElement_TRANSMISSION_OF_TAGS(fault_number, tag_position, values)
Create new instance of IoElement_TRANSMISSION_OF_TAGS(fault_number, tag_position, values)
474class IoElement_TRANSMISSION_OF_DISTURBANCE_VALUES(typing.NamedTuple): 475 fault_number: int 476 """fault_number in range [0, 65535]""" 477 channel: Channel 478 element_number: int 479 """element_number in range [0, 65535]""" 480 values: list[float] 481 """values are in range [-1.0, 1.0)"""
IoElement_TRANSMISSION_OF_DISTURBANCE_VALUES(fault_number, channel, element_number, values)
Create new instance of IoElement_TRANSMISSION_OF_DISTURBANCE_VALUES(fault_number, channel, element_number, values)
484class IoElement_END_OF_TRANSMISSION(typing.NamedTuple): 485 order_type: OrderType 486 fault_number: int 487 """fault_number in range [0, 65535]""" 488 channel: Channel
IoElement_END_OF_TRANSMISSION(order_type, fault_number, channel)
IO(address, elements)
Create new instance of IO(address, elements)
Alias for field number 1
521class ASDU(typing.NamedTuple): 522 type: AsduType 523 cause: Cause | OtherCause 524 address: AsduAddress 525 ios: list[IO]
ASDU(type, cause, address, ios)
14class Encoder: 15 16 def __init__(self): 17 self._encoder = encoder.Encoder( 18 cause_size=common.CauseSize.ONE, 19 asdu_address_size=common.AsduAddressSize.ONE, 20 io_address_size=common.IoAddressSize.TWO, 21 asdu_type_time_sizes={}, 22 inverted_sequence_bit=True, 23 decode_io_element_cb=_decode_io_element, 24 encode_io_element_cb=_encode_io_element) 25 26 def decode_asdu(self, 27 asdu_bytes: util.Bytes 28 ) -> tuple[common.ASDU, util.Bytes]: 29 asdu, rest = self._encoder.decode_asdu(asdu_bytes) 30 31 asdu_type = common.AsduType(asdu.type) 32 cause = _decode_cause(asdu.cause) 33 address = asdu.address 34 ios = [common.IO(address=_decode_io_address(io.address), 35 elements=io.elements) 36 for io in asdu.ios] 37 38 # TODO assert len(asdu.ios) == 1 39 40 asdu = common.ASDU(type=asdu_type, 41 cause=cause, 42 address=address, 43 ios=ios) 44 return asdu, rest 45 46 def encode_asdu(self, asdu: common.ASDU) -> util.Bytes: 47 asdu_type = asdu.type.value 48 cause = _encode_cause(asdu.cause) 49 address = asdu.address 50 ios = [encoder.common.IO(address=_encode_io_address(io.address), 51 elements=io.elements, 52 time=None) 53 for io in asdu.ios] 54 55 asdu = encoder.common.ASDU(type=asdu_type, 56 cause=cause, 57 address=address, 58 ios=ios) 59 60 return self._encoder.encode_asdu(asdu)
26 def decode_asdu(self, 27 asdu_bytes: util.Bytes 28 ) -> tuple[common.ASDU, util.Bytes]: 29 asdu, rest = self._encoder.decode_asdu(asdu_bytes) 30 31 asdu_type = common.AsduType(asdu.type) 32 cause = _decode_cause(asdu.cause) 33 address = asdu.address 34 ios = [common.IO(address=_decode_io_address(io.address), 35 elements=io.elements) 36 for io in asdu.ios] 37 38 # TODO assert len(asdu.ios) == 1 39 40 asdu = common.ASDU(type=asdu_type, 41 cause=cause, 42 address=address, 43 ios=ios) 44 return asdu, rest
46 def encode_asdu(self, asdu: common.ASDU) -> util.Bytes: 47 asdu_type = asdu.type.value 48 cause = _encode_cause(asdu.cause) 49 address = asdu.address 50 ios = [encoder.common.IO(address=_encode_io_address(io.address), 51 elements=io.elements, 52 time=None) 53 for io in asdu.ios] 54 55 asdu = encoder.common.ASDU(type=asdu_type, 56 cause=cause, 57 address=address, 58 ios=ios) 59 60 return self._encoder.encode_asdu(asdu)