mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
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 return
This commit is contained in:
parent
5914475fe5
commit
60f0988435
@ -447,6 +447,7 @@ omit =
|
|||||||
homeassistant/components/oem/climate.py
|
homeassistant/components/oem/climate.py
|
||||||
homeassistant/components/oasa_telematics/sensor.py
|
homeassistant/components/oasa_telematics/sensor.py
|
||||||
homeassistant/components/ohmconnect/sensor.py
|
homeassistant/components/ohmconnect/sensor.py
|
||||||
|
homeassistant/components/ombi/*
|
||||||
homeassistant/components/onewire/sensor.py
|
homeassistant/components/onewire/sensor.py
|
||||||
homeassistant/components/onkyo/media_player.py
|
homeassistant/components/onkyo/media_player.py
|
||||||
homeassistant/components/onvif/camera.py
|
homeassistant/components/onvif/camera.py
|
||||||
|
@ -198,6 +198,7 @@ homeassistant/components/nws/* @MatthewFlamm
|
|||||||
homeassistant/components/nzbget/* @chriscla
|
homeassistant/components/nzbget/* @chriscla
|
||||||
homeassistant/components/obihai/* @dshokouhi
|
homeassistant/components/obihai/* @dshokouhi
|
||||||
homeassistant/components/ohmconnect/* @robbiet480
|
homeassistant/components/ohmconnect/* @robbiet480
|
||||||
|
homeassistant/components/ombi/* @larssont
|
||||||
homeassistant/components/onboarding/* @home-assistant/core
|
homeassistant/components/onboarding/* @home-assistant/core
|
||||||
homeassistant/components/opentherm_gw/* @mvn23
|
homeassistant/components/opentherm_gw/* @mvn23
|
||||||
homeassistant/components/openuv/* @bachya
|
homeassistant/components/openuv/* @bachya
|
||||||
|
149
homeassistant/components/ombi/__init__.py
Normal file
149
homeassistant/components/ombi/__init__.py
Normal file
@ -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
|
24
homeassistant/components/ombi/const.py
Normal file
24
homeassistant/components/ombi/const.py
Normal file
@ -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"},
|
||||||
|
}
|
8
homeassistant/components/ombi/manifest.json
Normal file
8
homeassistant/components/ombi/manifest.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"domain": "ombi",
|
||||||
|
"name": "Ombi",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/ombi/",
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": ["@larssont"],
|
||||||
|
"requirements": ["pyombi==0.1.5"]
|
||||||
|
}
|
77
homeassistant/components/ombi/sensor.py
Normal file
77
homeassistant/components/ombi/sensor.py
Normal file
@ -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
|
27
homeassistant/components/ombi/services.yaml
Normal file
27
homeassistant/components/ombi/services.yaml
Normal file
@ -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
|
# homeassistant.components.obihai
|
||||||
pyobihai==1.1.0
|
pyobihai==1.1.0
|
||||||
|
|
||||||
|
# homeassistant.components.ombi
|
||||||
|
pyombi==0.1.5
|
||||||
|
|
||||||
# homeassistant.components.openuv
|
# homeassistant.components.openuv
|
||||||
pyopenuv==1.0.9
|
pyopenuv==1.0.9
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user