mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[liquidcheck] Initial contribution (#13287)
* Add new binding liquidcheck Signed-off-by: Marcel Goerentz <m.goerentz@t-online.de>
This commit is contained in:
parent
939c9caa1b
commit
ab16c94ace
@ -175,6 +175,7 @@
|
||||
/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
|
||||
|
@ -871,6 +871,11 @@
|
||||
<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>
|
||||
|
13
bundles/org.openhab.binding.liquidcheck/NOTICE
Normal file
13
bundles/org.openhab.binding.liquidcheck/NOTICE
Normal file
@ -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
|
64
bundles/org.openhab.binding.liquidcheck/README.md
Normal file
64
bundles/org.openhab.binding.liquidcheck/README.md
Normal file
@ -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}
|
||||
```
|
17
bundles/org.openhab.binding.liquidcheck/pom.xml
Normal file
17
bundles/org.openhab.binding.liquidcheck/pom.xml
Normal file
@ -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>
|
@ -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>
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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();
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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 = "";
|
||||
}
|
@ -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();
|
||||
}
|
@ -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>
|
@ -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
|
@ -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>
|
@ -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")));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"header":{
|
||||
"namespace":"Device.Control",
|
||||
"name":"StartMeasure.Response",
|
||||
"messageId":"6D6A415C-A116FF36",
|
||||
"payloadVersion":"1",
|
||||
"authorization":"1C9DC262BE70-001092EA-4D4KU4ID5ZCXPNTQJ3V8HD"
|
||||
},
|
||||
"context":{
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,6 +209,7 @@
|
||||
<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>
|
||||
|
Loading…
Reference in New Issue
Block a user