I am trying to use the new local calendar feature as a means to schedule radiator thermostats, but am having trouble picking up the trigger variables. It is not much documented or discussed yet so I do not know whether I am doing something wrong or have found bugs?
I define a local calendar for each radiator. Calendar events are for a period of time for which the radiator is to be set to a given temperature, which I write in the description field to one decimal place.
The automation needs the name of the event, the start time and the temperature (from the description). I am not sure about the required format for the start time or the casting of the description to a number, so for test purposes I defined input_text variables for these as well the and input_datetime and input_number variables that I would normally use.
Calendar event attributes cannot be read at any arbitrary time, as far as I can tell, so I am picking them up from the trigger variables in an automation that is triggered by the start of an event in the calendar. As I am writing to input variables I can read them anywhere and see them on a dashboard too.
I use the visual editor to create the automation, but the trigger variables have to be read using YAML. The event name is read as value: "{{ trigger.calendar_event.summary }}". I put this is an input_text variable. The start time is read as value: "{{ trigger.calendar_event.start }}". I put this in both an input_text variable and an input_datetime variable. I have also tried "{{ states(' trigger.calendar_event.start') }}" but that did not help. The description is read as value: "{{ trigger.calendar_event.description }}". I put this is an input_text variable. The required temperature is extracted with value: "{{ states ('trigger.calendar_event.description') | float(1) }}". I put this in an input_number variable.
Results:
The event name (summary) is read with no problem.
The start time is not read either as text or as date-time.
The description is read as text but the value cast to a number is not written (the input_number retains its default minimum value).
It would be easier to help is you provided the whole automation. From the visual editor click the 3-dots/kebab menu button on the top right and select “Edit in YAML”. Copy the contents and paste them here, starting and ending with 3 backticks (```).
The input_datetime.set_datetime service is particular about the format in which the data is passed to it. The trigger.calendar_event.start variable returns a time-zone aware datetime string that requires filtering to work with this service. What type of Input datetime are you using… time-only, date-only, time-and-date?
### radiator target temperature ###
- platform: template
sensors:
radiator_1_set_temperature:
friendly_name: Radiator 1 set temperature
unique_id: "3011e180-08a0-4cef-9793-e2c0a13e57e2"
unit_of_measurement: 'C'
icon_template: mdi:thermometer
value_template: "{{ state_attr('climate.radiator_1_thermostat_moesthermostat_2', 'temperature') }}"
### radiator measured temperature ###
radiator_1_ambient_temperature:
friendly_name: Radiator 1 ambient temperature
unique_id: "7b5b54c2-277e-486a-be67-3f0c93c17894"
unit_of_measurement: 'C'
icon_template: mdi:thermometer
value_template: "{{ state_attr('climate.radiator_1_thermostat_moesthermostat_2', 'current_temperature') }}"
Tests are ongoing but most of it works except the calendar event scheduling. When testing is complete I want to make it into a Blueprint where everything starting radiator_1 or radiator _x will be parameterised. I welcome any comments on how the code could be made more robust, simplified or streamlined.
I am using time and date so that I can calculate elapsed time since the start of the event even if it runs overnight.
It seems I changed something because since writing the first post the ‘radiator 2’ test version is working for date and time (though not for temperature), but the radiator X version is not, while I cannot spot the difference in the code!?!
When you wrap it in quotes, you turn the trigger variable into a string. In that process it’s data is stripped and thrown away. So {{ states('trigger.calendar_event.summary') }} is trying to get the state of a nonsense string and will just returns a None value.
Then you have an == comparison outside the template. When thing are not within the bounds of the curly braces, they do not have the function they have inside the braces. They just become part of a string.
I understand the bit about the comparison; thanks for spotting that. (I had not tested this section yet so did not see that it failed).
I am not clear what you think I ‘tidied up’ in the radiator 2 example? Examining the code where input_text, input_number or input_datetime are set they both look the same to me, so is it a matter of context?
When setting a value to an input_ variable, I was confused by when to add the quotes. By experiment (Radiator 2) I found that while {{ ... }} works in the template editor, value: {{ ... }} does not work in the automation; I have to write value: "{{ ... }}" (with the quotes). Is that correct?
I often have trouble getting the automation editor to save changes. If I use edit YAML locally to set the value within a call service … input_number set it sometimes does not give me the “save” button, and sometimes appears to save the value but when I go back it has replaced the value with “null”. What is going on here?
Now I want to tidy up the extraction of the temperature from the description. I decided to put the temperature between two # symbols, then I can write other stuff in the description as well. I could not find any more general way of extracting a number from string. It is annoying to have to wait 15 minutes for each calendar test, so I wrote an even simpler test automation that just triggers when an input_text variable changes and writes an input_number. The expression
… works nicely in the template editor but I cannot get it into the automaton! From the test text “Set temperature to #24.987# C” it correctly returns “24.9” in the template editor. The automation editor says “Message malformed: template value should be a string for dictionary value @ data[‘action’][0][‘data’]”. If I edit the YAML overall it appears to accept it but replaces the value with ‘null’ after I save.
Solved point 5 myself, though the template editor is no help here! The problem is in the quotation mark types. The template content must avoid the double quotes used to enclose the whole thing – so this works:
Temperature is not working because the template contained in that service has the states('trigger.....') issue I outlined in my previous post, as seen below.
Placing quotes around YAML configuration variable keys does not work. The following is invalid because there is essentially no key.
'value: {{ states("sensor.example") }}'
#4
I have had that happen before as well. For me it is most often due to an invalid template construction. Commonly it’s when I do something silly like forget to use single and double quote marks properly. When you fail to alternate single and double quotes as shown here:
value: "{{ states("sensor.example") }}"
The interpreter sees something like value: "{{states(" which throws an error because your template isn’t closed out. In the UI editor it just gets overwritten with null.
Sorry I did not fully understand what you meant by the states('trigger.....') issue. I think you are saying I cannot read a trigger with the states method but can just access it as a variable in the outer part of the template??
For my more advanced formula to extract the temperature from between hashes in a longer text description, should I store the description first in input_text.radiator_x_description and then read that with states?
#4
That’s probably it. My problem was that the template editor does not show up erroneous alternation of quote marks in the same way so it took me ages to spot it. The formulation I noted above …
…is accepted; i.e. my smallest test automation is working. I am now working my way back to the ‘Radiator 2’ test and then to the full ‘Radiator X’ automation.
I am closing this thread now. Thanks to @Didgeridrew for the help.
To summarise for anyone else following this:
Having a template working in the template editor does not mean it will work in an automation!
When using a template to provide a value is has to be quoted '{{ ... }}', so there should be none of the same type of quotes inside the template; use a different kind of quotes
The error “Message malformed: template value should be a string …" often mean that there is a mismatching of quote signs
Trigger variables cannot be read using states(' ... '), but they can be read with e.g.
value: '{{trigger.calendar_event.start}}'
To perform operations on trigger variables the value must therefore first be stored in a local variable or a global ‘helper’ variable. I use the latter because I need the value to persist and to be available on a dashboard. this example extracts a number enclosed in hash characters from the description field in a local calendar – I use it for the scheduled set temperature or a radiator: