Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Allow Templating in Configuration #46

Open
tdvantine opened this issue May 22, 2022 · 25 comments
Open

Feature Request: Allow Templating in Configuration #46

tdvantine opened this issue May 22, 2022 · 25 comments
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@tdvantine
Copy link

Currently the entry in configuration.yaml requires you to put your static location in: (broad location used here, yes I understand I could/should use a !secret here, but meh)

weather:
  - platform: pirateweather
    api_key: !secret pirate_weather_api
    # Additional optional values:
    latitude: '39'
    longitude: '-104'
    mode: "daily"
    name: PirateWeather

This works wonderful for home use, and I would say a good 95%+ of installations. However, I personally have a outlier case, as well as I am sure those that use HA for their RV or boat, etc would like this as well. I use HA to automate things on a touring show (think theatrical touring) and we are at a different city every week, being able to template the location would be amazing so we could get the weather for what ever city we are in that week.
An example of what the entry would look like:

weather:
  - platform: pirateweather
    api_key: !secret pirate_weather_api
    # Additional optional values:
    latitude: {{states.person.<NAME>.attributes.latitude}}
    longitude: {{states.person.<NAME>.attributes.longitude}}
    mode: "daily"
    name: PirateWeather

I have found some work-arounds to this, using a rest sensor to poll the api, but this wont do as it polls the api on every update of location instead of every 15mins/configured amount of time in the sensor.

I have a home instance (HA Core on Ubuntu) and the touring one (HAOS on a Pi) so I would be more than happy and willing to test out anything you need. I am also open to any other ideas to get this working.

@alexander0042
Copy link
Collaborator

Hi,

Thanks for trying out this service and opening this issue! That's a really interesting use case (I love hearing how people are using this service), and definitely something that would be worth adding.

At the moment, I'm in the middle of a re-write of this entire integration. It started out as just trying to allow setup via the web GUI config flow, but in order to do that the code had to be asynchronous, which led to all sorts of complications! The good news is that I almost have this working, and it should modernize most of the code base here, The way you've described the template it should "just work", but I remain skeptical.

One quick thing that would help here is if you could try adding a single variable rest sensor, since you've already started down that road a little bit. If you check out this issue: #4 (comment), I have instructions on how to create one for a single variable, Since the rest sensor supports templates (I think), it'd be worth testing that with temperature just to make sure that one part of it is updating.

@tdvantine
Copy link
Author

sensor:
  - platform: rest
    name: PW_1Day_Precip
    scan_interval: 15
    resource: https://api.pirateweather.net/forecast/<key>/<lat>,<long>,-86400?units=ca
    value_template: "{{ float(value_json.daily.data[0].precipAccumulation) }}"
    unit_of_measurement: "cm"

Is very very similar to the rest sensor I had set up. I will add in the scan_interval: and do some testing to see if that clears up the constant api call everytime my location is reported again. Will post back later today with the results and excact code block used.

I personally find the pirate weather intergration the best one avaible, a lot of the others lack features or you have to pay for them unlike PW.

@alexander0042
Copy link
Collaborator

Thanks, keep me posted!

This sort of feedback is really great to hear- it really bothered me that most weather forecasts come from government agencies, but then we have to go through poorly documented cooperate APIs to access the data, so I wanted to do something to fix it. It shouldn't be such a mystery what AccuWeather means by "percent of precipitation", but it is for some reason! Along the way, the Dark Sky syntax seemed to work perfectly well, and let me leverage a ton of existing code out there (like this integration).

@tdvantine
Copy link
Author

https://twitter.com/kleverlands/status/1338927247126827009?s=20&t=k4Ag7l-W7MY6PPG18cOdbw

- platform: rest
  resource_template: !secret pirate_rest_resource
  json_attributes_path: "$.currently"
  scan_interval: '00:15:00'
  json_attributes:
    - summary
    - temperature
    - precip_probability
    - precip_type
    - humidity
    - cloud_cover
    - nearest_storm_distance
    - precip_intensity
    - wind_speed
  name: pirateweather_api_test
  value_template: 'OK'

Didn't update on the 15min mark, as well as its missing some of the data.
image
Just noticed as I was typing, the attributes don't line up correctly. So for right this second, its just the update at the 15 min mark that isn't happening

@tdvantine
Copy link
Author

Corrected the JSON Attributes and solved that "problem".
image

@alexander0042
Copy link
Collaborator

Thanks for working out the syntax for getting multiple parameters from one call! I was trying to figure that one out, and it looks like you've got it,

Is the updating working now as well? The scan_interval documentation is pretty light, but appears to be able to be defined using seconds, so maybe try:
scan_interval: 900

@tdvantine
Copy link
Author

- platform: rest
  resource_template: !secret pirate_rest_resource
  json_attributes_path: "$.currently"
  scan_interval: '00:15:00'
  json_attributes:
    - summary
    - temperature
    - precipProbability
    - precipType
    - humidity
    - cloudCover
    - nearestStormDistance
    - precipIntensity
    - windSpeed
  name: pirateweather_api_test
  value_template: 'OK

Updates every 15 mins and does NOT update when the device tracker updates location so that's perfect. Now, too bad it isn't intergrated into a weather entity to use the weather cards.

The resource:

pirate_rest_resource: 'https://dev.pirateweather.net/forecast/<API>/{{states.person.tristan_van_tine.attributes.latitude}},{{states.person.tristan_van_tine.attributes.longitude

@tdvantine
Copy link
Author

Been playing around and I believe that using the rest calls just isn't going to work as nicely. Having a hard time getting forecast to show in a weather card.

So far I have this for the weather.dynamic_weather sensor:

weather:
  - platform: template
    name: "Dynamic Weather"
    unique_id: 472658229893
    # attribution: "Powered by PirateWeather"
    condition_template: "{{ state_attr('sensor.pirateweather_api_test', 'summary') }}"
    temperature_template: "{{ state_attr('sensor.pirateweather_api_test', 'temperature') | float }}"
    humidity_template: "{{ state_attr('sensor.pirateweather_api_test', 'humidity') | float }}"
    pressure_template: "{{ state_attr('sensor.pirateweather_api_test', 'pressure') }}"
    wind_speed_template: "{{ state_attr('sensor.pirateweather_api_test', 'windSpeed') }}"
    ozone_template: "{{ state_attr('sensor.pirateweather_api_test', 'ozone') }}"
    visibility_template: "{{ state_attr('sensor.pirateweather_api_test', 'visibility') }}"
    forecast_template: "{{ state_attr('pirateweather_api_forcast', 'data') }}"

image

Which all pulls in correctly, other than forecast.

I have this working great for current weather conditions:

- platform: rest
  resource_template: !secret pirate_rest_resource
  name: pirateweather_api_test
  json_attributes_path: "$.currently"
  scan_interval: '00:15:00'
  json_attributes:
    - summary
    - temperature
    - precipProbability
    - precipType
    - humidity
    - cloudCover
    - nearestStormDistance
    - precipIntensity
    - windSpeed
    - visibility
    - ozone
    - windBearing
    - pressure
  value_template: 'OK'

image

I tried to combine the call using the below, but it didnt work for the forecast once again:

rest:
- scan_interval: 900
  resource_template: !secret pirate_rest_resource
  sensor:
    - name: "pirateweather_api_current"
      json_attributes_path: "$.currently"
      value_template: "OK"
      json_attributes:
        - summary
        - temperature
        - precipProbability
        - precipType
        - humidity
        - cloudCover
        - nearestStormDistance
        - precipIntensity
        - windSpeed
        - visibility
        - ozone
        - windBearing
        - pressure
    - name: "pirateweather_api_forcast"
      json_attributes_path: "$.daily"
      value_template: "OK"
      json_attributes:
        - data

image
image

@tdvantine
Copy link
Author

Any new info?

@alexander0042
Copy link
Collaborator

Thanks for following up here! I haven't quite gotten the update integration working yet, but it's at the top of my list and shouldn't be too much longer. If you want to follow along with the progress, I've made a new branch that will eventually get merged in with the changes. It's super unstable at the moment, but gives an idea of how everything will fit together with the config flow/ async setup, and should addressing the templateing issue at the same time!

@mikegoubeaux
Copy link

mikegoubeaux commented Feb 23, 2023

I'm also interested in dynamic location weather reports. I love Pirate Weather, but can't figure out if the config supports dynamically updating location. I have a gps sensor updating Home Assistant core location and a device tracker available for use but it seems Pirate Weather location config is static and can only be updated manually. Is there a method for dynamically updating Pirate Weather location?

@elykrk
Copy link

elykrk commented May 3, 2023

Same here would love to be able to do dynamic location updates! Thanks for your work on this.

@alexander0042
Copy link
Collaborator

As part of the fundamental setup of integration, I don't think possible to change the location dynamically. The issue is that it uses a weather data coordinator that is based on the lat-lon of the setup location, and it sticks with that.

However, some of the comments above get is to the same place! You can combine the "rest" platform with a weather template to produce the card manually. As a first pass, I have something like this:


weather:
  - platform: template
    name: "Dynamic Weather"
    # attribution: "Powered by PirateWeather"
    condition_template: "{{ state_attr('sensor.PW_Template_Currently', 'summary') }}"
    temperature_template: "{{ state_attr('sensor.PW_Template_Currently', 'temperature') | float }}"
    humidity_template: "{{ state_attr('sensor.PW_Template_Currently', 'humidity') | float }}"
    pressure_template: "{{ state_attr('sensor.PW_Template_Currently', 'pressure') }}"
    wind_speed_template: "{{ state_attr('sensor.PW_Template_Currently', 'windSpeed') }}"
    ozone_template: "{{ state_attr('sensor.PW_Template_Currently', 'ozone') }}"
    visibility_template: "{{ state_attr('sensor.PW_Template_Currently', 'visibility') }}"
    forecast_template: >-
      [
        {
          {% set dat = now() + timedelta( days = 0 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily0', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily0', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily0', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily0', 'summary') }}",
        },
        {
          {% set dat = now() + timedelta( days = 1 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily1', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily1', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily1', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily1', 'summary') }}",          
        },
        {
          {% set dat = now() + timedelta( days = 2 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily2', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily2', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily2', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily2', 'summary') }}",          
        }
      ]

rest:
  resource: 'https://api.pirateweather.net/forecast/<PW_API_KEY>/45.4215,-75.697'
  scan_interval: 60
  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
    - name: "PW_Template_Daily0"
      json_attributes_path: "$.daily.data.[0]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow
        - precipAccumulation      
    - name: "PW_Template_Daily1"
      json_attributes_path: "$.daily.data.[1]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow
        - precipAccumulation 
    - name: "PW_Template_Daily2"
      json_attributes_path: "$.daily.data.[2]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow  
        - precipAccumulation      

I'll test this a bit more and see if I can't get the template into the location and flesh out the weather card a bit, but this absolutely should work! The only downside is that it makes we wonder if I should have just done this instead of building a whole integration...

@alexander0042
Copy link
Collaborator

alexander0042 commented May 16, 2023

Ok, got it! I feel like there must be a cleaner solution, but this works for now! I'll also add the example file to the repository in hopes that someone who knows more about templating can clean it up. The really nice thing about having this put together is that is provides a very flexible option for anyone that wants something specific, as it doesn't rely on any integration or specific Home Assistant features, building it up more or less from foundational data.

It's currently set up to create a weather card with current conditions and a 5 day forecast, following the location of a "person" entity. The key things to change are the , the person's name, integration name, and adjust the units depending on what you're looking for. Let me know if this works for you, since I'd love to interoperate any improvements.

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') | float }}"
    temperature_unit: "°C"
    humidity_template: "{{ state_attr('sensor.PW_Template_Currently', 'humidity')*100 | float }}"
    pressure_template: "{{ state_attr('sensor.PW_Template_Currently', 'pressure') }}"
    pressure_unit : "hPa"
    wind_speed_template: "{{ state_attr('sensor.PW_Template_Currently', 'windSpeed') }}"
    wind_speed_unit : "m/s"
    ozone_template: "{{ state_attr('sensor.PW_Template_Currently', 'ozone') }}" 
    visibility_template: "{{ state_attr('sensor.PW_Template_Currently', 'visibility') }}"
    visibility_unit : "km"
    precipitation_unit: "mm"
    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_template: >-
      [
        {
          {% set dat = now() + timedelta( days = 0 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily0', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily0', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily0', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily0', 'icon') }}",
          "wind_bearing": "{{ state_attr('sensor.PW_Template_Daily0', 'windBearing') | float }}",
          "wind_speed": "{{ state_attr('sensor.PW_Template_Daily0', 'windSpeed') | float }}",
          "condition": "{{ 'clear-night' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'clear-night') else 'sunny' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'clear-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'partly-cloudy-day') else 'cloudy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'cloudy') else 'fog' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'fog') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'partly-cloudy-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'partly-cloudy-night') else 'rainy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'rain') else 'snowy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'snow') else 'snowy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'sleet') else 'windy' if is_state_attr('sensor.PW_Template_Daily0', 'icon', 'wind')}}",
        },
        {
          {% set dat = now() + timedelta( days = 1 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily1', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily1', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily1', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily1', 'icon') }}",   
          "wind_bearing": "{{ state_attr('sensor.PW_Template_Daily1', 'windBearing') | float }}",
          "wind_speed": "{{ state_attr('sensor.PW_Template_Daily1', 'windSpeed') | float }}",         
          "condition": "{{ 'clear-night' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'clear-night') else 'sunny' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'clear-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'partly-cloudy-day') else 'cloudy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'cloudy') else 'fog' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'fog') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'partly-cloudy-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'partly-cloudy-night') else 'rainy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'rain') else 'snowy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'snow') else 'snowy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'sleet') else 'windy' if is_state_attr('sensor.PW_Template_Daily1', 'icon', 'wind')}}",
        },
        {
          {% set dat = now() + timedelta( days = 2 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily2', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily2', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily2', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily2', 'icon') }}",          
          "wind_bearing": "{{ state_attr('sensor.PW_Template_Daily2', 'windBearing') | float }}",
          "wind_speed": "{{ state_attr('sensor.PW_Template_Daily2', 'windSpeed') | float }}",      
          "condition": "{{ 'clear-night' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'clear-night') else 'sunny' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'clear-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'partly-cloudy-day') else 'cloudy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'cloudy') else 'fog' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'fog') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'partly-cloudy-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'partly-cloudy-night') else 'rainy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'rain') else 'snowy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'snow') else 'snowy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'sleet') else 'windy' if is_state_attr('sensor.PW_Template_Daily2', 'icon', 'wind')}}",
        },
        {
          {% set dat = now() + timedelta( days = 3 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily3', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily3', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily3', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily3', 'icon') }}",          
          "wind_bearing": "{{ state_attr('sensor.PW_Template_Daily3', 'windBearing') | float }}",
          "wind_speed": "{{ state_attr('sensor.PW_Template_Daily3', 'windSpeed') | float }}",
          "condition": "{{ 'clear-night' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'clear-night') else 'sunny' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'clear-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'partly-cloudy-day') else 'cloudy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'cloudy') else 'fog' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'fog') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'partly-cloudy-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'partly-cloudy-night') else 'rainy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'rain') else 'snowy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'snow') else 'snowy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'sleet') else 'windy' if is_state_attr('sensor.PW_Template_Daily3', 'icon', 'wind')}}",
        },
        {
          {% set dat = now() + timedelta( days = 4 ) %}
          "datetime": "{{ dat.strftime("%Y-%m-%dT00:00:00Z") }}",
          "temperature": "{{ state_attr('sensor.PW_Template_Daily4', 'temperatureHigh') | float }}",
          "templow": "{{ state_attr('sensor.PW_Template_Daily4', 'temperatureLow') | float }}",
          "precipitation": "{{ state_attr('sensor.PW_Template_Daily4', 'precipAccumulation') | float }}",
          "condition":  "{{ state_attr('sensor.PW_Template_Daily4', 'icon') }}",          
          "wind_bearing": "{{ state_attr('sensor.PW_Template_Daily4', 'windBearing') | float }}",
          "wind_speed": "{{ state_attr('sensor.PW_Template_Daily4', 'windSpeed') | float }}",   
          "condition": "{{ 'clear-night' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'clear-night') else 'sunny' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'clear-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'partly-cloudy-day') else 'cloudy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'cloudy') else 'fog' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'fog') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'partly-cloudy-day') else 'partlycloudy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'partly-cloudy-night') else 'rainy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'rain') else 'snowy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'snow') else 'snowy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'sleet') else 'windy' if is_state_attr('sensor.PW_Template_Daily4', 'icon', 'wind')}}",
        }
      ]

rest:
  resource_template: 'https://api.pirateweather.net/forecast/<APIKEY>/{{states.person.alexander.attributes.latitude}},{{states.person.alexander.attributes.longitude}}?units=si'
  scan_interval: 900
  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
    - name: "PW_Template_Daily0"
      json_attributes_path: "$.daily.data.[0]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow
        - precipAccumulation  
        - windBearing
        - windSpeed    
        - icon
    - name: "PW_Template_Daily1"
      json_attributes_path: "$.daily.data.[1]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow
        - precipAccumulation 
        - windBearing
        - windSpeed          
        - icon
    - name: "PW_Template_Daily2"
      json_attributes_path: "$.daily.data.[2]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow  
        - precipAccumulation  
        - windBearing
        - windSpeed
        - icon                 
    - name: "PW_Template_Daily3"
      json_attributes_path: "$.daily.data.[3]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow  
        - precipAccumulation  
        - windBearing
        - windSpeed   
        - icon          
    - name: "PW_Template_Daily4"
      json_attributes_path: "$.daily.data.[4]"
      value_template: "OK"
      json_attributes:
        - summary
        - temperatureHigh
        - temperatureLow  
        - precipAccumulation  
        - windBearing
        - windSpeed   
        - icon
             

image

@mikegoubeaux
Copy link

@alexander0042 that's a great solution! I just implemented this with the lat/lon from zone.home (which is updated by GPS sensor via an automation and homeassistant.set_location) for my Van implementation. So, the weather updates as we move from place to place!

Wondering if there is a sensible way to implement this for an hourly forcast for the next 24 hrs?

FWIW: I found I had to remove the "Z" from the forecast_template datetime string for the forecast to show the days correctly as I am (currently) UTC -7

Nice work!

@tdvantine
Copy link
Author

NWS had an update and saw this

...coordinates or you can get dynamic location alerts by configuring the integration to use a device_tracker entity from HA as long as that device tracker provides GPS coordinates.

Perhaps there is something that could help you out in getting a cleaner implementation
https://github.com/finity69x2/nws_alerts

@github-actions

This comment was marked as outdated.

@github-actions github-actions bot added the stale label Oct 2, 2023
@tdvantine
Copy link
Author

Is this something we are still looking to properly implement, or are we satisfied with the work arounds overall? Plus, will these still work with the HA changes needed for PirateWeather to continue working?

@cloneofghosts cloneofghosts added the documentation Improvements or additions to documentation label Jan 17, 2024
@breel007
Copy link

breel007 commented Mar 10, 2024

Thanks @alexander0042 for the starting point. I think I got it cleaned up quite a bit and got hourly working as well:

# 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') | int }}"
    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&extend=daily
  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

@mikegoubeaux
Copy link

@breel007 - any chance you can post using code blocks - like so

@breel007
Copy link

@mikegoubeaux good call, I think I fixed it.

@phurth
Copy link

phurth commented Apr 4, 2024

I'm not sure this works any longer since HA has moved forecasts to be retrievable via the weather.get_forecast service. I think the original request on this issue would provide the best support for out of the box HA weather functionality in the frontend. Is it not possible implement the use of a template in place of the literal latitude and longitude if PirateWeather is set up via YAML (or even better during onboarding when setting up the integration via the UI)? If not a template, then at least a sensor like sensor.home_latitude?

@alexander0042
Copy link
Collaborator

I noticed your other post in #149, but figured it was easier to just reply here. I agree that it is a really irritating limitation, but as far as I've puzzled it out, The (very clever!) approach from @breel007 doesn't rely on the integration at all, so really should template correctly. Is there a specific aspect of it that isn't working for you?

As far as a more HA specific solution, I was poking through some other integrations and while I don't see any that change the location of a Data Update Coordinator, there is one where the scan interval is changed, so I don't know why it wouldn't be possible? This might be a good question for the discord, just to see if it's even possible. The logic of it would be easy enough- if someone defines a latitude and longitude, use that, otherwise use the GPS data.

@phurth
Copy link

phurth commented Apr 4, 2024

Can the direct web service solution work with a Lovelace card to display current conditions as well as forecast data? I was able to get it set up, and did get data into HA through the API, but was not able to get to forecast data in a weather card. Could be I did something wrong as the setup is not trivial.

@phurth
Copy link

phurth commented Apr 4, 2024

By the way - this is an awesome thing you've done with the API. Tons of data, and all well documented. Nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
Status: Todo
Development

No branches or pull requests

7 participants