commit
3bbdc5bcd7
54 files changed
+750
-372
No files matched your search
@@ -31,6 +31,7 @@ omit =
|
||||
homeassistant/components/browser.py
|
||||
homeassistant/components/camera/*
|
||||
homeassistant/components/device_tracker/actiontec.py
|
||||
homeassistant/components/device_tracker/aruba.py
|
||||
homeassistant/components/device_tracker/asuswrt.py
|
||||
homeassistant/components/device_tracker/ddwrt.py
|
||||
homeassistant/components/device_tracker/luci.py
|
||||
|
||||
@@ -9,6 +9,8 @@ config/custom_components/*
|
||||
!config/custom_components/hello_world.py
|
||||
!config/custom_components/mqtt_example.py
|
||||
|
||||
tests/config/home-assistant.log
|
||||
|
||||
# Hide sublime text stuff
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
|
||||
@@ -5,6 +5,12 @@ VOLUME /config
|
||||
|
||||
RUN pip3 install --no-cache-dir -r requirements_all.txt
|
||||
|
||||
# For the nmap tracker
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends nmap net-tools && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Open Z-Wave disabled because broken
|
||||
#RUN apt-get update && \
|
||||
# apt-get install -y cython3 libudev-dev && \
|
||||
# apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
# Home Assistant [](https://travis-ci.org/balloob/home-assistant) [](https://coveralls.io/r/balloob/home-assistant?branch=master) [](https://gitter.im/balloob/home-assistant?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Home Assistant is a home automation platform running on Python 3. The goal of Home Assistant is to be able to track and control all devices at home and offer a platform for automating control. [Open a demo.](https://home-assistant.io/demo/)
|
||||
[demo]: https://home-assistant.io/demo/
|
||||
|
||||
Check out [the website](https://home-assistant.io) for installation instructions, tutorials and documentation.
|
||||
Home Assistant is a home automation platform running on Python 3. The goal of Home Assistant is to be able to track and control all devices at home and offer a platform for automating control.
|
||||
|
||||
[](https://home-assistant.io/demo/)
|
||||
To get started:
|
||||
```bash
|
||||
python3 -m pip install homeassistant
|
||||
hass --open-ui
|
||||
```
|
||||
|
||||
Check out [the website](https://home-assistant.io) for [a demo][demo], installation instructions, tutorials and documentation.
|
||||
|
||||
[][demo]
|
||||
|
||||
Examples of devices it can interface it:
|
||||
|
||||
* Monitoring connected devices to a wireless router: [OpenWrt](https://openwrt.org/), [Tomato](http://www.polarcloud.com/tomato), [Netgear](http://netgear.com), [DD-WRT](http://www.dd-wrt.com/site/index), [TPLink](http://www.tp-link.us/), and [ASUSWRT](http://event.asus.com/2013/nw/ASUSWRT/)
|
||||
* [Philips Hue](http://meethue.com) lights, [WeMo](http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/) switches, [Efergy](https://efergy.com) plugs, [Edimax](http://www.edimax.com/) switches, RFXtrx sensors, and [Tellstick](http://www.telldus.se/products/tellstick) devices and sensors
|
||||
* [Philips Hue](http://meethue.com) lights, [WeMo](http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/) switches, [Edimax](http://www.edimax.com/) switches, [Efergy](https://efergy.com) energy monitoring, RFXtrx sensors, and [Tellstick](http://www.telldus.se/products/tellstick) devices and sensors
|
||||
* [Google Chromecasts](http://www.google.com/intl/en/chrome/devices/chromecast), [Music Player Daemon](http://www.musicpd.org/), [Logitech Squeezebox](https://en.wikipedia.org/wiki/Squeezebox_%28network_music_player%29), and [Kodi (XBMC)](http://kodi.tv/)
|
||||
* Support for [ISY994](https://www.universal-devices.com/residential/isy994i-series/) (Insteon and X10 devices), [Z-Wave](http://www.z-wave.com/), [Nest Thermostats](https://nest.com/), [Arduino](https://www.arduino.cc/), [Raspberry Pi](https://www.raspberrypi.org/), and [Modbus](http://www.modbus.org/)
|
||||
* Integrate data from the [Bitcoin](https://bitcoin.org) network, meteorological data from [OpenWeatherMap](http://openweathermap.org/) and [Forecast.io](https://forecast.io/), [Transmission](http://www.transmissionbt.com/), or [SABnzbd](http://sabnzbd.org).
|
||||
@@ -21,26 +29,9 @@ Built home automation on top of your devices:
|
||||
* Turn on the lights when people get home after sun set
|
||||
* Turn on lights slowly during sun set to compensate for less light
|
||||
* Turn off all lights and devices when everybody leaves the house
|
||||
* Offers a [REST API](https://home-assistant.io/developers/api.html) for easy integration with other projects
|
||||
* Offers a [REST API](https://home-assistant.io/developers/api.html) and can interface with MQTT for easy integration with other projects
|
||||
* Allow sending notifications using [Instapush](https://instapush.im), [Notify My Android (NMA)](http://www.notifymyandroid.com/), [PushBullet](https://www.pushbullet.com/), [PushOver](https://pushover.net/), [Slack](https://slack.com/), and [Jabber (XMPP)](http://xmpp.org)
|
||||
|
||||
The system is built modular so support for other devices or actions can be implemented easily. See also the [section on architecture](https://home-assistant.io/developers/architecture.html) and the [section on creating your own components](https://home-assistant.io/developers/creating_components.html).
|
||||
|
||||
If you run into issues while using Home Assistant or during development of a component, reach out to the [Home Assistant help section](https://home-assistant.io/help/) how to reach us.
|
||||
|
||||
## Quick-start guide
|
||||
|
||||
Running Home Assistant requires [Python 3.4](https://www.python.org/). Run the following code to get up and running:
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/balloob/home-assistant.git
|
||||
python3 -m venv home-assistant
|
||||
cd home-assistant
|
||||
python3 -m homeassistant --open-ui
|
||||
```
|
||||
|
||||
The last command will start the Home Assistant server and launch its web interface. By default Home Assistant looks for the configuration file `config/configuration.yaml`. A standard configuration file will be written if none exists.
|
||||
|
||||
If you are still exploring if you want to use Home Assistant in the first place, you can enable the demo mode by adding the `--demo-mode` argument to the last command.
|
||||
|
||||
Please see [the getting started guide](https://home-assistant.io/getting-started/) on how to further configure Home Assistant.
|
||||
If you run into issues while using Home Assistant or during development of a component, check the [Home Assistant help section](https://home-assistant.io/help/) how to reach us.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 53 KiB |
@@ -7,7 +7,16 @@ import argparse
|
||||
|
||||
from homeassistant import bootstrap
|
||||
import homeassistant.config as config_util
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||
from homeassistant.const import __version__, EVENT_HOMEASSISTANT_START
|
||||
|
||||
|
||||
def validate_python():
|
||||
""" Validate we're running the right Python version. """
|
||||
major, minor = sys.version_info[:2]
|
||||
|
||||
if major < 3 or (major == 3 and minor < 4):
|
||||
print("Home Assistant requires atleast Python 3.4")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def ensure_config_path(config_dir):
|
||||
@@ -54,6 +63,7 @@ def get_arguments():
|
||||
""" Get parsed passed in arguments. """
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Home Assistant: Observe, Control, Automate.")
|
||||
parser.add_argument('--version', action='version', version=__version__)
|
||||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
metavar='path_to_config_dir',
|
||||
@@ -67,25 +77,99 @@ def get_arguments():
|
||||
'--open-ui',
|
||||
action='store_true',
|
||||
help='Open the webinterface in a browser')
|
||||
parser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
help="Enable verbose logging to file.")
|
||||
parser.add_argument(
|
||||
'--pid-file',
|
||||
metavar='path_to_pid_file',
|
||||
default=None,
|
||||
help='Path to PID file useful for running as daemon')
|
||||
if os.name != "nt":
|
||||
parser.add_argument(
|
||||
'--daemon',
|
||||
action='store_true',
|
||||
help='Run Home Assistant as daemon')
|
||||
|
||||
return parser.parse_args()
|
||||
arguments = parser.parse_args()
|
||||
if os.name == "nt":
|
||||
arguments.daemon = False
|
||||
return arguments
|
||||
|
||||
|
||||
def daemonize():
|
||||
""" Move current process to daemon process """
|
||||
# create first fork
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
sys.exit(0)
|
||||
|
||||
# decouple fork
|
||||
os.setsid()
|
||||
os.umask(0)
|
||||
|
||||
# create second fork
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def check_pid(pid_file):
|
||||
""" Check that HA is not already running """
|
||||
# check pid file
|
||||
try:
|
||||
pid = int(open(pid_file, 'r').readline())
|
||||
except IOError:
|
||||
# PID File does not exist
|
||||
return
|
||||
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError:
|
||||
# PID does not exist
|
||||
return
|
||||
print('Fatal Error: HomeAssistant is already running.')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def write_pid(pid_file):
|
||||
""" Create PID File """
|
||||
pid = os.getpid()
|
||||
try:
|
||||
open(pid_file, 'w').write(str(pid))
|
||||
except IOError:
|
||||
print('Fatal Error: Unable to write pid file {}'.format(pid_file))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
""" Starts Home Assistant. """
|
||||
validate_python()
|
||||
|
||||
args = get_arguments()
|
||||
|
||||
config_dir = os.path.join(os.getcwd(), args.config)
|
||||
ensure_config_path(config_dir)
|
||||
|
||||
# daemon functions
|
||||
if args.pid_file:
|
||||
check_pid(args.pid_file)
|
||||
if args.daemon:
|
||||
daemonize()
|
||||
if args.pid_file:
|
||||
write_pid(args.pid_file)
|
||||
|
||||
if args.demo_mode:
|
||||
hass = bootstrap.from_config_dict({
|
||||
'frontend': {},
|
||||
'demo': {}
|
||||
}, config_dir=config_dir)
|
||||
}, config_dir=config_dir, daemon=args.daemon, verbose=args.verbose)
|
||||
else:
|
||||
config_file = ensure_config_file(config_dir)
|
||||
hass = bootstrap.from_config_file(config_file)
|
||||
print('Config directory:', config_dir)
|
||||
hass = bootstrap.from_config_file(
|
||||
config_file, daemon=args.daemon, verbose=args.verbose)
|
||||
|
||||
if args.open_ui:
|
||||
def open_browser(event):
|
||||
|
||||
+34
-31
@@ -53,9 +53,6 @@ def setup_component(hass, domain, config=None):
|
||||
return False
|
||||
|
||||
for component in components:
|
||||
if component in hass.config.components:
|
||||
continue
|
||||
|
||||
if not _setup_component(hass, component, config):
|
||||
return False
|
||||
|
||||
@@ -78,6 +75,8 @@ def _handle_requirements(hass, component, name):
|
||||
|
||||
def _setup_component(hass, domain, config):
|
||||
""" Setup a component for Home Assistant. """
|
||||
if domain in hass.config.components:
|
||||
return True
|
||||
component = loader.get_component(domain)
|
||||
|
||||
missing_deps = [dep for dep in component.DEPENDENCIES
|
||||
@@ -150,8 +149,9 @@ def mount_local_lib_path(config_dir):
|
||||
sys.path.insert(0, os.path.join(config_dir, 'lib'))
|
||||
|
||||
|
||||
# pylint: disable=too-many-branches, too-many-statements
|
||||
def from_config_dict(config, hass=None, config_dir=None, enable_log=True):
|
||||
# pylint: disable=too-many-branches, too-many-statements, too-many-arguments
|
||||
def from_config_dict(config, hass=None, config_dir=None, enable_log=True,
|
||||
verbose=False, daemon=False):
|
||||
"""
|
||||
Tries to configure Home Assistant from a config dict.
|
||||
|
||||
@@ -167,7 +167,7 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True):
|
||||
process_ha_core_config(hass, config.get(core.DOMAIN, {}))
|
||||
|
||||
if enable_log:
|
||||
enable_logging(hass)
|
||||
enable_logging(hass, verbose, daemon)
|
||||
|
||||
_ensure_loader_prepared(hass)
|
||||
|
||||
@@ -196,7 +196,7 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True):
|
||||
return hass
|
||||
|
||||
|
||||
def from_config_file(config_path, hass=None):
|
||||
def from_config_file(config_path, hass=None, verbose=False, daemon=False):
|
||||
"""
|
||||
Reads the configuration file and tries to start all the required
|
||||
functionality. Will add functionality to 'hass' parameter if given,
|
||||
@@ -210,35 +210,36 @@ def from_config_file(config_path, hass=None):
|
||||
hass.config.config_dir = config_dir
|
||||
mount_local_lib_path(config_dir)
|
||||
|
||||
enable_logging(hass)
|
||||
enable_logging(hass, verbose, daemon)
|
||||
|
||||
config_dict = config_util.load_config_file(config_path)
|
||||
|
||||
return from_config_dict(config_dict, hass, enable_log=False)
|
||||
|
||||
|
||||
def enable_logging(hass):
|
||||
def enable_logging(hass, verbose=False, daemon=False):
|
||||
""" Setup the logging for home assistant. """
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) "
|
||||
"[%(name)s] %(message)s%(reset)s")
|
||||
try:
|
||||
from colorlog import ColoredFormatter
|
||||
logging.getLogger().handlers[0].setFormatter(ColoredFormatter(
|
||||
fmt,
|
||||
datefmt='%y-%m-%d %H:%M:%S',
|
||||
reset=True,
|
||||
log_colors={
|
||||
'DEBUG': 'cyan',
|
||||
'INFO': 'green',
|
||||
'WARNING': 'yellow',
|
||||
'ERROR': 'red',
|
||||
'CRITICAL': 'red',
|
||||
}
|
||||
))
|
||||
except ImportError:
|
||||
_LOGGER.warning(
|
||||
"Colorlog package not found, console coloring disabled")
|
||||
if not daemon:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) "
|
||||
"[%(name)s] %(message)s%(reset)s")
|
||||
try:
|
||||
from colorlog import ColoredFormatter
|
||||
logging.getLogger().handlers[0].setFormatter(ColoredFormatter(
|
||||
fmt,
|
||||
datefmt='%y-%m-%d %H:%M:%S',
|
||||
reset=True,
|
||||
log_colors={
|
||||
'DEBUG': 'cyan',
|
||||
'INFO': 'green',
|
||||
'WARNING': 'yellow',
|
||||
'ERROR': 'red',
|
||||
'CRITICAL': 'red',
|
||||
}
|
||||
))
|
||||
except ImportError:
|
||||
_LOGGER.warning(
|
||||
"Colorlog package not found, console coloring disabled")
|
||||
|
||||
# Log errors to a file if we have write access to file or config dir
|
||||
err_log_path = hass.config.path('home-assistant.log')
|
||||
@@ -252,11 +253,13 @@ def enable_logging(hass):
|
||||
err_handler = logging.FileHandler(
|
||||
err_log_path, mode='w', delay=True)
|
||||
|
||||
err_handler.setLevel(logging.WARNING)
|
||||
err_handler.setLevel(logging.INFO if verbose else logging.WARNING)
|
||||
err_handler.setFormatter(
|
||||
logging.Formatter('%(asctime)s %(name)s: %(message)s',
|
||||
datefmt='%y-%m-%d %H:%M:%S'))
|
||||
logging.getLogger('').addHandler(err_handler)
|
||||
logger = logging.getLogger('')
|
||||
logger.addHandler(err_handler)
|
||||
logger.setLevel(logging.INFO) # this sets the minimum log level
|
||||
|
||||
else:
|
||||
_LOGGER.error(
|
||||
|
||||
@@ -10,7 +10,7 @@ import re
|
||||
|
||||
from homeassistant import core
|
||||
from homeassistant.const import (
|
||||
ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF)
|
||||
ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF)
|
||||
|
||||
DOMAIN = "conversation"
|
||||
DEPENDENCIES = []
|
||||
@@ -44,7 +44,7 @@ def setup(hass, config):
|
||||
|
||||
entity_ids = [
|
||||
state.entity_id for state in hass.states.all()
|
||||
if state.attributes.get(ATTR_FRIENDLY_NAME, "").lower() == name]
|
||||
if state.name.lower() == name]
|
||||
|
||||
if not entity_ids:
|
||||
logger.error(
|
||||
|
||||
@@ -46,12 +46,12 @@ def setup(hass, config):
|
||||
hass, component, {component: {CONF_PLATFORM: 'demo'}})
|
||||
|
||||
# Setup room groups
|
||||
lights = hass.states.entity_ids('light')
|
||||
switches = hass.states.entity_ids('switch')
|
||||
lights = sorted(hass.states.entity_ids('light'))
|
||||
switches = sorted(hass.states.entity_ids('switch'))
|
||||
media_players = sorted(hass.states.entity_ids('media_player'))
|
||||
group.setup_group(hass, 'living room', [lights[0], lights[1], switches[0],
|
||||
group.setup_group(hass, 'living room', [lights[2], lights[1], switches[0],
|
||||
media_players[1]])
|
||||
group.setup_group(hass, 'bedroom', [lights[2], switches[1],
|
||||
group.setup_group(hass, 'bedroom', [lights[0], switches[1],
|
||||
media_players[0]])
|
||||
|
||||
# Setup IP Camera
|
||||
@@ -68,7 +68,7 @@ def setup(hass, config):
|
||||
hass, 'script',
|
||||
{'script': {
|
||||
'demo': {
|
||||
'alias': 'Demo {}'.format(lights[0]),
|
||||
'alias': 'Toggle {}'.format(lights[0].split('.')[1]),
|
||||
'sequence': [{
|
||||
'execute_service': 'light.turn_off',
|
||||
'service_data': {ATTR_ENTITY_ID: lights[0]}
|
||||
|
||||
@@ -10,11 +10,11 @@ import os
|
||||
import csv
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.helpers.entity import _OVERWRITE
|
||||
import homeassistant.util as util
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.bootstrap import prepare_setup_platform
|
||||
|
||||
from homeassistant.helpers.event import track_utc_time_change
|
||||
from homeassistant.const import (
|
||||
@@ -63,8 +63,8 @@ def setup(hass, config):
|
||||
|
||||
tracker_type = config[DOMAIN].get(CONF_PLATFORM)
|
||||
|
||||
tracker_implementation = get_component(
|
||||
'device_tracker.{}'.format(tracker_type))
|
||||
tracker_implementation = \
|
||||
prepare_setup_platform(hass, config, DOMAIN, tracker_type)
|
||||
|
||||
if tracker_implementation is None:
|
||||
_LOGGER.error("Unknown device_tracker type specified: %s.",
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
"""
|
||||
homeassistant.components.device_tracker.aruba
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Device tracker platform that supports scanning a Aruba Access Point for device
|
||||
presence.
|
||||
|
||||
This device tracker needs telnet to be enabled on the router.
|
||||
|
||||
Configuration:
|
||||
|
||||
To use the Aruba tracker you will need to add something like the following
|
||||
to your config/configuration.yaml. You also need to enable Telnet in the
|
||||
configuration pages.
|
||||
|
||||
device_tracker:
|
||||
platform: aruba
|
||||
host: YOUR_ACCESS_POINT_IP
|
||||
username: YOUR_ADMIN_USERNAME
|
||||
password: YOUR_ADMIN_PASSWORD
|
||||
|
||||
Variables:
|
||||
|
||||
host
|
||||
*Required
|
||||
The IP address of your router, e.g. 192.168.1.1.
|
||||
|
||||
username
|
||||
*Required
|
||||
The username of an user with administrative privileges, usually 'admin'.
|
||||
|
||||
password
|
||||
*Required
|
||||
The password for your given admin account.
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
import re
|
||||
import threading
|
||||
import telnetlib
|
||||
|
||||
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.components.device_tracker import DOMAIN
|
||||
|
||||
# Return cached results if last scan was less then this time ago
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_DEVICES_REGEX = re.compile(
|
||||
r'(?P<name>([^\s]+))\s+' +
|
||||
r'(?P<ip>([0-9]{1,3}[\.]){3}[0-9]{1,3})\s+' +
|
||||
r'(?P<mac>(([0-9a-f]{2}[:-]){5}([0-9a-f]{2})))\s+' +
|
||||
r'(?P<os>([^\s]+))\s+' +
|
||||
r'(?P<network>([^\s]+))\s+' +
|
||||
r'(?P<ap>([^\s]+))\s+' +
|
||||
r'(?P<channel>([^\s]+))\s+' +
|
||||
r'(?P<type>([^\s]+))\s+' +
|
||||
r'(?P<role>([^\s]+))\s+' +
|
||||
r'(?P<signal>([^\s]+))\s+' +
|
||||
r'(?P<speed>([^\s]+))')
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_scanner(hass, config):
|
||||
""" Validates config and returns a Aruba scanner. """
|
||||
if not validate_config(config,
|
||||
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
|
||||
_LOGGER):
|
||||
return None
|
||||
|
||||
scanner = ArubaDeviceScanner(config[DOMAIN])
|
||||
|
||||
return scanner if scanner.success_init else None
|
||||
|
||||
|
||||
class ArubaDeviceScanner(object):
|
||||
""" This class queries a Aruba Acces Point for connected devices. """
|
||||
def __init__(self, config):
|
||||
self.host = config[CONF_HOST]
|
||||
self.username = config[CONF_USERNAME]
|
||||
self.password = config[CONF_PASSWORD]
|
||||
|
||||
self.lock = threading.Lock()
|
||||
|
||||
self.last_results = {}
|
||||
|
||||
# Test the router is accessible
|
||||
data = self.get_aruba_data()
|
||||
self.success_init = data is not None
|
||||
|
||||
def scan_devices(self):
|
||||
""" Scans for new devices and return a list containing found device
|
||||
ids. """
|
||||
|
||||
self._update_info()
|
||||
return [client['mac'] for client in self.last_results]
|
||||
|
||||
def get_device_name(self, device):
|
||||
""" Returns the name of the given device or None if we don't know. """
|
||||
if not self.last_results:
|
||||
return None
|
||||
for client in self.last_results:
|
||||
if client['mac'] == device:
|
||||
return client['name']
|
||||
return None
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_SCANS)
|
||||
def _update_info(self):
|
||||
""" Ensures the information from the Aruba Access Point is up to date.
|
||||
Returns boolean if scanning successful. """
|
||||
if not self.success_init:
|
||||
return False
|
||||
|
||||
with self.lock:
|
||||
data = self.get_aruba_data()
|
||||
if not data:
|
||||
return False
|
||||
|
||||
self.last_results = data.values()
|
||||
return True
|
||||
|
||||
def get_aruba_data(self):
|
||||
""" Retrieve data from Aruba Access Point and return parsed
|
||||
result. """
|
||||
try:
|
||||
telnet = telnetlib.Telnet(self.host)
|
||||
telnet.read_until(b'User: ')
|
||||
telnet.write((self.username + '\r\n').encode('ascii'))
|
||||
telnet.read_until(b'Password: ')
|
||||
telnet.write((self.password + '\r\n').encode('ascii'))
|
||||
telnet.read_until(b'#')
|
||||
telnet.write(('show clients\r\n').encode('ascii'))
|
||||
devices_result = telnet.read_until(b'#').split(b'\r\n')
|
||||
telnet.write('exit\r\n'.encode('ascii'))
|
||||
except EOFError:
|
||||
_LOGGER.exception("Unexpected response from router")
|
||||
return
|
||||
except ConnectionRefusedError:
|
||||
_LOGGER.exception("Connection refused by router," +
|
||||
" is telnet enabled?")
|
||||
return
|
||||
|
||||
devices = {}
|
||||
for device in devices_result:
|
||||
match = _DEVICES_REGEX.search(device.decode('utf-8'))
|
||||
if match:
|
||||
devices[match.group('ip')] = {
|
||||
'ip': match.group('ip'),
|
||||
'mac': match.group('mac').upper(),
|
||||
'name': match.group('name')
|
||||
}
|
||||
return devices
|
||||
@@ -19,6 +19,11 @@ hosts
|
||||
*Required
|
||||
The IP addresses to scan in the network-prefix notation (192.168.1.1/24) or
|
||||
the range notation (192.168.1.1-255).
|
||||
|
||||
home_interval
|
||||
*Optional
|
||||
Number of minutes it will not scan devices that it found in previous results.
|
||||
This is to save battery.
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
@@ -26,13 +31,6 @@ from collections import namedtuple
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
try:
|
||||
from libnmap.process import NmapProcess
|
||||
from libnmap.parser import NmapParser, NmapParserException
|
||||
LIB_LOADED = True
|
||||
except ImportError:
|
||||
LIB_LOADED = False
|
||||
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.const import CONF_HOSTS
|
||||
from homeassistant.helpers import validate_config
|
||||
@@ -47,7 +45,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||
# interval in minutes to exclude devices from a scan while they are home
|
||||
CONF_HOME_INTERVAL = "home_interval"
|
||||
|
||||
REQUIREMENTS = ['python-libnmap==0.6.1']
|
||||
REQUIREMENTS = ['python-nmap==0.4.1']
|
||||
|
||||
|
||||
def get_scanner(hass, config):
|
||||
@@ -56,10 +54,6 @@ def get_scanner(hass, config):
|
||||
_LOGGER):
|
||||
return None
|
||||
|
||||
if not LIB_LOADED:
|
||||
_LOGGER.error("Error while importing dependency python-libnmap.")
|
||||
return False
|
||||
|
||||
scanner = NmapDeviceScanner(config[DOMAIN])
|
||||
|
||||
return scanner if scanner.success_init else None
|
||||
@@ -76,7 +70,7 @@ def _arp(ip_address):
|
||||
if match:
|
||||
return match.group(0)
|
||||
_LOGGER.info("No MAC address found for %s", ip_address)
|
||||
return ''
|
||||
return None
|
||||
|
||||
|
||||
class NmapDeviceScanner(object):
|
||||
@@ -89,8 +83,7 @@ class NmapDeviceScanner(object):
|
||||
minutes = convert(config.get(CONF_HOME_INTERVAL), int, 0)
|
||||
self.home_interval = timedelta(minutes=minutes)
|
||||
|
||||
self.success_init = True
|
||||
self._update_info()
|
||||
self.success_init = self._update_info()
|
||||
_LOGGER.info("nmap scanner initialized")
|
||||
|
||||
def scan_devices(self):
|
||||
@@ -112,43 +105,16 @@ class NmapDeviceScanner(object):
|
||||
else:
|
||||
return None
|
||||
|
||||
def _parse_results(self, stdout):
|
||||
""" Parses results from an nmap scan.
|
||||
Returns True if successful, False otherwise. """
|
||||
try:
|
||||
results = NmapParser.parse(stdout)
|
||||
now = dt_util.now()
|
||||
self.last_results = []
|
||||
for host in results.hosts:
|
||||
if host.is_up():
|
||||
if host.hostnames:
|
||||
name = host.hostnames[0]
|
||||
else:
|
||||
name = host.ipv4
|
||||
if host.mac:
|
||||
mac = host.mac
|
||||
else:
|
||||
mac = _arp(host.ipv4)
|
||||
if mac:
|
||||
device = Device(mac.upper(), name, host.ipv4, now)
|
||||
self.last_results.append(device)
|
||||
_LOGGER.info("nmap scan successful")
|
||||
return True
|
||||
except NmapParserException as parse_exc:
|
||||
_LOGGER.error("failed to parse nmap results: %s", parse_exc.msg)
|
||||
self.last_results = []
|
||||
return False
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_SCANS)
|
||||
def _update_info(self):
|
||||
""" Scans the network for devices.
|
||||
Returns boolean if scanning successful. """
|
||||
if not self.success_init:
|
||||
return False
|
||||
|
||||
_LOGGER.info("Scanning")
|
||||
|
||||
options = "-F --host-timeout 5"
|
||||
from nmap import PortScanner, PortScannerError
|
||||
scanner = PortScanner()
|
||||
|
||||
options = "-sP --host-timeout 5"
|
||||
exclude_targets = set()
|
||||
if self.home_interval:
|
||||
now = dt_util.now()
|
||||
@@ -159,14 +125,24 @@ class NmapDeviceScanner(object):
|
||||
target_list = [t.ip for t in exclude_targets]
|
||||
options += " --exclude {}".format(",".join(target_list))
|
||||
|
||||
nmap = NmapProcess(targets=self.hosts, options=options)
|
||||
|
||||
nmap.run()
|
||||
|
||||
if nmap.rc == 0:
|
||||
if self._parse_results(nmap.stdout):
|
||||
self.last_results.extend(exclude_targets)
|
||||
else:
|
||||
self.last_results = []
|
||||
_LOGGER.error(nmap.stderr)
|
||||
try:
|
||||
result = scanner.scan(hosts=self.hosts, arguments=options)
|
||||
except PortScannerError:
|
||||
return False
|
||||
|
||||
now = dt_util.now()
|
||||
self.last_results = []
|
||||
for ipv4, info in result['scan'].items():
|
||||
if info['status']['state'] != 'up':
|
||||
continue
|
||||
name = info['hostnames'][0] if info['hostnames'] else ipv4
|
||||
# Mac address only returned if nmap ran as root
|
||||
mac = info['addresses'].get('mac') or _arp(ipv4)
|
||||
if mac is None:
|
||||
continue
|
||||
device = Device(mac.upper(), name, ipv4, now)
|
||||
self.last_results.append(device)
|
||||
self.last_results.extend(exclude_targets)
|
||||
|
||||
_LOGGER.info("nmap scan successful")
|
||||
return True
|
||||
@@ -33,15 +33,16 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
#init p {
|
||||
margin-bottom: 101px;
|
||||
#init div {
|
||||
line-height: 34px;
|
||||
margin-bottom: 89px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body fullbleed>
|
||||
<div id='init'>
|
||||
<img src='/static/splash.png' height='230' />
|
||||
<p>Initializing</p>
|
||||
<div>Initializing</div>
|
||||
</div>
|
||||
<script src='/static/webcomponents-lite.min.js'></script>
|
||||
<link rel='import' href='/static/{{ app_url }}' />
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
""" DO NOT MODIFY. Auto-generated by build_frontend script """
|
||||
VERSION = "e9060d58fc9034468cfefa9794026d0c"
|
||||
VERSION = "35ecb5457a9ff0f4142c2605b53eb843"
|
||||
@@ -3768,7 +3768,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
pointer-events: none;
|
||||
}</style><template><div id="toggleContainer"><div id="toggleBar" class="toggle-bar"></div><div id="toggleButton" class="toggle-button"><paper-ripple id="ink" class="toggle-ink circle" recenters=""></paper-ripple></div></div></template><script>Polymer({is:"paper-toggle-button",behaviors:[Polymer.PaperInkyFocusBehavior],hostAttributes:{role:"button","aria-pressed":"false",tabindex:0},properties:{checked:{type:Boolean,value:!1,reflectToAttribute:!0,notify:!0,observer:"_checkedChanged"},toggles:{type:Boolean,value:!0,reflectToAttribute:!0}},listeners:{track:"_ontrack"},ready:function(){this._isReady=!0},_buttonStateChanged:function(){this.disabled||this._isReady&&(this.checked=this.active)},_checkedChanged:function(t){this.active=this.checked,this.fire("iron-change")},_ontrack:function(t){var e=t.detail;"start"===e.state?this._trackStart(e):"track"===e.state?this._trackMove(e):"end"===e.state&&this._trackEnd(e)},_trackStart:function(t){this._width=this.$.toggleBar.offsetWidth/2,this._trackChecked=this.checked,this.$.toggleButton.classList.add("dragging")},_trackMove:function(t){var e=t.dx;this._x=Math.min(this._width,Math.max(0,this._trackChecked?this._width+e:e)),this.translate3d(this._x+"px",0,0,this.$.toggleButton),this._userActivate(this._x>this._width/2)},_trackEnd:function(t){this.$.toggleButton.classList.remove("dragging"),this.transform("",this.$.toggleButton)}});</script></dom-module><dom-module id="state-card-toggle" assetpath="state-summary/"><style>paper-toggle-button {
|
||||
margin-left: 16px;
|
||||
}</style><template><div class="horizontal justified layout"><state-info state-obj="[[stateObj]]"></state-info><paper-toggle-button class="self-center" checked="[[toggleChecked]]" on-change="toggleChanged" on-click="toggleTapped"></paper-toggle-button></div></template></dom-module><dom-module id="state-card-thermostat" assetpath="state-summary/"><style>:host {
|
||||
}</style><template><div class="horizontal justified layout"><state-info state-obj="[[stateObj]]"></state-info><paper-toggle-button class="self-center" checked="[[toggleChecked]]" on-change="toggleChanged"></paper-toggle-button></div></template></dom-module><dom-module id="state-card-thermostat" assetpath="state-summary/"><style>:host {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@@ -3825,7 +3825,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
.content {
|
||||
padding: 0 16px 16px;
|
||||
}</style><template><ha-card header="Welcome Home!"><div class="content">Here are some resources to get started.<ul><li><a href="https://home-assistant.io/getting-started/configuration.html" target="_blank">Configuring Home Assistant</a></li><li><a href="https://home-assistant.io/components/" target="_blank">Available components</a></li><li><a href="https://gitter.im/balloob/home-assistant" target="_blank">Chat room</a></li></ul><template is="dom-if" if="[[showHideInstruction]]">To remove this card, edit your config in <code>configuration.yaml</code> and disable the <code>introduction</code> component.</template></div></ha-card></template></dom-module><dom-module id="ha-zone-cards" assetpath="components/"><style>:host {
|
||||
}
|
||||
.install {
|
||||
display: block;
|
||||
line-height: 1.5em;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 16px;
|
||||
}</style><template><ha-card header="Welcome Home!"><div class="content"><template is="dom-if" if="[[showInstallInstruction]]">To install Home Assistant, run:<br><code class="install">pip3 install homeassistant<br>hass --open-ui</code></template>Here are some resources to get started.<ul><template is="dom-if" if="[[showInstallInstruction]]"><li><a href="https://home-assistant.io/getting-started/">Installation instructions per platform</a></li><li><a href="https://home-assistant.io/getting-started/troubleshooting.html">Troubleshooting your installation</a></li></template><li><a href="https://home-assistant.io/getting-started/configuration.html" target="_blank">Configuring Home Assistant</a></li><li><a href="https://home-assistant.io/components/" target="_blank">Available components</a></li><li><a href="https://home-assistant.io/getting-started/troubleshooting-configuration.html">Troubleshooting your configuration</a></li><li><a href="https://home-assistant.io/help/" target="_blank">Getting help</a></li></ul><template is="dom-if" if="[[showHideInstruction]]">To remove this card, edit your config in <code>configuration.yaml</code> and disable the <code>introduction</code> component.</template></div></ha-card></template></dom-module><dom-module id="ha-zone-cards" assetpath="components/"><style>:host {
|
||||
display: block;
|
||||
padding-right: 8px;
|
||||
}
|
||||
@@ -5044,6 +5050,7 @@ paper-ripple {
|
||||
}
|
||||
|
||||
paper-icon-item {
|
||||
padding-left: 24px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -5077,9 +5084,9 @@ paper-ripple {
|
||||
}</style><template><template is="dom-if" if="[[!loaded]]"><login-form></login-form></template><template is="dom-if" if="[[loaded]]"><home-assistant-main></home-assistant-main></template></template></dom-module><script>!function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(1),o=r(i),u=n(2),a=n(4),s=r(a),c=n(64),l=r(c);n(152),n(151),e["default"]=new o["default"]({is:"home-assistant",hostAttributes:{auth:null},behaviors:[s["default"]],properties:{auth:{type:String},loaded:{type:Boolean,bindNuclear:u.syncGetters.isDataLoaded}},ready:function(){var t=this;u.reactor.batch(function(){t.auth?l["default"](t.auth,!1):u.localStoragePreferences.authToken&&l["default"](u.localStoragePreferences.authToken,!0),u.navigationActions.showSidebar(u.localStoragePreferences.showSidebar)}),u.startLocalStoragePreferencesSync();var e=document.getElementById("init");e.parentElement.removeChild(e)}}),t.exports=e["default"]},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=window.Polymer,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(85),o=r(i);e["default"]=new o["default"],t.exports=e["default"]},function(t,e,n){"use strict";!function(e,n){t.exports=n()}(void 0,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){var r=n(1);e.Reactor=n(4),e.Store=n(13),e.Immutable=n(2),e.isKeyPath=n(10).isKeyPath,e.isGetter=n(9).isGetter,e.toJS=r.toJS,e.toImmutable=r.toImmutable,e.isImmutable=r.isImmutable,e.createReactMixin=n(12)},function(t,e,n){function r(t){return a.Iterable.isIterable(t)}function i(t){return r(t)||!s(t)}function o(t){return r(t)?t.toJS():t}function u(t){return r(t)?t:a.fromJS(t)}var a=n(2),s=n(3).isObject;e.toJS=o,e.toImmutable=u,e.isImmutable=r,e.isImmutableValue=i},function(t,e,n){!function(e,n){t.exports=n()}(this,function(){function t(t,e){e&&(t.prototype=Object.create(e.prototype)),t.prototype.constructor=t}function e(t){return t.value=!1,t}function n(t){t&&(t.value=!0)}function r(){}function i(t,e){e=e||0;for(var n=Math.max(0,t.length-e),r=new Array(n),i=0;n>i;i++)r[i]=t[i+e];return r}function o(t){return void 0===t.size&&(t.size=t.__iterate(a)),t.size}function u(t,e){return e>=0?+e:o(t)+ +e}function a(){return!0}function s(t,e,n){return(0===t||void 0!==n&&-n>=t)&&(void 0===e||void 0!==n&&e>=n)}function c(t,e){return f(t,e,0)}function l(t,e){return f(t,e,e)}function f(t,e,n){return void 0===t?n:0>t?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}function d(t){return _(t)?t:P(t)}function p(t){return y(t)?t:D(t)}function h(t){return m(t)?t:C(t)}function v(t){return _(t)&&!g(t)?t:A(t)}function _(t){return!(!t||!t[vn])}function y(t){return!(!t||!t[_n])}function m(t){return!(!t||!t[yn])}function g(t){return y(t)||m(t)}function b(t){return!(!t||!t[mn])}function O(t){this.next=t}function w(t,e,n,r){var i=0===t?e:1===t?n:[e,n];return r?r.value=i:r={value:i,done:!1},r}function S(){return{value:void 0,done:!0}}function M(t){return!!E(t)}function T(t){return t&&"function"==typeof t.next}function j(t){var e=E(t);return e&&e.call(t)}function E(t){var e=t&&(wn&&t[wn]||t[Sn]);return"function"==typeof e?e:void 0}function I(t){return t&&"number"==typeof t.length}function P(t){return null===t||void 0===t?z():_(t)?t.toSeq():G(t)}function D(t){return null===t||void 0===t?z().toKeyedSeq():_(t)?y(t)?t.toSeq():t.fromEntrySeq():H(t)}function C(t){return null===t||void 0===t?z():_(t)?y(t)?t.entrySeq():t.toIndexedSeq():Y(t)}function A(t){return(null===t||void 0===t?z():_(t)?y(t)?t.entrySeq():t:Y(t)).toSetSeq()}function x(t){this._array=t,this.size=t.length}function k(t){var e=Object.keys(t);this._object=t,this._keys=e,this.size=e.length}function L(t){this._iterable=t,this.size=t.length||t.size}function N(t){this._iterator=t,this._iteratorCache=[]}function R(t){return!(!t||!t[Tn])}function z(){return jn||(jn=new x([]))}function H(t){var e=Array.isArray(t)?new x(t).fromEntrySeq():T(t)?new N(t).fromEntrySeq():M(t)?new L(t).fromEntrySeq():"object"==typeof t?new k(t):void 0;if(!e)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+t);return e}function Y(t){var e=U(t);if(!e)throw new TypeError("Expected Array or iterable object of values: "+t);return e}function G(t){var e=U(t)||"object"==typeof t&&new k(t);if(!e)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+t);return e}function U(t){return I(t)?new x(t):T(t)?new N(t):M(t)?new L(t):void 0}function F(t,e,n,r){var i=t._cLine truncated
|
||||
},Rt.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},Rt.prototype.set=function(t,e){return Jt(this,t,e)},Rt.prototype.setIn=function(t,e){return this.updateIn(t,dn,function(){return e})},Rt.prototype.remove=function(t){return Jt(this,t,dn)},Rt.prototype.deleteIn=function(t){return this.updateIn(t,function(){return dn})},Rt.prototype.update=function(t,e,n){return 1===arguments.length?t(this):this.updateIn([t],e,n)},Rt.prototype.updateIn=function(t,e,n){n||(n=e,e=void 0);var r=oe(this,Nt(t),e,n);return r===dn?void 0:r},Rt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):Kt()},Rt.prototype.merge=function(){return ne(this,void 0,arguments)},Rt.prototype.mergeWith=function(t){var e=an.call(arguments,1);return ne(this,t,e)},Rt.prototype.mergeIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Kt(),function(t){return"function"==typeof t.merge?t.merge.apply(t,e):e[e.length-1]})},Rt.prototype.mergeDeep=function(){return ne(this,re(void 0),arguments)},Rt.prototype.mergeDeepWith=function(t){var e=an.call(arguments,1);return ne(this,re(t),e)},Rt.prototype.mergeDeepIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Kt(),function(t){return"function"==typeof t.mergeDeep?t.mergeDeep.apply(t,e):e[e.length-1]})},Rt.prototype.sort=function(t){return Se(Tt(this,t))},Rt.prototype.sortBy=function(t,e){return Se(Tt(this,e,t))},Rt.prototype.withMutations=function(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this},Rt.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new r)},Rt.prototype.asImmutable=function(){return this.__ensureOwner()},Rt.prototype.wasAltered=function(){return this.__altered},Rt.prototype.__iterator=function(t,e){return new Bt(this,t,e)},Rt.prototype.__iterate=function(t,e){var n=this,r=0;return this._root&&this._root.iterate(function(e){return r++,t(e[1],e[0],n)},e),r},Rt.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Wt(this.size,this._root,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},Rt.isMap=zt;var zn="@@__IMMUTABLE_MAP__@@",Hn=Rt.prototype;Hn[zn]=!0,Hn[sn]=Hn.remove,Hn.removeIn=Hn.deleteIn,Ht.prototype.get=function(t,e,n,r){for(var i=this.entries,o=0,u=i.length;u>o;o++)if(J(n,i[o][0]))return i[o][1];return r},Ht.prototype.update=function(t,e,r,o,u,a,s){for(var c=u===dn,l=this.entries,f=0,d=l.length;d>f&&!J(o,l[f][0]);f++);var p=d>f;if(p?l[f][1]===u:c)return this;if(n(s),(c||!p)&&n(a),!c||1!==l.length){if(!p&&!c&&l.length>=Gn)return Qt(t,l,o,u);var h=t&&t===this.ownerID,v=h?l:i(l);return p?c?f===d-1?v.pop():v[f]=v.pop():v[f]=[o,u]:v.push([o,u]),h?(this.entries=v,this):new Ht(t,v)}},Yt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=1<<((0===t?e:e>>>t)&fn),o=this.bitmap;return 0===(o&i)?r:this.nodes[ue(o&i-1)].get(t+cn,e,n,r)},Yt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&fn,s=1<<a,c=this.bitmap,l=0!==(c&s);if(!l&&i===dn)return this;var f=ue(c&s-1),d=this.nodes,p=l?d[f]:void 0,h=$t(p,t,e+cn,n,r,i,o,u);if(h===p)return this;if(!l&&h&&d.length>=Un)return ee(t,d,c,a,h);if(l&&!h&&2===d.length&&Zt(d[1^f]))return d[1^f];if(l&&h&&1===d.length&&Zt(h))return h;var v=t&&t===this.ownerID,_=l?h?c:c^s:c|s,y=l?h?ae(d,f,h,v):ce(d,f,v):se(d,f,h,v);return v?(this.bitmap=_,this.nodes=y,this):new Yt(t,_,y)},Gt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=(0===t?e:e>>>t)&fn,o=this.nodes[i];return o?o.get(t+cn,e,n,r):r},Gt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&fn,s=i===dn,c=this.nodes,l=c[a];if(s&&!l)return this;var f=$t(l,t,e+cn,n,r,i,o,u);if(f===l)return this;var d=this.count;if(l){if(!f&&(d--,Fn>d))return te(t,c,d,a)}else d++;var p=t&&t===this.ownerID,h=ae(c,a,f,p);return p?(this.count=d,this.nodes=h,this):new Gt(t,d,h)},Ut.prototype.get=function(t,e,n,r){for(var i=this.entries,o=0,u=i.length;u>o;o++)if(J(n,i[o][0]))return i[o][1];return r},Ut.prototype.update=function(t,e,r,o,u,a,s){void 0===r&&(r=et(o));var c=u===dn;if(r!==this.keyHash)return c?this:(n(s),n(a),Xt(this,t,e,r,[o,u]));for(var l=this.entries,f=0,d=l.length;d>f&&!J(o,l[f][0]);f++);var p=d>f;if(p?l[f][1]===u:c)return this;if(n(s),(c||!p)&&n(a),c&&2===d)return new Ft(t,this.keyHash,l[1^f]);var h=t&&t===this.ownerID,v=h?l:i(l);return p?c?f===d-1?v.pop():v[f]=v.pop():v[f]=[o,u]:v.push([o,u]),h?(this.entries=v,this):new Ut(t,this.keyHash,v)},Ft.prototype.get=function(t,e,n,r){return J(n,this.entry[0])?this.entry[1]:r},Ft.prototype.update=function(t,e,r,i,o,u,a){var s=o===dn,c=J(i,this.entry[0]);return(c?o===this.entry[1]:s)?this:(n(a),s?void n(u):c?t&&t===this.ownerID?(this.entry[1]=o,this):new Ft(t,this.keyHash,[i,o]):(n(u),Xt(this,t,e,et(i),[i,o])))},Ht.prototype.iterate=Ut.prototype.iterate=function(t,e){for(var n=this.entries,r=0,i=n.length-1;i>=r;r++)if(t(n[e?i-r:r])===!1)return!1},Yt.prototype.iterate=GtLine truncated
|
||||
console.group&&(console.groupCollapsed("Dispatch: %s",t),console.group("payload"),console.debug(e),console.groupEnd())},e.dispatchError=function(t){console.group&&(console.debug("Dispatch error: "+t),console.groupEnd())},e.storeHandled=function(t,e,n){console.group&&e!==n&&console.debug("Store "+t+" handled action")},e.dispatchEnd=function(t){console.group&&(console.debug("Dispatch done, new state: ",t.toJS()),console.groupEnd())}},function(t,e,n){function r(t,e){this.__prevState=t,this.__evaluator=e,this.__prevValues=i.Map(),this.__observers=[]}var i=n(2),o=n(7),u=n(8);Object.defineProperty(r.prototype,"notifyObservers",{writable:!0,configurable:!0,value:function(t){if(this.__observers.length>0){var e=i.Map();this.__observers.forEach(function(n){var r,i=n.getter,a=o(i),s=this.__prevState;this.__prevValues.has(a)?r=this.__prevValues.get(a):(r=this.__evaluator.evaluate(s,i),this.__prevValues=this.__prevValues.set(a,r));var c=this.__evaluator.evaluate(t,i);u(r,c)||(n.handler.call(null,c),e=e.set(a,c))}.bind(this)),this.__prevValues=e}this.__prevState=t}}),Object.defineProperty(r.prototype,"onChange",{writable:!0,configurable:!0,value:function(t,e){var n={getter:t,handler:e};return this.__observers.push(n),function(){var t=this.__observers.indexOf(n);t>-1&&this.__observers.splice(t,1)}.bind(this)}}),Object.defineProperty(r.prototype,"reset",{writable:!0,configurable:!0,value:function(t){this.__prevState=t,this.__prevValues=i.Map(),this.__observers=[]}}),t.exports=r},function(t,e,n){var r=n(2);t.exports=function(t,e){if(t.hasOwnProperty("__hashCode"))return t.__hashCode;var n=r.fromJS(t).hashCode();return e||(Object.defineProperty(t,"__hashCode",{enumerable:!1,configurable:!1,writable:!1,value:n}),Object.freeze(t)),n}},function(t,e,n){var r=n(2);t.exports=function(t,e){return r.is(t,e)}},function(t,e,n){function r(t){return s(t)&&a(t[t.length-1])}function i(t){return t[t.length-1]}function o(t){return t.slice(0,t.length-1)}function u(t){if(!c(t))throw new Error("Cannot create Getter from KeyPath: "+t);return[t,l]}var a=n(3).isFunction,s=n(3).isArray,c=n(10).isKeyPath,l=function(t){return t};t.exports={isGetter:r,getComputeFn:i,getDeps:o,fromKeyPath:u}},function(t,e,n){var r=n(3).isArray,i=n(3).isFunction;e.isKeyPath=function(t){return r(t)&&!i(t[t.length-1])}},function(t,e,n){function r(){this.__cachedGetters=i.Map({})}var i=n(2),o=n(1).toImmutable,u=n(7),a=n(8),s=n(9).getComputeFn,c=n(9).getDeps,l=n(10).isKeyPath,f=n(9).isGetter,d=!1;Object.defineProperty(r.prototype,"evaluate",{writable:!0,configurable:!0,value:function(t,e){if(l(e))return t.getIn(e);if(!f(e))throw new Error("evaluate must be passed a keyPath or Getter");var n=u(e);if(this.__isCached(t,e))return this.__cachedGetters.getIn([n,"value"]);var r=c(e).map(function(e){return this.evaluate(t,e)}.bind(this));if(this.__hasStaleValue(t,e)){var i=this.__cachedGetters.getIn([n,"args"]);if(a(i,o(r))){var p=this.__cachedGetters.getIn([n,"value"]);return this.__cacheValue(t,e,i,p),p}}if(d===!0)throw d=!1,new Error("Evaluate may not be called within a Getters computeFn");var h;d=!0;try{h=s(e).apply(null,r),d=!1}catch(v){throw d=!1,v}return this.__cacheValue(t,e,r,h),h}}),Object.defineProperty(r.prototype,"__hasStaleValue",{writable:!0,configurable:!0,value:function(t,e){var n=u(e),r=this.__cachedGetters;return r.has(n)&&r.getIn([n,"stateHashCode"])!==t.hashCode()}}),Object.defineProperty(r.prototype,"__cacheValue",{writable:!0,configurable:!0,value:function(t,e,n,r){var a=u(e);this.__cachedGetters=this.__cachedGetters.set(a,i.Map({value:r,args:o(n),stateHashCode:t.hashCode()}))}}),Object.defineProperty(r.prototype,"__isCached",{writable:!0,configurable:!0,value:function(t,e){var n=u(e);return this.__cachedGetters.hasIn([n,"value"])&&this.__cachedGetters.getIn([n,"stateHashCode"])===t.hashCode()}}),Object.defineProperty(r.prototype,"untrack",{writable:!0,configurable:!0,value:function(t){}}),Object.defineProperty(r.prototype,"reset",{writable:!0,configurable:!0,value:function(){this.__cachedGetters=i.Map({})}}),t.exports=r},function(t,e,n){function r(t,e){var n={};return i(e,function(e,r){n[r]=t.evaluate(e)}),n}var i=n(3).each;t.exports=function(t){return{getInitialState:function(){return r(t,this.getDataBindings())},componentDidMount:function(){var e=this;e.__unwatchFns=[],i(this.getDataBindings(),function(n,r){var i=t.observe(n,function(t){var n={};n[r]=t,e.setState(n)});e.__unwatchFns.push(i)})},componentWillUnmount:function(){for(;this.__unwatchFns.length;)this.__unwatchFns.shift()()}}}},function(t,e,n){function r(t){return this instanceof r?(this.__handlers=o({}),t&&u(this,t),void this.initialize()):new r(t)}function i(t){return t instanceof r}var o=n(2).Map,u=n(3).extend,a=n(1).toJS,s=n(1).toImmutable;Object.defineProperty(r.prototype,"initialize",{writable:!0,configurable:!0,value:function(){}}),Object.defineProperty(r.prototype,"getInitialState",{writable:!0,configurable:!0,value:function(){return o()}}),Object.defineProperty(r.prototype,"handle",{wriLine truncated
|
||||
t._nextDay&&(t._a[lr]=24)}}function Ot(t){var e,n,r,i,o,u,a;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(o=1,u=4,n=mt(e.GG,t._a[ar],lt(Dt(),1,4).year),r=mt(e.W,1),i=mt(e.E,1)):(o=t._locale._week.dow,u=t._locale._week.doy,n=mt(e.gg,t._a[ar],lt(Dt(),o,u).year),r=mt(e.w,1),null!=e.d?(i=e.d,o>i&&++r):i=null!=e.e?e.e+o:o),a=_t(n,r,i,u,o),t._a[ar]=a.year,t._dayOfYear=a.dayOfYear}function wt(t){if(t._f===e.ISO_8601)return void rt(t);t._a=[],l(t).empty=!0;var n,r,i,o,u,a=""+t._i,s=a.length,c=0;for(i=z(t._f,t._locale).match(Gn)||[],n=0;n<i.length;n++)o=i[n],r=(a.match(G(o,t))||[])[0],r&&(u=a.substr(0,a.indexOf(r)),u.length>0&&l(t).unusedInput.push(u),a=a.slice(a.indexOf(r)+r.length),c+=r.length),Bn[o]?(r?l(t).empty=!1:l(t).unusedTokens.push(o),V(o,r,t)):t._strict&&!r&&l(t).unusedTokens.push(o);l(t).charsLeftOver=s-c,a.length>0&&l(t).unusedInput.push(a),l(t).bigHour===!0&&t._a[lr]<=12&&t._a[lr]>0&&(l(t).bigHour=void 0),t._a[lr]=St(t._locale,t._a[lr],t._meridiem),bt(t),Q(t)}function St(t,e,n){var r;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?(r=t.isPM(n),r&&12>e&&(e+=12),r||12!==e||(e=0),e):e}function Mt(t){var e,n,r,i,o;if(0===t._f.length)return l(t).invalidFormat=!0,void(t._d=new Date(NaN));for(i=0;i<t._f.length;i++)o=0,e=p({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[i],wt(e),f(e)&&(o+=l(e).charsLeftOver,o+=10*l(e).unusedTokens.length,l(e).score=o,(null==r||r>o)&&(r=o,n=e));a(t,n||e)}function Tt(t){if(!t._d){var e=I(t._i);t._a=[e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],bt(t)}}function jt(t){var e=new h(Q(Et(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Et(t){var e=t._i,n=t._f;return t._locale=t._locale||T(t._l),null===e||void 0===n&&""===e?d({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),v(e)?new h(Q(e)):(r(n)?Mt(t):n?wt(t):i(e)?t._d=e:It(t),t))}function It(t){var n=t._i;void 0===n?t._d=new Date:i(n)?t._d=new Date(+n):"string"==typeof n?it(t):r(n)?(t._a=o(n.slice(0),function(t){return parseInt(t,10)}),bt(t)):"object"==typeof n?Tt(t):"number"==typeof n?t._d=new Date(n):e.createFromInputFallback(t)}function Pt(t,e,n,r,i){var o={};return"boolean"==typeof n&&(r=n,n=void 0),o._isAMomentObject=!0,o._useUTC=o._isUTC=i,o._l=n,o._i=t,o._f=e,o._strict=r,jt(o)}function Dt(t,e,n,r){return Pt(t,e,n,r,!1)}function Ct(t,e){var n,i;if(1===e.length&&r(e[0])&&(e=e[0]),!e.length)return Dt();for(n=e[0],i=1;i<e.length;++i)(!e[i].isValid()||e[i][t](n))&&(n=e[i]);return n}function At(){var t=[].slice.call(arguments,0);return Ct("isBefore",t)}function xt(){var t=[].slice.call(arguments,0);return Ct("isAfter",t)}function kt(t){var e=I(t),n=e.year||0,r=e.quarter||0,i=e.month||0,o=e.week||0,u=e.day||0,a=e.hour||0,s=e.minute||0,c=e.second||0,l=e.millisecond||0;this._milliseconds=+l+1e3*c+6e4*s+36e5*a,this._days=+u+7*o,this._months=+i+3*r+12*n,this._data={},this._locale=T(),this._bubble()}function Lt(t){return t instanceof kt}function Nt(t,e){k(t,0,0,function(){var t=this.utcOffset(),n="+";return 0>t&&(t=-t,n="-"),n+x(~~(t/60),2)+e+x(~~t%60,2)})}function Rt(t){var e=(t||"").match(nr)||[],n=e[e.length-1]||[],r=(n+"").match(Tr)||["-",0,0],i=+(60*r[1])+y(r[2]);return"+"===r[0]?i:-i}function zt(t,n){var r,o;return n._isUTC?(r=n.clone(),o=(v(t)||i(t)?+t:+Dt(t))-+r,r._d.setTime(+r._d+o),e.updateOffset(r,!1),r):Dt(t).local()}function Ht(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Yt(t,n){var r,i=this._offset||0;return null!=t?("string"==typeof t&&(t=Rt(t)),Math.abs(t)<16&&(t=60*t),!this._isUTC&&n&&(r=Ht(this)),this._offset=t,this._isUTC=!0,null!=r&&this.add(r,"m"),i!==t&&(!n||this._changeInProgress?ne(this,Zt(t-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?i:Ht(this)}function Gt(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}function Ut(t){return this.utcOffset(0,t)}function Ft(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Ht(this),"m")),this}function Bt(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Rt(this._i)),this}function Vt(t){return t=t?Dt(t).utcOffset():0,(this.utcOffset()-t)%60===0}function qt(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Wt(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var t={};if(p(t,this),t=Et(t),t._a){var e=t._isUTC?s(t._a):Dt(t._a);this._isDSTShifted=this.isValid()&&m(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Kt(){return!this._isUTC}function Jt(){return this._isUTC}function $t(){return this._isUTC&&0===this._offset}function Zt(t,e){var n,r,i,o=t,a=null;return Lt(t)?o={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(o={},e?o[e]=t:o.milliseconds=t):(a=jr.exec(t))?(n="-"===a[1]?-1:1,o={y:0,d:y(a[cr])*n,h:y(a[lr])*n,m:y(a[fr])*n,s:y(a[dr])*n,ms:y(a[pr])Line truncated
|
||||
t.exports=r},function(t,e){"use strict";function n(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}t.exports=n},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=["isLoadingEntityHistory"];e.isLoadingEntityHistory=i;var o=["currentEntityHistoryDate"];e.currentDate=o;var u=["entityHistory"];e.entityHistoryMap=u;var a=[o,u,function(t,e){return e.get(t)||r.toImmutable({})}];e.entityHistoryForCurrentDate=a;var s=[o,u,function(t,e){return!!e.get(t)}];e.hasDataForCurrentDate=s;var c=["recentEntityHistory"];e.recentEntityHistoryMap=c;var l=["recentEntityHistory"];e.recentEntityHistoryUpdatedMap=l},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({currentEntityHistoryDate:a["default"],entityHistory:c["default"],isLoadingEntityHistory:f["default"],recentEntityHistory:p["default"],recentEntityHistoryUpdated:v["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(195),a=i(u),s=n(196),c=i(s),l=n(197),f=i(l),d=n(198),p=i(d),h=n(199),v=i(h),_=n(194),y=r(_),m=n(69),g=r(m),b=y;e.actions=b;var O=g;e.getters=O},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),u=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},a=n(3),s=n(7),c="event",l=new a.Immutable.Record({event:null,listenerCount:0},"Event"),f=function(t){function e(t){var n=arguments.length<=1||void 0===arguments[1]?0:arguments[1];r(this,e),u(Object.getPrototypeOf(e.prototype),"constructor",this).call(this,{event:t,listenerCount:n})}return i(e,t),o(e,null,[{key:"entity",value:c,enumerable:!0}]),o(e,[{key:"id",get:function(){return this.event}}],[{key:"fetchAll",value:function(t){return s.callApi(t,"GET","events")}},{key:"fromJSON",value:function(t){var n=t.event,r=t.listener_count;return new e(n,r)}}]),e}(l);e["default"]=f,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),o=r(i);e["default"]=o["default"]({SELECT_ENTITY:null,LOG_OUT:null}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({moreInfoEntityId:a["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(214),a=i(u),s=n(212),c=r(s),l=n(213),f=r(l),d=c;e.actions=d;var p=f;e.getters=p},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){t.dispatch(a["default"].SHOW_SIDEBAR,{show:e})}function o(t,e){t.dispatch(a["default"].NAVIGATE,{pane:e})}Object.defineProperty(e,"__esModule",{value:!0}),e.showSidebar=i,e.navigate=o;var u=n(38),a=r(u)},function(t,e){"use strict";function n(t){return[r,function(e){return e===t}]}Object.defineProperty(e,"__esModule",{value:!0}),e.isActivePane=n;var r=["selectedNavigationPanel"];e.activePane=r;var i=[["showSidebar"],function(t){return!!t}];e.showSidebar=i},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({selectedNavigationPanel:a["default"],showSidebar:c["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(215),a=i(u),s=n(216),c=i(s),l=n(74),f=r(l),d=n(75),p=r(d),h=n(217),v=r(h),_=f;e.actions=_;var y=p;e.getters=y;var m=v;e.urlSync=m},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),o=r(i);e["default"]=o["default"]({NOTIFICATION_CREATED:null}),t.exports=e["default"]},function(t,e,n){"use strict";fLine truncated
|
||||
n(29),n(134),n(58),e["default"]=new u["default"]({is:"logbook-entry",entityClicked:function(t){t.preventDefault(),i.moreInfoActions.selectEntity(this.entryObj.entityId)}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),o=n(1),u=r(o),a=n(4),s=r(a);n(29),e["default"]=new u["default"]({is:"services-list",behaviors:[s["default"]],properties:{serviceDomains:{type:Array,bindNuclear:[i.serviceGetters.entityMap,function(t){return t.valueSeq().sortBy(function(t){return t.domain}).toJS()}]}},computeServices:function(t){return this.services.get(t).toArray()},serviceClicked:function(t){t.preventDefault(),this.fire("service-selected",{domain:t.model.domain.domain,service:t.model.service})}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(90),o=r(i),u=n(86),a=r(u),s=n(88),c=r(s),l=n(91),f=r(l),d=n(1),p=r(d);e["default"]=new p["default"]({is:"state-history-chart-line",properties:{data:{type:Object,observer:"dataChanged"},unit:{type:String},isSingleDevice:{type:Boolean,value:!1},isAttached:{type:Boolean,value:!1,observer:"dataChanged"}},created:function(){this.style.display="block"},attached:function(){this.isAttached=!0},dataChanged:function(){this.drawChart()},drawChart:function(){if(this.isAttached){for(var t=p["default"].dom(this),e=this.unit,n=this.data;t.lastChild;)t.removeChild(t.lastChild);if(0!==n.length){var r=new google.visualization.LineChart(this),i=new google.visualization.DataTable;i.addColumn({type:"datetime",id:"Time"});var u={legend:{position:"top"},titlePosition:"none",vAxes:{0:{title:e}},hAxis:{format:"H:mm"},lineWidth:1,chartArea:{left:"60",width:"95%"},explorer:{actions:["dragToZoom","rightClickToReset","dragToPan"],keepInBounds:!0,axis:"horizontal",maxZoomIn:.1}};this.isSingleDevice&&(u.legend.position="none",u.vAxes[0].title=null,u.chartArea.left=40,u.chartArea.height="80%",u.chartArea.top=5,u.enableInteractivity=!1);var s=o["default"](a["default"](n),"lastChangedAsDate");s=f["default"](c["default"](s,function(t){return t.getTime()}));for(var l=[],d=new Array(n.length),h=0;h<d.length;h++)d[h]=0;for(var v=1,_=new Date,h=0;h<s.length;h++){var y=new Date(s[h]);l.push([y].concat(d)),l.push([s[h]].concat(d)),v++}l.push([_].concat(d));var m=0;n.forEach(function(t){var e=t[t.length-1].attributes;i.addColumn("number",e.friendly_name);var n=0,r=0,o=0,u=0,a=l[0][0];t.forEach(function(t){n=t.state;var e=t.lastChangedAsDate;"None"===t.state&&(n=r);for(var i=o;i<l.length;i++){if(l[i][1+m]=parseFloat(r),a.getTime()===l[i][0].getTime()&&l[i][0].getTime()===e.getTime()){l[i][1+m]=parseFloat(n),o=i,a=l[i][0];break}a=l[i][0]}r=n,u++});for(var s=o;s<l.length;s++)l[s][1+m]=parseFloat(r);m++}),i.addRows(l),r.draw(i,u)}}}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(1),o=r(i);e["default"]=new o["default"]({is:"state-history-chart-timeline",properties:{data:{type:Object,observer:"dataChanged"},isAttached:{type:Boolean,value:!1,observer:"dataChanged"}},attached:function(){this.isAttached=!0},dataChanged:function(){this.drawChart()},drawChart:function(){function t(t,e,n,r){var o=e.replace(/_/g," ");i.addRow([t,o,n,r])}if(this.isAttached){for(var e=o["default"].dom(this),n=this.data;e.node.lastChild;)e.node.removeChild(e.node.lastChild);if(n&&0!==n.length){var r=new google.visualization.Timeline(this),i=new google.visualization.DataTable;i.addColumn({type:"string",id:"Entity"}),i.addColumn({type:"string",id:"State"}),i.addColumn({type:"date",id:"Start"}),i.addColumn({type:"date",id:"End"});var u=new Date(n.reduce(function(t,e){return Math.min(t,e[0].lastChangedAsDate)},new Date)),a=new Date(u);a.setDate(a.getDate()+1),a>new Date&&(a=new Date);var s=0;n.forEach(function(e){if(0!==e.length){var n=e[0].entityDisplay,r=void 0,i=null,o=null;e.forEach(function(e){null!==i&&e.state!==i?(r=e.lastChangedAsDate,t(n,i,o,r),i=e.state,o=r):null===i&&(i=e.state,o=e.lastChangedAsDate)}),t(n,i,o,a),s++}}),r.draw(i,{height:55+42*s,timeline:{showRowLabels:n.length>1},hAxis:{format:"H:mm"}})}}}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),o=n(1),u=r(o),a=n(4),s=r(a);e["default"]=new u["default"]({is:"stream-status",behaviors:[s["default"]],properties:{isStreaming:{type:Boolean,bindNuclear:i.streamGetters.isStreamingEvents},hasError:{type:Boolean,bindNuclear:i.streamGetters.hasStreamingEventsError}},toggleChanged:function(){this.isStreaming?i.streamActions.stop():i.streamActions.start()}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),o=n(1),u=r(o),a=n(4),sLine truncated
|
||||
}}function j(t,e){t===e?P(t,g()):u(e)?T(t,e):I(t,e)}function E(t){t._onerror&&t._onerror(t._result),C(t)}function I(t,e){t._state===it&&(t._result=e,t._state=ot,0!==t._subscribers.length&&Z(C,t))}function P(t,e){t._state===it&&(t._state=ut,t._result=e,Z(E,t))}function D(t,e,n,r){var i=t._subscribers,o=i.length;t._onerror=null,i[o]=e,i[o+ot]=n,i[o+ut]=r,0===o&&t._state&&Z(C,t)}function C(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r,i,o=t._result,u=0;u<e.length;u+=3)r=e[u],i=e[u+n],r?k(n,r,i,o):i(o);t._subscribers.length=0}}function A(){this.error=null}function x(t,e){try{return t(e)}catch(n){return st.error=n,st}}function k(t,e,n,r){var i,o,u,s,c=a(n);if(c){if(i=x(n,r),i===st?(s=!0,o=i.error,i=null):u=!0,e===i)return void P(e,b())}else i=r,u=!0;e._state!==it||(c&&u?j(e,i):s?P(e,o):t===ot?I(e,i):t===ut&&P(e,i))}function L(t,e){try{e(function(e){j(t,e)},function(e){P(t,e)})}catch(n){P(t,n)}}function N(t,e){var n=this;n._instanceConstructor=t,n.promise=new t(m),n._validateInput(e)?(n._input=e,n.length=e.length,n._remaining=e.length,n._init(),0===n.length?I(n.promise,n._result):(n.length=n.length||0,n._enumerate(),0===n._remaining&&I(n.promise,n._result))):P(n.promise,n._validationError())}function R(t){return new ct(this,t).promise}function z(t){function e(t){j(i,t)}function n(t){P(i,t)}var r=this,i=new r(m);if(!J(t))return P(i,new TypeError("You must pass an array to race.")),i;for(var o=t.length,u=0;i._state===it&&o>u;u++)D(r.resolve(t[u]),void 0,e,n);return i}function H(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(m);return j(n,t),n}function Y(t){var e=this,n=new e(m);return P(n,t),n}function G(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function U(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function F(t){this._id=ht++,this._state=void 0,this._result=void 0,this._subscribers=[],m!==t&&(a(t)||G(),this instanceof F||U(),L(this,t))}function B(){var t;if("undefined"!=typeof i)t=i;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;(!n||"[object Promise]"!==Object.prototype.toString.call(n.resolve())||n.cast)&&(t.Promise=vt)}var V;V=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var q,W,K,J=V,$=0,Z=({}.toString,function(t,e){rt[$]=t,rt[$+1]=e,$+=2,2===$&&(W?W(_):K())}),X="undefined"!=typeof window?window:void 0,Q=X||{},tt=Q.MutationObserver||Q.WebKitMutationObserver,et="undefined"!=typeof t&&"[object process]"==={}.toString.call(t),nt="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,rt=new Array(1e3);K=et?f():tt?p():nt?h():void 0===X?y():v();var it=void 0,ot=1,ut=2,at=new A,st=new A;N.prototype._validateInput=function(t){return J(t)},N.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},N.prototype._init=function(){this._result=new Array(this.length)};var ct=N;N.prototype._enumerate=function(){for(var t=this,e=t.length,n=t.promise,r=t._input,i=0;n._state===it&&e>i;i++)t._eachEntry(r[i],i)},N.prototype._eachEntry=function(t,e){var n=this,r=n._instanceConstructor;s(t)?t.constructor===r&&t._state!==it?(t._onerror=null,n._settledAt(t._state,e,t._result)):n._willSettleAt(r.resolve(t),e):(n._remaining--,n._result[e]=t)},N.prototype._settledAt=function(t,e,n){var r=this,i=r.promise;i._state===it&&(r._remaining--,t===ut?P(i,n):r._result[e]=n),0===r._remaining&&I(i,r._result)},N.prototype._willSettleAt=function(t,e){var n=this;D(t,void 0,function(t){n._settledAt(ot,e,t)},function(t){n._settledAt(ut,e,t)})};var lt=R,ft=z,dt=H,pt=Y,ht=0,vt=F;F.all=lt,F.race=ft,F.resolve=dt,F.reject=pt,F._setScheduler=c,F._setAsap=l,F._asap=Z,F.prototype={constructor:F,then:function(t,e){var n=this,r=n._state;if(r===ot&&!t||r===ut&&!e)return this;var i=new this.constructor(m),o=n._result;if(r){var u=arguments[r-1];Z(function(){k(r,i,u,o)})}else D(n,i,t,e);return i},"catch":function(t){return this.then(null,t)}};var _t=B,yt={Promise:vt,polyfill:_t};n(249).amd?(r=function(){return yt}.call(e,n,e,o),!(void 0!==r&&(o.exports=r))):"undefined"!=typeof o&&o.exports?o.exports=yt:"undefined"!=typeof this&&(this.ES6Promise=yt),_t()}).call(void 0)}).call(e,n(246),function(){return this}(),n(247)(t))},function(t,e,n){"use strict";var r=n(65),i=r(Date,"now"),o=i||function(){return(new Date).getTime()};t.exports=o},function(t,e){"use strict";function n(t){return"number"==typeof t&&t>-1&&t%1==0&&r>=t}var r=9007199254740991;t.exports=n},function(t,e,n){"use strict";var r=n(65),i=n(181),o=n(66),u="[object Array]",a=Object.prototype,s=a.toString,c=r(Array,"isArray"),l=c||function(t){return o(t)&&i(t.length)&&s.call(t)==u};t.exports=l},function(t,e,n){"Line truncated
|
||||
t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){var n=e.date;return d["default"](n)}function a(){return _.getInitialState()}Object.defineProperty(e,"__esModule",{value:!0});var s=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),c=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},l=n(3),f=n(43),d=r(f),p=n(18),h=r(p),v=function(t){function e(){i(this,e),c(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),s(e,[{key:"getInitialState",value:function(){return d["default"](new Date)}},{key:"initialize",value:function(){this.on(h["default"].LOGBOOK_DATE_SELECTED,u),this.on(h["default"].LOG_OUT,a)}}]),e}(l.Store),_=new v;e["default"]=_,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var u=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),a=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},s=n(3),c=n(18),l=r(c),f=function(t){function e(){i(this,e),a(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),u(e,[{key:"getInitialState",value:function(){return!1}},{key:"initialize",value:function(){this.on(l["default"].LOGBOOK_ENTRIES_FETCH_START,function(){return!0}),this.on(l["default"].LOGBOOK_ENTRIES_FETCH_SUCCESS,function(){return!1}),this.on(l["default"].LOGBOOK_ENTRIES_FETCH_ERROR,function(){return!1}),this.on(l["default"].LOG_OUT,function(){return!1})}}]),e}(s.Store),d=new f;e["default"]=d,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){var n=e.date,r=e.entries;return t.set(n,l.toImmutable(r.map(h["default"].fromJSON)))}function a(){return _.getInitialState()}Object.defineProperty(e,"__esModule",{value:!0});var s=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),c=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},l=n(3),f=n(18),d=r(f),p=n(207),h=r(p),v=function(t){function e(){i(this,e),c(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),s(e,[{key:"getInitialState",value:function(){return l.toImmutable({})}},{key:"initialize",value:function(){this.on(d["default"].LOGBOOK_ENTRIES_FETCH_SUCCESS,u),this.on(d["default"].LOG_OUT,a)}}]),e}(l.Store),_=new v;e["default"]=_,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{coLine truncated
|
||||
e.isVoiceSupported=n;var r=["currentVoiceCommand","isListening"];e.isListening=r;var i=["currentVoiceCommand","isTransmitting"];e.isTransmitting=i;var o=["currentVoiceCommand","interimTranscript"];e.interimTranscript=o;var u=["currentVoiceCommand","finalTranscript"];e.finalTranscript=u;var a=[o,u,function(t,e){return t.slice(e.length)}];e.extraInterimTranscript=a},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({currentVoiceCommand:c["default"],isVoiceSupported:a["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(240),a=i(u),s=n(239),c=i(s),l=n(236),f=r(l),d=n(237),p=r(d),h=f;e.actions=h;var v=p;e.getters=v},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t){return t.set("isListening",!0)}function a(t,e){var n=e.interimTranscript,r=e.finalTranscript;return t.withMutations(function(t){return t.set("isListening",!0).set("isTransmitting",!1).set("interimTranscript",n).set("finalTranscript",r)})}function s(t,e){var n=e.finalTranscript;return t.withMutations(function(t){return t.set("isListening",!1).set("isTransmitting",!0).set("interimTranscript","").set("finalTranscript",n)})}function c(){return m.getInitialState()}function l(){return m.getInitialState()}function f(){return m.getInitialState()}Object.defineProperty(e,"__esModule",{value:!0});var d=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),p=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},h=n(3),v=n(83),_=r(v),y=function(t){function e(){i(this,e),p(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),d(e,[{key:"getInitialState",value:function(){return h.toImmutable({isListening:!1,isTransmitting:!1,interimTranscript:"",finalTranscript:""})}},{key:"initialize",value:function(){this.on(_["default"].VOICE_START,u),this.on(_["default"].VOICE_RESULT,a),this.on(_["default"].VOICE_TRANSMITTING,s),this.on(_["default"].VOICE_DONE,c),this.on(_["default"].VOICE_ERROR,l),this.on(_["default"].LOG_OUT,f)}}]),e}(h.Store),m=new y;e["default"]=m,t.exports=e["default"]},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),u=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},a=n(3),s=function(t){function e(){r(this,e),u(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return i(e,t),o(e,[{key:"getInitialState",value:function(){return"webkitSpeechRecognition"in window}}]),e}(a.Store),c=new s;e["default"]=c,t.exports=e["default"]},function(t,e,n){"use strict";function r(){var t=new i.Reactor({debug:!1});return t.hassId=o++,t}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=r;var i=n(3),o=0;t.exports=e["default"]},function(t,e,n){"use strict";function r(t,e){return i.toImmutable(t.attributes.entity_id.map(function(t){return e.get(t)}).filter(function(t){return!!t}))}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=r;var i=n(3);t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{Line truncated
|
||||
t._nextDay&&(t._a[lr]=24)}}function Ot(t){var e,n,r,i,o,u,a;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(o=1,u=4,n=mt(e.GG,t._a[ar],lt(Dt(),1,4).year),r=mt(e.W,1),i=mt(e.E,1)):(o=t._locale._week.dow,u=t._locale._week.doy,n=mt(e.gg,t._a[ar],lt(Dt(),o,u).year),r=mt(e.w,1),null!=e.d?(i=e.d,o>i&&++r):i=null!=e.e?e.e+o:o),a=_t(n,r,i,u,o),t._a[ar]=a.year,t._dayOfYear=a.dayOfYear}function wt(t){if(t._f===e.ISO_8601)return void rt(t);t._a=[],l(t).empty=!0;var n,r,i,o,u,a=""+t._i,s=a.length,c=0;for(i=z(t._f,t._locale).match(Gn)||[],n=0;n<i.length;n++)o=i[n],r=(a.match(G(o,t))||[])[0],r&&(u=a.substr(0,a.indexOf(r)),u.length>0&&l(t).unusedInput.push(u),a=a.slice(a.indexOf(r)+r.length),c+=r.length),Bn[o]?(r?l(t).empty=!1:l(t).unusedTokens.push(o),V(o,r,t)):t._strict&&!r&&l(t).unusedTokens.push(o);l(t).charsLeftOver=s-c,a.length>0&&l(t).unusedInput.push(a),l(t).bigHour===!0&&t._a[lr]<=12&&t._a[lr]>0&&(l(t).bigHour=void 0),t._a[lr]=St(t._locale,t._a[lr],t._meridiem),bt(t),Q(t)}function St(t,e,n){var r;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?(r=t.isPM(n),r&&12>e&&(e+=12),r||12!==e||(e=0),e):e}function Mt(t){var e,n,r,i,o;if(0===t._f.length)return l(t).invalidFormat=!0,void(t._d=new Date(NaN));for(i=0;i<t._f.length;i++)o=0,e=p({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[i],wt(e),f(e)&&(o+=l(e).charsLeftOver,o+=10*l(e).unusedTokens.length,l(e).score=o,(null==r||r>o)&&(r=o,n=e));a(t,n||e)}function Tt(t){if(!t._d){var e=I(t._i);t._a=[e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],bt(t)}}function jt(t){var e=new h(Q(Et(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Et(t){var e=t._i,n=t._f;return t._locale=t._locale||T(t._l),null===e||void 0===n&&""===e?d({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),v(e)?new h(Q(e)):(r(n)?Mt(t):n?wt(t):i(e)?t._d=e:It(t),t))}function It(t){var n=t._i;void 0===n?t._d=new Date:i(n)?t._d=new Date(+n):"string"==typeof n?it(t):r(n)?(t._a=o(n.slice(0),function(t){return parseInt(t,10)}),bt(t)):"object"==typeof n?Tt(t):"number"==typeof n?t._d=new Date(n):e.createFromInputFallback(t)}function Pt(t,e,n,r,i){var o={};return"boolean"==typeof n&&(r=n,n=void 0),o._isAMomentObject=!0,o._useUTC=o._isUTC=i,o._l=n,o._i=t,o._f=e,o._strict=r,jt(o)}function Dt(t,e,n,r){return Pt(t,e,n,r,!1)}function Ct(t,e){var n,i;if(1===e.length&&r(e[0])&&(e=e[0]),!e.length)return Dt();for(n=e[0],i=1;i<e.length;++i)(!e[i].isValid()||e[i][t](n))&&(n=e[i]);return n}function At(){var t=[].slice.call(arguments,0);return Ct("isBefore",t)}function xt(){var t=[].slice.call(arguments,0);return Ct("isAfter",t)}function kt(t){var e=I(t),n=e.year||0,r=e.quarter||0,i=e.month||0,o=e.week||0,u=e.day||0,a=e.hour||0,s=e.minute||0,c=e.second||0,l=e.millisecond||0;this._milliseconds=+l+1e3*c+6e4*s+36e5*a,this._days=+u+7*o,this._months=+i+3*r+12*n,this._data={},this._locale=T(),this._bubble()}function Lt(t){return t instanceof kt}function Nt(t,e){k(t,0,0,function(){var t=this.utcOffset(),n="+";return 0>t&&(t=-t,n="-"),n+x(~~(t/60),2)+e+x(~~t%60,2)})}function Rt(t){var e=(t||"").match(nr)||[],n=e[e.length-1]||[],r=(n+"").match(Tr)||["-",0,0],i=+(60*r[1])+y(r[2]);return"+"===r[0]?i:-i}function zt(t,n){var r,o;return n._isUTC?(r=n.clone(),o=(v(t)||i(t)?+t:+Dt(t))-+r,r._d.setTime(+r._d+o),e.updateOffset(r,!1),r):Dt(t).local()}function Ht(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Yt(t,n){var r,i=this._offset||0;return null!=t?("string"==typeof t&&(t=Rt(t)),Math.abs(t)<16&&(t=60*t),!this._isUTC&&n&&(r=Ht(this)),this._offset=t,this._isUTC=!0,null!=r&&this.add(r,"m"),i!==t&&(!n||this._changeInProgress?ne(this,Zt(t-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?i:Ht(this)}function Gt(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}function Ut(t){return this.utcOffset(0,t)}function Ft(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Ht(this),"m")),this}function Bt(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Rt(this._i)),this}function Vt(t){return t=t?Dt(t).utcOffset():0,(this.utcOffset()-t)%60===0}function qt(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Wt(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var t={};if(p(t,this),t=Et(t),t._a){var e=t._isUTC?s(t._a):Dt(t._a);this._isDSTShifted=this.isValid()&&m(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Kt(){return!this._isUTC}function Jt(){return this._isUTC}function $t(){return this._isUTC&&0===this._offset}function Zt(t,e){var n,r,i,o=t,a=null;return Lt(t)?o={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(o={},e?o[e]=t:o.milliseconds=t):(a=jr.exec(t))?(n="-"===a[1]?-1:1,o={y:0,d:y(a[cr])*n,h:y(a[lr])*n,m:y(a[fr])*n,s:y(a[dr])*n,ms:y(a[pr])Line truncated
|
||||
"use strict";function n(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}t.exports=n},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=["isLoadingEntityHistory"];e.isLoadingEntityHistory=i;var o=["currentEntityHistoryDate"];e.currentDate=o;var u=["entityHistory"];e.entityHistoryMap=u;var a=[o,u,function(t,e){return e.get(t)||r.toImmutable({})}];e.entityHistoryForCurrentDate=a;var s=[o,u,function(t,e){return!!e.get(t)}];e.hasDataForCurrentDate=s;var c=["recentEntityHistory"];e.recentEntityHistoryMap=c;var l=["recentEntityHistory"];e.recentEntityHistoryUpdatedMap=l},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({currentEntityHistoryDate:a["default"],entityHistory:c["default"],isLoadingEntityHistory:f["default"],recentEntityHistory:p["default"],recentEntityHistoryUpdated:v["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(195),a=i(u),s=n(196),c=i(s),l=n(197),f=i(l),d=n(198),p=i(d),h=n(199),v=i(h),_=n(194),y=r(_),m=n(69),g=r(m),b=y;e.actions=b;var O=g;e.getters=O},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),u=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},a=n(3),s=n(7),c="event",l=new a.Immutable.Record({event:null,listenerCount:0},"Event"),f=function(t){function e(t){var n=arguments.length<=1||void 0===arguments[1]?0:arguments[1];r(this,e),u(Object.getPrototypeOf(e.prototype),"constructor",this).call(this,{event:t,listenerCount:n})}return i(e,t),o(e,null,[{key:"entity",value:c,enumerable:!0}]),o(e,[{key:"id",get:function(){return this.event}}],[{key:"fetchAll",value:function(t){return s.callApi(t,"GET","events")}},{key:"fromJSON",value:function(t){var n=t.event,r=t.listener_count;return new e(n,r)}}]),e}(l);e["default"]=f,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),o=r(i);e["default"]=o["default"]({SELECT_ENTITY:null,LOG_OUT:null}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({moreInfoEntityId:a["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(214),a=i(u),s=n(212),c=r(s),l=n(213),f=r(l),d=c;e.actions=d;var p=f;e.getters=p},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){t.dispatch(a["default"].SHOW_SIDEBAR,{show:e})}function o(t,e){t.dispatch(a["default"].NAVIGATE,{pane:e})}Object.defineProperty(e,"__esModule",{value:!0}),e.showSidebar=i,e.navigate=o;var u=n(38),a=r(u)},function(t,e){"use strict";function n(t){return[r,function(e){return e===t}]}Object.defineProperty(e,"__esModule",{value:!0}),e.isActivePane=n;var r=["selectedNavigationPanel"];e.activePane=r;var i=[["showSidebar"],function(t){return!!t}];e.showSidebar=i},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({selectedNavigationPanel:a["default"],showSidebar:c["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(215),a=i(u),s=n(216),c=i(s),l=n(74),f=r(l),d=n(75),p=r(d),h=n(217),v=r(h),_=f;e.actions=_;var y=p;e.getters=y;var m=v;e.urlSync=m},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),o=r(i);e["default"]=o["default"]({NOTIFICATION_CREATED:null}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__Line truncated
|
||||
"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),o=n(1),u=r(o);n(29),n(134),n(58),e["default"]=new u["default"]({is:"logbook-entry",entityClicked:function(t){t.preventDefault(),i.moreInfoActions.selectEntity(this.entryObj.entityId)}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),o=n(1),u=r(o),a=n(4),s=r(a);n(29),e["default"]=new u["default"]({is:"services-list",behaviors:[s["default"]],properties:{serviceDomains:{type:Array,bindNuclear:[i.serviceGetters.entityMap,function(t){return t.valueSeq().sortBy(function(t){return t.domain}).toJS()}]}},computeServices:function(t){return this.services.get(t).toArray()},serviceClicked:function(t){t.preventDefault(),this.fire("service-selected",{domain:t.model.domain.domain,service:t.model.service})}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(90),o=r(i),u=n(86),a=r(u),s=n(88),c=r(s),l=n(91),f=r(l),d=n(1),p=r(d);e["default"]=new p["default"]({is:"state-history-chart-line",properties:{data:{type:Object,observer:"dataChanged"},unit:{type:String},isSingleDevice:{type:Boolean,value:!1},isAttached:{type:Boolean,value:!1,observer:"dataChanged"}},created:function(){this.style.display="block"},attached:function(){this.isAttached=!0},dataChanged:function(){this.drawChart()},drawChart:function(){if(this.isAttached){for(var t=p["default"].dom(this),e=this.unit,n=this.data;t.lastChild;)t.removeChild(t.lastChild);if(0!==n.length){var r=new google.visualization.LineChart(this),i=new google.visualization.DataTable;i.addColumn({type:"datetime",id:"Time"});var u={legend:{position:"top"},titlePosition:"none",vAxes:{0:{title:e}},hAxis:{format:"H:mm"},lineWidth:1,chartArea:{left:"60",width:"95%"},explorer:{actions:["dragToZoom","rightClickToReset","dragToPan"],keepInBounds:!0,axis:"horizontal",maxZoomIn:.1}};this.isSingleDevice&&(u.legend.position="none",u.vAxes[0].title=null,u.chartArea.left=40,u.chartArea.height="80%",u.chartArea.top=5,u.enableInteractivity=!1);var s=o["default"](a["default"](n),"lastChangedAsDate");s=f["default"](c["default"](s,function(t){return t.getTime()}));for(var l=[],d=new Array(n.length),h=0;h<d.length;h++)d[h]=0;for(var v=1,_=new Date,h=0;h<s.length;h++){var y=new Date(s[h]);l.push([y].concat(d)),l.push([s[h]].concat(d)),v++}l.push([_].concat(d));var m=0;n.forEach(function(t){var e=t[t.length-1].attributes;i.addColumn("number",e.friendly_name);var n=0,r=0,o=0,u=0,a=l[0][0];t.forEach(function(t){n=t.state;var e=t.lastChangedAsDate;"None"===t.state&&(n=r);for(var i=o;i<l.length;i++){if(l[i][1+m]=parseFloat(r),a.getTime()===l[i][0].getTime()&&l[i][0].getTime()===e.getTime()){l[i][1+m]=parseFloat(n),o=i,a=l[i][0];break}a=l[i][0]}r=n,u++});for(var s=o;s<l.length;s++)l[s][1+m]=parseFloat(r);m++}),i.addRows(l),r.draw(i,u)}}}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(1),o=r(i);e["default"]=new o["default"]({is:"state-history-chart-timeline",properties:{data:{type:Object,observer:"dataChanged"},isAttached:{type:Boolean,value:!1,observer:"dataChanged"}},attached:function(){this.isAttached=!0},dataChanged:function(){this.drawChart()},drawChart:function(){function t(t,e,n,r){var o=e.replace(/_/g," ");i.addRow([t,o,n,r])}if(this.isAttached){for(var e=o["default"].dom(this),n=this.data;e.node.lastChild;)e.node.removeChild(e.node.lastChild);if(n&&0!==n.length){var r=new google.visualization.Timeline(this),i=new google.visualization.DataTable;i.addColumn({type:"string",id:"Entity"}),i.addColumn({type:"string",id:"State"}),i.addColumn({type:"date",id:"Start"}),i.addColumn({type:"date",id:"End"});var u=new Date(n.reduce(function(t,e){return Math.min(t,e[0].lastChangedAsDate)},new Date)),a=new Date(u);a.setDate(a.getDate()+1),a>new Date&&(a=new Date);var s=0;n.forEach(function(e){if(0!==e.length){var n=e[0].entityDisplay,r=void 0,i=null,o=null;e.forEach(function(e){null!==i&&e.state!==i?(r=e.lastChangedAsDate,t(n,i,o,r),i=e.state,o=r):null===i&&(i=e.state,o=e.lastChangedAsDate)}),t(n,i,o,a),s++}}),r.draw(i,{height:55+42*s,timeline:{showRowLabels:n.length>1},hAxis:{format:"H:mm"}})}}}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=n(2),o=n(1),u=r(o),a=n(4),s=r(a);e["default"]=new u["default"]({is:"stream-status",behaviors:[s["default"]],properties:{isStreaming:{type:Boolean,bindNuclear:i.streamGetters.isStreamingEvents},hasError:{type:Boolean,bindNuclear:i.streamGetters.hasStreamingEventsError}},toggleChanged:function(){this.isStreaming?i.streamActions.stop():i.streamActions.start()}}),t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"defaultLine truncated
|
||||
if(e.constructor===t.constructor)M(t,e);else{var n=O(e);n===at?P(t,at.error):void 0===n?I(t,e):a(n)?S(t,e,n):I(t,e)}}function j(t,e){t===e?P(t,g()):u(e)?T(t,e):I(t,e)}function E(t){t._onerror&&t._onerror(t._result),C(t)}function I(t,e){t._state===it&&(t._result=e,t._state=ot,0!==t._subscribers.length&&Z(C,t))}function P(t,e){t._state===it&&(t._state=ut,t._result=e,Z(E,t))}function D(t,e,n,r){var i=t._subscribers,o=i.length;t._onerror=null,i[o]=e,i[o+ot]=n,i[o+ut]=r,0===o&&t._state&&Z(C,t)}function C(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r,i,o=t._result,u=0;u<e.length;u+=3)r=e[u],i=e[u+n],r?k(n,r,i,o):i(o);t._subscribers.length=0}}function A(){this.error=null}function x(t,e){try{return t(e)}catch(n){return st.error=n,st}}function k(t,e,n,r){var i,o,u,s,c=a(n);if(c){if(i=x(n,r),i===st?(s=!0,o=i.error,i=null):u=!0,e===i)return void P(e,b())}else i=r,u=!0;e._state!==it||(c&&u?j(e,i):s?P(e,o):t===ot?I(e,i):t===ut&&P(e,i))}function L(t,e){try{e(function(e){j(t,e)},function(e){P(t,e)})}catch(n){P(t,n)}}function N(t,e){var n=this;n._instanceConstructor=t,n.promise=new t(m),n._validateInput(e)?(n._input=e,n.length=e.length,n._remaining=e.length,n._init(),0===n.length?I(n.promise,n._result):(n.length=n.length||0,n._enumerate(),0===n._remaining&&I(n.promise,n._result))):P(n.promise,n._validationError())}function R(t){return new ct(this,t).promise}function z(t){function e(t){j(i,t)}function n(t){P(i,t)}var r=this,i=new r(m);if(!J(t))return P(i,new TypeError("You must pass an array to race.")),i;for(var o=t.length,u=0;i._state===it&&o>u;u++)D(r.resolve(t[u]),void 0,e,n);return i}function H(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(m);return j(n,t),n}function Y(t){var e=this,n=new e(m);return P(n,t),n}function G(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function U(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function F(t){this._id=ht++,this._state=void 0,this._result=void 0,this._subscribers=[],m!==t&&(a(t)||G(),this instanceof F||U(),L(this,t))}function B(){var t;if("undefined"!=typeof i)t=i;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;(!n||"[object Promise]"!==Object.prototype.toString.call(n.resolve())||n.cast)&&(t.Promise=vt)}var V;V=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var q,W,K,J=V,$=0,Z=({}.toString,function(t,e){rt[$]=t,rt[$+1]=e,$+=2,2===$&&(W?W(_):K())}),X="undefined"!=typeof window?window:void 0,Q=X||{},tt=Q.MutationObserver||Q.WebKitMutationObserver,et="undefined"!=typeof t&&"[object process]"==={}.toString.call(t),nt="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,rt=new Array(1e3);K=et?f():tt?p():nt?h():void 0===X?y():v();var it=void 0,ot=1,ut=2,at=new A,st=new A;N.prototype._validateInput=function(t){return J(t)},N.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},N.prototype._init=function(){this._result=new Array(this.length)};var ct=N;N.prototype._enumerate=function(){for(var t=this,e=t.length,n=t.promise,r=t._input,i=0;n._state===it&&e>i;i++)t._eachEntry(r[i],i)},N.prototype._eachEntry=function(t,e){var n=this,r=n._instanceConstructor;s(t)?t.constructor===r&&t._state!==it?(t._onerror=null,n._settledAt(t._state,e,t._result)):n._willSettleAt(r.resolve(t),e):(n._remaining--,n._result[e]=t)},N.prototype._settledAt=function(t,e,n){var r=this,i=r.promise;i._state===it&&(r._remaining--,t===ut?P(i,n):r._result[e]=n),0===r._remaining&&I(i,r._result)},N.prototype._willSettleAt=function(t,e){var n=this;D(t,void 0,function(t){n._settledAt(ot,e,t)},function(t){n._settledAt(ut,e,t)})};var lt=R,ft=z,dt=H,pt=Y,ht=0,vt=F;F.all=lt,F.race=ft,F.resolve=dt,F.reject=pt,F._setScheduler=c,F._setAsap=l,F._asap=Z,F.prototype={constructor:F,then:function(t,e){var n=this,r=n._state;if(r===ot&&!t||r===ut&&!e)return this;var i=new this.constructor(m),o=n._result;if(r){var u=arguments[r-1];Z(function(){k(r,i,u,o)})}else D(n,i,t,e);return i},"catch":function(t){return this.then(null,t)}};var _t=B,yt={Promise:vt,polyfill:_t};n(249).amd?(r=function(){return yt}.call(e,n,e,o),!(void 0!==r&&(o.exports=r))):"undefined"!=typeof o&&o.exports?o.exports=yt:"undefined"!=typeof this&&(this.ES6Promise=yt),_t()}).call(void 0)}).call(e,n(246),function(){return this}(),n(247)(t))},function(t,e,n){"use strict";var r=n(65),i=r(Date,"now"),o=i||function(){return(new Date).getTime()};t.exports=o},function(t,e){"use strict";function n(t){return"number"==typeof t&&t>-1&&t%1==0&&r>=t}var r=9007199254740991;t.exports=n},function(t,e,n){"use strict";var r=n(65),i=n(181),o=n(66),u="[object Array]",a=Object.prototype,s=a.toLine truncated
|
||||
function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){var n=e.date;return d["default"](n)}function a(){return _.getInitialState()}Object.defineProperty(e,"__esModule",{value:!0});var s=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),c=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},l=n(3),f=n(43),d=r(f),p=n(18),h=r(p),v=function(t){function e(){i(this,e),c(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),s(e,[{key:"getInitialState",value:function(){return d["default"](new Date)}},{key:"initialize",value:function(){this.on(h["default"].LOGBOOK_DATE_SELECTED,u),this.on(h["default"].LOG_OUT,a)}}]),e}(l.Store),_=new v;e["default"]=_,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var u=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),a=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},s=n(3),c=n(18),l=r(c),f=function(t){function e(){i(this,e),a(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),u(e,[{key:"getInitialState",value:function(){return!1}},{key:"initialize",value:function(){this.on(l["default"].LOGBOOK_ENTRIES_FETCH_START,function(){return!0}),this.on(l["default"].LOGBOOK_ENTRIES_FETCH_SUCCESS,function(){return!1}),this.on(l["default"].LOGBOOK_ENTRIES_FETCH_ERROR,function(){return!1}),this.on(l["default"].LOG_OUT,function(){return!1})}}]),e}(s.Store),d=new f;e["default"]=d,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){var n=e.date,r=e.entries;return t.set(n,l.toImmutable(r.map(h["default"].fromJSON)))}function a(){return _.getInitialState()}Object.defineProperty(e,"__esModule",{value:!0});var s=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),c=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},l=n(3),f=n(18),d=r(f),p=n(207),h=r(p),v=function(t){function e(){i(this,e),c(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),s(e,[{key:"getInitialState",value:function(){return l.toImmutable({})}},{key:"initialize",value:function(){this.on(d["default"].LOGBOOK_ENTRIES_FETCH_SUCCESS,u),this.on(d["default"].LOG_OUT,a)}}]),e}(l.Store),_=new v;e["default"]=_,t.exports=e["default"]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&nulLine truncated
|
||||
var s=n(34),c=r(s),l=n(19),f=n(83),d=r(f),p=3e3,h={}},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=["isVoiceSupported"];e.isVoiceSupported=n;var r=["currentVoiceCommand","isListening"];e.isListening=r;var i=["currentVoiceCommand","isTransmitting"];e.isTransmitting=i;var o=["currentVoiceCommand","interimTranscript"];e.interimTranscript=o;var u=["currentVoiceCommand","finalTranscript"];e.finalTranscript=u;var a=[o,u,function(t,e){return t.slice(e.length)}];e.extraInterimTranscript=a},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e["default"]=t,e}function i(t){return t&&t.__esModule?t:{"default":t}}function o(t){t.registerStores({currentVoiceCommand:c["default"],isVoiceSupported:a["default"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.register=o;var u=n(240),a=i(u),s=n(239),c=i(s),l=n(236),f=r(l),d=n(237),p=r(d),h=f;e.actions=h;var v=p;e.getters=v},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t){return t.set("isListening",!0)}function a(t,e){var n=e.interimTranscript,r=e.finalTranscript;return t.withMutations(function(t){return t.set("isListening",!0).set("isTransmitting",!1).set("interimTranscript",n).set("finalTranscript",r)})}function s(t,e){var n=e.finalTranscript;return t.withMutations(function(t){return t.set("isListening",!1).set("isTransmitting",!0).set("interimTranscript","").set("finalTranscript",n)})}function c(){return m.getInitialState()}function l(){return m.getInitialState()}function f(){return m.getInitialState()}Object.defineProperty(e,"__esModule",{value:!0});var d=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),p=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},h=n(3),v=n(83),_=r(v),y=function(t){function e(){i(this,e),p(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return o(e,t),d(e,[{key:"getInitialState",value:function(){return h.toImmutable({isListening:!1,isTransmitting:!1,interimTranscript:"",finalTranscript:""})}},{key:"initialize",value:function(){this.on(_["default"].VOICE_START,u),this.on(_["default"].VOICE_RESULT,a),this.on(_["default"].VOICE_TRANSMITTING,s),this.on(_["default"].VOICE_DONE,c),this.on(_["default"].VOICE_ERROR,l),this.on(_["default"].LOG_OUT,f)}}]),e}(h.Store),m=new y;e["default"]=m,t.exports=e["default"]},function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),u=function(t,e,n){for(var r=!0;r;){var i=t,o=e,u=n;a=c=s=void 0,r=!1,null===i&&(i=Function.prototype);var a=Object.getOwnPropertyDescriptor(i,o);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var c=Object.getPrototypeOf(i);if(null===c)return void 0;t=c,e=o,n=u,r=!0}},a=n(3),s=function(t){function e(){r(this,e),u(Object.getPrototypeOf(e.prototype),"constructor",this).apply(this,arguments)}return i(e,t),o(e,[{key:"getInitialState",value:function(){return"webkitSpeechRecognition"in window}}]),e}(a.Store),c=new s;e["default"]=c,t.exports=e["default"]},function(t,e,n){"use strict";function r(){var t=new i.Reactor({debug:!1});return t.hassId=o++,t}Object.defineProperty(e,"__esModule",{value:!0}),e["default"]=r;var i=n(3),o=0;t.exports=e["default"]},function(t,e,n){"use strict";function r(t,e){return i.toImmutable(t.attributes.entity_id.map(function(t){return e.get(t)}).filter(function(t){return!!t}))}Object.defiLine truncated
|
||||
@@ -104,7 +104,7 @@ def setup(hass, config):
|
||||
""" Sets up all groups found definded in the configuration. """
|
||||
for name, entity_ids in config.get(DOMAIN, {}).items():
|
||||
if isinstance(entity_ids, str):
|
||||
entity_ids = entity_ids.split(",")
|
||||
entity_ids = [ent.strip() for ent in entity_ids.split(",")]
|
||||
setup_group(hass, name, entity_ids)
|
||||
|
||||
return True
|
||||
|
||||
@@ -208,6 +208,11 @@ class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
|
||||
""" Registers a path wit the server. """
|
||||
self.paths.append((method, url, callback, require_auth))
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
""" Redirect built-in log to HA logging """
|
||||
# pylint: disable=no-self-use
|
||||
_LOGGER.info(fmt, *args)
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods,too-many-locals
|
||||
class RequestHandler(SimpleHTTPRequestHandler):
|
||||
@@ -225,6 +230,10 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
||||
self._session = None
|
||||
SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)
|
||||
|
||||
def log_message(self, fmt, *arguments):
|
||||
""" Redirect built-in log to HA logging """
|
||||
_LOGGER.info(fmt, *arguments)
|
||||
|
||||
def _handle_request(self, method): # pylint: disable=too-many-branches
|
||||
""" Does some common checks and calls appropriate method. """
|
||||
url = urlparse(self.path)
|
||||
|
||||
@@ -29,8 +29,11 @@ def setup(hass, config=None):
|
||||
- Available components:
|
||||
https://home-assistant.io/components/
|
||||
|
||||
- Chat room:
|
||||
https://gitter.im/balloob/home-assistant
|
||||
- Troubleshooting your configuration:
|
||||
https://home-assistant.io/getting-started/troubleshooting-configuration.html
|
||||
|
||||
- Getting help:
|
||||
https://home-assistant.io/help/
|
||||
|
||||
This message is generated by the introduction component. You can
|
||||
disable it in configuration.yaml.
|
||||
|
||||
@@ -12,9 +12,8 @@ from homeassistant.components.light import (
|
||||
|
||||
|
||||
LIGHT_COLORS = [
|
||||
[0.861, 0.3259],
|
||||
[0.6389, 0.3028],
|
||||
[0.1684, 0.0416]
|
||||
[0.368, 0.180],
|
||||
[0.460, 0.470],
|
||||
]
|
||||
|
||||
|
||||
@@ -22,8 +21,8 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return demo lights. """
|
||||
add_devices_callback([
|
||||
DemoLight("Bed Light", False),
|
||||
DemoLight("Ceiling", True),
|
||||
DemoLight("Kitchen", True)
|
||||
DemoLight("Ceiling Lights", True, LIGHT_COLORS[0]),
|
||||
DemoLight("Kitchen Lights", True, LIGHT_COLORS[1])
|
||||
])
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from homeassistant.components.media_player import (
|
||||
SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK,
|
||||
MEDIA_TYPE_MUSIC, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_VIDEO)
|
||||
|
||||
REQUIREMENTS = ['pychromecast==0.6.10']
|
||||
REQUIREMENTS = ['pychromecast==0.6.12']
|
||||
CONF_IGNORE_CEC = 'ignore_cec'
|
||||
CAST_SPLASH = 'https://home-assistant.io/images/cast/splash.png'
|
||||
SUPPORT_CAST = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
|
||||
|
||||
@@ -14,6 +14,7 @@ media_player:
|
||||
server: 127.0.0.1
|
||||
port: 6600
|
||||
location: bedroom
|
||||
password: superSecretPassword123
|
||||
|
||||
Variables:
|
||||
|
||||
@@ -28,6 +29,10 @@ Port of the Music Player Daemon, defaults to 6600. Example: 6600
|
||||
location
|
||||
*Optional
|
||||
Location of your Music Player Daemon.
|
||||
|
||||
password
|
||||
*Optional
|
||||
Password for your Music Player Daemon.
|
||||
"""
|
||||
import logging
|
||||
import socket
|
||||
@@ -61,6 +66,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
daemon = config.get('server', None)
|
||||
port = config.get('port', 6600)
|
||||
location = config.get('location', 'MPD')
|
||||
password = config.get('password', None)
|
||||
|
||||
global mpd # pylint: disable=invalid-name
|
||||
if mpd is None:
|
||||
@@ -71,6 +77,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
try:
|
||||
mpd_client = mpd.MPDClient()
|
||||
mpd_client.connect(daemon, port)
|
||||
|
||||
if password is not None:
|
||||
mpd_client.password(password)
|
||||
|
||||
mpd_client.close()
|
||||
mpd_client.disconnect()
|
||||
except socket.error:
|
||||
@@ -79,8 +89,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"Please check your settings")
|
||||
|
||||
return False
|
||||
except mpd.CommandError as error:
|
||||
|
||||
add_devices([MpdDevice(daemon, port, location)])
|
||||
if "incorrect password" in str(error):
|
||||
_LOGGER.error(
|
||||
"MPD reported incorrect password. "
|
||||
"Please check your password.")
|
||||
|
||||
return False
|
||||
else:
|
||||
raise
|
||||
|
||||
add_devices([MpdDevice(daemon, port, location, password)])
|
||||
|
||||
|
||||
class MpdDevice(MediaPlayerDevice):
|
||||
@@ -89,10 +109,11 @@ class MpdDevice(MediaPlayerDevice):
|
||||
# MPD confuses pylint
|
||||
# pylint: disable=no-member, abstract-method
|
||||
|
||||
def __init__(self, server, port, location):
|
||||
def __init__(self, server, port, location, password):
|
||||
self.server = server
|
||||
self.port = port
|
||||
self._name = location
|
||||
self.password = password
|
||||
self.status = None
|
||||
self.currentsong = None
|
||||
|
||||
@@ -107,6 +128,10 @@ class MpdDevice(MediaPlayerDevice):
|
||||
self.currentsong = self.client.currentsong()
|
||||
except mpd.ConnectionError:
|
||||
self.client.connect(self.server, self.port)
|
||||
|
||||
if self.password is not None:
|
||||
self.client.password(self.password)
|
||||
|
||||
self.status = self.client.status()
|
||||
self.currentsong = self.client.currentsong()
|
||||
|
||||
@@ -189,11 +214,11 @@ class MpdDevice(MediaPlayerDevice):
|
||||
|
||||
def media_play(self):
|
||||
""" Service to send the MPD the command for play/pause. """
|
||||
self.client.start()
|
||||
self.client.pause(0)
|
||||
|
||||
def media_pause(self):
|
||||
""" Service to send the MPD the command for play/pause. """
|
||||
self.client.pause()
|
||||
self.client.pause(1)
|
||||
|
||||
def media_next_track(self):
|
||||
""" Service to send the MPD the command for next track. """
|
||||
|
||||
@@ -24,6 +24,7 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
ATTR_TODAY_MWH = "today_mwh"
|
||||
ATTR_CURRENT_POWER_MWH = "current_power_mwh"
|
||||
ATTR_SENSOR_STATE = "sensor_state"
|
||||
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
||||
@@ -38,6 +39,7 @@ DISCOVERY_PLATFORMS = {
|
||||
PROP_TO_ATTR = {
|
||||
'current_power_mwh': ATTR_CURRENT_POWER_MWH,
|
||||
'today_power_mw': ATTR_TODAY_MWH,
|
||||
'sensor_state': ATTR_SENSOR_STATE
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -101,6 +103,16 @@ class SwitchDevice(ToggleEntity):
|
||||
""" Today total power usage in mw. """
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_standby(self):
|
||||
""" Is the device in standby. """
|
||||
return None
|
||||
|
||||
@property
|
||||
def sensor_state(self):
|
||||
""" Is the sensor on or off. """
|
||||
return None
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
""" Returns device specific state attributes. """
|
||||
|
||||
@@ -13,7 +13,7 @@ from homeassistant.const import DEVICE_DEFAULT_NAME
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return demo switches. """
|
||||
add_devices_callback([
|
||||
DemoSwitch('Ceiling', True),
|
||||
DemoSwitch('Decorative Lights', True),
|
||||
DemoSwitch('AC', False)
|
||||
])
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ Support for WeMo switches.
|
||||
import logging
|
||||
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
from homeassistant.const import STATE_ON, STATE_OFF, STATE_STANDBY
|
||||
|
||||
REQUIREMENTS = ['pywemo==0.2']
|
||||
REQUIREMENTS = ['pywemo==0.3']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@@ -39,6 +40,7 @@ class WemoSwitch(SwitchDevice):
|
||||
def __init__(self, wemo):
|
||||
self.wemo = wemo
|
||||
self.insight_params = None
|
||||
self.maker_params = None
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
@@ -50,6 +52,16 @@ class WemoSwitch(SwitchDevice):
|
||||
""" Returns the name of the switch if any. """
|
||||
return self.wemo.name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
""" Returns the state. """
|
||||
is_on = self.is_on
|
||||
if not is_on:
|
||||
return STATE_OFF
|
||||
elif self.is_standby:
|
||||
return STATE_STANDBY
|
||||
return STATE_ON
|
||||
|
||||
@property
|
||||
def current_power_mwh(self):
|
||||
""" Current power usage in mwh. """
|
||||
@@ -62,6 +74,40 @@ class WemoSwitch(SwitchDevice):
|
||||
if self.insight_params:
|
||||
return self.insight_params['todaymw']
|
||||
|
||||
@property
|
||||
def is_standby(self):
|
||||
""" Is the device on - or in standby. """
|
||||
if self.insight_params:
|
||||
standby_state = self.insight_params['state']
|
||||
# Standby is actually '8' but seems more defensive
|
||||
# to check for the On and Off states
|
||||
if standby_state == '1' or standby_state == '0':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@property
|
||||
def sensor_state(self):
|
||||
""" Is the sensor on or off. """
|
||||
if self.maker_params and self.has_sensor:
|
||||
# Note a state of 1 matches the WeMo app 'not triggered'!
|
||||
if self.maker_params['sensorstate']:
|
||||
return STATE_OFF
|
||||
else:
|
||||
return STATE_ON
|
||||
|
||||
@property
|
||||
def switch_mode(self):
|
||||
""" Is the switch configured as toggle(0) or momentary (1). """
|
||||
if self.maker_params:
|
||||
return self.maker_params['switchmode']
|
||||
|
||||
@property
|
||||
def has_sensor(self):
|
||||
""" Is the sensor present? """
|
||||
if self.maker_params:
|
||||
return self.maker_params['hassensor']
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
""" True if switch is on. """
|
||||
@@ -78,5 +124,8 @@ class WemoSwitch(SwitchDevice):
|
||||
def update(self):
|
||||
""" Update WeMo state. """
|
||||
self.wemo.get_state(True)
|
||||
if self.wemo.model.startswith('Belkin Insight'):
|
||||
if self.wemo.model_name == 'Insight':
|
||||
self.insight_params = self.wemo.insight_params
|
||||
self.insight_params['standby_state'] = self.wemo.get_standby_state
|
||||
elif self.wemo.model_name == 'Maker':
|
||||
self.maker_params = self.wemo.maker_params
|
||||
@@ -54,7 +54,7 @@ def ensure_config_exists(config_dir, detect_location=True):
|
||||
config_path = find_config_file(config_dir)
|
||||
|
||||
if config_path is None:
|
||||
print("Unable to find configuration. Creating default one at",
|
||||
print("Unable to find configuration. Creating default one in",
|
||||
config_dir)
|
||||
config_path = create_default_config(config_dir, detect_location)
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ STATE_CLOSED = 'closed'
|
||||
STATE_PLAYING = 'playing'
|
||||
STATE_PAUSED = 'paused'
|
||||
STATE_IDLE = 'idle'
|
||||
STATE_STANDBY = 'standby'
|
||||
|
||||
# #### STATE AND EVENT ATTRIBUTES ####
|
||||
# Contains current time for a TIME_CHANGED event
|
||||
|
||||
@@ -9,6 +9,7 @@ of entities and react to changes.
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import signal
|
||||
import threading
|
||||
import enum
|
||||
import re
|
||||
@@ -73,13 +74,16 @@ class HomeAssistant(object):
|
||||
will block until called. """
|
||||
request_shutdown = threading.Event()
|
||||
|
||||
def stop_homeassistant(service):
|
||||
def stop_homeassistant(*args):
|
||||
""" Stops Home Assistant. """
|
||||
request_shutdown.set()
|
||||
|
||||
self.services.register(
|
||||
DOMAIN, SERVICE_HOMEASSISTANT_STOP, stop_homeassistant)
|
||||
|
||||
if os.name != "nt":
|
||||
signal.signal(signal.SIGQUIT, stop_homeassistant)
|
||||
|
||||
while not request_shutdown.isSet():
|
||||
try:
|
||||
time.sleep(1)
|
||||
@@ -761,8 +765,10 @@ def create_timer(hass, interval=TIMER_INTERVAL):
|
||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_timer)
|
||||
|
||||
|
||||
def create_worker_pool(worker_count=MIN_WORKER_THREAD):
|
||||
def create_worker_pool(worker_count=None):
|
||||
""" Creates a worker pool to be used. """
|
||||
if worker_count is None:
|
||||
worker_count = MIN_WORKER_THREAD
|
||||
|
||||
def job_handler(job):
|
||||
""" Called whenever a job is available to do. """
|
||||
|
||||
@@ -16,7 +16,7 @@ phue==0.8
|
||||
ledcontroller==1.0.7
|
||||
|
||||
# Chromecast bindings (media_player.cast)
|
||||
pychromecast==0.6.10
|
||||
pychromecast==0.6.12
|
||||
|
||||
# Keyboard (keyboard)
|
||||
pyuserinput==0.1.9
|
||||
@@ -25,7 +25,7 @@ pyuserinput==0.1.9
|
||||
tellcore-py==1.0.4
|
||||
|
||||
# Nmap bindings (device_tracker.nmap)
|
||||
python-libnmap==0.6.3
|
||||
python-nmap==0.4.1
|
||||
|
||||
# PushBullet bindings (notify.pushbullet)
|
||||
pushbullet.py==0.7.1
|
||||
@@ -89,7 +89,7 @@ pynetgear==0.3
|
||||
netdisco==0.3
|
||||
|
||||
# Wemo (switch.wemo)
|
||||
pywemo==0.2
|
||||
pywemo==0.3
|
||||
|
||||
# Wink (*.wink)
|
||||
https://github.com/balloob/python-wink/archive/c2b700e8ca866159566ecf5e644d9c297f69f257.zip
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: hass
|
||||
# Required-Start: $local_fs $network $named $time $syslog
|
||||
# Required-Stop: $local_fs $network $named $time $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Description: Home\ Assistant
|
||||
### END INIT INFO
|
||||
|
||||
# /etc/init.d Service Script for Home Assistant
|
||||
# Created with: https://gist.github.com/naholyr/4275302#file-new-service-sh
|
||||
#
|
||||
# Installation:
|
||||
# 1) If any commands need to run before executing hass (like loading a
|
||||
# virutal environment), put them in PRE_EXEC. This command must end with
|
||||
# a semicolon.
|
||||
# 2) Set RUN_AS to the username that should be used to execute hass.
|
||||
# 3) Copy this script to /etc/init.d/
|
||||
# sudo cp hass-daemon /etc/init.d/hass-daemon
|
||||
# sudo chmod +x /etc/init.d/hass-daemon
|
||||
# 4) Register the daemon with Linux
|
||||
# sudo update-rc.d hass-daemon defaults
|
||||
# 5) Install this service
|
||||
# sudo service hass-daemon install
|
||||
# 6) Restart Machine
|
||||
#
|
||||
# After installation, HA should start automatically. If HA does not start,
|
||||
# check the log file output for errors.
|
||||
# /var/opt/homeassistant/home-assistant.log
|
||||
|
||||
PRE_EXEC=""
|
||||
RUN_AS="USER"
|
||||
PID_FILE="/var/run/hass.pid"
|
||||
CONFIG_DIR="/var/opt/homeassistant"
|
||||
FLAGS="-v --config $CONFIG_DIR --pid-file $PID_FILE --daemon"
|
||||
|
||||
start() {
|
||||
if [ -f $PID_FILE ] && kill -0 $(cat $PID_FILE); then
|
||||
echo 'Service already running' >&2
|
||||
return 1
|
||||
fi
|
||||
echo 'Starting service…' >&2
|
||||
local CMD="$PRE_EXEC hass $FLAGS;"
|
||||
su -c "$CMD" $RUN_AS
|
||||
echo 'Service started' >&2
|
||||
}
|
||||
|
||||
stop() {
|
||||
if [ ! -f "$PID_FILE" ] || ! kill -0 $(cat "$PID_FILE"); then
|
||||
echo 'Service not running' >&2
|
||||
return 1
|
||||
fi
|
||||
echo 'Stopping service…' >&2
|
||||
kill -3 $(cat "$PID_FILE")
|
||||
echo 'Service stopped' >&2
|
||||
}
|
||||
|
||||
install() {
|
||||
echo "Installing Home Assistant Daemon (hass-daemon)"
|
||||
echo "999999" > $PID_FILE
|
||||
chown $RUN_AS $PID_FILE
|
||||
mkdir -p $CONFIG_DIR
|
||||
chown $RUN_AS $CONFIG_DIR
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
|
||||
local SURE
|
||||
read SURE
|
||||
if [ "$SURE" = "yes" ]; then
|
||||
stop
|
||||
rm -fv "$PID_FILE"
|
||||
echo "Notice: The config directory has not been removed"
|
||||
echo $CONFIG_DIR
|
||||
update-rc.d -f hass-daemon remove
|
||||
rm -fv "$0"
|
||||
echo "Home Assistant Daemon has been removed. Home Assistant is still installed."
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
install)
|
||||
install
|
||||
;;
|
||||
uninstall)
|
||||
uninstall
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|install|uninstall}"
|
||||
esac
|
||||
@@ -1,78 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# To script is for running Home Assistant as a service and automatically starting it on boot.
|
||||
# Assuming you have cloned the HA repo into /home/pi/Apps/home-assistant adjust this path if necessary
|
||||
# This also assumes you installed HA on your raspberry pi using the instructions here:
|
||||
# https://home-assistant.io/getting-started/
|
||||
#
|
||||
# To install to the following:
|
||||
# sudo cp /home/pi/Apps/home-assistant/scripts/homeassistant-pi.sh /etc/init.d/homeassistant.sh
|
||||
# sudo chmod +x /etc/init.d/homeassistant.sh
|
||||
# sudo chown root:root /etc/init.d/homeassistant.sh
|
||||
#
|
||||
# If you want HA to start on boot also run the following:
|
||||
# sudo update-rc.d homeassistant.sh defaults
|
||||
# sudo update-rc.d homeassistant.sh enable
|
||||
#
|
||||
# You should now be able to start HA by running
|
||||
# sudo /etc/init.d/homeassistant.sh start
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: myservice
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Put a short description of the service here
|
||||
# Description: Put a long description of the service here
|
||||
### END INIT INFO
|
||||
|
||||
# Change the next 3 lines to suit where you install your script and what you want to call it
|
||||
DIR=/home/pi/Apps/home-assistant
|
||||
DAEMON="/home/pi/.pyenv/shims/python3 -m homeassistant"
|
||||
DAEMON_NAME=homeassistant
|
||||
|
||||
# Add any command line options for your daemon here
|
||||
DAEMON_OPTS=""
|
||||
|
||||
# This next line determines what user the script runs as.
|
||||
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
|
||||
DAEMON_USER=pi
|
||||
|
||||
# The process ID of the script when it runs is stored here:
|
||||
PIDFILE=/var/run/$DAEMON_NAME.pid
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
do_start () {
|
||||
log_daemon_msg "Starting system $DAEMON_NAME daemon"
|
||||
start-stop-daemon --start --background --chdir $DIR --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
|
||||
log_end_msg $?
|
||||
}
|
||||
do_stop () {
|
||||
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
|
||||
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
|
||||
log_end_msg $?
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
|
||||
start|stop)
|
||||
do_${1}
|
||||
;;
|
||||
|
||||
restart|reload|force-reload)
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
|
||||
status)
|
||||
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
exit 0
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: homeassistant
|
||||
# Required-Start: $local_fs $network $named $time $syslog
|
||||
# Required-Stop: $local_fs $network $named $time $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Description: Home\ Assistant
|
||||
### END INIT INFO
|
||||
|
||||
# /etc/init.d Service Script for Home Assistant
|
||||
# Created with: https://gist.github.com/naholyr/4275302#file-new-service-sh
|
||||
#
|
||||
# Installation:
|
||||
# 1) Populate RUNAS and RUNDIR variables
|
||||
# 2) Create Log -- sudo touch /var/log/homeassistant.log
|
||||
# 3) Set Log Ownership -- sudo chown USER:GROUP /var/log/homeassistant.log
|
||||
# 4) Create PID File -- sudo touch /var/run/homeassistant.pid
|
||||
# 5) Set PID File Ownership -- sudo chown USER:GROUP /var/run/homeassistant.pid
|
||||
# 6) Install init.d script -- cp homeassistant.daemon /etc/init.d/homeassistant
|
||||
# 7) Setup HA for Auto Start -- sudo update-rc.d homeassistant defaults
|
||||
# 8) Run HA -- sudo service homeassistant start
|
||||
#
|
||||
# After installation, HA should start automatically. If HA does not start,
|
||||
# check the log file output for errors. (/var/log/homeassistant.log)
|
||||
#
|
||||
# For this script, it is assumed that you are using a local Virtual Environment
|
||||
# per the install directions as http://home-assistant.io
|
||||
# If you are not, the SCRIPT variable must be modified to point to the correct
|
||||
# Python environment.
|
||||
|
||||
SCRIPT="source bin/activate; ./bin/python -m homeassistant"
|
||||
RUNAS=<USER TO RUN SERVER AS>
|
||||
RUNDIR=<LOCATION OF home-assistant DIR>
|
||||
PIDFILE=/var/run/homeassistant.pid
|
||||
LOGFILE=/var/log/homeassistant.log
|
||||
|
||||
start() {
|
||||
if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then
|
||||
echo 'Service already running' >&2
|
||||
return 1
|
||||
fi
|
||||
echo 'Starting service…' >&2
|
||||
local CMD="cd $RUNDIR; $SCRIPT &> \"$LOGFILE\" & echo \$!"
|
||||
su -c "$CMD" $RUNAS > "$PIDFILE"
|
||||
echo 'Service started' >&2
|
||||
}
|
||||
|
||||
stop() {
|
||||
if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
|
||||
echo 'Service not running' >&2
|
||||
return 1
|
||||
fi
|
||||
echo 'Stopping service…' >&2
|
||||
kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
|
||||
echo 'Service stopped' >&2
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
|
||||
local SURE
|
||||
read SURE
|
||||
if [ "$SURE" = "yes" ]; then
|
||||
stop
|
||||
rm -f "$PIDFILE"
|
||||
echo "Notice: log file is not be removed: '$LOGFILE'" >&2
|
||||
update-rc.d -f homeassistant remove
|
||||
rm -fv "$0"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
uninstall)
|
||||
uninstall
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|uninstall}"
|
||||
esac
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
# If current pwd is scripts, go 1 up.
|
||||
if [ ${PWD##*/} == "scripts" ]; then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
git pull
|
||||
echo "The update script has been deprecated since Home Assistant v0.7"
|
||||
echo
|
||||
echo "Home Assistant is now distributed via PyPi and can be installed and"
|
||||
echo "upgraded by running: pip3 install --upgrade homeassistant"
|
||||
echo
|
||||
echo "If you are developing a new feature for Home Assistant, run: git pull"
|
||||
@@ -7,7 +7,7 @@ HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
with open(os.path.join(HERE, PACKAGE_NAME, 'const.py')) as fp:
|
||||
VERSION = re.search("__version__ = ['\"]([^']+)['\"]\n", fp.read()).group(1)
|
||||
DOWNLOAD_URL = \
|
||||
'https://github.com/balloob/home-assistant/tarball/{}'.format(VERSION)
|
||||
'https://github.com/balloob/home-assistant/archive/{}.zip'.format(VERSION)
|
||||
|
||||
PACKAGES = find_packages() + \
|
||||
['homeassistant.external', 'homeassistant.external.noop',
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import logging
|
||||
logging.disable(logging.CRITICAL)
|
||||
+4
-1
@@ -8,7 +8,7 @@ import os
|
||||
from datetime import timedelta
|
||||
from unittest import mock
|
||||
|
||||
import homeassistant.core as ha
|
||||
from homeassistant import core as ha, loader
|
||||
import homeassistant.util.location as location_util
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
@@ -38,6 +38,9 @@ def get_test_home_assistant(num_threads=None):
|
||||
hass.config.latitude = 32.87336
|
||||
hass.config.longitude = -117.22743
|
||||
|
||||
# if not loader.PREPARED:
|
||||
loader. prepare(hass)
|
||||
|
||||
return hass
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ class TestAutomationTime(unittest.TestCase):
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
self.hass = ha.HomeAssistant()
|
||||
loader.prepare(self.hass)
|
||||
self.calls = []
|
||||
|
||||
def record_call(service):
|
||||
|
||||
@@ -7,6 +7,7 @@ Tests Home Assistant HTTP component does what it should do.
|
||||
# pylint: disable=protected-access,too-many-public-methods
|
||||
import unittest
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
import requests
|
||||
|
||||
@@ -35,7 +36,9 @@ def _url(path=""):
|
||||
return HTTP_BASE_URL + path
|
||||
|
||||
|
||||
def setUpModule(): # pylint: disable=invalid-name
|
||||
@patch('homeassistant.components.http.util.get_local_ip',
|
||||
return_value='127.0.0.1')
|
||||
def setUpModule(mock_get_local_ip): # pylint: disable=invalid-name
|
||||
""" Initalizes a Home Assistant server. """
|
||||
global hass
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
tests.components.test_conversation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tests Conversation component.
|
||||
"""
|
||||
# pylint: disable=too-many-public-methods,protected-access
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import homeassistant.components as core_components
|
||||
from homeassistant.components import conversation
|
||||
from homeassistant.const import ATTR_ENTITY_ID
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
class TestConversation(unittest.TestCase):
|
||||
""" Test the conversation component. """
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
""" Start up ha for testing """
|
||||
self.ent_id = 'light.kitchen_lights'
|
||||
self.hass = get_test_home_assistant(3)
|
||||
self.hass.states.set(self.ent_id, 'on')
|
||||
self.assertTrue(core_components.setup(self.hass, {}))
|
||||
self.assertTrue(
|
||||
conversation.setup(self.hass, {conversation.DOMAIN: {}}))
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""" Stop down stuff we started. """
|
||||
self.hass.stop()
|
||||
|
||||
def test_turn_on(self):
|
||||
""" Setup and perform good turn on requests """
|
||||
calls = []
|
||||
|
||||
def record_call(service):
|
||||
calls.append(service)
|
||||
|
||||
self.hass.services.register('light', 'turn_on', record_call)
|
||||
|
||||
event_data = {conversation.ATTR_TEXT: 'turn kitchen lights on'}
|
||||
self.assertTrue(self.hass.services.call(
|
||||
conversation.DOMAIN, 'process', event_data, True))
|
||||
|
||||
call = calls[-1]
|
||||
self.assertEqual('light', call.domain)
|
||||
self.assertEqual('turn_on', call.service)
|
||||
self.assertEqual([self.ent_id], call.data[ATTR_ENTITY_ID])
|
||||
|
||||
def test_turn_off(self):
|
||||
""" Setup and perform good turn off requests """
|
||||
calls = []
|
||||
|
||||
def record_call(service):
|
||||
calls.append(service)
|
||||
|
||||
self.hass.services.register('light', 'turn_off', record_call)
|
||||
|
||||
event_data = {conversation.ATTR_TEXT: 'turn kitchen lights off'}
|
||||
self.assertTrue(self.hass.services.call(
|
||||
conversation.DOMAIN, 'process', event_data, True))
|
||||
|
||||
call = calls[-1]
|
||||
self.assertEqual('light', call.domain)
|
||||
self.assertEqual('turn_off', call.service)
|
||||
self.assertEqual([self.ent_id], call.data[ATTR_ENTITY_ID])
|
||||
|
||||
@patch('homeassistant.components.conversation.logging.Logger.error')
|
||||
@patch('homeassistant.core.ServiceRegistry.call')
|
||||
def test_bad_request_format(self, mock_logger, mock_call):
|
||||
""" Setup and perform a badly formatted request """
|
||||
event_data = {
|
||||
conversation.ATTR_TEXT:
|
||||
'what is the answer to the ultimate question of life, ' +
|
||||
'the universe and everything'}
|
||||
self.assertTrue(self.hass.services.call(
|
||||
conversation.DOMAIN, 'process', event_data, True))
|
||||
self.assertTrue(mock_logger.called)
|
||||
self.assertFalse(mock_call.called)
|
||||
|
||||
@patch('homeassistant.components.conversation.logging.Logger.error')
|
||||
@patch('homeassistant.core.ServiceRegistry.call')
|
||||
def test_bad_request_entity(self, mock_logger, mock_call):
|
||||
""" Setup and perform requests with bad entity id """
|
||||
event_data = {conversation.ATTR_TEXT: 'turn something off'}
|
||||
self.assertTrue(self.hass.services.call(
|
||||
conversation.DOMAIN, 'process', event_data, True))
|
||||
self.assertTrue(mock_logger.called)
|
||||
self.assertFalse(mock_call.called)
|
||||
|
||||
@patch('homeassistant.components.conversation.logging.Logger.error')
|
||||
@patch('homeassistant.core.ServiceRegistry.call')
|
||||
def test_bad_request_command(self, mock_logger, mock_call):
|
||||
""" Setup and perform requests with bad command """
|
||||
event_data = {conversation.ATTR_TEXT: 'turn kitchen lights over'}
|
||||
self.assertTrue(self.hass.services.call(
|
||||
conversation.DOMAIN, 'process', event_data, True))
|
||||
self.assertTrue(mock_logger.called)
|
||||
self.assertFalse(mock_call.called)
|
||||
|
||||
@patch('homeassistant.components.conversation.logging.Logger.error')
|
||||
@patch('homeassistant.core.ServiceRegistry.call')
|
||||
def test_bad_request_notext(self, mock_logger, mock_call):
|
||||
""" Setup and perform requests with bad command with no text """
|
||||
event_data = {}
|
||||
self.assertTrue(self.hass.services.call(
|
||||
conversation.DOMAIN, 'process', event_data, True))
|
||||
self.assertTrue(mock_logger.called)
|
||||
self.assertFalse(mock_call.called)
|
||||
@@ -15,8 +15,8 @@ from homeassistant.components import (
|
||||
|
||||
|
||||
from tests.common import (
|
||||
get_test_home_assistant, ensure_sun_risen, ensure_sun_set,
|
||||
trigger_device_tracker_scan)
|
||||
get_test_config_dir, get_test_home_assistant, ensure_sun_risen,
|
||||
ensure_sun_set, trigger_device_tracker_scan)
|
||||
|
||||
|
||||
KNOWN_DEV_PATH = None
|
||||
@@ -26,13 +26,8 @@ def setUpModule(): # pylint: disable=invalid-name
|
||||
""" Initalizes a Home Assistant server. """
|
||||
global KNOWN_DEV_PATH
|
||||
|
||||
hass = get_test_home_assistant()
|
||||
|
||||
loader.prepare(hass)
|
||||
KNOWN_DEV_PATH = hass.config.path(
|
||||
device_tracker.KNOWN_DEVICES_FILE)
|
||||
|
||||
hass.stop()
|
||||
KNOWN_DEV_PATH = os.path.join(get_test_config_dir(),
|
||||
device_tracker.KNOWN_DEVICES_FILE)
|
||||
|
||||
with open(KNOWN_DEV_PATH, 'w') as fil:
|
||||
fil.write('device,name,track,picture\n')
|
||||
|
||||
@@ -7,7 +7,6 @@ Tests the device tracker compoments.
|
||||
# pylint: disable=protected-access,too-many-public-methods
|
||||
import unittest
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import os
|
||||
|
||||
import homeassistant.core as ha
|
||||
@@ -21,18 +20,12 @@ import homeassistant.components.device_tracker as device_tracker
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
def setUpModule(): # pylint: disable=invalid-name
|
||||
""" Setup to ignore group errors. """
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
|
||||
class TestComponentsDeviceTracker(unittest.TestCase):
|
||||
""" Tests homeassistant.components.device_tracker module. """
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
""" Init needed objects. """
|
||||
self.hass = get_test_home_assistant()
|
||||
loader.prepare(self.hass)
|
||||
|
||||
self.known_dev_path = self.hass.config.path(
|
||||
device_tracker.KNOWN_DEVICES_FILE)
|
||||
|
||||
@@ -7,6 +7,7 @@ Tests Home Assistant HTTP component does what it should do.
|
||||
# pylint: disable=protected-access,too-many-public-methods
|
||||
import re
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import requests
|
||||
|
||||
@@ -34,7 +35,9 @@ def _url(path=""):
|
||||
return HTTP_BASE_URL + path
|
||||
|
||||
|
||||
def setUpModule(): # pylint: disable=invalid-name
|
||||
@patch('homeassistant.components.http.util.get_local_ip',
|
||||
return_value='127.0.0.1')
|
||||
def setUpModule(mock_get_local_ip): # pylint: disable=invalid-name
|
||||
""" Initalizes a Home Assistant server. """
|
||||
global hass
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ class TestComponentsGroup(unittest.TestCase):
|
||||
self.hass,
|
||||
{
|
||||
group.DOMAIN: {
|
||||
'second_group': self.group_entity_id + ',light.Bowl'
|
||||
'second_group': 'light.Bowl, ' + self.group_entity_id
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -207,6 +207,8 @@ class TestComponentsGroup(unittest.TestCase):
|
||||
group.ENTITY_ID_FORMAT.format('second_group'))
|
||||
|
||||
self.assertEqual(STATE_ON, group_state.state)
|
||||
self.assertEqual(set((self.group_entity_id, 'light.bowl')),
|
||||
set(group_state.attributes['entity_id']))
|
||||
self.assertFalse(group_state.attributes[group.ATTR_AUTO])
|
||||
|
||||
def test_groups_get_unique_names(self):
|
||||
|
||||
@@ -20,7 +20,6 @@ class TestComponentsCore(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
""" Init needed objects. """
|
||||
self.hass = ha.HomeAssistant()
|
||||
loader.prepare(self.hass)
|
||||
self.assertTrue(comps.setup(self.hass, {}))
|
||||
|
||||
self.hass.states.set('light.Bowl', STATE_ON)
|
||||
|
||||
@@ -23,7 +23,6 @@ class TestLight(unittest.TestCase):
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
self.hass = get_test_home_assistant()
|
||||
loader.prepare(self.hass)
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""" Stop down stuff we started. """
|
||||
|
||||
@@ -5,7 +5,6 @@ tests.test_component_media_player
|
||||
Tests media_player component.
|
||||
"""
|
||||
# pylint: disable=too-many-public-methods,protected-access
|
||||
import logging
|
||||
import unittest
|
||||
|
||||
import homeassistant.core as ha
|
||||
@@ -18,11 +17,6 @@ import homeassistant.components.media_player as media_player
|
||||
from tests.common import mock_service
|
||||
|
||||
|
||||
def setUpModule(): # pylint: disable=invalid-name
|
||||
""" Setup to ignore media_player errors. """
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
|
||||
class TestMediaPlayer(unittest.TestCase):
|
||||
""" Test the media_player module. """
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ class TestSun(unittest.TestCase):
|
||||
""" Test if the state changes at next setting/rising. """
|
||||
self.hass.config.latitude = '32.87336'
|
||||
self.hass.config.longitude = '117.22743'
|
||||
sun.setup(self.hass, {})
|
||||
sun.setup(self.hass, {sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
|
||||
if sun.is_on(self.hass):
|
||||
test_state = sun.STATE_BELOW_HORIZON
|
||||
|
||||
@@ -19,7 +19,6 @@ class TestSwitch(unittest.TestCase):
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
self.hass = get_test_home_assistant()
|
||||
loader.prepare(self.hass)
|
||||
|
||||
platform = loader.get_component('switch.test')
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ class TestComponentsCore(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
""" Init needed objects. """
|
||||
self.hass = get_test_home_assistant()
|
||||
loader.prepare(self.hass)
|
||||
|
||||
self.hass.states.set('light.Bowl', STATE_ON)
|
||||
self.hass.states.set('light.Ceiling', STATE_OFF)
|
||||
|
||||
+13
-6
@@ -49,13 +49,15 @@ class TestConfig(unittest.TestCase):
|
||||
|
||||
self.assertEqual(YAML_PATH, config_util.find_config_file(CONFIG_DIR))
|
||||
|
||||
def test_ensure_config_exists_creates_config(self):
|
||||
@mock.patch('builtins.print')
|
||||
def test_ensure_config_exists_creates_config(self, mock_print):
|
||||
""" Test that calling ensure_config_exists creates a new config file if
|
||||
none exists. """
|
||||
|
||||
config_util.ensure_config_exists(CONFIG_DIR, False)
|
||||
|
||||
self.assertTrue(os.path.isfile(YAML_PATH))
|
||||
self.assertTrue(mock_print.called)
|
||||
|
||||
def test_ensure_config_exists_uses_existing_config(self):
|
||||
""" Test that calling ensure_config_exists uses existing config. """
|
||||
@@ -100,11 +102,12 @@ class TestConfig(unittest.TestCase):
|
||||
self.assertEqual({'hello': 'world'},
|
||||
config_util.load_config_file(YAML_PATH))
|
||||
|
||||
def test_create_default_config_detect_location(self):
|
||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||
mock_detect_location_info)
|
||||
@mock.patch('builtins.print')
|
||||
def test_create_default_config_detect_location(self, mock_print):
|
||||
""" Test that detect location sets the correct config keys. """
|
||||
with mock.patch('homeassistant.util.location.detect_location_info',
|
||||
mock_detect_location_info):
|
||||
config_util.ensure_config_exists(CONFIG_DIR)
|
||||
config_util.ensure_config_exists(CONFIG_DIR)
|
||||
|
||||
config = config_util.load_config_file(YAML_PATH)
|
||||
|
||||
@@ -121,11 +124,15 @@ class TestConfig(unittest.TestCase):
|
||||
}
|
||||
|
||||
self.assertEqual(expected_values, ha_conf)
|
||||
self.assertTrue(mock_print.called)
|
||||
|
||||
def test_create_default_config_returns_none_if_write_error(self):
|
||||
@mock.patch('builtins.print')
|
||||
def test_create_default_config_returns_none_if_write_error(self,
|
||||
mock_print):
|
||||
"""
|
||||
Test that writing default config to non existing folder returns None.
|
||||
"""
|
||||
self.assertIsNone(
|
||||
config_util.create_default_config(
|
||||
os.path.join(CONFIG_DIR, 'non_existing_dir/'), False))
|
||||
self.assertTrue(mock_print.called)
|
||||
@@ -17,7 +17,6 @@ class TestLoader(unittest.TestCase):
|
||||
""" Test the loader module. """
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
self.hass = get_test_home_assistant()
|
||||
loader.prepare(self.hass)
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""" Stop down stuff we started. """
|
||||
|
||||
@@ -8,6 +8,7 @@ Uses port 8125 as a port that nothing runs on
|
||||
"""
|
||||
# pylint: disable=protected-access,too-many-public-methods
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import homeassistant.core as ha
|
||||
import homeassistant.bootstrap as bootstrap
|
||||
@@ -29,7 +30,9 @@ def _url(path=""):
|
||||
return HTTP_BASE_URL + path
|
||||
|
||||
|
||||
def setUpModule(): # pylint: disable=invalid-name
|
||||
@patch('homeassistant.components.http.util.get_local_ip',
|
||||
return_value='127.0.0.1')
|
||||
def setUpModule(mock_get_local_ip): # pylint: disable=invalid-name
|
||||
""" Initalizes a Home Assistant server and Slave instance. """
|
||||
global hass, slave, master_api, broken_api
|
||||
|
||||
@@ -51,6 +54,10 @@ def setUpModule(): # pylint: disable=invalid-name
|
||||
|
||||
# Start slave
|
||||
slave = remote.HomeAssistant(master_api)
|
||||
bootstrap.setup_component(
|
||||
slave, http.DOMAIN,
|
||||
{http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD,
|
||||
http.CONF_SERVER_PORT: 8130}})
|
||||
|
||||
slave.start()
|
||||
|
||||
|
||||
Reference in new issue
Block a user