Skip to content

Commit

Permalink
client 21, alpha 19 - serial support
Browse files Browse the repository at this point in the history
  • Loading branch information
hikirsch committed Jan 17, 2025
1 parent d990da0 commit ee36f87
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 19 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# HTD Integration for Home Assistant
# Home Theater Direct Integration for Home Assistant

This integration adds support for the HTD line of Whole House Audio for Home
Assistant. This integration currently supports the following models.
This integration adds support for the Home Theater Direct line of Whole House Audio to Home Assistant.

Currently, it supports the following models.
- MC/MCA-66
- Lync 6
- Lync 12
Expand All @@ -13,21 +13,30 @@ Assistant. This integration currently supports the following models.

Easiest installation is via [HACS](https://hacs.xyz/):

Please click this button below to install the integration:

[![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=hikirsch&repository=htd-home-assistant&category=integration)

`HACS -> Integrations -> Explore & Add Repositories -> Home Theater Direct`
After you add the repository for the integration, you will then be able to install it into Home Assistant.

### Manually

Download all the files from this repo and upload as
`custom_components/htd` folder.
Download all the files from this repo and upload as `custom_components/htd` folder.

### Configuration

Configure using the new config flow!
Go to Configuration -> Integrations -> Add Integration -> Home Theater Direct.

## Code Credits
If you wish to use a USB to Serial adapter, you will need to configure the integration manually in your `configuration.yaml` file.

```yaml
htd:
- name: Lync 6 over Serial
path: /dev/ttyUSB0
```
## Code Credits
- https://github.com/dustinmcintire/htd-lync
- https://github.com/whitingj/mca66
- https://github.com/qguernsey/Lync12
- https://github.com/steve28/mca66
Expand Down
59 changes: 54 additions & 5 deletions custom_components/htd/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,72 @@
"""Support for Home Theater Direct products"""

from __future__ import annotations, annotations

import asyncio
import logging

import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform, CONF_PORT, CONF_HOST
from homeassistant.const import Platform, CONF_PORT, CONF_HOST, CONF_PATH, CONF_UNIQUE_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv, discovery
from htd_client import async_get_client

from .const import DOMAIN, CONF_DEVICE_KIND
from .const import DOMAIN, CONF_DEVICE_KIND, CONF_DEVICE_NAME
from .utils import _async_cleanup_registry_entries

PLATFORMS: list[Platform] = [Platform.MEDIA_PLAYER]

_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
[
vol.Schema(
{
vol.Required(CONF_DEVICE_NAME): cv.string,
vol.Required(CONF_PATH): cv.string,
}
)
]
)
},
extra=vol.ALLOW_EXTRA,
)


async def async_setup(hass: HomeAssistant, config: dict):
htd_config = config.get(DOMAIN)

if htd_config is None:
return True

devices = []

for config in htd_config:
serial_address = config[CONF_PATH]
device_name = config[CONF_DEVICE_NAME]

client = await async_get_client(
serial_address=serial_address,
loop=hass.loop
)

while not client.ready:
await asyncio.sleep(0)

unique_id = f"{client.model['name']}-{serial_address}"

devices.append({
"client": client,
CONF_UNIQUE_ID: unique_id,
CONF_DEVICE_NAME: device_name
})

hass.data[DOMAIN] = devices

for component in PLATFORMS:
await discovery.async_load_platform(hass, component, DOMAIN, {}, config)

async def async_setup(_: HomeAssistant, __: ConfigEntry):
return True


Expand Down
4 changes: 2 additions & 2 deletions custom_components/htd/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"@hikirsch"
],
"name": "Home Theater Direct",
"version": "2.0.0-alpha.18",
"version": "2.0.0-alpha.19",
"iot_class": "local_push",
"integration_type": "hub",
"requirements": [
"htd_client==0.0.20"
"htd_client==0.0.21"
],
"config_flow": true,
"dhcp": [
Expand Down
41 changes: 37 additions & 4 deletions custom_components/htd/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from htd_client import BaseClient, HtdConstants, HtdMcaClient
from htd_client.models import ZoneDetail

from .const import DOMAIN, CONF_DEVICE_NAME

MEDIA_PLAYER_PREFIX = "media_player.htd_"

SUPPORT_HTD = (
Expand All @@ -34,6 +36,36 @@
type HtdClientConfigEntry = ConfigEntry[BaseClient]


async def async_setup_platform(hass, _, async_add_entities, __=None):
htd_configs = hass.data[DOMAIN]
entities = []

for device_index in range(len(htd_configs)):
config = htd_configs[device_index]

unique_id = config[CONF_UNIQUE_ID]
device_name = config[CONF_DEVICE_NAME]
client = config["client"]

zone_count = client.get_zone_count()
source_count = client.get_source_count()
sources = [f"Source {i + 1}" for i in range(source_count)]
for zone in range(1, zone_count + 1):
entity = HtdDevice(
unique_id,
device_name,
zone,
sources,
client
)

entities.append(entity)

async_add_entities(entities)

return True


async def async_setup_entry(_: HomeAssistant, config_entry: HtdClientConfigEntry, async_add_entities):
entities = []

Expand Down Expand Up @@ -84,7 +116,7 @@ def __init__(

@property
def enabled(self) -> bool:
return self.zone_info is not None
return self.zone_info is not None and self.zone_info.enabled

@property
def supported_features(self):
Expand Down Expand Up @@ -175,7 +207,7 @@ def _do_update(self, zone: int):
if zone is None and self.zone_info is not None:
return

if zone is not None and zone != self.zone:
if zone is not None and zone != 0 and zone != self.zone:
return

if not self.client.has_zone_data(self.zone):
Expand All @@ -185,5 +217,6 @@ def _do_update(self, zone: int):
if isinstance(self.client, HtdMcaClient) and self.client.has_volume_target(self.zone):
return

self.zone_info = self.client.get_zone(self.zone)
self.schedule_update_ha_state()
if zone is not None and self.client.has_zone_data(zone):
self.zone_info = self.client.get_zone(zone)
self.schedule_update_ha_state(force_refresh=True)
Binary file modified logo-htd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ee36f87

Please sign in to comment.