Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
add configuration manually
Browse files Browse the repository at this point in the history
  • Loading branch information
georgezhao2010 authored Jul 11, 2021
1 parent 09a47db commit f19318c
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 29 deletions.
18 changes: 13 additions & 5 deletions custom_components/apple_airplayer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
from .const import DOMAIN, DEVICES
from homeassistant.core import HomeAssistant
from homeassistant.const import CONF_DEVICE
from homeassistant.const import CONF_DEVICE, CONF_ADDRESS

async def async_setup(hass: HomeAssistant, hass_config: dict):
hass.data.setdefault(DOMAIN, {})
return True


async def async_setup_entry(hass: HomeAssistant, config_entry):
identifier = config_entry.data[CONF_DEVICE]
identifier = config_entry.data.get(CONF_DEVICE)
address = config_entry.data.get(CONF_ADDRESS)
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {}
if DEVICES not in hass.data[DOMAIN]:
hass.data[DOMAIN][DEVICES] = []
hass.data[DOMAIN][DEVICES].append(identifier)
if identifier is not None:
hass.data[DOMAIN][DEVICES].append(identifier)
elif address is not None:
hass.data[DOMAIN][DEVICES].append(address)
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
config_entry, "media_player"))
return True


async def async_unload_entry(hass: HomeAssistant, config_entry):
identifier = config_entry.data[CONF_DEVICE]
hass.data[DOMAIN][DEVICES].remove(identifier)
identifier = config_entry.data(CONF_DEVICE)
address = config_entry.data.get(CONF_ADDRESS)
if identifier is not None:
hass.data[DOMAIN][DEVICES].remove(identifier)
elif address is not None:
hass.data[DOMAIN][DEVICES].remove(address)
await hass.config_entries.async_forward_entry_unload(config_entry, "media_player")
return True
28 changes: 26 additions & 2 deletions custom_components/apple_airplayer/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from .const import DOMAIN, DEVICES, CONF_CACHE_DIR
from homeassistant import config_entries
from homeassistant.const import CONF_DEVICE
from homeassistant.const import CONF_DEVICE, CONF_ADDRESS
from .device_manager import DeviceManager
import voluptuous as vol

Expand All @@ -26,7 +26,7 @@ async def async_step_user(self, user_input=None, error=None):
if len(self.available_device) > 0:
return await self.async_step_devinfo()
else:
return await self.async_step_user(error="no_devices")
return await self.async_step_manually()
_LOGGER.debug(user_input, error)
return self.async_show_form(
step_id="user",
Expand All @@ -47,3 +47,27 @@ async def async_step_devinfo(self, user_input=None, error=None):
}),
errors={"base": error} if error else None
)

async def async_step_manually(self, user_input=None, error=None):
if user_input is not None:
man = DeviceManager(self.hass.loop)
device = await man.async_get_device_by_address(user_input[CONF_ADDRESS])
if device is not None:
identifier = device.identifier
if identifier in self.hass.data[DOMAIN][DEVICES] or \
user_input[CONF_ADDRESS] in self.hass.data[DOMAIN][DEVICES]:
return await self.async_step_manually(error="device_exist")
return self.async_create_entry(
title=f"{device.name}",
data=user_input)
else:
return await self.async_step_manually(error="no_devices")

return self.async_show_form(
step_id="manually",
data_schema=vol.Schema({
vol.Required(CONF_ADDRESS): str,
vol.Required(CONF_CACHE_DIR, default="/tmp/tts"): str
}),
errors={"base": error} if error else None
)
35 changes: 21 additions & 14 deletions custom_components/apple_airplayer/device_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pyatv
import logging
from homeassistant.const import STATE_ON, STATE_OFF
from pyatv.const import DeviceModel, FeatureName, FeatureState, DeviceState
from pyatv.const import DeviceModel, FeatureName, FeatureState

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -69,13 +69,6 @@ def volume_level(self):
else:
return 0.5

async def async_set_volume_level(self, volume):
if self._atv_interface is not None and 0 <= volume <= 1:
try:
await self._atv_interface.audio.set_volume(volume * 100)
except Exception as e:
_LOGGER.debug(f"Exception raised in async_set_volume_level, {e}")

async def async_open(self):
if self._atv_interface is None:
try:
Expand All @@ -87,33 +80,36 @@ async def async_open(self):
elif k == FeatureName.StreamFile and f.state == FeatureState.Available:
self._support_stream_file = True
except Exception as e:
_LOGGER.debug(f"Exception raised in async_open, {e}")
_LOGGER.error(f"Exception raised in async_open, {e}")

async def async_close(self):
if self._atv_interface is not None:
try:
self._atv_interface.close()
self._atv_interface = None
except Exception as e:
_LOGGER.debug(f"Exception raised in async_close, {e}")
_LOGGER.error(f"Exception raised in async_close, {e}")

async def async_play_url(self, url):
if self._atv_interface is not None:
try:
await self._atv_interface.stream.play_url(url)
except Exception as e:
_LOGGER.debug(f"Exception raised in async_play_url, {e}")
_LOGGER.error(f"Exception raised in async_play_url, {e}")

async def async_stream_file(self, filename):
if self._atv_interface is not None:
try:
await self._atv_interface.stream.stream_file(filename)
except Exception as e:
_LOGGER.debug(f"Exception raised in async_stream_file, {e}")
_LOGGER.error(f"Exception raised in async_stream_file, {e}")

async def async_set_volume(self, volume):
if self._atv_interface is not None:
await self._atv_interface.audio.set_volume(volume * 100)
try:
await self._atv_interface.audio.set_volume(volume * 100)
except Exception as e:
_LOGGER.error(f"Exception raised in async_set_volume, {e}")


class DeviceManager:
Expand All @@ -131,9 +127,20 @@ async def async_get_all_devices(self):
await device.async_close()
return devices

async def async_get_device(self, identifier):
async def async_get_device_by_identifier(self, identifier):
atvs = await pyatv.scan(self._event_loop)
for atv in atvs:
if atv.identifier.replace(":", "").lower() == identifier.lower():
return AirPlayDevice(atv, self._event_loop)
return None

async def async_get_device_by_address(self, address):
atvs = await pyatv.scan(self._event_loop, hosts=[address])
if len(atvs) > 0:
atv = atvs[0]
device = AirPlayDevice(atv, self._event_loop)
await device.async_open()
await device.async_close()
if device.support_play_url or device.support_stream_file:
return device
return None
2 changes: 1 addition & 1 deletion custom_components/apple_airplayer/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "apple_airplayer",
"name": "Apple AirPlayer",
"version": "v0.0.3",
"version": "v0.0.4",
"config_flow": true,
"documentation": "https://github.com/georgezhao2010/apple_airplayer",
"issue_tracker": "https://github.com/georgezhao2010/apple_airplayer/issue",
Expand Down
16 changes: 11 additions & 5 deletions custom_components/apple_airplayer/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@
)
from .device_manager import DeviceManager, AirPlayDevice
from .const import DOMAIN, CONF_CACHE_DIR
from homeassistant.const import CONF_DEVICE
from homeassistant.const import CONF_DEVICE, CONF_ADDRESS

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config_entry, async_add_entities):
identifier = config_entry.data[CONF_DEVICE]
identifier = config_entry.data.get(CONF_DEVICE)
address = config_entry.data.get(CONF_ADDRESS)
cache_dir = config_entry.data[CONF_CACHE_DIR]
man = DeviceManager(hass.loop)
device = await man.async_get_device(identifier)
await device.async_open()
async_add_entities([AirPlayer(device, cache_dir)])
device = None
if identifier is not None:
device = await man.async_get_device_by_identifier(identifier)
elif address is not None:
device = await man.async_get_device_by_address(address)
if device is not None:
await device.async_open()
async_add_entities([AirPlayer(device, cache_dir)])


class AirPlayer(MediaPlayerEntity):
Expand Down
11 changes: 10 additions & 1 deletion custom_components/apple_airplayer/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"config": {
"error": {
"no_devices": "No available devices found on the network"
"no_devices": "No available devices found on the network",
"device_exist": "Device already configured, choice another one"
},
"step": {
"user": {
Expand All @@ -15,6 +16,14 @@
},
"description": "Choice a device to add",
"title": "New device found"
},
"manually": {
"data": {
"Address": "address",
"cache_dir": "Cache dir"
},
"description": "Enter the IP address of the AirPlay device you want to add",
"title": "No device found"
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion custom_components/apple_airplayer/translations/zh-Hans.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"config": {
"error": {
"no_devices": "未在网络上发现可用的AirPlay设备"
"no_devices": "未在网络上发现可用的AirPlay设备",
"device_exist": "设备已经存在,请添加其它设备"
},
"step": {
"user": {
Expand All @@ -15,6 +16,14 @@
},
"description": "选择一个设备并添加",
"title": "发现新设备"
},
"manually": {
"data": {
"Address": "地址",
"cache_dir": "缓存目录"
},
"description": "输入你想要添加的设备的IP地址",
"title": "没有自动发现设备"
}
}
}
Expand Down

0 comments on commit f19318c

Please sign in to comment.