Improve config schema of the blackbird component (#14007)
* Import moved, return values removed and redundant log message removed * Improve config schema of the blackbird component * Tests updated * Handle updated * Schema fixedpull/14173/merge
parent
e968b1a0f4
commit
8b13658d3b
|
@ -5,6 +5,7 @@ For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/media_player.blackbird
|
https://home-assistant.io/components/media_player.blackbird
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
import socket
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
@ -50,71 +51,68 @@ ZONE_IDS = vol.All(vol.Coerce(int), vol.Range(min=1, max=8))
|
||||||
# Valid source ids: 1-8
|
# Valid source ids: 1-8
|
||||||
SOURCE_IDS = vol.All(vol.Coerce(int), vol.Range(min=1, max=8))
|
SOURCE_IDS = vol.All(vol.Coerce(int), vol.Range(min=1, max=8))
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = vol.All(
|
||||||
vol.Required(CONF_TYPE): vol.In(['serial', 'socket']),
|
cv.has_at_least_one_key(CONF_PORT, CONF_HOST),
|
||||||
vol.Optional(CONF_PORT): cv.string,
|
PLATFORM_SCHEMA.extend({
|
||||||
vol.Optional(CONF_HOST): cv.string,
|
vol.Exclusive(CONF_PORT, CONF_TYPE): cv.string,
|
||||||
|
vol.Exclusive(CONF_HOST, CONF_TYPE): cv.string,
|
||||||
vol.Required(CONF_ZONES): vol.Schema({ZONE_IDS: ZONE_SCHEMA}),
|
vol.Required(CONF_ZONES): vol.Schema({ZONE_IDS: ZONE_SCHEMA}),
|
||||||
vol.Required(CONF_SOURCES): vol.Schema({SOURCE_IDS: SOURCE_SCHEMA}),
|
vol.Required(CONF_SOURCES): vol.Schema({SOURCE_IDS: SOURCE_SCHEMA}),
|
||||||
})
|
}))
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Set up the Monoprice Blackbird 4k 8x8 HDBaseT Matrix platform."""
|
"""Set up the Monoprice Blackbird 4k 8x8 HDBaseT Matrix platform."""
|
||||||
|
if DATA_BLACKBIRD not in hass.data:
|
||||||
|
hass.data[DATA_BLACKBIRD] = {}
|
||||||
|
|
||||||
port = config.get(CONF_PORT)
|
port = config.get(CONF_PORT)
|
||||||
host = config.get(CONF_HOST)
|
host = config.get(CONF_HOST)
|
||||||
device_type = config.get(CONF_TYPE)
|
|
||||||
|
|
||||||
import socket
|
|
||||||
from pyblackbird import get_blackbird
|
from pyblackbird import get_blackbird
|
||||||
from serial import SerialException
|
from serial import SerialException
|
||||||
|
|
||||||
if device_type == 'serial':
|
connection = None
|
||||||
if port is None:
|
if port is not None:
|
||||||
_LOGGER.error("No port configured")
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
blackbird = get_blackbird(port)
|
blackbird = get_blackbird(port)
|
||||||
|
connection = port
|
||||||
except SerialException:
|
except SerialException:
|
||||||
_LOGGER.error("Error connecting to the Blackbird controller")
|
_LOGGER.error("Error connecting to the Blackbird controller")
|
||||||
return
|
return
|
||||||
|
|
||||||
elif device_type == 'socket':
|
if host is not None:
|
||||||
try:
|
try:
|
||||||
if host is None:
|
|
||||||
_LOGGER.error("No host configured")
|
|
||||||
return
|
|
||||||
blackbird = get_blackbird(host, False)
|
blackbird = get_blackbird(host, False)
|
||||||
|
connection = host
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
_LOGGER.error("Error connecting to the Blackbird controller")
|
_LOGGER.error("Error connecting to the Blackbird controller")
|
||||||
return
|
return
|
||||||
|
|
||||||
else:
|
|
||||||
_LOGGER.error("Incorrect device type specified")
|
|
||||||
return
|
|
||||||
|
|
||||||
sources = {source_id: extra[CONF_NAME] for source_id, extra
|
sources = {source_id: extra[CONF_NAME] for source_id, extra
|
||||||
in config[CONF_SOURCES].items()}
|
in config[CONF_SOURCES].items()}
|
||||||
|
|
||||||
hass.data[DATA_BLACKBIRD] = []
|
devices = []
|
||||||
for zone_id, extra in config[CONF_ZONES].items():
|
for zone_id, extra in config[CONF_ZONES].items():
|
||||||
_LOGGER.info("Adding zone %d - %s", zone_id, extra[CONF_NAME])
|
_LOGGER.info("Adding zone %d - %s", zone_id, extra[CONF_NAME])
|
||||||
hass.data[DATA_BLACKBIRD].append(BlackbirdZone(
|
unique_id = "{}-{}".format(connection, zone_id)
|
||||||
blackbird, sources, zone_id, extra[CONF_NAME]))
|
device = BlackbirdZone(blackbird, sources, zone_id, extra[CONF_NAME])
|
||||||
|
hass.data[DATA_BLACKBIRD][unique_id] = device
|
||||||
|
devices.append(device)
|
||||||
|
|
||||||
add_devices(hass.data[DATA_BLACKBIRD], True)
|
add_devices(devices, True)
|
||||||
|
|
||||||
def service_handle(service):
|
def service_handle(service):
|
||||||
"""Handle for services."""
|
"""Handle for services."""
|
||||||
entity_ids = service.data.get(ATTR_ENTITY_ID)
|
entity_ids = service.data.get(ATTR_ENTITY_ID)
|
||||||
source = service.data.get(ATTR_SOURCE)
|
source = service.data.get(ATTR_SOURCE)
|
||||||
if entity_ids:
|
if entity_ids:
|
||||||
devices = [device for device in hass.data[DATA_BLACKBIRD]
|
devices = [device for device in hass.data[DATA_BLACKBIRD].values()
|
||||||
if device.entity_id in entity_ids]
|
if device.entity_id in entity_ids]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
devices = hass.data[DATA_BLACKBIRD]
|
devices = hass.data[DATA_BLACKBIRD].values()
|
||||||
|
|
||||||
for device in devices:
|
for device in devices:
|
||||||
if service.service == SERVICE_SETALLZONES:
|
if service.service == SERVICE_SETALLZONES:
|
||||||
|
@ -146,14 +144,13 @@ class BlackbirdZone(MediaPlayerDevice):
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
state = self._blackbird.zone_status(self._zone_id)
|
state = self._blackbird.zone_status(self._zone_id)
|
||||||
if not state:
|
if not state:
|
||||||
return False
|
return
|
||||||
self._state = STATE_ON if state.power else STATE_OFF
|
self._state = STATE_ON if state.power else STATE_OFF
|
||||||
idx = state.av
|
idx = state.av
|
||||||
if idx in self._source_id_name:
|
if idx in self._source_id_name:
|
||||||
self._source = self._source_id_name[idx]
|
self._source = self._source_id_name[idx]
|
||||||
else:
|
else:
|
||||||
self._source = None
|
self._source = None
|
||||||
return True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -187,7 +184,6 @@ class BlackbirdZone(MediaPlayerDevice):
|
||||||
|
|
||||||
def set_all_zones(self, source):
|
def set_all_zones(self, source):
|
||||||
"""Set all zones to one source."""
|
"""Set all zones to one source."""
|
||||||
_LOGGER.debug("Setting all zones")
|
|
||||||
if source not in self._source_name_id:
|
if source not in self._source_name_id:
|
||||||
return
|
return
|
||||||
idx = self._source_name_id[source]
|
idx = self._source_name_id[source]
|
||||||
|
|
|
@ -59,7 +59,6 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
"""Test valid schema."""
|
"""Test valid schema."""
|
||||||
valid_schema = {
|
valid_schema = {
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'serial',
|
|
||||||
'port': '/dev/ttyUSB0',
|
'port': '/dev/ttyUSB0',
|
||||||
'zones': {1: {'name': 'a'},
|
'zones': {1: {'name': 'a'},
|
||||||
2: {'name': 'a'},
|
2: {'name': 'a'},
|
||||||
|
@ -87,8 +86,7 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
"""Test valid schema."""
|
"""Test valid schema."""
|
||||||
valid_schema = {
|
valid_schema = {
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'socket',
|
'host': '192.168.1.50',
|
||||||
'port': '192.168.1.50',
|
|
||||||
'zones': {1: {'name': 'a'},
|
'zones': {1: {'name': 'a'},
|
||||||
2: {'name': 'a'},
|
2: {'name': 'a'},
|
||||||
3: {'name': 'a'},
|
3: {'name': 'a'},
|
||||||
|
@ -109,10 +107,18 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
schemas = (
|
schemas = (
|
||||||
{}, # Empty
|
{}, # Empty
|
||||||
None, # None
|
None, # None
|
||||||
# Missing type
|
# Port and host used concurrently
|
||||||
|
{
|
||||||
|
'platform': 'blackbird',
|
||||||
|
'port': '/dev/ttyUSB0',
|
||||||
|
'host': '192.168.1.50',
|
||||||
|
'name': 'Name',
|
||||||
|
'zones': {1: {'name': 'a'}},
|
||||||
|
'sources': {1: {'name': 'b'}},
|
||||||
|
},
|
||||||
|
# Port or host missing
|
||||||
{
|
{
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'port': 'aaa',
|
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'zones': {1: {'name': 'a'}},
|
'zones': {1: {'name': 'a'}},
|
||||||
'sources': {1: {'name': 'b'}},
|
'sources': {1: {'name': 'b'}},
|
||||||
|
@ -120,8 +126,7 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
# Invalid zone number
|
# Invalid zone number
|
||||||
{
|
{
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'serial',
|
'port': '/dev/ttyUSB0',
|
||||||
'port': 'aaa',
|
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'zones': {11: {'name': 'a'}},
|
'zones': {11: {'name': 'a'}},
|
||||||
'sources': {1: {'name': 'b'}},
|
'sources': {1: {'name': 'b'}},
|
||||||
|
@ -129,8 +134,7 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
# Invalid source number
|
# Invalid source number
|
||||||
{
|
{
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'serial',
|
'port': '/dev/ttyUSB0',
|
||||||
'port': 'aaa',
|
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'zones': {1: {'name': 'a'}},
|
'zones': {1: {'name': 'a'}},
|
||||||
'sources': {9: {'name': 'b'}},
|
'sources': {9: {'name': 'b'}},
|
||||||
|
@ -138,8 +142,7 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
# Zone missing name
|
# Zone missing name
|
||||||
{
|
{
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'serial',
|
'port': '/dev/ttyUSB0',
|
||||||
'port': 'aaa',
|
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'zones': {1: {}},
|
'zones': {1: {}},
|
||||||
'sources': {1: {'name': 'b'}},
|
'sources': {1: {'name': 'b'}},
|
||||||
|
@ -147,21 +150,11 @@ class TestBlackbirdSchema(unittest.TestCase):
|
||||||
# Source missing name
|
# Source missing name
|
||||||
{
|
{
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'serial',
|
'port': '/dev/ttyUSB0',
|
||||||
'port': 'aaa',
|
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'zones': {1: {'name': 'a'}},
|
'zones': {1: {'name': 'a'}},
|
||||||
'sources': {1: {}},
|
'sources': {1: {}},
|
||||||
},
|
},
|
||||||
# Invalid type
|
|
||||||
{
|
|
||||||
'platform': 'blackbird',
|
|
||||||
'type': 'aaa',
|
|
||||||
'port': 'aaa',
|
|
||||||
'name': 'Name',
|
|
||||||
'zones': {1: {'name': 'a'}},
|
|
||||||
'sources': {1: {'name': 'b'}},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
for value in schemas:
|
for value in schemas:
|
||||||
with self.assertRaises(vol.MultipleInvalid):
|
with self.assertRaises(vol.MultipleInvalid):
|
||||||
|
@ -181,7 +174,6 @@ class TestBlackbirdMediaPlayer(unittest.TestCase):
|
||||||
new=lambda *a: self.blackbird):
|
new=lambda *a: self.blackbird):
|
||||||
setup_platform(self.hass, {
|
setup_platform(self.hass, {
|
||||||
'platform': 'blackbird',
|
'platform': 'blackbird',
|
||||||
'type': 'serial',
|
|
||||||
'port': '/dev/ttyUSB0',
|
'port': '/dev/ttyUSB0',
|
||||||
'zones': {3: {'name': 'Zone name'}},
|
'zones': {3: {'name': 'Zone name'}},
|
||||||
'sources': {1: {'name': 'one'},
|
'sources': {1: {'name': 'one'},
|
||||||
|
@ -189,7 +181,7 @@ class TestBlackbirdMediaPlayer(unittest.TestCase):
|
||||||
2: {'name': 'two'}},
|
2: {'name': 'two'}},
|
||||||
}, lambda *args, **kwargs: None, {})
|
}, lambda *args, **kwargs: None, {})
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
self.media_player = self.hass.data[DATA_BLACKBIRD][0]
|
self.media_player = self.hass.data[DATA_BLACKBIRD]['/dev/ttyUSB0-3']
|
||||||
self.media_player.hass = self.hass
|
self.media_player.hass = self.hass
|
||||||
self.media_player.entity_id = 'media_player.zone_3'
|
self.media_player.entity_id = 'media_player.zone_3'
|
||||||
|
|
||||||
|
@ -203,7 +195,8 @@ class TestBlackbirdMediaPlayer(unittest.TestCase):
|
||||||
self.assertTrue(self.hass.services.has_service(DOMAIN,
|
self.assertTrue(self.hass.services.has_service(DOMAIN,
|
||||||
SERVICE_SETALLZONES))
|
SERVICE_SETALLZONES))
|
||||||
self.assertEqual(len(self.hass.data[DATA_BLACKBIRD]), 1)
|
self.assertEqual(len(self.hass.data[DATA_BLACKBIRD]), 1)
|
||||||
self.assertEqual(self.hass.data[DATA_BLACKBIRD][0].name, 'Zone name')
|
self.assertEqual(self.hass.data[DATA_BLACKBIRD]['/dev/ttyUSB0-3'].name,
|
||||||
|
'Zone name')
|
||||||
|
|
||||||
def test_setallzones_service_call_with_entity_id(self):
|
def test_setallzones_service_call_with_entity_id(self):
|
||||||
"""Test set all zone source service call with entity id."""
|
"""Test set all zone source service call with entity id."""
|
||||||
|
|
Loading…
Reference in New Issue