mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-02 22:30:08 +02:00
New plugin: Senec: Add support for SENEC.home P4 energy storages
This commit is contained in:
parent
2575f43518
commit
e9a0fe1f08
11
debian/control
vendored
11
debian/control
vendored
@ -703,6 +703,7 @@ Description: nymea integration plugin for TCP commander
|
||||
This package contains the nymea integration plugin for sending arbitrary
|
||||
TCP packets from and to nymea.
|
||||
|
||||
|
||||
Package: nymea-plugin-httpcommander
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
@ -713,6 +714,16 @@ Description: nymea integration plugin for HTTP commander
|
||||
HTTP requests from and to nymea.
|
||||
|
||||
|
||||
Package: nymea-plugin-senec
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
Conflicts: nymea-plugins-translations (<< 1.0.1)
|
||||
Description: nymea integration plugin for SENEC.home
|
||||
This package contains the nymea integration plugin for the SENEC.home
|
||||
energy storages.
|
||||
|
||||
|
||||
Package: nymea-plugin-senic
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
|
||||
2
debian/nymea-plugin-senec.install.in
vendored
Normal file
2
debian/nymea-plugin-senec.install.in
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginsenec.so
|
||||
senec/translations/*qm usr/share/nymea/translations/
|
||||
@ -60,6 +60,7 @@ PLUGIN_DIRS = \
|
||||
pushbullet \
|
||||
pushnotifications \
|
||||
reversessh \
|
||||
senec \
|
||||
senic \
|
||||
serialportcommander \
|
||||
sgready \
|
||||
|
||||
11
senec/README.md
Normal file
11
senec/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# SENEC.Home
|
||||
|
||||
Connects to the SENEC cloud and integrates the energy storages into the system.
|
||||
|
||||
Currently supported and tested models:
|
||||
|
||||
* SENEC.Home P4
|
||||
|
||||
## More
|
||||
|
||||
https://senec.com
|
||||
328
senec/integrationpluginsenec.cpp
Normal file
328
senec/integrationpluginsenec.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "integrationpluginsenec.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
|
||||
IntegrationPluginSenec::IntegrationPluginSenec()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IntegrationPluginSenec::~IntegrationPluginSenec()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::startPairing(ThingPairingInfo *info)
|
||||
{
|
||||
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter username and password for your SENEC.home account."));
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
|
||||
{
|
||||
qCDebug(dcSenec()) << "Start logging in" << username << secret.left(2) + QString(secret.length() - 2, '*');
|
||||
|
||||
QVariantMap requestMap;
|
||||
requestMap.insert("username", username);
|
||||
requestMap.insert("password", secret);
|
||||
|
||||
QNetworkRequest request(SenecAccount::loginUrl());
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request, QJsonDocument::fromVariant(requestMap).toJson(QJsonDocument::Indented));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, info, username, this] {
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
// Check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcSenec()) << "Login request finished with error. Status:" << status << "Error:" << reply->errorString();
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Username or password is invalid."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: as of now (API 4.4.3) the login seems to return a static token, which does not require any refresh.
|
||||
// Not as bad as saving user and password on the device, but almost ...
|
||||
|
||||
// https://documenter.getpostman.com/view/932140/2s9YXib2td
|
||||
|
||||
QByteArray responseData = reply->readAll();
|
||||
|
||||
QJsonParseError jsonError;
|
||||
QVariantMap responseMap = QJsonDocument::fromJson(responseData, &jsonError).toVariant().toMap();
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcSenec()) << "Login request finished successfully, but the response contains invalid JSON object:" << responseData;
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!responseMap.contains("token") || !responseMap.contains("refreshToken")) {
|
||||
qCWarning(dcSenec()) << "Login request finished successfully, but the response JSON does not contain the expected properties" << qUtf8Printable(responseData);
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
QString token = responseMap.value("token").toString();
|
||||
QString refreshToken = responseMap.value("refreshToken").toString();
|
||||
|
||||
pluginStorage()->beginGroup(info->thingId().toString());
|
||||
pluginStorage()->setValue("username", username);
|
||||
pluginStorage()->setValue("token", token);
|
||||
pluginStorage()->setValue("refreshToken", refreshToken);
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
qCDebug(dcSenec()) << "Setting up" << thing->name() << thing->params();
|
||||
|
||||
if (thing->thingClassId() == senecAccountThingClassId) {
|
||||
// Load login information
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
QString token = pluginStorage()->value("token").toString();
|
||||
QString refreshToken = pluginStorage()->value("refreshToken").toString();
|
||||
QString username = pluginStorage()->value("username").toString();
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
SenecAccount *account = new SenecAccount(hardwareManager()->networkManager(), username, token, refreshToken, this);
|
||||
m_accounts.insert(thing, account);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
thing->setStateValue(senecAccountUserDisplayNameStateTypeId, username);
|
||||
|
||||
} else if (thing->thingClassId() == senecStorageThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::postSetupThing(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == senecAccountThingClassId) {
|
||||
|
||||
// Search for now things, first poll the
|
||||
SenecAccount *account = m_accounts.value(thing);
|
||||
|
||||
// Check installation, create things if not already created
|
||||
QNetworkReply *reply = account->getSystems();
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, account, [reply, thing, this] {
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
// Check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcSenec()) << "Systems request finished with error. Status:" << status << "Error:" << reply->errorString();
|
||||
if (status == 401) {
|
||||
qCWarning(dcSenec()) << "Authentication error, reconfigure and re-login should fix this problem.";
|
||||
thing->setStateValue(senecAccountLoggedInStateTypeId, false);
|
||||
}
|
||||
|
||||
thing->setStateValue(senecAccountConnectedStateTypeId, false);
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray responseData = reply->readAll();
|
||||
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &jsonError);
|
||||
QVariant responseVariant = jsonDoc.toVariant();
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcSenec()) << "Systems request finished successfully, but the response contains invalid JSON object:" << responseData;
|
||||
thing->setStateValue(senecAccountConnectedStateTypeId, false);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSenec()) << "Systems request finished successfully" << qUtf8Printable(jsonDoc.toJson());
|
||||
thing->setStateValue(senecAccountLoggedInStateTypeId, true);
|
||||
thing->setStateValue(senecAccountConnectedStateTypeId, true);
|
||||
|
||||
ThingDescriptors descriptors;
|
||||
foreach (const QVariant &installation, responseVariant.toList()) {
|
||||
QVariantMap installationMap = installation.toMap();
|
||||
|
||||
// Note: for now we only support V4 systems
|
||||
if (!installationMap.value("systemType").toString().toLower().contains("v4"))
|
||||
continue;
|
||||
|
||||
// This is a V4 storage, let's check if we already created one
|
||||
QString id = installationMap.value("id").toString();
|
||||
Things existingThings = myThings().filterByThingClassId(senecStorageThingClassId).filterByParam(senecStorageThingIdParamTypeId, id);
|
||||
if (existingThings.isEmpty()) {
|
||||
qCDebug(dcSenec()) << "Creating new storage for" << id;
|
||||
ThingDescriptor descriptor(senecStorageThingClassId, "SENEC.Home P4", id);
|
||||
descriptor.setParentId(thing->id());
|
||||
ParamList params;
|
||||
params.append(Param(senecStorageThingIdParamTypeId, id));
|
||||
descriptor.setParams(params);
|
||||
descriptors.append(descriptor);
|
||||
} else {
|
||||
qCDebug(dcSenec()) << "Thing for storage" << id << "already created.";
|
||||
}
|
||||
}
|
||||
|
||||
if (!descriptors.isEmpty()) {
|
||||
qCDebug(dcSenec()) << "Adding" << descriptors.count() << "new SENEC.Home" << (descriptors.count() > 1 ? "storages" : "storage");
|
||||
emit autoThingsAppeared(descriptors);
|
||||
}
|
||||
});
|
||||
} else if (thing->thingClassId() == senecStorageThingClassId) {
|
||||
|
||||
SenecAccount *account = m_accounts.value(myThings().findById(thing->parentId()));
|
||||
QString id = thing->paramValue(senecStorageThingIdParamTypeId).toString();
|
||||
QNetworkReply *reply = account->getTechnicalData(id);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, account, [reply, thing, this] {
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
// Check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcSenec()) << "Technical data request finished with error. Status:" << status << "Error:" << reply->errorString();
|
||||
thing->setStateValue(senecStorageConnectedStateTypeId, false);
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray responseData = reply->readAll();
|
||||
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &jsonError);
|
||||
//QVariantMap responseMap = jsonDoc.toVariant().toMap();
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcSenec()) << "Technical data request finished successfully, but the response contains invalid JSON object:" << responseData;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSenec()) << "Technical data request finished successfully" << qUtf8Printable(jsonDoc.toJson());
|
||||
thing->setStateValue(senecStorageConnectedStateTypeId, true);
|
||||
|
||||
refresh(thing);
|
||||
});
|
||||
}
|
||||
|
||||
// Create the refresh timer if not already set up
|
||||
if (!m_refreshTimer) {
|
||||
qCDebug(dcSenec()) << "Starting refresh timer ...";
|
||||
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
|
||||
connect(m_refreshTimer, &PluginTimer::timeout, this, [this](){
|
||||
refresh();
|
||||
});
|
||||
m_refreshTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::thingRemoved(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == senecAccountThingClassId) {
|
||||
if (m_accounts.contains(thing))
|
||||
m_accounts.take(thing)->deleteLater();
|
||||
|
||||
// Wipe any stored login information
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
pluginStorage()->remove("");
|
||||
pluginStorage()->endGroup();
|
||||
}
|
||||
|
||||
if (myThings().isEmpty()) {
|
||||
qCDebug(dcSenec()) << "Stopping refresh timer";
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
|
||||
m_refreshTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
|
||||
void IntegrationPluginSenec::refresh(Thing *thing)
|
||||
{
|
||||
if (thing) {
|
||||
SenecAccount *account = m_accounts.value(myThings().findById(thing->parentId()));
|
||||
QString id = thing->paramValue(senecStorageThingIdParamTypeId).toString();
|
||||
QNetworkReply *reply = account->getDashboard(id);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, account, [reply, thing] {
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
// Check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcSenec()) << "Dashboard request finished with error. Status:" << status << "Error:" << reply->errorString();
|
||||
thing->setStateValue(senecStorageConnectedStateTypeId, false);
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray responseData = reply->readAll();
|
||||
|
||||
QJsonParseError jsonError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &jsonError);
|
||||
QVariantMap responseMap = jsonDoc.toVariant().toMap();
|
||||
if (jsonError.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcSenec()) << "Dashboard request finished successfully, but the response contains invalid JSON object:" << responseData;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcSenec()) << "Dashboard request finished successfully" << qUtf8Printable(jsonDoc.toJson());
|
||||
thing->setStateValue(senecStorageConnectedStateTypeId, true);
|
||||
|
||||
QVariantMap currentDataMap = responseMap.value("currently").toMap();
|
||||
float batteryCharge = qRound(currentDataMap.value("batteryChargeInW").toFloat() * 100) / 100.0;
|
||||
float batteryDischarge = qRound(currentDataMap.value("batteryDischargeInW").toFloat() * 100) / 100.0;
|
||||
int batteryLevel = currentDataMap.value("batteryLevelInPercent").toInt();
|
||||
|
||||
// qCDebug(dcSenec()) << "charge:" << batteryCharge << "W" << "discharge:" << batteryDischarge << "W" << "level" << batteryLevel << "%";
|
||||
|
||||
float currentPower = 0;
|
||||
|
||||
if (batteryCharge != 0) {
|
||||
currentPower = batteryCharge;
|
||||
thing->setStateValue(senecStorageChargingStateStateTypeId, "charging");
|
||||
} else if (batteryDischarge != 0) {
|
||||
currentPower = -batteryDischarge;
|
||||
thing->setStateValue(senecStorageChargingStateStateTypeId, "discharging");
|
||||
} else {
|
||||
thing->setStateValue(senecStorageChargingStateStateTypeId, "idle");
|
||||
}
|
||||
|
||||
thing->setStateValue(senecStorageCurrentPowerStateTypeId, currentPower);
|
||||
thing->setStateValue(senecStorageBatteryLevelStateTypeId, batteryLevel);
|
||||
thing->setStateValue(senecStorageBatteryCriticalStateTypeId, batteryLevel < 10);
|
||||
});
|
||||
} else {
|
||||
foreach (Thing *storageThing, myThings().filterByThingClassId(senecStorageThingClassId)) {
|
||||
refresh(storageThing);
|
||||
}
|
||||
}
|
||||
}
|
||||
70
senec/integrationpluginsenec.h
Normal file
70
senec/integrationpluginsenec.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef INTEGRATIONPLUGINSENEC_H
|
||||
#define INTEGRATIONPLUGINSENEC_H
|
||||
|
||||
#include <plugintimer.h>
|
||||
#include <integrations/integrationplugin.h>
|
||||
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include "senecaccount.h"
|
||||
|
||||
class IntegrationPluginSenec : public IntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginsenec.json")
|
||||
Q_INTERFACES(IntegrationPlugin)
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginSenec();
|
||||
~IntegrationPluginSenec();
|
||||
|
||||
void startPairing(ThingPairingInfo *info) override;
|
||||
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override;
|
||||
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
private:
|
||||
PluginTimer *m_refreshTimer = nullptr;
|
||||
QHash<Thing *, SenecAccount *> m_accounts;
|
||||
|
||||
private slots:
|
||||
void refresh(Thing *thing = nullptr);
|
||||
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINSENEC_H
|
||||
115
senec/integrationpluginsenec.json
Normal file
115
senec/integrationpluginsenec.json
Normal file
@ -0,0 +1,115 @@
|
||||
{
|
||||
"displayName": "SENEC",
|
||||
"name": "Senec",
|
||||
"id": "3f055ea5-a883-445d-9556-675f5eda6c9a",
|
||||
"vendors": [
|
||||
{
|
||||
"displayName": "SENEC",
|
||||
"name": "senec",
|
||||
"id": "1be922b9-4439-42cf-9caa-67f2ac7cc425",
|
||||
"thingClasses": [
|
||||
{
|
||||
"id": "f60497ea-a15a-4237-86bc-935182475e47",
|
||||
"name": "senecAccount",
|
||||
"displayName": "SENEC account",
|
||||
"interfaces": ["account"],
|
||||
"createMethods": ["user"],
|
||||
"setupMethod": "userandpassword",
|
||||
"providedInterfaces": ["energystorage"],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "2a508d04-3183-4c0b-9e92-90ff1ebce19e",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "6842e3b3-ff25-4f34-b1c4-ff3f83c23746",
|
||||
"name": "loggedIn",
|
||||
"displayName": "Logged in",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "7670bfb4-5dfc-47f1-9c99-80b120f2aa8b",
|
||||
"name": "userDisplayName",
|
||||
"displayName": "Username",
|
||||
"type": "QString",
|
||||
"defaultValue": "-"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "senecStorage",
|
||||
"displayName": "SENEC.Home storage",
|
||||
"id": "a983c5ee-1c58-4cad-87fb-1bc612cbe6e4",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": ["energystorage", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "9a0fa7b1-bc35-44d4-b987-5ecb87fd8b00",
|
||||
"name":"id",
|
||||
"displayName": "System ID",
|
||||
"type": "QString",
|
||||
"readOnly": true,
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "320cb3f0-d2c5-4a30-817f-474f0cc87253",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "09225a15-f2d0-46cf-a84f-4a91f389d488",
|
||||
"name": "currentPower",
|
||||
"displayName": "Current power",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0.00,
|
||||
"cached": true
|
||||
},
|
||||
{
|
||||
"id": "d6dd533a-beb2-4f57-a3d3-12c48a83306c",
|
||||
"name": "batteryLevel",
|
||||
"displayName": "Battery level",
|
||||
"type": "int",
|
||||
"unit": "Percentage",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "cba01bf1-5daf-4466-8ae3-ea864593bdc6",
|
||||
"name": "batteryCritical",
|
||||
"displayName": "Battery critical",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "cef34773-02c2-4eb1-8624-4e595847f674",
|
||||
"name": "chargingState",
|
||||
"displayName": "Charging state",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "charging", "discharging"],
|
||||
"defaultValue": "idle"
|
||||
},
|
||||
{
|
||||
"id": "4f571731-85f7-492e-ba51-eb6bf224776f",
|
||||
"name": "capacity",
|
||||
"displayName": "Capacity",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
13
senec/meta.json
Normal file
13
senec/meta.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"title": "SENEC",
|
||||
"tagline": "Connect nymea to your SENEC account.",
|
||||
"icon": "senec.svg",
|
||||
"stability": "community",
|
||||
"offline": false,
|
||||
"technologies": [
|
||||
"cloud"
|
||||
],
|
||||
"categories": [
|
||||
"energy"
|
||||
]
|
||||
}
|
||||
12
senec/senec.pro
Normal file
12
senec/senec.pro
Normal file
@ -0,0 +1,12 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT+= network
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginsenec.cpp \
|
||||
senecaccount.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginsenec.h \
|
||||
senecaccount.h
|
||||
|
||||
40
senec/senec.svg
Normal file
40
senec/senec.svg
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
data-name="Ebene 1"
|
||||
viewBox="0 0 100 23"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="senec_logo_de_clean_resize_1.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
width="100"
|
||||
height="23"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
id="namedview8"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.0458796"
|
||||
inkscape:cx="5.9096229"
|
||||
inkscape:cy="65.170008"
|
||||
inkscape:window-width="1728"
|
||||
inkscape:window-height="1006"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<path
|
||||
d="m 16.483695,17.845517 c 0,2.942408 -2.713129,5.216087 -6.9738891,5.216087 H 1.045605 c -0.55408995,0 -1.01264754,-0.458557 -1.01264754,-1.012647 v -2.445638 c 0,-0.55409 0.43945112,-1.012647 0.99354104,-1.031754 h 7.5661923 c 0.6687298,0 2.7322372,0 2.7322372,-1.757802 V 15.973075 A 1.6259672,1.6259672 0 0 0 9.8537235,14.215273 C 9.2614206,14.06242 4.6376363,13.030667 4.1981852,12.95424 A 5.1797851,5.1797851 0 0 1 0.01385098,7.4897667 V 5.7892839 C 0.01385098,2.789556 2.6505554,0 7.1596997,0 h 8.2158163 c 0.592303,0 0.802475,0.43945066 0.515876,0.84068815 L 14.381975,3.592031 C 14.076271,4.1079077 13.522181,4.432719 12.910771,4.432719 H 7.2552332 c -1.1463929,0 -2.0444004,0.9553274 -2.0444004,2.1017203 v 0.5731964 c 0.057314,0.7642619 0.6305158,1.4138846 1.394777,1.5476304 0,0 4.0314822,0.8406881 5.5791122,1.10818 3.229007,0.6687289 4.337187,2.9424099 4.337187,5.0059169 v 3.076154 z M 20.66803,1.0317536 C 20.66803,0.47766372 21.107481,0.01910658 21.661571,0 h 14.501868 c 0.592304,0 0.840688,0.36302443 0.515877,0.84068815 L 35.131686,3.592031 C 34.787769,4.0696947 34.252785,4.3753994 33.660482,4.432719 H 21.623357 c -0.554089,0 -1.012647,-0.420344 -1.031753,-0.9744339 V 3.4200721 Z M 55.499266,0 c -0.55409,0 -1.012647,0.42034408 -1.031753,0.97443391 V 13.56565 c 0,0.592303 -0.229279,0.668729 -0.592303,0.152852 L 45.277263,0.84068815 C 44.914238,0.34391785 44.341042,0.03821306 43.729633,0 H 41.455954 C 40.901864,0 40.443306,0.42034408 40.4242,0.97443391 V 22.02985 c 0,0.55409 0.420344,1.012648 0.974434,1.031754 h 3.114367 c 0.55409,0 1.012647,-0.420344 1.031753,-0.974434 V 9.9162979 c 0,-0.5923027 0.229279,-0.6687289 0.592303,-0.1528518 l 8.521521,12.4956829 c 0.363025,0.496771 0.936221,0.802475 1.547631,0.840688 h 2.426531 c 0.55409,0 1.012647,-0.420343 1.031754,-0.974433 V 1.0317536 A 1.0317536,1.0317536 0 0 0 58.670953,0 H 55.480159 Z M 21.699784,18.590672 c -0.55409,0 -1.012648,0.420344 -1.031754,0.974434 v 0.03821 l -0.07643,2.407425 c 0,0.55409 0.420343,1.012647 0.974433,1.031754 h 12.094445 c 0.592303,-0.05732 1.127287,-0.363024 1.471204,-0.840688 l 1.54763,-2.732237 c 0.286599,-0.515877 0.07643,-0.840688 -0.515877,-0.840688 L 21.699784,18.571565 Z M 20.66803,10.069151 c 0,-0.5540902 0.439451,-1.0126474 0.993541,-1.031754 h 11.998911 c 0.592303,0 0.840689,0.3630245 0.515876,0.840688 l -1.54763,2.713131 c -0.343917,0.477664 -0.878901,0.783369 -1.471204,0.840688 H 21.60425 c -0.55409,0 -1.012646,-0.420344 -1.031753,-0.974434 v -0.05732 l 0.07643,-2.350106 z M 65.855015,0 c -0.55409,0 -1.012647,0.42034408 -1.031754,0.97443391 v 0.0573194 l 0.07643,2.4265316 c 0,0.5540899 0.439451,1.0126471 0.993541,1.0317535 h 11.903379 c 0.592304,-0.057319 1.127286,-0.3630243 1.471205,-0.840688 L 80.853655,0.85979441 C 81.159359,0.34391785 80.93008,0.01910658 80.337778,0.01910658 H 65.874122 Z m -1.031754,19.603319 c 0,-0.55409 0.420344,-1.012647 0.974434,-1.031754 h 14.520976 c 0.592303,0 0.840688,0.363024 0.515877,0.840688 l -1.54763,2.713131 c -0.343919,0.477663 -0.878901,0.783367 -1.471204,0.840688 H 65.950548 c -0.55409,0.03821 -1.031754,-0.382132 -1.069967,-0.936222 v -0.03821 l -0.07643,-2.407424 z M 65.855015,9.037397 c -0.55409,0 -1.012647,0.4203441 -1.031754,0.974434 v 0.05731 l 0.07643,2.426533 c -0.03821,0.55409 0.382132,1.031753 0.955328,1.069967 h 9.495954 c 0.592303,-0.05733 1.127287,-0.363025 1.471204,-0.840688 l 1.54763,-2.713132 c 0.305702,-0.515867 0.07642,-0.8406783 -0.51588,-0.8406783 L 65.874122,9.0756101 Z m 25.62188,14.024207 h 5.36894 c 0.611409,0 1.165502,-0.324811 1.471206,-0.840688 l 1.54763,-2.732237 c 0.305699,-0.43945 0.07643,-0.840688 -0.51588,-0.840688 H 93.043632 C 90.024797,18.495139 89.012151,17.253214 89.012151,14.406339 V 8.0820696 a 3.5347113,3.5347113 0 0 1 3.439178,-3.6111374 h 4.337186 c 0.61141,0 1.165498,-0.3248114 1.471201,-0.8406882 l 1.54763,-2.78955585 C 100.11305,0.40123749 99.883772,0 99.291477,0 H 91.610641 C 86.834004,0 83.81517,3.6684572 83.81517,8.3113482 v 6.5344408 c 0.09554,4.26076 2.311892,8.234922 7.661725,8.234922 z"
|
||||
style="fill:#000099;fill-rule:evenodd;stroke-width:1"
|
||||
id="path4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
105
senec/senecaccount.cpp
Normal file
105
senec/senecaccount.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "senecaccount.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
SenecAccount::SenecAccount(NetworkAccessManager *networkManager, const QString &username, const QString &token, const QString &refreshToken, QObject *parent)
|
||||
: QObject{parent},
|
||||
m_networkManager{networkManager},
|
||||
m_username{username},
|
||||
m_token{token},
|
||||
m_refreshToken{refreshToken}
|
||||
{}
|
||||
|
||||
QUrl SenecAccount::baseUrl()
|
||||
{
|
||||
return QUrl("https://app-gateway.prod.senec.dev");
|
||||
}
|
||||
|
||||
QUrl SenecAccount::loginUrl()
|
||||
{
|
||||
QUrl url = SenecAccount::baseUrl();
|
||||
url.setPath("/v1/senec/login");
|
||||
return url;
|
||||
}
|
||||
|
||||
QUrl SenecAccount::systemsUrl()
|
||||
{
|
||||
QUrl url = SenecAccount::baseUrl();
|
||||
url.setPath("/v1/senec/systems");
|
||||
return url;
|
||||
}
|
||||
|
||||
bool SenecAccount::available() const
|
||||
{
|
||||
return m_available;
|
||||
}
|
||||
|
||||
QNetworkReply *SenecAccount::getSystems()
|
||||
{
|
||||
QNetworkRequest request(SenecAccount::systemsUrl());
|
||||
request.setRawHeader("authorization", m_token.toUtf8());
|
||||
return m_networkManager->get(request);
|
||||
}
|
||||
|
||||
QNetworkReply *SenecAccount::getDashboard(const QString &id)
|
||||
{
|
||||
QUrl url = SenecAccount::baseUrl();
|
||||
url.setPath("/v2/senec/systems/" + id +"/dashboard");
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setRawHeader("authorization", m_token.toUtf8());
|
||||
qCDebug(dcSenec()) << "Get" << url.toString();
|
||||
return m_networkManager->get(request);
|
||||
}
|
||||
|
||||
QNetworkReply *SenecAccount::getAbilities(const QString &id)
|
||||
{
|
||||
QUrl url = SenecAccount::baseUrl();
|
||||
url.setPath("/v1/senec/systems/" + id +"/abilities");
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setRawHeader("authorization", m_token.toUtf8());
|
||||
qCDebug(dcSenec()) << "Get" << url.toString();
|
||||
return m_networkManager->get(request);
|
||||
}
|
||||
|
||||
QNetworkReply *SenecAccount::getTechnicalData(const QString &id)
|
||||
{
|
||||
QUrl url = SenecAccount::baseUrl();
|
||||
url.setPath("/v1/senec/systems/" + id +"/technical-data");
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setRawHeader("authorization", m_token.toUtf8());
|
||||
qCDebug(dcSenec()) << "Get" << url.toString();
|
||||
return m_networkManager->get(request);
|
||||
}
|
||||
|
||||
70
senec/senecaccount.h
Normal file
70
senec/senecaccount.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef SENECACCOUNT_H
|
||||
#define SENECACCOUNT_H
|
||||
|
||||
#include <QUrl>
|
||||
#include <QObject>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <network/networkaccessmanager.h>
|
||||
|
||||
class SenecAccount : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SenecAccount(NetworkAccessManager *networkManager, const QString &username, const QString &token, const QString &refreshToken, QObject *parent = nullptr);
|
||||
|
||||
static QUrl baseUrl();
|
||||
static QUrl loginUrl();
|
||||
static QUrl systemsUrl();
|
||||
|
||||
bool available() const;
|
||||
|
||||
QNetworkReply *getSystems();
|
||||
QNetworkReply *getDashboard(const QString &id);
|
||||
QNetworkReply *getAbilities(const QString &id);
|
||||
QNetworkReply *getTechnicalData(const QString &id);
|
||||
|
||||
signals:
|
||||
bool availableChanged(bool available);
|
||||
|
||||
private:
|
||||
NetworkAccessManager *m_networkManager = nullptr;
|
||||
|
||||
QString m_username;
|
||||
QString m_token;
|
||||
QString m_refreshToken;
|
||||
|
||||
bool m_available = false;
|
||||
};
|
||||
|
||||
#endif // SENECACCOUNT_H
|
||||
116
senec/translations/3f055ea5-a883-445d-9556-675f5eda6c9a-de.ts
Normal file
116
senec/translations/3f055ea5-a883-445d-9556-675f5eda6c9a-de.ts
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="de">
|
||||
<context>
|
||||
<name>IntegrationPluginSenec</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginsenec.cpp" line="49"/>
|
||||
<source>Please enter username and password for your SENEC.home account.</source>
|
||||
<translation>Logge dich mit deinem SENEC.home account ein.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginsenec.cpp" line="71"/>
|
||||
<source>Username or password is invalid.</source>
|
||||
<translation>Benutzername oder Password ungültig.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Senec</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="39"/>
|
||||
<source>Battery critical</source>
|
||||
<extracomment>The name of the StateType ({cba01bf1-5daf-4466-8ae3-ea864593bdc6}) of ThingClass senecStorage</extracomment>
|
||||
<translation>Batterieladung kritisch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="42"/>
|
||||
<source>Battery level</source>
|
||||
<extracomment>The name of the StateType ({d6dd533a-beb2-4f57-a3d3-12c48a83306c}) of ThingClass senecStorage</extracomment>
|
||||
<translation>Ladestand</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="45"/>
|
||||
<source>Capacity</source>
|
||||
<extracomment>The name of the StateType ({4f571731-85f7-492e-ba51-eb6bf224776f}) of ThingClass senecStorage</extracomment>
|
||||
<translation>Kapazität</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="48"/>
|
||||
<source>Charging state</source>
|
||||
<extracomment>The name of the StateType ({cef34773-02c2-4eb1-8624-4e595847f674}) of ThingClass senecStorage</extracomment>
|
||||
<translation>Ladezustand</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="51"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="54"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the StateType ({320cb3f0-d2c5-4a30-817f-474f0cc87253}) of ThingClass senecStorage
|
||||
----------
|
||||
The name of the StateType ({2a508d04-3183-4c0b-9e92-90ff1ebce19e}) of ThingClass senecAccount</extracomment>
|
||||
<translation>Verbunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="57"/>
|
||||
<source>Current power</source>
|
||||
<extracomment>The name of the StateType ({09225a15-f2d0-46cf-a84f-4a91f389d488}) of ThingClass senecStorage</extracomment>
|
||||
<translation>Aktuelle Leistung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="60"/>
|
||||
<source>Logged in</source>
|
||||
<extracomment>The name of the StateType ({6842e3b3-ff25-4f34-b1c4-ff3f83c23746}) of ThingClass senecAccount</extracomment>
|
||||
<translation>Eingelogged</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="63"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="66"/>
|
||||
<source>SENEC</source>
|
||||
<extracomment>The name of the vendor ({1be922b9-4439-42cf-9caa-67f2ac7cc425})
|
||||
----------
|
||||
The name of the plugin Senec ({3f055ea5-a883-445d-9556-675f5eda6c9a})</extracomment>
|
||||
<translation>SENEC</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="69"/>
|
||||
<source>SENEC account</source>
|
||||
<extracomment>The name of the ThingClass ({f60497ea-a15a-4237-86bc-935182475e47})</extracomment>
|
||||
<translation>SENEC Account</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="72"/>
|
||||
<source>SENEC.Home storage</source>
|
||||
<extracomment>The name of the ThingClass ({a983c5ee-1c58-4cad-87fb-1bc612cbe6e4})</extracomment>
|
||||
<translation>SENEC.Home Speicher</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="75"/>
|
||||
<source>System ID</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: senecStorage, Type: thing, ID: {9a0fa7b1-bc35-44d4-b987-5ecb87fd8b00})</extracomment>
|
||||
<translation>System ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="78"/>
|
||||
<source>Username</source>
|
||||
<extracomment>The name of the StateType ({7670bfb4-5dfc-47f1-9c99-80b120f2aa8b}) of ThingClass senecAccount</extracomment>
|
||||
<translation>Benutzername</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="81"/>
|
||||
<source>charging</source>
|
||||
<extracomment>The name of a possible value of StateType {cef34773-02c2-4eb1-8624-4e595847f674} of ThingClass senecStorage</extracomment>
|
||||
<translation>lade</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="84"/>
|
||||
<source>discharging</source>
|
||||
<extracomment>The name of a possible value of StateType {cef34773-02c2-4eb1-8624-4e595847f674} of ThingClass senecStorage</extracomment>
|
||||
<translation>entlade</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="87"/>
|
||||
<source>idle</source>
|
||||
<extracomment>The name of a possible value of StateType {cef34773-02c2-4eb1-8624-4e595847f674} of ThingClass senecStorage</extracomment>
|
||||
<translation>leerlauf</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
116
senec/translations/3f055ea5-a883-445d-9556-675f5eda6c9a-en_US.ts
Normal file
116
senec/translations/3f055ea5-a883-445d-9556-675f5eda6c9a-en_US.ts
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>IntegrationPluginSenec</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginsenec.cpp" line="49"/>
|
||||
<source>Please enter username and password for your SENEC.home account.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginsenec.cpp" line="71"/>
|
||||
<source>Username or password is invalid.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Senec</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="39"/>
|
||||
<source>Battery critical</source>
|
||||
<extracomment>The name of the StateType ({cba01bf1-5daf-4466-8ae3-ea864593bdc6}) of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="42"/>
|
||||
<source>Battery level</source>
|
||||
<extracomment>The name of the StateType ({d6dd533a-beb2-4f57-a3d3-12c48a83306c}) of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="45"/>
|
||||
<source>Capacity</source>
|
||||
<extracomment>The name of the StateType ({4f571731-85f7-492e-ba51-eb6bf224776f}) of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="48"/>
|
||||
<source>Charging state</source>
|
||||
<extracomment>The name of the StateType ({cef34773-02c2-4eb1-8624-4e595847f674}) of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="51"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="54"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the StateType ({320cb3f0-d2c5-4a30-817f-474f0cc87253}) of ThingClass senecStorage
|
||||
----------
|
||||
The name of the StateType ({2a508d04-3183-4c0b-9e92-90ff1ebce19e}) of ThingClass senecAccount</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="57"/>
|
||||
<source>Current power</source>
|
||||
<extracomment>The name of the StateType ({09225a15-f2d0-46cf-a84f-4a91f389d488}) of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="60"/>
|
||||
<source>Logged in</source>
|
||||
<extracomment>The name of the StateType ({6842e3b3-ff25-4f34-b1c4-ff3f83c23746}) of ThingClass senecAccount</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="63"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="66"/>
|
||||
<source>SENEC</source>
|
||||
<extracomment>The name of the vendor ({1be922b9-4439-42cf-9caa-67f2ac7cc425})
|
||||
----------
|
||||
The name of the plugin Senec ({3f055ea5-a883-445d-9556-675f5eda6c9a})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="69"/>
|
||||
<source>SENEC account</source>
|
||||
<extracomment>The name of the ThingClass ({f60497ea-a15a-4237-86bc-935182475e47})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="72"/>
|
||||
<source>SENEC.Home storage</source>
|
||||
<extracomment>The name of the ThingClass ({a983c5ee-1c58-4cad-87fb-1bc612cbe6e4})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="75"/>
|
||||
<source>System ID</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: senecStorage, Type: thing, ID: {9a0fa7b1-bc35-44d4-b987-5ecb87fd8b00})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="78"/>
|
||||
<source>Username</source>
|
||||
<extracomment>The name of the StateType ({7670bfb4-5dfc-47f1-9c99-80b120f2aa8b}) of ThingClass senecAccount</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="81"/>
|
||||
<source>charging</source>
|
||||
<extracomment>The name of a possible value of StateType {cef34773-02c2-4eb1-8624-4e595847f674} of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="84"/>
|
||||
<source>discharging</source>
|
||||
<extracomment>The name of a possible value of StateType {cef34773-02c2-4eb1-8624-4e595847f674} of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/senec/plugininfo.h" line="87"/>
|
||||
<source>idle</source>
|
||||
<extracomment>The name of a possible value of StateType {cef34773-02c2-4eb1-8624-4e595847f674} of ThingClass senecStorage</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
Loading…
x
Reference in New Issue
Block a user