]> git.basschouten.com Git - openhab-addons.git/commitdiff
[liquidcheck] Initial contribution (#13287)
authorMarcel Goerentz <57457529+marcelGoerentz@users.noreply.github.com>
Sat, 13 May 2023 22:19:56 +0000 (00:19 +0200)
committerGitHub <noreply@github.com>
Sat, 13 May 2023 22:19:56 +0000 (00:19 +0200)
* Add new binding liquidcheck

Signed-off-by: Marcel Goerentz <m.goerentz@t-online.de>
34 files changed:
CODEOWNERS
bom/openhab-addons/pom.xml
bundles/org.openhab.binding.liquidcheck/NOTICE [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/README.md [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/pom.xml [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckHandlerFactory.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/discovery/LiquidCheckDiscoveryService.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/httpclient/LiquidCheckHttpClient.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/AccessPoint.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/CommData.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Context.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Device.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Expansion.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Header.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/LiquidCheckSystem.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Measure.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Model.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Payload.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Pump.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Raw.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Security.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Station.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Wifi.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/addon/addon.xml [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/i18n/liquidcheck.properties [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/thing/thing-types.xml [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/test/java/org/openhab/binding/liquidcheck/internal/json/ResponseTest.java [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/test/resources/CommandResponseExample.json [new file with mode: 0644]
bundles/org.openhab.binding.liquidcheck/src/test/resources/PollingResponseExample.json [new file with mode: 0644]
bundles/pom.xml

index 2e4a2c55e32284d4c798d43d94557f2f015cf78a..210ce9a6241249245c122a327a3df94e10a804b9 100644 (file)
 /bundles/org.openhab.binding.lifx/ @wborn
 /bundles/org.openhab.binding.linky/ @clinique @lolodomo
 /bundles/org.openhab.binding.linuxinput/ @t-8ch
+/bundles/org.openhab.binding.liquidcheck/ @marcelGoerentz
 /bundles/org.openhab.binding.lirc/ @kabili207
 /bundles/org.openhab.binding.livisismarthome/ @Novanic
 /bundles/org.openhab.binding.logreader/ @paulianttila
index 206ff34f0e385526c60520b6dd57502d1665a673..420d5cd44473b8d273705e700a29be6b569f5a27 100644 (file)
       <artifactId>org.openhab.binding.linuxinput</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.openhab.addons.bundles</groupId>
+      <artifactId>org.openhab.binding.liquidcheck</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.openhab.addons.bundles</groupId>
       <artifactId>org.openhab.binding.lirc</artifactId>
diff --git a/bundles/org.openhab.binding.liquidcheck/NOTICE b/bundles/org.openhab.binding.liquidcheck/NOTICE
new file mode 100644 (file)
index 0000000..38d625e
--- /dev/null
@@ -0,0 +1,13 @@
+This content is produced and maintained by the openHAB project.
+
+* Project home: https://www.openhab.org
+
+== Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License 2.0 which is available at
+https://www.eclipse.org/legal/epl-2.0/.
+
+== Source Code
+
+https://github.com/openhab/openhab-addons
diff --git a/bundles/org.openhab.binding.liquidcheck/README.md b/bundles/org.openhab.binding.liquidcheck/README.md
new file mode 100644 (file)
index 0000000..3eeb556
--- /dev/null
@@ -0,0 +1,64 @@
+# LiquidCheck Binding
+
+This binding is for the Liquid-Check device from SI-Elektronik GmbH which can be used to measure level and content of tanks.
+
+## Supported Things
+
+`liquidCheckDevice`:
+
+The Liquid-Check device in Hardwareversion B and Firmwareversion 1.60 has been tested and is working.
+You can access the measured data, raw data, the settings as properties and command a measurement.
+
+## Discovery
+
+This binding discovers the devices via a ping and request method.
+It uses every Ethernet/WLAN interface that is connected to the openHAB server.
+Therefore the discovery has to be manually triggered.
+
+## Thing Configuration
+
+You only need to set the IP address of the device or use the discovery method.
+If the maximum content has not been set the fill-indicator channel will not contain valid values.
+
+### `liquidCheckDevice` Thing Configuration
+
+| Name             | Type    | Description                              | Default | Required | Advanced |
+|------------------|---------|------------------------------------------|---------|----------|----------|
+| hostname         | text    | Hostname or IP address of the device     | N/A     | yes      | no       |
+| maxContent       | integer | Maximal content of the container         | 1       | no       | no       |
+| refreshInterval  | integer | Interval the device is polled in seconds | 60      | no       | yes      |
+| connectionTimeout| integer | Timeout after a request has been sent    | 5       | no       | yes      |
+
+## Channels
+
+| Channel        | Type                        | Read/Write | Description                           |
+|----------------|-----------------------------|------------|---------------------------------------|
+| content        | Number:Volume               | R          | This is the measured content          |
+| level          | Number:Length               | R          | This is the measured level            |
+| raw-content    | Number:Volume               | R          | This is the measured raw content data |
+| raw-level      | Number:Length               | R          | This is the measured raw level data   |
+| fill-indicator | Number:Dimensionless        | R          | This is the fill level in percentage  |
+| measure        | Switch                      | W          | This starts a measurement             |
+| pump-runs      | Number                      | R          | This is the total runs number         |
+| pump-runtime   | Number:Time                 | R          | This is the total runtime in sec.     |
+
+## Full Example
+
+### Thing
+
+```java
+Thing liquidcheck:liquidCheckDevice:myDevice "Label" @ "Location" [hostname="XXX.XXX.XXX.XXX", maxContent=9265, refreshInterval=600, connectionTimeout=5]
+```
+
+### Items
+
+```java
+Number:Volume ContentLiquidCheck "Content" {liquidcheck:liquidCheckDevice:myDevice:content}
+Number:Length LevelLiquidCheck "Level" {liquidcheck:liquidCheckDevice:myDevice:level}
+Number:Volume RawContentLiquidCheck "Raw Content" {liquidcheck:liquidCheckDevice:myDevice:raw-content}
+Number:Length RawLevelLiquidCheck "Raw Level" {liquidcheck:liquidCheckDevice:myDevice:raw-level}
+Number:Dimensionless FillIndicator "Fill Indicator" {liquidcheck:liquidCheckDevice:myDevice:fill-indicator}
+Switch MeasureLiquidCheck "Measure" {liquidcheck:liquidCheckDevice:myDevice:measure}
+Number PumpRuns "Pump runs" {liquidcheck:liquidCheckDevice:myDevice:pump-runs}
+Number PumpRuntime "Pump runtime" {liquidcheck:liquidCheckDevice:myDevice:pump-runtime}
+```
diff --git a/bundles/org.openhab.binding.liquidcheck/pom.xml b/bundles/org.openhab.binding.liquidcheck/pom.xml
new file mode 100644 (file)
index 0000000..8fc8fd3
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.openhab.addons.bundles</groupId>
+    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+    <version>4.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.binding.liquidcheck</artifactId>
+
+  <name>openHAB Add-ons :: Bundles :: LiquidCheck Binding</name>
+
+</project>
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/feature/feature.xml b/bundles/org.openhab.binding.liquidcheck/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..ef7b1ad
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.liquidcheck-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+       <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+       <feature name="openhab-binding-liquidcheck" description="LiquidCheck Binding" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.liquidcheck/${project.version}</bundle>
+       </feature>
+</features>
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckBindingConstants.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckBindingConstants.java
new file mode 100644 (file)
index 0000000..9d48b82
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link LiquidCheckBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class LiquidCheckBindingConstants {
+
+    private static final String BINDING_ID = "liquidcheck";
+
+    // List of all Thing Type UIDs
+    public static final ThingTypeUID THING_TYPE_LIQUID_CHECK = new ThingTypeUID(BINDING_ID, "liquidCheckDevice");
+
+    // List of all Channel ids
+    public static final String CONTENT_CHANNEL = "content";
+    public static final String RAW_CONTENT_CHANNEL = "raw-content";
+    public static final String LEVEL_CHANNEL = "level";
+    public static final String RAW_LEVEL_CHANNEL = "raw-level";
+    public static final String FILL_INDICATOR_CHANNEL = "fill-indicator";
+    public static final String PUMP_TOTAL_RUNS_CHANNEL = "pump-runs";
+    public static final String PUMP_TOTAL_RUNTIME_CHANNEL = "pump-runtime";
+    public static final String MEASURE_CHANNEL = "measure";
+
+    // List of all Property ids
+    public static final String PROPERTY_NAME = "name";
+    public static final String PROPERTY_SECURITY_CODE = "securityCode";
+    public static final String PROPERTY_IP = "ip";
+    public static final String PROPERTY_HOSTNAME = "hostname";
+    public static final String PROPERTY_SSID = "ssid";
+
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_LIQUID_CHECK);
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckConfiguration.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckConfiguration.java
new file mode 100644 (file)
index 0000000..2001464
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link LiquidCheckConfiguration} class contains fields mapping thing configuration parameters.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class LiquidCheckConfiguration {
+
+    public String hostname = "";
+    public int refreshInterval = 60;
+    public int maxContent = 1;
+    public byte connectionTimeout = 5;
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckHandler.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckHandler.java
new file mode 100644 (file)
index 0000000..8270968
--- /dev/null
@@ -0,0 +1,173 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal;
+
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.CONTENT_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.FILL_INDICATOR_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.LEVEL_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.MEASURE_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PUMP_TOTAL_RUNS_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PUMP_TOTAL_RUNTIME_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.RAW_CONTENT_CHANNEL;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.RAW_LEVEL_CHANNEL;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.binding.liquidcheck.internal.httpclient.LiquidCheckHttpClient;
+import org.openhab.binding.liquidcheck.internal.json.CommData;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.Units;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.types.Command;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link LiquidCheckHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class LiquidCheckHandler extends BaseThingHandler {
+
+    private final Logger logger = LoggerFactory.getLogger(LiquidCheckHandler.class);
+    private final HttpClient httpClient;
+
+    private Map<String, String> oldProps = new HashMap<>();
+
+    private LiquidCheckConfiguration config = new LiquidCheckConfiguration();
+    private @Nullable LiquidCheckHttpClient client;
+
+    private @Nullable ScheduledFuture<?> polling;
+
+    public LiquidCheckHandler(Thing thing, HttpClient httpClient) {
+        super(thing);
+        this.httpClient = httpClient;
+    }
+
+    @Override
+    @SuppressWarnings("null")
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        if (channelUID.getId().equals(MEASURE_CHANNEL)) {
+            if (command instanceof OnOffType) {
+                try {
+                    LiquidCheckHttpClient client = this.client;
+                    if (client != null && client.isConnected()) {
+                        String response = client.measureCommand();
+                        CommData commandResponse = new Gson().fromJson(response, CommData.class);
+                        if (commandResponse != null && !commandResponse.header.name.equals("")) {
+                            if (!"success".equals(commandResponse.context.status)) {
+                                logger.warn("Starting the measurement was not successful!");
+                            }
+                        } else {
+                            logger.debug("The object commandResponse is null!");
+                        }
+                    }
+                } catch (TimeoutException | ExecutionException | JsonSyntaxException e) {
+                    logger.warn("This went wrong in handleCommand: {}", e.getMessage());
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+                updateState(channelUID, OnOffType.OFF);
+            }
+        }
+    }
+
+    @Override
+    public void initialize() {
+        config = getConfigAs(LiquidCheckConfiguration.class);
+        oldProps = thing.getProperties();
+
+        updateStatus(ThingStatus.UNKNOWN);
+        var client = new LiquidCheckHttpClient(config, httpClient);
+        this.client = client;
+        PollingForData pollingRunnable = new PollingForData(client);
+        polling = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, config.refreshInterval, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void dispose() {
+        ScheduledFuture<?> polling = this.polling;
+        if (null != polling) {
+            polling.cancel(true);
+            this.polling = null;
+        }
+    }
+
+    private class PollingForData implements Runnable {
+
+        private final LiquidCheckHttpClient client;
+
+        public PollingForData(LiquidCheckHttpClient client) {
+            this.client = client;
+        }
+
+        @Override
+        public void run() {
+            try {
+                String jsonString = client.pollData();
+                CommData response = new Gson().fromJson(jsonString, CommData.class);
+                if (response != null && !response.header.messageId.equals("")) {
+                    Map<String, String> properties = response.createPropertyMap();
+                    if (!oldProps.equals(properties)) {
+                        oldProps = properties;
+                        updateProperties(properties);
+                    }
+                    updateState(CONTENT_CHANNEL, new QuantityType<>(response.payload.measure.content, Units.LITRE));
+                    updateState(LEVEL_CHANNEL, new QuantityType<>(response.payload.measure.level, SIUnits.METRE));
+                    updateState(RAW_CONTENT_CHANNEL,
+                            new QuantityType<>(response.payload.measure.raw.content, Units.LITRE));
+
+                    updateState(RAW_LEVEL_CHANNEL,
+                            new QuantityType<>(response.payload.measure.raw.level, SIUnits.METRE));
+
+                    updateState(PUMP_TOTAL_RUNS_CHANNEL, new DecimalType(response.payload.system.pump.totalRuns));
+                    updateState(PUMP_TOTAL_RUNTIME_CHANNEL,
+                            new QuantityType<>(response.payload.system.pump.totalRuntime, Units.SECOND));
+                    if (config.maxContent > 1) {
+                        double fillIndicator = response.payload.measure.content / config.maxContent * 100;
+                        updateState(FILL_INDICATOR_CHANNEL, new QuantityType<>(fillIndicator, Units.PERCENT));
+                    }
+                    if (!thing.getStatus().equals(ThingStatus.ONLINE)) {
+                        updateStatus(ThingStatus.ONLINE);
+                    }
+                } else {
+                    logger.debug("Json is null");
+                }
+            } catch (TimeoutException | ExecutionException | JsonSyntaxException e) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckHandlerFactory.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/LiquidCheckHandlerFactory.java
new file mode 100644 (file)
index 0000000..d3998bf
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal;
+
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.*;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.core.io.net.http.HttpClientFactory;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.BaseThingHandlerFactory;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * The {@link LiquidCheckHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+@Component(service = ThingHandlerFactory.class, configurationPid = "binding.liquidcheck")
+public class LiquidCheckHandlerFactory extends BaseThingHandlerFactory {
+
+    private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_LIQUID_CHECK);
+
+    private final HttpClient httpClient;
+
+    @Override
+    public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+        return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
+    }
+
+    @Activate
+    public LiquidCheckHandlerFactory(final @Reference HttpClientFactory httpClientFactory) {
+        this.httpClient = httpClientFactory.getCommonHttpClient();
+    }
+
+    @Override
+    protected @Nullable ThingHandler createHandler(Thing thing) {
+        ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+
+        if (THING_TYPE_LIQUID_CHECK.equals(thingTypeUID)) {
+            return new LiquidCheckHandler(thing, httpClient);
+        }
+
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/discovery/LiquidCheckDiscoveryService.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/discovery/LiquidCheckDiscoveryService.java
new file mode 100644 (file)
index 0000000..13091d7
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.discovery;
+
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.SUPPORTED_THING_TYPES_UIDS;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.THING_TYPE_LIQUID_CHECK;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.http.HttpMethod;
+import org.openhab.binding.liquidcheck.internal.json.CommData;
+import org.openhab.core.config.discovery.AbstractDiscoveryService;
+import org.openhab.core.config.discovery.DiscoveryResult;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.config.discovery.DiscoveryService;
+import org.openhab.core.io.net.http.HttpClientFactory;
+import org.openhab.core.thing.ThingUID;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link LiquidCheckDiscoveryService} class defines discovery service for the LiquidCheckBinding
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.liquidcheck")
+public class LiquidCheckDiscoveryService extends AbstractDiscoveryService {
+
+    private static final int DISCOVER_TIMEOUT_SECONDS = 300;
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+    private final HttpClient httpClient;
+
+    @Activate
+    public LiquidCheckDiscoveryService(@Reference HttpClientFactory httpClientFactory) {
+        super(SUPPORTED_THING_TYPES_UIDS, DISCOVER_TIMEOUT_SECONDS, false);
+        httpClient = httpClientFactory.getCommonHttpClient();
+    }
+
+    /**
+     * Method for starting the scan
+     */
+    @Override
+    protected void startScan() {
+        scheduler.execute(liquidCheckDiscoveryRunnable());
+    }
+
+    /**
+     * Method to stop the scan
+     */
+    @Override
+    protected synchronized void stopScan() {
+        super.stopScan();
+        removeOlderResults(getTimestampOfLastScan());
+    }
+
+    /**
+     * Method for creating a Runnable to start a scan
+     * 
+     * @return the Runnable
+     */
+    protected Runnable liquidCheckDiscoveryRunnable() {
+        return () -> {
+            try {
+                List<InetAddress> addresses = getIPv4Addresses();
+                List<InetAddress> hosts = findActiveHosts(addresses);
+                for (InetAddress host : hosts) {
+                    Request request = httpClient.newRequest("http://" + host.getHostAddress() + "/infos.json")
+                            .method(HttpMethod.GET).followRedirects(false);
+                    try {
+                        ContentResponse response = request.send();
+                        if (response.getStatus() == 200) {
+                            CommData json = null;
+                            try {
+                                json = new Gson().fromJson(response.getContentAsString(), CommData.class);
+                            } catch (JsonSyntaxException e) {
+                                logger.debug("Json Syntax Exception!");
+                            }
+                            if (null != json) {
+                                buildDiscoveryResult(json,
+                                        InetAddress.getByName(json.payload.wifi.station.hostname).isReachable(50));
+                            } else {
+                                logger.debug("Response Object is null!");
+                            }
+                        }
+                    } catch (TimeoutException e) {
+                        logger.debug("TimeOut: {}", e.getMessage());
+                    } catch (ExecutionException e) {
+                        logger.debug("ExecutionException: {}", e.getMessage());
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                    }
+
+                }
+            } catch (IOException e) {
+                logger.debug("Message: {}", e.getMessage());
+            }
+        };
+    }
+
+    /**
+     * This Method retrieves all IPv4 addresses of the server
+     * 
+     * @return A list of all available IPv4 addresses that are registered
+     * @throws SocketException
+     */
+    private List<InetAddress> getIPv4Addresses() throws SocketException {
+        Iterator<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces().asIterator();
+        List<InetAddress> addresses = new ArrayList<>();
+        // Get IPv4 addresses from all network interfaces
+        if (null != networkInterfaces) {
+            while (networkInterfaces.hasNext()) {
+                NetworkInterface currentNetworkInterface = networkInterfaces.next();
+                Iterator<InetAddress> inetAddresses = currentNetworkInterface.getInetAddresses().asIterator();
+                while (inetAddresses.hasNext()) {
+                    InetAddress currentAddress = inetAddresses.next();
+                    if (currentAddress instanceof Inet4Address && !currentAddress.isLoopbackAddress()) {
+                        addresses.add(currentAddress);
+                    }
+                }
+            }
+        }
+        return addresses;
+    }
+
+    /**
+     * This method will find any active host in the network and return a list of them
+     * 
+     * @param addresses
+     * @return List of hosts
+     * @throws UnknownHostException
+     * @throws IOException
+     */
+    private List<InetAddress> findActiveHosts(List<InetAddress> addresses) throws UnknownHostException, IOException {
+        List<InetAddress> hosts = new ArrayList<>();
+        for (InetAddress inetAddress : addresses) {
+            String[] addressStrings = inetAddress.getHostAddress().split("[.]");
+            String subnet = addressStrings[0] + "." + addressStrings[1] + "." + addressStrings[2];
+            int timeout = 50;
+            for (int i = 0; i < 255; i++) {
+                String host = subnet + "." + i;
+                if (!inetAddress.getHostAddress().equals(host)) {
+                    if (InetAddress.getByName(host).isReachable(timeout)) {
+                        hosts.add(InetAddress.getByName(host));
+                    }
+                }
+            }
+        }
+        return hosts;
+    }
+
+    /**
+     * This method builds a thing based on the response from the device
+     * 
+     * @param response
+     */
+    private void buildDiscoveryResult(CommData response, Boolean isHostname) {
+        ThingUID thingUID = new ThingUID(THING_TYPE_LIQUID_CHECK, response.payload.device.uuid);
+        DiscoveryResult dResult = DiscoveryResultBuilder.create(thingUID)
+                .withProperties(response.createPropertyMap(isHostname)).withLabel(response.payload.device.name).build();
+        thingDiscovered(dResult);
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/httpclient/LiquidCheckHttpClient.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/httpclient/LiquidCheckHttpClient.java
new file mode 100644 (file)
index 0000000..2ffa6e2
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.httpclient;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.util.StringContentProvider;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpMethod;
+import org.openhab.binding.liquidcheck.internal.LiquidCheckConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link LiquidCheckHttpClient} sets up the jetty client for the connection to the device.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class LiquidCheckHttpClient {
+
+    private final Logger logger = LoggerFactory.getLogger(LiquidCheckHttpClient.class);
+    private final HttpClient client;
+    private final LiquidCheckConfiguration config;
+
+    public boolean isClosed = false;
+
+    /**
+     * The Constructor of the LiquidCheckHttpClient class will set up a jetty client
+     * 
+     * @param config
+     */
+    public LiquidCheckHttpClient(LiquidCheckConfiguration config, HttpClient client) {
+        this.config = config;
+        this.client = client;
+    }
+
+    /**
+     * The pollData method will poll the data from device
+     * 
+     * @return String with the response of the request
+     * @throws InterruptedException
+     * @throws TimeoutException
+     * @throws ExecutionException
+     */
+    public String pollData() throws InterruptedException, TimeoutException, ExecutionException {
+        String uri = "http://" + config.hostname + "/infos.json";
+        Request request = client.newRequest(uri).method(HttpMethod.GET)
+                .timeout(config.connectionTimeout, TimeUnit.SECONDS).followRedirects(false);
+        logger.debug("Polling for data");
+        ContentResponse response = request.send();
+        return response.getContentAsString();
+    }
+
+    /**
+     * The measureCommand method will start a measurement
+     * 
+     * @return String with response of the request
+     * @throws InterruptedException
+     * @throws TimeoutException
+     * @throws ExecutionException
+     */
+    public String measureCommand() throws InterruptedException, TimeoutException, ExecutionException {
+        String uri = "http://" + config.hostname + "/command";
+        Request request = client.newRequest(uri);
+        request.method(HttpMethod.POST);
+        request.header(HttpHeader.CONTENT_TYPE, "applicaton/json");
+        request.content(new StringContentProvider(
+                "{\"header\":{\"namespace\":\"Device.Control\",\"name\":\"StartMeasure\",\"messageId\":\"1\",\"payloadVersion\":\"1\"},\"payload\":null}"));
+        ContentResponse response = request.send();
+        return response.getContentAsString();
+    }
+
+    /**
+     * The isConnected method will return the state of the http client
+     * 
+     * @return
+     */
+    public boolean isConnected() {
+        String state = this.client.getState();
+        return "STARTED".equals(state);
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/AccessPoint.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/AccessPoint.java
new file mode 100644 (file)
index 0000000..c54dbc6
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link AccessPoint} is used for serializing and deserializing of JSONs.
+ * It contains the data for ssid, bssid and the rssi value.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class AccessPoint {
+    public String ssid = "";
+    public String bssid = "";
+    public int rssi = 0;
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/CommData.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/CommData.java
new file mode 100644 (file)
index 0000000..1dde132
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PROPERTY_HOSTNAME;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PROPERTY_IP;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PROPERTY_NAME;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PROPERTY_SECURITY_CODE;
+import static org.openhab.binding.liquidcheck.internal.LiquidCheckBindingConstants.PROPERTY_SSID;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Thing;
+
+/**
+ * The {@link CommData} is used for serializing and deserializing of JSONs.
+ * It contains the complete communication data with header and payload or context.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+
+@NonNullByDefault
+public class CommData {
+
+    public Header header = new Header();
+    public Payload payload = new Payload();
+    public Context context = new Context();
+
+    public Map<String, String> createPropertyMap() {
+        Map<String, String> properties = new HashMap<>();
+        properties.put(Thing.PROPERTY_FIRMWARE_VERSION, payload.device.firmware);
+        properties.put(Thing.PROPERTY_HARDWARE_VERSION, payload.device.hardware);
+        properties.put(PROPERTY_NAME, payload.device.name);
+        properties.put(Thing.PROPERTY_VENDOR, payload.device.manufacturer);
+        properties.put(Thing.PROPERTY_SERIAL_NUMBER, payload.device.uuid);
+        properties.put(PROPERTY_SECURITY_CODE, payload.device.security.code);
+        properties.put(PROPERTY_IP, payload.wifi.station.ip);
+        properties.put(Thing.PROPERTY_MAC_ADDRESS, payload.wifi.station.mac);
+        properties.put(PROPERTY_SSID, payload.wifi.accessPoint.ssid);
+        return properties;
+    }
+
+    public Map<String, Object> createPropertyMap(boolean isHostname) {
+        Map<String, Object> properties = new HashMap<>(createPropertyMap());
+        if (isHostname) {
+            properties.put(PROPERTY_HOSTNAME, payload.wifi.station.hostname);
+        } else {
+            properties.put(PROPERTY_HOSTNAME, payload.wifi.station.ip);
+        }
+        return properties;
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Context.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Context.java
new file mode 100644 (file)
index 0000000..49f4b46
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Context} is used for serializing and deserializing of JSONs.
+ * It contains the status message.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Context {
+    public String status = "";
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Device.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Device.java
new file mode 100644 (file)
index 0000000..3949d7f
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Device} is used for serializing and deserializing of JSONs.
+ * It contains the device related data like firmware, hardware, name, the model class,
+ * manufacturer, uuid and the security class.
+ * 
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Device {
+    public String firmware = "";
+    public String hardware = "";
+    public String name = "";
+    public Model model = new Model();
+    public String manufacturer = "";
+    public String uuid = "";
+    public Security security = new Security();
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Expansion.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Expansion.java
new file mode 100644 (file)
index 0000000..fdbeb5c
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Expansion} is used for serializing and deserializing of JSONs.
+ * It contains the Expansion related data like boardType, oneWire and board.
+ * 
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Expansion {
+    public int boardType = 0;
+    public String oneWire = "";
+    public String board = "";
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Header.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Header.java
new file mode 100644 (file)
index 0000000..d04319e
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * The {@link Header} class is used for serializing and deserializing of JSONs.
+ * It contains the data lika namespace, name, messageId, payloadVersion and authorization.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Header {
+    @Expose
+    public String namespace = "";
+    @Expose
+    public String name = "";
+    @Expose
+    public String messageId = "";
+    @Expose
+    public String payloadVersion = "";
+
+    public String authorization = "";
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/LiquidCheckSystem.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/LiquidCheckSystem.java
new file mode 100644 (file)
index 0000000..bd4c3a0
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link LiquidCheckSystem} is used for serializing and deserializing of JSONs.
+ * It contains the error counter, the uptime and the pump class.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class LiquidCheckSystem {
+    public int error = 0;
+    public int uptime = 0;
+    public Pump pump = new Pump();
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Measure.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Measure.java
new file mode 100644 (file)
index 0000000..26511f4
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Measure} is used for serializing and deserializing of JSONs.
+ * It contains the measured data like level, content and the raw class and the age of the data.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Measure {
+    public double level = 0.0;
+    public double content = 0.0;
+    public Raw raw = new Raw();
+    public int age = 0;
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Model.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Model.java
new file mode 100644 (file)
index 0000000..33852d9
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Model} is used for serializing and deserializing of JSONs.
+ * It contains the name und the number of the model.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Model {
+    public String name = "";
+    public int number = 0;
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Payload.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Payload.java
new file mode 100644 (file)
index 0000000..9a56106
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Payload} is used for serializing and deserializing of JSONs.
+ * It contains the complete data set within the Measure class, the Expansion class, the Device class, the
+ * LiquidCheckSystem class and the wifi class.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Payload {
+    public Measure measure = new Measure();
+    public Expansion expansion = new Expansion();
+    public Device device = new Device();
+    public LiquidCheckSystem system = new LiquidCheckSystem();
+    public Wifi wifi = new Wifi();
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Pump.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Pump.java
new file mode 100644 (file)
index 0000000..543985b
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Pump} is used for serializing and deserializing of JSONs.
+ * It contains the pump data like total runs and total runtime.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Pump {
+    public int totalRuns = 0;
+    public int totalRuntime = 0;
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Raw.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Raw.java
new file mode 100644 (file)
index 0000000..a5e776d
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Raw} is used for serializing and deserializing of JSONs.
+ * It contains the raw data measured and calculated by the sensor.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Raw {
+    public double level = 0.0000;
+    public double content = 0.0000;
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Security.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Security.java
new file mode 100644 (file)
index 0000000..75a04a5
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Security} is used for serializing and deserializing of JSONs.
+ * It contains the security code for cloud connection of the device.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Security {
+    public String code = "";
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Station.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Station.java
new file mode 100644 (file)
index 0000000..5dcadd5
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Station} is used for serializing and deserializing of JSONs.
+ * It contains the station related data like hostname, ip address, gateway, netmask and mac address.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Station {
+    public String hostname = "";
+    public String ip = "";
+    public String gateway = "";
+    public String netmask = "";
+    public String mac = "";
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Wifi.java b/bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/json/Wifi.java
new file mode 100644 (file)
index 0000000..4880553
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link Wifi} is used for serializing and deserializing of JSONs.
+ * It conatains the wifi related data within the Station class and AccessPoint class.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class Wifi {
+    public Station station = new Station();
+    public AccessPoint accessPoint = new AccessPoint();
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/addon/addon.xml
new file mode 100644 (file)
index 0000000..56623ca
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<addon:addon id="liquidcheck" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
+
+       <type>binding</type>
+       <name>LiquidCheck Binding</name>
+       <description>This is the binding for LiquidCheck devices.</description>
+       <connection>local</connection>
+
+</addon:addon>
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/i18n/liquidcheck.properties b/bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/i18n/liquidcheck.properties
new file mode 100644 (file)
index 0000000..c711f1d
--- /dev/null
@@ -0,0 +1,38 @@
+# add-on
+
+addon.liquidcheck.name = LiquidCheck Binding
+addon.liquidcheck.description = This is the binding for LiquidCheck devices.
+
+# thing types
+
+thing-type.liquidcheck.liquidCheckDevice.label = Liquid Check Device
+
+# thing types config
+
+thing-type.config.liquidcheck.liquidCheckDevice.connectionTimeout.label = Connection Timeout
+thing-type.config.liquidcheck.liquidCheckDevice.connectionTimeout.description = After the given amount of seconds without a response, the connection will be seen as timed out.
+thing-type.config.liquidcheck.liquidCheckDevice.hostname.label = Hostname
+thing-type.config.liquidcheck.liquidCheckDevice.hostname.description = Hostname or IP address of the device.
+thing-type.config.liquidcheck.liquidCheckDevice.maxContent.label = Maximal Content
+thing-type.config.liquidcheck.liquidCheckDevice.maxContent.description = Maximal content in the container.
+thing-type.config.liquidcheck.liquidCheckDevice.refreshInterval.label = Refresh Interval
+thing-type.config.liquidcheck.liquidCheckDevice.refreshInterval.description = Interval the device is polled in seconds.
+
+# channel types
+
+channel-type.liquidcheck.content-channel.label = Content
+channel-type.liquidcheck.content-channel.description = Content in the container
+channel-type.liquidcheck.fill-indicator-channel.label = Fill Indicator
+channel-type.liquidcheck.fill-indicator-channel.description = Indicates the fill level based on max content and measured content
+channel-type.liquidcheck.level-channel.label = Level
+channel-type.liquidcheck.level-channel.description = Level in the container
+channel-type.liquidcheck.measure-channel.label = Measure
+channel-type.liquidcheck.measure-channel.description = Triggers a measurement
+channel-type.liquidcheck.pump-runs-channel.label = Pump Total Runs
+channel-type.liquidcheck.pump-runs-channel.description = Number of pump starts in total
+channel-type.liquidcheck.pump-runtime-channel.label = Pump Total Runtime
+channel-type.liquidcheck.pump-runtime-channel.description = Seconds the pump has runned since manufacturing
+channel-type.liquidcheck.raw-content-channel.label = Content Raw Data
+channel-type.liquidcheck.raw-content-channel.description = Content in the container as measured by the device
+channel-type.liquidcheck.raw-level-channel.label = Level Raw Data
+channel-type.liquidcheck.raw-level-channel.description = Level in the container as measured by the device
diff --git a/bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.liquidcheck/src/main/resources/OH-INF/thing/thing-types.xml
new file mode 100644 (file)
index 0000000..fa4c133
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="liquidcheck"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <thing-type id="liquidCheckDevice">
+               <label>Liquid Check Device</label>
+               <category>Sensor</category>
+
+               <channels>
+                       <channel id="content" typeId="content-channel"/>
+                       <channel id="level" typeId="level-channel"/>
+                       <channel id="fill-indicator" typeId="fill-indicator-channel"/>
+                       <channel id="raw-content" typeId="raw-content-channel"/>
+                       <channel id="raw-level" typeId="raw-level-channel"/>
+                       <channel id="pump-runs" typeId="pump-runs-channel"/>
+                       <channel id="pump-runtime" typeId="pump-runtime-channel"/>
+                       <channel id="measure" typeId="measure-channel"/>
+               </channels>
+
+               <config-description>
+                       <parameter name="hostname" type="text" required="true">
+                               <context>network-address</context>
+                               <label>Hostname</label>
+                               <description>Hostname or IP address of the device.</description>
+                       </parameter>
+                       <parameter name="maxContent" type="integer" unit="l" min="1">
+                               <label>Maximal Content</label>
+                               <description>Maximal content in the container.</description>
+                               <default>1</default>
+                       </parameter>
+                       <parameter name="refreshInterval" type="integer" unit="s" min="1" max="3600">
+                               <label>Refresh Interval</label>
+                               <description>Interval the device is polled in seconds.</description>
+                               <default>60</default>
+                               <advanced>true</advanced>
+                       </parameter>
+                       <parameter name="connectionTimeout" type="integer" unit="s" min="1" max="120">
+                               <label>Connection Timeout</label>
+                               <description>After the given amount of seconds without a response, the connection will be seen as timed out.</description>
+                               <default>5</default>
+                               <advanced>true</advanced>
+                       </parameter>
+               </config-description>
+       </thing-type>
+
+       <channel-type id="content-channel">
+               <item-type>Number:Volume</item-type>
+               <label>Content</label>
+               <description>Content in the container</description>
+               <state readOnly="true" pattern="%d l"/>
+       </channel-type>
+       <channel-type id="raw-content-channel">
+               <item-type>Number:Volume</item-type>
+               <label>Content Raw Data</label>
+               <description>Content in the container as measured by the device</description>
+               <state readOnly="true" pattern="%.4f l"/>
+       </channel-type>
+       <channel-type id="level-channel">
+               <item-type>Number:Length</item-type>
+               <label>Level</label>
+               <description>Level in the container</description>
+               <state readOnly="true" pattern="%.2f m"/>
+       </channel-type>
+       <channel-type id="raw-level-channel">
+               <item-type>Number:Length</item-type>
+               <label>Level Raw Data</label>
+               <description>Level in the container as measured by the device</description>
+               <state readOnly="true" pattern="%.4f m"/>
+       </channel-type>
+       <channel-type id="fill-indicator-channel">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Fill Indicator</label>
+               <description>Indicates the fill level based on max content and measured content</description>
+               <state readOnly="true" pattern="%.1f %%"/>
+       </channel-type>
+       <channel-type id="measure-channel">
+               <item-type>Switch</item-type>
+               <label>Measure</label>
+               <description>Triggers a measurement</description>
+       </channel-type>
+       <channel-type id="pump-runs-channel">
+               <item-type>Number</item-type>
+               <label>Pump Total Runs</label>
+               <description>Number of pump starts in total</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="pump-runtime-channel">
+               <item-type>Number:Time</item-type>
+               <label>Pump Total Runtime</label>
+               <description>Seconds the pump has run since manufacturing</description>
+               <state readOnly="true" pattern="%d s"/>
+       </channel-type>
+</thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.liquidcheck/src/test/java/org/openhab/binding/liquidcheck/internal/json/ResponseTest.java b/bundles/org.openhab.binding.liquidcheck/src/test/java/org/openhab/binding/liquidcheck/internal/json/ResponseTest.java
new file mode 100644 (file)
index 0000000..f61cfef
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.liquidcheck.internal.json;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link ResponseTest} will test the correct parsing from json responses for the CommData class.
+ *
+ * @author Marcel Goerentz - Initial contribution
+ */
+@NonNullByDefault
+public class ResponseTest {
+
+    @DisplayName("Test response from polling")
+    @Test
+    @SuppressWarnings("null")
+    public void pollingResponseTest() {
+        CommData response = new CommData();
+        try {
+            List<String> lines = Files.readAllLines(Paths.get("src/test/resources/PollingResponseExample.json"),
+                    StandardCharsets.UTF_8);
+            StringBuilder sb = new StringBuilder();
+            for (String line : lines) {
+                sb.append(line);
+            }
+            String json = sb.toString();
+            response = new Gson().fromJson(json, CommData.class);
+        } catch (Exception e) {
+            return;
+        }
+        if (response != null && !"".equals(response.header.messageId)) {
+            assertThat(response, is(notNullValue()));
+            assertThat(response.header.namespace, is(equalTo("Device")));
+            assertThat(response.header.name, is(equalTo("Response")));
+            assertThat(response.header.messageId, is(equalTo("499C7D21-F9579A3C")));
+            assertThat(response.header.payloadVersion, is(equalTo("1")));
+            assertThat(response.header.authorization, is(equalTo("1C9DC262BE70-00038BC8-TX0K103HIXCXVLTBMVKVXFF")));
+            assertThat(response.payload.measure.level, is(equalTo(2.23)));
+            assertThat(response.payload.measure.content, is(equalTo(9265.0)));
+            assertThat(response.payload.measure.age, is(equalTo(1981)));
+            assertThat(response.payload.measure.raw.level, is(equalTo(2.2276)));
+            assertThat(response.payload.measure.raw.content, is(equalTo(9255.3193)));
+            assertThat(response.payload.expansion.boardType, is(equalTo(-1)));
+            assertThat(response.payload.expansion.board, is(nullValue()));
+            assertThat(response.payload.expansion.oneWire, is(nullValue()));
+            assertThat(response.payload.device.firmware, is(equalTo("1.60")));
+            assertThat(response.payload.device.hardware, is(equalTo("B5")));
+            assertThat(response.payload.device.name, is(equalTo("Liquid-Check")));
+            assertThat(response.payload.device.manufacturer, is(equalTo("SI-Elektronik GmbH")));
+            assertThat(response.payload.device.uuid, is(equalTo("0ba64a0c-7a88b168-0001")));
+            assertThat(response.payload.device.model.name, is(equalTo("")));
+            assertThat(response.payload.device.model.number, is(equalTo(1)));
+            assertThat(response.payload.device.security.code, is(equalTo("gkzQ5uGo6ElSdUsDWKQu2A==")));
+            assertThat(response.payload.system.error, is(equalTo(0)));
+            assertThat(response.payload.system.uptime, is(equalTo(232392)));
+            assertThat(response.payload.system.pump.totalRuns, is(equalTo(351)));
+            assertThat(response.payload.system.pump.totalRuntime, is(equalTo(1249)));
+            assertThat(response.payload.wifi.station.hostname, is(equalTo("Liquid-Check")));
+            assertThat(response.payload.wifi.station.ip, is(equalTo("192.168.2.102")));
+            assertThat(response.payload.wifi.station.gateway, is(equalTo("192.168.2.1")));
+            assertThat(response.payload.wifi.station.netmask, is(equalTo("255.255.255.0")));
+            assertThat(response.payload.wifi.station.mac, is(equalTo("1C:9D:C2:62:BE:70")));
+            assertThat(response.payload.wifi.accessPoint.ssid, is(equalTo("WLAN-267994")));
+            assertThat(response.payload.wifi.accessPoint.bssid, is(equalTo("4C:09:D4:2B:C3:97")));
+            assertThat(response.payload.wifi.accessPoint.rssi, is(equalTo(-45)));
+        }
+    }
+
+    @DisplayName("Test response from measurement command")
+    @Test
+    public void commandResponseTest() {
+        CommData response = new CommData();
+        try {
+            List<String> lines = Files.readAllLines(Paths.get("src/test/resources/CommandResponseExample.json"),
+                    StandardCharsets.UTF_8);
+            StringBuilder sb = new StringBuilder();
+            for (String line : lines) {
+                sb.append(line);
+            }
+            String json = sb.toString();
+            response = new Gson().fromJson(json, CommData.class);
+        } catch (Exception e) {
+            return;
+        }
+        if (response != null && !"".equals(response.header.messageId)) {
+            assertThat(response, is(notNullValue()));
+            assertThat(response.header.namespace, is(equalTo("Device.Control")));
+            assertThat(response.header.name, is(equalTo("StartMeasure.Response")));
+            assertThat(response.header.messageId, is(equalTo("6D6A415C-A116FF36")));
+            assertThat(response.header.payloadVersion, is(equalTo("1")));
+            assertThat(response.header.authorization, is(equalTo("1C9DC262BE70-001092EA-4D4KU4ID5ZCXPNTQJ3V8HD")));
+            assertThat(response.context.status, is(equalTo("success")));
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/test/resources/CommandResponseExample.json b/bundles/org.openhab.binding.liquidcheck/src/test/resources/CommandResponseExample.json
new file mode 100644 (file)
index 0000000..e7b03a5
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "header":{
+        "namespace":"Device.Control",
+        "name":"StartMeasure.Response",
+        "messageId":"6D6A415C-A116FF36",
+        "payloadVersion":"1",
+        "authorization":"1C9DC262BE70-001092EA-4D4KU4ID5ZCXPNTQJ3V8HD"
+    },
+    "context":{
+        "status" : "success"
+    }
+}
diff --git a/bundles/org.openhab.binding.liquidcheck/src/test/resources/PollingResponseExample.json b/bundles/org.openhab.binding.liquidcheck/src/test/resources/PollingResponseExample.json
new file mode 100644 (file)
index 0000000..68bd171
--- /dev/null
@@ -0,0 +1,62 @@
+{
+    "header":{
+        "namespace":"Device",
+        "name":"Response",
+        "messageId":"499C7D21-F9579A3C",
+        "payloadVersion":"1",
+        "authorization":"1C9DC262BE70-00038BC8-TX0K103HIXCXVLTBMVKVXFF"
+    },
+    "payload":{
+        "measure":{
+            "level":2.23,
+            "content":9265,
+            "raw":{
+                "level":2.2276,
+                "content":9255.3193
+            },
+            "age":1981
+        },
+        "expansion":{
+            "boardType":-1,
+            "oneWire":null,
+            "board":null
+        },
+        "device":{
+            "firmware":"1.60",
+            "hardware":"B5",
+            "name":"Liquid-Check",
+            "model":{
+                "name":"",
+                "number":1
+            },
+            "manufacturer":"SI-Elektronik GmbH",
+            "uuid":"0ba64a0c-7a88b168-0001",
+            "security":{
+                "code":"gkzQ5uGo6ElSdUsDWKQu2A=="
+            }
+        },
+        "system":{
+            "error":0,
+            "uptime":232392,
+            "pump":{
+                "totalRuns":351,
+                "totalRuntime":1249
+            }
+        },
+        "wifi":{
+            "station":{
+                "hostname":"Liquid-Check",
+                "ip":"192.168.2.102",
+                "gateway":"192.168.2.1",
+                "netmask":"255.255.255.0",
+                "mac":"1C:9D:C2:62:BE:70"
+            },
+            "accessPoint":{
+                "ssid":"WLAN-267994",
+                "bssid":"4C:09:D4:2B:C3:97",
+                "rssi":-45
+            }
+        }
+    }
+}
+
index ab2a843d0525dee1e8cae0bcd1ef91211f41665f..6ee1c3186b7daf469a2f78d74d63da51e64b5d9a 100644 (file)
     <module>org.openhab.binding.lifx</module>
     <module>org.openhab.binding.linky</module>
     <module>org.openhab.binding.linuxinput</module>
+    <module>org.openhab.binding.liquidcheck</module>
     <module>org.openhab.binding.lirc</module>
     <module>org.openhab.binding.livisismarthome</module>
     <module>org.openhab.binding.logreader</module>