Build a Complete Home Assistant Plugin for AmpVortex Series Amplifiers
AmpVortex amplifiers provide multi-room streaming, AirPlay 2, Google Cast, and BT Audio support. By integrating them into Home Assistant, you can control all zones, inputs, volume, mute, and EQ settings from a single interface. This guide shows you how to create a fully functional custom component using the AmpVortex Web API.
home assistant plugin: https://drive.google.com/file/d/18N8YrgUVENWHTIMqXE7D-LHtfyRrUMRs/view?usp=sharing
Note: This Home Assistant Plugin is written by ChatGPT.
- Plugin Directory Structure
Create the following structure under custom_components/ampvortex/:
custom_components/ampvortex/
├── __init__.py
├── manifest.json
├── config_flow.py
├── api_client.py
├── media_player.py
├── input_entity.py
├── eq_entity.py
- manifest.json
{
“domain”: “ampvortex”,
“name”: “AmpVortex”,
“version”: “1.1.0”,
“documentation”: “https://www.ampvortex.com”,
“requirements”: [“aiohttp”],
“dependencies”: [],
“codeowners”: [“@yourname”]
}
- api_client.py
import aiohttp
class AmpVortexClient:
def __init__(self, base_url, token):
self.base_url = base_url
self.token = token
async def get_zones(self):
async with aiohttp.ClientSession() as session:
headers = {“Authorization”: f”Bearer {self.token}”}
async with session.get(f”{self.base_url}/api/v3/zones/”, headers=headers) as resp:
return await resp.json()
async def get_zone_info(self, zone_id):
async with aiohttp.ClientSession() as session:
headers = {“Authorization”: f”Bearer {self.token}”}
async with session.get(f”{self.base_url}/api/v3/zones/{zone_id}”, headers=headers) as resp:
return await resp.json()
async def set_zone_volume(self, zone_id, volume):
async with aiohttp.ClientSession() as session:
headers = {“Authorization”: f”Bearer {self.token}”}
data = {“volume”: volume}
async with session.put(f”{self.base_url}/api/v3/zones/{zone_id}/volume”, json=data, headers=headers) as resp:
return await resp.json()
async def mute_zone(self, zone_id, enable=True):
async with aiohttp.ClientSession() as session:
headers = {“Authorization”: f”Bearer {self.token}”}
data = {“enable”: enable}
async with session.put(f”{self.base_url}/api/v3/zones/{zone_id}/mute”, json=data, headers=headers) as resp:
return await resp.json()
async def set_zone_input(self, zone_id, input_ids):
async with aiohttp.ClientSession() as session:
headers = {“Authorization”: f”Bearer {self.token}”}
data = {“input_ids”: input_ids}
async with session.put(f”{self.base_url}/api/v3/zones/{zone_id}/input”, json=data, headers=headers) as resp:
return await resp.json()
async def set_zone_eq(self, zone_id, eq_type, value):
async with aiohttp.ClientSession() as session:
headers = {“Authorization”: f”Bearer {self.token}”}
data = {eq_type: value}
async with session.put(f”{self.base_url}/api/v3/zones/{zone_id}/eq”, json=data, headers=headers) as resp:
return await resp.json()
- media_player.py
from homeassistant.components.media_player import MediaPlayerEntity
class AmpVortexZone(MediaPlayerEntity):
def __init__(self, client, zone):
self.client = client
self.zone_id = zone[“zone_id”]
self._name = zone[“name”]
self._volume = zone[“volume”]
self._muted = zone[“muted”]
self._active_input = zone.get(“active_input”, “”)
@property
def name(self):
return self._name
@property
def volume_level(self):
return self._volume / 100
@property
def is_volume_muted(self):
return self._muted
async def async_set_volume_level(self, volume):
await self.client.set_zone_volume(self.zone_id, int(volume * 100))
self._volume = int(volume * 100)
async def async_mute_volume(self, mute):
await self.client.mute_zone(self.zone_id, enable=mute)
self._muted = mute
async def async_select_source(self, source):
await self.client.set_zone_input(self.zone_id, [source])
self._active_input = source
- input_entity.py (Inputs as Separate Entities)
from homeassistant.components.select import SelectEntity
class AmpVortexInput(SelectEntity):
def __init__(self, client, zone):
self.client = client
self.zone_id = zone[“zone_id”]
self._name = f”{zone[‘name’]} Input”
self._options = zone.get(“available_inputs”, [])
self._current = zone.get(“active_input”, “”)
@property
def name(self):
return self._name
@property
def options(self):
return self._options
@property
def current_option(self):
return self._current
async def async_select_option(self, option):
await self.client.set_zone_input(self.zone_id, [option])
self._current = option
- eq_entity.py (Zone EQ Controls)
from homeassistant.components.number import NumberEntity
class AmpVortexEQ(NumberEntity):
def __init__(self, client, zone, eq_type):
self.client = client
self.zone_id = zone[“zone_id”]
self.eq_type = eq_type # bass, treble, balance
self._name = f”{zone[‘name’]} {eq_type.capitalize()}”
self._value = zone.get(eq_type, 0)
@property
def name(self):
return self._name
@property
def min_value(self):
return -10
@property
def max_value(self):
return 10
@property
def step(self):
return 1
@property
def value(self):
return self._value
async def async_set_value(self, value):
await self.client.set_zone_eq(self.zone_id, self.eq_type, value)
self._value = value
- init.py
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .api_client import AmpVortexClient
from .media_player import AmpVortexZone
from .input_entity import AmpVortexInput
from .eq_entity import AmpVortexEQ
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
token = entry.data[“token”]
base_url = entry.data[“base_url”]
client = AmpVortexClient(base_url, token)
zones = await client.get_zones()
entities = [AmpVortexZone(client, z) for z in zones]
for z in zones:
entities.append(AmpVortexInput(client, z))
for eq in [“bass”, “treble”, “balance”]:
entities.append(AmpVortexEQ(client, z, eq))
hass.data.setdefault(“ampvortex”, {})[entry.entry_id] = entities
hass.helpers.discovery.async_load_platform(“media_player”, “ampvortex”, {}, entry.data)
return True
- config_flow.py (UI Setup)
from homeassistant import config_entries
import voluptuous as vol
class AmpVortexConfigFlow(config_entries.ConfigFlow, domain=”ampvortex”):
async def async_step_user(self, user_input=None):
if user_input is not None:
return self.async_create_entry(title=”AmpVortex”, data=user_input)
return self.async_show_form(
step_id=”user”,
data_schema=vol.Schema({
vol.Required(“base_url”): str,
vol.Required(“token”): str
})
)
- Installing and Testing
- Place the ampvortex folder under custom_components/ in your Home Assistant configuration directory.
- Restart Home Assistant.
- Add a new AmpVortex integration via the UI using base_url and token.
- Verify that:
- Each zone appears as a media player entity.
- Each zone’s inputsappear as separate select entities.
- EQ controls appear as number slidersfor bass, treble, and balance.
- Test volume, mute, input selection, and EQ adjustment.
✅ This extended plugin now fully supports:
- Multi-room zones as media players
- Input selection as separate entities
- EQ adjustments per zone (bass, treble, balance)
- Volume control and mute
This gives you a complete, modular Home Assistant integration for AmpVortex amplifiers.

