added basic thing states

master
bernhard.trinnes 2020-07-15 23:58:40 +02:00 committed by Boernsman
parent a42e1d2274
commit 1ed1306e50
5 changed files with 557 additions and 15 deletions

View File

@ -348,6 +348,42 @@ void HomeConnect::getProgramsActiveOption(const QString &haId, const QString &op
});
}
void HomeConnect::getStatus(const QString &haid)
{
QUrl url = QUrl(m_baseControlUrl+"/api/homeappliances/"+haid+"/status");
QNetworkRequest request(url);
request.setRawHeader("Authorization", "Bearer "+m_accessToken);
request.setRawHeader("Accept-Language", "en-US");
request.setRawHeader("accept", "application/vnd.bsh.sdk.v1+json");
QNetworkReply *reply = m_networkManager->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [this, reply]{
// Remote control activation state
// Remote start allowance state
// Local control state
// Operation state
// Door state
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCDebug(dcHomeConnect()) << "Get home appliances: Recieved invalide JSON object";
return;
}
qCDebug(dcHomeConnect()) << "Get home appliances" << data.toJson();
if (data.toVariant().toMap().contains("data")) {
QVariantMap dataMap = data.toVariant().toMap().value("data").toMap();
qCDebug(dcHomeConnect()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
} else if (data.toVariant().toMap().contains("error")) {
qCWarning(dcHomeConnect()) << "Get home appliences" << data.toVariant().toMap().value("error").toMap().value("description").toString();
}
});
}
/* Get a list of available setting of the home appliance.
* Possible Settings:
* Power state
@ -385,3 +421,42 @@ void HomeConnect::getSettings(const QString &haid)
}
});
}
QUuid HomeConnect::sendCommand(const QString &haid, const QString &command)
{
QUuid commandId = QUuid::createUuid();
QUrl url = QUrl(m_baseControlUrl+"/api/homeappliances/"+haid+"/commands/"+command);
QNetworkRequest request(url);
request.setRawHeader("Authorization", "Bearer "+m_accessToken);
request.setRawHeader("Accept-Language", "en-US");
request.setRawHeader("accept", "application/vnd.bsh.sdk.v1+json");
QJsonDocument doc;
QJsonObject data;
data.insert("key", command);
data.insert("value", true);
QJsonObject obj;
obj.insert("data", data);
doc.setObject(obj);
QNetworkReply *reply = m_networkManager->put(request, doc.toJson());
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, [this, commandId, reply]{
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCDebug(dcHomeConnect()) << "Send command: Recieved invalide JSON object";
return;
}
qCDebug(dcHomeConnect()) << "Send command" << data.toJson();
if (data.toVariant().toMap().contains("data")) {
QVariantMap dataMap = data.toVariant().toMap().value("data").toMap();
qCDebug(dcHomeConnect()) << "key" << dataMap.value("key").toString() << "value" << dataMap.value("value").toString() << dataMap.value("unit").toString();
} else if (data.toVariant().toMap().contains("error")) {
qCWarning(dcHomeConnect()) << "Send command" << data.toVariant().toMap().value("error").toMap().value("description").toString();
}
emit commandExecuted(commandId, true);
});
return commandId;
}

View File

@ -33,6 +33,7 @@
#include <QObject>
#include <QTimer>
#include <QUuid>
#include "network/networkaccessmanager.h"
@ -88,8 +89,11 @@ public:
void getProgramsAvailable(const QString &haId);
void getProgramsActiveOption(const QString &haId, const QString &optionKey);
void getStatus(const QString &haid);
void getSettings(const QString &haid);
QUuid sendCommand(const QString &haid, const QString &command); //commands "BSH.Common.Command.ResumeProgram" & "PauseProgram"
private:
bool m_simulationMode = false;
QByteArray m_baseAuthorizationUrl;
@ -112,7 +116,7 @@ private slots:
signals:
void connectionChanged(bool connected);
void authenticationStatusChanged(bool authenticated);
void actionExecuted(QUuid actionId,bool success);
void commandExecuted(QUuid commandId,bool success);
void receivedHomeAppliances(const QList<HomeAppliance> &appliances);
};

View File

@ -46,13 +46,15 @@ IntegrationPluginHomeConnect::IntegrationPluginHomeConnect()
m_idParamTypeIds.insert(dishwasherThingClassId, dishwasherThingIdParamTypeId);
m_idParamTypeIds.insert(washerThingClassId, washerThingIdParamTypeId);
m_idParamTypeIds.insert(ovenThingClassId, ovenThingIdParamTypeId);
m_idParamTypeIds.insert(cookTopThingClassId, cookTopThingIdParamTypeId);
//TODO add new devices
m_connectedStateTypeIds.insert(fridgeThingClassId, fridgeConnectedStateTypeId);
m_connectedStateTypeIds.insert(dryerThingClassId, dryerConnectedStateTypeId);
m_connectedStateTypeIds.insert(coffeMakerThingClassId, coffeMakerConnectedStateTypeId);
m_connectedStateTypeIds.insert(dishwasherThingClassId, dishwasherConnectedStateTypeId);
m_connectedStateTypeIds.insert(washerThingClassId, washerConnectedStateTypeId);
m_connectedStateTypeIds.insert(ovenThingClassId, ovenConnectedStateTypeId);
//TODO add new devices
}
void IntegrationPluginHomeConnect::startPairing(ThingPairingInfo *info)
@ -132,7 +134,7 @@ void IntegrationPluginHomeConnect::setupThing(ThingSetupInfo *info)
qCDebug(dcHomeConnect()) << "HomeConnect OAuth setup complete";
homeConnect = m_setupHomeConnectConnections.take(thing->id());
connect(homeConnect, &HomeConnect::connectionChanged, this, &IntegrationPluginHomeConnect::onConnectionChanged);
connect(homeConnect, &HomeConnect::actionExecuted, this, &IntegrationPluginHomeConnect::onRequestExecuted);
connect(homeConnect, &HomeConnect::commandExecuted, this, &IntegrationPluginHomeConnect::onRequestExecuted);
connect(homeConnect, &HomeConnect::authenticationStatusChanged, this, &IntegrationPluginHomeConnect::onAuthenticationStatusChanged);
connect(homeConnect, &HomeConnect::receivedHomeAppliances, this, &IntegrationPluginHomeConnect::onReceivedHomeAppliances);
m_homeConnectConnections.insert(thing, homeConnect);
@ -145,18 +147,18 @@ void IntegrationPluginHomeConnect::setupThing(ThingSetupInfo *info)
homeConnect = new HomeConnect(hardwareManager()->networkManager(), "423713AB3EDA5B44BCE6E7B3546C43DADCB27A156C681E30455250637B2213DB", "AE182EA9F1CB99416DFD62CE61BF6DCDB3BB7D4697B58D4499D3792EC9F7412D", simulationMode, this);
connect(homeConnect, &HomeConnect::connectionChanged, this, &IntegrationPluginHomeConnect::onConnectionChanged);
connect(homeConnect, &HomeConnect::actionExecuted, this, &IntegrationPluginHomeConnect::onRequestExecuted);
connect(homeConnect, &HomeConnect::commandExecuted, this, &IntegrationPluginHomeConnect::onRequestExecuted);
connect(homeConnect, &HomeConnect::authenticationStatusChanged, this, &IntegrationPluginHomeConnect::onAuthenticationStatusChanged);
connect(homeConnect, &HomeConnect::receivedHomeAppliances, this, &IntegrationPluginHomeConnect::onReceivedHomeAppliances);
homeConnect->getAccessTokenFromRefreshToken(refreshToken);
m_asyncSetup.insert(homeConnect, info);
}
} else if ((thing->thingClassId() == dryerThingClassId) ||
(thing->thingClassId() == fridgeThingClassId) ||
(thing->thingClassId() == washerThingClassId) ||
(thing->thingClassId() == dishwasherThingClassId) ||
(thing->thingClassId() == coffeMakerThingClassId) ||
(thing->thingClassId() == ovenThingClassId)) {
(thing->thingClassId() == fridgeThingClassId) ||
(thing->thingClassId() == washerThingClassId) ||
(thing->thingClassId() == dishwasherThingClassId) ||
(thing->thingClassId() == coffeMakerThingClassId) ||
(thing->thingClassId() == ovenThingClassId)) {
Thing *parentThing = myThings().findById(thing->parentId());
if (parentThing->setupComplete()) {
info->finish(Thing::ThingErrorNoError);
@ -179,12 +181,15 @@ void IntegrationPluginHomeConnect::postSetupThing(Thing *thing)
connect(m_pluginTimer5sec, &PluginTimer::timeout, this, [this]() {
foreach (Thing *connectionThing, myThings().filterByThingClassId(homeConnectConnectionThingClassId)) {
HomeConnect *HomeConnect = m_homeConnectConnections.value(connectionThing);
if (!HomeConnect) {
HomeConnect *homeConnect = m_homeConnectConnections.value(connectionThing);
if (!homeConnect) {
qWarning(dcHomeConnect()) << "No HomeConnect account found for" << connectionThing->name();
continue;
}
//TODO upate thing states
foreach (Thing *childThing, myThings().filterByParentId(connectionThing->id())) {
QString haid = childThing->paramValue(m_idParamTypeIds.value(childThing->thingClassId())).toString();
homeConnect->getStatus(haid);
}
}
});
}
@ -222,7 +227,8 @@ void IntegrationPluginHomeConnect::postSetupThing(Thing *thing)
if (!homeConnect) {
qCWarning(dcHomeConnect()) << "Could not find HomeConnect connection for thing" << thing->name();
} else {
homeConnect->getProgramsAvailable(haId);
homeConnect->getStatus(haId);
homeConnect->getSettings(haId);
}
} else {
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
@ -234,8 +240,15 @@ void IntegrationPluginHomeConnect::executeAction(ThingActionInfo *info)
Thing *thing = info->thing();
Action action = info->action();
if (thing->thingClassId() == homeConnectConnectionThingClassId) {
if (action.actionTypeId() == ActionTypeId("asdf")) { //TODO
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
} else if (thing->thingClassId() == ovenThingClassId) {
HomeConnect *homeConnect = m_homeConnectConnections.value(myThings().findById(thing->parentId()));
QString haid = thing->stateValue(m_idParamTypeIds.value(thing->thingClassId())).toString();
if (action.actionTypeId() == ovenPauseActionTypeId) {
homeConnect->sendCommand(haid, "BSH.Common.Command.PauseProgram");
} else if (action.actionTypeId() == ovenResumeActionTypeId) {
homeConnect->sendCommand(haid, "BSH.Common.Command.ResumeProgram");
} else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
}
@ -263,6 +276,21 @@ void IntegrationPluginHomeConnect::thingRemoved(Thing *thing)
}
}
void IntegrationPluginHomeConnect::browseThing(BrowseResult *result)
{
Q_UNUSED(result)
}
void IntegrationPluginHomeConnect::browserItem(BrowserItemResult *result)
{
Q_UNUSED(result)
}
void IntegrationPluginHomeConnect::executeBrowserItem(BrowserActionInfo *info)
{
Q_UNUSED(info)
}
void IntegrationPluginHomeConnect::onConnectionChanged(bool connected)
{
HomeConnect *homeConnect = static_cast<HomeConnect *>(sender());
@ -355,7 +383,7 @@ void IntegrationPluginHomeConnect::onReceivedHomeAppliances(QList<HomeConnect::H
thingClassId = fridgeThingClassId;
} else if (appliance.type.contains("WineCooler", Qt::CaseInsensitive)) {
thingClassId = fridgeThingClassId;
} else if (appliance.type.contains("CoffeMaker", Qt::CaseInsensitive)) {
} else if (appliance.type.contains("CoffeeMaker", Qt::CaseInsensitive)) {
thingClassId = coffeMakerThingClassId;
} else if (appliance.type.contains("Dryer", Qt::CaseInsensitive)) {
thingClassId = dryerThingClassId;

View File

@ -55,6 +55,10 @@ public:
void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override;
void browseThing(BrowseResult *result) override;
void browserItem(BrowserItemResult *result) override;
void executeBrowserItem(BrowserActionInfo *info) override;
private:
PluginTimer *m_pluginTimer5sec = nullptr;
PluginTimer *m_pluginTimer60sec = nullptr;

View File

@ -60,6 +60,7 @@
"displayName": "Oven",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "661c1603-356e-4a78-baf4-7ea0bc9da316",
@ -78,6 +79,86 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "e892ca9e-5b31-41f5-a568-44474091f0f6",
"name": "doorState",
"displayName": "Door state",
"displayNameEvent": "Door state changed",
"defaultValue": "Open",
"type": "QString",
"possibleValues": [
"Open",
"Closed"
]
},
{
"id": "c9f9bd33-513f-4834-a504-c2c1611fb4be",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Inactive",
"type": "QString",
"possibleValues": [
"Inactive",
"Ready",
"Delayed start",
"Run",
"Pause",
"Action required",
"Finished",
"Error",
"Aborting"
]
},
{
"id": "8843a1ce-796a-40c3-ab24-cf97b821d45c",
"name": "localControlState",
"displayName": "Local control state",
"displayNameEvent": "Local control state changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "6afd574a-3c22-46cd-bc28-4dfcba01c51d",
"name": "remoteControlActivationState",
"displayName": "Remote control activation state",
"displayNameEvent": "Remote control state activation changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "9f9cb8ea-8527-48c9-8bf2-f5148d5b53f1",
"name": "remoteStartAllowanceState",
"displayName": "Remote start allowance state",
"displayNameEvent": "Remote start allowance changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "f3f5f257-5887-4d64-b61a-8179424912b3",
"name": "targetTemperature",
"displayName": "Target temperature",
"displayNameEvent": "Target temperature changed",
"displayNameAction": "Set target temperature",
"defaultValue": 180,
"minValue": 30,
"maxValue": 250,
"writable": true,
"unit": "DegreeCelsius",
"type": "int"
}
],
"actionTypes": [
{
"id": "c7b9b467-6ac5-4870-8874-da977fa30987",
"name": "pause",
"displayName": "Pause"
},
{
"id": "0467aeed-b275-4e5f-a288-1a600465b582",
"name": "resume",
"displayName": "Resume"
}
]
},
@ -87,6 +168,7 @@
"displayName": "Dishwasher",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "f6b86d1b-481a-4496-975e-055f5ecc2bdb",
@ -105,6 +187,51 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "8cbb3746-7e04-4fc8-93eb-b774b606a057",
"name": "doorState",
"displayName": "Door state",
"displayNameEvent": "Door state changed",
"defaultValue": "Open",
"type": "QString",
"possibleValues": [
"Open",
"Closed"
]
},
{
"id": "2b45fbfc-d3d7-4dd4-91f8-4a789405246e",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Inactive",
"type": "QString",
"possibleValues": [
"Inactive",
"Ready",
"Delayed start",
"Run",
"Action required",
"Finished",
"Aborting"
]
},
{
"id": "c8bf60d2-e8e3-44dd-9cea-c7bcbe17c2b1",
"name": "remoteControlActivationState",
"displayName": "Remote control activation state",
"displayNameEvent": "Remote control state activation changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "a8ce4a4e-fae3-4100-ad05-7c390b774b4a",
"name": "remoteStartAllowanceState",
"displayName": "Remote start allowance state",
"displayNameEvent": "Remote start allowance changed",
"defaultValue": false,
"type": "bool"
}
]
},
@ -114,6 +241,7 @@
"displayName": "Coffe Maker",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "85d48203-e97b-45cc-a899-494c375389a5",
@ -132,6 +260,51 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "5011efa7-9915-4ecc-b717-6ced369abcb7",
"name": "doorState",
"displayName": "Door state",
"displayNameEvent": "Door state changed",
"defaultValue": "Open",
"type": "QString",
"possibleValues": [
"Open",
"Closed"
]
},
{
"id": "693fc8d2-d9a9-4109-b8c5-f3d22091500c",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Inactive",
"type": "QString",
"possibleValues": [
"Inactive",
"Ready",
"Run",
"Action required",
"Finished",
"Error",
"Aborting"
]
},
{
"id": "dc0fbd4b-364e-4856-a237-7d789a99f321",
"name": "localControlState",
"displayName": "Local control state",
"displayNameEvent": "Local control state changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "598985c1-7c9a-4b04-aabd-f72e6dd8cab8",
"name": "remoteStartAllowanceState",
"displayName": "Remote start allowance state",
"displayNameEvent": "Remote start allowance changed",
"defaultValue": false,
"type": "bool"
}
]
},
@ -141,6 +314,7 @@
"displayName": "Dryer",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "cad8a1f9-6313-48dd-bb1d-b285006c760b",
@ -159,6 +333,74 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "81aa609e-69c0-4d5c-98f0-46e6f14c7eaa",
"name": "doorState",
"displayName": "Door state",
"displayNameEvent": "Door state changed",
"defaultValue": "Open",
"type": "QString",
"possibleValues": [
"Open",
"Closed",
"Locked"
]
},
{
"id": "52fde732-ed14-437e-8fbf-461d2ed19654",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Inactive",
"type": "QString",
"possibleValues": [
"Inactive",
"Ready",
"Delayed start",
"Run",
"Pause",
"Action required",
"Finished",
"Error",
"Aborting"
]
},
{
"id": "d73c04c4-7082-4259-a225-10c453247103",
"name": "localControlState",
"displayName": "Local control state",
"displayNameEvent": "Local control state changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "ed8a56a1-18db-469f-b51d-487111037c71",
"name": "remoteControlActivationState",
"displayName": "Remote control activation state",
"displayNameEvent": "Remote control state activation changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "d18d89c1-d04f-491c-b817-7234ea531deb",
"name": "remoteStartAllowanceState",
"displayName": "Remote start allowance state",
"displayNameEvent": "Remote start allowance changed",
"defaultValue": false,
"type": "bool"
}
],
"actionTypes": [
{
"id": "aedd85a6-0f9a-4bc4-b2ba-90ba11d1a955",
"name": "pause",
"displayName": "Pause"
},
{
"id": "8c9923f6-2a2d-48bb-aaf4-5f887565c58a",
"name": "resume",
"displayName": "Resume"
}
]
},
@ -186,6 +428,18 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "99bba70c-5ead-4076-8b71-720a931668a4",
"name": "doorState",
"displayName": "Door state",
"displayNameEvent": "Door state changed",
"defaultValue": "Open",
"type": "QString",
"possibleValues": [
"Open",
"Closed"
]
}
]
},
@ -195,6 +449,7 @@
"displayName": "Washer",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"browsable": true,
"paramTypes": [
{
"id": "be4a1dcf-a0ce-44bb-a374-65f875e53c94",
@ -213,6 +468,182 @@
"defaultValue": true,
"cached": false,
"type": "bool"
},
{
"id": "99296e86-09bf-4b74-b122-ee82b6bfdb62",
"name": "doorState",
"displayName": "Door state",
"displayNameEvent": "Door state changed",
"defaultValue": "Open",
"type": "QString",
"possibleValues": [
"Open",
"Closed",
"Locked"
]
},
{
"id": "2ad3e2f8-c955-4e1d-b394-1e71a16f03bb",
"name": "operationState",
"displayName": "Operation state",
"displayNameEvent": "Operation state changed",
"defaultValue": "Inactive",
"type": "QString",
"possibleValues": [
"Inactive",
"Ready",
"Delayed start",
"Run",
"Pause",
"Action required",
"Finished",
"Error",
"Aborting"
]
},
{
"id": "f3aa6f6e-bfa3-4465-906c-3d5137d4098c",
"name": "localControlState",
"displayName": "Local control state",
"displayNameEvent": "Local control state changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "3c9c7163-b5f5-47cc-86b1-aa95273a22f6",
"name": "remoteControlActivationState",
"displayName": "Remote control activation state",
"displayNameEvent": "Remote control state activation changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "f7a68b23-6d74-451b-89c8-b2d2fb5d0839",
"name": "remoteStartAllowanceState",
"displayName": "Remote start allowance state",
"displayNameEvent": "Remote start allowance changed",
"defaultValue": false,
"type": "bool"
}
],
"actionTypes": [
{
"id": "c87d6825-f37d-4da6-8545-945bd589dbc2",
"name": "pause",
"displayName": "Pause"
},
{
"id": "044582ca-30e6-4d37-9377-809fb5fa120a",
"name": "resume",
"displayName": "Resume"
}
]
},
{
"id": "6ab99f5b-c8b6-4391-84d3-2e258a529174",
"name": "cookTop",
"displayName": "Cook top",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "5babea64-0cd3-4477-9b95-3a71433b9c0c",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "d8113d26-045d-4fd5-a2f5-f202968408e0",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "62ce7eee-f6bb-43e5-8adf-dfd030276987",
"name": "hood",
"displayName": "Hood",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "7aa9f92a-e8ad-4b89-80d2-4ed0f3ead114",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "bb137bcd-bb6e-464b-8fdc-fb376efd1f59",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "a7bfe39f-14d1-481a-a255-eea7f40e0c07",
"name": "cleaningRobot",
"displayName": "Cleaning robot",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "a48821ab-b777-4d34-9b49-f3422c190825",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "f0f81c21-b10e-44ef-8606-600ebaf646e0",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
},
{
"id": "8b792638-11dc-4288-ac94-5b41d9e11a4e",
"name": "cookProcessor",
"displayName": "Cook processor",
"interfaces": ["connectable"],
"createMethods": ["auto"],
"paramTypes": [
{
"id": "a104145b-a373-45b3-a457-0245681f8256",
"name": "id",
"displayName": "ID",
"defaultValue": "-",
"type": "QString"
}
],
"stateTypes": [
{
"id": "434c5690-a62d-4815-ad8b-e3c306745d9f",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"defaultValue": true,
"cached": false,
"type": "bool"
}
]
}