mirror of
https://github.com/home-assistant/core.git
synced 2025-08-13 07:20:01 +00:00
.github
docs
homeassistant
components
alarm_control_panel
alexa
automation
binary_sensor
calendar
camera
climate
cloud
config
cover
device_tracker
emulated_hue
fan
frontend
group
http
image_processing
light
lock
mailbox
media_player
mqtt
notify
persistent_notification
recorder
remote
scene
sensor
__init__.py
abode.py
airvisual.py
alarmdecoder.py
amcrest.py
android_ip_webcam.py
apcupsd.py
api_streams.py
arduino.py
arest.py
arlo.py
arwn.py
bbox.py
bh1750.py
bitcoin.py
blink.py
blockchain.py
bloomsky.py
bme280.py
bom.py
broadlink.py
buienradar.py
cert_expiry.py
citybikes.py
coinmarketcap.py
comed_hourly_pricing.py
comfoconnect.py
command_line.py
cpuspeed.py
crimereports.py
cups.py
currencylayer.py
darksky.py
demo.py
deutsche_bahn.py
dht.py
dnsip.py
dovado.py
dsmr.py
dte_energy_bridge.py
dublin_bus_transport.py
dwd_weather_warnings.py
dweet.py
dyson.py
ebox.py
ecobee.py
eddystone_temperature.py
efergy.py
eight_sleep.py
eliqonline.py
emoncms.py
enocean.py
envirophat.py
envisalink.py
etherscan.py
fastdotcom.py
fedex.py
fido.py
file.py
fitbit.py
fixer.py
fritzbox_callmonitor.py
fritzbox_netmonitor.py
geizhals.py
geo_rss_events.py
gitter.py
glances.py
google_travel_time.py
google_wifi.py
gpsd.py
gtfs.py
haveibeenpwned.py
hddtemp.py
history_stats.py
homematic.py
hp_ilo.py
htu21d.py
hydroquebec.py
imap.py
imap_email_content.py
influxdb.py
ios.py
isy994.py
juicenet.py
kira.py
knx.py
kwb.py
lastfm.py
linux_battery.py
london_air.py
london_underground.py
loopenergy.py
lyft.py
metoffice.py
mfi.py
mhz19.py
miflora.py
min_max.py
modbus.py
modem_callerid.py
mold_indicator.py
moon.py
mopar.py
mqtt.py
mqtt_room.py
mvglive.py
mysensors.py
neato.py
nest.py
netatmo.py
netdata.py
neurio_energy.py
nut.py
nzbget.py
octoprint.py
ohmconnect.py
onewire.py
openevse.py
openexchangerates.py
openhardwaremonitor.py
opensky.py
openweathermap.py
otp.py
pi_hole.py
pilight.py
plex.py
pocketcasts.py
pushbullet.py
pvoutput.py
qnap.py
radarr.py
raincloud.py
random.py
rest.py
rflink.py
rfxtrx.py
ring.py
ripple.py
sabnzbd.py
scrape.py
season.py
sensehat.py
serial_pm.py
shodan.py
skybeacon.py
sleepiq.py
sma.py
snmp.py
sonarr.py
speedtest.py
statistics.py
steam_online.py
supervisord.py
swiss_hydrological_data.py
swiss_public_transport.py
synologydsm.py
systemmonitor.py
tado.py
tank_utility.py
tcp.py
ted5000.py
tellduslive.py
tellstick.py
temper.py
template.py
tesla.py
thethingsnetwork.py
thinkingcleaner.py
tibber.py
time_date.py
torque.py
tradfri.py
transmission.py
travisci.py
twitch.py
uber.py
uk_transport.py
upnp.py
ups.py
usps.py
vasttrafik.py
vera.py
verisure.py
version.py
volvooncall.py
waqi.py
wink.py
worldclock.py
worldtidesinfo.py
worxlandroid.py
wsdot.py
wunderground.py
xbox_live.py
xiaomi_aqara.py
yahoo_finance.py
yr.py
yweather.py
zabbix.py
zamg.py
zha.py
zigbee.py
zoneminder.py
zwave.py
switch
telegram_bot
tts
vacuum
weather
zha
zwave
__init__.py
abode.py
alarmdecoder.py
alert.py
amcrest.py
android_ip_webcam.py
apcupsd.py
api.py
apiai.py
apple_tv.py
arduino.py
arlo.py
asterisk_mbox.py
axis.py
bbb_gpio.py
blink.py
bloomsky.py
browser.py
comfoconnect.py
configurator.py
conversation.py
counter.py
datadog.py
demo.py
device_sun_light_trigger.py
digital_ocean.py
discovery.py
doorbird.py
downloader.py
duckdns.py
dweet.py
dyson.py
ecobee.py
eight_sleep.py
emoncms_history.py
enocean.py
envisalink.py
feedreader.py
ffmpeg.py
foursquare.py
google.py
graphite.py
hassio.py
hdmi_cec.py
history.py
history_graph.py
homematic.py
ifttt.py
influxdb.py
input_boolean.py
input_datetime.py
input_number.py
input_select.py
input_text.py
insteon_local.py
insteon_plm.py
intent_script.py
introduction.py
ios.py
isy994.py
joaoapps_join.py
juicenet.py
keyboard.py
keyboard_remote.py
kira.py
knx.py
lametric.py
lirc.py
litejet.py
logbook.py
logentries.py
logger.py
lutron.py
lutron_caseta.py
mailgun.py
maxcube.py
media_extractor.py
microsoft_face.py
mochad.py
modbus.py
mqtt_eventstream.py
mqtt_statestream.py
mycroft.py
mysensors.py
neato.py
nest.py
netatmo.py
nuimo_controller.py
octoprint.py
panel_custom.py
panel_iframe.py
pilight.py
plant.py
prometheus.py
proximity.py
python_script.py
qwikswitch.py
raincloud.py
raspihats.py
rest_command.py
rflink.py
rfxtrx.py
ring.py
rpi_gpio.py
rpi_pfio.py
rss_feed_template.py
satel_integra.py
script.py
scsgate.py
services.yaml
shell_command.py
shiftr.py
shopping_list.py
sleepiq.py
snips.py
spc.py
splunk.py
statsd.py
sun.py
tado.py
tellduslive.py
tellstick.py
tesla.py
thethingsnetwork.py
thingspeak.py
tradfri.py
twilio.py
updater.py
upnp.py
usps.py
velbus.py
velux.py
vera.py
verisure.py
volvooncall.py
wake_on_lan.py
weblink.py
websocket_api.py
wemo.py
wink.py
xiaomi_aqara.py
zabbix.py
zeroconf.py
zigbee.py
zone.py
zoneminder.py
helpers
scripts
util
__init__.py
__main__.py
bootstrap.py
config.py
const.py
core.py
exceptions.py
loader.py
monkey_patch.py
package_constraints.txt
remote.py
setup.py
script
tests
virtualization
.coveragerc
.dockerignore
.gitignore
.gitmodules
.hound.yml
.ignore
.travis.yml
CLA.md
CODEOWNERS
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Dockerfile
LICENSE.md
MANIFEST.in
README.rst
pylintrc
requirements_all.txt
requirements_docs.txt
requirements_test.txt
requirements_test_all.txt
setup.cfg
setup.py
tox.ini
205 lines
6.7 KiB
Python
Executable File
205 lines
6.7 KiB
Python
Executable File
"""
|
|
Support for the OpenWeatherMap (OWM) service.
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
https://home-assistant.io/components/sensor.openweathermap/
|
|
"""
|
|
import logging
|
|
from datetime import timedelta
|
|
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
|
from homeassistant.const import (
|
|
CONF_API_KEY, CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
|
CONF_MONITORED_CONDITIONS, ATTR_ATTRIBUTION)
|
|
import homeassistant.helpers.config_validation as cv
|
|
from homeassistant.helpers.entity import Entity
|
|
from homeassistant.util import Throttle
|
|
|
|
REQUIREMENTS = ['pyowm==2.7.1']
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
CONF_ATTRIBUTION = "Data provided by OpenWeatherMap"
|
|
CONF_FORECAST = 'forecast'
|
|
CONF_LANGUAGE = 'language'
|
|
|
|
DEFAULT_NAME = 'OWM'
|
|
|
|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
|
|
|
|
SENSOR_TYPES = {
|
|
'weather': ['Condition', None],
|
|
'temperature': ['Temperature', None],
|
|
'wind_speed': ['Wind speed', 'm/s'],
|
|
'wind_bearing': ['Wind bearing', '°'],
|
|
'humidity': ['Humidity', '%'],
|
|
'pressure': ['Pressure', 'mbar'],
|
|
'clouds': ['Cloud coverage', '%'],
|
|
'rain': ['Rain', 'mm'],
|
|
'snow': ['Snow', 'mm'],
|
|
}
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|
vol.Required(CONF_API_KEY): cv.string,
|
|
vol.Optional(CONF_MONITORED_CONDITIONS, default=[]):
|
|
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
|
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
vol.Optional(CONF_FORECAST, default=False): cv.boolean,
|
|
vol.Optional(CONF_LANGUAGE, default=None): cv.string,
|
|
})
|
|
|
|
|
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
|
"""Set up 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
|
|
|
|
from pyowm import OWM
|
|
|
|
SENSOR_TYPES['temperature'][1] = hass.config.units.temperature_unit
|
|
|
|
name = config.get(CONF_NAME)
|
|
forecast = config.get(CONF_FORECAST)
|
|
language = config.get(CONF_LANGUAGE)
|
|
if isinstance(language, str):
|
|
language = language.lower()[:2]
|
|
|
|
owm = OWM(API_key=config.get(CONF_API_KEY), language=language)
|
|
|
|
if not owm:
|
|
_LOGGER.error("Unable to connect to OpenWeatherMap")
|
|
return False
|
|
|
|
data = WeatherData(owm, forecast, hass.config.latitude,
|
|
hass.config.longitude)
|
|
dev = []
|
|
for variable in config[CONF_MONITORED_CONDITIONS]:
|
|
dev.append(OpenWeatherMapSensor(
|
|
name, data, variable, SENSOR_TYPES[variable][1]))
|
|
|
|
if forecast:
|
|
SENSOR_TYPES['forecast'] = ['Forecast', None]
|
|
dev.append(OpenWeatherMapSensor(
|
|
name, data, 'forecast', SENSOR_TYPES['temperature'][1]))
|
|
|
|
add_devices(dev, True)
|
|
|
|
|
|
class OpenWeatherMapSensor(Entity):
|
|
"""Implementation of an OpenWeatherMap sensor."""
|
|
|
|
def __init__(self, name, weather_data, sensor_type, temp_unit):
|
|
"""Initialize the sensor."""
|
|
self.client_name = name
|
|
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]
|
|
|
|
@property
|
|
def name(self):
|
|
"""Return the name of the sensor."""
|
|
return '{} {}'.format(self.client_name, self._name)
|
|
|
|
@property
|
|
def state(self):
|
|
"""Return the state of the device."""
|
|
return self._state
|
|
|
|
@property
|
|
def unit_of_measurement(self):
|
|
"""Return the unit of measurement of this entity, if any."""
|
|
return self._unit_of_measurement
|
|
|
|
@property
|
|
def device_state_attributes(self):
|
|
"""Return the state attributes."""
|
|
return {
|
|
ATTR_ATTRIBUTION: CONF_ATTRIBUTION,
|
|
}
|
|
|
|
def update(self):
|
|
"""Get 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 data is None or fc_data is None:
|
|
return
|
|
|
|
if self.type == 'weather':
|
|
self._state = data.get_detailed_status()
|
|
elif self.type == 'temperature':
|
|
if self.temp_unit == TEMP_CELSIUS:
|
|
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 = round(data.get_wind()['speed'], 1)
|
|
elif self.type == 'wind_bearing':
|
|
self._state = round(data.get_wind()['deg'], 1)
|
|
elif self.type == 'humidity':
|
|
self._state = round(data.get_humidity(), 1)
|
|
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):
|
|
"""Get the latest data from OpenWeatherMap."""
|
|
|
|
def __init__(self, owm, forecast, latitude, longitude):
|
|
"""Initialize the data object."""
|
|
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):
|
|
"""Get the latest data from OpenWeatherMap."""
|
|
try:
|
|
obs = self.owm.weather_at_coords(self.latitude, self.longitude)
|
|
except TypeError:
|
|
obs = None
|
|
if obs is None:
|
|
_LOGGER.warning("Failed to fetch data")
|
|
return
|
|
|
|
self.data = obs.get_weather()
|
|
|
|
if self.forecast == 1:
|
|
try:
|
|
obs = self.owm.three_hours_forecast_at_coords(
|
|
self.latitude, self.longitude)
|
|
self.fc_data = obs.get_forecast()
|
|
except TypeError:
|
|
_LOGGER.warning("Failed to fetch forecast")
|