DLMS-SPODES-client 0.19.36__py3-none-any.whl → 0.19.37__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 +2093 -2093
  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 +90 -90
  52. DLMS_SPODES_client/session.py +363 -363
  53. DLMS_SPODES_client/settings.py +48 -48
  54. DLMS_SPODES_client/task.py +1884 -1884
  55. {dlms_spodes_client-0.19.36.dist-info → dlms_spodes_client-0.19.37.dist-info}/METADATA +29 -29
  56. dlms_spodes_client-0.19.37.dist-info/RECORD +61 -0
  57. {dlms_spodes_client-0.19.36.dist-info → dlms_spodes_client-0.19.37.dist-info}/WHEEL +1 -1
  58. dlms_spodes_client-0.19.36.dist-info/RECORD +0 -61
  59. {dlms_spodes_client-0.19.36.dist-info → dlms_spodes_client-0.19.37.dist-info}/entry_points.txt +0 -0
  60. {dlms_spodes_client-0.19.36.dist-info → dlms_spodes_client-0.19.37.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,90 +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
+ 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")