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.
Files changed (20) hide show
  1. {violet_poolcontroller_api-0.0.19/violet_poolController_api.egg-info → violet_poolcontroller_api-0.0.22}/PKG-INFO +1 -1
  2. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/pyproject.toml +3 -3
  3. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/setup.py +1 -1
  4. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/tests/test_api.py +16 -17
  5. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22/violet_poolController_api.egg-info}/PKG-INFO +1 -1
  6. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/api.py +10 -34
  7. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/LICENSE +0 -0
  8. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/README.md +0 -0
  9. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/setup.cfg +0 -0
  10. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/tests/__init__.py +0 -0
  11. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/SOURCES.txt +0 -0
  12. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/dependency_links.txt +0 -0
  13. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/requires.txt +0 -0
  14. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolController_api.egg-info/top_level.txt +0 -0
  15. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/__init__.py +0 -0
  16. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/circuit_breaker.py +0 -0
  17. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/const_api.py +0 -0
  18. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/const_devices.py +0 -0
  19. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/utils_rate_limiter.py +0 -0
  20. {violet_poolcontroller_api-0.0.19 → violet_poolcontroller_api-0.0.22}/violet_poolcontroller_api/utils_sanitizer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: violet-poolController-api
3
- Version: 0.0.19
3
+ Version: 0.0.22
4
4
  Summary: Asynchronous Python client for the Violet Pool Controller.
5
5
  Home-page: https://github.com/Xerolux/violet-poolController-api
6
6
  Author: Basti (Xerolux)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "violet-poolController-api"
7
- version = "0.0.19"
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.19"
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.19"
55
+ python_version = "0.0.22"
56
56
  warn_return_any = true
57
57
  warn_unused_configs = true
@@ -1,7 +1,7 @@
1
1
  from setuptools import setup, find_packages
2
2
  setup(
3
3
  name="violet-poolController-api",
4
- version="0.0.19",
4
+ version="0.0.22",
5
5
  author="Basti (Xerolux)",
6
6
  author_email="git@xerolux.de",
7
7
  description="Asynchronous Python client for the Violet Pool Controller.",
@@ -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 JSON payload."""
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["json_payload"] = kwargs.get("json_payload")
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["json_payload"] == {"poolmode": "A<mode>", "speed": 3.7}
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 ALLOFF to all 12 DMX scenes."""
698
- for i in range(1, 13):
699
- url = f"http://192.168.1.100/setFunctionManually?DMX_SCENE{i},ALLOFF,0,0"
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/setTargetValues?target=HEATER_TARGET_TEMP&value=28.0"
781
- mock_aioresponse.get(url, body="OK", status=200)
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/setTargetValues?target=pH&value=7.2"
795
- mock_aioresponse.get(url, body="OK", status=200)
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/setTargetValues?target=ORP&value=750"
809
- mock_aioresponse.get(url, body="OK", status=200)
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/setTargetValues?target=MinChlorine&value=0.5"
823
- mock_aioresponse.get(url, body="OK", status=200)
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/setTargetValues?target=CUSTOM&value=42.0"
837
- mock_aioresponse.get(url, body="OK", status=200)
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: violet-poolController-api
3
- Version: 0.0.19
3
+ Version: 0.0.22
4
4
  Summary: Asynchronous Python client for the Violet Pool Controller.
5
5
  Home-page: https://github.com/Xerolux/violet-poolController-api
6
6
  Author: Basti (Xerolux)
@@ -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
- json_payload=sanitized_config,
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
- json_payload={"sensor": sensor, "timestamp": timestamp},
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 the same command to all DMX scenes.
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 combined command results.
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
- tasks = []
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
- params = {"target": key, "value": value}
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
- json_payload=dict(parameters),
1188
+ data=dict(parameters),
1213
1189
  )
1214
1190
  return self._command_result(body)
1215
1191