Skip to content

Commit

Permalink
Merge pull request #5 from NitorCreations/more-work
Browse files Browse the repository at this point in the history
Improved entity names, duplicate device detection, initial auto-discovery support
  • Loading branch information
Jalle19 authored Sep 10, 2024
2 parents 643a835 + 8995c57 commit 96c131f
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 14 deletions.
3 changes: 2 additions & 1 deletion custom_components/vinx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
class DeviceInformation:
mac_address: str
product_name: str
device_label: str
device_info: DeviceInfo


Expand Down Expand Up @@ -44,7 +45,7 @@ async def get_device_information(lw3: LW3) -> DeviceInformation:
configuration_url=f"http://{ip_address}/",
)

return DeviceInformation(mac_address, product_name, device_info)
return DeviceInformation(mac_address, product_name, device_label, device_info)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
Expand Down
52 changes: 44 additions & 8 deletions custom_components/vinx/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,74 @@
import logging

from typing import Any

import voluptuous as vol

from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.helpers.device_registry import format_mac

from .const import CONF_HOST, CONF_PORT, DOMAIN
from .lw3 import LW3

STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Required(CONF_PORT, default=6107): int,
}
)
_LOGGER = logging.getLogger(__name__)


class VinxConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1

def __init__(self):
# Potentially prepopulated values (e.g. during auto-discovery)
self.host: str | None = None
self.port: int = 6107

@property
def schema(self):
return vol.Schema(
{
vol.Required(CONF_HOST, default=self.host): str,
vol.Required(CONF_PORT, default=self.port): int,
}
)

async def async_step_user(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
"""Handle user initiated configuration"""
errors: dict[str, str] = {}
if user_input is not None:
try:
# Query the device for enough information to make an entry title
# Verify that the device is connectable
lw3 = LW3(user_input["host"], user_input["port"])
async with lw3.connection():
# Query information for the entry title and entry unique ID
product_name = await lw3.get_property("/.ProductName")
device_label = await lw3.get_property("/SYS/MB.DeviceLabel")
mac_address = await lw3.get_property("/.MacAddress")

title = f"{device_label} ({product_name})"

unique_id = format_mac(str(mac_address))
await self.async_set_unique_id(unique_id)

# Abort the configuration if the device is already configured
self._abort_if_unique_id_configured()
except (BrokenPipeError, ConnectionError, OSError): # all technically OSError
errors["base"] = "cannot_connect"
else:
return self.async_create_entry(title=title, data=user_input)

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

async def async_step_zeroconf(self, discovery_info: ZeroconfServiceInfo) -> ConfigFlowResult:
_LOGGER.info(f"Zeroconf discovery info: {discovery_info}")

# Abort if the device is already configured
unique_id = format_mac(discovery_info.properties.get("mac"))
await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured()

# Pre-populate the form
self.host = discovery_info.ip_address
self.port = discovery_info.port

# Trigger the user configuration flow
return await self.async_step_user()
2 changes: 1 addition & 1 deletion custom_components/vinx/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"iot_class": "local_polling",
"requirements": [],
"ssdp": [],
"zeroconf": []
"zeroconf": ["_lwr3._tcp.local."]
}
17 changes: 13 additions & 4 deletions custom_components/vinx/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
_LOGGER.warning("Unknown device type, no entities will be added")


class AbstractVinxDevice(MediaPlayerEntity):
class AbstractVinxMediaPlayerEntity(MediaPlayerEntity):
def __init__(self, lw3: LW3, device_information: DeviceInformation) -> None:
self._lw3 = lw3
self._device_information = device_information
Expand Down Expand Up @@ -53,14 +53,23 @@ def device_info(self) -> DeviceInfo:

@property
def name(self):
return "Media Player"
# Use increasingly less descriptive names depending on what information is available
device_label = self._device_information.device_label
serial_number = self._device_information.device_info.get("serial_number")

if device_label:
return f"{self._device_information.device_label} media player"
elif serial_number:
return f"VINX {serial_number} media player"
else:
return "VINX media player"

class VinxEncoder(AbstractVinxDevice):

class VinxEncoder(AbstractVinxMediaPlayerEntity):
pass


class VinxDecoder(AbstractVinxDevice):
class VinxDecoder(AbstractVinxMediaPlayerEntity):
def __init__(self, lw3: LW3, device_information: DeviceInformation) -> None:
super().__init__(lw3, device_information)

Expand Down

0 comments on commit 96c131f

Please sign in to comment.