DLMS-SPODES-client 0.19.12__tar.gz → 0.19.13__tar.gz

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.
Files changed (79) hide show
  1. {dlms_spodes_client-0.19.12/src/DLMS_SPODES_client.egg-info → dlms_spodes_client-0.19.13}/PKG-INFO +2 -2
  2. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/pyproject.toml +2 -2
  3. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/client.py +1 -0
  4. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/task.py +53 -52
  5. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13/src/DLMS_SPODES_client.egg-info}/PKG-INFO +2 -2
  6. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client.egg-info/requires.txt +1 -1
  7. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/client_log.txt +771 -0
  8. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/test_Client.py +3 -2
  9. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/.gitignore +0 -0
  10. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/README.md +0 -0
  11. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/setup.cfg +0 -0
  12. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/FCS16.py +0 -0
  13. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/__init__.py +0 -0
  14. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +0 -0
  15. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_common/enums/__init__.py +0 -0
  16. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +0 -0
  17. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/CountType.py +0 -0
  18. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +0 -0
  19. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXCiphering.py +0 -0
  20. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMS.py +0 -0
  21. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +0 -0
  22. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +0 -0
  23. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +0 -0
  24. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +0 -0
  25. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +0 -0
  26. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +0 -0
  27. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +0 -0
  28. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/GXReplyData.py +0 -0
  29. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +0 -0
  30. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/MBusCommand.py +0 -0
  31. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +0 -0
  32. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/ResponseType.py +0 -0
  33. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/SetResponseType.py +0 -0
  34. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +0 -0
  35. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/__init__.py +0 -0
  36. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Access.py +0 -0
  37. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +0 -0
  38. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +0 -0
  39. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/BerType.py +0 -0
  40. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Command.py +0 -0
  41. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Definition.py +0 -0
  42. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +0 -0
  43. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +0 -0
  44. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +0 -0
  45. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +0 -0
  46. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +0 -0
  47. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +0 -0
  48. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +0 -0
  49. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Priority.py +0 -0
  50. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +0 -0
  51. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Security.py +0 -0
  52. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Service.py +0 -0
  53. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +0 -0
  54. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +0 -0
  55. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Standard.py +0 -0
  56. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/StateError.py +0 -0
  57. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/Task.py +0 -0
  58. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +0 -0
  59. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/enums/__init__.py +0 -0
  60. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +0 -0
  61. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/logger.py +0 -0
  62. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/py.typed +0 -0
  63. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/services.py +0 -0
  64. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/session.py +0 -0
  65. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client/settings.py +0 -0
  66. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client.egg-info/SOURCES.txt +0 -0
  67. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client.egg-info/dependency_links.txt +0 -0
  68. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client.egg-info/entry_points.txt +0 -0
  69. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/src/DLMS_SPODES_client.egg-info/top_level.txt +0 -0
  70. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/Firmwares/firmwares.dat +0 -0
  71. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/Firmwares/firmwares_1_2_11.dat +0 -0
  72. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/Firmwares/firmwares_1_7_2.dat +0 -0
  73. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/Types/303030/0000600101ff020009054d324d5f31/0000600102ff02000906312e332e3330.xml +0 -0
  74. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/Types/313031/0000600101ff020009054d324d5f31/0000600102ff02000906312e322e3131.xml +0 -0
  75. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/config.toml +0 -0
  76. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/name2.csv +0 -0
  77. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/test_logger.py +0 -0
  78. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test/test_services.py +0 -0
  79. {dlms_spodes_client-0.19.12 → dlms_spodes_client-0.19.13}/test//320/272/320/276/320/275/321/204/320/270/320/263/321/203/321/200/320/260/321/206/320/270/321/217 GSM.csv" +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DLMS_SPODES_client
3
- Version: 0.19.12
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
@@ -15,7 +15,7 @@ exclude = ["Types"]
15
15
 
16
16
  [project]
17
17
  name = "DLMS_SPODES_client"
18
- version = "0.19.12"
18
+ version = "0.19.13"
19
19
  requires-python = ">= 3.12"
20
20
  authors = [
21
21
  {name="Serj Kotilevski", email="youserj@outlook.com"}
@@ -26,7 +26,7 @@ dependencies = [
26
26
  "semver >= 3.0",
27
27
  "StructResult >= 0.9.2, <0.10",
28
28
  "DLMS-SPODES-communications >= 1.4.9, <1.5",
29
- "DLMS_SPODES >= 0.87.6, < 0.88",
29
+ "DLMS_SPODES >= 0.87.7, < 0.88",
30
30
  "DLMSadapter >= 0.7.5, < 0.8",
31
31
  "DLMSCommunicationProfile >= 0.1.11, < 0.2",
32
32
  "numpy >= 2.3.2"
@@ -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
@@ -291,11 +291,11 @@ class StrictOK(Base[result.StrictOk], Protocol):
291
291
  async def exchange(self, c: Client) -> result.StrictOk | result.Error: ...
292
292
 
293
293
 
294
- @dataclass
294
+ @dataclass(frozen=True)
295
295
  class ClientBlocking(SimpleCopy, OK):
296
296
  """complete by time or abort"""
297
- delay: Final[float] = field(default=99999999.0)
298
- msg: str = ""
297
+ delay: float = field(default=99999999.0)
298
+ msg: str = "client blocking"
299
299
 
300
300
  async def run(self, c: Client) -> result.Ok | result.Error:
301
301
  try:
@@ -312,8 +312,9 @@ class ClientBlocking(SimpleCopy, OK):
312
312
 
313
313
 
314
314
  # todo: make with <data_link>
315
+ @dataclass
315
316
  class TestDataLink(SimpleCopy, OK):
316
- msg: str = ""
317
+ msg: str = "test DLink"
317
318
 
318
319
  async def physical(self, c: Client) -> result.Ok | result.Error:
319
320
  if OSI.PHYSICAL not in c.level:
@@ -336,18 +337,18 @@ class TestDataLink(SimpleCopy, OK):
336
337
  return result.OK
337
338
 
338
339
 
339
- @dataclass
340
+ @dataclass(frozen=True)
340
341
  class Dummy(SimpleCopy, OK):
341
- msg: str = ""
342
+ msg: str = "dummy"
342
343
 
343
344
  async def exchange(self, c: Client) -> result.Ok | result.Error:
344
345
  """"""
345
346
  return result.OK
346
347
 
347
348
 
348
- @dataclass
349
+ @dataclass(frozen=True)
349
350
  class HardwareDisconnect(SimpleCopy, OK):
350
- msg: str = ""
351
+ msg: str = "hardware disconnect"
351
352
 
352
353
  @override
353
354
  async def exchange(self, c: Client) -> result.Ok | result.Error:
@@ -358,9 +359,9 @@ class HardwareDisconnect(SimpleCopy, OK):
358
359
  return result.OK
359
360
 
360
361
 
361
- @dataclass
362
+ @dataclass(frozen=True)
362
363
  class HardwareReconnect(SimpleCopy, OK):
363
- delay: Final[float] = 0.0
364
+ delay: float = 0.0
364
365
  """delay between disconnect and restore Application"""
365
366
  msg: str = "reconnect media without response"
366
367
 
@@ -374,13 +375,13 @@ class HardwareReconnect(SimpleCopy, OK):
374
375
  return result.OK
375
376
 
376
377
 
377
- @dataclass
378
+ @dataclass(frozen=True)
378
379
  class Loop(OK):
379
380
  task: Base[result.Result]
380
381
  func: Callable[[Any], bool]
381
- delay: Final[int] = 0.0
382
- msg: str = ""
383
- attempt_amount: Final[int] = 0
382
+ delay: int = 0.0
383
+ msg: str = "loop"
384
+ attempt_amount: int = 0
384
385
  """0 is never end loop"""
385
386
 
386
387
  def copy(self) -> Self:
@@ -411,7 +412,7 @@ class ConditionalTask[T](Base):
411
412
  comp_value: T
412
413
  predicate: Callable[[T, T], bool]
413
414
  main_task: Base[result.Result]
414
- msg: str
415
+ msg: str = "conditional task"
415
416
 
416
417
  async def exchange(self, c: Client) -> result.Result:
417
418
  res = await self.precondition_task.exchange(c)
@@ -434,7 +435,7 @@ class Scheduler[T: result.Result](Base[T]):
434
435
  repetition_delay_min: Final[int] = 1
435
436
  repetition_delay_exponent: Final[int] = 100
436
437
  repetition_delay_max: Final[int] = 100
437
- msg: str = ""
438
+ msg: str = "sheduler"
438
439
 
439
440
  def copy(self) -> "Scheduler[T]":
440
441
  return Scheduler(
@@ -492,8 +493,8 @@ class Subtasks[U: Base[result.Result]](Protocol):
492
493
  class List[T: result.Result, U: Base[result.Result]](Subtasks[U], _List[T]):
493
494
  """for exchange task sequence"""
494
495
  __is_exchange: bool
495
- msg: str
496
496
  err_ignore: bool
497
+ msg: str
497
498
  __current: Base[T]
498
499
 
499
500
  def __init__(self, *tasks: Base[T], msg: str = "", err_ignore: bool = True):
@@ -546,7 +547,7 @@ class Sequence[*Ts](Subtasks[Base[result.Result]], _Sequence[*Ts]):
546
547
  __current: "Base[result.Result] | Sequence[*Ts]"
547
548
  tasks: tuple[Base[result.Result], ...]
548
549
 
549
- 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):
550
551
  self.tasks = tasks
551
552
  self.__current = self
552
553
  self.msg = self.__class__.__name__ if msg == "" else msg
@@ -570,20 +571,21 @@ class Sequence[*Ts](Subtasks[Base[result.Result]], _Sequence[*Ts]):
570
571
  for t in self.tasks:
571
572
  self.__current = t
572
573
  try:
573
- if (
574
- isinstance(res_one := await t.exchange(c), result.Error)
575
- and not self.err_ignore
576
- ):
577
- 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
578
579
  res = res.add(res_one)
579
580
  except exc.ResultError as e: # todo: make without except
580
- res.add(result.Error.from_e(e).with_msg(t.msg))
581
+ res = res.add(result.Error.from_e(e).with_msg(self.msg))
581
582
  return cast("result.Sequence[*Ts]", res)
582
583
 
583
584
 
585
+ @dataclass(frozen=True)
584
586
  class SetLocalTime(SimpleCopy, OK):
585
587
  """without decide time transfer"""
586
- msg: str
588
+ msg: str = "set local time"
587
589
 
588
590
  async def exchange(self, c: Client) -> result.Ok | result.Error:
589
591
  clock_obj: Clock = c.objects.get_object("0.0.1.0.0.255")
@@ -603,17 +605,17 @@ class SetLocalTime(SimpleCopy, OK):
603
605
  return result.OK
604
606
 
605
607
 
608
+ @dataclass(frozen=True)
606
609
  class GetFirmwareVersion(SimpleCopy, CDT):
607
- """get firmware version by Client.id"""
608
- msg: str
610
+ msg: str = "get firmware version"
609
611
 
610
612
  async def exchange(self, c: Client) -> result.SimpleOrError[cdt.CommonDataType]:
611
613
  return await Par2Data(Parameter(c.objects.id.f_ver.par[:6]).get_attr(c.objects.id.f_ver.par[6])).exchange(c)
612
614
 
613
615
 
616
+ @dataclass(frozen=True)
614
617
  class FindFirmwareVersion(SimpleCopy, Simple[collection.ParameterValue]):
615
- """try find COSEM server version, return: instance(B group), CDT"""
616
- msg: str
618
+ msg: str = "try find COSEM server version, return: instance(B group), CDT"
617
619
 
618
620
  async def exchange(self, c: Client) -> result.SimpleOrError[collection.ParameterValue]:
619
621
  err = result.ErrorAccumulator()
@@ -636,8 +638,8 @@ class FindFirmwareVersion(SimpleCopy, Simple[collection.ParameterValue]):
636
638
  raise RuntimeError(f"empty {err}")
637
639
 
638
640
 
641
+ @dataclass(frozen=True)
639
642
  class FindFirmwareId(SimpleCopy, Simple[collection.ParameterValue]):
640
- """try find COSEM server identifier, return: FirmwareID"""
641
643
  msg: str = "find firmaware Identifier"
642
644
 
643
645
  async def exchange(self, c: Client) -> result.SimpleOrError[collection.ParameterValue]:
@@ -661,10 +663,9 @@ class FindFirmwareId(SimpleCopy, Simple[collection.ParameterValue]):
661
663
  raise RuntimeError(f"empty {err}")
662
664
 
663
665
 
664
- @dataclass
666
+ @dataclass(frozen=True)
665
667
  class KeepAlive(SimpleCopy, OK):
666
- """use read LDN.ln"""
667
- msg: str = "keep alive"
668
+ msg: str = "keep alive(read LND.ln)"
668
669
 
669
670
  async def exchange(self, c: Client) -> result.Ok | result.Error:
670
671
  if isinstance(res := await Par2Data(dlms_par.LDN.value).exchange(c), result.Error):
@@ -697,7 +698,7 @@ class GetLDN(SimpleCopy, CDT[octet_string.LDN]):
697
698
  @dataclass
698
699
  class MatchLDN(OK):
699
700
  universal: bool = field(default=False)
700
- msg: str = ""
701
+ msg: str = "matching LDN"
701
702
 
702
703
  async def exchange(self, c: Client) -> result.Ok | result.Error:
703
704
  if isinstance((res := await GetLDN().exchange(c)), result.Error):
@@ -945,7 +946,7 @@ class MapTypeCreator:
945
946
  @dataclass
946
947
  class InitType(SimpleCopy, Simple[collection.Collection]):
947
948
  adapter: Adapter
948
- msg: str = ""
949
+ msg: str = "initiate type"
949
950
 
950
951
  async def exchange(self, c: Client) -> result.SimpleOrError[collection.Collection]:
951
952
  if isinstance((res := await Sequence(
@@ -992,7 +993,7 @@ get_adapter(gag) # Dummy Adapter
992
993
  class ReadAttribute(SimpleCopy, CDT):
993
994
  ln: collection.LNContaining
994
995
  index: int
995
- msg: str = ""
996
+ msg: str = "read LN attribute"
996
997
 
997
998
  async def exchange(self, c: Client) -> result.Simple[cdt.CommonDataType]:
998
999
  obj = c.objects.get_object(self.ln)
@@ -1003,7 +1004,7 @@ class ReadAttribute(SimpleCopy, CDT):
1003
1004
  class ReadObjAttr(SimpleCopy, CDT):
1004
1005
  obj: collection.InterfaceClass
1005
1006
  index: int
1006
- msg: str = ""
1007
+ msg: str = "read object attribute"
1007
1008
 
1008
1009
  async def exchange(self, c: Client) -> result.SimpleOrError[cdt.CommonDataType]:
1009
1010
  # TODO: check is_readable?
@@ -1025,7 +1026,7 @@ class ReadObjAttr(SimpleCopy, CDT):
1025
1026
  return result.Error.from_e(e)
1026
1027
 
1027
1028
 
1028
- @dataclass
1029
+ @dataclass(frozen=True)
1029
1030
  class Par2Data[T: cdt.CommonDataType](SimpleCopy, CDT[T]):
1030
1031
  """get CommonDataType by Parameter"""
1031
1032
  par: Parameter
@@ -1056,13 +1057,13 @@ def is_empty(value: cdt.CommonDataType | None) -> bool:
1056
1057
  return True if value is None else False
1057
1058
 
1058
1059
 
1059
- @dataclass
1060
+ @dataclass(frozen=True)
1060
1061
  class ReadAttributeIf(SimpleCopy, Base):
1061
1062
  """read if func with arg as value is True"""
1062
1063
  ln: collection.LNContaining
1063
1064
  index: int
1064
1065
  func: AttrValueComp
1065
- msg: str
1066
+ msg: str = "read attribute with condition"
1066
1067
 
1067
1068
  async def exchange(self, c: Client) -> result.Simple[cdt.CommonDataType]:
1068
1069
  # TODO: check is_readable
@@ -1075,7 +1076,7 @@ class ReadAttributeIf(SimpleCopy, Base):
1075
1076
  return result.OK
1076
1077
 
1077
1078
 
1078
- @dataclass
1079
+ @dataclass(frozen=True)
1079
1080
  class ReadEmptyAttribute(SimpleCopy, Base):
1080
1081
  ln: collection.LNContaining
1081
1082
  index: int
@@ -1090,7 +1091,7 @@ class ReadEmptyAttribute(SimpleCopy, Base):
1090
1091
  ).exchange(c)
1091
1092
 
1092
1093
 
1093
- @dataclass
1094
+ @dataclass(frozen=True)
1094
1095
  class ReadWritableAttributes(SimpleCopy, Base):
1095
1096
  ln: collection.LNContaining
1096
1097
  indexes: tuple[int, ...]
@@ -1116,7 +1117,7 @@ class ReadWritableAttributes(SimpleCopy, Base):
1116
1117
 
1117
1118
 
1118
1119
  # copy past from ReadWritableAttributes
1119
- @dataclass
1120
+ @dataclass(frozen=True)
1120
1121
  class ActualizeAttributes(SimpleCopy, OK):
1121
1122
  ln: collection.LNContaining
1122
1123
  indexes: tuple[int, ...]
@@ -1142,7 +1143,7 @@ class ActualizeAttributes(SimpleCopy, OK):
1142
1143
  return result.OK
1143
1144
 
1144
1145
 
1145
- @dataclass
1146
+ @dataclass(frozen=True)
1146
1147
  class ReadAttributes(SimpleCopy, _List[cdt.CommonDataType]):
1147
1148
  ln: collection.LNContaining
1148
1149
  indexes: tuple[int, ...]
@@ -1361,7 +1362,7 @@ class ImageTransfer(SimpleCopy, StrictOK):
1361
1362
  n_t_b: int = field(init=False, default=0)
1362
1363
  """not transferred block"""
1363
1364
  n_blocks: int = field(init=False)
1364
- msg: str = ""
1365
+ msg: str = "image transfer"
1365
1366
 
1366
1367
  def __post_init__(self) -> None:
1367
1368
  self.ITI = ImageTransferInitiate((
@@ -1562,7 +1563,7 @@ class ActivateImage(SimpleCopy, OK):
1562
1563
 
1563
1564
  class TestAll(Base):
1564
1565
  """read all attributes with check access""" # todo: add Write with access
1565
- msg: str = ""
1566
+ msg: str = "test all"
1566
1567
 
1567
1568
  async def exchange(self, c: Client):
1568
1569
  # todo: refactoring with <append_err>
@@ -1615,7 +1616,7 @@ class TestAll(Base):
1615
1616
  @dataclass
1616
1617
  class ApplyTemplate(Base):
1617
1618
  template: collection.Template
1618
- msg: str = ""
1619
+ msg: str = "apply template"
1619
1620
 
1620
1621
  async def exchange(self, c: Client) -> result.Result:
1621
1622
  # todo: search col
@@ -1645,7 +1646,7 @@ class ApplyTemplate(Base):
1645
1646
  @dataclass
1646
1647
  class ReadTemplate(OK):
1647
1648
  template: collection.Template
1648
- msg: str = ""
1649
+ msg: str = "read template"
1649
1650
 
1650
1651
  async def exchange(self, c: Client) -> result.Ok | result.Error:
1651
1652
  # todo: copypast from <ApplyTemplate>
@@ -1676,7 +1677,7 @@ class ReadTemplate(OK):
1676
1677
  class AccessValidate(Base[result.Ok | result.Simple[list[Parameter]]]):
1677
1678
  """check all access rights for current SAP"""
1678
1679
  with_correct: bool = False
1679
- msg: str = ""
1680
+ msg: str = "all access validate"
1680
1681
 
1681
1682
  # todo: make with result.Error
1682
1683
  async def exchange(self, c: Client) -> result.Ok | result.Simple[list[Parameter]] | result.Error:
@@ -1742,7 +1743,7 @@ class WriteList(SimpleCopy, _List[result.Ok]):
1742
1743
  par_datas: tuple[tuple[Parameter, cdt.CommonDataType], ...]
1743
1744
  err_ignore: bool
1744
1745
 
1745
- 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:
1746
1747
  self.par_datas = par_datas
1747
1748
  self.err_ignore = err_ignore
1748
1749
  self.msg = msg
@@ -1769,7 +1770,7 @@ class WriteTranscript(SimpleCopy, OK):
1769
1770
  async def exchange(self, c: Client) -> result.Ok | result.Error:
1770
1771
  if isinstance((res := await Par2Data[cdt.CommonDataType](self.par).exchange(c)), result.Error):
1771
1772
  return res
1772
- if isinstance(data, cdt.Digital):
1773
+ if isinstance(res.value, cdt.Digital):
1773
1774
  s_u = c.objects.par2su(self.par)
1774
1775
  if isinstance(s_u, cdt.ScalUnitType):
1775
1776
  if not isinstance(self.value, str):
@@ -1790,7 +1791,7 @@ class WriteTranscripts(SimpleCopy, _List[result.Ok]):
1790
1791
  par_values: tuple[tuple[Parameter, cdt.Transcript], ...]
1791
1792
  err_ignore: bool
1792
1793
 
1793
- 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"):
1794
1795
  self.par_values = par_values
1795
1796
  self.err_ignore = err_ignore
1796
1797
  self.msg = msg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DLMS_SPODES_client
3
- Version: 0.19.12
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
@@ -3,7 +3,7 @@ pycryptodomex>=3.22.0
3
3
  semver>=3.0
4
4
  StructResult<0.10,>=0.9.2
5
5
  DLMS-SPODES-communications<1.5,>=1.4.9
6
- DLMS_SPODES<0.88,>=0.87.6
6
+ DLMS_SPODES<0.88,>=0.87.7
7
7
  DLMSadapter<0.8,>=0.7.5
8
8
  DLMSCommunicationProfile<0.2,>=0.1.11
9
9
  numpy>=2.3.2