Home Assistant Integration Documentaion
This integration is designed to replace the defunct Dark Sky integration in Home Assistant with a modified and updated, but fully compatible version that relies on the Pirate Weather API instead!
While this integration is designed to be compatible with Dark Sky, the underlying code is significantly different. This version is designed to work with more modern versions of Home Assistant, and relies on asyncio, unified data update coordinators, and setup via the UI! A legacy branch that is a 1:1 replacement for the previous Dark Sky integration is also available, but is not recommended.
Installation
There are two methods to install this installation:
HACS Installation (easiest)
- Add
https://github.com/Pirate-Weather/pirate-weather-ha
as a custom repository - Restart Home Assistant
- Register for a Pirate Weather API Key here: https://pirate-weather.apiable.io
- Log into the Pirate Weather API interface (https://pirate-weather.apiable.io) and subscribe to the API!
- Add the Pirate Weather on the Integrations page of your Home Assistant Installation following the steps below.
Manual Installation
- Using the tool of choice open the directory (folder) for your HA configuration (where you find
configuration.yaml
). - If you do not have a
custom_components
directory (folder) there, you need to create it. - In the
custom_components
directory (folder) create a new folder calledpirateweather
. - Download all the files from the
custom_components/pirateweather/
directory (folder) in this repository. - Place the files you downloaded in the new directory (folder) you created.
- Restart Home Assistant
- Register for a Pirate Weather API Key here: https://pirate-weather.apiable.io
- Log into the Pirate Weather API interface (https://pirate-weather.apiable.io), and subscribe to the API!
- Add the Pirate Weather on the Integrations page of your Home Assistant Installation following the steps below.
Configuration
HACS Configuration
The use to integration, click on the "Add Integration" button on the Integrations page in the Home Assistant Settings and search for Pirate Weather. This will open the add integration UI, shown below.
- The API key can be received from Apiable, and is only used to track usage and keep my AWS bills reasonable
- The Integration Name is what this weather source will be called. If you want to track the weather at multiple locations, change this.
- The Latitude and Longitude for the forecast.
- The update interval the forecast (in seconds). Anything below 900 seconds (15 minutes) is not recommended will likely lead to running out of quota.
- Select if a Weather Entity and/or Sensor Entity is required
- A Weather Entity creates the dashboard standard weather card, and can provide a daily and hourly forecast.
- A Sensor Entity will create separate sensors for each condition and forecast time. For example, a sensor for the temperature on hour/day 0 (today), hour/day 1, and hour/day 2, for a total of three sensors. If unsure, start with leaving only the Weather Entity selected.
- Note that for alerts to work, this needs to be selected, along with "alerts" under the monitored conditions.
- Note that you must also setup the monitored conditions you would like to create sensors for otherwise no sensors will be created.
- The language. At the moment, only English is supported.
- The days forecast sensors should be created for, in a csv list.
- If daily sensor entities need to be created, this is required.
- The hours forecast sensors should be created for, in a csv list.
- If hourly sensors need to be created, this is required.
- The monitored conditions forecast sensors should be created for.
- If sensor entity values should be rounded to the nearest integer.
- And which units the forecast sensors should be in. This integration works with the built-in Home Assistant units; however, this option allows rounding to be used.
YAML Configuration
YAML configuration is still supported, but is depreciated and may be removed at some point in the future. If the integration detects an existing YAML integration, it will import and save it, allowing the yaml to be safely removed.
To use the integration via this approach, either add or edit to your configuration.yaml
file with this block, using the new API key:
weather:
- platform: pirateweather
api_key: <APIKEY>
# Additional optional values:
latitude: Location latitude
longitude: Location longitude
mode: "hourly" (default) or "daily"
name: Custom name
# you can also get a sensor data
sensor:
- platform: pirateweather
api_key: <APIKEY>
scan_interval: '00:15:00'
monitored_conditions:
- temperature
- precip_probability
- precip_type
- humidity
- cloud_cover
- nearest_storm_distance
- precip_intensity
- wind_speed
Sensors
The available sensors for the integration are:
- Summary
- Icon
- Precipitation Type
- Precipitation Intensity
- Precipitation Probability
- Precipitation Accumulation
- Temperature
- Apparent Temperature
- Dew Point
- Humidity
- Wind Speed
- Wind Gust
- Wind Bearing
- Cloud Cover
- Pressure
- Visibility
- Ozone
- Minutely Summary
- Hourly Summary
- Daily Summary
- Temperature High
- Temperature Low
- Apparent Temperature High
- Apparent Temperature Low
- Precip Intensity Max
- UV Index
- Moon Phase
- Sunrise Time
- Sunset Time
- Nearest Storm Distance
- Nearest Storm Bearing
- Alerts
- Time
- Fire Index
- Fire Risk Level
- Fire Index Max
- Smoke
- Smoke Max
- Liquid Accumulation
- Snow Accumulation
- Ice Accumulation
- Daytime High Apparent Temperature Time
- Overnight Low Apparent Temperature Time
- Daytime High Temperature Time
- Daily Low Temperature Time
Full documentation of the different data points is available here https://pirateweather.net/en/latest/API/#data-point. A full list of conditions supported by HA is available here https://www.home-assistant.io/integrations/weather/#condition-mapping.
The only data point that is included in HA but not the API is a described Fire Risk Level, converting from the numeric index to a qualitative term following this approach.
Frequently Asked Questions
What is the recommended update frequency?
The default value of 1200 (20 minutes) is fine for most use cases and it's not recommended to go any lower than 900 seconds (15 minutes). The model data that underpins this whole thing has only provides data in 15 minute increments, so while the API interpolates this down to a minute-by-minute data, there isn't much benefit to requesting data faster than that.
Can I update my API key or update interval after the initial setup?
No. The way HA stores the data and sets things up means that it's not possible to update the key/update interval after creation.
After updating to V1.3 I can no longer access forecast attributes directly
In release 2023.9 HA depreciated the forecast attribute and as a result you are not able to access the forecast attributes directly. In order to access them you need to create a template like the following:
- trigger:
- platform: time_pattern
minutes: "/30"
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.pirateweather
response_variable: daily
sensor:
- name: Pirate Weather Daily
unique_id: pirateweather_daily
state: "{{ daily['weather.pirateweather'].forecast[0].condition }}"
attributes:
forecast: "{{ daily['weather.pirateweather'].forecast }}"
- trigger:
- platform: time_pattern
minutes: "/30"
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.pirateweather
response_variable: hourly
sensor:
- name: Pirate Weather Hourly
unique_id: pirateweather_hourly
state: "{{ hourly['weather.pirateweather'].forecast[0].condition }}"
attributes:
forecast: "{{ hourly['weather.pirateweather'].forecast[:24] }}"
For more information see issue #157 and https://github.com/hg1337/homeassistant-dwd/blob/f47840bfade5ed21781843542674f7ccb6be0ba3/questions_and_answers.md#im-using-a-third-party-weather-card-that-doesnt-support-the-new-forecast-mechanism-can-i-continue-using-it
Can I use a dynamic location with the integration?
The integration uses a weather data coordinator that is based on the lat-lon of the setup location, and it sticks with that. What you can do is create a weather template using a rest sensor like so:
# setup pirate weather dynamic location
weather:
- platform: template
name: "Dynamic Weather Template"
unique_id: "pw_template"
attribution_template: "Powered by Pirate Weather"
temperature_template: "{{ state_attr('sensor.PW_Template_Currently', 'temperature') }}"
temperature_unit: "°F"
humidity_template: "{{ state_attr('sensor.PW_Template_Currently', 'humidity')*100 | int }}"
pressure_template: "{{ state_attr('sensor.PW_Template_Currently', 'pressure') }}"
pressure_unit: "hPa"
wind_speed_template: "{{ state_attr('sensor.PW_Template_Currently', 'windSpeed') | int}}"
wind_speed_unit: "mph"
ozone_template: "{{ state_attr('sensor.PW_Template_Currently', 'ozone') }}"
visibility_template: "{{ state_attr('sensor.PW_Template_Currently', 'visibility') }}"
visibility_unit: "mi"
precipitation_unit: "in"
condition_template: >-
{% if state_attr('sensor.PW_Template_Currently', 'icon') == "clear-night" %}
clear-night
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "clear-day" %}
sunny
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "cloudy" %}
cloudy
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "fog" %}
fog
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "partly-cloudy-day" %}
partlycloudy
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "partly-cloudy-night" %}
partlycloudy
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "rain" %}
rainy
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "snow" %}
snowy
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "sleet" %}
snowy
{% elif state_attr('sensor.PW_Template_Currently', 'icon') == "wind" %}
windy
{% endif %}
forecast_daily_template: >-
{%set return=namespace(data=[])%}
{%for datapoint in state_attr('sensor.forecast_daily', 'data')%}
{% set condition=datapoint.icon%}
{% if datapoint.icon == "clear-day" %}
{%set condition="sunny"%}
{% elif datapoint.icon == "partly-cloudy-day" or datapoint.icon == "partly-cloudy-night"%}
{%set condition="partlycloudy"%}
{% elif datapoint.icon == "rain" %}
{%set condition="rainy"%}
{% elif datapoint.icon == "snow" or datapoint.icon=="sleet"%}
{%set condition="snowy"%}
{% elif datapoint.icon == "wind" %}
{%set condition="windy"%}
{% endif %}
{%set returnPoint=[{'datetime':as_local(as_datetime(datapoint.time)).strftime("%Y-%m-%dT%H:%M:%S")
,'temperature':datapoint.temperatureHigh, 'templow':datapoint.temperatureLow, 'condition':condition,'precipitation':datapoint.precipAccumulation
, 'wind_bearing':datapoint.windBearing, 'wind_speed':datapoint.windSpeed}]%}
{% set return.data=return.data+returnPoint%}
{% endfor%}
{{return.data}}
forecast_hourly_template: >-
{%set return=namespace(data=[])%}
{%for datapoint in state_attr('sensor.forecast_hourly', 'data')%}
{% set condition=datapoint.icon%}
{% if datapoint.icon == "clear-day" %}
{%set condition="sunny"%}
{% elif datapoint.icon == "partly-cloudy-day" or datapoint.icon == "partly-cloudy-night"%}
{%set condition="partlycloudy"%}
{% elif datapoint.icon == "rain" %}
{%set condition="rainy"%}
{% elif datapoint.icon == "snow" or datapoint.icon=="sleet"%}
{%set condition="snowy"%}
{% elif datapoint.icon == "wind" %}
{%set condition="windy"%}
{% endif %}
{%set returnPoint=[{'datetime':as_local(as_datetime(datapoint.time)).strftime("%Y-%m-%dT%H:%M:%S")
,'temperature':datapoint.temperature,'condition':condition,'precipitation':datapoint.precipAccumulation
, 'wind_bearing':datapoint.windBearing, 'wind_speed':datapoint.windSpeed}]%}
{% set return.data=return.data+returnPoint%}
{% endfor%}
{{return.data}}
rest:
resource_template: https://api.pirateweather.net/forecast/<API KEY>/{{ state_attr('sensor.gps', 'latitude') }},{{ state_attr('sensor.gps', 'longitude') }}?units=us&exclude=minutely&exclude=alerts&extend=hourly
scan_interval: 300
sensor:
- name: "PW_Template_Currently"
json_attributes_path: "$.currently"
value_template: "OK"
json_attributes:
- summary
- temperature
- precipProbability
- precipType
- humidity
- cloudCover
- nearestStormDistance
- precipIntensity
- windSpeed
- visibility
- ozone
- windBearing
- pressure
- icon
- time
- name: "Forecast Hourly"
json_attributes_path: "$.hourly"
value_template: "OK"
json_attributes:
- summary
- icon
- data
- name: "Forecast Daily"
json_attributes_path: "$.daily"
value_template: "OK"
json_attributes:
- summary
- icon
- data
Thanks to breel007 for posting the template here and for more information see issues #46 and #149
Does having multiple integrations setup result in multiple calls to the API?
Yes, every time you setup a new instance of the integration it results in more queries to the API. For more information see #243