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:
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
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.
Nice one, @barma-lej.
Was actually thinking of making something along those lines myself - just haven’t had the time yet
Yeee, time is gold
I’m sick now with CoVID, now the time has appeared
In the next release:
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
- Download
landroid-card.js
file from the latest releae. - Put
landroid-card.js
file into yourconfig/www
folder. - Add reference to
landroid-card.js
in Lovelace
but in lovelance doesent work custom:landroid-card
where my error?
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
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.