diff --git a/custom_components/growcube/coordinator.py b/custom_components/growcube/coordinator.py index c9f3d33..140e769 100644 --- a/custom_components/growcube/coordinator.py +++ b/custom_components/growcube/coordinator.py @@ -3,20 +3,28 @@ from typing import Optional, List, Tuple from growcube_client import GrowcubeClient, GrowcubeReport, Channel, WateringMode -from growcube_client import (WaterStateGrowcubeReport, - DeviceVersionGrowcubeReport, - MoistureHumidityStateGrowcubeReport, - PumpOpenGrowcubeReport, - PumpCloseGrowcubeReport, - CheckSensorGrowcubeReport, - CheckPumpBlockedGrowcubeReport, - CheckSensorNotConnectedGrowcubeReport, - CheckSensorLockGrowcubeReport, - LockStateGrowcubeReport, - CheckOutletLockGrowcubeReport) +from growcube_client import ( + WaterStateGrowcubeReport, + DeviceVersionGrowcubeReport, + MoistureHumidityStateGrowcubeReport, + PumpOpenGrowcubeReport, + PumpCloseGrowcubeReport, + CheckSensorGrowcubeReport, + CheckOutletBlockedGrowcubeReport, + CheckSensorNotConnectedGrowcubeReport, + LockStateGrowcubeReport, + CheckOutletLockedGrowcubeReport, +) from growcube_client import WateringModeCommand, SyncTimeCommand from homeassistant.core import HomeAssistant, ServiceCall -from homeassistant.const import STATE_UNAVAILABLE, STATE_OK, STATE_PROBLEM, STATE_LOCKED, STATE_OPEN, STATE_CLOSED +from homeassistant.const import ( + STATE_UNAVAILABLE, + STATE_OK, + STATE_PROBLEM, + STATE_LOCKED, + STATE_OPEN, + STATE_CLOSED, +) import logging from homeassistant.helpers.device_registry import DeviceInfo @@ -52,9 +60,9 @@ def __init__(self, host: str): class GrowcubeDataCoordinator(DataUpdateCoordinator): def __init__(self, host: str, hass: HomeAssistant): - self.client = GrowcubeClient(host, self.handle_report, - self.on_connected, - self.on_disconnected) + self.client = GrowcubeClient( + host, self.handle_report, self.on_connected, self.on_disconnected + ) super().__init__(hass, _LOGGER, name=DOMAIN) self.entities = [] self.device_id = None @@ -68,7 +76,7 @@ def set_device_id(self, device_id: str) -> None: "identifiers": {(DOMAIN, self.data.device_id)}, "manufacturer": "Elecrow", "model": "Growcube", - "sw_version": self.data.version + "sw_version": self.data.version, } async def _async_update_data(self): @@ -90,7 +98,7 @@ async def connect(self) -> Tuple[bool, str]: @staticmethod async def get_device_id(host: str) -> tuple[bool, str]: - """ This is used in the config flow to check for a valid device """ + """This is used in the config flow to check for a valid device""" device_id = "" def _handle_device_id_report(report: GrowcubeReport): @@ -113,7 +121,7 @@ async def _check_device_id_assigned(): client.disconnect() except asyncio.TimeoutError: client.disconnect() - return False, 'Timed out waiting for device ID' + return False, "Timed out waiting for device ID" return True, device_id @@ -121,8 +129,11 @@ def on_connected(self, host: str) -> None: _LOGGER.debug(f"Connection to {host} established") def on_disconnected(self, host: str) -> None: - _LOGGER.debug(f"{self.data.device_id}: Connection to {host} lost") - self.hass.states.async_set(DOMAIN + '.' + self.data.device_id, STATE_UNAVAILABLE) + _LOGGER.debug(f"Connection to {host} lost") + if self.data.device_id is not None: + self.hass.states.async_set( + DOMAIN + "." + self.data.device_id, STATE_UNAVAILABLE + ) def disconnect(self) -> None: """Disconnect from the Growcube device.""" @@ -132,7 +143,9 @@ def handle_report(self, report: GrowcubeReport): """Handle a report from the Growcube.""" # 24 - RepDeviceVersion if isinstance(report, DeviceVersionGrowcubeReport): - _LOGGER.debug(f"Device device_id: {report.device_id}, version {report.version}") + _LOGGER.debug( + f"Device device_id: {report.device_id}, version {report.version}" + ) self.data.version = report.version self.set_device_id(report.device_id) @@ -143,11 +156,13 @@ def handle_report(self, report: GrowcubeReport): # 21 - RepSTHSate elif isinstance(report, MoistureHumidityStateGrowcubeReport): - _LOGGER.debug(f"{self.data.device_id}: Sensor reading, channel %s, humidity %s, temperature %s, moisture %s", - report.channel, - report.humidity, - report.temperature, - report.moisture) + _LOGGER.debug( + f"{self.data.device_id}: Sensor reading, channel %s, humidity %s, temperature %s, moisture %s", + report.channel, + report.humidity, + report.temperature, + report.moisture, + ) self.data.humidity = report.humidity self.data.temperature = report.temperature self.data.moisture[report.channel.value] = report.moisture @@ -159,22 +174,30 @@ def handle_report(self, report: GrowcubeReport): # 27 - RepPumpClose elif isinstance(report, PumpCloseGrowcubeReport): - _LOGGER.debug(f"{self.data.device_id}: Pump closed, channel {report.channel}") + _LOGGER.debug( + f"{self.data.device_id}: Pump closed, channel {report.channel}" + ) self.data.pump_open[report.channel.value] = False # 28 - RepCheckSenSorNotConnected elif isinstance(report, CheckSensorGrowcubeReport): - _LOGGER.debug(f"{self.data.device_id}: Sensor abnormal, channel {report.channel}") + _LOGGER.debug( + f"{self.data.device_id}: Sensor abnormal, channel {report.channel}" + ) self.data.sensor_abnormal[report.channel.value] = True # 29 - Pump channel blocked - elif isinstance(report, CheckSensorLockGrowcubeReport): - _LOGGER.debug(f"{self.data.device_id}: Pump blocked, channel {report.channel}") + elif isinstance(report, CheckOutletBlockedGrowcubeReport): + _LOGGER.debug( + f"{self.data.device_id}: Outlet blocked, channel {report.channel}" + ) self.data.outlet_blocked_state[report.channel.value] = True # 30 - RepCheckSenSorNotConnect elif isinstance(report, CheckSensorNotConnectedGrowcubeReport): - _LOGGER.debug(f"{self.data.device_id}: Check sensor, channel {report.channel}") + _LOGGER.debug( + f"{self.data.device_id}: Check sensor, channel {report.channel}" + ) self.data.sensor_disconnected[report.channel.value] = True # self.moisture_sensors[report.channel.value].update(None) @@ -184,8 +207,10 @@ def handle_report(self, report: GrowcubeReport): self.data.device_lock_state = report.lock_state # 34 - ReqCheckSenSorLock - elif isinstance(report, CheckOutletLockGrowcubeReport): - _LOGGER.debug(f"{self.data.device_id}: Check outlet, channel {report.channel}") + elif isinstance(report, CheckOutletLockedGrowcubeReport): + _LOGGER.debug( + f"{self.data.device_id}: Check outlet, channel {report.channel}" + ) self.data.outlet_locked_state[report.channel.value] = True async def water_plant(self, channel: int) -> None: @@ -193,9 +218,9 @@ async def water_plant(self, channel: int) -> None: async def handle_water_plant(self, call: ServiceCall): # Validate channel - channel_str = call.data.get('channel') - duration_str = call.data.get('duration') - channel_names = ['A', 'B', 'C', 'D'] + channel_str = call.data.get("channel") + duration_str = call.data.get("duration") + channel_names = ["A", "B", "C", "D"] # Validate data if channel_str not in channel_names: @@ -209,7 +234,9 @@ async def handle_water_plant(self, call: ServiceCall): return if duration < 1 or duration > 60: - _LOGGER.error("Invalid duration '%s' for water_plant, should be 1-60", duration) + _LOGGER.error( + "Invalid duration '%s' for water_plant, should be 1-60", duration + ) return channel = Channel(channel_names.index(channel_str)) @@ -218,30 +245,40 @@ async def handle_water_plant(self, call: ServiceCall): await self.client.water_plant(channel, duration) async def handle_set_watering_mode(self, call: ServiceCall): - channel_str = call.data.get('channel') - min_value = call.data.get('min_value') - max_value = call.data.get('max_value') - channel_names = ['A', 'B', 'C', 'D'] + # Set watering mode + channel_str = call.data.get("channel") + min_value = call.data.get("min_value") + max_value = call.data.get("max_value") + channel_names = ["A", "B", "C", "D"] # Validate data if channel_str not in channel_names: - _LOGGER.error("Invalid channel specified for set_watering_mode: %s", channel_str) + _LOGGER.error( + "Invalid channel specified for set_watering_mode: %i", channel_str + ) return if min_value <= 0 or min_value > 100: - _LOGGER.error("Invalid value specified for min_value: %s", min_value_str) + _LOGGER.error("Invalid value specified for min_value: %i", min_value) return - if max_value <=0 or max_value > 100: - _LOGGER.error("Invalid value specified for max_value: %s", max_value_str) + if max_value <= 0 or max_value > 100: + _LOGGER.error("Invalid value specified for max_value: %i", max_value) return if max_value <= min_value: - _LOGGER.error("Invalid values specified, max_value must be bigger than min_value") + _LOGGER.error( + "Invalid values specified, max_value must be bigger than min_value" + ) return channel = Channel(channel_names.index(channel_str)) command = WateringModeCommand(channel, WateringMode.Smart, min_value, max_value) - _LOGGER.debug("Service set_watering_mode called, %s, %i, %i", channel_str, min_value, max_value) - self.client.send_command(command) \ No newline at end of file + _LOGGER.debug( + "Service set_watering_mode called, %s, %i, %i", + channel_str, + min_value, + max_value, + ) + self.client.send_command(command) diff --git a/custom_components/growcube/manifest.json b/custom_components/growcube/manifest.json index 0390957..2eb8d70 100644 --- a/custom_components/growcube/manifest.json +++ b/custom_components/growcube/manifest.json @@ -11,7 +11,7 @@ "issue_tracker": "https://github.com/jonnybergdahl/homeassistant_growcube/issues", "iot_class": "local_push", "requirements": [ - "growcube-client==1.0.16" + "growcube-client==1.1.0" ], - "version": "0.9.7" + "version": "0.9.8b" }