Skip to content

Commit

Permalink
feat: support 500 device type (#3)
Browse files Browse the repository at this point in the history
Resolves #1
  • Loading branch information
Michsior14 authored Dec 16, 2023
1 parent 0fda07b commit 1ae1f06
Show file tree
Hide file tree
Showing 19 changed files with 446 additions and 99 deletions.
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# ha-venta

A Home Assistant custom Integration for Venta devices with wifi module.
A Home Assistant custom Integration for Venta devices (protocol: v2, v3) with wifi module.

The following Venta device are currently tested and supported:

* LW73/LW74 Humidifier
- **Protocol v2:**
- LW73/LW74 Humidifier

- **Protocol v3:**
- AH550/AH555/AH510/AH515 Humidifier

## Features

* Humidifier control (fan speed, target humidity, and auto/sleep mode).
* LED strip control (on/off, color, mode).
* Diagnostic sensors (water level, temperature, cleaning time, etc.).
- Humidifier control (fan speed, target humidity, and auto/sleep mode).
- LED strip control (on/off, color, mode).
- Diagnostic sensors (water level, temperature, cleaning time, etc.).

## Installation

Expand All @@ -20,12 +24,12 @@ For manual installation, copy the venta folder and all of its contents into your

## Usage

Before the next steps make sure the device is configured using the Venta Home app and connected to the network.
Before the next steps make sure the device is configured using the Venta Home app and connected to the network. Next note down it's IP address, then visit `http://<your-ip>` and find property `ProtocolV` - this will be yours API version to fill later on.

### Adding the Integration

To start configuring the integration, just press the "+ADD INTEGRATION" button in the Settings - Integrations page, and select Venta from the drop-down menu.
The configuration page will appear, requesting to input ip of the device.
The configuration page will appear, requesting to input ip and API version of the device.

## Contributing

Expand Down
25 changes: 20 additions & 5 deletions custom_components/venta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.const import CONF_HOST, CONF_MAC
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_API_VERSION

from .const import DOMAIN, TIMEOUT

from .venta import VentaApi, VentaDevice, VentaDataUpdateCoordinator
from .venta import VentaApi, VentaDevice, VentaDataUpdateCoordinator, VentaApiVersion

_LOGGER = logging.getLogger(__name__)

Expand All @@ -27,6 +27,7 @@
Platform.LIGHT,
Platform.SELECT,
Platform.BINARY_SENSOR,
Platform.SWITCH,
]


Expand All @@ -36,7 +37,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if entry.unique_id is None:
hass.config_entries.async_update_entry(entry, unique_id=conf[CONF_MAC])

api = await venta_api_setup(hass, conf[CONF_HOST])
api = await venta_api_setup(hass, conf[CONF_HOST], conf[CONF_API_VERSION])
if not api:
return False

Expand All @@ -60,12 +61,12 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return unload_ok


async def venta_api_setup(hass: HomeAssistant, host):
async def venta_api_setup(hass: HomeAssistant, host, api_version):
"""Create a Venta instance only once."""
session = async_get_clientsession(hass)
try:
async with asyncio.timeout(TIMEOUT):
device = VentaDevice(host, session)
device = VentaDevice(host, api_version, session)
await device.init()
except asyncio.TimeoutError as err:
_LOGGER.debug("Connection to %s timed out", host)
Expand All @@ -80,3 +81,17 @@ async def venta_api_setup(hass: HomeAssistant, host):
api = VentaApi(device)

return api


async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Migrate old entry."""
_LOGGER.debug("Migrating from version %s", entry.version)

if entry.version == 1:
new = {**entry.data, CONF_API_VERSION: VentaApiVersion.V2.value}
entry.version = 2
hass.config_entries.async_update_entry(entry, data=new)

_LOGGER.debug("Migration to version %s successful", entry.version)

return True
65 changes: 46 additions & 19 deletions custom_components/venta/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN, NO_WATER_THRESHOLD
from .venta import VentaData, VentaDataUpdateCoordinator
from .venta import VentaData, VentaDataUpdateCoordinator, VentaDeviceType


ATTR_NEEDS_REFILL = "needs_refill"
Expand All @@ -35,23 +35,50 @@ class VentaBinarySensorEntityDescription(
"""Describes Venta binary sensor entity."""


BINARY_SENSOR_TYPES: tuple[VentaBinarySensorEntityDescription, ...] = (
VentaBinarySensorEntityDescription(
key=ATTR_NEEDS_REFILL,
translation_key="needs_refill",
icon="mdi:water-alert",
value_func=(
lambda data: data.info.get("Warnings") != 0
and data.measure.get("WaterLevel") < NO_WATER_THRESHOLD
),
),
VentaBinarySensorEntityDescription(
key=ATTR_NEEDS_SERVICE,
translation_key="needs_service",
icon="mdi:account-wrench",
value_func=(lambda data: data.info.get("Warnings") == 16),
),
)
def _supported_sensors(
device_type: VentaDeviceType,
) -> tuple[VentaBinarySensorEntityDescription, ...]:
"""Return supported sensors for given device type."""
match device_type:
case VentaDeviceType.LW73_LW74 | VentaDeviceType.UNKNOWN:
return (
VentaBinarySensorEntityDescription(
key=ATTR_NEEDS_REFILL,
translation_key="needs_refill",
icon="mdi:water-alert",
value_func=(
lambda data: data.info.get("Warnings") != 0
and data.measure.get("WaterLevel") < NO_WATER_THRESHOLD
),
),
VentaBinarySensorEntityDescription(
key=ATTR_NEEDS_SERVICE,
translation_key="needs_service",
icon="mdi:account-wrench",
value_func=(
lambda data: 16 <= data.info.get("Warnings")
and data.info.get("Warnings") <= 17
),
),
)
case VentaDeviceType.AH550_AH555:
return (
VentaBinarySensorEntityDescription(
key=ATTR_NEEDS_REFILL,
translation_key="needs_refill",
icon="mdi:water-alert",
value_func=(lambda data: data.info.get("Warnings") == 1),
),
VentaBinarySensorEntityDescription(
key=ATTR_NEEDS_SERVICE,
translation_key="needs_service",
icon="mdi:account-wrench",
value_func=(
lambda data: data.info.get("ServiceT") is not None
and data.info.get("ServiceT") >= data.info.get("ServiceMax")
),
),
)


async def async_setup_entry(
Expand All @@ -65,7 +92,7 @@ async def async_setup_entry(
]
entities = [
VentaBinarySensor(coordinator, description)
for description in BINARY_SENSOR_TYPES
for description in _supported_sensors(coordinator.api.device.device_type)
if description.key in sensors
]
async_add_entities(entities)
Expand Down
25 changes: 17 additions & 8 deletions custom_components/venta/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,29 @@
from aiohttp import ClientError
from homeassistant import config_entries
from homeassistant.data_entry_flow import FlowResult
from homeassistant.const import CONF_HOST, CONF_MAC
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_API_VERSION
from homeassistant.helpers.aiohttp_client import async_get_clientsession

from .const import DOMAIN, TIMEOUT
from .venta import VentaDevice
from .venta import VentaDevice, VentaApiVersion

_LOGGER = logging.getLogger(__name__)

STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required("host"): str,
vol.Required(CONF_HOST): str,
vol.Required(
CONF_API_VERSION,
default=VentaApiVersion.V2.value,
): vol.In([entry.value for entry in list(VentaApiVersion)]),
}
)


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Venta."""

VERSION = 1
VERSION = 2

async def async_step_user(
self, user_input: dict[str, Any] | None = None
Expand All @@ -38,8 +42,11 @@ async def async_step_user(
if user_input is not None:
try:
host = user_input[CONF_HOST]
api_version = user_input[CONF_API_VERSION]
async with asyncio.timeout(TIMEOUT):
device = VentaDevice(host, async_get_clientsession(self.hass))
device = VentaDevice(
host, api_version, async_get_clientsession(self.hass)
)
await device.init()
except (asyncio.TimeoutError, ClientError):
_LOGGER.debug("Connection to %s timed out", host)
Expand All @@ -48,19 +55,21 @@ async def async_step_user(
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
return await self._create_entry(device.host, device.mac)
return await self._create_entry(
device.host, device.api_version, device.mac
)

return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
)

async def _create_entry(self, host, mac):
async def _create_entry(self, host, api_version, mac):
"""Register new entry."""
if not self.unique_id:
await self.async_set_unique_id(mac)
self._abort_if_unique_id_configured()

return self.async_create_entry(
title=host,
data={CONF_HOST: host, CONF_MAC: mac},
data={CONF_HOST: host, CONF_API_VERSION: api_version, CONF_MAC: mac},
)
2 changes: 0 additions & 2 deletions custom_components/venta/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
TIMEOUT = 10
NO_WATER_THRESHOLD = 50000

UNKNOWN_DEVICE_TYPE = "Unknown"

MODE_SLEEP = "sleep"
MODE_LEVEL_1 = "level 1"
MODE_LEVEL_2 = "level 2"
Expand Down
Loading

0 comments on commit 1ae1f06

Please sign in to comment.