gitignore ready for emacs

This commit is contained in:
Malte Deiseroth
2015-09-16 08:34:08 +02:00
275 changed files with 21134 additions and 6724 deletions
+3 -1
View File
@@ -6,7 +6,7 @@ Component to interface with various sensors that can be monitored.
import logging
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.components import wink, zwave
from homeassistant.components import wink, zwave, isy994, verisure
DOMAIN = 'sensor'
DEPENDENCIES = []
@@ -18,6 +18,8 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}'
DISCOVERY_PLATFORMS = {
wink.DISCOVER_SENSORS: 'wink',
zwave.DISCOVER_SENSORS: 'zwave',
isy994.DISCOVER_SENSORS: 'isy994',
verisure.DISCOVER_SENSORS: 'verisure'
}
@@ -0,0 +1,90 @@
"""
homeassistant.components.sensor.arduino
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for getting information from Arduino pins. Only analog pins are
supported.
Configuration:
To use the arduino sensor you will need to add something like the following
to your configuration.yaml file.
sensor:
platform: arduino
pins:
7:
name: Door switch
type: analog
0:
name: Brightness
type: analog
Variables:
pins
*Required
An array specifying the digital pins to use on the Arduino board.
These are the variables for the pins array:
name
*Required
The name for the pin that will be used in the frontend.
type
*Required
The type of the pin: 'analog'.
"""
import logging
import homeassistant.components.arduino as arduino
from homeassistant.helpers.entity import Entity
from homeassistant.const import DEVICE_DEFAULT_NAME
DEPENDENCIES = ['arduino']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Arduino platform. """
# Verify that the Arduino board is present
if arduino.BOARD is None:
_LOGGER.error('A connection has not been made to the Arduino board.')
return False
sensors = []
pins = config.get('pins')
for pinnum, pin in pins.items():
if pin.get('name'):
sensors.append(ArduinoSensor(pin.get('name'),
pinnum,
'analog'))
add_devices(sensors)
class ArduinoSensor(Entity):
""" Represents an Arduino Sensor. """
def __init__(self, name, pin, pin_type):
self._pin = pin
self._name = name or DEVICE_DEFAULT_NAME
self.pin_type = pin_type
self.direction = 'in'
self._value = None
arduino.BOARD.set_mode(self._pin, self.direction, self.pin_type)
@property
def state(self):
""" Returns the state of the sensor. """
return self._value
@property
def name(self):
""" Get the name of the sensor. """
return self._name
def update(self):
""" Get the latest value from the pin. """
self._value = arduino.BOARD.get_analog_inputs()[self._pin][1]
+150
View File
@@ -0,0 +1,150 @@
"""
homeassistant.components.sensor.arest
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The arest sensor will consume an exposed aREST API of a device.
Configuration:
To use the arest sensor you will need to add something like the following
to your configuration.yaml file.
sensor:
platform: arest
resource: http://IP_ADDRESS
monitored_variables:
- name: temperature
unit: '°C'
- name: humidity
unit: '%'
Variables:
resource:
*Required
IP address of the device that is exposing an aREST API.
These are the variables for the monitored_variables array:
name
*Required
The name of the variable you wish to monitor.
unit
*Optional
Defines the units of measurement of the sensor, if any.
Details for the API: http://arest.io
Format of a default JSON response by aREST:
{
"variables":{
"temperature":21,
"humidity":89
},
"id":"device008",
"name":"Bedroom",
"connected":true
}
"""
import logging
from requests import get, exceptions
from datetime import timedelta
from homeassistant.util import Throttle
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the aREST sensor. """
resource = config.get('resource', None)
try:
response = get(resource)
except exceptions.MissingSchema:
_LOGGER.error("Missing resource or schema in configuration. "
"Add http:// to your URL.")
return False
except exceptions.ConnectionError:
_LOGGER.error("No route to device. "
"Please check the IP address in the configuration file.")
return False
rest = ArestData(resource)
dev = []
for variable in config['monitored_variables']:
if 'unit' not in variable:
variable['unit'] = ' '
if variable['name'] not in response.json()['variables']:
_LOGGER.error('Variable: "%s" does not exist', variable['name'])
else:
dev.append(ArestSensor(rest,
response.json()['name'],
variable['name'],
variable['unit']))
add_devices(dev)
class ArestSensor(Entity):
""" Implements an aREST sensor. """
def __init__(self, rest, location, variable, unit_of_measurement):
self.rest = rest
self._name = '{} {}'.format(location.title(), variable.title())
self._variable = variable
self._state = 'n/a'
self._unit_of_measurement = unit_of_measurement
self.update()
@property
def name(self):
""" The name of the sensor. """
return self._name
@property
def unit_of_measurement(self):
""" Unit the value is expressed in. """
return self._unit_of_measurement
@property
def state(self):
""" Returns the state of the device. """
return self._state
def update(self):
""" Gets the latest data from aREST API and updates the state. """
self.rest.update()
values = self.rest.data
if 'error' in values:
self._state = values['error']
else:
self._state = values[self._variable]
# pylint: disable=too-few-public-methods
class ArestData(object):
""" Class for handling the data retrieval. """
def __init__(self, resource):
self.resource = resource
self.data = dict()
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from aREST device. """
try:
response = get(self.resource)
if 'error' in self.data:
del self.data['error']
self.data = response.json()['variables']
except exceptions.ConnectionError:
_LOGGER.error("No route to device. Is device offline?")
self.data['error'] = 'n/a'
+250
View File
@@ -0,0 +1,250 @@
"""
homeassistant.components.sensor.bitcoin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Bitcoin information service that uses blockchain.info and its online wallet.
Configuration:
You need to enable the API access for your online wallet to get the balance.
To do that log in and move to 'Account Setting', choose 'IP Restrictions', and
check 'Enable Api Access'. You will get an email message from blockchain.info
where you must authorize the API access.
To use the Bitcoin sensor you will need to add something like the following
to your configuration.yaml file.
sensor:
platform: bitcoin
wallet: 'YOUR WALLET_ID'
password: YOUR_ACCOUNT_PASSWORD
currency: YOUR CURRENCY
display_options:
- exchangerate
- trade_volume_btc
- miners_revenue_usd
- btc_mined
- trade_volume_usd
- difficulty
- minutes_between_blocks
- number_of_transactions
- hash_rate
- timestamp
- mined_blocks
- blocks_size
- total_fees_btc
- total_btc_sent
- estimated_btc_sent
- total_btc
- total_blocks
- next_retarget
- estimated_transaction_volume_usd
- miners_revenue_btc
- market_price_usd
Variables:
wallet
*Optional
This is your wallet identifier from https://blockchain.info to access the
online wallet.
password
*Optional
Password your your online wallet.
currency
*Optional
The currency to exchange to, eg. CHF, USD, EUR,etc. Default is USD.
display_options
*Optional
An array specifying the variables to display.
These are the variables for the display_options array. See the configuration
example above for a list of all available variables.
"""
import logging
from datetime import timedelta
from homeassistant.util import Throttle
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['blockchain==1.1.2']
_LOGGER = logging.getLogger(__name__)
OPTION_TYPES = {
'wallet': ['Wallet balance', 'BTC'],
'exchangerate': ['Exchange rate (1 BTC)', ''],
'trade_volume_btc': ['Trade volume', 'BTC'],
'miners_revenue_usd': ['Miners revenue', 'USD'],
'btc_mined': ['Mined', 'BTC'],
'trade_volume_usd': ['Trade volume', 'USD'],
'difficulty': ['Difficulty', ''],
'minutes_between_blocks': ['Time between Blocks', 'min'],
'number_of_transactions': ['No. of Transactions', ''],
'hash_rate': ['Hash rate', 'PH/s'],
'timestamp': ['Timestamp', ''],
'mined_blocks': ['Minded Blocks', ''],
'blocks_size': ['Block size', ''],
'total_fees_btc': ['Total fees', 'BTC'],
'total_btc_sent': ['Total sent', 'BTC'],
'estimated_btc_sent': ['Estimated sent', 'BTC'],
'total_btc': ['Total', 'BTC'],
'total_blocks': ['Total Blocks', ''],
'next_retarget': ['Next retarget', ''],
'estimated_transaction_volume_usd': ['Est. Transaction volume', 'USD'],
'miners_revenue_btc': ['Miners revenue', 'BTC'],
'market_price_usd': ['Market price', 'USD']
}
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the Bitcoin sensor. """
try:
from blockchain.wallet import Wallet
from blockchain import exchangerates, exceptions
except ImportError:
_LOGGER.exception(
"Unable to import blockchain. "
"Did you maybe not install the 'blockchain' package?")
return False
wallet_id = config.get('wallet', None)
password = config.get('password', None)
currency = config.get('currency', 'USD')
if currency not in exchangerates.get_ticker():
_LOGGER.error('Currency "%s" is not available. Using "USD".', currency)
currency = 'USD'
wallet = Wallet(wallet_id, password)
try:
wallet.get_balance()
except exceptions.APIException as error:
_LOGGER.error(error)
wallet = None
data = BitcoinData()
dev = []
if wallet is not None and password is not None:
dev.append(BitcoinSensor(data, 'wallet', currency, wallet))
for variable in config['display_options']:
if variable not in OPTION_TYPES:
_LOGGER.error('Option type: "%s" does not exist', variable)
else:
dev.append(BitcoinSensor(data, variable, currency))
add_devices(dev)
# pylint: disable=too-few-public-methods
class BitcoinSensor(Entity):
""" Implements a Bitcoin sensor. """
def __init__(self, data, option_type, currency, wallet=''):
self.data = data
self._name = OPTION_TYPES[option_type][0]
self._unit_of_measurement = OPTION_TYPES[option_type][1]
self._currency = currency
self._wallet = wallet
self.type = option_type
self._state = None
self.update()
@property
def name(self):
""" Returns the name of the device. """
return self._name
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
return self._unit_of_measurement
# pylint: disable=too-many-branches
def update(self):
""" Gets the latest data and updates the states. """
self.data.update()
stats = self.data.stats
ticker = self.data.ticker
# pylint: disable=no-member
if self.type == 'wallet' and self._wallet is not None:
self._state = '{0:.8f}'.format(self._wallet.get_balance() *
0.00000001)
elif self.type == 'exchangerate':
self._state = ticker[self._currency].p15min
self._unit_of_measurement = self._currency
elif self.type == 'trade_volume_btc':
self._state = '{0:.1f}'.format(stats.trade_volume_btc)
elif self.type == 'miners_revenue_usd':
self._state = '{0:.0f}'.format(stats.miners_revenue_usd)
elif self.type == 'btc_mined':
self._state = '{}'.format(stats.btc_mined * 0.00000001)
elif self.type == 'trade_volume_usd':
self._state = '{0:.1f}'.format(stats.trade_volume_usd)
elif self.type == 'difficulty':
self._state = '{0:.0f}'.format(stats.difficulty)
elif self.type == 'minutes_between_blocks':
self._state = '{0:.2f}'.format(stats.minutes_between_blocks)
elif self.type == 'number_of_transactions':
self._state = '{}'.format(stats.number_of_transactions)
elif self.type == 'hash_rate':
self._state = '{0:.1f}'.format(stats.hash_rate * 0.000001)
elif self.type == 'timestamp':
self._state = stats.timestamp
elif self.type == 'mined_blocks':
self._state = '{}'.format(stats.mined_blocks)
elif self.type == 'blocks_size':
self._state = '{0:.1f}'.format(stats.blocks_size)
elif self.type == 'total_fees_btc':
self._state = '{0:.2f}'.format(stats.total_fees_btc * 0.00000001)
elif self.type == 'total_btc_sent':
self._state = '{0:.2f}'.format(stats.total_btc_sent * 0.00000001)
elif self.type == 'estimated_btc_sent':
self._state = '{0:.2f}'.format(stats.estimated_btc_sent *
0.00000001)
elif self.type == 'total_btc':
self._state = '{0:.2f}'.format(stats.total_btc * 0.00000001)
elif self.type == 'total_blocks':
self._state = '{0:.2f}'.format(stats.total_blocks)
elif self.type == 'next_retarget':
self._state = '{0:.2f}'.format(stats.next_retarget)
elif self.type == 'estimated_transaction_volume_usd':
self._state = '{0:.2f}'.format(
stats.estimated_transaction_volume_usd)
elif self.type == 'miners_revenue_btc':
self._state = '{0:.1f}'.format(stats.miners_revenue_btc *
0.00000001)
elif self.type == 'market_price_usd':
self._state = '{0:.2f}'.format(stats.market_price_usd)
class BitcoinData(object):
""" Gets the latest data and updates the states. """
def __init__(self):
self.stats = None
self.ticker = None
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from blockchain.info. """
from blockchain import statistics, exchangerates
self.stats = statistics.get()
self.ticker = exchangerates.get_ticker()
+6 -1
View File
@@ -1,4 +1,8 @@
""" Support for Wink sensors. """
"""
homeassistant.components.sensor.demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Demo platform that has a couple of fake sensors.
"""
from homeassistant.helpers.entity import Entity
from homeassistant.const import TEMP_CELCIUS, ATTR_BATTERY_LEVEL
@@ -9,6 +13,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
add_devices([
DemoSensor('Outside Temperature', 15.6, TEMP_CELCIUS, 12),
DemoSensor('Outside Humidity', 54, '%', None),
DemoSensor('Alarm back', 'Armed', None, None),
])
+164
View File
@@ -0,0 +1,164 @@
"""
homeassistant.components.sensor.dht
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adafruit DHT temperature and humidity sensor.
You need a Python3 compatible version of the Adafruit_Python_DHT library
(e.g. https://github.com/mala-zaba/Adafruit_Python_DHT,
also see requirements.txt).
As this requires access to the GPIO, you will need to run home-assistant
as root.
Configuration:
To use the Adafruit DHT sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: dht
sensor: DHT22
pin: 23
monitored_conditions:
- temperature
- humidity
Variables:
sensor
*Required
The sensor type, DHT11, DHT22 or AM2302
pin
*Required
The pin the sensor is connected to, something like
'P8_11' for Beaglebone, '23' for Raspberry Pi
monitored_conditions
*Optional
Conditions to monitor. Available conditions are temperature and humidity.
"""
import logging
from datetime import timedelta
from homeassistant.util import Throttle
from homeassistant.const import TEMP_FAHRENHEIT
from homeassistant.helpers.entity import Entity
# update this requirement to upstream as soon as it supports python3
REQUIREMENTS = ['http://github.com/mala-zaba/Adafruit_Python_DHT/archive/'
'4101340de8d2457dd194bca1e8d11cbfc237e919.zip'
'#Adafruit_DHT==1.1.0']
_LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = {
'temperature': ['Temperature', ''],
'humidity': ['Humidity', '%']
}
# Return cached results if last scan was less then this time ago
# DHT11 is able to deliver data once per second, DHT22 once every two
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the DHT sensor. """
try:
import Adafruit_DHT
except ImportError:
_LOGGER.exception(
"Unable to import Adafruit_DHT. "
"Did you maybe not install the 'Adafruit_DHT' package?")
return False
SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit
unit = hass.config.temperature_unit
available_sensors = {
"DHT11": Adafruit_DHT.DHT11,
"DHT22": Adafruit_DHT.DHT22,
"AM2302": Adafruit_DHT.AM2302
}
sensor = available_sensors[config['sensor']]
pin = config['pin']
if not sensor or not pin:
_LOGGER.error(
"Config error "
"Please check your settings for DHT, sensor not supported.")
return None
data = DHTClient(Adafruit_DHT, sensor, pin)
dev = []
try:
for variable in config['monitored_conditions']:
if variable not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable)
else:
dev.append(DHTSensor(data, variable, unit))
except KeyError:
pass
add_devices(dev)
# pylint: disable=too-few-public-methods
class DHTSensor(Entity):
""" Implements an DHT sensor. """
def __init__(self, dht_client, sensor_type, temp_unit):
self.client_name = 'DHT sensor'
self._name = SENSOR_TYPES[sensor_type][0]
self.dht_client = dht_client
self.temp_unit = temp_unit
self.type = sensor_type
self._state = None
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self.update()
@property
def name(self):
return '{} {}'.format(self.client_name, self._name)
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._unit_of_measurement
def update(self):
""" Gets the latest data from the DHT and updates the states. """
self.dht_client.update()
data = self.dht_client.data
if self.type == 'temperature':
self._state = round(data['temperature'], 1)
if self.temp_unit == TEMP_FAHRENHEIT:
self._state = round(data['temperature'] * 1.8 + 32, 1)
elif self.type == 'humidity':
self._state = round(data['humidity'], 1)
class DHTClient(object):
""" Gets the latest data from the DHT sensor. """
def __init__(self, adafruit_dht, sensor, pin):
self.adafruit_dht = adafruit_dht
self.sensor = sensor
self.pin = pin
self.data = dict()
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data the DHT sensor. """
humidity, temperature = self.adafruit_dht.read_retry(self.sensor,
self.pin)
if temperature:
self.data['temperature'] = temperature
if humidity:
self.data['humidity'] = humidity
+137
View File
@@ -0,0 +1,137 @@
"""
homeassistant.components.sensor.efergy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Monitors home energy use as measured by an efergy engage hub using its
(unofficial, undocumented) API.
Configuration:
To use the efergy sensor you will need to add something like the following
to your configuration.yaml file.
sensor:
platform: efergy
app_token: APP_TOKEN
utc_offset: UTC_OFFSET
monitored_variables:
- type: instant_readings
- type: budget
- type: cost
period: day
currency: $
Variables:
api_key
*Required
To get a new App Token, log in to your efergy account, go
to the Settings page, click on App tokens, and click "Add token".
utc_offset
*Required for some variables
Some variables (currently only the daily_cost) require that the
negative number of minutes your timezone is ahead/behind UTC time.
monitored_variables
*Required
An array specifying the variables to monitor.
period
*Optional
Some variables take a period argument. Valid options are "day", "week",
"month", and "year".
currency
*Optional
This is used to display the cost/period as the unit when monitoring the
cost. It should correspond to the actual currency used in your dashboard.
"""
import logging
from requests import get
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
_RESOURCE = 'https://engage.efergy.com/mobile_proxy/'
SENSOR_TYPES = {
'instant_readings': ['Energy Usage', 'kW'],
'budget': ['Energy Budget', ''],
'cost': ['Energy Cost', ''],
}
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Efergy sensor. """
app_token = config.get("app_token")
if not app_token:
_LOGGER.error(
"Configuration Error"
"Please make sure you have configured your app token")
return None
utc_offset = str(config.get("utc_offset"))
dev = []
for variable in config['monitored_variables']:
if 'period' not in variable:
variable['period'] = ''
if 'currency' not in variable:
variable['currency'] = ''
if variable['type'] not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable)
else:
dev.append(EfergySensor(variable['type'], app_token, utc_offset,
variable['period'], variable['currency']))
add_devices(dev)
# pylint: disable=too-many-instance-attributes
class EfergySensor(Entity):
""" Implements an Efergy sensor. """
# pylint: disable=too-many-arguments
def __init__(self, sensor_type, app_token, utc_offset, period, currency):
self._name = SENSOR_TYPES[sensor_type][0]
self.type = sensor_type
self.app_token = app_token
self.utc_offset = utc_offset
self._state = None
self.period = period
self.currency = currency
if self.type == 'cost':
self._unit_of_measurement = self.currency + '/' + self.period
else:
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
@property
def name(self):
""" Returns the name. """
return self._name
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._unit_of_measurement
def update(self):
""" Gets the Efergy monitor data from the web service. """
if self.type == 'instant_readings':
url_string = _RESOURCE + 'getInstant?token=' + self.app_token
response = get(url_string)
self._state = response.json()['reading'] / 1000
elif self.type == 'budget':
url_string = _RESOURCE + 'getBudget?token=' + self.app_token
response = get(url_string)
self._state = response.json()['status']
elif self.type == 'cost':
url_string = _RESOURCE + 'getCost?token=' + self.app_token \
+ '&offset=' + self.utc_offset + '&period=' \
+ self.period
response = get(url_string)
self._state = response.json()['sum']
else:
self._state = 'Unknown'
+220
View File
@@ -0,0 +1,220 @@
"""
homeassistant.components.sensor.forecast
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Forecast.io weather service.
Configuration:
To use the Forecast sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: forecast
api_key: YOUR_APP_KEY
monitored_conditions:
- summary
- precip_type
- precip_intensity
- temperature
- dew_point
- wind_speed
- wind_bearing
- cloud_cover
- humidity
- pressure
- visibility
- ozone
Variables:
api_key
*Required
To retrieve this value log into your account at http://forecast.io/. You can
make 1000 requests per day. This means that you could create every 1.4 minute
one.
monitored_conditions
*Required
An array specifying the conditions to monitor.
monitored_conditions
*Required
Conditions to monitor. See the configuration example above for a
list of all available conditions to monitor.
Details for the API : https://developer.forecast.io/docs/v2
"""
import logging
from datetime import timedelta
REQUIREMENTS = ['python-forecastio==1.3.3']
try:
import forecastio
except ImportError:
forecastio = None
from homeassistant.util import Throttle
from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS, TEMP_FAHRENHEIT)
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = {
'summary': ['Summary', ''],
'precip_type': ['Precip', ''],
'precip_intensity': ['Precip intensity', 'mm'],
'temperature': ['Temperature', ''],
'dew_point': ['Dew point', '°C'],
'wind_speed': ['Wind Speed', 'm/s'],
'wind_bearing': ['Wind Bearing', '°'],
'cloud_cover': ['Cloud coverage', '%'],
'humidity': ['Humidity', '%'],
'pressure': ['Pressure', 'mBar'],
'visibility': ['Visibility', 'km'],
'ozone': ['Ozone', 'DU'],
}
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the Forecast.io sensor. """
global forecastio # pylint: disable=invalid-name
if forecastio is None:
import forecastio as forecastio_
forecastio = forecastio_
if None in (hass.config.latitude, hass.config.longitude):
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
return False
SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit
unit = hass.config.temperature_unit
try:
forecast = forecastio.load_forecast(config.get(CONF_API_KEY, None),
hass.config.latitude,
hass.config.longitude)
forecast.currently()
except ValueError:
_LOGGER.error(
"Connection error "
"Please check your settings for Forecast.io.")
return False
data = ForeCastData(config.get(CONF_API_KEY, None),
hass.config.latitude,
hass.config.longitude)
dev = []
for variable in config['monitored_conditions']:
if variable not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable)
else:
dev.append(ForeCastSensor(data, variable, unit))
add_devices(dev)
# pylint: disable=too-few-public-methods
class ForeCastSensor(Entity):
""" Implements an Forecast.io sensor. """
def __init__(self, weather_data, sensor_type, unit):
self.client_name = 'Weather'
self._name = SENSOR_TYPES[sensor_type][0]
self.forecast_client = weather_data
self._unit = unit
self.type = sensor_type
self._state = None
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self.update()
@property
def name(self):
return '{} {}'.format(self.client_name, self._name)
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._unit_of_measurement
# pylint: disable=too-many-branches
def update(self):
""" Gets the latest data from Forecast.io and updates the states. """
self.forecast_client.update()
data = self.forecast_client.data
try:
if self.type == 'summary':
self._state = data.summary
elif self.type == 'precip_intensity':
if data.precipIntensity == 0:
self._state = 'None'
self._unit_of_measurement = ''
else:
self._state = data.precipIntensity
elif self.type == 'precip_type':
if data.precipType is None:
self._state = 'None'
self._unit_of_measurement = ''
else:
self._state = data.precipType
elif self.type == 'dew_point':
if self._unit == TEMP_CELCIUS:
self._state = round(data.dewPoint, 1)
elif self._unit == TEMP_FAHRENHEIT:
self._state = round(data.dewPoint * 1.8 + 32.0, 1)
else:
self._state = round(data.dewPoint, 1)
elif self.type == 'temperature':
if self._unit == TEMP_CELCIUS:
self._state = round(data.temperature, 1)
elif self._unit == TEMP_FAHRENHEIT:
self._state = round(data.temperature * 1.8 + 32.0, 1)
else:
self._state = round(data.temperature, 1)
elif self.type == 'wind_speed':
self._state = data.windSpeed
elif self.type == 'wind_bearing':
self._state = data.windBearing
elif self.type == 'cloud_cover':
self._state = round(data.cloudCover * 100, 1)
elif self.type == 'humidity':
self._state = round(data.humidity * 100, 1)
elif self.type == 'pressure':
self._state = round(data.pressure, 1)
elif self.type == 'visibility':
self._state = data.visibility
elif self.type == 'ozone':
self._state = round(data.ozone, 1)
except forecastio.utils.PropertyUnavailable:
pass
class ForeCastData(object):
""" Gets the latest data from Forecast.io. """
def __init__(self, api_key, latitude, longitude):
self._api_key = api_key
self.latitude = latitude
self.longitude = longitude
self.data = None
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from Forecast.io. """
forecast = forecastio.load_forecast(self._api_key,
self.latitude,
self.longitude,
units='si')
self.data = forecast.currently()
+92
View File
@@ -0,0 +1,92 @@
"""
homeassistant.components.sensor.isy994
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for ISY994 sensors.
"""
import logging
from homeassistant.components.isy994 import (ISY, ISYDeviceABC, SENSOR_STRING,
HIDDEN_STRING)
from homeassistant.const import (STATE_OPEN, STATE_CLOSED, STATE_HOME,
STATE_NOT_HOME, STATE_ON, STATE_OFF)
DEFAULT_HIDDEN_WEATHER = ['Temperature_High', 'Temperature_Low', 'Feels_Like',
'Temperature_Average', 'Pressure', 'Dew_Point',
'Gust_Speed', 'Evapotranspiration',
'Irrigation_Requirement', 'Water_Deficit_Yesterday',
'Elevation', 'Average_Temperature_Tomorrow',
'High_Temperature_Tomorrow',
'Low_Temperature_Tomorrow', 'Humidity_Tomorrow',
'Wind_Speed_Tomorrow', 'Gust_Speed_Tomorrow',
'Rain_Tomorrow', 'Snow_Tomorrow',
'Forecast_Average_Temperature',
'Forecast_High_Temperature',
'Forecast_Low_Temperature', 'Forecast_Humidity',
'Forecast_Rain', 'Forecast_Snow']
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the ISY994 platform. """
# pylint: disable=protected-access
logger = logging.getLogger(__name__)
devs = []
# verify connection
if ISY is None or not ISY.connected:
logger.error('A connection has not been made to the ISY controller.')
return False
# import weather
if ISY.climate is not None:
for prop in ISY.climate._id2name:
if prop is not None:
prefix = HIDDEN_STRING \
if prop in DEFAULT_HIDDEN_WEATHER else ''
node = WeatherPseudoNode('ISY.weather.' + prop, prefix + prop,
getattr(ISY.climate, prop),
getattr(ISY.climate, prop + '_units'))
devs.append(ISYSensorDevice(node))
# import sensor nodes
for (path, node) in ISY.nodes:
if SENSOR_STRING in node.name:
if HIDDEN_STRING in path:
node.name += HIDDEN_STRING
devs.append(ISYSensorDevice(node, [STATE_ON, STATE_OFF]))
# import sensor programs
for (folder_name, states) in (
('HA.locations', [STATE_HOME, STATE_NOT_HOME]),
('HA.sensors', [STATE_OPEN, STATE_CLOSED]),
('HA.states', [STATE_ON, STATE_OFF])):
try:
folder = ISY.programs['My Programs'][folder_name]
except KeyError:
# folder does not exist
pass
else:
for _, _, node_id in folder.children:
node = folder[node_id].leaf
devs.append(ISYSensorDevice(node, states))
add_devices(devs)
class WeatherPseudoNode(object):
""" This class allows weather variable to act as regular nodes. """
# pylint: disable=too-few-public-methods
def __init__(self, device_id, name, status, units=None):
self._id = device_id
self.name = name
self.status = status
self.units = units
class ISYSensorDevice(ISYDeviceABC):
""" Represents a ISY sensor. """
_domain = 'sensor'
def __init__(self, node, states=None):
super().__init__(node)
self._states = states or []
+167
View File
@@ -0,0 +1,167 @@
"""
homeassistant.components.modbus
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for Modbus sensors.
Configuration:
To use the Modbus sensors you will need to add something like the following to
your configuration.yaml file.
sensor:
platform: modbus
slave: 1
registers:
16:
name: My integer sensor
unit: C
24:
bits:
0:
name: My boolean sensor
2:
name: My other boolean sensor
coils:
0:
name: My coil switch
Variables:
slave
*Required
Slave number (ignored and can be omitted if not serial Modbus).
unit
*Required
Unit to attach to value (optional, ignored for boolean sensors).
registers
*Required
Contains a list of relevant registers to read from. It can contain a
"bits" section, listing relevant bits.
coils
*Optional
Contains a list of relevant coils to read from.
Note:
- Each named register will create an integer sensor.
- Each named bit will create a boolean sensor.
"""
import logging
import homeassistant.components.modbus as modbus
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
TEMP_CELCIUS, TEMP_FAHRENHEIT,
STATE_ON, STATE_OFF)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['modbus']
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Read config and create Modbus devices. """
sensors = []
slave = config.get("slave", None)
if modbus.TYPE == "serial" and not slave:
_LOGGER.error("No slave number provided for serial Modbus")
return False
registers = config.get("registers")
if registers:
for regnum, register in registers.items():
if register.get("name"):
sensors.append(ModbusSensor(register.get("name"),
slave,
regnum,
None,
register.get("unit")))
if register.get("bits"):
bits = register.get("bits")
for bitnum, bit in bits.items():
if bit.get("name"):
sensors.append(ModbusSensor(bit.get("name"),
slave,
regnum,
bitnum))
coils = config.get("coils")
if coils:
for coilnum, coil in coils.items():
sensors.append(ModbusSensor(coil.get("name"),
slave,
coilnum,
coil=True))
add_devices(sensors)
class ModbusSensor(Entity):
# pylint: disable=too-many-arguments
""" Represents a Modbus Sensor. """
def __init__(self, name, slave, register, bit=None, unit=None, coil=False):
self._name = name
self.slave = int(slave) if slave else 1
self.register = int(register)
self.bit = int(bit) if bit else None
self._value = None
self._unit = unit
self._coil = coil
def __str__(self):
return "%s: %s" % (self.name, self.state)
@property
def should_poll(self):
"""
We should poll, because slaves are not allowed to
initiate communication on Modbus networks.
"""
return True
@property
def unique_id(self):
""" Returns a unique id. """
return "MODBUS-SENSOR-{}-{}-{}".format(self.slave,
self.register,
self.bit)
@property
def state(self):
""" Returns the state of the sensor. """
if self.bit:
return STATE_ON if self._value else STATE_OFF
else:
return self._value
@property
def name(self):
""" Get the name of the sensor. """
return self._name
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
if self._unit == "C":
return TEMP_CELCIUS
elif self._unit == "F":
return TEMP_FAHRENHEIT
else:
return self._unit
def update(self):
""" Update the state of the sensor. """
if self._coil:
result = modbus.NETWORK.read_coils(self.register, 1)
self._value = result.bits[0]
else:
result = modbus.NETWORK.read_holding_registers(
unit=self.slave, address=self.register,
count=1)
val = 0
for i, res in enumerate(result.registers):
val += res * (2**(i*16))
if self.bit:
self._value = val & (0x0001 << self.bit)
else:
self._value = val
+103
View File
@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
"""
homeassistant.components.sensor.mqtt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to configure a MQTT sensor.
This generic sensor implementation uses the MQTT message payload
as the sensor value. If messages in this state_topic are published
with RETAIN flag, the sensor will receive an instant update with
last known value. Otherwise, the initial state will be undefined.
sensor:
platform: mqtt
name: "MQTT Sensor"
state_topic: "home/bedroom/temperature"
qos: 0
unit_of_measurement: "ºC"
Variables:
name
*Optional
The name of the sensor. Default is 'MQTT Sensor'.
state_topic
*Required
The MQTT topic subscribed to receive sensor values.
qos
*Optional
The maximum QoS level of the state topic. Default is 0.
unit_of_measurement
*Optional
Defines the units of measurement of the sensor, if any.
"""
import logging
from homeassistant.helpers.entity import Entity
import homeassistant.components.mqtt as mqtt
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "MQTT Sensor"
DEFAULT_QOS = 0
DEPENDENCIES = ['mqtt']
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Add MQTT Sensor """
if config.get('state_topic') is None:
_LOGGER.error("Missing required variable: state_topic")
return False
add_devices_callback([MqttSensor(
hass,
config.get('name', DEFAULT_NAME),
config.get('state_topic'),
config.get('qos', DEFAULT_QOS),
config.get('unit_of_measurement'))])
# pylint: disable=too-many-arguments, too-many-instance-attributes
class MqttSensor(Entity):
""" Represents a sensor that can be updated using MQTT """
def __init__(self, hass, name, state_topic, qos, unit_of_measurement):
self._state = "-"
self._hass = hass
self._name = name
self._state_topic = state_topic
self._qos = qos
self._unit_of_measurement = unit_of_measurement
def message_received(topic, payload, qos):
""" A new MQTT message has been received. """
self._state = payload
self.update_ha_state()
mqtt.subscribe(hass, self._state_topic, message_received, self._qos)
@property
def should_poll(self):
""" No polling needed """
return False
@property
def name(self):
""" The name of the sensor """
return self._name
@property
def unit_of_measurement(self):
""" Unit this state is expressed in. """
return self._unit_of_measurement
@property
def state(self):
""" Returns the state of the entity. """
return self._state
@@ -0,0 +1,161 @@
"""
homeassistant.components.sensor.mysensors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for MySensors sensors.
Configuration:
To use the MySensors sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: mysensors
port: '/dev/ttyACM0'
Variables:
port
*Required
Port of your connection to your MySensors device.
"""
import logging
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
ATTR_BATTERY_LEVEL, EVENT_HOMEASSISTANT_STOP,
TEMP_CELCIUS, TEMP_FAHRENHEIT,
STATE_ON, STATE_OFF)
CONF_PORT = "port"
CONF_DEBUG = "debug"
CONF_PERSISTENCE = "persistence"
ATTR_NODE_ID = "node_id"
ATTR_CHILD_ID = "child_id"
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['https://github.com/theolind/pymysensors/archive/'
'35b87d880147a34107da0d40cb815d75e6cb4af7.zip'
'#pymysensors==0.2']
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Setup the mysensors platform. """
import mysensors.mysensors as mysensors
import mysensors.const_14 as const
devices = {} # keep track of devices added to HA
# Just assume celcius means that the user wants metric for now.
# It may make more sense to make this a global config option in the future.
is_metric = (hass.config.temperature_unit == TEMP_CELCIUS)
def sensor_update(update_type, nid):
""" Callback for sensor updates from the MySensors gateway. """
_LOGGER.info("sensor_update %s: node %s", update_type, nid)
sensor = gateway.sensors[nid]
if sensor.sketch_name is None:
return
if nid not in devices:
devices[nid] = {}
node = devices[nid]
new_devices = []
for child_id, child in sensor.children.items():
if child_id not in node:
node[child_id] = {}
for value_type, value in child.values.items():
if value_type not in node[child_id]:
name = '{} {}.{}'.format(sensor.sketch_name, nid, child.id)
node[child_id][value_type] = \
MySensorsNodeValue(
nid, child_id, name, value_type, is_metric, const)
new_devices.append(node[child_id][value_type])
else:
node[child_id][value_type].update_sensor(
value, sensor.battery_level)
if new_devices:
_LOGGER.info("adding new devices: %s", new_devices)
add_devices(new_devices)
port = config.get(CONF_PORT)
if port is None:
_LOGGER.error("Missing required key 'port'")
return False
persistence = config.get(CONF_PERSISTENCE, True)
gateway = mysensors.SerialGateway(port, sensor_update,
persistence=persistence)
gateway.metric = is_metric
gateway.debug = config.get(CONF_DEBUG, False)
gateway.start()
if persistence:
for nid in gateway.sensors:
sensor_update('sensor_update', nid)
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP,
lambda event: gateway.stop())
class MySensorsNodeValue(Entity):
""" Represents the value of a MySensors child node. """
# pylint: disable=too-many-arguments, too-many-instance-attributes
def __init__(self, node_id, child_id, name, value_type, metric, const):
self._name = name
self.node_id = node_id
self.child_id = child_id
self.battery_level = 0
self.value_type = value_type
self.metric = metric
self._value = ''
self.const = const
@property
def should_poll(self):
""" MySensor gateway pushes its state to HA. """
return False
@property
def name(self):
""" The name of this sensor. """
return self._name
@property
def state(self):
""" Returns the state of the device. """
return self._value
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity. """
if self.value_type == self.const.SetReq.V_TEMP:
return TEMP_CELCIUS if self.metric else TEMP_FAHRENHEIT
elif self.value_type == self.const.SetReq.V_HUM or \
self.value_type == self.const.SetReq.V_DIMMER or \
self.value_type == self.const.SetReq.V_LIGHT_LEVEL:
return '%'
return None
@property
def state_attributes(self):
""" Returns the state attributes. """
return {
ATTR_NODE_ID: self.node_id,
ATTR_CHILD_ID: self.child_id,
ATTR_BATTERY_LEVEL: self.battery_level,
}
def update_sensor(self, value, battery_level):
""" Update a sensor with the latest value from the controller. """
_LOGGER.info("%s value = %s", self._name, value)
if self.value_type == self.const.SetReq.V_TRIPPED or \
self.value_type == self.const.SetReq.V_ARMED:
self._value = STATE_ON if int(value) == 1 else STATE_OFF
else:
self._value = value
self.battery_level = battery_level
self.update_ha_state()
@@ -0,0 +1,208 @@
"""
homeassistant.components.sensor.openweathermap
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OpenWeatherMap (OWM) service.
Configuration:
To use the OpenWeatherMap sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: openweathermap
api_key: YOUR_APP_KEY
forecast: 0 or 1
monitored_conditions:
- weather
- temperature
- wind_speed
- humidity
- pressure
- clouds
- rain
- snow
Variables:
api_key
*Required
To retrieve this value log into your account at http://openweathermap.org/
forecast
*Optional
Enables the forecast. The default is to display the current conditions.
monitored_conditions
*Required
Conditions to monitor. See the configuration example above for a
list of all available conditions to monitor.
Details for the API : http://bugs.openweathermap.org/projects/api/wiki
Only metric measurements are supported at the moment.
"""
import logging
from datetime import timedelta
from homeassistant.util import Throttle
from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS, TEMP_FAHRENHEIT)
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['pyowm==2.2.1']
_LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = {
'weather': ['Condition', ''],
'temperature': ['Temperature', ''],
'wind_speed': ['Wind speed', 'm/s'],
'humidity': ['Humidity', '%'],
'pressure': ['Pressure', 'hPa'],
'clouds': ['Cloud coverage', '%'],
'rain': ['Rain', 'mm'],
'snow': ['Snow', 'mm']
}
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the OpenWeatherMap sensor. """
if None in (hass.config.latitude, hass.config.longitude):
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
return False
try:
from pyowm import OWM
except ImportError:
_LOGGER.exception(
"Unable to import pyowm. "
"Did you maybe not install the 'PyOWM' package?")
return False
SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit
unit = hass.config.temperature_unit
forecast = config.get('forecast', 0)
owm = OWM(config.get(CONF_API_KEY, None))
if not owm:
_LOGGER.error(
"Connection error "
"Please check your settings for OpenWeatherMap.")
return None
data = WeatherData(owm, forecast, hass.config.latitude,
hass.config.longitude)
dev = []
try:
for variable in config['monitored_conditions']:
if variable not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable)
else:
dev.append(OpenWeatherMapSensor(data, variable, unit))
except KeyError:
pass
if forecast == 1:
SENSOR_TYPES['forecast'] = ['Forecast', '']
dev.append(OpenWeatherMapSensor(data, 'forecast', unit))
add_devices(dev)
# pylint: disable=too-few-public-methods
class OpenWeatherMapSensor(Entity):
""" Implements an OpenWeatherMap sensor. """
def __init__(self, weather_data, sensor_type, temp_unit):
self.client_name = 'Weather'
self._name = SENSOR_TYPES[sensor_type][0]
self.owa_client = weather_data
self.temp_unit = temp_unit
self.type = sensor_type
self._state = None
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self.update()
@property
def name(self):
return '{} {}'.format(self.client_name, self._name)
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._unit_of_measurement
# pylint: disable=too-many-branches
def update(self):
""" Gets the latest data from OWM and updates the states. """
self.owa_client.update()
data = self.owa_client.data
fc_data = self.owa_client.fc_data
if self.type == 'weather':
self._state = data.get_detailed_status()
elif self.type == 'temperature':
if self.temp_unit == TEMP_CELCIUS:
self._state = round(data.get_temperature('celsius')['temp'],
1)
elif self.temp_unit == TEMP_FAHRENHEIT:
self._state = round(data.get_temperature('fahrenheit')['temp'],
1)
else:
self._state = round(data.get_temperature()['temp'], 1)
elif self.type == 'wind_speed':
self._state = data.get_wind()['speed']
elif self.type == 'humidity':
self._state = data.get_humidity()
elif self.type == 'pressure':
self._state = round(data.get_pressure()['press'], 0)
elif self.type == 'clouds':
self._state = data.get_clouds()
elif self.type == 'rain':
if data.get_rain():
self._state = round(data.get_rain()['3h'], 0)
self._unit_of_measurement = 'mm'
else:
self._state = 'not raining'
self._unit_of_measurement = ''
elif self.type == 'snow':
if data.get_snow():
self._state = round(data.get_snow(), 0)
self._unit_of_measurement = 'mm'
else:
self._state = 'not snowing'
self._unit_of_measurement = ''
elif self.type == 'forecast':
self._state = fc_data.get_weathers()[0].get_status()
class WeatherData(object):
""" Gets the latest data from OpenWeatherMap. """
def __init__(self, owm, forecast, latitude, longitude):
self.owm = owm
self.forecast = forecast
self.latitude = latitude
self.longitude = longitude
self.data = None
self.fc_data = None
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from OpenWeatherMap. """
obs = self.owm.weather_at_coords(self.latitude, self.longitude)
self.data = obs.get_weather()
if self.forecast == 1:
obs = self.owm.three_hours_forecast_at_coords(self.latitude,
self.longitude)
self.fc_data = obs.get_forecast()
+105
View File
@@ -0,0 +1,105 @@
"""
homeassistant.components.sensor.rfxtrx
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Shows sensor values from RFXtrx sensors.
Configuration:
To use the rfxtrx sensors you will need to add something like the following to
your configuration.yaml file.
sensor:
platform: rfxtrx
device: PATH_TO_DEVICE
Variables:
device
*Required
Path to your RFXtrx device.
E.g. /dev/serial/by-id/usb-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0
"""
import logging
from collections import OrderedDict
from homeassistant.const import (TEMP_CELCIUS)
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['https://github.com/Danielhiversen/pyRFXtrx/archive/' +
'ec7a1aaddf8270db6e5da1c13d58c1547effd7cf.zip#RFXtrx==0.15']
DATA_TYPES = OrderedDict([
('Temperature', TEMP_CELCIUS),
('Humidity', '%'),
('Barometer', ''),
('Wind direction', ''),
('Rain rate', '')])
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Setup the RFXtrx platform. """
logger = logging.getLogger(__name__)
sensors = {} # keep track of sensors added to HA
def sensor_update(event):
""" Callback for sensor updates from the RFXtrx gateway. """
if event.device.id_string in sensors:
sensors[event.device.id_string].event = event
else:
logger.info("adding new sensor: %s", event.device.type_string)
new_sensor = RfxtrxSensor(event)
sensors[event.device.id_string] = new_sensor
add_devices([new_sensor])
try:
import RFXtrx as rfxtrx
except ImportError:
logger.exception(
"Failed to import rfxtrx")
return False
device = config.get("device", "")
rfxtrx.Core(device, sensor_update)
class RfxtrxSensor(Entity):
""" Represents a RFXtrx sensor. """
def __init__(self, event):
self.event = event
self._unit_of_measurement = None
self._data_type = None
for data_type in DATA_TYPES:
if data_type in self.event.values:
self._unit_of_measurement = DATA_TYPES[data_type]
self._data_type = data_type
break
id_string = int(event.device.id_string.replace(":", ""), 16)
self._name = "{} {} ({})".format(self._data_type,
self.event.device.type_string,
id_string)
def __str__(self):
return self._name
@property
def state(self):
if self._data_type:
return self.event.values[self._data_type]
return None
@property
def name(self):
""" Get the mame of the sensor. """
return self._name
@property
def state_attributes(self):
return self.event.values
@property
def unit_of_measurement(self):
""" Unit this state is expressed in. """
return self._unit_of_measurement
+132
View File
@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
"""
homeassistant.components.sensor.rpi_gpio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to configure a binary state sensor using RPi GPIO.
Note: To use RPi GPIO, Home Assistant must be run as root.
sensor:
platform: rpi_gpio
pull_mode: "UP"
value_high: "Active"
value_low: "Inactive"
ports:
11: PIR Office
12: PIR Bedroom
Variables:
pull_mode
*Optional
The internal pull to use (UP or DOWN). Default is UP.
value_high
*Optional
The value of the sensor when the port is HIGH. Default is "HIGH".
value_low
*Optional
The value of the sensor when the port is LOW. Default is "LOW".
bouncetime
*Optional
The time in milliseconds for port debouncing. Default is 50ms.
ports
*Required
An array specifying the GPIO ports to use and the name to use in the frontend.
"""
import logging
from homeassistant.helpers.entity import Entity
try:
import RPi.GPIO as GPIO
except ImportError:
GPIO = None
from homeassistant.const import (DEVICE_DEFAULT_NAME,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP)
DEFAULT_PULL_MODE = "UP"
DEFAULT_VALUE_HIGH = "HIGH"
DEFAULT_VALUE_LOW = "LOW"
DEFAULT_BOUNCETIME = 50
REQUIREMENTS = ['RPi.GPIO==0.5.11']
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Raspberry PI GPIO ports. """
if GPIO is None:
_LOGGER.error('RPi.GPIO not available. rpi_gpio ports ignored.')
return
# pylint: disable=no-member
GPIO.setmode(GPIO.BCM)
sensors = []
pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE)
value_high = config.get('value_high', DEFAULT_VALUE_HIGH)
value_low = config.get('value_low', DEFAULT_VALUE_LOW)
bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME)
ports = config.get('ports')
for port_num, port_name in ports.items():
sensors.append(RPiGPIOSensor(
port_name, port_num, pull_mode,
value_high, value_low, bouncetime))
add_devices(sensors)
def cleanup_gpio(event):
""" Stuff to do before stop home assistant. """
# pylint: disable=no-member
GPIO.cleanup()
def prepare_gpio(event):
""" Stuff to do when home assistant starts. """
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gpio)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, prepare_gpio)
# pylint: disable=too-many-arguments, too-many-instance-attributes
class RPiGPIOSensor(Entity):
""" Sets up the Raspberry PI GPIO ports. """
def __init__(self, port_name, port_num, pull_mode,
value_high, value_low, bouncetime):
# pylint: disable=no-member
self._name = port_name or DEVICE_DEFAULT_NAME
self._port = port_num
self._pull = GPIO.PUD_DOWN if pull_mode == "DOWN" else GPIO.PUD_UP
self._vhigh = value_high
self._vlow = value_low
self._bouncetime = bouncetime
GPIO.setup(self._port, GPIO.IN, pull_up_down=self._pull)
self._state = self._vhigh if GPIO.input(self._port) else self._vlow
def edge_callback(channel):
""" port changed state """
# pylint: disable=no-member
self._state = self._vhigh if GPIO.input(channel) else self._vlow
self.update_ha_state()
GPIO.add_event_detect(
self._port,
GPIO.BOTH,
callback=edge_callback,
bouncetime=self._bouncetime)
@property
def should_poll(self):
""" No polling needed. """
return False
@property
def name(self):
""" The name of the sensor. """
return self._name
@property
def state(self):
""" Returns the state of the entity. """
return self._state
+15 -17
View File
@@ -1,13 +1,12 @@
"""
homeassistant.components.sensor.sabnzbd
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Monitors SABnzbd NZB client API
Configuration:
To use the SABnzbd sensor you will need to add something like the following to
your config/configuration.yaml
your configuration.yaml file.
sensor:
platform: sabnzbd
@@ -22,18 +21,16 @@ sensor:
- type: 'disk_size'
- type: 'disk_free'
VARIABLES:
Variables:
base_url
*Required
This is the base URL of your SABnzbd instance including the port number if not
running on 80
Example: http://192.168.1.32:8124/
running on 80, e.g. http://192.168.1.32:8124/
name
*Optional
The name to use when displaying this SABnzbd instance
The name to use when displaying this SABnzbd instance.
monitored_variables
*Required
@@ -44,21 +41,19 @@ These are the variables for the monitored_variables array:
type
*Required
The variable you wish to monitor, see the configuration example above for a
list of all available variables
list of all available variables.
"""
from homeassistant.util import Throttle
from datetime import timedelta
from homeassistant.helpers.entity import Entity
# pylint: disable=no-name-in-module, import-error
from homeassistant.external.nzbclients.sabnzbd import SabnzbdApi
from homeassistant.external.nzbclients.sabnzbd import SabnzbdApiException
import logging
REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/'
'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip'
'#python-sabnzbd==0.1']
SENSOR_TYPES = {
'current_status': ['Status', ''],
'speed': ['Speed', 'MB/s'],
@@ -75,7 +70,9 @@ _THROTTLED_REFRESH = None
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the sensors """
""" Sets up the SABnzbd sensors. """
from pysabnzbd import SabnzbdApi, SabnzbdApiException
api_key = config.get("api_key")
base_url = config.get("base_url")
name = config.get("name", "SABnzbd")
@@ -109,7 +106,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class SabnzbdSensor(Entity):
""" A Sabnzbd sensor """
""" Represents an SABnzbd sensor. """
def __init__(self, sensor_type, sabnzb_client, client_name):
self._name = SENSOR_TYPES[sensor_type][0]
@@ -136,6 +133,7 @@ class SabnzbdSensor(Entity):
def refresh_sabnzbd_data(self):
""" Calls the throttled SABnzbd refresh method. """
if _THROTTLED_REFRESH is not None:
from pysabnzbd import SabnzbdApiException
try:
_THROTTLED_REFRESH()
except SabnzbdApiException:
@@ -0,0 +1,131 @@
"""
homeassistant.components.sensor.swiss_public_transport
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Swiss public transport sensor will give you the next two departure times
from a given location to another one. This sensor is limited to Switzerland.
Configuration:
To use the Swiss public transport sensor you will need to add something like
the following to your configuration.yaml file.
sensor:
platform: swiss_public_transport
from: STATION_ID
to: STATION_ID
Variables:
from
*Required
Start station/stop of your trip. To search for the ID of the station, use the
an URL like this: http://transport.opendata.ch/v1/locations?query=Wankdorf
to query for the station. If the score is 100 ("score":"100" in the response),
it is a perfect match.
to
*Required
Destination station/stop of the trip. Same procedure as for the start station.
Details for the API : http://transport.opendata.ch
"""
import logging
from datetime import timedelta
from requests import get
from homeassistant.util import Throttle
import homeassistant.util.dt as dt_util
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
_RESOURCE = 'http://transport.opendata.ch/v1/'
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the Swiss public transport sensor. """
# journal contains [0] Station ID start, [1] Station ID destination
# [2] Station name start, and [3] Station name destination
journey = [config.get('from'), config.get('to')]
try:
for location in [config.get('from', None), config.get('to', None)]:
# transport.opendata.ch doesn't play nice with requests.Session
result = get(_RESOURCE + 'locations?query=%s' % location)
journey.append(result.json()['stations'][0]['name'])
except KeyError:
_LOGGER.exception(
"Unable to determine stations. "
"Check your settings and/or the availability of opendata.ch")
return None
dev = []
data = PublicTransportData(journey)
dev.append(SwissPublicTransportSensor(data, journey))
add_devices(dev)
# pylint: disable=too-few-public-methods
class SwissPublicTransportSensor(Entity):
""" Implements an Swiss public transport sensor. """
def __init__(self, data, journey):
self.data = data
self._name = '{}-{}'.format(journey[2], journey[3])
self.update()
@property
def name(self):
""" Returns the name. """
return self._name
@property
def state(self):
""" Returns the state of the device. """
return self._state
# pylint: disable=too-many-branches
def update(self):
""" Gets the latest data from opendata.ch and updates the states. """
times = self.data.update()
try:
self._state = ', '.join(times)
except TypeError:
pass
# pylint: disable=too-few-public-methods
class PublicTransportData(object):
""" Class for handling the data retrieval. """
def __init__(self, journey):
self.start = journey[0]
self.destination = journey[1]
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from opendata.ch. """
response = get(
_RESOURCE +
'connections?' +
'from=' + self.start + '&' +
'to=' + self.destination + '&' +
'fields[]=connections/from/departureTimestamp/&' +
'fields[]=connections/')
connections = response.json()['connections'][:2]
try:
return [
dt_util.datetime_to_time_str(
dt_util.as_local(dt_util.utc_from_timestamp(
item['from']['departureTimestamp']))
)
for item in connections
]
except KeyError:
return ['n/a']
@@ -1,17 +1,71 @@
"""
homeassistant.components.sensor.systemmonitor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Shows system monitor values such as: disk, memory, and processor use.
Shows system monitor values such as: disk, memory and processor use
Configuration:
To use the System monitor sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: systemmonitor
resources:
- type: 'disk_use_percent'
arg: '/'
- type: 'disk_use'
arg: '/home'
- type: 'disk_free'
arg: '/'
- type: 'memory_use_percent'
- type: 'memory_use'
- type: 'memory_free'
- type: 'swap_use_percent'
- type: 'swap_use'
- type: 'swap_free'
- type: 'network_in'
arg: 'eth0'
- type: 'network_out'
arg: 'eth0'
- type: 'packets_in'
arg: 'eth0'
- type: 'packets_out'
arg: 'eth0'
- type: 'ipv4_address'
arg: 'eth0'
- type: 'ipv6_address'
arg: 'eth0'
- type: 'processor_use'
- type: 'process'
arg: 'octave-cli'
- type: 'last_boot'
- type: 'since_last_boot'
Variables:
resources
*Required
An array specifying the variables to monitor.
These are the variables for the resources array:
type
*Required
The variable you wish to monitor, see the configuration example above for a
sample list of variables.
arg
*Optional
Additional details for the type, eg. path, binary name, etc.
"""
import logging
import psutil
import homeassistant.util.dt as dt_util
from homeassistant.helpers.entity import Entity
from homeassistant.const import STATE_ON, STATE_OFF
import psutil
import logging
REQUIREMENTS = ['psutil==3.0.0']
SENSOR_TYPES = {
'disk_use_percent': ['Disk Use', '%'],
'disk_use': ['Disk Use', 'GiB'],
@@ -21,6 +75,17 @@ SENSOR_TYPES = {
'memory_free': ['RAM Free', 'MiB'],
'processor_use': ['CPU Use', '%'],
'process': ['Process', ''],
'swap_use_percent': ['Swap Use', '%'],
'swap_use': ['Swap Use', 'GiB'],
'swap_free': ['Swap Free', 'GiB'],
'network_out': ['Sent', 'MiB'],
'network_in': ['Recieved', 'MiB'],
'packets_out': ['Packets sent', ''],
'packets_in': ['Packets recieved', ''],
'ipv4_address': ['IPv4 address', ''],
'ipv6_address': ['IPv6 address', ''],
'last_boot': ['Last Boot', ''],
'since_last_boot': ['Since Last Boot', '']
}
_LOGGER = logging.getLogger(__name__)
@@ -28,7 +93,7 @@ _LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the sensors """
""" Sets up the sensors. """
dev = []
for resource in config['resources']:
@@ -43,7 +108,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class SystemMonitorSensor(Entity):
""" A system monitor sensor """
""" A system monitor sensor. """
def __init__(self, sensor_type, argument=''):
self._name = SENSOR_TYPES[sensor_type][0] + ' ' + argument
@@ -66,6 +131,7 @@ class SystemMonitorSensor(Entity):
def unit_of_measurement(self):
return self._unit_of_measurement
# pylint: disable=too-many-branches
def update(self):
if self.type == 'disk_use_percent':
self._state = psutil.disk_usage(self.argument).percent
@@ -83,6 +149,12 @@ class SystemMonitorSensor(Entity):
1024**2, 1)
elif self.type == 'memory_free':
self._state = round(psutil.virtual_memory().available / 1024**2, 1)
elif self.type == 'swap_use_percent':
self._state = psutil.swap_memory().percent
elif self.type == 'swap_use':
self._state = round(psutil.swap_memory().used / 1024**3, 1)
elif self.type == 'swap_free':
self._state = round(psutil.swap_memory().free / 1024**3, 1)
elif self.type == 'processor_use':
self._state = round(psutil.cpu_percent(interval=None))
elif self.type == 'process':
@@ -90,3 +162,24 @@ class SystemMonitorSensor(Entity):
self._state = STATE_ON
else:
self._state = STATE_OFF
elif self.type == 'network_out':
self._state = round(psutil.net_io_counters(pernic=True)
[self.argument][0] / 1024**2, 1)
elif self.type == 'network_in':
self._state = round(psutil.net_io_counters(pernic=True)
[self.argument][1] / 1024**2, 1)
elif self.type == 'packets_out':
self._state = psutil.net_io_counters(pernic=True)[self.argument][2]
elif self.type == 'packets_in':
self._state = psutil.net_io_counters(pernic=True)[self.argument][3]
elif self.type == 'ipv4_address':
self._state = psutil.net_if_addrs()[self.argument][0][1]
elif self.type == 'ipv6_address':
self._state = psutil.net_if_addrs()[self.argument][1][1]
elif self.type == 'last_boot':
self._state = dt_util.datetime_to_date_str(
dt_util.as_local(
dt_util.utc_from_timestamp(psutil.boot_time())))
elif self.type == 'since_last_boot':
self._state = dt_util.utcnow() - dt_util.utc_from_timestamp(
psutil.boot_time())
+4 -3
View File
@@ -1,8 +1,7 @@
"""
homeassistant.components.sensor.tellstick
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Shows sensor values from tellstick sensors.
Shows sensor values from Tellstick sensors.
Possible config keys:
@@ -35,6 +34,8 @@ import homeassistant.util as util
DatatypeDescription = namedtuple("DatatypeDescription", ['name', 'unit'])
REQUIREMENTS = ['tellcore-py==1.0.4']
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
@@ -77,7 +78,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
try:
sensor_name = config[ts_sensor.id]
except KeyError:
if 'only_named' in config:
if util.convert(config.get('only_named'), bool, False):
continue
sensor_name = str(ts_sensor.id)
+71
View File
@@ -0,0 +1,71 @@
"""
homeassistant.components.sensor.temper
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for getting temperature from TEMPer devices.
Configuration:
To use the temper sensors you will need to add something like the following to
your configuration.yaml file.
sensor:
platform: temper
"""
import logging
from homeassistant.helpers.entity import Entity
from homeassistant.const import CONF_NAME, DEVICE_DEFAULT_NAME
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['https://github.com/rkabadi/temper-python/archive/'
'3dbdaf2d87b8db9a3cd6e5585fc704537dd2d09b.zip'
'#temperusb==1.2.3']
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Find and return Temper sensors. """
try:
# pylint: disable=no-name-in-module, import-error
from temperusb.temper import TemperHandler
except ImportError:
_LOGGER.error('Failed to import temperusb')
return False
temp_unit = hass.config.temperature_unit
name = config.get(CONF_NAME, DEVICE_DEFAULT_NAME)
temper_devices = TemperHandler().get_devices()
add_devices_callback([TemperSensor(dev, temp_unit, name + '_' + str(idx))
for idx, dev in enumerate(temper_devices)])
class TemperSensor(Entity):
""" Represents an Temper temperature sensor. """
def __init__(self, temper_device, temp_unit, name):
self.temper_device = temper_device
self.temp_unit = temp_unit
self.current_value = None
self._name = name
@property
def name(self):
""" Returns the name of the temperature sensor. """
return self._name
@property
def state(self):
""" Returns the state of the entity. """
return self.current_value
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self.temp_unit
def update(self):
""" Retrieve latest state. """
try:
self.current_value = self.temper_device.get_temperature()
except IOError:
_LOGGER.error('Failed to get temperature due to insufficient '
'permissions. Try running with "sudo"')
@@ -0,0 +1,105 @@
"""
homeassistant.components.sensor.time_date
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Date and Time service.
Configuration:
To use the Date and Time sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: time_date
display_options:
- 'time'
- 'date'
- 'date_time'
- 'time_date'
- 'time_utc'
- 'beat'
Variables:
display_options
*Required
The variable you wish to display. See the configuration example above for a
list of all available variables.
"""
import logging
import homeassistant.util.dt as dt_util
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
OPTION_TYPES = {
'time': 'Time',
'date': 'Date',
'date_time': 'Date & Time',
'time_date': 'Time & Date',
'beat': 'Time (beat)',
'time_utc': 'Time (UTC)',
}
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the Time and Date sensor. """
if hass.config.time_zone is None:
_LOGGER.error("Timezone is not set in Home Assistant config")
return False
dev = []
for variable in config['display_options']:
if variable not in OPTION_TYPES:
_LOGGER.error('Option type: "%s" does not exist', variable)
else:
dev.append(TimeDateSensor(variable))
add_devices(dev)
# pylint: disable=too-few-public-methods
class TimeDateSensor(Entity):
""" Implements a Time and Date sensor. """
def __init__(self, option_type):
self._name = OPTION_TYPES[option_type]
self.type = option_type
self._state = None
self.update()
@property
def name(self):
""" Returns the name of the device. """
return self._name
@property
def state(self):
""" Returns the state of the device. """
return self._state
def update(self):
""" Gets the latest data and updates the states. """
time_date = dt_util.utcnow()
time = dt_util.datetime_to_time_str(dt_util.as_local(time_date))
time_utc = dt_util.datetime_to_time_str(time_date)
date = dt_util.datetime_to_date_str(dt_util.as_local(time_date))
# Calculate the beat (Swatch Internet Time) time without date.
hours, minutes, seconds = time_date.strftime('%H:%M:%S').split(':')
beat = ((int(seconds) + (int(minutes) * 60) + ((int(hours) + 1) *
3600)) / 86.4)
if self.type == 'time':
self._state = time
elif self.type == 'date':
self._state = date
elif self.type == 'date_time':
self._state = date + ', ' + time
elif self.type == 'time_date':
self._state = time + ', ' + date
elif self.type == 'time_utc':
self._state = time_utc
elif self.type == 'beat':
self._state = '{0:.2f}'.format(beat)
@@ -0,0 +1,175 @@
"""
homeassistant.components.sensor.transmission
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Monitors Transmission BitTorrent client API.
Configuration:
To use the Transmission sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: transmission
name: Transmission
host: 192.168.1.26
port: 9091
username: YOUR_USERNAME
password: YOUR_PASSWORD
monitored_variables:
- 'current_status'
- 'download_speed'
- 'upload_speed'
Variables:
host
*Required
This is the IP address of your Transmission daemon, e.g. 192.168.1.32
port
*Optional
The port your Transmission daemon uses, defaults to 9091. Example: 8080
username
*Required
Your Transmission username.
password
*Required
Your Transmission password.
name
*Optional
The name to use when displaying this Transmission instance.
monitored_variables
*Required
Variables to monitor. See the configuration example above for a
list of all available variables to monitor.
"""
from homeassistant.util import Throttle
from datetime import timedelta
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.helpers.entity import Entity
# pylint: disable=no-name-in-module, import-error
import transmissionrpc
from transmissionrpc.error import TransmissionError
import logging
REQUIREMENTS = ['transmissionrpc==0.11']
SENSOR_TYPES = {
'current_status': ['Status', ''],
'download_speed': ['Down Speed', 'MB/s'],
'upload_speed': ['Up Speed', 'MB/s']
}
_LOGGER = logging.getLogger(__name__)
_THROTTLED_REFRESH = None
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Transmission sensors. """
host = config.get(CONF_HOST)
username = config.get(CONF_USERNAME, None)
password = config.get(CONF_PASSWORD, None)
port = config.get('port', 9091)
name = config.get("name", "Transmission")
if not host:
_LOGGER.error('Missing config variable %s', CONF_HOST)
return False
# import logging
# logging.getLogger('transmissionrpc').setLevel(logging.DEBUG)
transmission_api = transmissionrpc.Client(
host, port=port, user=username, password=password)
try:
transmission_api.session_stats()
except TransmissionError:
_LOGGER.exception("Connection to Transmission API failed.")
return False
# pylint: disable=global-statement
global _THROTTLED_REFRESH
_THROTTLED_REFRESH = Throttle(timedelta(seconds=1))(
transmission_api.session_stats)
dev = []
for variable in config['monitored_variables']:
if variable not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable)
else:
dev.append(TransmissionSensor(
variable, transmission_api, name))
add_devices(dev)
class TransmissionSensor(Entity):
""" A Transmission sensor. """
def __init__(self, sensor_type, transmission_client, client_name):
self._name = SENSOR_TYPES[sensor_type][0]
self.transmission_client = transmission_client
self.type = sensor_type
self.client_name = client_name
self._state = None
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
@property
def name(self):
return self.client_name + ' ' + self._name
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._unit_of_measurement
def refresh_transmission_data(self):
""" Calls the throttled Transmission refresh method. """
if _THROTTLED_REFRESH is not None:
try:
_THROTTLED_REFRESH()
except TransmissionError:
_LOGGER.exception(
self.name + " Connection to Transmission API failed."
)
def update(self):
""" Gets the latest data from Transmission and updates the state. """
self.refresh_transmission_data()
if self.type == 'current_status':
if self.transmission_client.session:
upload = self.transmission_client.session.uploadSpeed
download = self.transmission_client.session.downloadSpeed
if upload > 0 and download > 0:
self._state = 'Up/Down'
elif upload > 0 and download == 0:
self._state = 'Seeding'
elif upload == 0 and download > 0:
self._state = 'Downloading'
else:
self._state = 'Idle'
else:
self._state = 'Unknown'
if self.transmission_client.session:
if self.type == 'download_speed':
mb_spd = float(self.transmission_client.session.downloadSpeed)
mb_spd = mb_spd / 1024 / 1024
self._state = round(mb_spd, 2 if mb_spd < 0.1 else 1)
elif self.type == 'upload_speed':
mb_spd = float(self.transmission_client.session.uploadSpeed)
mb_spd = mb_spd / 1024 / 1024
self._state = round(mb_spd, 2 if mb_spd < 0.1 else 1)
+46 -22
View File
@@ -1,9 +1,12 @@
"""
homeassistant.components.sensor.vera
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for Vera sensors.
Configuration:
To use the Vera sensors you will need to add something like the following to
your config/configuration.yaml
your configuration.yaml file.
sensor:
platform: vera
@@ -15,13 +18,12 @@ sensor:
13:
name: Another sensor
VARIABLES:
Variables:
vera_controller_url
*Required
This is the base URL of your vera controller including the port number if not
running on 80
Example: http://192.168.1.21:3480/
running on 80, e.g. http://192.168.1.21:3480/
device_data
@@ -29,7 +31,7 @@ device_data
This contains an array additional device info for your Vera devices. It is not
required and if not specified all sensors configured in your Vera controller
will be added with default values. You should use the id of your vera device
as the key for the device within device_data
as the key for the device within device_data.
These are the variables for the device_data array:
@@ -37,24 +39,25 @@ name
*Optional
This parameter allows you to override the name of your Vera device in the HA
interface, if not specified the value configured for the device in your Vera
will be used
will be used.
exclude
*Optional
This parameter allows you to exclude the specified device from homeassistant,
it should be set to "true" if you want this device excluded
This parameter allows you to exclude the specified device from Home Assistant,
it should be set to "true" if you want this device excluded.
"""
import logging
import time
from requests.exceptions import RequestException
import homeassistant.util.dt as dt_util
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
ATTR_BATTERY_LEVEL, ATTR_TRIPPED, ATTR_ARMED, ATTR_LAST_TRIP_TIME)
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.vera.vera as veraApi
ATTR_BATTERY_LEVEL, ATTR_TRIPPED, ATTR_ARMED, ATTR_LAST_TRIP_TIME,
TEMP_CELCIUS, TEMP_FAHRENHEIT)
REQUIREMENTS = ['https://github.com/balloob/home-assistant-vera-api/archive/'
'a8f823066ead6c7da6fb5e7abaf16fef62e63364.zip'
'#python-vera==0.1']
_LOGGER = logging.getLogger(__name__)
@@ -62,6 +65,7 @@ _LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def get_devices(hass, config):
""" Find and return Vera Sensors. """
import pyvera as veraApi
base_url = config.get('vera_controller_url')
if not base_url:
@@ -95,12 +99,12 @@ def get_devices(hass, config):
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Performs setup for Vera controller devices """
""" Performs setup for Vera controller devices. """
add_devices(get_devices(hass, config))
class VeraSensor(Entity):
""" Represents a Vera Sensor """
""" Represents a Vera Sensor. """
def __init__(self, vera_device, extra_data=None):
self.vera_device = vera_device
@@ -110,6 +114,7 @@ class VeraSensor(Entity):
else:
self._name = self.vera_device.name
self.current_value = ''
self._temperature_units = None
def __str__(self):
return "%s %s %s" % (self.name, self.vera_device.deviceId, self.state)
@@ -123,6 +128,11 @@ class VeraSensor(Entity):
""" Get the mame of the sensor. """
return self._name
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._temperature_units
@property
def state_attributes(self):
attr = super().state_attributes
@@ -135,11 +145,12 @@ class VeraSensor(Entity):
if self.vera_device.is_trippable:
last_tripped = self.vera_device.refresh_value('LastTrip')
trip_time_str = time.strftime(
"%Y-%m-%d %H:%M",
time.localtime(int(last_tripped))
)
attr[ATTR_LAST_TRIP_TIME] = trip_time_str
if last_tripped is not None:
utc_time = dt_util.utc_from_timestamp(int(last_tripped))
attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str(
utc_time)
else:
attr[ATTR_LAST_TRIP_TIME] = None
tripped = self.vera_device.refresh_value('Tripped')
attr[ATTR_TRIPPED] = 'True' if tripped == '1' else 'False'
@@ -151,7 +162,20 @@ class VeraSensor(Entity):
self.vera_device.refresh_value('CurrentTemperature')
current_temp = self.vera_device.get_value('CurrentTemperature')
vera_temp_units = self.vera_device.veraController.temperature_units
self.current_value = current_temp + '°' + vera_temp_units
if vera_temp_units == 'F':
self._temperature_units = TEMP_FAHRENHEIT
else:
self._temperature_units = TEMP_CELCIUS
if self.hass:
temp = self.hass.config.temperature(
current_temp,
self._temperature_units)
current_temp, self._temperature_units = temp
self.current_value = current_temp
elif self.vera_device.category == "Light Sensor":
self.vera_device.refresh_value('CurrentLevel')
self.current_value = self.vera_device.get_value('CurrentLevel')
+127
View File
@@ -0,0 +1,127 @@
"""
homeassistant.components.sensor.verisure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interfaces with Verisure sensors.
"""
import logging
import homeassistant.components.verisure as verisure
from homeassistant.helpers.entity import Entity
from homeassistant.const import TEMP_CELCIUS
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Verisure platform. """
if not verisure.MY_PAGES:
_LOGGER.error('A connection has not been made to Verisure mypages.')
return False
sensors = []
sensors.extend([
VerisureThermometer(value)
for value in verisure.get_climate_status().values()
if verisure.SHOW_THERMOMETERS and
hasattr(value, 'temperature') and value.temperature
])
sensors.extend([
VerisureHygrometer(value)
for value in verisure.get_climate_status().values()
if verisure.SHOW_HYGROMETERS and
hasattr(value, 'humidity') and value.humidity
])
sensors.extend([
VerisureAlarm(value)
for value in verisure.get_alarm_status().values()
if verisure.SHOW_ALARM
])
add_devices(sensors)
class VerisureThermometer(Entity):
""" represents a Verisure thermometer within home assistant. """
def __init__(self, climate_status):
self._id = climate_status.id
self._device = verisure.MY_PAGES.DEVICE_CLIMATE
@property
def name(self):
""" Returns the name of the device. """
return '{} {}'.format(
verisure.STATUS[self._device][self._id].location,
"Temperature")
@property
def state(self):
""" Returns the state of the device. """
# remove ° character
return verisure.STATUS[self._device][self._id].temperature[:-1]
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity """
return TEMP_CELCIUS # can verisure report in fahrenheit?
def update(self):
''' update sensor '''
verisure.update()
class VerisureHygrometer(Entity):
""" represents a Verisure hygrometer within home assistant. """
def __init__(self, climate_status):
self._id = climate_status.id
self._device = verisure.MY_PAGES.DEVICE_CLIMATE
@property
def name(self):
""" Returns the name of the device. """
return '{} {}'.format(
verisure.STATUS[self._device][self._id].location,
"Humidity")
@property
def state(self):
""" Returns the state of the device. """
# remove % character
return verisure.STATUS[self._device][self._id].humidity[:-1]
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity """
return "%"
def update(self):
''' update sensor '''
verisure.update()
class VerisureAlarm(Entity):
""" represents a Verisure alarm status within home assistant. """
def __init__(self, alarm_status):
self._id = alarm_status.id
self._device = verisure.MY_PAGES.DEVICE_ALARM
@property
def name(self):
""" Returns the name of the device. """
return 'Alarm {}'.format(self._id)
@property
def state(self):
""" Returns the state of the device. """
return verisure.STATUS[self._device][self._id].label
def update(self):
''' update sensor '''
verisure.update()
+12 -5
View File
@@ -1,15 +1,22 @@
""" Support for Wink sensors. """
"""
homeassistant.components.sensor.wink
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for Wink sensors.
"""
import logging
# pylint: disable=no-name-in-module, import-error
import homeassistant.external.wink.pywink as pywink
from homeassistant.helpers.entity import Entity
from homeassistant.const import CONF_ACCESS_TOKEN, STATE_OPEN, STATE_CLOSED
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/'
'c2b700e8ca866159566ecf5e644d9c297f69f257.zip'
'#python-wink==0.1']
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Wink platform. """
import pywink
if discovery_info is None:
token = config.get(CONF_ACCESS_TOKEN)
@@ -25,7 +32,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class WinkSensorDevice(Entity):
""" represents a wink sensor within home assistant. """
""" Represents a wink sensor. """
def __init__(self, wink):
self.wink = wink
-1
View File
@@ -1,7 +1,6 @@
"""
homeassistant.components.sensor.zwave
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interfaces with Z-Wave sensors.
"""
# pylint: disable=import-error