diff --git a/README.md b/README.md
index c225c84..8f907ec 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,12 @@
-# alpdesk-automationservice
\ No newline at end of file
+# Alpdesk-Automationservice
+Java-Service for Automation (like Homeautomation)
+
+To start on RaspberryPi with Shell-Script:
+
+#!/bin/sh
+cd /home/pi/xhomeautomation
+mount /dev/sda1 /media/xhomeautomationusb/
+sudo mount | grep sda1
+java -Xdebug -Xrunjdwp:transport=dt_socket,address=5001,server=y,suspend=n -jar XHomeautomation-Service-Deploy.jar /home/pi/xhomeautomation/homeautomation.properties --spring.profiles.active=prod --spring.datasource.url=jdbc:h2:file:/media/xhomeautomationusb/xhomeautomationdb_prod
+
+
diff --git a/nb-configuration.xml b/nb-configuration.xml
new file mode 100644
index 0000000..5b0f1f8
--- /dev/null
+++ b/nb-configuration.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ true
+
+
diff --git a/nbactions-build_jdk11.xml b/nbactions-build_jdk11.xml
new file mode 100644
index 0000000..bcab3ff
--- /dev/null
+++ b/nbactions-build_jdk11.xml
@@ -0,0 +1,49 @@
+
+
+
+ run
+
+ jar
+
+
+ process-classes
+ org.codehaus.mojo:exec-maven-plugin:1.5.0:exec
+
+
+ -Dspring.profiles.active=dev -classpath %classpath x.main.XHomeautomationMain homeautomationtest.properties
+ java
+ ./src/main/resources/data
+
+
+
+ debug
+
+ jar
+
+
+ process-classes
+ org.codehaus.mojo:exec-maven-plugin:1.5.0:exec
+
+
+ -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} -Dspring.profiles.active=dev -classpath %classpath x.main.XHomeautomationMain homeautomationtest.properties
+ java
+ true
+ ./src/main/resources/data
+
+
+
+ profile
+
+ jar
+
+
+ process-classes
+ org.codehaus.mojo:exec-maven-plugin:1.5.0:exec
+
+
+ -Dspring.profiles.active=dev -classpath %classpath x.main.XHomeautomationMain homeautomationtest.properties
+ java
+ ./src/main/resources/data
+
+
+
diff --git a/nbactions.xml b/nbactions.xml
new file mode 100644
index 0000000..bcab3ff
--- /dev/null
+++ b/nbactions.xml
@@ -0,0 +1,49 @@
+
+
+
+ run
+
+ jar
+
+
+ process-classes
+ org.codehaus.mojo:exec-maven-plugin:1.5.0:exec
+
+
+ -Dspring.profiles.active=dev -classpath %classpath x.main.XHomeautomationMain homeautomationtest.properties
+ java
+ ./src/main/resources/data
+
+
+
+ debug
+
+ jar
+
+
+ process-classes
+ org.codehaus.mojo:exec-maven-plugin:1.5.0:exec
+
+
+ -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} -Dspring.profiles.active=dev -classpath %classpath x.main.XHomeautomationMain homeautomationtest.properties
+ java
+ true
+ ./src/main/resources/data
+
+
+
+ profile
+
+ jar
+
+
+ process-classes
+ org.codehaus.mojo:exec-maven-plugin:1.5.0:exec
+
+
+ -Dspring.profiles.active=dev -classpath %classpath x.main.XHomeautomationMain homeautomationtest.properties
+ java
+ ./src/main/resources/data
+
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..0d775cf
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,153 @@
+
+
+
+ 4.0.0
+ x
+ Alpdesk-Automationservice
+ 2.2.0
+
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.1.RELEASE
+
+
+
+
+ net.wimpi
+ jamod
+ 1.2
+
+
+ commons-codec
+ commons-codec
+ 1.14
+
+
+ com.typesafe.akka
+ akka-actor_2.13
+ 2.6.6
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+ runtime
+ 1.4.200
+
+
+
+
+
+ build_jdk8
+
+ true
+ 1.8
+ 1.8
+ x.main.XHomeautomationMain
+
+
+
+
+ src/main/resources
+
+ **/*
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ ${project.artifactId}-Deploy
+ true
+ true
+ x.main.XHomeautomationMain
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+ build_jdk11
+
+ true
+ 11
+ 11
+ x.main.XHomeautomationMain
+
+
+
+
+ src/main/resources
+
+ **/*
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ ${project.artifactId}-Deploy
+ true
+ true
+ x.main.XHomeautomationMain
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+
+
+ UTF-8
+
+
+
+
+
+ src/main/java
+
+ **/*.properties
+ **/*.txt
+ **/*.png
+ **/*.gif
+ **/*.GIF
+ **/*.dll
+ **/*.theme
+
+
+
+
+ Alpdesk-Automationservice
+
\ No newline at end of file
diff --git a/src/main/java/x/DeviceEffects/BaseEffect.java b/src/main/java/x/DeviceEffects/BaseEffect.java
new file mode 100755
index 0000000..b943084
--- /dev/null
+++ b/src/main/java/x/DeviceEffects/BaseEffect.java
@@ -0,0 +1,28 @@
+package x.DeviceEffects;
+
+public class BaseEffect {
+
+ long startTime = 0;
+ int delay = 0;
+ public boolean idle = true;
+ public String[] outputs = null;
+
+ public BaseEffect(int delay, String outputs) {
+ this.delay = delay;
+ this.outputs = outputs.split(";");
+ }
+
+ synchronized public void initEffect(long startTime) {
+ this.idle = false;
+ this.startTime = startTime;
+ }
+
+ synchronized public void resetEffect() {
+ this.idle = true;
+ this.startTime = 0;
+ }
+
+ synchronized public void trigger(boolean value) {
+ }
+
+}
diff --git a/src/main/java/x/DeviceEffects/BridgeEffect.java b/src/main/java/x/DeviceEffects/BridgeEffect.java
new file mode 100755
index 0000000..873538d
--- /dev/null
+++ b/src/main/java/x/DeviceEffects/BridgeEffect.java
@@ -0,0 +1,43 @@
+package x.DeviceEffects;
+
+import x.DeviceUtils.DeviceListUtils;
+import x.Devices.OutputDevice;
+
+public class BridgeEffect extends BaseEffect {
+
+ boolean bridgeValid = false;
+
+ public BridgeEffect(int delay, String outputs) {
+ super(delay, outputs);
+ }
+
+ @Override
+ synchronized public void initEffect(long startTime) {
+ super.initEffect(startTime);
+ bridgeValid = false;
+ }
+
+ @Override
+ synchronized public void trigger(boolean value) {
+ if (idle == false) {
+ if (value == true && (System.currentTimeMillis() - startTime) >= delay) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != value) {
+ o.sendMessage(value);
+ }
+ }
+ bridgeValid = true;
+ } else if (bridgeValid && value == false) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != value) {
+ o.sendMessage(value);
+ }
+ }
+ bridgeValid = false;
+ idle = true;
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/DeviceEffects/DimmerEffect.java b/src/main/java/x/DeviceEffects/DimmerEffect.java
new file mode 100755
index 0000000..3c73149
--- /dev/null
+++ b/src/main/java/x/DeviceEffects/DimmerEffect.java
@@ -0,0 +1,43 @@
+package x.DeviceEffects;
+
+import x.DeviceUtils.DeviceListUtils;
+import x.Devices.DimmerDevice;
+
+public class DimmerEffect extends BaseEffect {
+
+ boolean bridgeValid = false;
+
+ public DimmerEffect(int delay, String outputs) {
+ super(delay, outputs);
+ }
+
+ @Override
+ synchronized public void initEffect(long startTime) {
+ super.initEffect(startTime);
+ bridgeValid = false;
+ }
+
+ @Override
+ synchronized public void trigger(boolean value) {
+ if (idle == false) {
+ if (value == true && (System.currentTimeMillis() - startTime) >= delay) {
+ for (String output : outputs) {
+ DimmerDevice o = DeviceListUtils.getInstance().getDimmerById(output);
+ if (o.isValue() != value) {
+ o.sendMessage(value);
+ }
+ }
+ bridgeValid = true;
+ } else if (bridgeValid && value == false) {
+ for (String output : outputs) {
+ DimmerDevice o = DeviceListUtils.getInstance().getDimmerById(output);
+ if (o.isValue() != value) {
+ o.sendMessage(value);
+ }
+ }
+ bridgeValid = false;
+ idle = true;
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/DeviceEffects/OffEffect.java b/src/main/java/x/DeviceEffects/OffEffect.java
new file mode 100755
index 0000000..cc35f64
--- /dev/null
+++ b/src/main/java/x/DeviceEffects/OffEffect.java
@@ -0,0 +1,26 @@
+package x.DeviceEffects;
+
+import x.DeviceUtils.DeviceListUtils;
+import x.Devices.OutputDevice;
+
+public class OffEffect extends BaseEffect {
+
+ public OffEffect(int delay, String outputs) {
+ super(delay, outputs);
+ }
+
+ @Override
+ synchronized public void trigger(boolean value) {
+ if (idle == false) {
+ if (value == true && (System.currentTimeMillis() - startTime) >= delay) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() == true) {
+ o.sendMessage(false);
+ }
+ }
+ idle = true;
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/DeviceEffects/OnEffect.java b/src/main/java/x/DeviceEffects/OnEffect.java
new file mode 100755
index 0000000..fbc14ef
--- /dev/null
+++ b/src/main/java/x/DeviceEffects/OnEffect.java
@@ -0,0 +1,59 @@
+package x.DeviceEffects;
+
+import x.DeviceUtils.DeviceListUtils;
+import x.Devices.OutputDevice;
+
+public class OnEffect extends BaseEffect {
+
+ int duration = 0;
+ long startTimeDuration = 0;
+ boolean durationValid = false;
+
+ public OnEffect(int duration, int delay, String outputs) {
+ super(delay, outputs);
+ this.duration = duration;
+ }
+
+ @Override
+ synchronized public void initEffect(long startTime) {
+ super.initEffect(startTime);
+ durationValid = false;
+ startTimeDuration = 0;
+ }
+
+ @Override
+ synchronized public void trigger(boolean value) {
+ if (idle == false) {
+ if (value == true && (System.currentTimeMillis() - startTime) >= delay) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() == false) {
+ o.sendMessage(true);
+ }
+ }
+ if (duration != 0) {
+ if (startTimeDuration == 0) {
+ startTimeDuration = System.currentTimeMillis();
+ durationValid = true;
+ }
+ } else {
+ idle = true;
+ }
+ }
+ if (durationValid) {
+ if ((System.currentTimeMillis() - startTimeDuration) >= duration) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() == true) {
+ o.sendMessage(false);
+ }
+ }
+ startTimeDuration = 0;
+ durationValid = false;
+ idle = true;
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/x/DeviceEffects/ToggleEffect.java b/src/main/java/x/DeviceEffects/ToggleEffect.java
new file mode 100755
index 0000000..46f281f
--- /dev/null
+++ b/src/main/java/x/DeviceEffects/ToggleEffect.java
@@ -0,0 +1,28 @@
+package x.DeviceEffects;
+
+import x.DeviceUtils.DeviceListUtils;
+import x.Devices.OutputDevice;
+
+public class ToggleEffect extends BaseEffect {
+
+ public ToggleEffect(int delay, String outputs) {
+ super(delay, outputs);
+ }
+
+ @Override
+ synchronized public void trigger(boolean value) {
+ if (idle == false) {
+ if (value == true && (System.currentTimeMillis() - startTime) >= delay) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() == false) {
+ o.sendMessage(true);
+ } else {
+ o.sendMessage(false);
+ }
+ }
+ idle = true;
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/DeviceUtils/DateUtils.java b/src/main/java/x/DeviceUtils/DateUtils.java
new file mode 100755
index 0000000..4ed670f
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/DateUtils.java
@@ -0,0 +1,80 @@
+package x.DeviceUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+public class DateUtils {
+
+ SimpleDateFormat dateFormat = null;
+ SimpleDateFormat dateFormatd = null;
+ SimpleDateFormat dateFormatt = null;
+ SimpleDateFormat dateFormatts = null;
+ Calendar now = null;
+ Calendar xmlDateStart = null;
+ Calendar xmlDateStop = null;
+ Calendar dateTemp = null;
+
+ public DateUtils() {
+ this.dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
+ this.dateFormatd = new SimpleDateFormat("dd.MM");
+ this.dateFormatt = new SimpleDateFormat("HH:mm:ss");
+ this.dateFormatts = new SimpleDateFormat("HH:mm");
+ }
+
+ public boolean checkStatus(String timeStart, String timeStop) {
+ try {
+ if (!timeStart.equals("") && !timeStop.equals("")) {
+ now = Calendar.getInstance();
+ xmlDateStart = Calendar.getInstance();
+ xmlDateStop = Calendar.getInstance();
+ xmlDateStart.setTime(dateFormat.parse(dateFormatd.format(now.getTime()) + "." + now.get(Calendar.YEAR) + " " + timeStart));
+ xmlDateStop.setTime(dateFormat.parse(dateFormatd.format(now.getTime()) + "." + now.get(Calendar.YEAR) + " " + timeStop));
+
+ if (xmlDateStop.compareTo(xmlDateStart) < 0) {
+ if (now.compareTo(xmlDateStop) < 0) {
+ now.add(Calendar.DATE, 1);
+ }
+ xmlDateStop.add(Calendar.DATE, 1);
+ }
+
+ return now.after(xmlDateStart) && now.before(xmlDateStop);
+ } else {
+ return false;
+ }
+ } catch (ParseException ex) {
+ return false;
+ }
+ }
+
+ public String[] getCompleteDateString() {
+ String[] data = new String[2];
+ if (xmlDateStart != null) {
+ data[0] = dateFormat.format(xmlDateStart.getTime());
+ }
+ if (xmlDateStop != null) {
+ data[1] = dateFormat.format(xmlDateStop.getTime());
+ }
+ return data;
+ }
+
+ public String increaseTime(String currentTime, int s) {
+ String returnvalue = currentTime;
+ Calendar temp = Calendar.getInstance();
+ try {
+ temp.setTime(dateFormat.parse(dateFormatd.format(Calendar.getInstance().getTime()) + "." + Calendar.getInstance().get(Calendar.YEAR) + " " + currentTime));
+ temp.add(Calendar.SECOND, s);
+ returnvalue = dateFormatt.format(temp.getTime());
+ } catch (ParseException ex) {
+ }
+ return returnvalue;
+ }
+
+ public String getHourMinuteString() {
+ return dateFormatts.format(Calendar.getInstance().getTime());
+ }
+
+ public String getTimeStampString() {
+ return dateFormat.format(Calendar.getInstance().getTime());
+ }
+}
diff --git a/src/main/java/x/DeviceUtils/DeviceListUtils.java b/src/main/java/x/DeviceUtils/DeviceListUtils.java
new file mode 100755
index 0000000..2a24d20
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/DeviceListUtils.java
@@ -0,0 +1,322 @@
+package x.DeviceUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import x.Devices.BaseDevice;
+import x.Devices.DHT22Device;
+import x.Devices.DimmerDevice;
+import x.Devices.HeatingPumpDevice;
+import x.Devices.InputDevice;
+import x.Devices.OutputDevice;
+import x.Devices.SceneDevice;
+import x.Devices.SensorTemperatureDevice;
+import x.Devices.ShadingDevice;
+import x.Devices.TemperatureDevice;
+import x.Devices.TimeDevice;
+import x.Devices.VentilationDevice;
+
+public class DeviceListUtils {
+
+ List deviceList = null;
+ private int maxInputBusaddress = -1;
+ private int maxOutputBusaddress = -1;
+ private int maxAnalogInBusaddress = -1;
+
+ private static DeviceListUtils singleton = null;
+
+ public DeviceListUtils() {
+ }
+
+ public static DeviceListUtils getInstance() {
+ if (singleton == null) {
+ singleton = new DeviceListUtils();
+ }
+ return singleton;
+ }
+
+ public void setDeviceList(List deviceList) {
+ this.deviceList = deviceList;
+ }
+
+ public List getDeviceList() {
+ return this.deviceList;
+ }
+
+ public ArrayList getInputDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof InputDevice) {
+ InputDevice temp = (InputDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getOutputDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof OutputDevice) {
+ OutputDevice temp = (OutputDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getDimmerDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof DimmerDevice) {
+ DimmerDevice temp = (DimmerDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getDHT22DevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof DHT22Device) {
+ DHT22Device temp = (DHT22Device) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getHeatingPumpDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof HeatingPumpDevice) {
+ HeatingPumpDevice temp = (HeatingPumpDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getVentilationDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof VentilationDevice) {
+ VentilationDevice temp = (VentilationDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getShadingDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof ShadingDevice) {
+ ShadingDevice temp = (ShadingDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getTemperatureDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof TemperatureDevice) {
+ TemperatureDevice temp = (TemperatureDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getSensorTemperatureDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof SensorTemperatureDevice) {
+ SensorTemperatureDevice temp = (SensorTemperatureDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getSceneDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof SceneDevice) {
+ SceneDevice temp = (SceneDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public ArrayList getTimeDevicesByCategorie(String categorie) {
+ ArrayList list = new ArrayList<>();
+ for (Object device : deviceList) {
+ if (device instanceof TimeDevice) {
+ TimeDevice temp = (TimeDevice) device;
+ if (temp.categorie.equals(categorie)) {
+ list.add(temp);
+ }
+ }
+ }
+ return list;
+ }
+
+ public OutputDevice getOutputById(String id) {
+ OutputDevice d = null;
+ for (Object device : deviceList) {
+ if (device instanceof OutputDevice) {
+ if (((OutputDevice) device).id.equals(id)) {
+ d = (OutputDevice) device;
+ break;
+ }
+ }
+ }
+ return d;
+ }
+
+ public TemperatureDevice getTemperatureDeviceById(String id) {
+ TemperatureDevice d = null;
+ for (Object device : deviceList) {
+ if (device instanceof TemperatureDevice) {
+ if (((TemperatureDevice) device).id.equals(id)) {
+ d = (TemperatureDevice) device;
+ break;
+ }
+ }
+ }
+ return d;
+ }
+
+ public SensorTemperatureDevice getSensorTemperatureDeviceById(String id) {
+ SensorTemperatureDevice d = null;
+ for (Object device : deviceList) {
+ if (device instanceof SensorTemperatureDevice) {
+ if (((SensorTemperatureDevice) device).id.equals(id)) {
+ d = (SensorTemperatureDevice) device;
+ break;
+ }
+ }
+ }
+ return d;
+ }
+
+ public DimmerDevice getDimmerById(String id) {
+ DimmerDevice d = null;
+ for (Object device : deviceList) {
+ if (device instanceof DimmerDevice) {
+ if (((DimmerDevice) device).id.equals(id)) {
+ d = (DimmerDevice) device;
+ break;
+ }
+ }
+ }
+ return d;
+ }
+
+ public SceneDevice getSceneDeviceBySpeechIdent(String ident) {
+ SceneDevice d = null;
+ for (Object device : deviceList) {
+ if (device instanceof SceneDevice) {
+ if (((SceneDevice) device).speechIdent.equals(ident)) {
+ d = (SceneDevice) device;
+ break;
+ }
+ }
+ }
+ return d;
+ }
+
+ public SceneDevice getSceneDeviceByHandle(int deviceHandle) {
+ SceneDevice d = null;
+ for (Object device : deviceList) {
+ if (device instanceof SceneDevice) {
+ if (((SceneDevice) device).deviceHandle == deviceHandle) {
+ d = (SceneDevice) device;
+ break;
+ }
+ }
+ }
+ return d;
+ }
+
+ public int getMaxInputBusAddress() {
+ if (maxInputBusaddress == -1) {
+ for (Object device : deviceList) {
+ if (device instanceof InputDevice) {
+ if (((InputDevice) device).busAddress > maxInputBusaddress) {
+ maxInputBusaddress = ((InputDevice) device).busAddress;
+ }
+ }
+ }
+ }
+ return maxInputBusaddress;
+ }
+
+ public int getMaxOutputBusAddress() {
+ if (maxOutputBusaddress == -1) {
+ for (Object device : deviceList) {
+ if (device instanceof OutputDevice) {
+ if (((OutputDevice) device).busAddress > maxOutputBusaddress) {
+ maxOutputBusaddress = ((OutputDevice) device).busAddress;
+ }
+ }
+ }
+ }
+ return maxOutputBusaddress;
+ }
+
+ public int getMaxAnalogInBusAddress() {
+ if (maxAnalogInBusaddress == -1) {
+ for (Object device : deviceList) {
+ if (device instanceof TemperatureDevice) {
+ if (((TemperatureDevice) device).busAddress > maxAnalogInBusaddress) {
+ maxAnalogInBusaddress = ((TemperatureDevice) device).busAddress;
+ }
+ } else if (device instanceof SensorTemperatureDevice) {
+ if (((SensorTemperatureDevice) device).busAddress > maxAnalogInBusaddress) {
+ maxAnalogInBusaddress = ((SensorTemperatureDevice) device).busAddress;
+ }
+ }
+ }
+ }
+ return maxAnalogInBusaddress;
+ }
+
+ public boolean anyTemperatureDeviceIsActive() {
+ boolean state = false;
+ for (Object device : deviceList) {
+ if (device instanceof TemperatureDevice) {
+ if (((TemperatureDevice) device).isOutputState()) {
+ state = true;
+ break;
+ }
+ }
+ }
+ return state;
+ }
+
+}
diff --git a/src/main/java/x/DeviceUtils/InputParameter.java b/src/main/java/x/DeviceUtils/InputParameter.java
new file mode 100755
index 0000000..10beb83
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/InputParameter.java
@@ -0,0 +1,14 @@
+package x.DeviceUtils;
+
+import x.DeviceEffects.BaseEffect;
+
+public class InputParameter {
+
+ public int type;
+ public BaseEffect effect = null;
+
+ public InputParameter(int type, BaseEffect effect) {
+ this.type = type;
+ this.effect = effect;
+ }
+}
diff --git a/src/main/java/x/DeviceUtils/PropertyChangedEvent.java b/src/main/java/x/DeviceUtils/PropertyChangedEvent.java
new file mode 100755
index 0000000..7531b27
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/PropertyChangedEvent.java
@@ -0,0 +1,111 @@
+package x.DeviceUtils;
+
+import java.lang.reflect.Field;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.Devices.BaseDevice;
+import x.utils.PropertyInfo;
+
+public class PropertyChangedEvent {
+
+ private final Logger logger = LoggerFactory.getLogger(PropertyChangedEvent.class);
+
+ private final Field f;
+ private final PropertyInfo p;
+ private final String value;
+ private final boolean byDatabase;
+
+ public PropertyChangedEvent(Field f, PropertyInfo p, String value, boolean byDatabase) {
+ this.f = f;
+ this.p = p;
+ this.value = value;
+ this.byDatabase = byDatabase;
+ }
+
+ public void execute(BaseDevice d) throws Exception {
+ if (byDatabase == true) {
+ executeByDatabase(d);
+ } else {
+ executeByValue(d);
+ }
+ }
+
+ private void executeByDatabase(BaseDevice d) throws Exception {
+ switch (p.type()) {
+ case Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE: {
+ logger.debug("DB-PROPERTY TYPE_PROPERTIEINFO_CHANGESOLLVALUE <" + d.id + "><" + p.displayName() + "/" + p.handle() + "> => <" + value + ">");
+ if (f.getType().isAssignableFrom(Integer.TYPE)) {
+ f.set(d, Integer.parseInt(value));
+ } else if (f.getType().isAssignableFrom(String.class)) {
+ f.set(d, value);
+ }
+ break;
+ }
+ case Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION: {
+ if (f.getType().isAssignableFrom(Boolean.TYPE)) {
+ f.set(d, value.equalsIgnoreCase("ON"));
+ logger.debug("DB-PROPERTY TYPE_PROPERTIEINFO_TOGGLEACTIVATION <" + d.id + "><" + p.displayName() + "/" + p.handle() + "> => <" + value.equalsIgnoreCase("ON") + ">");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ private void executeByValue(BaseDevice d) throws Exception {
+ switch (p.type()) {
+ case Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE: {
+ logger.debug("PROPERTY TYPE_PROPERTIEINFO_CHANGESOLLVALUE <" + d.id + "><" + p.displayName() + "/" + p.handle() + "> => <" + value + ">");
+ switch (value) {
+ case "+": {
+ if (f.getType().isAssignableFrom(Integer.TYPE)) {
+ int temp = (int) f.get(d);
+ temp++;
+ f.set(d, temp);
+ } else if (f.getType().isAssignableFrom(String.class)) {
+ String temp = (String) f.get(d);
+ if (p.propertyType() == Types.PROPERTYTYPE_TIME) {
+ if (!temp.equals("-")) {
+ DateUtils dUtils = new DateUtils();
+ temp = dUtils.increaseTime(temp, p.stepValue());
+ }
+ }
+ f.set(d, temp);
+ }
+ break;
+ }
+ case "-": {
+ if (f.getType().isAssignableFrom(Integer.TYPE)) {
+ int temp = (int) f.get(d);
+ temp--;
+ f.set(d, temp);
+ } else if (f.getType().isAssignableFrom(String.class)) {
+ String temp = (String) f.get(d);
+ if (p.propertyType() == Types.PROPERTYTYPE_TIME) {
+ if (!temp.equals("-")) {
+ DateUtils dUtils = new DateUtils();
+ temp = dUtils.increaseTime(temp, -(p.stepValue()));
+ }
+ }
+ f.set(d, temp);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION: {
+ if (f.getType().isAssignableFrom(Boolean.TYPE)) {
+ boolean temp = (boolean) f.get(d);
+ temp = temp != true;
+ f.set(d, temp);
+ logger.debug("PROPERTY TYPE_PROPERTIEINFO_TOGGLEACTIVATION <" + d.id + "><" + p.displayName() + "/" + p.handle() + "> => <" + temp + ">");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/main/java/x/DeviceUtils/RecorderItem.java b/src/main/java/x/DeviceUtils/RecorderItem.java
new file mode 100755
index 0000000..140c1a2
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/RecorderItem.java
@@ -0,0 +1,201 @@
+package x.DeviceUtils;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Queue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RecorderItem {
+
+ private final Logger logger = LoggerFactory.getLogger(RecorderItem.class);
+ public static final int LEGENDTYPE_DATE_HOUT_MINUTE = 1;
+
+ private int legendType = 0;
+ private int maxEntries = 20;
+ private long triggerTime = 1000;
+ private int timeLaps = 0;
+ private Queue- itemsFifo = null;
+ private DateUtils du = null;
+ private boolean active = false;
+ private boolean firstRun = true;
+
+ public RecorderItem(int maxEntries, int legendType, int timeLaps) {
+ this.maxEntries = maxEntries;
+ this.legendType = legendType;
+ this.timeLaps = timeLaps;
+ this.itemsFifo = new LinkedList<>();
+ this.du = new DateUtils();
+ this.triggerTime = System.currentTimeMillis();
+ this.active = false;
+ }
+
+ public int getMaxEntries() {
+ return maxEntries;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ if (active == false && itemsFifo != null && itemsFifo.size() > 0) {
+ itemsFifo.clear();
+ }
+ }
+
+ synchronized public ArrayList getAllItems() {
+ ArrayList items = new ArrayList<>();
+ if (active && itemsFifo != null) {
+ Object[] tempItems = itemsFifo.toArray();
+ if (tempItems != null) {
+ for (Object o : tempItems) {
+ if (o != null) {
+ ResultItem ri = new ResultItem(((Item) o).getX(), ((Item) o).getY(), ((Item) o).getTimeStamp(), ((Item) o).getDateTime());
+ items.add(ri);
+ }
+ }
+ }
+ }
+ return items;
+ }
+
+ synchronized public void clearItems() {
+ if (itemsFifo != null) {
+ itemsFifo.clear();
+ }
+ }
+
+ synchronized public void addItem(InsertItem temp, String parentId) {
+ if (active && checkValid()) {
+ if (itemsFifo != null) {
+ if (itemsFifo.size() >= maxEntries) {
+ itemsFifo.poll();
+ }
+ Item i = new Item(temp.getY());
+ itemsFifo.add(i);
+ logger.debug("RECORD <" + parentId + ">");
+ }
+ }
+ }
+
+ private boolean checkValid() {
+ boolean returnvalue = false;
+ if (System.currentTimeMillis() >= (triggerTime + timeLaps) || firstRun) {
+ returnvalue = true;
+ firstRun = false;
+ triggerTime = System.currentTimeMillis();
+ }
+ return returnvalue;
+ }
+
+ public static class InsertItem {
+
+ private Object[] y = null;
+
+ public InsertItem(Object[] y) {
+ this.y = y;
+ }
+
+ public Object[] getY() {
+ return y;
+ }
+ }
+
+ public static class ResultItem {
+
+ private Object[] y = null;
+ private String x = "";
+ private long timeStamp = 0;
+ private String dateTime = "";
+
+ public ResultItem(String x, Object[] y, long timeStamp, String dateTime) {
+ this.x = x;
+ this.y = y;
+ this.timeStamp = timeStamp;
+ this.dateTime = dateTime;
+ }
+
+ public String getX() {
+ return x;
+ }
+
+ public Object[] getY() {
+ return y;
+ }
+
+ public int getYDimension() {
+ return y.length;
+ }
+
+ public String getYasString() {
+ String value = "";
+ if (y != null && y.length > 0) {
+ int counter = 0;
+ for (Object o : y) {
+ if (counter > 0) {
+ value += "|";
+ }
+ String writeValue = "";
+ if (o instanceof Boolean) {
+ writeValue = ((Boolean) o == true ? "1" : "0");
+ } else {
+ writeValue = "" + o;
+ }
+ value += writeValue;
+ counter++;
+ }
+ }
+ return value;
+ }
+
+ public long getTimeStamp() {
+ return timeStamp;
+ }
+
+ public String getDateTime() {
+ return dateTime;
+ }
+ }
+
+ private class Item {
+
+ private Object[] y = null;
+ private String x = "";
+ private long timeStamp = 0;
+ private String dateTime = "";
+
+ public Item(Object[] y) {
+ this.y = y;
+ switch (legendType) {
+ case RecorderItem.LEGENDTYPE_DATE_HOUT_MINUTE: {
+ x = du.getHourMinuteString();
+ break;
+ }
+ default:
+ x = du.getHourMinuteString();
+ break;
+ }
+ this.timeStamp = System.currentTimeMillis();
+ this.dateTime = du.getTimeStampString();
+ }
+
+ public String getX() {
+ return x;
+ }
+
+ public Object[] getY() {
+ return y;
+ }
+
+ public long getTimeStamp() {
+ return timeStamp;
+ }
+
+ public String getDateTime() {
+ return dateTime;
+ }
+
+ }
+}
diff --git a/src/main/java/x/DeviceUtils/TransferObject.java b/src/main/java/x/DeviceUtils/TransferObject.java
new file mode 100755
index 0000000..0bd4936
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/TransferObject.java
@@ -0,0 +1,15 @@
+package x.DeviceUtils;
+
+public class TransferObject {
+
+ private boolean valueBoolean = false;
+
+ public TransferObject(boolean valueBoolean) {
+ this.valueBoolean = valueBoolean;
+ }
+
+ public boolean isValueBoolean() {
+ return valueBoolean;
+ }
+
+}
diff --git a/src/main/java/x/DeviceUtils/Types.java b/src/main/java/x/DeviceUtils/Types.java
new file mode 100755
index 0000000..f2ef27b
--- /dev/null
+++ b/src/main/java/x/DeviceUtils/Types.java
@@ -0,0 +1,28 @@
+package x.DeviceUtils;
+
+public class Types {
+
+ public static final int TYPE_INPUT = 1000;
+ public static final int TYPE_OUTPUT = 2000;
+ public static final int TYPE_TEMPERATURE = 3000;
+ public static final int TYPE_SCENE = 4000;
+ public static final int TYPE_TIME = 5000;
+ public static final int TYPE_DIMMERDEVICE = 6000;
+ public static final int TYPE_SENSOR = 7000;
+ public static final int TYPE_DHT22 = 8000;
+ public static final int TYPE_HEATINGPUMP = 9000;
+ public static final int TYPE_VENTILATION = 10000;
+ public static final int TYPE_SHADING = 11000;
+ public static final int TYPE_TOGGLE = 100;
+ public static final int TYPE_ON = 101;
+ public static final int TYPE_OFF = 102;
+ public static final int TYPE_BRIDGE = 103;
+ public static final int TYPE_DIMMER = 104;
+ public static final int TYPE_PROPERTIEINFO_DEFAULT = 0;
+ public static final int TYPE_PROPERTIEINFO_CHANGESOLLVALUE = 1;
+ public static final int TYPE_PROPERTIEINFO_TOGGLEACTIVATION = 2;
+ public static final int TYPE_PROPERTIEINFO_INFO = 3;
+ public static final int PROPERTYTYPE_DEFAULT = 0;
+ public static final int PROPERTYTYPE_TIME = 1;
+
+}
diff --git a/src/main/java/x/Devices/BaseDevice.java b/src/main/java/x/Devices/BaseDevice.java
new file mode 100644
index 0000000..56e6395
--- /dev/null
+++ b/src/main/java/x/Devices/BaseDevice.java
@@ -0,0 +1,141 @@
+package x.Devices;
+
+import akka.actor.AbstractActor;
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.actor.ReceiveTimeout;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import java.time.Duration;
+import java.util.Random;
+import x.DeviceUtils.PropertyChangedEvent;
+import x.DeviceUtils.RecorderItem;
+
+public class BaseDevice {
+
+ private static final ActorSystem ACTORSYSTEM = ActorSystem.create("homeautomationsystem");
+
+ private ActorRef deviceActor = null;
+
+ public static final int DEFAULTCYCLETIME = 50;
+ private int cycleTime = BaseDevice.DEFAULTCYCLETIME;
+
+ public int deviceHandle = 0;
+ public String displayName = "";
+ public String style = "";
+ public String categorie = "";
+ public String id = "";
+ public boolean dashboard = false;
+ protected RecorderItem ri = null;
+
+ public BaseDevice(int cycleTime) {
+ Random rN = new Random();
+ this.id = System.currentTimeMillis() + "_" + System.nanoTime() + "_" + rN.nextInt(10000);
+ this.cycleTime = cycleTime;
+ }
+
+ public BaseDevice(String id, int cycleTime) {
+ this.id = id;
+ this.cycleTime = cycleTime;
+ }
+
+ public void idleDevice() {
+ if (deviceActor == null) {
+ //deviceActor = system.actorOf(Props.create(DeviceActor.class, () -> new DeviceActor(id, cycleTime)).withDispatcher("default-dispatcher"), id);
+ deviceActor = ACTORSYSTEM.actorOf(Props.create(DeviceActor.class, () -> new DeviceActor(id, cycleTime)), id);
+ afterIdle();
+ }
+ }
+
+ public void afterIdle() {
+ }
+
+ public int getCycleTime() {
+ return this.cycleTime;
+ }
+
+ public RecorderItem getRecorderItem() {
+ return ri;
+ }
+
+ public void receiveMessage(Object message) {
+ }
+
+ public void receiveIdle() {
+ }
+
+ void propertyChangedEvent(PropertyChangedEvent event) {
+ try {
+ event.execute(this);
+ } catch (Exception ex) {
+ }
+ }
+
+ public boolean sendPropertyChangedEvent(PropertyChangedEvent pcv) {
+ boolean value = false;
+ try {
+ if (deviceActor != null) {
+ deviceActor.tell(pcv, null);
+ value = true;
+ }
+ } catch (Exception ex) {
+ value = false;
+ }
+ return value;
+ }
+
+ public boolean sendMessage(Object message) {
+ boolean value = false;
+ try {
+ if (deviceActor != null) {
+ deviceActor.tell(message, null);
+ value = true;
+ }
+ } catch (Exception ex) {
+ value = false;
+ }
+ return value;
+ }
+
+ private class DeviceActor extends AbstractActor {
+
+ final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
+ private int cycleTime = BaseDevice.DEFAULTCYCLETIME;
+ private String id = "";
+
+ public DeviceActor(String id, int cycleTime) {
+ this.id = id;
+ this.cycleTime = cycleTime;
+ getContext().setReceiveTimeout(Duration.ofMillis(cycleTime));
+ }
+
+ @Override
+ public void preStart() {
+ //log.info(id + " started with timeout " + cycleTime);
+ }
+
+ @Override
+ public void postStop() {
+ //log.info(id + " stopped");
+ }
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder()
+ .match(ReceiveTimeout.class, message -> {
+ receiveIdle();
+ })
+ .matchAny(message -> {
+ if (message instanceof PropertyChangedEvent) {
+ propertyChangedEvent((PropertyChangedEvent) message);
+ } else {
+ receiveMessage(message);
+ }
+ })
+ .build();
+ }
+
+ }
+
+}
diff --git a/src/main/java/x/Devices/DHT22Device.java b/src/main/java/x/Devices/DHT22Device.java
new file mode 100755
index 0000000..4f5a55d
--- /dev/null
+++ b/src/main/java/x/Devices/DHT22Device.java
@@ -0,0 +1,129 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.RecorderItem;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.ExecCommander;
+import x.utils.PropertyInfo;
+
+public class DHT22Device extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(DHT22Device.class);
+
+ @PropertyInfo(handle = 0, displayName = "Temp.", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 0, displayName = "Temp.")
+ public String temperature = "";
+
+ @PropertyInfo(handle = 1, displayName = "Hum.", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 1, displayName = "Hum.")
+ public String humanity = "";
+
+ @PropertyInfo(handle = 2, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true)
+ @DashboardInfo(handle = 2, displayName = "Status", stateful = true)
+ public boolean activ = true;
+
+ private String commandExec = "";
+ private String commandParams = "";
+ private boolean commandSetWritable = false;
+ private final int commandTimeout = 15000;
+ private final ExecCommander dht22ExecCommander = new ExecCommander();
+
+ public DHT22Device(int cycleTime) {
+ super(cycleTime);
+ this.ri = new RecorderItem(24, RecorderItem.LEGENDTYPE_DATE_HOUT_MINUTE, (1000 * 60 * 60));
+ }
+
+ public void addExec(String command, String params, boolean setWritable) {
+ this.commandExec = command;
+ this.commandParams = params;
+ this.commandSetWritable = setWritable;
+ }
+
+ private void setErrorInfo() {
+ temperature = "-";
+ humanity = "-";
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (activ) {
+ if (!commandExec.equals("")) {
+ try {
+ ExecCommander.RetVal value = dht22ExecCommander.executeCommand(commandExec, commandParams, commandSetWritable, commandTimeout);
+ if (value.isError() || value.isKilled()) {
+ setErrorInfo();
+ } else {
+ for (String s : value.getReturnvalues()) {
+ if (!s.equals("")) {
+ String[] values = s.split(";");
+ if (values.length == 2) {
+ temperature = values[0];
+ humanity = values[1];
+ logger.debug("DHT22 <" + id + "> => <" + temperature + "> <" + humanity + "> => STATE <" + activ + ">");
+ } else {
+ setErrorInfo();
+ }
+ } else {
+ setErrorInfo();
+ }
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ setErrorInfo();
+ }
+ } else {
+ setErrorInfo();
+ }
+ super.receiveIdle();
+ } else {
+ setErrorInfo();
+ }
+
+ if (ri != null) {
+ ri.setActive(activ);
+ Object data[] = {getTemperatureAsFloat(), getHumanityAsFloat()};
+ ri.addItem(new RecorderItem.InsertItem(data), id);
+ }
+ }
+
+ public float getTemperatureAsFloat() {
+ float result = (float) 0.0;
+ if (!temperature.equals("-")) {
+ String[] split = temperature.split(" ");
+ if (split.length == 2) {
+ try {
+ result = Float.parseFloat(split[0]);
+ } catch (Exception e) {
+ result = (float) 0.0;
+ }
+ }
+ }
+ return result;
+ }
+
+ public float getHumanityAsFloat() {
+ float result = (float) 0.0;
+ if (!humanity.equals("-")) {
+ String[] split = humanity.split(" ");
+ if (split.length == 2) {
+ try {
+ result = Float.parseFloat(split[0]);
+ } catch (Exception e) {
+ result = (float) 0.0;
+ }
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/src/main/java/x/Devices/DimmerDevice.java b/src/main/java/x/Devices/DimmerDevice.java
new file mode 100755
index 0000000..1ed5097
--- /dev/null
+++ b/src/main/java/x/Devices/DimmerDevice.java
@@ -0,0 +1,93 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.TransferObject;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class DimmerDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(DimmerDevice.class);
+ public static final int MAX_VALUE = 0x7FFF;
+ public static final int MIN_VALUE = 0;
+ private static final int DIRECTION_UP = 1;
+ private static final int DIRECTION_DOWN = 2;
+
+ @PropertyInfo(handle = 0, displayName = "Aktiv", type = Types.TYPE_PROPERTIEINFO_INFO, stateful = true)
+ public boolean activ = false;
+ @PropertyInfo(handle = 1, displayName = "Wert (%)", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 1, displayName = "Wert (%)")
+ public String valuePercent;
+ @PropertyInfo(handle = 2, displayName = "Verzögerung (ms)", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public int startDelay = 1250;
+ public int busAddress = 0;
+
+ private long startDelayTime = 0;
+ private boolean value = false;
+ private int CURRENTDIRECTION = DimmerDevice.DIRECTION_UP;
+ private int value2set = 1;
+ private int liveValue = 0;
+ private boolean stateChanged = true;
+
+ public DimmerDevice(int cycleTime) {
+ super(cycleTime);
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ if (message instanceof TransferObject) {
+ stateChanged = ((TransferObject) message).isValueBoolean();
+ } else {
+ value = (boolean) message;
+ if (value) {
+ startDelayTime = System.currentTimeMillis();
+ if (liveValue == DimmerDevice.MIN_VALUE) {
+ liveValue = value2set;
+ activ = true;
+ } else {
+ liveValue = DimmerDevice.MIN_VALUE;
+ activ = false;
+ }
+ stateChanged = true;
+ }
+ logger.debug("DIMMER <" + id + "> => <" + value + "><" + value2set + "><" + liveValue + "><" + CURRENTDIRECTION + ">");
+ }
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (value && (System.currentTimeMillis() - startDelayTime) >= startDelay) {
+ if (value2set >= DimmerDevice.MAX_VALUE) {
+ CURRENTDIRECTION = DimmerDevice.DIRECTION_DOWN;
+ } else if (value2set <= DimmerDevice.MIN_VALUE) {
+ CURRENTDIRECTION = DimmerDevice.DIRECTION_UP;
+ }
+ if (CURRENTDIRECTION == DimmerDevice.DIRECTION_UP) {
+ value2set += 250;
+ } else {
+ value2set -= 250;
+ }
+ liveValue = value2set;
+ stateChanged = true;
+ activ = true;
+ }
+ valuePercent = ((int) ((value2set * 100.0f) / DimmerDevice.MAX_VALUE)) + "";
+ super.receiveIdle();
+ }
+
+ public boolean isValue() {
+ return value;
+ }
+
+ public int getLiveValue() {
+ return liveValue;
+ }
+
+ public boolean isStateChanged() {
+ return stateChanged;
+ }
+
+}
diff --git a/src/main/java/x/Devices/HeatingPumpDevice.java b/src/main/java/x/Devices/HeatingPumpDevice.java
new file mode 100755
index 0000000..a15d95a
--- /dev/null
+++ b/src/main/java/x/Devices/HeatingPumpDevice.java
@@ -0,0 +1,259 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DateUtils;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.RecorderItem;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class HeatingPumpDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(HeatingPumpDevice.class);
+ private static final int WATERINDEX = 0;
+ private static final int PUFFERINDEX = 1;
+ private static final int FLOWINDEX = 2;
+ private static final int PUMPINDEX = 0;
+ private static final int FLOWWARMINDEX = 1;
+ private static final int FLOWCOLDINDEX = 2;
+ private static final int FLOWSHUTDOWNTIME = 180000;
+ private static final int FLOWHYSTERESE = 20;
+ private static final int FLOWSECURITSHUTDOWN = 490;
+ // 140s komplettlauf => 2% = 2,8s
+ private static final int FLOWTHREADWAIT = 2800;
+
+ @PropertyInfo(handle = 0, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true, visibleOnREST = true)
+ @DashboardInfo(handle = 0, displayName = "Status", stateful = true)
+ public boolean activ = false;
+
+ @PropertyInfo(handle = 1, displayName = "Abh. Sens.Temp.", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String concurrentSensorTemperatureInfo = "-";
+
+ @PropertyInfo(handle = 2, displayName = "Abh. Outputs", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String outputsInfo = "-";
+
+ @PropertyInfo(handle = 3, editable = true, displayName = "Start-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30, visibleOnREST = true)
+ public String timeStart;
+
+ @PropertyInfo(handle = 4, editable = true, displayName = "Stop-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30, visibleOnREST = true)
+ public String timeStop;
+
+ @PropertyInfo(handle = 5, displayName = "Running", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 1, displayName = "Running", stateful = true)
+ public boolean runningState = false;
+
+ @PropertyInfo(handle = 6, editable = true, displayName = "Force Activ", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true, visibleOnREST = true)
+ @DashboardInfo(handle = 2, displayName = "Force Activ", stateful = true)
+ public boolean forceActiv = false;
+
+ String[] outputs = null;
+ String[] concurrentTemperatureIds = null;
+ private DateUtils du = null;
+
+ public HeatingPumpDevice(int cycleTime) {
+ super(cycleTime);
+ this.du = new DateUtils();
+ this.ri = new RecorderItem(24, RecorderItem.LEGENDTYPE_DATE_HOUT_MINUTE, (1000 * 60 * 60));
+ }
+
+ public void addOutputs(String outputs) {
+ this.outputs = outputs.split(";");
+ }
+
+ public void addConcurrentTemperatureIds(String concurrentTemperatureIds) {
+ this.concurrentTemperatureIds = concurrentTemperatureIds.split(";");
+ }
+
+ @Override
+ public void afterIdle() {
+ if (concurrentTemperatureIds != null) {
+ StringBuilder namedconcurrentSensorTemperatureIds = new StringBuilder();
+ for (String tId : concurrentTemperatureIds) {
+ if (!tId.equals(id)) {
+ SensorTemperatureDevice td = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(tId);
+ if (td != null) {
+ namedconcurrentSensorTemperatureIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ concurrentSensorTemperatureInfo = namedconcurrentSensorTemperatureIds.toString();
+ }
+ if (outputs != null) {
+ StringBuilder namedOutputIds = new StringBuilder();
+ for (String tId : outputs) {
+ if (!tId.equals(id)) {
+ OutputDevice td = DeviceListUtils.getInstance().getOutputById(tId);
+ if (td != null) {
+ namedOutputIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ outputsInfo = namedOutputIds.toString();
+ }
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (activ && checkAnyTemperatureDevicesIsActive()) {
+ boolean outputState = false;
+ boolean checkWaterCondition = checkTemperatureCondition(HeatingPumpDevice.WATERINDEX);
+ boolean checkPufferCondition = checkTemperatureCondition(HeatingPumpDevice.PUFFERINDEX);
+ if (forceActiv) {
+ outputState = checkPufferCondition;
+ } else {
+ if (checkTime()) {
+ outputState = checkPufferCondition;
+ } else {
+ outputState = (checkWaterCondition && checkPufferCondition);
+ }
+ }
+ if (outputState) {
+ outputState = checkFlowTemperatureForPumpSecurityShutdown();
+ }
+ setOutput(HeatingPumpDevice.PUMPINDEX, outputState);
+ setFlowTemperature(outputState);
+ runningState = outputState;
+ String[] dateString = du.getCompleteDateString();
+ logger.debug("HEATINGPUMP <" + id + "> => (" + dateString[0] + "," + dateString[1] + ") => STATE <" + activ + "> WATERCHECK <" + checkWaterCondition + "> PUFFERCHECK <" + checkPufferCondition + "> OUTPUTSTATE <" + outputState + "> RUNNINGSTATE <" + runningState + ">" + " => FORCE <" + forceActiv + ">");
+ } else {
+ setOutput(HeatingPumpDevice.PUMPINDEX, false);
+ setFlowTemperature(false);
+ runningState = false;
+ }
+ if (ri != null) {
+ ri.setActive(activ);
+ Object data[] = {runningState};
+ ri.addItem(new RecorderItem.InsertItem(data), id);
+ }
+ super.receiveIdle();
+ }
+
+ private void setOutput(int index, boolean state) {
+ if (outputs != null) {
+ if (outputs.length >= (index + 1)) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(outputs[index]);
+ if (o != null) {
+ if (o.isValue() != state) {
+ o.sendMessage(state);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean checkTime() {
+ return du.checkStatus(timeStart, timeStop);
+ }
+
+ private boolean checkTemperatureCondition(int index) {
+ boolean state = false;
+ if (concurrentTemperatureIds != null) {
+ if (concurrentTemperatureIds.length >= (index + 1)) {
+ SensorTemperatureDevice o = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(concurrentTemperatureIds[index]);
+ if (o != null) {
+ state = ((o.getValueAsInt() - o.getSollValueAsInt()) > 0);
+ }
+ }
+ }
+ return state;
+ }
+
+ private boolean checkFlowTemperatureForPumpSecurityShutdown() {
+ boolean state = false;
+ if (concurrentTemperatureIds != null) {
+ if (concurrentTemperatureIds.length >= (HeatingPumpDevice.FLOWINDEX + 1)) {
+ SensorTemperatureDevice o = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(concurrentTemperatureIds[HeatingPumpDevice.FLOWINDEX]);
+ if (o != null) {
+ state = ((HeatingPumpDevice.FLOWSECURITSHUTDOWN - o.getValueAsInt()) > 0);
+ }
+ }
+ }
+ return state;
+ }
+
+ private void setFlowTemperature(boolean statePump) {
+ boolean triggered = false;
+ if (statePump) {
+ if (concurrentTemperatureIds != null) {
+ if (concurrentTemperatureIds.length >= (HeatingPumpDevice.FLOWINDEX + 1)) {
+ SensorTemperatureDevice o = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(concurrentTemperatureIds[HeatingPumpDevice.FLOWINDEX]);
+ if (o != null) {
+ resetFlowShutdown();
+ triggered = true;
+ int valueToCompare = o.getValueAsInt() - o.getSollValueAsInt();
+ if (valueToCompare > 0) {
+ if (valueToCompare >= HeatingPumpDevice.FLOWHYSTERESE) {
+ setFlowTemperatureMixer(false);
+ }
+ } else if (valueToCompare < 0) {
+ valueToCompare = valueToCompare * -1;
+ if (valueToCompare >= HeatingPumpDevice.FLOWHYSTERESE) {
+ setFlowTemperatureMixer(true);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (triggered == false) {
+ setFlowShutdown();
+ }
+ }
+
+ private void setFlowTemperatureMixer(boolean state) {
+ if (state) {
+ setOutput(HeatingPumpDevice.FLOWCOLDINDEX, false);
+ setOutput(HeatingPumpDevice.FLOWWARMINDEX, true);
+ try {
+ Thread.sleep(HeatingPumpDevice.FLOWTHREADWAIT);
+ } catch (InterruptedException ex) {
+ }
+ setOutput(HeatingPumpDevice.FLOWWARMINDEX, false);
+ } else {
+ setOutput(HeatingPumpDevice.FLOWWARMINDEX, false);
+ setOutput(HeatingPumpDevice.FLOWCOLDINDEX, true);
+ try {
+ Thread.sleep(HeatingPumpDevice.FLOWTHREADWAIT);
+ } catch (InterruptedException ex) {
+ }
+ setOutput(HeatingPumpDevice.FLOWCOLDINDEX, false);
+ }
+
+ }
+
+ private long shutdownFlowTemperatureStart = 0;
+
+ public void setFlowShutdown() {
+ if (shutdownFlowTemperatureStart == 0) {
+ setOutput(HeatingPumpDevice.FLOWWARMINDEX, false);
+ setOutput(HeatingPumpDevice.FLOWCOLDINDEX, true);
+ shutdownFlowTemperatureStart = System.currentTimeMillis();
+ }
+ if ((shutdownFlowTemperatureStart + HeatingPumpDevice.FLOWSHUTDOWNTIME) <= System.currentTimeMillis()) {
+ setOutput(HeatingPumpDevice.FLOWCOLDINDEX, false);
+ }
+ }
+
+ private void resetFlowShutdown() {
+ if (shutdownFlowTemperatureStart != 0) {
+ setOutput(HeatingPumpDevice.FLOWCOLDINDEX, false);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ }
+ }
+ shutdownFlowTemperatureStart = 0;
+ }
+
+ private boolean checkAnyTemperatureDevicesIsActive() {
+ return DeviceListUtils.getInstance().anyTemperatureDeviceIsActive();
+ }
+
+}
diff --git a/src/main/java/x/Devices/InputDevice.java b/src/main/java/x/Devices/InputDevice.java
new file mode 100755
index 0000000..ff5b49a
--- /dev/null
+++ b/src/main/java/x/Devices/InputDevice.java
@@ -0,0 +1,68 @@
+package x.Devices;
+
+import java.util.ArrayList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.InputParameter;
+import x.DeviceEffects.BaseEffect;
+
+public class InputDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(InputDevice.class);
+ private boolean value = false;
+ private long startTime = 0;
+ private boolean lockedByVisu = false;
+ private long removeTimeLockedByVisu = 0;
+ public ArrayList inputParams = new ArrayList<>();
+ public int busAddress = 0;
+
+ public InputDevice(int cycleTime) {
+ super(cycleTime);
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ value = (boolean) message;
+ logger.debug("INPUT <" + id + "> => <" + value + ">");
+ if (value) {
+ startTime = System.currentTimeMillis();
+ for (InputParameter param : inputParams) {
+ ((BaseEffect) param.effect).resetEffect();
+ ((BaseEffect) param.effect).initEffect(startTime);
+ ((BaseEffect) param.effect).trigger(value);
+ }
+ }
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ for (InputParameter param : inputParams) {
+ ((BaseEffect) param.effect).trigger(value);
+ }
+ if (isLockedByVisu()) {
+ if (System.currentTimeMillis() > removeTimeLockedByVisu) {
+ setLockedByVisu(false);
+ }
+ }
+ super.receiveIdle();
+ }
+
+ synchronized public boolean isLockedByVisu() {
+ return lockedByVisu;
+ }
+
+ synchronized public void setLockedByVisu(boolean lockedByVisu) {
+ this.lockedByVisu = lockedByVisu;
+ if (lockedByVisu) {
+ removeTimeLockedByVisu = 90000 + System.currentTimeMillis();
+ } else {
+ removeTimeLockedByVisu = 0;
+ }
+ }
+
+ public boolean isValue() {
+ return value;
+ }
+
+}
diff --git a/src/main/java/x/Devices/OutputDevice.java b/src/main/java/x/Devices/OutputDevice.java
new file mode 100755
index 0000000..5d89eb6
--- /dev/null
+++ b/src/main/java/x/Devices/OutputDevice.java
@@ -0,0 +1,95 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DateUtils;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.Types;
+import x.MessageHandling.MessageHandler;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+import x.websocket.model.AsyncStatusMessage;
+
+public class OutputDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(OutputDevice.class);
+
+ @PropertyInfo(handle = 0, editable = true, displayName = "Start-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 60)
+ public String timeStart = "-";
+
+ @PropertyInfo(handle = 1, editable = true, displayName = "Stop-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 60)
+ public String timeStop = "-";
+
+ @PropertyInfo(handle = 2, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 0, displayName = "Status", stateful = true)
+ public boolean valueVisu = false;
+
+ private DateUtils du = null;
+ private boolean value = false;
+ public int busAddress = 0;
+ String[] concurrentOutputs = null;
+
+ public OutputDevice(int cycleTime) {
+ super(cycleTime);
+ this.du = new DateUtils();
+ }
+
+ public void setTimeSettings(String timeStart, String timeStop) {
+ this.timeStart = timeStart;
+ this.timeStop = timeStop;
+ }
+
+ public void addConcurrentOutputs(String concurrentOutputs) {
+ if (!concurrentOutputs.equals("")) {
+ this.concurrentOutputs = concurrentOutputs.split(";");
+ }
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ if (concurrentOutputs != null && concurrentOutputs.length > 0 && ((boolean) message) == true) {
+ boolean valid = true;
+ for (String output : concurrentOutputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o != null && o.isValue()) {
+ valid = false;
+ break;
+ }
+ }
+ value = checkTimeSettings(valid);
+ } else {
+ value = checkTimeSettings((boolean) message);
+ }
+
+ valueVisu = value;
+
+ logger.debug("OUTPUT <" + id + "> => <" + value + ">");
+
+ AsyncStatusMessage asm = new AsyncStatusMessage();
+ asm.setId("" + deviceHandle);
+ asm.setValue((value == true ? "1" : "0"));
+ asm.setKind(AsyncStatusMessage.SET);
+ MessageHandler.getInstance().messageToWebSocketClients(asm);
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ super.receiveIdle();
+ }
+
+ public boolean isValue() {
+ return value;
+ }
+
+ private boolean checkTimeSettings(boolean currentStateValue) {
+ boolean returnValue = currentStateValue;
+ if (currentStateValue == true && du != null && !timeStart.equals("-") && !timeStop.equals("-")) {
+ returnValue = du.checkStatus(timeStart, timeStop);
+ String[] dateString = du.getCompleteDateString();
+ logger.debug("OUTPUT TIMECHECK <" + id + "> => <" + returnValue + "><" + dateString[0] + "><" + dateString[1] + ">");
+ }
+ return returnValue;
+ }
+
+}
diff --git a/src/main/java/x/Devices/RemoteDevice.java b/src/main/java/x/Devices/RemoteDevice.java
new file mode 100644
index 0000000..bd40eb1
--- /dev/null
+++ b/src/main/java/x/Devices/RemoteDevice.java
@@ -0,0 +1,45 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.utils.RemoteAccessRequest;
+
+public class RemoteDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(RemoteDevice.class);
+ RemoteAccessRequest request = null;
+ public boolean activ = false;
+ private int retryCounter = 0;
+
+ public RemoteDevice(boolean activ, String url, int cycleTime, String jwt) {
+ super(cycleTime);
+ this.activ = activ;
+ this.request = new RemoteAccessRequest(url, jwt);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (request != null && activ == true) {
+ try {
+ boolean response = request.execute();
+ if (response == false) {
+ retryCounter++;
+ if (retryCounter >= 50) {
+ activ = false;
+ logger.info("Deaktivating RemoteAccess in response!");
+ }
+ } else {
+ retryCounter = 0;
+ logger.debug("REMOTE " + response);
+ }
+ } catch (Exception ex) {
+ retryCounter++;
+ if (retryCounter >= 50) {
+ activ = false;
+ logger.info("Deaktivating RemoteAccess in Exception!");
+ logger.error(ex.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/Devices/RetainDevice.java b/src/main/java/x/Devices/RetainDevice.java
new file mode 100644
index 0000000..85198ab
--- /dev/null
+++ b/src/main/java/x/Devices/RetainDevice.java
@@ -0,0 +1,51 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.retain.RetainProcess;
+
+public class RetainDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(RetainDevice.class);
+
+ public boolean activ = true;
+ private int retryCounter = 0;
+ private RetainProcess retainProcess;
+ private static final int CYCLETIME = (1000 * 60 * 60);
+
+ public RetainDevice(boolean active, RetainProcess retainProcess) {
+ super(CYCLETIME);
+ this.activ = active;
+ this.retainProcess = retainProcess;
+ this.preIdle();
+ }
+
+ private void preIdle() {
+ if (retainProcess != null) {
+ try {
+ retainProcess.runonce();
+ } catch (Exception ex) {
+ activ = false;
+ logger.error(ex.getMessage());
+ }
+ }
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (retainProcess != null && activ == true) {
+ try {
+ retainProcess.execute();
+ retryCounter = 0;
+ logger.debug("REMOTE Request ok");
+ } catch (Exception ex) {
+ retryCounter++;
+ if (retryCounter >= 5) {
+ activ = false;
+ logger.error("Deaktivating RetainDevice in Exception!");
+ logger.error(ex.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/Devices/SceneDevice.java b/src/main/java/x/Devices/SceneDevice.java
new file mode 100755
index 0000000..f39862c
--- /dev/null
+++ b/src/main/java/x/Devices/SceneDevice.java
@@ -0,0 +1,50 @@
+package x.Devices;
+
+import java.util.ArrayList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.InputParameter;
+import x.DeviceEffects.BaseEffect;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class SceneDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(SceneDevice.class);
+ private boolean value = false;
+ private long startTime = 0;
+ public ArrayList inputParams = new ArrayList<>();
+
+ @PropertyInfo(handle = 0, displayName = "Sprachkennung", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 0, displayName = "Scene", editable = true)
+ public String speechIdent = "";
+
+ public SceneDevice(int cycleTime) {
+ super(cycleTime);
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ value = (boolean) message;
+ logger.debug("SCENE <" + id + "> => <" + value + ">");
+ if (value) {
+ startTime = System.currentTimeMillis();
+ for (InputParameter param : inputParams) {
+ ((BaseEffect) param.effect).resetEffect();
+ ((BaseEffect) param.effect).initEffect(startTime);
+ ((BaseEffect) param.effect).trigger(value);
+ }
+ }
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ for (InputParameter param : inputParams) {
+ ((BaseEffect) param.effect).trigger(value);
+ }
+ super.receiveIdle();
+ }
+}
diff --git a/src/main/java/x/Devices/SensorTemperatureDevice.java b/src/main/java/x/Devices/SensorTemperatureDevice.java
new file mode 100755
index 0000000..206a4db
--- /dev/null
+++ b/src/main/java/x/Devices/SensorTemperatureDevice.java
@@ -0,0 +1,85 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.RecorderItem;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class SensorTemperatureDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(SensorTemperatureDevice.class);
+
+ public int busAddress = 0;
+
+ @PropertyInfo(handle = 0, displayName = "Temp. (°C)", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 0, displayName = "Temp. (°C)")
+ public int valueVisu = 1000000;
+ private int value = 1000000;
+
+ @PropertyInfo(handle = 1, editable = true, displayName = "Sollwert ändern", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, visibleOnREST = true)
+ public int sollvalue = 0;
+
+ @PropertyInfo(handle = 2, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true)
+ @DashboardInfo(handle = 1, displayName = "Status", stateful = true)
+ public boolean activ = false;
+
+ private String[] concurrentTemperatureIds = null;
+ @PropertyInfo(handle = 3, displayName = "Valid", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 2, displayName = "Valid", stateful = true)
+ public boolean status = true;
+
+ public SensorTemperatureDevice(int cycleTime) {
+ super(cycleTime);
+ this.ri = new RecorderItem(24, RecorderItem.LEGENDTYPE_DATE_HOUT_MINUTE, (1000 * 60 * 60));
+ }
+
+ public void addConcurrentTemperatureIds(String concurrentTemperatureIds) {
+ this.concurrentTemperatureIds = concurrentTemperatureIds.split(";");
+ }
+
+ public String[] getConcurrentTemperatureIds() {
+ return concurrentTemperatureIds;
+ }
+
+ public boolean getStatus() {
+ return status;
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ value = (int) ((short) ((int) message)); // Zweierkomplement => 65535 -> -1
+ status = (value >= sollvalue);
+ logger.debug("SENSOR-TEMPERATURE <" + id + "> => <" + value + ";" + status + "> (" + sollvalue + ")> => STATE <" + activ + ">");
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ valueVisu = value;
+ if (ri != null) {
+ ri.setActive(activ);
+ Object data[] = {getValueAsFloat(), getSollValueAsFloat()};
+ ri.addItem(new RecorderItem.InsertItem(data), id);
+ }
+ super.receiveIdle();
+ }
+
+ public float getValueAsFloat() {
+ return (float) (value / 10.0);
+ }
+
+ public float getSollValueAsFloat() {
+ return (float) (sollvalue / 10.0);
+ }
+
+ public int getValueAsInt() {
+ return value;
+ }
+
+ public int getSollValueAsInt() {
+ return sollvalue;
+ }
+
+}
diff --git a/src/main/java/x/Devices/ShadingDevice.java b/src/main/java/x/Devices/ShadingDevice.java
new file mode 100644
index 0000000..05f5adb
--- /dev/null
+++ b/src/main/java/x/Devices/ShadingDevice.java
@@ -0,0 +1,158 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DateUtils;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class ShadingDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(ShadingDevice.class);
+
+ @PropertyInfo(handle = 0, editable = true, displayName = "Start-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30)
+ public String timeStart;
+
+ @PropertyInfo(handle = 1, editable = true, displayName = "Stop-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30)
+ public String timeStop;
+
+ @PropertyInfo(handle = 2, displayName = "Abh. Sens.Temp.", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String concurrentSensorTemperatureInfo = "-";
+
+ @PropertyInfo(handle = 3, displayName = "Abh. Outputs", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String outputsInfo = "-";
+
+ @PropertyInfo(handle = 4, editable = true, displayName = "Sollwert Temp. ändern", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, visibleOnREST = true)
+ public int sollvalueTemp = 0;
+
+ @PropertyInfo(handle = 5, editable = true, displayName = "Dauer activ", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, visibleOnREST = true)
+ public int durationActive = 5;
+
+ @PropertyInfo(handle = 6, editable = true, displayName = "Dauer Nachlauf aktiv", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, visibleOnREST = true)
+ public int durationPostActive = 100;
+
+ @PropertyInfo(handle = 7, editable = true, displayName = "Dauer reactiv", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, visibleOnREST = true)
+ public int durationReactive = 5;
+
+ @PropertyInfo(handle = 8, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true)
+ @DashboardInfo(handle = 0, displayName = "Status", stateful = true)
+ public boolean activ = false;
+
+ private DateUtils du = null;
+ private boolean started = false;
+ private boolean idle = true;
+ String[] outputs = null;
+ String[] concurrentTemperatureIds = null;
+
+ public ShadingDevice(int cycleTime) {
+ super(cycleTime);
+ this.du = new DateUtils();
+ }
+
+ public void addOutputs(String outputs) {
+ this.outputs = outputs.split(";");
+ }
+
+ public void addConcurrentTemperatureIds(String concurrentTemperatureIds) {
+ this.concurrentTemperatureIds = concurrentTemperatureIds.split(";");
+ }
+
+ @Override
+ public void afterIdle() {
+ if (concurrentTemperatureIds != null) {
+ StringBuilder namedconcurrentSensorTemperatureIds = new StringBuilder();
+ for (String tId : concurrentTemperatureIds) {
+ if (!tId.equals(id)) {
+ SensorTemperatureDevice td = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(tId);
+ if (td != null) {
+ namedconcurrentSensorTemperatureIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ concurrentSensorTemperatureInfo = namedconcurrentSensorTemperatureIds.toString();
+ }
+ if (outputs != null) {
+ StringBuilder namedOutputIds = new StringBuilder();
+ for (String tId : outputs) {
+ if (!tId.equals(id)) {
+ OutputDevice td = DeviceListUtils.getInstance().getOutputById(tId);
+ if (td != null) {
+ namedOutputIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ outputsInfo = namedOutputIds.toString();
+ }
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (activ) {
+ if (this.outputs != null && this.outputs.length == 2 && idle == true) {
+ boolean condition = false;
+ if (du.checkStatus(timeStart, timeStop) && checkTemperatureCondition()) {
+ condition = true;
+ }
+ if (condition && started == false) {
+ String[] dateString = du.getCompleteDateString();
+ logger.debug("SHADING <" + id + "> => (" + dateString[0] + "," + dateString[1] + ") => STATE ON");
+ setOutput(0, durationActive * 1000, durationPostActive);
+ started = true;
+ } else if (condition == false && started) {
+ String[] dateString = du.getCompleteDateString();
+ logger.debug("SHADING <" + id + "> => (" + dateString[0] + "," + dateString[1] + ") => STATE OFF");
+ setOutput(1, durationReactive * 1000, 0);
+ started = false;
+ }
+ }
+ }
+ super.receiveIdle();
+ }
+
+ private void setOutput(int index, int duration, int postduration) {
+ if (outputs != null && duration > 0) {
+ idle = false;
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(outputs[index]);
+ try {
+ if (o.isValue() != true) {
+ o.sendMessage(true);
+ }
+ Thread.sleep(duration);
+ o.sendMessage(false);
+ if (postduration > 0) {
+ Thread.sleep(3000);
+ if (o.isValue() != true) {
+ o.sendMessage(true);
+ }
+ Thread.sleep(postduration);
+ o.sendMessage(false);
+ }
+ } catch (Exception ex) {
+ if (o.isValue() == true) {
+ o.sendMessage(false);
+ }
+ }
+ idle = true;
+ }
+ }
+
+ private boolean checkTemperatureCondition() {
+ boolean state = false;
+ if (concurrentTemperatureIds != null) {
+ if (concurrentTemperatureIds.length >= 1) {
+ SensorTemperatureDevice o = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(concurrentTemperatureIds[0]);
+ if (o != null) {
+ state = ((o.getValueAsInt() - sollvalueTemp) > 0);
+ }
+ }
+ }
+ return state;
+ }
+}
diff --git a/src/main/java/x/Devices/TemperatureDevice.java b/src/main/java/x/Devices/TemperatureDevice.java
new file mode 100755
index 0000000..1ed95ba
--- /dev/null
+++ b/src/main/java/x/Devices/TemperatureDevice.java
@@ -0,0 +1,204 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.RecorderItem;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class TemperatureDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(TemperatureDevice.class);
+
+ @PropertyInfo(handle = 0, editable = true, displayName = "Sollwert ändern", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, visibleOnREST = true)
+ public int sollvalue = 0;
+
+ @PropertyInfo(handle = 1, displayName = "Aktuelle Temp. (°C)", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 0, displayName = "Temp. (°C)")
+ public int valueVisu = 1000000;
+
+ @PropertyInfo(handle = 2, displayName = "Schaltschwelle unten (°C)", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public int uHysterese = 0;
+
+ @PropertyInfo(handle = 3, displayName = "Schaltschwelle oben (°C)", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public int oHysterese = 0;
+
+ @PropertyInfo(handle = 4, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true, visibleOnREST = true)
+ @DashboardInfo(handle = 1, displayName = "Status", stateful = true)
+ public boolean activ = false;
+
+ @PropertyInfo(handle = 5, displayName = "Enabled", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 2, displayName = "Enabled", stateful = true)
+ public boolean enabled = true;
+
+ @PropertyInfo(handle = 6, displayName = "Abh. Temp.", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String concurrentTemperatureInfo = "-";
+ @PropertyInfo(handle = 7, editable = true, displayName = "Abh. Temp. Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true)
+ public boolean concurrentTemperatureActive = true;
+
+ public int busAddress = 0;
+ String[] outputs = null;
+ String[] concurrentTemperatureIds = null;
+ private int value = 1000000;
+ private boolean outputState = false;
+
+ public TemperatureDevice(int cycleTime) {
+ super(cycleTime);
+ this.ri = new RecorderItem(24, RecorderItem.LEGENDTYPE_DATE_HOUT_MINUTE, (1000 * 60 * 60));
+ }
+
+ public void addOutputs(String outputs) {
+ this.outputs = outputs.split(";");
+ }
+
+ public void addConcurrentTemperatureIds(String concurrentTemperatureIds) {
+ this.concurrentTemperatureIds = concurrentTemperatureIds.split(";");
+ }
+
+ @Override
+ public void afterIdle() {
+ if (concurrentTemperatureIds != null) {
+ StringBuilder namedconcurrentTemperatureIds = new StringBuilder();
+ for (String tId : concurrentTemperatureIds) {
+ if (!tId.equals(id)) {
+ TemperatureDevice td = DeviceListUtils.getInstance().getTemperatureDeviceById(tId);
+ if (td != null) {
+ namedconcurrentTemperatureIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ concurrentTemperatureInfo = namedconcurrentTemperatureIds.toString();
+ }
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ value = (int) ((short) ((int) message)); // Zweierkomplement => 65535 -> -1
+ logger.debug("TEMPERATURE <" + id + "> => <" + value + "> (" + sollvalue + "," + oHysterese + "," + uHysterese + ") => STATE <" + activ + ">");
+ if (activ) {
+ if (value != 1000000) {
+ enabled = checkConcurrentTemperatures();
+ if (enabled == true) {
+ enabled = checkSensorDevice();
+ }
+ if (enabled == true) {
+ int valueToCompare = value - sollvalue;
+ if (valueToCompare > 0) {
+ if (valueToCompare >= oHysterese) {
+ logger.debug("TEMPERATURE <" + id + "> => ");
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != false) {
+ o.sendMessage(false);
+ }
+ }
+ outputState = false;
+ }
+ } else if (valueToCompare < 0) {
+ valueToCompare = valueToCompare * -1;
+ if (valueToCompare >= uHysterese) {
+ logger.debug("TEMPERATURE <" + id + "> => ");
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != true) {
+ o.sendMessage(true);
+ }
+ }
+ outputState = true;
+ }
+ }
+ } else {
+ logger.debug("TEMPERATURE <" + id + "> => ");
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != false) {
+ o.sendMessage(false);
+ }
+ }
+ outputState = false;
+ }
+ }
+ super.receiveMessage(message);
+ }
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (activ == false) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != false) {
+ o.sendMessage(false);
+ }
+ }
+ outputState = false;
+ }
+
+ if (ri != null) {
+ ri.setActive(activ);
+ Object data[] = {getValueAsFloat(), outputState, getSollValueAsFloat()};
+ ri.addItem(new RecorderItem.InsertItem(data), id);
+ }
+
+ valueVisu = value;
+ super.receiveIdle();
+ }
+
+ public float getValueAsFloat() {
+ return (float) (value / 10.0);
+ }
+
+ public float getSollValueAsFloat() {
+ return (float) (sollvalue / 10.0);
+ }
+
+ private boolean checkConcurrentTemperatures() {
+ boolean enableDevice = true;
+ if (concurrentTemperatureIds != null && concurrentTemperatureActive) {
+ for (String tId : concurrentTemperatureIds) {
+ if (!tId.equals(id)) {
+ TemperatureDevice td = DeviceListUtils.getInstance().getTemperatureDeviceById(tId);
+ if (td != null) {
+ int triggerTemperatureLevel = td.sollvalue - td.uHysterese;
+ if (td.value < triggerTemperatureLevel) {
+ enableDevice = false;
+ logger.debug("TEMPERATURE <" + id + "> disabled because TEMPERATURE <" + td.id + "> to low");
+ break;
+ }
+ }
+ }
+ }
+ }
+ return enableDevice;
+ }
+
+ private boolean checkSensorDevice() {
+ boolean enableDevice = true;
+ for (Object deviceHandleList : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandleList instanceof SensorTemperatureDevice) {
+ if (((SensorTemperatureDevice) deviceHandleList).activ == true) {
+ String[] concurrentIds = ((SensorTemperatureDevice) deviceHandleList).getConcurrentTemperatureIds();
+ if (concurrentIds != null) {
+ for (String cId : concurrentIds) {
+ if (cId.equals(id)) {
+ if (((SensorTemperatureDevice) deviceHandleList).getStatus() == false) {
+ enableDevice = false;
+ logger.debug("TEMPERATURE <" + id + "> disabled because SENSOR <" + ((SensorTemperatureDevice) deviceHandleList).id + "> status");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return enableDevice;
+ }
+
+ public boolean isOutputState() {
+ return outputState;
+ }
+
+}
diff --git a/src/main/java/x/Devices/TimeDevice.java b/src/main/java/x/Devices/TimeDevice.java
new file mode 100755
index 0000000..4d08691
--- /dev/null
+++ b/src/main/java/x/Devices/TimeDevice.java
@@ -0,0 +1,71 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DateUtils;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class TimeDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(TimeDevice.class);
+
+ @PropertyInfo(handle = 0, editable = true, displayName = "Start-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30)
+ public String timeStart;
+ @PropertyInfo(handle = 1, editable = true, displayName = "Stop-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30)
+ public String timeStop;
+ @PropertyInfo(handle = 2, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true)
+ @DashboardInfo(handle = 0, displayName = "Status", stateful = true)
+ public boolean activ = false;
+
+ private DateUtils du = null;
+ private boolean started = false;
+ private boolean timevalue = false;
+ String[] outputs = null;
+
+ public TimeDevice(int cycleTime) {
+ super(cycleTime);
+ this.du = new DateUtils();
+ }
+
+ public void addOutputs(String outputs) {
+ this.outputs = outputs.split(";");
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (activ) {
+ timevalue = du.checkStatus(timeStart, timeStop);
+ if (timevalue && started == false) {
+ String[] dateString = du.getCompleteDateString();
+ logger.debug("TIME <" + id + "> => (" + dateString[0] + "," + dateString[1] + ") => STATE <" + activ + ">");
+ setOutputs(true);
+ started = true;
+ } else if (timevalue == false && started) {
+ String[] dateString = du.getCompleteDateString();
+ logger.debug("TIME <" + id + "> => (" + dateString[0] + "," + dateString[1] + ") => STATE <" + activ + ">");
+ setOutputs(false);
+ started = false;
+ }
+ }
+ super.receiveIdle();
+ }
+
+ private void setOutputs(boolean state) {
+ if (outputs != null) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != state) {
+ o.sendMessage(state);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/Devices/VentilationDevice.java b/src/main/java/x/Devices/VentilationDevice.java
new file mode 100644
index 0000000..cbd0f9e
--- /dev/null
+++ b/src/main/java/x/Devices/VentilationDevice.java
@@ -0,0 +1,153 @@
+package x.Devices;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import x.DeviceUtils.DateUtils;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.RecorderItem;
+import x.DeviceUtils.Types;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+
+public class VentilationDevice extends BaseDevice {
+
+ private final Logger logger = LoggerFactory.getLogger(VentilationDevice.class);
+
+ @PropertyInfo(handle = 0, editable = true, displayName = "Sollwert ändern", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE)
+ public int sollvalue = 0;
+
+ @PropertyInfo(handle = 1, editable = true, displayName = "Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true, visibleOnREST = true)
+ @DashboardInfo(handle = 0, displayName = "Status", stateful = true)
+ public boolean activ = false;
+
+ @PropertyInfo(handle = 2, displayName = "Abh. Sens.Temp.", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String concurrentSensorTemperatureInfo = "-";
+
+ @PropertyInfo(handle = 3, displayName = "Abh. Outputs", type = Types.TYPE_PROPERTIEINFO_INFO)
+ public String outputsInfo = "-";
+
+ @PropertyInfo(handle = 4, displayName = "Running", type = Types.TYPE_PROPERTIEINFO_INFO)
+ @DashboardInfo(handle = 1, displayName = "Running", stateful = true)
+ public boolean runningState = false;
+
+ @PropertyInfo(handle = 5, editable = true, displayName = "Force Activ", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true, visibleOnREST = true)
+ @DashboardInfo(handle = 2, displayName = "Force Activ", stateful = true)
+ public boolean forceActiv = false;
+
+ @PropertyInfo(handle = 6, editable = true, displayName = "Start-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30, visibleOnREST = true)
+ public String timeStart;
+ @PropertyInfo(handle = 7, editable = true, displayName = "Stop-Zeit", type = Types.TYPE_PROPERTIEINFO_CHANGESOLLVALUE, propertyType = Types.PROPERTYTYPE_TIME, stepValue = 30, visibleOnREST = true)
+ public String timeStop;
+ @PropertyInfo(handle = 8, editable = true, displayName = "AUS-Zeit Status", type = Types.TYPE_PROPERTIEINFO_TOGGLEACTIVATION, stateful = true, visibleOnREST = true)
+ public boolean offTimeActive = false;
+
+ String[] outputs = null;
+ String[] concurrentTemperatureIds = null;
+ private DateUtils du = null;
+
+ public VentilationDevice(int cycleTime) {
+ super(cycleTime);
+ this.du = new DateUtils();
+ this.ri = new RecorderItem(24, RecorderItem.LEGENDTYPE_DATE_HOUT_MINUTE, (1000 * 60 * 60));
+ }
+
+ public void addOutputs(String outputs) {
+ this.outputs = outputs.split(";");
+ }
+
+ public void addConcurrentTemperatureIds(String concurrentTemperatureIds) {
+ this.concurrentTemperatureIds = concurrentTemperatureIds.split(";");
+ }
+
+ @Override
+ public void afterIdle() {
+ if (concurrentTemperatureIds != null) {
+ StringBuilder namedconcurrentSensorTemperatureIds = new StringBuilder();
+ for (String tId : concurrentTemperatureIds) {
+ if (!tId.equals(id)) {
+ SensorTemperatureDevice td = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(tId);
+ if (td != null) {
+ namedconcurrentSensorTemperatureIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ concurrentSensorTemperatureInfo = namedconcurrentSensorTemperatureIds.toString();
+ }
+ if (outputs != null) {
+ StringBuilder namedOutputIds = new StringBuilder();
+ for (String tId : outputs) {
+ if (!tId.equals(id)) {
+ OutputDevice td = DeviceListUtils.getInstance().getOutputById(tId);
+ if (td != null) {
+ namedOutputIds.append(td.categorie).append(" (").append(td.displayName).append(")" + ";");
+ }
+ }
+ }
+ outputsInfo = namedOutputIds.toString();
+ }
+ }
+
+ @Override
+ public void receiveMessage(Object message) {
+ super.receiveMessage(message);
+ }
+
+ @Override
+ public void receiveIdle() {
+ if (activ) {
+ if (forceActiv) {
+ runningState = true;
+ } else {
+ if (checkTemperatureCondition()) {
+ runningState = !(offTimeActive && checkOffTime());
+ } else {
+ runningState = false;
+ }
+ }
+ } else {
+ runningState = false;
+ }
+ setOutputs(runningState);
+ if (ri != null) {
+ ri.setActive(activ);
+ Object data[] = {runningState};
+ ri.addItem(new RecorderItem.InsertItem(data), id);
+ }
+ logger.debug("VentilationDevice <" + id + "> => STATE <" + activ + "> => RUNNINGSTATE <" + runningState + ">" + " => FORCE <" + forceActiv + ">");
+ super.receiveIdle();
+ }
+
+ private void setOutputs(boolean state) {
+ if (outputs != null) {
+ for (String output : outputs) {
+ OutputDevice o = DeviceListUtils.getInstance().getOutputById(output);
+ if (o.isValue() != state) {
+ o.sendMessage(state);
+ }
+ }
+ }
+ }
+
+ private boolean checkTemperatureCondition() {
+ boolean state = false;
+ if (concurrentTemperatureIds != null) {
+ for (String temp : concurrentTemperatureIds) {
+ SensorTemperatureDevice o = DeviceListUtils.getInstance().getSensorTemperatureDeviceById(temp);
+ if (o != null) {
+ state = ((o.getValueAsInt() - sollvalue) >= 0);
+ if (state == false) {
+ break;
+ }
+ } else {
+ state = false;
+ break;
+ }
+ }
+ }
+ return state;
+ }
+
+ private boolean checkOffTime() {
+ return du.checkStatus(timeStart, timeStop);
+ }
+}
diff --git a/src/main/java/x/MessageHandling/MessageHandler.java b/src/main/java/x/MessageHandling/MessageHandler.java
new file mode 100755
index 0000000..3e6ef29
--- /dev/null
+++ b/src/main/java/x/MessageHandling/MessageHandler.java
@@ -0,0 +1,102 @@
+package x.MessageHandling;
+
+import java.lang.reflect.Field;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.PropertyChangedEvent;
+import x.Devices.InputDevice;
+import x.Devices.SceneDevice;
+import x.Devices.BaseDevice;
+import x.utils.PropertyInfo;
+import x.websocket.model.AsyncStatusMessage;
+import x.websocket.model.ConnectionManager;
+
+public class MessageHandler {
+
+ private static MessageHandler singleton = null;
+ private ConnectionManager cm = null;
+
+ public MessageHandler() {
+ }
+
+ synchronized public static MessageHandler getInstance() {
+ if (singleton == null) {
+ singleton = new MessageHandler();
+ }
+ return singleton;
+ }
+
+ public void setConnectionManager(ConnectionManager cm) {
+ if (this.cm == null) {
+ this.cm = cm;
+ }
+ }
+
+ synchronized public void messageToWebSocketClients(AsyncStatusMessage messageToSend) {
+ if (this.cm != null) {
+ synchronized (this.cm.getConnections()) {
+ this.cm.cleanConnections();
+ if (this.cm.getConnections().size() > 0) {
+ for (ConnectionManager.Status u : this.cm.getConnections()) {
+ if (u.isInitDone()) {
+ this.cm.sendMessage(u.getUuid(), messageToSend);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ synchronized public void messageToDevice(String message) {
+ String[] messageIdentifier = message.split("#");
+ if (messageIdentifier.length == 2) {
+ if (messageIdentifier[0].startsWith("p")) {
+ String[] handleObject = messageIdentifier[0].substring(1, messageIdentifier[0].length()).split("_");
+ if (handleObject.length == 2) {
+ int deviceHandle = Integer.parseInt(handleObject[0]);
+ int propertyHandle = Integer.parseInt(handleObject[1]);
+ for (Object deviceHandleMap : DeviceListUtils.getInstance().getDeviceList()) {
+ if (((BaseDevice) deviceHandleMap).deviceHandle == deviceHandle) {
+ Field[] fields = ((BaseDevice) deviceHandleMap).getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ if (p.handle() == propertyHandle) {
+ ((BaseDevice) deviceHandleMap).sendPropertyChangedEvent(new PropertyChangedEvent(f, p, messageIdentifier[1], false));
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ } else if (messageIdentifier[0].equals("scene")) {
+ SceneDevice d = null;
+ if (messageIdentifier[1].startsWith("-") && messageIdentifier[1].length() == 5) {
+ d = DeviceListUtils.getInstance().getSceneDeviceByHandle(Integer.parseInt(messageIdentifier[1]));
+ } else {
+ d = DeviceListUtils.getInstance().getSceneDeviceBySpeechIdent(messageIdentifier[1]);
+ }
+ if (d != null) {
+ d.sendMessage(true);
+ }
+ } else if (!messageIdentifier[0].equals("") && !messageIdentifier[0].equals("undefined")) {
+ int deviceHandle = Integer.parseInt(messageIdentifier[0]);
+ for (Object inputMap : DeviceListUtils.getInstance().getDeviceList()) {
+ if (inputMap instanceof InputDevice) {
+ if (((InputDevice) inputMap).deviceHandle == deviceHandle) {
+ ((InputDevice) inputMap).setLockedByVisu(messageIdentifier[1].equals("1"));
+ ((InputDevice) inputMap).sendMessage(messageIdentifier[1].equals("1"));
+ AsyncStatusMessage asm = new AsyncStatusMessage();
+ asm.setKind(AsyncStatusMessage.SET);
+ asm.setId(messageIdentifier[0]);
+ asm.setValue(messageIdentifier[1]);
+ messageToWebSocketClients(asm);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/x/main/XHomeautomationMain.java b/src/main/java/x/main/XHomeautomationMain.java
new file mode 100755
index 0000000..657d47d
--- /dev/null
+++ b/src/main/java/x/main/XHomeautomationMain.java
@@ -0,0 +1,128 @@
+package x.main;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.util.List;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import x.DeviceUtils.DeviceListUtils;
+import x.MessageHandling.MessageHandler;
+import x.modbus.XModbusMaster;
+import x.Devices.BaseDevice;
+import x.Devices.RemoteDevice;
+import x.Devices.RetainDevice;
+import x.retain.RetainProcess;
+import x.utils.DeviceXMLParser;
+
+@SpringBootApplication(scanBasePackages = {"x.rest", "x.websocket", "x.retain"})
+@EntityScan("x.retain.database")
+@EnableJpaRepositories("x.retain.database")
+public class XHomeautomationMain implements ApplicationRunner {
+
+ Logger logger = LoggerFactory.getLogger(XHomeautomationMain.class);
+
+ public static final String VERSION = "2.2.0";
+
+ @Autowired
+ RetainProcess retainProcess;
+
+ private XModbusMaster mbs = null;
+ private Thread modbusThread = null;
+
+ public void start(String modbusIP, boolean simulation, int cycleTimeMS) {
+ MessageHandler.getInstance();
+ mbs = new XModbusMaster(modbusIP, simulation, cycleTimeMS);
+ modbusThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ logger.info("Starting ModbusMaster...");
+ mbs.start();
+ }
+ });
+ modbusThread.setPriority(Thread.MAX_PRIORITY);
+ modbusThread.start();
+ }
+
+ public boolean getDevices(String filename) {
+ boolean returnvalue = false;
+ try {
+
+ DeviceXMLParser xmlParser = new DeviceXMLParser();
+ List deviceList = xmlParser.initConfigFile(filename);
+ if (deviceList != null && deviceList.size() > 0) {
+ returnvalue = true;
+ DeviceListUtils.getInstance().setDeviceList(deviceList);
+ for (BaseDevice o : DeviceListUtils.getInstance().getDeviceList()) {
+ o.idleDevice();
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return returnvalue;
+ }
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ String[] argsv = args.getSourceArgs();
+ for (String s : argsv) {
+ logger.info("arg = " + s);
+ }
+ if (argsv.length >= 1) {
+ logger.info("Version: " + XHomeautomationMain.VERSION);
+ Properties prop = new Properties();
+ BufferedInputStream stream;
+ try {
+ stream = new BufferedInputStream(new FileInputStream(argsv[0]));
+ prop.load(stream);
+ String configXML = prop.getProperty("configXml");
+ String simulationString = prop.getProperty("simulation");
+ boolean simulation = false;
+ if (simulationString.equals("true")) {
+ logger.info("Simulation activated");
+ simulation = true;
+ }
+ String ipString = prop.getProperty("ip");
+ String cycleTimeString = prop.getProperty("cycleTime");
+ int cycleTimeMS = Integer.parseInt(cycleTimeString);
+ String remoteURLString = prop.getProperty("remoteURL");
+ String remoteAccessSecondsString = prop.getProperty("remoteAccessSeconds");
+ int remoteTimeAccess = Integer.parseInt(remoteAccessSecondsString) * 1000;
+ String remoteAccessString = prop.getProperty("remoteAccess");
+ boolean remoteAccess = false;
+ if (remoteAccessString.equals("true")) {
+ logger.info("RemoteAccess activated: " + remoteURLString);
+ remoteAccess = true;
+ }
+ String remoteJWTString = prop.getProperty("remoteJWT");
+ boolean parseDeviceList = getDevices(configXML);
+ if (parseDeviceList == true) {
+ RetainDevice rd = new RetainDevice(true, retainProcess);
+ rd.idleDevice();
+ RemoteDevice r = new RemoteDevice(remoteAccess, remoteURLString, remoteTimeAccess, remoteJWTString);
+ r.idleDevice();
+ start(ipString, simulation, cycleTimeMS);
+ } else {
+ logger.error("Error reading Devicelist...");
+ }
+ } catch (Exception ex) {
+ logger.error("Error reading PropertiesFile");
+ }
+ } else {
+ logger.error("Wrong number of Arguments: " + argsv.length);
+ }
+ }
+
+ public static void main(String[] args) {
+ SpringApplicationBuilder builder = new SpringApplicationBuilder(XHomeautomationMain.class);
+ builder.headless(false).run(args);
+ }
+}
diff --git a/src/main/java/x/modbus/XModbusMaster.java b/src/main/java/x/modbus/XModbusMaster.java
new file mode 100755
index 0000000..221407b
--- /dev/null
+++ b/src/main/java/x/modbus/XModbusMaster.java
@@ -0,0 +1,306 @@
+package x.modbus;
+
+import java.lang.reflect.Field;
+import java.util.Random;
+import net.wimpi.modbus.Modbus;
+import net.wimpi.modbus.ModbusException;
+import net.wimpi.modbus.facade.ModbusTCPMaster;
+import net.wimpi.modbus.procimg.InputRegister;
+import net.wimpi.modbus.procimg.SimpleRegister;
+import net.wimpi.modbus.util.BitVector;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.TransferObject;
+import x.Devices.InputDevice;
+import x.Devices.OutputDevice;
+import x.Devices.TemperatureDevice;
+import x.Devices.BaseDevice;
+import x.Devices.DimmerDevice;
+import x.Devices.SensorTemperatureDevice;
+import x.MessageHandling.MessageHandler;
+import x.utils.DashboardInfo;
+import x.utils.PropertyInfo;
+import x.utils.FieldParser;
+import x.websocket.model.AsyncStatusMessage;
+
+public class XModbusMaster {
+
+ private final Logger logger = LoggerFactory.getLogger(XModbusMaster.class);
+
+ private int cycleTime = 75;
+ private long worstCycleTime = 75;
+ long startTime = 0;
+ long elapsedTime = 0;
+ int cyclicCounter = 0;
+ boolean modBusInit = false;
+ private String modbusHost = "192.168.1.1";
+ private final int modbusPort = Modbus.DEFAULT_PORT;
+ ModbusTCPMaster modbusMaster = null;
+ BitVector bvOutput = null;
+ BitVector bvInput = null;
+ private boolean simulation = false;
+ public static final int modbusDigitalInputOffset = 0;
+ public static final int modbusDigitalOutputOffset = 0x200;
+ public static final int modbusAnalogOutputOffset = 0x200;
+ private static final int modbusUnitID = 1;
+
+ public XModbusMaster(String modbusIP, boolean simulation, int cycleTimeMS) {
+ this.modbusHost = modbusIP;
+ this.simulation = simulation;
+ this.cycleTime = cycleTimeMS;
+ this.worstCycleTime = (long) cycleTimeMS;
+ initModbus();
+ }
+
+ private void initModbus() {
+ if (this.simulation == false) {
+ this.modbusMaster = new ModbusTCPMaster(this.modbusHost, this.modbusPort);
+ } else {
+ logger.info("ModbusTCPMaster startet in Simulation!");
+ }
+
+ }
+
+ private void connectModbus(boolean reconnect) {
+
+ if (reconnect && simulation == false) {
+ modbusMaster.disconnect();
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException ex) {
+ logger.error(ex.getMessage());
+ }
+ modbusMaster = null;
+ this.modbusMaster = new ModbusTCPMaster(this.modbusHost, this.modbusPort);
+ }
+
+ if (modbusMaster != null) {
+ try {
+ modbusMaster.connect();
+ modBusInit = true;
+ } catch (Exception ex) {
+ logger.error(ex.getMessage());
+ }
+ } else if (simulation) {
+ modBusInit = true;
+ }
+ }
+
+ public void start() {
+ connectModbus(false);
+ if (modBusInit == true) {
+ while (true) {
+ startTime = System.currentTimeMillis();
+ try {
+ readModbusDigitalInputs();
+ } catch (ModbusException ex) {
+ logger.error(ex.getMessage());
+ connectModbus(true);
+ }
+
+ try {
+ writeModbusDigitalOutputs();
+ } catch (ModbusException ex) {
+ logger.error(ex.getMessage());
+ connectModbus(true);
+ }
+
+ try {
+ writeModbusDimmerAnalogOutputs();
+ } catch (ModbusException ex) {
+ logger.error(ex.getMessage());
+ connectModbus(true);
+ }
+
+ if (cyclicCounter % 150 == 0) {
+ try {
+ readModbusAnalogInputs();
+ } catch (ModbusException ex) {
+ logger.error(ex.getMessage());
+ connectModbus(true);
+ }
+ }
+
+ if (cyclicCounter % 50 == 0) {
+ updateDeviceHandleStatusForWebSocket();
+ }
+
+ if (cyclicCounter >= 1000) {
+ cyclicCounter = 0;
+ logger.debug("INFO <" + cycleTime + "ms><" + elapsedTime + "ms><" + worstCycleTime + "ms>");
+ }
+ elapsedTime = System.currentTimeMillis() - startTime;
+ if (elapsedTime < cycleTime) {
+ try {
+ Thread.sleep(cycleTime - elapsedTime);
+ } catch (InterruptedException ex) {
+ logger.error(ex.getMessage());
+ }
+ } else {
+ if (elapsedTime > worstCycleTime) {
+ worstCycleTime = elapsedTime;
+ }
+ }
+ cyclicCounter++;
+ }
+ } else {
+ logger.error("Error init Modbus!!");
+ }
+ }
+
+ private void readModbusDigitalInputs() throws ModbusException {
+ if (simulation == false) {
+ int max = DeviceListUtils.getInstance().getMaxInputBusAddress();
+ if (max >= 0) {
+ int bitCount = max + 1;
+ bvInput = modbusMaster.readInputDiscretes(XModbusMaster.modbusDigitalInputOffset, bitCount);
+ for (int address = 0; address < bitCount; address++) {
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle instanceof InputDevice) {
+ if (((InputDevice) deviceHandle).busAddress == address) {
+ if (((InputDevice) deviceHandle).isLockedByVisu() == false && ((InputDevice) deviceHandle).isValue() != bvInput.getBit(address)) {
+ ((InputDevice) deviceHandle).sendMessage(bvInput.getBit(address));
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void writeModbusDigitalOutputs() throws ModbusException {
+ if (simulation == false) {
+ int max = DeviceListUtils.getInstance().getMaxOutputBusAddress();
+ if (max >= 0) {
+ int bitCount = max + 1;
+ bvOutput = modbusMaster.readCoils(XModbusMaster.modbusDigitalOutputOffset, bitCount);
+ for (int address = 0; address < bitCount; address++) {
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle instanceof OutputDevice) {
+ if (((OutputDevice) deviceHandle).busAddress == address) {
+ if (bvOutput.getBit(address) != ((OutputDevice) deviceHandle).isValue()) {
+ modbusMaster.writeCoil(XModbusMaster.modbusUnitID, ((OutputDevice) deviceHandle).busAddress, ((OutputDevice) deviceHandle).isValue());
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void readModbusAnalogInputs() throws ModbusException {
+ if (simulation == false) {
+ int max = DeviceListUtils.getInstance().getMaxAnalogInBusAddress();
+ if (max >= 0) {
+ int bitCount = max + 1;
+ InputRegister iReg[] = modbusMaster.readInputRegisters(0, bitCount);
+ for (int address = 0; address < bitCount; address++) {
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle instanceof TemperatureDevice) {
+ if (((TemperatureDevice) deviceHandle).busAddress == address) {
+ ((TemperatureDevice) deviceHandle).sendMessage(iReg[address].getValue());
+ break;
+ }
+ } else if (deviceHandle instanceof SensorTemperatureDevice) {
+ if (((SensorTemperatureDevice) deviceHandle).busAddress == address) {
+ ((SensorTemperatureDevice) deviceHandle).sendMessage(iReg[address].getValue());
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Random r = new Random();
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle instanceof TemperatureDevice) {
+ ((TemperatureDevice) deviceHandle).sendMessage(r.nextInt(300));
+ } else if (deviceHandle instanceof SensorTemperatureDevice) {
+ ((SensorTemperatureDevice) deviceHandle).sendMessage(200 + r.nextInt(500));
+ }
+ }
+ }
+ }
+
+ private void writeModbusDimmerAnalogOutputs() throws ModbusException {
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle instanceof DimmerDevice) {
+ if (((DimmerDevice) deviceHandle).isStateChanged()) {
+ ((DimmerDevice) deviceHandle).sendMessage(new TransferObject(false));
+ int value = ((DimmerDevice) deviceHandle).getLiveValue();
+ if (value > DimmerDevice.MAX_VALUE) {
+ value = DimmerDevice.MAX_VALUE;
+ } else if (value < DimmerDevice.MIN_VALUE) {
+ value = DimmerDevice.MIN_VALUE;
+ }
+ SimpleRegister outregister = new SimpleRegister(value);
+ if (simulation == false) {
+ modbusMaster.writeSingleRegister(((DimmerDevice) deviceHandle).busAddress, outregister);
+ // Read Back
+ //InputRegister iReg[] = modbusMaster.readInputRegisters(XModbusMaster.modbusAnalogOutputOffset, ((DimmerDevice) deviceHandle).busAddress + 1);
+ }
+ logger.debug("SPS-DIMMERVALUE <" + outregister.getValue() + ">");
+ }
+ }
+ }
+ }
+
+ private void updateDeviceHandleStatusForWebSocket() {
+ AsyncStatusMessage globalASM = new AsyncStatusMessage();
+ globalASM.setKind(AsyncStatusMessage.MULTISET);
+ globalASM.setError(AsyncStatusMessage.NOERROR);
+ globalASM.getAsm().add(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "-10", cycleTime + "|" + elapsedTime + "|" + worstCycleTime));
+ //MessageHandler.getInstance().messageToWebSocketClients(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "-10", cycleTime + "|" + elapsedTime + "|" + worstCycleTime));
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle instanceof OutputDevice) {
+ globalASM.getAsm().add(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "" + ((OutputDevice) deviceHandle).deviceHandle, (((OutputDevice) deviceHandle).isValue() == true ? "1" : "0")));
+ //MessageHandler.getInstance().messageToWebSocketClients(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "" + ((OutputDevice) deviceHandle).deviceHandle, (((OutputDevice) deviceHandle).isValue() == true ? "1" : "0")));
+ }
+ Field[] fields = deviceHandle.getClass().getFields();
+ for (Field f : fields) {
+
+ // PropertyInfos
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ try {
+ String value2Send = FieldParser.convertField(f, deviceHandle);
+ if (p.stateful()) {
+ if (FieldParser.convertFieldState(f, deviceHandle)) {
+ value2Send = value2Send + "|xactive";
+ }
+ }
+ //MessageHandler.getInstance().messageToWebSocketClients(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "p" + ((BaseDevice) deviceHandle).deviceHandle + "_" + p.handle(), value2Send));
+ globalASM.getAsm().add(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "p" + ((BaseDevice) deviceHandle).deviceHandle + "_" + p.handle(), value2Send));
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+
+ // DashboardInfos
+ if (((BaseDevice) deviceHandle).dashboard == true) {
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ try {
+ String value2Send = FieldParser.convertField(f, deviceHandle);
+ if (d.stateful()) {
+ if (FieldParser.convertFieldState(f, deviceHandle)) {
+ value2Send = value2Send + "|xactive";
+ }
+ }
+ //MessageHandler.getInstance().messageToWebSocketClients(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "d" + ((BaseDevice) deviceHandle).deviceHandle + "_" + d.handle(), value2Send));
+ globalASM.getAsm().add(new AsyncStatusMessage(AsyncStatusMessage.NOERROR, AsyncStatusMessage.SET, "d" + ((BaseDevice) deviceHandle).deviceHandle + "_" + d.handle(), value2Send));
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ }
+ }
+ }
+ MessageHandler.getInstance().messageToWebSocketClients(globalASM);
+ }
+}
diff --git a/src/main/java/x/rest/RestServerMessageResource.java b/src/main/java/x/rest/RestServerMessageResource.java
new file mode 100755
index 0000000..7bf0491
--- /dev/null
+++ b/src/main/java/x/rest/RestServerMessageResource.java
@@ -0,0 +1,184 @@
+package x.rest;
+
+import java.lang.reflect.Field;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.PropertyChangedEvent;
+import x.DeviceUtils.Types;
+import x.Devices.DHT22Device;
+import x.Devices.HeatingPumpDevice;
+import x.Devices.OutputDevice;
+import x.Devices.SensorTemperatureDevice;
+import x.Devices.TemperatureDevice;
+import x.Devices.VentilationDevice;
+import x.rest.data.DashboardResponse;
+import x.rest.data.devices.RestBaseDevice;
+import x.rest.data.devices.RestParam;
+import x.utils.PropertyInfo;
+import x.utils.FieldParser;
+import x.Devices.BaseDevice;
+import x.rest.data.StatusRequest;
+import x.rest.data.StatusResponse;
+
+@RestController
+@CrossOrigin(origins = "*")
+@RequestMapping(path = "/rest/data")
+public class RestServerMessageResource {
+
+ private final Logger logger = LoggerFactory.getLogger(RestServerMessageResource.class);
+
+ private DashboardResponse dashboard() {
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
+ String tsTamp = dateFormat.format(Calendar.getInstance().getTime());
+
+ DashboardResponse sr = new DashboardResponse();
+ sr.setError(0);
+ sr.setTstamp(tsTamp);
+
+ for (Object deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ BaseDevice bdo = (BaseDevice) deviceHandle;
+ RestBaseDevice bd = new RestBaseDevice();
+ bd.setNameCategory("" + bdo.categorie);
+ bd.setHandleDevice("" + bdo.deviceHandle);
+ bd.setIdDevice(bdo.id);
+ bd.setDisplayNameDevice(bdo.displayName);
+ bd.setStyleDevice(bdo.style);
+ boolean valid = false;
+ if (deviceHandle instanceof SensorTemperatureDevice) {
+ bd.setTypeDevice("" + Types.TYPE_SENSOR);
+ bd.setSollvalue("" + ((SensorTemperatureDevice) deviceHandle).getSollValueAsFloat());
+ bd.setValue("" + ((SensorTemperatureDevice) deviceHandle).getValueAsFloat());
+ getPropertyInfosForDevice(deviceHandle, bd);
+ valid = true;
+ } else if (deviceHandle instanceof DHT22Device) {
+ bd.setTypeDevice("" + Types.TYPE_DHT22);
+ bd.setActiv("" + ((DHT22Device) deviceHandle).activ);
+ bd.setTemperature("" + ((DHT22Device) deviceHandle).getTemperatureAsFloat());
+ bd.setHumanity("" + ((DHT22Device) deviceHandle).getHumanityAsFloat());
+ getPropertyInfosForDevice(deviceHandle, bd);
+ valid = true;
+ } else if (deviceHandle instanceof HeatingPumpDevice) {
+ bd.setTypeDevice("" + Types.TYPE_HEATINGPUMP);
+ bd.setRunningState("" + ((HeatingPumpDevice) deviceHandle).runningState);
+ bd.setForceActiv("" + ((HeatingPumpDevice) deviceHandle).forceActiv);
+ bd.setActiv("" + ((HeatingPumpDevice) deviceHandle).activ);
+ getPropertyInfosForDevice(deviceHandle, bd);
+ valid = true;
+ } else if (deviceHandle instanceof VentilationDevice) {
+ bd.setTypeDevice("" + Types.TYPE_VENTILATION);
+ bd.setRunningState("" + ((VentilationDevice) deviceHandle).runningState);
+ bd.setForceActiv("" + ((VentilationDevice) deviceHandle).forceActiv);
+ bd.setActiv("" + ((VentilationDevice) deviceHandle).activ);
+ getPropertyInfosForDevice(deviceHandle, bd);
+ valid = true;
+ } else if (deviceHandle instanceof OutputDevice) {
+ bd.setTypeDevice("" + Types.TYPE_OUTPUT);
+ bd.setValue("" + ((OutputDevice) deviceHandle).isValue());
+ getPropertyInfosForDevice(deviceHandle, bd);
+ valid = true;
+ } else if (deviceHandle instanceof TemperatureDevice) {
+ bd.setTypeDevice("" + Types.TYPE_TEMPERATURE);
+ bd.setSollvalue("" + ((TemperatureDevice) deviceHandle).getSollValueAsFloat());
+ bd.setValue("" + ((TemperatureDevice) deviceHandle).getValueAsFloat());
+ getPropertyInfosForDevice(deviceHandle, bd);
+ valid = true;
+ }
+
+ if (valid) {
+ sr.getDevices().add(bd);
+ }
+
+ }
+ return sr;
+
+ }
+
+ private void getPropertyInfosForDevice(Object deviceHandle, RestBaseDevice bd) {
+ Field[] fields = deviceHandle.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ try {
+ if (p.visibleOnREST()) {
+ RestParam param = new RestParam();
+ param.setHandle("" + p.handle());
+ param.setEditable("" + p.editable());
+ param.setVisibleValue("" + p.visibleValue());
+ param.setType("" + p.type());
+ param.setValue(FieldParser.convertField(f, deviceHandle));
+ param.setDisplayName(p.displayName());
+ bd.getParams().add(param);
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ }
+ }
+
+ private boolean messageToDevice(String message) {
+ boolean error = true;
+ String[] messageIdentifier = message.split("@");
+ if (messageIdentifier.length == 2) {
+ if (messageIdentifier[0].startsWith("p")) {
+ String[] handleObject = messageIdentifier[0].substring(1, messageIdentifier[0].length()).split("_");
+ if (handleObject.length == 2) {
+ int deviceHandle = Integer.parseInt(handleObject[0]);
+ int propertyHandle = Integer.parseInt(handleObject[1]);
+ for (Object deviceHandleMap : DeviceListUtils.getInstance().getDeviceList()) {
+ if (((BaseDevice) deviceHandleMap).deviceHandle == deviceHandle) {
+ Field[] fields = ((BaseDevice) deviceHandleMap).getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ if (p.handle() == propertyHandle) {
+ ((BaseDevice) deviceHandleMap).sendPropertyChangedEvent(new PropertyChangedEvent(f, p, messageIdentifier[1], false));
+ error = false;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ return error;
+ }
+
+ @RequestMapping(value = "/dashboardv2", method = RequestMethod.GET)
+ @ResponseStatus(value = HttpStatus.OK)
+ @ResponseBody
+ public DashboardResponse dashboardv2() {
+ return dashboard();
+ }
+
+ //http://localhost:5005/rest/data/set/p-3005_1@1/true
+ @RequestMapping(value = "/setv2", method = RequestMethod.POST)
+ @ResponseStatus(value = HttpStatus.OK)
+ @ResponseBody
+ public StatusResponse setv2(@RequestBody StatusRequest data) {
+ boolean error = true;
+ if (data != null && data.getValue().length() > 0) {
+ error = messageToDevice(data.getValue());
+ }
+ StatusResponse sr = new StatusResponse();
+ sr.setError("" + error);
+ sr.setEcho(data.getValue());
+ return sr;
+ }
+
+}
diff --git a/src/main/java/x/rest/data/DashboardResponse.java b/src/main/java/x/rest/data/DashboardResponse.java
new file mode 100644
index 0000000..29eedf8
--- /dev/null
+++ b/src/main/java/x/rest/data/DashboardResponse.java
@@ -0,0 +1,38 @@
+package x.rest.data;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.ArrayList;
+import x.rest.data.devices.RestBaseDevice;
+
+public class DashboardResponse {
+
+ private int error = 0;
+ private String tstamp = "";
+ private ArrayList devices = new ArrayList<>();
+
+ public int getError() {
+ return error;
+ }
+
+ public void setError(int error) {
+ this.error = error;
+ }
+
+ public String getTstamp() {
+ return tstamp;
+ }
+
+ public void setTstamp(String tstamp) {
+ this.tstamp = tstamp;
+ }
+
+ @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+ public ArrayList getDevices() {
+ return devices;
+ }
+
+ public void setDevices(ArrayList devices) {
+ this.devices = devices;
+ }
+
+}
diff --git a/src/main/java/x/rest/data/StatusRequest.java b/src/main/java/x/rest/data/StatusRequest.java
new file mode 100644
index 0000000..3be79e7
--- /dev/null
+++ b/src/main/java/x/rest/data/StatusRequest.java
@@ -0,0 +1,15 @@
+package x.rest.data;
+
+public class StatusRequest {
+
+ private String value = "";
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+}
diff --git a/src/main/java/x/rest/data/StatusResponse.java b/src/main/java/x/rest/data/StatusResponse.java
new file mode 100644
index 0000000..fb66e46
--- /dev/null
+++ b/src/main/java/x/rest/data/StatusResponse.java
@@ -0,0 +1,24 @@
+package x.rest.data;
+
+public class StatusResponse {
+
+ private String error = "";
+ private String echo = "";
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public String getEcho() {
+ return echo;
+ }
+
+ public void setEcho(String echo) {
+ this.echo = echo;
+ }
+
+}
diff --git a/src/main/java/x/rest/data/devices/Record.java b/src/main/java/x/rest/data/devices/Record.java
new file mode 100644
index 0000000..7b4872e
--- /dev/null
+++ b/src/main/java/x/rest/data/devices/Record.java
@@ -0,0 +1,51 @@
+package x.rest.data.devices;
+
+public class Record {
+
+ private String id = "";
+ private String dimension = "";
+ private String legend = "";
+ private String values = "";
+ private String date = "";
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getDimension() {
+ return dimension;
+ }
+
+ public void setDimension(String dimension) {
+ this.dimension = dimension;
+ }
+
+ public String getLegend() {
+ return legend;
+ }
+
+ public void setLegend(String legend) {
+ this.legend = legend;
+ }
+
+ public String getValues() {
+ return values;
+ }
+
+ public void setValues(String values) {
+ this.values = values;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public void setDate(String date) {
+ this.date = date;
+ }
+
+}
diff --git a/src/main/java/x/rest/data/devices/RestBaseDevice.java b/src/main/java/x/rest/data/devices/RestBaseDevice.java
new file mode 100644
index 0000000..ba48921
--- /dev/null
+++ b/src/main/java/x/rest/data/devices/RestBaseDevice.java
@@ -0,0 +1,136 @@
+package x.rest.data.devices;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.ArrayList;
+
+public class RestBaseDevice {
+
+ private String nameCategory = "";
+ private String handleDevice = "";
+ private String idDevice = "";
+ private String typeDevice = "";
+ private String displayNameDevice = "";
+ private String styleDevice = "";
+ private String sollvalue = "";
+ private String value = "";
+ private String activ = "false";
+ private String temperature = "";
+ private String humanity = "";
+ private String runningState = "false";
+ private String forceActiv = "false";
+ private ArrayList params = new ArrayList<>();
+
+ public String getNameCategory() {
+ return nameCategory;
+ }
+
+ public void setNameCategory(String nameCategory) {
+ this.nameCategory = nameCategory;
+ }
+
+ public String getHandleDevice() {
+ return handleDevice;
+ }
+
+ public void setHandleDevice(String handleDevice) {
+ this.handleDevice = handleDevice;
+ }
+
+ public String getIdDevice() {
+ return idDevice;
+ }
+
+ public void setIdDevice(String idDevice) {
+ this.idDevice = idDevice;
+ }
+
+ public String getTypeDevice() {
+ return typeDevice;
+ }
+
+ public void setTypeDevice(String typeDevice) {
+ this.typeDevice = typeDevice;
+ }
+
+ public String getDisplayNameDevice() {
+ return displayNameDevice;
+ }
+
+ public void setDisplayNameDevice(String displayNameDevice) {
+ this.displayNameDevice = displayNameDevice;
+ }
+
+ public String getStyleDevice() {
+ return styleDevice;
+ }
+
+ public void setStyleDevice(String styleDevice) {
+ this.styleDevice = styleDevice;
+ }
+
+ public String getSollvalue() {
+ return sollvalue;
+ }
+
+ public void setSollvalue(String sollvalue) {
+ this.sollvalue = sollvalue;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getActiv() {
+ return activ;
+ }
+
+ public void setActiv(String activ) {
+ this.activ = activ;
+ }
+
+ public String getTemperature() {
+ return temperature;
+ }
+
+ public void setTemperature(String temperature) {
+ this.temperature = temperature;
+ }
+
+ public String getHumanity() {
+ return humanity;
+ }
+
+ public void setHumanity(String humanity) {
+ this.humanity = humanity;
+ }
+
+ public String getRunningState() {
+ return runningState;
+ }
+
+ public void setRunningState(String runningState) {
+ this.runningState = runningState;
+ }
+
+ public String getForceActiv() {
+ return forceActiv;
+ }
+
+ public void setForceActiv(String forceActiv) {
+ this.forceActiv = forceActiv;
+ }
+
+ @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+ public ArrayList getParams() {
+ return params;
+ }
+
+ public void setParams(ArrayList params) {
+ this.params = params;
+ }
+
+}
diff --git a/src/main/java/x/rest/data/devices/RestParam.java b/src/main/java/x/rest/data/devices/RestParam.java
new file mode 100644
index 0000000..2190bf7
--- /dev/null
+++ b/src/main/java/x/rest/data/devices/RestParam.java
@@ -0,0 +1,60 @@
+package x.rest.data.devices;
+
+public class RestParam {
+
+ private String handle = "";
+ private String editable = "false";
+ private String visibleValue = "";
+ private String type = "";
+ private String value = "";
+ private String displayName = "";
+
+ public String getHandle() {
+ return handle;
+ }
+
+ public void setHandle(String handle) {
+ this.handle = handle;
+ }
+
+ public String getEditable() {
+ return editable;
+ }
+
+ public void setEditable(String editable) {
+ this.editable = editable;
+ }
+
+ public String getVisibleValue() {
+ return visibleValue;
+ }
+
+ public void setVisibleValue(String visibleValue) {
+ this.visibleValue = visibleValue;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+}
diff --git a/src/main/java/x/retain/RetainProcess.java b/src/main/java/x/retain/RetainProcess.java
new file mode 100644
index 0000000..e44cf67
--- /dev/null
+++ b/src/main/java/x/retain/RetainProcess.java
@@ -0,0 +1,106 @@
+package x.retain;
+
+import java.lang.reflect.Field;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.PropertyChangedEvent;
+import x.Devices.BaseDevice;
+import x.Devices.DimmerDevice;
+import x.Devices.HeatingPumpDevice;
+import x.Devices.SensorTemperatureDevice;
+import x.Devices.TemperatureDevice;
+import x.Devices.TimeDevice;
+import x.Devices.OutputDevice;
+import x.Devices.ShadingDevice;
+import x.Devices.VentilationDevice;
+import x.retain.database.Retainvariables;
+import x.retain.database.RetainvariablesRepository;
+import x.utils.FieldParser;
+import x.utils.PropertyInfo;
+
+@Service
+public class RetainProcess {
+
+ private final Logger logger = LoggerFactory.getLogger(RetainProcess.class);
+
+ @Autowired
+ private RetainvariablesRepository retainvariablesRepository;
+
+ public RetainProcess() {
+ logger.debug("RetainProcess initialized");
+ }
+
+ public void runonce() throws Exception {
+ Iterable entries = retainvariablesRepository.findAll();
+ for (Retainvariables rv : entries) {
+ for (BaseDevice deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if (deviceHandle.deviceHandle == rv.getDevicehandle()) {
+ updateProperty(deviceHandle, rv.getPropertyhandle(), rv.getPropertyvalue());
+ break;
+ }
+ }
+ }
+ }
+
+ private void updateProperty(BaseDevice deviceHandleObject, int properryHandle, String propertyValue) {
+ Field[] fields = deviceHandleObject.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ if (p.handle() == properryHandle) {
+ if (p.stateful() || p.editable()) {
+ deviceHandleObject.sendPropertyChangedEvent(new PropertyChangedEvent(f, p, propertyValue, true));
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void getProperties(BaseDevice deviceHandleObject) throws Exception {
+ Field[] fields = deviceHandleObject.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ if (p.stateful() || p.editable()) {
+ int deviceHandle = deviceHandleObject.deviceHandle;
+ int propertyHandle = p.handle();
+ String propertyValue = FieldParser.convertField(f, deviceHandleObject);
+ String displayName = p.displayName();
+ LocalDate ld = LocalDate.now();
+ Retainvariables rv = retainvariablesRepository.findByDevicehandleAndPropertyhandle(deviceHandle, propertyHandle);
+ if (rv == null) {
+ rv = new Retainvariables();
+ rv.setDevicehandle(deviceHandle);
+ rv.setPropertyhandle(propertyHandle);
+ rv.setPropertyname(displayName);
+ }
+ rv.setPropertyvalue(propertyValue);
+ rv.setTstamp(ld.atTime(LocalTime.now()));
+ retainvariablesRepository.save(rv);
+ }
+ }
+ }
+ }
+
+ public void execute() throws Exception {
+ for (BaseDevice deviceHandle : DeviceListUtils.getInstance().getDeviceList()) {
+ if ((deviceHandle instanceof TemperatureDevice)
+ || (deviceHandle instanceof HeatingPumpDevice)
+ || (deviceHandle instanceof SensorTemperatureDevice)
+ || (deviceHandle instanceof TimeDevice)
+ || (deviceHandle instanceof VentilationDevice)
+ || (deviceHandle instanceof OutputDevice)
+ || (deviceHandle instanceof ShadingDevice)
+ || (deviceHandle instanceof DimmerDevice)) {
+ getProperties(deviceHandle);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/x/retain/database/Retainvariables.java b/src/main/java/x/retain/database/Retainvariables.java
new file mode 100644
index 0000000..50db64b
--- /dev/null
+++ b/src/main/java/x/retain/database/Retainvariables.java
@@ -0,0 +1,70 @@
+package x.retain.database;
+
+import java.time.LocalDateTime;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Retainvariables {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+
+ private int devicehandle = 0;
+ private int propertyhandle = 0;
+ private String propertyvalue = "";
+ private String propertyname = "";
+ private LocalDateTime tstamp;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public int getDevicehandle() {
+ return devicehandle;
+ }
+
+ public void setDevicehandle(int devicehandle) {
+ this.devicehandle = devicehandle;
+ }
+
+ public int getPropertyhandle() {
+ return propertyhandle;
+ }
+
+ public void setPropertyhandle(int propertyhandle) {
+ this.propertyhandle = propertyhandle;
+ }
+
+ public String getPropertyvalue() {
+ return propertyvalue;
+ }
+
+ public void setPropertyvalue(String propertyvalue) {
+ this.propertyvalue = propertyvalue;
+ }
+
+ public String getPropertyname() {
+ return propertyname;
+ }
+
+ public void setPropertyname(String propertyname) {
+ this.propertyname = propertyname;
+ }
+
+ public LocalDateTime getTstamp() {
+ return tstamp;
+ }
+
+ public void setTstamp(LocalDateTime tstamp) {
+ this.tstamp = tstamp;
+ }
+
+}
diff --git a/src/main/java/x/retain/database/RetainvariablesRepository.java b/src/main/java/x/retain/database/RetainvariablesRepository.java
new file mode 100644
index 0000000..be3cff4
--- /dev/null
+++ b/src/main/java/x/retain/database/RetainvariablesRepository.java
@@ -0,0 +1,16 @@
+package x.retain.database;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface RetainvariablesRepository extends CrudRepository {
+
+ Retainvariables findById(int id);
+
+ Retainvariables findByDevicehandle(int handle);
+
+ Retainvariables findByPropertyhandle(int handle);
+
+ Retainvariables findByDevicehandleAndPropertyhandle(int devicehandle, int propertyhandle);
+}
diff --git a/src/main/java/x/utils/DashboardInfo.java b/src/main/java/x/utils/DashboardInfo.java
new file mode 100755
index 0000000..57adfef
--- /dev/null
+++ b/src/main/java/x/utils/DashboardInfo.java
@@ -0,0 +1,19 @@
+package x.utils;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface DashboardInfo {
+
+ int handle() default 0;
+
+ String displayName() default "";
+
+ boolean stateful() default false;
+
+ boolean editable() default false;
+}
diff --git a/src/main/java/x/utils/DeviceXMLParser.java b/src/main/java/x/utils/DeviceXMLParser.java
new file mode 100644
index 0000000..cbf3730
--- /dev/null
+++ b/src/main/java/x/utils/DeviceXMLParser.java
@@ -0,0 +1,685 @@
+package x.utils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import x.DeviceEffects.BaseEffect;
+import x.DeviceEffects.BridgeEffect;
+import x.DeviceEffects.DimmerEffect;
+import x.DeviceEffects.OffEffect;
+import x.DeviceEffects.OnEffect;
+import x.DeviceEffects.ToggleEffect;
+import x.DeviceUtils.InputParameter;
+import x.Devices.OutputDevice;
+import x.Devices.BaseDevice;
+import x.DeviceUtils.Types;
+import x.Devices.DHT22Device;
+import x.Devices.DimmerDevice;
+import x.Devices.HeatingPumpDevice;
+import x.Devices.InputDevice;
+import x.Devices.SceneDevice;
+import x.Devices.SensorTemperatureDevice;
+import x.Devices.ShadingDevice;
+import x.Devices.TemperatureDevice;
+import x.Devices.TimeDevice;
+import x.Devices.VentilationDevice;
+
+public class DeviceXMLParser {
+
+ private final ArrayList outputsId = new ArrayList<>();
+ private final ArrayList dimmerId = new ArrayList<>();
+ private final ArrayList inputId = new ArrayList<>();
+ private final ArrayList temperatureId = new ArrayList<>();
+ private final ArrayList temperatureSensorId = new ArrayList<>();
+ private final ArrayList outputsBus = new ArrayList<>();
+ private final ArrayList dimmerBus = new ArrayList<>();
+ private final ArrayList inputsBus = new ArrayList<>();
+ private final ArrayList temperature_sensorTemperatureBus = new ArrayList<>();
+ private final ArrayList sceneId = new ArrayList<>();
+ private final ArrayList sceneSpeechIdent = new ArrayList<>();
+ private final ArrayList timeId = new ArrayList<>();
+ private final ArrayList dht22Id = new ArrayList<>();
+ private final ArrayList heatingPumpId = new ArrayList<>();
+ private final ArrayList ventilationId = new ArrayList<>();
+ private final ArrayList shadingId = new ArrayList<>();
+
+ private void checkForValidOutput(String output) throws Exception {
+ String[] outputs = output.split(";");
+ for (String s : outputs) {
+ if (!outputsId.contains(s)) {
+ throw new Exception("Output-ID :" + s + " not valid/found");
+ }
+ }
+ }
+
+ private void checkForValidTemperatures(String temperatureIds) throws Exception {
+ String[] temperatureIdsList = temperatureIds.split(";");
+ for (String s : temperatureIdsList) {
+ if (!temperatureId.contains(s)) {
+ throw new Exception("Temperature-ID :" + s + " not valid/found");
+ }
+ }
+ }
+
+ private void checkForValidSensorTemperatures(String temperatureIds) throws Exception {
+ String[] temperatureIdsList = temperatureIds.split(";");
+ for (String s : temperatureIdsList) {
+ if (!temperatureSensorId.contains(s)) {
+ throw new Exception("SensorTemperature-ID :" + s + " not valid/found");
+ }
+ }
+ }
+
+ private void checkForValidDimmer(String dimmer) throws Exception {
+ String[] outputs = dimmer.split(";");
+ for (String s : outputs) {
+ if (!dimmerId.contains(s)) {
+ throw new Exception("Dimmer-ID :" + s + " not valid/found");
+ }
+ }
+ }
+
+ private int getType(String type) throws Exception {
+ int returnType = 0;
+ if (type.equalsIgnoreCase("TOGGLE")) {
+ returnType = Types.TYPE_TOGGLE;
+ } else if (type.equalsIgnoreCase("ON")) {
+ returnType = Types.TYPE_ON;
+ } else if (type.equalsIgnoreCase("OFF")) {
+ returnType = Types.TYPE_OFF;
+ } else if (type.equalsIgnoreCase("BRIDGE")) {
+ returnType = Types.TYPE_BRIDGE;
+ } else if (type.equalsIgnoreCase("DIMMER")) {
+ returnType = Types.TYPE_DIMMER;
+ }
+ if (returnType == 0) {
+ throw new Exception("Invalid Type :" + type);
+ }
+ return returnType;
+ }
+
+ private String checkAndGetAttribute(Element e, String name, boolean blankCheck) throws Exception {
+ String value = null;
+ if (e.hasAttribute(name)) {
+ String attr = e.getAttribute(name);
+ if (blankCheck) {
+ if (!attr.isEmpty()) {
+ value = attr;
+ }
+ } else {
+ value = attr;
+ }
+ }
+ if (value == null) {
+ throw new Exception("error in checkAttribute == null for " + e.getNodeName() + " and " + name);
+ }
+ return value;
+ }
+
+ private String getCategoryName(Element e) throws Exception {
+ String name = null;
+ Element p = (Element) e.getParentNode();
+ if (p.getNodeName().equals("category")) {
+ name = checkAndGetAttribute(p, "name", true);
+ } else {
+ throw new Exception("Wrong parent Node. Should be Category");
+ }
+ return name;
+ }
+
+ void parseOutputDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String busAddress = checkAndGetAttribute(e, "busAddress", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String concurrentOutputs = checkAndGetAttribute(e, "concurrentOutputs", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ String timeStart = checkAndGetAttribute(e, "timeStart", false);
+ String timeStop = checkAndGetAttribute(e, "timeStop", false);
+ OutputDevice d = new OutputDevice(BaseDevice.DEFAULTCYCLETIME * 20);
+ d.id = id;
+ d.busAddress = Integer.parseInt(busAddress);
+ if (!outputsId.contains(d.id) && !"".equals(d.id)) {
+ outputsId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for OutputDevice");
+ }
+ if (!outputsBus.contains(d.busAddress)) {
+ outputsBus.add(d.busAddress);
+ } else {
+ throw new Exception("Double OutputBusAddress:" + d.busAddress);
+ }
+ d.deviceHandle = (d.busAddress + Types.TYPE_OUTPUT) * -1;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ if (!concurrentOutputs.equals("")) {
+ d.addConcurrentOutputs(concurrentOutputs);
+ }
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ if (!timeStart.equals("") && !timeStop.equals("")) {
+ d.setTimeSettings(timeStart, timeStop);
+ }
+ devices.add(d);
+ }
+
+ void parseDimmerDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String busAddress = checkAndGetAttribute(e, "busAddress", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ String startDelay = checkAndGetAttribute(e, "startDelay", false);
+ String style = checkAndGetAttribute(e, "style", false);
+ DimmerDevice d = new DimmerDevice(BaseDevice.DEFAULTCYCLETIME);
+ d.id = id;
+ d.busAddress = Integer.parseInt(busAddress);
+ if (!dimmerId.contains(d.id) && !"".equals(d.id)) {
+ dimmerId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for DimmerDevice");
+ }
+ if (!dimmerBus.contains(d.busAddress)) {
+ dimmerBus.add(d.busAddress);
+ } else {
+ throw new Exception("Double DimmerBusAddress:" + d.busAddress);
+ }
+ d.deviceHandle = (d.busAddress + Types.TYPE_DIMMERDEVICE) * -1;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ d.startDelay = (startDelay.equals("") ? 1250 : Integer.parseInt(startDelay));
+ d.style = (style.equals("") ? "dimmer" : style);
+ devices.add(d);
+ }
+
+ void parseInputDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String busAddress = checkAndGetAttribute(e, "busAddress", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ InputDevice d = new InputDevice(BaseDevice.DEFAULTCYCLETIME);
+ d.id = id;
+ d.busAddress = Integer.parseInt(busAddress);
+ if (!inputId.contains(d.id) && !"".equals(d.id)) {
+ inputId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for InputDevice");
+ }
+ if (!inputsBus.contains(d.busAddress)) {
+ inputsBus.add(d.busAddress);
+ } else {
+ throw new Exception("Double InputBusAddress:" + d.busAddress);
+ }
+ d.deviceHandle = (d.busAddress + Types.TYPE_INPUT) * -1;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.style = (style.equals("") ? "light" : style);
+ NodeList params = e.getChildNodes();
+ for (int i = 0; i < params.getLength(); i++) {
+ if (params.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element el = (Element) params.item(i);
+ String forwardHandle = checkAndGetAttribute(el, "forwardHandle", true);
+ String typeString = checkAndGetAttribute(el, "type", true);
+ String delay = checkAndGetAttribute(el, "delay", true);
+ String duration = checkAndGetAttribute(el, "duration", true);
+ int type = getType(typeString);
+ if (type == Types.TYPE_DIMMER) {
+ checkForValidDimmer(forwardHandle);
+ } else {
+ checkForValidOutput(forwardHandle);
+ }
+ BaseEffect effect = null;
+ if (type != 0) {
+ if (type == Types.TYPE_ON) {
+ effect = new OnEffect(Integer.parseInt(duration), Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_OFF) {
+ effect = new OffEffect(Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_TOGGLE) {
+ effect = new ToggleEffect(Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_BRIDGE) {
+ effect = new BridgeEffect(Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_DIMMER) {
+ effect = new DimmerEffect(Integer.parseInt(delay), forwardHandle);
+ }
+ InputParameter deviceParam = new InputParameter(type, effect);
+ d.inputParams.add(deviceParam);
+ }
+ }
+ }
+ devices.add(d);
+ }
+
+ void parseTemperatureDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String busAddress = checkAndGetAttribute(e, "busAddress", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String sollvalue = checkAndGetAttribute(e, "sollvalue", true);
+ String uHysterese = checkAndGetAttribute(e, "uHysterese", true);
+ String oHysterese = checkAndGetAttribute(e, "oHysterese", true);
+ String forwardHandle = checkAndGetAttribute(e, "forwardHandle", true);
+ String active = checkAndGetAttribute(e, "active", false);
+ String style = checkAndGetAttribute(e, "style", false);
+ String concurrentTemperatures = checkAndGetAttribute(e, "concurrentTemperatures", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ TemperatureDevice d = new TemperatureDevice(BaseDevice.DEFAULTCYCLETIME * 50);
+ d.id = id;
+ d.busAddress = Integer.parseInt(busAddress);
+ if (!temperatureId.contains(d.id) && !"".equals(d.id)) {
+ temperatureId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for TemperatureDevice");
+ }
+ if (!temperature_sensorTemperatureBus.contains(d.busAddress)) {
+ temperature_sensorTemperatureBus.add(d.busAddress);
+ } else {
+ throw new Exception("Double TemperatureBusAddress:" + d.busAddress);
+ }
+ checkForValidOutput(forwardHandle);
+ d.deviceHandle = (d.busAddress + Types.TYPE_TEMPERATURE) * -1;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.sollvalue = Integer.parseInt(sollvalue);
+ d.uHysterese = Integer.parseInt(uHysterese);
+ d.oHysterese = Integer.parseInt(oHysterese);
+ if (active.equals("true")) {
+ d.activ = true;
+ }
+ d.style = (style.equals("") ? "temperature" : style);
+ d.addOutputs(forwardHandle);
+ if (!concurrentTemperatures.equals("")) {
+ d.addConcurrentTemperatureIds(concurrentTemperatures);
+ }
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ void parseSensorTemperatureDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String busAddress = checkAndGetAttribute(e, "busAddress", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String sollvalue = checkAndGetAttribute(e, "sollvalue", true);
+ String concurrentTemperatures = checkAndGetAttribute(e, "concurrentTemperatures", false);
+ String active = checkAndGetAttribute(e, "active", false);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ SensorTemperatureDevice d = new SensorTemperatureDevice(BaseDevice.DEFAULTCYCLETIME * 50);
+ d.id = id;
+ d.busAddress = Integer.parseInt(busAddress);
+ if (!temperatureSensorId.contains(d.id) && d.id != "") {
+ temperatureSensorId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for SensorTemperatureDevice");
+ }
+ if (!temperature_sensorTemperatureBus.contains(d.busAddress)) {
+ temperature_sensorTemperatureBus.add(d.busAddress);
+ } else {
+ throw new Exception("Double SensorTemperatureBusAddress:" + d.busAddress);
+ }
+ if (!"".equals(concurrentTemperatures)) {
+ checkForValidTemperatures(concurrentTemperatures);
+ }
+ d.deviceHandle = (d.busAddress + Types.TYPE_SENSOR) * -1;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.sollvalue = Integer.parseInt(sollvalue);
+ if (active.equals("true")) {
+ d.activ = true;
+ }
+ d.style = (style.equals("") ? "sensor" : style);
+ if (!"".equals(concurrentTemperatures)) {
+ d.addConcurrentTemperatureIds(concurrentTemperatures);
+ }
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ private int sceneCounter = 0;
+
+ void parseSceneDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String speechIdent = checkAndGetAttribute(e, "speechIdent", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ SceneDevice d = new SceneDevice(BaseDevice.DEFAULTCYCLETIME);
+ d.id = id;
+ d.speechIdent = speechIdent;
+ if (!sceneId.contains(d.id) && !"".equals(d.id)) {
+ sceneId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for SceneDevice");
+ }
+ if (!sceneSpeechIdent.contains(d.speechIdent)) {
+ sceneSpeechIdent.add(d.speechIdent);
+ } else {
+ throw new Exception("Double SceneSpeechIdent:" + d.speechIdent);
+ }
+ d.deviceHandle = (sceneCounter + Types.TYPE_SCENE) * -1;
+ sceneCounter++;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.style = (style.equals("") ? "scene" : style);
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ NodeList params = e.getChildNodes();
+ for (int i = 0; i < params.getLength(); i++) {
+ if (params.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element el = (Element) params.item(i);
+ String forwardHandle = checkAndGetAttribute(el, "forwardHandle", true);
+ String typeString = checkAndGetAttribute(el, "type", true);
+ String delay = checkAndGetAttribute(el, "delay", true);
+ int type = getType(typeString);
+ if (type == Types.TYPE_DIMMER) {
+ checkForValidDimmer(forwardHandle);
+ } else {
+ checkForValidOutput(forwardHandle);
+ }
+ String duration = checkAndGetAttribute(el, "duration", true);
+ BaseEffect effect = null;
+ if (type != 0) {
+ if (type == Types.TYPE_ON) {
+ effect = new OnEffect(Integer.parseInt(duration), Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_OFF) {
+ effect = new OffEffect(Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_TOGGLE) {
+ effect = new ToggleEffect(Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_BRIDGE) {
+ effect = new BridgeEffect(Integer.parseInt(delay), forwardHandle);
+ } else if (type == Types.TYPE_DIMMER) {
+ effect = new DimmerEffect(Integer.parseInt(delay), forwardHandle);
+ }
+ InputParameter deviceParam = new InputParameter(type, effect);
+ d.inputParams.add(deviceParam);
+ }
+ }
+ }
+ devices.add(d);
+ }
+
+ private int timeCounter = 0;
+
+ void parseTimeDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String timeStart = checkAndGetAttribute(e, "timeStart", true);
+ String timeStop = checkAndGetAttribute(e, "timeStop", true);
+ String forwardHandle = checkAndGetAttribute(e, "forwardHandle", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ TimeDevice d = new TimeDevice(BaseDevice.DEFAULTCYCLETIME * 20);
+ d.id = id;
+ if (!timeId.contains(d.id) && !"".equals(d.id)) {
+ timeId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for TimeDevice");
+ }
+ d.deviceHandle = (timeCounter + Types.TYPE_TIME) * -1;
+ timeCounter++;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ // Format e.g. 23:00:00 => HH:mm:ss
+ d.timeStart = timeStart;
+ d.timeStop = timeStop;
+ d.style = (style.equals("") ? "time" : style);
+ checkForValidOutput(forwardHandle);
+ d.addOutputs(forwardHandle);
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ private int dht22Counter = 0;
+
+ void parseDhtDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String command = checkAndGetAttribute(e, "command", true);
+ String params = checkAndGetAttribute(e, "params", true);
+ String writable = checkAndGetAttribute(e, "writable", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ DHT22Device d = new DHT22Device(BaseDevice.DEFAULTCYCLETIME * 6000);
+ d.id = id;
+ if (!dht22Id.contains(d.id) && !"".equals(d.id)) {
+ dht22Id.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for DhTDevice");
+ }
+ d.deviceHandle = (dht22Counter + Types.TYPE_DHT22) * -1;
+ dht22Counter++;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.addExec(command, params, (writable.equals("true")));
+ d.style = (style.equals("") ? "dht22" : style);
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ private int heatingPumpCounter = 0;
+
+ void parseHeatingDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String timeStart = checkAndGetAttribute(e, "timeStart", true);
+ String timeStop = checkAndGetAttribute(e, "timeStop", true);
+ String forwardHandle = checkAndGetAttribute(e, "forwardHandle", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ String concurrentTemperatures = checkAndGetAttribute(e, "concurrentTemperatures", false);
+ String active = checkAndGetAttribute(e, "active", false);
+ HeatingPumpDevice d = new HeatingPumpDevice(BaseDevice.DEFAULTCYCLETIME * 900);
+ d.id = id;
+ if (!heatingPumpId.contains(d.id) && !"".equals(d.id)) {
+ heatingPumpId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for HeatingPumpDevice");
+ }
+ checkForValidSensorTemperatures(concurrentTemperatures);
+ d.deviceHandle = (heatingPumpCounter + Types.TYPE_HEATINGPUMP) * -1;
+ heatingPumpCounter++;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.timeStart = timeStart;
+ d.timeStop = timeStop;
+ checkForValidOutput(forwardHandle);
+ d.addOutputs(forwardHandle);
+ if (!"".equals(concurrentTemperatures)) {
+ d.addConcurrentTemperatureIds(concurrentTemperatures);
+ }
+ if (active.equals("true")) {
+ d.activ = true;
+ }
+ d.style = (style.equals("") ? "heating" : style);
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ private int ventilationCounter = 0;
+
+ void parseVentilationDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String forwardHandle = checkAndGetAttribute(e, "forwardHandle", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ String sollvalue = checkAndGetAttribute(e, "sollvalue", false);
+ String timeStart = checkAndGetAttribute(e, "timeStart", false);
+ String timeStop = checkAndGetAttribute(e, "timeStop", false);
+ String concurrentTemperatures = checkAndGetAttribute(e, "concurrentTemperatures", false);
+ String active = checkAndGetAttribute(e, "active", false);
+ VentilationDevice d = new VentilationDevice(BaseDevice.DEFAULTCYCLETIME * 1200);
+ d.id = id;
+ if (!ventilationId.contains(d.id) && !"".equals(d.id)) {
+ ventilationId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for VentilationDevice");
+ }
+ d.deviceHandle = (ventilationCounter + Types.TYPE_VENTILATION) * -1;
+ ventilationCounter++;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.timeStart = timeStart;
+ d.timeStop = timeStop;
+ d.sollvalue = Integer.parseInt(sollvalue);
+ checkForValidOutput(forwardHandle);
+ d.addOutputs(forwardHandle);
+ if (!"".equals(concurrentTemperatures)) {
+ d.addConcurrentTemperatureIds(concurrentTemperatures);
+ }
+ if (active.equals("true")) {
+ d.activ = true;
+ }
+ d.style = (style.equals("") ? "dht22" : style);
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ private int shadingCounter = 0;
+
+ void parseShadingDevice(List devices, Element e, String nodeType) throws Exception {
+ String categorieName = getCategoryName(e);
+ String id = checkAndGetAttribute(e, "id", true);
+ String forwardHandle = checkAndGetAttribute(e, "forwardHandle", true);
+ String displayName = checkAndGetAttribute(e, "displayName", true);
+ String style = checkAndGetAttribute(e, "style", false);
+ String dashboard = checkAndGetAttribute(e, "dashboard", false);
+ String sollvalue = checkAndGetAttribute(e, "sollvalue", false);
+ String timeStart = checkAndGetAttribute(e, "timeStart", false);
+ String timeStop = checkAndGetAttribute(e, "timeStop", false);
+ String durationactive = checkAndGetAttribute(e, "durationactive", false);
+ String durationpostActive = checkAndGetAttribute(e, "durationpostactive", false);
+ String durationreactive = checkAndGetAttribute(e, "durationreactive", false);
+ String concurrentTemperatures = checkAndGetAttribute(e, "concurrentTemperatures", false);
+ String active = checkAndGetAttribute(e, "active", false);
+ ShadingDevice d = new ShadingDevice(BaseDevice.DEFAULTCYCLETIME * 18000);
+ d.id = id;
+ if (!shadingId.contains(d.id) && !"".equals(d.id)) {
+ shadingId.add(d.id);
+ } else {
+ throw new Exception("Double ID/Invalid:" + d.id + " for ShadingDevice");
+ }
+ checkForValidSensorTemperatures(concurrentTemperatures);
+ d.deviceHandle = (shadingCounter + Types.TYPE_SHADING) * -1;
+ shadingCounter++;
+ d.categorie = categorieName;
+ d.displayName = displayName;
+ d.timeStart = timeStart;
+ d.timeStop = timeStop;
+ d.sollvalueTemp = Integer.parseInt(sollvalue);
+ d.durationActive = Integer.parseInt(durationactive);
+ d.durationPostActive = Integer.parseInt(durationpostActive);
+ d.durationReactive = Integer.parseInt(durationreactive);
+ checkForValidOutput(forwardHandle);
+ d.addOutputs(forwardHandle);
+ if (!"".equals(concurrentTemperatures)) {
+ d.addConcurrentTemperatureIds(concurrentTemperatures);
+ }
+ if (active.equals("true")) {
+ d.activ = true;
+ }
+ d.style = (style.equals("") ? "shading" : style);
+ if (dashboard.equals("true")) {
+ d.dashboard = true;
+ }
+ devices.add(d);
+ }
+
+ private void parseNode(List devices, Element e, String nodeType) throws Exception {
+ String nodeName = e.getNodeName();
+ NodeList nl = e.getChildNodes();
+ if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("output")) {
+ parseOutputDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("dimmer")) {
+ parseDimmerDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("input")) {
+ parseInputDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("temperature")) {
+ parseTemperatureDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("sensorTemperature")) {
+ parseSensorTemperatureDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("scene")) {
+ parseSceneDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("time")) {
+ parseTimeDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("dht22")) {
+ parseDhtDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("heatingpump")) {
+ parseHeatingDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("ventilation")) {
+ parseVentilationDevice(devices, e, nodeType);
+ } else if (nodeName.equalsIgnoreCase(nodeType) && nodeName.equalsIgnoreCase("shading")) {
+ parseShadingDevice(devices, e, nodeType);
+ }
+ for (int i = 0; i < nl.getLength(); i++) {
+ if (nl.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element el = (Element) nl.item(i);
+ parseNode(devices, el, nodeType);
+ }
+ }
+ }
+
+ public List initConfigFile(String filename) throws Exception {
+
+ List devices = new ArrayList<>();
+ File file = new File(filename);
+ if (file.exists()) {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.parse(new File(filename));
+
+ parseNode(devices, document.getDocumentElement(), "output");
+ parseNode(devices, document.getDocumentElement(), "dimmer");
+ parseNode(devices, document.getDocumentElement(), "input");
+ parseNode(devices, document.getDocumentElement(), "temperature");
+ parseNode(devices, document.getDocumentElement(), "sensorTemperature");
+ parseNode(devices, document.getDocumentElement(), "scene");
+ parseNode(devices, document.getDocumentElement(), "time");
+ parseNode(devices, document.getDocumentElement(), "dht22");
+ parseNode(devices, document.getDocumentElement(), "heatingpump");
+ parseNode(devices, document.getDocumentElement(), "ventilation");
+ parseNode(devices, document.getDocumentElement(), "shading");
+
+ }
+ return devices;
+ }
+
+ public static void main(String[] args) {
+ DeviceXMLParser xmpP = new DeviceXMLParser();
+ try {
+ List bd = xmpP.initConfigFile("/home/deployment/Documents/GitHub/XHomeautomation-Service/src/main/resources/data/homeautomation.xml");
+ System.out.println("Ready");
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/x/utils/ExecCommander.java b/src/main/java/x/utils/ExecCommander.java
new file mode 100755
index 0000000..ddcfc89
--- /dev/null
+++ b/src/main/java/x/utils/ExecCommander.java
@@ -0,0 +1,264 @@
+package x.utils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class ExecCommander {
+
+ private AtomicBoolean globalState = new AtomicBoolean(true);
+ private final RetVal globalRetVal = new RetVal();
+ public static int OS_WIN = 1;
+ public static int OS_LINUX = 2;
+ public static int OS_MAC = 3;
+ public static int OS_SOLARIS = 4;
+
+ public static class RetVal {
+
+ private final Object mutex = new Object();
+ private boolean ready = false;
+ private boolean error = false;
+ private boolean killed = false;
+ private boolean timeout = false;
+ private int PID = 0;
+ private final ArrayList returnvalues = new ArrayList<>();
+
+ public boolean isReady() {
+ return ready;
+ }
+
+ public void setReady(boolean ready) {
+ synchronized (mutex) {
+ this.ready = ready;
+ }
+ }
+
+ public boolean isError() {
+ return error;
+ }
+
+ public void setError(boolean error) {
+ synchronized (mutex) {
+ this.error = error;
+ }
+ }
+
+ public int getPID() {
+ return PID;
+ }
+
+ public void setPID(int PID) {
+ synchronized (mutex) {
+ this.PID = PID;
+ }
+ }
+
+ public boolean isKilled() {
+ return killed;
+ }
+
+ public void setKilled(boolean killed) {
+ synchronized (mutex) {
+ this.killed = killed;
+ }
+ }
+
+ public boolean isTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(boolean timeout) {
+ synchronized (mutex) {
+ this.timeout = timeout;
+ }
+ }
+
+ public void addItem(String item) {
+ synchronized (mutex) {
+ returnvalues.add(item);
+ }
+ }
+
+ public void clearItems() {
+ synchronized (mutex) {
+ returnvalues.clear();
+ }
+ }
+
+ public ArrayList getReturnvalues() {
+ return returnvalues;
+ }
+ }
+
+ private void initGlobalRetVal() {
+ globalRetVal.setReady(false);
+ globalRetVal.setError(true);
+ globalRetVal.setPID(0);
+ globalRetVal.setKilled(false);
+ globalRetVal.setTimeout(false);
+ globalRetVal.clearItems();
+ }
+
+ private Thread runCommand(ArrayList commands) throws Exception {
+ Thread processThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessBuilder commandProcessBuilder = new ProcessBuilder(commands);
+ commandProcessBuilder.redirectErrorStream(true);
+ Process commandProcess = commandProcessBuilder.start();
+ globalRetVal.setPID(getProcessID(commandProcess));
+ BufferedReader inpCommandReader = new BufferedReader(new InputStreamReader(commandProcess.getInputStream()));
+ while (globalState.get()) {
+ String ret = inpCommandReader.readLine();
+ if (ret != null) {
+ globalRetVal.addItem(ret);
+ }
+ if (!processIsRunning(commandProcess) && ret == null) {
+ globalState.set(false);
+ }
+ Thread.sleep(10);
+ }
+ commandProcess.waitFor();
+ commandProcess.destroy();
+ globalRetVal.setReady(true);
+ } catch (IOException | InterruptedException ex) {
+ Logger.getLogger(ExecCommander.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ });
+ processThread.start();
+ return processThread;
+ }
+
+ public RetVal executeCommand(String command, String params, boolean setWriteable, int timeoutMS) throws Exception {
+
+ File f = new File(command);
+ if (!f.exists()) {
+ globalRetVal.setError(true);
+ return globalRetVal;
+ }
+ if (setWriteable) {
+ f.setReadable(true, true);
+ f.setWritable(true, true);
+ f.setExecutable(true, true);
+ }
+
+ globalState.set(true);
+ initGlobalRetVal();
+
+ ArrayList commands = new ArrayList<>();
+ if (params.length() > 0) {
+ command = command + " " + params;
+ }
+ String[] commandList = command.split(" ");
+ for (String s : commandList) {
+ commands.add(s);
+ }
+ long startTime = System.currentTimeMillis();
+ Thread processThread = runCommand(commands);
+
+ boolean loop = true;
+ while (loop) {
+ if (globalRetVal.isReady() || !globalState.get()) {
+ loop = false;
+ if (!globalRetVal.isTimeout() && !globalRetVal.isKilled()) {
+ globalRetVal.setError(false);
+ }
+ }
+ if (System.currentTimeMillis() > (startTime + timeoutMS)) {
+ globalState.set(false);
+ globalRetVal.setTimeout(true);
+ if (!globalRetVal.isReady()) {
+ try {
+ if (getOS() == OS_LINUX && globalRetVal.getPID() != 0) {
+ Runtime.getRuntime().exec("kill -9 " + globalRetVal.getPID());
+ globalRetVal.setKilled(true);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ globalRetVal.setError(true);
+ }
+ }
+ Thread.sleep(10);
+ }
+
+ processThread.join();
+
+ return globalRetVal;
+ }
+
+ private int getProcessID(Process p) {
+ int pid = 0;
+ if (getOS() == OS_LINUX) {
+ if (p.getClass().getName().equals("java.lang.UNIXProcess")) {
+ try {
+ Field f = p.getClass().getDeclaredField("pid");
+ f.setAccessible(true);
+ pid = f.getInt(p);
+ } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return pid;
+ }
+
+ protected boolean processIsRunning(Process process) {
+ try {
+ if (getOS() == OS_LINUX) {
+ process.exitValue();
+ }
+ return false;
+ } catch (Exception e) {
+ return true;
+ }
+ }
+
+ private int getOS() {
+ int retval = -1;
+ String OS = System.getProperty("os.name").toLowerCase();
+ if (OS.indexOf("win") >= 0) {
+ retval = OS_WIN;
+ } else if (OS.indexOf("mac") >= 0) {
+ retval = OS_MAC;
+ } else if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) {
+ retval = OS_LINUX;
+ } else if (OS.indexOf("sunos") >= 0) {
+ retval = OS_SOLARIS;
+ }
+ return retval;
+ }
+
+ public static void main(String[] args) {
+ ExecCommander ap = new ExecCommander();
+ System.out.println("OS:" + ap.getOS());
+ try {
+ for (int k = 0; k < 2000; k++) {
+ System.out.println("NR.: " + k);
+ ExecCommander.RetVal value = ap.executeCommand("/home/pi/XHomeautomation/dht22", "22 4", true, 15000);
+ for (String s : value.getReturnvalues()) {
+ System.out.println(s);
+ }
+ if (value.isError() || value.isKilled()) {
+ System.out.println("READY:" + value.isReady());
+ System.out.println("ERROR:" + value.isError());
+ System.out.println("KILLED:" + value.isKilled());
+ System.out.println("PID = " + value.getPID());
+ //break;
+ }
+ Thread.sleep(2500);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/x/utils/FieldParser.java b/src/main/java/x/utils/FieldParser.java
new file mode 100644
index 0000000..fe9d5e6
--- /dev/null
+++ b/src/main/java/x/utils/FieldParser.java
@@ -0,0 +1,63 @@
+package x.utils;
+
+import java.lang.reflect.Field;
+
+public class FieldParser {
+
+ public static String convertField(Field field, Object device) {
+ String value = "";
+ try {
+ if (field.getType().equals(Integer.TYPE)) {
+ value = "" + field.getInt(device);
+ } else if (field.getType().equals(Long.TYPE)) {
+ value = "" + field.getLong(device);
+ } else if (field.getType().equals(Boolean.TYPE)) {
+ value = "" + field.getBoolean(device);
+ if (value.equals("true")) {
+ value = "ON";
+ } else {
+ value = "OFF";
+ }
+ } else if (field.getType().equals(Float.TYPE)) {
+ value = "" + field.getFloat(device);
+ } else if (field.getType().equals(String.class)) {
+ value = (String) field.get(device);
+ }
+ } catch (IllegalAccessException | IllegalArgumentException ex) {
+ value = "";
+ }
+ return value;
+ }
+
+ public static boolean convertFieldState(Field field, Object device) {
+ boolean returnvalue = false;
+ try {
+ if (field.getType().equals(Integer.TYPE)) {
+ int value = field.getInt(device);
+ if (value > 0) {
+ returnvalue = true;
+ }
+ } else if (field.getType().equals(Long.TYPE)) {
+ long value = field.getLong(device);
+ if (value > 0) {
+ returnvalue = true;
+ }
+ } else if (field.getType().equals(Boolean.TYPE)) {
+ returnvalue = field.getBoolean(device);
+ } else if (field.getType().equals(Float.TYPE)) {
+ float value = field.getFloat(device);
+ if (value > 0) {
+ returnvalue = true;
+ }
+ } else if (field.getType().equals(String.class)) {
+ String value = (String) field.get(device);
+ if (!"0".equals(value)) {
+ returnvalue = true;
+ }
+ }
+ } catch (IllegalAccessException | IllegalArgumentException ex) {
+ returnvalue = false;
+ }
+ return returnvalue;
+ }
+}
diff --git a/src/main/java/x/utils/JsonBuilder.java b/src/main/java/x/utils/JsonBuilder.java
new file mode 100755
index 0000000..559ca93
--- /dev/null
+++ b/src/main/java/x/utils/JsonBuilder.java
@@ -0,0 +1,372 @@
+package x.utils;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+import x.DeviceUtils.DeviceListUtils;
+import x.DeviceUtils.RecorderItem;
+import x.DeviceUtils.Types;
+import x.Devices.InputDevice;
+import x.Devices.OutputDevice;
+import x.Devices.SceneDevice;
+import x.Devices.TemperatureDevice;
+import x.Devices.BaseDevice;
+import x.Devices.DHT22Device;
+import x.Devices.HeatingPumpDevice;
+import x.Devices.DimmerDevice;
+import x.Devices.SensorTemperatureDevice;
+import x.Devices.ShadingDevice;
+import x.Devices.TimeDevice;
+import x.Devices.VentilationDevice;
+import x.rest.data.devices.Record;
+import x.rest.data.devices.RestBaseDevice;
+import x.rest.data.devices.RestParam;
+import x.websocket.model.AsyncStatusMessage;
+
+public class JsonBuilder {
+
+ private final ArrayList globalResultList;
+
+ public JsonBuilder() {
+ globalResultList = sortList();
+ }
+
+ public DeviceHandleList fromDeviceHandleList() {
+
+ DeviceHandleList dhl = new DeviceHandleList();
+
+ for (SortableList sort : globalResultList) {
+ RestBaseDeviceRecorder rbd = new RestBaseDeviceRecorder();
+ rbd.setNameCategory(sort.categorie);
+ rbd.setHandleDevice("" + sort.handleDevice);
+ rbd.setStyleDevice(sort.styleDevice);
+ rbd.setTypeDevice("" + sort.typeDevice);
+ rbd.setDisplayNameDevice(sort.displayName);
+ if (sort.params != null) {
+ for (PropertyInfo param : sort.params) {
+ RestParam rp = new RestParam();
+ rp.setHandle("" + param.handle());
+ rp.setEditable("" + param.editable());
+ rp.setVisibleValue("" + param.visibleValue());
+ rp.setType("" + param.type());
+ rp.setValue("");
+ rp.setDisplayName(param.displayName());
+ rbd.getParams().add(rp);
+ }
+ }
+ if (sort.ri != null) {
+ ArrayList riItems = sort.ri.getAllItems();
+ if (riItems.size() > 0) {
+ for (RecorderItem.ResultItem ri : riItems) {
+ Record r = new Record();
+ r.setId(getUUID());
+ r.setDimension("" + ri.getYDimension());
+ r.setLegend(ri.getX());
+ r.setValues(ri.getYasString());
+ r.setDate(ri.getDateTime());
+ rbd.getRecords().add(r);
+ }
+ }
+ }
+ dhl.getDevices().add(rbd);
+ }
+ return dhl;
+ }
+
+ private String getUUID() {
+ AtomicLong counter = new AtomicLong(System.currentTimeMillis() * 1000);
+ return Long.toString(counter.incrementAndGet(), 36);
+ }
+
+ private ArrayList sortList() {
+
+ // Categorie
+ ArrayList returnList = new ArrayList<>();
+ HashMap categorieList = new HashMap<>();
+ for (int k = 0; k < DeviceListUtils.getInstance().getDeviceList().size(); k++) {
+ BaseDevice temp = (BaseDevice) DeviceListUtils.getInstance().getDeviceList().get(k);
+ if (!categorieList.containsKey(temp.categorie)) {
+ categorieList.put(temp.categorie, "");
+ }
+ }
+ Iterator iterator = categorieList.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry mentry = (Map.Entry) iterator.next();
+
+ // Input
+ ArrayList in = DeviceListUtils.getInstance().getInputDevicesByCategorie(mentry.getKey().toString());
+ for (InputDevice device : in) {
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_INPUT, device.displayName, null, null, device.getRecorderItem()));
+ }
+
+ // Temperature
+ ArrayList temp = DeviceListUtils.getInstance().getTemperatureDevicesByCategorie(mentry.getKey().toString());
+ for (TemperatureDevice device : temp) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_TEMPERATURE, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Sensor
+ ArrayList sensor = DeviceListUtils.getInstance().getSensorTemperatureDevicesByCategorie(mentry.getKey().toString());
+ for (SensorTemperatureDevice device : sensor) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_SENSOR, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Scene
+ ArrayList scene = DeviceListUtils.getInstance().getSceneDevicesByCategorie(mentry.getKey().toString());
+ for (SceneDevice device : scene) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_SCENE, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Time
+ ArrayList time = DeviceListUtils.getInstance().getTimeDevicesByCategorie(mentry.getKey().toString());
+ for (TimeDevice device : time) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_TIME, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Shading
+ ArrayList shading = DeviceListUtils.getInstance().getShadingDevicesByCategorie(mentry.getKey().toString());
+ for (ShadingDevice device : shading) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_SHADING, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Output
+ ArrayList output = DeviceListUtils.getInstance().getOutputDevicesByCategorie(mentry.getKey().toString());
+ for (OutputDevice device : output) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_OUTPUT, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Dimmer
+ ArrayList dimmer = DeviceListUtils.getInstance().getDimmerDevicesByCategorie(mentry.getKey().toString());
+ for (DimmerDevice device : dimmer) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_DIMMERDEVICE, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // DHT22
+ ArrayList dht22 = DeviceListUtils.getInstance().getDHT22DevicesByCategorie(mentry.getKey().toString());
+ for (DHT22Device device : dht22) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_DHT22, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Heatingpump
+ ArrayList heatingPump = DeviceListUtils.getInstance().getHeatingPumpDevicesByCategorie(mentry.getKey().toString());
+ for (HeatingPumpDevice device : heatingPump) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_HEATINGPUMP, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ // Ventilation
+ ArrayList ventilation = DeviceListUtils.getInstance().getVentilationDevicesByCategorie(mentry.getKey().toString());
+ for (VentilationDevice device : ventilation) {
+ ArrayList params = new ArrayList<>();
+ ArrayList dashboard = new ArrayList<>();
+ Field[] fields = device.getClass().getFields();
+ for (Field f : fields) {
+ PropertyInfo p = (PropertyInfo) f.getAnnotation(PropertyInfo.class);
+ if (p != null) {
+ params.add(p);
+ }
+ DashboardInfo d = (DashboardInfo) f.getAnnotation(DashboardInfo.class);
+ if (d != null) {
+ dashboard.add(d);
+ }
+ }
+ returnList.add(new SortableList(device.categorie, device.deviceHandle, device.style, Types.TYPE_VENTILATION, device.displayName, params, (device.dashboard == true ? dashboard : null), device.getRecorderItem()));
+ }
+
+ }
+ return returnList;
+ }
+
+ static class SortableList {
+
+ String categorie = "";
+ int handleDevice = 0;
+ String styleDevice = "";
+ int typeDevice = 0;
+ String displayName = "";
+ ArrayList params = null;
+ ArrayList dashboard = null;
+ RecorderItem ri = null;
+
+ public SortableList(String categorie, int handleDevice, String styleDevice, int typeDevice, String displayName, ArrayList params, ArrayList dashboard, RecorderItem ri) {
+ this.categorie = categorie;
+ this.handleDevice = handleDevice;
+ this.styleDevice = styleDevice;
+ this.typeDevice = typeDevice;
+ this.displayName = displayName;
+ this.params = params;
+ this.dashboard = dashboard;
+ this.ri = ri;
+ }
+
+ }
+
+ public static class DeviceHandleList {
+
+ private int error = AsyncStatusMessage.NOERROR;
+ private int kind = AsyncStatusMessage.INIT;
+ private ArrayList devices = new ArrayList<>();
+
+ public int getError() {
+ return error;
+ }
+
+ public void setError(int error) {
+ this.error = error;
+ }
+
+ public int getKind() {
+ return kind;
+ }
+
+ public void setKind(int kind) {
+ this.kind = kind;
+ }
+
+ @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+ public ArrayList getDevices() {
+ return devices;
+ }
+
+ public void setDevices(ArrayList devices) {
+ this.devices = devices;
+ }
+
+ }
+
+ public static class RestBaseDeviceRecorder extends RestBaseDevice {
+
+ private ArrayList records = new ArrayList<>();
+
+ @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+ public ArrayList getRecords() {
+ return records;
+ }
+
+ public void setRecords(ArrayList records) {
+ this.records = records;
+ }
+
+ }
+
+}
diff --git a/src/main/java/x/utils/JsonUtils.java b/src/main/java/x/utils/JsonUtils.java
new file mode 100644
index 0000000..57f824f
--- /dev/null
+++ b/src/main/java/x/utils/JsonUtils.java
@@ -0,0 +1,64 @@
+package x.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class JsonUtils {
+
+ private final HashMap