Segway Navimow

Thanks all for the great work provided by each of you. I’ve been trying to iterate on it further together with ChatGPT and I now have a working lawn mower object in Home Assistant. The only requirement is that you have MQTT set up next to above mentioned requirements, but that is something you might have already.

I’ve written all steps within a blog article which you can find here: Integrating Segway Navimow with Home Assistant - YASH!
But if you prefer to stay within this page you can also view the additional steps I took here:

Set up a MQTT lawn mower device:

mqtt:
  lawn_mower:
    - name: "navimow i105e"
      unique_id: navimow_i105e
      activity_state_topic: "mower/navimow_i105e/state"
      activity_value_template: "{{ value_json.activity }}"
      start_mowing_command_topic: "mower/navimow_i105e/cmd"
      start_mowing_command_template: '{"action":"start"}'
      pause_command_topic: "mower/navimow_i105e/cmd"
      pause_command_template: '{"action":"pause"}'
      dock_command_topic: "mower/navimow_i105e/cmd"
      dock_command_template: '{"action":"dock"}'
      device:
        identifiers:
          - "12345"
        manufacturer: "Segway"
        model: "Navimow"
        model_id: "i105E"
        name: "Navimow i105E"
        serial_number: "12345"
  sensor:
    - name: "Navimow i105e Battery"
      unique_id: navimow_i105e_battery
      state_topic: "mower/navimow_i105e/state"
      value_template: "{{ value_json.battery | int }}"
      device_class: battery
      unit_of_measurement: "%"
      state_class: measurement
      device:
        identifiers:
          - "12345"
        manufacturer: "Segway"
        model: "Navimow"
        model_id: "i105E"
        name: "Navimow i105E"
        serial_number: "12345"

Make sure the identifiers are the same so the battery level is part of the lawn mower device.

Get status updates of the lawn mower, every 5 minutes:

- id: lawn_mower_update
  alias: "Navimow i105: Get state"
  initial_state: 'on'
  mode: restart
  description: >-
    Notes:

    * Google Assistant API rate limit: 500 requests per 24 hours (seems to reset
    at 7:00am UTC).

    * Quota status:
    https://console.cloud.google.com/apis/api/embeddedassistant.googleapis.com/quotas?...
  triggers:
    - trigger: time_pattern
      minutes: /5
    - trigger: homeassistant
      event: start
  conditions:
    - condition: numeric_state
      entity_id: sun.sun
      attribute: elevation
      above: -15
  actions:
    - action: google_assistant_sdk_custom.send_text_command
      metadata: {}
      data:
        command:
          - what is Navimow i105 battery level
          - what is Navimow i105 doing
      response_variable: result
    - variables:
        raw_status: >-
          {{ (result.responses[1].text | default(''))
             | regex_replace(
                 find='^[\\s\\S]*?Navimow\\s*i\\s*105\\s*([^.?!]+)[.?!]?.*',
                 replace='\\1',
                 ignorecase=True)
             | trim }}
        s: "{{ raw_status | lower | replace('’', \"'\") }}"
        activity: >-
          {# errors first #}
          {% if s is search('lost|error|fault|alarm|stuck|blocked|obstacle|outside|disconnected|offline', ignorecase=True) %}
            error
          {# paused #}
          {% elif s is search("\\bpause(?:d|ing|s)?\\b", ignorecase=True) %}
            paused
          {# explicitly "isn't/is not/not running" → docked #}
          {% elif s is search("\\bisn['’]?t\\s+running\\b|\\bis\\s+not\\s+running\\b|\\bnot\\s+running\\b", ignorecase=True) %}
            docked
          {# docked keywords #}
          {% elif s is search("\\b(charging|charge|base|home|station)\\b", ignorecase=True) %}
            docked
          {# "is running" / running #}
          {% elif s is search("\\bis\\s+running\\b|\\brunning\\b", ignorecase=True) %}
            mowing
          {# mowing keywords #}
          {% elif s is search("\\b(mow|cut|working|in\\s*progress)\\b", ignorecase=True) %}
            mowing
          {% else %}
            docked
          {% endif %}
        battery: >-
          {% set bt = result.responses[0].text | default('') %}
          {% if bt is search('([0-9]{1,3})\\s?(?:percent|%)', ignorecase=True) %}
            {{ bt | regex_replace(find='.*?([0-9]{1,3})\\s?(?:percent|%).*', replace='\\1', ignorecase=True) | int }}
          {% else %}
            0
          {% endif %}
    - service: mqtt.publish
      data:
        topic: mower/navimow_i105e/state
        payload: >
          {"activity":"{{ activity }}","battery":{{ battery | int }}}
        retain: true

Sent commands to the mower through MQTT and Google Assistant:

- alias: "Navimow i105: Command handler (MQTT → Google SDK)"
  id: navimow_i105_cmd_handler
  mode: single
  trigger:
    - platform: mqtt
      topic: mower/navimow_i105e/cmd
  variables:
    action: "{{ trigger.payload_json.action | default('') }}"
  action:
    - choose:
        - conditions: "{{ action == 'start' }}"
          sequence:
            - service: google_assistant_sdk_custom.send_text_command
              data:
                command:
                  - "start mowing with Navimow i105"
                  - "Navimow i105 start mowing"
        - conditions: "{{ action == 'pause' }}"
          sequence:
            - service: google_assistant_sdk_custom.send_text_command
              data:
                command:
                  - "pause Navimow i105"
                  - "Navimow i105 pause"
        - conditions: "{{ action == 'dock' }}"
          sequence:
            - service: google_assistant_sdk_custom.send_text_command
              data:
                command:
                  - "return Navimow i105 to the dock"
                  - "Navimow i105 go to base"

Unfortunately I haven’t been able yet to the lawn_mower card to work with this entity :frowning: