Skip to content

Commit

Permalink
feat(vendor.roborock): Do not disturb capability (#659)
Browse files Browse the repository at this point in the history
* Roborock/Capability Do Not Disturb

Co-authored-by: bensweet86 <bensweet@outlook.com.au>
  • Loading branch information
Hypfer and bensweet86 committed Jan 20, 2021
1 parent fde2ffd commit 4b3ed97
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 42 deletions.
26 changes: 14 additions & 12 deletions client/services/api.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,22 @@ export class ApiService {
await this.fetch("DELETE", "api/timers/" + id);
}

static async getDnd() {
return await this.fetch("GET", "api/get_dnd");
static async getDndConfiguration() {
return await this.fetch("GET", "api/v2/robot/capabilities/DoNotDisturbCapability");
}

static async deleteDnd() {
await this.fetch("PUT", "api/delete_dnd");
}

static async setDnd(start_hour, start_minute, end_hour, end_minute) {
await this.fetch("POST", "api/set_dnd", {start_hour, start_minute, end_hour, end_minute});
static async setDndConfiguration(enabled, start_hour, start_minute, end_hour, end_minute) {
await this.fetch("PUT", "api/v2/robot/capabilities/DoNotDisturbCapability", {
enabled: enabled,
start: {
hour: start_hour,
minute: start_minute
},
end: {
hour: end_hour,
minute: end_minute
}
});
}

static async getCarpetMode() {
Expand Down Expand Up @@ -270,10 +276,6 @@ export class ApiService {
}


static async setLabStatus(labStatus) {
await this.fetch("PUT", "api/set_lab_status", {lab_status: labStatus});
}

static async resetConsumable(type, subType) {
var url = "api/v2/robot/capabilities/ConsumableMonitoringCapability/" + type;

Expand Down
7 changes: 5 additions & 2 deletions client/settings-timers.html
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,21 @@
</div>
<div class="center">Timers</div>
<div class="right">
<!--
<ons-toolbar-button id="settings-timers-timezone" onclick="showTimeZoneDialog();">
<ons-icon icon="fa-cog"></ons-icon>
</ons-toolbar-button>
-->
</div>
</ons-toolbar>
<ons-progress-bar id="loading-bar-settings-timers" value="0" indeterminate="indeterminate"></ons-progress-bar>

<!--
<ons-list-title style="margin-top:5px;">
Cleaning - Timers <ons-toolbar-button id="settings-timers-create-new-timer" onclick="showAddTimerDialog(-1);"><ons-icon icon="fa-plus"></ons-icon></ons-toolbar-button></div>
</ons-list-title>
<ons-list id="settings-timers-timer-list"></ons-list>

-->
<ons-list-title style="margin-top:5px;">"Do Not Disturb" - Timer</ons-list-title>
<ons-list id="settings-dnd-timer-list"></ons-list>

Expand All @@ -148,7 +151,7 @@
ons.getScriptPage().appendChild(s);

ons.getScriptPage().onShow = function() {
updateSettingsTimersPage();
//updateSettingsTimersPage();
updateDndTimerPage();
};
}
Expand Down
53 changes: 30 additions & 23 deletions client/settings-timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ async function updateDndTimerPage() {
dndTimerList.removeChild(dndTimerList.lastChild);
}
try {
let res = await ApiService.getDnd();
let res = await ApiService.getDndConfiguration();
// TODO: Check if multiple dnd timers can be created!
if (res.length === 0 || res[0].enabled === 0) {
if (res.length === 0 || !(res.enabled) ) {
// no timer is enabled yet, show possibility to add dnd timer
dndTimerList.appendChild(ons.createElement(
"<ons-list-item>\n" +
Expand All @@ -110,24 +110,23 @@ async function updateDndTimerPage() {
"</ons-list-item>"));
} else {
// Show current active timer
res.forEach(function(dndTimer) {
dndTimerList.appendChild(ons.createElement(
"<ons-list-item>\n" +
" <div class='left'>DND will start at " + dndTimer.start_hour + ":" +
asTwoDigitNumber(dndTimer.start_minute) + " and end on " +
dndTimer.end_hour + ":" + asTwoDigitNumber(dndTimer.end_minute) + "</div>" +
" <div class='right'>" +
" <ons-button modifier='quiet' class='button-margin' style='font-size: 2em;' onclick='showDndTimerDialog(" +
dndTimer.start_hour + ", " + dndTimer.start_minute + ", " +
dndTimer.end_hour + ", " + dndTimer.end_minute + ");'>" +
" <ons-icon icon='fa-edit'></ons-icon>" +
" </ons-button>" +
" <ons-button modifier='quiet' class='button-margin' style='font-size: 2em;' onclick='deleteDndTimer();'>" +
" <ons-icon icon='fa-trash'></ons-icon>" +
" </ons-button>" +
" </div>" +
"</ons-list-item>"));
});
dndTimerList.appendChild(ons.createElement(
"<ons-list-item>\n" +
" <div class='left'>DND will start at " + res.start.hour + ":" +
asTwoDigitNumber(res.start.minute) + " and end on " +
res.end.hour + ":" + asTwoDigitNumber(res.end.minute) + "</div>" +
" <div class='right'>" +
" <ons-button modifier='quiet' class='button-margin' style='font-size: 2em;' onclick='showDndTimerDialog(" +
res.start.hour + ", " + res.start.minute + ", " +
res.end.hour + ", " + res.end.minute + ");'>" +
" <ons-icon icon='fa-edit'></ons-icon>" +
" </ons-button>" +
" <ons-button modifier='quiet' class='button-margin' style='font-size: 2em;' onclick='deleteDndTimer();'>" +
" <ons-icon icon='fa-trash'></ons-icon>" +
" </ons-button>" +
" </div>" +
"</ons-list-item>"
));
}
} catch (err) {
ons.notification.toast(err.message,
Expand All @@ -143,7 +142,7 @@ async function deleteDndTimer() {
let answer = await ons.notification.confirm("Do you really want to disable DND?");
if (answer === 1) {
loadingBarSettingsTimers.setAttribute("indeterminate", "indeterminate");
await ApiService.deleteDnd();
await ApiService.setDndConfiguration(false, 0, 0, 0, 0);
updateDndTimerPage();
}
} catch (err) {
Expand All @@ -160,9 +159,17 @@ async function saveDndTimer() {
var start_minute = document.getElementById("edit-dnd-form").start_minute.value;
var end_hour = document.getElementById("edit-dnd-form").end_hour.value;
var end_minute = document.getElementById("edit-dnd-form").end_minute.value;

if (start_hour && start_minute && end_hour && end_minute) {
try {
await ApiService.setDnd(start_hour, start_minute, end_hour, end_minute);
await ApiService.setDndConfiguration(
true,
parseInt(start_hour),
parseInt(start_minute),
parseInt(end_hour),
parseInt(end_minute)
);

hideDndTimerDialog();
updateDndTimerPage();
} catch (err) {
Expand Down Expand Up @@ -413,4 +420,4 @@ window.deleteDndTimer = deleteDndTimer;
window.saveDndTimer = saveDndTimer;
window.addNewTimer = addNewTimer;
window.showAddTimerDialog = showAddTimerDialog;
window.hideNewTimerDialog = hideNewTimerDialog;
window.hideNewTimerDialog = hideNewTimerDialog;
4 changes: 2 additions & 2 deletions client/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<div class="title"><ons-icon icon="fa-info"></ons-icon> Info</div>
<div class="content">View device information</div>
</ons-card>
<!--

<ons-card onclick="fn.pushPage({'id': 'settings-timers.html', 'title': 'Timers'})">
<div class="title"><ons-icon icon="fa-clock-o"></ons-icon> Timers</div>
<div class="content">Manage timers</div>
</ons-card>
-->

<!--
<ons-card onclick="fn.pushPage({'id': 'settings-carpet-mode.html', 'title': 'Carpet Mode'})">
<div class="title"><ons-icon icon="fa-cart-arrow-down"></ons-icon> Carpet Mode</div>
Expand Down
30 changes: 30 additions & 0 deletions lib/core/capabilities/DoNotDisturbCapability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const Capability = require("./Capability");
const NotImplementedError = require("../NotImplementedError");

class DoNotDisturbCapability extends Capability {
/**
*
* @abstract
* @returns {Promise<import("../../entities/core/ValetudoDNDConfiguration")>}
*/
async getDndConfiguration() {
throw new NotImplementedError();
}

/**
* @abstract
* @param {import("../../entities/core/ValetudoDNDConfiguration")} dndConfig
* @returns {Promise<void>}
*/
async setDndConfiguration(dndConfig) {
throw new NotImplementedError();
}

getType() {
return DoNotDisturbCapability.TYPE;
}
}

DoNotDisturbCapability.TYPE = "DoNotDisturbCapability";

module.exports = DoNotDisturbCapability;
1 change: 1 addition & 0 deletions lib/core/capabilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ module.exports = {
SensorCalibrationCapability: require("./SensorCalibrationCapability"),
SpeakerVolumeControlCapability: require("./SpeakerVolumeControlCapability"),
RawCommandCapability: require("./RawCommandCapability"),
DoNotDisturbCapability: require("./DoNotDisturbCapability"),
};
31 changes: 31 additions & 0 deletions lib/entities/core/ValetudoDNDConfiguration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const SerializableEntity = require("../SerializableEntity");


// noinspection JSCheckFunctionSignatures
class ValetudoDNDConfiguration extends SerializableEntity {
/**
* @param {object} options
* @param {boolean} options.enabled
*
* @param {object} options.start
* @param {number} options.start.hour
* @param {number} options.start.minute
*
* @param {object} options.end
* @param {number} options.end.hour
* @param {number} options.end.minute
*
* @param {object} [options.metaData]
*
* @class
*/
constructor(options) {
super(options);

this.enabled = options.enabled;
this.start = options.start;
this.end = options.end;
}
}

module.exports = ValetudoDNDConfiguration;
3 changes: 3 additions & 0 deletions lib/robots/roborock/RoborockValetudoRobot.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class RoborockValetudoRobot extends MiioValetudoRobot {
this.registerCapability(new capabilities.RoborockLocateCapability({
robot: this
}));
this.registerCapability(new capabilities.RoborockDoNotDisturbCapability({
robot: this
}));
}

setEmbeddedParameters() {
Expand Down
45 changes: 45 additions & 0 deletions lib/robots/roborock/capabilities/RoborockDoNotDisturbCapability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const DoNotDisturbCapability = require("../../../core/capabilities/DoNotDisturbCapability");
const ValetudoDNDConfiguration = require("../../../entities/core/ValetudoDNDConfiguration");

class RoborockDoNotDisturbCapability extends DoNotDisturbCapability {
/**
*
* @abstract
* @returns {Promise<ValetudoDNDConfiguration>}
*/
async getDndConfiguration() {
const res = await this.robot.sendCommand("get_dnd_timer", [], {});

return new ValetudoDNDConfiguration({
enabled: (res[0].enabled === 1),
start: {
hour: res[0].start_hour,
minute: res[0].start_minute
},
end: {
hour: res[0].end_hour,
minute: res[0].end_minute
}
});
}

/**
* @abstract
* @param {ValetudoDNDConfiguration} dndConfig
* @returns {Promise<void>}
*/
async setDndConfiguration(dndConfig) {
if (dndConfig.enabled === true) {
return this.robot.sendCommand("set_dnd_timer", [
dndConfig.start.hour,
dndConfig.start.minute,
dndConfig.end.hour,
dndConfig.end.minute
], {});
} else {
return this.robot.sendCommand("close_dnd_timer", [], {});
}
}
}

module.exports = RoborockDoNotDisturbCapability;
3 changes: 2 additions & 1 deletion lib/robots/roborock/capabilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ module.exports = {
RoborockCombinedVirtualRestrictionsCapability: require("./RoborockCombinedVirtualRestrictionsCapability"),
RoborockPersistentMapControlCapability: require("./RoborockPersistentMapControlCapability"),
RoborockMultiMapPersistentMapControlCapability: require("./RoborockMultiMapPersistentMapControlCapability"),
RoborockMapSegmentationCapability: require("./RoborockMapSegmentationCapability")
RoborockMapSegmentationCapability: require("./RoborockMapSegmentationCapability"),
RoborockDoNotDisturbCapability: require("./RoborockDoNotDisturbCapability")
};
3 changes: 2 additions & 1 deletion lib/webserver/CapabilitiesRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ const CAPABILITY_TYPE_TO_ROUTER_MAPPING = {
[capabilities.SensorCalibrationCapability.TYPE]: capabilityRouters.SensorCalibrationCapabilityRouter,
[capabilities.SpeakerVolumeControlCapability.TYPE]: capabilityRouters.SpeakerVolumeControlCapabilityRouter,
[capabilities.RawCommandCapability.TYPE]: capabilityRouters.RawCommandCapabilityRouter,
[capabilities.MapSegmentationCapability.TYPE]: capabilityRouters.MapSegmentationCapabilityRouter
[capabilities.MapSegmentationCapability.TYPE]: capabilityRouters.MapSegmentationCapabilityRouter,
[capabilities.DoNotDisturbCapability.TYPE]: capabilityRouters.DoNotDisturbCapabilityRouter
};

module.exports = CapabilitiesRouter;
30 changes: 30 additions & 0 deletions lib/webserver/capabilityRouters/DoNotDisturbCapabilityRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const Logger = require("../../Logger");

const CapabilityRouter = require("./CapabilityRouter");
const ValetudoDNDConfiguration = require("../../entities/core/ValetudoDNDConfiguration");

class DoNotDisturbCapabilityRouter extends CapabilityRouter {

initRoutes() {
this.router.get("/", async (req, res) => {
res.json(await this.capability.getDndConfiguration());
});

this.router.put("/", async (req, res) => {
if (req.body && req.body.start && req.body.end) {
try {
await this.capability.setDndConfiguration(new ValetudoDNDConfiguration(req.body));

res.sendStatus(200);
} catch (e) {
Logger.warn("Error while configuring do not disturb setting", e);
res.status(500).json(e.message);
}
} else {
res.status(400).send("Missing parameters in request body");
}
});
}
}

module.exports = DoNotDisturbCapabilityRouter;
3 changes: 2 additions & 1 deletion lib/webserver/capabilityRouters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ module.exports = {
SensorCalibrationCapabilityRouter: require("./SensorCalibrationCapabilityRouter"),
SpeakerVolumeControlCapabilityRouter: require("./SpeakerVolumeControlCapabilityRouter"),
RawCommandCapabilityRouter: require("./RawCommandCapabilityRouter"),
MapSegmentationCapabilityRouter: require("./MapSegmentationCapabilityRouter")
MapSegmentationCapabilityRouter: require("./MapSegmentationCapabilityRouter"),
DoNotDisturbCapabilityRouter: require("./DoNotDisturbCapabilityRouter")
};

0 comments on commit 4b3ed97

Please sign in to comment.