Template sensor for dumb robomower

In order to know if my robomower is in the charger or mowing, I am using this template sensor:

  - sensor:
      - name: "mower"
        state: >
         {% if states("sensor.mower_mean") | float == 0 %}
           disconnected
         {% elif states("sensor.mower_mean") | float <= 3.99 %}
           charging
         {% elif states("sensor.mower_mean") | float <= 4.99 %}
           mowing
         {% else %}
           charging
         {% endif %}

It works reasonably well, but has some false mowing positives:

My YAML skills are really lacking, so need your help with improving the template sensor. I would like to do something like (in C notation…):

if { (4 <= sensor.mower_mean <= 5) && (4 <= sensor.mower_filtered <=5)
  then state = mowing;
  else state = charging;
}

As you can see, when mowing, the filtered (for zeroes) value is either 4 or 5 watts (the power plug can only report whole watts) - never anything else. The problem lies in the fact that those two values appear occasionally when charging as well. Not even a mean value gives a robust result. In addition, every mean value introduces a delay between the two states, which is undesirable.

How would you do it?

Thanks,
/Fumble

That would be something like:

- sensor:
      - name: "mower"
        state: >
         {% if states("sensor.mower_mean") | int == 0 %}
           disconnected
         {% elif ( 4 <= ( states("sensor.mower_mean") | int ) <= 5 ) and ( 4 <= ( states("sensor.mower_filtered") | int ) <= 5 ) %}
           mowing
         {% else %}
           charging
         {% endif %}

It looks like the robomower filtered power usage is changing only marginally while mowing, so an alternative approach could be to use a statistics sensor with a distance_absolute filter.
Something like:

sensor:
  - platform: statistics
    name: "mower power change"
    unique_id: uid_mower_power_change
    entity_id: sensor.mower_filtered
    state_characteristic: distance_absolute
    keep_last_sample: true
    max_age:
      minutes: 2

Let this run for a while, and play with the max_age value to get an useable output. Check whether the value only stays below a specific value while the mower is mowing, and is higher in the charging mode.
If so, you can use this value to distinct between mowing or not, probably combining this with checking for being below the fast charging value.

- sensor:
      - name: "mower"
        state: >
         {% if states("sensor.mower_mean") | int == 0 %}
           disconnected
         {% elif ( states("sensor.mower_power_change") | int < 3 ) and ( states("sensor.mower_mean") | int < 20 ) %}
           mowing
         {% else %}
           charging
         {% endif %}
1 Like

Two solutions - thank you, thank you! :grinning:
I will start with the first, right now and move on to the next if the first isn’t good enough.

/Fumble

It got better, but not good enough:

I will move on to see if statistics distance-absolute can do it better. I think I need at least three samples of 4 or 5 watts to conclude that it is indeed mowing.

/Fumble

Oh, I should clarify that I changed the mower_mean to float:

        state: >
         {% if states("sensor.mower_mean") | float == 0 %}
           disconnected
         {% elif ( 4 <= ( states("sensor.mower_mean") | float ) <= 4.95 ) and ( 4 <= ( states("sensor.mower_filtered") | int ) <= 5 ) %}
           mowing
         {% else %}
           charging
         {% endif %}

/Fumble

The initial idea didn’t work as well as I had hoped. Your idea with looking more at the statistics sensor got me going. I ended up with this bit, effectively looking at the max of four samples:

  - platform: statistics
    name: "mower max"
    entity_id: sensor.mower_filtered
    state_characteristic: value_max
    sampling_size: 4

“Mowing” is simply when mower_max is <= 5. Everything else is charging. There have been a couple glitches tonight of 20s and 10s. To get rid of those, I would have to increase the sampling_size to five, which would cost in the vicinity of another 20s in addition to the minute and a half or so it takes to identify the mowing state:


The glitches have no practical effect, other than that you want a proper indication when you look at it - which is likely daytime anyway. I would say that this is good enough:

Although I didn’t copy your idea in the end, it led to this solution and I am very grateful for that. Besides, you taught me some useful YAML as well. Big thanks!

/Fumble

Thusassistint’s idea of setting up a sensor and monitor it appealed to me, so I set up a totally different sensor to compare with.

The critical bit is to properly identify a mowing state. Anything else is charging. Analyzing the mowing state, I realized that it always starts with a pretty long (more than a minute) phase with exactly 4W consumption. After that, it can go to either 5 or 0W. With that in mind, I defined an input select helper in GUI with three states:

  • disconnected
  • mowing
  • charging
    Corresponding automations were also created in GUI:
alias: mower_disconnected
description: ""
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.nous_grasklippare_effekt
    for:
      hours: 0
      minutes: 5
      seconds: 0
    below: 1
conditions: []
actions:
  - action: input_select.set_options
    metadata: {}
    data:
      options:
        - disconnected
    target:
      entity_id: input_select.mower_status
mode: single

alias: mower_mowing
description: ""
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.nous_grasklippare_effekt
    for:
      hours: 0
      minutes: 1
      seconds: 0
    above: 3
    below: 5
conditions: []
actions:
  - action: input_select.set_options
    metadata: {}
    data:
      options:
        - mowing
    target:
      entity_id: input_select.mower_status
mode: single
alias: mower_charging
description: ""
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.nous_grasklippare_effekt
    above: 5
conditions: []
actions:
  - action: input_select.set_options
    metadata: {}
    data:
      options:
        - charging
    target:
      entity_id: input_select.mower_status
mode: single

Here is the result:


“mower_status” reacts faster than the old “mower” sensor and has zero glitches. :grinning:
On top of that, it uses 100% GUI configuration. I can now remove the stuff I made in config.yaml. Yay!
/Fumble