Skip to content

Commit 94dad5c

Browse files
authored
Add WaterValve support and update pre-commit configuration (#151)
* Add WaterValve support and update pre-commit configuration - Introduced WaterValveController and WaterValve model for managing water valves. - Updated .pre-commit-config.yaml to include GitHub hooks and dependencies. - Added task to install the package in editable mode in VSCode tasks. - Revised README for clarity on usage examples and device support. - Commented out unused dependencies in requirements-dev.txt. * Added targeted dependencies to mypy .pre-commit.config.yaml to get precommit.ci behavior to replicate local mypy. * Disable test GitHub action. No tests rn.
1 parent 3fc948f commit 94dad5c

File tree

9 files changed

+189
-83
lines changed

9 files changed

+189
-83
lines changed
Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
name: PyTest & Code Coverage Report
2-
on: [workflow_dispatch, pull_request]
3-
jobs:
4-
run:
5-
runs-on: ubuntu-latest
6-
env:
7-
OS: ubuntu-latest
8-
PYTHON: '3.11'
9-
steps:
10-
- uses: actions/checkout@master
11-
- name: Setup Python
12-
uses: actions/setup-python@master
13-
with:
14-
python-version: '3.11'
15-
- name: Generate coverage report
16-
run: |
17-
pip install pytest-cov
18-
pip install -r requirements-dev.txt
19-
pytest --cov=./ --cov-report=xml --cov-report=html
20-
- name: Upload coverage reports to Codecov
21-
uses: codecov/codecov-action@v3
1+
# name: PyTest & Code Coverage Report
2+
# on: [workflow_dispatch, pull_request]
3+
# jobs:
4+
# run:
5+
# runs-on: ubuntu-latest
6+
# env:
7+
# OS: ubuntu-latest
8+
# PYTHON: '3.11'
9+
# steps:
10+
# - uses: actions/checkout@master
11+
# - name: Setup Python
12+
# uses: actions/setup-python@master
13+
# with:
14+
# python-version: '3.11'
15+
# - name: Generate coverage report
16+
# run: |
17+
# pip install pytest-cov
18+
# pip install -r requirements-dev.txt
19+
# pytest --cov=./ --cov-report=xml --cov-report=html
20+
# - name: Upload coverage reports to Codecov
21+
# uses: codecov/codecov-action@v3

.pre-commit-config.yaml

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,59 @@
11
default_language_version:
2-
python: python3.13
2+
python: python3.13
33

44
repos:
5-
- repo: local
6-
hooks:
7-
- id: ruff
8-
name: Ruff
9-
description: Run Ruff linter and autofixer
10-
entry: ruff check --fix
11-
language: python
12-
types: [python]
5+
- repo: https://github.com/astral-sh/ruff-pre-commit
6+
rev: v0.11.9
7+
hooks:
8+
- id: ruff
9+
name: Ruff
10+
description: Run Ruff linter and autofixer
11+
entry: ruff check --fix
12+
language: python
13+
types: [python]
1314

14-
- id: mypy
15-
name: MyPy
16-
description: Run static type checking
17-
entry: mypy
18-
language: python
19-
types: [python]
15+
- repo: https://github.com/pre-commit/mirrors-mypy
16+
rev: v1.15.0
17+
hooks:
18+
- id: mypy
19+
name: MyPy
20+
description: Run static type checking
21+
entry: mypy
22+
language: python
23+
types: [python]
24+
args: [--config-file, pyproject.toml]
25+
additional_dependencies:
26+
- types-PyYaml
27+
- types-requests
28+
- mashumaro
29+
- typer
30+
- pyhumps
2031

21-
- id: codespell
22-
name: Codespell
23-
description: Spell check source files
24-
entry: codespell
25-
language: python
26-
types: [text]
32+
- repo: https://github.com/codespell-project/codespell
33+
rev: v2.4.1
34+
hooks:
35+
- id: codespell
36+
name: Codespell
37+
description: Spell check source files
38+
entry: codespell
39+
language: python
40+
types: [text]
41+
additional_dependencies: [tomli]
2742

28-
- id: yamllint
29-
name: YAMLLint
30-
description: Lint YAML files using relaxed config
31-
entry: yamllint -d relaxed
32-
language: python
33-
types: [yaml]
34-
exclude: (.vscode|.devcontainer|.github)
43+
- repo: https://github.com/adrienverge/yamllint.git
44+
rev: v1.37.1
45+
hooks:
46+
- id: yamllint
47+
name: YAMLLint
48+
description: Lint YAML files using relaxed config
49+
entry: yamllint -d relaxed
50+
language: python
51+
types: [yaml]
52+
exclude: (\.vscode|\.devcontainer|\.github)
3553

36-
- repo: https://github.com/pappasam/toml-sort
37-
rev: v0.23.1
38-
hooks:
39-
- id: toml-sort
40-
args: ["--in-place", "--all", "--ignore-case"]
41-
types: [toml]
54+
- repo: https://github.com/pappasam/toml-sort
55+
rev: v0.24.2
56+
hooks:
57+
- id: toml-sort
58+
args: ["--in-place", "--all", "--ignore-case"]
59+
types: [toml]

.vscode/tasks.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@
5757
"command": "sphinx-build -b html docs docs/_build/html",
5858
"problemMatcher": [],
5959
"group": "build"
60+
},
61+
{
62+
"label": "Install pyalarmdotcomajax (editable)",
63+
"type": "shell",
64+
"command": "pip install --editable ../pyalarmdotcomajax --config-settings editable_mode=strict",
65+
"group": "build"
6066
}
6167
]
6268
}

README.md

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pip install .
3232

3333
## Usage
3434

35-
See `examples/basic_sensor_data.py` for a basic usage example.
35+
Usage examples not yet posted for v0.6 beta.
3636

3737
## Device Support (Core Functions)
3838

@@ -50,31 +50,11 @@ Pyalarmdotcomajax supports core features (monitoring and using actions) of the d
5050
| System | stop alarms, clear smoke sensor, clear alarms in memory | |
5151
| Thermostat | set attributes | |
5252
| Water Sensor | (none) | |
53-
54-
### Known Sensor deviceTypes
55-
56-
This list identifies deviceTypes used in the alarm.com API and is incomplete. Please help by submitting missing values.
57-
58-
| deviceType | Description |
59-
| ---------- | -------------------------------------- |
60-
| 1 | Contact Sensor |
61-
| 2 | Motion Sensor |
62-
| 5 | Smoke Detector |
63-
| 6 | CO Detector |
64-
| 8 | Freeze Sensor |
65-
| 9 | Panic Button |
66-
| 10 | Fixed Panic Button |
67-
| 14 | Siren |
68-
| 19 | Glass Break Detector |
69-
| 52 | Vibration Contact Sensor |
70-
| 68 | Panel Image Sensor |
71-
| 69 | Mobile Phone (for Bluetooth Disarming) |
72-
| 83 | Panel Glass Break Sensor |
73-
| 89 | Panel Motion Sensor |
53+
| Water Valve | open, close | |
7454

7555
## Device Support (Configuration)
7656

77-
Skybell HD configuration support not yet implemented in v6 beta.
57+
Skybell HD configuration support not yet implemented in v0.6 beta.
7858

7959
## Command Line Interface
8060

pyalarmdotcomajax/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
AvailableSystemsController,
5151
)
5252
from pyalarmdotcomajax.controllers.water_sensors import WaterSensorController
53+
from pyalarmdotcomajax.controllers.water_valve import WaterValveController
5354
from pyalarmdotcomajax.events import (
5455
EventBroker,
5556
EventBrokerCallbackT,
@@ -89,6 +90,7 @@
8990
trouble_condition,
9091
user,
9192
water_sensor,
93+
water_valve,
9294
)
9395
from pyalarmdotcomajax.models.auth import OtpType
9496
from pyalarmdotcomajax.models.base import (
@@ -153,6 +155,7 @@
153155
"trouble_condition",
154156
"user",
155157
"water_sensor",
158+
"water_valve",
156159
# controllers
157160
"AdcControllerT",
158161
"ResourceEventMessage",
@@ -209,6 +212,7 @@ def __init__(
209212
self._sensors = SensorController(self, self._device_catalogs)
210213
self._thermostats = ThermostatController(self, self._device_catalogs)
211214
self._water_sensors = WaterSensorController(self, self._device_catalogs)
215+
self._water_valves = WaterValveController(self, self._device_catalogs)
212216

213217
self._image_sensors = ImageSensorController(self)
214218
self._image_sensor_images = ImageSensorImageController(self)
@@ -407,6 +411,11 @@ def water_sensors(self) -> WaterSensorController:
407411
"""Get the water sensors controller."""
408412
return self._water_sensors
409413

414+
@property
415+
def water_valves(self) -> WaterValveController:
416+
"""Get the water valves controller."""
417+
return self._water_valves
418+
410419
@property
411420
def auth_controller(self) -> AuthenticationController:
412421
"""Get the authentication controller."""
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""Alarm.com controller for WaterValves."""
2+
3+
import logging
4+
from enum import StrEnum
5+
from types import MappingProxyType
6+
7+
from pyalarmdotcomajax.adc.util import Param_Id, cli_action
8+
from pyalarmdotcomajax.controllers.base import BaseController
9+
from pyalarmdotcomajax.exceptions import UnsupportedOperation
10+
from pyalarmdotcomajax.models.base import ResourceType
11+
from pyalarmdotcomajax.models.water_valve import WaterValve, WaterValveState
12+
from pyalarmdotcomajax.websocket.client import SupportedResourceEvents
13+
from pyalarmdotcomajax.websocket.messages import ResourceEventType
14+
15+
log = logging.getLogger(__name__)
16+
17+
18+
class WaterValveCommand(StrEnum):
19+
"""Commands for ADC WaterValves."""
20+
21+
OPEN = "open"
22+
CLOSE = "close"
23+
24+
25+
STATE_COMMAND_MAP = {
26+
WaterValveState.OPEN: WaterValveCommand.OPEN,
27+
WaterValveState.CLOSED: WaterValveCommand.CLOSE,
28+
}
29+
30+
31+
class WaterValveController(BaseController[WaterValve]):
32+
"""Controller for WaterValves."""
33+
34+
resource_type = ResourceType.WATER_VALVE
35+
_resource_class = WaterValve
36+
_event_state_map = MappingProxyType(
37+
{
38+
ResourceEventType.Opened: WaterValveState.OPEN,
39+
ResourceEventType.Closed: WaterValveState.CLOSED,
40+
}
41+
)
42+
_supported_resource_events = SupportedResourceEvents(
43+
events=[*_event_state_map.keys()]
44+
)
45+
46+
@cli_action()
47+
async def open(self, id: Param_Id) -> None:
48+
"""Open a water valve."""
49+
50+
await self.set_state(id, state=WaterValveState.OPEN)
51+
52+
@cli_action()
53+
async def close(self, id: Param_Id) -> None:
54+
"""Close a water valve."""
55+
56+
await self.set_state(id, state=WaterValveState.CLOSED)
57+
58+
async def set_state(self, id: str, state: WaterValveState) -> None:
59+
"""Change water valve state."""
60+
61+
if not (command := STATE_COMMAND_MAP.get(state)):
62+
raise UnsupportedOperation(f"State {state} not implemented.")
63+
64+
await self._send_command(id, command)

pyalarmdotcomajax/models/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class ResourceType(StrEnum):
3131
THERMOSTAT = "devices/thermostat"
3232
WATER_SENSOR = "devices/water-sensor"
3333
SWITCH = "devices/switch"
34+
WATER_VALVE = "devices/water-valve"
3435

3536
IMAGE_SENSOR = "image-sensor/image-sensor"
3637
IMAGE_SENSOR_IMAGE = "image-sensor/image-sensor-image"
@@ -61,7 +62,6 @@ class ResourceType(StrEnum):
6162
# SUMP_PUMP = "devices/sump-pump"
6263
# VALVE_SWITCH = "valve-switch"
6364
# WATER_METER = "devices/water-meter"
64-
# WATER_VALVE = "devices/water-valve"
6565
# X10_LIGHT = "devices/x10-light"
6666

6767
@classmethod
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Alarm.com model for WaterValves."""
2+
3+
from dataclasses import dataclass
4+
from enum import Enum
5+
6+
from pyalarmdotcomajax.models.base import (
7+
AdcDeviceResource,
8+
BaseManagedDeviceAttributes,
9+
ResourceType,
10+
)
11+
12+
13+
class WaterValveState(Enum):
14+
"""Enum of water valve states."""
15+
16+
UNKNOWN = 0
17+
OPEN = 1
18+
CLOSED = 2
19+
20+
21+
WaterValveAttributes = BaseManagedDeviceAttributes[WaterValveState]
22+
23+
24+
@dataclass
25+
class WaterValve(AdcDeviceResource[WaterValveAttributes]):
26+
"""WaterValve resource."""
27+
28+
resource_type = ResourceType.WATER_VALVE
29+
attributes_type = WaterValveAttributes

requirements-dev.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
ruff>=0.11.8
2-
codespell>=2.4.1
3-
yamllint>=1.37.0
41
pre-commit>=4.2.0
52
pytest>=8.3.5
63
pytest-asyncio>=0.26.0
@@ -9,9 +6,12 @@ tomli_w>=1.2.0
96
types-requests==2.31.0.6 # Required to prevent dependency conflict with Home Assistant over urllib3
107
types-PyYAML>=6.0.12.20250402
118
setuptools-scm>=8.3.1
12-
mypy>=1.15.0
139
pathspec>=0.11.1
1410
gitpython>=3.1.40
11+
# mypy>=1.15.0
12+
# ruff>=0.11.8
13+
# codespell>=2.4.1
14+
# yamllint>=1.37.0
1515
# Sphinx and its dependencies
1616
sphinx>=7.2
1717
myst-parser>=2.0

0 commit comments

Comments
 (0)