Change line endings to LN (#7660)

This commit is contained in:
Fabian Affolter 2017-05-19 16:39:13 +02:00 committed by Paulus Schoutsen
parent d369d70ca5
commit b5c54864ac
6 changed files with 843 additions and 843 deletions

View File

@ -1,82 +1,82 @@
""" """
Demo platform that has two fake binary sensors. Demo platform that has two fake binary sensors.
For more details about this platform, please refer to the documentation For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/ https://home-assistant.io/components/demo/
""" """
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.components.calendar import CalendarEventDevice from homeassistant.components.calendar import CalendarEventDevice
from homeassistant.components.google import CONF_DEVICE_ID, CONF_NAME from homeassistant.components.google import CONF_DEVICE_ID, CONF_NAME
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Demo Calendar platform.""" """Set up the Demo Calendar platform."""
calendar_data_future = DemoGoogleCalendarDataFuture() calendar_data_future = DemoGoogleCalendarDataFuture()
calendar_data_current = DemoGoogleCalendarDataCurrent() calendar_data_current = DemoGoogleCalendarDataCurrent()
add_devices([ add_devices([
DemoGoogleCalendar(hass, calendar_data_future, { DemoGoogleCalendar(hass, calendar_data_future, {
CONF_NAME: 'Future Event', CONF_NAME: 'Future Event',
CONF_DEVICE_ID: 'future_event', CONF_DEVICE_ID: 'future_event',
}), }),
DemoGoogleCalendar(hass, calendar_data_current, { DemoGoogleCalendar(hass, calendar_data_current, {
CONF_NAME: 'Current Event', CONF_NAME: 'Current Event',
CONF_DEVICE_ID: 'current_event', CONF_DEVICE_ID: 'current_event',
}), }),
]) ])
class DemoGoogleCalendarData(object): class DemoGoogleCalendarData(object):
"""Representation of a Demo Calendar element.""" """Representation of a Demo Calendar element."""
# pylint: disable=no-self-use # pylint: disable=no-self-use
def update(self): def update(self):
"""Return true so entity knows we have new data.""" """Return true so entity knows we have new data."""
return True return True
class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData): class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
"""Representation of a Demo Calendar for a future event.""" """Representation of a Demo Calendar for a future event."""
def __init__(self): def __init__(self):
"""Set the event to a future event.""" """Set the event to a future event."""
one_hour_from_now = dt_util.now() \ one_hour_from_now = dt_util.now() \
+ dt_util.dt.timedelta(minutes=30) + dt_util.dt.timedelta(minutes=30)
self.event = { self.event = {
'start': { 'start': {
'dateTime': one_hour_from_now.isoformat() 'dateTime': one_hour_from_now.isoformat()
}, },
'end': { 'end': {
'dateTime': (one_hour_from_now + dt_util.dt. 'dateTime': (one_hour_from_now + dt_util.dt.
timedelta(minutes=60)).isoformat() timedelta(minutes=60)).isoformat()
}, },
'summary': 'Future Event', 'summary': 'Future Event',
} }
class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData): class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData):
"""Representation of a Demo Calendar for a current event.""" """Representation of a Demo Calendar for a current event."""
def __init__(self): def __init__(self):
"""Set the event data.""" """Set the event data."""
middle_of_event = dt_util.now() \ middle_of_event = dt_util.now() \
- dt_util.dt.timedelta(minutes=30) - dt_util.dt.timedelta(minutes=30)
self.event = { self.event = {
'start': { 'start': {
'dateTime': middle_of_event.isoformat() 'dateTime': middle_of_event.isoformat()
}, },
'end': { 'end': {
'dateTime': (middle_of_event + dt_util.dt. 'dateTime': (middle_of_event + dt_util.dt.
timedelta(minutes=60)).isoformat() timedelta(minutes=60)).isoformat()
}, },
'summary': 'Current Event', 'summary': 'Current Event',
} }
class DemoGoogleCalendar(CalendarEventDevice): class DemoGoogleCalendar(CalendarEventDevice):
"""Representation of a Demo Calendar element.""" """Representation of a Demo Calendar element."""
def __init__(self, hass, calendar_data, data): def __init__(self, hass, calendar_data, data):
"""Initialize Google Calendar but without the API calls.""" """Initialize Google Calendar but without the API calls."""
self.data = calendar_data self.data = calendar_data
super().__init__(hass, data) super().__init__(hass, data)

View File

@ -1,78 +1,78 @@
""" """
Support for Google Calendar Search binary sensors. Support for Google Calendar Search binary sensors.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.google_calendar/ https://home-assistant.io/components/binary_sensor.google_calendar/
""" """
# pylint: disable=import-error # pylint: disable=import-error
import logging import logging
from datetime import timedelta from datetime import timedelta
from homeassistant.components.calendar import CalendarEventDevice from homeassistant.components.calendar import CalendarEventDevice
from homeassistant.components.google import ( from homeassistant.components.google import (
CONF_CAL_ID, CONF_ENTITIES, CONF_TRACK, TOKEN_FILE, CONF_CAL_ID, CONF_ENTITIES, CONF_TRACK, TOKEN_FILE,
GoogleCalendarService) GoogleCalendarService)
from homeassistant.util import Throttle, dt from homeassistant.util import Throttle, dt
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEFAULT_GOOGLE_SEARCH_PARAMS = { DEFAULT_GOOGLE_SEARCH_PARAMS = {
'orderBy': 'startTime', 'orderBy': 'startTime',
'maxResults': 1, 'maxResults': 1,
'singleEvents': True, 'singleEvents': True,
} }
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15) MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
def setup_platform(hass, config, add_devices, disc_info=None): def setup_platform(hass, config, add_devices, disc_info=None):
"""Set up the calendar platform for event devices.""" """Set up the calendar platform for event devices."""
if disc_info is None: if disc_info is None:
return return
if not any([data[CONF_TRACK] for data in disc_info[CONF_ENTITIES]]): if not any([data[CONF_TRACK] for data in disc_info[CONF_ENTITIES]]):
return return
calendar_service = GoogleCalendarService(hass.config.path(TOKEN_FILE)) calendar_service = GoogleCalendarService(hass.config.path(TOKEN_FILE))
add_devices([GoogleCalendarEventDevice(hass, calendar_service, add_devices([GoogleCalendarEventDevice(hass, calendar_service,
disc_info[CONF_CAL_ID], data) disc_info[CONF_CAL_ID], data)
for data in disc_info[CONF_ENTITIES] if data[CONF_TRACK]]) for data in disc_info[CONF_ENTITIES] if data[CONF_TRACK]])
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
class GoogleCalendarEventDevice(CalendarEventDevice): class GoogleCalendarEventDevice(CalendarEventDevice):
"""A calendar event device.""" """A calendar event device."""
def __init__(self, hass, calendar_service, calendar, data): def __init__(self, hass, calendar_service, calendar, data):
"""Create the Calendar event device.""" """Create the Calendar event device."""
self.data = GoogleCalendarData(calendar_service, calendar, self.data = GoogleCalendarData(calendar_service, calendar,
data.get('search', None)) data.get('search', None))
super().__init__(hass, data) super().__init__(hass, data)
class GoogleCalendarData(object): class GoogleCalendarData(object):
"""Class to utilize calendar service object to get next event.""" """Class to utilize calendar service object to get next event."""
def __init__(self, calendar_service, calendar_id, search=None): def __init__(self, calendar_service, calendar_id, search=None):
"""Set up how we are going to search the google calendar.""" """Set up how we are going to search the google calendar."""
self.calendar_service = calendar_service self.calendar_service = calendar_service
self.calendar_id = calendar_id self.calendar_id = calendar_id
self.search = search self.search = search
self.event = None self.event = None
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self): def update(self):
"""Get the latest data.""" """Get the latest data."""
service = self.calendar_service.get() service = self.calendar_service.get()
params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS) params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS)
params['timeMin'] = dt.now().isoformat('T') params['timeMin'] = dt.now().isoformat('T')
params['calendarId'] = self.calendar_id params['calendarId'] = self.calendar_id
if self.search: if self.search:
params['q'] = self.search params['q'] = self.search
events = service.events() # pylint: disable=no-member events = service.events() # pylint: disable=no-member
result = events.list(**params).execute() result = events.list(**params).execute()
items = result.get('items', []) items = result.get('items', [])
self.event = items[0] if len(items) == 1 else None self.event = items[0] if len(items) == 1 else None
return True return True

View File

@ -1,250 +1,250 @@
""" """
Support for Synology Surveillance Station Cameras. Support for Synology Surveillance Station Cameras.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.synology/ https://home-assistant.io/components/camera.synology/
""" """
import asyncio import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
import aiohttp import aiohttp
import async_timeout import async_timeout
from homeassistant.const import ( from homeassistant.const import (
CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_NAME, CONF_USERNAME, CONF_PASSWORD,
CONF_URL, CONF_WHITELIST, CONF_VERIFY_SSL, CONF_TIMEOUT) CONF_URL, CONF_WHITELIST, CONF_VERIFY_SSL, CONF_TIMEOUT)
from homeassistant.components.camera import ( from homeassistant.components.camera import (
Camera, PLATFORM_SCHEMA) Camera, PLATFORM_SCHEMA)
from homeassistant.helpers.aiohttp_client import ( from homeassistant.helpers.aiohttp_client import (
async_get_clientsession, async_create_clientsession, async_get_clientsession, async_create_clientsession,
async_aiohttp_proxy_web) async_aiohttp_proxy_web)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.async import run_coroutine_threadsafe from homeassistant.util.async import run_coroutine_threadsafe
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'Synology Camera' DEFAULT_NAME = 'Synology Camera'
DEFAULT_STREAM_ID = '0' DEFAULT_STREAM_ID = '0'
DEFAULT_TIMEOUT = 5 DEFAULT_TIMEOUT = 5
CONF_CAMERA_NAME = 'camera_name' CONF_CAMERA_NAME = 'camera_name'
CONF_STREAM_ID = 'stream_id' CONF_STREAM_ID = 'stream_id'
QUERY_CGI = 'query.cgi' QUERY_CGI = 'query.cgi'
QUERY_API = 'SYNO.API.Info' QUERY_API = 'SYNO.API.Info'
AUTH_API = 'SYNO.API.Auth' AUTH_API = 'SYNO.API.Auth'
CAMERA_API = 'SYNO.SurveillanceStation.Camera' CAMERA_API = 'SYNO.SurveillanceStation.Camera'
STREAMING_API = 'SYNO.SurveillanceStation.VideoStream' STREAMING_API = 'SYNO.SurveillanceStation.VideoStream'
SESSION_ID = '0' SESSION_ID = '0'
WEBAPI_PATH = '/webapi/' WEBAPI_PATH = '/webapi/'
AUTH_PATH = 'auth.cgi' AUTH_PATH = 'auth.cgi'
CAMERA_PATH = 'camera.cgi' CAMERA_PATH = 'camera.cgi'
STREAMING_PATH = 'SurveillanceStation/videoStreaming.cgi' STREAMING_PATH = 'SurveillanceStation/videoStreaming.cgi'
CONTENT_TYPE_HEADER = 'Content-Type' CONTENT_TYPE_HEADER = 'Content-Type'
SYNO_API_URL = '{0}{1}{2}' SYNO_API_URL = '{0}{1}{2}'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_URL): cv.string, vol.Required(CONF_URL): cv.string,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
vol.Optional(CONF_WHITELIST, default=[]): cv.ensure_list, vol.Optional(CONF_WHITELIST, default=[]): cv.ensure_list,
vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
}) })
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up a Synology IP Camera.""" """Set up a Synology IP Camera."""
verify_ssl = config.get(CONF_VERIFY_SSL) verify_ssl = config.get(CONF_VERIFY_SSL)
timeout = config.get(CONF_TIMEOUT) timeout = config.get(CONF_TIMEOUT)
websession_init = async_get_clientsession(hass, verify_ssl) websession_init = async_get_clientsession(hass, verify_ssl)
# Determine API to use for authentication # Determine API to use for authentication
syno_api_url = SYNO_API_URL.format( syno_api_url = SYNO_API_URL.format(
config.get(CONF_URL), WEBAPI_PATH, QUERY_CGI) config.get(CONF_URL), WEBAPI_PATH, QUERY_CGI)
query_payload = { query_payload = {
'api': QUERY_API, 'api': QUERY_API,
'method': 'Query', 'method': 'Query',
'version': '1', 'version': '1',
'query': 'SYNO.' 'query': 'SYNO.'
} }
try: try:
with async_timeout.timeout(timeout, loop=hass.loop): with async_timeout.timeout(timeout, loop=hass.loop):
query_req = yield from websession_init.get( query_req = yield from websession_init.get(
syno_api_url, syno_api_url,
params=query_payload params=query_payload
) )
# Skip content type check because Synology doesn't return JSON with # Skip content type check because Synology doesn't return JSON with
# right content type # right content type
query_resp = yield from query_req.json(content_type=None) query_resp = yield from query_req.json(content_type=None)
auth_path = query_resp['data'][AUTH_API]['path'] auth_path = query_resp['data'][AUTH_API]['path']
camera_api = query_resp['data'][CAMERA_API]['path'] camera_api = query_resp['data'][CAMERA_API]['path']
camera_path = query_resp['data'][CAMERA_API]['path'] camera_path = query_resp['data'][CAMERA_API]['path']
streaming_path = query_resp['data'][STREAMING_API]['path'] streaming_path = query_resp['data'][STREAMING_API]['path']
except (asyncio.TimeoutError, aiohttp.ClientError): except (asyncio.TimeoutError, aiohttp.ClientError):
_LOGGER.exception("Error on %s", syno_api_url) _LOGGER.exception("Error on %s", syno_api_url)
return False return False
# Authticate to NAS to get a session id # Authticate to NAS to get a session id
syno_auth_url = SYNO_API_URL.format( syno_auth_url = SYNO_API_URL.format(
config.get(CONF_URL), WEBAPI_PATH, auth_path) config.get(CONF_URL), WEBAPI_PATH, auth_path)
session_id = yield from get_session_id( session_id = yield from get_session_id(
hass, hass,
websession_init, websession_init,
config.get(CONF_USERNAME), config.get(CONF_USERNAME),
config.get(CONF_PASSWORD), config.get(CONF_PASSWORD),
syno_auth_url, syno_auth_url,
timeout timeout
) )
# init websession # init websession
websession = async_create_clientsession( websession = async_create_clientsession(
hass, verify_ssl, cookies={'id': session_id}) hass, verify_ssl, cookies={'id': session_id})
# Use SessionID to get cameras in system # Use SessionID to get cameras in system
syno_camera_url = SYNO_API_URL.format( syno_camera_url = SYNO_API_URL.format(
config.get(CONF_URL), WEBAPI_PATH, camera_api) config.get(CONF_URL), WEBAPI_PATH, camera_api)
camera_payload = { camera_payload = {
'api': CAMERA_API, 'api': CAMERA_API,
'method': 'List', 'method': 'List',
'version': '1' 'version': '1'
} }
try: try:
with async_timeout.timeout(timeout, loop=hass.loop): with async_timeout.timeout(timeout, loop=hass.loop):
camera_req = yield from websession.get( camera_req = yield from websession.get(
syno_camera_url, syno_camera_url,
params=camera_payload params=camera_payload
) )
except (asyncio.TimeoutError, aiohttp.ClientError): except (asyncio.TimeoutError, aiohttp.ClientError):
_LOGGER.exception("Error on %s", syno_camera_url) _LOGGER.exception("Error on %s", syno_camera_url)
return False return False
camera_resp = yield from camera_req.json(content_type=None) camera_resp = yield from camera_req.json(content_type=None)
cameras = camera_resp['data']['cameras'] cameras = camera_resp['data']['cameras']
# add cameras # add cameras
devices = [] devices = []
for camera in cameras: for camera in cameras:
if not config.get(CONF_WHITELIST): if not config.get(CONF_WHITELIST):
camera_id = camera['id'] camera_id = camera['id']
snapshot_path = camera['snapshot_path'] snapshot_path = camera['snapshot_path']
device = SynologyCamera( device = SynologyCamera(
hass, websession, config, camera_id, camera['name'], hass, websession, config, camera_id, camera['name'],
snapshot_path, streaming_path, camera_path, auth_path, timeout snapshot_path, streaming_path, camera_path, auth_path, timeout
) )
devices.append(device) devices.append(device)
async_add_devices(devices) async_add_devices(devices)
@asyncio.coroutine @asyncio.coroutine
def get_session_id(hass, websession, username, password, login_url, timeout): def get_session_id(hass, websession, username, password, login_url, timeout):
"""Get a session id.""" """Get a session id."""
auth_payload = { auth_payload = {
'api': AUTH_API, 'api': AUTH_API,
'method': 'Login', 'method': 'Login',
'version': '2', 'version': '2',
'account': username, 'account': username,
'passwd': password, 'passwd': password,
'session': 'SurveillanceStation', 'session': 'SurveillanceStation',
'format': 'sid' 'format': 'sid'
} }
try: try:
with async_timeout.timeout(timeout, loop=hass.loop): with async_timeout.timeout(timeout, loop=hass.loop):
auth_req = yield from websession.get( auth_req = yield from websession.get(
login_url, login_url,
params=auth_payload params=auth_payload
) )
auth_resp = yield from auth_req.json(content_type=None) auth_resp = yield from auth_req.json(content_type=None)
return auth_resp['data']['sid'] return auth_resp['data']['sid']
except (asyncio.TimeoutError, aiohttp.ClientError): except (asyncio.TimeoutError, aiohttp.ClientError):
_LOGGER.exception("Error on %s", login_url) _LOGGER.exception("Error on %s", login_url)
return False return False
class SynologyCamera(Camera): class SynologyCamera(Camera):
"""An implementation of a Synology NAS based IP camera.""" """An implementation of a Synology NAS based IP camera."""
def __init__(self, hass, websession, config, camera_id, def __init__(self, hass, websession, config, camera_id,
camera_name, snapshot_path, streaming_path, camera_path, camera_name, snapshot_path, streaming_path, camera_path,
auth_path, timeout): auth_path, timeout):
"""Initialize a Synology Surveillance Station camera.""" """Initialize a Synology Surveillance Station camera."""
super().__init__() super().__init__()
self.hass = hass self.hass = hass
self._websession = websession self._websession = websession
self._name = camera_name self._name = camera_name
self._synology_url = config.get(CONF_URL) self._synology_url = config.get(CONF_URL)
self._camera_name = config.get(CONF_CAMERA_NAME) self._camera_name = config.get(CONF_CAMERA_NAME)
self._stream_id = config.get(CONF_STREAM_ID) self._stream_id = config.get(CONF_STREAM_ID)
self._camera_id = camera_id self._camera_id = camera_id
self._snapshot_path = snapshot_path self._snapshot_path = snapshot_path
self._streaming_path = streaming_path self._streaming_path = streaming_path
self._camera_path = camera_path self._camera_path = camera_path
self._auth_path = auth_path self._auth_path = auth_path
self._timeout = timeout self._timeout = timeout
def camera_image(self): def camera_image(self):
"""Return bytes of camera image.""" """Return bytes of camera image."""
return run_coroutine_threadsafe( return run_coroutine_threadsafe(
self.async_camera_image(), self.hass.loop).result() self.async_camera_image(), self.hass.loop).result()
@asyncio.coroutine @asyncio.coroutine
def async_camera_image(self): def async_camera_image(self):
"""Return a still image response from the camera.""" """Return a still image response from the camera."""
image_url = SYNO_API_URL.format( image_url = SYNO_API_URL.format(
self._synology_url, WEBAPI_PATH, self._camera_path) self._synology_url, WEBAPI_PATH, self._camera_path)
image_payload = { image_payload = {
'api': CAMERA_API, 'api': CAMERA_API,
'method': 'GetSnapshot', 'method': 'GetSnapshot',
'version': '1', 'version': '1',
'cameraId': self._camera_id 'cameraId': self._camera_id
} }
try: try:
with async_timeout.timeout(self._timeout, loop=self.hass.loop): with async_timeout.timeout(self._timeout, loop=self.hass.loop):
response = yield from self._websession.get( response = yield from self._websession.get(
image_url, image_url,
params=image_payload params=image_payload
) )
except (asyncio.TimeoutError, aiohttp.ClientError): except (asyncio.TimeoutError, aiohttp.ClientError):
_LOGGER.error("Error fetching %s", image_url) _LOGGER.error("Error fetching %s", image_url)
return None return None
image = yield from response.read() image = yield from response.read()
return image return image
@asyncio.coroutine @asyncio.coroutine
def handle_async_mjpeg_stream(self, request): def handle_async_mjpeg_stream(self, request):
"""Return a MJPEG stream image response directly from the camera.""" """Return a MJPEG stream image response directly from the camera."""
streaming_url = SYNO_API_URL.format( streaming_url = SYNO_API_URL.format(
self._synology_url, WEBAPI_PATH, self._streaming_path) self._synology_url, WEBAPI_PATH, self._streaming_path)
streaming_payload = { streaming_payload = {
'api': STREAMING_API, 'api': STREAMING_API,
'method': 'Stream', 'method': 'Stream',
'version': '1', 'version': '1',
'cameraId': self._camera_id, 'cameraId': self._camera_id,
'format': 'mjpeg' 'format': 'mjpeg'
} }
stream_coro = self._websession.get( stream_coro = self._websession.get(
streaming_url, params=streaming_payload) streaming_url, params=streaming_payload)
yield from async_aiohttp_proxy_web(self.hass, request, stream_coro) yield from async_aiohttp_proxy_web(self.hass, request, stream_coro)
@property @property
def name(self): def name(self):
"""Return the name of this device.""" """Return the name of this device."""
return self._name return self._name

View File

@ -1,4 +1,4 @@
""" """
Tado component to create a climate device for each zone. Tado component to create a climate device for each zone.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at

View File

@ -1,187 +1,187 @@
""" """
Support for Harmony Hub devices. Support for Harmony Hub devices.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/remote.harmony/ https://home-assistant.io/components/remote.harmony/
""" """
import logging import logging
from os import path from os import path
import urllib.parse import urllib.parse
import voluptuous as vol import voluptuous as vol
import homeassistant.components.remote as remote import homeassistant.components.remote as remote
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.const import ( from homeassistant.const import (
CONF_NAME, CONF_HOST, CONF_PORT, ATTR_ENTITY_ID) CONF_NAME, CONF_HOST, CONF_PORT, ATTR_ENTITY_ID)
from homeassistant.components.remote import ( from homeassistant.components.remote import (
PLATFORM_SCHEMA, DOMAIN, ATTR_DEVICE, ATTR_COMMAND, ATTR_ACTIVITY) PLATFORM_SCHEMA, DOMAIN, ATTR_DEVICE, ATTR_COMMAND, ATTR_ACTIVITY)
from homeassistant.util import slugify from homeassistant.util import slugify
from homeassistant.config import load_yaml_config_file from homeassistant.config import load_yaml_config_file
REQUIREMENTS = ['pyharmony==1.0.12'] REQUIREMENTS = ['pyharmony==1.0.12']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEFAULT_PORT = 5222 DEFAULT_PORT = 5222
DEVICES = [] DEVICES = []
SERVICE_SYNC = 'harmony_sync' SERVICE_SYNC = 'harmony_sync'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_NAME): cv.string, vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_HOST): cv.string, vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Required(ATTR_ACTIVITY, default=None): cv.string, vol.Required(ATTR_ACTIVITY, default=None): cv.string,
}) })
HARMONY_SYNC_SCHEMA = vol.Schema({ HARMONY_SYNC_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
}) })
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Harmony platform.""" """Set up the Harmony platform."""
import pyharmony import pyharmony
global DEVICES global DEVICES
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
host = config.get(CONF_HOST) host = config.get(CONF_HOST)
port = config.get(CONF_PORT) port = config.get(CONF_PORT)
_LOGGER.debug("Loading Harmony platform: %s", name) _LOGGER.debug("Loading Harmony platform: %s", name)
harmony_conf_file = hass.config.path( harmony_conf_file = hass.config.path(
'{}{}{}'.format('harmony_', slugify(name), '.conf')) '{}{}{}'.format('harmony_', slugify(name), '.conf'))
try: try:
_LOGGER.debug("Calling pyharmony.ha_get_token for remote at: %s:%s", _LOGGER.debug("Calling pyharmony.ha_get_token for remote at: %s:%s",
host, port) host, port)
token = urllib.parse.quote_plus(pyharmony.ha_get_token(host, port)) token = urllib.parse.quote_plus(pyharmony.ha_get_token(host, port))
except ValueError as err: except ValueError as err:
_LOGGER.warning("%s for remote: %s", err.args[0], name) _LOGGER.warning("%s for remote: %s", err.args[0], name)
return False return False
_LOGGER.debug("Received token: %s", token) _LOGGER.debug("Received token: %s", token)
DEVICES = [HarmonyRemote( DEVICES = [HarmonyRemote(
config.get(CONF_NAME), config.get(CONF_HOST), config.get(CONF_PORT), config.get(CONF_NAME), config.get(CONF_HOST), config.get(CONF_PORT),
config.get(ATTR_ACTIVITY), harmony_conf_file, token)] config.get(ATTR_ACTIVITY), harmony_conf_file, token)]
add_devices(DEVICES, True) add_devices(DEVICES, True)
register_services(hass) register_services(hass)
return True return True
def register_services(hass): def register_services(hass):
"""Register all services for harmony devices.""" """Register all services for harmony devices."""
descriptions = load_yaml_config_file( descriptions = load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml')) path.join(path.dirname(__file__), 'services.yaml'))
hass.services.register( hass.services.register(
DOMAIN, SERVICE_SYNC, _sync_service, descriptions.get(SERVICE_SYNC), DOMAIN, SERVICE_SYNC, _sync_service, descriptions.get(SERVICE_SYNC),
schema=HARMONY_SYNC_SCHEMA) schema=HARMONY_SYNC_SCHEMA)
def _apply_service(service, service_func, *service_func_args): def _apply_service(service, service_func, *service_func_args):
"""Handle services to apply.""" """Handle services to apply."""
entity_ids = service.data.get('entity_id') entity_ids = service.data.get('entity_id')
if entity_ids: if entity_ids:
_devices = [device for device in DEVICES _devices = [device for device in DEVICES
if device.entity_id in entity_ids] if device.entity_id in entity_ids]
else: else:
_devices = DEVICES _devices = DEVICES
for device in _devices: for device in _devices:
service_func(device, *service_func_args) service_func(device, *service_func_args)
device.schedule_update_ha_state(True) device.schedule_update_ha_state(True)
def _sync_service(service): def _sync_service(service):
_apply_service(service, HarmonyRemote.sync) _apply_service(service, HarmonyRemote.sync)
class HarmonyRemote(remote.RemoteDevice): class HarmonyRemote(remote.RemoteDevice):
"""Remote representation used to control a Harmony device.""" """Remote representation used to control a Harmony device."""
def __init__(self, name, host, port, activity, out_path, token): def __init__(self, name, host, port, activity, out_path, token):
"""Initialize HarmonyRemote class.""" """Initialize HarmonyRemote class."""
import pyharmony import pyharmony
from pathlib import Path from pathlib import Path
_LOGGER.debug("HarmonyRemote device init started for: %s", name) _LOGGER.debug("HarmonyRemote device init started for: %s", name)
self._name = name self._name = name
self._ip = host self._ip = host
self._port = port self._port = port
self._state = None self._state = None
self._current_activity = None self._current_activity = None
self._default_activity = activity self._default_activity = activity
self._token = token self._token = token
self._config_path = out_path self._config_path = out_path
_LOGGER.debug("Retrieving harmony config using token: %s", token) _LOGGER.debug("Retrieving harmony config using token: %s", token)
self._config = pyharmony.ha_get_config(self._token, host, port) self._config = pyharmony.ha_get_config(self._token, host, port)
if not Path(self._config_path).is_file(): if not Path(self._config_path).is_file():
_LOGGER.debug("Writing harmony configuration to file: %s", _LOGGER.debug("Writing harmony configuration to file: %s",
out_path) out_path)
pyharmony.ha_write_config_file(self._config, self._config_path) pyharmony.ha_write_config_file(self._config, self._config_path)
@property @property
def name(self): def name(self):
"""Return the Harmony device's name.""" """Return the Harmony device's name."""
return self._name return self._name
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Add platform specific attributes.""" """Add platform specific attributes."""
return {'current_activity': self._current_activity} return {'current_activity': self._current_activity}
@property @property
def is_on(self): def is_on(self):
"""Return False if PowerOff is the current activity, otherwise True.""" """Return False if PowerOff is the current activity, otherwise True."""
return self._current_activity != 'PowerOff' return self._current_activity != 'PowerOff'
def update(self): def update(self):
"""Return current activity.""" """Return current activity."""
import pyharmony import pyharmony
name = self._name name = self._name
_LOGGER.debug("Polling %s for current activity", name) _LOGGER.debug("Polling %s for current activity", name)
state = pyharmony.ha_get_current_activity( state = pyharmony.ha_get_current_activity(
self._token, self._config, self._ip, self._port) self._token, self._config, self._ip, self._port)
_LOGGER.debug("%s current activity reported as: %s", name, state) _LOGGER.debug("%s current activity reported as: %s", name, state)
self._current_activity = state self._current_activity = state
self._state = bool(state != 'PowerOff') self._state = bool(state != 'PowerOff')
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Start an activity from the Harmony device.""" """Start an activity from the Harmony device."""
import pyharmony import pyharmony
if kwargs[ATTR_ACTIVITY]: if kwargs[ATTR_ACTIVITY]:
activity = kwargs[ATTR_ACTIVITY] activity = kwargs[ATTR_ACTIVITY]
else: else:
activity = self._default_activity activity = self._default_activity
if activity: if activity:
pyharmony.ha_start_activity( pyharmony.ha_start_activity(
self._token, self._ip, self._port, self._config, activity) self._token, self._ip, self._port, self._config, activity)
self._state = True self._state = True
else: else:
_LOGGER.error("No activity specified with turn_on service") _LOGGER.error("No activity specified with turn_on service")
def turn_off(self): def turn_off(self):
"""Start the PowerOff activity.""" """Start the PowerOff activity."""
import pyharmony import pyharmony
pyharmony.ha_power_off(self._token, self._ip, self._port) pyharmony.ha_power_off(self._token, self._ip, self._port)
def send_command(self, **kwargs): def send_command(self, **kwargs):
"""Send a command to one device.""" """Send a command to one device."""
import pyharmony import pyharmony
pyharmony.ha_send_command( pyharmony.ha_send_command(
self._token, self._ip, self._port, kwargs[ATTR_DEVICE], self._token, self._ip, self._port, kwargs[ATTR_DEVICE],
kwargs[ATTR_COMMAND]) kwargs[ATTR_COMMAND])
def sync(self): def sync(self):
"""Sync the Harmony device with the web service.""" """Sync the Harmony device with the web service."""
import pyharmony import pyharmony
_LOGGER.debug("Syncing hub with Harmony servers") _LOGGER.debug("Syncing hub with Harmony servers")
pyharmony.ha_sync(self._token, self._ip, self._port) pyharmony.ha_sync(self._token, self._ip, self._port)
self._config = pyharmony.ha_get_config( self._config = pyharmony.ha_get_config(
self._token, self._ip, self._port) self._token, self._ip, self._port)
_LOGGER.debug("Writing hub config to file: %s", self._config_path) _LOGGER.debug("Writing hub config to file: %s", self._config_path)
pyharmony.ha_write_config_file(self._config, self._config_path) pyharmony.ha_write_config_file(self._config, self._config_path)

View File

@ -1,245 +1,245 @@
""" """
Support for Synology NAS Sensors. Support for Synology NAS Sensors.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.synologydsm/ https://home-assistant.io/components/sensor.synologydsm/
""" """
import logging import logging
from datetime import timedelta from datetime import timedelta
from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_USERNAME, CONF_PASSWORD, CONF_PORT, CONF_HOST, CONF_USERNAME, CONF_PASSWORD, CONF_PORT,
CONF_MONITORED_CONDITIONS, TEMP_CELSIUS, EVENT_HOMEASSISTANT_START) CONF_MONITORED_CONDITIONS, TEMP_CELSIUS, EVENT_HOMEASSISTANT_START)
from homeassistant.util import Throttle from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import voluptuous as vol import voluptuous as vol
REQUIREMENTS = ['python-synology==0.1.0'] REQUIREMENTS = ['python-synology==0.1.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CONF_DISKS = 'disks' CONF_DISKS = 'disks'
CONF_VOLUMES = 'volumes' CONF_VOLUMES = 'volumes'
DEFAULT_NAME = 'Synology DSM' DEFAULT_NAME = 'Synology DSM'
DEFAULT_PORT = 5000 DEFAULT_PORT = 5000
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15) MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
_UTILISATION_MON_COND = { _UTILISATION_MON_COND = {
'cpu_other_load': ['CPU Load (Other)', '%', 'mdi:chip'], 'cpu_other_load': ['CPU Load (Other)', '%', 'mdi:chip'],
'cpu_user_load': ['CPU Load (User)', '%', 'mdi:chip'], 'cpu_user_load': ['CPU Load (User)', '%', 'mdi:chip'],
'cpu_system_load': ['CPU Load (System)', '%', 'mdi:chip'], 'cpu_system_load': ['CPU Load (System)', '%', 'mdi:chip'],
'cpu_total_load': ['CPU Load (Total)', '%', 'mdi:chip'], 'cpu_total_load': ['CPU Load (Total)', '%', 'mdi:chip'],
'cpu_1min_load': ['CPU Load (1 min)', '%', 'mdi:chip'], 'cpu_1min_load': ['CPU Load (1 min)', '%', 'mdi:chip'],
'cpu_5min_load': ['CPU Load (5 min)', '%', 'mdi:chip'], 'cpu_5min_load': ['CPU Load (5 min)', '%', 'mdi:chip'],
'cpu_15min_load': ['CPU Load (15 min)', '%', 'mdi:chip'], 'cpu_15min_load': ['CPU Load (15 min)', '%', 'mdi:chip'],
'memory_real_usage': ['Memory Usage (Real)', '%', 'mdi:memory'], 'memory_real_usage': ['Memory Usage (Real)', '%', 'mdi:memory'],
'memory_size': ['Memory Size', 'Mb', 'mdi:memory'], 'memory_size': ['Memory Size', 'Mb', 'mdi:memory'],
'memory_cached': ['Memory Cached', 'Mb', 'mdi:memory'], 'memory_cached': ['Memory Cached', 'Mb', 'mdi:memory'],
'memory_available_swap': ['Memory Available (Swap)', 'Mb', 'mdi:memory'], 'memory_available_swap': ['Memory Available (Swap)', 'Mb', 'mdi:memory'],
'memory_available_real': ['Memory Available (Real)', 'Mb', 'mdi:memory'], 'memory_available_real': ['Memory Available (Real)', 'Mb', 'mdi:memory'],
'memory_total_swap': ['Memory Total (Swap)', 'Mb', 'mdi:memory'], 'memory_total_swap': ['Memory Total (Swap)', 'Mb', 'mdi:memory'],
'memory_total_real': ['Memory Total (Real)', 'Mb', 'mdi:memory'], 'memory_total_real': ['Memory Total (Real)', 'Mb', 'mdi:memory'],
'network_up': ['Network Up', 'Kbps', 'mdi:upload'], 'network_up': ['Network Up', 'Kbps', 'mdi:upload'],
'network_down': ['Network Down', 'Kbps', 'mdi:download'], 'network_down': ['Network Down', 'Kbps', 'mdi:download'],
} }
_STORAGE_VOL_MON_COND = { _STORAGE_VOL_MON_COND = {
'volume_status': ['Status', None, 'mdi:checkbox-marked-circle-outline'], 'volume_status': ['Status', None, 'mdi:checkbox-marked-circle-outline'],
'volume_device_type': ['Type', None, 'mdi:harddisk'], 'volume_device_type': ['Type', None, 'mdi:harddisk'],
'volume_size_total': ['Total Size', None, 'mdi:chart-pie'], 'volume_size_total': ['Total Size', None, 'mdi:chart-pie'],
'volume_size_used': ['Used Space', None, 'mdi:chart-pie'], 'volume_size_used': ['Used Space', None, 'mdi:chart-pie'],
'volume_percentage_used': ['Volume Used', '%', 'mdi:chart-pie'], 'volume_percentage_used': ['Volume Used', '%', 'mdi:chart-pie'],
'volume_disk_temp_avg': ['Average Disk Temp', None, 'mdi:thermometer'], 'volume_disk_temp_avg': ['Average Disk Temp', None, 'mdi:thermometer'],
'volume_disk_temp_max': ['Maximum Disk Temp', None, 'mdi:thermometer'], 'volume_disk_temp_max': ['Maximum Disk Temp', None, 'mdi:thermometer'],
} }
_STORAGE_DSK_MON_COND = { _STORAGE_DSK_MON_COND = {
'disk_name': ['Name', None, 'mdi:harddisk'], 'disk_name': ['Name', None, 'mdi:harddisk'],
'disk_device': ['Device', None, 'mdi:dots-horizontal'], 'disk_device': ['Device', None, 'mdi:dots-horizontal'],
'disk_smart_status': ['Status (Smart)', None, 'disk_smart_status': ['Status (Smart)', None,
'mdi:checkbox-marked-circle-outline'], 'mdi:checkbox-marked-circle-outline'],
'disk_status': ['Status', None, 'mdi:checkbox-marked-circle-outline'], 'disk_status': ['Status', None, 'mdi:checkbox-marked-circle-outline'],
'disk_exceed_bad_sector_thr': ['Exceeded Max Bad Sectors', None, 'disk_exceed_bad_sector_thr': ['Exceeded Max Bad Sectors', None,
'mdi:test-tube'], 'mdi:test-tube'],
'disk_below_remain_life_thr': ['Below Min Remaining Life', None, 'disk_below_remain_life_thr': ['Below Min Remaining Life', None,
'mdi:test-tube'], 'mdi:test-tube'],
'disk_temp': ['Temperature', None, 'mdi:thermometer'], 'disk_temp': ['Temperature', None, 'mdi:thermometer'],
} }
_MONITORED_CONDITIONS = list(_UTILISATION_MON_COND.keys()) + \ _MONITORED_CONDITIONS = list(_UTILISATION_MON_COND.keys()) + \
list(_STORAGE_VOL_MON_COND.keys()) + \ list(_STORAGE_VOL_MON_COND.keys()) + \
list(_STORAGE_DSK_MON_COND.keys()) list(_STORAGE_DSK_MON_COND.keys())
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string, vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_MONITORED_CONDITIONS): vol.Optional(CONF_MONITORED_CONDITIONS):
vol.All(cv.ensure_list, [vol.In(_MONITORED_CONDITIONS)]), vol.All(cv.ensure_list, [vol.In(_MONITORED_CONDITIONS)]),
vol.Optional(CONF_DISKS, default=None): cv.ensure_list, vol.Optional(CONF_DISKS, default=None): cv.ensure_list,
vol.Optional(CONF_VOLUMES, default=None): cv.ensure_list, vol.Optional(CONF_VOLUMES, default=None): cv.ensure_list,
}) })
def setup_platform(hass, config, add_devices_callback, discovery_info=None): def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Set up the Synology NAS Sensor.""" """Set up the Synology NAS Sensor."""
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
def run_setup(event): def run_setup(event):
"""Wait until HASS is fully initialized before creating. """Wait until HASS is fully initialized before creating.
Delay the setup until Home Assistant is fully initialized. Delay the setup until Home Assistant is fully initialized.
This allows any entities to be created already This allows any entities to be created already
""" """
# Setup API # Setup API
api = SynoApi(config.get(CONF_HOST), config.get(CONF_PORT), api = SynoApi(config.get(CONF_HOST), config.get(CONF_PORT),
config.get(CONF_USERNAME), config.get(CONF_PASSWORD), config.get(CONF_USERNAME), config.get(CONF_PASSWORD),
hass.config.units.temperature_unit) hass.config.units.temperature_unit)
sensors = [SynoNasUtilSensor(api, variable, sensors = [SynoNasUtilSensor(api, variable,
_UTILISATION_MON_COND[variable]) _UTILISATION_MON_COND[variable])
for variable in config[CONF_MONITORED_CONDITIONS] for variable in config[CONF_MONITORED_CONDITIONS]
if variable in _UTILISATION_MON_COND] if variable in _UTILISATION_MON_COND]
# Handle all Volumes # Handle all Volumes
volumes = config['volumes'] volumes = config['volumes']
if volumes is None: if volumes is None:
volumes = api.storage.volumes volumes = api.storage.volumes
for volume in volumes: for volume in volumes:
sensors += [SynoNasStorageSensor(api, variable, sensors += [SynoNasStorageSensor(api, variable,
_STORAGE_VOL_MON_COND[variable], _STORAGE_VOL_MON_COND[variable],
volume) volume)
for variable in config[CONF_MONITORED_CONDITIONS] for variable in config[CONF_MONITORED_CONDITIONS]
if variable in _STORAGE_VOL_MON_COND] if variable in _STORAGE_VOL_MON_COND]
# Handle all Disks # Handle all Disks
disks = config['disks'] disks = config['disks']
if disks is None: if disks is None:
disks = api.storage.disks disks = api.storage.disks
for disk in disks: for disk in disks:
sensors += [SynoNasStorageSensor(api, variable, sensors += [SynoNasStorageSensor(api, variable,
_STORAGE_DSK_MON_COND[variable], _STORAGE_DSK_MON_COND[variable],
disk) disk)
for variable in config[CONF_MONITORED_CONDITIONS] for variable in config[CONF_MONITORED_CONDITIONS]
if variable in _STORAGE_DSK_MON_COND] if variable in _STORAGE_DSK_MON_COND]
add_devices_callback(sensors) add_devices_callback(sensors)
# Wait until start event is sent to load this component. # Wait until start event is sent to load this component.
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, run_setup) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, run_setup)
class SynoApi(): class SynoApi():
"""Class to interface with API.""" """Class to interface with API."""
# pylint: disable=too-many-arguments, bare-except # pylint: disable=too-many-arguments, bare-except
def __init__(self, host, port, username, password, temp_unit): def __init__(self, host, port, username, password, temp_unit):
"""Initialize the API wrapper class.""" """Initialize the API wrapper class."""
from SynologyDSM import SynologyDSM from SynologyDSM import SynologyDSM
self.temp_unit = temp_unit self.temp_unit = temp_unit
try: try:
self._api = SynologyDSM(host, self._api = SynologyDSM(host,
port, port,
username, username,
password) password)
except: except:
_LOGGER.error("Error setting up Synology DSM") _LOGGER.error("Error setting up Synology DSM")
# Will be updated when `update` gets called. # Will be updated when `update` gets called.
self.utilisation = self._api.utilisation self.utilisation = self._api.utilisation
self.storage = self._api.storage self.storage = self._api.storage
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self): def update(self):
"""Update function for updating api information.""" """Update function for updating api information."""
self._api.update() self._api.update()
class SynoNasSensor(Entity): class SynoNasSensor(Entity):
"""Representation of a Synology Nas Sensor.""" """Representation of a Synology Nas Sensor."""
def __init__(self, api, variable, variableInfo, monitor_device=None): def __init__(self, api, variable, variableInfo, monitor_device=None):
"""Initialize the sensor.""" """Initialize the sensor."""
self.var_id = variable self.var_id = variable
self.var_name = variableInfo[0] self.var_name = variableInfo[0]
self.var_units = variableInfo[1] self.var_units = variableInfo[1]
self.var_icon = variableInfo[2] self.var_icon = variableInfo[2]
self.monitor_device = monitor_device self.monitor_device = monitor_device
self._api = api self._api = api
@property @property
def name(self): def name(self):
"""Return the name of the sensor, if any.""" """Return the name of the sensor, if any."""
if self.monitor_device is not None: if self.monitor_device is not None:
return "{} ({})".format(self.var_name, self.monitor_device) return "{} ({})".format(self.var_name, self.monitor_device)
else: else:
return self.var_name return self.var_name
@property @property
def icon(self): def icon(self):
"""Icon to use in the frontend, if any.""" """Icon to use in the frontend, if any."""
return self.var_icon return self.var_icon
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
if self.var_id in ['volume_disk_temp_avg', 'volume_disk_temp_max', if self.var_id in ['volume_disk_temp_avg', 'volume_disk_temp_max',
'disk_temp']: 'disk_temp']:
return self._api.temp_unit return self._api.temp_unit
else: else:
return self.var_units return self.var_units
def update(self): def update(self):
"""Get the latest data for the states.""" """Get the latest data for the states."""
if self._api is not None: if self._api is not None:
self._api.update() self._api.update()
class SynoNasUtilSensor(SynoNasSensor): class SynoNasUtilSensor(SynoNasSensor):
"""Representation a Synology Utilisation Sensor.""" """Representation a Synology Utilisation Sensor."""
@property @property
def state(self): def state(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
network_sensors = ['network_up', 'network_down'] network_sensors = ['network_up', 'network_down']
memory_sensors = ['memory_size', 'memory_cached', memory_sensors = ['memory_size', 'memory_cached',
'memory_available_swap', 'memory_available_real', 'memory_available_swap', 'memory_available_real',
'memory_total_swap', 'memory_total_real'] 'memory_total_swap', 'memory_total_real']
if self.var_id in network_sensors or self.var_id in memory_sensors: if self.var_id in network_sensors or self.var_id in memory_sensors:
attr = getattr(self._api.utilisation, self.var_id)(False) attr = getattr(self._api.utilisation, self.var_id)(False)
if self.var_id in network_sensors: if self.var_id in network_sensors:
return round(attr / 1024.0, 1) return round(attr / 1024.0, 1)
elif self.var_id in memory_sensors: elif self.var_id in memory_sensors:
return round(attr / 1024.0 / 1024.0, 1) return round(attr / 1024.0 / 1024.0, 1)
else: else:
return getattr(self._api.utilisation, self.var_id) return getattr(self._api.utilisation, self.var_id)
class SynoNasStorageSensor(SynoNasSensor): class SynoNasStorageSensor(SynoNasSensor):
"""Representation a Synology Utilisation Sensor.""" """Representation a Synology Utilisation Sensor."""
@property @property
def state(self): def state(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
temp_sensors = ['volume_disk_temp_avg', 'volume_disk_temp_max', temp_sensors = ['volume_disk_temp_avg', 'volume_disk_temp_max',
'disk_temp'] 'disk_temp']
if self.monitor_device is not None: if self.monitor_device is not None:
if self.var_id in temp_sensors: if self.var_id in temp_sensors:
attr = getattr(self._api.storage, attr = getattr(self._api.storage,
self.var_id)(self.monitor_device) self.var_id)(self.monitor_device)
if self._api.temp_unit == TEMP_CELSIUS: if self._api.temp_unit == TEMP_CELSIUS:
return attr return attr
else: else:
return round(attr * 1.8 + 32.0, 1) return round(attr * 1.8 + 32.0, 1)
else: else:
return getattr(self._api.storage, return getattr(self._api.storage,
self.var_id)(self.monitor_device) self.var_id)(self.monitor_device)