diff --git a/debian/control b/debian/control
index 4a3dc3c..bfaa5ac 100644
--- a/debian/control
+++ b/debian/control
@@ -35,6 +35,7 @@ Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
+ nymea-plugins-translations
Description: nymea.io plugin to send and receive generic modbus commands
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
@@ -50,7 +51,7 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
- nymea-plugins-modbus-translations,
+ nymea-plugins-modbus-translations
Description: nymea.io plugin for my-pv heating rods
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
@@ -61,6 +62,21 @@ Description: nymea.io plugin for my-pv heating rods
This package will install the nymea.io plugin for my-pv
+Package: nymea-plugin-sunspec
+Architecture: any
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+ nymea-plugins-modbus-translations
+Description: nymea.io plugin for SunSpec Modbus devices.
+ The nymea daemon is a plugin based IoT (Internet of Things) server. The
+ server works like a translator for devices, things and services and
+ allows them to interact.
+ With the powerful rule engine you are able to connect any device available
+ in the system and create individual scenes and behaviors for your environment.
+ .
+ This package will install the nymea.io plugin for manufactor independent sunspec devices.
+
+
Package: nymea-plugin-wallbe
Architecture: any
Section: libs
@@ -89,4 +105,3 @@ Description: Translation files for nymea modbus plugins - translations
in the system and create individual scenes and behaviors for your environment.
.
This package provides the translation files for all nymea modbus plugins.
-
diff --git a/debian/nymea-plugin-sunspec.install.in b/debian/nymea-plugin-sunspec.install.in
new file mode 100644
index 0000000..03cc550
--- /dev/null
+++ b/debian/nymea-plugin-sunspec.install.in
@@ -0,0 +1 @@
+usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginsunspec.so
diff --git a/mypv/integrationpluginmypv.cpp b/mypv/integrationpluginmypv.cpp
index 1dae803..f779210 100644
--- a/mypv/integrationpluginmypv.cpp
+++ b/mypv/integrationpluginmypv.cpp
@@ -195,7 +195,6 @@ void IntegrationPluginMyPv::executeAction(ThingActionInfo *info)
void IntegrationPluginMyPv::onRefreshTimer()
{
-
foreach (Thing *thing, myThings()) {
update(thing);
}
diff --git a/nymea-plugins-modbus.pro b/nymea-plugins-modbus.pro
index 7d5b93a..92c6b5c 100644
--- a/nymea-plugins-modbus.pro
+++ b/nymea-plugins-modbus.pro
@@ -4,6 +4,7 @@ PLUGIN_DIRS = \
drexelundweiss \
modbuscommander \
mypv \
+ sunspec \
wallbe \
message(============================================)
diff --git a/sunspec/README.md b/sunspec/README.md
new file mode 100644
index 0000000..95286d7
--- /dev/null
+++ b/sunspec/README.md
@@ -0,0 +1,16 @@
+# SunSpec
+
+## Supported Things
+
+* SunSpec Inverter
+* SunSpec PV Modules
+* SunSpec Meter
+* SunSpec Tracker
+* SunSpec Storage
+
+## Requirements
+
+* The package 'nymea-plugin-sunspec' must be installed.
+
+## More
+https://sunspec.org
diff --git a/sunspec/integrationpluginsunspec.cpp b/sunspec/integrationpluginsunspec.cpp
new file mode 100644
index 0000000..7974f77
--- /dev/null
+++ b/sunspec/integrationpluginsunspec.cpp
@@ -0,0 +1,119 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, 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 .
+*
+* 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 "plugininfo.h"
+#include "integrationpluginsunspec.h"
+
+#include
+
+IntegrationPluginSunSpec::IntegrationPluginSunSpec()
+{
+}
+
+void IntegrationPluginSunSpec::discoverThings(ThingDiscoveryInfo *info)
+{
+ // Discovery possible?
+ Q_ASSERT_X(false, "discoverThing", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8());
+}
+
+void IntegrationPluginSunSpec::setupThing(ThingSetupInfo *info)
+{
+ if (info->thing()->thingClassId() == sunspecInverterThingClassId) {
+
+ } else if (info->thing()->thingClassId() == sunspecPvModuleThingClassId) {
+
+ } else if (info->thing()->thingClassId() == sunspecMeterThingClassId) {
+
+ } else if (info->thing()->thingClassId() == sunspecTrackerThingClassId) {
+
+ } else if (info->thing()->thingClassId() == sunspecStorageThingClassId) {
+
+ } else {
+ Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(info->thing()->thingClassId().toString()).toUtf8());
+ }
+}
+
+void IntegrationPluginSunSpec::postSetupThing(Thing *thing)
+{
+ Q_UNUSED(thing)
+
+ if (!m_refreshTimer) {
+ int refreshTime = configValue(sunSpecPluginUpdateIntervalParamTypeId).toInt();
+ m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(refreshTime);
+ connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginSunSpec::onRefreshTimer);
+ }
+}
+
+void IntegrationPluginSunSpec::thingRemoved(Thing *thing)
+{
+ Q_UNUSED(thing)
+
+ if (myThings().isEmpty()) {
+ hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
+ m_refreshTimer = nullptr;
+ }
+}
+
+void IntegrationPluginSunSpec::executeAction(ThingActionInfo *info)
+{
+ Thing *thing = info->thing();
+ //Action action = info->action();
+
+ if (thing->thingClassId() == sunspecInverterThingClassId) {
+ info->finish(Thing::ThingErrorActionTypeNotFound);
+ } else if (thing->thingClassId() == sunspecMeterThingClassId) {
+ info->finish(Thing::ThingErrorActionTypeNotFound);
+ } else if (thing->thingClassId() == sunspecTrackerThingClassId) {
+ info->finish(Thing::ThingErrorActionTypeNotFound);
+ } else if (thing->thingClassId() == sunspecPvModuleThingClassId) {
+ info->finish(Thing::ThingErrorActionTypeNotFound);
+ } else if (thing->thingClassId() == sunspecStorageThingClassId) {
+ info->finish(Thing::ThingErrorActionTypeNotFound);
+ } else {
+ Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(info->thing()->thingClassId().toString()).toUtf8());
+ }
+}
+
+void IntegrationPluginSunSpec::onRefreshTimer()
+{
+ //get data
+}
+
+void IntegrationPluginSunSpec::onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value)
+{
+ // Check refresh schedule
+ if (paramTypeId == sunSpecPluginUpdateIntervalParamTypeId) {
+ if (m_refreshTimer) {
+ int refreshTime = value.toInt();
+ m_refreshTimer->stop();
+ m_refreshTimer->startTimer(refreshTime);
+ }
+ }
+}
diff --git a/sunspec/integrationpluginsunspec.h b/sunspec/integrationpluginsunspec.h
new file mode 100644
index 0000000..85e62a9
--- /dev/null
+++ b/sunspec/integrationpluginsunspec.h
@@ -0,0 +1,80 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, 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 .
+*
+* 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 INTEGRATIONPLUGINSUNSPEC_H
+#define INTEGRATIONPLUGINSUNSPEC_H
+
+#include "integrations/integrationplugin.h"
+#include "plugintimer.h"
+
+#include "../modbus/modbustcpmaster.h"
+
+#include
+
+class IntegrationPluginSunSpec: public IntegrationPlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginsunspec.json")
+ Q_INTERFACES(IntegrationPlugin)
+
+
+public:
+ explicit IntegrationPluginSunSpec();
+
+ void discoverThings(ThingDiscoveryInfo *info) 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 m_modbusTcpMasters;
+ QHash m_asyncActions;
+
+ void update(Thing *thing);
+
+private slots:
+ void onRefreshTimer();
+
+ void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
+
+ void onConnectionStateChanged(bool status);
+ void onWriteRequestExecuted(QUuid requestId, bool success);
+ void onWriteRequestError(QUuid requestId, const QString &error);
+
+ void onReceivedHoldingRegister(quint32 slaveAddress, quint32 modbusRegister, const QVector &values);
+ void onReceivedInputRegister(quint32 slaveAddress, quint32 modbusRegister, const QVector &values);
+};
+
+#endif // INTEGRATIONPLUGINSUNSPEC_H
+
diff --git a/sunspec/integrationpluginsunspec.json b/sunspec/integrationpluginsunspec.json
new file mode 100644
index 0000000..3a0ffbf
--- /dev/null
+++ b/sunspec/integrationpluginsunspec.json
@@ -0,0 +1,238 @@
+{
+ "name": "SunSpec",
+ "displayName": "sunspec",
+ "id": "73c7efcc-80d5-4166-ad97-2cbbeb129d91",
+ "paramTypes":[
+ {
+ "id": "52da5222-9a94-47a2-9adc-004541d2f5ed",
+ "name": "updateInterval",
+ "displayName": "Update interval",
+ "type": "int",
+ "unit": "Seconds",
+ "defaultValue": 15
+ }
+ ],
+ "vendors": [
+ {
+ "name": "sunspec",
+ "displayName": "SunSpec",
+ "id": "c143a7b4-a16c-4fff-86a3-9ffab3d6841d",
+ "thingClasses": [
+ {
+ "name": "sunspecInverter",
+ "displayName": "SunSpec Inverter",
+ "id": "2e4122ea-96a5-415c-b5e2-7d6012265a83",
+ "createMethods": [ "User" ],
+ "interfaces": ["connectable"],
+ "paramTypes": [
+ {
+ "id": "6ffaa694-a4f2-4936-b043-37679449a34b",
+ "name":"ipAddress",
+ "displayName": "IP address",
+ "type": "QString"
+ },
+ {
+ "id": "08bf6597-976d-4fb9-8fc2-4372c07961d4",
+ "name":"serialNumber",
+ "displayName": "Serial number",
+ "type": "QString"
+ }
+ ],
+ "stateTypes":[
+ {
+ "id": "4401468c-0385-40a9-b436-daf7ed6a50d5",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "9bdcc785-4738-437e-88a0-fc231095c2dd",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Change power",
+ "type": "bool",
+ "defaultValue": 0,
+ "writable": true
+ }
+ ]
+ },
+ {
+ "name": "sunspecPvModule",
+ "displayName": "SunSpec PV Module",
+ "id": "fb7ff0df-a745-4313-83e4-1e5007b06fe2",
+ "createMethods": [ "User" ],
+ "interfaces": ["connectable"],
+ "paramTypes": [
+ {
+ "id": "890e468b-fc76-4641-9569-93cd45e6bb8d",
+ "name":"ipAddress",
+ "displayName": "IP address",
+ "type": "QString"
+ },
+ {
+ "id": "d5a9510d-720f-4a28-9d91-977eedd022bd",
+ "name":"serialNumber",
+ "displayName": "Serial number",
+ "type": "QString"
+ }
+ ],
+ "stateTypes":[
+ {
+ "id": "edc032d2-022f-43f7-9131-831ad23ee62a",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "0b7485eb-3cf7-45b2-87cf-9ec85366b197",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Change power",
+ "type": "bool",
+ "defaultValue": 0,
+ "writable": true
+ }
+ ]
+ },
+ {
+ "name": "sunspecMeter",
+ "displayName": "SunSpec Meter",
+ "id": "68f822f9-ff30-4275-b229-39a3674fead7",
+ "createMethods": [ "User" ],
+ "interfaces": ["connectable"],
+ "paramTypes": [
+ {
+ "id": "66bdb89b-bbd4-4edf-96df-649014d94c42",
+ "name":"ipAddress",
+ "displayName": "IP address",
+ "type": "QString"
+ },
+ {
+ "id": "89af6d27-4b81-42ef-9883-1e2ba2067884",
+ "name":"serialNumber",
+ "displayName": "Serial number",
+ "type": "QString"
+ }
+ ],
+ "stateTypes":[
+ {
+ "id": "36f861c7-afc1-4725-b41f-67113200d78f",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "36f18720-69ca-4021-9328-262d87397f1b",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Change power",
+ "type": "bool",
+ "defaultValue": 0,
+ "writable": true
+ }
+ ]
+ },
+ {
+ "name": "sunspecTracker",
+ "displayName": "SunSpec Tracker",
+ "id": "9941da30-a6d6-475d-8244-3c2145b419e6",
+ "createMethods": [ "User" ],
+ "interfaces": ["connectable"],
+ "paramTypes": [
+ {
+ "id": "ccdcca78-7efa-4253-8fdb-8731e6880e9b",
+ "name":"ipAddress",
+ "displayName": "IP address",
+ "type": "QString"
+ },
+ {
+ "id": "67ce05ff-14bf-4d43-94ba-d5f290278514",
+ "name":"serialNumber",
+ "displayName": "Serial number",
+ "type": "QString"
+ }
+ ],
+ "stateTypes":[
+ {
+ "id": "fe57e465-e49e-4d50-b880-6d9a243783ff",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "d2bbba4b-998f-444e-935f-f958927afddd",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Change power",
+ "type": "bool",
+ "defaultValue": 0,
+ "writable": true
+ }
+ ]
+ },
+ {
+ "name": "sunspecStorage",
+ "displayName": "SunSpec Storage",
+ "id": "9a643ba8-346c-4127-a2f8-956a7133d75e",
+ "createMethods": [ "User" ],
+ "interfaces": ["connectable"],
+ "paramTypes": [
+ {
+ "id": "421cacb9-a94d-4ba9-923c-3bc30d8b94c8",
+ "name":"ipAddress",
+ "displayName": "IP address",
+ "type": "QString"
+ },
+ {
+ "id": "ae76db81-7969-440f-85f0-28ed46d772db",
+ "name":"serialNumber",
+ "displayName": "Serial number",
+ "type": "QString"
+ }
+ ],
+ "stateTypes":[
+ {
+ "id": "25a1fb10-a6b9-4037-b7cf-ad481a65beb4",
+ "name": "connected",
+ "displayName": "Connected",
+ "displayNameEvent": "Connected changed",
+ "type": "bool",
+ "defaultValue": false,
+ "cached": false
+ },
+ {
+ "id": "9c0e0b08-4461-4e54-aaf3-cab9155028da",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Change power",
+ "type": "bool",
+ "defaultValue": 0,
+ "writable": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
+
+
+
diff --git a/sunspec/meta.json b/sunspec/meta.json
new file mode 100644
index 0000000..d93e59c
--- /dev/null
+++ b/sunspec/meta.json
@@ -0,0 +1,12 @@
+{
+ "title": "SunSpec",
+ "tagline": "Connect to SunSpec devices.",
+ "icon": "sunspec.png",
+ "stability": "consumer",
+ "offline": true,
+ "technologies": [
+ "network"
+ ],
+ "categories": [
+ ]
+}
diff --git a/sunspec/sunspec.cpp b/sunspec/sunspec.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/sunspec/sunspec.h b/sunspec/sunspec.h
new file mode 100644
index 0000000..e69de29
diff --git a/sunspec/sunspec.png b/sunspec/sunspec.png
new file mode 100644
index 0000000..7a52a45
Binary files /dev/null and b/sunspec/sunspec.png differ
diff --git a/sunspec/sunspec.pro b/sunspec/sunspec.pro
new file mode 100644
index 0000000..a9c3e6a
--- /dev/null
+++ b/sunspec/sunspec.pro
@@ -0,0 +1,15 @@
+include(../plugins.pri)
+
+QT += \
+ network \
+ serialbus \
+
+SOURCES += \
+ integrationpluginsunspec.cpp \
+ sunspec.cpp \
+ ../modbus/modbustcpmaster.cpp \
+
+HEADERS += \
+ integrationpluginsunspec.h \
+ sunspec.h \
+ ../modbus/modbustcpmaster.h \