Worx Landroid Package (Deprecated)

Looks great! Works well on dark backgrounds too, shown here in a landscape orientation and combined with some square button-cards and mini-graph-cards:

3 Likes

Hi, looks fantastic. Can you share the code for the button cards and where you found the service info

Button cards are using the switch entities created by @Barmalej’s package. My button design is based on @Mattias_Persson’s UI design, but you could also use the default button-card 'Apple Homekit-like buttons.

Homekit-like buttons
- type: custom:button-card
  entity: switch.mower_mowing
  show_state: true
  styles:
    card:
      - width: 100px
      - height: 100px
    grid:
      - grid-template-areas: '"i" "n" "s"'
      - grid-template-columns: 1fr
      - grid-template-rows: 1fr min-content min-content
    img_cell:
      - align-self: start
      - text-align: start
    name:
      - justify-self: start
      - padding-left: 10px
      - font-weight: bold
      - text-transform: lowercase
    state:
      - justify-self: start
      - padding-left: 10px
  state:
    - value: 'off'
      styles:
        card:
          - filter: opacity(50%)
        icon:
          - filter: grayscale(100%)
My button-card template
  base:
    variables:
      state: |
        [[[ return entity === undefined || entity.state; ]]]
    aspect_ratio: 1/1
    tap_action:
      action: toggle
      haptic: medium
      ui_sound_tablet: |
        [[[
          let screensaver = states[variables.entity_tablet] === undefined || 
            states[variables.entity_tablet].state;

          if (screensaver === 'off') {
            hass.callService('media_player', 'play_media', {
              entity_id: variables.entity_browser_mod,
              media_content_id: '/local/sound/tap.m4a',
              media_content_type: 'music'
            });
          }
        ]]]
      animation_card: |
        [[[
          let time = 900;
          this.shadowRoot.getElementById('card').style.animation =
            `card_bounce ${time}ms cubic-bezier(0.22, 1, 0.36, 1)`,
            window.setTimeout(() => {
              this.shadowRoot.getElementById('card').style.animation = 'none'
            }, time);
        ]]]
    hold_action:
      action: more-info
      haptic: success
    show_state: true
    styles:
      card:
        - font-size: 13px
        - padding-right: 5px
      icon:
        - color: var(--text-color)
        - width: 25px
        - align-items: start
        - justify-content: start
        - margin-left: 0px
        - margin-top: '-30px'
      grid:
        - grid-template-areas: '"i l l w" "n n n n" "s s s s"'
        - grid-template-columns: 0.35fr 0.15fr 0.15fr 0.3fr
        - grid-template-rows: 1fr min-content min-content
        - align-items: start
      img_cell:
        - align-self: start
        - text-align: start
      name:
        - justify-self: start
        - padding: 0 10px 5px 10px
      state:
        - justify-self: start
        - padding-left: 10px
        - padding-bottom: 5px
        - font-size: 15px
      custom_fields:
        w:
          - justify-content: flex-end
          - align-items: flex-end
          - padding-top: 10px
          - color: '#c9c9c9'
    custom_fields:
      w: |
        [[[
          var pow = Math.round(states[entity.entity_id].attributes.current_power_w);
          if (entity.state == "on" && pow > 0) return pow + `W`; 
          else return ``;
        ]]]
    state:
      - value: 'on'
        styles:
          card:
            - background-color: var(--accent-color)
      - value: 'off'
        styles:
          state:
            - color: var(--disabled-text-color)
          custom_fields:
            custom_state:
              - color: var(--disabled-text-color)
      - value: unlocked
        styles:
          card:
            - background-color: '#ff9800'
      - value: locked
        styles:
          state:
            - color: var(--disabled-text-color)
          custom_fields:
            custom_state:
              - color: var(--disabled-text-color)
      - value: open
        styles:
          card:
            - background-color: var(--accent-color)
      - value: closed
        styles:
          state:
            - color: var(--disabled-text-color)
    extra_styles: |
      [[[
        return `
          #container {
            text-align: left !important;
          }
          @keyframes card_bounce {
            0% {
              transform: scale(1);
            }
            15% {
              transform: scale(0.9);
            }
            25% {
              transform: scale(1);
            }
            30% {
              transform: scale(0.98);
            }
            100% {
              transform: scale(1);
            }
          }
          .marquee {
            animation: marquee 20s linear infinite;
          }
          @keyframes marquee {
            from {
              transform: translateX(0%);
            }
            to {
              transform: translateX(-50%);
            }
          }
        `
      ]]]

Mini-graph-cards:

Battery
          - type: custom:mini-graph-card
            style:
              .icon ha-icon:
                $: |
                  ha-svg-icon {
                    height: 15px;
                  }
            font_size_header: 10
            font_size: 60
            name: Battery
            entities:
              - entity: sensor.mower_battery
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 0
            align_icon: right
            color_thresholds:
              - value: 80
                color: '#3ab54a'
              - value: 50
                color: '#05f7f9'
              - value: 30
                color: '#ff9e07'
              - value: 15
                color: '#fe0000'
Battery temperature
          - type: custom:mini-graph-card
            font_size_header: 10
            font_size: 70
            name: Battery temp.
            entities:
              - entity: sensor.mower_battery_temperature
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 1
            align_icon: right
            color_thresholds:
              - value: 30
                color: '#fe0000'
              - value: 25
                color: '#ff9e07'
              - value: 20
                color: '#3ab54a'
              - value: 15
                color: '#05f7f9'
              - value: 10
                color: '#00ccff'
              - value: 5
                color: '#017eff'
              - value: 0
                color: '#7030a2'
              - value: -10
                color: '#980299'
              - value: -15
                color: '#cc0199'
            style:
              .icon ha-icon:
                $: |
                  ha-svg-icon {
                    height: 15px;
                  }
Total distance
          - type: custom:mini-graph-card
            font_size_header: 10
            font_size: 70
            name: Total distance
            entities:
              - entity: sensor.mower_distance
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 0
            show:
              icon: false
            align_icon: right

Also added one sensor to landroid.yaml in order to get the battery temperature:

      - name: "mower_battery_temperature"
        unique_id: mower_battery_temperature
        state: "{{ state_attr('vacuum.mower','battery_temperature') | float }}"
        device_class: temperature
        unit_of_measurement: "°C"

Here’s the full source code of my Landroid Lovelace dashboard, if you’re interested:

Code
type: vertical-stack
cards:
  - type: custom:gap-card
    height: 10
  - type: custom:html-card
    content: Mururobot
    style: |
      .type-custom-html-card {
        font-size: 30px;
        font-weight: 300;
        background: none;
        box-shadow: none;
      }
  - type: horizontal-stack
    cards:
      - square: true
        columns: 3
        type: grid
        cards:
          - type: custom:button-card
            entity: vacuum.mower
            template: base
            icon: mdi:robot-mower
            tap_action:
              action: more-info
            show_state: true
            show_name: false
            styles:
              grid:
                - grid-template-areas: >-
                    "i l l w" "s s s s" "custom_state custom_state custom_state
                    custom_state"
              custom_fields:
                custom_state:
                  - justify-self: start
                  - padding: 0 10px 5px 10px
            custom_fields:
              custom_state: |
                [[[
                  var num = entity.attributes.rain_delay_remaining;
                  var hours = (num / 60);
                  var rhours = Math.floor(hours);
                  var minutes = (hours - rhours) * 60;
                  var rminutes = Math.round(minutes);
                  if(entity.attributes.error == "rain delay" && entity.attributes.rain_sensor_triggered === false) 
                    if(rhours > 0)
                      return rhours + "h " + rminutes + "min to go";
                    else return rminutes + "min to go";
                  else if(entity.attributes.error == "rain delay" && entity.attributes.rain_sensor_triggered === true)
                    return "Sensor wet";
                  else return entity.attributes.error;
                ]]]
            state:
              - value: error
                styles:
                  card:
                    - background-color: var(--alarm-color-armed)
              - value: mowing
                styles:
                  card:
                    - background-color: var(--label-badge-green)
          - type: custom:button-card
            entity: switch.mower_mowing
            template: base
          - type: custom:button-card
            entity: switch.mower_home
            template: base
          - type: custom:mini-graph-card
            style:
              .icon ha-icon:
                $: |
                  ha-svg-icon {
                    height: 15px;
                  }
            font_size_header: 10
            font_size: 60
            name: Battery
            entities:
              - entity: sensor.mower_battery
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 0
            align_icon: right
            color_thresholds:
              - value: 80
                color: '#3ab54a'
              - value: 50
                color: '#05f7f9'
              - value: 30
                color: '#ff9e07'
              - value: 15
                color: '#fe0000'
          - type: custom:button-card
            entity: switch.mower_edgecut
            template: base
          - type: custom:button-card
            entity: switch.mower_partymode
            template: base
          - type: custom:mini-graph-card
            font_size_header: 10
            font_size: 70
            name: Wifi
            entities:
              - entity: sensor.mower_wifi
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 0
            align_icon: right
            color_thresholds:
              - value: -50
                color: '#3ab54a'
              - value: -70
                color: '#05f7f9'
              - value: -80
                color: '#ff9e07'
              - value: -90
                color: '#fe0000'
            style:
              .icon ha-icon:
                $: |
                  ha-svg-icon {
                    height: 15px;
                  }
          - type: custom:mini-graph-card
            font_size_header: 10
            font_size: 70
            name: Battery temp.
            entities:
              - entity: sensor.mower_battery_temperature
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 1
            align_icon: right
            color_thresholds:
              - value: 30
                color: '#fe0000'
              - value: 25
                color: '#ff9e07'
              - value: 20
                color: '#3ab54a'
              - value: 15
                color: '#05f7f9'
              - value: 10
                color: '#00ccff'
              - value: 5
                color: '#017eff'
              - value: 0
                color: '#7030a2'
              - value: -10
                color: '#980299'
              - value: -15
                color: '#cc0199'
            style:
              .icon ha-icon:
                $: |
                  ha-svg-icon {
                    height: 15px;
                  }
          - type: custom:mini-graph-card
            font_size_header: 10
            font_size: 70
            name: Total distance
            entities:
              - entity: sensor.mower_distance
            hours_to_show: 48
            points_per_hour: 2
            hour24: true
            decimals: 0
            show:
              icon: false
            align_icon: right
      - type: vertical-stack
        cards:
          - type: custom:landroid-card
            entity: vacuum.mower
            image: default
            compact_view: false
            show_status: true
            show_name: true
            show_toolbar: true
            stats:
              default:
                - attribute: total_blade_time
                  subtitle: Total blade time
                  value_template: '{{ as_timedelta((value | float(0) * 60) | string) }}'
                - attribute: current_blade_time
                  subtitle: Current blade time
                  value_template: '{{ as_timedelta((value | float(0) * 60) | string) }}'
                - attribute: work_time
                  subtitle: Work time
                  value_template: '{{ as_timedelta((value | float(0) * 60) | string) }}'
                - attribute: distance
                  value_template: '{{ (value | float(0) / 1000) | round(3) }}'
                  unit: km
                  subtitle: Distance
              mowing:
                - attribute: yaw
                  subtitle: Yaw
                  unit: °
                - attribute: roll
                  subtitle: Roll
                  unit: °
                - attribute: pitch
                  subtitle: Pitch
                  unit: °
            shortcuts:
              - name: Clean living room
                service: script.clean_living_room
                icon: mdi:sofa
              - name: Clean bedroom
                service: script.clean_bedroom
                icon: mdi:bed-empty
              - name: Clean kitchen
                service: script.clean_kitchen
                icon: mdi:silverware-fork-knife

2 Likes

Hi, i already installed it today and i got this .
What i am doing wrong?

1 Like

I don’t understand why I have this error when I check my configuration:
Package landroid setup failed. Component script cannot be merged. Dict expected in main config.

In configuration.yaml:

homeassistant:
  packages: !include_dir_named packages

and packages directory contains:

  • landroid.yaml
  • landroid_fr.yaml

What is wrong ?

Thanks in advance

Looking forward to see the new card in a stable version! If you could please also put just the clean image file of the mower, I am using a mix of the new and old with some extra custom buttons and entities for the options i need. This way it’s easier on my (small) wall tablet to activate the actions. I also cannot use the transparent effect to match the button/entity card.

Thank you , great job, if you need help for testing let me know.

https://raw.githubusercontent.com/Barma-lej/landroid-card/master/src/landroid.svg

1 Like

Nice one, @barma-lej.
Was actually thinking of making something along those lines myself - just haven’t had the time yet :smiley:

Yeee, time is gold :slightly_smiling_face:
I’m sick now with CoVID, now the time has appeared :see_no_evil:
In the next release:
Screenshot 2022-07-01 184522

2 Likes

Thank you for your valuable work and fast recovery!

A few minutes ago I was just too curious and updated the Landroid Cloud to brand new 2.1.4 version.
Now 2.0.3 is not available anymore to download directly from hacs, only on github.
Struggling to install it manually.
@everybody, do not repeat my error. 2.0.3 is still the last version usable for Landroid Cloud, or I need to learn something. What?

Later edit:
I managed to install manually Landroid Cloud 2.0.3, error was something about pyworxcloud 2.1.8 which was not released yet. Just to find out that MTrab just released the new version and another user confirmed it working.

Hi all, I have this installed and working perfectly with my Landroid S300 - thank you for this!

I’m wondering - I have 2 zones setup. The native Landroid app doesn’t allow you to schedule zones separately, is this possible with this package and a HA automation?

If yes, what service etc would I need to call in an automation to tell the mower to cut zone 2 please?

Any advice appreciated.

G

I have Landroid Cloud 2.0.3

  1. Download landroid-card.js file from the latest releae.
  2. Put landroid-card.js file into your config/www folder.
  3. Add reference to landroid-card.js in Lovelace

but in lovelance doesent work custom:landroid-card
where my error?Schermata 2022-07-04 alle 12.25.45


Schermata 2022-07-04 alle 12.27.53

I have the same, but with yaml lovelace configuration

does it work for you?

Please try to add repository to HACS and install from it
Correct works only with Landroid Cloud >2.1

Yes - you can override the next mowed zone with som automation and the landroid_cloud integration

1 Like

Thank you for replying.

Can you advise which service or script I would need to call to enact that automation please?

Thanks,
Gareth

MTrab/landroid_cloud: Landroid Cloud component for Home Assistant (github.com)
Here you can see the services.
Not fully up to date, but setzone is mentioned.

1 Like

Thank you, I think I am calling the correct service (shown below), however I am unsure what data needs to be attributed to it to tell the mower to go to zone 2, for example.

Do I call this script from automation?

Or am I better calling this service?

What is the difference?