Need help making a sensor for my lawn mower

So I have a ‘dumb’ automatic lawnmower. I’ve attached a door sensor between the mower and the dock so I can tell if it is docked or not. I want to build a template sensor or similar so I can represent the mowers states.

Door sensor closed = Docked
Door sensor open = Mowing
Door sensor open > 2 hrs = Error

The first part seemed easy using templates. How do I represent that the mower in is error if the door sensor is open more than 2 hrs? It usually only takes an 1.5 hrs to mow my lawn and any longer than that, the mower will have got stuck on something.

      lawn_mower_status:
        value_template: '{% if states.binary_sensor.lumi_lumi_sensor_magnet_aq2_ce212304_on_off %}
          {% if states.binary_sensor.lumi_lumi_sensor_magnet_aq2_ce212304_on_off.state == "on" %}
            Mowing
          {% else %}
            Docked
          {% endif %}
          {% else %}
          n/a
          {% endif %}'
        friendly_name: 'Lawn Mower Status'

I think this should do it:

lawn_mower_status:
  entity_id: sensor.time
  value_template: >
    {% if is_state('binary_sensor.lumi_lumi_sensor_magnet_aq2_ce212304_on_off', 'on') and (as_timestamp(now()) - as_timestamp(states.binary_sensor.lumi_lumi_sensor_magnet_aq2_ce212304_on_off.last_changed)) / 60 > 120 %}
      error
    {% elif is_state('binary_sensor.lumi_lumi_sensor_magnet_aq2_ce212304_on_off.state', 'on' %}
      Mowing
    {% else %}
      Docked
    {% endif %}
  friendly_name: 'Lawn Mower Status'

Just make sure you have the time_date sensor configured:

sensor:
  - platform: time_date
    display_options:
      - 'time'
      - 'date'
      - 'date_time'
      - 'date_time_utc'
      - 'date_time_iso'
      - 'time_date'
      - 'time_utc'

Here is the complete package I use for exactly same purpose.
Few notes:

  • I use fibaro smart implant input connected to reed switch to detect mover presence in base, so you will find reference to it my package. So my actual sensor iz zwave based.
  • I also use iPhone notifications (actually after 2:15, not after 2h as descriptions would suggest (in Polish :smiley: ), it is controlled by timer that is easy to reconfigure.
  • I have 2 cards in Lovelace configured; one is showing status of mover and one is conditional, that pops up on main dashbord if automover did not returned to base.
  • input_boolean.automover_automation is used to control whole package for winter, if set to false it disables notifications and hides cards from dashboards.

Here is whole code package:

########################################################
########################################################
### Automover automation package
########################################################
########################################################
#
# Actual presence detection sensor for automover is:
# sensor.fibaro_system_fgbs222_smart_implant_burglar_5
#
########################################################
### Sensors
########################################################

sensor:
- platform: template
  sensors:
    automover_status:
      friendly_name: "Automover Status"
      value_template: >-
        {% if is_state('input_boolean.automover_automation', 'off') %}
          Automation Disabled
        {% elif is_state('input_boolean.automover_status', 'off') %}
          Charging
        {% elif is_state('input_boolean.automover_status', 'on') and is_state('input_boolean.automover_out', 'on') %}
          Did not return to the base!!!
        {% else %}  
          Working
        {% endif %}
      icon_template: >-
        {% if is_state('input_boolean.automover_status', 'off') %}
          mdi:battery-charging-50
        {% elif is_state('input_boolean.automover_status', 'on') and is_state('input_boolean.automover_out', 'on') %}
          mdi:close-box-outline
        {% else %}  
          mdi:robot-vacuum-variant
        {% endif %}


########################################################
### Input Boolean
########################################################

input_boolean:
  automover_out:
    name: Automover did not returned to base!!!
    icon: mdi:robot-vacuum-variant
    initial: off

  automover_status:
    name: Automevier Status

  automover_automation:
    name: Enable Automover automation
    icon: mdi:robot-vacuum-variant
  

#########################################################
# Timers
#########################################################
timer:
  automover:
    duration: '02:15:00'


########################################################
### Automations
########################################################

automation:
# Automover out of base
  - id: 'automover_left_base'
    alias: Automover Left Base Satation
    initial_state: true
    trigger: 
      platform: state
      entity_id: sensor.fibaro_system_fgbs222_smart_implant_burglar_5
      to: '2'
    action:
      - service: input_boolean.turn_on
        entity_id: input_boolean.automover_status
      - service: script.rotate_log
        data:
          new_log_entry: "Automover is working now"
      - service: timer.start
        entity_id: timer.automover

# Automover returned to base
  - id: 'automover_returned_to_base'
    alias: Automover Returned to Base
    initial_state: true
    trigger: 
      platform: state
      entity_id: sensor.fibaro_system_fgbs222_smart_implant_burglar_5
      to: '0'
    action:
      - service: input_boolean.turn_off
        entity_id: input_boolean.automover_out
      - service: input_boolean.turn_off
        entity_id: input_boolean.automover_status
      - service: script.rotate_log
        data:
          new_log_entry: "Automover is charging now"
      - service: timer.cancel
        entity_id: timer.automover

# Notify about automover being out of base for more than 2 hours
  - id: 'automover_out_of_base'
    alias: Automover out of base for more than 2 hours
    initial_state: True
    trigger:
    - platform: event
      event_type: timer.finished
      event_data:
        entity_id: timer.automover
    action:
      - service: notify.mobile_app_mireks_iphone
        data:
          title: "UWAGA !!!"
          message: "Kosiarka poza bazą ponad 2 godziny!"
      - service: input_boolean.turn_on
        entity_id: input_boolean.automover_out

Here is status card:

card:
  cards:
    - text: AUTOMOVER
      type: 'custom:text-divider-row'
    - aspect_ratio: 5/1
      entity: sensor.automover_status
      icon: 'mdi:robot-mower-outline'
      layout: icon_name_state
      name: Automover Status
      show_state: true
      size: 100%
      styles:
        icon:
          - color: |
              [[[
                if (entity.state == 'Charging') return 'var(--cyanish)';
                if (entity.state == 'Working') return 'var(--greenish)';
                else return 'var(--alert-text)';
              ]]]
      type: 'custom:button-card'
    - entities:
        - sensor.automover_status
      hours_to_show: 24
      refresh_interval: 5
      type: history-graph
    - entities:
        - entity: timer.automover
          name: Automover timer
      show_header_toggle: false
      type: entities
  type: 'custom:vertical-stack-in-card'
conditions:
  - entity: input_boolean.automover_automation
    state: 'on'
type: conditional

Screenshot 2020-08-23 at 4.04.53

And here is the conditional popup card:

card:
  entity: input_boolean.automover_automation
  icon: 'mdi:robot-mower-outline'
  name: Automover did not return to the base ! ! !
  size: 20%
  styles:
    icon:
      - animation: blink 2s ease infinite
      - color: 'rgb(255, 0, 0)'
  tap_action:
    action: none
  type: 'custom:button-card'
conditions:
  - entity: sensor.automover_status
    state: Did not return to the base!!!
  - entity: input_boolean.automover_automation
    state: 'on'
type: conditional

Screenshot 2020-08-23 at 4.06.35

2 Likes

Thanks. I don’t think my sensor has a last change record though.

Wow, that’s certainly more than I asked for. Great work, can’t wait to try this out.

What is script.rotate_log?

Oh, forgot to mention… I created a small custom log script to record events that I wan to know about (just few vs. standard log that records many unwanted items). This script rotate the log entries (20 entries) deleteting the oldest one and adding specific event on top of log. For the mover automation this activity can be safely deleted.

1 Like

I believe every entity in HA has a last_changed attribute.

try putting this in the template editor and see what you get:

{{ states.binary_sensor.lumi_lumi_sensor_magnet_aq2_ce212304_on_off.last_changed }}

Indeed that worked thanks! Every day’s a school day :slight_smile:

1 Like

So I did this in a very crude way for my Robomow RM400.

I’m using a Shelly 2.5 providing a 240v socket for the mower docking station.

Having monitored the power consumption(wattage) in various states, I noticed that the average values are different between;

  • Charging Stage 1,2,3,4
  • Idle in Dock
  • Cutting.

So I used the statistics template to create an average reading, and then I have an if statement off that based on the values.

It’s SUPER UGLY, but it seems to be working for me right now.
The really choppy states before the most recent cutting, were me tweaking the if statements.

 - platform: statistics
   name: "Buggy Charging Details"
   entity_id: sensor.buggy_power
   state_characteristic: average_linear
   max_age:
    minutes: 5
   sampling_size: 50
   precision: 1

   lawnmower_state_buggy:
      friendly_name: Buggy - State
      value_template: >
        {% if states.sensor.buggy_charging_details.state| float < 5.5 %}
            Idle
          {% elif states.sensor.buggy_charging_details.state| float < 8%}
            Cutting
          {% elif states.sensor.buggy_charging_details.state | float > 35 %}
            Charging Stage 1
          {% elif states.sensor.buggy_charging_details.state | float > 30 %}
            Charging Stage 2
          {% elif states.sensor.buggy_charging_details.state | float > 22 %}
            Charging Stage 3
          {% elif states.sensor.buggy_charging_details.state | float < 20 %}
            Charging Stage 4
        {% endif %}

I have automated my incredible dumb mower as per @mirekmal post.

Everything works good, with the exception of the initial sensor for registering if the mower is charging or not. I have a Fibaro wall plug, and watt is the only option I have.

The issue is that the mower is programmed to work between 0900-2100. But as you can see from the images, if the mower has started its job before 2100 it might be mowing after. Not quite sure how to set this up.

Programmed to work from 0900 - 2100:

Programmed to work from 0900-2200:

I currently have a binary sensor as this:

- platform: template
  sensors:
    robotklipper_charging:
      value_template: "{{ states('sensor.veggplugg_robotklipper_power')|float > 2 }}"

So if the mower is fully charged, but the time is after 21:00, watt drops to 1.6w, making my binary sensor registering off (for not charging = mowing).

Is there a smarter way I could set this up?

Is there any (slight) difference between power consumtion of just power supply and power supply with automover in base, but not charging?
Otherwise additional condition to be applied based on time of the day (when you could expect moving window or not, but in case of mover not returning to base just after inactivity window start it could be recognized as in base, charging finished… not easy problem.

No difference, except time.

I have tried the past couple days with the following:

- id: '1686679644003'
  alias: Automover out of base
  description: ''
  trigger:
  - platform: state
    entity_id:
    - binary_sensor.robotklipper_charging
    from: 'on'
    to: 'off'
    for:
      hours: 0
      minutes: 10
      seconds: 0
  condition:
  - condition: time
    after: 09:00:00
    before: '21:00:00'
  action:
  - service: input_boolean.turn_on
    data: {}
    target:
      entity_id: input_boolean.automover_status
  - service: timer.start
    data: {}
    target:
      entity_id: timer.automower
  mode: single
- id: '1686679794583'
  alias: Automover returned to base
  description: ''
  trigger:
  - platform: state
    entity_id:
    - binary_sensor.robotklipper_charging
    from: 'off'
    to: 'on'
    for:
      hours: 0
      minutes: 3
      seconds: 0
  condition: []
  action:
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id:
      - input_boolean.automover_out
      - input_boolean.automover_status
  - service: timer.cancel
    data: {}
    target:
      entity_id: timer.automower
  mode: single
- id: '1686679935427'
  alias: Automover being out of base for more than 2 hours
  description: ''
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.automower
  condition: []
  action:
  - service: notify.mobile_app_daniels_iphone_2
    data:
      message: Robotklipper vært ute i meir enn 2t og 15min
  - service: input_boolean.turn_on
    data: {}
    target:
      entity_id: input_boolean.automover_out
  mode: single

So far it has worked pretty good. The marked “out of base” time period was correct, the mower was stuck…under a car :sweat_smile: