DLMS-SPODES-client 0.19.27__tar.gz → 0.19.28__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.27 → dlms_spodes_client-0.19.28}/PKG-INFO +1 -1
  2. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/pyproject.toml +1 -1
  3. dlms_spodes_client-0.19.28/src/DLMS_SPODES_client/services.py +90 -0
  4. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client.egg-info/PKG-INFO +1 -1
  5. dlms_spodes_client-0.19.27/src/DLMS_SPODES_client/services.py +0 -97
  6. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/.github/workflows/publish.yaml +0 -0
  7. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/.gitignore +0 -0
  8. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/README.md +0 -0
  9. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/setup.cfg +0 -0
  10. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/FCS16.py +0 -0
  11. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/__init__.py +0 -0
  12. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/client.py +0 -0
  13. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +0 -0
  14. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_common/enums/__init__.py +0 -0
  15. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +0 -0
  16. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/CountType.py +0 -0
  17. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +0 -0
  18. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXCiphering.py +0 -0
  19. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMS.py +0 -0
  20. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +0 -0
  21. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +0 -0
  22. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +0 -0
  23. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +0 -0
  24. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +0 -0
  25. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +0 -0
  26. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +0 -0
  27. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/GXReplyData.py +0 -0
  28. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +0 -0
  29. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/MBusCommand.py +0 -0
  30. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +0 -0
  31. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/ResponseType.py +0 -0
  32. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/SetResponseType.py +0 -0
  33. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +0 -0
  34. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/__init__.py +0 -0
  35. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Access.py +0 -0
  36. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +0 -0
  37. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +0 -0
  38. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/BerType.py +0 -0
  39. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Command.py +0 -0
  40. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Definition.py +0 -0
  41. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +0 -0
  42. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +0 -0
  43. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +0 -0
  44. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +0 -0
  45. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +0 -0
  46. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +0 -0
  47. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +0 -0
  48. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Priority.py +0 -0
  49. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +0 -0
  50. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Security.py +0 -0
  51. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Service.py +0 -0
  52. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +0 -0
  53. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +0 -0
  54. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Standard.py +0 -0
  55. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/StateError.py +0 -0
  56. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/Task.py +0 -0
  57. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +0 -0
  58. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/enums/__init__.py +0 -0
  59. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +0 -0
  60. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/logger.py +0 -0
  61. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/py.typed +0 -0
  62. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/session.py +0 -0
  63. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/settings.py +0 -0
  64. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client/task.py +0 -0
  65. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client.egg-info/SOURCES.txt +0 -0
  66. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client.egg-info/dependency_links.txt +0 -0
  67. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client.egg-info/entry_points.txt +0 -0
  68. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client.egg-info/requires.txt +0 -0
  69. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/src/DLMS_SPODES_client.egg-info/top_level.txt +0 -0
  70. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/Firmwares/firmwares.dat +0 -0
  71. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/Firmwares/firmwares_1_2_11.dat +0 -0
  72. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/Firmwares/firmwares_1_7_2.dat +0 -0
  73. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/client_log.txt +0 -0
  74. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/config.toml +0 -0
  75. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/name2.csv +0 -0
  76. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/test_Client.py +0 -0
  77. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/test_logger.py +0 -0
  78. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/test/test_services.py +0 -0
  79. {dlms_spodes_client-0.19.27 → dlms_spodes_client-0.19.28}/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.27
3
+ Version: 0.19.28
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 @@ exclude = ["Types"]
15
15
 
16
16
  [project]
17
17
  name = "DLMS_SPODES_client"
18
- version = "0.19.27"
18
+ version = "0.19.28"
19
19
  requires-python = ">= 3.12"
20
20
  authors = [
21
21
  {name="Serj Kotilevski", email="youserj@outlook.com"}
@@ -0,0 +1,90 @@
1
+ from .client import Client, Network, IDFactory, c_pf
2
+ import csv
3
+ from itertools import count
4
+ from .settings import settings
5
+
6
+
7
+ _h: dict[str, [str]] = dict(settings.from_csv.header_names)
8
+ """header names"""
9
+
10
+
11
+ class IpAddress:
12
+ __value: list[int]
13
+
14
+ def __init__(self, value: str = "127.0.0.1"):
15
+ self.__value = list()
16
+ for el1 in value.split("."):
17
+ if el1.isdigit():
18
+ el = int(el1)
19
+ if 0 <= el <= 255:
20
+ self.__value.append(el)
21
+ else:
22
+ raise ValueError(F"Wrong digit in value: {el}, must be 0..255")
23
+ else:
24
+ raise ValueError(F"Value is not digit: {el1}")
25
+ if len(self.__value) != 4:
26
+ raise ValueError(F"Length of Ip address {value} must be 4, got {len(self.__value)}")
27
+
28
+ @classmethod
29
+ def is_valid(cls, value: str) -> bool:
30
+ try:
31
+ cls(value)
32
+ return True
33
+ except ValueError:
34
+ return False
35
+
36
+ def __str__(self):
37
+ return ".".join(map(str, self.__value))
38
+
39
+
40
+ def get_client_from_csv(
41
+ file_name: str,
42
+ id_factory: IDFactory,
43
+ universal: bool = False
44
+ ) -> list[Client]:
45
+ """file in utf-8 format"""
46
+ da: str
47
+ with open(file_name, "r", encoding="utf-8-sig") as csv_file:
48
+ dialect = csv.Sniffer().sniff(csv_file.readline(1024))
49
+ csv_file.seek(0)
50
+ reader = csv.reader(csv_file, dialect=dialect)
51
+ first_row: list[str] = next(reader)
52
+ if any(map(IpAddress.is_valid, first_row)): # search ip_address in first row
53
+ raise ValueError("Table header not found")
54
+ # header is exist search column by name
55
+ field_names: list[str] = []
56
+ for index, cell in enumerate(first_row):
57
+ for column in _h:
58
+ if any(map(cell.lower().startswith, _h[column])):
59
+ field_names.append(_h[column][0])
60
+ break
61
+ else:
62
+ field_names.append(F"unknown{index}")
63
+ if all(map(lambda name: name in field_names, ("ip",))):
64
+ csv_file.seek(0)
65
+ reader = csv.DictReader(csv_file, fieldnames=field_names, dialect=dialect)
66
+ next(reader) # skeep header
67
+ res: list[Client] = []
68
+ for i in reader:
69
+ if IpAddress.is_valid(i["ip"]):
70
+ res.append(c := Client(
71
+ media=Network(
72
+ host=i.get("ip") or "127.0.0.1",
73
+ port=i.get("port") or "8888",
74
+ to_recv=float(i.get("timeout") or 120.0)
75
+ ),
76
+ SAP=int(i.get("sap") or 0x30),
77
+ secret=bytes(i.get("secret", "0000000000000000"), "utf-8"),
78
+ m_id=int(i.get("m_id") or 2),
79
+ id_=id_factory.create(),
80
+ universal=universal
81
+ ))
82
+ if (
83
+ (da := i.get("da"))
84
+ and da.isdigit()
85
+ ):
86
+ c.com_profile.parameters.device_address = int(da)
87
+ if name := i.get("name"):
88
+ c.name = name
89
+ return res
90
+ raise ValueError("not find at least one client")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DLMS_SPODES_client
3
- Version: 0.19.27
3
+ Version: 0.19.28
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
@@ -1,97 +0,0 @@
1
- from .client import Client, Network, IDFactory, c_pf
2
- import csv
3
- from itertools import count
4
- from .settings import settings
5
-
6
-
7
- _h: dict[str, [str]] = dict(settings.from_csv.header_names)
8
- """header names"""
9
-
10
-
11
- class IpAddress:
12
- __value: list[int]
13
-
14
- def __init__(self, value: str = '127.0.0.1'):
15
- self.__value = list()
16
- for el1 in value.split('.'):
17
- if el1.isdigit():
18
- el = int(el1)
19
- if 0 <= el <= 255:
20
- self.__value.append(el)
21
- else:
22
- raise ValueError(F'Wrong digit in value: {el}, must be 0..255')
23
- else:
24
- raise ValueError(F'Value is not digit: {el1}')
25
- if len(self.__value) != 4:
26
- raise ValueError(F'Length of Ip address {value} must be 4, got {len(self.__value)}')
27
-
28
- @classmethod
29
- def is_valid(cls, value: str) -> bool:
30
- try:
31
- cls(value)
32
- return True
33
- except ValueError:
34
- return False
35
-
36
- def __str__(self):
37
- return '.'.join(map(str, self.__value))
38
-
39
-
40
- def get_client_from_csv(
41
- file_name: str,
42
- id_factory: IDFactory = None,
43
- universal: bool = False
44
- ) -> list[Client]:
45
- """file in utf-8 format"""
46
- da: str
47
- with open(file_name, 'r', encoding="utf-8-sig") as csv_file:
48
- sniffer = csv.Sniffer()
49
- dialect = sniffer.sniff(csv_file.readline(1024))
50
- csv_file.seek(0)
51
- reader = csv.reader(csv_file, dialect=dialect)
52
- first_row: list[str] = next(reader)
53
- if any(map(IpAddress.is_valid, first_row)): # search ip_address in first row
54
- # header is absence
55
- raise ValueError('Не найден заголовок таблицы')
56
- else: # header is exist
57
- # search column by name
58
- column_name_count = count()
59
- field_names: list[str] = list()
60
- for index, cell in enumerate(first_row):
61
- for column in _h:
62
- if any(map(cell.lower().startswith, _h[column])):
63
- field_names.append(_h[column][0])
64
- break
65
- else:
66
- field_names.append(F'unknown{next(column_name_count)}')
67
- if all(map(lambda name: name in field_names, ('ip',))):
68
- csv_file.seek(0)
69
- reader = csv.DictReader(csv_file, fieldnames=field_names, dialect=dialect)
70
- next(reader)
71
- res: list[Client] = list()
72
- for i in reader:
73
- if IpAddress.is_valid(i['ip']):
74
- res.append(c := Client(
75
- media=Network(
76
- host=i.get("ip", "127.0.0.1"),
77
- port="8888"
78
- ),
79
- id_=id_factory.create() if id_factory else None,
80
- universal=universal
81
- ))
82
- c.com_profile.parameters.inactivity_time_out = int(i.get("timeout", 120)) # todo: work only for HDLC, make better
83
- c.secret = bytes(i.get('secret', '0000000000000000'), 'utf-8')
84
- if m_id := i.get('m_id'):
85
- c.m_id.set(m_id)
86
- if port := i.get('port'):
87
- c.media.port = port
88
- if sap := i.get('sap'):
89
- c.SAP.set(sap)
90
- if (
91
- (da := i.get('da'))
92
- and da.isdigit()
93
- ):
94
- c.com_profile.parameters.device_address = int(da)
95
- if name := i.get("name"):
96
- c.name = name
97
- return res