-
Notifications
You must be signed in to change notification settings - Fork 19
/
heating_control.yaml
928 lines (808 loc) · 34.3 KB
/
heating_control.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
blueprint:
name: Advanced Heating Control
author: panhans
description: "
## Core Features
- heating based on a scheduler, presence of persons and/or presence sensor
- window open / TRV off
- party mode
- guest mode (if nobody is home who activates heating automatically)
- winter mode: enable / disable the automation itself
- holiday mode: provide a 2nd holiday scheduler
- trv calibration by an external temperature sensor
- several tweaks for fixing your TRV issues
## New in version 3.0
- Guest Mode can be timer
- multiple windows / doors possible
- calibration only triggers when external sensor or current temperature of trv gets updated - not time based anymore
- adjustable calibration
- comfort temperature can be set in automation **or** by an input_number
- party mode overrides all other settings
- simplified and more functional presence detection
- presence detection only possible
- option to set climates off instead of minmum temperature
- several tweaks under the hood to prevent flooding zigbee mesh and reducing service calls
## Additional Information
**Version**: 3.0
**Help & FAQ**: [Advanced Heating Control](https://community.home-assistant.io/t/advanced-heating-control)
**Debug Configuration**: `blueprints.panhans.heatingcontrol: debug`
If you like my work and support feel free to support me.
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Q5Q3QEH52)
"
source_url: https://github.com/panhans/homeassistant/blob/main/blueprints/automation/panhans/heating_control.yaml
domain: automation
input:
input_trvs:
name: Thermostats / Valves
description: Thermostats to be controlled
selector:
entity:
filter:
- domain:
- climate
multiple: true
input_scheduler_regular:
name: Scheduler (optional)
description:
Scheduler that specifies when the comfort temperature can be set
(scheduler state on). Scheduler can be added in the helpers section in your
home assistant settings.
default:
selector:
entity:
filter:
- domain:
- schedule
multiple: false
input_temperature_minimum:
name: Minimum Temp
description:
If nobody is at home or the scheduler state is off, the minimum
temperature is set.
default: 19
selector:
number:
min: 12.0
max: 24.0
step: 0.5
mode: slider
unit_of_measurement: °C
input_temperature_comfort_static:
name: Comfort Temperature
description: Set a static comfort temperature.
default: 22
selector:
number:
min: 12.0
max: 30.0
step: 0.5
mode: slider
unit_of_measurement: °C
input_temperature_comfort:
name: Comfort temperature (optional)
description: If you want to set the comfort temperature in ui just provide an input number helper.
default:
selector:
entity:
filter:
- domain:
- input_number
multiple: false
input_persons:
name: Persons (optional)
description:
If a person is at home and the scheduler state is on, the comfort
temperature will be set.
default: []
selector:
entity:
filter:
- domain:
- person
multiple: true
input_mode_party:
name: Party mode (optional)
description: Overwrites winter mode and scheduler. If on, heating is activated.
default:
selector:
entity:
filter:
- domain:
- input_boolean
- binary_sensor
- timer
multiple: false
input_mode_guest:
name: Guest mode (optional)
description: Activates the scheduler and ignores if anybody is at home or not.
default:
selector:
entity:
filter:
- domain:
- input_boolean
- binary_sensor
- timer
multiple: false
input_windows:
name: Windows / Doors (optional)
description: If open during airing TRVs will set to off.
default: []
selector:
entity:
filter:
- domain:
- binary_sensor
multiple: true
input_windows_reaction_time:
name: Window / Door Reaction Time
description: Duration for which a window or door must be open/closed for the thermostats to close/open.
default: 10
selector:
number:
min: 0.0
max: 60.0
step: 1.0
mode: slider
unit_of_measurement: s
input_mode_winter:
name: Winter mode (optional)
description: If on scheduled heating is activated, otherwise TRVs stay off.
default:
selector:
entity:
filter:
- domain:
- input_boolean
- binary_sensor
multiple: false
input_scheduler_holiday:
name: Holiday scheduler (optional)
description: Scheduler for holidays
default:
selector:
entity:
filter:
- domain:
- schedule
multiple: false
input_mode_holiday:
name: Holiday mode (optional)
description: If on the defined holiday scheduler is active instead of the default one.
default:
selector:
entity:
filter:
- domain:
- input_boolean
- binary_sensor
multiple: false
input_presence_sensor:
name: Presence Sensor (optional)
description: If a presence sensor has been specified, heating is also carried out if the scheduler is off but presence has been detected. This presence sensor only has impact when no scheduler is defined or the active scheduler is off.
default:
selector:
entity:
filter:
- domain:
- binary_sensor
multiple: false
input_scheduler_presence:
name: Presence Sensor Scheduler (optional)
description: This optional scheduler specifies when heating is controlled by presence. If this is not specified, presence-based heating is always active.
default:
selector:
entity:
filter:
- domain:
- schedule
multiple: false
input_presence_reaction_off_time:
name: Presence Reaction Off Time
description:
Define how many minutes the presence sensor must be off so the
temperature turns to minimum.
default: 5
selector:
number:
min: 1
max: 30.0
step: 1.0
mode: slider
unit_of_measurement: min
input_presence_reaction_on_time:
name: Presence Reaction On Time
description: Define how many minutes the presence sensor must be on to turn on heating.
default: 5
selector:
number:
min: 1
max: 10.0
step: 1.0
mode: slider
unit_of_measurement: min
input_temperature_sensor:
name: External Temperatur Sensor (optional)
description: >
Temperature calibration for your TRVs. Following is supported:
* TRVs must porvide calibration number entity (entity_id must contain *calibration* or *offset*)
* TADO TRVs
default:
selector:
entity:
filter:
- domain:
- sensor
device_class:
- temperature
multiple: false
input_calibration_delta:
name: Calibration Delta
description: If the difference between TRV temperature and the external sensor temperature is greater or less than the calibration delta the TRV calibration will be triggered.
default: 0.5
selector:
number:
min: 0
max: 2
step: 0.1
mode: slider
unit_of_measurement: °C
input_force_max_temperature:
name: Force Max Temperature (optional)
description: Set the maximum temperature of all TRVs regardless of any other settings.
default:
selector:
entity:
filter:
- domain:
- input_boolean
multiple: false
input_off_instead_min:
name: Off Instead Of Minimum Temperature
description: If enabled your climates turn *off* instead of lower temperature when scheduler is off or no presence is detected.
default: false
selector:
boolean: {}
input_force_minimum_temperature:
name: Force Mimimum Temperature
description: Activate this option if you have problems with OFF mode. Instead of setting them to off all TRVs will be set to their individual minimum temperature.
default: false
selector:
boolean: {}
input_split_service_calls:
name: Split Service Calls
description: Mode and temperature are set in one service call. Some TRVs have problems by setting it this way. Activate this option to set mode and temperature in seperate service calls.
default: false
selector:
boolean: {}
input_service_call_delay:
name: Service Call Delay
description:
Some TRVs have problems with setting mode and temperature. You can try to increas the
delay between the service calls. This could fix your problems.
default: 2
selector:
number:
min: 1.0
max: 10.0
step: 1.0
mode: slider
unit_of_measurement: s
##################################################
############### T R I G G E R ####################
##################################################
trigger_variables:
# M O D E S
input_mode_winter: !input input_mode_winter
input_mode_party: !input input_mode_party
input_mode_guest: !input input_mode_guest
input_force_max_temperature: !input input_force_max_temperature
input_mode_holiday: !input input_mode_holiday
input_temperature_comfort: !input input_temperature_comfort
input_temperature_comfort_static: !input input_temperature_comfort_static
# S C H E D U L E R
input_scheduler_regular: !input input_scheduler_regular
input_scheduler_holiday: !input input_scheduler_holiday
input_scheduler_presence: !input input_scheduler_holiday
# A D D I T I O N A L S E T T I N G S
input_windows: !input input_windows
input_temperature_sensor: !input input_temperature_sensor
input_persons: !input input_persons
input_presence_sensor: !input input_presence_sensor
is_default_scheduler_configured: "{{ input_scheduler_regular != none }}"
is_mode_holiday_configured: "{{ input_scheduler_holiday != none and mode_holiday != none }}"
trigger:
# S Y S T E M T R I G G E R S
- platform: homeassistant
event: start
- platform: event
event_type: automation_reloaded
# T E M P E R A T U R E C H A N G E S
- platform: template
value_template: >
{% if input_temperature_comfort != none %}
{{ as_timestamp(now()) - as_timestamp(states.input_number[input_temperature_comfort.split('.')[1]].last_updated) >= 2 }}
{% else %}
{{ false }}
{% endif %}
# S C H E D U L E R O N / O F F
- platform: template
value_template: >
{% if is_default_scheduler_configured %}
{% set active_scheduler = iif(is_mode_holiday_configured and is_state(input_mode_holiday,'on'), input_scheduler_holiday, input_scheduler_regular) %}
{{ is_state(active_scheduler, 'on') }}
{% else %}
false
{% endif %}
- platform: template
value_template: >
{% if is_default_scheduler_configured %}
{% set active_scheduler = iif(is_mode_holiday_configured and is_state(input_mode_holiday,'on'), input_scheduler_holiday, input_scheduler_regular) %}
{{ is_state(active_scheduler, 'off') }}
{% else %}
false
{% endif %}
# P E R S O N P R E S E N C E
- platform: template
value_template: "{{ expand(input_persons) | selectattr('state', 'eq', 'home') | list | count > 0 }}"
for:
seconds: 2
- platform: template
value_template: "{{ expand(input_persons) | selectattr('state', 'eq', 'home') | list | count == 0 }}"
for:
seconds: 2
# W I N D O W O P E N
- platform: template
value_template: "{{ expand(input_windows) | selectattr('state', 'eq', 'on') | list | count > 0 }}"
for:
seconds: !input input_windows_reaction_time
- platform: template
value_template: "{{ expand(input_windows) | selectattr('state', 'eq', 'on') | list | count == 0 }}"
for:
seconds: !input input_windows_reaction_time
# M O D E - H O L I D A Y
- platform: template
value_template: "{{ is_mode_holiday_configured and is_state(input_mode_holiday, 'on') }}"
for:
seconds: 2
- platform: template
value_template: "{{ is_mode_holiday_configured and is_state(input_mode_holiday, 'off') }}"
for:
seconds: 2
# M O D E - W I N T E R
- platform: template
value_template: "{{ input_mode_winter != none and is_state(input_mode_winter, 'on') }}"
for:
seconds: 2
- platform: template
value_template: "{{ input_mode_winter != none and is_state(input_mode_winter, 'off') }}"
for:
seconds: 2
# M O D E - M A I N T A N A C E
- platform: template
value_template: "{{ input_force_max_temperature != none and is_state(input_force_max_temperature, 'on') }}"
for:
seconds: 2
- platform: template
value_template: "{{ input_force_max_temperature != none and is_state(input_force_max_temperature, 'off') }}"
for:
seconds: 2
# M O D E - P A R T Y
- platform: template
value_template: "{{ input_mode_party != none and states(input_mode_party) in ['on','active'] }}"
for:
seconds: 2
- platform: template
value_template: "{{ input_mode_party != none and states(input_mode_party) in ['off','idle','paused'] }}"
for:
seconds: 2
# M O D E - G U E S T
- platform: template
value_template: "{{ input_mode_guest != none and states(input_mode_guest) in ['on','active'] }}"
for:
seconds: 2
- platform: template
value_template: "{{ input_mode_guest != none and states(input_mode_guest) in ['off','idle','paused'] }}"
for:
seconds: 2
# P R E S E N C E S E N S O R
- platform: template
value_template: "{{ input_presence_sensor != none and is_state(input_presence_sensor, 'on') }}"
for:
minutes: !input input_presence_reaction_on_time
- platform: template
value_template: "{{ input_presence_sensor != none and is_state(input_presence_sensor, 'off') }}"
for:
minutes: !input input_presence_reaction_off_time
# P R E S E N C E S C H E D U L E R
- platform: template
value_template: "{{ input_scheduler_presence != none and is_state(input_scheduler_presence, 'on') }}"
for:
seconds: 2
- platform: template
value_template: "{{ input_scheduler_presence != none and is_state(input_scheduler_presence, 'off') }}"
for:
seconds: 2
# E X T E R N A L C A L I B R A T I O N S E N S O R
- platform: template
id: "calibration_sensor_temp"
value_template: >
{% if input_temperature_sensor != none %}
{{ as_timestamp(now()) - as_timestamp(states.sensor[input_temperature_sensor.split('.')[1]].last_updated) <= 30 }}
{% else %}
{{ false }}
{% endif %}
- platform: state
id: "calibration_trv_temp"
entity_id: !input input_trvs
attribute: current_temperature
for:
seconds: 2
##################################################
############### V A R I A B L E S ################
##################################################
variables:
# I N P U T S
input_trvs: !input input_trvs
input_force_minimum_temperature: !input input_force_minimum_temperature
input_temperature_comfort: !input input_temperature_comfort
input_temperature_comfort_static: !input input_temperature_comfort_static
input_temperature_minimum: !input input_temperature_minimum
input_scheduler_regular: !input input_scheduler_regular
input_scheduler_holiday: !input input_scheduler_holiday
input_scheduler_presence: !input input_scheduler_presence
input_windows: !input input_windows
input_mode_holiday: !input input_mode_holiday
input_mode_winter: !input input_mode_winter
input_mode_party: !input input_mode_party
input_mode_guest: !input input_mode_guest
input_force_max_temperature: !input input_force_max_temperature
input_persons: !input input_persons
input_presence_sensor: !input input_presence_sensor
input_presence_reaction_off_time: !input input_presence_reaction_off_time
input_presence_reaction_on_time: !input input_presence_reaction_on_time
input_temperature_sensor: !input input_temperature_sensor
input_split_service_calls: !input input_split_service_calls
input_calibration_delta: !input input_calibration_delta
input_off_instead_min: !input input_off_instead_min
# V A L V E G R O U P S
valves: "{{ expand(input_trvs) | map(attribute='entity_id') | list }}"
valves_off_mode: >
{% set climates_off = namespace(name=[]) %}
{% for climate in valves %}
{% if state_attr(climate,'hvac_modes') | regex_search('off', ignorecase=True) %}
{% set climates_off.name = climates_off.name + [climate] %}
{% endif %}
{% endfor %}
{{ climates_off.name }}
valves_without_off_mode: >
{% set climates_not_off = namespace(name=[]) %}
{% for climate in valves %}
{% if climate not in valves_off_mode %}
{% set climates_not_off.name = climates_not_off.name + [climate] %}
{% endif %}
{% endfor %}
{{ climates_not_off.name }}
valves_tado: |
{% set climates_tado = namespace(name=[]) %}
{% for climate in valves %}
{% if device_attr(climate,'manufacturer') | regex_search('tado', ignorecase=True)%}
{% set climates_tado.name = climates_tado.name + [climate] %}
{% endif %}
{% endfor %}
{{ climates_tado.name }}
##################################################
########### C O N D I T I O N S ##################
##################################################
condition:
- condition: or
conditions:
- condition: template
value_template: "{{ (trigger.id == 'calibration_sensor_temp' or trigger.id == 'calibration_trv_temp') and input_temperature_sensor != none }}"
- condition: template
value_template: "{{ trigger.id != 'calibration_sensor_temp' and trigger.id != 'calibration_trv_temp' }}"
##################################################
################## A C T I O N ###################
##################################################
action:
- variables:
# S T A T E S
state_mode_party: "{{ input_mode_party != none and states(input_mode_party) in ['on','active'] }}"
state_mode_guest: "{{ input_mode_guest != none and is_state(input_mode_guest, 'on') }}"
state_mode_winter: "{{ input_mode_winter == none or (input_mode_winter != none and is_state(input_mode_winter, 'on')) }}"
state_force_max_temperature: "{{ input_force_max_temperature != none and is_state(input_force_max_temperature, 'on') }}"
state_window: "{{ expand(input_windows) | selectattr('state', 'eq', 'on') | list | count > 0 }}"
state_presence_sensor: "{{ input_presence_sensor != none and is_state(input_presence_sensor, 'on') }}"
state_temperature_comfort: >
{% if input_temperature_comfort != none%}
{{ states(input_temperature_comfort) }}
{% else %}
{{ input_temperature_comfort_static }}
{% endif %}
state_mode_holiday: "{{ input_mode_holiday != none and is_state(input_mode_holiday, 'on') }}"
active_scheduler: "{{ iif(state_mode_holiday, input_scheduler_holiday, input_scheduler_regular) }}"
is_anybody_home: "{{ expand(input_persons) | selectattr('state', 'eq', 'home') | list | count > 0 or state_mode_guest }}"
is_mode_holiday_configured: "{{ input_scheduler_holiday != none and input_mode_holiday != none and is_state(input_mode_holiday, 'on') }}"
is_scheduler_on: "{{ active_scheduler != none and states(active_scheduler) == 'on' }}"
is_presence_sensor_defined: "{{ input_presence_sensor != none }}"
is_presence_scheduler_defined: "{{ input_scheduler_presence != none }}"
is_presence: >
{{
(is_presence_scheduler_defined == true and is_state(input_scheduler_presence,'on') and is_presence_sensor_defined == true and is_state(input_presence_sensor, 'on'))
or
(is_presence_scheduler_defined == false and is_presence_sensor_defined == true and is_state(input_presence_sensor, 'on'))
}}
# T R V - V A L U E S
set_comfort: >
{% if state_mode_party == true %}
{{ true }}
{% else %}
{% if (is_scheduler_on == true and is_anybody_home) %}
{{ true }}
{% else %}
{% if (is_presence == true) %}
{{ true }}
{% else %}
{{ false }}
{% endif %}
{% endif %}
{% endif %}
mode: >
{% if ((state_mode_winter == true or state_mode_party == true) and state_window == false) or state_force_max_temperature == true %}
{% if input_off_instead_min == true and set_comfort == false %}
off
{% else %}
heat
{% endif %}
{% else %}
off
{% endif %}
temperature: "{{ iif(set_comfort, state_temperature_comfort, input_temperature_minimum) }}"
trvs_temp_is_none: "{{ expand(input_trvs) | selectattr('attributes.temperature', 'defined') | selectattr('attributes.temperature', 'eq', none) | map(attribute='entity_id') | list }}"
trvs_temp_not_set: "{{ expand(input_trvs) | selectattr('attributes.temperature', 'defined') | rejectattr('attributes.temperature', 'eq', float(temperature)) | map(attribute='entity_id') | list }}"
trvs_mode_not_set: "{{ expand(input_trvs) | rejectattr('state', 'eq', mode) | map(attribute='entity_id') | list }}"
trvs_mode_and_temp_not_set: "{{ (((trvs_temp_not_set + trvs_temp_is_none) | reject('in', trvs_mode_not_set) | list) + trvs_mode_not_set) | list }}"
- service: system_log.write
data:
message: >
{{" \n "}}
- state_mode_party: {{ state_mode_party }} {{" \n "}}
- state_mode_guest: {{state_mode_guest }} {{" \n "}}
- state_mode_winter: {{ state_mode_winter }} {{" \n "}}
- state_force_max_temperature: {{ state_force_max_temperature }} {{" \n "}}
- state_window: {{ state_window }} {{" \n "}}
- state_presence_sensor: {{ state_presence_sensor }} {{" \n "}}
- state_temperature_comfort: {{ state_temperature_comfort }} {{" \n "}}
- state_mode_holiday: {{ state_mode_holiday }} {{" \n "}}
- mode: {{ mode }} {{" \n "}}
- active_scheduler: {{ active_scheduler }} {{" \n "}}
- is_anybody_home: {{ is_anybody_home }} {{" \n "}}
- is_mode_holiday_configured: {{ is_mode_holiday_configured }} {{" \n "}}
- is_scheduler_on: {{ is_scheduler_on }} {{" \n "}}
- is_presence_sensor_defined: {{ is_presence_sensor_defined }} {{" \n "}}
- is_presence_scheduler_defined: {{ is_presence_scheduler_defined }} {{" \n "}}
- is_presence: {{ is_presence }} {{" \n "}}
- temperature: {{ temperature }} {{" \n "}}
- valves: {{ valves }} {{" \n "}}
- valves_off_mode: {{ valves_off_mode }} {{" \n "}}
- valves_without_off_mode: {{ valves_without_off_mode }} {{" \n "}}
- valves_tado: {{ valves_tado }} {{" \n "}}
- trvs_temp_not_set: {{ trvs_temp_not_set }} {{" \n "}}
- trvs_mode_not_set: {{ trvs_mode_not_set }} {{" \n "}}
- trvs_mode_and_temp_not_set: {{ trvs_mode_and_temp_not_set }}
level: debug
logger: blueprints.panhans.heatingcontrol
# CALIBRATION
- if:
- condition: or
conditions:
- condition: trigger
id: "calibration_trv_temp"
- condition: trigger
id: "calibration_sensor_temp"
- condition: template
value_template: "{{ mode == 'heat' }}"
then:
- repeat:
count: "{{ valves | count | int }}"
sequence:
- variables:
current_valve: "{{ valves[repeat.index-1] }}"
calibration_entity: >
{% set entities = device_entities(device_id(current_valve)) %}
{% set calibration_entity_id = namespace(id=[]) %}
{% for s in entities %}
{% if (('calibration' in s) or ('offset' in s)) %}
{% set calibration_entity_id.id = s %}
{% endif %}
{% endfor %}
{{ iif (calibration_entity_id.id[0] is defined, calibration_entity_id.id, '') }}
- if:
- condition: template
value_template: "{{ calibration_entity != '' or current_valve in valves_tado }}"
then:
- variables:
offset_old: >
{% if calibration_entity != '' %}
{{ states(calibration_entity) }}
{% else %}
{{ state_attr(current_valve, 'offset_celsius') }}
{% endif %}
offset_new: >
{% set actual_sensor_temperature = states(input_temperature_sensor) | float(0) | round(1) %}
{% set local_temperature = state_attr(current_valve,'current_temperature') %}
{% if calibration_entity != '' %}
{% set current_calibration_value = states(calibration_entity) %}
{% set step = state_attr(calibration_entity,'step') %}
{% set actual_trv_temperature = (local_temperature | float(0) - current_calibration_value | float(0)) | round(1) %}
{% set new_calibration_value = actual_sensor_temperature - actual_trv_temperature %}
{% set min_calibration_value = state_attr(calibration_entity,'min') %}
{% set max_calibration_value = state_attr(calibration_entity,'max') %}
{% if(new_calibration_value > max_calibration_value) %}
{% set new_calibration_value = max_calibration_value %}
{% elif (new_calibration_value < min_calibration_value) %}
{% set new_calibration_value = min_calibration_value %}
{% endif %}
{{ (new_calibration_value | float(0) / step) | round(0) * step }}
{% else %}
{% set offset = float(actual_sensor_temperature) - float(local_temperature) %}
{% set calculated_offset = ( float(offset) + float(offset_old) ) | round(2) %}
{{ calculated_offset }}
{% endif %}
- service: system_log.write
data:
message: >
- is_tado_calibration: {{ calibration_entity == '' }} {{" \n "}}
- offset_old: {{ offset_old }} {{" \n "}}
- offset_new: {{ offset_new }}
level: debug
logger: blueprints.panhans.heatingcontrol
- if:
- condition: template
value_template: "{{ (float(offset_old) - float(offset_new)) | abs >= float(input_calibration_delta) }}"
then:
- if:
- condition: template
value_template: "{{ calibration_entity != '' }}"
# SET GENERIC OFFSET
then:
- service: number.set_value
data:
value: "{{ float(offset_new) }}"
target:
entity_id: "{{ calibration_entity }}"
# SET TADO OFFSET
else:
- service: tado.set_climate_temperature_offset
data:
offset: "{{ offset_new }}"
entity_id: "{{ current_valve }}"
- delay:
seconds: !input input_service_call_delay
# SET MODE & TEMPERRATURE
else:
- if:
- condition: template
value_template: "{{ mode == 'off' }}"
then:
# SET TEMPERATURE TO MINIMUM INSTEAD TO MODE OFF
- if:
- condition: template
value_template: "{{ input_force_minimum_temperature or valves_without_off_mode | count > 0 }}"
then:
- variables:
low_temp_valves: "{{ iif(input_force_minimum_temperature == true, valves, valves_without_off_mode) }}"
- repeat:
count: "{{ low_temp_valves | count | int }}"
sequence:
- variables:
current_valve: "{{ low_temp_valves[repeat.index-1] }}"
off_temperature: "{{ state_attr(current_valve,'input_temperature_minimum') }}"
temperature: "{{ state_attr(current_valve,'temperature') }}"
- if:
- condition: template
value_template: "{{ temperature != off_temperature }}"
then:
- service: climate.set_temperature
data:
entity_id: "{{ current_valve }}"
temperature: "{{ off_temperature | float }}"
- delay:
seconds: !input input_service_call_delay
# SET MODE TO OFF AND NOT MIN TEMP
else:
- if:
- condition: template
value_template: "{{ valves_off_mode | count > 0 }}"
- condition: template
value_template: "{{ input_force_minimum_temperature == false }}"
then:
if:
- condition: template
value_template: "{{ trvs_mode_not_set | count > 0 }}"
then:
- variables:
valves_to_turn_off: "{{ (valves_off_mode | select('in', trvs_mode_not_set) | list) }}"
- if:
- condition: template
value_template: "{{ input_split_service_calls == true }}"
then:
- repeat:
count: "{{ valves_to_turn_off | count | int }}"
sequence:
- variables:
current_valve: "{{ valves_to_turn_off[repeat.index-1] }}"
- service: climate.set_hvac_mode
target:
entity_id: "{{ current_valve }}"
data:
hvac_mode: "off"
- delay:
seconds: !input input_service_call_delay
else:
- service: climate.set_hvac_mode
target:
entity_id: "{{ (valves_off_mode | select('in', trvs_mode_not_set) | list)}}"
data:
hvac_mode: "off"
- delay:
seconds: !input input_service_call_delay
# IF NOT OFF -> HEAT
else:
- if:
- condition: template
value_template: "{{ state_force_max_temperature or input_split_service_calls }}"
# FORCE MAX TEMP
then:
- variables:
valves_to_be_set: "{{ iif(state_force_max_temperature, valves, trvs_mode_and_temp_not_set) }}"
- repeat:
count: "{{ valves_to_be_set | count | int }}"
sequence:
- variables:
current_valve: "{{ valves_to_be_set[repeat.index-1] }}"
new_temperature: "{{ iif(state_force_max_temperature,state_attr(current_valve,'max_temp'),temperature) }}"
- if:
- condition: template
value_template: "{{ states(current_valve) != mode }}"
then:
- service: climate.set_hvac_mode
target:
entity_id: "{{ current_valve }}"
data:
hvac_mode: "{{ mode }}"
- delay:
seconds: !input input_service_call_delay
- if:
- condition: template
value_template: "{{ state_attr(current_valve, 'temperature') != new_temperature }}"
then:
- service: climate.set_temperature
data:
entity_id: "{{ current_valve }}"
temperature: "{{ new_temperature | float }}"
- delay:
seconds: !input input_service_call_delay
else:
- if:
- condition: template
value_template: "{{ trvs_mode_not_set | count > 0 }}"
then:
- service: climate.set_hvac_mode
target:
entity_id: "{{ trvs_mode_not_set }}"
data:
hvac_mode: "{{ mode }}"
- delay:
seconds: !input input_service_call_delay
- if:
- condition: template
value_template: "{{ trvs_temp_not_set | count > 0 }}"
then:
- service: climate.set_temperature
data:
entity_id: "{{ trvs_temp_not_set }}"
temperature: "{{ temperature | float }}"
- delay:
seconds: !input input_service_call_delay
mode: queued