From b82df43ae9d1ce8f0946ea9d87c5bd0b83f1aca2 Mon Sep 17 00:00:00 2001 From: e2002 Date: Fri, 4 Mar 2022 14:56:08 +0300 Subject: [PATCH] home assistant --- HA/custom_components/yoradio/__init__.py | 0 HA/custom_components/yoradio/manifest.json | 9 + HA/custom_components/yoradio/media_player.py | 216 +++++++++++++++++++ HA/exsample_configuration.yaml | 18 ++ README.md | 12 ++ images/ha.jpg | Bin 0 -> 31896 bytes 6 files changed, 255 insertions(+) create mode 100644 HA/custom_components/yoradio/__init__.py create mode 100644 HA/custom_components/yoradio/manifest.json create mode 100644 HA/custom_components/yoradio/media_player.py create mode 100644 HA/exsample_configuration.yaml create mode 100644 images/ha.jpg diff --git a/HA/custom_components/yoradio/__init__.py b/HA/custom_components/yoradio/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HA/custom_components/yoradio/manifest.json b/HA/custom_components/yoradio/manifest.json new file mode 100644 index 0000000..8530a54 --- /dev/null +++ b/HA/custom_components/yoradio/manifest.json @@ -0,0 +1,9 @@ +{ + "domain": "yoradio", + "name": "ёRadio", + "documentation": "https://github.com/e2002/yoradio", + "dependencies": ["http", "mqtt"], + "codeowners": ["@e2002"], + "requirements": [], + "version": "0.4.322" + } diff --git a/HA/custom_components/yoradio/media_player.py b/HA/custom_components/yoradio/media_player.py new file mode 100644 index 0000000..338ee44 --- /dev/null +++ b/HA/custom_components/yoradio/media_player.py @@ -0,0 +1,216 @@ +import aiohttp +import asyncio +import logging +import voluptuous as vol +import json + +from homeassistant.helpers.aiohttp_client import async_get_clientsession + +_LOGGER = logging.getLogger(__name__) + +VERSION = '0.4.322' + +DOMAIN = "yoradio" + +from homeassistant.helpers import config_validation as cv + +from homeassistant.components.media_player import ( + MediaPlayerEntity, + PLATFORM_SCHEMA +) + +from homeassistant.components.media_player.const import ( + MEDIA_TYPE_MUSIC, + SUPPORT_TURN_ON, SUPPORT_TURN_OFF, + SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_SET, + SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_STOP, + SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, + SUPPORT_SELECT_SOURCE +) + +from homeassistant.const import ( + CONF_NAME, + STATE_IDLE, + STATE_PLAYING, + STATE_OFF +) + +SUPPORT_YORADIO = SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_STOP |\ + SUPPORT_VOLUME_SET | SUPPORT_VOLUME_STEP | \ + SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \ + SUPPORT_SELECT_SOURCE + +DEFAULT_NAME = 'yoRadio' +CONF_MAX_VOLUME = 'max_volume' +CONF_ROOT_TOPIC = 'root_topic' +YORADIO_SOURCE_TYPE = [] + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_ROOT_TOPIC, default="yoradio"): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_MAX_VOLUME, default='254'): cv.string +}) + +def setup_platform(hass, config, add_devices, discovery_info=None): + root_topic = config.get(CONF_ROOT_TOPIC) + name = config.get(CONF_NAME) + max_volume = int(config.get(CONF_MAX_VOLUME)) + session = async_get_clientsession(hass) + api = yoradioApi(root_topic, session, hass) + add_devices([yoradioDevice(name, max_volume, api)], True) + +class yoradioApi(): + def __init__(self, root_topic, session, hass): + self.session = session + self.hass = hass + self.mqtt = hass.components.mqtt + self.root_topic = root_topic + + async def set_command(self, command): + self.mqtt.async_publish(self.root_topic + '/command', command) + + async def set_volume(self, volume): + command = "vol " + str(volume) + self.mqtt.async_publish(self.root_topic + '/command', command) + + async def set_source(self, source): + number = source.split('.') + command = "play " + number[0] + self.mqtt.async_publish(self.root_topic + '/command', command) + + async def load_playlist(self, msg): + try: + async with aiohttp.ClientSession() as session: + async with session.get(msg.payload) as resp: + file = await resp.text() + except aiohttp.ClientConnectorError as e: + _LOGGER.error('Error downloading ' + msg.payload) + else: + file = file.split('\n') + counter = 1 + for line in file: + res = line.split('\t') + station = str(counter) + '. ' + res[0] + YORADIO_SOURCE_TYPE.append(station) + counter=counter+1 + +class yoradioDevice(MediaPlayerEntity): + def __init__(self, name, max_volume, api): + self._name = name + self.api = api + self._state = STATE_OFF + self._current_source = None + self._media_title = '' + self._track_artist = '' + self._track_album_name = '' + self._volume = 0 + self._muted = False + self._max_volume = max_volume + self.api.mqtt.subscribe(self.api.root_topic+'/status', self.status_listener, 0, "utf-8") + self.api.mqtt.subscribe(self.api.root_topic+'/playlist', self.playlist_listener, 0, "utf-8") + self.api.mqtt.subscribe(self.api.root_topic+'/volume', self.volume_listener, 0, "utf-8") + + async def status_listener(self, msg): + js = json.loads(msg.payload) + self._media_title = js['title'] + self._track_artist = js['name'] + self._state = STATE_PLAYING if js['status']==1 else STATE_IDLE + self._current_source = str(js['station']) + '. ' + js['name'] + try: + self.async_schedule_update_ha_state() + except: + pass + + async def playlist_listener(self, msg): + await self.api.load_playlist(msg) + try: + self.async_schedule_update_ha_state() + except: + pass + + async def volume_listener(self, msg): + self._volume = int(msg.payload) / self._max_volume + try: + self.async_schedule_update_ha_state() + except: + pass + + @property + def supported_features(self): + return SUPPORT_YORADIO + + @property + def name(self): + return self._name + + @property + def media_title(self): + return self._media_title + + @property + def media_artist(self): + return self._track_artist + + @property + def media_album_name(self): + return self._track_album_name + + @property + def state(self): + return self._state + + @property + def volume_level(self): + return self._volume + + async def async_set_volume_level(self, volume): + await self.api.set_volume(round(volume * self._max_volume,1)) + + @property + def source(self): + return self._current_source + + @property + def source_list(self): + return YORADIO_SOURCE_TYPE + + async def async_select_source(self, source): + await self.api.set_source(source) + self._current_source = source + + async def async_volume_up(self): + newVol = float(self._volume) + 0.05 + await self.async_set_volume_level(newVol) + self._volume = newVol + + async def async_volume_down(self): + newVol = float(self._volume) - 0.05 + await self.async_set_volume_level(newVol) + self._volume = newVol + + async def async_media_next_track(self): + await self.api.set_command("next") + + async def async_media_previous_track(self): + await self.api.set_command("prev") + + async def async_turn_off(self): + await self.api.set_command("stop") + self._state = STATE_IDLE + + async def async_media_stop(self): + await self.api.set_command("stop") + self._state = STATE_IDLE + + async def async_turn_on(self): + await self.api.set_command("start") + self._state = STATE_PLAYING + + async def async_media_play(self): + await self.api.set_command("start") + self._state = STATE_PLAYING + + async def async_media_pause(self): + await self.api.set_command("stop") + self._state = STATE_IDLE + diff --git a/HA/exsample_configuration.yaml b/HA/exsample_configuration.yaml new file mode 100644 index 0000000..4c7e1e7 --- /dev/null +++ b/HA/exsample_configuration.yaml @@ -0,0 +1,18 @@ + +# Configure a default setup of Home Assistant (frontend, api, etc) +default_config: + +# Text to speech +tts: + - platform: google_translate + +group: !include groups.yaml +automation: !include automations.yaml +script: !include scripts.yaml +scene: !include scenes.yaml + +# yoRadio entity +media_player: + - platform: yoradio + name: YoRadio (kitchen) + root_topic: yoradio/100 diff --git a/README.md b/README.md index 1c0e773..b694074 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - [Quick start](#quick-start) - [Update](#update) - [MQTT](#mqtt) +- [Home Assistant](#home-assistant) - [More features](#more-features) - [Version history](#version-history) --- @@ -180,6 +181,17 @@ download _http://\/data/playlist.csv_ and _http://\/data 2. In the mqttoptions.h file, change the options to the ones you need 3. Well done! +--- +## Home Assistant +
+ +0. Requires [MQTT integration](https://www.home-assistant.io/integrations/mqtt/) +1. Copy directory HA/custom_components/yoradio to .homeassistant/custom_components/ +2. Add yoRadio entity into .homeassistant/configuration.yaml ([see exsample](HA/exsample_configuration.yaml)) +3. Restart Home Assistant +4. Add Lovelace Media Player card to UI (or [mini-media-player](https://github.com/kalkih/mini-media-player) card) +5. Well done! + --- ## More features - Сan add up to 65535 stations to a playlist. Supports and imports [KaRadio](https://github.com/karawin/Ka-Radio32) playlists (WebStations.txt) diff --git a/images/ha.jpg b/images/ha.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a1125d2dd8ec1296cb45c301a416e2d2221e1586 GIT binary patch literal 31896 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