add home assistant integration
This commit is contained in:
parent
2a575c456c
commit
dece26ef3d
55
vendors/home_assistant_integration/__init__.py
vendored
Normal file
55
vendors/home_assistant_integration/__init__.py
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
"""The Immersive Home integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from . import hub, websocket_api
|
||||
from .const import DOMAIN
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the ImmersiveHome component."""
|
||||
|
||||
hass.data[DOMAIN] = {
|
||||
"hub": hub.Hub(hass),
|
||||
}
|
||||
|
||||
websocket_api.async_setup_commands(hass)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up ImmersiveHome from a config entry."""
|
||||
registration = entry.data
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, registration["device_id"])},
|
||||
manufacturer="Someone",
|
||||
model=registration["platform"],
|
||||
name=registration["name"],
|
||||
sw_version=registration["version"],
|
||||
)
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
return unload_ok
|
29
vendors/home_assistant_integration/config_flow.py
vendored
Normal file
29
vendors/home_assistant_integration/config_flow.py
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
"""Config flow for Immersive Home."""
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
class ImmersiveHomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a Mobile App config flow."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow initialized by the user."""
|
||||
placeholders = {
|
||||
"apps_url": "https://www.home-assistant.io/integrations/immersive_home/#apps"
|
||||
}
|
||||
|
||||
return self.async_abort(
|
||||
reason="install_app", description_placeholders=placeholders
|
||||
)
|
||||
|
||||
async def async_step_registration(self, user_input=None):
|
||||
"""Handle a flow initialized during registration."""
|
||||
|
||||
if "device_id" in user_input:
|
||||
await self.async_set_unique_id(f"{user_input['device_id']}")
|
||||
|
||||
return self.async_create_entry(title=user_input["name"], data=user_input)
|
3
vendors/home_assistant_integration/const.py
vendored
Normal file
3
vendors/home_assistant_integration/const.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""Constants for the Immersive Home integration."""
|
||||
|
||||
DOMAIN = "immersive_home"
|
48
vendors/home_assistant_integration/hub.py
vendored
Normal file
48
vendors/home_assistant_integration/hub.py
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
class Hub:
|
||||
manufacturer = "Immersive Home"
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
self._hass = hass
|
||||
self.devices = {}
|
||||
|
||||
def add_device(self, device: Device) -> None:
|
||||
self.devices[device.id] = device
|
||||
|
||||
def get_device(self, device_id: str) -> Device:
|
||||
return self.devices.get(device_id)
|
||||
|
||||
|
||||
class Device:
|
||||
def __init__(self, device_id: str, name: str, version: str, platform: str) -> None:
|
||||
self.id = device_id
|
||||
self.name = name
|
||||
self.version = version
|
||||
self.platform = platform
|
||||
self.room = None
|
||||
|
||||
self._callbacks = set()
|
||||
|
||||
def set_room(self, room: str) -> None:
|
||||
self.room = room
|
||||
|
||||
asyncio.create_task(self.publish_updates())
|
||||
|
||||
def add_callback(self, callback: callable[[], None]) -> None:
|
||||
"""Register callback, called when Roller changes state."""
|
||||
self._callbacks.add(callback)
|
||||
|
||||
def remove_callback(self, callback: callable[[], None]) -> None:
|
||||
"""Remove previously registered callback."""
|
||||
self._callbacks.discard(callback)
|
||||
|
||||
async def publish_updates(self) -> None:
|
||||
"""Schedule call all registered callbacks."""
|
||||
for callback in self._callbacks:
|
||||
callback()
|
14
vendors/home_assistant_integration/manifest.json
vendored
Normal file
14
vendors/home_assistant_integration/manifest.json
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"domain": "immersive_home",
|
||||
"name": "ImmersiveHome",
|
||||
"codeowners": ["@nitwel"],
|
||||
"config_flow": true,
|
||||
"dependencies": ["http", "websocket_api"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/immersive_home",
|
||||
"homekit": {},
|
||||
"iot_class": "local_push",
|
||||
"requirements": [],
|
||||
"ssdp": [],
|
||||
"zeroconf": [],
|
||||
"version": "0.0.1"
|
||||
}
|
59
vendors/home_assistant_integration/sensor.py
vendored
Normal file
59
vendors/home_assistant_integration/sensor.py
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
"""Platform for sensor integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import DOMAIN
|
||||
from .hub import Device, Hub
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the sensor platform."""
|
||||
|
||||
hub: Hub = hass.data[DOMAIN]["hub"]
|
||||
|
||||
for device in hub.devices.values():
|
||||
async_add_entities([RoomSensor(device)])
|
||||
|
||||
|
||||
class RoomSensor(SensorEntity):
|
||||
"""Representation of a Sensor."""
|
||||
|
||||
def __init__(self, device: Device) -> None:
|
||||
"""Initialize the sensor."""
|
||||
self._attr_name = f"{device.name} Room"
|
||||
self._attr_unique_id = f"{device.id}_room"
|
||||
self._device = device
|
||||
self._attr_should_poll = False
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self._device.id)},
|
||||
}
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._device.room
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
return True
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Run when this Entity has been added to HA."""
|
||||
# Sensors should also register callbacks to HA when their state changes
|
||||
self._device.add_callback(self.async_write_ha_state)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Entity being removed from hass."""
|
||||
# The opposite of async_added_to_hass. Remove any registered call backs here.
|
||||
self._device.remove_callback(self.async_write_ha_state)
|
13
vendors/home_assistant_integration/strings.json
vendored
Normal file
13
vendors/home_assistant_integration/strings.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
|
||||
}
|
||||
}
|
||||
}
|
86
vendors/home_assistant_integration/websocket_api.py
vendored
Normal file
86
vendors/home_assistant_integration/websocket_api.py
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
"""Home Assistant websocket API."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .hub import Device, Hub
|
||||
|
||||
|
||||
@callback
|
||||
def async_setup_commands(hass):
|
||||
"""Set up the mobile app websocket API."""
|
||||
websocket_api.async_register_command(hass, handle_register)
|
||||
websocket_api.async_register_command(hass, handle_update)
|
||||
|
||||
|
||||
@callback
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "immersive_home/register",
|
||||
vol.Required("device_id"): str,
|
||||
vol.Required("name"): str,
|
||||
vol.Required("version"): str,
|
||||
vol.Required("platform"): str,
|
||||
}
|
||||
)
|
||||
@websocket_api.async_response
|
||||
async def handle_register(
|
||||
hass: HomeAssistant,
|
||||
connection: websocket_api.ActiveConnection,
|
||||
msg: dict[str, Any],
|
||||
) -> None:
|
||||
"""Set up a new Immersive Home Device."""
|
||||
|
||||
hub: Hub = hass.data[DOMAIN]["hub"]
|
||||
|
||||
hub.add_device(
|
||||
Device(
|
||||
msg["device_id"],
|
||||
msg["name"],
|
||||
msg["version"],
|
||||
msg["platform"],
|
||||
)
|
||||
)
|
||||
|
||||
await hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN, data=msg, context={"source": "registration"}
|
||||
)
|
||||
)
|
||||
|
||||
connection.send_result(msg["id"], {"result": "success"})
|
||||
|
||||
|
||||
@callback
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "immersive_home/update",
|
||||
vol.Required("device_id"): str,
|
||||
vol.Optional("room"): str,
|
||||
}
|
||||
)
|
||||
def handle_update(
|
||||
hass: HomeAssistant,
|
||||
connection: websocket_api.ActiveConnection,
|
||||
msg: dict[str, Any],
|
||||
) -> None:
|
||||
"""Update data of a Immersive Home Device."""
|
||||
|
||||
hub: Hub = hass.data[DOMAIN]["hub"]
|
||||
device = hub.get_device(msg["device_id"])
|
||||
|
||||
if device is None:
|
||||
connection.send_error(msg["id"], "device_not_found", "Device not found")
|
||||
return
|
||||
|
||||
if "room" in msg:
|
||||
device.set_room(msg["room"])
|
||||
|
||||
connection.send_result(msg["id"], {"result": "success"})
|
Loading…
Reference in New Issue
Block a user