diff --git a/src/common/const.js b/src/common/const.js
index 1582b1a05c..2f604bd000 100644
--- a/src/common/const.js
+++ b/src/common/const.js
@@ -20,6 +20,7 @@ export const DOMAINS_WITH_CARD = [
'scene',
'script',
'timer',
+ 'vacuum',
'weblink',
];
diff --git a/src/components/ha-vacuum-state.js b/src/components/ha-vacuum-state.js
new file mode 100644
index 0000000000..3cc3377e26
--- /dev/null
+++ b/src/components/ha-vacuum-state.js
@@ -0,0 +1,89 @@
+import '@polymer/paper-button/paper-button.js';
+import { html } from '@polymer/polymer/lib/utils/html-tag.js';
+import { PolymerElement } from '@polymer/polymer/polymer-element.js';
+
+import LocalizeMixin from '../mixins/localize-mixin.js';
+
+const STATES_INTERCEPTABLE = {
+ cleaning: {
+ action: 'return_to_base',
+ service: 'return_to_base'
+ },
+ docked: {
+ action: 'start_cleaning',
+ service: 'start_pause'
+ },
+ idle: {
+ action: 'start_cleaning',
+ service: 'start_pause'
+ },
+ off: {
+ action: 'turn_on',
+ service: 'turn_on'
+ },
+ on: {
+ action: 'turn_off',
+ service: 'turn_off'
+ },
+ paused: {
+ action: 'resume_cleaning',
+ service: 'start_pause'
+ },
+};
+
+/*
+ * @appliesMixin LocalizeMixin
+ */
+class HaVacuumState extends LocalizeMixin(PolymerElement) {
+ static get template() {
+ return html`
+
+
+ [[_computeLabel(stateObj.state, _interceptable)]]
+ `;
+ }
+
+ static get properties() {
+ return {
+ hass: Object,
+ stateObj: Object,
+ _interceptable: {
+ type: Boolean,
+ computed: '_computeInterceptable(stateObj.state, stateObj.attributes.supported_features)'
+ }
+ };
+ }
+
+ _computeInterceptable(state, supportedFeatures) {
+ return state in STATES_INTERCEPTABLE && supportedFeatures !== 0;
+ }
+
+ _computeLabel(state, interceptable) {
+ return interceptable ?
+ this.localize(`ui.card.vacuum.actions.${STATES_INTERCEPTABLE[state].action}`)
+ : this.localize(`state.vacuum.${state}`);
+ }
+
+ _callService(ev) {
+ ev.stopPropagation();
+ const stateObj = this.stateObj;
+ const service = STATES_INTERCEPTABLE[stateObj.state].service;
+ this.hass.callService('vacuum', service, { entity_id: stateObj.entity_id });
+ }
+}
+customElements.define('ha-vacuum-state', HaVacuumState);
diff --git a/src/state-summary/state-card-content.js b/src/state-summary/state-card-content.js
index 9a202241ac..c183ef3c44 100644
--- a/src/state-summary/state-card-content.js
+++ b/src/state-summary/state-card-content.js
@@ -13,6 +13,7 @@ import './state-card-scene.js';
import './state-card-script.js';
import './state-card-timer.js';
import './state-card-toggle.js';
+import './state-card-vacuum.js';
import './state-card-weblink.js';
import stateCardType from '../common/entity/state_card_type.js';
diff --git a/src/state-summary/state-card-vacuum.js b/src/state-summary/state-card-vacuum.js
new file mode 100644
index 0000000000..6842a9bf53
--- /dev/null
+++ b/src/state-summary/state-card-vacuum.js
@@ -0,0 +1,41 @@
+import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
+import { html } from '@polymer/polymer/lib/utils/html-tag.js';
+import { PolymerElement } from '@polymer/polymer/polymer-element.js';
+
+import '../components/entity/state-info.js';
+import '../components/ha-vacuum-state.js';
+
+class StateCardVacuum extends PolymerElement {
+ static get template() {
+ return html`
+
+
+
+ ${this.stateInfoTemplate}
+
+
+`;
+ }
+
+ static get stateInfoTemplate() {
+ return html`
+
+`;
+ }
+
+ static get properties() {
+ return {
+ hass: Object,
+ stateObj: Object,
+ inDialog: {
+ type: Boolean,
+ value: false,
+ }
+ };
+ }
+}
+customElements.define('state-card-vacuum', StateCardVacuum);
diff --git a/src/translations/en.json b/src/translations/en.json
index 0ec6eb32bc..e7936c8630 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -33,6 +33,7 @@
"sun": "Sun",
"switch": "Switch",
"updater": "Updater",
+ "vacuum": "Vacuum",
"weblink": "Weblink",
"zwave": "Z-Wave"
},
@@ -263,6 +264,16 @@
"off": "[%key:state::default::off%]",
"on": "[%key:state::default::on%]"
},
+ "vacuum": {
+ "cleaning": "Cleaning",
+ "docked": "Docked",
+ "error": "Error",
+ "idle": "Idle",
+ "off": "[%key:state::default::off%]",
+ "on": "[%key:state::default::on%]",
+ "paused": "Paused",
+ "returning": "Returning to dock"
+ },
"weather": {
"clear-night": "Clear, night",
"cloudy": "Cloudy",
@@ -375,6 +386,15 @@
"script": {
"execute": "Execute"
},
+ "vacuum": {
+ "actions": {
+ "resume_cleaning": "Resume cleaning",
+ "return_to_base": "Return to dock",
+ "start_cleaning": "Start cleaning",
+ "turn_on": "Turn on",
+ "turn_off": "Turn off"
+ }
+ },
"weather": {
"attributes": {
"air_pressure": "Air pressure",