violet-poolController-api 0.0.19__tar.gz → 0.0.22__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.
- {violet_poolcontroller_api-0.0.19/violet_poolController_api.egg-info → violet_poolcontroller_api-0.0.22}/PKG-INFO +1 -1
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/pyproject.toml +3 -3
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/setup.py +1 -1
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/tests/test_api.py +16 -17
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22/violet_poolController_api.egg-info}/PKG-INFO +1 -1
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/api.py +10 -34
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/LICENSE +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/README.md +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/setup.cfg +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/tests/__init__.py +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/SOURCES.txt +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/dependency_links.txt +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/requires.txt +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/top_level.txt +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/__init__.py +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/circuit_breaker.py +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/const_api.py +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/const_devices.py +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/utils_rate_limiter.py +0 -0
- {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/utils_sanitizer.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "violet-poolController-api"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.22"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Basti (Xerolux)", email="git@xerolux.de" },
|
|
10
10
|
]
|
|
@@ -45,13 +45,13 @@ asyncio_mode = "auto"
|
|
|
45
45
|
|
|
46
46
|
[tool.ruff]
|
|
47
47
|
line-length = 100
|
|
48
|
-
target-version = "0.0.
|
|
48
|
+
target-version = "0.0.22"
|
|
49
49
|
|
|
50
50
|
[tool.ruff.lint]
|
|
51
51
|
select = ["E", "F", "W", "I", "UP"]
|
|
52
52
|
ignore = ["E501"]
|
|
53
53
|
|
|
54
54
|
[tool.mypy]
|
|
55
|
-
python_version = "0.0.
|
|
55
|
+
python_version = "0.0.22"
|
|
56
56
|
warn_return_any = true
|
|
57
57
|
warn_unused_configs = true
|
|
@@ -214,12 +214,12 @@ async def test_set_config_sanitizes_payload_before_request(
|
|
|
214
214
|
api_client: VioletPoolAPI,
|
|
215
215
|
monkeypatch: pytest.Monkeypatch,
|
|
216
216
|
) -> None:
|
|
217
|
-
"""Test set_config applies sanitizer before sending
|
|
217
|
+
"""Test set_config applies sanitizer before sending form-encoded payload."""
|
|
218
218
|
captured: dict[str, object] = {}
|
|
219
219
|
|
|
220
220
|
async def fake_request(endpoint: str, **kwargs: Any) -> str: # noqa: ANN401
|
|
221
221
|
captured["endpoint"] = endpoint
|
|
222
|
-
captured["
|
|
222
|
+
captured["data"] = kwargs.get("data")
|
|
223
223
|
return "OK"
|
|
224
224
|
|
|
225
225
|
monkeypatch.setattr(api_client, "_request", fake_request)
|
|
@@ -228,7 +228,7 @@ async def test_set_config_sanitizes_payload_before_request(
|
|
|
228
228
|
|
|
229
229
|
assert result["success"] is True
|
|
230
230
|
assert result["response"] == "OK"
|
|
231
|
-
assert captured["
|
|
231
|
+
assert captured["data"] == {"poolmode": "A<mode>", "speed": 3.7}
|
|
232
232
|
|
|
233
233
|
|
|
234
234
|
@pytest.mark.asyncio
|
|
@@ -694,10 +694,9 @@ async def test_set_all_dmx_scenes_alloff(
|
|
|
694
694
|
mock_aioresponse: aioresponses,
|
|
695
695
|
api_client: VioletPoolAPI,
|
|
696
696
|
) -> None:
|
|
697
|
-
"""Test set_all_dmx_scenes sends
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
mock_aioresponse.get(url, body="OK", status=200)
|
|
697
|
+
"""Test set_all_dmx_scenes sends a single ALLOFF request to DMX_SCENE1."""
|
|
698
|
+
url = "http://192.168.1.100/setFunctionManually?DMX_SCENE1,ALLOFF,0,0"
|
|
699
|
+
mock_aioresponse.get(url, body="OK", status=200)
|
|
701
700
|
|
|
702
701
|
result = await api_client.set_all_dmx_scenes("ALLOFF")
|
|
703
702
|
|
|
@@ -777,8 +776,8 @@ async def test_set_device_temperature(
|
|
|
777
776
|
api_client: VioletPoolAPI,
|
|
778
777
|
) -> None:
|
|
779
778
|
"""Test set_device_temperature sends correct target temperature."""
|
|
780
|
-
url = "http://192.168.1.100/
|
|
781
|
-
mock_aioresponse.
|
|
779
|
+
url = "http://192.168.1.100/setConfig"
|
|
780
|
+
mock_aioresponse.post(url, body="OK", status=200)
|
|
782
781
|
|
|
783
782
|
result = await api_client.set_device_temperature("HEATER", 28.0)
|
|
784
783
|
|
|
@@ -791,8 +790,8 @@ async def test_set_ph_target(
|
|
|
791
790
|
api_client: VioletPoolAPI,
|
|
792
791
|
) -> None:
|
|
793
792
|
"""Test set_ph_target sends correct pH target value."""
|
|
794
|
-
url = "http://192.168.1.100/
|
|
795
|
-
mock_aioresponse.
|
|
793
|
+
url = "http://192.168.1.100/setConfig"
|
|
794
|
+
mock_aioresponse.post(url, body="OK", status=200)
|
|
796
795
|
|
|
797
796
|
result = await api_client.set_ph_target(7.2)
|
|
798
797
|
|
|
@@ -805,8 +804,8 @@ async def test_set_orp_target(
|
|
|
805
804
|
api_client: VioletPoolAPI,
|
|
806
805
|
) -> None:
|
|
807
806
|
"""Test set_orp_target sends correct ORP target value."""
|
|
808
|
-
url = "http://192.168.1.100/
|
|
809
|
-
mock_aioresponse.
|
|
807
|
+
url = "http://192.168.1.100/setConfig"
|
|
808
|
+
mock_aioresponse.post(url, body="OK", status=200)
|
|
810
809
|
|
|
811
810
|
result = await api_client.set_orp_target(750)
|
|
812
811
|
|
|
@@ -819,8 +818,8 @@ async def test_set_min_chlorine_level(
|
|
|
819
818
|
api_client: VioletPoolAPI,
|
|
820
819
|
) -> None:
|
|
821
820
|
"""Test set_min_chlorine_level sends correct chlorine target value."""
|
|
822
|
-
url = "http://192.168.1.100/
|
|
823
|
-
mock_aioresponse.
|
|
821
|
+
url = "http://192.168.1.100/setConfig"
|
|
822
|
+
mock_aioresponse.post(url, body="OK", status=200)
|
|
824
823
|
|
|
825
824
|
result = await api_client.set_min_chlorine_level(0.5)
|
|
826
825
|
|
|
@@ -833,8 +832,8 @@ async def test_set_target_value(
|
|
|
833
832
|
api_client: VioletPoolAPI,
|
|
834
833
|
) -> None:
|
|
835
834
|
"""Test set_target_value sends generic target value update."""
|
|
836
|
-
url = "http://192.168.1.100/
|
|
837
|
-
mock_aioresponse.
|
|
835
|
+
url = "http://192.168.1.100/setConfig"
|
|
836
|
+
mock_aioresponse.post(url, body="OK", status=200)
|
|
838
837
|
|
|
839
838
|
result = await api_client.set_target_value("CUSTOM", 42.0)
|
|
840
839
|
|
|
@@ -53,7 +53,6 @@ from .const_api import (
|
|
|
53
53
|
API_SET_DOSING_PARAMETERS,
|
|
54
54
|
API_SET_FUNCTION_MANUALLY,
|
|
55
55
|
API_SET_OUTPUT_TESTMODE,
|
|
56
|
-
API_SET_TARGET_VALUES,
|
|
57
56
|
API_TRIGGER_MANUAL_DOSING,
|
|
58
57
|
DOSING_FUNCTIONS,
|
|
59
58
|
DOSING_OUTPUT_INDEX,
|
|
@@ -775,7 +774,7 @@ class VioletPoolAPI:
|
|
|
775
774
|
body = await self._request(
|
|
776
775
|
API_SET_CONFIG,
|
|
777
776
|
method="POST",
|
|
778
|
-
|
|
777
|
+
data=sanitized_config,
|
|
779
778
|
)
|
|
780
779
|
return self._command_result(body)
|
|
781
780
|
|
|
@@ -866,7 +865,7 @@ class VioletPoolAPI:
|
|
|
866
865
|
body = await self._request(
|
|
867
866
|
API_RESTORE_CALIBRATION,
|
|
868
867
|
method="POST",
|
|
869
|
-
|
|
868
|
+
data={"sensor": sensor, "timestamp": timestamp},
|
|
870
869
|
)
|
|
871
870
|
return self._command_result(body)
|
|
872
871
|
|
|
@@ -1040,13 +1039,16 @@ class VioletPoolAPI:
|
|
|
1040
1039
|
)
|
|
1041
1040
|
|
|
1042
1041
|
async def set_all_dmx_scenes(self, action: str) -> dict[str, Any]:
|
|
1043
|
-
"""Send
|
|
1042
|
+
"""Send a global DMX command that affects all scenes and the LIGHT output.
|
|
1043
|
+
|
|
1044
|
+
The controller treats ALLON/ALLOFF/ALLAUTO as global actions: a single
|
|
1045
|
+
request to any DMX_SCENE key switches all 12 scenes and LIGHT at once.
|
|
1044
1046
|
|
|
1045
1047
|
Args:
|
|
1046
1048
|
action: The action to perform (ALLON, ALLOFF, ALLAUTO).
|
|
1047
1049
|
|
|
1048
1050
|
Returns:
|
|
1049
|
-
A dictionary with the
|
|
1051
|
+
A dictionary with the command result.
|
|
1050
1052
|
|
|
1051
1053
|
Raises:
|
|
1052
1054
|
VioletPoolAPIError: If the action is unsupported.
|
|
@@ -1056,28 +1058,7 @@ class VioletPoolAPI:
|
|
|
1056
1058
|
msg = f"Unsupported DMX action: {action}"
|
|
1057
1059
|
raise VioletPoolAPIError(msg)
|
|
1058
1060
|
|
|
1059
|
-
|
|
1060
|
-
for scene in range(1, 13):
|
|
1061
|
-
key = f"DMX_SCENE{scene}"
|
|
1062
|
-
tasks.append(self.set_switch_state(key, action))
|
|
1063
|
-
|
|
1064
|
-
# Run requests concurrently
|
|
1065
|
-
raw_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
1066
|
-
|
|
1067
|
-
results: list[dict[str, Any]] = []
|
|
1068
|
-
for res in raw_results:
|
|
1069
|
-
if isinstance(res, Exception):
|
|
1070
|
-
results.append(
|
|
1071
|
-
{"success": False, "response": f"{type(res).__name__}: {res!s}"},
|
|
1072
|
-
)
|
|
1073
|
-
elif isinstance(res, dict):
|
|
1074
|
-
results.append(res)
|
|
1075
|
-
|
|
1076
|
-
success = all(result.get("success") is True for result in results)
|
|
1077
|
-
response = ", ".join(
|
|
1078
|
-
str(result.get("response", "")) for result in results if result.get("response")
|
|
1079
|
-
)
|
|
1080
|
-
return {"success": success, "response": response}
|
|
1061
|
+
return await self.set_switch_state("DMX_SCENE1", action)
|
|
1081
1062
|
|
|
1082
1063
|
async def set_light_color_pulse(self) -> dict[str, Any]:
|
|
1083
1064
|
"""Trigger the color pulse animation for the pool light.
|
|
@@ -1186,12 +1167,7 @@ class VioletPoolAPI:
|
|
|
1186
1167
|
A dictionary with the command result.
|
|
1187
1168
|
|
|
1188
1169
|
"""
|
|
1189
|
-
|
|
1190
|
-
body = await self._request(
|
|
1191
|
-
API_SET_TARGET_VALUES,
|
|
1192
|
-
params=params,
|
|
1193
|
-
)
|
|
1194
|
-
return self._command_result(body)
|
|
1170
|
+
return await self.set_config({key: value})
|
|
1195
1171
|
|
|
1196
1172
|
async def set_dosing_parameters(
|
|
1197
1173
|
self,
|
|
@@ -1209,7 +1185,7 @@ class VioletPoolAPI:
|
|
|
1209
1185
|
body = await self._request(
|
|
1210
1186
|
API_SET_DOSING_PARAMETERS,
|
|
1211
1187
|
method="POST",
|
|
1212
|
-
|
|
1188
|
+
data=dict(parameters),
|
|
1213
1189
|
)
|
|
1214
1190
|
return self._command_result(body)
|
|
1215
1191
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|