pysamsungnasa 0.4.0__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.
- pysamsungnasa-0.4.0/LICENSE +1 -0
- pysamsungnasa-0.4.0/PKG-INFO +106 -0
- pysamsungnasa-0.4.0/README.md +59 -0
- pysamsungnasa-0.4.0/pyproject.toml +310 -0
- pysamsungnasa-0.4.0/pysamsungnasa/__init__.py +9 -0
- pysamsungnasa-0.4.0/pysamsungnasa/__main__.py +70 -0
- pysamsungnasa-0.4.0/pysamsungnasa/autodiscovery.py +30 -0
- pysamsungnasa-0.4.0/pysamsungnasa/cli.py +428 -0
- pysamsungnasa-0.4.0/pysamsungnasa/config.py +37 -0
- pysamsungnasa-0.4.0/pysamsungnasa/device/__init__.py +430 -0
- pysamsungnasa-0.4.0/pysamsungnasa/device/controllers.py +384 -0
- pysamsungnasa-0.4.0/pysamsungnasa/helpers.py +49 -0
- pysamsungnasa-0.4.0/pysamsungnasa/nasa.py +123 -0
- pysamsungnasa-0.4.0/pysamsungnasa/nasa_client.py +829 -0
- pysamsungnasa-0.4.0/pysamsungnasa/pnp/__init__.py +152 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/__init__.py +1 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/enum.py +2505 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/factory/__init__.py +86 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/factory/messages/__init__.py +27 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/factory/messages/indoor.py +2030 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/factory/messages/network.py +98 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/factory/messages/outdoor.py +2057 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/factory/messaging.py +187 -0
- pysamsungnasa-0.4.0/pysamsungnasa/protocol/parser.py +343 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
MIT License
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pysamsungnasa
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Connect to Samsung ASHP / AC units over NASA via RS485
|
|
5
|
+
Author-email: Jordan Harvey <jordan@hrvy.uk>
|
|
6
|
+
Requires-Python: >=3.13.0
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: aiotelnet~=1.1.0
|
|
15
|
+
Requires-Dist: prompt_toolkit>=3.0.0 ; extra == "cli"
|
|
16
|
+
Requires-Dist: python-dotenv>=0.9.9 ; extra == "cli"
|
|
17
|
+
Requires-Dist: mkdocs>=1.4.0 ; extra == "docs"
|
|
18
|
+
Requires-Dist: mkdocs-material>=9.0.0 ; extra == "docs"
|
|
19
|
+
Requires-Dist: mkdocstrings[python]>=0.23.0 ; extra == "docs"
|
|
20
|
+
Requires-Dist: griffe>=0.40 ; extra == "docs"
|
|
21
|
+
Requires-Dist: pymdown-extensions>=10.0 ; extra == "docs"
|
|
22
|
+
Requires-Dist: bandit[toml]==1.9.2 ; extra == "test"
|
|
23
|
+
Requires-Dist: black==25.12.0 ; extra == "test"
|
|
24
|
+
Requires-Dist: check-manifest==0.51 ; extra == "test"
|
|
25
|
+
Requires-Dist: flake8-bugbear==25.11.29 ; extra == "test"
|
|
26
|
+
Requires-Dist: flake8-docstrings ; extra == "test"
|
|
27
|
+
Requires-Dist: flake8-formatter_junit_xml ; extra == "test"
|
|
28
|
+
Requires-Dist: flake8 ; extra == "test"
|
|
29
|
+
Requires-Dist: flake8-pyproject ; extra == "test"
|
|
30
|
+
Requires-Dist: pre-commit==4.5.1 ; extra == "test"
|
|
31
|
+
Requires-Dist: pylint==4.0.4 ; extra == "test"
|
|
32
|
+
Requires-Dist: pylint_junit ; extra == "test"
|
|
33
|
+
Requires-Dist: pytest-cov==7.0.0 ; extra == "test"
|
|
34
|
+
Requires-Dist: pytest-mock<3.15.2 ; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-runner ; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-asyncio==1.3.0 ; extra == "test"
|
|
37
|
+
Requires-Dist: pytest==9.0.2 ; extra == "test"
|
|
38
|
+
Requires-Dist: pytest-github-actions-annotate-failures ; extra == "test"
|
|
39
|
+
Requires-Dist: shellcheck-py==0.11.0.1 ; extra == "test"
|
|
40
|
+
Project-URL: Documentation, https://github.com/pantherale0/pysamsungnasa
|
|
41
|
+
Project-URL: Source, https://github.com/pantherale0/pysamsungnasa
|
|
42
|
+
Project-URL: Tracker, https://github.com/pantherale0/pysamsungnasa/issues
|
|
43
|
+
Provides-Extra: cli
|
|
44
|
+
Provides-Extra: docs
|
|
45
|
+
Provides-Extra: test
|
|
46
|
+
|
|
47
|
+
# pysamsungnasa
|
|
48
|
+
|
|
49
|
+
[](https://github.com/pantherale0/pysamsungnasa/actions/workflows/test.yml)
|
|
50
|
+
[](https://codecov.io/gh/pantherale0/pysamsungnasa)
|
|
51
|
+
|
|
52
|
+
A Python library to communicate with Samsung heat pumps, in theory both cool only and cool+heat units are supported, although only tested on an EHS unit (cool+heat)
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- Connect and disconnect from Samsung HVAC/EHS units via a TCP socket over the F1/F2 connectors (NasaClient).
|
|
57
|
+
- Discover new devices on the NASA network and manage known devices (SamsungNasa).
|
|
58
|
+
- Send commands to devices and handle responses (SamsungNasa, NasaClient).
|
|
59
|
+
- Parse incoming data packets from devices (NasaPacketParser, various message classes).
|
|
60
|
+
- Represent devices with attributes and control their functions (NasaDevice, DhwController, ClimateController).
|
|
61
|
+
- Control DHW (Domestic Hot Water) settings like power, operation mode, and target temperature (DhwController).
|
|
62
|
+
- Control climate settings like power, mode, target temperature, fan speed, and more (ClimateController).
|
|
63
|
+
- Provide a mechanism for callbacks to be notified of device and packet updates (NasaDevice).
|
|
64
|
+
- Support reading device configurations (NasaDevice).
|
|
65
|
+
- Handle message construction and parsing based on message types (protocol.factory).
|
|
66
|
+
- Define specific message formats for indoor and outdoor units (protocol.factory.messages).
|
|
67
|
+
|
|
68
|
+
## Future plans
|
|
69
|
+
|
|
70
|
+
These might not end up happening, but I would like to have a go at creating these one day.
|
|
71
|
+
|
|
72
|
+
- Simulate a remote controller for a "dummy" zone 2
|
|
73
|
+
- Send custom Z1/Z2 temperature readings to the master controller
|
|
74
|
+
- Implement TPI/load awareness/preditive model algorithms for an advanced complete custom controller
|
|
75
|
+
|
|
76
|
+
## Installation
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install pysamsungnasa
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
TODO
|
|
85
|
+
|
|
86
|
+
## Configuration
|
|
87
|
+
|
|
88
|
+
TODO
|
|
89
|
+
|
|
90
|
+
## Contributing
|
|
91
|
+
|
|
92
|
+
TODO
|
|
93
|
+
|
|
94
|
+
## Thanks
|
|
95
|
+
|
|
96
|
+
This project utilizes or incorporates ideas, code and work from the following sources,
|
|
97
|
+
and I would like to express my sincere gratitude to their creators and contributors:
|
|
98
|
+
|
|
99
|
+
- [ESPHome Samsung HVAC Bus](https://github.com/omerfaruk-aran/esphome_samsung_hvac_bus/)
|
|
100
|
+
- [Samsung NASA MQTT Bridge](https://github.com/70p4z/samsung-nasa-mqtt/)
|
|
101
|
+
- [Samsung ASHP NASA link MQTT bridge / Home Assistant](https://community.openenergymonitor.org/t/contribution-samsung-ashp-nasa-link-mqtt-bridge-home-assistant)
|
|
102
|
+
- [OpenEnergyMonitoring Forum](https://community.openenergymonitor.org/search?q=samsung) for all the shared wisdom on multiple threads.
|
|
103
|
+
- @betaphi for the [EHS Wiki](https://wiki.myehs.eu/wiki/Main_Page), which provided valuable insights into different messages. The protocol is mostly documented [here](NOTES.md) as the NASA Protocol page is no longer on the wiki. More messages are defined within the parser classes from the latest version of S-Net.
|
|
104
|
+
|
|
105
|
+
None of this would have been possible without the above.
|
|
106
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# pysamsungnasa
|
|
2
|
+
|
|
3
|
+
[](https://github.com/pantherale0/pysamsungnasa/actions/workflows/test.yml)
|
|
4
|
+
[](https://codecov.io/gh/pantherale0/pysamsungnasa)
|
|
5
|
+
|
|
6
|
+
A Python library to communicate with Samsung heat pumps, in theory both cool only and cool+heat units are supported, although only tested on an EHS unit (cool+heat)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- Connect and disconnect from Samsung HVAC/EHS units via a TCP socket over the F1/F2 connectors (NasaClient).
|
|
11
|
+
- Discover new devices on the NASA network and manage known devices (SamsungNasa).
|
|
12
|
+
- Send commands to devices and handle responses (SamsungNasa, NasaClient).
|
|
13
|
+
- Parse incoming data packets from devices (NasaPacketParser, various message classes).
|
|
14
|
+
- Represent devices with attributes and control their functions (NasaDevice, DhwController, ClimateController).
|
|
15
|
+
- Control DHW (Domestic Hot Water) settings like power, operation mode, and target temperature (DhwController).
|
|
16
|
+
- Control climate settings like power, mode, target temperature, fan speed, and more (ClimateController).
|
|
17
|
+
- Provide a mechanism for callbacks to be notified of device and packet updates (NasaDevice).
|
|
18
|
+
- Support reading device configurations (NasaDevice).
|
|
19
|
+
- Handle message construction and parsing based on message types (protocol.factory).
|
|
20
|
+
- Define specific message formats for indoor and outdoor units (protocol.factory.messages).
|
|
21
|
+
|
|
22
|
+
## Future plans
|
|
23
|
+
|
|
24
|
+
These might not end up happening, but I would like to have a go at creating these one day.
|
|
25
|
+
|
|
26
|
+
- Simulate a remote controller for a "dummy" zone 2
|
|
27
|
+
- Send custom Z1/Z2 temperature readings to the master controller
|
|
28
|
+
- Implement TPI/load awareness/preditive model algorithms for an advanced complete custom controller
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install pysamsungnasa
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
TODO
|
|
39
|
+
|
|
40
|
+
## Configuration
|
|
41
|
+
|
|
42
|
+
TODO
|
|
43
|
+
|
|
44
|
+
## Contributing
|
|
45
|
+
|
|
46
|
+
TODO
|
|
47
|
+
|
|
48
|
+
## Thanks
|
|
49
|
+
|
|
50
|
+
This project utilizes or incorporates ideas, code and work from the following sources,
|
|
51
|
+
and I would like to express my sincere gratitude to their creators and contributors:
|
|
52
|
+
|
|
53
|
+
- [ESPHome Samsung HVAC Bus](https://github.com/omerfaruk-aran/esphome_samsung_hvac_bus/)
|
|
54
|
+
- [Samsung NASA MQTT Bridge](https://github.com/70p4z/samsung-nasa-mqtt/)
|
|
55
|
+
- [Samsung ASHP NASA link MQTT bridge / Home Assistant](https://community.openenergymonitor.org/t/contribution-samsung-ashp-nasa-link-mqtt-bridge-home-assistant)
|
|
56
|
+
- [OpenEnergyMonitoring Forum](https://community.openenergymonitor.org/search?q=samsung) for all the shared wisdom on multiple threads.
|
|
57
|
+
- @betaphi for the [EHS Wiki](https://wiki.myehs.eu/wiki/Main_Page), which provided valuable insights into different messages. The protocol is mostly documented [here](NOTES.md) as the NASA Protocol page is no longer on the wiki. More messages are defined within the parser classes from the latest version of S-Net.
|
|
58
|
+
|
|
59
|
+
None of this would have been possible without the above.
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core >=2,<4"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pysamsungnasa"
|
|
7
|
+
authors = [
|
|
8
|
+
{name = "Jordan Harvey", email = "jordan@hrvy.uk"},
|
|
9
|
+
]
|
|
10
|
+
description = "Connect to Samsung ASHP / AC units over NASA via RS485"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Programming Language :: Python :: 3.13"
|
|
18
|
+
]
|
|
19
|
+
requires-python = ">=3.13.0"
|
|
20
|
+
dynamic = ["version"]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"aiotelnet~=1.1.0"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
cli = [
|
|
27
|
+
"prompt_toolkit>=3.0.0",
|
|
28
|
+
"python-dotenv>=0.9.9"
|
|
29
|
+
]
|
|
30
|
+
docs = [
|
|
31
|
+
"mkdocs>=1.4.0",
|
|
32
|
+
"mkdocs-material>=9.0.0",
|
|
33
|
+
"mkdocstrings[python]>=0.23.0",
|
|
34
|
+
"griffe>=0.40",
|
|
35
|
+
"pymdown-extensions>=10.0"
|
|
36
|
+
]
|
|
37
|
+
test = [
|
|
38
|
+
"bandit[toml]==1.9.2",
|
|
39
|
+
"black==25.12.0",
|
|
40
|
+
"check-manifest==0.51",
|
|
41
|
+
"flake8-bugbear==25.11.29",
|
|
42
|
+
"flake8-docstrings",
|
|
43
|
+
"flake8-formatter_junit_xml",
|
|
44
|
+
"flake8",
|
|
45
|
+
"flake8-pyproject",
|
|
46
|
+
"pre-commit==4.5.1",
|
|
47
|
+
"pylint==4.0.4",
|
|
48
|
+
"pylint_junit",
|
|
49
|
+
"pytest-cov==7.0.0",
|
|
50
|
+
"pytest-mock<3.15.2",
|
|
51
|
+
"pytest-runner",
|
|
52
|
+
"pytest-asyncio==1.3.0",
|
|
53
|
+
"pytest==9.0.2",
|
|
54
|
+
"pytest-github-actions-annotate-failures",
|
|
55
|
+
"shellcheck-py==0.11.0.1"
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[project.urls]
|
|
59
|
+
Documentation = "https://github.com/pantherale0/pysamsungnasa"
|
|
60
|
+
Source = "https://github.com/pantherale0/pysamsungnasa"
|
|
61
|
+
Tracker = "https://github.com/pantherale0/pysamsungnasa/issues"
|
|
62
|
+
|
|
63
|
+
[tool.flit.module]
|
|
64
|
+
name = "pysamsungnasa"
|
|
65
|
+
|
|
66
|
+
[tool.bandit]
|
|
67
|
+
exclude_dirs = ["build","dist","tests","scripts"]
|
|
68
|
+
number = 4
|
|
69
|
+
recursive = true
|
|
70
|
+
targets = "src/pysamsungnasa"
|
|
71
|
+
|
|
72
|
+
[tool.black]
|
|
73
|
+
line-length = 120
|
|
74
|
+
fast = true
|
|
75
|
+
|
|
76
|
+
[tool.coverage.run]
|
|
77
|
+
branch = true
|
|
78
|
+
|
|
79
|
+
[tool.coverage.report]
|
|
80
|
+
fail_under = 100
|
|
81
|
+
|
|
82
|
+
[tool.flake8]
|
|
83
|
+
max-line-length = 120
|
|
84
|
+
select = "F,E,W,B,B901,B902,B903"
|
|
85
|
+
exclude = [
|
|
86
|
+
".eggs",
|
|
87
|
+
".git",
|
|
88
|
+
".tox",
|
|
89
|
+
"nssm",
|
|
90
|
+
"obj",
|
|
91
|
+
"out",
|
|
92
|
+
"packages",
|
|
93
|
+
"pywin32",
|
|
94
|
+
"tests",
|
|
95
|
+
"swagger_client"
|
|
96
|
+
]
|
|
97
|
+
ignore = [
|
|
98
|
+
"E722",
|
|
99
|
+
"B001",
|
|
100
|
+
"W503",
|
|
101
|
+
"E203"
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
[tool.pyright]
|
|
105
|
+
include = ["src/pysamsungnasa"]
|
|
106
|
+
exclude = [
|
|
107
|
+
"**/node_modules",
|
|
108
|
+
"**/__pycache__",
|
|
109
|
+
]
|
|
110
|
+
venv = "env37"
|
|
111
|
+
|
|
112
|
+
reportMissingImports = true
|
|
113
|
+
reportMissingTypeStubs = false
|
|
114
|
+
|
|
115
|
+
pythonVersion = "3.13"
|
|
116
|
+
pythonPlatform = "Linux"
|
|
117
|
+
|
|
118
|
+
executionEnvironments = [
|
|
119
|
+
{ root = "src/pysamsungnasa" }
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[tool.pytest.ini_options]
|
|
123
|
+
addopts = "--cov-report xml:coverage.xml --cov pysamsungnasa --cov-fail-under 0 --cov-append -m 'not integration'"
|
|
124
|
+
pythonpath = [
|
|
125
|
+
"."
|
|
126
|
+
]
|
|
127
|
+
testpaths = "tests"
|
|
128
|
+
junit_family = "xunit2"
|
|
129
|
+
markers = [
|
|
130
|
+
"integration: marks as integration test",
|
|
131
|
+
"slow: marks tests as slow",
|
|
132
|
+
"unit: fast offline tests",
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[tool.tox]
|
|
136
|
+
legacy_tox_ini = """
|
|
137
|
+
[tox]
|
|
138
|
+
envlist = py, integration, all
|
|
139
|
+
|
|
140
|
+
[testenv]
|
|
141
|
+
commands =
|
|
142
|
+
pytest -m "not integration" {posargs}
|
|
143
|
+
|
|
144
|
+
[testenv:integration]
|
|
145
|
+
commands =
|
|
146
|
+
pytest -m "integration" {posargs}
|
|
147
|
+
|
|
148
|
+
[testenv:all]
|
|
149
|
+
extras = all
|
|
150
|
+
commands =
|
|
151
|
+
pytest {posargs}
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
[tool.pylint]
|
|
155
|
+
extension-pkg-whitelist= [
|
|
156
|
+
"numpy",
|
|
157
|
+
"torch",
|
|
158
|
+
"cv2",
|
|
159
|
+
"pyodbc",
|
|
160
|
+
"pydantic",
|
|
161
|
+
"ciso8601",
|
|
162
|
+
"netcdf4",
|
|
163
|
+
"scipy"
|
|
164
|
+
]
|
|
165
|
+
ignore="CVS"
|
|
166
|
+
ignore-patterns="test.*?py,conftest.py"
|
|
167
|
+
init-hook='import sys; sys.setrecursionlimit(8 * sys.getrecursionlimit())'
|
|
168
|
+
jobs=0
|
|
169
|
+
limit-inference-results=100
|
|
170
|
+
persistent="yes"
|
|
171
|
+
suggestion-mode="yes"
|
|
172
|
+
unsafe-load-any-extension="no"
|
|
173
|
+
|
|
174
|
+
[tool.pylint.'MESSAGES CONTROL']
|
|
175
|
+
enable="c-extension-no-member"
|
|
176
|
+
|
|
177
|
+
[tool.pylint.'REPORTS']
|
|
178
|
+
evaluation="10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)"
|
|
179
|
+
output-format="text"
|
|
180
|
+
reports="no"
|
|
181
|
+
score="yes"
|
|
182
|
+
|
|
183
|
+
[tool.pylint.'REFACTORING']
|
|
184
|
+
max-nested-blocks=5
|
|
185
|
+
never-returning-functions="sys.exit"
|
|
186
|
+
|
|
187
|
+
[tool.pylint.'BASIC']
|
|
188
|
+
argument-naming-style="snake_case"
|
|
189
|
+
attr-naming-style="snake_case"
|
|
190
|
+
bad-names= [
|
|
191
|
+
"foo",
|
|
192
|
+
"bar"
|
|
193
|
+
]
|
|
194
|
+
class-attribute-naming-style="any"
|
|
195
|
+
class-naming-style="PascalCase"
|
|
196
|
+
const-naming-style="UPPER_CASE"
|
|
197
|
+
docstring-min-length=-1
|
|
198
|
+
function-naming-style="snake_case"
|
|
199
|
+
good-names= [
|
|
200
|
+
"i",
|
|
201
|
+
"j",
|
|
202
|
+
"k",
|
|
203
|
+
"ex",
|
|
204
|
+
"Run",
|
|
205
|
+
"_"
|
|
206
|
+
]
|
|
207
|
+
include-naming-hint="yes"
|
|
208
|
+
inlinevar-naming-style="any"
|
|
209
|
+
method-naming-style="snake_case"
|
|
210
|
+
module-naming-style="any"
|
|
211
|
+
no-docstring-rgx="^_"
|
|
212
|
+
property-classes="abc.abstractproperty"
|
|
213
|
+
variable-naming-style="snake_case"
|
|
214
|
+
|
|
215
|
+
[tool.pylint.'FORMAT']
|
|
216
|
+
ignore-long-lines="^\\s*(# )?.*['\"]?<?https?://\\S+>?"
|
|
217
|
+
indent-after-paren=4
|
|
218
|
+
indent-string=' '
|
|
219
|
+
max-line-length=120
|
|
220
|
+
max-module-lines=1000
|
|
221
|
+
single-line-class-stmt="no"
|
|
222
|
+
single-line-if-stmt="no"
|
|
223
|
+
|
|
224
|
+
[tool.pylint.'LOGGING']
|
|
225
|
+
logging-format-style="old"
|
|
226
|
+
logging-modules="logging"
|
|
227
|
+
|
|
228
|
+
[tool.pylint.'MISCELLANEOUS']
|
|
229
|
+
notes= [
|
|
230
|
+
"FIXME",
|
|
231
|
+
"XXX",
|
|
232
|
+
"TODO"
|
|
233
|
+
]
|
|
234
|
+
|
|
235
|
+
[tool.pylint.'SIMILARITIES']
|
|
236
|
+
ignore-comments="yes"
|
|
237
|
+
ignore-docstrings="yes"
|
|
238
|
+
ignore-imports="yes"
|
|
239
|
+
min-similarity-lines=7
|
|
240
|
+
|
|
241
|
+
[tool.pylint.'SPELLING']
|
|
242
|
+
max-spelling-suggestions=4
|
|
243
|
+
spelling-store-unknown-words="no"
|
|
244
|
+
|
|
245
|
+
[tool.pylint.'STRING']
|
|
246
|
+
check-str-concat-over-line-jumps="no"
|
|
247
|
+
|
|
248
|
+
[tool.pylint.'TYPECHECK']
|
|
249
|
+
contextmanager-decorators="contextlib.contextmanager"
|
|
250
|
+
generated-members="numpy.*,np.*,collect_list"
|
|
251
|
+
ignore-mixin-members="yes"
|
|
252
|
+
ignore-none="yes"
|
|
253
|
+
ignore-on-opaque-inference="yes"
|
|
254
|
+
ignored-classes="optparse.Values,thread._local,_thread._local,numpy,torch,swagger_client"
|
|
255
|
+
ignored-modules="numpy,torch,swagger_client,netCDF4,scipy"
|
|
256
|
+
missing-member-hint="yes"
|
|
257
|
+
missing-member-hint-distance=1
|
|
258
|
+
missing-member-max-choices=1
|
|
259
|
+
|
|
260
|
+
[tool.pylint.'VARIABLES']
|
|
261
|
+
additional-builtins="dbutils"
|
|
262
|
+
allow-global-unused-variables="yes"
|
|
263
|
+
callbacks= [
|
|
264
|
+
"cb_",
|
|
265
|
+
"_cb"
|
|
266
|
+
]
|
|
267
|
+
dummy-variables-rgx="_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_"
|
|
268
|
+
ignored-argument-names="_.*|^ignored_|^unused_"
|
|
269
|
+
init-import="no"
|
|
270
|
+
redefining-builtins-modules="six.moves,past.builtins,future.builtins,builtins,io"
|
|
271
|
+
|
|
272
|
+
[tool.pylint.'CLASSES']
|
|
273
|
+
defining-attr-methods= [
|
|
274
|
+
"__init__",
|
|
275
|
+
"__new__",
|
|
276
|
+
"setUp",
|
|
277
|
+
"__post_init__"
|
|
278
|
+
]
|
|
279
|
+
exclude-protected= [
|
|
280
|
+
"_asdict",
|
|
281
|
+
"_fields",
|
|
282
|
+
"_replace",
|
|
283
|
+
"_source",
|
|
284
|
+
"_make"
|
|
285
|
+
]
|
|
286
|
+
valid-classmethod-first-arg="cls"
|
|
287
|
+
valid-metaclass-classmethod-first-arg="cls"
|
|
288
|
+
|
|
289
|
+
[tool.pylint.'DESIGN']
|
|
290
|
+
max-args=5
|
|
291
|
+
max-attributes=7
|
|
292
|
+
max-bool-expr=5
|
|
293
|
+
max-branches=12
|
|
294
|
+
max-locals=15
|
|
295
|
+
max-parents=7
|
|
296
|
+
max-public-methods=20
|
|
297
|
+
max-returns=6
|
|
298
|
+
max-statements=50
|
|
299
|
+
min-public-methods=2
|
|
300
|
+
|
|
301
|
+
[tool.pylint.'IMPORTS']
|
|
302
|
+
allow-wildcard-with-all="no"
|
|
303
|
+
analyse-fallback-blocks="no"
|
|
304
|
+
deprecated-modules="optparse,tkinter.tix"
|
|
305
|
+
|
|
306
|
+
[tool.pylint.'EXCEPTIONS']
|
|
307
|
+
overgeneral-exceptions= [
|
|
308
|
+
"BaseException",
|
|
309
|
+
"Exception"
|
|
310
|
+
]
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Functionality to execute when run as a script."""
|
|
2
|
+
|
|
3
|
+
# Uses cli.py to provide an interactive CLI for testing.
|
|
4
|
+
# Environment variables can be used to set the host and port of the Samsung NASA device:
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
import os
|
|
8
|
+
import logging
|
|
9
|
+
from dotenv import load_dotenv
|
|
10
|
+
|
|
11
|
+
from .nasa import SamsungNasa
|
|
12
|
+
from .cli import interactive_cli
|
|
13
|
+
|
|
14
|
+
load_dotenv()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def main():
|
|
18
|
+
"""Main function to start the interactive CLI."""
|
|
19
|
+
if os.getenv("SAMSUNG_HP_HOST") is None or os.getenv("SAMSUNG_HP_PORT") is None:
|
|
20
|
+
print("Please set the SAMSUNG_HP_HOST and SAMSUNG_HP_PORT environment variables.", file=sys.stderr)
|
|
21
|
+
sys.exit(1)
|
|
22
|
+
|
|
23
|
+
nasa = SamsungNasa(
|
|
24
|
+
host=os.getenv("SAMSUNG_HP_HOST"),
|
|
25
|
+
port=int(os.getenv("SAMSUNG_HP_PORT")),
|
|
26
|
+
config={
|
|
27
|
+
"device_pnp": os.getenv("SAMSUNG_HP_DEVICE_PNP", "True").lower() in ("true", "1", "yes"),
|
|
28
|
+
"device_dump_only": os.getenv("SAMSUNG_HP_DEVICE_DUMP_ONLY", "False").lower() in ("true", "1", "yes"),
|
|
29
|
+
"log_all_messages": os.getenv("SAMSUNG_HP_LOG_ALL_MESSAGES", "False").lower() in ("true", "1", "yes"),
|
|
30
|
+
"log_buffer_messages": os.getenv("SAMSUNG_HP_LOG_BUFFER_MESSAGES", "False").lower() in ("true", "1", "yes"),
|
|
31
|
+
"messages_to_log": (
|
|
32
|
+
[int(x, 0) for x in os.getenv("SAMSUNG_HP_MESSAGES_TO_LOG", "").split(",") if x.strip()]
|
|
33
|
+
if os.getenv("SAMSUNG_HP_MESSAGES_TO_LOG")
|
|
34
|
+
else []
|
|
35
|
+
),
|
|
36
|
+
"devices_to_log": (
|
|
37
|
+
[x.strip() for x in os.getenv("SAMSUNG_HP_DEVICES_TO_LOG", "").split(",") if x.strip()]
|
|
38
|
+
if os.getenv("SAMSUNG_HP_DEVICES_TO_LOG")
|
|
39
|
+
else []
|
|
40
|
+
),
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
await nasa.start()
|
|
44
|
+
try:
|
|
45
|
+
await interactive_cli(nasa)
|
|
46
|
+
finally:
|
|
47
|
+
await nasa.stop()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == "__main__":
|
|
51
|
+
# Log to nasa.log in CWD at level defined by LOG_LEVEL env var (default DEBUG)
|
|
52
|
+
log_level = os.getenv("LOG_LEVEL", "DEBUG").upper()
|
|
53
|
+
logging.basicConfig(
|
|
54
|
+
level=getattr(logging, log_level, logging.DEBUG),
|
|
55
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
56
|
+
filename="nasa.log",
|
|
57
|
+
filemode="a",
|
|
58
|
+
)
|
|
59
|
+
# Add a logger for error messages to console
|
|
60
|
+
console = logging.StreamHandler()
|
|
61
|
+
console.setLevel(logging.ERROR)
|
|
62
|
+
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
|
63
|
+
console.setFormatter(formatter)
|
|
64
|
+
logging.getLogger().addHandler(console)
|
|
65
|
+
|
|
66
|
+
# Suppress noisy aiotelnet.client debug logs
|
|
67
|
+
logging.getLogger("aiotelnet.client").setLevel(logging.INFO)
|
|
68
|
+
|
|
69
|
+
# Execute main
|
|
70
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""NASA Device Autodiscovery."""
|
|
2
|
+
|
|
3
|
+
from .nasa import SamsungNasa
|
|
4
|
+
from .nasa_client import NasaClient
|
|
5
|
+
from .protocol.enum import DataType
|
|
6
|
+
from .protocol.factory import build_message, SendMessage
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def request_network_address(client: NasaClient):
|
|
10
|
+
"""Request a network address from the client."""
|
|
11
|
+
await client.send_command(
|
|
12
|
+
message=[
|
|
13
|
+
build_message(
|
|
14
|
+
source="500000",
|
|
15
|
+
destination="B0FFFF",
|
|
16
|
+
messages=[SendMessage(MESSAGE_ID=hex(0x10000 + 0x210)[-4:], PAYLOAD=bytes.fromhex(hex(0x10000)[-4:]))],
|
|
17
|
+
)
|
|
18
|
+
]
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def autodiscover_devices(client: NasaClient):
|
|
23
|
+
"""Send auto disocvery packets to the client."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def nasa_poke(client: SamsungNasa):
|
|
27
|
+
"""Send poke packets to the client."""
|
|
28
|
+
await client.send_message(
|
|
29
|
+
0x4242, payload=bytes.fromhex("FFFF"), destination="200000", request_type=DataType.REQUEST
|
|
30
|
+
)
|