Snippet content copied to clipboard.
Are you sure to delete this snippet? No, don't delete
  1. {
  2. "trace": {
  3. "last_step": "condition/0/conditions/4",
  4. "run_id": "890613d36bab56185dbf043885c24b1a",
  5. "state": "stopped",
  6. "script_execution": "failed_conditions",
  7. "timestamp": {
  8. "start": "2025-04-17T10:56:58.025475+00:00",
  9. "finish": "2025-04-17T10:56:58.046853+00:00"
  10. },
  11. "domain": "automation",
  12. "item_id": "1739643486506",
  13. "trigger": "binary_sensor.turkontakt_esszimmer via template",
  14. "trace": {
  15. "trigger/19": [
  16. {
  17. "path": "trigger/19",
  18. "timestamp": "2025-04-17T10:56:58.045292+00:00",
  19. "changed_variables": {
  20. "this": {
  21. "entity_id": "automation.automatisierung_heizung_esszimmer",
  22. "state": "on",
  23. "attributes": {
  24. "id": "1739643486506",
  25. "last_triggered": "2025-04-17T10:54:55.289898+00:00",
  26. "mode": "queued",
  27. "current": 0,
  28. "max": 10,
  29. "friendly_name": "AUTOMATISIERUNG - Heizung Esszimmer"
  30. },
  31. "last_changed": "2025-04-17T10:54:01.185468+00:00",
  32. "last_reported": "2025-04-17T10:54:58.141392+00:00",
  33. "last_updated": "2025-04-17T10:54:58.141392+00:00",
  34. "context": {
  35. "id": "01JS1P6B8Z5CZZ59TD8JGSYAB6",
  36. "parent_id": "01JS1P5DZBRP4J05D68NBJSWY0",
  37. "user_id": null
  38. }
  39. },
  40. "trigger": {
  41. "platform": "template",
  42. "entity_id": "binary_sensor.turkontakt_esszimmer",
  43. "from_state": {
  44. "entity_id": "binary_sensor.turkontakt_esszimmer",
  45. "state": "on",
  46. "attributes": {
  47. "interface_id": "RaspberryMatic-HmIP-RF",
  48. "address": "0000DA499AD292:1",
  49. "model": "HMIP-SWDO",
  50. "parameter": "STATE",
  51. "function": null,
  52. "value_state": "valid",
  53. "device_class": "window",
  54. "friendly_name": "Türkontakt Esszimmer"
  55. },
  56. "last_changed": "2025-04-17T10:54:25.259293+00:00",
  57. "last_reported": "2025-04-17T10:54:25.259293+00:00",
  58. "last_updated": "2025-04-17T10:54:25.259293+00:00",
  59. "context": {
  60. "id": "01JS1P5DZBRP4J05D68NBJSWY0",
  61. "parent_id": null,
  62. "user_id": "efb6cf9cd2644b73b3e8338a28fb4e54"
  63. }
  64. },
  65. "to_state": {
  66. "entity_id": "binary_sensor.turkontakt_esszimmer",
  67. "state": "off",
  68. "attributes": {
  69. "interface_id": "RaspberryMatic-HmIP-RF",
  70. "address": "0000DA499AD292:1",
  71. "model": "HMIP-SWDO",
  72. "parameter": "STATE",
  73. "function": null,
  74. "value_state": "valid",
  75. "device_class": "window",
  76. "friendly_name": "Türkontakt Esszimmer"
  77. },
  78. "last_changed": "2025-04-17T10:56:28.021146+00:00",
  79. "last_reported": "2025-04-17T10:56:28.021146+00:00",
  80. "last_updated": "2025-04-17T10:56:28.021146+00:00",
  81. "context": {
  82. "id": "01JS1P95VNB9R4F7VHEQM89YYF",
  83. "parent_id": null,
  84. "user_id": "efb6cf9cd2644b73b3e8338a28fb4e54"
  85. }
  86. },
  87. "id": "temperature_change_window_off",
  88. "idx": "19",
  89. "alias": null,
  90. "for": {
  91. "__type": "<class 'datetime.timedelta'>",
  92. "total_seconds": 30
  93. },
  94. "description": "binary_sensor.turkontakt_esszimmer via template"
  95. },
  96. "input_trvs": [
  97. "climate.heizung_esszimmer"
  98. ],
  99. "input_temperature_sensor": [],
  100. "is_temperature_sensor_defined": false,
  101. "input_persons": [],
  102. "input_mode_guest": null,
  103. "input_people_entering_home_duration": {
  104. "hours": 0,
  105. "minutes": 0,
  106. "seconds": 2
  107. },
  108. "input_people_leaving_home_duration": {
  109. "hours": 0,
  110. "minutes": 0,
  111. "seconds": 2
  112. },
  113. "input_person_count": 0,
  114. "is_person_defined": false,
  115. "is_guest_mode_defined": false,
  116. "input_schedulers": [],
  117. "input_scheduler_selector": null,
  118. "input_scheduler_presence": null,
  119. "is_scheduler_presence_defined": false,
  120. "input_temperature_comfort": [],
  121. "input_temperature_eco": [],
  122. "input_hvac_mode": "heat",
  123. "factor": 1,
  124. "is_heat_only_if_below_real_temp": false,
  125. "input_mode_winter": null,
  126. "input_mode_outside_temperature": null,
  127. "input_mode_outside_temperature_threshold": 20,
  128. "input_mode_room_temperature_threshold": 18,
  129. "input_mode_room_temperature": false,
  130. "input_invert_winter_mode_value": false,
  131. "input_mode_party": [],
  132. "input_adjustments": "[]",
  133. "input_calibration_timeout": {
  134. "hours": 24,
  135. "minutes": 0,
  136. "seconds": 0
  137. },
  138. "input_windows": [
  139. "binary_sensor.status_fenster_esszimmer_wohnzimmer_kuche"
  140. ],
  141. "input_presence_sensor": null,
  142. "is_presence_sensor_defined": false,
  143. "input_presence_reaction_on_time": {
  144. "hours": 0,
  145. "minutes": 5,
  146. "seconds": 0
  147. },
  148. "input_presence_reaction_off_time": {
  149. "hours": 0,
  150. "minutes": 5,
  151. "seconds": 0
  152. },
  153. "input_proximity": null,
  154. "input_proximity_duration": {
  155. "hours": 0,
  156. "minutes": 2,
  157. "seconds": 0
  158. },
  159. "input_proximity_distance": 500,
  160. "input_frost_protection_duration": {
  161. "days": 0,
  162. "hours": 0,
  163. "minutes": 0,
  164. "seconds": 0
  165. },
  166. "input_liming_protection": false,
  167. "input_liming_protection_day": "Mon",
  168. "input_liming_protection_time": "12:00:00",
  169. "input_liming_in_winter": false,
  170. "input_liming_protection_duration": 1,
  171. "input_temperature_comfort_entity": null,
  172. "input_temperature_comfort_static": 22,
  173. "input_temperature_eco_entity": null,
  174. "input_temperature_eco_static": 19,
  175. "input_frost_protection_temp": 5,
  176. "input_windows_reaction_time_open": {
  177. "hours": 0,
  178. "minutes": 0,
  179. "seconds": 30
  180. },
  181. "input_windows_reaction_time_close": {
  182. "hours": 0,
  183. "minutes": 0,
  184. "seconds": 30
  185. },
  186. "input_window_open_temperature": 0,
  187. "input_party_legacy_restore": false,
  188. "input_window_legacy_restore": true,
  189. "is_legacy_restore": true,
  190. "input_force_max_temperature": [],
  191. "input_force_eco_temperature": [],
  192. "input_calibration_delta": 5,
  193. "input_calibration_generic": false,
  194. "input_calibration_step_size": "0.1",
  195. "input_calibration_key_word": "calibration",
  196. "input_generic_calibration_offset": 5,
  197. "input_aggressive_mode_offset": 0,
  198. "input_aggressive_mode_range": 0,
  199. "input_aggressive_mode_calibration": false,
  200. "input_away_offset": 0,
  201. "is_scheduler_away_mode": false,
  202. "is_presence_away_mode": false,
  203. "presence_ignor_people": false,
  204. "is_reset_temperature": false,
  205. "is_off_instead_min": false,
  206. "is_not_off_but_min": false,
  207. "is_fahrenheit": false,
  208. "is_physical_change_enabled": false,
  209. "is_off_if_nobody_home": false,
  210. "input_action_call_delay": {
  211. "hours": 0,
  212. "minutes": 0,
  213. "seconds": 2
  214. },
  215. "input_custom_action": null,
  216. "input_startup_delay": {
  217. "hours": 0,
  218. "minutes": 1,
  219. "seconds": 0
  220. },
  221. "input_fully_open_difference": 1,
  222. "input_valve_opening_keyword": "valve_opening_degree",
  223. "input_valve_positioning_step_size": "10",
  224. "input_valve_positioning_mode": "off",
  225. "input_valve_positioning_timeout": {
  226. "hours": 0,
  227. "minutes": 20,
  228. "seconds": 0
  229. },
  230. "input_valve_positioning_max_opening": 100,
  231. "invalid_states": [
  232. "unknown",
  233. "unavailable"
  234. ],
  235. "value_temperature_sensor": "unknown",
  236. "valid_temperature_sensor": false,
  237. "current_time_stamp": "2025-04-17 12:56:58.026987+02:00",
  238. "is_metric": true,
  239. "up_time_sensor": null,
  240. "is_uptime_defined": false,
  241. "uptime": "2025-04-17 12:56:58.026987+02:00",
  242. "startup_delay": null,
  243. "state_outside_temp": null,
  244. "state_ahc": true,
  245. "is_proximity_defined": false,
  246. "state_proximity_arrived": false,
  247. "state_proximity_way_home": false,
  248. "is_guest_mode": false,
  249. "is_anybody_home": false,
  250. "is_anybody_home_or_proximity": false,
  251. "active_scheduler": null,
  252. "is_scheduler_defined": false,
  253. "state_scheduler": false,
  254. "is_presence_scheduler_defined": false,
  255. "state_presence_scheduler": false,
  256. "state_presence_sensor": false,
  257. "state_presence": false,
  258. "is_force_max_temperature": false,
  259. "is_force_eco_temperature": false,
  260. "active_party_entity": null,
  261. "state_party": false,
  262. "party_temp": null,
  263. "is_away": false,
  264. "state_window": false,
  265. "is_aggressive_mode": false,
  266. "is_aggressive_mode_calibration": false,
  267. "is_frost_protection": false,
  268. "is_liming_protection": false,
  269. "valves": [
  270. "climate.heizung_esszimmer"
  271. ],
  272. "valves_unsupported": [],
  273. "valves_off_mode": [
  274. "climate.heizung_esszimmer"
  275. ],
  276. "valves_without_off_mode": [],
  277. "valves_tado": [],
  278. "valves_xiaomi_xiaomi": [],
  279. "valves_xiaomi_aqara": [],
  280. "valves_xiaomi": [],
  281. "valves_danfoss": [],
  282. "valves_popp": [],
  283. "valves_hive": [],
  284. "valves_dph": [],
  285. "valves_calibration_common": [
  286. "climate.heizung_esszimmer"
  287. ],
  288. "last_comfort_entity_change": null,
  289. "last_eco_entity_change": null,
  290. "latest_entry_today": null,
  291. "latest_entry_day_before": null,
  292. "entry": null,
  293. "entry_time": "",
  294. "entry_comfort_temp": null,
  295. "entry_eco_temp": null,
  296. "entry_calibration": true,
  297. "entry_mode": "auto",
  298. "trigger_id_defined": true,
  299. "is_calibration_trigger": false,
  300. "is_generic_calibration_trigger": false,
  301. "is_generic_calibration": false,
  302. "is_aggressive_mode_trigger": false,
  303. "is_change_trigger": false,
  304. "set_max_temperature": false,
  305. "is_pysical_change": false,
  306. "is_adjustment_trigger": false,
  307. "is_reset": false,
  308. "is_changes_trigger": true,
  309. "is_scene_create_trigger": false,
  310. "is_scene_apply_trigger": false,
  311. "is_scene_destroy_trigger": false,
  312. "scene_entities": [
  313. "climate.heizung_esszimmer"
  314. ],
  315. "scene_window_id": "scene.automatisierung_heizung_esszimmer_window",
  316. "scene_party_id": "scene.automatisierung_heizung_esszimmer_party",
  317. "scenes_all": [
  318. "scene.automatisierung_heizung_esszimmer_window",
  319. "scene.automatisierung_heizung_esszimmer_party"
  320. ],
  321. "scene_to_apply": null,
  322. "scenes_to_destroy": [],
  323. "scene_to_create": "scene.automatisierung_heizung_esszimmer_party",
  324. "set_comfort": false,
  325. "mode": "heat",
  326. "temperature_comfort_of_entity": null,
  327. "temperature_eco_of_entity": null,
  328. "temperature_comfort": 22,
  329. "temperature_away": 22,
  330. "temperature_eco": 19,
  331. "target_temperature": 19,
  332. "changes": {
  333. "climate.heizung_esszimmer": [
  334. {
  335. "mode": "heat",
  336. "temp": 19
  337. }
  338. ]
  339. },
  340. "positioning": [],
  341. "reset_data": [],
  342. "is_reset_trigger": false,
  343. "is_native_calibration": false,
  344. "is_native_calibration_trigger": false,
  345. "rounding_mode": "manual",
  346. "calibration_tado": {},
  347. "calibration_xiaomi": {},
  348. "calibration_dph": {},
  349. "calibration_common": {},
  350. "calibration_value_set": {},
  351. "no_changes": true,
  352. "scene_trigger": false,
  353. "change_trigger": false,
  354. "reset_trigger": false,
  355. "calibration_trigger": false,
  356. "positioning_trigger": false,
  357. "automation_name": "AUTOMATISIERUNG - Heizung Esszimmer",
  358. "warnings": [
  359. "To make Advance Heating Control work properly just setup the uptime integration (https://www.home-assistant.io/integrations/uptime/)"
  360. ],
  361. "climates_information": [
  362. {
  363. "entity_id": "climate.heizung_esszimmer",
  364. "state": "off",
  365. "temperature": 4.5,
  366. "current_temperature": 23.2
  367. }
  368. ]
  369. }
  370. }
  371. ],
  372. "condition/0": [
  373. {
  374. "path": "condition/0",
  375. "timestamp": "2025-04-17T10:56:58.045380+00:00",
  376. "result": {
  377. "result": false
  378. }
  379. }
  380. ],
  381. "condition/0/conditions/0": [
  382. {
  383. "path": "condition/0/conditions/0",
  384. "timestamp": "2025-04-17T10:56:58.045518+00:00",
  385. "result": {
  386. "result": false,
  387. "entities": []
  388. }
  389. }
  390. ],
  391. "condition/0/conditions/1": [
  392. {
  393. "path": "condition/0/conditions/1",
  394. "timestamp": "2025-04-17T10:56:58.045767+00:00",
  395. "result": {
  396. "result": false,
  397. "entities": []
  398. }
  399. }
  400. ],
  401. "condition/0/conditions/2": [
  402. {
  403. "path": "condition/0/conditions/2",
  404. "timestamp": "2025-04-17T10:56:58.046012+00:00",
  405. "result": {
  406. "result": false,
  407. "entities": []
  408. }
  409. }
  410. ],
  411. "condition/0/conditions/3": [
  412. {
  413. "path": "condition/0/conditions/3",
  414. "timestamp": "2025-04-17T10:56:58.046286+00:00",
  415. "result": {
  416. "result": false,
  417. "entities": []
  418. }
  419. }
  420. ],
  421. "condition/0/conditions/4": [
  422. {
  423. "path": "condition/0/conditions/4",
  424. "timestamp": "2025-04-17T10:56:58.046597+00:00",
  425. "result": {
  426. "result": false,
  427. "entities": []
  428. }
  429. }
  430. ]
  431. },
  432. "config": {
  433. "trigger_variables": {
  434. "input_trvs": [
  435. "climate.heizung_esszimmer"
  436. ],
  437. "input_temperature_sensor": [],
  438. "is_temperature_sensor_defined": "{{ input_temperature_sensor != [] }}",
  439. "input_persons": [],
  440. "input_mode_guest": null,
  441. "input_people_entering_home_duration": {
  442. "hours": 0,
  443. "minutes": 0,
  444. "seconds": 2
  445. },
  446. "input_people_leaving_home_duration": {
  447. "hours": 0,
  448. "minutes": 0,
  449. "seconds": 2
  450. },
  451. "input_person_count": "{{ input_persons | count }}",
  452. "is_person_defined": "{{ input_person_count > 0 }}",
  453. "is_guest_mode_defined": "{{ input_mode_guest != none }}",
  454. "input_schedulers": [],
  455. "input_scheduler_selector": null,
  456. "input_scheduler_presence": null,
  457. "is_scheduler_presence_defined": "{{ input_scheduler_presence != none }}",
  458. "input_temperature_comfort": [],
  459. "input_temperature_eco": [],
  460. "input_hvac_mode": "heat",
  461. "factor": "{{ iif(input_hvac_mode == 'cool', -1, 1) | int }}",
  462. "is_heat_only_if_below_real_temp": false,
  463. "input_mode_winter": null,
  464. "input_mode_outside_temperature": null,
  465. "input_mode_outside_temperature_threshold": 20,
  466. "input_mode_room_temperature_threshold": 18,
  467. "input_mode_room_temperature": false,
  468. "input_invert_winter_mode_value": false,
  469. "input_mode_party": [],
  470. "input_adjustments": "[]",
  471. "input_calibration_timeout": {
  472. "hours": 24,
  473. "minutes": 0,
  474. "seconds": 0
  475. },
  476. "input_windows": [
  477. "binary_sensor.status_fenster_esszimmer_wohnzimmer_kuche"
  478. ],
  479. "input_presence_sensor": null,
  480. "is_presence_sensor_defined": "{{ input_presence_sensor != none }}",
  481. "input_presence_reaction_on_time": {
  482. "hours": 0,
  483. "minutes": 5,
  484. "seconds": 0
  485. },
  486. "input_presence_reaction_off_time": {
  487. "hours": 0,
  488. "minutes": 5,
  489. "seconds": 0
  490. },
  491. "input_proximity": null,
  492. "input_proximity_duration": {
  493. "hours": 0,
  494. "minutes": 2,
  495. "seconds": 0
  496. },
  497. "input_proximity_distance": 500,
  498. "input_frost_protection_duration": {
  499. "days": 0,
  500. "hours": 0,
  501. "minutes": 0,
  502. "seconds": 0
  503. },
  504. "input_liming_protection": false,
  505. "input_liming_protection_day": "Mon",
  506. "input_liming_protection_time": "12:00:00",
  507. "input_liming_in_winter": false,
  508. "input_liming_protection_duration": 1
  509. },
  510. "variables": {
  511. "input_trvs": [
  512. "climate.heizung_esszimmer"
  513. ],
  514. "input_hvac_mode": "heat",
  515. "input_temperature_sensor": [],
  516. "input_temperature_comfort": [],
  517. "input_temperature_comfort_entity": "{{ iif(input_temperature_comfort == [], none, input_temperature_comfort) }}",
  518. "input_temperature_comfort_static": 22,
  519. "input_temperature_eco": [],
  520. "input_temperature_eco_entity": "{{ iif(input_temperature_eco == [], none, input_temperature_eco) }}",
  521. "input_temperature_eco_static": 19,
  522. "input_frost_protection_temp": 5,
  523. "input_frost_protection_duration": {
  524. "days": 0,
  525. "hours": 0,
  526. "minutes": 0,
  527. "seconds": 0
  528. },
  529. "input_liming_protection": false,
  530. "input_liming_protection_day": "Mon",
  531. "input_liming_protection_time": "12:00:00",
  532. "input_liming_in_winter": false,
  533. "input_liming_protection_duration": 1,
  534. "input_schedulers": [],
  535. "input_scheduler_selector": null,
  536. "input_presence_sensor": null,
  537. "input_scheduler_presence": null,
  538. "input_presence_reaction_off_time": {
  539. "hours": 0,
  540. "minutes": 5,
  541. "seconds": 0
  542. },
  543. "input_presence_reaction_on_time": {
  544. "hours": 0,
  545. "minutes": 5,
  546. "seconds": 0
  547. },
  548. "input_windows": [
  549. "binary_sensor.status_fenster_esszimmer_wohnzimmer_kuche"
  550. ],
  551. "input_windows_reaction_time_open": {
  552. "hours": 0,
  553. "minutes": 0,
  554. "seconds": 30
  555. },
  556. "input_windows_reaction_time_close": {
  557. "hours": 0,
  558. "minutes": 0,
  559. "seconds": 30
  560. },
  561. "input_window_open_temperature": 0,
  562. "input_party_legacy_restore": false,
  563. "input_window_legacy_restore": true,
  564. "is_legacy_restore": "{{ input_party_legacy_restore or input_window_legacy_restore }}",
  565. "input_mode_winter": null,
  566. "input_invert_winter_mode_value": false,
  567. "input_mode_outside_temperature": null,
  568. "input_mode_outside_temperature_threshold": 20,
  569. "input_mode_room_temperature": false,
  570. "input_mode_room_temperature_threshold": 18,
  571. "input_proximity": null,
  572. "input_persons": [],
  573. "input_mode_guest": null,
  574. "input_people_entering_home_duration": {
  575. "hours": 0,
  576. "minutes": 0,
  577. "seconds": 2
  578. },
  579. "input_people_leaving_home_duration": {
  580. "hours": 0,
  581. "minutes": 0,
  582. "seconds": 2
  583. },
  584. "input_mode_party": [],
  585. "input_force_max_temperature": [],
  586. "input_force_eco_temperature": [],
  587. "input_calibration_delta": 5,
  588. "input_calibration_generic": false,
  589. "input_calibration_step_size": "0.1",
  590. "input_calibration_key_word": "calibration",
  591. "input_generic_calibration_offset": 5,
  592. "input_aggressive_mode_offset": 0,
  593. "input_aggressive_mode_range": 0,
  594. "input_aggressive_mode_calibration": false,
  595. "input_away_offset": 0,
  596. "is_scheduler_away_mode": false,
  597. "is_presence_away_mode": false,
  598. "presence_ignor_people": false,
  599. "input_adjustments": "[]",
  600. "is_reset_temperature": false,
  601. "is_off_instead_min": false,
  602. "is_not_off_but_min": false,
  603. "is_fahrenheit": false,
  604. "is_heat_only_if_below_real_temp": false,
  605. "is_physical_change_enabled": false,
  606. "is_off_if_nobody_home": false,
  607. "input_action_call_delay": {
  608. "hours": 0,
  609. "minutes": 0,
  610. "seconds": 2
  611. },
  612. "input_custom_action": null,
  613. "input_startup_delay": {
  614. "hours": 0,
  615. "minutes": 1,
  616. "seconds": 0
  617. },
  618. "input_fully_open_difference": 1,
  619. "input_valve_opening_keyword": "valve_opening_degree",
  620. "input_valve_positioning_step_size": "10",
  621. "input_valve_positioning_mode": "off",
  622. "input_valve_positioning_timeout": {
  623. "hours": 0,
  624. "minutes": 20,
  625. "seconds": 0
  626. },
  627. "input_valve_positioning_max_opening": 100,
  628. "is_temperature_sensor_defined": "{{ input_temperature_sensor != [] }}",
  629. "invalid_states": "{{ ['unknown', 'unavailable'] }}\n",
  630. "value_temperature_sensor": "{% if is_temperature_sensor_defined %}\n {{ states(input_temperature_sensor) }}\n{% else %}\n {{ 'unknown' }}\n{% endif %}\n",
  631. "valid_temperature_sensor": "{{ value_temperature_sensor not in invalid_states }}\n",
  632. "factor": "{{ iif(input_hvac_mode == 'cool', -1, 1) | int }}",
  633. "current_time_stamp": "{{ now() }}",
  634. "is_metric": "{{ not is_temperature_sensor_defined or (is_temperature_sensor_defined and state_attr(input_temperature_sensor,VAR_UNIT_OF_MEASUREMENT) == '°C') }}",
  635. "up_time_sensor": "{{ integration_entities('uptime') | first | default(none) }}",
  636. "is_uptime_defined": "{{ up_time_sensor != none }}",
  637. "uptime": "{% if is_uptime_defined %}\n {{ states(up_time_sensor) | as_datetime }}\n{% else %}\n {{ current_time_stamp | as_datetime }}\n{% endif %}\n",
  638. "startup_delay": "{% set start_delay_seconds = timedelta(**input_startup_delay).total_seconds() %}\n{% if not is_uptime_defined or start_delay_seconds == 0 %}\n {{ none }}\n{% else %}\n {% set difference = (current_time_stamp | as_datetime - uptime | as_datetime).total_seconds() %}\n {% set real_start_delay = (start_delay_seconds - difference) %}\n\n {{ iif(real_start_delay > 0, real_start_delay, none) }}\n{% endif %}\n",
  639. "state_outside_temp": "{% if input_mode_outside_temperature == none %}\n {{ none }}\n{% else %}\n {% set outside_state = false %}\n {% set use_room_temp = input_mode_room_temperature and valid_temperature_sensor %}\n {% set room_state = iif(use_room_temp, false, true) %}\n\n {% set state = states(input_mode_outside_temperature) %}\n {% set state = iif(is_number(state) == true, state, state_attr(input_mode_outside_temperature,'temperature'))%}\n\n {% if is_number(state) %}\n {% set outside_state = (state | float - input_mode_outside_temperature_threshold | float) * factor < 0 %}\n {% endif %}\n\n {% if use_room_temp %}\n {% set state = states(input_temperature_sensor) %}\n\n {% if is_number(state) %}\n {% set room_state = (state | float - input_mode_room_temperature_threshold | float) * factor < 0 %}\n {% endif %}\n {% endif %}\n\n {{ room_state and outside_state }}\n{% endif %}\n",
  640. "state_ahc": "{% set result = true %} {% if input_mode_winter != none %}\n {% set activation_state = iif(input_invert_winter_mode_value, 'off', 'on') %}\n {% set result = is_state(input_mode_winter, activation_state) %}\n{% endif %}\n{{ iif(state_outside_temp == none, result, result and state_outside_temp) }}\n",
  641. "is_proximity_defined": "{{ input_proximity != none }}",
  642. "state_proximity_arrived": "{% set proximity_entities = device_entities(input_proximity) %} {% set is_arrived = proximity_entities \n | select('is_state','arrived') \n | expand \n | selectattr('attributes.device_class', 'eq', 'enum') \n | list | count > 0 %}\n{{ is_arrived }}\n",
  643. "state_proximity_way_home": "{% set proximity_entities = device_entities(input_proximity) %}\n{% set earliest_timestamp = current_time_stamp | as_datetime - timedelta(**input_proximity_duration) %} {% set uptime_duration = as_datetime(uptime) + timedelta(**input_proximity_duration) %}\n{% if uptime_duration > earliest_timestamp %}\n {% set earliest_timestamp = uptime_duration%}\n{% endif %}\n{% set entities_towards = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'enum') \n | selectattr('last_changed', '<=', earliest_timestamp)\n | map(attribute='entity_id') | select('is_state','towards')\n | map('regex_replace','_(?=[^_]*$)(.*)', '')\n | list %}\n\n{% set distances = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'distance')\n | map(attribute='state')\n | reject('eq', 'unknown')\n | map('int')\n | select('<=', input_proximity_distance | int)\n | map('string')\n | list %}\n\n{% set entities_distances = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'distance')\n | selectattr('state', 'in', distances)\n | map(attribute='entity_id')\n | map('regex_replace','_(?=[^_]*$)(.*)', '')\n | list %}\n\n{% set towards_and_in_distance = entities_towards | select('in', entities_distances) | list | count > 0 %}\n{{ towards_and_in_distance }}\n",
  644. "is_person_defined": "{{ input_persons | count > 0 or input_mode_guest != none }}",
  645. "is_guest_mode": "{{ input_mode_guest != none and is_state(input_mode_guest, 'on') }}",
  646. "is_anybody_home": "{% if is_guest_mode %}\n {{ true }}\n{% elif not is_person_defined %}\n {{ false }}\n{% else %}\n {% set on_time_delta = current_time_stamp | as_datetime - timedelta(**input_people_entering_home_duration) %}\n {% set off_time_delta = current_time_stamp | as_datetime - timedelta(**input_people_leaving_home_duration) %}\n\n {% set uptime_on = as_datetime(uptime) + timedelta(**input_people_entering_home_duration) %}\n {% set uptime_off = as_datetime(uptime) + timedelta(**input_people_leaving_home_duration) %}\n\n {% set result = false %}\n\n {% if uptime_on > on_time_delta or uptime_off > off_time_delta %}\n {{ input_persons | expand \n | selectattr('state', 'eq', 'home') \n | list \n | count > 0 }}\n {% else %}\n {% set persons_home = state_attr('zone.home','persons') | select('in', input_persons) | list %}\n\n {% set somebody_is_home = persons_home | expand\n | selectattr('last_changed', '<=', on_time_delta)\n | list\n | count > 0 %}\n\n {% set somebody_is_leaving = persons_home | count == 0 and ['zone.home'] | expand | map(attribute='last_changed') | first | default(off_time_delta) > off_time_delta %}\n\n {{ somebody_is_home or somebody_is_leaving }}\n {% endif %}\n{% endif %}\n",
  647. "is_anybody_home_or_proximity": "{{ is_anybody_home or state_proximity_way_home or state_proximity_arrived}}",
  648. "active_scheduler": "{% set selected_scheduler = none %} {% set schedules_count = input_schedulers | count %}\n{% if schedules_count == 0 %}\n {% set selected_scheduler = none %}\n{% elif schedules_count == 1 or input_scheduler_selector == none %}\n {% set selected_scheduler = input_schedulers | first %}\n{% elif schedules_count > 1 %}\n {% set selector_value = states(input_scheduler_selector) %}\n\n {% if is_number(selector_value) %}\n {% set selector_value = iif(selector_value | int > schedules_count, schedules_count, selector_value) %}\n {% set selector_value = iif(selector_value | int <= 0, 1, selector_value) %}\n {% set selected_scheduler = input_schedulers[selector_value | int - 1] %}\n {% elif selector_value in ['on','off'] %}\n {% set selected_scheduler = iif(selector_value == 'off', input_schedulers[0], input_schedulers[1]) %}\n {% else %}\n {% set selected_scheduler = input_schedulers | expand | selectattr('attributes.friendly_name', 'eq', selector_value) | map(attribute='entity_id') | first | default(none) %}\n {% if (selected_scheduler == none) %}\n {% set selected_scheduler = input_schedulers | expand | selectattr('attributes.friendly_name', 'search', '(?i)' + selector_value) | map(attribute='entity_id') | first | default(none) %}\n {% endif %}\n {% endif %}\n{% endif %}\n{{ selected_scheduler }}\n",
  649. "is_scheduler_defined": "{{ active_scheduler != none }}",
  650. "state_scheduler": "{{ active_scheduler != none and is_state(active_scheduler,'on') }}",
  651. "is_presence_sensor_defined": "{{ input_presence_sensor != none }}",
  652. "is_presence_scheduler_defined": "{{ input_scheduler_presence != none }}",
  653. "state_presence_scheduler": "{{ is_presence_scheduler_defined and is_state(input_scheduler_presence, 'on') }}",
  654. "state_presence_sensor": "{% if not is_presence_sensor_defined %}\n {{ false }}\n{% else %}\n {% set last_changed = [input_presence_sensor] | expand | map(attribute='last_changed') | first %}\n {% set sensor_state = is_state(input_presence_sensor, 'on') %}\n {% set reaction_time = iif(sensor_state, input_presence_reaction_on_time, input_presence_reaction_off_time) %}\n {% set min_timestamp = last_changed + timedelta(**reaction_time) %}\n {% set current_ts = current_time_stamp | as_datetime%}\n\n {% if is_uptime_defined and as_datetime(uptime) + timedelta(**reaction_time) > current_ts - timedelta(**reaction_time) %}\n {{ sensor_state }}\n {% else %}\n {% set is_limit = min_timestamp <= current_ts %}\n\n {{ (sensor_state == true and is_limit) or (sensor_state == false and not is_limit) }}\n {% endif %}\n{% endif %}\n",
  655. "state_presence": "{{ iif(is_presence_scheduler_defined, state_presence_scheduler and state_presence_sensor, state_presence_sensor) }}\n",
  656. "is_force_max_temperature": "{{ input_force_max_temperature != [] and is_state(input_force_max_temperature, 'on') }}",
  657. "is_force_eco_temperature": "{{ input_force_eco_temperature != [] and is_state(input_force_eco_temperature, 'on') }}",
  658. "active_party_entity": "{{ input_mode_party | expand | selectattr('state', 'in', ['active','on']) | map(attribute='entity_id') | first | default(none) }}",
  659. "state_party": "{{ active_party_entity != none }}",
  660. "party_temp": "{% set pos_party_temp = none %} {% if state_party == true %}\n {% set name = state_attr(active_party_entity,'friendly_name') %}\n {% set pos_temp = name.split(' ') | last %}\n {% if is_number(pos_temp) %}\n {% set pos_party_temp = pos_temp | float %}\n {% endif %}\n{% endif %} {{ pos_party_temp }}\n",
  661. "is_away": "{% if is_person_defined and not is_anybody_home_or_proximity %}\n {{ (is_scheduler_away_mode and state_scheduler) or (is_presence_away_mode and state_presence_scheduler and not state_presence) }}\n{% elif presence_ignor_people and is_presence_away_mode %}\n {{ state_presence_scheduler and not state_presence }}\n{% elif is_presence_away_mode and is_person_defined and is_anybody_home_or_proximity and not presence_ignor_people %}\n {{ not state_presence }}\n{% else %}\n {{ false }}\n{% endif %}\n",
  662. "state_window": "{% set current_ts = current_time_stamp | as_datetime %} {% set on_time_delta = current_ts - timedelta(**input_windows_reaction_time_open) %} {% set off_time_delta = current_ts - timedelta(**input_windows_reaction_time_close) %}\n{% set has_open_windows = input_windows \n | expand\n | selectattr('state', 'in', ['on','open','tilted'])\n | selectattr('last_changed', '<=', on_time_delta)\n | list\n | count > 0 %}\n\n{% set closed_but_not_in_duration = input_windows \n | expand\n | selectattr('state', 'in', ['off','closed'])\n | selectattr('last_changed', '>=', off_time_delta)\n | list\n | count > 0 %}\n\n{{ has_open_windows or closed_but_not_in_duration }}\n",
  663. "is_aggressive_mode": "{{ input_aggressive_mode_offset > 0 }}",
  664. "is_aggressive_mode_calibration": "{{ is_aggressive_mode and input_aggressive_mode_calibration and valid_temperature_sensor }}",
  665. "is_frost_protection": "{% set frost_protection_timestamp = as_datetime(current_time_stamp) - timedelta(**input_frost_protection_duration) %} {% if frost_protection_timestamp == as_datetime(current_time_stamp) %}\n {{ false }}\n{% else %}\n {% set relevant_entities = [input_presence_sensor] + [input_mode_guest] + input_persons %}\n {% set relevant_entities_count = relevant_entities | reject('eq',none) | list | count %}\n\n {% if relevant_entities_count > 0 %}\n\n {% set presence_count = [input_presence_sensor] \n | reject('eq',none)\n | reject('is_state','on')\n | expand \n | selectattr('last_changed', '<=', frost_protection_timestamp)\n | list | count %}\n\n {% set persons_count = input_persons\n | reject('eq',none)\n | reject('is_state','home')\n | expand\n | selectattr('last_changed', '<=', frost_protection_timestamp)\n | list | count %}\n\n {% set guest_mode_count = [input_mode_guest] \n | reject('eq',none)\n | reject('is_state','on')\n | expand \n | selectattr('last_changed', '<=', frost_protection_timestamp)\n | list | count %}\n\n {{ presence_count + guest_mode_count + persons_count == relevant_entities_count }}\n {% else %}\n {{ false }}\n {% endif %}\n{% endif %}\n",
  666. "is_liming_protection": "{% if not input_liming_protection%}\n {{ false }}\n{% else %}\n {% set enable_liming = true %}\n {% if input_mode_winter != none %}\n {% set enable_liming = is_state(input_mode_winter,'on') or input_liming_in_winter %}\n {% endif %}\n\n {% set current_timestamp = now() %}\n\n {% set is_liming_day = input_liming_protection_day == as_datetime(current_timestamp).strftime('%a') %}\n\n {% set start_hour = input_liming_protection_time.split(':')[0] | int %}\n {% set start_minute = input_liming_protection_time.split(':')[1] | int %}\n\n {% set today_start = as_datetime(current_timestamp).replace(second=0,microsecond=0,hour=start_hour,minute=start_minute) %}\n {% set today_end = as_datetime(current_timestamp).replace(second=0,microsecond=0,hour=start_hour,minute=start_minute) + timedelta(minutes=input_liming_protection_duration | int) %}\n\n {% set is_liming_time = as_datetime(current_timestamp) >= today_start and as_datetime(current_timestamp) <= today_end %}\n\n {{ enable_liming and is_liming_day and is_liming_time }}\n{% endif %}\n",
  667. "valves": "{{ input_trvs | expand\n | selectattr('attributes.hvac_modes','search','(?i)'+input_hvac_mode) \n | map(attribute='entity_id') \n | list }}\n",
  668. "valves_unsupported": "{{ input_trvs | reject('in',valves) | list }}\n",
  669. "valves_off_mode": "{{ valves | expand | selectattr('attributes.hvac_modes','search','(?i)off') \n | map(attribute='entity_id') \n | list }}\n",
  670. "valves_without_off_mode": "{{ valves | reject('in',valves_off_mode) | list }}\n",
  671. "valves_tado": "{{ valves | select('is_device_attr', 'manufacturer', 'Tado') | list }}",
  672. "valves_xiaomi_xiaomi": "{{ valves | select('is_device_attr', 'manufacturer', 'Xiaomi') | list }}",
  673. "valves_xiaomi_aqara": "{{ valves | select('is_device_attr', 'manufacturer', 'Aqara') | list }}",
  674. "valves_xiaomi": "{{ valves_xiaomi_xiaomi + valves_xiaomi_aqara }}",
  675. "valves_danfoss": "{{ valves | select('is_device_attr', 'manufacturer', 'Danfoss') | list }}",
  676. "valves_popp": "{{ valves | select('is_device_attr', 'manufacturer', 'Popp') | list }}",
  677. "valves_hive": "{{ valves | select('is_device_attr', 'manufacturer', 'Hive') | list }}",
  678. "valves_dph": "{{ valves_danfoss + valves_popp + valves_hive }}",
  679. "valves_calibration_common": "{{ valves | reject('in', valves_tado + valves_dph + valves_xiaomi) | list }}",
  680. "last_comfort_entity_change": "{{ [input_temperature_comfort_entity] | expand | map(attribute='last_changed') | list | first | default(none) }}",
  681. "last_eco_entity_change": "{{ [input_temperature_eco_entity] | expand | map(attribute='last_changed') | list | first | default(none) }}",
  682. "latest_entry_today": "{% set scheduler_name = none %} {% if active_scheduler != none %}\n {% set scheduler_name = state_attr(active_scheduler,'friendly_name') %}\n{% endif %}\n{% set current_ts = current_time_stamp | as_datetime %}\n{% set current_day = current_ts.strftime('%a') %} {% set current_time = current_ts.strftime('%H:%M') %}\n{% set plan = input_adjustments | rejectattr('time', 'undefined') \n | selectattr('time','<=', current_time| string)\n | list %}\n\n{% set selected_entries_days_and_schedule = plan | rejectattr('days','==',Undefined) | selectattr('days','search',current_day) \n | rejectattr('scheduler','==',Undefined) | selectattr('scheduler','in',scheduler_name) \n | list %}\n\n{% set selected_entries_days = plan | rejectattr('days','==',Undefined) | selectattr('days','search',current_day) \n | selectattr('scheduler','in',[Undefined])\n | list %}\n\n{% set selected_entries_schedule = plan | rejectattr('scheduler','==',Undefined) | selectattr('scheduler','in',scheduler_name) \n | selectattr('days','in',[Undefined])\n | list %}\n\n{% set selected_entries_time_only = plan | selectattr('days','in',[Undefined]) \n | selectattr('scheduler','in',[Undefined]) \n | list %}\n\n{% set selected_entries = selected_entries_days_and_schedule + selected_entries_days + selected_entries_schedule + selected_entries_time_only %}\n{% if selected_entries | count > 0%}\n {{ selected_entries | sort(attribute='time', reverse = true) | first }}\n{% else %}\n {{ none }}\n{% endif %}\n",
  683. "latest_entry_day_before": "{% set timestamp = as_datetime(current_time_stamp).replace(hour=23,minute=59) + timedelta(days=-1) %}\n{% set scheduler_name = none %} {% if active_scheduler != none %}\n {% set scheduler_name = state_attr(active_scheduler,'friendly_name') %}\n{% endif %}\n{% set current_day = timestamp.strftime('%a') %} {% set current_time = timestamp.strftime('%H:%M') %}\n{% set plan = input_adjustments | rejectattr('time', 'undefined') \n | selectattr('time','<=', current_time| string)\n | list %}\n\n{% set selected_entries_days_and_schedule = plan | rejectattr('days','==',Undefined) | selectattr('days','search',current_day) \n | rejectattr('scheduler','==',Undefined) | selectattr('scheduler','in',scheduler_name) \n | list %}\n\n{% set selected_entries_days = plan | rejectattr('days','==',Undefined) | selectattr('days','search',current_day) \n | selectattr('scheduler','in',[Undefined])\n | list %}\n\n{% set selected_entries_schedule = plan | rejectattr('scheduler','==',Undefined) | selectattr('scheduler','in',scheduler_name) \n | selectattr('days','in',[Undefined])\n | list %}\n\n{% set selected_entries_time_only = plan | selectattr('days','in',[Undefined]) \n | selectattr('scheduler','in',[Undefined]) \n | list %}\n\n{% set selected_entries = selected_entries_days_and_schedule + selected_entries_days + selected_entries_schedule + selected_entries_time_only %}\n{% if selected_entries | count > 0%}\n {{ selected_entries | sort(attribute='time', reverse = true) | first }}\n{% else %}\n {{ none }}\n{% endif %}\n",
  684. "entry": "{{ iif(latest_entry_today != none, latest_entry_today, latest_entry_day_before) }}",
  685. "entry_time": "{% if entry != none %}\n {% set entry_hour = entry['time'].split(':')[0] | int %}\n {% set entry_minute = entry['time'].split(':')[1] | int %}\n {{ as_datetime(current_time_stamp).replace(hour=entry_hour, minute=entry_minute, second=0, microsecond=0) + timedelta(days=iif(latest_entry_today == none,-1,0)) }}\n{% endif %}\n",
  686. "entry_comfort_temp": "{% if entry != none and 'comfort' in entry.keys() and (last_comfort_entity_change == none or as_datetime(entry_time) > as_datetime(last_comfort_entity_change)) %}\n {% set entry_temp = entry['comfort']%} \n {% if is_number(entry_temp) %}\n {{ entry_temp }}\n {% elif states[entry_temp] != none %}\n {{ states(entry_temp) }}\n {% endif %}\n{% else %}\n {{ none }}\n{% endif %}\n",
  687. "entry_eco_temp": "{% if entry != none and 'eco' in entry.keys() and (last_eco_entity_change == none or as_datetime(entry_time) > as_datetime(last_eco_entity_change)) %}\n {% set entry_temp = entry['eco']%} \n {% if is_number(entry_temp) %}\n {{ entry_temp }}\n {% elif states[entry_temp] != none %}\n {{ states(entry_temp) }}\n {% endif %}\n{% else %}\n {{ none }}\n{% endif %}\n",
  688. "entry_calibration": "{% if entry != none and 'calibration' in entry.keys() %}\n {{ entry['calibration'] == 'on' }}\n{% else %}\n {{ true }}\n{% endif %}\n",
  689. "entry_mode": "{% if entry != none and 'mode' in entry.keys() %}\n {{ entry['mode'] }}\n{% else %}\n {{ 'auto' }}\n{% endif %}\n",
  690. "trigger_id_defined": "{{ trigger.id is defined }}",
  691. "is_calibration_trigger": "{% if valves_dph | count > 0 and trigger_id_defined and trigger.id in ['calibration_popp_ping','calibration_popp_change'] %}\n {{ true }}\n{% elif is_aggressive_mode_calibration and trigger_id_defined and 'aggressive_mode' in trigger.id %}\n {{ true }}\n{% else %}\n {{ trigger_id_defined and 'calibration' in trigger.id and not trigger.id == 'calibration_aggressive_mode_thermostat_temp_change' }}\n{% endif %}\n",
  692. "is_generic_calibration_trigger": "{{ is_calibration_trigger and input_calibration_generic }}",
  693. "is_generic_calibration": "{{ is_generic_calibration_trigger and entry_calibration and valid_temperature_sensor }}",
  694. "is_aggressive_mode_trigger": "{{ is_aggressive_mode and trigger_id_defined and 'aggressive_mode' in trigger.id }}",
  695. "is_change_trigger": "{{ trigger_id_defined and \n 'temperature_change' in trigger.id and \n ('presence' in trigger.id or \n 'scheduler' in trigger.id or \n 'proximity' in trigger.id or \n 'person' in trigger.id or\n '_ds' in trigger.id)\n and not trigger.id == 'temperature_change_valve_target' }}\n",
  696. "set_max_temperature": "{{ is_force_max_temperature or is_liming_protection }}",
  697. "is_pysical_change": "{{ trigger_id_defined \n and trigger.id == 'temperature_change_valve_target' \n and is_physical_change_enabled\n and not state_window\n and not set_max_temperature\n and not is_away }}\n",
  698. "is_adjustment_trigger": "{{ trigger_id_defined and trigger.id == 'temperature_change_heating_adjustment' and (entry_comfort_temp != none or entry_eco_temp != none) }}",
  699. "is_reset": "{{ (is_reset_temperature and is_change_trigger) or \n is_pysical_change or is_adjustment_trigger }}\n",
  700. "is_changes_trigger": "{% if state_window %}\n {% if trigger_id_defined and 'temperature_change_window_on' in trigger.id %}\n {{ true }}\n {% elif trigger_id_defined and 'temperature_change_window_off' not in trigger.id %}\n {{ false }}\n {% endif %}\n{% elif trigger.platform == none %}\n {{ true }}\n{% elif trigger_id_defined and trigger.id == 'temperature_change_valve_target' %}\n {{ false }}\n{% elif is_heat_only_if_below_real_temp and trigger_id_defined and 'above_temp' in trigger.id %}\n {{ true }}\n{% elif is_aggressive_mode_calibration and is_aggressive_mode_trigger %}\n {{ false }}\n{% elif is_aggressive_mode_trigger %}\n {{ true }}\n{% elif is_generic_calibration %}\n {{ true }}\n{% else %}\n {{ trigger_id_defined and 'temperature_change' in trigger.id}}\n{% endif %}\n",
  701. "is_scene_create_trigger": "{{ trigger_id_defined and ((\"window_on\" in trigger.id and not state_party) or (\"party_on\" in trigger.id and not state_window)) }}\n",
  702. "is_scene_apply_trigger": "{{ trigger_id_defined and (\"window_off\" in trigger.id or \"party_off\" in trigger.id) and not is_legacy_restore and not (state_window or state_party) }}\n",
  703. "is_scene_destroy_trigger": "{{ (is_change_trigger or trigger.id == 'temperature_change_heating_adjustment') and (state_window or state_party) }}\n",
  704. "scene_entities": "{{ valves }}",
  705. "scene_window_id": "{{ 'scene.' + this.entity_id | replace('automation.','') | replace('.','_') + '_window' }}",
  706. "scene_party_id": "{{ 'scene.' + this.entity_id | replace('automation.','') | replace('.','_') + '_party' }}",
  707. "scenes_all": "{{ [scene_window_id, scene_party_id] }}",
  708. "scene_to_apply": "{% if is_scene_apply_trigger and \"window_off\" in trigger.id %}\n {{ scene_window_id }}\n{% elif is_scene_apply_trigger and \"party_off\" in trigger.id %}\n {{ scene_party_id }}\n{% else %}\n {{ none }}\n{% endif %}\n",
  709. "scenes_to_destroy": "{% set scenes = [] %} {% if is_scene_destroy_trigger %}\n {% set scenes = iif(state_window, scenes + [scene_window_id], scenes) %}\n {% set scenes = iif(state_party, scenes + [scene_party_id], scenes) %}\n{% endif %} {{ scenes }}\n",
  710. "scene_to_create": "{{ iif(is_scene_create_trigger and \"window_on\" in trigger.id, scene_window_id, scene_party_id) }}\n",
  711. "set_comfort": "{% if is_force_max_temperature %}\n {{ true }}\n{% elif entry_mode == 'eco' %}\n {{ false }}\n{% elif entry_mode == 'comfort' %}\n {{ true }}\n{% elif state_party %}\n {{ true }}\n{% elif is_force_eco_temperature %}\n {{ false }}\n{% elif is_away %}\n {{ true }}\n{% elif not is_scheduler_defined and not is_presence_sensor_defined %}\n {{ is_anybody_home_or_proximity }}\n{% else %}\n {% set comfort_state = state_scheduler or state_presence %}\n\n {% if is_person_defined or is_proximity_defined %}\n {{ is_anybody_home_or_proximity and comfort_state }}\n {% else %}\n {{ comfort_state }}\n {% endif %}\n{% endif %}\n",
  712. "mode": "{% if not state_ahc %}\n {{ 'off' }}\n{% elif state_window and input_window_open_temperature | int == 0 and not set_max_temperature %}\n {{ 'off' }}\n{% elif entry_mode == 'off' %}\n {{ 'off' }}\n{% elif is_off_instead_min and not set_comfort %} \n {{ 'off' }}\n{% elif is_off_if_nobody_home and is_person_defined and not is_anybody_home_or_proximity and not set_comfort %}\n {{ 'off' }}\n{% else %}\n {{ input_hvac_mode }}\n{% endif %}\n",
  713. "temperature_comfort_of_entity": "{% if(input_temperature_comfort_entity != none) %}\n {{ states(input_temperature_comfort_entity) | float }}\n{% else %}\n {{ none }}\n{% endif %}\n",
  714. "temperature_eco_of_entity": "{% if(input_temperature_eco_entity != none) %}\n {{ states(input_temperature_eco_entity) | float }}\n{% else %}\n {{ none }}\n{% endif %}\n",
  715. "temperature_comfort": "{{ [entry_comfort_temp, temperature_comfort_of_entity, input_temperature_comfort_static] | reject('==', none) | first }}",
  716. "temperature_away": "{{ temperature_comfort | float - input_away_offset }}",
  717. "temperature_eco": "{{ [entry_eco_temp, temperature_eco_of_entity, input_temperature_eco_static] | reject('==', none) | first }}",
  718. "target_temperature": "{% if state_window and input_window_open_temperature > 0 %}\n {{ input_window_open_temperature }}\n{% elif state_party %}\n {{ iif(party_temp != none, party_temp, temperature_comfort) }}\n{% elif is_frost_protection %}\n {{ input_frost_protection_temp }}\n{% else %}\n {{ iif(set_comfort, iif(is_away, temperature_away, temperature_comfort), temperature_eco) }}\n{% endif %}\n",
  719. "changes": "{% set n = namespace(dict=[]) %}\n{% set original_mode = mode %}\n{% if not is_changes_trigger %}\n {{ n.dict }}\n{% else %}\n {% for valve in input_trvs %}\n\n {% set current_valve_temp = state_attr(valve, 'current_temperature') | float(20) %}\n {% set current_valve_target_temp = state_attr(valve, 'temperature') | float(temperature) %}\n {% set current_valve_mode = states(valve) %}\n {% set min_temp = state_attr(valve, 'min_temp') | float(5) %}\n {% set max_temp = state_attr(valve, 'max_temp') | float(30) %}\n\n {% set valve_temp = target_temperature %}\n\n {% set dont_turn_off = \n valve in valves_without_off_mode or \n is_not_off_but_min or \n (state_window and input_window_open_temperature > 0) or\n set_max_temperature %}\n\n {% set ref_temp = current_valve_temp %}\n {% if valid_temperature_sensor %}\n {% set ref_temp = value_temperature_sensor | float(current_valve_temp) %}\n {% endif %}\n\n {% if is_heat_only_if_below_real_temp and iif(factor == 1, target_temperature <= ref_temp, target_temperature >= ref_temp) %}\n {% set mode = 'off' %}\n {% endif %}\n\n {% set valve_mode = iif(mode == 'off' and dont_turn_off, current_valve_mode, mode) %}\n\n {% if mode != 'off' %}\n\n {% if is_aggressive_mode and not is_aggressive_mode_calibration %}\n\n {% set temp_diff = valve_temp - ref_temp %}\n\n {% if temp_diff * factor < input_aggressive_mode_range * -1 %}\n {% set valve_temp = valve_temp - input_aggressive_mode_offset * factor %}\n {% elif temp_diff * factor > input_aggressive_mode_range %}\n {% set valve_temp = valve_temp + input_aggressive_mode_offset * factor %}\n {% endif %}\n\n {% endif %}\n\n {% if input_calibration_generic %}\n\n {% if current_valve_temp != ref_temp %}\n {% set offset = current_valve_temp - ref_temp %}\n\n {% set offset = iif(offset > float(input_generic_calibration_offset), input_generic_calibration_offset, offset) %}\n {% set offset = iif(offset < float(input_generic_calibration_offset) * -1, input_generic_calibration_offset * -1, offset) %}\n\n {% set temp_with_offset = float(valve_temp) + float(offset) %}\n {% set step = state_attr(valve, 'target_temp_step') | float(0.5) %}\n\n {% set temp_with_offset = (temp_with_offset | float(0) / float(step)) | round(0) * float(step) %}\n\n {% set valve_temp = iif(input_calibration_step_size == 'full', float(temp_with_offset) | round(), temp_with_offset | round(1)) %}\n\n {% endif %}\n {% endif %}\n\n {% endif %}\n\n {% if mode == 'off' and dont_turn_off %}\n {% set valve_temp = min_temp %}\n {% endif %}\n\n {% set valve_temp = iif(set_max_temperature, max_temp, valve_temp) %}\n {% set valve_temp = iif(valve_temp > max_temp, max_temp, valve_temp) %}\n {% set valve_temp = iif(valve_temp < min_temp, min_temp, valve_temp) %}\n\n {% if current_valve_mode != valve_mode or current_valve_target_temp != valve_temp %}\n {% set n.dict = n.dict + [(valve, [{'mode': valve_mode , 'temp': valve_temp}])] %}\n {% endif %}\n\n {% endfor %}\n\n {% set mode = original_mode %}\n\n {{ dict.from_keys(n.dict) }}\n{% endif %}\n",
  720. "positioning": "{% set n = namespace(dict=[]) %}\n{% if input_valve_positioning_mode == 'off' %}\n {{ n.dict }}\n{% else %}\n {% for valve in input_trvs %}\n\n {% set current_temp = state_attr(valve, 'current_temperature') | float(none) %}\n {% if valid_temperature_sensor %}\n {% set current_temp = value_temperature_sensor | float(none) %}\n {% endif %}\n\n {% set target_temp = state_attr(valve, 'temperature') | float(none) %}\n\n {% set open_valve_entity = device_entities(device_id(valve)) | expand \n | selectattr('domain','in','number') \n | selectattr('entity_id', 'search', input_valve_opening_keyword)\n | map(attribute='entity_id') \n | list | first | default(none) %}\n\n {% if open_valve_entity != none and current_temp != none and target_temp != none and\n (\n (trigger_id_defined and trigger.id == 'positioning_event') or \n ([open_valve_entity] | expand | map(attribute='last_changed') | first) + timedelta(**input_valve_positioning_timeout) <= now()\n )\n %}\n\n {% set opening = 100 %}\n {% set difference = target_temp - current_temp %}\n {% set step_size = input_valve_positioning_step_size | int %}\n\n {% if input_fully_open_difference > 0 and not is_force_max_temperature %}\n\n {% set opening_regular = (100 / input_fully_open_difference) * difference %}\n {% set opening_pessimistic = sqrt(((100 / input_fully_open_difference) * difference) | abs) * 10 %}\n {% set opening_optimistic = ((100 / input_fully_open_difference) * difference)**2 / 100 %}\n\n {% set opening = opening_regular %}\n {% set opening = iif(input_valve_positioning_mode == 'pessimistic', opening_pessimistic, opening) %}\n {% set opening = iif(input_valve_positioning_mode == 'optimistic', opening_optimistic, opening) %}\n\n {% set opening = iif(difference >= input_fully_open_difference, 100, opening) %}\n {% set opening = iif(difference < 0, 0, opening) %}\n\n {% set opening = opening / 100 * input_valve_positioning_max_opening %}\n\n {% set opening = ((opening + step_size / 2) // step_size * step_size) | int %}\n {% endif %}\n\n {% set open_valve_entity_value = states(open_valve_entity) | int %}\n\n {% if open_valve_entity_value != opening %}\n {% set n.dict = n.dict + [(valve, [{'entity': open_valve_entity , 'value': opening, 'current_temp': current_temp, 'target_temp': target_temp, 'difference': difference}])] %}\n {% endif %}\n\n {% endif %}\n {% endfor %}\n\n {{ dict.from_keys(n.dict) }}\n{% endif %}\n",
  721. "reset_data": "{% set result = [] %} {% if is_adjustment_trigger %}\n {% if entry_comfort_temp != none and input_temperature_comfort_entity != none %}\n {% set result = result + [{'entity': input_temperature_comfort_entity, 'temp': entry_comfort_temp}] %}\n {% endif %}\n {% if entry_eco_temp != none and input_temperature_eco_entity != none %}\n {% set result = result + [{'entity': input_temperature_eco_entity, 'temp': entry_eco_temp}] %}\n {% endif %}\n{% else %}\n {% set entity = none %}\n {% if is_reset and set_comfort %}\n {% set entity = iif(is_pysical_change, input_temperature_comfort_entity, input_temperature_eco_entity) %}\n {% elif is_reset and not set_comfort %}\n {% set entity = iif(is_pysical_change, input_temperature_eco_entity, input_temperature_comfort_entity) %}\n {% endif %}\n\n {% set temp_r = none %}\n {% if is_pysical_change %}\n {% set temp_r = state_attr(trigger.to_state.entity_id,'temperature') %}\n {% else %}\n {% set temp_r = iif(is_reset and entity == input_temperature_eco_entity, \n input_temperature_eco_static, input_temperature_comfort_static) %}\n {% endif %}\n\n {% if entity != none and temp_r != none %}\n {% set result = result + [{'entity': entity, 'temp': temp_r}] %}\n {% endif %}\n{% endif %}\n{{ result }}\n",
  722. "is_reset_trigger": "{{ is_reset and reset_data | count > 0 }}",
  723. "is_native_calibration": "{{ not input_calibration_generic and entry_calibration and valid_temperature_sensor }}",
  724. "is_native_calibration_trigger": "{{ is_calibration_trigger and is_native_calibration }}",
  725. "rounding_mode": "{% if is_number(input_calibration_step_size) or input_calibration_step_size == 'full' %}\n {{ 'manual' }}\n{% else %}\n {{ 'auto' }}\n{% endif %}\n",
  726. "calibration_tado": "{% set n = namespace(dict=[]) %}\n{% if is_native_calibration_trigger %}\n {% for valve in valves_tado %}\n\n {% set offset_old = state_attr(valve, 'offset_celsius') | float(0) %}\n {% set local_temperature = state_attr(valve, 'current_temperature') | float %}\n {% set calibration_sensor_temperature = value_temperature_sensor | float %}\n \n {% set offset_new = (-(local_temperature - calibration_sensor_temperature) + offset_old) %}\n\n {% if is_aggressive_mode_calibration %} \n {% set temp_diff = state_attr(valve,'temperature') | float(target_temperature) - calibration_sensor_temperature %}\n\n {% if temp_diff * factor < input_aggressive_mode_range * -1 %}\n {% set offset_new = offset_new + input_aggressive_mode_offset * factor %}\n {% elif temp_diff * factor > input_aggressive_mode_range %}\n {% set offset_new = offset_new - input_aggressive_mode_offset * factor %}\n {% endif %}\n {% endif %}\n\n {% set t_min = -10.9 %}\n {% set t_max = 10.9 %}\n\n {% set offset_new = iif(offset_new > t_max, t_max, offset_new) %}\n {% set offset_new = iif(offset_new < t_min, t_min, offset_new) %}\n\n {% set offset_new = offset_new | round(1) %}\n\n {% if (float(offset_old) - float(offset_new)) | abs >= float(input_calibration_delta) %}\n {% set n.dict = n.dict + [(valve, [{'value': offset_new }])] %}\n {% endif %}\n\n {% endfor %}\n{% endif %}\n{{ dict.from_keys(n.dict) }}\n",
  727. "calibration_xiaomi": "{% set n = namespace(dict=[]) %}\n{% if is_native_calibration_trigger %}\n {% for valve in valves_xiaomi %}\n\n {% set calibration_entities = device_entities(device_id(valve)) |\n expand | selectattr('domain','in','number') |\n selectattr('entity_id', 'search', input_calibration_key_word) |\n map(attribute='entity_id') | list %}\n\n {% if calibration_entities | count > 0 %}\n\n {% set calibration_entity = calibration_entities | first %}\n {% set offset_old = states(calibration_entity) | float(0) %}\n {% set offset_new = value_temperature_sensor | float %}\n \n {% set step = state_attr(calibration_entity, 'step') | float(1) %}\n {% if rounding_mode == 'manual' %} \n {% set step = input_calibration_step_size | float(1) %}\n {% endif %}\n\n {% set min_val = state_attr(calibration_entity,'min') | float(0) %}\n {% set max_val = state_attr(calibration_entity,'max') | float(55) %}\n \n {% if is_aggressive_mode_calibration %} \n {% set temp_diff = state_attr(valve,'temperature') | float(target_temperature) - value_temperature_sensor | float %}\n\n {% if temp_diff * factor < input_aggressive_mode_range * -1 %}\n {% set offset_new = offset_new + input_aggressive_mode_offset * factor %}\n {% elif temp_diff * factor > input_aggressive_mode_range %}\n {% set offset_new = offset_new - input_aggressive_mode_offset * factor %}\n {% endif %}\n {% endif %}\n\n {% set round_size = iif('.' in (step | string), (step | string).split('.')[1] | length, 0) %}\n {% set offset_new = ((offset_new | float(0) / step) | round(0) * step) | round(round_size) | float %}\n\n {% set offset_new = iif(offset_new > max_val, max_val, offset_new) %}\n {% set offset_new = iif(offset_new < min_val, min_val, offset_new) %}\n\n {% if (float(offset_old) - float(offset_new)) | abs >= float(input_calibration_delta) %}\n {% set n.dict = n.dict + [(calibration_entity, [{'value': offset_new, 'valve': valve}])] %}\n {% endif %}\n {% endif %}\n\n {% endfor %}\n{% endif %}\n{{ dict.from_keys(n.dict) }}\n",
  728. "calibration_dph": "{% set n = namespace(dict=[]) %} {% if is_native_calibration_trigger %}\n\n {% for valve in valves_dph %}\n\n {% set calibration_entities = device_entities(device_id(valve)) |\n expand | selectattr('domain','in','number') |\n selectattr('entity_id', 'search', input_calibration_key_word) |\n map(attribute='entity_id') | list %}\n\n {% if calibration_entity != calibration_entities | count > 0 %}\n\n {% set calibration_entity = calibration_entities | first %}\n\n {% set min_val = state_attr(calibration_entity,'min')%}\n {% set max_val = state_attr(calibration_entity,'max')%}\n \n {% set step = state_attr(calibration_entity, 'step') | float(1) %}\n {% if rounding_mode == 'manual' %} \n {% set step = input_calibration_step_size | float(1) %}\n {% endif %}\n\n {% set current_temp = state_attr(valve,'current_temperature') | float(20) %}\n\n {% set new_state = value_temperature_sensor | float(current_temp) %}\n {% set old_state = states(calibration_entity) | float %}\n\n {% if is_aggressive_mode_calibration %} \n {% set temp_diff = state_attr(valve,'temperature') | float(target_temperature) - value_temperature_sensor | float %}\n\n {% if temp_diff * factor < input_aggressive_mode_range * -1 %}\n {% set new_state = new_state + input_aggressive_mode_offset * factor %}\n {% elif temp_diff * factor > input_aggressive_mode_range %}\n {% set new_state = new_state - input_aggressive_mode_offset * factor %}\n {% endif %}\n {% endif %}\n\n {% if step <= 1 and max_val | string | count < 4 %}\n {% set round_size = iif('.' in (step | string), (step | string).split('.')[1] | length, 0) %}\n {% set new_state = ((new_state | float(0) / step) | round(0) * step) | round(round_size) | float %}\n {% else %}\n {% set new_state = new_state * 100 | int %}\n {% set old_state = old_state | int %}\n {% endif %}\n\n {% set update_calibration = old_state != new_state %}\n\n {% if is_calibration_trigger and not update_calibration %}\n {% set last_updated = [calibration_entity] | expand | map(attribute='last_updated') | first %}\n {% set update_calibration = as_datetime(current_time_stamp) - timedelta(minutes=20) >= last_updated %}\n {% endif %}\n\n {% if update_calibration %}\n {% set n.dict = n.dict + [(calibration_entity, [{'value': new_state, 'valve': valve}])] %}\n {% endif%}\n\n {% endif %}\n\n {% endfor %}\n{% endif %}\n{{ dict.from_keys(n.dict) }}\n",
  729. "calibration_common": "{% set n = namespace(dict=[]) %}\n{% if is_native_calibration_trigger %}\n\n {% for valve in valves_calibration_common %}\n\n {% set calibration_entities = device_entities(device_id(valve)) |\n expand | selectattr('domain','in','number') |\n selectattr('entity_id', 'search', input_calibration_key_word) |\n map(attribute='entity_id') | list %}\n\n {% if calibration_entities | count > 0%}\n\n {% set calibration_entity = calibration_entities | first %}\n \n {% set step = state_attr(calibration_entity, 'step') | float(1) %}\n {% if rounding_mode == 'manual' %} \n {% set step = input_calibration_step_size | float(1) %}\n {% endif %}\n\n {% set min_calibration_value = state_attr(calibration_entity,'min') | float %}\n {% set max_calibration_value = state_attr(calibration_entity,'max') | float %}\n {% set thermostat_temperature = state_attr(valve, 'current_temperature') | float %}\n {% set offset_old = states(calibration_entity) | float(0) %}\n\n {% set new_calibration_value = (-(thermostat_temperature - value_temperature_sensor) + offset_old) %}\n\n {% if is_aggressive_mode_calibration %} \n {% set temp_diff = state_attr(valve,'temperature') | float(target_temperature) - value_temperature_sensor %}\n\n {% if temp_diff * factor < input_aggressive_mode_range * -1 %}\n {% set new_calibration_value = new_calibration_value + input_aggressive_mode_offset * factor %}\n {% elif temp_diff * factor > input_aggressive_mode_range %}\n {% set new_calibration_value = new_calibration_value - input_aggressive_mode_offset * factor %}\n {% endif %}\n {% endif %}\n\n {% set new_calibration_value = iif(new_calibration_value > max_calibration_value, max_calibration_value, new_calibration_value) %}\n {% set new_calibration_value = iif(new_calibration_value < min_calibration_value, min_calibration_value, new_calibration_value) %}\n\n {% set round_size = iif('.' in (step | string), (step | string).split('.')[1] | length, 0) %}\n\n {% set offset_new = ((new_calibration_value | float(0) / step) | round(0) * step) | round(round_size) | float %}\n\n {% if (float(offset_old) - float(offset_new)) | abs >= float(input_calibration_delta) %}\n {% set n.dict = n.dict + [(calibration_entity, [{'value': offset_new, 'valve': valve}])] %}\n {% endif %}\n\n {% endif %}\n\n {% endfor %}\n{% endif %}\n{{ dict.from_keys(n.dict) }}\n",
  730. "calibration_value_set": "{{ dict(dict(calibration_xiaomi, **calibration_dph),**calibration_common) }}",
  731. "no_changes": "{{ \n (input_persons | count == 0 and \n input_mode_guest == none and \n input_schedulers | count == 0 and \n input_presence_sensor == none and \n input_proximity == none) or\n (is_temperature_sensor_defined and not valid_temperature_sensor)\n}}\n",
  732. "scene_trigger": "{{ is_scene_create_trigger or is_scene_apply_trigger or is_scene_destroy_trigger }}",
  733. "change_trigger": "{{ is_changes_trigger and not scene_trigger and changes | count > 0 and not no_changes}}",
  734. "reset_trigger": "{{ is_reset_trigger and not no_changes }}",
  735. "calibration_trigger": "{{ is_calibration_trigger and not input_calibration_generic and (calibration_value_set | count > 0 or calibration_tado | count > 0) }}",
  736. "positioning_trigger": "{{ positioning | count > 0 }}",
  737. "automation_name": "{{ state_attr(this.entity_id,'friendly_name') }}",
  738. "warnings": "{% set messages = [] %} {% if not is_uptime_defined %}\n {% set messages = messages + ['To make Advance Heating Control work properly just setup the uptime integration (https://www.home-assistant.io/integrations/uptime/)'] %}\n{% elif is_aggressive_mode and not input_aggressive_mode_calibration and is_physical_change_enabled %}\n {% set messages = messages + ['Aggressive Mode in combination with physical change / sync feature is not recommended. Expect unwanted side effects.'] %}\n{% elif is_generic_calibration and is_physical_change_enabled %}\n {% set messages = messages + ['Generic Calibration in combination with physical change / sync feature is not recommended. Expect unwanted side effects.'] %}\n{% elif valves_unsupported | count > 0 %}\n {% set messages = messages + ['Unsupported climate entities: ' + valves_unsupported | join(',') | string ] %}\n{% elif is_temperature_sensor_defined and not valid_temperature_sensor %}\n {% set messages = messages + ['The temperature sensor' + input_temperature_sensor + ' has an invalid state: ' + states(input_temperature_sensor) ] %}\n{% endif %}\n{{ messages }}\n",
  739. "climates_information": "{% set n = namespace(dict=[]) %}\n{% for valve in input_trvs %}\n {% set temperature = state_attr(valve,'temperature') %}\n {% set current_temperature = state_attr(valve,'current_temperature') %}\n {% set state = states(valve) %}\n {% set n.dict = n.dict + [{'entity_id': valve, 'state': state, 'temperature': temperature, 'current_temperature': current_temperature}] %}\n{% endfor %}\n{{ n.dict }}\n"
  740. },
  741. "conditions": [
  742. {
  743. "condition": "or",
  744. "conditions": [
  745. {
  746. "condition": "template",
  747. "value_template": "{{ calibration_trigger }}"
  748. },
  749. {
  750. "condition": "template",
  751. "value_template": "{{ scene_trigger }}"
  752. },
  753. {
  754. "condition": "template",
  755. "value_template": "{{ change_trigger }}"
  756. },
  757. {
  758. "condition": "template",
  759. "value_template": "{{ reset_trigger }}"
  760. },
  761. {
  762. "condition": "template",
  763. "value_template": "{{ positioning_trigger }}"
  764. }
  765. ]
  766. }
  767. ],
  768. "actions": [
  769. {
  770. "variables": {
  771. "is_delayed": "{{ not (not is_uptime_defined or (now() | as_datetime - states(up_time_sensor) | as_datetime) > timedelta(**input_startup_delay)) }}"
  772. }
  773. },
  774. {
  775. "action": "system_log.write",
  776. "data": {
  777. "message": "{{ 'AHC - ' + automation_name | string + ' \\n ' + 'automation delayed: ' + is_delayed | string }}\n",
  778. "level": "debug",
  779. "logger": "blueprints.panhans.heatingcontrol"
  780. }
  781. },
  782. {
  783. "wait_template": "{{ not is_uptime_defined or (now() | as_datetime - states(up_time_sensor) | as_datetime) > timedelta(**input_startup_delay) }}\n"
  784. },
  785. {
  786. "choose": [
  787. {
  788. "conditions": "{{ is_delayed }}",
  789. "sequence": [
  790. {
  791. "event": "ahc_delay_event",
  792. "event_data": {
  793. "automation": "{{ this.entity_id }}"
  794. }
  795. }
  796. ]
  797. }
  798. ],
  799. "default": [
  800. {
  801. "if": [
  802. {
  803. "condition": "template",
  804. "value_template": "{{ warnings | count > 0 }}"
  805. }
  806. ],
  807. "then": [
  808. {
  809. "action": "system_log.write",
  810. "data": {
  811. "level": "warning",
  812. "logger": "blueprints.panhans.heatingcontrol",
  813. "message": "{{ 'AHC-Warnings - ' + automation_name + ':\\n' + warnings | join('\\n') }}\n"
  814. }
  815. }
  816. ]
  817. },
  818. {
  819. "event": "ahc_event",
  820. "event_data": {
  821. "state": "{{ state_ahc }}",
  822. "mode": "{{ iif(set_comfort == true, 'comfort', 'eco') }}",
  823. "automation": "{{ this.entity_id }}",
  824. "is_person_defined": "{{ is_person_defined }}",
  825. "is_anybody_home": "{{ is_anybody_home }}",
  826. "is_proximity_defined": "{{ is_proximity_defined }}",
  827. "is_anybody_home_or_proximity": "{{ is_anybody_home_or_proximity }}",
  828. "is_guest_mode": "{{ is_guest_mode }}",
  829. "active_scheduler": "{{ active_scheduler }}",
  830. "state_scheduler": "{{ state_scheduler }}",
  831. "state_presence_sensor": "{{ state_presence_sensor }}",
  832. "state_presence_scheduler": "{{ state_presence_scheduler }}",
  833. "state_presence": "{{ state_presence }}",
  834. "state_proximity_arrived": "{{ state_proximity_arrived }}",
  835. "state_proximity_way_home": "{{ state_proximity_way_home }}",
  836. "is_force_max_temperature": "{{ is_force_max_temperature }}",
  837. "is_force_eco_temperature": "{{ is_force_eco_temperature }}",
  838. "active_party_entity": "{{ active_party_entity }}",
  839. "party_temp": "{{ party_temp }}",
  840. "is_away": "{{ is_away }}",
  841. "state_window": "{{ state_window }}",
  842. "is_aggressive_mode": "{{ is_aggressive_mode }}",
  843. "is_frost_protection": "{{ is_frost_protection }}",
  844. "is_liming_protection": "{{ is_liming_protection }}",
  845. "state_outside_temp": "{{ state_outside_temp }}",
  846. "entry_time": "{{ entry_time }}",
  847. "thermostats": "{{ input_trvs }}",
  848. "hvac_mode": "{{ mode }}",
  849. "temperature_comfort": "{{ temperature_comfort }}",
  850. "temperature_eco": "{{ temperature_eco }}",
  851. "target_temperature": "{{ target_temperature }}",
  852. "set_max_temperature": "{{ set_max_temperature }}",
  853. "last_trigger_id": "{{ iif(trigger_id_defined, trigger.id, '') }}",
  854. "calibration_trigger": "{{ is_generic_calibration_trigger or calibration_trigger }}",
  855. "change_trigger": "{{ change_trigger }}",
  856. "warnings": "{{ warnings | count > 0 }}"
  857. }
  858. },
  859. {
  860. "if": [
  861. {
  862. "condition": "template",
  863. "value_template": "{{ calibration_trigger }}"
  864. },
  865. {
  866. "condition": "and",
  867. "conditions": null
  868. }
  869. ],
  870. "then": [
  871. {
  872. "action": "system_log.write",
  873. "data": {
  874. "message": "{{ 'AHC - Calibration - ' + automation_name | string + ' \\n ' + 'calibration data set: ' + calibration_value_set | string }}\n",
  875. "level": "debug",
  876. "logger": "blueprints.panhans.heatingcontrol"
  877. }
  878. },
  879. {
  880. "repeat": {
  881. "count": "{{ calibration_value_set | count | int }}",
  882. "sequence": [
  883. {
  884. "variables": {
  885. "index": "{{ repeat.index-1 }}",
  886. "calibration_entity": "{{ (calibration_value_set.keys() | list) [index] }}",
  887. "thermostat": "{{ (((calibration_value_set.values() | list) [index]) | first) ['valve'] }}",
  888. "offset": "{{ (((calibration_value_set.values() | list) [index]) | first) ['value'] }}",
  889. "select_entity": "{{ device_entities(device_id(thermostat)) | expand | selectattr('domain','in','select') | selectattr('attributes.options', 'contains', 'external') | map(attribute='entity_id') | list | first | default(none) }}"
  890. }
  891. },
  892. {
  893. "action": "system_log.write",
  894. "data": {
  895. "message": "{{ 'AHC - Calibration - ' + automation_name | string + ' \\n ' + 'calibration entity: ' + calibration_entity | string + ' \\n ' + 'offset: ' + offset | string }}\n",
  896. "level": "debug",
  897. "logger": "blueprints.panhans.heatingcontrol"
  898. }
  899. },
  900. {
  901. "if": [
  902. {
  903. "condition": "template",
  904. "value_template": "{{ thermostat in valves_xiaomi }}"
  905. },
  906. {
  907. "condition": "template",
  908. "value_template": "{{ select_entity != none and not is_state(select_entity, 'external') }}"
  909. }
  910. ],
  911. "then": [
  912. {
  913. "action": "select.select_option",
  914. "target": {
  915. "entity_id": "{{ select_entity }}"
  916. },
  917. "data": {
  918. "option": "external"
  919. }
  920. },
  921. {
  922. "delay": {
  923. "hours": 0,
  924. "minutes": 0,
  925. "seconds": 2
  926. }
  927. }
  928. ]
  929. },
  930. {
  931. "action": "number.set_value",
  932. "data": {
  933. "value": "{{ float(offset) }}"
  934. },
  935. "target": {
  936. "entity_id": "{{ calibration_entity }}"
  937. }
  938. },
  939. {
  940. "delay": {
  941. "hours": 0,
  942. "minutes": 0,
  943. "seconds": 2
  944. }
  945. }
  946. ]
  947. }
  948. },
  949. {
  950. "repeat": {
  951. "count": "{{ calibration_tado | count | int }}",
  952. "sequence": [
  953. {
  954. "variables": {
  955. "index": "{{ repeat.index-1 }}",
  956. "thermostat": "{{ (calibration_tado.keys() | list) [index] }}",
  957. "offset": "{{ (((calibration_tado.values() | list) [index]) | first) ['value'] }}"
  958. }
  959. },
  960. {
  961. "action": "{{ 'tado.set_climate_temperature_offset' }}",
  962. "data": {
  963. "offset": "{{ offset }}",
  964. "entity_id": "{{ thermostat }}"
  965. }
  966. },
  967. {
  968. "delay": {
  969. "hours": 0,
  970. "minutes": 0,
  971. "seconds": 2
  972. }
  973. }
  974. ]
  975. }
  976. }
  977. ]
  978. },
  979. {
  980. "if": [
  981. {
  982. "condition": "template",
  983. "value_template": "{{ positioning_trigger }}"
  984. }
  985. ],
  986. "then": [
  987. {
  988. "repeat": {
  989. "count": "{{ positioning | count | int }}",
  990. "sequence": [
  991. {
  992. "variables": {
  993. "index": "{{ repeat.index-1 }}",
  994. "thermostat": "{{ (positioning.keys() | list) [index] }}",
  995. "positioning_value": "{{ (((positioning.values() | list) [index]) | first) ['value'] }}",
  996. "positioning_entity": "{{ (((positioning.values() | list) [index]) | first) ['entity'] }}"
  997. }
  998. },
  999. {
  1000. "action": "system_log.write",
  1001. "data": {
  1002. "message": "{{ 'AHC - Positioning - ' + automation_name | string + ' \\n ' + 'entity: ' + positioning_entity | string + ' \\n ' + 'value: ' + positioning_value | string }}\n",
  1003. "level": "debug",
  1004. "logger": "blueprints.panhans.heatingcontrol"
  1005. }
  1006. },
  1007. {
  1008. "action": "number.set_value",
  1009. "data": {
  1010. "value": "{{ positioning_value | int }}"
  1011. },
  1012. "target": {
  1013. "entity_id": "{{ positioning_entity }}"
  1014. }
  1015. },
  1016. {
  1017. "delay": {
  1018. "hours": 0,
  1019. "minutes": 0,
  1020. "seconds": 2
  1021. }
  1022. }
  1023. ]
  1024. }
  1025. }
  1026. ]
  1027. },
  1028. {
  1029. "if": [
  1030. {
  1031. "condition": "template",
  1032. "value_template": "{{ is_scene_create_trigger }}"
  1033. },
  1034. {
  1035. "condition": "template",
  1036. "value_template": "{{ states[scene_to_create] == none }}"
  1037. }
  1038. ],
  1039. "then": [
  1040. {
  1041. "action": "scene.create",
  1042. "data": {
  1043. "snapshot_entities": "{{ scene_entities }}",
  1044. "scene_id": "{{ scene_to_create.split('.')[1] }}"
  1045. }
  1046. }
  1047. ]
  1048. },
  1049. {
  1050. "if": [
  1051. {
  1052. "condition": "template",
  1053. "value_template": "{{ is_scene_destroy_trigger }}"
  1054. },
  1055. {
  1056. "condition": "template",
  1057. "value_template": "{{ scenes_to_destroy | count > 0 }}"
  1058. }
  1059. ],
  1060. "then": [
  1061. {
  1062. "repeat": {
  1063. "count": "{{ scenes_to_destroy | count | int }}",
  1064. "sequence": [
  1065. {
  1066. "variables": {
  1067. "scene_to_destroy": "{{ scenes_to_destroy[repeat.index-1] }}"
  1068. }
  1069. },
  1070. {
  1071. "if": [
  1072. {
  1073. "condition": "template",
  1074. "value_template": "{{ states[scene_to_destroy] != none }}"
  1075. }
  1076. ],
  1077. "then": [
  1078. {
  1079. "action": "scene.delete",
  1080. "target": {
  1081. "entity_id": "{{ scene_to_destroy }}"
  1082. }
  1083. }
  1084. ]
  1085. }
  1086. ]
  1087. }
  1088. }
  1089. ]
  1090. },
  1091. {
  1092. "variables": {
  1093. "scene_to_apply_tmp": "{% if scene_to_apply != none and states[scene_to_apply] != none %}\n {{ scene_to_apply }}\n{% else %}\n {{ scenes_all | expand | reject('==',none) | map(attribute=\"entity_id\") | list | first | default(none) }}\n{% endif %}\n"
  1094. }
  1095. },
  1096. {
  1097. "if": [
  1098. {
  1099. "condition": "template",
  1100. "value_template": "{{ is_scene_apply_trigger }}"
  1101. },
  1102. {
  1103. "condition": "template",
  1104. "value_template": "{{ scene_to_apply_tmp != none and states[scene_to_apply_tmp] != none }}"
  1105. }
  1106. ],
  1107. "then": [
  1108. {
  1109. "action": "system_log.write",
  1110. "data": {
  1111. "message": "{{ 'AHC - Calibration - ' + automation_name | string + ' \\n ' + 'apply scene: ' + scene_to_apply_tmp | string + ' state: ' + states[scene_to_apply_tmp] | string }}\n",
  1112. "level": "debug",
  1113. "logger": "blueprints.panhans.heatingcontrol"
  1114. }
  1115. },
  1116. {
  1117. "action": "scene.turn_on",
  1118. "target": {
  1119. "entity_id": "{{ scene_to_apply_tmp }}"
  1120. }
  1121. },
  1122. {
  1123. "action": "scene.delete",
  1124. "target": {
  1125. "entity_id": "{{ scene_to_apply_tmp }}"
  1126. }
  1127. },
  1128. {
  1129. "condition": "template",
  1130. "value_template": "{{ false }}"
  1131. }
  1132. ],
  1133. "else": [
  1134. {
  1135. "if": [
  1136. {
  1137. "condition": "template",
  1138. "value_template": "{{ is_reset_trigger }}"
  1139. }
  1140. ],
  1141. "then": [
  1142. {
  1143. "repeat": {
  1144. "count": "{{ reset_data | count | int }}",
  1145. "sequence": [
  1146. {
  1147. "action": "system_log.write",
  1148. "data": {
  1149. "message": "{{ 'AHC - Calibration - ' + automation_name | string + ' \\n ' + 'reset data: ' + reset_data | string }}\n",
  1150. "level": "debug",
  1151. "logger": "blueprints.panhans.heatingcontrol"
  1152. }
  1153. },
  1154. {
  1155. "variables": {
  1156. "index": "{{ repeat.index-1 }}",
  1157. "reset_entity": "{{ reset_data[index]['entity'] }}",
  1158. "reset_temp": "{% set temp_r = reset_data[index]['temp'] %} {% set t_min = state_attr(reset_entity,'min') %} {% set t_max = state_attr(reset_entity,'max') %} {% set step = state_attr(reset_entity,'step') %}\n{% set temp_r = ((temp_r | float(0) / step) | round(0) * step) | float %} {% set temp_r = iif(temp_r > t_max, t_max, temp_r) %} {% set temp_r = iif(temp_r < t_min, t_min, temp_r) %} {{ temp_r }}\n"
  1159. }
  1160. },
  1161. {
  1162. "action": "input_number.set_value",
  1163. "data": {
  1164. "value": "{{ reset_temp }}"
  1165. },
  1166. "target": {
  1167. "entity_id": "{{ reset_entity }}"
  1168. }
  1169. }
  1170. ]
  1171. }
  1172. }
  1173. ]
  1174. },
  1175. {
  1176. "if": [
  1177. {
  1178. "condition": "and",
  1179. "conditions": null
  1180. },
  1181. {
  1182. "condition": "template",
  1183. "value_template": "{{ changes | count | int > 0 and (not no_changes or (no_changes and state_window)) }}"
  1184. }
  1185. ],
  1186. "then": [
  1187. {
  1188. "repeat": {
  1189. "count": "{{ changes | count | int }}",
  1190. "sequence": [
  1191. {
  1192. "variables": {
  1193. "index": "{{ repeat.index-1 }}",
  1194. "thermostat": "{{ (changes.keys() | list) [index] }}",
  1195. "mode": "{{ (((changes.values() | list) [index]) | first) ['mode'] }}",
  1196. "temp_target": "{{ (((changes.values() | list) [index]) | first) ['temp'] }}"
  1197. }
  1198. },
  1199. {
  1200. "action": "system_log.write",
  1201. "data": {
  1202. "message": "AHC - Change - {{ automation_name }} {{\" \\n \"}} Trigger ID: {{ iif(trigger_id_defined, trigger.id, '') }} Thermostat: {{ thermostat }} {{\" \\n \"}} Mode: {{ mode }} {{\" \\n \"}} New Target Temp: {{ temp_target }} {{\" \\n \"}} Current Target Temp: {{ state_attr(thermostat,'temperature') }}\n",
  1203. "level": "debug",
  1204. "logger": "blueprints.panhans.heatingcontrol"
  1205. }
  1206. },
  1207. {
  1208. "if": [
  1209. {
  1210. "condition": "template",
  1211. "value_template": "{{ states(thermostat) | lower != mode | lower }}"
  1212. }
  1213. ],
  1214. "then": [
  1215. {
  1216. "action": "climate.set_hvac_mode",
  1217. "data": {
  1218. "entity_id": "{{ thermostat }}",
  1219. "hvac_mode": "{{ mode }}"
  1220. }
  1221. },
  1222. {
  1223. "delay": {
  1224. "hours": 0,
  1225. "minutes": 0,
  1226. "seconds": 2
  1227. }
  1228. }
  1229. ]
  1230. },
  1231. {
  1232. "if": [
  1233. {
  1234. "condition": "template",
  1235. "value_template": "{{ state_attr(thermostat, 'temperature') != temp_target and mode != 'off' }}"
  1236. }
  1237. ],
  1238. "then": [
  1239. {
  1240. "action": "climate.set_temperature",
  1241. "data": {
  1242. "entity_id": "{{ thermostat }}",
  1243. "temperature": "{{ temp_target | float }}"
  1244. }
  1245. },
  1246. {
  1247. "delay": {
  1248. "hours": 0,
  1249. "minutes": 0,
  1250. "seconds": 2
  1251. }
  1252. }
  1253. ]
  1254. }
  1255. ]
  1256. }
  1257. }
  1258. ]
  1259. }
  1260. ]
  1261. },
  1262. {
  1263. "if": [
  1264. {
  1265. "condition": "template",
  1266. "value_template": "{{ input_valve_positioning_mode != 'off' }}"
  1267. },
  1268. {
  1269. "condition": "template",
  1270. "value_template": "{{ changes | count | int > 0 or is_scene_apply_trigger }}"
  1271. }
  1272. ],
  1273. "then": [
  1274. {
  1275. "delay": {
  1276. "seconds": 10
  1277. }
  1278. },
  1279. {
  1280. "event": "ahc_positioning_event",
  1281. "event_data": {
  1282. "automation": "{{ this.entity_id }}"
  1283. }
  1284. },
  1285. {
  1286. "delay": {
  1287. "hours": 0,
  1288. "minutes": 0,
  1289. "seconds": 2
  1290. }
  1291. }
  1292. ]
  1293. },
  1294. {
  1295. "if": [
  1296. {
  1297. "condition": "template",
  1298. "value_template": "{{ input_custom_action != none }}"
  1299. }
  1300. ],
  1301. "then": null
  1302. }
  1303. ]
  1304. }
  1305. ],
  1306. "mode": "queued",
  1307. "triggers": [
  1308. {
  1309. "trigger": "homeassistant",
  1310. "event": "start",
  1311. "id": "temperature_change_hastart"
  1312. },
  1313. {
  1314. "trigger": "event",
  1315. "event_type": "automation_reloaded",
  1316. "id": "temperature_change_reload"
  1317. },
  1318. {
  1319. "trigger": "event",
  1320. "event_type": "ahc_delay_event",
  1321. "id": "delayed_call_temperature_change",
  1322. "event_data": {
  1323. "automation": "{{ this.entity_id }}"
  1324. }
  1325. },
  1326. {
  1327. "trigger": "event",
  1328. "event_type": "ahc_positioning_event",
  1329. "id": "positioning_event",
  1330. "event_data": {
  1331. "automation": "{{ this.entity_id }}"
  1332. }
  1333. },
  1334. {
  1335. "trigger": "state",
  1336. "entity_id": [
  1337. "climate.heizung_esszimmer"
  1338. ],
  1339. "from": [
  1340. "unknown",
  1341. "unavailable"
  1342. ],
  1343. "for": {
  1344. "seconds": 5
  1345. },
  1346. "id": "temperature_change_available"
  1347. },
  1348. {
  1349. "trigger": "state",
  1350. "entity_id": [
  1351. "climate.heizung_esszimmer"
  1352. ],
  1353. "attribute": "temperature",
  1354. "for": {
  1355. "seconds": 5
  1356. },
  1357. "id": "temperature_change_valve_target"
  1358. },
  1359. {
  1360. "trigger": "state",
  1361. "entity_id": [],
  1362. "for": {
  1363. "hours": 0,
  1364. "minutes": 0,
  1365. "seconds": 2
  1366. },
  1367. "id": "temperature_change_eco"
  1368. },
  1369. {
  1370. "trigger": "state",
  1371. "entity_id": [],
  1372. "for": {
  1373. "hours": 0,
  1374. "minutes": 0,
  1375. "seconds": 2
  1376. },
  1377. "id": "temperature_change_comfort"
  1378. },
  1379. {
  1380. "trigger": "template",
  1381. "value_template": "{{ input_persons | expand \n | selectattr('state', 'eq', 'home') \n | list \n | count > 0 \n \n or (is_guest_mode_defined and states(input_mode_guest) in ['on','active'] ) }}\n",
  1382. "id": "temperature_change_person_on",
  1383. "for": {
  1384. "hours": 0,
  1385. "minutes": 0,
  1386. "seconds": 2
  1387. }
  1388. },
  1389. {
  1390. "trigger": "template",
  1391. "value_template": "{{ input_persons | expand \n | selectattr('state', 'eq', 'home') \n | list \n | count == 0 \n \n and (not is_guest_mode_defined or (is_guest_mode_defined and states(input_mode_guest) not in ['on','active'])) }}\n",
  1392. "id": "temperature_change_person_off",
  1393. "for": {
  1394. "hours": 0,
  1395. "minutes": 0,
  1396. "seconds": 2
  1397. }
  1398. },
  1399. {
  1400. "trigger": "template",
  1401. "id": "temperature_change_scheduler_on",
  1402. "value_template": "{% set selected_scheduler = none %} {% set schedules_count = input_schedulers | count %}\n{% if schedules_count == 0 %}\n {% set selected_scheduler = none %}\n{% elif schedules_count == 1 or input_scheduler_selector == none %}\n {% set selected_scheduler = input_schedulers | first %}\n{% elif schedules_count > 1 %}\n {% set selector_value = states(input_scheduler_selector) %}\n\n {% if is_number(selector_value) %}\n {% set selector_value = iif(selector_value | int > schedules_count, schedules_count, selector_value) %}\n {% set selector_value = iif(selector_value | int <= 0, 1, selector_value) %}\n {% set selected_scheduler = input_schedulers[selector_value | int - 1] %}\n {% elif selector_value in ['on','off'] %}\n {% set selected_scheduler = iif(selector_value == 'off', input_schedulers[0], input_schedulers[1]) %}\n {% else %}\n {% set selected_scheduler = input_schedulers | expand | selectattr('attributes.friendly_name', 'eq', selector_value) | map(attribute='entity_id') | first | default(none) %}\n {% if (selected_scheduler == none) %}\n {% set selected_scheduler = input_schedulers | expand | selectattr('attributes.friendly_name', 'search', '(?i)' + selector_value) | map(attribute='entity_id') | first | default(none) %}\n {% endif %}\n {% endif %}\n{% endif %}\n{% if selected_scheduler == none %}\n {{ false }}\n{% else %}\n {{ is_state(selected_scheduler, 'on') }}\n{% endif %}\n"
  1403. },
  1404. {
  1405. "trigger": "template",
  1406. "id": "temperature_change_scheduler_off",
  1407. "value_template": "{% set selected_scheduler = none %} {% set schedules_count = input_schedulers | count %}\n{% if schedules_count == 0 %}\n {% set selected_scheduler = none %}\n{% elif schedules_count == 1 or input_scheduler_selector == none %}\n {% set selected_scheduler = input_schedulers | first %}\n{% elif schedules_count > 1 %}\n {% set selector_value = states(input_scheduler_selector) %}\n\n {% if is_number(selector_value) %}\n {% set selector_value = iif(selector_value | int > schedules_count, schedules_count, selector_value) %}\n {% set selector_value = iif(selector_value | int <= 0, 1, selector_value) %}\n {% set selected_scheduler = input_schedulers[selector_value | int - 1] %}\n {% elif selector_value in ['on','off'] %}\n {% set selected_scheduler = iif(selector_value == 'off', input_schedulers[0], input_schedulers[1]) %}\n {% else %}\n {% set selected_scheduler = input_schedulers | expand | selectattr('attributes.friendly_name', 'eq', selector_value) | map(attribute='entity_id') | first | default(none) %}\n {% if (selected_scheduler == none) %}\n {% set selected_scheduler = input_schedulers | expand | selectattr('attributes.friendly_name', 'search', '(?i)' + selector_value) | map(attribute='entity_id') | first | default(none) %}\n {% endif %}\n {% endif %}\n{% endif %}\n{% if selected_scheduler == none %}\n {{ false }}\n{% else %}\n {{ is_state(selected_scheduler, 'off') }}\n{% endif %}\n"
  1408. },
  1409. {
  1410. "trigger": "template",
  1411. "id": "temperature_change_presence_on",
  1412. "value_template": "{{ input_presence_sensor != none and is_state(input_presence_sensor, 'on') }}",
  1413. "for": {
  1414. "hours": 0,
  1415. "minutes": 5,
  1416. "seconds": 0
  1417. }
  1418. },
  1419. {
  1420. "trigger": "template",
  1421. "id": "temperature_change_presence_off",
  1422. "value_template": "{{ input_presence_sensor != none and is_state(input_presence_sensor, 'off') }}",
  1423. "for": {
  1424. "hours": 0,
  1425. "minutes": 5,
  1426. "seconds": 0
  1427. }
  1428. },
  1429. {
  1430. "trigger": "template",
  1431. "id": "temperature_change_presence_scheduler_on",
  1432. "value_template": "{{ input_scheduler_presence != none and is_state(input_scheduler_presence, 'on') }}",
  1433. "for": {
  1434. "hours": 0,
  1435. "minutes": 0,
  1436. "seconds": 2
  1437. }
  1438. },
  1439. {
  1440. "trigger": "template",
  1441. "id": "temperature_change_presence_scheduler_off",
  1442. "value_template": "{{ input_scheduler_presence != none and is_state(input_scheduler_presence, 'off') }}",
  1443. "for": {
  1444. "hours": 0,
  1445. "minutes": 0,
  1446. "seconds": 2
  1447. }
  1448. },
  1449. {
  1450. "trigger": "template",
  1451. "id": "temperature_change_person_proximity_on",
  1452. "value_template": "{% set proximity_entities = device_entities(input_proximity) %}\n{% set is_arrived = proximity_entities \n | select('is_state','arrived') \n | expand \n | selectattr('attributes.device_class', 'eq', 'enum')\n | list | count > 0 %}\n\n{% set entities_towards = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'enum') \n | map(attribute='entity_id') | select('is_state','towards') \n | map('regex_replace','_(?=[^_]*$)(.*)', '')\n | list %}\n\n{% set distances = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'distance')\n | map(attribute='state')\n | reject('eq', 'unknown')\n | map('int')\n | select('<=', input_proximity_distance | int)\n | map('string')\n | list %}\n\n{% set entities_distances = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'distance')\n | selectattr('state', 'in', distances)\n | map(attribute='entity_id')\n | map('regex_replace','_(?=[^_]*$)(.*)', '')\n | list %}\n\n{% set entites_towards_and_in_distance = entities_towards | select('in', entities_distances) | list | count > 0 %}\n{{ entites_towards_and_in_distance or is_arrived }}\n",
  1453. "for": {
  1454. "hours": 0,
  1455. "minutes": 2,
  1456. "seconds": 0
  1457. }
  1458. },
  1459. {
  1460. "trigger": "template",
  1461. "id": "temperature_change_person_proximity_off",
  1462. "value_template": "{% set proximity_entities = device_entities(input_proximity) %} {% set is_arrived = proximity_entities \n | select('is_state','arrived') \n | expand \n | selectattr('attributes.device_class', 'eq', 'enum') \n | list | count > 0 %}\n\n{% set entities_towards = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'enum') \n | map(attribute='entity_id') | select('is_state','towards') \n | map('regex_replace','_(?=[^_]*$)(.*)', '')\n | list %}\n\n{% set distances = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'distance')\n | map(attribute='state')\n | reject('eq', 'unknown')\n | map('int')\n | select('<=', input_proximity_distance | int)\n | map('string')\n | list %}\n\n{% set entities_distances = proximity_entities \n | expand \n | selectattr('attributes.device_class', 'eq', 'distance')\n | selectattr('state', 'in', distances)\n | map(attribute='entity_id')\n | map('regex_replace','_(?=[^_]*$)(.*)', '')\n | list %}\n\n{% set entites_towards_and_in_distance = entities_towards | select('in', entities_distances) | list | count > 0 %}\n{{ entites_towards_and_in_distance == false and is_arrived == false }}\n",
  1463. "for": {
  1464. "hours": 0,
  1465. "minutes": 2,
  1466. "seconds": 0
  1467. }
  1468. },
  1469. {
  1470. "trigger": "template",
  1471. "value_template": "{{ expand(input_windows) | selectattr('state', 'in', ['on','open','tilted']) | list | count > 0 }}",
  1472. "for": {
  1473. "hours": 0,
  1474. "minutes": 0,
  1475. "seconds": 30
  1476. },
  1477. "id": "temperature_change_window_on"
  1478. },
  1479. {
  1480. "trigger": "template",
  1481. "value_template": "{{ expand(input_windows) | selectattr('state', 'in', ['on','open','tilted']) | list | count == 0 }}",
  1482. "for": {
  1483. "hours": 0,
  1484. "minutes": 0,
  1485. "seconds": 30
  1486. },
  1487. "id": "temperature_change_window_off"
  1488. },
  1489. {
  1490. "trigger": "template",
  1491. "id": "temperature_change_winter_mode_on",
  1492. "value_template": "{% if input_mode_winter != none %}\n {% set activation_state = iif(input_invert_winter_mode_value, 'off', 'on') %}\n {{ is_state(input_mode_winter, activation_state) }}\n{% endif %}\n",
  1493. "for": {
  1494. "hours": 0,
  1495. "minutes": 0,
  1496. "seconds": 2
  1497. }
  1498. },
  1499. {
  1500. "trigger": "template",
  1501. "id": "temperature_change_winter_mode_off",
  1502. "value_template": "{% if input_mode_winter != none %}\n {% set activation_state = iif(input_invert_winter_mode_value, 'off', 'on') %}\n {{ not is_state(input_mode_winter, activation_state) }}\n{% endif %}\n",
  1503. "for": {
  1504. "hours": 0,
  1505. "minutes": 0,
  1506. "seconds": 2
  1507. }
  1508. },
  1509. {
  1510. "trigger": "template",
  1511. "id": "temperature_change_outside_on",
  1512. "value_template": "{% if input_mode_outside_temperature == none %}\n {{ false }}\n{% else %}\n {% set outside_state = false %}\n {% set use_room_temp = input_mode_room_temperature and is_temperature_sensor_defined %}\n {% set room_state = iif(use_room_temp, false, true) %}\n\n {% set state = states(input_mode_outside_temperature) %}\n {% set state = iif(is_number(state) == true, state, state_attr(input_mode_outside_temperature,'temperature'))%}\n\n {% if is_number(state) %}\n {% set outside_state = (state | float - input_mode_outside_temperature_threshold | float) * factor < 0 %}\n {% endif %}\n\n {% if use_room_temp %}\n {% set state = states(input_temperature_sensor) %}\n\n {% if is_number(state) %}\n {% set room_state = (state | float - input_mode_room_temperature_threshold | float) * factor < 0 %}\n {% endif %}\n {% endif %}\n\n {{ room_state and outside_state }}\n{% endif %}\n",
  1513. "for": {
  1514. "hours": 0,
  1515. "minutes": 0,
  1516. "seconds": 2
  1517. }
  1518. },
  1519. {
  1520. "trigger": "template",
  1521. "id": "temperature_change_outside_off",
  1522. "value_template": "{% if input_mode_outside_temperature == none %}\n {{ false }}\n{% else %}\n {% set outside_state = false %}\n {% set use_room_temp = input_mode_room_temperature and is_temperature_sensor_defined %}\n {% set room_state = iif(use_room_temp, false, true) %}\n\n {% set state = states(input_mode_outside_temperature) %}\n {% set state = iif(is_number(state) == true, state, state_attr(input_mode_outside_temperature,'temperature'))%}\n\n {% if is_number(state) %}\n {% set outside_state = (state | float - input_mode_outside_temperature_threshold | float) * factor < 0 %}\n {% endif %}\n\n {% if use_room_temp %}\n {% set state = states(input_temperature_sensor) %}\n\n {% if is_number(state) %}\n {% set room_state = (state | float - input_mode_room_temperature_threshold | float) * factor < 0 %}\n {% endif %}\n {% endif %}\n\n {{ not (room_state and outside_state) }}\n{% endif %}\n",
  1523. "for": {
  1524. "hours": 0,
  1525. "minutes": 0,
  1526. "seconds": 2
  1527. }
  1528. },
  1529. {
  1530. "trigger": "state",
  1531. "id": "temperature_change_force_max_temperature_on",
  1532. "entity_id": [],
  1533. "for": {
  1534. "hours": 0,
  1535. "minutes": 0,
  1536. "seconds": 2
  1537. }
  1538. },
  1539. {
  1540. "trigger": "state",
  1541. "id": "temperature_change_force_eco_temperature_ds",
  1542. "entity_id": [],
  1543. "for": {
  1544. "hours": 0,
  1545. "minutes": 0,
  1546. "seconds": 2
  1547. }
  1548. },
  1549. {
  1550. "trigger": "template",
  1551. "id": "temperature_change_party_on",
  1552. "value_template": "{{ input_mode_party | expand | selectattr('state', 'in', ['active','on']) | list | count > 0 }}",
  1553. "for": {
  1554. "hours": 0,
  1555. "minutes": 0,
  1556. "seconds": 2
  1557. }
  1558. },
  1559. {
  1560. "trigger": "template",
  1561. "value_template": "{{ input_mode_party | expand | selectattr('state', 'in', ['active','on']) | list | count == 0 }}",
  1562. "id": "temperature_change_party_off",
  1563. "for": {
  1564. "hours": 0,
  1565. "minutes": 0,
  1566. "seconds": 2
  1567. }
  1568. },
  1569. {
  1570. "trigger": "state",
  1571. "id": "calibration_aggressive_mode_above_temp_thermostat_current_temp_change",
  1572. "entity_id": [
  1573. "climate.heizung_esszimmer"
  1574. ],
  1575. "attribute": "current_temperature",
  1576. "for": {
  1577. "hours": 24,
  1578. "minutes": 0,
  1579. "seconds": 0
  1580. }
  1581. },
  1582. {
  1583. "trigger": "state",
  1584. "id": "calibration_aggressive_mode_thermostat_temp_change",
  1585. "entity_id": [
  1586. "climate.heizung_esszimmer"
  1587. ],
  1588. "attribute": "temperature",
  1589. "for": {
  1590. "seconds": 30
  1591. }
  1592. },
  1593. {
  1594. "trigger": "state",
  1595. "id": "aggressive_mode_above_temp_sensor_change",
  1596. "entity_id": [],
  1597. "for": {
  1598. "seconds": 30
  1599. }
  1600. },
  1601. {
  1602. "trigger": "state",
  1603. "id": "calibration_sensor_change",
  1604. "entity_id": [],
  1605. "for": {
  1606. "hours": 24,
  1607. "minutes": 0,
  1608. "seconds": 0
  1609. }
  1610. },
  1611. {
  1612. "trigger": "state",
  1613. "id": "calibration_popp_change",
  1614. "entity_id": [],
  1615. "for": {
  1616. "seconds": 2
  1617. }
  1618. },
  1619. {
  1620. "trigger": "template",
  1621. "id": "calibration_popp_ping",
  1622. "value_template": "{% set has_valves_danfoss = input_trvs | select('is_device_attr', 'manufacturer', 'Danfoss') | list %} {% set has_valves_popp = input_trvs | select('is_device_attr', 'manufacturer', 'Popp') | list %} {% set valves_hive = input_trvs | select('is_device_attr', 'manufacturer', 'Hive') | list %}\n{% set has_valves = (has_valves_danfoss + has_valves_popp + valves_hive) | count > 0 %}\n{{ has_valves and is_temperature_sensor_defined and now().strftime('%M') | int % 10 == 0 }}\n"
  1623. },
  1624. {
  1625. "trigger": "template",
  1626. "id": "temperature_change_heating_adjustment",
  1627. "value_template": "{% set timestamp = now() %}\n{% set current_day = timestamp.strftime('%a') %} {% set current_time = timestamp.strftime('%H:%M') %}\n{% set plan = input_adjustments | rejectattr('time', 'undefined') \n | selectattr('time','eq', current_time | string)\n | sort(attribute='time', reverse = true)\n | list %}\n\n{{ plan | count > 0 and now() < now().replace(second=2) }}\n"
  1628. },
  1629. {
  1630. "trigger": "template",
  1631. "value_template": "{% if not input_liming_protection%}\n {{ false }}\n{% else %}\n {% set enable_liming = true %}\n {% if input_mode_winter != none %}\n {% set enable_liming = is_state(input_mode_winter,'on') or input_liming_in_winter %}\n {% endif %}\n\n {% set current_timestamp = now() %}\n\n {% set is_liming_day = input_liming_protection_day == as_datetime(current_timestamp).strftime('%a') %}\n\n {% set start_hour = input_liming_protection_time.split(':')[0] | int %}\n {% set start_minute = input_liming_protection_time.split(':')[1] | int %}\n\n {% set today_start = as_datetime(current_timestamp).replace(second=0,microsecond=0,hour=start_hour,minute=start_minute) %}\n {% set today_end = as_datetime(current_timestamp).replace(second=0,microsecond=0,hour=start_hour,minute=start_minute) + timedelta(minutes=input_liming_protection_duration | int) %}\n\n {% set is_liming_time = as_datetime(current_timestamp) >= today_start and as_datetime(current_timestamp) <= today_end %}\n\n {{ enable_liming and is_liming_day and is_liming_time }}\n{% endif %}\n",
  1632. "id": "temperature_change_liming_protection_on"
  1633. },
  1634. {
  1635. "trigger": "template",
  1636. "value_template": "{% if not input_liming_protection%}\n {{ false }}\n{% else %}\n {% set enable_liming = true %}\n {% if input_mode_winter != none %}\n {% set enable_liming = is_state(input_mode_winter,'on') or input_liming_in_winter %}\n {% endif %}\n\n {% set current_timestamp = now() %}\n\n {% set current_timestamp = now() %}\n\n {% set is_liming_day = input_liming_protection_day == as_datetime(current_timestamp).strftime('%a') %}\n\n {% set start_hour = input_liming_protection_time.split(':')[0] | int %}\n {% set start_minute = input_liming_protection_time.split(':')[1] | int %}\n\n {% set today_start = as_datetime(current_timestamp).replace(second=0,microsecond=0,hour=start_hour,minute=start_minute) %}\n {% set today_end = as_datetime(current_timestamp).replace(second=0,microsecond=0,hour=start_hour,minute=start_minute) + timedelta(minutes=input_liming_protection_duration | int) %}\n\n {% set is_liming_time = as_datetime(current_timestamp) >= today_start and as_datetime(current_timestamp) <= today_end %}\n\n {{ not (enable_liming and is_liming_day and is_liming_time) }}\n{% endif %}\n",
  1637. "id": "temperature_change_liming_protection_off"
  1638. },
  1639. {
  1640. "trigger": "template",
  1641. "id": "temperature_change_frost_protection_on",
  1642. "for": {
  1643. "days": 0,
  1644. "hours": 0,
  1645. "minutes": 0,
  1646. "seconds": 0
  1647. },
  1648. "value_template": "{% set now_ts = now() %} {% set frost_protection_timestamp = as_datetime(now_ts) - timedelta(**input_frost_protection_duration) %} {% if frost_protection_timestamp == now_ts %}\n {{ false }}\n{% else %}\n \n {% set relevant_entities = [input_presence_sensor] + [input_mode_guest] + input_persons %}\n {% set relevant_entities_count = relevant_entities | reject('eq',none) | list | count %}\n\n {% if relevant_entities_count > 0 %}\n {% set presence_count = [input_presence_sensor] \n | reject('eq',none)\n | reject('is_state','on')\n | list\n | count %}\n\n {% set guest_mode_count = [input_mode_guest] \n | reject('eq',none)\n | reject('is_state','on')\n | list\n | count %}\n\n {% set person_count = input_persons\n | reject('is_state','home')\n | list\n | count %}\n\n {{ presence_count + guest_mode_count + person_count == relevant_entities_count }}\n {% else %}\n {{ false }}\n {% endif %}\n{% endif %}\n"
  1649. }
  1650. ],
  1651. "id": "1739643486506",
  1652. "alias": "AUTOMATISIERUNG - Heizung Esszimmer",
  1653. "description": ""
  1654. },
  1655. "blueprint_inputs": {
  1656. "id": "1739643486506",
  1657. "alias": "AUTOMATISIERUNG - Heizung Esszimmer",
  1658. "description": "",
  1659. "use_blueprint": {
  1660. "path": "panhans/advanced_heating_control.yaml",
  1661. "input": {
  1662. "input_trvs": [
  1663. "climate.heizung_esszimmer"
  1664. ],
  1665. "input_off_instead_of_eco": false,
  1666. "input_windows": [
  1667. "binary_sensor.status_fenster_esszimmer_wohnzimmer_kuche"
  1668. ],
  1669. "input_calibration_timeout": {
  1670. "hours": 24,
  1671. "minutes": 0,
  1672. "seconds": 0
  1673. },
  1674. "input_calibration_delta": 5,
  1675. "input_calibration_step_size": "0.1",
  1676. "input_startup_delay": {
  1677. "hours": 0,
  1678. "minutes": 1,
  1679. "seconds": 0
  1680. },
  1681. "input_mode_outside_temperature_threshold": 20,
  1682. "input_window_legacy_restore": true
  1683. }
  1684. }
  1685. },
  1686. "context": {
  1687. "id": "01JS1PA359H90MAH1C6XN8ZC45",
  1688. "parent_id": "01JS1P95VNB9R4F7VHEQM89YYF",
  1689. "user_id": null
  1690. }
  1691. },
  1692. "logbookEntries": []
  1693. }

Edit this Snippet