Is there a CASE statement (or equivalent) when using templates?

Hi All,

I’m overengineering again!
What I want to do is convert my Weather Alerting system which provides its output as words … “Green”, “Yellow”, “Orange”, “Red”
I want to change this to a numeric value 0-3 or 1-4 so that I can use a gauge card to present this info.

Is there an equivalent of a CASE statement for templates … something like

CASE
  "Green"
     set alertvariable to 0
  "Yellow"
     set alertvariable to 1
  "Orange"
     set alertvariable to 2
  "Red"
     set alertvariable to 3
END CASE

Thanks in advance

2 Likes

Use a dictionary and get()

{% set d = {
  'Green': 0,
  'Yellow': 1,
  'Orange': 2,
  'Red': 3 } %}
{{ d.get( states('sensor.weather_alerting') ) }}
4 Likes

Thank you. That’s perfect!

Another alternative, using a list:

{{ ['Green', 'Yellow', 'Orange', 'Red'].index(states('sensor.weather_alerting')) }}

Note that this will raise an error if the sensor does not match one of the four colours, unlike the get() version which returns null.

Just to show that there are lots of ways of achieving the result, here are some options for trying out in the Template Editor, where c is your sensor, including a stupid code golf one. All four options cope with an offline sensor (unknown or unavailable) in differing ways:

{% set c = "Green" %}

# Drew's get() solution: returns None if offline
{{ {'Green': 0, 'Yellow': 1, 'Orange': 2, 'Red': 3}.get(c) }}

# List lookup: returns 4 or 5 if offline
{{ ['Green', 'Yellow', 'Orange', 'Red', 'unknown', 'unavailable'].index(c) }}

# String lookup of first character: returns 4 if offline
{{ 'GYORu'.index(c.0) }}

# Playing games with character codes: returns 1 if offline
{{ c.0|ord%14//4 }}
1 Like

If you eventually find yourself looking for the equivalent of ‘case else’, the get method allows for a default value.

For example, if ‘case else’ should report blue then do this:

{{ d.get(states('sensor.weather_alerting'), 'blue') }}

Reference: python dictionary get method

1 Like

Thank you!

Hello.
I decided to try to create a sensor based on this design, but it didn’t work out.

The sensor returns the geomagnetic storm level

{{ states("sensor.sweet_home_geomagnetic_field") }} 6

Create a template using the design above.

{% set geostorm = {
'No noticeable geomagnetic disturbances': 1,
'Small geomagnetic disturbances': 2,
'Weak geomagnetic storm': 3,
'Small geomagnetic storm': 4,
'Moderate geomagnetic storm': 5,
'Strong geomagnetic storm': 6,
'Strong geomagnetic storm': 7,
'Severe Geomagnetic Storm': 8 } -%}
{{ geostorm.get( states('sensor.sweet_home_geomagnetic_field') ) }}

and get - none sleepy:
Of course, you can use the standard method.

{% set geostorm=states('sensor.sweet_home_geomagnetic_field') %}
{% if (geostorm | int(0) == 1 ) %}
 No noticeable geomagnetic disturbances
{% elif(geostorm | int(0) == 2 ) %}
 Small geomagnetic disturbances
{% elif (geostorm | int(0) == 3 ) %}
 Weak geomagnetic storm
{% elif (geostorm | int(0) == 4 ) %}
 Minor geomagnetic storm
{% elif (geostorm | int(0) == 5 ) %}
 Moderate geomagnetic storm
{% elif (geostorm | int(0) == 6 ) %}
 Strong geomagnetic storm
{% elif (geostorm | int(0) == 7 ) %}
 Strong geomagnetic storm
{% elif (geostorm | int(0) == 8 ) %}
 Strong geomagnetic storm
{% else %}
 unknown
{% endif %}

But admit it, the first method looks more concise and elegant.
The question arises, what am I doing wrong?

you should really start a new thread (and refer to this one if you want)… instead of replying to a nearly year old thread.

the short answer is that you’re mixing key and value. the “get” looks for the key (left side) and returns the associated value (right side).

if that doesn’t give you want you need, please do start a new thread.

2 Likes

Yeah, this. The prior post was about looking up a description and returning a number; your requirement is the other way around.

So you want, for example:

'3': 'Weak geomagnetic storm',

Oops, I read the topic through Google Translator and the translation is not always correct.
I assumed that in Python array “key => values” it was my mistake. :pensive:

There is no need to open a new topic, now those who are looking for information will see an error. Thank you

Just going to add on to this thread for anyone else that came here from a Google search. You can actually have a “case-like” statement in a single template expression if you make use of Python’s ternary expression syntax.

For example, if you have a variable thing that’s set to Apple, and you run this template:

{{ 'A Banana' if 'banana' in (thing | lower) else
   'An Apple' if 'apple' in (thing | lower) else
   'An Orange' if 'orange' in (thing | lower) else
   'A Pear' if 'pear' in (thing | lower)
   else 'Not Sure' }}

You’ll get: An Apple

Watch out for case sensitivity. :smiling_imp:

And partial matches… If thing is set to Pineapple; you’ll get An Apple too.