hat.drivers.iec104

IEC 60870-5-104 communication protocol

  1"""IEC 60870-5-104 communication protocol"""
  2
  3from hat.drivers.iec104.common import (AsduTypeError,
  4                                       TimeSize,
  5                                       Time,
  6                                       OriginatorAddress,
  7                                       AsduAddress,
  8                                       IoAddress,
  9                                       IndicationQuality,
 10                                       MeasurementQuality,
 11                                       CounterQuality,
 12                                       ProtectionQuality,
 13                                       Quality,
 14                                       FreezeCode,
 15                                       SingleValue,
 16                                       DoubleValue,
 17                                       RegulatingValue,
 18                                       StepPositionValue,
 19                                       BitstringValue,
 20                                       NormalizedValue,
 21                                       ScaledValue,
 22                                       FloatingValue,
 23                                       BinaryCounterValue,
 24                                       ProtectionValue,
 25                                       ProtectionStartValue,
 26                                       ProtectionCommandValue,
 27                                       StatusValue,
 28                                       OtherCause,
 29                                       DataResCause,
 30                                       DataCause,
 31                                       CommandReqCause,
 32                                       CommandResCause,
 33                                       CommandCause,
 34                                       InitializationResCause,
 35                                       InitializationCause,
 36                                       ReadReqCause,
 37                                       ReadResCause,
 38                                       ReadCause,
 39                                       ClockSyncReqCause,
 40                                       ClockSyncResCause,
 41                                       ClockSyncCause,
 42                                       ActivationReqCause,
 43                                       ActivationResCause,
 44                                       ActivationCause,
 45                                       DelayReqCause,
 46                                       DelayResCause,
 47                                       DelayCause,
 48                                       ParameterReqCause,
 49                                       ParameterResCause,
 50                                       ParameterCause,
 51                                       ParameterActivationReqCause,
 52                                       ParameterActivationResCause,
 53                                       ParameterActivationCause,
 54                                       SingleData,
 55                                       DoubleData,
 56                                       StepPositionData,
 57                                       BitstringData,
 58                                       NormalizedData,
 59                                       ScaledData,
 60                                       FloatingData,
 61                                       BinaryCounterData,
 62                                       ProtectionData,
 63                                       ProtectionStartData,
 64                                       ProtectionCommandData,
 65                                       StatusData,
 66                                       Data,
 67                                       SingleCommand,
 68                                       DoubleCommand,
 69                                       RegulatingCommand,
 70                                       NormalizedCommand,
 71                                       ScaledCommand,
 72                                       FloatingCommand,
 73                                       BitstringCommand,
 74                                       Command,
 75                                       NormalizedParameter,
 76                                       ScaledParameter,
 77                                       FloatingParameter,
 78                                       Parameter,
 79                                       DataMsg,
 80                                       CommandMsg,
 81                                       InitializationMsg,
 82                                       InterrogationMsg,
 83                                       CounterInterrogationMsg,
 84                                       ReadMsg,
 85                                       ClockSyncMsg,
 86                                       TestMsg,
 87                                       ResetMsg,
 88                                       ParameterMsg,
 89                                       ParameterActivationMsg,
 90                                       Msg,
 91                                       time_from_datetime,
 92                                       time_to_datetime)
 93from hat.drivers.iec104.connection import (ConnectionCb,
 94                                           connect,
 95                                           listen,
 96                                           Connection)
 97
 98
 99__all__ = ['AsduTypeError',
100           'TimeSize',
101           'Time',
102           'OriginatorAddress',
103           'AsduAddress',
104           'IoAddress',
105           'IndicationQuality',
106           'MeasurementQuality',
107           'CounterQuality',
108           'ProtectionQuality',
109           'Quality',
110           'FreezeCode',
111           'SingleValue',
112           'DoubleValue',
113           'RegulatingValue',
114           'StepPositionValue',
115           'BitstringValue',
116           'NormalizedValue',
117           'ScaledValue',
118           'FloatingValue',
119           'BinaryCounterValue',
120           'ProtectionValue',
121           'ProtectionStartValue',
122           'ProtectionCommandValue',
123           'StatusValue',
124           'OtherCause',
125           'DataResCause',
126           'DataCause',
127           'CommandReqCause',
128           'CommandResCause',
129           'CommandCause',
130           'InitializationResCause',
131           'InitializationCause',
132           'ReadReqCause',
133           'ReadResCause',
134           'ReadCause',
135           'ClockSyncReqCause',
136           'ClockSyncResCause',
137           'ClockSyncCause',
138           'ActivationReqCause',
139           'ActivationResCause',
140           'ActivationCause',
141           'DelayReqCause',
142           'DelayResCause',
143           'DelayCause',
144           'ParameterReqCause',
145           'ParameterResCause',
146           'ParameterCause',
147           'ParameterActivationReqCause',
148           'ParameterActivationResCause',
149           'ParameterActivationCause',
150           'SingleData',
151           'DoubleData',
152           'StepPositionData',
153           'BitstringData',
154           'NormalizedData',
155           'ScaledData',
156           'FloatingData',
157           'BinaryCounterData',
158           'ProtectionData',
159           'ProtectionStartData',
160           'ProtectionCommandData',
161           'StatusData',
162           'Data',
163           'SingleCommand',
164           'DoubleCommand',
165           'RegulatingCommand',
166           'NormalizedCommand',
167           'ScaledCommand',
168           'FloatingCommand',
169           'BitstringCommand',
170           'Command',
171           'NormalizedParameter',
172           'ScaledParameter',
173           'FloatingParameter',
174           'Parameter',
175           'DataMsg',
176           'CommandMsg',
177           'InitializationMsg',
178           'InterrogationMsg',
179           'CounterInterrogationMsg',
180           'ReadMsg',
181           'ClockSyncMsg',
182           'TestMsg',
183           'ResetMsg',
184           'ParameterMsg',
185           'ParameterActivationMsg',
186           'Msg',
187           'time_from_datetime',
188           'time_to_datetime',
189           'ConnectionCb',
190           'connect',
191           'listen',
192           'Connection']
class AsduTypeError(builtins.Exception):
12class AsduTypeError(Exception):
13    pass

Common base class for all non-exit exceptions.

class TimeSize(enum.Enum):
24class TimeSize(enum.Enum):
25    TWO = 2
26    THREE = 3
27    FOUR = 4
28    SEVEN = 7
TWO = <TimeSize.TWO: 2>
THREE = <TimeSize.THREE: 3>
FOUR = <TimeSize.FOUR: 4>
SEVEN = <TimeSize.SEVEN: 7>
class Time(typing.NamedTuple):
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)

Time( size: TimeSize, milliseconds: int, invalid: bool | None, minutes: int | None, summer_time: bool | None, hours: int | None, day_of_week: int | None, day_of_month: int | None, months: int | None, years: int | None)

Create new instance of Time(size, milliseconds, invalid, minutes, summer_time, hours, day_of_week, day_of_month, months, years)

size: TimeSize

Alias for field number 0

milliseconds: int

milliseconds in range [0, 59999]

invalid: bool | None

available for size THREE, FOUR, SEVEN

minutes: int | None

available for size THREE, FOUR, SEVEN (minutes in range [0, 59])

summer_time: bool | None

available for size FOUR, SEVEN

hours: int | None

available for size FOUR, SEVEN (hours in range [0, 23])

day_of_week: int | None

available for size SEVEN (day_of_week in range [1, 7])

day_of_month: int | None

available for size SEVEN (day_of_month in range [1, 31])

months: int | None

available for size SEVEN (months in range [1, 12])

years: int | None

available for size SEVEN (years in range [0, 99])

OriginatorAddress = <class 'int'>
AsduAddress = <class 'int'>
IoAddress = <class 'int'>
class IndicationQuality(typing.NamedTuple):
147class IndicationQuality(typing.NamedTuple):
148    invalid: bool
149    not_topical: bool
150    substituted: bool
151    blocked: bool

IndicationQuality(invalid, not_topical, substituted, blocked)

IndicationQuality(invalid: bool, not_topical: bool, substituted: bool, blocked: bool)

Create new instance of IndicationQuality(invalid, not_topical, substituted, blocked)

invalid: bool

Alias for field number 0

not_topical: bool

Alias for field number 1

substituted: bool

Alias for field number 2

blocked: bool

Alias for field number 3

class MeasurementQuality(typing.NamedTuple):
154class MeasurementQuality(typing.NamedTuple):
155    invalid: bool
156    not_topical: bool
157    substituted: bool
158    blocked: bool
159    overflow: bool

MeasurementQuality(invalid, not_topical, substituted, blocked, overflow)

MeasurementQuality( invalid: bool, not_topical: bool, substituted: bool, blocked: bool, overflow: bool)

Create new instance of MeasurementQuality(invalid, not_topical, substituted, blocked, overflow)

invalid: bool

Alias for field number 0

not_topical: bool

Alias for field number 1

substituted: bool

Alias for field number 2

blocked: bool

Alias for field number 3

overflow: bool

Alias for field number 4

class CounterQuality(typing.NamedTuple):
162class CounterQuality(typing.NamedTuple):
163    invalid: bool
164    adjusted: bool
165    overflow: bool
166    sequence: int
167    """sequence in range [0, 31]"""

CounterQuality(invalid, adjusted, overflow, sequence)

CounterQuality(invalid: bool, adjusted: bool, overflow: bool, sequence: int)

Create new instance of CounterQuality(invalid, adjusted, overflow, sequence)

invalid: bool

Alias for field number 0

adjusted: bool

Alias for field number 1

overflow: bool

Alias for field number 2

sequence: int

sequence in range [0, 31]

class ProtectionQuality(typing.NamedTuple):
170class ProtectionQuality(typing.NamedTuple):
171    invalid: bool
172    not_topical: bool
173    substituted: bool
174    blocked: bool
175    time_invalid: bool

ProtectionQuality(invalid, not_topical, substituted, blocked, time_invalid)

ProtectionQuality( invalid: bool, not_topical: bool, substituted: bool, blocked: bool, time_invalid: bool)

Create new instance of ProtectionQuality(invalid, not_topical, substituted, blocked, time_invalid)

invalid: bool

Alias for field number 0

not_topical: bool

Alias for field number 1

substituted: bool

Alias for field number 2

blocked: bool

Alias for field number 3

time_invalid: bool

Alias for field number 4

class FreezeCode(enum.Enum):
184class FreezeCode(enum.Enum):
185    READ = 0
186    FREEZE = 1
187    FREEZE_AND_RESET = 2
188    RESET = 3
READ = <FreezeCode.READ: 0>
FREEZE = <FreezeCode.FREEZE: 1>
FREEZE_AND_RESET = <FreezeCode.FREEZE_AND_RESET: 2>
RESET = <FreezeCode.RESET: 3>
class SingleValue(enum.Enum):
191class SingleValue(enum.Enum):
192    OFF = 0
193    ON = 1
OFF = <SingleValue.OFF: 0>
ON = <SingleValue.ON: 1>
class DoubleValue(enum.Enum):
196class DoubleValue(enum.Enum):
197    """DoubleDataValue
198
199    `FAULT` stands for value 3, defined in the protocol as *INDETERMINATE*.
200    This is in order to make it more distinguishable from ``INTERMEDIATE``.
201
202    """
203    INTERMEDIATE = 0
204    OFF = 1
205    ON = 2
206    FAULT = 3

DoubleDataValue

FAULT stands for value 3, defined in the protocol as INDETERMINATE. This is in order to make it more distinguishable from INTERMEDIATE.

INTERMEDIATE = <DoubleValue.INTERMEDIATE: 0>
OFF = <DoubleValue.OFF: 1>
ON = <DoubleValue.ON: 2>
FAULT = <DoubleValue.FAULT: 3>
class RegulatingValue(enum.Enum):
209class RegulatingValue(enum.Enum):
210    LOWER = 1
211    HIGHER = 2
LOWER = <RegulatingValue.LOWER: 1>
HIGHER = <RegulatingValue.HIGHER: 2>
class StepPositionValue(typing.NamedTuple):
214class StepPositionValue(typing.NamedTuple):
215    value: int
216    """value in range [-64, 63]"""
217    transient: bool

StepPositionValue(value, transient)

StepPositionValue(value: int, transient: bool)

Create new instance of StepPositionValue(value, transient)

value: int

value in range [-64, 63]

transient: bool

Alias for field number 1

class BitstringValue(typing.NamedTuple):
220class BitstringValue(typing.NamedTuple):
221    value: util.Bytes
222    """bitstring encoded as 4 bytes"""

BitstringValue(value,)

BitstringValue(value: bytes | bytearray | memoryview)

Create new instance of BitstringValue(value,)

value: bytes | bytearray | memoryview

bitstring encoded as 4 bytes

class NormalizedValue(typing.NamedTuple):
225class NormalizedValue(typing.NamedTuple):
226    value: float
227    """value in range [-1.0, 1.0)"""

NormalizedValue(value,)

NormalizedValue(value: float)

Create new instance of NormalizedValue(value,)

value: float

value in range [-1.0, 1.0)

class ScaledValue(typing.NamedTuple):
230class ScaledValue(typing.NamedTuple):
231    value: int
232    """value in range [-2^15, 2^15-1]"""

ScaledValue(value,)

ScaledValue(value: int)

Create new instance of ScaledValue(value,)

value: int

value in range [-2^15, 2^15-1]

class FloatingValue(typing.NamedTuple):
235class FloatingValue(typing.NamedTuple):
236    value: float

FloatingValue(value,)

FloatingValue(value: float)

Create new instance of FloatingValue(value,)

value: float

Alias for field number 0

class BinaryCounterValue(typing.NamedTuple):
239class BinaryCounterValue(typing.NamedTuple):
240    value: int
241    """value in range [-2^31, 2^31-1]"""

BinaryCounterValue(value,)

BinaryCounterValue(value: int)

Create new instance of BinaryCounterValue(value,)

value: int

value in range [-2^31, 2^31-1]

class ProtectionValue(enum.Enum):
244class ProtectionValue(enum.Enum):
245    OFF = 1
246    ON = 2
OFF = <ProtectionValue.OFF: 1>
ON = <ProtectionValue.ON: 2>
class ProtectionStartValue(typing.NamedTuple):
249class ProtectionStartValue(typing.NamedTuple):
250    general: bool
251    l1: bool
252    l2: bool
253    l3: bool
254    ie: bool
255    reverse: bool

ProtectionStartValue(general, l1, l2, l3, ie, reverse)

ProtectionStartValue(general: bool, l1: bool, l2: bool, l3: bool, ie: bool, reverse: bool)

Create new instance of ProtectionStartValue(general, l1, l2, l3, ie, reverse)

general: bool

Alias for field number 0

l1: bool

Alias for field number 1

l2: bool

Alias for field number 2

l3: bool

Alias for field number 3

ie: bool

Alias for field number 4

reverse: bool

Alias for field number 5

class ProtectionCommandValue(typing.NamedTuple):
258class ProtectionCommandValue(typing.NamedTuple):
259    general: bool
260    l1: bool
261    l2: bool
262    l3: bool

ProtectionCommandValue(general, l1, l2, l3)

ProtectionCommandValue(general: bool, l1: bool, l2: bool, l3: bool)

Create new instance of ProtectionCommandValue(general, l1, l2, l3)

general: bool

Alias for field number 0

l1: bool

Alias for field number 1

l2: bool

Alias for field number 2

l3: bool

Alias for field number 3

class StatusValue(typing.NamedTuple):
265class StatusValue(typing.NamedTuple):
266    value: list[bool]
267    """value length is 16"""
268    change: list[bool]
269    """change length is 16"""

StatusValue(value, change)

StatusValue(value: list[bool], change: list[bool])

Create new instance of StatusValue(value, change)

value: list[bool]

value length is 16

change: list[bool]

change length is 16

OtherCause = <class 'int'>
class DataResCause(enum.Enum):
52class DataResCause(enum.Enum):
53    PERIODIC = iec101.CauseType.PERIODIC.value
54    BACKGROUND_SCAN = iec101.CauseType.BACKGROUND_SCAN.value
55    SPONTANEOUS = iec101.CauseType.SPONTANEOUS.value
56    REQUEST = iec101.CauseType.REQUEST.value
57    REMOTE_COMMAND = iec101.CauseType.REMOTE_COMMAND.value
58    LOCAL_COMMAND = iec101.CauseType.LOCAL_COMMAND.value
59    INTERROGATED_STATION = iec101.CauseType.INTERROGATED_STATION.value
60    INTERROGATED_GROUP01 = iec101.CauseType.INTERROGATED_GROUP01.value
61    INTERROGATED_GROUP02 = iec101.CauseType.INTERROGATED_GROUP02.value
62    INTERROGATED_GROUP03 = iec101.CauseType.INTERROGATED_GROUP03.value
63    INTERROGATED_GROUP04 = iec101.CauseType.INTERROGATED_GROUP04.value
64    INTERROGATED_GROUP05 = iec101.CauseType.INTERROGATED_GROUP05.value
65    INTERROGATED_GROUP06 = iec101.CauseType.INTERROGATED_GROUP06.value
66    INTERROGATED_GROUP07 = iec101.CauseType.INTERROGATED_GROUP07.value
67    INTERROGATED_GROUP08 = iec101.CauseType.INTERROGATED_GROUP08.value
68    INTERROGATED_GROUP09 = iec101.CauseType.INTERROGATED_GROUP09.value
69    INTERROGATED_GROUP10 = iec101.CauseType.INTERROGATED_GROUP10.value
70    INTERROGATED_GROUP11 = iec101.CauseType.INTERROGATED_GROUP11.value
71    INTERROGATED_GROUP12 = iec101.CauseType.INTERROGATED_GROUP12.value
72    INTERROGATED_GROUP13 = iec101.CauseType.INTERROGATED_GROUP13.value
73    INTERROGATED_GROUP14 = iec101.CauseType.INTERROGATED_GROUP14.value
74    INTERROGATED_GROUP15 = iec101.CauseType.INTERROGATED_GROUP15.value
75    INTERROGATED_GROUP16 = iec101.CauseType.INTERROGATED_GROUP16.value
76    INTERROGATED_COUNTER = iec101.CauseType.INTERROGATED_COUNTER.value
77    INTERROGATED_COUNTER01 = iec101.CauseType.INTERROGATED_COUNTER01.value
78    INTERROGATED_COUNTER02 = iec101.CauseType.INTERROGATED_COUNTER02.value
79    INTERROGATED_COUNTER03 = iec101.CauseType.INTERROGATED_COUNTER03.value
80    INTERROGATED_COUNTER04 = iec101.CauseType.INTERROGATED_COUNTER04.value
PERIODIC = <DataResCause.PERIODIC: 1>
BACKGROUND_SCAN = <DataResCause.BACKGROUND_SCAN: 2>
SPONTANEOUS = <DataResCause.SPONTANEOUS: 3>
REQUEST = <DataResCause.REQUEST: 5>
REMOTE_COMMAND = <DataResCause.REMOTE_COMMAND: 11>
LOCAL_COMMAND = <DataResCause.LOCAL_COMMAND: 12>
INTERROGATED_STATION = <DataResCause.INTERROGATED_STATION: 20>
INTERROGATED_GROUP01 = <DataResCause.INTERROGATED_GROUP01: 21>
INTERROGATED_GROUP02 = <DataResCause.INTERROGATED_GROUP02: 22>
INTERROGATED_GROUP03 = <DataResCause.INTERROGATED_GROUP03: 23>
INTERROGATED_GROUP04 = <DataResCause.INTERROGATED_GROUP04: 24>
INTERROGATED_GROUP05 = <DataResCause.INTERROGATED_GROUP05: 25>
INTERROGATED_GROUP06 = <DataResCause.INTERROGATED_GROUP06: 26>
INTERROGATED_GROUP07 = <DataResCause.INTERROGATED_GROUP07: 27>
INTERROGATED_GROUP08 = <DataResCause.INTERROGATED_GROUP08: 28>
INTERROGATED_GROUP09 = <DataResCause.INTERROGATED_GROUP09: 29>
INTERROGATED_GROUP10 = <DataResCause.INTERROGATED_GROUP10: 30>
INTERROGATED_GROUP11 = <DataResCause.INTERROGATED_GROUP11: 31>
INTERROGATED_GROUP12 = <DataResCause.INTERROGATED_GROUP12: 32>
INTERROGATED_GROUP13 = <DataResCause.INTERROGATED_GROUP13: 33>
INTERROGATED_GROUP14 = <DataResCause.INTERROGATED_GROUP14: 34>
INTERROGATED_GROUP15 = <DataResCause.INTERROGATED_GROUP15: 35>
INTERROGATED_GROUP16 = <DataResCause.INTERROGATED_GROUP16: 36>
INTERROGATED_COUNTER = <DataResCause.INTERROGATED_COUNTER: 37>
INTERROGATED_COUNTER01 = <DataResCause.INTERROGATED_COUNTER01: 38>
INTERROGATED_COUNTER02 = <DataResCause.INTERROGATED_COUNTER02: 39>
INTERROGATED_COUNTER03 = <DataResCause.INTERROGATED_COUNTER03: 40>
INTERROGATED_COUNTER04 = <DataResCause.INTERROGATED_COUNTER04: 41>
DataCause = DataResCause | int
class CommandReqCause(enum.Enum):
86class CommandReqCause(enum.Enum):
87    ACTIVATION = iec101.CauseType.ACTIVATION.value
88    DEACTIVATION = iec101.CauseType.DEACTIVATION.value
ACTIVATION = <CommandReqCause.ACTIVATION: 6>
DEACTIVATION = <CommandReqCause.DEACTIVATION: 8>
class CommandResCause(enum.Enum):
91class CommandResCause(enum.Enum):
92    ACTIVATION_CONFIRMATION = iec101.CauseType.ACTIVATION_CONFIRMATION.value
93    DEACTIVATION_CONFIRMATION = iec101.CauseType.DEACTIVATION_CONFIRMATION.value  # NOQA
94    ACTIVATION_TERMINATION = iec101.CauseType.ACTIVATION_TERMINATION.value
95    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
96    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
97    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
98    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
ACTIVATION_CONFIRMATION = <CommandResCause.ACTIVATION_CONFIRMATION: 7>
DEACTIVATION_CONFIRMATION = <CommandResCause.DEACTIVATION_CONFIRMATION: 9>
ACTIVATION_TERMINATION = <CommandResCause.ACTIVATION_TERMINATION: 10>
UNKNOWN_TYPE = <CommandResCause.UNKNOWN_TYPE: 44>
UNKNOWN_CAUSE = <CommandResCause.UNKNOWN_CAUSE: 45>
UNKNOWN_ASDU_ADDRESS = <CommandResCause.UNKNOWN_ASDU_ADDRESS: 46>
UNKNOWN_IO_ADDRESS = <CommandResCause.UNKNOWN_IO_ADDRESS: 47>
CommandCause = CommandReqCause | CommandResCause | int
class InitializationResCause(enum.Enum):
104class InitializationResCause(enum.Enum):
105    LOCAL_POWER = 0
106    LOCAL_RESET = 1
107    REMOTE_RESET = 2
InitializationCause = InitializationResCause | int
class ReadReqCause(enum.Enum):
113class ReadReqCause(enum.Enum):
114    REQUEST = iec101.CauseType.REQUEST.value
REQUEST = <ReadReqCause.REQUEST: 5>
class ReadResCause(enum.Enum):
117class ReadResCause(enum.Enum):
118    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
119    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
120    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
121    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
UNKNOWN_TYPE = <ReadResCause.UNKNOWN_TYPE: 44>
UNKNOWN_CAUSE = <ReadResCause.UNKNOWN_CAUSE: 45>
UNKNOWN_ASDU_ADDRESS = <ReadResCause.UNKNOWN_ASDU_ADDRESS: 46>
UNKNOWN_IO_ADDRESS = <ReadResCause.UNKNOWN_IO_ADDRESS: 47>
ReadCause = ReadReqCause | ReadResCause | int
class ClockSyncReqCause(enum.Enum):
127class ClockSyncReqCause(enum.Enum):
128    ACTIVATION = iec101.CauseType.ACTIVATION.value
ACTIVATION = <ClockSyncReqCause.ACTIVATION: 6>
class ClockSyncResCause(enum.Enum):
131class ClockSyncResCause(enum.Enum):
132    SPONTANEOUS = iec101.CauseType.SPONTANEOUS.value
133    ACTIVATION_CONFIRMATION = iec101.CauseType.ACTIVATION_CONFIRMATION.value
134    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
135    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
136    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
137    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
SPONTANEOUS = <ClockSyncResCause.SPONTANEOUS: 3>
ACTIVATION_CONFIRMATION = <ClockSyncResCause.ACTIVATION_CONFIRMATION: 7>
UNKNOWN_TYPE = <ClockSyncResCause.UNKNOWN_TYPE: 44>
UNKNOWN_CAUSE = <ClockSyncResCause.UNKNOWN_CAUSE: 45>
UNKNOWN_ASDU_ADDRESS = <ClockSyncResCause.UNKNOWN_ASDU_ADDRESS: 46>
UNKNOWN_IO_ADDRESS = <ClockSyncResCause.UNKNOWN_IO_ADDRESS: 47>
ClockSyncCause = ClockSyncReqCause | ClockSyncResCause | int
class ActivationReqCause(enum.Enum):
145class ActivationReqCause(enum.Enum):
146    ACTIVATION = iec101.CauseType.ACTIVATION.value
ACTIVATION = <ActivationReqCause.ACTIVATION: 6>
class ActivationResCause(enum.Enum):
149class ActivationResCause(enum.Enum):
150    ACTIVATION_CONFIRMATION = iec101.CauseType.ACTIVATION_CONFIRMATION.value
151    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
152    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
153    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
154    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
ACTIVATION_CONFIRMATION = <ActivationResCause.ACTIVATION_CONFIRMATION: 7>
UNKNOWN_TYPE = <ActivationResCause.UNKNOWN_TYPE: 44>
UNKNOWN_CAUSE = <ActivationResCause.UNKNOWN_CAUSE: 45>
UNKNOWN_ASDU_ADDRESS = <ActivationResCause.UNKNOWN_ASDU_ADDRESS: 46>
UNKNOWN_IO_ADDRESS = <ActivationResCause.UNKNOWN_IO_ADDRESS: 47>
ActivationCause = ActivationReqCause | ActivationResCause | int
class DelayReqCause(enum.Enum):
162class DelayReqCause(enum.Enum):
163    SPONTANEOUS = iec101.CauseType.SPONTANEOUS.value
164    ACTIVATION = iec101.CauseType.ACTIVATION.value
SPONTANEOUS = <DelayReqCause.SPONTANEOUS: 3>
ACTIVATION = <DelayReqCause.ACTIVATION: 6>
class DelayResCause(enum.Enum):
167class DelayResCause(enum.Enum):
168    ACTIVATION_CONFIRMATION = iec101.CauseType.ACTIVATION_CONFIRMATION.value
169    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
170    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
171    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
172    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
ACTIVATION_CONFIRMATION = <DelayResCause.ACTIVATION_CONFIRMATION: 7>
UNKNOWN_TYPE = <DelayResCause.UNKNOWN_TYPE: 44>
UNKNOWN_CAUSE = <DelayResCause.UNKNOWN_CAUSE: 45>
UNKNOWN_ASDU_ADDRESS = <DelayResCause.UNKNOWN_ASDU_ADDRESS: 46>
UNKNOWN_IO_ADDRESS = <DelayResCause.UNKNOWN_IO_ADDRESS: 47>
DelayCause = DelayReqCause | DelayResCause | int
class ParameterReqCause(enum.Enum):
178class ParameterReqCause(enum.Enum):
179    SPONTANEOUS = iec101.CauseType.SPONTANEOUS.value
180    ACTIVATION = iec101.CauseType.ACTIVATION.value
SPONTANEOUS = <ParameterReqCause.SPONTANEOUS: 3>
ACTIVATION = <ParameterReqCause.ACTIVATION: 6>
class ParameterResCause(enum.Enum):
183class ParameterResCause(enum.Enum):
184    ACTIVATION_CONFIRMATION = iec101.CauseType.ACTIVATION_CONFIRMATION.value
185    INTERROGATED_STATION = iec101.CauseType.INTERROGATED_STATION.value
186    INTERROGATED_GROUP01 = iec101.CauseType.INTERROGATED_GROUP01.value
187    INTERROGATED_GROUP02 = iec101.CauseType.INTERROGATED_GROUP02.value
188    INTERROGATED_GROUP03 = iec101.CauseType.INTERROGATED_GROUP03.value
189    INTERROGATED_GROUP04 = iec101.CauseType.INTERROGATED_GROUP04.value
190    INTERROGATED_GROUP05 = iec101.CauseType.INTERROGATED_GROUP05.value
191    INTERROGATED_GROUP06 = iec101.CauseType.INTERROGATED_GROUP06.value
192    INTERROGATED_GROUP07 = iec101.CauseType.INTERROGATED_GROUP07.value
193    INTERROGATED_GROUP08 = iec101.CauseType.INTERROGATED_GROUP08.value
194    INTERROGATED_GROUP09 = iec101.CauseType.INTERROGATED_GROUP09.value
195    INTERROGATED_GROUP10 = iec101.CauseType.INTERROGATED_GROUP10.value
196    INTERROGATED_GROUP11 = iec101.CauseType.INTERROGATED_GROUP11.value
197    INTERROGATED_GROUP12 = iec101.CauseType.INTERROGATED_GROUP12.value
198    INTERROGATED_GROUP13 = iec101.CauseType.INTERROGATED_GROUP13.value
199    INTERROGATED_GROUP14 = iec101.CauseType.INTERROGATED_GROUP14.value
200    INTERROGATED_GROUP15 = iec101.CauseType.INTERROGATED_GROUP15.value
201    INTERROGATED_GROUP16 = iec101.CauseType.INTERROGATED_GROUP16.value
202    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
203    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
204    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
205    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
ACTIVATION_CONFIRMATION = <ParameterResCause.ACTIVATION_CONFIRMATION: 7>
INTERROGATED_STATION = <ParameterResCause.INTERROGATED_STATION: 20>
INTERROGATED_GROUP01 = <ParameterResCause.INTERROGATED_GROUP01: 21>
INTERROGATED_GROUP02 = <ParameterResCause.INTERROGATED_GROUP02: 22>
INTERROGATED_GROUP03 = <ParameterResCause.INTERROGATED_GROUP03: 23>
INTERROGATED_GROUP04 = <ParameterResCause.INTERROGATED_GROUP04: 24>
INTERROGATED_GROUP05 = <ParameterResCause.INTERROGATED_GROUP05: 25>
INTERROGATED_GROUP06 = <ParameterResCause.INTERROGATED_GROUP06: 26>
INTERROGATED_GROUP07 = <ParameterResCause.INTERROGATED_GROUP07: 27>
INTERROGATED_GROUP08 = <ParameterResCause.INTERROGATED_GROUP08: 28>
INTERROGATED_GROUP09 = <ParameterResCause.INTERROGATED_GROUP09: 29>
INTERROGATED_GROUP10 = <ParameterResCause.INTERROGATED_GROUP10: 30>
INTERROGATED_GROUP11 = <ParameterResCause.INTERROGATED_GROUP11: 31>
INTERROGATED_GROUP12 = <ParameterResCause.INTERROGATED_GROUP12: 32>
INTERROGATED_GROUP13 = <ParameterResCause.INTERROGATED_GROUP13: 33>
INTERROGATED_GROUP14 = <ParameterResCause.INTERROGATED_GROUP14: 34>
INTERROGATED_GROUP15 = <ParameterResCause.INTERROGATED_GROUP15: 35>
INTERROGATED_GROUP16 = <ParameterResCause.INTERROGATED_GROUP16: 36>
UNKNOWN_TYPE = <ParameterResCause.UNKNOWN_TYPE: 44>
UNKNOWN_CAUSE = <ParameterResCause.UNKNOWN_CAUSE: 45>
UNKNOWN_ASDU_ADDRESS = <ParameterResCause.UNKNOWN_ASDU_ADDRESS: 46>
UNKNOWN_IO_ADDRESS = <ParameterResCause.UNKNOWN_IO_ADDRESS: 47>
ParameterCause = ParameterReqCause | ParameterResCause | int
class ParameterActivationReqCause(enum.Enum):
213class ParameterActivationReqCause(enum.Enum):
214    ACTIVATION = iec101.CauseType.ACTIVATION.value
215    DEACTIVATION = iec101.CauseType.DEACTIVATION.value
class ParameterActivationResCause(enum.Enum):
218class ParameterActivationResCause(enum.Enum):
219    ACTIVATION_CONFIRMATION = iec101.CauseType.ACTIVATION_CONFIRMATION.value
220    DEACTIVATION_CONFIRMATION = iec101.CauseType.DEACTIVATION_CONFIRMATION.value  # NOQA
221    UNKNOWN_TYPE = iec101.CauseType.UNKNOWN_TYPE.value
222    UNKNOWN_CAUSE = iec101.CauseType.UNKNOWN_CAUSE.value
223    UNKNOWN_ASDU_ADDRESS = iec101.CauseType.UNKNOWN_ASDU_ADDRESS.value
224    UNKNOWN_IO_ADDRESS = iec101.CauseType.UNKNOWN_IO_ADDRESS.value
ParameterActivationCause = ParameterActivationReqCause | ParameterActivationResCause | int
class SingleData(typing.NamedTuple):
232class SingleData(typing.NamedTuple):
233    value: SingleValue
234    quality: IndicationQuality

SingleData(value, quality)

SingleData( value: SingleValue, quality: IndicationQuality)

Create new instance of SingleData(value, quality)

value: SingleValue

Alias for field number 0

Alias for field number 1

class DoubleData(typing.NamedTuple):
237class DoubleData(typing.NamedTuple):
238    value: DoubleValue
239    quality: IndicationQuality

DoubleData(value, quality)

DoubleData( value: DoubleValue, quality: IndicationQuality)

Create new instance of DoubleData(value, quality)

value: DoubleValue

Alias for field number 0

Alias for field number 1

class StepPositionData(typing.NamedTuple):
242class StepPositionData(typing.NamedTuple):
243    value: StepPositionValue
244    quality: MeasurementQuality

StepPositionData(value, quality)

StepPositionData( value: StepPositionValue, quality: MeasurementQuality)

Create new instance of StepPositionData(value, quality)

Alias for field number 0

Alias for field number 1

class BitstringData(typing.NamedTuple):
247class BitstringData(typing.NamedTuple):
248    value: BitstringValue
249    quality: MeasurementQuality

BitstringData(value, quality)

BitstringData( value: BitstringValue, quality: MeasurementQuality)

Create new instance of BitstringData(value, quality)

Alias for field number 0

Alias for field number 1

class NormalizedData(typing.NamedTuple):
252class NormalizedData(typing.NamedTuple):
253    value: NormalizedValue
254    quality: MeasurementQuality | None

NormalizedData(value, quality)

NormalizedData( value: NormalizedValue, quality: MeasurementQuality | None)

Create new instance of NormalizedData(value, quality)

Alias for field number 0

quality: MeasurementQuality | None

Alias for field number 1

class ScaledData(typing.NamedTuple):
257class ScaledData(typing.NamedTuple):
258    value: ScaledValue
259    quality: MeasurementQuality

ScaledData(value, quality)

ScaledData( value: ScaledValue, quality: MeasurementQuality)

Create new instance of ScaledData(value, quality)

value: ScaledValue

Alias for field number 0

Alias for field number 1

class FloatingData(typing.NamedTuple):
262class FloatingData(typing.NamedTuple):
263    value: FloatingValue
264    quality: MeasurementQuality

FloatingData(value, quality)

FloatingData( value: FloatingValue, quality: MeasurementQuality)

Create new instance of FloatingData(value, quality)

value: FloatingValue

Alias for field number 0

Alias for field number 1

class BinaryCounterData(typing.NamedTuple):
267class BinaryCounterData(typing.NamedTuple):
268    value: BinaryCounterValue
269    quality: CounterQuality

BinaryCounterData(value, quality)

BinaryCounterData( value: BinaryCounterValue, quality: CounterQuality)

Create new instance of BinaryCounterData(value, quality)

Alias for field number 0

quality: CounterQuality

Alias for field number 1

class ProtectionData(typing.NamedTuple):
272class ProtectionData(typing.NamedTuple):
273    value: ProtectionValue
274    quality: ProtectionQuality
275    elapsed_time: int
276    """elapsed_time in range [0, 65535]"""

ProtectionData(value, quality, elapsed_time)

ProtectionData( value: ProtectionValue, quality: ProtectionQuality, elapsed_time: int)

Create new instance of ProtectionData(value, quality, elapsed_time)

Alias for field number 0

Alias for field number 1

elapsed_time: int

elapsed_time in range [0, 65535]

class ProtectionStartData(typing.NamedTuple):
279class ProtectionStartData(typing.NamedTuple):
280    value: ProtectionStartValue
281    quality: ProtectionQuality
282    duration_time: int
283    """duration_time in range [0, 65535]"""

ProtectionStartData(value, quality, duration_time)

ProtectionStartData( value: ProtectionStartValue, quality: ProtectionQuality, duration_time: int)

Create new instance of ProtectionStartData(value, quality, duration_time)

Alias for field number 0

Alias for field number 1

duration_time: int

duration_time in range [0, 65535]

class ProtectionCommandData(typing.NamedTuple):
286class ProtectionCommandData(typing.NamedTuple):
287    value: ProtectionCommandValue
288    quality: ProtectionQuality
289    operating_time: int
290    """operating_time in range [0, 65535]"""

ProtectionCommandData(value, quality, operating_time)

ProtectionCommandData( value: ProtectionCommandValue, quality: ProtectionQuality, operating_time: int)

Create new instance of ProtectionCommandData(value, quality, operating_time)

Alias for field number 0

Alias for field number 1

operating_time: int

operating_time in range [0, 65535]

class StatusData(typing.NamedTuple):
293class StatusData(typing.NamedTuple):
294    value: StatusValue
295    quality: MeasurementQuality

StatusData(value, quality)

StatusData( value: StatusValue, quality: MeasurementQuality)

Create new instance of StatusData(value, quality)

value: StatusValue

Alias for field number 0

Alias for field number 1

class SingleCommand(typing.NamedTuple):
312class SingleCommand(typing.NamedTuple):
313    value: SingleValue
314    select: bool
315    qualifier: int
316    """qualifier in range [0, 31]"""

SingleCommand(value, select, qualifier)

SingleCommand( value: SingleValue, select: bool, qualifier: int)

Create new instance of SingleCommand(value, select, qualifier)

value: SingleValue

Alias for field number 0

select: bool

Alias for field number 1

qualifier: int

qualifier in range [0, 31]

class DoubleCommand(typing.NamedTuple):
319class DoubleCommand(typing.NamedTuple):
320    value: DoubleValue
321    select: bool
322    qualifier: int
323    """qualifier in range [0, 31]"""

DoubleCommand(value, select, qualifier)

DoubleCommand( value: DoubleValue, select: bool, qualifier: int)

Create new instance of DoubleCommand(value, select, qualifier)

value: DoubleValue

Alias for field number 0

select: bool

Alias for field number 1

qualifier: int

qualifier in range [0, 31]

class RegulatingCommand(typing.NamedTuple):
326class RegulatingCommand(typing.NamedTuple):
327    value: RegulatingValue
328    select: bool
329    qualifier: int
330    """qualifier in range [0, 31]"""

RegulatingCommand(value, select, qualifier)

RegulatingCommand( value: RegulatingValue, select: bool, qualifier: int)

Create new instance of RegulatingCommand(value, select, qualifier)

Alias for field number 0

select: bool

Alias for field number 1

qualifier: int

qualifier in range [0, 31]

class NormalizedCommand(typing.NamedTuple):
333class NormalizedCommand(typing.NamedTuple):
334    value: NormalizedValue
335    select: bool

NormalizedCommand(value, select)

NormalizedCommand( value: NormalizedValue, select: bool)

Create new instance of NormalizedCommand(value, select)

Alias for field number 0

select: bool

Alias for field number 1

class ScaledCommand(typing.NamedTuple):
338class ScaledCommand(typing.NamedTuple):
339    value: ScaledValue
340    select: bool

ScaledCommand(value, select)

ScaledCommand( value: ScaledValue, select: bool)

Create new instance of ScaledCommand(value, select)

value: ScaledValue

Alias for field number 0

select: bool

Alias for field number 1

class FloatingCommand(typing.NamedTuple):
343class FloatingCommand(typing.NamedTuple):
344    value: FloatingValue
345    select: bool

FloatingCommand(value, select)

FloatingCommand( value: FloatingValue, select: bool)

Create new instance of FloatingCommand(value, select)

value: FloatingValue

Alias for field number 0

select: bool

Alias for field number 1

class BitstringCommand(typing.NamedTuple):
348class BitstringCommand(typing.NamedTuple):
349    value: BitstringValue

BitstringCommand(value,)

BitstringCommand(value: BitstringValue)

Create new instance of BitstringCommand(value,)

Alias for field number 0

class NormalizedParameter(typing.NamedTuple):
361class NormalizedParameter(typing.NamedTuple):
362    value: NormalizedValue
363    qualifier: int
364    """qualifier in range [0, 255]"""

NormalizedParameter(value, qualifier)

NormalizedParameter( value: NormalizedValue, qualifier: int)

Create new instance of NormalizedParameter(value, qualifier)

Alias for field number 0

qualifier: int

qualifier in range [0, 255]

class ScaledParameter(typing.NamedTuple):
367class ScaledParameter(typing.NamedTuple):
368    value: ScaledValue
369    qualifier: int
370    """qualifier in range [0, 255]"""

ScaledParameter(value, qualifier)

ScaledParameter( value: ScaledValue, qualifier: int)

Create new instance of ScaledParameter(value, qualifier)

value: ScaledValue

Alias for field number 0

qualifier: int

qualifier in range [0, 255]

class FloatingParameter(typing.NamedTuple):
373class FloatingParameter(typing.NamedTuple):
374    value: FloatingValue
375    qualifier: int
376    """qualifier in range [0, 255]"""

FloatingParameter(value, qualifier)

FloatingParameter( value: FloatingValue, qualifier: int)

Create new instance of FloatingParameter(value, qualifier)

value: FloatingValue

Alias for field number 0

qualifier: int

qualifier in range [0, 255]

class DataMsg(typing.NamedTuple):
384class DataMsg(typing.NamedTuple):
385    is_test: bool
386    originator_address: OriginatorAddress
387    asdu_address: AsduAddress
388    io_address: IoAddress
389    data: Data
390    time: Time | None
391    cause: DataCause

DataMsg(is_test, originator_address, asdu_address, io_address, data, time, cause)

DataMsg( is_test: bool, originator_address: int, asdu_address: int, io_address: int, data: SingleData | DoubleData | StepPositionData | BitstringData | NormalizedData | ScaledData | FloatingData | BinaryCounterData | ProtectionData | ProtectionStartData | ProtectionCommandData | StatusData, time: Time | None, cause: DataResCause | int)

Create new instance of DataMsg(is_test, originator_address, asdu_address, io_address, data, time, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

io_address: int

Alias for field number 3

time: Time | None

Alias for field number 5

cause: DataResCause | int

Alias for field number 6

class CommandMsg(typing.NamedTuple):
120class CommandMsg(typing.NamedTuple):
121    is_test: bool
122    originator_address: OriginatorAddress
123    asdu_address: AsduAddress
124    io_address: IoAddress
125    command: Command
126    is_negative_confirm: bool
127    time: Time | None
128    cause: CommandCause

CommandMsg(is_test, originator_address, asdu_address, io_address, command, is_negative_confirm, time, cause)

CommandMsg( is_test: bool, originator_address: int, asdu_address: int, io_address: int, command: SingleCommand | DoubleCommand | RegulatingCommand | NormalizedCommand | ScaledCommand | FloatingCommand | BitstringCommand, is_negative_confirm: bool, time: Time | None, cause: CommandReqCause | CommandResCause | int)

Create new instance of CommandMsg(is_test, originator_address, asdu_address, io_address, command, is_negative_confirm, time, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

io_address: int

Alias for field number 3

is_negative_confirm: bool

Alias for field number 5

time: Time | None

Alias for field number 6

Alias for field number 7

class InitializationMsg(typing.NamedTuple):
404class InitializationMsg(typing.NamedTuple):
405    is_test: bool
406    originator_address: OriginatorAddress
407    asdu_address: AsduAddress
408    param_change: bool
409    cause: InitializationCause

InitializationMsg(is_test, originator_address, asdu_address, param_change, cause)

InitializationMsg( is_test: bool, originator_address: int, asdu_address: int, param_change: bool, cause: InitializationResCause | int)

Create new instance of InitializationMsg(is_test, originator_address, asdu_address, param_change, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

param_change: bool

Alias for field number 3

cause: InitializationResCause | int

Alias for field number 4

class InterrogationMsg(typing.NamedTuple):
412class InterrogationMsg(typing.NamedTuple):
413    is_test: bool
414    originator_address: OriginatorAddress
415    asdu_address: AsduAddress
416    request: int
417    """request in range [0, 255]"""
418    is_negative_confirm: bool
419    cause: CommandCause

InterrogationMsg(is_test, originator_address, asdu_address, request, is_negative_confirm, cause)

InterrogationMsg( is_test: bool, originator_address: int, asdu_address: int, request: int, is_negative_confirm: bool, cause: CommandReqCause | CommandResCause | int)

Create new instance of InterrogationMsg(is_test, originator_address, asdu_address, request, is_negative_confirm, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

request: int

request in range [0, 255]

is_negative_confirm: bool

Alias for field number 4

Alias for field number 5

class CounterInterrogationMsg(typing.NamedTuple):
422class CounterInterrogationMsg(typing.NamedTuple):
423    is_test: bool
424    originator_address: OriginatorAddress
425    asdu_address: AsduAddress
426    request: int
427    """request in range [0, 63]"""
428    freeze: FreezeCode
429    is_negative_confirm: bool
430    cause: CommandCause

CounterInterrogationMsg(is_test, originator_address, asdu_address, request, freeze, is_negative_confirm, cause)

CounterInterrogationMsg( is_test: bool, originator_address: int, asdu_address: int, request: int, freeze: FreezeCode, is_negative_confirm: bool, cause: CommandReqCause | CommandResCause | int)

Create new instance of CounterInterrogationMsg(is_test, originator_address, asdu_address, request, freeze, is_negative_confirm, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

request: int

request in range [0, 63]

freeze: FreezeCode

Alias for field number 4

is_negative_confirm: bool

Alias for field number 5

Alias for field number 6

class ReadMsg(typing.NamedTuple):
433class ReadMsg(typing.NamedTuple):
434    is_test: bool
435    originator_address: OriginatorAddress
436    asdu_address: AsduAddress
437    io_address: IoAddress
438    cause: ReadCause

ReadMsg(is_test, originator_address, asdu_address, io_address, cause)

ReadMsg( is_test: bool, originator_address: int, asdu_address: int, io_address: int, cause: ReadReqCause | ReadResCause | int)

Create new instance of ReadMsg(is_test, originator_address, asdu_address, io_address, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

io_address: int

Alias for field number 3

cause: ReadReqCause | ReadResCause | int

Alias for field number 4

class ClockSyncMsg(typing.NamedTuple):
441class ClockSyncMsg(typing.NamedTuple):
442    is_test: bool
443    originator_address: OriginatorAddress
444    asdu_address: AsduAddress
445    time: Time
446    is_negative_confirm: bool
447    cause: ClockSyncCause

ClockSyncMsg(is_test, originator_address, asdu_address, time, is_negative_confirm, cause)

ClockSyncMsg( is_test: bool, originator_address: int, asdu_address: int, time: Time, is_negative_confirm: bool, cause: ClockSyncReqCause | ClockSyncResCause | int)

Create new instance of ClockSyncMsg(is_test, originator_address, asdu_address, time, is_negative_confirm, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

time: Time

Alias for field number 3

is_negative_confirm: bool

Alias for field number 4

Alias for field number 5

class TestMsg(typing.NamedTuple):
131class TestMsg(typing.NamedTuple):
132    is_test: bool
133    originator_address: OriginatorAddress
134    asdu_address: AsduAddress
135    counter: int
136    """counter in range [0, 65535]"""
137    time: Time
138    cause: ActivationCause

TestMsg(is_test, originator_address, asdu_address, counter, time, cause)

TestMsg( is_test: bool, originator_address: int, asdu_address: int, counter: int, time: Time, cause: ActivationReqCause | ActivationResCause | int)

Create new instance of TestMsg(is_test, originator_address, asdu_address, counter, time, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

counter: int

counter in range [0, 65535]

time: Time

Alias for field number 4

Alias for field number 5

class ResetMsg(typing.NamedTuple):
457class ResetMsg(typing.NamedTuple):
458    is_test: bool
459    originator_address: OriginatorAddress
460    asdu_address: AsduAddress
461    qualifier: int
462    """qualifier in range [0, 255]"""
463    cause: ActivationCause

ResetMsg(is_test, originator_address, asdu_address, qualifier, cause)

ResetMsg( is_test: bool, originator_address: int, asdu_address: int, qualifier: int, cause: ActivationReqCause | ActivationResCause | int)

Create new instance of ResetMsg(is_test, originator_address, asdu_address, qualifier, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

qualifier: int

qualifier in range [0, 255]

Alias for field number 4

class ParameterMsg(typing.NamedTuple):
475class ParameterMsg(typing.NamedTuple):
476    is_test: bool
477    originator_address: OriginatorAddress
478    asdu_address: AsduAddress
479    io_address: IoAddress
480    parameter: Parameter
481    cause: ParameterCause

ParameterMsg(is_test, originator_address, asdu_address, io_address, parameter, cause)

ParameterMsg( is_test: bool, originator_address: int, asdu_address: int, io_address: int, parameter: NormalizedParameter | ScaledParameter | FloatingParameter, cause: ParameterReqCause | ParameterResCause | int)

Create new instance of ParameterMsg(is_test, originator_address, asdu_address, io_address, parameter, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

io_address: int

Alias for field number 3

Alias for field number 4

Alias for field number 5

class ParameterActivationMsg(typing.NamedTuple):
484class ParameterActivationMsg(typing.NamedTuple):
485    is_test: bool
486    originator_address: OriginatorAddress
487    asdu_address: AsduAddress
488    io_address: IoAddress
489    qualifier: int
490    """qualifier in range [0, 255]"""
491    cause: ParameterActivationCause

ParameterActivationMsg(is_test, originator_address, asdu_address, io_address, qualifier, cause)

ParameterActivationMsg( is_test: bool, originator_address: int, asdu_address: int, io_address: int, qualifier: int, cause: ParameterActivationReqCause | ParameterActivationResCause | int)

Create new instance of ParameterActivationMsg(is_test, originator_address, asdu_address, io_address, qualifier, cause)

is_test: bool

Alias for field number 0

originator_address: int

Alias for field number 1

asdu_address: int

Alias for field number 2

io_address: int

Alias for field number 3

qualifier: int

qualifier in range [0, 255]

Alias for field number 5

def time_from_datetime( dt: datetime.datetime, invalid: bool = False) -> Time:
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

def time_to_datetime(t: Time) -> 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 support TimeSize.FOUR
 96    if t.size == TimeSize.TWO:
 97        local_now = datetime.datetime.now()
 98        local_dt = local_now.replace(
 99            second=int(t.milliseconds / 1000),
100            microsecond=(t.milliseconds % 1000) * 1000)
101
102        local_seconds = local_now.second + local_now.microsecond / 1_000_000
103        t_seconds = t.milliseconds / 1_000
104
105        if abs(local_seconds - t_seconds) > 30:
106            if local_seconds < t_seconds:
107                local_dt = local_dt - datetime.timedelta(minutes=1)
108
109            else:
110                local_dt = local_dt + datetime.timedelta(minutes=1)
111
112    elif t.size == TimeSize.THREE:
113        local_now = datetime.datetime.now()
114        local_dt = local_now.replace(
115            minute=t.minutes,
116            second=int(t.milliseconds / 1000),
117            microsecond=(t.milliseconds % 1000) * 1000)
118
119        local_minutes = (local_now.minute +
120                         local_now.second / 60 +
121                         local_now.microsecond / 60_000_000)
122        t_minutes = t.minutes + t.milliseconds / 60_000
123
124        if abs(local_minutes - t_minutes) > 30:
125            if local_minutes < t_minutes:
126                local_dt = local_dt - datetime.timedelta(hours=1)
127
128            else:
129                local_dt = local_dt + datetime.timedelta(hours=1)
130
131    elif t.size == TimeSize.SEVEN:
132        local_dt = datetime.datetime(
133            year=2000 + t.years if t.years < 70 else 1900 + t.years,
134            month=t.months,
135            day=t.day_of_month,
136            hour=t.hours,
137            minute=t.minutes,
138            second=int(t.milliseconds / 1000),
139            microsecond=(t.milliseconds % 1000) * 1000,
140            fold=not t.summer_time)
141
142    else:
143        raise ValueError('unsupported time size')
144
145    return local_dt.astimezone(tz=datetime.timezone.utc)

Convert Time to datetime.datetime

ConnectionCb = typing.Callable[[ForwardRef('Connection')], None | collections.abc.Awaitable[None]]
async def connect( addr: hat.drivers.tcp.Address, *, response_timeout: float = 15, supervisory_timeout: float = 10, test_timeout: float = 20, send_window_size: int = 12, receive_window_size: int = 8, **kwargs) -> Connection:
22async def connect(addr: tcp.Address,
23                  *,
24                  response_timeout: float = 15,
25                  supervisory_timeout: float = 10,
26                  test_timeout: float = 20,
27                  send_window_size: int = 12,
28                  receive_window_size: int = 8,
29                  **kwargs
30                  ) -> 'Connection':
31    conn = await apci.connect(addr=addr,
32                              response_timeout=response_timeout,
33                              supervisory_timeout=supervisory_timeout,
34                              test_timeout=test_timeout,
35                              send_window_size=send_window_size,
36                              receive_window_size=receive_window_size,
37                              **kwargs)
38
39    return Connection(conn)
async def listen( connection_cb: Callable[[Connection], None | Awaitable[None]], addr: hat.drivers.tcp.Address = Address(host='0.0.0.0', port=2404), *, response_timeout: float = 15, supervisory_timeout: float = 10, test_timeout: float = 20, send_window_size: int = 12, receive_window_size: int = 8, **kwargs) -> hat.drivers.tcp.Server:
42async def listen(connection_cb: ConnectionCb,
43                 addr: tcp.Address = tcp.Address('0.0.0.0', 2404),
44                 *,
45                 response_timeout: float = 15,
46                 supervisory_timeout: float = 10,
47                 test_timeout: float = 20,
48                 send_window_size: int = 12,
49                 receive_window_size: int = 8,
50                 **kwargs
51                 ) -> tcp.Server:
52    log = logger.create_server_logger(mlog, kwargs.get('name'), None)
53
54    async def on_connection(conn):
55        try:
56            try:
57                conn = Connection(conn)
58                await aio.call(connection_cb, conn)
59
60            except BaseException:
61                await aio.uncancellable(conn.async_close())
62                raise
63
64        except Exception as e:
65            log.error("on connection error: %s", e, exc_info=e)
66
67    server = await apci.listen(connection_cb=on_connection,
68                               addr=addr,
69                               response_timeout=response_timeout,
70                               supervisory_timeout=supervisory_timeout,
71                               test_timeout=test_timeout,
72                               send_window_size=send_window_size,
73                               receive_window_size=receive_window_size,
74                               **kwargs)
75
76    log = logger.create_server_logger(mlog, server.info.name, server.info)
77
78    return server
class Connection(hat.aio.group.Resource):
 81class Connection(aio.Resource):
 82
 83    def __init__(self, conn: apci.Connection):
 84        self._conn = conn
 85        self._encoder = encoder.Encoder()
 86        self._comm_log = logger.CommunicationLogger(mlog, conn.info)
 87
 88        self.async_group.spawn(aio.call_on_cancel, self._comm_log.log,
 89                               common.CommLogAction.CLOSE)
 90        self._comm_log.log(common.CommLogAction.OPEN)
 91
 92    @property
 93    def async_group(self) -> aio.Group:
 94        return self._conn.async_group
 95
 96    @property
 97    def info(self) -> tcp.ConnectionInfo:
 98        return self._conn.info
 99
100    @property
101    def is_enabled(self) -> bool:
102        return self._conn.is_enabled
103
104    def register_enabled_cb(self,
105                            cb: typing.Callable[[bool], None]
106                            ) -> util.RegisterCallbackHandle:
107        return self._conn.register_enabled_cb(cb)
108
109    async def send(self,
110                   msgs: typing.List[common.Msg],
111                   wait_ack: bool = False):
112        self._comm_log.log(common.CommLogAction.SEND, msgs)
113
114        data = collections.deque(self._encoder.encode(msgs))
115        while data:
116            head = data.popleft()
117            head_wait_ack = False if data else wait_ack
118            await self._conn.send(head, head_wait_ack)
119
120    async def drain(self, wait_ack: bool = False):
121        await self._conn.drain(wait_ack)
122
123    async def receive(self) -> list[common.Msg]:
124        data = await self._conn.receive()
125        msgs = list(self._encoder.decode(data))
126
127        self._comm_log.log(common.CommLogAction.RECEIVE, msgs)
128
129        return msgs

Resource with lifetime control based on Group.

Connection(conn: Connection)
83    def __init__(self, conn: apci.Connection):
84        self._conn = conn
85        self._encoder = encoder.Encoder()
86        self._comm_log = logger.CommunicationLogger(mlog, conn.info)
87
88        self.async_group.spawn(aio.call_on_cancel, self._comm_log.log,
89                               common.CommLogAction.CLOSE)
90        self._comm_log.log(common.CommLogAction.OPEN)
async_group: hat.aio.group.Group
92    @property
93    def async_group(self) -> aio.Group:
94        return self._conn.async_group

Group controlling resource's lifetime.

info: hat.drivers.tcp.ConnectionInfo
96    @property
97    def info(self) -> tcp.ConnectionInfo:
98        return self._conn.info
is_enabled: bool
100    @property
101    def is_enabled(self) -> bool:
102        return self._conn.is_enabled
def register_enabled_cb( self, cb: Callable[[bool], NoneType]) -> hat.util.callback.RegisterCallbackHandle:
104    def register_enabled_cb(self,
105                            cb: typing.Callable[[bool], None]
106                            ) -> util.RegisterCallbackHandle:
107        return self._conn.register_enabled_cb(cb)
async def send( self, msgs: List[DataMsg | CommandMsg | InitializationMsg | InterrogationMsg | CounterInterrogationMsg | ReadMsg | ClockSyncMsg | TestMsg | ResetMsg | ParameterMsg | ParameterActivationMsg], wait_ack: bool = False):
109    async def send(self,
110                   msgs: typing.List[common.Msg],
111                   wait_ack: bool = False):
112        self._comm_log.log(common.CommLogAction.SEND, msgs)
113
114        data = collections.deque(self._encoder.encode(msgs))
115        while data:
116            head = data.popleft()
117            head_wait_ack = False if data else wait_ack
118            await self._conn.send(head, head_wait_ack)
async def drain(self, wait_ack: bool = False):
120    async def drain(self, wait_ack: bool = False):
121        await self._conn.drain(wait_ack)
123    async def receive(self) -> list[common.Msg]:
124        data = await self._conn.receive()
125        msgs = list(self._encoder.decode(data))
126
127        self._comm_log.log(common.CommLogAction.RECEIVE, msgs)
128
129        return msgs