mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 05:37:44 +00:00
Merge remote-tracking branch 'balloob/dev' into dev
This commit is contained in:
commit
582ed1fc8d
@ -18,7 +18,7 @@ For help on building your component, please see the [developer documentation](ht
|
|||||||
After you finish adding support for your device:
|
After you finish adding support for your device:
|
||||||
|
|
||||||
- Update the supported devices in the `README.md` file.
|
- Update the supported devices in the `README.md` file.
|
||||||
- Add any new dependencies to `requirements.txt`.
|
- Add any new dependencies to `requirements_all.txt`. There is no ordering right now, so just add it to the end.
|
||||||
- Update the `.coveragerc` file.
|
- Update the `.coveragerc` file.
|
||||||
- Provide some documentation for [home-assistant.io](https://home-assistant.io/). The documentation is handled in a separate [git repository](https://github.com/balloob/home-assistant.io).
|
- Provide some documentation for [home-assistant.io](https://home-assistant.io/). The documentation is handled in a separate [git repository](https://github.com/balloob/home-assistant.io).
|
||||||
- Make sure all your code passes Pylint and flake8 (PEP8 and some more) validation. To generate reports, run `pylint homeassistant > pylint.txt` and `flake8 homeassistant --exclude bower_components,external > flake8.txt`.
|
- Make sure all your code passes Pylint and flake8 (PEP8 and some more) validation. To generate reports, run `pylint homeassistant > pylint.txt` and `flake8 homeassistant --exclude bower_components,external > flake8.txt`.
|
||||||
|
50
homeassistant/components/device_tracker/demo.py
Normal file
50
homeassistant/components/device_tracker/demo.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
homeassistant.components.device_tracker.demo
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Demo platform for the device tracker.
|
||||||
|
|
||||||
|
device_tracker:
|
||||||
|
platform: demo
|
||||||
|
"""
|
||||||
|
import random
|
||||||
|
|
||||||
|
from homeassistant.components.device_tracker import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
def setup_scanner(hass, config, see):
|
||||||
|
""" Set up a demo tracker. """
|
||||||
|
|
||||||
|
def offset():
|
||||||
|
""" Return random offset. """
|
||||||
|
return (random.randrange(500, 2000)) / 2e5 * random.choice((-1, 1))
|
||||||
|
|
||||||
|
def random_see(dev_id, name):
|
||||||
|
""" Randomize a sighting. """
|
||||||
|
see(
|
||||||
|
dev_id=dev_id,
|
||||||
|
host_name=name,
|
||||||
|
gps=(hass.config.latitude + offset(),
|
||||||
|
hass.config.longitude + offset()),
|
||||||
|
gps_accuracy=random.randrange(50, 150),
|
||||||
|
battery=random.randrange(10, 90)
|
||||||
|
)
|
||||||
|
|
||||||
|
def observe(call=None):
|
||||||
|
""" Observe three entities. """
|
||||||
|
random_see('demo_paulus', 'Paulus')
|
||||||
|
random_see('demo_anne_therese', 'Anne Therese')
|
||||||
|
|
||||||
|
observe()
|
||||||
|
|
||||||
|
see(
|
||||||
|
dev_id='demo_home_boy',
|
||||||
|
host_name='Home Boy',
|
||||||
|
gps=[hass.config.latitude - 0.00002, hass.config.longitude + 0.00002],
|
||||||
|
gps_accuracy=20,
|
||||||
|
battery=53
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.services.register(DOMAIN, 'demo', observe)
|
||||||
|
|
||||||
|
return True
|
@ -8,6 +8,7 @@ device_tracker:
|
|||||||
platform: owntracks
|
platform: owntracks
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
import homeassistant.components.mqtt as mqtt
|
import homeassistant.components.mqtt as mqtt
|
||||||
|
|
||||||
@ -24,18 +25,29 @@ def setup_scanner(hass, config, see):
|
|||||||
|
|
||||||
# Docs on available data:
|
# Docs on available data:
|
||||||
# http://owntracks.org/booklet/tech/json/#_typelocation
|
# http://owntracks.org/booklet/tech/json/#_typelocation
|
||||||
|
|
||||||
parts = topic.split('/')
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(payload)
|
data = json.loads(payload)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# If invalid JSON
|
# If invalid JSON
|
||||||
|
logging.getLogger(__name__).error(
|
||||||
|
'Unable to parse payload as JSON: %s', payload)
|
||||||
return
|
return
|
||||||
|
|
||||||
if data.get('_type') != 'location':
|
if data.get('_type') != 'location':
|
||||||
return
|
return
|
||||||
dev_id = '{}_{}'.format(parts[1], parts[2])
|
|
||||||
see(dev_id=dev_id, host_name=parts[1], gps=(data['lat'], data['lon']),
|
parts = topic.split('/')
|
||||||
gps_accuracy=data['acc'], battery=data['batt'])
|
kwargs = {
|
||||||
|
'dev_id': '{}_{}'.format(parts[1], parts[2]),
|
||||||
|
'host_name': parts[1],
|
||||||
|
'gps': (data['lat'], data['lon']),
|
||||||
|
}
|
||||||
|
if 'acc' in data:
|
||||||
|
kwargs['gps_accuracy'] = data['acc']
|
||||||
|
if 'batt' in data:
|
||||||
|
kwargs['battery'] = data['batt']
|
||||||
|
|
||||||
|
see(**kwargs)
|
||||||
|
|
||||||
mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1)
|
mqtt.subscribe(hass, LOCATION_TOPIC, owntracks_location_update, 1)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ from homeassistant.const import (
|
|||||||
|
|
||||||
DOMAIN = "discovery"
|
DOMAIN = "discovery"
|
||||||
DEPENDENCIES = []
|
DEPENDENCIES = []
|
||||||
REQUIREMENTS = ['netdisco==0.4']
|
REQUIREMENTS = ['netdisco==0.4.1']
|
||||||
|
|
||||||
SCAN_INTERVAL = 300 # seconds
|
SCAN_INTERVAL = 300 # seconds
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
FRONTEND_URLS = [
|
FRONTEND_URLS = [
|
||||||
URL_ROOT, '/logbook', '/history', '/devService', '/devState', '/devEvent']
|
URL_ROOT, '/logbook', '/history', '/map', '/devService', '/devState',
|
||||||
|
'/devEvent']
|
||||||
STATES_URL = re.compile(r'/states(/([a-zA-Z\._\-0-9/]+)|)')
|
STATES_URL = re.compile(r'/states(/([a-zA-Z\._\-0-9/]+)|)')
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
""" DO NOT MODIFY. Auto-generated by build_frontend script """
|
""" DO NOT MODIFY. Auto-generated by build_frontend script """
|
||||||
VERSION = "5f35285bc502e3f69f564240fee04baa"
|
VERSION = "3a3ed81f9d66bf24e17f1d02b8403335"
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
Subproject commit 68f6c6ae5d37a1f0fcd1c36a8803581f9367ac5f
|
Subproject commit 6989009b2d59e39fd39b3025ff5899877f618bd3
|
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 797 B |
@ -12,6 +12,7 @@ from tellcore.library import DirectCallbackDispatcher
|
|||||||
REQUIREMENTS = ['tellcore-py==1.0.4']
|
REQUIREMENTS = ['tellcore-py==1.0.4']
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||||
""" Find and return Tellstick lights. """
|
""" Find and return Tellstick lights. """
|
||||||
|
|
||||||
@ -36,7 +37,6 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
|||||||
if switch.methods(tellcore_constants.TELLSTICK_DIM):
|
if switch.methods(tellcore_constants.TELLSTICK_DIM):
|
||||||
lights.append(TellstickLight(switch))
|
lights.append(TellstickLight(switch))
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
|
||||||
def _device_event_callback(id_, method, data, cid):
|
def _device_event_callback(id_, method, data, cid):
|
||||||
""" Called from the TelldusCore library to update one device """
|
""" Called from the TelldusCore library to update one device """
|
||||||
for light_device in lights:
|
for light_device in lights:
|
||||||
|
188
homeassistant/components/media_player/plex.py
Normal file
188
homeassistant/components/media_player/plex.py
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
"""
|
||||||
|
homeassistant.components.media_player.plex
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Provides an interface to the Plex API
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
|
||||||
|
To use Plex add something like this to your configuration:
|
||||||
|
|
||||||
|
media_player:
|
||||||
|
platform: plex
|
||||||
|
name: plex_server
|
||||||
|
user: plex
|
||||||
|
password: my_secure_password
|
||||||
|
|
||||||
|
Variables:
|
||||||
|
|
||||||
|
name
|
||||||
|
*Required
|
||||||
|
The name of the backend device (Under Plex Media Server > settings > server).
|
||||||
|
|
||||||
|
user
|
||||||
|
*Required
|
||||||
|
The Plex username
|
||||||
|
|
||||||
|
password
|
||||||
|
*Required
|
||||||
|
The Plex password
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from homeassistant.components.media_player import (
|
||||||
|
MediaPlayerDevice, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK,
|
||||||
|
SUPPORT_NEXT_TRACK, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_VIDEO)
|
||||||
|
from homeassistant.const import (
|
||||||
|
STATE_IDLE, STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN)
|
||||||
|
|
||||||
|
REQUIREMENTS = ['https://github.com/miniconfig/python-plexapi/archive/'
|
||||||
|
'437e36dca3b7780dc0cb73941d662302c0cd2fa9.zip'
|
||||||
|
'#python-plexapi==1.0.2']
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SUPPORT_PLEX = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK
|
||||||
|
|
||||||
|
# pylint: disable=abstract-method
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
|
""" Sets up the plex platform. """
|
||||||
|
from plexapi.myplex import MyPlexUser
|
||||||
|
name = config.get('name', '')
|
||||||
|
user = config.get('user', '')
|
||||||
|
password = config.get('password', '')
|
||||||
|
plexuser = MyPlexUser.signin(user, password)
|
||||||
|
plexserver = plexuser.getResource(name).connect()
|
||||||
|
dev = plexserver.clients()
|
||||||
|
for device in dev:
|
||||||
|
if "PlayStation" not in device.name:
|
||||||
|
add_devices([PlexClient(device.name, plexserver)])
|
||||||
|
|
||||||
|
|
||||||
|
class PlexClient(MediaPlayerDevice):
|
||||||
|
""" Represents a Plex device. """
|
||||||
|
|
||||||
|
# pylint: disable=too-many-public-methods
|
||||||
|
|
||||||
|
def __init__(self, name, plexserver):
|
||||||
|
self.client = plexserver.client(name)
|
||||||
|
self._name = name
|
||||||
|
self._media = None
|
||||||
|
self.update()
|
||||||
|
self.server = plexserver
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
""" Returns the name of the device. """
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self):
|
||||||
|
""" Returns the state of the device. """
|
||||||
|
if self._media is None:
|
||||||
|
return STATE_IDLE
|
||||||
|
else:
|
||||||
|
state = self._media.get('state')
|
||||||
|
if state == 'playing':
|
||||||
|
return STATE_PLAYING
|
||||||
|
elif state == 'paused':
|
||||||
|
return STATE_PAUSED
|
||||||
|
return STATE_UNKNOWN
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
timeline = self.client.timeline()
|
||||||
|
for timeline_item in timeline:
|
||||||
|
if timeline_item.get('state') in ('playing', 'paused'):
|
||||||
|
self._media = timeline_item
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_content_id(self):
|
||||||
|
""" Content ID of current playing media. """
|
||||||
|
if self._media is not None:
|
||||||
|
return self._media.get('ratingKey')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_content_type(self):
|
||||||
|
""" Content type of current playing media. """
|
||||||
|
if self._media is None:
|
||||||
|
return None
|
||||||
|
media_type = self.server.library.getByKey(
|
||||||
|
self.media_content_id).type
|
||||||
|
if media_type == 'episode':
|
||||||
|
return MEDIA_TYPE_TVSHOW
|
||||||
|
elif media_type == 'movie':
|
||||||
|
return MEDIA_TYPE_VIDEO
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_duration(self):
|
||||||
|
""" Duration of current playing media in seconds. """
|
||||||
|
if self._media is not None:
|
||||||
|
total_time = self._media.get('duration')
|
||||||
|
return total_time
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_image_url(self):
|
||||||
|
""" Image url of current playing media. """
|
||||||
|
if self._media is not None:
|
||||||
|
return self.server.library.getByKey(self.media_content_id).thumbUrl
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_title(self):
|
||||||
|
""" Title of current playing media. """
|
||||||
|
# find a string we can use as a title
|
||||||
|
if self._media is not None:
|
||||||
|
return self.server.library.getByKey(self.media_content_id).title
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_season(self):
|
||||||
|
""" Season of curent playing media. (TV Show only) """
|
||||||
|
if self._media is not None:
|
||||||
|
show_season = self.server.library.getByKey(
|
||||||
|
self.media_content_id).season().index
|
||||||
|
return show_season
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_series_title(self):
|
||||||
|
""" Series title of current playing media. (TV Show only)"""
|
||||||
|
if self._media is not None:
|
||||||
|
series_title = self.server.library.getByKey(
|
||||||
|
self.media_content_id).show().title
|
||||||
|
return series_title
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_episode(self):
|
||||||
|
""" Episode of current playing media. (TV Show only) """
|
||||||
|
if self._media is not None:
|
||||||
|
show_episode = self.server.library.getByKey(
|
||||||
|
self.media_content_id).index
|
||||||
|
return show_episode
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_media_commands(self):
|
||||||
|
""" Flags of media commands that are supported. """
|
||||||
|
return SUPPORT_PLEX
|
||||||
|
|
||||||
|
def media_play(self):
|
||||||
|
""" media_play media player. """
|
||||||
|
self.client.play()
|
||||||
|
|
||||||
|
def media_pause(self):
|
||||||
|
""" media_pause media player. """
|
||||||
|
self.client.pause()
|
||||||
|
|
||||||
|
def media_next_track(self):
|
||||||
|
""" Send next track command. """
|
||||||
|
self.client.skipNext()
|
||||||
|
|
||||||
|
def media_previous_track(self):
|
||||||
|
""" Send previous track command. """
|
||||||
|
self.client.skipPrevious()
|
@ -48,7 +48,6 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
|||||||
switches.append(
|
switches.append(
|
||||||
TellstickSwitchDevice(switch, signal_repetitions))
|
TellstickSwitchDevice(switch, signal_repetitions))
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
|
||||||
def _device_event_callback(id_, method, data, cid):
|
def _device_event_callback(id_, method, data, cid):
|
||||||
""" Called from the TelldusCore library to update one device """
|
""" Called from the TelldusCore library to update one device """
|
||||||
for switch_device in switches:
|
for switch_device in switches:
|
||||||
|
@ -86,7 +86,7 @@ https://github.com/theolind/pymysensors/archive/35b87d880147a34107da0d40cb815d75
|
|||||||
pynetgear==0.3
|
pynetgear==0.3
|
||||||
|
|
||||||
# Netdisco (discovery)
|
# Netdisco (discovery)
|
||||||
netdisco==0.4
|
netdisco==0.4.1
|
||||||
|
|
||||||
# Wemo (switch.wemo)
|
# Wemo (switch.wemo)
|
||||||
pywemo==0.3
|
pywemo==0.3
|
||||||
@ -133,3 +133,6 @@ https://github.com/balloob/home-assistant-vera-api/archive/a8f823066ead6c7da6fb5
|
|||||||
|
|
||||||
# Sonos bindings (media_player.sonos)
|
# Sonos bindings (media_player.sonos)
|
||||||
SoCo==0.11.1
|
SoCo==0.11.1
|
||||||
|
|
||||||
|
# PlexAPI (media_player.plex)
|
||||||
|
https://github.com/miniconfig/python-plexapi/archive/437e36dca3b7780dc0cb73941d662302c0cd2fa9.zip#python-plexapi==1.0.2
|
||||||
|
14
script/home-assistant@.service
Normal file
14
script/home-assistant@.service
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# This is a simple service file for systems with systemd to tun HA as user.
|
||||||
|
#
|
||||||
|
[Unit]
|
||||||
|
Description=Home Assistant for %i
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=%i
|
||||||
|
WorkingDirectory=%h
|
||||||
|
ExecStart=/usr/bin/hass --config %h/.homeassistant/
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -13,7 +13,7 @@ PYLINT_STATUS=$?
|
|||||||
|
|
||||||
if [ $FLAKE8_STATUS -eq 0 ]
|
if [ $FLAKE8_STATUS -eq 0 ]
|
||||||
then
|
then
|
||||||
exit $FLAKE8_STATUS
|
|
||||||
else
|
|
||||||
exit $PYLINT_STATUS
|
exit $PYLINT_STATUS
|
||||||
|
else
|
||||||
|
exit $FLAKE8_STATUS
|
||||||
fi
|
fi
|
||||||
|
Loading…
x
Reference in New Issue
Block a user