DLMS-SPODES-client 0.19.11__py3-none-any.whl → 0.19.13__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.
@@ -14,6 +14,7 @@ import datetime
14
14
  import os
15
15
  import hashlib
16
16
  from Cryptodome.Cipher import AES
17
+ from StructResult import result
17
18
  from DLMS_SPODES_communications import Network, Serial, RS485, BLEKPZ, base
18
19
  from DLMS_SPODES.cosem_interface_classes import overview
19
20
  from DLMS_SPODES.cosem_interface_classes.collection import Collection, InterfaceClass, ic, cdt, ut, Data, AssociationLN
@@ -50,10 +50,6 @@ class Base[T: result.Result](Protocol):
50
50
  """Exchange task for DLMS client"""
51
51
  msg: str
52
52
 
53
- def __post_init__(self) -> None:
54
- if self.msg == "":
55
- self.msg = self.__class__.__name__
56
-
57
53
  def copy(self) -> Self: ...
58
54
 
59
55
  @property
@@ -295,11 +291,11 @@ class StrictOK(Base[result.StrictOk], Protocol):
295
291
  async def exchange(self, c: Client) -> result.StrictOk | result.Error: ...
296
292
 
297
293
 
298
- @dataclass
294
+ @dataclass(frozen=True)
299
295
  class ClientBlocking(SimpleCopy, OK):
300
296
  """complete by time or abort"""
301
- delay: Final[float] = field(default=99999999.0)
302
- msg: str = ""
297
+ delay: float = field(default=99999999.0)
298
+ msg: str = "client blocking"
303
299
 
304
300
  async def run(self, c: Client) -> result.Ok | result.Error:
305
301
  try:
@@ -316,8 +312,9 @@ class ClientBlocking(SimpleCopy, OK):
316
312
 
317
313
 
318
314
  # todo: make with <data_link>
315
+ @dataclass
319
316
  class TestDataLink(SimpleCopy, OK):
320
- msg: str = ""
317
+ msg: str = "test DLink"
321
318
 
322
319
  async def physical(self, c: Client) -> result.Ok | result.Error:
323
320
  if OSI.PHYSICAL not in c.level:
@@ -340,18 +337,18 @@ class TestDataLink(SimpleCopy, OK):
340
337
  return result.OK
341
338
 
342
339
 
343
- @dataclass
340
+ @dataclass(frozen=True)
344
341
  class Dummy(SimpleCopy, OK):
345
- msg: str = ""
342
+ msg: str = "dummy"
346
343
 
347
344
  async def exchange(self, c: Client) -> result.Ok | result.Error:
348
345
  """"""
349
346
  return result.OK
350
347
 
351
348
 
352
- @dataclass
349
+ @dataclass(frozen=True)
353
350
  class HardwareDisconnect(SimpleCopy, OK):
354
- msg: str = ""
351
+ msg: str = "hardware disconnect"
355
352
 
356
353
  @override
357
354
  async def exchange(self, c: Client) -> result.Ok | result.Error:
@@ -362,9 +359,9 @@ class HardwareDisconnect(SimpleCopy, OK):
362
359
  return result.OK
363
360
 
364
361
 
365
- @dataclass
362
+ @dataclass(frozen=True)
366
363
  class HardwareReconnect(SimpleCopy, OK):
367
- delay: Final[float] = 0.0
364
+ delay: float = 0.0
368
365
  """delay between disconnect and restore Application"""
369
366
  msg: str = "reconnect media without response"
370
367
 
@@ -378,13 +375,13 @@ class HardwareReconnect(SimpleCopy, OK):
378
375
  return result.OK
379
376
 
380
377
 
381
- @dataclass
378
+ @dataclass(frozen=True)
382
379
  class Loop(OK):
383
380
  task: Base[result.Result]
384
381
  func: Callable[[Any], bool]
385
- delay: Final[int] = 0.0
386
- msg: str = ""
387
- attempt_amount: Final[int] = 0
382
+ delay: int = 0.0
383
+ msg: str = "loop"
384
+ attempt_amount: int = 0
388
385
  """0 is never end loop"""
389
386
 
390
387
  def copy(self) -> Self:
@@ -415,7 +412,7 @@ class ConditionalTask[T](Base):
415
412
  comp_value: T
416
413
  predicate: Callable[[T, T], bool]
417
414
  main_task: Base[result.Result]
418
- msg: str
415
+ msg: str = "conditional task"
419
416
 
420
417
  async def exchange(self, c: Client) -> result.Result:
421
418
  res = await self.precondition_task.exchange(c)
@@ -438,7 +435,7 @@ class Scheduler[T: result.Result](Base[T]):
438
435
  repetition_delay_min: Final[int] = 1
439
436
  repetition_delay_exponent: Final[int] = 100
440
437
  repetition_delay_max: Final[int] = 100
441
- msg: str = ""
438
+ msg: str = "sheduler"
442
439
 
443
440
  def copy(self) -> "Scheduler[T]":
444
441
  return Scheduler(
@@ -496,8 +493,8 @@ class Subtasks[U: Base[result.Result]](Protocol):
496
493
  class List[T: result.Result, U: Base[result.Result]](Subtasks[U], _List[T]):
497
494
  """for exchange task sequence"""
498
495
  __is_exchange: bool
499
- msg: str
500
496
  err_ignore: bool
497
+ msg: str
501
498
  __current: Base[T]
502
499
 
503
500
  def __init__(self, *tasks: Base[T], msg: str = "", err_ignore: bool = True):
@@ -550,7 +547,7 @@ class Sequence[*Ts](Subtasks[Base[result.Result]], _Sequence[*Ts]):
550
547
  __current: "Base[result.Result] | Sequence[*Ts]"
551
548
  tasks: tuple[Base[result.Result], ...]
552
549
 
553
- def __init__(self, *tasks: Base[result.Result], msg: str = "", err_ignore: bool = False):
550
+ def __init__(self, *tasks: Base[result.Result], msg: str = "sequence", err_ignore: bool = False):
554
551
  self.tasks = tasks
555
552
  self.__current = self
556
553
  self.msg = self.__class__.__name__ if msg == "" else msg
@@ -574,20 +571,21 @@ class Sequence[*Ts](Subtasks[Base[result.Result]], _Sequence[*Ts]):
574
571
  for t in self.tasks:
575
572
  self.__current = t
576
573
  try:
577
- if (
578
- isinstance(res_one := await t.exchange(c), result.Error)
579
- and not self.err_ignore
580
- ):
581
- return res_one
574
+ if isinstance(res_one := await t.exchange(c), result.Error):
575
+ if self.err_ignore:
576
+ res_one = res_one.with_msg(self.msg)
577
+ else:
578
+ return res_one
582
579
  res = res.add(res_one)
583
580
  except exc.ResultError as e: # todo: make without except
584
- res.add(result.Error.from_e(e).with_msg(t.msg))
581
+ res = res.add(result.Error.from_e(e).with_msg(self.msg))
585
582
  return cast("result.Sequence[*Ts]", res)
586
583
 
587
584
 
585
+ @dataclass(frozen=True)
588
586
  class SetLocalTime(SimpleCopy, OK):
589
587
  """without decide time transfer"""
590
- msg: str
588
+ msg: str = "set local time"
591
589
 
592
590
  async def exchange(self, c: Client) -> result.Ok | result.Error:
593
591
  clock_obj: Clock = c.objects.get_object("0.0.1.0.0.255")
@@ -607,17 +605,17 @@ class SetLocalTime(SimpleCopy, OK):
607
605
  return result.OK
608
606
 
609
607
 
608
+ @dataclass(frozen=True)
610
609
  class GetFirmwareVersion(SimpleCopy, CDT):
611
- """get firmware version by Client.id"""
612
- msg: str
610
+ msg: str = "get firmware version"
613
611
 
614
612
  async def exchange(self, c: Client) -> result.SimpleOrError[cdt.CommonDataType]:
615
613
  return await Par2Data(Parameter(c.objects.id.f_ver.par[:6]).get_attr(c.objects.id.f_ver.par[6])).exchange(c)
616
614
 
617
615
 
616
+ @dataclass(frozen=True)
618
617
  class FindFirmwareVersion(SimpleCopy, Simple[collection.ParameterValue]):
619
- """try find COSEM server version, return: instance(B group), CDT"""
620
- msg: str
618
+ msg: str = "try find COSEM server version, return: instance(B group), CDT"
621
619
 
622
620
  async def exchange(self, c: Client) -> result.SimpleOrError[collection.ParameterValue]:
623
621
  err = result.ErrorAccumulator()
@@ -640,8 +638,8 @@ class FindFirmwareVersion(SimpleCopy, Simple[collection.ParameterValue]):
640
638
  raise RuntimeError(f"empty {err}")
641
639
 
642
640
 
641
+ @dataclass(frozen=True)
643
642
  class FindFirmwareId(SimpleCopy, Simple[collection.ParameterValue]):
644
- """try find COSEM server identifier, return: FirmwareID"""
645
643
  msg: str = "find firmaware Identifier"
646
644
 
647
645
  async def exchange(self, c: Client) -> result.SimpleOrError[collection.ParameterValue]:
@@ -665,10 +663,9 @@ class FindFirmwareId(SimpleCopy, Simple[collection.ParameterValue]):
665
663
  raise RuntimeError(f"empty {err}")
666
664
 
667
665
 
668
- @dataclass
666
+ @dataclass(frozen=True)
669
667
  class KeepAlive(SimpleCopy, OK):
670
- """use read LDN.ln"""
671
- msg: str = "keep alive"
668
+ msg: str = "keep alive(read LND.ln)"
672
669
 
673
670
  async def exchange(self, c: Client) -> result.Ok | result.Error:
674
671
  if isinstance(res := await Par2Data(dlms_par.LDN.value).exchange(c), result.Error):
@@ -701,7 +698,7 @@ class GetLDN(SimpleCopy, CDT[octet_string.LDN]):
701
698
  @dataclass
702
699
  class MatchLDN(OK):
703
700
  universal: bool = field(default=False)
704
- msg: str = ""
701
+ msg: str = "matching LDN"
705
702
 
706
703
  async def exchange(self, c: Client) -> result.Ok | result.Error:
707
704
  if isinstance((res := await GetLDN().exchange(c)), result.Error):
@@ -949,7 +946,7 @@ class MapTypeCreator:
949
946
  @dataclass
950
947
  class InitType(SimpleCopy, Simple[collection.Collection]):
951
948
  adapter: Adapter
952
- msg: str = ""
949
+ msg: str = "initiate type"
953
950
 
954
951
  async def exchange(self, c: Client) -> result.SimpleOrError[collection.Collection]:
955
952
  if isinstance((res := await Sequence(
@@ -996,7 +993,7 @@ get_adapter(gag) # Dummy Adapter
996
993
  class ReadAttribute(SimpleCopy, CDT):
997
994
  ln: collection.LNContaining
998
995
  index: int
999
- msg: str = ""
996
+ msg: str = "read LN attribute"
1000
997
 
1001
998
  async def exchange(self, c: Client) -> result.Simple[cdt.CommonDataType]:
1002
999
  obj = c.objects.get_object(self.ln)
@@ -1007,7 +1004,7 @@ class ReadAttribute(SimpleCopy, CDT):
1007
1004
  class ReadObjAttr(SimpleCopy, CDT):
1008
1005
  obj: collection.InterfaceClass
1009
1006
  index: int
1010
- msg: str = ""
1007
+ msg: str = "read object attribute"
1011
1008
 
1012
1009
  async def exchange(self, c: Client) -> result.SimpleOrError[cdt.CommonDataType]:
1013
1010
  # TODO: check is_readable?
@@ -1029,7 +1026,7 @@ class ReadObjAttr(SimpleCopy, CDT):
1029
1026
  return result.Error.from_e(e)
1030
1027
 
1031
1028
 
1032
- @dataclass
1029
+ @dataclass(frozen=True)
1033
1030
  class Par2Data[T: cdt.CommonDataType](SimpleCopy, CDT[T]):
1034
1031
  """get CommonDataType by Parameter"""
1035
1032
  par: Parameter
@@ -1060,13 +1057,13 @@ def is_empty(value: cdt.CommonDataType | None) -> bool:
1060
1057
  return True if value is None else False
1061
1058
 
1062
1059
 
1063
- @dataclass
1060
+ @dataclass(frozen=True)
1064
1061
  class ReadAttributeIf(SimpleCopy, Base):
1065
1062
  """read if func with arg as value is True"""
1066
1063
  ln: collection.LNContaining
1067
1064
  index: int
1068
1065
  func: AttrValueComp
1069
- msg: str
1066
+ msg: str = "read attribute with condition"
1070
1067
 
1071
1068
  async def exchange(self, c: Client) -> result.Simple[cdt.CommonDataType]:
1072
1069
  # TODO: check is_readable
@@ -1079,7 +1076,7 @@ class ReadAttributeIf(SimpleCopy, Base):
1079
1076
  return result.OK
1080
1077
 
1081
1078
 
1082
- @dataclass
1079
+ @dataclass(frozen=True)
1083
1080
  class ReadEmptyAttribute(SimpleCopy, Base):
1084
1081
  ln: collection.LNContaining
1085
1082
  index: int
@@ -1094,7 +1091,7 @@ class ReadEmptyAttribute(SimpleCopy, Base):
1094
1091
  ).exchange(c)
1095
1092
 
1096
1093
 
1097
- @dataclass
1094
+ @dataclass(frozen=True)
1098
1095
  class ReadWritableAttributes(SimpleCopy, Base):
1099
1096
  ln: collection.LNContaining
1100
1097
  indexes: tuple[int, ...]
@@ -1120,7 +1117,7 @@ class ReadWritableAttributes(SimpleCopy, Base):
1120
1117
 
1121
1118
 
1122
1119
  # copy past from ReadWritableAttributes
1123
- @dataclass
1120
+ @dataclass(frozen=True)
1124
1121
  class ActualizeAttributes(SimpleCopy, OK):
1125
1122
  ln: collection.LNContaining
1126
1123
  indexes: tuple[int, ...]
@@ -1146,7 +1143,7 @@ class ActualizeAttributes(SimpleCopy, OK):
1146
1143
  return result.OK
1147
1144
 
1148
1145
 
1149
- @dataclass
1146
+ @dataclass(frozen=True)
1150
1147
  class ReadAttributes(SimpleCopy, _List[cdt.CommonDataType]):
1151
1148
  ln: collection.LNContaining
1152
1149
  indexes: tuple[int, ...]
@@ -1321,7 +1318,7 @@ class Execute2(SimpleCopy, OK):
1321
1318
  """execute method"""
1322
1319
  par: Parameter
1323
1320
  data: cdt.CommonDataType
1324
- msg: str = ""
1321
+ msg: str = "Execute method"
1325
1322
 
1326
1323
  async def exchange(self, c: Client) -> result.Ok | result.Error:
1327
1324
  if isinstance(res := c.objects.par2obj(self.par), result.Error):
@@ -1365,7 +1362,7 @@ class ImageTransfer(SimpleCopy, StrictOK):
1365
1362
  n_t_b: int = field(init=False, default=0)
1366
1363
  """not transferred block"""
1367
1364
  n_blocks: int = field(init=False)
1368
- msg: str = ""
1365
+ msg: str = "image transfer"
1369
1366
 
1370
1367
  def __post_init__(self) -> None:
1371
1368
  self.ITI = ImageTransferInitiate((
@@ -1566,7 +1563,7 @@ class ActivateImage(SimpleCopy, OK):
1566
1563
 
1567
1564
  class TestAll(Base):
1568
1565
  """read all attributes with check access""" # todo: add Write with access
1569
- msg: str = ""
1566
+ msg: str = "test all"
1570
1567
 
1571
1568
  async def exchange(self, c: Client):
1572
1569
  # todo: refactoring with <append_err>
@@ -1619,7 +1616,7 @@ class TestAll(Base):
1619
1616
  @dataclass
1620
1617
  class ApplyTemplate(Base):
1621
1618
  template: collection.Template
1622
- msg: str = ""
1619
+ msg: str = "apply template"
1623
1620
 
1624
1621
  async def exchange(self, c: Client) -> result.Result:
1625
1622
  # todo: search col
@@ -1649,7 +1646,7 @@ class ApplyTemplate(Base):
1649
1646
  @dataclass
1650
1647
  class ReadTemplate(OK):
1651
1648
  template: collection.Template
1652
- msg: str = ""
1649
+ msg: str = "read template"
1653
1650
 
1654
1651
  async def exchange(self, c: Client) -> result.Ok | result.Error:
1655
1652
  # todo: copypast from <ApplyTemplate>
@@ -1680,7 +1677,7 @@ class ReadTemplate(OK):
1680
1677
  class AccessValidate(Base[result.Ok | result.Simple[list[Parameter]]]):
1681
1678
  """check all access rights for current SAP"""
1682
1679
  with_correct: bool = False
1683
- msg: str = ""
1680
+ msg: str = "all access validate"
1684
1681
 
1685
1682
  # todo: make with result.Error
1686
1683
  async def exchange(self, c: Client) -> result.Ok | result.Simple[list[Parameter]] | result.Error:
@@ -1746,7 +1743,7 @@ class WriteList(SimpleCopy, _List[result.Ok]):
1746
1743
  par_datas: tuple[tuple[Parameter, cdt.CommonDataType], ...]
1747
1744
  err_ignore: bool
1748
1745
 
1749
- def __init__(self, *par_datas: tuple[Parameter, cdt.CommonDataType], err_ignore: bool = False, msg: str = "") -> None:
1746
+ def __init__(self, *par_datas: tuple[Parameter, cdt.CommonDataType], err_ignore: bool = False, msg: str = "write list") -> None:
1750
1747
  self.par_datas = par_datas
1751
1748
  self.err_ignore = err_ignore
1752
1749
  self.msg = msg
@@ -1768,12 +1765,12 @@ class WriteTranscript(SimpleCopy, OK):
1768
1765
  """write by ParValues[Transcript]"""
1769
1766
  par: Parameter
1770
1767
  value: cdt.Transcript
1771
- msg: str = ""
1768
+ msg: str = "write with transcript"
1772
1769
 
1773
1770
  async def exchange(self, c: Client) -> result.Ok | result.Error:
1774
1771
  if isinstance((res := await Par2Data[cdt.CommonDataType](self.par).exchange(c)), result.Error):
1775
1772
  return res
1776
- if isinstance(data, cdt.Digital):
1773
+ if isinstance(res.value, cdt.Digital):
1777
1774
  s_u = c.objects.par2su(self.par)
1778
1775
  if isinstance(s_u, cdt.ScalUnitType):
1779
1776
  if not isinstance(self.value, str):
@@ -1794,7 +1791,7 @@ class WriteTranscripts(SimpleCopy, _List[result.Ok]):
1794
1791
  par_values: tuple[tuple[Parameter, cdt.Transcript], ...]
1795
1792
  err_ignore: bool
1796
1793
 
1797
- def __init__(self, *par_values: tuple[Parameter, cdt.Transcript], err_ignore: bool = False, msg: str =""):
1794
+ def __init__(self, *par_values: tuple[Parameter, cdt.Transcript], err_ignore: bool = False, msg: str ="write transcripts"):
1798
1795
  self.par_values = par_values
1799
1796
  self.err_ignore = err_ignore
1800
1797
  self.msg = msg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DLMS_SPODES_client
3
- Version: 0.19.11
3
+ Version: 0.19.13
4
4
  Summary: dlms-spodes
5
5
  Author-email: Serj Kotilevski <youserj@outlook.com>
6
6
  Project-URL: Source, https://github.com/youserj/SPODESclient_prj
@@ -15,7 +15,7 @@ Requires-Dist: pycryptodomex>=3.22.0
15
15
  Requires-Dist: semver>=3.0
16
16
  Requires-Dist: StructResult<0.10,>=0.9.2
17
17
  Requires-Dist: DLMS-SPODES-communications<1.5,>=1.4.9
18
- Requires-Dist: DLMS_SPODES<0.88,>=0.87.6
18
+ Requires-Dist: DLMS_SPODES<0.88,>=0.87.7
19
19
  Requires-Dist: DLMSadapter<0.8,>=0.7.5
20
20
  Requires-Dist: DLMSCommunicationProfile<0.2,>=0.1.11
21
21
  Requires-Dist: numpy>=2.3.2
@@ -1,12 +1,12 @@
1
1
  DLMS_SPODES_client/FCS16.py,sha256=RhoN4fX7eesKWfWCkRT_uWNfiQHqFd3T6lRwxfamUqw,2697
2
2
  DLMS_SPODES_client/__init__.py,sha256=6wphXvqkodng7h4nKNmkfldbaxf--IDVGfT0yNbas-o,449
3
- DLMS_SPODES_client/client.py,sha256=Dqe2gMTp4x_sAurInpOujFNBxrSRi35HfHgW6oS6148,112189
3
+ DLMS_SPODES_client/client.py,sha256=WuWg9OW3uRMQ4EtcWPEqUuG9QQLjNyL-JR2gZSTUifo,112222
4
4
  DLMS_SPODES_client/logger.py,sha256=zAbihLloMU99w8Sw3djQ0cwItzyGq0Fz8DI9_suazv4,1913
5
5
  DLMS_SPODES_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  DLMS_SPODES_client/services.py,sha256=xM_-h322V1bGBcw9cJh7XOSUMTL3_E-GX89-z3YwIYw,3909
7
7
  DLMS_SPODES_client/session.py,sha256=1sa4wJny2xwDqL3DXpfYTS7mZcabVdC5fW1H60VB5QA,12681
8
8
  DLMS_SPODES_client/settings.py,sha256=6mitGe9UYeEgL61sf933MJ-S5N-ReoxvXqiI3agBGYE,1623
9
- DLMS_SPODES_client/task.py,sha256=MSXIMnvAhO4GPBhB9eh12AIWINYxdM9VhASg3Mpmy9s,76093
9
+ DLMS_SPODES_client/task.py,sha256=xgiEk7Fu3pp24rgVcRQ_R2asK9rZwA0KhtZXfvZYi6Q,76509
10
10
  DLMS_SPODES_client/gurux_common/enums/TraceLevel.py,sha256=Ne0Rn3c9ACqQjmde_ksbiQxIUv6nXsPQRnhkGwIv3QI,521
11
11
  DLMS_SPODES_client/gurux_common/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py,sha256=HJt0uvxtkqKEkvfiqXTMNsiayN15AgPJa9_iMSSFZsQ,1429
@@ -54,8 +54,8 @@ DLMS_SPODES_client/gurux_dlms/enums/Task.py,sha256=chuOL6-IMxBvABUZtoFcaYaQQB4GZ
54
54
  DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py,sha256=qT87LMbIYEs3TYPIp3N-dR2Tcg9KhKyiELwhVl5U-tw,233
55
55
  DLMS_SPODES_client/gurux_dlms/enums/__init__.py,sha256=F_sgGwNmmdpbKvP1klJQUNiLXxU2BtZ-LgEI9e6xP8g,1314
56
56
  DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py,sha256=7D9EYcfiZxwbk8sfpHv7s2nYqrbmGf-Tbwv2T-gqmgk,53226
57
- dlms_spodes_client-0.19.11.dist-info/METADATA,sha256=WNXbO-vb3vSfL9nYm9kEFyTr1xPWa8aTVfNkAe25s6I,986
58
- dlms_spodes_client-0.19.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
59
- dlms_spodes_client-0.19.11.dist-info/entry_points.txt,sha256=Z6UTeQjjCf2k1Y3Bjs0s7yr-UYSWb-TvJMuG2K2MApw,70
60
- dlms_spodes_client-0.19.11.dist-info/top_level.txt,sha256=rh_3Uig5bc6J_lKni01btol7dX_IgIJulNtGjGehmBE,19
61
- dlms_spodes_client-0.19.11.dist-info/RECORD,,
57
+ dlms_spodes_client-0.19.13.dist-info/METADATA,sha256=T6U2znlwbvDl53LDxlksEmmOXJKGett3mwG5QeR08UI,986
58
+ dlms_spodes_client-0.19.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
59
+ dlms_spodes_client-0.19.13.dist-info/entry_points.txt,sha256=Z6UTeQjjCf2k1Y3Bjs0s7yr-UYSWb-TvJMuG2K2MApw,70
60
+ dlms_spodes_client-0.19.13.dist-info/top_level.txt,sha256=rh_3Uig5bc6J_lKni01btol7dX_IgIJulNtGjGehmBE,19
61
+ dlms_spodes_client-0.19.13.dist-info/RECORD,,