diff --git a/tplink/README.md b/tplink/README.md index 379a3444..4cadc8bd 100644 --- a/tplink/README.md +++ b/tplink/README.md @@ -7,6 +7,7 @@ This plugin adds support for the following tp-link Kasa devices to nymea. * HS105 Kasa Smart Wi-Fi Plug Mini * HS110 Kasa Smart Wi-Fi Plug With Energy Monitoring * HS200 Kasa Smart Wi-Fi Light Switch +* HS300 Kasa Smart Wi-Fi Power Strip * KP100 Kasa Smart Wi-Fi Plug Slim Edition In order to use such a device, it must be connected to the same network as nymea. The Kasa app is required diff --git a/tplink/integrationplugintplink.cpp b/tplink/integrationplugintplink.cpp index 8a8e0787..f16fc16a 100644 --- a/tplink/integrationplugintplink.cpp +++ b/tplink/integrationplugintplink.cpp @@ -39,33 +39,62 @@ #include #include -// https://github.com/softScheck/tplink-smartplug/blob/master/tplink-smarthome-commands.txt +// Related projects: + +// Local api: +// https://github.com/plasticrake/tplink-smarthome-api/ +// https://github.com/softScheck/tplink-smartplug + +// Cloud api: +// https://github.com/piekstra/tplink-cloud-api/ + +QHash idParamTypesMap = { + {kasaPlug100ThingClassId, kasaPlug100ThingIdParamTypeId}, + {kasaPlug110ThingClassId, kasaPlug110ThingIdParamTypeId}, + {kasaSwitch200ThingClassId, kasaSwitch200ThingIdParamTypeId}, + {kasaPowerStrip300ThingClassId, kasaPowerStrip300ThingIdParamTypeId}, +}; + +QHash connectedStateTypesMap = { + {kasaPlug100ThingClassId, kasaPlug100ConnectedStateTypeId}, + {kasaPlug110ThingClassId, kasaPlug110ConnectedStateTypeId}, + {kasaSwitch200ThingClassId, kasaSwitch200ConnectedStateTypeId}, + {kasaPowerStrip300ThingClassId, kasaPowerStrip300ConnectedStateTypeId}, +}; + + +QHash signalStrengthStateTypesMap = { + {kasaPlug100ThingClassId, kasaPlug100SignalStrengthStateTypeId}, + {kasaPlug110ThingClassId, kasaPlug110SignalStrengthStateTypeId}, + {kasaSwitch200ThingClassId, kasaSwitch200SignalStrengthStateTypeId}, + {kasaPowerStrip300ThingClassId, kasaPowerStrip300SignalStrengthStateTypeId}, +}; + +QHash powerStateTypesMap = { + {kasaPlug100ThingClassId, kasaPlug100PowerStateTypeId}, + {kasaPlug110ThingClassId, kasaPlug110PowerStateTypeId}, + {kasaSwitch200ThingClassId, kasaSwitch200PowerStateTypeId}, +}; + +QHash currentPowerStatetTypesMap = { + {kasaPlug110ThingClassId, kasaPlug110CurrentPowerStateTypeId}, + {kasaPowerStrip300ThingClassId, kasaPowerStrip300CurrentPowerStateTypeId}, +}; + +QHash totalEnergyConsumedStatetTypesMap = { + {kasaPlug110ThingClassId, kasaPlug110TotalEnergyConsumedStateTypeId}, + {kasaPowerStrip300ThingClassId, kasaPowerStrip300TotalEnergyConsumedStateTypeId}, +}; + +QHash powerActionParamTypesMap = { + {kasaPlug100ThingClassId, kasaPlug100PowerActionPowerParamTypeId}, + {kasaPlug110ThingClassId, kasaPlug110PowerActionPowerParamTypeId}, + {kasaSwitch200ThingClassId, kasaSwitch200PowerActionPowerParamTypeId}, +}; + IntegrationPluginTPLink::IntegrationPluginTPLink() { - m_idParamTypesMap[kasaPlug100ThingClassId] = kasaPlug100ThingIdParamTypeId; - m_idParamTypesMap[kasaPlug110ThingClassId] = kasaPlug110ThingIdParamTypeId; - m_idParamTypesMap[kasaSwitch200ThingClassId] = kasaSwitch200ThingIdParamTypeId; - - m_connectedStateTypesMap[kasaPlug100ThingClassId] = kasaPlug100ConnectedStateTypeId; - m_connectedStateTypesMap[kasaPlug110ThingClassId] = kasaPlug110ConnectedStateTypeId; - m_connectedStateTypesMap[kasaSwitch200ThingClassId] = kasaSwitch200ConnectedStateTypeId; - - m_signalStrengthStateTypesMap[kasaPlug100ThingClassId] = kasaPlug100SignalStrengthStateTypeId; - m_signalStrengthStateTypesMap[kasaPlug110ThingClassId] = kasaPlug110SignalStrengthStateTypeId; - m_signalStrengthStateTypesMap[kasaSwitch200ThingClassId] = kasaSwitch200SignalStrengthStateTypeId; - - m_powerStatetTypesMap[kasaPlug100ThingClassId] = kasaPlug100PowerStateTypeId; - m_powerStatetTypesMap[kasaPlug110ThingClassId] = kasaPlug110PowerStateTypeId; - m_powerStatetTypesMap[kasaSwitch200ThingClassId] = kasaSwitch200PowerStateTypeId; - - m_currentPowerStatetTypesMap[kasaPlug110ThingClassId] = kasaPlug110CurrentPowerStateTypeId; - - m_totalEnergyConsumedStatetTypesMap[kasaPlug110ThingClassId] = kasaPlug110TotalEnergyConsumedStateTypeId; - - m_powerActionParamTypesMap[kasaPlug100ThingClassId] = kasaPlug100PowerActionPowerParamTypeId; - m_powerActionParamTypesMap[kasaPlug110ThingClassId] = kasaPlug110PowerActionPowerParamTypeId; - m_powerActionParamTypesMap[kasaSwitch200ThingClassId] = kasaSwitch200PowerActionPowerParamTypeId; } IntegrationPluginTPLink::~IntegrationPluginTPLink() @@ -95,9 +124,9 @@ void IntegrationPluginTPLink::discoverThings(ThingDiscoveryInfo *info) QTimer::singleShot(2000, info, [this, info](){ while(m_broadcastSocket->hasPendingDatagrams()) { - char buffer[1024]; + char buffer[4096]; QHostAddress senderAddress; - qint64 len = m_broadcastSocket->readDatagram(buffer, 1024, &senderAddress); + qint64 len = m_broadcastSocket->readDatagram(buffer, 4096, &senderAddress); QByteArray data = decryptPayload(QByteArray::fromRawData(buffer, len)); QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); @@ -117,18 +146,31 @@ void IntegrationPluginTPLink::discoverThings(ThingDiscoveryInfo *info) modelFilter = QRegExp("HS110.*"); } else if (info->thingClassId() == kasaSwitch200ThingClassId) { modelFilter = QRegExp("HS200.*"); + } else if (info->thingClassId() == kasaPowerStrip300ThingClassId) { + modelFilter = QRegExp("HS300.*"); } QString model = sysInfo.value("model").toString(); if (modelFilter.exactMatch(model)) { ThingDescriptor descriptor(info->thingClassId(), sysInfo.value("alias").toString(), sysInfo.value("dev_name").toString()); - Param idParam = Param(m_idParamTypesMap.value(info->thingClassId()), sysInfo.value("deviceId").toString()); + Param idParam = Param(idParamTypesMap.value(info->thingClassId()), sysInfo.value("deviceId").toString()); descriptor.setParams(ParamList() << idParam); Thing *existingThing = myThings().findByParams(ParamList() << idParam); if (existingThing) { descriptor.setThingId(existingThing->id()); } - info->addThingDescriptor(descriptor); + + // Sometimes kasa devices reply multiple times on the discovery call. Prevent duplicates in the search results. + bool found = false; + foreach (const ThingDescriptor &existingDescriptor, info->thingDescriptors()) { + if (existingDescriptor.params().paramValue(idParamTypesMap.value(info->thingClassId())) == idParam.value()) { + found = true; + break; + } + } + if (!found) { + info->addThingDescriptor(descriptor); + } } else { qCWarning(dcTplink()) << "Ignoring not matching device type:\n" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented)); } @@ -140,6 +182,12 @@ void IntegrationPluginTPLink::discoverThings(ThingDiscoveryInfo *info) void IntegrationPluginTPLink::setupThing(ThingSetupInfo *info) { + if (info->thing()->thingClassId() == kasaSocketThingClassId) { + qCDebug(dcTplink()) << "Setup thing for child socket:" << info->thing()->paramValue(kasaSocketThingIdParamTypeId).toString(); + info->finish(Thing::ThingErrorNoError); + return; + } + QVariantMap map; QVariantMap getSysInfo; getSysInfo.insert("get_sysinfo", QVariant()); @@ -159,9 +207,9 @@ void IntegrationPluginTPLink::setupThing(ThingSetupInfo *info) QTimer::singleShot(2000, info, [this, info](){ while(m_broadcastSocket->hasPendingDatagrams()) { - char buffer[1024]; + char buffer[4096]; QHostAddress senderAddress; - qint64 len = m_broadcastSocket->readDatagram(buffer, 1024, &senderAddress); + qint64 len = m_broadcastSocket->readDatagram(buffer, 4096, &senderAddress); QByteArray data = decryptPayload(QByteArray::fromRawData(buffer, len)); QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); @@ -171,13 +219,33 @@ void IntegrationPluginTPLink::setupThing(ThingSetupInfo *info) } QVariantMap properties = jsonDoc.toVariant().toMap(); QVariantMap sysInfo = properties.value("system").toMap().value("get_sysinfo").toMap(); - if (info->thing()->paramValue(m_idParamTypesMap.value(info->thing()->thingClassId())).toString() == sysInfo.value("deviceId").toString()) { + if (info->thing()->paramValue(idParamTypesMap.value(info->thing()->thingClassId())).toString() == sysInfo.value("deviceId").toString()) { qCDebug(dcTplink()) << "Found thing at" << senderAddress; + // We need to finish the setup before we can generate childs for this thing + info->finish(Thing::ThingErrorNoError); + m_setupRetries.remove(info); + + // Set up child sockets if needed (currently only the HS300) + QVariantList children = sysInfo.value("children").toList(); + if (children.count() > 0 && myThings().filterByParentId(info->thing()->id()).isEmpty()) { + ThingDescriptors descriptors; + foreach (const QVariant &childVariant, children) { + QVariantMap childMap = childVariant.toMap(); + ThingDescriptor descriptor(kasaSocketThingClassId, childMap.value("alias").toString(), QString(), info->thing()->id()); + + QString devId = QString("%1%2") + .arg(info->thing()->paramValue(idParamTypesMap.value(info->thing()->thingClassId())).toString()) + .arg(childMap.value("id").toString()); + descriptor.setParams(ParamList() << Param(kasaSocketThingIdParamTypeId, devId)); + qCDebug(dcTplink()) << "Creating child socket for" << info->thing()->name() << "with ID" << devId; + descriptors.append(descriptor); + } + emit autoThingsAppeared(descriptors); + } + connectToDevice(info->thing(), senderAddress); - info->finish(Thing::ThingErrorNoError); - m_setupRetries.remove(info); return; } } @@ -195,6 +263,7 @@ void IntegrationPluginTPLink::setupThing(ThingSetupInfo *info) void IntegrationPluginTPLink::postSetupThing(Thing *thing) { + qCDebug(dcTplink()) << "Post setup thing" << thing->name(); connect(thing, &Thing::nameChanged, this, [this, thing](){ QVariantMap map; QVariantMap systemMap; @@ -221,12 +290,18 @@ void IntegrationPluginTPLink::postSetupThing(Thing *thing) m_timer = hardwareManager()->pluginTimerManager()->registerTimer(1); connect(m_timer, &PluginTimer::timeout, this, [this](){ foreach (Thing *d, myThings()) { - if (!m_pendingJobs.contains(d) && m_jobQueue[d].isEmpty()) { + if (d->parentId().isNull() && !m_pendingJobs.contains(d) && m_jobQueue[d].isEmpty()) { fetchState(d); } } }); } + + // Update connected state in case the parent connected before we've completed the child setups + if (thing->thingClassId() == kasaSocketThingClassId) { + Thing *parent = myThings().findById(thing->parentId()); + thing->setStateValue(kasaSocketConnectedStateTypeId, parent->stateValue(connectedStateTypesMap.value(parent->thingClassId()))); + } } void IntegrationPluginTPLink::thingRemoved(Thing *thing) @@ -244,14 +319,23 @@ void IntegrationPluginTPLink::thingRemoved(Thing *thing) void IntegrationPluginTPLink::executeAction(ThingActionInfo *info) { - QVariantMap map; - QVariantMap systemMap; + // The actual thing to send the command to (either directly a physical thing or in case of a virtual socket the parent thing) + Thing *targetThing = info->thing()->parentId().isNull() ? info->thing() : myThings().findById(info->thing()->parentId()); + QVariantMap powerMap; - ParamTypeId powerActionParamTypeId = m_powerActionParamTypesMap.value(info->thing()->thingClassId()); - powerMap.insert("state", info->action().param(powerActionParamTypeId).value().toBool() ? 1 : 0); + powerMap.insert("state", info->action().param(info->action().actionTypeId()).value().toBool() ? 1 : 0); + QVariantMap systemMap; systemMap.insert("set_relay_state", powerMap); + QVariantMap map; map.insert("system", systemMap); + // If we're switching a virtual child, we need to add a context map for the child_ids + if (info->thing()->thingClassId() == kasaSocketThingClassId) { + QVariantMap contextMap; + contextMap.insert("child_ids", QVariantList() << info->thing()->paramValue(kasaSocketThingIdParamTypeId).toString()); + map.insert("context", contextMap); + } + qCDebug(dcTplink()) << "Executing action" << qUtf8Printable(QJsonDocument::fromVariant(map).toJson(QJsonDocument::Compact)); QByteArray payload = encryptPayload(QJsonDocument::fromVariant(map).toJson(QJsonDocument::Compact)); @@ -264,15 +348,15 @@ void IntegrationPluginTPLink::executeAction(ThingActionInfo *info) job.id = m_jobIdx++; job.data = data; job.actionInfo = info; - m_jobQueue[info->thing()].append(job); + m_jobQueue[targetThing].append(job); connect(info, &ThingActionInfo::aborted, this, [=](){ - m_jobQueue[info->thing()].removeAll(job); + m_jobQueue[targetThing].removeAll(job); }); // Directly queue up fetchState - fetchState(info->thing(), info); + fetchState(targetThing); - processQueue(info->thing()); + processQueue(targetThing); } QByteArray IntegrationPluginTPLink::encryptPayload(const QByteArray &payload) @@ -311,9 +395,16 @@ void IntegrationPluginTPLink::connectToDevice(Thing *thing, const QHostAddress & m_sockets.insert(thing, socket); connect(socket, &QTcpSocket::connected, thing, [this, thing, address] () { - qCDebug(dcTplink()) << "Connected to device" << address; - StateTypeId connectedStateTypeId = m_connectedStateTypesMap.value(thing->thingClassId()); + qCDebug(dcTplink()) << "Connected to device" << thing->name() << "at address:" << address; + StateTypeId connectedStateTypeId = connectedStateTypesMap.value(thing->thingClassId()); thing->setStateValue(connectedStateTypeId, true); + + qCDebug(dcTplink()) << "Has childs:" << myThings().count(); + foreach (Thing *child, myThings().filterByParentId(thing->id())) { + qCDebug(dcTplink()) << "Setting child online:" << child->paramValue(kasaSocketThingIdParamTypeId); + child->setStateValue(kasaSocketConnectedStateTypeId, true); + } + fetchState(thing); }); @@ -343,6 +434,7 @@ void IntegrationPluginTPLink::connectToDevice(Thing *thing, const QHostAddress & processQueue(thing); return; } + Job job = m_pendingJobs.take(thing); QJsonParseError error; @@ -368,21 +460,48 @@ void IntegrationPluginTPLink::connectToDevice(Thing *thing, const QHostAddress & } } if (systemMap.contains("get_sysinfo")) { - int relayState = systemMap.value("get_sysinfo").toMap().value("relay_state").toInt(); - StateTypeId powerStateTypeId = m_powerStatetTypesMap.value(thing->thingClassId()); - thing->setStateValue(powerStateTypeId, relayState == 1 ? true : false); - StateTypeId signalStrengthStateTypeId = m_signalStrengthStateTypesMap.value(thing->thingClassId()); + StateTypeId signalStrengthStateTypeId = signalStrengthStateTypesMap.value(thing->thingClassId()); int rssi = systemMap.value("get_sysinfo").toMap().value("rssi").toInt(); - int signalStrength = qMax(0, qMin(1000, 2 * (rssi + 100))); + int signalStrength = qMax(0, qMin(100, 2 * (rssi + 100))); thing->setStateValue(signalStrengthStateTypeId, signalStrength); + if (thing->thingClassId() == kasaSocketThingClassId) { + foreach (Thing *child, myThings().filterByParentId(kasaSocketThingClassId)) { + child->setStateValue(kasaSocketSignalStrengthStateTypeId, signalStrength); + } + } + QString alias = systemMap.value("get_sysinfo").toMap().value("alias").toString(); if (thing->name() != alias) { thing->setName(alias); } + if (systemMap.value("get_sysinfo").toMap().contains("relay_state")) { + int relayState = systemMap.value("get_sysinfo").toMap().value("relay_state").toInt(); + StateTypeId powerStateTypeId = powerStateTypesMap.value(thing->thingClassId()); + thing->setStateValue(powerStateTypeId, relayState == 1 ? true : false); + + } else if (systemMap.value("get_sysinfo").toMap().contains("children")) { + // For now, only the HS300 has children, which we map to child things of type kasaSocket + QVariantList children = systemMap.value("get_sysinfo").toMap().value("children").toList(); + foreach (const QVariant &childVariant, children) { + QVariantMap childMap = childVariant.toMap(); + QString idParam = childMap.value("id").toString(); + bool relayState = childMap.value("state").toInt() == 1; + Things things = myThings().filterByParentId(thing->id()).filterByParam(kasaSocketThingIdParamTypeId, idParam); + if (things.count() == 1) { + things.first()->setStateValue(kasaSocketPowerStateTypeId, relayState); + } else { + qCWarning(dcTplink()) << "Error matching child devices" << qUtf8Printable(jsonDoc.toJson()); + foreach (Thing *child, myThings().filterByParentId(thing->id())) { + qCDebug(dcTplink()) << "Existing child device:" << child->name() << child->params(); + } + } + } + } if (job.actionInfo) { + qCDebug(dcTplink()) << "Finishing action execution"; job.actionInfo->finish(Thing::ThingErrorNoError); } } @@ -391,13 +510,13 @@ void IntegrationPluginTPLink::connectToDevice(Thing *thing, const QHostAddress & QVariantMap emeterMap = map.value("emeter").toMap(); if (emeterMap.contains("get_realtime")) { // This has quite a bit of jitter... Let's smoothen it while within +/- 0.1W to produce less events in the system - StateTypeId currentPowerStateTypeId = m_currentPowerStatetTypesMap.value(thing->thingClassId()); + StateTypeId currentPowerStateTypeId = currentPowerStatetTypesMap.value(thing->thingClassId()); double oldValue = thing->stateValue(currentPowerStateTypeId).toDouble(); double newValue = emeterMap.value("get_realtime").toMap().value("power_mw").toDouble() / 1000; if (qAbs(oldValue - newValue) > 0.1) { thing->setStateValue(currentPowerStateTypeId, newValue); } - StateTypeId totalEnergyConsumedStateTypeId = m_totalEnergyConsumedStatetTypesMap.value(thing->thingClassId()); + StateTypeId totalEnergyConsumedStateTypeId = totalEnergyConsumedStatetTypesMap.value(thing->thingClassId()); thing->setStateValue(totalEnergyConsumedStateTypeId, emeterMap.value("get_realtime").toMap().value("total_wh").toDouble() / 1000); } } @@ -406,16 +525,23 @@ void IntegrationPluginTPLink::connectToDevice(Thing *thing, const QHostAddress & } }); - connect(socket, &QTcpSocket::disconnected, thing, [this, thing, address](){ - qCDebug(dcTplink()) << "Device disconnected"; - m_sockets.take(thing)->deleteLater(); - if (m_pendingJobs.contains(thing)) { - // Putting active job back to queue - m_jobQueue[thing].prepend(m_pendingJobs.take(thing)); + connect(socket, &QTcpSocket::stateChanged, thing, [this, thing, address](QAbstractSocket::SocketState newState){ + if (newState == QAbstractSocket::UnconnectedState) { + qCDebug(dcTplink()) << "Device disconnected"; + m_sockets.take(thing)->deleteLater(); + if (m_pendingJobs.contains(thing)) { + // Putting active job back to queue + m_jobQueue[thing].prepend(m_pendingJobs.take(thing)); + } + StateTypeId connectedStateTypeId = connectedStateTypesMap.value(thing->thingClassId()); + thing->setStateValue(connectedStateTypeId, false); + + foreach (Thing *child, myThings().filterByParentId(thing->id())) { + child->setStateValue(kasaSocketConnectedStateTypeId, false); + } + + QTimer::singleShot(500, thing, [this, thing, address]() {connectToDevice(thing, address);}); } - StateTypeId connectedStateTypeId = m_connectedStateTypesMap.value(thing->thingClassId()); - thing->setStateValue(connectedStateTypeId, false); - QTimer::singleShot(500, thing, [this, thing, address]() {connectToDevice(thing, address);}); }); socket->connectToHost(address.toString(), 9999, QIODevice::ReadWrite); @@ -423,11 +549,6 @@ void IntegrationPluginTPLink::connectToDevice(Thing *thing, const QHostAddress & void IntegrationPluginTPLink::fetchState(Thing *thing, ThingActionInfo *info) { - QTcpSocket *socket = m_sockets.value(thing); - if (!socket || !socket->isOpen()) { - qCWarning(dcTplink()) << "Cannot fetch state"; - } - QVariantMap map; QVariantMap getSysInfo; getSysInfo.insert("get_sysinfo", QVariant()); @@ -456,6 +577,7 @@ void IntegrationPluginTPLink::fetchState(Thing *thing, ThingActionInfo *info) void IntegrationPluginTPLink::processQueue(Thing *thing) { if (m_pendingJobs.contains(thing)) { + qCDebug(dcTplink()) << "Already processing a message to" << thing->name(); // Busy return; } diff --git a/tplink/integrationplugintplink.h b/tplink/integrationplugintplink.h index 669676eb..ccec936c 100644 --- a/tplink/integrationplugintplink.h +++ b/tplink/integrationplugintplink.h @@ -85,14 +85,6 @@ private: QHash m_inputBuffers; PluginTimer *m_timer = nullptr; - - QHash m_idParamTypesMap; - QHash m_connectedStateTypesMap; - QHash m_signalStrengthStateTypesMap; - QHash m_powerStatetTypesMap; - QHash m_currentPowerStatetTypesMap; - QHash m_totalEnergyConsumedStatetTypesMap; - QHash m_powerActionParamTypesMap; }; #endif // INTEGRATIONPLUGINANEL_H diff --git a/tplink/integrationplugintplink.json b/tplink/integrationplugintplink.json index 4097c25c..d0625fef 100644 --- a/tplink/integrationplugintplink.json +++ b/tplink/integrationplugintplink.json @@ -172,6 +172,111 @@ "writable": true } ] + }, + { + "id": "bbdee989-9431-4187-b135-5030a7a11be2", + "name": "kasaPowerStrip300", + "displayName": "Kasa Smart Wi-Fi Power Strip (HS300)", + "createMethods": ["discovery"], + "interfaces": [ "gateway", "extendedsmartmeterconsumer", "wirelessconnectable" ], + "paramTypes": [ + { + "id": "62b38ddf-f6d7-44e1-955f-f04b375d960d", + "name": "id", + "displayName": "ID", + "type": "QString", + "defaultValue": "" + } + ], + "stateTypes": [ + { + "id": "9bcec21d-7207-44c6-8ebf-d2720bb7a63a", + "name": "connected", + "displayName": "Connected", + "displayNameEvent": "Connected changed", + "type": "bool", + "defaultValue": false, + "cached": false + }, + { + "id": "1a587f62-8274-4c2e-bdc6-1b0b6368e5f7", + "name": "signalStrength", + "displayName": "Signal strength", + "displayNameEvent": "Signal strength changed", + "type": "uint", + "unit": "Percentage", + "minValue": 0, + "maxValue": 100, + "defaultValue": 100 + }, + { + "id": "f2992226-1f36-477f-b053-04dc5dc3a31c", + "name": "totalEnergyConsumed", + "displayName": "Total energy consumed", + "displayNameEvent": "Total energy consumed changed", + "type": "double", + "unit": "KiloWattHour", + "defaultValue": 0 + }, + { + "id": "f973b4e8-99fb-4331-8193-e287bd37f5a0", + "name": "currentPower", + "displayName": "Current power consumption", + "displayNameEvent": "Current power consumption changed", + "type": "double", + "unit": "Watt", + "defaultValue": 0 + } + ] + }, + { + "id": "2f40e28c-2484-4e09-bda9-e7accc29ab41", + "name": "kasaSocket", + "displayName": "Kasa power socket", + "createMethods": ["auto"], + "interfaces": ["powersocket", "wirelessconnectable"], + "paramTypes": [ + { + "id": "dd944807-c7f2-49da-b443-b69eb8387f41", + "name": "id", + "displayName": "ID", + "type": "QString", + "defaultValue": "" + } + ], + "stateTypes": [ + { + "id": "59feb3a8-d35e-4c10-ac2e-01361e711a5e", + "name": "connected", + "displayName": "Connected", + "displayNameEvent": "Connected changed", + "type": "bool", + "defaultValue": false, + "cached": false + }, + { + "id": "16b71516-2ff4-4a2f-b0fc-53fff11f3a16", + "name": "signalStrength", + "displayName": "Signal strength", + "displayNameEvent": "Signal strength changed", + "type": "uint", + "unit": "Percentage", + "minValue": 0, + "maxValue": 100, + "defaultValue": 100 + }, + { + "id": "b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8", + "name": "power", + "displayName": "Power", + "displayNameEvent": "Turned on or off", + "displayNameAction": "Turn on or off", + "type": "bool", + "defaultValue": false, + "writable": true, + "ioType": "digitalOutput" + } + ] } ] } diff --git a/tplink/sampledata/HS105-TCP.txt b/tplink/sampledata/HS105-TCP.txt new file mode 100644 index 00000000..e6684de9 --- /dev/null +++ b/tplink/sampledata/HS105-TCP.txt @@ -0,0 +1,37 @@ +{ + "emeter": { + "err_code": -1, + "err_msg": "module not support" + }, + "system": { + "get_sysinfo": { + "active_mode": "none", + "alias": "Kasa Plug Mini HS105", + "dev_name": "Smart Wi-Fi Plug Mini", + "deviceId": "8006F282D515B22F869313C3D0F2E45F1D93EEC2", + "err_code": 0, + "feature": "TIM", + "hwId": "845AC58F61A995F454064635A2E42A92", + "hw_ver": "4.0", + "icon_hash": "", + "latitude_i": 398287, + "led_off": 0, + "longitude_i": -1049759, + "mac": "84:D8:1B:C2:C6:39", + "mic_type": "IOT.SMARTPLUGSWITCH", + "model": "HS105(US)", + "next_action": { + "type": -1 + }, + "ntc_state": 0, + "obd_src": "tplink", + "oemId": "69A0595CB3878B4927CC17675B69DBA9", + "on_time": 468, + "relay_state": 1, + "rssi": -50, + "status": "new", + "sw_ver": "1.0.2 Build 200804 Rel.091847", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS105-UDP.txt b/tplink/sampledata/HS105-UDP.txt new file mode 100644 index 00000000..1da2bf99 --- /dev/null +++ b/tplink/sampledata/HS105-UDP.txt @@ -0,0 +1,32 @@ +{ + "system": { + "get_sysinfo": { + "active_mode": "none", + "alias": "Kasa Plug Mini HS105", + "dev_name": "Smart Wi-Fi Plug Mini", + "deviceId": "80060D6638AF0FF5268C04E19ACD7A631D92524B", + "err_code": 0, + "feature": "TIM", + "hwId": "6EEF0BBCE1D91460D5F5201C65C8A549", + "hw_ver": "5.0", + "icon_hash": "", + "latitude_i": 398287, + "led_off": 0, + "longitude_i": -1049759, + "mac": "84:D8:1B:CB:A6:89", + "mic_type": "IOT.SMARTPLUGSWITCH", + "model": "HS105(US)", + "next_action": { + "type": -1 + }, + "obd_src": "tplink", + "oemId": "A3BE45A15350D76F11728AC99180D5E8", + "on_time": 466, + "relay_state": 1, + "rssi": -39, + "status": "new", + "sw_ver": "1.0.2 Build 200819 Rel.103733", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS110-TCP.txt b/tplink/sampledata/HS110-TCP.txt new file mode 100644 index 00000000..5899eec3 --- /dev/null +++ b/tplink/sampledata/HS110-TCP.txt @@ -0,0 +1,40 @@ +{ + "emeter": { + "get_realtime": { + "current_ma": 16, + "err_code": 0, + "power_mw": 812, + "total_wh": 15, + "voltage_mv": 232313 + } + }, + "system": { + "get_sysinfo": { + "active_mode": "none", + "alias": "Kasa Plug With Energy Monitoring HS110", + "dev_name": "Smart Wi-Fi Plug With Energy Monitoring", + "deviceId": "8006BBCA9B42F7D495ED9636570C21571BA8D9C1", + "err_code": 0, + "feature": "TIM:ENE", + "fwId": "00000000000000000000000000000000", + "hwId": "044A516EE63C875F9458DA25C2CCC5A0", + "hw_ver": "2.0", + "icon_hash": "", + "latitude_i": 484108, + "led_off": 0, + "longitude_i": 99379, + "mac": "98:DA:C4:6A:67:34", + "model": "HS110(EU)", + "next_action": { + "type": -1 + }, + "oemId": "1998A14DAA86E4E001FD7CAF42868B5E", + "on_time": 27113, + "relay_state": 1, + "rssi": -52, + "sw_ver": "1.5.6 Build 191125 Rel.083657", + "type": "IOT.SMARTPLUGSWITCH", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS110-UDP.txt b/tplink/sampledata/HS110-UDP.txt new file mode 100644 index 00000000..df898185 --- /dev/null +++ b/tplink/sampledata/HS110-UDP.txt @@ -0,0 +1,31 @@ +{ + "system": { + "get_sysinfo": { + "active_mode": "none", + "alias": "Kasa Plug With Power Monitoring HS110", + "dev_name": "Smart Wi-Fi Plug With Energy Monitoring", + "deviceId": "8006BBCA9B42F7D495ED9636570C21571BA8D9C1", + "err_code": 0, + "feature": "TIM:ENE", + "fwId": "00000000000000000000000000000000", + "hwId": "044A516EE63C875F9458DA25C2CCC5A0", + "hw_ver": "2.0", + "icon_hash": "", + "latitude_i": 484108, + "led_off": 0, + "longitude_i": 99379, + "mac": "98:DA:C4:6A:67:34", + "model": "HS110(EU)", + "next_action": { + "type": -1 + }, + "oemId": "1998A14DAA86E4E001FD7CAF42868B5E", + "on_time": 27035, + "relay_state": 1, + "rssi": -52, + "sw_ver": "1.5.6 Build 191125 Rel.083657", + "type": "IOT.SMARTPLUGSWITCH", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS200-TCP.txt b/tplink/sampledata/HS200-TCP.txt new file mode 100644 index 00000000..44e8e008 --- /dev/null +++ b/tplink/sampledata/HS200-TCP.txt @@ -0,0 +1,35 @@ +{ + "emeter": { + "err_code": -1, + "err_msg": "module not support" + }, + "system": { + "get_sysinfo": { + "active_mode": "none", + "alias": "Kasa Light Switch HS200", + "dev_name": "Smart Wi-Fi Light Switch", + "deviceId": "800637201AAD76731FEC32A6D953ABDA1D5A4663", + "err_code": 0, + "feature": "TIM", + "hwId": "F30CA3404523AE331168A102F897B7F0", + "hw_ver": "3.0", + "icon_hash": "", + "latitude_i": 398287, + "led_off": 0, + "longitude_i": -1049759, + "mac": "D8:07:B6:F7:E9:8D", + "mic_type": "IOT.SMARTPLUGSWITCH", + "model": "HS200(US)", + "next_action": { + "type": -1 + }, + "oemId": "59F15C39F35FEBCF7E5A84FF7620AFA1", + "on_time": 0, + "relay_state": 0, + "rssi": -51, + "status": "new", + "sw_ver": "1.1.4 Build 200814 Rel.105352", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS200-UDP.txt b/tplink/sampledata/HS200-UDP.txt new file mode 100644 index 00000000..0ede9360 --- /dev/null +++ b/tplink/sampledata/HS200-UDP.txt @@ -0,0 +1,31 @@ +{ + "system": { + "get_sysinfo": { + "active_mode": "none", + "alias": "Kasa Light Switch HS200", + "dev_name": "Smart Wi-Fi Light Switch", + "deviceId": "424535436543654365435435425234591D5AF3F3", + "err_code": 0, + "feature": "TIM", + "hwId": "F305453657676574756546534653B7F0", + "hw_ver": "3.0", + "icon_hash": "", + "latitude_i": 123456, + "led_off": 0, + "longitude_i": -1234567, + "mac": "23:45:67:89:AB:CD", + "mic_type": "IOT.SMARTPLUGSWITCH", + "model": "HS200(US)", + "next_action": { + "type": -1 + }, + "oemId": "5545465654756654365653455340AFA1", + "on_time": 0, + "relay_state": 0, + "rssi": -43, + "status": "new", + "sw_ver": "1.1.4 Build 200814 Rel.105352", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS300-TCP.txt b/tplink/sampledata/HS300-TCP.txt new file mode 100644 index 00000000..1c493db7 --- /dev/null +++ b/tplink/sampledata/HS300-TCP.txt @@ -0,0 +1,89 @@ +{ + "emeter": { + "get_realtime": { + "current_ma": 4, + "err_code": 0, + "power_mw": 0, + "total_wh": 1475, + "voltage_mv": 123011 + } + }, + "system": { + "get_sysinfo": { + "alias": "TP-LINK_Power Strip_9BF2", + "child_num": 6, + "children": [ + { + "alias": "Shipping table Plug 1", + "id": "80064FCD1EFC96482DF70A7E66F341841D58B49200", + "next_action": { + "type": -1 + }, + "on_time": 417662, + "state": 1 + }, + { + "alias": "Shipping table Plug 2", + "id": "80064FCD1EFC96482DF70A7E66F341841D58B49201", + "next_action": { + "type": -1 + }, + "on_time": 418526, + "state": 1 + }, + { + "alias": "Shipping table Plug 3", + "id": "80064FCD1EFC96482DF70A7E66F341841D58B49202", + "next_action": { + "type": -1 + }, + "on_time": 418526, + "state": 1 + }, + { + "alias": "Shipping table Plug 4", + "id": "80064FCD1EFC96482DF70A7E66F341841D58B49203", + "next_action": { + "type": -1 + }, + "on_time": 418526, + "state": 1 + }, + { + "alias": "Shipping table Plug 5", + "id": "80064FCD1EFC96482DF70A7E66F341841D58B49204", + "next_action": { + "type": -1 + }, + "on_time": 418526, + "state": 0 + }, + { + "alias": "Shipping table Plug 6", + "id": "80064FCD1EFC96482DF70A7E66F341841D58B49205", + "next_action": { + "type": -1 + }, + "on_time": 417659, + "state": 1 + } + ], + "deviceId": "80064FCD1EFC96482DF70A7E66F341841D58B492", + "err_code": 0, + "feature": "TIM:ENE", + "hwId": "34C41AA028022D0CCEA5E678E8547C54", + "hw_ver": "1.0", + "latitude_i": 398287, + "led_off": 0, + "longitude_i": -1049759, + "mac": "3C:84:6A:66:9B:F2", + "mic_type": "IOT.SMARTPLUGSWITCH", + "model": "HS300(US)", + "oemId": "5C9E6254BEBAED63B2B6102966D24C17", + "rssi": -65, + "status": "new", + "sw_ver": "1.0.19 Build 200224 Rel.090814", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/HS300-UDP.txt b/tplink/sampledata/HS300-UDP.txt new file mode 100644 index 00000000..3c732c62 --- /dev/null +++ b/tplink/sampledata/HS300-UDP.txt @@ -0,0 +1,80 @@ +{ + "system": { + "get_sysinfo": { + "alias": "TP-LINK_Power Strip_9BF2", + "child_num": 6, + "children": [ + { + "alias": "Shipping table Plug 1", + "id": "00", + "next_action": { + "type": -1 + }, + "on_time": 417655, + "state": 1 + }, + { + "alias": "Shipping table Plug 2", + "id": "01", + "next_action": { + "type": -1 + }, + "on_time": 418519, + "state": 1 + }, + { + "alias": "Shipping table Plug 3", + "id": "02", + "next_action": { + "type": -1 + }, + "on_time": 418519, + "state": 1 + }, + { + "alias": "Shipping table Plug 4", + "id": "03", + "next_action": { + "type": -1 + }, + "on_time": 418519, + "state": 1 + }, + { + "alias": "Shipping table Plug 5", + "id": "04", + "next_action": { + "type": -1 + }, + "on_time": 418519, + "state": 1 + }, + { + "alias": "Shipping table Plug 6", + "id": "05", + "next_action": { + "type": -1 + }, + "on_time": 417652, + "state": 1 + } + ], + "deviceId": "80064FCD1EFC96482DF70A7E66F341841D58B492", + "err_code": 0, + "feature": "TIM:ENE", + "hwId": "34C41AA028022D0CCEA5E678E8547C54", + "hw_ver": "1.0", + "latitude_i": 398287, + "led_off": 0, + "longitude_i": -1049759, + "mac": "3C:84:6A:66:9B:F2", + "mic_type": "IOT.SMARTPLUGSWITCH", + "model": "HS300(US)", + "oemId": "5C9E6254BEBAED63B2B6102966D24C17", + "rssi": -65, + "status": "new", + "sw_ver": "1.0.19 Build 200224 Rel.090814", + "updating": 0 + } + } +} diff --git a/tplink/sampledata/simulator.cpp b/tplink/sampledata/simulator.cpp new file mode 100644 index 00000000..c993738b --- /dev/null +++ b/tplink/sampledata/simulator.cpp @@ -0,0 +1,95 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MODEL "HS300" + +QByteArray decryptPayload(const QByteArray &payload) +{ + QByteArray result; + int k = 171; + for (int i = 0; i < payload.length(); i++){ + char t = payload.at(i); + result.append(t xor k); + k = t; + } + return result; +} + +QByteArray encryptPayload(const QByteArray &payload) +{ + QByteArray result; + int k = 171; + for (int i = 0; i < payload.length(); i++){ + char t = payload.at(i) xor k; + k = t; + result.append(t); + } + return result; +} + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + + QGuiApplication app(argc, argv); + + qDebug() << "Simulating" << MODEL; + + QFile f(QString("%1-UDP.txt").arg(MODEL)); + f.open(QFile::ReadOnly); + QByteArray systemDataUdp = f.readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(systemDataUdp); + systemDataUdp = encryptPayload(jsonDoc.toJson(QJsonDocument::Compact)); + f.close(); + + f.setFileName(QString("%1-TCP.txt").arg(MODEL)); + f.open(QFile::ReadOnly); + QByteArray systemDataTcp = f.readAll(); + jsonDoc = QJsonDocument::fromJson(systemDataTcp); + systemDataTcp = encryptPayload(jsonDoc.toJson(QJsonDocument::Compact)); + + QUdpSocket *udp = new QUdpSocket(&app); + udp->bind(QHostAddress("0.0.0.0"), 9999); + QObject::connect(udp, &QUdpSocket::readyRead, &app, [=](){ + while (udp->hasPendingDatagrams()) { + char buffer[4096]; + QHostAddress sourceAddress; + quint16 sourcePort; + udp->readDatagram(buffer, 4096, &sourceAddress, &sourcePort); + QByteArray data(buffer); + data = decryptPayload(data); + qDebug() << "Incoming datagram:" << data << "from" << sourceAddress; + + udp->writeDatagram(systemDataUdp, sourceAddress, sourcePort); + } + }); + + QTcpServer *tcp = new QTcpServer(&app); + bool success = tcp->listen(QHostAddress("0.0.0.0"), 9999); + qDebug() << "Listening on tcp" << success; + QObject::connect(tcp, &QTcpServer::newConnection, &app, [=](){ + qDebug() << "new connection"; + QTcpSocket *client = tcp->nextPendingConnection(); + QObject::connect(client, &QTcpSocket::readyRead, tcp, [=](){ + QByteArray data = decryptPayload(client->readAll()); + qDebug() << "Incoming request:" << data; + + QByteArray output; + QDataStream stream(&output, QIODevice::WriteOnly); + qint32 len = systemDataTcp.length(); + stream << len; + output.append(systemDataTcp); + qDebug() << "written:" << client->write(output); + + }); + }); + + return app.exec(); +} diff --git a/tplink/sampledata/simulator.pro b/tplink/sampledata/simulator.pro new file mode 100644 index 00000000..acf1d71d --- /dev/null +++ b/tplink/sampledata/simulator.pro @@ -0,0 +1,5 @@ +CONFIG += c++11 + +QT += network + +SOURCES += simulator.cpp diff --git a/tplink/tplink.pro b/tplink/tplink.pro index 1afbeb63..a9a89cc9 100644 --- a/tplink/tplink.pro +++ b/tplink/tplink.pro @@ -7,3 +7,10 @@ SOURCES += \ HEADERS += \ integrationplugintplink.h \ + +OTHER_FILES += \ + sampledata/HS200.txt \ + sampledata/HS300-UDP.txt + +DISTFILES += \ + sampledata/HS300-TCP.txt diff --git a/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-de.ts b/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-de.ts index fc3476ed..a0b3480b 100644 --- a/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-de.ts +++ b/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-de.ts @@ -4,22 +4,22 @@ IntegrationPluginTPLink - + An error happened sending the discovery to the network. Beim Durchsuchen des Netzwerks ist ein Fehler aufgetreten. - + An error happened finding the device in the network. Beim Suchen des Geräts ist ein Fehler aufgetreten. - + The device could not be found on the network. Das Gerät konnte nicht im Netzwerk gefunden werden. - + Error sending command to the network. Der Befehl konnte nicht ins Netzwerk gesendet werden. @@ -27,14 +27,26 @@ tplink - - - - - - + + + + + + + + + + Connected - The name of the ParamType (ThingClass: kasaSwitch200, EventType: connected, ID: {8792b3d1-f83d-44c3-b649-249a935d1eb4}) + The name of the ParamType (ThingClass: kasaSocket, EventType: connected, ID: {59feb3a8-d35e-4c10-ac2e-01361e711a5e}) +---------- +The name of the StateType ({59feb3a8-d35e-4c10-ac2e-01361e711a5e}) of ThingClass kasaSocket +---------- +The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: connected, ID: {9bcec21d-7207-44c6-8ebf-d2720bb7a63a}) +---------- +The name of the StateType ({9bcec21d-7207-44c6-8ebf-d2720bb7a63a}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaSwitch200, EventType: connected, ID: {8792b3d1-f83d-44c3-b649-249a935d1eb4}) ---------- The name of the StateType ({8792b3d1-f83d-44c3-b649-249a935d1eb4}) of ThingClass kasaSwitch200 ---------- @@ -48,11 +60,17 @@ The name of the StateType ({79bcdd81-2e9d-4312-a4a7-85f808d046ef}) of ThingClass Verbunden - - - + + + + + Connected changed - The name of the EventType ({8792b3d1-f83d-44c3-b649-249a935d1eb4}) of ThingClass kasaSwitch200 + The name of the EventType ({59feb3a8-d35e-4c10-ac2e-01361e711a5e}) of ThingClass kasaSocket +---------- +The name of the EventType ({9bcec21d-7207-44c6-8ebf-d2720bb7a63a}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({8792b3d1-f83d-44c3-b649-249a935d1eb4}) of ThingClass kasaSwitch200 ---------- The name of the EventType ({b66825ec-9f1b-48da-af18-f36913291c0e}) of ThingClass kasaPlug110 ---------- @@ -60,26 +78,41 @@ The name of the EventType ({79bcdd81-2e9d-4312-a4a7-85f808d046ef}) of ThingClass Verbunden/getrennt - - + + + + Current power consumption - The name of the ParamType (ThingClass: kasaPlug110, EventType: currentPower, ID: {ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) + The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: currentPower, ID: {f973b4e8-99fb-4331-8193-e287bd37f5a0}) +---------- +The name of the StateType ({f973b4e8-99fb-4331-8193-e287bd37f5a0}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaPlug110, EventType: currentPower, ID: {ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) ---------- The name of the StateType ({ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) of ThingClass kasaPlug110 Aktueller Energieverbrauch - + + Current power consumption changed - The name of the EventType ({ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) of ThingClass kasaPlug110 + The name of the EventType ({f973b4e8-99fb-4331-8193-e287bd37f5a0}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) of ThingClass kasaPlug110 Aktueller Energieverbrauch geändert - - - + + + + + ID - The name of the ParamType (ThingClass: kasaSwitch200, Type: thing, ID: {fe989b2f-034e-4615-8a47-4a8aa775ed99}) + The name of the ParamType (ThingClass: kasaSocket, Type: thing, ID: {dd944807-c7f2-49da-b443-b69eb8387f41}) +---------- +The name of the ParamType (ThingClass: kasaPowerStrip300, Type: thing, ID: {62b38ddf-f6d7-44e1-955f-f04b375d960d}) +---------- +The name of the ParamType (ThingClass: kasaSwitch200, Type: thing, ID: {fe989b2f-034e-4615-8a47-4a8aa775ed99}) ---------- The name of the ParamType (ThingClass: kasaPlug110, Type: thing, ID: {de3238f7-fe94-440d-b212-61cd4e221b50}) ---------- @@ -87,35 +120,56 @@ The name of the ParamType (ThingClass: kasaPlug100, Type: thing, ID: {7c7a4d88-6 ID - + Kasa Smart Wi-Fi Light Switch (HS200) The name of the ThingClass ({d527e576-d65e-4ae6-ae43-c89b594fb4c1}) Kasa Smart Wi-Fi Lichtschalter (HS200) - + Kasa Smart Wi-Fi Plug (HS100/HS103/HS105/KP100) The name of the ThingClass ({48f981ba-3836-4810-9744-a349088f4545}) Kasa Smart WLAN-Steckdose (HS100/HS103/HS105/KP100) - + Kasa Smart Wi-Fi Plug With Energy Monitoring (HS110) The name of the ThingClass ({32830124-9efb-4614-8227-ee269b1889b0}) Kasa Smart WLAN-Steckdose mit Verbrauchsanzeige (HS110) - - - - - - - - - + + Kasa Smart Wi-Fi Power Strip (HS300) + The name of the ThingClass ({bbdee989-9431-4187-b135-5030a7a11be2}) + + + + + Kasa power socket + The name of the ThingClass ({2f40e28c-2484-4e09-bda9-e7accc29ab41}) + + + + + + + + + + + + + + + Power - The name of the ParamType (ThingClass: kasaSwitch200, ActionType: power, ID: {3b0daf6c-ba04-4ff1-a381-685c869665b1}) + The name of the ParamType (ThingClass: kasaSocket, ActionType: power, ID: {b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) +---------- +The name of the ParamType (ThingClass: kasaSocket, EventType: power, ID: {b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) +---------- +The name of the StateType ({b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) of ThingClass kasaSocket +---------- +The name of the ParamType (ThingClass: kasaSwitch200, ActionType: power, ID: {3b0daf6c-ba04-4ff1-a381-685c869665b1}) ---------- The name of the ParamType (ThingClass: kasaSwitch200, EventType: power, ID: {3b0daf6c-ba04-4ff1-a381-685c869665b1}) ---------- @@ -135,14 +189,26 @@ The name of the StateType ({a8991ea0-89f0-477b-97fb-414dd7d185b3}) of ThingClass Eingeschaltet - - - - - - + + + + + + + + + + Signal strength - The name of the ParamType (ThingClass: kasaSwitch200, EventType: signalStrength, ID: {6387c4e3-b0c1-4151-a3c9-925929c2d51e}) + The name of the ParamType (ThingClass: kasaSocket, EventType: signalStrength, ID: {16b71516-2ff4-4a2f-b0fc-53fff11f3a16}) +---------- +The name of the StateType ({16b71516-2ff4-4a2f-b0fc-53fff11f3a16}) of ThingClass kasaSocket +---------- +The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: signalStrength, ID: {1a587f62-8274-4c2e-bdc6-1b0b6368e5f7}) +---------- +The name of the StateType ({1a587f62-8274-4c2e-bdc6-1b0b6368e5f7}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaSwitch200, EventType: signalStrength, ID: {6387c4e3-b0c1-4151-a3c9-925929c2d51e}) ---------- The name of the StateType ({6387c4e3-b0c1-4151-a3c9-925929c2d51e}) of ThingClass kasaSwitch200 ---------- @@ -156,11 +222,17 @@ The name of the StateType ({1de7fac2-87f1-4c2b-9286-1b0895c5ac49}) of ThingClass Signalstärke - - - + + + + + Signal strength changed - The name of the EventType ({6387c4e3-b0c1-4151-a3c9-925929c2d51e}) of ThingClass kasaSwitch200 + The name of the EventType ({16b71516-2ff4-4a2f-b0fc-53fff11f3a16}) of ThingClass kasaSocket +---------- +The name of the EventType ({1a587f62-8274-4c2e-bdc6-1b0b6368e5f7}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({6387c4e3-b0c1-4151-a3c9-925929c2d51e}) of ThingClass kasaSwitch200 ---------- The name of the EventType ({cb16cfb0-6608-486f-abe5-264aa652704d}) of ThingClass kasaPlug110 ---------- @@ -168,26 +240,38 @@ The name of the EventType ({1de7fac2-87f1-4c2b-9286-1b0895c5ac49}) of ThingClass Signalstärke geändert - - + + + + Total energy consumed - The name of the ParamType (ThingClass: kasaPlug110, EventType: totalEnergyConsumed, ID: {a3533121-69ee-44fd-8394-13373e8f960e}) + The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: totalEnergyConsumed, ID: {f2992226-1f36-477f-b053-04dc5dc3a31c}) +---------- +The name of the StateType ({f2992226-1f36-477f-b053-04dc5dc3a31c}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaPlug110, EventType: totalEnergyConsumed, ID: {a3533121-69ee-44fd-8394-13373e8f960e}) ---------- The name of the StateType ({a3533121-69ee-44fd-8394-13373e8f960e}) of ThingClass kasaPlug110 Gesamter Energieverbrauch - + + Total energy consumed changed - The name of the EventType ({a3533121-69ee-44fd-8394-13373e8f960e}) of ThingClass kasaPlug110 + The name of the EventType ({f2992226-1f36-477f-b053-04dc5dc3a31c}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({a3533121-69ee-44fd-8394-13373e8f960e}) of ThingClass kasaPlug110 Gesamter Energieverbrauch geändert - - - + + + + Turn on or off - The name of the ActionType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 + The name of the ActionType ({b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) of ThingClass kasaSocket +---------- +The name of the ActionType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 ---------- The name of the ActionType ({f1a5fda4-87a6-46f6-9499-16811a5f4f4d}) of ThingClass kasaPlug110 ---------- @@ -195,11 +279,14 @@ The name of the ActionType ({a8991ea0-89f0-477b-97fb-414dd7d185b3}) of ThingClas Ein- ausschalten - - - + + + + Turned on or off - The name of the EventType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 + The name of the EventType ({b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) of ThingClass kasaSocket +---------- +The name of the EventType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 ---------- The name of the EventType ({f1a5fda4-87a6-46f6-9499-16811a5f4f4d}) of ThingClass kasaPlug110 ---------- @@ -207,8 +294,8 @@ The name of the EventType ({a8991ea0-89f0-477b-97fb-414dd7d185b3}) of ThingClass Ein- ausgeschaltet - - + + tp-link The name of the vendor ({8603b6cf-52ec-4481-aca2-f29ebd6cd8a8}) ---------- diff --git a/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-en_US.ts b/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-en_US.ts index a545d37b..48cf121e 100644 --- a/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-en_US.ts +++ b/tplink/translations/024ff2e3-30df-44a1-9c8d-63cc416f1fb8-en_US.ts @@ -4,22 +4,22 @@ IntegrationPluginTPLink - + An error happened sending the discovery to the network. - + An error happened finding the device in the network. - + The device could not be found on the network. - + Error sending command to the network. @@ -27,14 +27,26 @@ tplink - - - - - - + + + + + + + + + + Connected - The name of the ParamType (ThingClass: kasaSwitch200, EventType: connected, ID: {8792b3d1-f83d-44c3-b649-249a935d1eb4}) + The name of the ParamType (ThingClass: kasaSocket, EventType: connected, ID: {59feb3a8-d35e-4c10-ac2e-01361e711a5e}) +---------- +The name of the StateType ({59feb3a8-d35e-4c10-ac2e-01361e711a5e}) of ThingClass kasaSocket +---------- +The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: connected, ID: {9bcec21d-7207-44c6-8ebf-d2720bb7a63a}) +---------- +The name of the StateType ({9bcec21d-7207-44c6-8ebf-d2720bb7a63a}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaSwitch200, EventType: connected, ID: {8792b3d1-f83d-44c3-b649-249a935d1eb4}) ---------- The name of the StateType ({8792b3d1-f83d-44c3-b649-249a935d1eb4}) of ThingClass kasaSwitch200 ---------- @@ -48,11 +60,17 @@ The name of the StateType ({79bcdd81-2e9d-4312-a4a7-85f808d046ef}) of ThingClass - - - + + + + + Connected changed - The name of the EventType ({8792b3d1-f83d-44c3-b649-249a935d1eb4}) of ThingClass kasaSwitch200 + The name of the EventType ({59feb3a8-d35e-4c10-ac2e-01361e711a5e}) of ThingClass kasaSocket +---------- +The name of the EventType ({9bcec21d-7207-44c6-8ebf-d2720bb7a63a}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({8792b3d1-f83d-44c3-b649-249a935d1eb4}) of ThingClass kasaSwitch200 ---------- The name of the EventType ({b66825ec-9f1b-48da-af18-f36913291c0e}) of ThingClass kasaPlug110 ---------- @@ -60,26 +78,41 @@ The name of the EventType ({79bcdd81-2e9d-4312-a4a7-85f808d046ef}) of ThingClass - - + + + + Current power consumption - The name of the ParamType (ThingClass: kasaPlug110, EventType: currentPower, ID: {ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) + The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: currentPower, ID: {f973b4e8-99fb-4331-8193-e287bd37f5a0}) +---------- +The name of the StateType ({f973b4e8-99fb-4331-8193-e287bd37f5a0}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaPlug110, EventType: currentPower, ID: {ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) ---------- The name of the StateType ({ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) of ThingClass kasaPlug110 - + + Current power consumption changed - The name of the EventType ({ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) of ThingClass kasaPlug110 + The name of the EventType ({f973b4e8-99fb-4331-8193-e287bd37f5a0}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({ccb52b57-5800-4f03-b7fa-f36dcebe1d4e}) of ThingClass kasaPlug110 - - - + + + + + ID - The name of the ParamType (ThingClass: kasaSwitch200, Type: thing, ID: {fe989b2f-034e-4615-8a47-4a8aa775ed99}) + The name of the ParamType (ThingClass: kasaSocket, Type: thing, ID: {dd944807-c7f2-49da-b443-b69eb8387f41}) +---------- +The name of the ParamType (ThingClass: kasaPowerStrip300, Type: thing, ID: {62b38ddf-f6d7-44e1-955f-f04b375d960d}) +---------- +The name of the ParamType (ThingClass: kasaSwitch200, Type: thing, ID: {fe989b2f-034e-4615-8a47-4a8aa775ed99}) ---------- The name of the ParamType (ThingClass: kasaPlug110, Type: thing, ID: {de3238f7-fe94-440d-b212-61cd4e221b50}) ---------- @@ -87,35 +120,56 @@ The name of the ParamType (ThingClass: kasaPlug100, Type: thing, ID: {7c7a4d88-6 - + Kasa Smart Wi-Fi Light Switch (HS200) The name of the ThingClass ({d527e576-d65e-4ae6-ae43-c89b594fb4c1}) - + Kasa Smart Wi-Fi Plug (HS100/HS103/HS105/KP100) The name of the ThingClass ({48f981ba-3836-4810-9744-a349088f4545}) - + Kasa Smart Wi-Fi Plug With Energy Monitoring (HS110) The name of the ThingClass ({32830124-9efb-4614-8227-ee269b1889b0}) - - - - - - - - - + + Kasa Smart Wi-Fi Power Strip (HS300) + The name of the ThingClass ({bbdee989-9431-4187-b135-5030a7a11be2}) + + + + + Kasa power socket + The name of the ThingClass ({2f40e28c-2484-4e09-bda9-e7accc29ab41}) + + + + + + + + + + + + + + + Power - The name of the ParamType (ThingClass: kasaSwitch200, ActionType: power, ID: {3b0daf6c-ba04-4ff1-a381-685c869665b1}) + The name of the ParamType (ThingClass: kasaSocket, ActionType: power, ID: {b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) +---------- +The name of the ParamType (ThingClass: kasaSocket, EventType: power, ID: {b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) +---------- +The name of the StateType ({b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) of ThingClass kasaSocket +---------- +The name of the ParamType (ThingClass: kasaSwitch200, ActionType: power, ID: {3b0daf6c-ba04-4ff1-a381-685c869665b1}) ---------- The name of the ParamType (ThingClass: kasaSwitch200, EventType: power, ID: {3b0daf6c-ba04-4ff1-a381-685c869665b1}) ---------- @@ -135,14 +189,26 @@ The name of the StateType ({a8991ea0-89f0-477b-97fb-414dd7d185b3}) of ThingClass - - - - - - + + + + + + + + + + Signal strength - The name of the ParamType (ThingClass: kasaSwitch200, EventType: signalStrength, ID: {6387c4e3-b0c1-4151-a3c9-925929c2d51e}) + The name of the ParamType (ThingClass: kasaSocket, EventType: signalStrength, ID: {16b71516-2ff4-4a2f-b0fc-53fff11f3a16}) +---------- +The name of the StateType ({16b71516-2ff4-4a2f-b0fc-53fff11f3a16}) of ThingClass kasaSocket +---------- +The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: signalStrength, ID: {1a587f62-8274-4c2e-bdc6-1b0b6368e5f7}) +---------- +The name of the StateType ({1a587f62-8274-4c2e-bdc6-1b0b6368e5f7}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaSwitch200, EventType: signalStrength, ID: {6387c4e3-b0c1-4151-a3c9-925929c2d51e}) ---------- The name of the StateType ({6387c4e3-b0c1-4151-a3c9-925929c2d51e}) of ThingClass kasaSwitch200 ---------- @@ -156,11 +222,17 @@ The name of the StateType ({1de7fac2-87f1-4c2b-9286-1b0895c5ac49}) of ThingClass - - - + + + + + Signal strength changed - The name of the EventType ({6387c4e3-b0c1-4151-a3c9-925929c2d51e}) of ThingClass kasaSwitch200 + The name of the EventType ({16b71516-2ff4-4a2f-b0fc-53fff11f3a16}) of ThingClass kasaSocket +---------- +The name of the EventType ({1a587f62-8274-4c2e-bdc6-1b0b6368e5f7}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({6387c4e3-b0c1-4151-a3c9-925929c2d51e}) of ThingClass kasaSwitch200 ---------- The name of the EventType ({cb16cfb0-6608-486f-abe5-264aa652704d}) of ThingClass kasaPlug110 ---------- @@ -168,26 +240,38 @@ The name of the EventType ({1de7fac2-87f1-4c2b-9286-1b0895c5ac49}) of ThingClass - - + + + + Total energy consumed - The name of the ParamType (ThingClass: kasaPlug110, EventType: totalEnergyConsumed, ID: {a3533121-69ee-44fd-8394-13373e8f960e}) + The name of the ParamType (ThingClass: kasaPowerStrip300, EventType: totalEnergyConsumed, ID: {f2992226-1f36-477f-b053-04dc5dc3a31c}) +---------- +The name of the StateType ({f2992226-1f36-477f-b053-04dc5dc3a31c}) of ThingClass kasaPowerStrip300 +---------- +The name of the ParamType (ThingClass: kasaPlug110, EventType: totalEnergyConsumed, ID: {a3533121-69ee-44fd-8394-13373e8f960e}) ---------- The name of the StateType ({a3533121-69ee-44fd-8394-13373e8f960e}) of ThingClass kasaPlug110 - + + Total energy consumed changed - The name of the EventType ({a3533121-69ee-44fd-8394-13373e8f960e}) of ThingClass kasaPlug110 + The name of the EventType ({f2992226-1f36-477f-b053-04dc5dc3a31c}) of ThingClass kasaPowerStrip300 +---------- +The name of the EventType ({a3533121-69ee-44fd-8394-13373e8f960e}) of ThingClass kasaPlug110 - - - + + + + Turn on or off - The name of the ActionType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 + The name of the ActionType ({b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) of ThingClass kasaSocket +---------- +The name of the ActionType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 ---------- The name of the ActionType ({f1a5fda4-87a6-46f6-9499-16811a5f4f4d}) of ThingClass kasaPlug110 ---------- @@ -195,11 +279,14 @@ The name of the ActionType ({a8991ea0-89f0-477b-97fb-414dd7d185b3}) of ThingClas - - - + + + + Turned on or off - The name of the EventType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 + The name of the EventType ({b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8}) of ThingClass kasaSocket +---------- +The name of the EventType ({3b0daf6c-ba04-4ff1-a381-685c869665b1}) of ThingClass kasaSwitch200 ---------- The name of the EventType ({f1a5fda4-87a6-46f6-9499-16811a5f4f4d}) of ThingClass kasaPlug110 ---------- @@ -207,8 +294,8 @@ The name of the EventType ({a8991ea0-89f0-477b-97fb-414dd7d185b3}) of ThingClass - - + + tp-link The name of the vendor ({8603b6cf-52ec-4481-aca2-f29ebd6cd8a8}) ----------