Hi,
have you solved the problem for displaying the “stanze da pulire”? I still see the message “stanze da pulire: unknow”
After a few hours it also works on the app!
Thanks!
I see all the fields except the status…
Okay, I’ve solved some of my problems.
To adjust the fan speed and the water level, the 2 sensors must be created.
sensor:
- platform: template
sensors:
deebot_fan_speed:
friendly_name: "fan speed"
value_template: "{{ state_attr('vacuum.aspirapolvere', 'fan_speed') }}"
deebot_water_level:
friendly_name: "water level"
value_template: "{{ state_attr('vacuum.aspirapolvere', 'water_level') }}"
I have an Ozmo 950 and to see the status of the vacuum in the “xiaomi_card” you have to replace it in the “xiaomi-vacuum-card.js” file posted by @StefanoGiu, vacuum_status with robot_status.
For cleaning the rooms I solved it like this:
- I created an input_boolean for each room.
Example: input_boolean_deebot_cucina, input_boolean_deebot_sala, etc. - I replaced this part of card:
- color: black
entity: null
icon: null
name: >
[[[
var stanze = states['input_text.valuestanze'].state;
stanze = stanze.substring(0,stanze.length - 1);
return "Stanze da pulire: <br>" + stanze;
]]]
styles:
card:
- font-size: 13px
- background-color: black
- color: white
name:
- width: 100%
- align: 'left'
- justify-self: start
- padding-left: 10px
- word-wrap: anywhere
type: 'custom:button-card'
With this:
- color: black
entity: null
icon: null
name: Stanze da pulire
styles:
card:
- font-size: 16px
- background-color: black
- color: white
name:
- justify-self: start
- padding-left: 16px
type: 'custom:button-card'
- I used this script:
vacuum_clean_zone:
alias: Pulisci zona
sequence:
- service: vacuum.send_command
data_template:
command: spot_area
entity_id: vacuum.aspirapolvere
params:
rooms: >-
{%- set x = "" %}
{% if is_state('input_boolean.deebot_cucina', 'on') %}
{% set x = x + "6," %}
{% endif %}
{% if is_state('input_boolean.deebot_sala', 'on') %}
{% set x = x + "5," %}
{% endif %}
{% if is_state('input_boolean.deebot_camera', 'on') %}
{% set x = x + "3," %}
{% endif %}
{% if is_state('input_boolean.deebot_bagno','on') %}
{% set x = x + "4," %}
{% endif %}
{% if is_state('input_boolean.deebot_lavanderia','on') %}
{% set x = x + "7," %}
{% endif %}
{% if is_state('input_boolean.deebot_corridoio', 'on') %}
{% set x = x + "1," %}
{% endif %}
{% if is_state('input_boolean.deebot_cameretta', 'on') %}
{% set x = x + "8," %}
{% endif %}
{% if is_state('input_boolean.deebot_studio', 'on') %}
{% set x = x + "0," %}
{% endif %}
{{x[:-1]}}
cleanings: >-
{%- if is_state('input_boolean.deebot_times', 'on') -%}2{%- else
-%}1{%- endif -%}
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_cucina
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_sala
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_camera
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_bagno
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_lavanderia
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_corridoio
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_cameretta
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_studio
- service: input_boolean.turn_off
data:
entity_id: input_boolean.deebot_times
Hello,
I have an ecovacs deebot 950, not working at all with H.A (not able to log in).
Can you tell me if an update of the integration will be available in the future ?
Best regards.
Thierry
oh nice, for schur I will be very interested !
Very nice, keep me please in touch !
best regards
Thierry
This is how it looks like in my interface…
What I die after quite a while of tinkering:
- remove any custom components, configs or settings you might have for the Deebot
- than install And3rsL’s custom component
Home Assistant Custom Component for Ecovacs Deebot Ozmo 960/950/920
This is my working config even thou I am not in the US (am in Norway)
vacuum:
- platform: deebot
username: !secret deebot_username
password: !secret deebot_password
country: us
continent: na
deviceid: !secret deebot_deviceid
livemappath: ‘www/live_map.png’
In order to get it working with the xiaomi-vacuum-card, you’ll need to edit the xiaomi-vacuum-card.js
file.
- open the file with your preferred editor its in
www/community/lovelace-xiaomi-vacuum-card/xiaomi-vacuum-card.js - delete the content and replace with this version
((LitElement) => {
const html = LitElement.prototype.html;
const css = LitElement.prototype.css;
class XiaomiVacuumCard extends LitElement {
static get properties() {
return {
_hass: {},
_config: {},
stateObj: {},
state: {},
style: {}
}
}
static get styles() {
return css`
.background {
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
.title {
font-size: 20px;
padding: 16px 16px 0;
text-align: center;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.content {
cursor: pointer;
}
.flex {
display: flex;
align-items: center;
justify-content: space-evenly;
}
.button {
cursor: pointer;
padding: 16px;
}
.grid {
display: grid;
grid-template-columns: repeat(2, auto);
}
.grid-content {
display: grid;
align-content: space-between;
grid-row-gap: 6px;
}
.grid-left {
text-align: left;
font-size: 110%;
padding-left: 10px;
border-left: 2px solid var(--primary-color);
}
.grid-right {
text-align: right;
padding-right: 10px;
border-right: 2px solid var(--primary-color);
}`;
}
render() {
return html`
<ha-card .hass="${this._hass}" .config="${this._config}" class="background" style="${this.style.background}">
${this.state.name ?
html`<div class="title" style="${this.style.text}" @click="${() => this.fireEvent('hass-more-info')}">${this.state.name}</div>`
: null}
${this.state.showLabels ? html`
<div class="content grid" style="${this.style.content + this.style.text}" @click="${() => this.fireEvent('hass-more-info')}">
<div class="grid-content grid-left">
<div>${this.getValue('vacuum_status')}</div>
<div>${this.getValue('battery', ' %')}</div>
<div>${this.getValue('mode')}</div>
</div>
${this.state.showDetails ? html`
<div class="grid-content grid-right" >
<div>${this.getValue('main_brush', ' %')}</div>
<div>${this.getValue('side_brush', ' %')}</div>
<div>${this.getValue('filter', ' %')}</div>
<div>${this.getValue('water_level')}</div>
</div>` : null}
</div>` : null}
${this.state.showButtons ? html`
<div class="flex" style="${this.style.text}">
${Object.keys(this.state.buttons).map(this.renderButton.bind(this))}
</div>` : null}
</ha-card>`;
}
renderButton(key) {
return this.state.buttons[key]
? html`<div class="button" @tap="${() => this.callService(key)}"><ha-icon icon="${this.state.icons[key]}"></ha-icon></div>`
: null;
}
getValue(field, unit = '') {
const value = (this.stateObj && this.state.attributes[field] in this.stateObj.attributes)
? this.stateObj.attributes[this.state.attributes[field]] + unit
: (this._hass ? this._hass.localize('state.default.unavailable') : 'Unavailable');
return `${this.state.labels[field]}: ${value}`;
};
computeValue(field) {
if (this.state.attributes[field] === undefined || this.state.attributes[field] === false) {
return null;
} else if (this.stateObj && this.state.attributes[field] in this.stateObj.attributes) {
const computed = this.state.computeValue(this.stateObj.attributes[this.state.attributes[field]]);
const unit = typeof computed === 'number' ? ` ${this.state.labels.hours}` : '';
return `${this.state.labels[field]}: ${computed}${unit}`;
} else {
return `${this.state.labels[field]}: - `;
}
};
callService(service) {
this._hass.callService('vacuum', this.state.service[service], {entity_id: this.stateObj.entity_id});
}
fireEvent(type, options = {}) {
const event = new Event(type, {
bubbles: options.bubbles || true,
cancelable: options.cancelable || true,
composed: options.composed || true,
});
event.detail = {entityId: this.stateObj.entity_id};
this.dispatchEvent(event);
}
getCardSize() {
if (this.state.name && this.state.showButtons) return 5;
if (this.state.name || this.state.showButtons) return 4;
return 3;
}
setConfig(config) {
const labels = {
vacuum_status: 'Status',
battery: 'Battery',
mode: 'Mode',
main_brush: 'Main Brush',
side_brush: 'Main Brush',
filter: 'Filter',
water_level: 'Water Level',
hours: 'h',
};
const attributes = {
vacuum_status: 'robot_status',
battery: 'battery_level',
mode: 'fan_speed',
main_brush: 'component_brush',
side_brush: 'component_sideBrush',
filter: 'component_heap',
water_level: 'water_level',
};
const services = {
start: 'start',
pause: 'pause',
stop: 'stop',
locate: 'locate',
return: 'return_to_base',
spot: 'clean_spot',
};
const buttons = {
start: true,
pause: true,
stop: true,
spot: false,
locate: true,
return: true,
};
const icons = {
start: 'mdi:play',
pause: 'mdi:pause',
stop: 'mdi:stop',
locate: 'mdi:map-marker',
return: 'mdi:home-map-marker',
spot: 'mdi:broom',
};
const vendors = {
xiaomi: {
details: true,
},
valetudo: {
details: true,
attributes: {
vacuum_status: 'vacuum_status',
main_brush: 'mainBrush',
side_brush: 'sideBrush',
filter: 'filter',
sensor: 'water_level',
},
},
roomba: {
details: true,
attributes: {
main_brush: 'bin_present',
side_brush: 'bin_full',
filter: false,
sensor: false,
},
labels: {
main_brush: 'Bin Present',
side_brush: 'Bin Full',
},
computeValue: v => (v === true ? 'Yes' : (v === false ? 'No' : '-')),
},
robovac: {
details: false,
buttons: {
stop: false,
spot: true,
},
},
ecovacs: {
image: '/local/img/vacuum_ecovacs.png',
details: false,
buttons: {
stop: false,
spot: true,
},
service: {
start: 'turn_on',
pause: 'stop',
stop: 'turn_off',
},
},
deebot: {
image: '/local/img/vacuum_ecovacs.png',
details: true,
service: {
start: 'turn_on',
pause: 'stop',
stop: 'turn_off',
},
attributes: {
main_brush: 'component_brush',
side_brush: 'component_sideBrush',
filter: 'component_heap',
water_level: 'water_level',
},
}
};
if (!config.entity) throw new Error('Please define an entity.');
if (config.entity.split('.')[0] !== 'vacuum') throw new Error('Please define a vacuum entity.');
if (config.vendor && !config.vendor in vendors) throw new Error('Please define a valid vendor.');
const vendor = vendors[config.vendor] || vendors.xiaomi;
this.state = {
showDetails: vendor.details,
showButtons: config.buttons !== false,
showLabels: config.labels !== false,
showName: config.name !== false,
service: Object.assign({}, services, vendor.service),
buttons: Object.assign({}, buttons, vendor.buttons, config.buttons),
attributes: Object.assign({}, attributes, vendor.attributes, config.attributes),
labels: Object.assign({}, labels, vendor.labels, config.labels),
icons: Object.assign({}, icons, config.icons),
computeValue: vendor.computeValue || (val => val),
};
this.style = {
text: `color: ${config.image !== false ? 'white; text-shadow: 0 0 10px black;' : 'var(--primary-text-color);'}`,
content: `padding: ${config.showButtons ? '16px 16px 4px' : '16px'};`,
background: config.image !== false ? `background-image: url('${config.image || vendor.image || '/local/img/vacuum.png'}')` : ''
};
this._config = config;
}
set hass(hass) {
this._hass = hass;
if (hass && this._config) {
this.stateObj = this._config.entity in hass.states ? hass.states[this._config.entity] : null;
if (this.stateObj && this.state.showName) {
this.state.name = this._config.name || this.stateObj.attributes.friendly_name;
}
}
}
}
customElements.define('xiaomi-vacuum-card', XiaomiVacuumCard);
})(window.LitElement || Object.getPrototypeOf(customElements.get("hui-view")));
After that you should be able to integrate your Deebot 950 into your dashboard.
If you have problems ill be here
Hello,
Can you tell me how to know the device id ?
Regards
Thierry
Read the read me to the 950 component.
https://github.com/And3rsL/Deebot-for-hassio/blob/4823caa80362b80775bb67e350d0af40b2b541c8/README.md
It’s the serial number in the deebot app
Hello,
Yes I see the id…
unfortunaltly, HA is not able to log in…
Here is the log:
Uncaught exception
13:02:00 – util/thread.py (ERROR)
Uncaught exception
13:01:58 – util/thread.py (ERROR)
MapID not found – did you finish your first auto cleaning?
13:01:58 – util/thread.py (WARNING)
Entity id already exists - ignoring: person.vorms. Platform person does not generate unique IDs
13:01:55 – Personne (ERROR)
Platform squeezebox not ready yet. Retrying in 30 seconds.
13:01:55 – Lecteur multimédia (WARNING)
Failed communicating with LMS: <class ‘aiohttp.client_exceptions.ClientConnectorError’>
13:01:54 – main.py (ERROR)
You are using a custom integration for deebot which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant.
13:01:53 – loader.py (WARNING)
Many thanks for your help.
Best regards
Sorry I can’t help you with this log either
Maybe look here if you can find someone with the same problem. Or open a new issue.
https://github.com/And3rsL/Deebot-for-hassio/issues?q=
Just a short feedback, the integration from And3rsL (installed via HACS) works - as of now - fine with my Ozmo T8 AIVI here
Using it with the Vacuum Card i installed from HACS
Hi, I have a T8 AIVI as well, can you tell me the procedure you followed to integrate it please? Can we also get the camera back on HA?
Thank you in advance for your help.
Hi @niconath,
i just installed HACS, in HACS i used the big “+”-Button to search for “deebot” and added the integrations repository.
After that i just added this to my configuration:
vacuum:
- platform: deebot
username: !secret ecovacs_user
password: !secret ecovacs_pass
country: DE
continent: EU
deviceid: !secret ecovacs_deviceid
# Optional
live_map: True # Enable Live Map.. may cause issues on low power hardware | Default: True
show_color_rooms: True # Enable draw room colors as in the app | Default: False
livemappath: 'www/live_map.png' # Path where to save live_map
camera:
# Saugroboter
- platform: generic
name: Vacuum Map
still_image_url: "https://192.168.178.101:8123/local/live_map.png" #Example configuration for livemappath: 'www/live_map.png'
verify_ssl: false
The camera Live-Image is as far as i know not supported. As of now i think it is only available when using the bot in patrol mode, so not while its cleaning as it uses it for the AIVI functions exclusive
Okay, great, thanks to you. Do you know if it’s possible to retrieve the map and select the washing areas on HA as on the app?
Yes, you get the map as a pseudo-camera (as shown in my code-example).
For the areas you might need to consult the documentation, it seems to be possible to name the areas as recognized by the robot and set custom / area cleanings and start by calling the service.
Read the docs for this (just scroll down): https://github.com/And3rsL/Deebot-for-hassio
Okay, that’s all right. I made it. Thanks for your help.
TypeError: ‘NoneType’ object is not callable
Hi,
lately I always have this error and the icon marked in yellow does not change color returning to the previous state. Do you also have the same mistake?
Logger: homeassistant.components.script
Source: custom_components/deebot/vacuum.py:222
Integration: Script (documentation, issues)
First occurred: 15:00:32 (1 occurrences)
Last logged: 15:00:32
Pulisci zona: Error executing script. Unexpected error for call_service at pos 1: ‘NoneType’ object is not callable
Traceback (most recent call last): File “/usr/src/homeassistant/homeassistant/helpers/script.py”, line 153, in _async_step self, f"async{cv.determine_script_action(self._action)}_step" File “/usr/src/homeassistant/homeassistant/helpers/script.py”, line 656, in _async_call_service_step *self._prep_call_service_step(), blocking=True, context=self._context File “/usr/src/homeassistant/homeassistant/core.py”, line 1260, in async_call task.result() File “/usr/src/homeassistant/homeassistant/core.py”, line 1295, in _execute_service await handler.func(service_call) File “/usr/src/homeassistant/homeassistant/helpers/entity_component.py”, line 209, in handle_service self._platforms.values(), func, call, required_features File “/usr/src/homeassistant/homeassistant/helpers/service.py”, line 454, in entity_service_call future.result() # pop exception if have File “/usr/src/homeassistant/homeassistant/helpers/entity.py”, line 595, in async_request_call await coro File “/usr/src/homeassistant/homeassistant/helpers/service.py”, line 485, in _handle_entity_call await result File “/config/custom_components/deebot/vacuum.py”, line 222, in async_send_command return await self.hass.async_add_executor_job(self.device.SpotArea(params[‘rooms’], params[‘cleanings’])) File “/usr/local/lib/python3.7/concurrent/futures/thread.py”, line 57, in run result = self.fn(*self.args, **self.kwargs) TypeError: ‘NoneType’ object is not callable