-
-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(vendor.cecotec): add support for cecotec conga
- Loading branch information
Showing
38 changed files
with
2,794 additions
and
585 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
38 changes: 38 additions & 0 deletions
38
backend/lib/robots/cecotec/capabilities/CecotecBasicControlCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const BasicControlCapability = require("../../../core/capabilities/BasicControlCapability"); | ||
|
||
/** | ||
* @extends BasicControlCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
module.exports = class CecotecBasicControlCapability extends BasicControlCapability { | ||
async start() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.start(); | ||
} | ||
|
||
async stop() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.stop(); | ||
} | ||
|
||
async pause() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.pause(); | ||
} | ||
|
||
async home() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.home(); | ||
} | ||
}; |
46 changes: 46 additions & 0 deletions
46
backend/lib/robots/cecotec/capabilities/CecotecCarpetModeControlCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
const CarpetModeControlCapability = require("../../../core/capabilities/CarpetModeControlCapability"); | ||
|
||
/** | ||
* @extends CarpetModeControlCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
class CecotecCarpetModeControlCapability extends CarpetModeControlCapability { | ||
/** | ||
* This function polls the current carpet mode state and stores the attributes in our robostate | ||
* | ||
* @abstract | ||
* @returns {Promise<boolean>} | ||
*/ | ||
async isEnabled() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
return this.robot.robot.device.config?.isCarpetModeEnabled || false; | ||
} | ||
|
||
/** | ||
* @abstract | ||
* @returns {Promise<void>} | ||
*/ | ||
async enable() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.setCarpetMode(true); | ||
} | ||
|
||
/** | ||
* @abstract | ||
* @returns {Promise<void>} | ||
*/ | ||
async disable() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.setCarpetMode(false); | ||
} | ||
} | ||
|
||
module.exports = CecotecCarpetModeControlCapability; |
76 changes: 76 additions & 0 deletions
76
backend/lib/robots/cecotec/capabilities/CecotecCombinedVirtualRestrictionsCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/** | ||
* @typedef {import("../../../entities/core/ValetudoVirtualRestrictions")} ValetudoVirtualRestrictions | ||
*/ | ||
|
||
const CombinedVirtualRestrictionsCapability = require("../../../core/capabilities/CombinedVirtualRestrictionsCapability"); | ||
const {Pixel} = require("@agnoc/core"); | ||
|
||
/** | ||
* @extends CombinedVirtualRestrictionsCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
class CecotecCombinedVirtualRestrictionsCapability extends CombinedVirtualRestrictionsCapability { | ||
/** | ||
* @param {ValetudoVirtualRestrictions} virtualRestrictions | ||
* @returns {Promise<void>} | ||
*/ | ||
async setVirtualRestrictions({ virtualWalls, restrictedZones }) { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
const map = this.robot.robot.device.map; | ||
|
||
if (!map) { | ||
return; | ||
} | ||
|
||
const offset = map.size.y; | ||
const areas = [ | ||
...virtualWalls.map(({ points }) => { | ||
return [ | ||
map.toCoordinate(new Pixel({ | ||
x: points.pA.x, | ||
y: offset - points.pA.y, | ||
})), | ||
map.toCoordinate(new Pixel({ | ||
x: points.pB.x, | ||
y: offset - points.pB.y, | ||
})), | ||
map.toCoordinate(new Pixel({ | ||
x: points.pA.x, | ||
y: offset - points.pA.y, | ||
})), | ||
map.toCoordinate(new Pixel({ | ||
x: points.pB.x, | ||
y: offset - points.pB.y, | ||
})), | ||
]; | ||
}), | ||
...restrictedZones.map(({ points }) => { | ||
return [ | ||
map.toCoordinate(new Pixel({ | ||
x: points.pA.x, | ||
y: offset - points.pA.y, | ||
})), | ||
map.toCoordinate(new Pixel({ | ||
x: points.pD.x, | ||
y: offset - points.pD.y, | ||
})), | ||
map.toCoordinate(new Pixel({ | ||
x: points.pC.x, | ||
y: offset - points.pC.y, | ||
})), | ||
map.toCoordinate(new Pixel({ | ||
x: points.pB.x, | ||
y: offset - points.pB.y, | ||
})), | ||
]; | ||
}) | ||
]; | ||
|
||
await this.robot.robot.setRestrictedZones(areas); | ||
await this.robot.robot.updateMap(); | ||
} | ||
} | ||
|
||
module.exports = CecotecCombinedVirtualRestrictionsCapability; |
101 changes: 101 additions & 0 deletions
101
backend/lib/robots/cecotec/capabilities/CecotecConsumableMonitoringCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
const ConsumableMonitoringCapability = require("../../../core/capabilities/ConsumableMonitoringCapability"); | ||
const ConsumableStateAttribute = require("../../../entities/state/attributes/ConsumableStateAttribute"); | ||
const {CONSUMABLE_TYPE} = require("@agnoc/core"); | ||
|
||
const { TYPE, SUB_TYPE, UNITS } = ConsumableStateAttribute; | ||
const MAIN_BRUSH_LIFE_TIME = 320 * 60; | ||
const SIDE_BRUSH_LIFE_TIME = 220 * 60; | ||
const FILTER_LIFE_TIME = 160 * 60; | ||
const DISHCLOTH_LIFE_TIME = 100 * 60; | ||
|
||
/** | ||
* @extends ConsumableMonitoringCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
module.exports = class CecotecConsumableMonitoringCapability extends ConsumableMonitoringCapability { | ||
async getConsumables() { | ||
if (!this.robot.robot) { | ||
return []; | ||
} | ||
|
||
const list = await this.robot.robot.getConsumables(); | ||
const consumables = list.map(({ type, used }) => { | ||
switch (type) { | ||
case CONSUMABLE_TYPE.MAIN_BRUSH: | ||
return new ConsumableStateAttribute({ | ||
type: TYPE.BRUSH, | ||
subType: SUB_TYPE.MAIN, | ||
remaining: { | ||
unit: UNITS.MINUTES, | ||
value: Math.max(MAIN_BRUSH_LIFE_TIME - used, 0) | ||
} | ||
}); | ||
case CONSUMABLE_TYPE.SIDE_BRUSH: | ||
return new ConsumableStateAttribute({ | ||
type: TYPE.BRUSH, | ||
subType: SUB_TYPE.SIDE_RIGHT, | ||
remaining: { | ||
unit: UNITS.MINUTES, | ||
value: Math.max(SIDE_BRUSH_LIFE_TIME - used, 0) | ||
} | ||
}); | ||
case CONSUMABLE_TYPE.FILTER: | ||
return new ConsumableStateAttribute({ | ||
type: TYPE.FILTER, | ||
subType: SUB_TYPE.MAIN, | ||
remaining: { | ||
unit: UNITS.MINUTES, | ||
value: Math.max(FILTER_LIFE_TIME - used, 0) | ||
} | ||
}); | ||
case CONSUMABLE_TYPE.DISHCLOTH: | ||
return new ConsumableStateAttribute({ | ||
type: TYPE.MOP, | ||
subType: SUB_TYPE.MAIN, | ||
remaining: { | ||
unit: UNITS.MINUTES, | ||
value: Math.max(DISHCLOTH_LIFE_TIME - used, 0) | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
consumables.forEach(c => { | ||
return this.robot.state.upsertFirstMatchingAttribute(c); | ||
}); | ||
|
||
// @ts-ignore | ||
this.robot.emitStateUpdated(); | ||
|
||
return consumables; | ||
} | ||
|
||
/** | ||
* @param {string} type | ||
* @param {string} [subType] | ||
* @returns {Promise<void>} | ||
*/ | ||
async resetConsumable(type, subType) { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
/** | ||
* @type {import("@agnoc/core").ConsumableType} | ||
*/ | ||
let consumable; | ||
|
||
if (type === TYPE.BRUSH && subType === SUB_TYPE.MAIN) { | ||
consumable = CONSUMABLE_TYPE.MAIN_BRUSH; | ||
} else if (type === TYPE.BRUSH && subType === SUB_TYPE.SIDE_RIGHT) { | ||
consumable = CONSUMABLE_TYPE.SIDE_BRUSH; | ||
} else if (type === TYPE.FILTER) { | ||
consumable = CONSUMABLE_TYPE.FILTER; | ||
} else if (type === TYPE.MOP) { | ||
consumable = CONSUMABLE_TYPE.DISHCLOTH; | ||
} | ||
|
||
if (consumable) { | ||
await this.robot.robot.resetConsumable(consumable); | ||
} | ||
} | ||
}; |
34 changes: 34 additions & 0 deletions
34
backend/lib/robots/cecotec/capabilities/CecotecCurrentStatisticsCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
const CurrentStatisticsCapability = require("../../../core/capabilities/CurrentStatisticsCapability"); | ||
const ValetudoDataPoint = require("../../../entities/core/ValetudoDataPoint"); | ||
|
||
/** | ||
* @extends CurrentStatisticsCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
class CecotecCurrentStatisticsCapability extends CurrentStatisticsCapability { | ||
/** | ||
* @return {Promise<Array<ValetudoDataPoint>>} | ||
*/ | ||
async getStatistics() { | ||
return [ | ||
new ValetudoDataPoint({ | ||
type: ValetudoDataPoint.TYPES.TIME, | ||
value: (this.robot.robot?.device.currentClean?.time || 0) * 60, | ||
}), | ||
new ValetudoDataPoint({ | ||
type: ValetudoDataPoint.TYPES.AREA, | ||
value: (this.robot.robot?.device.currentClean?.size || 0) * 100, | ||
}), | ||
]; | ||
} | ||
|
||
getProperties() { | ||
return { | ||
availableStatistics: [ | ||
ValetudoDataPoint.TYPES.TIME, | ||
ValetudoDataPoint.TYPES.AREA, | ||
], | ||
}; | ||
} | ||
} | ||
|
||
module.exports = CecotecCurrentStatisticsCapability; |
54 changes: 54 additions & 0 deletions
54
backend/lib/robots/cecotec/capabilities/CecotecDoNotDisturbCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
const DoNotDisturbCapability = require("../../../core/capabilities/DoNotDisturbCapability"); | ||
const ValetudoDNDConfiguration = require("../../../entities/core/ValetudoDNDConfiguration"); | ||
const {DeviceQuietHours, DeviceTime} = require("@agnoc/core"); | ||
|
||
/** | ||
* @extends DoNotDisturbCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
module.exports = class CecotecDoNotDisturbCapability extends DoNotDisturbCapability { | ||
|
||
/** | ||
* @returns {Promise<import("../../../entities/core/ValetudoDNDConfiguration")>} | ||
*/ | ||
async getDndConfiguration() { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
const quietHours = await this.robot.robot.getQuietHours(); | ||
|
||
return new ValetudoDNDConfiguration({ | ||
enabled: quietHours.isEnabled, | ||
start: { | ||
hour: quietHours.begin.hour, | ||
minute: quietHours.begin.minute | ||
}, | ||
end: { | ||
hour: quietHours.end.hour, | ||
minute: quietHours.end.minute | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* @param {import("../../../entities/core/ValetudoDNDConfiguration")} dndConfig | ||
* @returns {Promise<void>} | ||
*/ | ||
async setDndConfiguration(dndConfig) { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
await this.robot.robot.setQuietHours(new DeviceQuietHours({ | ||
isEnabled: dndConfig.enabled, | ||
begin: new DeviceTime({ | ||
hour: dndConfig.start.hour, | ||
minute: dndConfig.start.minute, | ||
}), | ||
end: new DeviceTime({ | ||
hour: dndConfig.end.hour, | ||
minute: dndConfig.end.minute, | ||
}), | ||
})); | ||
} | ||
}; |
32 changes: 32 additions & 0 deletions
32
backend/lib/robots/cecotec/capabilities/CecotecFanSpeedControlCapability.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
const FanSpeedControlCapability = require("../../../core/capabilities/FanSpeedControlCapability"); | ||
const {DeviceFanSpeed} = require("@agnoc/core"); | ||
|
||
/** | ||
* @extends FanSpeedControlCapability<import("../CecotecCongaRobot")> | ||
*/ | ||
module.exports = class CecotecFanSpeedControlCapability extends FanSpeedControlCapability { | ||
/** | ||
* @returns {Array<string>} | ||
*/ | ||
getFanSpeedPresets() { | ||
return this.presets.map(p => { | ||
return p.name; | ||
}); | ||
} | ||
|
||
async selectPreset(preset) { | ||
if (!this.robot.robot) { | ||
throw new Error("There is no robot connected to server"); | ||
} | ||
|
||
const matchedPreset = this.presets.find(p => { | ||
return p.name === preset; | ||
}); | ||
|
||
if (!matchedPreset) { | ||
throw new Error("Invalid Preset"); | ||
} | ||
|
||
await this.robot.robot.setFanSpeed(new DeviceFanSpeed({ value: matchedPreset.value })); | ||
} | ||
}; |
Oops, something went wrong.