DLMS-SPODES-client 0.19.22__py3-none-any.whl → 0.19.24__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.
Files changed (60) hide show
  1. DLMS_SPODES_client/FCS16.py +39 -39
  2. DLMS_SPODES_client/__init__.py +12 -12
  3. DLMS_SPODES_client/client.py +2091 -2091
  4. DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +21 -21
  5. DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +37 -37
  6. DLMS_SPODES_client/gurux_dlms/CountType.py +16 -16
  7. DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +545 -545
  8. DLMS_SPODES_client/gurux_dlms/GXCiphering.py +196 -196
  9. DLMS_SPODES_client/gurux_dlms/GXDLMS.py +426 -426
  10. DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +237 -237
  11. DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +977 -977
  12. DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +90 -90
  13. DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +139 -139
  14. DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +33 -33
  15. DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +21 -21
  16. DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +254 -254
  17. DLMS_SPODES_client/gurux_dlms/GXReplyData.py +87 -87
  18. DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +9 -9
  19. DLMS_SPODES_client/gurux_dlms/MBusCommand.py +8 -8
  20. DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +27 -27
  21. DLMS_SPODES_client/gurux_dlms/ResponseType.py +8 -8
  22. DLMS_SPODES_client/gurux_dlms/SetResponseType.py +29 -29
  23. DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +9 -9
  24. DLMS_SPODES_client/gurux_dlms/__init__.py +75 -75
  25. DLMS_SPODES_client/gurux_dlms/enums/Access.py +12 -12
  26. DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +14 -14
  27. DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +41 -41
  28. DLMS_SPODES_client/gurux_dlms/enums/BerType.py +35 -35
  29. DLMS_SPODES_client/gurux_dlms/enums/Command.py +285 -285
  30. DLMS_SPODES_client/gurux_dlms/enums/Definition.py +9 -9
  31. DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +46 -46
  32. DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +12 -12
  33. DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +10 -10
  34. DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +9 -9
  35. DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +10 -10
  36. DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +13 -13
  37. DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +306 -306
  38. DLMS_SPODES_client/gurux_dlms/enums/Priority.py +7 -7
  39. DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +9 -9
  40. DLMS_SPODES_client/gurux_dlms/enums/Security.py +14 -14
  41. DLMS_SPODES_client/gurux_dlms/enums/Service.py +16 -16
  42. DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +9 -9
  43. DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +8 -8
  44. DLMS_SPODES_client/gurux_dlms/enums/Standard.py +18 -18
  45. DLMS_SPODES_client/gurux_dlms/enums/StateError.py +7 -7
  46. DLMS_SPODES_client/gurux_dlms/enums/Task.py +10 -10
  47. DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +10 -10
  48. DLMS_SPODES_client/gurux_dlms/enums/__init__.py +33 -33
  49. DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +1673 -1673
  50. DLMS_SPODES_client/logger.py +56 -56
  51. DLMS_SPODES_client/services.py +97 -97
  52. DLMS_SPODES_client/session.py +365 -365
  53. DLMS_SPODES_client/settings.py +48 -48
  54. DLMS_SPODES_client/task.py +1841 -1842
  55. {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.24.dist-info}/METADATA +29 -27
  56. dlms_spodes_client-0.19.24.dist-info/RECORD +61 -0
  57. dlms_spodes_client-0.19.22.dist-info/RECORD +0 -61
  58. {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.24.dist-info}/WHEEL +0 -0
  59. {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.24.dist-info}/entry_points.txt +0 -0
  60. {dlms_spodes_client-0.19.22.dist-info → dlms_spodes_client-0.19.24.dist-info}/top_level.txt +0 -0
@@ -1,56 +1,56 @@
1
- import logging
2
- import sys
3
- from enum import IntEnum
4
- from DLMS_SPODES.config_parser import get_values
5
-
6
-
7
- _log_config = {
8
- """logging configuration according with config.toml:[DLMSClient.logging] by default"""
9
- "disabled": False,
10
- "name": "DLMSClient",
11
- "level": logging.INFO,
12
- "fmt": "%(id)s: %(asctime)s - %(name)s - %(levelname)s - %(message)s",
13
- "datefmt": "%d.%m %H:%M",
14
- "handlers": [
15
- {"type": "Stream"}
16
- ]
17
- }
18
- logger = logging.getLogger(name=F"{_log_config['name']}")
19
- is_file_handler_exist: bool = False
20
- if __log_config_toml := get_values("DLMSClient", "logging"):
21
- _log_config.update(__log_config_toml)
22
- logger.disabled = _log_config.get("disabled", False)
23
- _state_level = _log_config.get("state_level", 19)
24
- logger.setLevel(level=_log_config["level"])
25
- formatter = logging.Formatter(
26
- fmt=_log_config["fmt"],
27
- datefmt=_log_config["datefmt"])
28
- for h in _log_config["handlers"]:
29
- match h.get("type"):
30
- case "Stream":
31
- handler = logging.StreamHandler(stream=sys.stdout)
32
- case "File":
33
- is_file_handler_exist = True
34
- handler = logging.FileHandler(
35
- filename=h.get("filename", "client_log.txt"),
36
- mode=h.get("mode", "a"),
37
- encoding="utf-8")
38
- case err:
39
- raise ValueError(F"got error logger type Handler: {err}")
40
- handler.setFormatter(formatter)
41
- logger.addHandler(handler)
42
- logger.debug(F"Start {logger}", extra={"id": "#common"})
43
- logger.propagate = False
44
- else:
45
- _state_level = 19
46
- logger.disabled = True
47
-
48
-
49
- class LogLevel(IntEnum):
50
- DEB = logging.DEBUG
51
- STATE = _state_level
52
- """for keep in client"""
53
- INFO = logging.INFO
54
- WARN = logging.WARNING
55
- ERR = logging.ERROR
56
- CRIT = logging.CRITICAL
1
+ import logging
2
+ import sys
3
+ from enum import IntEnum
4
+ from DLMS_SPODES.config_parser import get_values
5
+
6
+
7
+ _log_config = {
8
+ """logging configuration according with config.toml:[DLMSClient.logging] by default"""
9
+ "disabled": False,
10
+ "name": "DLMSClient",
11
+ "level": logging.INFO,
12
+ "fmt": "%(id)s: %(asctime)s - %(name)s - %(levelname)s - %(message)s",
13
+ "datefmt": "%d.%m %H:%M",
14
+ "handlers": [
15
+ {"type": "Stream"}
16
+ ]
17
+ }
18
+ logger = logging.getLogger(name=F"{_log_config['name']}")
19
+ is_file_handler_exist: bool = False
20
+ if __log_config_toml := get_values("DLMSClient", "logging"):
21
+ _log_config.update(__log_config_toml)
22
+ logger.disabled = _log_config.get("disabled", False)
23
+ _state_level = _log_config.get("state_level", 19)
24
+ logger.setLevel(level=_log_config["level"])
25
+ formatter = logging.Formatter(
26
+ fmt=_log_config["fmt"],
27
+ datefmt=_log_config["datefmt"])
28
+ for h in _log_config["handlers"]:
29
+ match h.get("type"):
30
+ case "Stream":
31
+ handler = logging.StreamHandler(stream=sys.stdout)
32
+ case "File":
33
+ is_file_handler_exist = True
34
+ handler = logging.FileHandler(
35
+ filename=h.get("filename", "client_log.txt"),
36
+ mode=h.get("mode", "a"),
37
+ encoding="utf-8")
38
+ case err:
39
+ raise ValueError(F"got error logger type Handler: {err}")
40
+ handler.setFormatter(formatter)
41
+ logger.addHandler(handler)
42
+ logger.debug(F"Start {logger}", extra={"id": "#common"})
43
+ logger.propagate = False
44
+ else:
45
+ _state_level = 19
46
+ logger.disabled = True
47
+
48
+
49
+ class LogLevel(IntEnum):
50
+ DEB = logging.DEBUG
51
+ STATE = _state_level
52
+ """for keep in client"""
53
+ INFO = logging.INFO
54
+ WARN = logging.WARNING
55
+ ERR = logging.ERROR
56
+ CRIT = logging.CRITICAL
@@ -1,97 +1,97 @@
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
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