Help NEEDED with value_template & dynamic icons

Hi there,

I am fairly new to Home Assistant, and I need help with better yaml code for my template sensor. This is my first post, so if it not according to standards, please let me know

I’ve got a water tank for which I custom built a proximity sensor to measure the height of the water from the top. This works perfect, and I am getting back the information via a Wemos D1 loaded with Tasmota and MQTT. Everything works fine, but I want to streamline my coding, and I want to customise my icons depending on the tank water level percentage from empty, i.e how full is the tank!

Can someone assist me in streamlining my coding for the percentage level calculation as in my sensor value_template?

I also then want to have a more dynamic icon linked to that percentage. Something that displays similarly to a battery level with various level of charge.

my sensors platform code:

################################################################
#
# Home Assistant  - Tank Level Controller with Temp & Humidity
#
# Tank Info:
#   Tank Total Height = 180cm (Bottom to Sensor Mount Height)
#   Sensor level from Top of Tank to Overflow level = 20cm
#   Outlet Pipe above Bottom = 10cm
#   Usable Water Level Distance = 140cm (Outlet Pipe to Overflow)
#
################################################################
- platform: template
  sensors:
    water_level:
      value_template: >-
        {% set water_level = states.sensor.water_tank_level.state %}
        {% if water_level | float >180 %}Fault
        {% elif water_level | float <=20.9 %}100%
        {% elif 21 <= water_level | float <=37.9 %}90%
        {% elif 38 <= water_level | float <=54.9 %}80%
        {% elif 55 <= water_level | float <=71.9 %}70%
        {% elif 72 <= water_level | float <=88.9 %}60%
        {% elif 89 <= water_level | float <=105.9 %}50%
        {% elif 106 <= water_level | float <=122.9 %}40%
        {% elif 123 <= water_level | float <=139.9 %}30%
        {% elif 140 <= water_level | float <=156.9 %}20%
        {% elif 157 <= water_level | float <=173.9 %}10%
        {%- endif %}       

My view within Home Assistant
image

Any assistance would be greatly appreciated

You’ve actually got it pretty streamlined. Your only option to streamline it more is to make an equation.

So, with that being said, it appears your step size is 17. Anything below 21 is 100%, and everything above 174 is 0%.

We will end up with this.

{% set water_level = states('sensor.water_tank_level') | float %}
{% if water_level < 21 %}100%
{% elif 21 <= water_level < 174 %}
  {{ (9-((water_level -21)//17))*10 }}%
{% if 174 <= water_level <= 180 %}0%
{% else %}Fault
{% endif %}

This is what I used to test the template in the template editor:

{%- for i in range(191) %}
{% if i< 21 %}{{ i }} -> 100%
{%- elif 21 <= i< 174 %}
  {{- i }} -> {{ (9-((i-21)//17))*10 }}%
{%- else %}{{ i }} -> 0%
{%- endif %}
{%- endfor %}

and this is the value output

water_level percent
0 100%
1 100%
2 100%
3 100%
4 100%
5 100%
6 100%
7 100%
8 100%
9 100%
10 100%
11 100%
12 100%
13 100%
14 100%
15 100%
16 100%
17 100%
18 100%
19 100%
20 100%
21 90%
22 90%
23 90%
24 90%
25 90%
26 90%
27 90%
28 90%
29 90%
30 90%
31 90%
32 90%
33 90%
34 90%
35 90%
36 90%
37 90%
38 80%
39 80%
40 80%
41 80%
42 80%
43 80%
44 80%
45 80%
46 80%
47 80%
48 80%
49 80%
50 80%
51 80%
52 80%
53 80%
54 80%
55 70%
56 70%
57 70%
58 70%
59 70%
60 70%
61 70%
62 70%
63 70%
64 70%
65 70%
66 70%
67 70%
68 70%
69 70%
70 70%
71 70%
72 60%
73 60%
74 60%
75 60%
76 60%
77 60%
78 60%
79 60%
80 60%
81 60%
82 60%
83 60%
84 60%
85 60%
86 60%
87 60%
88 60%
89 50%
90 50%
91 50%
92 50%
93 50%
94 50%
95 50%
96 50%
97 50%
98 50%
99 50%
100 50%
101 50%
102 50%
103 50%
104 50%
105 50%
106 40%
107 40%
108 40%
109 40%
110 40%
111 40%
112 40%
113 40%
114 40%
115 40%
116 40%
117 40%
118 40%
119 40%
120 40%
121 40%
122 40%
123 30%
124 30%
125 30%
126 30%
127 30%
128 30%
129 30%
130 30%
131 30%
132 30%
133 30%
134 30%
135 30%
136 30%
137 30%
138 30%
139 30%
140 20%
141 20%
142 20%
143 20%
144 20%
145 20%
146 20%
147 20%
148 20%
149 20%
150 20%
151 20%
152 20%
153 20%
154 20%
155 20%
156 20%
157 10%
158 10%
159 10%
160 10%
161 10%
162 10%
163 10%
164 10%
165 10%
166 10%
167 10%
168 10%
169 10%
170 10%
171 10%
172 10%
173 10%
174 0%
175 0%
176 0%
177 0%
178 0%
179 0%
180 0%
181 0%
182 0%
183 0%
184 0%
185 0%
186 0%
187 0%
188 0%
189 0%
190 0%
1 Like

If you want to graph this information, you’ll need to remove your % and the word fault and make it have a unit of measurement %. Or if you make it a device_class: battery, it will auto make your icon into a battery symbol that separates on percentage. But it will look like a battery.

- platform: template
  sensors:
    water_level:
      unit_of_measurement: %
      value_template: >
        {% set water_level = states('sensor.water_tank_level') | float %}
        {% if water_level < 21 %}100
        {% elif 21 <= water_level < 174 %}
          {{ (9-((water_level -21)//17))*10 }}
        {% else %}0
        {% endif %}

This will appear as a line graph in your history section with a % as a unit.

You can even start to remove the int division if you want real numerical values:

- platform: template
  sensors:
    water_level:
      unit_of_measurement: %
      value_template: >
        {% set water_level = states('sensor.water_tank_level') | float %}
        {% if water_level < 21 %}100.0
        {% elif 21 <= water_level < 174 %}
          {{ ((10-((water_level -21)/17))*10) round(1) }}
        {% else %}0
        {% endif %}
water_level percent
0 100.0
1 100.0
2 100.0
3 100.0
4 100.0
5 100.0
6 100.0
7 100.0
8 100.0
9 100.0
10 100.0
11 100.0
12 100.0
13 100.0
14 100.0
15 100.0
16 100.0
17 100.0
18 100.0
19 100.0
20 100.0
21 100.0
22 99.4
23 98.8
24 98.2
25 97.6
26 97.1
27 96.5
28 95.9
29 95.3
30 94.7
31 94.1
32 93.5
33 92.9
34 92.4
35 91.8
36 91.2
37 90.6
38 90.0
39 89.4
40 88.8
41 88.2
42 87.6
43 87.1
44 86.5
45 85.9
46 85.3
47 84.7
48 84.1
49 83.5
50 82.9
51 82.4
52 81.8
53 81.2
54 80.6
55 80.0
56 79.4
57 78.8
58 78.2
59 77.6
60 77.1
61 76.5
62 75.9
63 75.3
64 74.7
65 74.1
66 73.5
67 72.9
68 72.4
69 71.8
70 71.2
71 70.6
72 70.0
73 69.4
74 68.8
75 68.2
76 67.6
77 67.1
78 66.5
79 65.9
80 65.3
81 64.7
82 64.1
83 63.5
84 62.9
85 62.4
86 61.8
87 61.2
88 60.6
89 60.0
90 59.4
91 58.8
92 58.2
93 57.6
94 57.1
95 56.5
96 55.9
97 55.3
98 54.7
99 54.1
100 53.5
101 52.9
102 52.4
103 51.8
104 51.2
105 50.6
106 50.0
107 49.4
108 48.8
109 48.2
110 47.6
111 47.1
112 46.5
113 45.9
114 45.3
115 44.7
116 44.1
117 43.5
118 42.9
119 42.4
120 41.8
121 41.2
122 40.6
123 40.0
124 39.4
125 38.8
126 38.2
127 37.6
128 37.1
129 36.5
130 35.9
131 35.3
132 34.7
133 34.1
134 33.5
135 32.9
136 32.4
137 31.8
138 31.2
139 30.6
140 30.0
141 29.4
142 28.8
143 28.2
144 27.6
145 27.1
146 26.5
147 25.9
148 25.3
149 24.7
150 24.1
151 23.5
152 22.9
153 22.4
154 21.8
155 21.2
156 20.6
157 20.0
158 19.4
159 18.8
160 18.2
161 17.6
162 17.1
163 16.5
164 15.9
165 15.3
166 14.7
167 14.1
168 13.5
169 12.9
170 12.4
171 11.8
172 11.2
173 10.6
174 10.0
175 9.4
176 8.8
177 8.2
178 7.6
179 7.1
180 0.0
181 0.0
182 0.0
183 0.0
184 0.0
185 0.0
186 0.0
187 0.0
188 0.0
189 0.0
190 0.0
1 Like

Petro,

Thanks a lot for this, and the detailed explanation and code. This is exactly what I needed, but I could not figure out how to code the equations to do this.

The first example are working 100%, but when I used the last version of your code, for the real numeric values, I got the following error:

First time:
(It looks like the issue is with unit_of_measurement: % - Line 15 in my code)
Configuration invalid

Error loading /config/configuration.yaml: while scanning for the next token found character '%' that cannot start any token in "/config/includes/sensors/water_level.yaml", line 15, column 28

Second time:
So I removed that line (commented it out) and now I get the following error:
Invalid config for [sensor.template]: invalid template (TemplateSyntaxError: expected token 'end of print statement', got 'round') for dictionary value @ data['sensors']['water_level']['value_template']. Got "{% set water_level = states('sensor.water_tank_level') | float %} {% if water_level &lt; 21 %}100 {% elif 21 &lt;= water_level &lt; 174 %}\n {{ ((10-((water_level -21)/17))*10) round(1) }}\n{% else %}0 {% endif %}". (See ?, line ?). Please check the docs at https://home-assistant.io/components/sensor.template/

Lastly, I see you refer to the Template Editor. Where do I get access to that?

Probably just need to put the percent symbol in quotes.

Also, heres the template editor

And lastly as for the template editor, I forgot the pipe before round()

- platform: template
  sensors:
    water_level:
      unit_of_measurement: '%'
      value_template: >
        {% set water_level = states('sensor.water_tank_level') | float %}
        {% if water_level < 21 %}100.0
        {% elif 21 <= water_level < 174 %}
          {{ ((10-((water_level -21)/17))*10) | round(1) }}
        {% else %}0
        {% endif %}
1 Like

Petro

Thanks for all the feedback. All your examples are now working 100%. Looking at everything I cannot believe how simple it was actually. And the quotes around the % sorted out that issue as well

I must make use of the template editor more. That will definitely make it easier in future

please allow me to jump in here, since Ive been following this solution, and noted it in my cookbook :wink:

I dont have the sensor.water_tank_level and still this happens:

30

How can this be?
Note that adding |int or |float to a non existent entity_id might makes that 0. So smaller than 21 in this case :wink:

I use that technique in cases of light brightness, (an Off light hasn’t got a brightness and with the |int you can still use templates and automations in the case) and it is really a hack to keep things going.

Because the equation inverts the value from the tank. 0 is 100% and 180 is 0%. You don’t have the sensor so it returns 0, i.e. 100%.

Yes I see that, but it only does when | int is added. Otherwise the template returns nothing.

Yes, that’s because int returns zero when it cannot parse test like ‘unknown’. Which is what is happening. ‘unknown’ is not a number, so it defaults your value to zero.

Cool. That’s what my original jump-in post suggested :wink:
All good, glad I completely understand :wink:

@Jackie.P
Could you please share your final code for this? I’m i no way a programmer but would like to have a sensor like this to monitor a holding tank. Which sensor did you use and does it hold up in the long run given that it’s high humidity?
Cheers, Marcus

Hi Magren

Everything is holding up fine. I’ve used a Wemos D1 mini and flashed it with Tasmota as I want all my devices to communicate with MQTT to HA, and I also like the Tasmota Web interface. I’ve not used the normal HC-SR04 ultrasonic sensor. I opted to go for the waterproof version (JSN SR04T) which basically looks the same as your park distance control sensor on your car bumper. Completely waterproof.

I’ve printed a small mounting holder for this and glued the sensor into this holder which then gets mounted right at the top in the middle of the tank at the highest level. So, the JSN-SR04T cannot measure a distance less than 20cm, but in my case that was no issue as the top of my tank where the sensor is mounted is just on about 20 cm above highest water level, so it worked out fine.

SO my WemosD1 is mounted in a box with the sensor attached with about 1.8meter of wire to the tank and have been working flawlessly for about 2 years now. The sensor is sometimes completely wet with condensation but still reports my levels 100% correctly

My final code:

############################################################
# Wemos D1 Sensor linked to HC-SR04 for Water Tank Level
#                 and DHT11 for Humidity & Temperature
############################################################
platform: mqtt
name: "Water_Tank_Level_From_Top"
state_topic: "tele/sonoffD1_1/SENSOR"
value_template: "{{ value_json.SR04.Distance }}"
unit_of_measurement: "cm"

################################################################
#
# Home Assistant  - Tank Level Controller with Temp & Humidity
#
# Tank Info:
#   Tank Total Height = 180cm (Bottom to Sensor Mount Height)
#   Sensor level from Top of Tank to Overflow level = 20cm
#   Outlet Pipe above Bottom = 10cm
#   Usable Water Level Distance = 140cm (Outlet Pipe to Overflow)
#
################################################################

platform: template
sensors:
  water_level_percentage:
    unit_of_measurement: '%'
    value_template: >-
      {% set water_level = states('sensor.water_tank_level_from_top') | float %}
      {% if water_level < 21 %}100.0
      {% elif 21 <= water_level < 174 %}
        {{ ((10-((water_level -21)/17))*10) | round(1) }}
      {% else %}0
      {% endif %}

Hope this helps but let me know if you need more info

Jackie

3 Likes