From e6a0fee2aa77786d2eaf4604e70f576df1756517 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 11 Apr 2021 15:42:48 +0200 Subject: [PATCH] Simulation: Add a cleaning robot simulated thing --- simulation/integrationpluginsimulation.cpp | 70 +++++++++++++++- simulation/integrationpluginsimulation.h | 2 + simulation/integrationpluginsimulation.json | 88 +++++++++++++++++++++ 3 files changed, 158 insertions(+), 2 deletions(-) diff --git a/simulation/integrationpluginsimulation.cpp b/simulation/integrationpluginsimulation.cpp index 78dd33e9..675f336c 100644 --- a/simulation/integrationpluginsimulation.cpp +++ b/simulation/integrationpluginsimulation.cpp @@ -73,7 +73,8 @@ void IntegrationPluginSimulation::setupThing(ThingSetupInfo *info) thing->thingClassId() == fingerPrintSensorThingClassId || thing->thingClassId() == barcodeScannerThingClassId || thing->thingClassId() == contactSensorThingClassId || - thing->thingClassId() == waterSensorThingClassId) { + thing->thingClassId() == waterSensorThingClassId || + thing->thingClassId() == cleaningRobotThingClassId) { m_simulationTimers.insert(thing, new QTimer(thing)); connect(m_simulationTimers[thing], &QTimer::timeout, this, &IntegrationPluginSimulation::simulationTimerTimeout); } @@ -576,6 +577,48 @@ void IntegrationPluginSimulation::executeAction(ThingActionInfo *info) } } + if (thing->thingClassId() == cleaningRobotThingClassId) { + if (action.actionTypeId() == cleaningRobotStartCleaningActionTypeId) { + qCDebug(dcSimulation()) << "Starting to clean..."; + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "cleaning"); + m_simulationTimers.value(thing)->stop(); + info->finish(Thing::ThingErrorNoError); + return; + } + if (action.actionTypeId() == cleaningRobotPauseCleaningActionTypeId) { + qCDebug(dcSimulation()) << "Pausing..."; + if (thing->stateValue(cleaningRobotRobotStateStateTypeId).toString() == "paused") { + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "cleaning"); + } else if (thing->stateValue(cleaningRobotRobotStateStateTypeId).toString() == "cleaning"){ + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "paused"); + } + info->finish(Thing::ThingErrorNoError); + return; + } + if (action.actionTypeId() == cleaningRobotStopCleaningActionTypeId) { + qCDebug(dcSimulation()) << "Stopping."; + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "stopped"); + info->finish(Thing::ThingErrorNoError); + return; + } + if (action.actionTypeId() == cleaningRobotReturnToBaseActionTypeId) { + qCDebug(dcSimulation()) << "Returning to base..."; + QString robotState = thing->stateValue(cleaningRobotRobotStateStateTypeId).toString(); + if (robotState == "cleaning" || robotState == "paused" || robotState == "error") { + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "traveling"); + m_simulationTimers.value(thing)->start(5000); + } + info->finish(Thing::ThingErrorNoError); + return; + } + if (action.actionTypeId() == cleaningRobotSimulateErrorActionTypeId) { + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "error"); + thing->setStateValue(cleaningRobotErrorMessageStateTypeId, QT_TR_NOOP("Help me, I'm stuck!")); + info->finish(Thing::ThingErrorNoError); + return; + } + } + qCWarning(dcSimulation()) << "Unhandled thing class" << thing->thingClassId() << "for" << thing->name(); } @@ -719,8 +762,28 @@ void IntegrationPluginSimulation::onPluginTimer20Seconds() thing->setProperty("lastUpdate", lastUpdate); qreal consumptionKWH = 1.0 * currentPower * (1.0 * m_pluginTimer20Seconds->interval() / 1000 / 60 / 60) / 1000; thing->setStateValue(solarPanelTotalEnergyProducedStateTypeId, thing->stateValue(solarPanelTotalEnergyProducedStateTypeId).toDouble() + consumptionKWH); + } else if (thing->thingClassId() == cleaningRobotThingClassId) { + QString robotState = thing->stateValue(cleaningRobotRobotStateStateTypeId).toString(); + int batteryLevel = thing->stateValue(cleaningRobotBatteryLevelStateTypeId).toInt(); + bool charging = false; + bool pluggedIn = false; + if (robotState == "cleaning") { + batteryLevel -= 1; + if (batteryLevel < 5) { + robotState = "traveling"; + m_simulationTimers.value(thing)->start(5000); + } + } else if (robotState == "docked") { + batteryLevel = qMin(100, batteryLevel + 2); + charging = batteryLevel < 100; + pluggedIn = true; + } + thing->setStateValue(cleaningRobotRobotStateStateTypeId, robotState); + thing->setStateValue(cleaningRobotBatteryLevelStateTypeId, batteryLevel); + thing->setStateValue(cleaningRobotBatteryCriticalStateTypeId, batteryLevel < 10); + thing->setStateValue(cleaningRobotChargingStateTypeId, charging); + thing->setStateValue(cleaningRobotPluggedInStateTypeId, pluggedIn); } - } } @@ -853,5 +916,8 @@ void IntegrationPluginSimulation::simulationTimerTimeout() } else if (thing->thingClassId() == waterSensorThingClassId) { bool wet = qrand() > (RAND_MAX / 2); thing->setStateValue(waterSensorWaterDetectedStateTypeId, wet); + } else if (thing->thingClassId() == cleaningRobotThingClassId) { + thing->setStateValue(cleaningRobotRobotStateStateTypeId, "docked"); } + } diff --git a/simulation/integrationpluginsimulation.h b/simulation/integrationpluginsimulation.h index b928f6b6..5a04c6b1 100644 --- a/simulation/integrationpluginsimulation.h +++ b/simulation/integrationpluginsimulation.h @@ -36,6 +36,8 @@ #include +#include "extern-plugininfo.h" + class IntegrationPluginSimulation : public IntegrationPlugin { Q_OBJECT diff --git a/simulation/integrationpluginsimulation.json b/simulation/integrationpluginsimulation.json index 6c3f6b9a..62d7133c 100644 --- a/simulation/integrationpluginsimulation.json +++ b/simulation/integrationpluginsimulation.json @@ -1216,6 +1216,94 @@ "defaultValue": false } ] + }, + { + "id": "67bc68f1-8131-471f-9aa3-392284064ea2", + "name": "cleaningRobot", + "displayName": "Cleaning robot", + "createMethods": ["user"], + "interfaces": ["cleaningrobot", "battery"], + "stateTypes": [ + { + "id": "ec324f2a-582b-4bd2-a2c8-03d5f20aa4f9", + "name": "robotState", + "displayName": "Robot state", + "displayNameEvent": "Robot state changed", + "type": "QString", + "possibleValues": ["docked", "cleaning", "paused", "traveling", "stopped", "error"], + "defaultValue": "docked" + }, + { + "id": "71d0eff8-160a-4cff-a349-4beb40c33129", + "name": "errorMessage", + "displayName": "Robot error", + "displayNameEvent": "Robot error changed", + "type": "QString", + "defaultValue": "" + }, + { + "id": "f68f35f8-85c9-49ca-8ac1-50579653704e", + "name": "batteryCritical", + "displayName": "Battery critical", + "displayNameEvent": "Battery entered or left critical state", + "type": "bool", + "defaultValue": false + }, + { + "id": "e17a25db-1e32-479e-8802-7fab6b91b44f", + "name": "batteryLevel", + "displayName": "Battery level", + "displayNameEvent": "Battery level changed", + "type": "int", + "minValue": 0, + "maxValue": 100, + "unit": "Percentage", + "defaultValue": 50 + }, + { + "id": "f31930c5-0886-4152-9001-ae8e52f85b21", + "name": "charging", + "displayName": "Charging", + "displayNameEvent": "Started or stopped charging", + "type": "bool", + "defaultValue": true + }, + { + "id": "f3b00428-9123-43a2-bc72-684e2eec692e", + "name": "pluggedIn", + "displayName": "Plugged in", + "displayNameEvent": "Plugged or unplugged", + "type": "bool", + "defaultValue": true + } + ], + "actionTypes": [ + { + "id": "4d12df39-e4d8-4dfe-aa8b-8c3dd5adb79b", + "name": "startCleaning", + "displayName": "Start cleaning" + }, + { + "id": "22c5aab2-6348-4a60-93b9-d09779b2366b", + "name": "pauseCleaning", + "displayName": "Pause cleaning" + }, + { + "id": "3c5c752b-429d-4749-9c69-89a6953bfd7d", + "name": "stopCleaning", + "displayName": "Stop cleaning" + }, + { + "id": "8f6831fb-1335-48e5-8235-e235feadf2b7", + "name": "returnToBase", + "displayName": "Return to base" + }, + { + "id": "da19677e-c04b-4114-a744-a14dee039c4f", + "name": "simulateError", + "displayName": "Simulate error" + } + ] } ] }