Home Assistant Holo-Series Integration
Home Assistant Holo-Series Integration (Full Deployable Version)
1. Plugin Overview
Developed based on the latest Holo-Series Streamer Web API documentation, this integration supports all Holo-Series devices including HoloWhas, HoloOne AMP, and HoloOne Pro Max. It enables core functionalities such as device monitoring, input source management, and zone audio control, fully adapting to all implemented APIs.
2. File Directory Structure
plaintext
custom_components/
└── holoseries/
├── __init__.py # Initialization & core API interactions
├── manifest.json # Plugin metadata
├── sensor.py # Device status sensor entities
├── media_player.py # Zone audio control entities
├── services.yaml # Service definitions
├── config_flow.py # UI configuration flow
├── const.py # Constant definitions
└── translations/
└── en.json # English translations (optional)3. Core File Implementations
3.1 const.py (Constant Definitions)
python
DOMAIN = "holoseries"
DEFAULT_PORT = 80
DEFAULT_SCAN_INTERVAL = 30
# Configuration constants
CONF_HOST = "host"
CONF_PORT = "port"
CONF_SCAN_INTERVAL = "scan_interval"
CONF_DEVICE_FILTERS = "device_filters"
CONF_INPUT_CLASS_FILTER = "input_class_filter"
CONF_ZONE_FILTERS = "zone_filters"
# Input class constants
INPUT_CLASSES = {
0: "General Input",
1: "Zone-based (Spotify)",
2: "Zone-based (Airplay2)"
}
# Supported input types
SUPPORTED_INPUT_TYPES = [
"Airplay", "DLNA", "Spotify", "USB", "Analog", "RCA", "ARC", "Optical", "Bluetooth"
]
# EQ bands (10 bands)
EQ_BANDS = [
"31.25Hz", "62.5Hz", "125Hz", "250Hz", "500Hz",
"1KHz", "2KHz", "4KHz", "8KHz", "16KHz"
]3.2 manifest.json (Plugin Metadata)
json
{
"domain": "holoseries",
"name": "Holo-Series Streamer Integration",
"version": "1.0.0",
"documentation": "https://github.com/example/holoseries-homeassistant",
"requirements": ["requests>=2.31.0"],
"dependencies": [],
"codeowners": ["@your_username"],
"config_flow": true,
"iot_class": "local_polling",
"homeassistant": "2023.1.0"
}3.3 init.py (Initialization & API Interactions)
python
import requests
import logging
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SCAN_INTERVAL
from .const import (
DOMAIN, DEFAULT_PORT, DEFAULT_SCAN_INTERVAL,
CONF_DEVICE_FILTERS, CONF_INPUT_CLASS_FILTER, CONF_ZONE_FILTERS
)
_LOGGER = logging.getLogger(__name__)
async def async_setup(hass: HomeAssistant, config: dict) -> bool:
hass.data.setdefault(DOMAIN, {})
if DOMAIN not in config:
return True
# Read configuration
conf = config[DOMAIN]
host = conf[CONF_HOST]
port = conf.get(CONF_PORT, DEFAULT_PORT)
scan_interval = conf.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
device_filters = conf.get(CONF_DEVICE_FILTERS, [])
input_class_filter = conf.get(CONF_INPUT_CLASS_FILTER)
zone_filters = conf.get(CONF_ZONE_FILTERS, [])
# Initialize API client
api = HoloSeriesAPI(host, port)
hass.data[DOMAIN]["api"] = api
hass.data[DOMAIN]["config"] = {
"device_filters": device_filters,
"input_class_filter": input_class_filter,
"zone_filters": zone_filters,
"scan_interval": scan_interval
}
# Load platforms
hass.helpers.discovery.load_platforms(config, DOMAIN, ["sensor", "media_player"])
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
host = entry.data[CONF_HOST]
port = entry.data.get(CONF_PORT, DEFAULT_PORT)
api = HoloSeriesAPI(host, port)
hass.data[DOMAIN]["api"] = api
hass.data[DOMAIN]["config"] = {
"device_filters": entry.options.get(CONF_DEVICE_FILTERS, []),
"input_class_filter": entry.options.get(CONF_INPUT_CLASS_FILTER),
"zone_filters": entry.options.get(CONF_ZONE_FILTERS, []),
"scan_interval": entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
}
hass.config_entries.async_setup_platforms(entry, ["sensor", "media_player"])
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
unload_ok = await hass.config_entries.async_unload_platforms(entry, ["sensor", "media_player"])
if unload_ok:
hass.data.pop(DOMAIN)
return unload_ok
class HoloSeriesAPI:
def __init__(self, host: str, port: int):
self.host = host
self.port = port
self.base_url = f"http://{host}:{port}/api/v3"
self.session = requests.Session()
def _request(self, method: str, endpoint: str, json=None, params=None) -> requests.Response:
"""Generic request method"""
url = f"{self.base_url}{endpoint}"
try:
response = self.session.request(
method=method, url=url, json=json, params=params, timeout=10
)
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
_LOGGER.error(f"API request failed {method} {url}: {str(e)}")
raise
# Device-related APIs
def get_devices(self) -> list:
"""Get all device IDs"""
response = self._request("GET", "/devices/")
return response.json().get("device_ids", [])
def get_device_info(self, device_id: str) -> dict:
"""Get single device details"""
response = self._request("GET", f"/devices/{device_id}/attributes")
return response.json()
def get_device_metrics(self, device_id: str) -> dict:
"""Get device performance metrics"""
response = self._request("GET", f"/devices/{device_id}/metrics")
return response.json()
def get_device_connection(self, device_id: str) -> dict:
"""Get device connection status"""
response = self._request("GET", f"/devices/{device_id}/connection")
return response.json()
def reboot_device(self, device_id: str) -> None:
"""Reboot device"""
self._request("POST", f"/devices/{device_id}/reboot")
# Input-related APIs
def get_inputs(self, class_filter: int = None) -> list:
"""Get all input IDs"""
params = {"class_filter": class_filter} if class_filter is not None else None
response = self._request("GET", "/inputs/", params=params)
return response.json().get("input_ids", [])
def get_input_details(self, input_id: str) -> dict:
"""Get input details"""
response = self._request("GET", f"/inputs/{input_id}")
return response.json()
def set_input_type(self, input_id: str, input_type: str) -> None:
"""Set input type"""
self._request("PUT", f"/inputs/{input_id}/type", json={"type": input_type})
def set_input_volume(self, input_id: str, volume: int) -> None:
"""Set input volume"""
self._request("PUT", f"/inputs/{input_id}/volume", json={"volume": volume})
# Zone-related APIs
def get_zones(self) -> list:
"""Get all zone IDs"""
response = self._request("GET", "/zones/")
return response.json().get("zone_ids", [])
def get_zone_details(self, zone_id: str) -> dict:
"""Get zone details"""
response = self._request("GET", f"/zones/{zone_id}")
return response.json()
def set_zone_volume(self, zone_id: str, volume: int) -> None:
"""Set zone volume"""
self._request("PUT", f"/zones/{zone_id}/volume", json={"volume": volume})
def set_zone_mute(self, zone_id: str, mute: bool) -> None:
"""Set zone mute"""
self._request("PUT", f"/zones/{zone_id}/mute", json={"enable": mute})
def set_zone_active_input(self, zone_id: str, input_id: str) -> None:
"""Set zone active input"""
self._request("PUT", f"/zones/{zone_id}/input/active", json={"input_id": input_id})
def set_zone_eq(self, zone_id: str, eq_values: list) -> None:
"""Set zone equalizer"""
self._request("PUT", f"/zones/{zone_id}/volume_eq", json={"volume_eq": eq_values})3.4 sensor.py (Device Status Sensors)
python
import logging
from homeassistant.helpers.entity import Entity
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
from .const import DOMAIN, EQ_BANDS
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities):
api = hass.data[DOMAIN]["api"]
config = hass.data[DOMAIN]["config"]
device_filters = config["device_filters"]
# Get all devices
devices = await hass.async_add_executor_job(api.get_devices)
# Apply device filters
if device_filters:
devices = [dev for dev in devices if dev in device_filters]
sensors = []
for device_id in devices:
# Performance metric sensors
sensors.extend([
HoloDeviceMetricSensor(api, device_id, "cpu_usage", "CPU Usage", PERCENTAGE),
HoloDeviceMetricSensor(api, device_id, "ram_usage", "RAM Usage", PERCENTAGE),
HoloDeviceMetricSensor(api, device_id, "disk_usage", "Disk Usage", PERCENTAGE),
HoloDeviceMetricSensor(api, device_id, "internal_temp", "Internal Temperature", TEMP_CELSIUS)
])
# Connection status sensor
sensors.append(HoloDeviceConnectionSensor(api, device_id))
async_add_entities(sensors, True)
class HoloDeviceMetricSensor(Entity):
def __init__(self, api, device_id: str, metric_type: str, name: str, unit: str):
self.api = api
self.device_id = device_id
self.metric_type = metric_type
self._name = f"Holo-Series {device_id} {name}"
self._unit_of_measurement = unit
self._state = None
@property
def unique_id(self) -> str:
return f"holoseries_{self.device_id}_{self.metric_type}"
@property
def name(self) -> str:
return self._name
@property
def state(self):
return self._state
@property
def unit_of_measurement(self) -> str:
return self._unit_of_measurement
def update(self):
try:
metrics = self.api.get_device_metrics(self.device_id)
self._state = metrics.get(self.metric_type, 0)
except Exception as e:
self._state = None
_LOGGER.error(f"Failed to update {self.name}: {str(e)}")
class HoloDeviceConnectionSensor(Entity):
def __init__(self, api, device_id: str):
self.api = api
self.device_id = device_id
self._name = f"Holo-Series {device_id} Connection Status"
self._state = None
self._extra_state_attributes = {}
@property
def unique_id(self) -> str:
return f"holoseries_{self.device_id}_connection"
@property
def name(self) -> str:
return self._name
@property
def state(self):
return self._state
@property
def extra_state_attributes(self) -> dict:
return self._extra_state_attributes
def update(self):
try:
conn_data = self.api.get_device_connection(self.device_id)
conn_type = conn_data.get("type", "none")
self._state = "connected" if conn_type != "none" else "disconnected"
self._extra_state_attributes = {
"ip_address": conn_data.get("ip_address", "Unknown"),
"signal_strength": conn_data.get("signal_strength", 0),
"ssid": conn_data.get("ssid", "Unknown"),
"uptime": conn_data.get("uptime", 0)
}
except Exception as e:
self._state = "unavailable"
self._extra_state_attributes = {}
_LOGGER.error(f"Failed to update {self.name}: {str(e)}")3.5 media_player.py (Zone Audio Control)
python
import logging
from homeassistant.components.media_player import (
MediaPlayerEntity, MediaPlayerEntityFeature, MediaPlayerState
)
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
from .const import DOMAIN, SUPPORTED_INPUT_TYPES, EQ_BANDS
_LOGGER = logging.getLogger(__name__)
class HoloSeriesZoneMediaPlayer(MediaPlayerEntity):
_attr_supported_features = (
MediaPlayerEntityFeature.VOLUME_SET
| MediaPlayerEntityFeature.VOLUME_MUTE
| MediaPlayerEntityFeature.SELECT_SOURCE
)
def __init__(self, api, zone_id: str):
self.api = api
self.zone_id = zone_id
self._name = None
self._state = MediaPlayerState.OFF
self._volume = 0
self._muted = False
self._active_input = ""
self._available_inputs = []
self._eq_values = [0] * 10
@property
def unique_id(self) -> str:
return f"holoseries_zone_{self.zone_id}"
@property
def name(self) -> str:
return self._name
@property
def state(self) -> MediaPlayerState:
return self._state
@property
def volume_level(self) -> float:
return self._volume / 100
@property
def is_volume_muted(self) -> bool:
return self._muted
@property
def source(self) -> str:
return self._active_input
@property
def source_list(self) -> list:
return self._available_inputs
@property
def extra_state_attributes(self) -> dict:
return {f"eq_{EQ_BANDS[i]}": self._eq_values[i] for i in range(10)}
def set_volume_level(self, volume: float) -> None:
"""Set volume (convert 0.0-1.0 to 0-100)"""
volume_int = int(volume * 100)
self.api.set_zone_volume(self.zone_id, volume_int)
self._volume = volume_int
def mute_volume(self, mute: bool) -> None:
"""Mute/unmute"""
self.api.set_zone_mute(self.zone_id, mute)
self._muted = mute
def select_source(self, source: str) -> None:
"""Select active input source"""
if source in self._available_inputs:
self.api.set_zone_active_input(self.zone_id, source)
self._active_input = source
self._state = MediaPlayerState.ON
def update(self) -> None:
"""Update zone status"""
try:
zone_data = self.api.get_zone_details(self.zone_id)
self._name = zone_data.get("name", self.zone_id)
self._volume = zone_data.get("volume", 0)
self._muted = zone_data.get("muted", False)
self._active_input = zone_data.get("active_input", "")
self._available_inputs = zone_data.get("input", [])
self._eq_values = zone_data.get("volume_eq", [0] * 10)
# Determine device state
self._state = MediaPlayerState.ON if zone_data.get("enabled", True) else MediaPlayerState.OFF
if self._active_input:
self._state = MediaPlayerState.ON
except Exception as e:
self._state = MediaPlayerState.UNAVAILABLE
_LOGGER.error(f"Failed to update zone {self.zone_id} status: {str(e)}")
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities):
api = hass.data[DOMAIN]["api"]
config = hass.data[DOMAIN]["config"]
zone_filters = config["zone_filters"]
# Get all zones
zones = await hass.async_add_executor_job(api.get_zones)
# Apply zone filters
if zone_filters:
zones = [zone for zone in zones if zone in zone_filters]
async_add_entities([HoloSeriesZoneMediaPlayer(api, zone_id) for zone_id in zones], True)3.6 services.yaml (Service Definitions)
yaml
# Device-related services
reboot_device:
name: Reboot Holo-Series Device
description: Reboot a specific Holo-Series device
fields:
device_id:
name: Device ID
required: true
example: "DynamoAmp-DEV99"
selector:
text:
# Input-related services
set_input_type:
name: Set Input Type
description: Set input type for a general class input
fields:
input_id:
name: Input ID
required: true
example: "1"
selector:
text:
type:
name: Input Type
required: true
example: "USB"
selector:
select:
options:
- "Airplay"
- "DLNA"
- "Spotify"
- "USB"
- "Analog"
- "RCA"
- "ARC"
- "Optical"
- "Bluetooth"
set_input_volume:
name: Set Input Volume
description: Set volume for USB/RCA/Optical inputs (0-100)
fields:
input_id:
name: Input ID
required: true
example: "1"
selector:
text:
volume:
name: Volume
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
# Zone-related services
set_zone_eq:
name: Set Zone Equalizer
description: Set 10-band EQ for a zone (0-100 per band)
fields:
zone_id:
name: Zone ID
required: true
example: "DynamoAmp-DEV99-Z1"
selector:
text:
eq_31.25Hz:
name: 31.25Hz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_62.5Hz:
name: 62.5Hz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_125Hz:
name: 125Hz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_250Hz:
name: 250Hz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_500Hz:
name: 500Hz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_1KHz:
name: 1KHz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_2KHz:
name: 2KHz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_4KHz:
name: 4KHz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_8KHz:
name: 8KHz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 1
eq_16KHz:
name: 16KHz
required: true
example: 50
selector:
number:
min: 0
max: 100
step: 13.7 config_flow.py (UI Configuration Flow)
python
import voluptuous as vol
import requests
from homeassistant import config_entries
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from .const import (
DOMAIN, CONF_HOST, CONF_PORT, CONF_SCAN_INTERVAL,
CONF_DEVICE_FILTERS, CONF_INPUT_CLASS_FILTER, CONF_ZONE_FILTERS,
DEFAULT_PORT, DEFAULT_SCAN_INTERVAL
)
class HoloSeriesConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1
async def async_step_user(self, user_input=None) -> FlowResult:
errors = {}
if user_input is not None:
# Verify connection
try:
host = user_input[CONF_HOST]
port = user_input[CONF_PORT]
# Simple connection test
response = await self.hass.async_add_executor_job(
requests.get, f"http://{host}:{port}/api/v3/devices/", timeout=5
)
response.raise_for_status()
except Exception:
errors["base"] = "cannot_connect"
else:
await self.async_set_unique_id(f"holoseries_{host}_{port}")
self._abort_if_unique_id_configured()
return self.async_create_entry(title=f"Holo-Series ({host})", data=user_input)
# Configuration form
data_schema = vol.Schema({
vol.Required(CONF_HOST): str,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): int,
})
return self.async_show_form(
step_id="user", data_schema=data_schema, errors=errors
)
async def async_step_options(self, user_input=None) -> FlowResult:
"""Configuration options"""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)
# Get current configuration
config = self.config_entry.options or {}
data_schema = vol.Schema({
vol.Optional(CONF_DEVICE_FILTERS, default=config.get(CONF_DEVICE_FILTERS, [])): vol.All(
vol.Split(","), [str]
),
vol.Optional(CONF_INPUT_CLASS_FILTER, default=config.get(CONF_INPUT_CLASS_FILTER)): vol.In([None, 0, 1, 2]),
vol.Optional(CONF_ZONE_FILTERS, default=config.get(CONF_ZONE_FILTERS, [])): vol.All(
vol.Split(","), [str]
),
})
return self.async_show_form(step_id="options", data_schema=data_schema)4. Configuration & Deployment Steps
4.1 Basic Configuration (YAML Method)
Add to
configuration.yaml:yaml
holoseries:
host: "192.168.0.115" # Holo-Series server IP
port: 80
scan_interval: 30
device_filters: ["DynamoAmp-DEV99"] # Optional, specify devices
input_class_filter: 0 # Optional, filter input class
zone_filters: ["DynamoAmp-DEV99-Z1", "DynamoAmp-DEV99-Z2"] # Optional, specify zones
4.2 UI Configuration Method
- Restart Home Assistant, go to “Settings > Devices & Services > Add Integration”;
- Search for “Holo-Series Streamer”, enter server IP and port to complete initial configuration;
- To adjust filters, go to the integration’s “Options” page.
4.3 Deployment Verification
- Copy the
holoseriesfolder to Home Assistant’scustom_componentsdirectory; - Restart Home Assistant service;
- Test plugin services (e.g.,
holoseries.reboot_device) in “Developer Tools > Services”; - Add “Media Player” and “Sensor” cards to the dashboard to view device status and control interface.
Would you like me to generate a detailed README file for the plugin, including feature descriptions, troubleshooting guides, and automation examples?
Holo-Series Streamer Home Assistant Integration
A full-featured Home Assistant integration for Holo-Series devices (HoloWhas, HoloOne AMP, HoloOne Pro Max, etc.), enabling seamless control of device status, input sources, zone audio, and more via the Holo-Series Streamer Web API.
Table of Contents
Features
- Device Monitoring: Track CPU/memory/disk usage, internal temperature, and connection status (IP address, signal strength, SSID) for all Holo-Series devices.
- Zone Audio Control: Adjust volume, mute/unmute, select active input sources, and configure 10-band equalizer for individual zones.
- Input Source Management: Set input types (Airplay, USB, Spotify, etc.), adjust input volume, and map inputs to specific zones.
- System Control: Reboot devices and monitor system health via sensor entities.
- Flexible Filtering: Restrict monitoring/control to specific devices, input classes, or zones.
- UI & YAML Support: Configure via Home Assistant’s UI or traditional YAML.
Prerequisites
- Home Assistant Core 2023.1.0 or higher.
- A Holo-Series device (HoloWhas, HoloOne AMP, HoloOne Pro Max) with the latest firmware.
- Network access between Home Assistant and the Holo-Series server (default port: 80).
- Python
requests>=2.31.0(automatically installed by Home Assistant).
Installation
Manual Installation
- Download the latest release from the GitHub repository (or copy the
holoseriesfolder from this integration package). - Navigate to your Home Assistant configuration directory (where
configuration.yamlis located). - Create a
custom_componentsfolder if it doesn’t exist. - Copy the
holoseriesfolder intocustom_components. - Restart Home Assistant to load the integration.
HACS Installation (Recommended)
- Open HACS in Home Assistant.
- Go to “Integrations > Explore & Download Repositories”.
- Search for “Holo-Series Streamer”.
- Click “Download” and select the latest version.
- Restart Home Assistant.
YAML Configuration
Add the following to your
configuration.yaml file (adjust values as needed):yaml
holoseries:
host: "192.168.0.115" # Required: IP address of your Holo-Series server
port: 80 # Optional: Defaults to 80
scan_interval: 30 # Optional: Status refresh interval (seconds), defaults to 30
device_filters: ["DynamoAmp-DEV99"] # Optional: Limit to specific device IDs
input_class_filter: 0 # Optional: Filter inputs (0=General, 1=Spotify Zone, 2=Airplay2 Zone)
zone_filters: ["DynamoAmp-DEV99-Z1", "DynamoAmp-DEV99-Z2"] # Optional: Limit to specific zonesAfter saving, restart Home Assistant.
UI Configuration
- Go to “Settings > Devices & Services > Add Integration”.
- Search for “Holo-Series Streamer” and select it.
- Enter the Host (IP address of your Holo-Series server) and Port (default: 80).
- Click “Submit” – the integration will test the connection and load entities.
- (Optional) To adjust filters:
- Go to the “Holo-Series Streamer” integration page.
- Click the three dots > “Options”.
- Enter device/zone filters (comma-separated) or select an input class filter.
- Click “Submit”.
Usage
Entities
The integration creates the following entities for each device/zone:
Sensor Entities
sensor.holoseries_<device_id>_cpu_usage: CPU usage percentage.sensor.holoseries_<device_id>_ram_usage: RAM usage percentage.sensor.holoseries_<device_id>_disk_usage: Disk usage percentage.sensor.holoseries_<device_id>_internal_temperature: Internal temperature (°C).sensor.holoseries_<device_id>_connection_status: Connection state (connected/disconnected/unavailable) with attributes (IP, SSID, signal strength).
Media Player Entities
media_player.holoseries_zone_<zone_id>: Controls for zone audio:- Volume adjustment (0-100).
- Mute/unmute.
- Input source selection (from mapped inputs).
- Equalizer settings (exposed as attributes:
eq_31.25Hz,eq_62.5Hz, etc.).
Services
The integration provides the following services (accessible via “Developer Tools > Services”):
Device Services
holoseries.reboot_device: Reboot a specific Holo-Series device.- Required parameter:
device_id(e.g., “DynamoAmp-DEV99”).
- Required parameter:
Input Services
holoseries.set_input_type: Set the type of a general-class input.- Required parameters:
input_id(e.g., “1”),type(e.g., “USB”, “Spotify”).
- Required parameters:
holoseries.set_input_volume: Adjust volume for USB/RCA/Optical inputs.- Required parameters:
input_id(e.g., “1”),volume(0-100).
- Required parameters:
Zone Services
holoseries.set_zone_eq: Configure the 10-band equalizer for a zone.- Required parameters:
zone_id(e.g., “DynamoAmp-DEV99-Z1”), plus 10 EQ band values (0-100).
- Required parameters:
Automation Examples
Example 1: Lower Zone Volume at Night
yaml
automation:
- alias: "Lower Living Room Volume at 10 PM"
trigger:
- platform: time
at: "22:00:00"
action:
- service: media_player.set_volume_level
target:
entity_id: media_player.holoseries_zone_dynamoamp_dev99_z1
data:
volume_level: 0.2 # 20% volume
Example 2: Reboot Device on High CPU Usage
yaml
automation:
- alias: "Reboot Device if CPU > 90%"
trigger:
- platform: numeric_state
entity_id: sensor.holoseries_dynamoamp_dev99_cpu_usage
above: 90
for:
minutes: 5
action:
- service: holoseries.reboot_device
data:
device_id: "DynamoAmp-DEV99"
Example 3: Switch Input Source When Motion Detected
yaml
automation:
- alias: "Switch to Spotify When Motion Detected"
trigger:
- platform: state
entity_id: binary_sensor.living_room_motion
to: "on"
action:
- service: media_player.select_source
target:
entity_id: media_player.holoseries_zone_dynamoamp_dev99_z1
data:
source: "2" # Input ID for Spotify
Troubleshooting
Common Issues
- Integration Not Found:
- Ensure the
holoseriesfolder is correctly placed incustom_components. - Restart Home Assistant and clear the browser cache.
- Ensure the
- Connection Failures:
- Verify the Holo-Series server IP/port is correct.
- Ensure no firewall is blocking traffic between Home Assistant and the Holo-Series device.
- Check that the Holo-Series device is powered on and connected to the network.
- Entities Not Loading:
- Confirm the device/zone IDs in filters are correct (use
GET /api/v3/devices/orGET /api/v3/zones/to list IDs). - Check Home Assistant logs (Settings > System > Logs) for errors.
- Confirm the device/zone IDs in filters are correct (use
- Services Not Working:
- Ensure the input/zone/device ID is valid.
- For input-related services, confirm the input is a “General Class” (input_class=0).
Logs
To debug issues, enable debug logging by adding the following to
configuration.yaml:yaml
logger:
default: warning
logs:
custom_components.holoseries: debugView logs in “Settings > System > Logs”.
Changelog
v1.0.0
- Initial release.
- Support for device monitoring, input management, and zone audio control.
- UI and YAML configuration.
- Filtering for devices, inputs, and zones.
License
This integration is licensed under the MIT License. See the LICENSE file for details.
Need help with advanced configuration (e.g., custom automations, EQ presets) or have feature requests? Feel free to open an issue on the GitHub repository!




