Count substring occurences inside a string returned from sensor

So I leaned something new today.

When templates reference themselves (e.g. using this) they resolve twice.

Going to have to think of a new approach.

1 Like

Template entities resolve twice. Because of availability, we update when the state updates, then we check the availability and resolve the state again. This causes this.state to increment twice if you’re using it as a counter.

IIRC, if you omit availability, it should only resolve once but I could be wrong on that. It’s been a while since I’ve looked at that portion of the code. I do know it’s unavoidable unless the system is overhauled, which I’m not willing to do.

So increment by 0.5 then :slight_smile:

There’s still the missing counts too though.

trigger based template entities avoid this all together, or at least they should. FYI.

It’s only affected by state based template entities because each template is asyncronous, leading to order of operation issues when things are updated at the same time.

Trigger based template entities only update with the trigger and check availability first, then state, then all the rest (in any order).

thank you @petro and @tom_l ; first attempt will be with the path with the least effort so I’ll give it a try at adding just 0.5 :slight_smile:

I’ll keep you aligned with the results…

A trigger based template would be easier if you’re already using yaml :wink:

template:
  - triggers:
    - trigger: state
      entity_id: input_text.zyxel
    sensor:
    - name: "B7 Count"
      unique_id: "B7_count"
      state: >
        {% if this is defined %}
          {% if 'B7' in trigger.to_state.state %}
            {{ this.state|int(0) + 1 }}
          {% else %}
            {{ this.state|int(0) }}
          {% endif %}
        {% else %}
          0
        {% endif %}

Just understand that trigger based template entities restore state on restart. So this should always count up, forever.

1 Like
template:
  - triggers:
    - trigger: state
      entity_id: input_text.zyxel

That was Hellis81’s.

template:
  - triggers:
    - trigger: state
      entity_id: sensor.zyxel_cellular_intf_current_band
    sensor:
    - name: "B7 Count"
      unique_id: "B7_count"
      state: >
        {% if this is defined %}
          {% if 'B7' in trigger.to_state.state %}
            {{ this.state|int(0) + 1 }}
          {% else %}
            {{ this.state|int(0) }}
          {% endif %}
        {% else %}
          0
        {% endif %}
1 Like

Working for me :man_shrugging:

Keep in mind, with input texts, you need to click enter on your keyboard to enter the state.

firefox_hlATzETs06

Tom meant you used the wrong entity ID in the code.
It should not be input_text for OP.
The input text code was just mine for testing, as you also did.
But for OP the code should be the sensor…

1 Like

hi @tom_l the try with 0.5 increment didn’t worked

  - name: "B7 Count"
    unique_id: "B7_count"
    state: >
      {% if this is defined %}
        {% if 'B7' in states('sensor.zyxel_cellular_intf_current_band') %}
          {{ this.state|int(0) + 0.5 }}
        {% else %}
          {{ this.state|int(0) }}
        {% endif %}
      {% else %}
        0
      {% endif %}
  - name: "B1 Count"
    unique_id: "B1_count"
    state: >
      {% if this is defined %}
        {% if 'B1' in states('sensor.zyxel_cellular_intf_current_band') %}
          {{ this.state|int(0) + 0.5 }}
        {% else %}
          {{ this.state|int(0) }}
        {% endif %}
      {% else %}
        0
      {% endif %}
...

now I get even less sensors incremented and the max is the value 0.5

I’ll give a try to @petro suggestion at using trigger based template and I’ll report back.

in the meanwhile thank you all for your help and time, I really appreciate it!

I was joking, you should definitely use the triggered template sensor.

1 Like

After a week of testing I can confirm that the triggered template sensor it’s working as a charm! thank you to all that contributed and of course to @petro and @tom_l for having guided me to the solution.

All the best!

Interesting thread - in a number of ways.

I know this has been solved, but when I read the original post from @qm28jSLtTnkW, I thought an automation would be the way to go instead of creating separate templates. For one thing, maybe you would want to know when there’s a band that doesn’t have a template sensor defined.

One question, if the state changes from B7,B1,B3 to (say) B7,B1,B3,B4 i.e. only B4 was added, would you increment just that one or all of them?

Does sensor.zyxel_cellular_intf_current_band get updated periodically or only when a band is added or removed?

Anyway, I was curious so did it as an automation. Pros and cons over the template approach?

alias: Test increment bands
description: ""
triggers:
  - trigger: state
    entity_id:
      - input_text.zyxel_band
conditions: []
actions:
  - variables:
      bands: "{{ states(trigger.entity_id) }}"
  - repeat:
      for_each: "{{ bands.split(',') }}"
      sequence:
        - variables:
            this_band: "{{ repeat.item|trim }}"
            counter_entity: counter.zyxl_band_{{ this_band }}
        - if:
            - condition: template
              value_template: "{{ states(counter_entity) != 'unknown' }}"
          then:
            - action: counter.increment
              metadata: {}
              data: {}
              target:
                entity_id: "{{ counter_entity }}"
          else:
            - action: persistent_notification.create
              metadata: {}
              data:
                message: >-
                  Received band update of "{{ this_band }}" in "{{ bands }}",
                  but counter "{{ counter_entity }}" does not exist.
mode: queued

The difference is that you need to pre set up the counter with a paired automation where the template entities are a single template section with mutiple sensors. Everything in 1 place requiring no setup from the UI before hand. In fact, if you turn this into a single template entity with band names as the attributes, you can have n number of counters with a single template entity. No additional setup.