Chat
Search
Ithy Logo

Creating a Custom Integration for Home Assistant to Control Levoit Humidifiers using a Python Library

A Comprehensive Guide for Seamless Home Automation

levoit humidifier smart home

Key Takeaways

  • Establish a Robust Development Environment: Ensure all necessary tools and libraries are properly installed to facilitate smooth integration.
  • Understand Home Assistant's Architecture: Familiarize yourself with Home Assistant's integration structure to effectively create and manage custom components.
  • Leverage the pyvesync Library: Utilize the pyvesync library to interact with Levoit humidifiers, enabling seamless control and monitoring within Home Assistant.

Introduction

Integrating Levoit humidifiers into Home Assistant enhances your smart home ecosystem by providing seamless control and monitoring capabilities. By leveraging a third-party Python library, such as pyvesync, you can create a custom integration that allows Home Assistant to communicate effectively with your Levoit devices. This guide provides a step-by-step approach to developing this integration, ensuring a comprehensive and reliable setup.

Setting Up Your Development Environment

1. Install Python

Ensure that Python is installed on your system. Home Assistant recommends using Python 3.9 or later versions for compatibility and performance.

python --version
# Example output: Python 3.9.7

2. Set Up Home Assistant Core

Create a virtual environment to manage dependencies for Home Assistant Core. This isolated environment ensures that your custom integration does not interfere with other projects.


python -m venv homeassistant_venv
source homeassistant_venv/bin/activate
pip install homeassistant

3. Install the pyvesync Library

The pyvesync library facilitates communication with Levoit and other VeSync-compatible devices. Install it using pip:

pip install pyvesync

Creating the Integration Structure

1. Create Custom Components Directory

Navigate to the Home Assistant configuration directory and create a new folder for your custom integration:

mkdir -p /config/custom_components/levoit_humidifier

2. Define Required Files

Inside the levoit_humidifier directory, create the following essential files:

  • __init__.py
  • manifest.json
  • config_flow.py (optional for UI-based configuration)
  • const.py
  • humidifier.py

3. Directory Structure Overview

The final directory structure should resemble the following:

Directory/File Description
custom_components/levoit_humidifier/__init__.py Initializes the integration and manages setup processes.
custom_components/levoit_humidifier/manifest.json Contains metadata about the integration.
custom_components/levoit_humidifier/config_flow.py Handles UI-based configuration flows.
custom_components/levoit_humidifier/const.py Defines constants used across the integration.
custom_components/levoit_humidifier/humidifier.py Implements the humidifier entity and its functionalities.

Defining Integration Metadata

Creating the manifest.json File

The manifest.json file provides essential metadata about the integration, including dependencies and requirements.


{
  "domain": "levoit_humidifier",
  "name": "Levoit Humidifier",
  "documentation": "https://github.com/yourusername/ha-levoit-humidifier",
  "dependencies": [],
  "codeowners": ["@yourusername"],
  "requirements": ["pyvesync>=2.0.0"],
  "iot_class": "local_polling",
  "version": "1.0.0"
}
  
  • domain: Unique identifier for the integration.
  • requirements: Specifies the third-party libraries needed.
  • codeowners: GitHub handles of the integration maintainers.

Defining Constants in const.py

The const.py file holds constants that are used throughout the integration, promoting maintainability and readability.


DOMAIN = "levoit_humidifier"
CONF_USERNAME = "username"
CONF_PASSWORD = "password"

Implementing the Integration Code

Initializing the Integration in __init__.py

The __init__.py file is responsible for initializing the integration, handling setup and teardown processes.


from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .const import DOMAIN
from pyvesync import VeSync
import logging

_LOGGER = logging.getLogger(__name__)

async def async_setup(hass: HomeAssistant, config: dict):
    """Set up the Levoit Humidifier integration."""
    hass.data.setdefault(DOMAIN, {})
    return True

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Set up Levoit Humidifier from a config entry."""
    username = entry.data[CONF_USERNAME]
    password = entry.data[CONF_PASSWORD]

    manager = VeSync(username, password)
    authenticated = manager.login()

    if not authenticated:
        _LOGGER.error("Authentication failed for VeSync account")
        return False

    hass.data[DOMAIN][entry.entry_id] = manager

    hass.config_entries.async_setup_platforms(entry, ["humidifier"])

    return True

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Unload a config entry."""
    unload_ok = await hass.config_entries.async_unload_platforms(entry, ["humidifier"])
    if unload_ok:
        hass.data[DOMAIN].pop(entry.entry_id)
    return unload_ok
  

Creating the Humidifier Entity in humidifier.py

The humidifier.py file defines the humidifier entity, encapsulating its properties and behaviors.


from homeassistant.components.humidifier import HumidifierEntity
from homeassistant.components.humidifier.const import (
    HUMIDIFIER_MODE_AUTO,
    HUMIDIFIER_MODE_MANUAL,
    SUPPORT_MODES,
    SUPPORT_TARGET_HUMIDITY,
)
from .const import DOMAIN

class LevoitHumidifier(HumidifierEntity):
    """Representation of a Levoit Humidifier."""

    def __init__(self, manager):
        """Initialize the Levoit Humidifier."""
        self._manager = manager
        self._device = self._manager.get_device()
        self._attr_name = self._device.device_name
        self._attr_unique_id = self._device.device_id
        self._attr_supported_features = SUPPORT_MODES | SUPPORT_TARGET_HUMIDITY
        self._attr_current_humidity = self._device.humidity
        self._attr_target_humidity = self._device.target_humidity
        self._attr_mode = HUMIDIFIER_MODE_AUTO if self._device.auto_mode else HUMIDIFIER_MODE_MANUAL
        self._attr_is_on = self._device.is_on

    @property
    def mode(self):
        """Return the current mode."""
        return self._attr_mode

    @property
    def target_humidity(self):
        """Return the target humidity."""
        return self._attr_target_humidity

    @property
    def current_humidity(self):
        """Return the current humidity."""
        return self._attr_current_humidity

    async def async_set_humidity(self, humidity):
        """Set new target humidity."""
        await self._manager.set_humidity(humidity)
        self._attr_target_humidity = humidity
        self.async_write_ha_state()

    async def async_set_mode(self, mode):
        """Set the mode of the humidifier."""
        if mode == HUMIDIFIER_MODE_AUTO:
            await self._manager.set_auto_mode(True)
            self._attr_mode = HUMIDIFIER_MODE_AUTO
        elif mode == HUMIDIFIER_MODE_MANUAL:
            await self._manager.set_auto_mode(False)
            self._attr_mode = HUMIDIFIER_MODE_MANUAL
        self.async_write_ha_state()

    async def async_turn_on(self):
        """Turn the humidifier on."""
        await self._manager.turn_on()
        self._attr_is_on = True
        self.async_write_ha_state()

    async def async_turn_off(self):
        """Turn the humidifier off."""
        await self._manager.turn_off()
        self._attr_is_on = False
        self.async_write_ha_state()
  

Implementing Configuration Flow in config_flow.py

The config_flow.py facilitates a user-friendly configuration interface within Home Assistant.


import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import callback
from .const import DOMAIN, CONF_USERNAME, CONF_PASSWORD

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

    VERSION = 1

    async def async_step_user(self, user_input=None):
        """Handle the initial step."""
        errors = {}
        if user_input is not None:
            username = user_input[CONF_USERNAME]
            password = user_input[CONF_PASSWORD]
            manager = VeSync(username, password)
            authenticated = manager.login()
            if authenticated:
                return self.async_create_entry(title="Levoit Humidifier", data=user_input)
            else:
                errors["base"] = "auth_error"

        data_schema = vol.Schema({
            vol.Required(CONF_USERNAME): str,
            vol.Required(CONF_PASSWORD): str,
        })

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

Configuring Home Assistant

1. Adding Configuration to configuration.yaml

Alternatively to using the UI-based configuration, you can define your integration directly in the configuration.yaml file:


levoit_humidifier:
  username: your_vesync_email@example.com
  password: your_vesync_password
  # Optional parameters can be added here
  # For example, scan_interval: 60

2. Restarting Home Assistant

After configuring the integration, restart Home Assistant to apply the changes:

# Using Home Assistant CLI
ha core restart

Alternatively, you can restart Home Assistant through the web interface by navigating to Settings > System > Restart.

3. Verifying the Integration

Once Home Assistant has restarted, navigate to Settings > Devices & Services to ensure that the Levoit Humidifier integration is listed and active. Your humidifier should appear as an entity, ready to be controlled and monitored.


Testing and Troubleshooting

1. Verifying Connectivity

Ensure that Home Assistant can communicate with your Levoit humidifier. Check the logs for any authentication errors or connectivity issues:

# Access Home Assistant logs
ha core logs

2. Testing Entity Controls

Use the Home Assistant interface to turn the humidifier on and off, adjust humidity levels, and switch between modes. Confirm that the actions reflect accurately on the physical device.

3. Handling Common Issues

  • Authentication Failures: Double-check the username and password provided. Ensure that your VeSync account is active and credentials are correct.
  • Device Not Found: Ensure that the humidifier is connected to the same network as Home Assistant and that it is compatible with the pyvesync library.
  • Library Version Mismatch: Verify that the pyvesync library version specified in manifest.json is compatible with your integration code.

Enhancing the Integration

1. Adding Additional Features

Consider implementing advanced features such as scheduling, automation triggers based on humidity levels, and integration with other smart home devices.

2. Improving Error Handling

Enhance the integration's robustness by implementing comprehensive error handling mechanisms to gracefully manage unexpected scenarios and maintain stability.

3. Contributing to the Community

Share your custom integration on platforms like GitHub and the Home Assistant Community to contribute to the ecosystem and receive feedback for further improvements.


Conclusion

Creating a custom integration for Home Assistant to control Levoit humidifiers using the pyvesync library involves understanding Home Assistant's architecture, setting up a proper development environment, and implementing the necessary code to facilitate communication between Home Assistant and the humidifier. By following this guide, you can achieve a seamless and efficient integration, enhancing your smart home capabilities.


References



Last updated January 19, 2025
Ask Ithy AI
Export Article
Delete Article