How to extract last three digits of sensor value for automation condition

I am trying to improve an automation I have which gives an announcement when a sensor value is above certain levels.

In order to optimise, I need to be able to extract the last three digits of the sensor value. E.g. if the value is 21345, I want to use 345 in the condition of the automation.

How can I extract that value?

If your value is a string or can be converted to a string you can use string slicing:

{{ states('sensor.example')[-3:] }}

{{ (state_attr('sensor.example', 'integer')|string)[-3:] }}

Thanks for the tip, what I’m trying to do is make a condition that each time the value of the last three digits is >100 make one announcement, then again when it’s over 500, make an announcement e.g.

25123 make announcement
25543 make announcement
24789 make announcement
26101 make announcement

The first 2-3 digits can be anything and are not part of the condition, only when the values go above 100, then again above 500.

Any ideas as to a formula would be most welcome :pray:

It would be helpful if you describe the goals, function, and design of the automation as you see it. It seems like you want the condition to pass when the last three digits’ have any value above 99
 but I don’t think that’s really what you want.

Does the value only increase, or does it fluctuate up and down?

Should the condition pass for value changes in both directions?

If it is numbers, then %1000
% instead of / is just a division, but instead of returning the normal result it will return the rest of an integer division, ie. 25123%1000=123

1 Like

Thanks @WallyR that does indeed get the last three digits, now I need to work out the conditions.

@Didgeridrew here is my current automation which works, and hopefully shows what I am trying to achieve. The question is how can I get rid of all the numeric_state triggers and replace with a more efficient way of achieving the same result. Currently there are lots more triggers than listed below, which I have cut out to make it more readable here. The sensor value can go up & down.

alias: sensor announcement
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.mysensor
    above: 41100
  - platform: numeric_state
    entity_id: sensor.mysensor
    above: 41500
  - platform: numeric_state
    entity_id: sensor.mysensor
    above: 42100
  - platform: numeric_state
    entity_id: sensor.mysensor
    above: 42500
  - platform: numeric_state
    entity_id: sensor.mysensor
    above: 43100
condition:
  - condition: time
    after: "08:00:00"
    before: "00:00:00"
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
      - sat
      - sun
action:
  - service: notify.alexa_media_echo_dot
    data:
      message: >-
        "<amazon:emotion name='excited' intensity='high'>Hey, sensor is now {{
        states('sensor.mysensor')|int }} </amazon:emotion>"
      data:
        type: announce
        method: emotion
mode: single

Are all the triggers based on above values? We need to know whether you want it to only trigger on rising values or on both rising and falling values.

Use value_template to modify the input signal to the trigger:

  - platform: numeric_state
    entity_id: sensor.mysensor
    value_template: "{{ state.state[-3:]|int(0) }}"
    above: 100
    id: message_100
  - platform: numeric_state
    entity_id: sensor.mysensor
    value_template: "{{ state.state[-3:]|int(0) }}"
    above: 500
    id: message_500

Then use the value of trigger.id in the action if you need to give different messages. If you don’t need that, you can remove the id: lines.

This might not trigger as you expect, though. If the sensor goes from say 42000 to 42150, the “>100” trigger will fire. If it then goes from 42150 to 43120, I don’t think anything will happen.

If you care about that, you need to work out a description of what you want to happen in such cases. Perhaps this for 100, which will fire for every state change above xx100:

trigger:
  - platform: state
    entity_id: sensor.mysensor
condition:
  - "{{ trigger.to_state.state|int(0) % 1000 > 100 }}"
action:
   ACTION HERE

Add some examples when you don’t want an announcement.

1 Like

IIRC, those should be value_template: "{{ state.state[-3:]|int(0) }}".

However, I don’t think that trigger is going to work the way OP seems to want, but they’ve been a bit vague


2 Likes

Thanks, you’re right. Fixed.

Thanks everyone, I will test the above and let you know if it works as I wanted (I think it will) :slight_smile: - Your help is very much appreciated!

After experimenting, I found it didn’t trigger at all when the sensor was updated, however, I changed the state.state to:

value_template: “{{ (states.mysensor|int) % 1000 }}”

And it now triggers based on the 100/500 values. However, it now triggers every time the sensor is updated where >500 is true e.g. if the sensor updates to 550, it’s trigger, 600 it’s triggered etc

On my original method above, it only triggered once per trigger value. Is there a way to replicate that? So stop it triggering again until it reaches the next value (100 or 500)?

Try {{((((states(‘mysensor’)|int)/100)|int) % 10)*100 }}

It is a using int as a way to round, so you only get the hundreds digit.
You can remove the last *100 if you want to use a single digit in your triggers instead, so 5 for 500 and 2 for 200 and so on.

You can also do it with a round function if you want. The important thing here is that it stays at the same number in the hundred interval.

What if it skips a value: e.g. 23150 to 24120? See my prior post: please give more details of how you want this to work?

Thanks for the tip, I can get the value using the method I mentioned above, the problem now is as below


It would be very rare for that to happen, so I don’t mind if 23500+ announcement was skipped and just the 24120 announcement was made.

At the moment, if the sensor value is above 100, it’s being triggered, if above 500, it’s being triggered twice after it updates (once for the 100 and one for the 500 trigger).

I would like it to trigger once when the value goes above xx100, then not trigger again until the value goes above xx500. That could be either;

24100 → 23400 → 23550 = trigger
or
24100 → 24550 = trigger

trigger:
  - platform: template
    value_template: |-
      {% set val = states('sensor.mysensor')|int % 1000 %}
      {{ 100 < val < 500 }}
  - platform: template
    value_template: |-
      {% set val = states('sensor.mysensor')|int % 1000 %}
      {{ val > 500 }}
    id: five
condition:
  - condition: template
    value_template: |-
      {% set diff = trigger.from_state.state |int % 1000 %}
      {{ diff <= 500 if trigger.id == 'five' else ( 100 >= diff or diff >= 500 )}}

The calculation I made will give you 100,200,300 and so on as result. (if you removed the *100, then it would be 1,2,3 and so on)
If your trigger is made to trigger on the value and not with the above attribute, then you should work.

trigger:
  - platform: state
    entity_id: sensor.mysensor
condition:
  - condition: template
    value_template: >
      {% set old = trigger.from_state.state %}
      {% set new = trigger.to_state.state %}
      {% set oldpre = old[:-3] %}
      {% set newpre = new[:-3] %}
      {% set oldsuf = old[-3:]|int %}
      {% set newsuf = new[-3:]|int %}
      {{ (oldsuf <= 100 and newsuf > 100) or
         (oldsuf <= 500 and newsuf > 500) or
         (oldpre != newpre and newsuf > 100) or
         (oldpre != newpre and newsuf > 500) }}
action:
  - NOTIFICATION HERE

The four lines of logic should cover cases like:

  1. 23080 » 23105
  2. 23480 » 23510
  3. 23150 » 24120
  4. 23550 » 24510

It relies on the sensor state always being a numeric string of at least three digits.

It will also trigger on e.g. 25600 » 23105 (old prefix different from new, suffix above 100). If you don’t want that, either tweak the logic above or explain the rules in even more detail.

The first digits are part of the condition if we need to use them to distinguish 23120 » 23250 (no action) versus 23120 » 24250 (action).

You haven’t answered either of these important questions. I’ve assumed either in my logic, taking the prefix part of the sensor state as a “token”, not caring what its numeric value is but only comparing before and after.

Thanks for the updated conditions and your time on this (I am learning a lot by seeing them), I will test them out later.

Yes, the sensor value goes up and down and the condition should pass in both directions. The likely range of the sensor is between 1,000 to 1,000,000 (unlikely to go outside of that range).

It should trigger for both rising and falling values. It would be great if I could tell if it was a rise or fall in the action but that’s more of a nice to have than must have.

Using the new conditions, the sensor value has just changed from 20933 to 21263 (which should have triggered) but it didn’t trigger, trace says it failed a condition.