Splitting sensor text result into two new helper sensors

Hey community,

I have a sensor, called sensor.wastetime that shows me the upcoming waste collection time as a text value like this:
Recycle trash in 0 days
Paper trash in 1 day
Special waste in 3 days

In order to sent this to some displays in my house, I need to split the information from this text up into 2 seperate helper text sensors: helper.text1 and helper.text2 like this:
Paper trash goes to helper.text1
in 1 day goes to helper.text2
and also skip the line that has 0 in it.
So in my example above I would start with Paper trash in 1 day, split that information and also replace the 1 day with tomorrow.

How would you do this? With an automation? With a template?

Thank you very much for your help.

Hi @monkeyking

Something like this may work:

It assumes that the source info comes from a sensor called sensor.my_waste_collection_sensor, so youā€™ll need to change this. It also assumes your text helpers are called input_text.helper_1 and input_text.helper_2.

I hope Iā€™ve understood your needs correctly. If not, you may get something out of this.

description: ""
mode: single
trigger:
  - platform: time
    at: "01:00:00"
condition: []
action:
  - service: input_text.set_value
    data:
      value: >-
        {% set sensor_text = states('sensor.my_waste_collection_sensor') %} {%
        set split_text = sensor_text.split('trash ') %} {% set helper_1_text =
        split_text[0] ~ 'trash' %} {{ helper_1_text }}
    target:
      entity_id: input_text.helper_1
  - service: input_text.set_value
    data:
      value: >-
        {% set sensor_text = states('sensor.my_waste_collection_sensor') %} {%
        set split_text = sensor_text.split('trash ') %} {% if '0 days' in split_text[1] %} 
        {% set helper_2_text = 'today' %} {% elif '1 day' in split_text[1] %} {% set
        helper_2_text = 'tomorrow' %} {% else %} {% set helper_2_text =
        split_text[1] %} {% endif %} {{ helper_2_text }}
    target:
      entity_id: input_text.helper_2

1 Like

Why do you want to use helpers?

Are you going to edit them?

If not, template sensors would be a better fit.

Thank you so much for your quick replies @templeton_nash and @tom_l !
@templeton_nash solution with the automation template, is exacly what I was looking for and it works great! Learned something new here! Thank you for that!

@tom_l but I am always open to learn different ways and things, so the goal I had was:

  1. receive waste collection times from API through Home Assistant
  2. convert and split those into 2 Helper entities text 1 and text 2
  3. send them on to the KNX BUS as 2 seperate group addresses
    - type: latin_1          # string for 16.000 or latin_1 for 16.001
      entity_id: input_text.helper_1
      address: "3/4/0"
    - type: latin_1          # string for 16.000 or latin_1 for 16.001
      entity_id: input_text.helper_2
      address: "3/4/1" 
  1. use those 2 different group address to display the Inofrmation on wall displays throughout the house.

I had to use 2 text fields, as the Information is too long and overflows the current length of the display field. Unfortunately I think you have to split up the text for KNX BUS based displays (if you donā€™t want to have a rolling text band)

How would you have solved this with template sensor? Would you be able to split the sensor as well over one template sensor? Thank you!

A rough version could be this:

You may want to add icons and availability stuff but hereā€™s a start.

template:
	- sensor:
		- name: "Waste collection type"
		  unique_id: waste_collection_type
		  state: >
			{% set sensor_text = states('sensor.my_waste_collection_sensor') %}
			{% set split_text = sensor_text.split('trash ') %}
			{% set helper_1_text = split_text[0] ~ 'trash' %}
			{{ helper_1_text }}
	- sensor:
		- name: "Waste collection due"
		  unique_id: waste_collection_due
		  state: >
			{% set sensor_text = states('sensor.my_waste_collection_sensor') %}
			{% set split_text = sensor_text.split('trash ') %}
			{% if '0 days' in split_text[1] %}
			{% set helper_2_text = 'today' %}
			{% elif '1 day' in split_text[1] %}
			{% set helper_2_text = 'tomorrow' %}
			{% else %}
			{% set helper_2_text = split_text[1] %}
			{% endif %}
			{{ helper_2_text }}

Thanks @templeton_nash . That works great as well.

But to understand the differences here for the future: why should I prefer the template script over the automation? The only differences I can think of, is that the automation has a trigger/timer and the sensor template is automatically tied to the state of the source sensor.

Anything I am overlooking? Thanks!

Hi @monkeyking

My decision to trigger the automation at 1 am each day was a bit arbitrary. I could have set it to trigger when your sensor.my_waste_collection_sensor changes. The template sensor updates automatically when this sensor changes.

The relevant difference, as @tom_l has stated, is that the input helpers provide additional functionality that you do not need and could be counterproductive. That is, they allow the text to be edited through a dashboard.

Thank you @templeton_nash taht makes sense, I will use the template then instead in this case.

One more question about this: how would you skip to the next line in the list of attributes of a sensors entity?
So for example what I try to do:

template:
	- sensor:
		- name: "Waste collection type"
		  unique_id: waste_collection_type
		  state: >
			{% set sensor_text = states('sensor.my_waste_collection_sensor') %}
            {% if '0 days' in sensor_text %}
              ## here skip to the second line of the attribute list, the next pickup date 
              {% set sensor_text = state_attr[1].('sensor.my_waste_collection_sensor') %}
			{% else %}
			  {% set split_text = sensor_text.split('trash ') %}
			  {% set helper_1_text = split_text[0] ~ 'trash' %}
			{% endif %}
			{{ helper_1_text }}

Obviously state_attr[1].('sensor.my_waste_collection_sensor') is not working for skipping to the next line of attributes / pickup dates.

Thank you for any hints how to loop through sensor attribute lines!

Hi @monkeyking

When you say ā€œskip to the second line of the attribute listā€, Iā€™m not sure what you mean. I think Iā€™ll need to see what your sensor actually outputs.

Could you use the Developer Tools > States to produce the yaml output from your sensor and post that here.

Thanks

Sure @templeton_nash !
Here is the yaml from the sensor:

"2023-11-15": Paper trash 
"2023-11-20": Plastic trash
"2023-11-22": Bio trash
"2023-11-23": Recycle trash
"2023-11-24": Paper trash
"2023-11-29": Bio trash
"2023-12-04": plastic trash
"2023-12-06": Recycle trash
daysTo: 5
attribution: "Last update: 11/10/23 09:57:06"
icon: mdi:numeric-2-box-multiple
friendly_name: Waste collection dates

I am trying to skip the first date if its down to 0 days remaining to already show the next date.
Reason: if you have two dates following directly the next day, it wonā€˜t show the day before on the screen because its still occupied by the actual today/0 day output.

Thanks a lot!

This is a bit experimental but I think you need something like this:

{% if (states.sensor.my_waste_collection_sensor.attributes.items() | list)[0][0] == now().date() %}

{% else %}

{% endif %}

Maybe @tom_l can help?

1 Like

Wow, honestly what a cool solution @templeton_nash ! This also made my initial task of splitting the sensor text so much easier and nicer! Also gave me great ideas for other sensor with listed attributes I have! Super cool, thank you for that idea!

Here is how my final two sensor looks now, one for the time remaining, one for the waste type. And they skip to the next event if its 0 days / today :slight_smile: Works really great!

Waste days remaining:

        ## check if upcoming pickup date is today
        {% if (states.sensor.waste_collection_dates.attributes.items() | list)[0][0] == now().date() %}
          ## get the remaining days of second pickup date as clear number, because first date is today
          {% set days_remaining = ((now() - (states.sensor.waste_collection_dates.attributes.items() | list)[1][0] 
          | as_datetime | as_local ).days | float(0) | abs | round(0)) %}  
            ## check if days_remaining is tomorrow or not
            {% if days_remaining == 1 %}
            Tomorrow
            {% else %}
            in {{ days_remaining }} days
            {% endif %}
        ## if date is not today, just use the first attribute of the remaining days as clear number
        {% else %}
          {% set days_remaining = ((now() - (states.sensor.waste_collection_dates.attributes.items() | list)[0][0] 
          | as_datetime | as_local ).days | float(0) | abs | round(0)) %} 
            ## check if days_remaining is tomorrow or not
            {% if days_remaining == 1 %}
            Tomorrow
            {% else %}
            in {{ days_remaining }} days
            {% endif %}
        {% endif %}

Waste type:

        ## check if upcoming pickup date is today
        {% if (states.sensor.waste_collection_dates.attributes.items() | list)[0][0] == now().date() %}
          ## get the waste_type of second pickup date, because first date is today
          {% set waste_type = (states.sensor.waste_collection_dates.attributes.items() | list)[1][1] %}  
          {{ waste_type }}
        ## if date is not today, just use the first attribute of the waste_type
        {% else %}
          {% set waste_type = (states.sensor.waste_collection_dates.attributes.items() | list)[0][1] %} 
          {{ waste_type }}
        {% endif %}   

Full final template in Home Assistant looks like:

template:
  - sensor:
    - name: "Waste collection type"
      unique_id: "waste_collection_type"
      state: >
        {% if (states.sensor.waste_collection_dates.attributes.items() | list)[0][0] == now().date() %}
          {% set waste_type = (states.sensor.waste_collection_dates.attributes.items() | list)[1][1] %}  
          {{ waste_type }}
        {% else %}
          {% set waste_type = (states.sensor.waste_collection_dates.attributes.items() | list)[0][1] %} 
          {{ waste_type }}
        {% endif %}
        
    - name: "Waste collection due"
      unique_id: "waste_collection_due"
      state: >
        {% if (states.sensor.waste_collection_dates.attributes.items() | list)[0][0] == now().date() %}
          {% set days_remaining = ((now() - (states.sensor.waste_collection_dates.attributes.items() | list)[1][0] 
          | as_datetime | as_local ).days | float(0) | abs | round(0)) %}  
            {% if days_remaining == 1 %}
            Tomorrow
            {% else %}
            in {{ days_remaining }} days
            {% endif %}
        {% else %}
          {% set days_remaining = ((now() - (states.sensor.waste_collection_dates.attributes.items() | list)[0][0] 
          | as_datetime | as_local ).days | float(0) | abs | round(0)) %} 
            {% if days_remaining == 1 %}
            Tomorrow
            {% else %}
            in {{ days_remaining }} days
            {% endif %}
        {% endif %}

Its SO amazing what you can all do with Home Assistant and the templatesā€¦literally ANYTHING is possible!

Thank you so much for your help, I learned a lot here!

Hi @monkeyking

Iā€™m glad I could help.

Home Assistant gets criticised for being difficult. In some ways it can be. But, in my experience, complexity is the price of flexibility.