DLMS-SPODES-client 0.19.22__py3-none-any.whl → 0.19.23__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DLMS_SPODES_client/FCS16.py +39 -39
- DLMS_SPODES_client/__init__.py +12 -12
- DLMS_SPODES_client/client.py +2091 -2091
- DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +21 -21
- DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +37 -37
- DLMS_SPODES_client/gurux_dlms/CountType.py +16 -16
- DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +545 -545
- DLMS_SPODES_client/gurux_dlms/GXCiphering.py +196 -196
- DLMS_SPODES_client/gurux_dlms/GXDLMS.py +426 -426
- DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +237 -237
- DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +977 -977
- DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +90 -90
- DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +139 -139
- DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +33 -33
- DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +21 -21
- DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +254 -254
- DLMS_SPODES_client/gurux_dlms/GXReplyData.py +87 -87
- DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +9 -9
- DLMS_SPODES_client/gurux_dlms/MBusCommand.py +8 -8
- DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +27 -27
- DLMS_SPODES_client/gurux_dlms/ResponseType.py +8 -8
- DLMS_SPODES_client/gurux_dlms/SetResponseType.py +29 -29
- DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +9 -9
- DLMS_SPODES_client/gurux_dlms/__init__.py +75 -75
- DLMS_SPODES_client/gurux_dlms/enums/Access.py +12 -12
- DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +14 -14
- DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +41 -41
- DLMS_SPODES_client/gurux_dlms/enums/BerType.py +35 -35
- DLMS_SPODES_client/gurux_dlms/enums/Command.py +285 -285
- DLMS_SPODES_client/gurux_dlms/enums/Definition.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +46 -46
- DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +12 -12
- DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +13 -13
- DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +306 -306
- DLMS_SPODES_client/gurux_dlms/enums/Priority.py +7 -7
- DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/Security.py +14 -14
- DLMS_SPODES_client/gurux_dlms/enums/Service.py +16 -16
- DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +9 -9
- DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +8 -8
- DLMS_SPODES_client/gurux_dlms/enums/Standard.py +18 -18
- DLMS_SPODES_client/gurux_dlms/enums/StateError.py +7 -7
- DLMS_SPODES_client/gurux_dlms/enums/Task.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +10 -10
- DLMS_SPODES_client/gurux_dlms/enums/__init__.py +33 -33
- DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +1673 -1673
- DLMS_SPODES_client/logger.py +56 -56
- DLMS_SPODES_client/services.py +97 -97
- DLMS_SPODES_client/session.py +365 -365
- DLMS_SPODES_client/settings.py +48 -48
- DLMS_SPODES_client/task.py +1842 -1842
- {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.23.dist-info}/METADATA +29 -27
- dlms_spodes_client-0.19.23.dist-info/RECORD +61 -0
- dlms_spodes_client-0.19.22.dist-info/RECORD +0 -61
- {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.23.dist-info}/WHEEL +0 -0
- {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.23.dist-info}/entry_points.txt +0 -0
- {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.23.dist-info}/top_level.txt +0 -0
|
@@ -1,254 +1,254 @@
|
|
|
1
|
-
from __future__ import print_function
|
|
2
|
-
from ..gurux_dlms.GXCiphering import GXCiphering
|
|
3
|
-
from .enums import Priority, ServiceClass, Authentication, Standard
|
|
4
|
-
from DLMS_SPODES.hdlc.frame import Control
|
|
5
|
-
from DLMS_SPODES.enums import Conformance
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class GXDLMSSettings:
|
|
9
|
-
""" This class includes DLMS communication settings. """
|
|
10
|
-
ctoSChallenge: bytes | None
|
|
11
|
-
|
|
12
|
-
@classmethod
|
|
13
|
-
def getInitialConformance(cls, useLN):
|
|
14
|
-
if useLN:
|
|
15
|
-
return Conformance.BLOCK_TRANSFER_WITH_ACTION | Conformance.BLOCK_TRANSFER_WITH_SET_OR_WRITE | Conformance.BLOCK_TRANSFER_WITH_GET_OR_READ | Conformance.SET | Conformance.SELECTIVE_ACCESS | Conformance.ACTION | Conformance.MULTIPLE_REFERENCES | Conformance.GET
|
|
16
|
-
return Conformance.INFORMATION_REPORT | Conformance.READ | Conformance.UN_CONFIRMED_WRITE | Conformance.WRITE | Conformance.PARAMETERIZED_ACCESS | Conformance.MULTIPLE_REFERENCES
|
|
17
|
-
|
|
18
|
-
def __init__(self, isServer: bool):
|
|
19
|
-
self.customChallenges = False
|
|
20
|
-
self.ctoSChallenge = None
|
|
21
|
-
self.stoCChallenge = None
|
|
22
|
-
self.sourceSystemTitle = None
|
|
23
|
-
self.invokeId = 1
|
|
24
|
-
self.longInvokeID = 0x1
|
|
25
|
-
self.priority = Priority.HIGH
|
|
26
|
-
self.serviceClass = ServiceClass.CONFIRMED
|
|
27
|
-
self.clientAddress = 0
|
|
28
|
-
self.serverAddress = 0
|
|
29
|
-
self.pushClientAddress = 0
|
|
30
|
-
self.serverAddressSize = 0
|
|
31
|
-
self.__useLogicalNameReferencing = True
|
|
32
|
-
self.authentication = Authentication.NONE
|
|
33
|
-
self.password = None
|
|
34
|
-
self.kek = None
|
|
35
|
-
self.count = 0
|
|
36
|
-
self.index = 0
|
|
37
|
-
self.targetEphemeralKey = None
|
|
38
|
-
self.dlmsVersion = 6
|
|
39
|
-
""" deprecated """
|
|
40
|
-
self.allowAnonymousAccess = False
|
|
41
|
-
self.maxPduSize = 0xFFFF
|
|
42
|
-
self.maxServerPDUSize = 0xFFFF
|
|
43
|
-
self.startingPacketIndex = 1
|
|
44
|
-
# Gets current block index.
|
|
45
|
-
self.blockIndex = 1
|
|
46
|
-
self.cipher = GXCiphering("ABCDEFGH".encode())
|
|
47
|
-
self.blockNumberAck = 0
|
|
48
|
-
self.protocolVersion = None
|
|
49
|
-
self.isServer = isServer
|
|
50
|
-
self.gateway = None
|
|
51
|
-
self.proposedConformance = GXDLMSSettings.getInitialConformance(self.__useLogicalNameReferencing)
|
|
52
|
-
self.resetFrameSequence()
|
|
53
|
-
self.windowSize = 1
|
|
54
|
-
self.userId = -1
|
|
55
|
-
self.qualityOfService = 0
|
|
56
|
-
""" deprecated """
|
|
57
|
-
self.useUtc2NormalTime = False
|
|
58
|
-
self.standard = Standard.DLMS
|
|
59
|
-
self.negotiatedConformance = Conformance.NONE
|
|
60
|
-
self.receiverFrame = Control.S0_R0 # 0
|
|
61
|
-
self.senderFrame = Control.S0_R0 # 0
|
|
62
|
-
self.command = 0
|
|
63
|
-
self.commandType = 0
|
|
64
|
-
self.useUtc2NormalTime = False
|
|
65
|
-
|
|
66
|
-
def setCtoSChallenge(self, value):
|
|
67
|
-
""" Client to Server challenge setter """
|
|
68
|
-
if not self.customChallenges or self.ctoSChallenge is None:
|
|
69
|
-
self.ctoSChallenge = value
|
|
70
|
-
|
|
71
|
-
def getStoCChallenge(self):
|
|
72
|
-
""" Server to Client challenge getter """
|
|
73
|
-
return self.stoCChallenge
|
|
74
|
-
|
|
75
|
-
def setStoCChallenge(self, value):
|
|
76
|
-
""" Server to Client challenge setter """
|
|
77
|
-
if not self.customChallenges or self.stoCChallenge is None:
|
|
78
|
-
self.stoCChallenge = value
|
|
79
|
-
|
|
80
|
-
def resetFrameSequence(self):
|
|
81
|
-
if self.isServer:
|
|
82
|
-
self.senderFrame = Control.S7_R0_PF
|
|
83
|
-
self.receiverFrame = Control.S7_R7_PF
|
|
84
|
-
else:
|
|
85
|
-
self.senderFrame = Control.S7_R7_PF
|
|
86
|
-
self.receiverFrame = Control.S7_R0_PF
|
|
87
|
-
|
|
88
|
-
def getNextSend(self, is_first: bool) -> int:
|
|
89
|
-
""" Generates I-frame. Is this first packet. """
|
|
90
|
-
if is_first:
|
|
91
|
-
self.senderFrame = Control.next_receiver_sequence(Control.next_send_sequence(self.senderFrame))
|
|
92
|
-
else:
|
|
93
|
-
self.senderFrame = Control.next_send_sequence(self.senderFrame)
|
|
94
|
-
return self.senderFrame
|
|
95
|
-
|
|
96
|
-
def getReceiverReady(self):
|
|
97
|
-
""" Generates Receiver Ready S-frame """
|
|
98
|
-
self.senderFrame = Control.next_receiver_sequence(self.senderFrame | 1)
|
|
99
|
-
return self.senderFrame & 0xF1
|
|
100
|
-
|
|
101
|
-
def getKeepAlive(self):
|
|
102
|
-
""" Generates Keep Alive S-frame """
|
|
103
|
-
self.senderFrame = (self.senderFrame | 1)
|
|
104
|
-
return self.senderFrame & 0xF1
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
# Gets starting block index in HDLC framing. Default is One based,
|
|
108
|
-
# but some
|
|
109
|
-
# meters use Zero based value. Usually this is not used.
|
|
110
|
-
#
|
|
111
|
-
# Current block index.
|
|
112
|
-
#
|
|
113
|
-
def getStartingPacketIndex(self):
|
|
114
|
-
return self.startingPacketIndex
|
|
115
|
-
|
|
116
|
-
#
|
|
117
|
-
# Set starting block index in HDLC framing. Default is One based,
|
|
118
|
-
# but some
|
|
119
|
-
# meters use Zero based value. Usually this is not used.
|
|
120
|
-
#
|
|
121
|
-
# @param value
|
|
122
|
-
# Zero based starting index.
|
|
123
|
-
#
|
|
124
|
-
def setStartingPacketIndex(self, value):
|
|
125
|
-
self.startingPacketIndex = value
|
|
126
|
-
self.resetBlockIndex()
|
|
127
|
-
|
|
128
|
-
#
|
|
129
|
-
# Sets current block index.
|
|
130
|
-
#
|
|
131
|
-
# @param value
|
|
132
|
-
# Block index.
|
|
133
|
-
#
|
|
134
|
-
def setBlockIndex(self, value):
|
|
135
|
-
self.blockIndex = value
|
|
136
|
-
|
|
137
|
-
#
|
|
138
|
-
# Block number acknowledged in GBT.
|
|
139
|
-
#
|
|
140
|
-
def getBlockNumberAck(self):
|
|
141
|
-
return self.blockNumberAck
|
|
142
|
-
|
|
143
|
-
#
|
|
144
|
-
# @param value
|
|
145
|
-
# Block number acknowledged in GBT.
|
|
146
|
-
#
|
|
147
|
-
def setBlockNumberAck(self, value):
|
|
148
|
-
self.blockNumberAck = value
|
|
149
|
-
|
|
150
|
-
#
|
|
151
|
-
# Resets block index to default value.
|
|
152
|
-
#
|
|
153
|
-
def resetBlockIndex(self):
|
|
154
|
-
self.blockIndex = self.startingPacketIndex
|
|
155
|
-
self.blockNumberAck = 0
|
|
156
|
-
|
|
157
|
-
#
|
|
158
|
-
# Increases block index.
|
|
159
|
-
#
|
|
160
|
-
def increaseBlockIndex(self):
|
|
161
|
-
self.blockIndex += 1
|
|
162
|
-
|
|
163
|
-
# Is Logical Name Referencing used.
|
|
164
|
-
# Don't use property. For some reason Python 2.7 doesn't call it in Rasbperry PI.
|
|
165
|
-
def getUseLogicalNameReferencing(self):
|
|
166
|
-
return self.__useLogicalNameReferencing
|
|
167
|
-
|
|
168
|
-
# Is Logical Name Referencing used.
|
|
169
|
-
def setUseLogicalNameReferencing(self, value):
|
|
170
|
-
if self.__useLogicalNameReferencing != value:
|
|
171
|
-
self.__useLogicalNameReferencing = value
|
|
172
|
-
self.proposedConformance = GXDLMSSettings.getInitialConformance(self.__useLogicalNameReferencing)
|
|
173
|
-
|
|
174
|
-
#
|
|
175
|
-
# @param value
|
|
176
|
-
# update invoke ID.
|
|
177
|
-
#
|
|
178
|
-
def updateInvokeId(self, value):
|
|
179
|
-
if (value & 0x80) != 0:
|
|
180
|
-
self.priority = Priority.HIGH
|
|
181
|
-
else:
|
|
182
|
-
self.priority = Priority.NORMAL
|
|
183
|
-
if (value & 0x40) != 0:
|
|
184
|
-
self.serviceClass = ServiceClass.CONFIRMED
|
|
185
|
-
else:
|
|
186
|
-
self.serviceClass = ServiceClass.UN_CONFIRMED
|
|
187
|
-
self.invokeId = int((value & 0xF))
|
|
188
|
-
|
|
189
|
-
#
|
|
190
|
-
# @param value
|
|
191
|
-
# Invoke ID.
|
|
192
|
-
#
|
|
193
|
-
def setInvokeID(self, value):
|
|
194
|
-
if value > 0xF:
|
|
195
|
-
raise ValueError("Invalid InvokeID")
|
|
196
|
-
self.invokeId = int(value)
|
|
197
|
-
|
|
198
|
-
#
|
|
199
|
-
# Invoke ID.
|
|
200
|
-
#
|
|
201
|
-
def getLongInvokeID(self):
|
|
202
|
-
return self.longInvokeID
|
|
203
|
-
|
|
204
|
-
#
|
|
205
|
-
# @param value
|
|
206
|
-
# Invoke ID.
|
|
207
|
-
#
|
|
208
|
-
def setLongInvokeID(self, value):
|
|
209
|
-
if value > 0xFFFFFFFF:
|
|
210
|
-
raise ValueError("Invalid InvokeID")
|
|
211
|
-
self.longInvokeID = value
|
|
212
|
-
|
|
213
|
-
#
|
|
214
|
-
# Source system title.
|
|
215
|
-
#
|
|
216
|
-
def getSourceSystemTitle(self):
|
|
217
|
-
return self.sourceSystemTitle
|
|
218
|
-
|
|
219
|
-
#
|
|
220
|
-
# @param value
|
|
221
|
-
# Source system title.
|
|
222
|
-
#
|
|
223
|
-
def setSourceSystemTitle(self, value):
|
|
224
|
-
if not value or len(value) != 8:
|
|
225
|
-
raise ValueError("Invalid client system title.")
|
|
226
|
-
self.sourceSystemTitle = value
|
|
227
|
-
|
|
228
|
-
#
|
|
229
|
-
# Long data count.
|
|
230
|
-
#
|
|
231
|
-
def getCount(self):
|
|
232
|
-
return self.count
|
|
233
|
-
|
|
234
|
-
#
|
|
235
|
-
# @param value
|
|
236
|
-
# Data count.
|
|
237
|
-
#
|
|
238
|
-
def setCount(self, value):
|
|
239
|
-
if value < 0:
|
|
240
|
-
raise ValueError("Invalid count.")
|
|
241
|
-
self.count = value
|
|
242
|
-
|
|
243
|
-
#
|
|
244
|
-
# @param value
|
|
245
|
-
# Long data index
|
|
246
|
-
#
|
|
247
|
-
def setIndex(self, value):
|
|
248
|
-
if value < 0:
|
|
249
|
-
raise ValueError("Invalid Index.")
|
|
250
|
-
self.index = value
|
|
251
|
-
|
|
252
|
-
def is_multiple_block(self) -> bool:
|
|
253
|
-
""" Are there more data to send or more data to receive. !!! instead GXDLMSLNParameters.multipleBlocks """
|
|
254
|
-
return self.count != self.index
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
from ..gurux_dlms.GXCiphering import GXCiphering
|
|
3
|
+
from .enums import Priority, ServiceClass, Authentication, Standard
|
|
4
|
+
from DLMS_SPODES.hdlc.frame import Control
|
|
5
|
+
from DLMS_SPODES.enums import Conformance
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class GXDLMSSettings:
|
|
9
|
+
""" This class includes DLMS communication settings. """
|
|
10
|
+
ctoSChallenge: bytes | None
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def getInitialConformance(cls, useLN):
|
|
14
|
+
if useLN:
|
|
15
|
+
return Conformance.BLOCK_TRANSFER_WITH_ACTION | Conformance.BLOCK_TRANSFER_WITH_SET_OR_WRITE | Conformance.BLOCK_TRANSFER_WITH_GET_OR_READ | Conformance.SET | Conformance.SELECTIVE_ACCESS | Conformance.ACTION | Conformance.MULTIPLE_REFERENCES | Conformance.GET
|
|
16
|
+
return Conformance.INFORMATION_REPORT | Conformance.READ | Conformance.UN_CONFIRMED_WRITE | Conformance.WRITE | Conformance.PARAMETERIZED_ACCESS | Conformance.MULTIPLE_REFERENCES
|
|
17
|
+
|
|
18
|
+
def __init__(self, isServer: bool):
|
|
19
|
+
self.customChallenges = False
|
|
20
|
+
self.ctoSChallenge = None
|
|
21
|
+
self.stoCChallenge = None
|
|
22
|
+
self.sourceSystemTitle = None
|
|
23
|
+
self.invokeId = 1
|
|
24
|
+
self.longInvokeID = 0x1
|
|
25
|
+
self.priority = Priority.HIGH
|
|
26
|
+
self.serviceClass = ServiceClass.CONFIRMED
|
|
27
|
+
self.clientAddress = 0
|
|
28
|
+
self.serverAddress = 0
|
|
29
|
+
self.pushClientAddress = 0
|
|
30
|
+
self.serverAddressSize = 0
|
|
31
|
+
self.__useLogicalNameReferencing = True
|
|
32
|
+
self.authentication = Authentication.NONE
|
|
33
|
+
self.password = None
|
|
34
|
+
self.kek = None
|
|
35
|
+
self.count = 0
|
|
36
|
+
self.index = 0
|
|
37
|
+
self.targetEphemeralKey = None
|
|
38
|
+
self.dlmsVersion = 6
|
|
39
|
+
""" deprecated """
|
|
40
|
+
self.allowAnonymousAccess = False
|
|
41
|
+
self.maxPduSize = 0xFFFF
|
|
42
|
+
self.maxServerPDUSize = 0xFFFF
|
|
43
|
+
self.startingPacketIndex = 1
|
|
44
|
+
# Gets current block index.
|
|
45
|
+
self.blockIndex = 1
|
|
46
|
+
self.cipher = GXCiphering("ABCDEFGH".encode())
|
|
47
|
+
self.blockNumberAck = 0
|
|
48
|
+
self.protocolVersion = None
|
|
49
|
+
self.isServer = isServer
|
|
50
|
+
self.gateway = None
|
|
51
|
+
self.proposedConformance = GXDLMSSettings.getInitialConformance(self.__useLogicalNameReferencing)
|
|
52
|
+
self.resetFrameSequence()
|
|
53
|
+
self.windowSize = 1
|
|
54
|
+
self.userId = -1
|
|
55
|
+
self.qualityOfService = 0
|
|
56
|
+
""" deprecated """
|
|
57
|
+
self.useUtc2NormalTime = False
|
|
58
|
+
self.standard = Standard.DLMS
|
|
59
|
+
self.negotiatedConformance = Conformance.NONE
|
|
60
|
+
self.receiverFrame = Control.S0_R0 # 0
|
|
61
|
+
self.senderFrame = Control.S0_R0 # 0
|
|
62
|
+
self.command = 0
|
|
63
|
+
self.commandType = 0
|
|
64
|
+
self.useUtc2NormalTime = False
|
|
65
|
+
|
|
66
|
+
def setCtoSChallenge(self, value):
|
|
67
|
+
""" Client to Server challenge setter """
|
|
68
|
+
if not self.customChallenges or self.ctoSChallenge is None:
|
|
69
|
+
self.ctoSChallenge = value
|
|
70
|
+
|
|
71
|
+
def getStoCChallenge(self):
|
|
72
|
+
""" Server to Client challenge getter """
|
|
73
|
+
return self.stoCChallenge
|
|
74
|
+
|
|
75
|
+
def setStoCChallenge(self, value):
|
|
76
|
+
""" Server to Client challenge setter """
|
|
77
|
+
if not self.customChallenges or self.stoCChallenge is None:
|
|
78
|
+
self.stoCChallenge = value
|
|
79
|
+
|
|
80
|
+
def resetFrameSequence(self):
|
|
81
|
+
if self.isServer:
|
|
82
|
+
self.senderFrame = Control.S7_R0_PF
|
|
83
|
+
self.receiverFrame = Control.S7_R7_PF
|
|
84
|
+
else:
|
|
85
|
+
self.senderFrame = Control.S7_R7_PF
|
|
86
|
+
self.receiverFrame = Control.S7_R0_PF
|
|
87
|
+
|
|
88
|
+
def getNextSend(self, is_first: bool) -> int:
|
|
89
|
+
""" Generates I-frame. Is this first packet. """
|
|
90
|
+
if is_first:
|
|
91
|
+
self.senderFrame = Control.next_receiver_sequence(Control.next_send_sequence(self.senderFrame))
|
|
92
|
+
else:
|
|
93
|
+
self.senderFrame = Control.next_send_sequence(self.senderFrame)
|
|
94
|
+
return self.senderFrame
|
|
95
|
+
|
|
96
|
+
def getReceiverReady(self):
|
|
97
|
+
""" Generates Receiver Ready S-frame """
|
|
98
|
+
self.senderFrame = Control.next_receiver_sequence(self.senderFrame | 1)
|
|
99
|
+
return self.senderFrame & 0xF1
|
|
100
|
+
|
|
101
|
+
def getKeepAlive(self):
|
|
102
|
+
""" Generates Keep Alive S-frame """
|
|
103
|
+
self.senderFrame = (self.senderFrame | 1)
|
|
104
|
+
return self.senderFrame & 0xF1
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
# Gets starting block index in HDLC framing. Default is One based,
|
|
108
|
+
# but some
|
|
109
|
+
# meters use Zero based value. Usually this is not used.
|
|
110
|
+
#
|
|
111
|
+
# Current block index.
|
|
112
|
+
#
|
|
113
|
+
def getStartingPacketIndex(self):
|
|
114
|
+
return self.startingPacketIndex
|
|
115
|
+
|
|
116
|
+
#
|
|
117
|
+
# Set starting block index in HDLC framing. Default is One based,
|
|
118
|
+
# but some
|
|
119
|
+
# meters use Zero based value. Usually this is not used.
|
|
120
|
+
#
|
|
121
|
+
# @param value
|
|
122
|
+
# Zero based starting index.
|
|
123
|
+
#
|
|
124
|
+
def setStartingPacketIndex(self, value):
|
|
125
|
+
self.startingPacketIndex = value
|
|
126
|
+
self.resetBlockIndex()
|
|
127
|
+
|
|
128
|
+
#
|
|
129
|
+
# Sets current block index.
|
|
130
|
+
#
|
|
131
|
+
# @param value
|
|
132
|
+
# Block index.
|
|
133
|
+
#
|
|
134
|
+
def setBlockIndex(self, value):
|
|
135
|
+
self.blockIndex = value
|
|
136
|
+
|
|
137
|
+
#
|
|
138
|
+
# Block number acknowledged in GBT.
|
|
139
|
+
#
|
|
140
|
+
def getBlockNumberAck(self):
|
|
141
|
+
return self.blockNumberAck
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# @param value
|
|
145
|
+
# Block number acknowledged in GBT.
|
|
146
|
+
#
|
|
147
|
+
def setBlockNumberAck(self, value):
|
|
148
|
+
self.blockNumberAck = value
|
|
149
|
+
|
|
150
|
+
#
|
|
151
|
+
# Resets block index to default value.
|
|
152
|
+
#
|
|
153
|
+
def resetBlockIndex(self):
|
|
154
|
+
self.blockIndex = self.startingPacketIndex
|
|
155
|
+
self.blockNumberAck = 0
|
|
156
|
+
|
|
157
|
+
#
|
|
158
|
+
# Increases block index.
|
|
159
|
+
#
|
|
160
|
+
def increaseBlockIndex(self):
|
|
161
|
+
self.blockIndex += 1
|
|
162
|
+
|
|
163
|
+
# Is Logical Name Referencing used.
|
|
164
|
+
# Don't use property. For some reason Python 2.7 doesn't call it in Rasbperry PI.
|
|
165
|
+
def getUseLogicalNameReferencing(self):
|
|
166
|
+
return self.__useLogicalNameReferencing
|
|
167
|
+
|
|
168
|
+
# Is Logical Name Referencing used.
|
|
169
|
+
def setUseLogicalNameReferencing(self, value):
|
|
170
|
+
if self.__useLogicalNameReferencing != value:
|
|
171
|
+
self.__useLogicalNameReferencing = value
|
|
172
|
+
self.proposedConformance = GXDLMSSettings.getInitialConformance(self.__useLogicalNameReferencing)
|
|
173
|
+
|
|
174
|
+
#
|
|
175
|
+
# @param value
|
|
176
|
+
# update invoke ID.
|
|
177
|
+
#
|
|
178
|
+
def updateInvokeId(self, value):
|
|
179
|
+
if (value & 0x80) != 0:
|
|
180
|
+
self.priority = Priority.HIGH
|
|
181
|
+
else:
|
|
182
|
+
self.priority = Priority.NORMAL
|
|
183
|
+
if (value & 0x40) != 0:
|
|
184
|
+
self.serviceClass = ServiceClass.CONFIRMED
|
|
185
|
+
else:
|
|
186
|
+
self.serviceClass = ServiceClass.UN_CONFIRMED
|
|
187
|
+
self.invokeId = int((value & 0xF))
|
|
188
|
+
|
|
189
|
+
#
|
|
190
|
+
# @param value
|
|
191
|
+
# Invoke ID.
|
|
192
|
+
#
|
|
193
|
+
def setInvokeID(self, value):
|
|
194
|
+
if value > 0xF:
|
|
195
|
+
raise ValueError("Invalid InvokeID")
|
|
196
|
+
self.invokeId = int(value)
|
|
197
|
+
|
|
198
|
+
#
|
|
199
|
+
# Invoke ID.
|
|
200
|
+
#
|
|
201
|
+
def getLongInvokeID(self):
|
|
202
|
+
return self.longInvokeID
|
|
203
|
+
|
|
204
|
+
#
|
|
205
|
+
# @param value
|
|
206
|
+
# Invoke ID.
|
|
207
|
+
#
|
|
208
|
+
def setLongInvokeID(self, value):
|
|
209
|
+
if value > 0xFFFFFFFF:
|
|
210
|
+
raise ValueError("Invalid InvokeID")
|
|
211
|
+
self.longInvokeID = value
|
|
212
|
+
|
|
213
|
+
#
|
|
214
|
+
# Source system title.
|
|
215
|
+
#
|
|
216
|
+
def getSourceSystemTitle(self):
|
|
217
|
+
return self.sourceSystemTitle
|
|
218
|
+
|
|
219
|
+
#
|
|
220
|
+
# @param value
|
|
221
|
+
# Source system title.
|
|
222
|
+
#
|
|
223
|
+
def setSourceSystemTitle(self, value):
|
|
224
|
+
if not value or len(value) != 8:
|
|
225
|
+
raise ValueError("Invalid client system title.")
|
|
226
|
+
self.sourceSystemTitle = value
|
|
227
|
+
|
|
228
|
+
#
|
|
229
|
+
# Long data count.
|
|
230
|
+
#
|
|
231
|
+
def getCount(self):
|
|
232
|
+
return self.count
|
|
233
|
+
|
|
234
|
+
#
|
|
235
|
+
# @param value
|
|
236
|
+
# Data count.
|
|
237
|
+
#
|
|
238
|
+
def setCount(self, value):
|
|
239
|
+
if value < 0:
|
|
240
|
+
raise ValueError("Invalid count.")
|
|
241
|
+
self.count = value
|
|
242
|
+
|
|
243
|
+
#
|
|
244
|
+
# @param value
|
|
245
|
+
# Long data index
|
|
246
|
+
#
|
|
247
|
+
def setIndex(self, value):
|
|
248
|
+
if value < 0:
|
|
249
|
+
raise ValueError("Invalid Index.")
|
|
250
|
+
self.index = value
|
|
251
|
+
|
|
252
|
+
def is_multiple_block(self) -> bool:
|
|
253
|
+
""" Are there more data to send or more data to receive. !!! instead GXDLMSLNParameters.multipleBlocks """
|
|
254
|
+
return self.count != self.index
|