Add Ombi integration (#26755)
* Add Ombi integration * Black * Remove trailing comma * Change dict.get to dict[key] for known keys * Remove monitored conditions from config * Define SCAN_INTERVAL for default scan interval * Adjust requests syntax and add music_requests * Remove Ombi object initialization * Move constants to const.py * Fix imports * Set pyombi requirement to version 0.1.3 * Add services.yaml * Add config schema and setup for integration * Set pyombi requirement to version 0.1.3 * Fix syntax for scan interval * Fix datetime import * Add all files from ombi component * Move imports around * Move imports around * Move pyombi import to top of module * Move scan_interval to sensor module * Add custom validator for urlbase * Add guard clause for discovery_info * Add service validation schemas and constants * Bump pyombi version * Adjust urlbase validation * Add exception warnings for irretrievable media * Bump pyombi * Change from .get to dict[key] * Change schema and conf variable names * Set return to return false * Remove unneeded returnpull/26840/head
parent
5914475fe5
commit
60f0988435
|
@ -447,6 +447,7 @@ omit =
|
|||
homeassistant/components/oem/climate.py
|
||||
homeassistant/components/oasa_telematics/sensor.py
|
||||
homeassistant/components/ohmconnect/sensor.py
|
||||
homeassistant/components/ombi/*
|
||||
homeassistant/components/onewire/sensor.py
|
||||
homeassistant/components/onkyo/media_player.py
|
||||
homeassistant/components/onvif/camera.py
|
||||
|
|
|
@ -198,6 +198,7 @@ homeassistant/components/nws/* @MatthewFlamm
|
|||
homeassistant/components/nzbget/* @chriscla
|
||||
homeassistant/components/obihai/* @dshokouhi
|
||||
homeassistant/components/ohmconnect/* @robbiet480
|
||||
homeassistant/components/ombi/* @larssont
|
||||
homeassistant/components/onboarding/* @home-assistant/core
|
||||
homeassistant/components/opentherm_gw/* @mvn23
|
||||
homeassistant/components/openuv/* @bachya
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
"""Support for Ombi."""
|
||||
import logging
|
||||
|
||||
import pyombi
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY,
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_SSL,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from .const import (
|
||||
ATTR_NAME,
|
||||
ATTR_SEASON,
|
||||
CONF_URLBASE,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_SEASON,
|
||||
DEFAULT_SSL,
|
||||
DEFAULT_URLBASE,
|
||||
DOMAIN,
|
||||
SERVICE_MOVIE_REQUEST,
|
||||
SERVICE_MUSIC_REQUEST,
|
||||
SERVICE_TV_REQUEST,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def urlbase(value) -> str:
|
||||
"""Validate and transform urlbase."""
|
||||
if value is None:
|
||||
raise vol.Invalid("string value is None")
|
||||
value = str(value).strip("/")
|
||||
if not value:
|
||||
return value
|
||||
return value + "/"
|
||||
|
||||
|
||||
SUBMIT_MOVIE_REQUEST_SERVICE_SCHEMA = vol.Schema({vol.Required(ATTR_NAME): cv.string})
|
||||
|
||||
SUBMIT_MUSIC_REQUEST_SERVICE_SCHEMA = vol.Schema({vol.Required(ATTR_NAME): cv.string})
|
||||
|
||||
SUBMIT_TV_REQUEST_SERVICE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_NAME): cv.string,
|
||||
vol.Optional(ATTR_SEASON, default=DEFAULT_SEASON): vol.In(
|
||||
["first", "latest", "all"]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||
vol.Optional(CONF_URLBASE, default=DEFAULT_URLBASE): urlbase,
|
||||
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up the Ombi component platform."""
|
||||
|
||||
ombi = pyombi.Ombi(
|
||||
ssl=config[DOMAIN][CONF_SSL],
|
||||
host=config[DOMAIN][CONF_HOST],
|
||||
port=config[DOMAIN][CONF_PORT],
|
||||
api_key=config[DOMAIN][CONF_API_KEY],
|
||||
username=config[DOMAIN][CONF_USERNAME],
|
||||
urlbase=config[DOMAIN][CONF_URLBASE],
|
||||
)
|
||||
|
||||
try:
|
||||
ombi.test_connection()
|
||||
except pyombi.OmbiError as err:
|
||||
_LOGGER.warning("Unable to setup Ombi: %s", err)
|
||||
return False
|
||||
|
||||
hass.data[DOMAIN] = {"instance": ombi}
|
||||
|
||||
def submit_movie_request(call):
|
||||
"""Submit request for movie."""
|
||||
name = call.data[ATTR_NAME]
|
||||
movies = ombi.search_movie(name)
|
||||
if movies:
|
||||
movie = movies[0]
|
||||
ombi.request_movie(movie["theMovieDbId"])
|
||||
else:
|
||||
raise Warning("No movie found.")
|
||||
|
||||
def submit_tv_request(call):
|
||||
"""Submit request for TV show."""
|
||||
name = call.data[ATTR_NAME]
|
||||
tv_shows = ombi.search_tv(name)
|
||||
|
||||
if tv_shows:
|
||||
season = call.data[ATTR_SEASON]
|
||||
show = tv_shows[0]["id"]
|
||||
if season == "first":
|
||||
ombi.request_tv(show, request_first=True)
|
||||
elif season == "latest":
|
||||
ombi.request_tv(show, request_latest=True)
|
||||
elif season == "all":
|
||||
ombi.request_tv(show, request_all=True)
|
||||
else:
|
||||
raise Warning("No TV show found.")
|
||||
|
||||
def submit_music_request(call):
|
||||
"""Submit request for music album."""
|
||||
name = call.data[ATTR_NAME]
|
||||
music = ombi.search_music_album(name)
|
||||
if music:
|
||||
ombi.request_music(music[0]["foreignAlbumId"])
|
||||
else:
|
||||
raise Warning("No music album found.")
|
||||
|
||||
hass.services.register(
|
||||
DOMAIN,
|
||||
SERVICE_MOVIE_REQUEST,
|
||||
submit_movie_request,
|
||||
schema=SUBMIT_MOVIE_REQUEST_SERVICE_SCHEMA,
|
||||
)
|
||||
hass.services.register(
|
||||
DOMAIN,
|
||||
SERVICE_MUSIC_REQUEST,
|
||||
submit_music_request,
|
||||
schema=SUBMIT_MUSIC_REQUEST_SERVICE_SCHEMA,
|
||||
)
|
||||
hass.services.register(
|
||||
DOMAIN,
|
||||
SERVICE_TV_REQUEST,
|
||||
submit_tv_request,
|
||||
schema=SUBMIT_TV_REQUEST_SERVICE_SCHEMA,
|
||||
)
|
||||
hass.helpers.discovery.load_platform("sensor", DOMAIN, {}, config)
|
||||
|
||||
return True
|
|
@ -0,0 +1,24 @@
|
|||
"""Support for Ombi."""
|
||||
ATTR_NAME = "name"
|
||||
ATTR_SEASON = "season"
|
||||
|
||||
CONF_URLBASE = "urlbase"
|
||||
|
||||
DEFAULT_NAME = DOMAIN = "ombi"
|
||||
DEFAULT_PORT = 5000
|
||||
DEFAULT_SEASON = "latest"
|
||||
DEFAULT_SSL = False
|
||||
DEFAULT_URLBASE = ""
|
||||
|
||||
SERVICE_MOVIE_REQUEST = "submit_movie_request"
|
||||
SERVICE_MUSIC_REQUEST = "submit_music_request"
|
||||
SERVICE_TV_REQUEST = "submit_tv_request"
|
||||
|
||||
SENSOR_TYPES = {
|
||||
"movies": {"type": "Movie requests", "icon": "mdi:movie"},
|
||||
"tv": {"type": "TV show requests", "icon": "mdi:television-classic"},
|
||||
"music": {"type": "Music album requests", "icon": "mdi:album"},
|
||||
"pending": {"type": "Pending requests", "icon": "mdi:clock-alert-outline"},
|
||||
"approved": {"type": "Approved requests", "icon": "mdi:check"},
|
||||
"available": {"type": "Available requests", "icon": "mdi:download"},
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"domain": "ombi",
|
||||
"name": "Ombi",
|
||||
"documentation": "https://www.home-assistant.io/components/ombi/",
|
||||
"dependencies": [],
|
||||
"codeowners": ["@larssont"],
|
||||
"requirements": ["pyombi==0.1.5"]
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
"""Support for Ombi."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from pyombi import OmbiError
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import DOMAIN, SENSOR_TYPES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=60)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up the Ombi sensor platform."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
sensors = []
|
||||
|
||||
ombi = hass.data[DOMAIN]["instance"]
|
||||
|
||||
for sensor in SENSOR_TYPES:
|
||||
sensor_label = sensor
|
||||
sensor_type = SENSOR_TYPES[sensor]["type"]
|
||||
sensor_icon = SENSOR_TYPES[sensor]["icon"]
|
||||
sensors.append(OmbiSensor(sensor_label, sensor_type, ombi, sensor_icon))
|
||||
|
||||
add_entities(sensors, True)
|
||||
|
||||
|
||||
class OmbiSensor(Entity):
|
||||
"""Representation of an Ombi sensor."""
|
||||
|
||||
def __init__(self, label, sensor_type, ombi, icon):
|
||||
"""Initialize the sensor."""
|
||||
self._state = None
|
||||
self._label = label
|
||||
self._type = sensor_type
|
||||
self._ombi = ombi
|
||||
self._icon = icon
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return f"Ombi {self._type}"
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon to use in the frontend."""
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
def update(self):
|
||||
"""Update the sensor."""
|
||||
try:
|
||||
if self._label == "movies":
|
||||
self._state = self._ombi.movie_requests
|
||||
elif self._label == "tv":
|
||||
self._state = self._ombi.tv_requests
|
||||
elif self._label == "music":
|
||||
self._state = self._ombi.music_requests
|
||||
elif self._label == "pending":
|
||||
self._state = self._ombi.total_requests["pending"]
|
||||
elif self._label == "approved":
|
||||
self._state = self._ombi.total_requests["approved"]
|
||||
elif self._label == "available":
|
||||
self._state = self._ombi.total_requests["available"]
|
||||
except OmbiError as err:
|
||||
_LOGGER.warning("Unable to update Ombi sensor: %s", err)
|
||||
self._state = None
|
|
@ -0,0 +1,27 @@
|
|||
# Ombi services.yaml entries
|
||||
|
||||
submit_movie_request:
|
||||
description: Searches for a movie and requests the first result.
|
||||
fields:
|
||||
name:
|
||||
description: Search parameter
|
||||
example: "beverly hills cop"
|
||||
|
||||
|
||||
submit_tv_request:
|
||||
description: Searches for a TV show and requests the first result.
|
||||
fields:
|
||||
name:
|
||||
description: Search parameter
|
||||
example: "breaking bad"
|
||||
season:
|
||||
description: Which season(s) to request (first, latest or all)
|
||||
example: "latest"
|
||||
|
||||
|
||||
submit_music_request:
|
||||
description: Searches for a music album and requests the first result.
|
||||
fields:
|
||||
name:
|
||||
description: Search parameter
|
||||
example: "nevermind"
|
|
@ -1353,6 +1353,9 @@ pynzbgetapi==0.2.0
|
|||
# homeassistant.components.obihai
|
||||
pyobihai==1.1.0
|
||||
|
||||
# homeassistant.components.ombi
|
||||
pyombi==0.1.5
|
||||
|
||||
# homeassistant.components.openuv
|
||||
pyopenuv==1.0.9
|
||||
|
||||
|
|
Loading…
Reference in New Issue