Beginner's templating question

For reference: this is what I have in my sensors.yaml file:

# Day min and max temp
- platform: template
  sensors:
    day_max_temp:
      friendly_name: "Tagshöchsttemperatur"
      unit_of_measurement: "°C"
      entity_id: weather.openweathermap
      value_template: >
        {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
        {% set end = start + 86400000 %}
        {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>=', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | max }}

    day_min_temp:
      friendly_name: "Tagstiefsttemperatur"
      unit_of_measurement: "°C"
      entity_id: weather.openweathermap
      value_template: >
        {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
        {% set end = start + 86400000 %}
        {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>=', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | min }}
2 Likes

start from here and from there to Jinja website on templates.
you won’t be able to do everything that python allows (you need to use set var = val, no val += 1, variables’ scope is a block etc) but some python types (like strings, datetime) are there and you can use anything they offer. Think about Jinja as a filtering wrapper around python. HA add some functions/filters to it and makes accessible some data types. Here’s how.

Yesterday I started reading “Python Crash Course” by Eric Matthes. Great book! I’ll also continue reading on the Jinja website… :blush:

I have read with interest this thread. While I am impressed with the fantastic solutions that you were given, I thought “how easy it would be in nodered…”.
Have you tried?
If you don’t know python (like me), if you don’t know jinja2 (like me), and unless you want to learn (I don’t) then, I find that node-red make things so much easier than these cryptic (for me) templates.
Worse case scenario in nodered, you will have to write a few lines of javascript.
My 2 cents…
GV

I followed this thread to. Very interesting.

If it is so easy in node-red, why don’t you show us your solution?

Sounds interesting! No I have not tried so far. I don’t know Python/Jinja either, but I am quite interested in learning a bit. And I don’t use HASS.IO, so I think that it is not so easy to install NodeRed.

I am using something similar, but, I think more complex. I have defined for my wife and I, we usually cycle to work , what I call a bike comfort index. The idea is to show on lovelace something like this:
Screenshot.04-03-2020-19.40.17

The color of the bike is a combination of min temp, max temp, wind and rain. The values at the 4 corners are the minTemp / maxTemp / rain and max wind.

Getting the values from the weather API up to sending all the results to HA through API is done like this:

The complex part is the javascript in BikeSensorsMF:

minTemp = {}
maxTemp = {}
windGust = {}
maxRain = {}
confort = {}
var windGustmax = 0;
var Tmin = 50;
var Tmax = -30;
var Rain = 0;


for (var i=0; i<24;i++) {
  if (msg.payload.forecast[i].wind.speed > windGustmax) { 
        windGustmax = msg.payload.forecast[i].wind.speed;
    }
  if (msg.payload.forecast[i].wind.gust > windGustmax) { 
        windGustmax = msg.payload.forecast[i].wind.gust;
    } 
  if (msg.payload.forecast[i].T.value < Tmin ) {
        Tmin = msg.payload.forecast[i].T.value;
  }
  if (msg.payload.forecast[i].T.value > Tmax ) {
        Tmax = msg.payload.forecast[i].T.value;
  }  
  Rain += msg.payload.forecast[i].rain["1h"];
}
minTemp.value = Tmin;
maxTemp.value = Tmax;
windGust.value = (windGustmax * 3.6).toFixed(1);
maxRain.value = Rain.toFixed(1);

indice = 0
if ( minTemp.value < -5 ) indice = 6 + indice ;
else if ( minTemp.value < 0 ) indice = 4 + indice ;
else if ( minTemp.value < 5 ) indice = 2 + indice ;
else if ( minTemp.value < 10 ) indice = 1 + indice ;

if ( maxTemp.value > 40 ) indice = 6 + indice ;
else if ( maxTemp.value > 35 ) indice = 4 + indice ;
else if ( maxTemp.value > 30 ) indice = 2 + indice ;
else if ( maxTemp.value > 25 ) indice = 1 + indice ;

if ( windGust.value > 50 ) indice = 10 + indice ;
else if ( windGust.value > 40 ) indice = 6 + indice ;
else if ( windGust.value > 30 ) indice = 4 + indice ;
else if ( windGust.value > 20 ) indice = 1 + indice ;

if ( maxRain.value > 5 ) indice = 6 + indice ;
else if ( maxRain.value > 4 ) indice = 4 + indice ;
else if ( maxRain.value > 3 ) indice = 2 + indice ;
else if ( maxRain.value > 2 ) indice = 1 + indice ;

if ( indice >= 10 ) confort.value = 5;
else if ( indice >= 6 ) confort.value = 4;
else if ( indice >= 4 ) confort.value = 3;
else if ( indice >= 2 ) confort.value = 2;
else confort.value = 1;

return [ minTemp, maxTemp, windGust, maxRain, confort ];

I assume all of this is doable in templates. The problem (for me at least) is the debugging part of templates.
I know very little of javascript. And I was able to do this (crappy) code.

So, not perfect, but, I believe easier to code and to debug than templates. At least for me :slight_smile:

GV

Everyone thinks differently. Personally, I hate looking at flowcharts. Takes to long to read what’s going on, I’ll always stick to my templates.

2 Likes

…but the bike comfort index (sensor.bci) is a great idea… :heart_eyes: :heart_eyes: :heart_eyes:

I appreciate that. The absolute fantastic thing with HA is that you can choose what suits you :slight_smile:
I have migrated from another home automation system a bit more than one year ago. At first, I started with templates and it (almost) killed me!
I am reasonably good in IT but not a programmer at heart. HA + node-red is the right fit for me… For me. Not for everyone.
The title of the thread “Beginner’s templating question” reminded me of my failed attempts from last year.
GV

I’ve tried this, but keep on getting an error TypeError: ‘>=’ not supported between instances of ‘str’ and ‘int’

Looking at this it appears I need to convert the filter for datetime selectattr(‘datetime’, ‘>’, start) to an INT, but i have tried many combinations, but doesnt work. Any ideas?

That purely depends on what the datetime string represents.

The code im using:

 {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
        {% set end = start + 86400000 %}
        {{ state_attr('weather.kden_hourly', 'forecast') | selectattr('datetime', '>=', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | max }}

The data it is checking:

temperature: 2
humidity: 79
pressure: 1026
wind_bearing: 50
wind_speed: 5
visibility: 16
attribution: Data from National Weather Service/NOAA
forecast:
  - detailed_description: ''
    temperature: 4
    datetime: '2020-05-08T07:00:00-06:00'
    condition: cloudy
    precipitation_probability: 0
    wind_bearing: 247.5

I believe i need to change the selectattr so it is comparing and int to an int, but im struggling to find out how to convert it within that function.

Hi, I tried to get the max/min Results of some OpenWeatherMap-Forecasts like above described.
I want to know the max/min Temperature in the next 24 hours and the max Windspeed/Cloud Coverage/Rain also in the next 24h.

I used this code:

# Maximale und minimale Temperaturwerte aus Openweathermap
  - platform: template
    sensors:
      min_temp_next_24h:
        friendly_name: Minimale Temperatur in den naechsten 24h
        value_template: >-
          {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
          {% set end = start + 86400000 %}
          {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | min }}         
      max_temp_next_24h:
        friendly_name: Maximale Temperatur in den naechsten 24h
        value_template: >-    
          {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
          {% set end = start + 86400000 %}
          {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | max }}
      max_windspeed_next_24h:
        friendly_name: Maximale Windgeschwindigkeit in den naechsten 24h
        value_template: >-    
          {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
          {% set end = start + 86400000 %}
          {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='wind_speed') | list | max }}
      max_cloudcoverage_next_24h:
        friendly_name: Maximale Bewoelkung in den naechsten 24h
        value_template: >-    
          {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
          {% set end = start + 86400000 %}
          {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='cloud_coverage') | list | max }}
      max_raining_next_24h:
        friendly_name: Maximale Regenmenge in den naechsten 24h
        value_template: >-    
          {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
          {% set end = start + 86400000 %}
          {{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='rain') | list | max }}

But there must be an error in the code.
There is just a result for min and max temperature.
And the other sensors just show “unknown”. Maybe the name of the attribute is wrong. But i can’t find the right name.
Can someone help with the code?

Do those attributes exist in the forecast? Are those attributes numbers?

Well this unfortunately does not solve your problem, but in the long run it might be easier to ask the maintainer (who is it?) of the OWM platform to include directly within the platform’s code… :thinking:

PS: The OWM One Call API is being implemented (Convert OpenweatherMap Integration to use “one-call-api”). So just be patient… :slightly_smiling_face:

Hi,

referring to the generator

{{ state_attr('weather.openweathermap', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | max }}

how would the generator look like if the datetime comparison should take place by comparing with a datetime string?

The datetime which my forecasts deliver are strings of different formats depending on the weather provider, like this:

‘2020-10-10T07:00:00+00:00’
‘2020-10-10’

you won’t be able to use a generator. You’ll need a for loop and convert each string timestamp to a int timestamp.

Actually it is already in the needed format:

platform: template
  sensors:
    min_temp_next_24h_home:
      friendly_name: Min temperature in the next 24h at home
      value_template: >-
          {% set start = (now().replace(hour=0,minute=0,second=0)) %}
          {% set end = (start + timedelta(days=1)) %}
          {{ state_attr('weather.openweathermap_home', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | min }}
    max_temp_next_24h_home:
      friendly_name: Max temperature in the next 24h at home
      value_template: >-
          {% set start = (now().replace(hour=0,minute=0,second=0)) %}
          {% set end = (start + timedelta(days=1)) %}
          {{ state_attr('weather.openweathermap_home', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | max }}
    max_raining_next_24h_home:
      friendly_name: Max precipitation in the next 24h at home
      value_template: >-
          {% set start = (now().replace(hour=0,minute=0,second=0)) %}
          {% set end = (start + timedelta(days=1)) %}
          {{ state_attr('weather.openweathermap_home', 'forecast') | selectattr('datetime', '>', start) | selectattr('datetime','<=', end) | selectattr('precipitation','!=', None) | map(attribute='precipitation') | list |max }}

Dear all
According to this article I configured a sensor for today’s max temperature:

  - platform: template
    sensors:
      day_max_temp:
        friendly_name: "Max. Tagestemperatur"
        unit_of_measurement: "°C"
        entity_id: weather.home
        value_template: >
          {% set start = (now().replace(hour=0,minute=0,second=0).timestamp() * 1000) | int %}
          {% set end = start + 86400000 %}
          {{ state_attr('weather.home', 'forecast') | selectattr('datetime', '>=', start) | selectattr('datetime','<=', end) | map(attribute='temperature') | list | max }}
  

Since a couple of weeks/months there occures an error. When I try to validate the code in the developer tools - template register I get the following output:

TypeError: '>=' not supported between instances of 'str' and 'int'

What might be the problem? How can I fix this string? Is this error related to the updates on homeassistant?