2019-04-03 15:40:03 +00:00
|
|
|
"""Support for LG soundbars."""
|
2022-01-03 15:04:15 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2019-10-21 08:09:38 +00:00
|
|
|
import temescal
|
|
|
|
|
2022-04-07 07:34:58 +00:00
|
|
|
from homeassistant.components.media_player import (
|
|
|
|
MediaPlayerEntity,
|
|
|
|
MediaPlayerEntityFeature,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2022-06-30 17:00:39 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
|
|
from homeassistant.const import CONF_HOST, CONF_PORT, STATE_ON
|
2022-01-03 15:04:15 +00:00
|
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2018-10-18 08:39:33 +00:00
|
|
|
|
|
|
|
|
2022-06-30 17:00:39 +00:00
|
|
|
async def async_setup_entry(
|
2022-01-03 15:04:15 +00:00
|
|
|
hass: HomeAssistant,
|
2022-06-30 17:00:39 +00:00
|
|
|
config_entry: ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
2022-01-03 15:04:15 +00:00
|
|
|
) -> None:
|
2022-06-30 17:00:39 +00:00
|
|
|
"""Set up media_player from a config entry created in the integrations UI."""
|
|
|
|
async_add_entities(
|
|
|
|
[
|
|
|
|
LGDevice(
|
|
|
|
config_entry.data[CONF_HOST],
|
|
|
|
config_entry.data[CONF_PORT],
|
|
|
|
config_entry.unique_id,
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
2018-10-18 08:39:33 +00:00
|
|
|
|
|
|
|
|
2020-04-25 16:00:57 +00:00
|
|
|
class LGDevice(MediaPlayerEntity):
|
2018-10-18 08:39:33 +00:00
|
|
|
"""Representation of an LG soundbar device."""
|
|
|
|
|
2022-06-30 17:00:39 +00:00
|
|
|
_attr_should_poll = False
|
2022-04-07 07:34:58 +00:00
|
|
|
_attr_supported_features = (
|
|
|
|
MediaPlayerEntityFeature.VOLUME_SET
|
|
|
|
| MediaPlayerEntityFeature.VOLUME_MUTE
|
|
|
|
| MediaPlayerEntityFeature.SELECT_SOURCE
|
|
|
|
| MediaPlayerEntityFeature.SELECT_SOUND_MODE
|
|
|
|
)
|
|
|
|
|
2022-06-30 17:00:39 +00:00
|
|
|
def __init__(self, host, port, unique_id):
|
2018-10-18 08:39:33 +00:00
|
|
|
"""Initialize the LG speakers."""
|
2022-06-30 17:00:39 +00:00
|
|
|
self._host = host
|
|
|
|
self._port = port
|
|
|
|
self._attr_unique_id = unique_id
|
2018-10-18 08:39:33 +00:00
|
|
|
|
2022-06-30 17:00:39 +00:00
|
|
|
self._name = None
|
2018-10-18 08:39:33 +00:00
|
|
|
self._volume = 0
|
|
|
|
self._volume_min = 0
|
|
|
|
self._volume_max = 0
|
|
|
|
self._function = -1
|
|
|
|
self._functions = []
|
|
|
|
self._equaliser = -1
|
|
|
|
self._equalisers = []
|
|
|
|
self._mute = 0
|
|
|
|
self._rear_volume = 0
|
|
|
|
self._rear_volume_min = 0
|
|
|
|
self._rear_volume_max = 0
|
|
|
|
self._woofer_volume = 0
|
|
|
|
self._woofer_volume_min = 0
|
|
|
|
self._woofer_volume_max = 0
|
|
|
|
self._bass = 0
|
|
|
|
self._treble = 0
|
2020-07-28 07:55:24 +00:00
|
|
|
self._device = None
|
2018-10-18 08:39:33 +00:00
|
|
|
|
2020-07-28 07:55:24 +00:00
|
|
|
async def async_added_to_hass(self):
|
|
|
|
"""Register the callback after hass is ready for it."""
|
|
|
|
await self.hass.async_add_executor_job(self._connect)
|
|
|
|
|
|
|
|
def _connect(self):
|
|
|
|
"""Perform the actual devices setup."""
|
|
|
|
self._device = temescal.temescal(
|
|
|
|
self._host, port=self._port, callback=self.handle_event
|
|
|
|
)
|
2022-06-30 17:00:39 +00:00
|
|
|
self._device.get_product_info()
|
|
|
|
self._device.get_mac_info()
|
2018-10-18 08:39:33 +00:00
|
|
|
self.update()
|
|
|
|
|
|
|
|
def handle_event(self, response):
|
|
|
|
"""Handle responses from the speakers."""
|
2019-07-31 19:25:30 +00:00
|
|
|
data = response["data"]
|
|
|
|
if response["msg"] == "EQ_VIEW_INFO":
|
|
|
|
if "i_bass" in data:
|
|
|
|
self._bass = data["i_bass"]
|
|
|
|
if "i_treble" in data:
|
|
|
|
self._treble = data["i_treble"]
|
|
|
|
if "ai_eq_list" in data:
|
|
|
|
self._equalisers = data["ai_eq_list"]
|
|
|
|
if "i_curr_eq" in data:
|
|
|
|
self._equaliser = data["i_curr_eq"]
|
|
|
|
elif response["msg"] == "SPK_LIST_VIEW_INFO":
|
|
|
|
if "i_vol" in data:
|
|
|
|
self._volume = data["i_vol"]
|
|
|
|
if "s_user_name" in data:
|
|
|
|
self._name = data["s_user_name"]
|
|
|
|
if "i_vol_min" in data:
|
|
|
|
self._volume_min = data["i_vol_min"]
|
|
|
|
if "i_vol_max" in data:
|
|
|
|
self._volume_max = data["i_vol_max"]
|
|
|
|
if "b_mute" in data:
|
|
|
|
self._mute = data["b_mute"]
|
|
|
|
if "i_curr_func" in data:
|
|
|
|
self._function = data["i_curr_func"]
|
|
|
|
elif response["msg"] == "FUNC_VIEW_INFO":
|
|
|
|
if "i_curr_func" in data:
|
|
|
|
self._function = data["i_curr_func"]
|
|
|
|
if "ai_func_list" in data:
|
|
|
|
self._functions = data["ai_func_list"]
|
|
|
|
elif response["msg"] == "SETTING_VIEW_INFO":
|
|
|
|
if "i_rear_min" in data:
|
|
|
|
self._rear_volume_min = data["i_rear_min"]
|
|
|
|
if "i_rear_max" in data:
|
|
|
|
self._rear_volume_max = data["i_rear_max"]
|
|
|
|
if "i_rear_level" in data:
|
|
|
|
self._rear_volume = data["i_rear_level"]
|
|
|
|
if "i_woofer_min" in data:
|
|
|
|
self._woofer_volume_min = data["i_woofer_min"]
|
|
|
|
if "i_woofer_max" in data:
|
|
|
|
self._woofer_volume_max = data["i_woofer_max"]
|
|
|
|
if "i_woofer_level" in data:
|
|
|
|
self._woofer_volume = data["i_woofer_level"]
|
|
|
|
if "i_curr_eq" in data:
|
|
|
|
self._equaliser = data["i_curr_eq"]
|
|
|
|
if "s_user_name" in data:
|
2022-06-30 17:00:39 +00:00
|
|
|
self._attr_name = data["s_user_name"]
|
|
|
|
|
2018-10-18 08:39:33 +00:00
|
|
|
self.schedule_update_ha_state()
|
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Trigger updates from the device."""
|
|
|
|
self._device.get_eq()
|
|
|
|
self._device.get_info()
|
|
|
|
self._device.get_func()
|
|
|
|
self._device.get_settings()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def volume_level(self):
|
|
|
|
"""Volume level of the media player (0..1)."""
|
|
|
|
if self._volume_max != 0:
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._volume / self._volume_max
|
2018-10-18 08:39:33 +00:00
|
|
|
return 0
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_volume_muted(self):
|
|
|
|
"""Boolean if volume is currently muted."""
|
|
|
|
return self._mute
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the state of the device."""
|
|
|
|
return STATE_ON
|
|
|
|
|
|
|
|
@property
|
|
|
|
def sound_mode(self):
|
|
|
|
"""Return the current sound mode."""
|
2020-05-25 20:07:58 +00:00
|
|
|
if self._equaliser == -1 or self._equaliser >= len(temescal.equalisers):
|
|
|
|
return None
|
2018-10-18 08:39:33 +00:00
|
|
|
return temescal.equalisers[self._equaliser]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def sound_mode_list(self):
|
|
|
|
"""Return the available sound modes."""
|
|
|
|
modes = []
|
|
|
|
for equaliser in self._equalisers:
|
2021-03-18 13:06:17 +00:00
|
|
|
if equaliser < len(temescal.equalisers):
|
|
|
|
modes.append(temescal.equalisers[equaliser])
|
2018-10-18 08:39:33 +00:00
|
|
|
return sorted(modes)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def source(self):
|
|
|
|
"""Return the current input source."""
|
2021-01-27 09:17:04 +00:00
|
|
|
if self._function == -1 or self._function >= len(temescal.functions):
|
2020-05-25 20:07:58 +00:00
|
|
|
return None
|
2018-10-18 08:39:33 +00:00
|
|
|
return temescal.functions[self._function]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def source_list(self):
|
|
|
|
"""List of available input sources."""
|
|
|
|
sources = []
|
|
|
|
for function in self._functions:
|
2021-03-18 13:06:17 +00:00
|
|
|
if function < len(temescal.functions):
|
|
|
|
sources.append(temescal.functions[function])
|
2018-10-18 08:39:33 +00:00
|
|
|
return sorted(sources)
|
|
|
|
|
|
|
|
def set_volume_level(self, volume):
|
|
|
|
"""Set volume level, range 0..1."""
|
|
|
|
volume = volume * self._volume_max
|
|
|
|
self._device.set_volume(int(volume))
|
|
|
|
|
|
|
|
def mute_volume(self, mute):
|
|
|
|
"""Mute (true) or unmute (false) media player."""
|
|
|
|
self._device.set_mute(mute)
|
|
|
|
|
|
|
|
def select_source(self, source):
|
|
|
|
"""Select input source."""
|
|
|
|
self._device.set_func(temescal.functions.index(source))
|
|
|
|
|
|
|
|
def select_sound_mode(self, sound_mode):
|
|
|
|
"""Set Sound Mode for Receiver.."""
|
|
|
|
self._device.set_eq(temescal.equalisers.index(sound_mode))
|