mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[wolfsmartset] Initial contribution (#10751)
Signed-off-by: Bo Biene <openhab.github@biene.eu>
This commit is contained in:
parent
277c65f43a
commit
8440745ceb
@ -326,6 +326,7 @@
|
||||
/bundles/org.openhab.binding.windcentrale/ @marcelrv
|
||||
/bundles/org.openhab.binding.wlanthermo/ @CSchlipp
|
||||
/bundles/org.openhab.binding.wled/ @Skinah
|
||||
/bundles/org.openhab.binding.wolfsmartset/ @BoBiene
|
||||
/bundles/org.openhab.binding.xmltv/ @clinique
|
||||
/bundles/org.openhab.binding.xmppclient/ @pavel-gololobov
|
||||
/bundles/org.openhab.binding.yamahareceiver/ @davidgraeff @zarusz
|
||||
|
13
bundles/org.openhab.binding.wolfsmartset/NOTICE
Normal file
13
bundles/org.openhab.binding.wolfsmartset/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
|
149
bundles/org.openhab.binding.wolfsmartset/README.md
Normal file
149
bundles/org.openhab.binding.wolfsmartset/README.md
Normal file
@ -0,0 +1,149 @@
|
||||
# Wolf Smartset Binding
|
||||
|
||||
This binding communicates with the www.wolf-smartset.de API and provides values readonly.
|
||||
Wolf systems are connected with official gateways (Wolf Link Home or Wolf Link Pro) https://www.wolf.eu/produkte/smarthome/
|
||||
|
||||
## Supported Things
|
||||
|
||||
- Account (``thing-type:wolfsmartset:account``)
|
||||
* holding the credentials to connect to the wolf-smartset online portal.
|
||||
- System (``thing-type:wolfsmartset:system``)
|
||||
* represents one wolf system connected to the wolf-smartset online portal.
|
||||
- Unit (``thing-type:wolfsmartset:unit``)
|
||||
* unit is a part of the system with values and parameter
|
||||
|
||||
## Discovery
|
||||
|
||||
- System things (bridge) are discovered after Account thing (bridge) is set up
|
||||
- Unit things are discovered after System things are set up
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
### Account (bridge)
|
||||
|
||||
The account thing holds the credentials to connect to the wolf-smartset online portal.
|
||||
|
||||
| Parameter | Type | Defaut | Description |
|
||||
|-----------------|---------|----------|---------------------------------------------------------------------|
|
||||
| username | text | | username to authenticate to www.wolf-smartset.de |
|
||||
| password | text | | password to authenticate to www.wolf-smartset.de |
|
||||
| refreshIntervalStructure | integer | 10 | Specifies the refresh interval to refresh the Structure in minutes |
|
||||
| refreshIntervalValues | integer | 15 | Specifies time in seconds to refresh values |
|
||||
| discoveryEnabled | boolean | true | disable the Thing discovery |
|
||||
|
||||
### System (bridge)
|
||||
|
||||
The system thing represents one wolf system connected via a WOLF Link home or a WOLF Link pro to the wolf-smartset online portal.
|
||||
You have access to your own or to shared systems.
|
||||
|
||||
| Parameter | Type | Defaut | Description |
|
||||
|-----------------|---------|----------|---------------------------------------------------------------------|
|
||||
| systemId | integer | | System ID assigned to the system by WolfSmartset |
|
||||
|
||||
### Unit
|
||||
|
||||
A system is divided into different units.
|
||||
In the wolf-smartset portal, the system has an "Expert" section, each submenu item within the "Expert" section has multiple tabs.
|
||||
Each of these tabs is treated as one unit.
|
||||
|
||||
| Parameter | Type | Defaut | Description |
|
||||
|-----------------|---------|----------|---------------------------------------------------------------------|
|
||||
| unitId | integer | | The BundleId assigned to the unit by WolfSmartset |
|
||||
|
||||
## Tested WOLF-Devices
|
||||
|
||||
| WOLF Equipment | openhab Version | Used gateway |
|
||||
|-------------------|-----------------|---------------|
|
||||
| CSZ (CGB and SM1) | 3.1 | WOLF Link Pro |
|
||||
| CGB-2 | 3.1 | WOLF Link home|
|
||||
|
||||
|
||||
## Channels
|
||||
|
||||
| channel | type | description |
|
||||
|----------|--------|------------------------------|
|
||||
| number | Number | a generic number |
|
||||
| contact | Contact | a generic contact |
|
||||
| temperature | Number:Temperature | a generic temperature |
|
||||
| string | String | a generic String |
|
||||
| datetime | DateTime | a generic DateTime |
|
||||
|
||||
## Full Example
|
||||
|
||||
### Things
|
||||
|
||||
````
|
||||
Bridge wolfsmartset:account:account "Wolf Smartset Account" [ username="User", password="Password" ] {
|
||||
Bridge system 32122305166 "WolfSmartset System CSZ" [ systemId="32122305166" ] {
|
||||
Thing unitId uinit0 "CSZ Heizgerät" [ unitId="unit0" ] {
|
||||
}
|
||||
}
|
||||
}
|
||||
````
|
||||
_You need to use the corrosponding systemId and unitId returned by the discovery_
|
||||
|
||||
### Items
|
||||
|
||||
````
|
||||
"Number CSZHeizgerat_Raumtemperatur "Raumtemperatur" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900000"}
|
||||
Number CSZHeizgerat_Flamme "Flamme" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900001"}
|
||||
Number CSZHeizgerat_AnalogeFernbedienung "Analoge Fernbedienung" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900002"}
|
||||
Number CSZHeizgerat_Raumsolltemperatur "Raumsolltemperatur" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900003"}
|
||||
Number CSZHeizgerat_AusgangA1 "Ausgang A1" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900004"}
|
||||
String CSZHeizgerat_ZeitprogrammdirekterHeizkreis "Zeitprogramm direkter Heizkreis" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900005"}
|
||||
Number CSZHeizgerat_Ventil1 "Ventil 1" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900006"}
|
||||
Number CSZHeizgerat_Ventil2 "Ventil 2" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900007"}
|
||||
Number CSZHeizgerat_WiSoUmschaltung "Wi/So Umschaltung" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900008"}
|
||||
Number CSZHeizgerat_Tagtemperatur "Tagtemperatur" { channel="wolfsmartset:unit:account:32122305166:uinit0:1000900009"}
|
||||
Number CSZHeizgerat_PWMPumpe "PWM Pumpe" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000010"}
|
||||
Number CSZHeizgerat_Speichersolltemperatur "Speichersolltemperatur" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000011"}
|
||||
Number CSZHeizgerat_Heizkurve "Heizkurve" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000012"}
|
||||
Number CSZHeizgerat_Raumeinfluss "Raumeinfluss" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000013"}
|
||||
Number CSZHeizgerat_TWVorlauf "TW-Vorlauf" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000014"}
|
||||
Number CSZHeizgerat_Spartemperatur "Spartemperatur" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000015"}
|
||||
Number CSZHeizgerat_Geblase "Gebläse" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000016"}
|
||||
Number CSZHeizgerat_Vorlaufsolltemperatur "Vorlaufsolltemperatur" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000017"}
|
||||
Group CSZHeizgerat "CSZ Heizgerät" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000018"}
|
||||
Number CSZHeizgerat_ECOABS "ECO/ABS" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000019"}
|
||||
Number CSZHeizgerat_Netzbetriebstunden "Netzbetriebstunden" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000020"}
|
||||
Number CSZHeizgerat_TWAbgas "TW-Abgas" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000021"}
|
||||
Number CSZHeizgerat_HGStatus "HG Status" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000022"}
|
||||
Number CSZHeizgerat_EingangE1 "Eingang E1" { channel="wolfsmartset:unit:account:32122305166:uinit0:10009000023"}"
|
||||
````
|
||||
|
||||
## Supported Heating-Devices
|
||||
|
||||
All devices able to be connected to www.wolf-smartset.de
|
||||
|
||||
### Related Documentation from WOLF
|
||||
|
||||
https://www.wolf.eu/fileadmin/Wolf_Daten/Dokumente/FAQ/3065655_201711.pdf
|
||||
|
||||
| Heating system | WOLF Link home | WOLF Link pro |
|
||||
|-------------------------------------------|-----------------------|--------------------|
|
||||
| Gas condensing boiler CGB-2, CGW-2, CGS-2 | ✅ | ✅ |
|
||||
| Oil condensing boiler TOB | ✅ | ✅ |
|
||||
| MGK-2 gas condensing boiler | ✅ | ✅ |
|
||||
| split air/water heat pump BWL-1S | ✅ | ✅ |
|
||||
| Oil condensing boiler COB | | ✅ |
|
||||
| gas condensing boiler MGK | | ✅ |
|
||||
| Gas condensing boilers CGB, CGW, CGS, FGB | | ✅ |
|
||||
| Gas condensing boilers CGG-2, CGU-2 | | ✅ |
|
||||
| Boiler controls R2, R3, R21 | | ✅ |
|
||||
| Monobloc heat pumps BWW-1, BWL-1, BWS-1 | | ✅ |
|
||||
| mixer module MM, MM-2 | ⬜ | ✅ |
|
||||
| cascade module KM, KM-2 | ⬜ | ✅ |
|
||||
| solar modules SM1, SM1-2, SM-2, SM2-2 | ⬜ | ✅ |
|
||||
| Comfort apartment ventilation CWL Excellent | ⬜ | ✅ |
|
||||
| Air handling units KG Top, CKL Pool``*`` | | ✅ |
|
||||
| Air handling units CKL, CFL, CRL``*`` | | ✅ |
|
||||
| Combined heat and power units | | ✅ |
|
||||
|
||||
|
||||
Note:
|
||||
|
||||
⬜ possible in connection with a WOLF Link home compatible heater,
|
||||
full functionality only for devices with current software version.
|
||||
|
||||
``*`` Modbus interface required in the device,
|
||||
Special programming cannot be mapped.
|
17
bundles/org.openhab.binding.wolfsmartset/pom.xml
Normal file
17
bundles/org.openhab.binding.wolfsmartset/pom.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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>3.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.wolfsmartset</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: WolfSmartset Binding</name>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.wolfsmartset-${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-wolfsmartset" description="Wolf Smartset Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.wolfsmartset/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.SubMenuEntryWithMenuItemTabView;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetBindingConstants} class defines common constants that are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "wolfsmartset";
|
||||
|
||||
// Account bridge
|
||||
public static final String THING_TYPE_ACCOUNT = "account";
|
||||
public static final ThingTypeUID UID_ACCOUNT_BRIDGE = new ThingTypeUID(BINDING_ID, THING_TYPE_ACCOUNT);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_ACCOUNT_BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(UID_ACCOUNT_BRIDGE).collect(Collectors.toSet()));
|
||||
|
||||
// System bridge
|
||||
public static final String THING_TYPE_SYSTEM = "system";
|
||||
public static final ThingTypeUID UID_SYSTEM_BRIDGE = new ThingTypeUID(BINDING_ID, THING_TYPE_SYSTEM);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_SYSTEM_BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(UID_SYSTEM_BRIDGE).collect(Collectors.toSet()));
|
||||
|
||||
// unit thing
|
||||
public static final String THING_TYPE_UNIT = "unit";
|
||||
public static final ThingTypeUID UID_UNIT_THING = new ThingTypeUID(BINDING_ID, THING_TYPE_UNIT);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_UNIT_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(UID_UNIT_THING).collect(Collectors.toSet()));
|
||||
|
||||
// Collection of system and unit thing types
|
||||
public static final Set<ThingTypeUID> SUPPORTED_SYSTEM_AND_UNIT_THING_TYPES_UIDS = Stream
|
||||
.concat(SUPPORTED_SYSTEM_BRIDGE_THING_TYPES_UIDS.stream(), SUPPORTED_UNIT_THING_TYPES_UIDS.stream())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// Collection of all supported thing types
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
|
||||
Stream.of(UID_ACCOUNT_BRIDGE, UID_SYSTEM_BRIDGE, UID_UNIT_THING).collect(Collectors.toSet()));
|
||||
|
||||
// System Properties
|
||||
public static final String THING_PROPERTY_GATEWAY_ID = "GatewayId";
|
||||
public static final String THING_PROPERTY_GATEWAY_USERNAME = "GatewayUsername";
|
||||
public static final String THING_PROPERTY_INSTALLATION_DATE = "InstallationDate";
|
||||
public static final String THING_PROPERTY_LOCATION = "Location";
|
||||
public static final String THING_PROPERTY_OPERATOR_NAME = "OperatorName";
|
||||
public static final String THING_PROPERTY_USERNAME_OWNER = "UserNameOwner";
|
||||
public static final String THING_PROPERTY_ACCESSLEVEL = "AccessLevel";
|
||||
|
||||
public static final String CH_TEMPERATURE = "temperature";
|
||||
public static final String CH_PRESSURE = "barometric-pressure";
|
||||
public static final String CH_STRING = "string";
|
||||
public static final String CH_CONTACT = "contact";
|
||||
public static final String CH_NUMBER = "number";
|
||||
public static final String CH_DATETIME = "datetime";
|
||||
|
||||
// Background discovery frequency
|
||||
public static final int DISCOVERY_INTERVAL_SECONDS = 300;
|
||||
public static final int DISCOVERY_INITIAL_DELAY_SECONDS = 10;
|
||||
|
||||
// System bridge and remote unit thing config parameters
|
||||
public static final String CONFIG_SYSTEM_ID = "systemId";
|
||||
public static final String CONFIG_UNIT_ID = "unitId";
|
||||
|
||||
public static final List<SubMenuEntryWithMenuItemTabView> EMPTY_UNITS = Collections
|
||||
.<SubMenuEntryWithMenuItemTabView> emptyList();
|
||||
public static final List<GetSystemListDTO> EMPTY_SYSTEMS = Collections.<GetSystemListDTO> emptyList();
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal;
|
||||
|
||||
import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.wolfsmartset.internal.handler.WolfSmartsetAccountBridgeHandler;
|
||||
import org.openhab.binding.wolfsmartset.internal.handler.WolfSmartsetSystemBridgeHandler;
|
||||
import org.openhab.binding.wolfsmartset.internal.handler.WolfSmartsetUnitThingHandler;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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 WolfSmartsetHandlerFactory} is responsible for creating thing handlers
|
||||
* for the account bridge, system bridge, and unit thing.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.wolfsmartset", service = ThingHandlerFactory.class)
|
||||
public class WolfSmartsetHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public WolfSmartsetHandlerFactory(@Reference HttpClientFactory httpClientFactory) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (SUPPORTED_ACCOUNT_BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new WolfSmartsetAccountBridgeHandler((Bridge) thing, httpClient);
|
||||
}
|
||||
if (SUPPORTED_SYSTEM_BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new WolfSmartsetSystemBridgeHandler((Bridge) thing);
|
||||
}
|
||||
if (SUPPORTED_UNIT_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new WolfSmartsetUnitThingHandler(thing);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,610 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.api;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
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.eclipse.jetty.client.HttpResponseException;
|
||||
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.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.CreateSession2DTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetGuiDescriptionForGatewayDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetParameterValuesDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemStateListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.LoginResponseDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.ReadFaultMessagesDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetCloudConnector} class is used for connecting to the Wolf Smartset cloud service
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetApi {
|
||||
private static final int MAX_QUEUE_SIZE = 1000; // maximum queue size
|
||||
private static final int REQUEST_TIMEOUT_SECONDS = 10;
|
||||
|
||||
private static final DateTimeFormatter SESSION_TIME_STAMP = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private static final String WOLF_API_URL = "https://www.wolf-smartset.com/portal/";
|
||||
|
||||
private Instant blockRequestsUntil = Instant.now();
|
||||
private String username;
|
||||
private String password;
|
||||
private String serviceToken = "";
|
||||
private @Nullable CreateSession2DTO session = null;
|
||||
private int loginFailedCounter = 0;
|
||||
private HttpClient httpClient;
|
||||
private int delay = 500; // in ms
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final Gson gson = new GsonBuilder().serializeNulls().create();
|
||||
private final LinkedBlockingQueue<RequestQueueEntry> requestQueue = new LinkedBlockingQueue<>(MAX_QUEUE_SIZE);
|
||||
private @Nullable ScheduledFuture<?> processJob;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WolfSmartsetApi.class);
|
||||
|
||||
public WolfSmartsetApi(String username, String password, HttpClient httpClient, ScheduledExecutorService scheduler)
|
||||
throws WolfSmartsetCloudException {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.httpClient = httpClient;
|
||||
this.scheduler = scheduler;
|
||||
if (!checkCredentials()) {
|
||||
throw new WolfSmartsetCloudException("username or password can't be empty");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Login to wolf smartset. Returns true if valid token is available, otherwise tries to authenticate with
|
||||
* wolf smartset portal
|
||||
*/
|
||||
public synchronized boolean login() {
|
||||
if (!checkCredentials()) {
|
||||
return false;
|
||||
}
|
||||
if (!serviceToken.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
logger.debug("Wolf Smartset login with username {}", username);
|
||||
try {
|
||||
loginRequest();
|
||||
loginFailedCounter = 0;
|
||||
this.session = getCreateSession();
|
||||
if (this.session != null) {
|
||||
logger.debug("login successful, browserSessionId {}", session.getBrowserSessionId());
|
||||
return true;
|
||||
} else {
|
||||
loginFailedCounter++;
|
||||
this.session = null;
|
||||
logger.trace("Login succeeded but failed to create session {}", loginFailedCounter);
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch (WolfSmartsetCloudException e) {
|
||||
logger.debug("Error logging on to Wolf Smartset ({}): {}", loginFailedCounter, e.getMessage());
|
||||
loginFailedCounter++;
|
||||
serviceToken = "";
|
||||
loginFailedCounterCheck();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the systems available for the authenticated account
|
||||
*
|
||||
* @return a list of the available systems
|
||||
*/
|
||||
public List<GetSystemListDTO> getSystems() {
|
||||
final String response = getSystemString();
|
||||
List<GetSystemListDTO> devicesList = new ArrayList<>();
|
||||
try {
|
||||
GetSystemListDTO[] cdl = gson.fromJson(response, GetSystemListDTO[].class);
|
||||
if (cdl != null) {
|
||||
for (GetSystemListDTO system : cdl) {
|
||||
devicesList.add(system);
|
||||
}
|
||||
}
|
||||
} catch (JsonSyntaxException | IllegalStateException | ClassCastException e) {
|
||||
loginFailedCounter++;
|
||||
logger.warn("Error while parsing devices: {}", e.getMessage());
|
||||
}
|
||||
return devicesList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the description of the given system
|
||||
*
|
||||
* @param systemId the id of the system
|
||||
* @param gatewayId the id of the gateway the system relates to
|
||||
* @return dto describing the requested system
|
||||
*/
|
||||
public @Nullable GetGuiDescriptionForGatewayDTO getSystemDescription(Integer systemId, Integer gatewayId) {
|
||||
final String response = getSystemDescriptionString(systemId, gatewayId);
|
||||
GetGuiDescriptionForGatewayDTO deviceDescription = null;
|
||||
try {
|
||||
deviceDescription = gson.fromJson(response, GetGuiDescriptionForGatewayDTO.class);
|
||||
} catch (JsonSyntaxException | IllegalStateException | ClassCastException e) {
|
||||
loginFailedCounter++;
|
||||
logger.warn("Error while parsing device descriptions: {}", e.getMessage());
|
||||
}
|
||||
return deviceDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the system state of the given systems
|
||||
*
|
||||
* @param systems a list of {@link GetSystemListDTO}
|
||||
* @return the {@link GetSystemStateListDTO} descibing the state of the given {@link GetSystemListDTO} items
|
||||
*/
|
||||
public @Nullable GetSystemStateListDTO @Nullable [] getSystemState(Collection<@Nullable GetSystemListDTO> systems) {
|
||||
final String response = getSystemStateString(systems);
|
||||
GetSystemStateListDTO[] systemState = null;
|
||||
try {
|
||||
systemState = gson.fromJson(response, GetSystemStateListDTO[].class);
|
||||
} catch (JsonSyntaxException | IllegalStateException | ClassCastException e) {
|
||||
loginFailedCounter++;
|
||||
logger.warn("Error while parsing device descriptions: {}", e.getMessage());
|
||||
}
|
||||
if (systemState != null && systemState.length >= 1) {
|
||||
return systemState;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the fault messages of the given system
|
||||
*
|
||||
* @param systemId the id of the system
|
||||
* @param gatewayId the id of the gateway the system relates to
|
||||
* @return {@link ReadFaultMessagesDTO} containing the faultmessages
|
||||
*/
|
||||
public @Nullable ReadFaultMessagesDTO getFaultMessages(Integer systemId, Integer gatewayId) {
|
||||
final String response = getFaultMessagesString(systemId, gatewayId);
|
||||
ReadFaultMessagesDTO faultMessages = null;
|
||||
try {
|
||||
faultMessages = gson.fromJson(response, ReadFaultMessagesDTO.class);
|
||||
} catch (JsonSyntaxException | IllegalStateException | ClassCastException e) {
|
||||
loginFailedCounter++;
|
||||
logger.warn("Error while parsing faultmessages: {}", e.getMessage());
|
||||
}
|
||||
return faultMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the current values for a unit associated with the given system.
|
||||
* if lastAccess is not null, only value changes newer than the given timestamp are returned
|
||||
*
|
||||
* @param systemId the id of the system
|
||||
* @param gatewayId the id of the gateway the system relates to
|
||||
* @param bundleId the id of the Unit
|
||||
* @param valueIdList list of the values to request
|
||||
* @param lastAccess timestamp of the last valid value request
|
||||
* @return {@link GetParameterValuesDTO} containing the requested values
|
||||
*/
|
||||
public @Nullable GetParameterValuesDTO getGetParameterValues(Integer systemId, Integer gatewayId, Long bundleId,
|
||||
List<Long> valueIdList, @Nullable Instant lastAccess) {
|
||||
final String response = getGetParameterValuesString(systemId, gatewayId, bundleId, valueIdList, lastAccess);
|
||||
GetParameterValuesDTO parameterValues = null;
|
||||
try {
|
||||
parameterValues = gson.fromJson(response, GetParameterValuesDTO.class);
|
||||
} catch (JsonSyntaxException | IllegalStateException | ClassCastException e) {
|
||||
loginFailedCounter++;
|
||||
logger.warn("Error while parsing device parameter values: {}", e.getMessage());
|
||||
}
|
||||
return parameterValues;
|
||||
}
|
||||
|
||||
public void stopRequestQueue() {
|
||||
try {
|
||||
stopProcessJob();
|
||||
requestQueue.forEach(queueEntry -> queueEntry.future.completeExceptionally(new CancellationException()));
|
||||
} catch (Exception e) {
|
||||
logger.debug("Error stopping request queue background processing:{}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new delay
|
||||
*
|
||||
* @param delay in ms between to requests
|
||||
*/
|
||||
private void setDelay(int delay) {
|
||||
if (delay < 0) {
|
||||
throw new IllegalArgumentException("Delay needs to be larger or equal to zero");
|
||||
}
|
||||
this.delay = delay;
|
||||
stopProcessJob();
|
||||
if (delay != 0) {
|
||||
processJob = scheduler.scheduleWithFixedDelay(() -> processQueue(), 0, delay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkCredentials() {
|
||||
if (username.trim().isEmpty() || password.trim().isEmpty()) {
|
||||
logger.debug("Wolf Smartset: username or password missing.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getCreateSessionString() {
|
||||
String resp = "";
|
||||
try {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("Timestamp", SESSION_TIME_STAMP.format(LocalDateTime.now()));
|
||||
resp = requestPOST("api/portal/CreateSession2", json).get();
|
||||
logger.trace("api/portal/CreateSession2 response: {}", resp);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
logger.warn("getSystemStateString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
} catch (WolfSmartsetCloudException e) {
|
||||
logger.debug("getSystemStateString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
private @Nullable CreateSession2DTO getCreateSession() {
|
||||
final String response = getCreateSessionString();
|
||||
CreateSession2DTO session = null;
|
||||
try {
|
||||
session = gson.fromJson(response, CreateSession2DTO.class);
|
||||
} catch (JsonSyntaxException | IllegalStateException | ClassCastException e) {
|
||||
loginFailedCounter++;
|
||||
logger.warn("getCreateSession failed with {}: {}", e.getCause(), e.getMessage());
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
private String getSystemString() {
|
||||
String resp = "";
|
||||
try {
|
||||
resp = requestGET("api/portal/GetSystemList").get();
|
||||
logger.trace("api/portal/GetSystemList response: {}", resp);
|
||||
} catch (InterruptedException | ExecutionException | WolfSmartsetCloudException e) {
|
||||
logger.warn("getSystemString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private String getSystemDescriptionString(Integer systemId, Integer gatewayId) {
|
||||
String resp = "";
|
||||
try {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("SystemId", systemId.toString());
|
||||
params.put("GatewayId", gatewayId.toString());
|
||||
resp = requestGET("api/portal/GetGuiDescriptionForGateway", params).get();
|
||||
logger.trace("api/portal/GetGuiDescriptionForGateway response: {}", resp);
|
||||
} catch (InterruptedException | ExecutionException | WolfSmartsetCloudException e) {
|
||||
logger.warn("getSystemDescriptionString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private String getSystemStateString(Collection<@Nullable GetSystemListDTO> systems) {
|
||||
String resp = "";
|
||||
try {
|
||||
JsonArray jsonSystemList = new JsonArray();
|
||||
|
||||
for (@Nullable
|
||||
GetSystemListDTO system : systems) {
|
||||
if (system != null) {
|
||||
JsonObject jsonSystem = new JsonObject();
|
||||
jsonSystem.addProperty("SystemId", system.getId());
|
||||
jsonSystem.addProperty("GatewayId", system.getGatewayId());
|
||||
|
||||
if (system.getSystemShareId() != null) {
|
||||
jsonSystem.addProperty("SystemShareId", system.getSystemShareId());
|
||||
}
|
||||
jsonSystemList.add(jsonSystem);
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject json = new JsonObject();
|
||||
|
||||
json.add("SystemList", jsonSystemList);
|
||||
resp = requestPOST("api/portal/GetSystemStateList", json).get();
|
||||
logger.trace("api/portal/GetSystemStateList response: {}", resp);
|
||||
} catch (InterruptedException | ExecutionException | WolfSmartsetCloudException e) {
|
||||
logger.warn("getSystemStateString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private String getFaultMessagesString(Integer systemId, Integer gatewayId) {
|
||||
String resp = "";
|
||||
try {
|
||||
JsonObject json = new JsonObject();
|
||||
|
||||
json.addProperty("SystemId", systemId);
|
||||
json.addProperty("GatewayId", gatewayId);
|
||||
resp = requestPOST("api/portal/ReadFaultMessages", json).get();
|
||||
logger.trace("api/portal/ReadFaultMessages response: {}", resp);
|
||||
} catch (InterruptedException | ExecutionException | WolfSmartsetCloudException e) {
|
||||
logger.warn("getFaultMessagesString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private String getGetParameterValuesString(Integer systemId, Integer gatewayId, Long bundleId,
|
||||
List<Long> valueIdList, @Nullable Instant lastAccess) {
|
||||
String resp = "";
|
||||
try {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("SystemId", systemId);
|
||||
json.addProperty("GatewayId", gatewayId);
|
||||
json.addProperty("BundleId", bundleId);
|
||||
json.addProperty("IsSubBundle", false);
|
||||
json.add("ValueIdList", gson.toJsonTree(valueIdList));
|
||||
if (lastAccess != null) {
|
||||
json.addProperty("LastAccess", DateTimeFormatter.ISO_INSTANT.format(lastAccess));
|
||||
} else {
|
||||
json.addProperty("LastAccess", (String) null);
|
||||
}
|
||||
json.addProperty("GuiIdChanged", false);
|
||||
if (session != null) {
|
||||
json.addProperty("SessionId", session.getBrowserSessionId());
|
||||
}
|
||||
resp = requestPOST("api/portal/GetParameterValues", json).get();
|
||||
logger.trace("api/portal/GetParameterValues response: {}", resp);
|
||||
} catch (InterruptedException | ExecutionException | WolfSmartsetCloudException e) {
|
||||
logger.warn("getGetParameterValuesString failed with {}: {}", e.getCause(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private CompletableFuture<String> requestGET(String url) throws WolfSmartsetCloudException {
|
||||
return requestGET(url, new HashMap<String, String>());
|
||||
}
|
||||
|
||||
private CompletableFuture<String> requestGET(String url, Map<String, String> params)
|
||||
throws WolfSmartsetCloudException {
|
||||
return rateLimtedRequest(() -> {
|
||||
if (this.serviceToken.isEmpty()) {
|
||||
throw new WolfSmartsetCloudException("Cannot execute request. service token missing");
|
||||
}
|
||||
loginFailedCounterCheck();
|
||||
|
||||
var requestUrl = WOLF_API_URL + url;
|
||||
Request request = httpClient.newRequest(requestUrl).timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
// using HTTP GET with ContentType application/x-www-form-urlencoded like the iOS App does
|
||||
request.header(HttpHeader.AUTHORIZATION, serviceToken);
|
||||
request.method(HttpMethod.GET);
|
||||
request.header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
|
||||
for (Entry<String, String> entry : params.entrySet()) {
|
||||
logger.debug("Send request param: {}={} to {}", entry.getKey(), entry.getValue().toString(), url);
|
||||
request.param(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return request;
|
||||
});
|
||||
}
|
||||
|
||||
private CompletableFuture<String> requestPOST(String url, JsonElement json) throws WolfSmartsetCloudException {
|
||||
return rateLimtedRequest(() -> {
|
||||
if (this.serviceToken.isEmpty()) {
|
||||
throw new WolfSmartsetCloudException("Cannot execute request. service token missing");
|
||||
}
|
||||
loginFailedCounterCheck();
|
||||
|
||||
var request = createPOSTRequest(url, json);
|
||||
request.header(HttpHeader.AUTHORIZATION, serviceToken);
|
||||
return request;
|
||||
});
|
||||
}
|
||||
|
||||
private Request createPOSTRequest(String url, JsonElement json) {
|
||||
var requestUrl = WOLF_API_URL + url;
|
||||
Request request = httpClient.newRequest(requestUrl).timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
request.header(HttpHeader.ACCEPT, "application/json");
|
||||
request.header(HttpHeader.CONTENT_TYPE, "application/json");
|
||||
request.method(HttpMethod.POST);
|
||||
|
||||
request.content(new StringContentProvider(json.toString()), "application/json");
|
||||
return request;
|
||||
}
|
||||
|
||||
private CompletableFuture<String> rateLimtedRequest(SupplyRequestFunctionalInterface buildRequest) {
|
||||
// if no delay is set, return a completed CompletableFuture
|
||||
CompletableFuture<String> future = new CompletableFuture<>();
|
||||
RequestQueueEntry queueEntry = new RequestQueueEntry(buildRequest, future);
|
||||
|
||||
if (delay == 0) {
|
||||
queueEntry.completeFuture((r) -> this.getResponse(r));
|
||||
} else {
|
||||
if (!requestQueue.offer(queueEntry)) {
|
||||
future.completeExceptionally(new RejectedExecutionException("Maximum queue size exceeded."));
|
||||
}
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
private void stopProcessJob() {
|
||||
ScheduledFuture<?> processJob = this.processJob;
|
||||
if (processJob != null) {
|
||||
processJob.cancel(false);
|
||||
this.processJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void processQueue() {
|
||||
// No new Requests until blockRequestsUntil, is set when recieved HttpStatus.TOO_MANY_REQUESTS_429
|
||||
if (blockRequestsUntil.isBefore(Instant.now())) {
|
||||
RequestQueueEntry queueEntry = requestQueue.poll();
|
||||
if (queueEntry != null) {
|
||||
queueEntry.completeFuture((r) -> this.getResponse(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface SupplyRequestFunctionalInterface {
|
||||
Request get() throws WolfSmartsetCloudException;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface GetResponseFunctionalInterface {
|
||||
String get(Request request) throws WolfSmartsetCloudException;
|
||||
}
|
||||
|
||||
private String getResponse(Request request) throws WolfSmartsetCloudException {
|
||||
try {
|
||||
logger.debug("execute request {} {}", request.getMethod(), request.getURI());
|
||||
final ContentResponse response = request.send();
|
||||
if (response.getStatus() == HttpStatus.NOT_FOUND_404) {
|
||||
throw new WolfSmartsetCloudException("Invalid request, not found " + request.getURI());
|
||||
} else if (response.getStatus() == HttpStatus.TOO_MANY_REQUESTS_429) {
|
||||
blockRequestsUntil = Instant.now().plusSeconds(30);
|
||||
throw new WolfSmartsetCloudException("Error too many requests: " + response.getContentAsString());
|
||||
} else if (response.getStatus() >= HttpStatus.BAD_REQUEST_400
|
||||
&& response.getStatus() < HttpStatus.INTERNAL_SERVER_ERROR_500) {
|
||||
this.serviceToken = "";
|
||||
logger.debug("Status {} while executing request to {} :{}", response.getStatus(), request.getURI(),
|
||||
response.getContentAsString());
|
||||
} else {
|
||||
return response.getContentAsString();
|
||||
}
|
||||
} catch (HttpResponseException e) {
|
||||
serviceToken = "";
|
||||
logger.debug("Error while executing request to {} :{}", request.getURI(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException /* | IOException */ e) {
|
||||
logger.debug("Error while executing request to {} :{}", request.getURI(), e.getMessage());
|
||||
loginFailedCounter++;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void loginFailedCounterCheck() {
|
||||
if (loginFailedCounter > 10) {
|
||||
logger.debug("Repeated errors logging on to Wolf Smartset");
|
||||
serviceToken = "";
|
||||
loginFailedCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void loginRequest() throws WolfSmartsetCloudException {
|
||||
try {
|
||||
setDelay(delay);
|
||||
logger.trace("Wolf Smartset Login");
|
||||
|
||||
String url = WOLF_API_URL + "connect/token";
|
||||
Request request = httpClient.POST(url).timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
request.header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
|
||||
// Building Request body exacly the way the iOS App did this
|
||||
var encodedUser = URLEncoder.encode(username, StandardCharsets.UTF_8);
|
||||
var encodedPassword = URLEncoder.encode(password, StandardCharsets.UTF_8);
|
||||
var authRequestBody = "grant_type=password&username=" + encodedUser + "&password=" + encodedPassword;
|
||||
|
||||
request.content(new StringContentProvider("application/x-www-form-urlencoded", authRequestBody,
|
||||
StandardCharsets.UTF_8));
|
||||
|
||||
final ContentResponse response;
|
||||
response = request.send();
|
||||
|
||||
final String content = response.getContentAsString();
|
||||
logger.trace("Wolf smartset Login response= {}", response);
|
||||
logger.trace("Wolf smartset Login content= {}", content);
|
||||
|
||||
switch (response.getStatus()) {
|
||||
case HttpStatus.FORBIDDEN_403:
|
||||
throw new WolfSmartsetCloudException(
|
||||
"Access denied. Did you set the correct password and/or username?");
|
||||
case HttpStatus.OK_200:
|
||||
LoginResponseDTO jsonResp = gson.fromJson(content, LoginResponseDTO.class);
|
||||
if (jsonResp == null) {
|
||||
throw new WolfSmartsetCloudException("Error getting logon details: " + content);
|
||||
}
|
||||
|
||||
serviceToken = jsonResp.getTokenType() + " " + jsonResp.getAccessToken();
|
||||
|
||||
logger.trace("Wolf Smartset login scope = {}", jsonResp.getScope());
|
||||
logger.trace("Wolf Smartset login expiresIn = {}", jsonResp.getExpiresIn());
|
||||
logger.trace("Wolf Smartset login tokenType = {}", jsonResp.getTokenType());
|
||||
return;
|
||||
default:
|
||||
logger.trace("request returned status '{}', reason: {}, content = {}", response.getStatus(),
|
||||
response.getReason(), response.getContentAsString());
|
||||
throw new WolfSmartsetCloudException(response.getStatus() + response.getReason());
|
||||
}
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException | JsonParseException e) {
|
||||
throw new WolfSmartsetCloudException("Cannot logon to Wolf Smartset cloud: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RequestQueueEntry {
|
||||
private SupplyRequestFunctionalInterface buildRequest;
|
||||
private CompletableFuture<String> future;
|
||||
|
||||
public RequestQueueEntry(SupplyRequestFunctionalInterface buildRequest, CompletableFuture<String> future) {
|
||||
this.buildRequest = buildRequest;
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public void completeFuture(GetResponseFunctionalInterface getResponse) {
|
||||
try {
|
||||
String response = getResponse.get(this.buildRequest.get());
|
||||
future.complete(response);
|
||||
} catch (WolfSmartsetCloudException e) {
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Will be thrown for cloud errors
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetCloudException extends Exception {
|
||||
/**
|
||||
* required variable to avoid IncorrectMultilineIndexException warning
|
||||
*/
|
||||
private static final Long serialVersionUID = -1280858607995252321L;
|
||||
|
||||
public WolfSmartsetCloudException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public WolfSmartsetCloudException(@Nullable String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public WolfSmartsetCloudException(@Nullable String message, @Nullable Exception e) {
|
||||
super(message, e);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetAccountConfiguration} class contains fields mapping
|
||||
* to the account thing configuration parameters.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetAccountConfiguration {
|
||||
|
||||
public @Nullable String username = "";
|
||||
public @Nullable String password = "";
|
||||
/**
|
||||
* Time in seconds between information refresh
|
||||
*/
|
||||
public @Nullable Integer refreshIntervalStructure;
|
||||
|
||||
/**
|
||||
* Time in seconds to wait after successful update, command or action before refresh
|
||||
*/
|
||||
public @Nullable Integer refreshIntervalValues;
|
||||
|
||||
/*
|
||||
* Enable/disable automatic discovery
|
||||
*/
|
||||
public @Nullable Boolean discoveryEnabled;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetSystemConfiguration} class contains fields mapping
|
||||
* to the system thing configuration parameters.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetSystemConfiguration {
|
||||
|
||||
/**
|
||||
* System ID assigned by WolfSmartset
|
||||
*/
|
||||
public @Nullable String systemId;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetUnitConfiguration} class contains fields mapping
|
||||
* to the unit thing configuration parameters.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetUnitConfiguration {
|
||||
|
||||
/**
|
||||
* Id of remote unit
|
||||
*/
|
||||
public @Nullable String unitId;
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.handler.WolfSmartsetAccountBridgeHandler;
|
||||
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.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetAccountDiscoveryService} is responsible for discovering the WolfSmartset
|
||||
* systems that are associated with the WolfSmartset Account
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetAccountDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WolfSmartsetAccountDiscoveryService.class);
|
||||
|
||||
private @NonNullByDefault({}) WolfSmartsetAccountBridgeHandler bridgeHandler;
|
||||
|
||||
private @Nullable Future<?> discoveryJob;
|
||||
|
||||
public WolfSmartsetAccountDiscoveryService() {
|
||||
super(SUPPORTED_SYSTEM_AND_UNIT_THING_TYPES_UIDS, 8, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof WolfSmartsetAccountBridgeHandler) {
|
||||
this.bridgeHandler = (WolfSmartsetAccountBridgeHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return bridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_SYSTEM_AND_UNIT_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
logger.debug("WolfSmartsetDiscovery: Starting background discovery job");
|
||||
|
||||
Future<?> localDiscoveryJob = discoveryJob;
|
||||
if (localDiscoveryJob == null || localDiscoveryJob.isCancelled()) {
|
||||
discoveryJob = scheduler.scheduleWithFixedDelay(this::backgroundDiscover, DISCOVERY_INITIAL_DELAY_SECONDS,
|
||||
DISCOVERY_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopBackgroundDiscovery() {
|
||||
logger.debug("WolfSmartsetDiscovery: Stopping background discovery job");
|
||||
Future<?> localDiscoveryJob = discoveryJob;
|
||||
if (localDiscoveryJob != null) {
|
||||
localDiscoveryJob.cancel(true);
|
||||
discoveryJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
logger.debug("WolfSmartsetDiscovery: Starting discovery scan");
|
||||
discover();
|
||||
}
|
||||
|
||||
private void backgroundDiscover() {
|
||||
if (!bridgeHandler.isBackgroundDiscoveryEnabled()) {
|
||||
return;
|
||||
}
|
||||
discover();
|
||||
}
|
||||
|
||||
private void discover() {
|
||||
if (bridgeHandler.getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("WolfSmartsetDiscovery: Skipping discovery because Account Bridge thing is not ONLINE");
|
||||
return;
|
||||
}
|
||||
logger.debug("WolfSmartsetDiscovery: Discovering WolfSmartset devices");
|
||||
discoverSystems();
|
||||
}
|
||||
|
||||
private synchronized void discoverSystems() {
|
||||
logger.debug("WolfSmartsetDiscovery: Discovering systems");
|
||||
var registeredSytems = bridgeHandler.getRegisteredSystems();
|
||||
if (registeredSytems != null) {
|
||||
for (GetSystemListDTO system : registeredSytems) {
|
||||
String name = system.getName();
|
||||
String identifier = null;
|
||||
if (system.getId() != null) {
|
||||
identifier = system.getId().toString();
|
||||
}
|
||||
if (identifier != null && name != null) {
|
||||
ThingUID thingUID = new ThingUID(UID_SYSTEM_BRIDGE, bridgeHandler.getThing().getUID(), identifier);
|
||||
thingDiscovered(createSystemDiscoveryResult(thingUID, identifier, name));
|
||||
logger.debug("WolfSmartsetDiscovery: System '{}' and name '{}' added with UID '{}'", identifier,
|
||||
name, thingUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DiscoveryResult createSystemDiscoveryResult(ThingUID systemUID, String identifier, String name) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(CONFIG_SYSTEM_ID, identifier);
|
||||
return DiscoveryResultBuilder.create(systemUID).withProperties(properties)
|
||||
.withRepresentationProperty(CONFIG_SYSTEM_ID).withBridge(bridgeHandler.getThing().getUID())
|
||||
.withLabel(String.format("WolfSmartset System %s", name)).build();
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.SubMenuEntryWithMenuItemTabView;
|
||||
import org.openhab.binding.wolfsmartset.internal.handler.WolfSmartsetSystemBridgeHandler;
|
||||
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.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetAccountDiscoveryService} is responsible for discovering the WolfSmartset Units
|
||||
* that are associated with the WolfSmartset System
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetSystemDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WolfSmartsetSystemDiscoveryService.class);
|
||||
|
||||
private @NonNullByDefault({}) WolfSmartsetSystemBridgeHandler bridgeHandler;
|
||||
|
||||
private @Nullable Future<?> discoveryJob;
|
||||
|
||||
public WolfSmartsetSystemDiscoveryService() {
|
||||
super(SUPPORTED_SYSTEM_AND_UNIT_THING_TYPES_UIDS, 8, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof WolfSmartsetSystemBridgeHandler) {
|
||||
this.bridgeHandler = (WolfSmartsetSystemBridgeHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return bridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_SYSTEM_AND_UNIT_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
logger.debug("WolfSmartsetSystemDiscovery: Starting background discovery job");
|
||||
Future<?> localDiscoveryJob = discoveryJob;
|
||||
if (localDiscoveryJob == null || localDiscoveryJob.isCancelled()) {
|
||||
discoveryJob = scheduler.scheduleWithFixedDelay(() -> this.backgroundDiscover(),
|
||||
DISCOVERY_INITIAL_DELAY_SECONDS, DISCOVERY_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopBackgroundDiscovery() {
|
||||
logger.debug("WolfSmartsetSystemDiscovery: Stopping background discovery job");
|
||||
Future<?> localDiscoveryJob = discoveryJob;
|
||||
if (localDiscoveryJob != null) {
|
||||
localDiscoveryJob.cancel(true);
|
||||
discoveryJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
logger.debug("WolfSmartsetSystemDiscovery: Starting discovery scan");
|
||||
discover();
|
||||
}
|
||||
|
||||
private void backgroundDiscover() {
|
||||
var accountBridgeHandler = bridgeHandler.getAccountBridgeHandler();
|
||||
if (accountBridgeHandler == null || !accountBridgeHandler.isBackgroundDiscoveryEnabled()) {
|
||||
return;
|
||||
}
|
||||
discover();
|
||||
}
|
||||
|
||||
private void discover() {
|
||||
if (bridgeHandler.getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("WolfSmartsetSystemDiscovery: Skipping discovery because Account Bridge thing is not ONLINE");
|
||||
return;
|
||||
}
|
||||
logger.debug("WolfSmartsetSystemDiscovery: Discovering WolfSmartset devices");
|
||||
discoverUnits();
|
||||
}
|
||||
|
||||
private synchronized void discoverUnits() {
|
||||
if (this.bridgeHandler != null) {
|
||||
String systemId = this.bridgeHandler.getSystemId();
|
||||
var systemConfig = this.bridgeHandler.getSystemConfig();
|
||||
if (systemConfig != null) {
|
||||
logger.debug("WolfSmartsetSystemDiscovery: Discovering units for system '{}' (id {})",
|
||||
systemConfig.getName(), systemId);
|
||||
for (var unit : this.bridgeHandler.getUnits()) {
|
||||
ThingUID bridgeUID = this.bridgeHandler.getThing().getUID();
|
||||
ThingUID unitUID = new ThingUID(UID_UNIT_THING, bridgeUID,
|
||||
unit.menuItemTabViewDTO.bundleId.toString());
|
||||
thingDiscovered(createUnitDiscoveryResult(unitUID, bridgeUID, systemConfig, unit));
|
||||
logger.debug(
|
||||
"WolfSmartsetSystemDiscovery: Unit for '{}' with id '{}' and name '{}' added with UID '{}'",
|
||||
systemId, unit.menuItemTabViewDTO.bundleId, unit.menuItemTabViewDTO.tabName, unitUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DiscoveryResult createUnitDiscoveryResult(ThingUID unitUID, ThingUID bridgeUID,
|
||||
GetSystemListDTO systemConfig, SubMenuEntryWithMenuItemTabView unit) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(CONFIG_UNIT_ID, unit.menuItemTabViewDTO.bundleId.toString());
|
||||
var tabName = unit.menuItemTabViewDTO.tabName;
|
||||
var menuName = unit.subMenuEntryDTO.getName();
|
||||
tabName = tabName.isEmpty() || tabName.equalsIgnoreCase("NULL") || menuName.equalsIgnoreCase(tabName) ? ""
|
||||
: "-" + tabName;
|
||||
|
||||
return DiscoveryResultBuilder.create(unitUID).withProperties(properties)
|
||||
.withRepresentationProperty(CONFIG_UNIT_ID).withBridge(bridgeUID)
|
||||
.withLabel(String.format("%s %s%s", systemConfig.getName(), menuName, tabName)).build();
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class CreateSession2DTO {
|
||||
|
||||
@SerializedName("CultureInfoCode")
|
||||
@Expose
|
||||
private String cultureInfoCode;
|
||||
@SerializedName("IsPasswordReset")
|
||||
@Expose
|
||||
private Boolean isPasswordReset;
|
||||
@SerializedName("IsProfessional")
|
||||
@Expose
|
||||
private Boolean isProfessional;
|
||||
@SerializedName("IsProfessionalPasswordReset")
|
||||
@Expose
|
||||
private Boolean isProfessionalPasswordReset;
|
||||
@SerializedName("BrowserSessionId")
|
||||
@Expose
|
||||
private Integer browserSessionId;
|
||||
|
||||
public String getCultureInfoCode() {
|
||||
return cultureInfoCode;
|
||||
}
|
||||
|
||||
public void setCultureInfoCode(String cultureInfoCode) {
|
||||
this.cultureInfoCode = cultureInfoCode;
|
||||
}
|
||||
|
||||
public Boolean getIsPasswordReset() {
|
||||
return isPasswordReset;
|
||||
}
|
||||
|
||||
public void setIsPasswordReset(Boolean isPasswordReset) {
|
||||
this.isPasswordReset = isPasswordReset;
|
||||
}
|
||||
|
||||
public Boolean getIsProfessional() {
|
||||
return isProfessional;
|
||||
}
|
||||
|
||||
public void setIsProfessional(Boolean isProfessional) {
|
||||
this.isProfessional = isProfessional;
|
||||
}
|
||||
|
||||
public Boolean getIsProfessionalPasswordReset() {
|
||||
return isProfessionalPasswordReset;
|
||||
}
|
||||
|
||||
public void setIsProfessionalPasswordReset(Boolean isProfessionalPasswordReset) {
|
||||
this.isProfessionalPasswordReset = isProfessionalPasswordReset;
|
||||
}
|
||||
|
||||
public Integer getBrowserSessionId() {
|
||||
return browserSessionId;
|
||||
}
|
||||
|
||||
public void setBrowserSessionId(Integer browserSessionId) {
|
||||
this.browserSessionId = browserSessionId;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class CurrentMessageDTO {
|
||||
|
||||
@SerializedName("Id")
|
||||
@Expose
|
||||
private Integer id;
|
||||
@SerializedName("ErrorCode")
|
||||
@Expose
|
||||
private Integer errorCode;
|
||||
@SerializedName("Description")
|
||||
@Expose
|
||||
private String description;
|
||||
@SerializedName("OccurTimeLocal")
|
||||
@Expose
|
||||
private String occurTimeLocal;
|
||||
@SerializedName("Active")
|
||||
@Expose
|
||||
private Boolean active;
|
||||
@SerializedName("Index")
|
||||
@Expose
|
||||
private Integer index;
|
||||
@SerializedName("Device")
|
||||
@Expose
|
||||
private String device;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public void setErrorCode(Integer errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getOccurTimeLocal() {
|
||||
return occurTimeLocal;
|
||||
}
|
||||
|
||||
public void setOccurTimeLocal(String occurTimeLocal) {
|
||||
this.occurTimeLocal = occurTimeLocal;
|
||||
}
|
||||
|
||||
public Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(Boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public Integer getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(Integer index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class GatewayStateDTO {
|
||||
|
||||
@SerializedName("GatewayId")
|
||||
@Expose
|
||||
private Integer gatewayId;
|
||||
@SerializedName("IsOnline")
|
||||
@Expose
|
||||
private Boolean isOnline;
|
||||
@SerializedName("GatewayOfflineCause")
|
||||
@Expose
|
||||
private Integer gatewayOfflineCause;
|
||||
@SerializedName("IsLocked")
|
||||
@Expose
|
||||
private Boolean isLocked;
|
||||
@SerializedName("IsDeleted")
|
||||
@Expose
|
||||
private Boolean isDeleted;
|
||||
@SerializedName("IsBusy")
|
||||
@Expose
|
||||
private Boolean isBusy;
|
||||
@SerializedName("ImageName")
|
||||
@Expose
|
||||
private String imageName;
|
||||
|
||||
public Integer getGatewayId() {
|
||||
return gatewayId;
|
||||
}
|
||||
|
||||
public void setGatewayId(Integer gatewayId) {
|
||||
this.gatewayId = gatewayId;
|
||||
}
|
||||
|
||||
public Boolean getIsOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public void setIsOnline(Boolean isOnline) {
|
||||
this.isOnline = isOnline;
|
||||
}
|
||||
|
||||
public Integer getGatewayOfflineCause() {
|
||||
return gatewayOfflineCause;
|
||||
}
|
||||
|
||||
public void setGatewayOfflineCause(Integer gatewayOfflineCause) {
|
||||
this.gatewayOfflineCause = gatewayOfflineCause;
|
||||
}
|
||||
|
||||
public Boolean getIsLocked() {
|
||||
return isLocked;
|
||||
}
|
||||
|
||||
public void setIsLocked(Boolean isLocked) {
|
||||
this.isLocked = isLocked;
|
||||
}
|
||||
|
||||
public Boolean getIsDeleted() {
|
||||
return isDeleted;
|
||||
}
|
||||
|
||||
public void setIsDeleted(Boolean isDeleted) {
|
||||
this.isDeleted = isDeleted;
|
||||
}
|
||||
|
||||
public Boolean getIsBusy() {
|
||||
return isBusy;
|
||||
}
|
||||
|
||||
public void setIsBusy(Boolean isBusy) {
|
||||
this.isBusy = isBusy;
|
||||
}
|
||||
|
||||
public String getImageName() {
|
||||
return imageName;
|
||||
}
|
||||
|
||||
public void setImageName(String imageName) {
|
||||
this.imageName = imageName;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class GetGuiDescriptionForGatewayDTO {
|
||||
|
||||
@SerializedName("MenuItems")
|
||||
@Expose
|
||||
private List<MenuItemDTO> menuItems = null;
|
||||
@SerializedName("DynFaultMessageDevices")
|
||||
@Expose
|
||||
private List<Object> dynFaultMessageDevices = null;
|
||||
@SerializedName("SystemHasWRSClassicDevices")
|
||||
@Expose
|
||||
private Boolean systemHasWRSClassicDevices;
|
||||
|
||||
public List<MenuItemDTO> getMenuItems() {
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
public void setMenuItems(List<MenuItemDTO> menuItems) {
|
||||
this.menuItems = menuItems;
|
||||
}
|
||||
|
||||
public List<Object> getDynFaultMessageDevices() {
|
||||
return dynFaultMessageDevices;
|
||||
}
|
||||
|
||||
public void setDynFaultMessageDevices(List<Object> dynFaultMessageDevices) {
|
||||
this.dynFaultMessageDevices = dynFaultMessageDevices;
|
||||
}
|
||||
|
||||
public Boolean getSystemHasWRSClassicDevices() {
|
||||
return systemHasWRSClassicDevices;
|
||||
}
|
||||
|
||||
public void setSystemHasWRSClassicDevices(Boolean systemHasWRSClassicDevices) {
|
||||
this.systemHasWRSClassicDevices = systemHasWRSClassicDevices;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class GetParameterValuesDTO {
|
||||
|
||||
@SerializedName("LastAccess")
|
||||
@Expose
|
||||
private String lastAccess;
|
||||
@SerializedName("Values")
|
||||
@Expose
|
||||
private List<ValueDTO> values = null;
|
||||
@SerializedName("IsNewJobCreated")
|
||||
@Expose
|
||||
private Boolean isNewJobCreated;
|
||||
|
||||
public String getLastAccess() {
|
||||
return lastAccess;
|
||||
}
|
||||
|
||||
public void setLastAccess(String lastAccess) {
|
||||
this.lastAccess = lastAccess;
|
||||
}
|
||||
|
||||
public List<ValueDTO> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(List<ValueDTO> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public Boolean getIsNewJobCreated() {
|
||||
return isNewJobCreated;
|
||||
}
|
||||
|
||||
public void setIsNewJobCreated(Boolean isNewJobCreated) {
|
||||
this.isNewJobCreated = isNewJobCreated;
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class GetSystemListDTO {
|
||||
|
||||
@SerializedName("Id")
|
||||
@Expose
|
||||
private Integer id;
|
||||
@SerializedName("GatewayId")
|
||||
@Expose
|
||||
private Integer gatewayId;
|
||||
@SerializedName("IsForeignSystem")
|
||||
@Expose
|
||||
private Boolean isForeignSystem;
|
||||
@SerializedName("AccessLevel")
|
||||
@Expose
|
||||
private Integer accessLevel;
|
||||
@SerializedName("GatewayUsername")
|
||||
@Expose
|
||||
private String gatewayUsername;
|
||||
@SerializedName("Name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("SystemShares")
|
||||
@Expose
|
||||
private List<Object> systemShares = null;
|
||||
@SerializedName("GatewaySoftwareVersion")
|
||||
@Expose
|
||||
private String gatewaySoftwareVersion;
|
||||
@SerializedName("UserNameOwner")
|
||||
@Expose
|
||||
private String userNameOwner;
|
||||
@SerializedName("SystemShareId")
|
||||
@Expose
|
||||
private Integer systemShareId;
|
||||
@SerializedName("OperatorName")
|
||||
@Expose
|
||||
private String operatorName;
|
||||
@SerializedName("Location")
|
||||
@Expose
|
||||
private String location;
|
||||
@SerializedName("InstallationDate")
|
||||
@Expose
|
||||
private String installationDate;
|
||||
@SerializedName("ImageId")
|
||||
@Expose
|
||||
private Integer imageId;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getGatewayId() {
|
||||
return gatewayId;
|
||||
}
|
||||
|
||||
public void setGatewayId(Integer gatewayId) {
|
||||
this.gatewayId = gatewayId;
|
||||
}
|
||||
|
||||
public Boolean getIsForeignSystem() {
|
||||
return isForeignSystem;
|
||||
}
|
||||
|
||||
public void setIsForeignSystem(Boolean isForeignSystem) {
|
||||
this.isForeignSystem = isForeignSystem;
|
||||
}
|
||||
|
||||
public Integer getAccessLevel() {
|
||||
return accessLevel;
|
||||
}
|
||||
|
||||
public void setAccessLevel(Integer accessLevel) {
|
||||
this.accessLevel = accessLevel;
|
||||
}
|
||||
|
||||
public String getGatewayUsername() {
|
||||
return gatewayUsername;
|
||||
}
|
||||
|
||||
public void setGatewayUsername(String gatewayUsername) {
|
||||
this.gatewayUsername = gatewayUsername;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Object> getSystemShares() {
|
||||
return systemShares;
|
||||
}
|
||||
|
||||
public void setSystemShares(List<Object> systemShares) {
|
||||
this.systemShares = systemShares;
|
||||
}
|
||||
|
||||
public String getGatewaySoftwareVersion() {
|
||||
return gatewaySoftwareVersion;
|
||||
}
|
||||
|
||||
public void setGatewaySoftwareVersion(String gatewaySoftwareVersion) {
|
||||
this.gatewaySoftwareVersion = gatewaySoftwareVersion;
|
||||
}
|
||||
|
||||
public String getUserNameOwner() {
|
||||
return userNameOwner;
|
||||
}
|
||||
|
||||
public void setUserNameOwner(String userNameOwner) {
|
||||
this.userNameOwner = userNameOwner;
|
||||
}
|
||||
|
||||
public @Nullable Integer getSystemShareId() {
|
||||
return systemShareId;
|
||||
}
|
||||
|
||||
public void setSystemShareId(Integer systemShareId) {
|
||||
this.systemShareId = systemShareId;
|
||||
}
|
||||
|
||||
public String getOperatorName() {
|
||||
return operatorName;
|
||||
}
|
||||
|
||||
public void setOperatorName(String operatorName) {
|
||||
this.operatorName = operatorName;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public String getInstallationDate() {
|
||||
return installationDate;
|
||||
}
|
||||
|
||||
public void setInstallationDate(String installationDate) {
|
||||
this.installationDate = installationDate;
|
||||
}
|
||||
|
||||
public Integer getImageId() {
|
||||
return imageId;
|
||||
}
|
||||
|
||||
public void setImageId(Integer imageId) {
|
||||
this.imageId = imageId;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class GetSystemStateListDTO {
|
||||
|
||||
@SerializedName("SystemId")
|
||||
@Expose
|
||||
private Integer systemId;
|
||||
@SerializedName("GatewayState")
|
||||
@Expose
|
||||
private GatewayStateDTO gatewayState;
|
||||
@SerializedName("AccessLevel")
|
||||
@Expose
|
||||
private Integer accessLevel;
|
||||
@SerializedName("IsSystemShareDeleted")
|
||||
@Expose
|
||||
private Boolean isSystemShareDeleted;
|
||||
@SerializedName("IsSystemShareRejected")
|
||||
@Expose
|
||||
private Boolean isSystemShareRejected;
|
||||
@SerializedName("IsSystemDeleted")
|
||||
@Expose
|
||||
private Boolean isSystemDeleted;
|
||||
@SerializedName("FirstActiveAlertCode")
|
||||
@Expose
|
||||
private Integer firstActiveAlertCode;
|
||||
|
||||
public Integer getSystemId() {
|
||||
return systemId;
|
||||
}
|
||||
|
||||
public void setSystemId(Integer systemId) {
|
||||
this.systemId = systemId;
|
||||
}
|
||||
|
||||
public GatewayStateDTO getGatewayState() {
|
||||
return gatewayState;
|
||||
}
|
||||
|
||||
public void setGatewayState(GatewayStateDTO gatewayState) {
|
||||
this.gatewayState = gatewayState;
|
||||
}
|
||||
|
||||
public Integer getAccessLevel() {
|
||||
return accessLevel;
|
||||
}
|
||||
|
||||
public void setAccessLevel(Integer accessLevel) {
|
||||
this.accessLevel = accessLevel;
|
||||
}
|
||||
|
||||
public Boolean getIsSystemShareDeleted() {
|
||||
return isSystemShareDeleted;
|
||||
}
|
||||
|
||||
public void setIsSystemShareDeleted(Boolean isSystemShareDeleted) {
|
||||
this.isSystemShareDeleted = isSystemShareDeleted;
|
||||
}
|
||||
|
||||
public Boolean getIsSystemShareRejected() {
|
||||
return isSystemShareRejected;
|
||||
}
|
||||
|
||||
public void setIsSystemShareRejected(Boolean isSystemShareRejected) {
|
||||
this.isSystemShareRejected = isSystemShareRejected;
|
||||
}
|
||||
|
||||
public Boolean getIsSystemDeleted() {
|
||||
return isSystemDeleted;
|
||||
}
|
||||
|
||||
public void setIsSystemDeleted(Boolean isSystemDeleted) {
|
||||
this.isSystemDeleted = isSystemDeleted;
|
||||
}
|
||||
|
||||
public Integer getFirstActiveAlertCode() {
|
||||
return firstActiveAlertCode;
|
||||
}
|
||||
|
||||
public void setFirstActiveAlertCode(Integer firstActiveAlertCode) {
|
||||
this.firstActiveAlertCode = firstActiveAlertCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class HistoryMessageDTO {
|
||||
|
||||
@SerializedName("Id")
|
||||
@Expose
|
||||
private Integer id;
|
||||
@SerializedName("ErrorCode")
|
||||
@Expose
|
||||
private Integer errorCode;
|
||||
@SerializedName("Description")
|
||||
@Expose
|
||||
private String description;
|
||||
@SerializedName("OccurTimeLocal")
|
||||
@Expose
|
||||
private String occurTimeLocal;
|
||||
@SerializedName("Active")
|
||||
@Expose
|
||||
private Boolean active;
|
||||
@SerializedName("Index")
|
||||
@Expose
|
||||
private Integer index;
|
||||
@SerializedName("Device")
|
||||
@Expose
|
||||
private String device;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public void setErrorCode(Integer errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getOccurTimeLocal() {
|
||||
return occurTimeLocal;
|
||||
}
|
||||
|
||||
public void setOccurTimeLocal(String occurTimeLocal) {
|
||||
this.occurTimeLocal = occurTimeLocal;
|
||||
}
|
||||
|
||||
public Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(Boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public Integer getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(Integer index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class LoginResponseDTO {
|
||||
|
||||
@SerializedName("access_token")
|
||||
@Expose
|
||||
private String accessToken;
|
||||
@SerializedName("expires_in")
|
||||
@Expose
|
||||
private Integer expiresIn;
|
||||
@SerializedName("token_type")
|
||||
@Expose
|
||||
private String tokenType;
|
||||
@SerializedName("refresh_token")
|
||||
@Expose
|
||||
private String refreshToken;
|
||||
@SerializedName("scope")
|
||||
@Expose
|
||||
private String scope;
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public Integer getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public void setExpiresIn(Integer expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class MenuItemDTO {
|
||||
|
||||
@SerializedName("Name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("SubMenuEntries")
|
||||
@Expose
|
||||
private List<SubMenuEntryDTO> subMenuEntries = null;
|
||||
@SerializedName("ParameterNode")
|
||||
@Expose
|
||||
private Boolean parameterNode;
|
||||
@SerializedName("ImageName")
|
||||
@Expose
|
||||
private String imageName;
|
||||
@SerializedName("TabViews")
|
||||
@Expose
|
||||
private List<Object> tabViews = null;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<SubMenuEntryDTO> getSubMenuEntries() {
|
||||
return subMenuEntries;
|
||||
}
|
||||
|
||||
public void setSubMenuEntries(List<SubMenuEntryDTO> subMenuEntries) {
|
||||
this.subMenuEntries = subMenuEntries;
|
||||
}
|
||||
|
||||
public Boolean getParameterNode() {
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
public void setParameterNode(Boolean parameterNode) {
|
||||
this.parameterNode = parameterNode;
|
||||
}
|
||||
|
||||
public String getImageName() {
|
||||
return imageName;
|
||||
}
|
||||
|
||||
public void setImageName(String imageName) {
|
||||
this.imageName = imageName;
|
||||
}
|
||||
|
||||
public List<Object> getTabViews() {
|
||||
return tabViews;
|
||||
}
|
||||
|
||||
public void setTabViews(List<Object> tabViews) {
|
||||
this.tabViews = tabViews;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
public class MenuItemTabViewDTO {
|
||||
@SerializedName("IsExpertView")
|
||||
@Expose
|
||||
public Boolean isExpertView;
|
||||
|
||||
@SerializedName("TabName")
|
||||
@Expose
|
||||
public String tabName;
|
||||
|
||||
@SerializedName("GuiId")
|
||||
@Expose
|
||||
public Long guiId;
|
||||
|
||||
@SerializedName("BundleId")
|
||||
@Expose
|
||||
public Long bundleId;
|
||||
|
||||
@SerializedName("ParameterDescriptors")
|
||||
@Expose
|
||||
public List<ParameterDescriptorDTO> parameterDescriptors;
|
||||
|
||||
@SerializedName("ViewType")
|
||||
@Expose
|
||||
public Long viewType;
|
||||
|
||||
@SerializedName("SvgSchemaDeviceId")
|
||||
@Expose
|
||||
public Long svgSchemaDeviceId;
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
public class ParameterDescriptorDTO {
|
||||
@SerializedName("ValueId")
|
||||
@Expose
|
||||
public Long valueId;
|
||||
|
||||
@SerializedName("SortId")
|
||||
@Expose
|
||||
public Long sortId;
|
||||
|
||||
@SerializedName("SubBundleId")
|
||||
@Expose
|
||||
public Long subBundleId;
|
||||
|
||||
@SerializedName("ParameterId")
|
||||
@Expose
|
||||
public Long parameterId;
|
||||
|
||||
@SerializedName("IsReadOnly")
|
||||
@Expose
|
||||
public Boolean isReadOnly;
|
||||
|
||||
@SerializedName("NoDataPoint")
|
||||
@Expose
|
||||
public Boolean noDataPoint;
|
||||
|
||||
@SerializedName("IsExpertProtectable")
|
||||
@Expose
|
||||
public Boolean isExpertProtectable;
|
||||
|
||||
@SerializedName("Name")
|
||||
@Expose
|
||||
public String name;
|
||||
|
||||
@SerializedName("Group")
|
||||
@Expose
|
||||
public String group;
|
||||
|
||||
@SerializedName("ControlType")
|
||||
@Expose
|
||||
public Integer controlType;
|
||||
|
||||
@SerializedName("Value")
|
||||
@Expose
|
||||
public String value;
|
||||
|
||||
@SerializedName("ValueState")
|
||||
@Expose
|
||||
public Long valueState;
|
||||
|
||||
@SerializedName("HasDependentParameter")
|
||||
@Expose
|
||||
public Boolean hasDependentParameter;
|
||||
|
||||
@SerializedName("ProtGrp")
|
||||
@Expose
|
||||
public String protGrp;
|
||||
|
||||
@SerializedName("Unit")
|
||||
@Expose
|
||||
public String unit;
|
||||
|
||||
@SerializedName("Decimals")
|
||||
@Expose
|
||||
public Long decimals;
|
||||
|
||||
@SerializedName("MinValueCondition")
|
||||
@Expose
|
||||
public String minValueCondition;
|
||||
|
||||
@SerializedName("MaxValueCondition")
|
||||
@Expose
|
||||
public String maxValueCondition;
|
||||
|
||||
@SerializedName("MinValue")
|
||||
@Expose
|
||||
public Long minValue;
|
||||
|
||||
@SerializedName("MaxValue")
|
||||
@Expose
|
||||
public Long maxValue;
|
||||
|
||||
@SerializedName("StepWidth")
|
||||
@Expose
|
||||
public double stepWidth;
|
||||
|
||||
@SerializedName("NamePrefix")
|
||||
@Expose
|
||||
public String namePrefix;
|
||||
|
||||
@SerializedName("TurnOffValue")
|
||||
@Expose
|
||||
public Long turnOffValue;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class ReadFaultMessagesDTO {
|
||||
|
||||
@SerializedName("MessagesChanged")
|
||||
@Expose
|
||||
private Boolean messagesChanged;
|
||||
@SerializedName("LastRead")
|
||||
@Expose
|
||||
private String lastRead;
|
||||
@SerializedName("CurrentMessages")
|
||||
@Expose
|
||||
private List<CurrentMessageDTO> currentMessages = null;
|
||||
@SerializedName("HistoryMessages")
|
||||
@Expose
|
||||
private List<HistoryMessageDTO> historyMessages = null;
|
||||
@SerializedName("DeviceFaultMessages")
|
||||
@Expose
|
||||
private List<Object> deviceFaultMessages = null;
|
||||
|
||||
public Boolean getMessagesChanged() {
|
||||
return messagesChanged;
|
||||
}
|
||||
|
||||
public void setMessagesChanged(Boolean messagesChanged) {
|
||||
this.messagesChanged = messagesChanged;
|
||||
}
|
||||
|
||||
public String getLastRead() {
|
||||
return lastRead;
|
||||
}
|
||||
|
||||
public void setLastRead(String lastRead) {
|
||||
this.lastRead = lastRead;
|
||||
}
|
||||
|
||||
public List<CurrentMessageDTO> getCurrentMessages() {
|
||||
return currentMessages;
|
||||
}
|
||||
|
||||
public void setCurrentMessages(List<CurrentMessageDTO> currentMessages) {
|
||||
this.currentMessages = currentMessages;
|
||||
}
|
||||
|
||||
public List<HistoryMessageDTO> getHistoryMessages() {
|
||||
return historyMessages;
|
||||
}
|
||||
|
||||
public void setHistoryMessages(List<HistoryMessageDTO> historyMessages) {
|
||||
this.historyMessages = historyMessages;
|
||||
}
|
||||
|
||||
public List<Object> getDeviceFaultMessages() {
|
||||
return deviceFaultMessages;
|
||||
}
|
||||
|
||||
public void setDeviceFaultMessages(List<Object> deviceFaultMessages) {
|
||||
this.deviceFaultMessages = deviceFaultMessages;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class SubMenuEntryDTO {
|
||||
|
||||
@SerializedName("Name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("SubMenuEntries")
|
||||
@Expose
|
||||
private List<Object> subMenuEntries = null;
|
||||
@SerializedName("ParameterNode")
|
||||
@Expose
|
||||
private Boolean parameterNode;
|
||||
@SerializedName("ImageName")
|
||||
@Expose
|
||||
private String imageName;
|
||||
@SerializedName("TabViews")
|
||||
@Expose
|
||||
private List<MenuItemTabViewDTO> tabViews = null;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Object> getSubMenuEntries() {
|
||||
return subMenuEntries;
|
||||
}
|
||||
|
||||
public void setSubMenuEntries(List<Object> subMenuEntries) {
|
||||
this.subMenuEntries = subMenuEntries;
|
||||
}
|
||||
|
||||
public Boolean getParameterNode() {
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
public void setParameterNode(Boolean parameterNode) {
|
||||
this.parameterNode = parameterNode;
|
||||
}
|
||||
|
||||
public String getImageName() {
|
||||
return imageName;
|
||||
}
|
||||
|
||||
public void setImageName(String imageName) {
|
||||
this.imageName = imageName;
|
||||
}
|
||||
|
||||
public List<MenuItemTabViewDTO> getTabViews() {
|
||||
return tabViews;
|
||||
}
|
||||
|
||||
public void setTabViews(List<MenuItemTabViewDTO> tabViews) {
|
||||
this.tabViews = tabViews;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
/**
|
||||
* Link the SubMenuEntryDTO with the MenuItemTabViewDTO
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
public class SubMenuEntryWithMenuItemTabView {
|
||||
public SubMenuEntryDTO subMenuEntryDTO;
|
||||
public MenuItemTabViewDTO menuItemTabViewDTO;
|
||||
|
||||
public SubMenuEntryWithMenuItemTabView(SubMenuEntryDTO subMenuEntryDTO, MenuItemTabViewDTO menuItemTabViewDTO) {
|
||||
this.subMenuEntryDTO = subMenuEntryDTO;
|
||||
this.menuItemTabViewDTO = menuItemTabViewDTO;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.dto;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* generated with https://www.jsonschema2pojo.org/
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@Generated("jsonschema2pojo")
|
||||
public class ValueDTO {
|
||||
|
||||
@SerializedName("ValueId")
|
||||
@Expose
|
||||
private Long valueId;
|
||||
@SerializedName("Value")
|
||||
@Expose
|
||||
private String value;
|
||||
@SerializedName("State")
|
||||
@Expose
|
||||
private Integer state;
|
||||
|
||||
public Long getValueId() {
|
||||
return valueId;
|
||||
}
|
||||
|
||||
public void setValueId(Long valueId) {
|
||||
this.valueId = valueId;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Integer getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(Integer state) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.handler;
|
||||
|
||||
import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.CONFIG_SYSTEM_ID;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.wolfsmartset.internal.api.WolfSmartsetApi;
|
||||
import org.openhab.binding.wolfsmartset.internal.api.WolfSmartsetCloudException;
|
||||
import org.openhab.binding.wolfsmartset.internal.config.WolfSmartsetAccountConfiguration;
|
||||
import org.openhab.binding.wolfsmartset.internal.discovery.WolfSmartsetAccountDiscoveryService;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetGuiDescriptionForGatewayDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemListDTO;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetAccountBridgeHandler} is responsible for managing
|
||||
* communication with the WolfSmartset API.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetAccountBridgeHandler extends BaseBridgeHandler {
|
||||
private static final int REFRESH_STARTUP_DELAY_SECONDS = 3;
|
||||
private static final int REFRESH_INTERVAL_SECONDS = 1;
|
||||
private static final int DEFAULT_REFRESH_INTERVAL_CONFIGURATION_MINUTES = 10;
|
||||
private static final int DEFAULT_REFRESH_INTERVAL_VALUES_SECONDS = 15;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WolfSmartsetAccountBridgeHandler.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private @NonNullByDefault({}) WolfSmartsetApi api;
|
||||
private int refreshIntervalStructureMinutes;
|
||||
private int refreshIntervalValuesSeconds;
|
||||
private boolean discoveryEnabled;
|
||||
private @Nullable List<GetSystemListDTO> cachedSystems = null;
|
||||
|
||||
private final Map<String, WolfSmartsetSystemBridgeHandler> systemHandlers = new ConcurrentHashMap<>();
|
||||
private final Set<String> systemIds = new CopyOnWriteArraySet<>();
|
||||
|
||||
private @Nullable Future<?> refreshSystemsJob;
|
||||
private final AtomicInteger refreshConfigurationCounter = new AtomicInteger(REFRESH_STARTUP_DELAY_SECONDS);
|
||||
private final AtomicInteger refreshValuesCounter = new AtomicInteger(REFRESH_STARTUP_DELAY_SECONDS);
|
||||
|
||||
public WolfSmartsetAccountBridgeHandler(final Bridge bridge, HttpClient httpClient) {
|
||||
super(bridge);
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("AccountBridge: Initializing");
|
||||
|
||||
WolfSmartsetAccountConfiguration config = getConfigAs(WolfSmartsetAccountConfiguration.class);
|
||||
|
||||
Integer value;
|
||||
value = config.refreshIntervalStructure;
|
||||
refreshIntervalStructureMinutes = value == null ? DEFAULT_REFRESH_INTERVAL_CONFIGURATION_MINUTES : value;
|
||||
|
||||
value = config.refreshIntervalValues;
|
||||
refreshIntervalValuesSeconds = value == null ? DEFAULT_REFRESH_INTERVAL_VALUES_SECONDS : value;
|
||||
|
||||
String username = config.username;
|
||||
String password = config.password;
|
||||
username = username == null ? "" : username;
|
||||
password = password == null ? "" : password;
|
||||
|
||||
Boolean booleanValue = config.discoveryEnabled;
|
||||
discoveryEnabled = booleanValue == null ? false : booleanValue.booleanValue();
|
||||
logger.debug("AccountBridge: System and unit discovery is {}", discoveryEnabled ? "enabled" : "disabled");
|
||||
if (username.trim().isEmpty() || password.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Missing username or password");
|
||||
} else {
|
||||
try {
|
||||
api = new WolfSmartsetApi(username, password, httpClient, scheduler);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Checking authorization");
|
||||
scheduleRefreshJob();
|
||||
} catch (WolfSmartsetCloudException e) {
|
||||
logger.error("unable to create wolf smartset api", e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
cancelRefreshJob();
|
||||
api.stopRequestQueue();
|
||||
logger.debug("AccountBridge: Disposing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(WolfSmartsetAccountDiscoveryService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(ThingHandler systemHandler, Thing systemThing) {
|
||||
String systemId = (String) systemThing.getConfiguration().get(CONFIG_SYSTEM_ID);
|
||||
systemHandlers.put(systemId, (WolfSmartsetSystemBridgeHandler) systemHandler);
|
||||
systemIds.add(systemId);
|
||||
scheduleRefreshJob();
|
||||
logger.debug("AccountBridge: Adding system handler for {} with id {}", systemThing.getUID(), systemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerDisposed(ThingHandler systemHandler, Thing systemThing) {
|
||||
String systemId = (String) systemThing.getConfiguration().get(CONFIG_SYSTEM_ID);
|
||||
systemHandlers.remove(systemId);
|
||||
systemIds.remove(systemId);
|
||||
logger.debug("AccountBridge: Removing system handler for {} with id {}", systemThing.getUID(), systemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns truee if BackgroundDiscoveryEnabled
|
||||
*/
|
||||
public boolean isBackgroundDiscoveryEnabled() {
|
||||
return discoveryEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the list of the GetSystemListDTO available
|
||||
*/
|
||||
public @Nullable List<GetSystemListDTO> getRegisteredSystems() {
|
||||
return cachedSystems;
|
||||
}
|
||||
|
||||
/**
|
||||
* force a full update of the wolf smartset cloud configuration
|
||||
*/
|
||||
public void scheduleRefreshJob() {
|
||||
logger.debug("AccountBridge: Scheduling system refresh job");
|
||||
cancelRefreshJob();
|
||||
refreshConfigurationCounter.set(0);
|
||||
refreshValuesCounter.set(0);
|
||||
refreshSystemsJob = scheduler.scheduleWithFixedDelay(this::refreshSystems, REFRESH_STARTUP_DELAY_SECONDS,
|
||||
REFRESH_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* The refresh job updates the system channels on the refresh interval set in the system thing config.
|
||||
* The system update process involves first running a system summary transaction to
|
||||
* determine if any system data has changed since the last summary. If any change is detected,
|
||||
* a full query of the systems is performed.
|
||||
*/
|
||||
private void refreshSystems() {
|
||||
if (refreshConfigurationCounter.getAndDecrement() == 0) {
|
||||
refreshConfigurationCounter.set(refreshIntervalStructureMinutes * 60);
|
||||
if (api.login()) {
|
||||
logger.debug("AccountBridge: refreshing configuration");
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
cachedSystems = api.getSystems();
|
||||
if (cachedSystems != null) {
|
||||
for (GetSystemListDTO system : api.getSystems()) {
|
||||
WolfSmartsetSystemBridgeHandler handler = systemHandlers.get(system.getId().toString());
|
||||
if (handler != null) {
|
||||
GetGuiDescriptionForGatewayDTO systemDescription = api.getSystemDescription(system.getId(),
|
||||
system.getGatewayId());
|
||||
handler.updateConfiguration(system, systemDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Authorization failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshValuesCounter.getAndDecrement() == 0) {
|
||||
refreshValuesCounter.set(refreshIntervalValuesSeconds);
|
||||
if (api.login()) {
|
||||
logger.debug("AccountBridge: refreshing values");
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
var systemConfigs = systemHandlers.values().stream().map(s -> s.getSystemConfig())
|
||||
.filter(s -> s != null).collect(Collectors.toSet());
|
||||
if (systemConfigs != null && systemConfigs.size() > 0) {
|
||||
var systemStates = api.getSystemState(systemConfigs);
|
||||
if (systemStates != null) {
|
||||
for (var systemState : systemStates) {
|
||||
if (systemState != null) {
|
||||
var systemHandler = systemHandlers.get(systemState.getSystemId().toString());
|
||||
if (systemHandler != null) {
|
||||
systemHandler.updateSystemState(systemState);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Failed to update system states");
|
||||
}
|
||||
|
||||
for (var systemHandler : systemHandlers.values()) {
|
||||
if (systemHandler != null) {
|
||||
var systemConfig = systemHandler.getSystemConfig();
|
||||
if (systemConfig != null) {
|
||||
var faultMessages = api.getFaultMessages(systemConfig.getId(),
|
||||
systemConfig.getGatewayId());
|
||||
|
||||
systemHandler.updateFaultMessages(faultMessages);
|
||||
|
||||
for (var unitHandler : systemHandler.getUnitHandler()) {
|
||||
if (unitHandler != null) {
|
||||
var tabmenu = unitHandler.getTabMenu();
|
||||
if (tabmenu != null) {
|
||||
var lastRefreshTime = unitHandler.getLastRefreshTime();
|
||||
var valueIds = tabmenu.parameterDescriptors.stream()
|
||||
.filter(p -> p.valueId > 0).map(p -> p.valueId)
|
||||
.collect(Collectors.toList());
|
||||
var paramValues = api.getGetParameterValues(systemConfig.getId(),
|
||||
systemConfig.getGatewayId(), tabmenu.bundleId, valueIds,
|
||||
lastRefreshTime);
|
||||
|
||||
unitHandler.updateValues(paramValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// waiting for config.
|
||||
systemHandler.updateSystemState(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Authorization failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelRefreshJob() {
|
||||
Future<?> localRefreshSystemsJob = refreshSystemsJob;
|
||||
if (localRefreshSystemsJob != null) {
|
||||
localRefreshSystemsJob.cancel(true);
|
||||
logger.debug("AccountBridge: Canceling system refresh job");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.handler;
|
||||
|
||||
import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.wolfsmartset.internal.config.WolfSmartsetSystemConfiguration;
|
||||
import org.openhab.binding.wolfsmartset.internal.discovery.WolfSmartsetSystemDiscoveryService;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetGuiDescriptionForGatewayDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetSystemStateListDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.ReadFaultMessagesDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.SubMenuEntryWithMenuItemTabView;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetSystemBridgeHandler} is the handler for an WolfSmartset system.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetSystemBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WolfSmartsetSystemBridgeHandler.class);
|
||||
|
||||
private @NonNullByDefault({}) String systemId;
|
||||
|
||||
private final Map<String, WolfSmartsetUnitThingHandler> unitHandlers = new ConcurrentHashMap<>();
|
||||
|
||||
private @Nullable GetSystemListDTO savedSystem;
|
||||
private @Nullable List<SubMenuEntryWithMenuItemTabView> savedUnits;
|
||||
private Map<String, State> stateCache = new ConcurrentHashMap<>();
|
||||
|
||||
public WolfSmartsetSystemBridgeHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
systemId = getConfigAs(WolfSmartsetSystemConfiguration.class).systemId;
|
||||
logger.debug("SystemBridge: Initializing system '{}'", systemId);
|
||||
clearSavedState();
|
||||
updateStatus(WolfSmartsetUtils.isBridgeOnline(getBridge()) ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(WolfSmartsetSystemDiscoveryService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("SystemBridge: Disposing system '{}'", systemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(ThingHandler unitHandler, Thing unitThing) {
|
||||
String unitId = (String) unitThing.getConfiguration().get(CONFIG_UNIT_ID);
|
||||
unitHandlers.put(unitId, (WolfSmartsetUnitThingHandler) unitHandler);
|
||||
logger.debug("SystemBridge: Saving unit handler for {} with id {}", unitThing.getUID(), unitId);
|
||||
var accountBridgeHandler = getAccountBridgeHandler();
|
||||
if (accountBridgeHandler != null) {
|
||||
accountBridgeHandler.scheduleRefreshJob();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerDisposed(ThingHandler unitHandler, Thing unitThing) {
|
||||
String unitId = (String) unitThing.getConfiguration().get(CONFIG_UNIT_ID);
|
||||
unitHandlers.remove(unitId);
|
||||
logger.debug("SystemBridge: Removing unit handler for {} with id {}", unitThing.getUID(), unitId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
State state = stateCache.get(channelUID.getId());
|
||||
if (state != null) {
|
||||
updateState(channelUID.getId(), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated account bridge handler
|
||||
*
|
||||
* @return returns the {@link WolfSmartsetAccountBridgeHandler} linked to this
|
||||
* {@link WolfSmartsetSystemBridgeHandler}
|
||||
*/
|
||||
public @Nullable WolfSmartsetAccountBridgeHandler getAccountBridgeHandler() {
|
||||
var bridgeHandler = this.getBridge();
|
||||
if (bridgeHandler != null) {
|
||||
return (WolfSmartsetAccountBridgeHandler) bridgeHandler.getHandler();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subordinated unit handler
|
||||
*
|
||||
* @return a List of {@link WolfSmartsetUnitThingHandler} with the subordinated unit handler
|
||||
*/
|
||||
public Collection<WolfSmartsetUnitThingHandler> getUnitHandler() {
|
||||
return unitHandlers.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list configuration of the units available for this system
|
||||
*
|
||||
* @return a list of {@link SubMenuEntryWithMenuItemTabView} representing the available units for this system
|
||||
*/
|
||||
public List<SubMenuEntryWithMenuItemTabView> getUnits() {
|
||||
List<SubMenuEntryWithMenuItemTabView> localSavedUnits = savedUnits;
|
||||
return localSavedUnits == null ? EMPTY_UNITS : localSavedUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configuration of this system
|
||||
*
|
||||
* @return {@link GetSystemListDTO} representing the this system
|
||||
*/
|
||||
public @Nullable GetSystemListDTO getSystemConfig() {
|
||||
return savedSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id of this system
|
||||
*
|
||||
* @return the id of this system
|
||||
*/
|
||||
public String getSystemId() {
|
||||
return systemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the system state with the dto
|
||||
*
|
||||
* @param systemState {@link GetSystemStateListDTO} the dto representing the current state of this system
|
||||
*/
|
||||
public void updateSystemState(@Nullable GetSystemStateListDTO systemState) {
|
||||
if (systemState != null) {
|
||||
if (systemState.getIsSystemDeleted()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "System has been deleted");
|
||||
} else if (systemState.getIsSystemShareDeleted()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"System share has been removed");
|
||||
} else if (systemState.getIsSystemShareRejected()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"System share has been rejected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the available fault messages
|
||||
*
|
||||
* @param faultMessages {@link ReadFaultMessagesDTO} the dto representing the list of the current faultmessages
|
||||
*/
|
||||
public void updateFaultMessages(@Nullable ReadFaultMessagesDTO faultMessages) {
|
||||
if (faultMessages != null) {
|
||||
if (faultMessages.getCurrentMessages() != null) {
|
||||
for (var message : faultMessages.getCurrentMessages()) {
|
||||
logger.warn("System {} faultmessage: {}, since {}", systemId, message.getDescription(),
|
||||
message.getOccurTimeLocal());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the configuration of the system and the subordinated units
|
||||
*
|
||||
* @param system {@link GetSystemListDTO} representing this system
|
||||
* @param systemDescription {@link GetGuiDescriptionForGatewayDTO} repesenting the units of this system
|
||||
*/
|
||||
public void updateConfiguration(@Nullable GetSystemListDTO system,
|
||||
@Nullable GetGuiDescriptionForGatewayDTO systemDescription) {
|
||||
if (system != null && systemDescription != null) {
|
||||
logger.debug("SystemBridge: Updating channels for system id {}, name {}", system.getId(), system.getName());
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
savedSystem = system;
|
||||
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, system.getGatewaySoftwareVersion());
|
||||
properties.put(THING_PROPERTY_GATEWAY_ID, system.getGatewayId().toString());
|
||||
properties.put(THING_PROPERTY_GATEWAY_USERNAME, system.getGatewayUsername());
|
||||
properties.put(THING_PROPERTY_INSTALLATION_DATE, system.getInstallationDate());
|
||||
properties.put(THING_PROPERTY_LOCATION, system.getLocation());
|
||||
properties.put(THING_PROPERTY_OPERATOR_NAME, system.getOperatorName());
|
||||
properties.put(THING_PROPERTY_USERNAME_OWNER, system.getUserNameOwner());
|
||||
properties.put(THING_PROPERTY_ACCESSLEVEL, system.getAccessLevel().toString());
|
||||
updateProperties(properties);
|
||||
|
||||
updateUnitsConfiguration(systemDescription);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Unable to retrieve configuration");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUnitsConfiguration(GetGuiDescriptionForGatewayDTO systemDescription) {
|
||||
List<SubMenuEntryWithMenuItemTabView> listUnits = new ArrayList<>();
|
||||
var fachmannNode = systemDescription.getMenuItems().stream()
|
||||
.filter(m -> "Fachmann".equalsIgnoreCase(m.getName())).findFirst();
|
||||
|
||||
if (fachmannNode.isPresent()) {
|
||||
for (var submenu : fachmannNode.get().getSubMenuEntries()) {
|
||||
for (var tabmenu : submenu.getTabViews()) {
|
||||
listUnits.add(new SubMenuEntryWithMenuItemTabView(submenu, tabmenu));
|
||||
|
||||
var handler = unitHandlers.get(tabmenu.bundleId.toString());
|
||||
if (handler != null) {
|
||||
handler.updateConfiguration(submenu, tabmenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
savedUnits = listUnits;
|
||||
}
|
||||
|
||||
private void clearSavedState() {
|
||||
savedSystem = null;
|
||||
savedUnits = null;
|
||||
stateCache.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.handler;
|
||||
|
||||
import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.wolfsmartset.internal.config.WolfSmartsetUnitConfiguration;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.GetParameterValuesDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.MenuItemTabViewDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.ParameterDescriptorDTO;
|
||||
import org.openhab.binding.wolfsmartset.internal.dto.SubMenuEntryDTO;
|
||||
import org.openhab.core.thing.Channel;
|
||||
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.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetUnitThingHandler} is responsible for updating the channels associated
|
||||
* with an WolfSmartset unit.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WolfSmartsetUnitThingHandler extends BaseThingHandler {
|
||||
|
||||
public static final String CAPABILITY_ADC = "adc";
|
||||
public static final String CAPABILITY_CO2 = "co2";
|
||||
public static final String CAPABILITY_DRY_CONTACT = "dryContact";
|
||||
public static final String CAPABILITY_HUMIDITY = "humidity";
|
||||
public static final String CAPABILITY_OCCUPANCY = "occupancy";
|
||||
public static final String CAPABILITY_TEMPERATURE = "temperature";
|
||||
public static final String CAPABILITY_UNKNOWN = "unknown";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WolfSmartsetUnitThingHandler.class);
|
||||
|
||||
private @NonNullByDefault({}) String unitId;
|
||||
private @Nullable Instant lastRefreshTime;
|
||||
|
||||
private Map<String, State> stateCache = new ConcurrentHashMap<>();
|
||||
private Map<Long, ParameterDescriptorDTO> paramDescriptionMap = new ConcurrentHashMap<>();
|
||||
private @Nullable SubMenuEntryDTO submenu;
|
||||
private @Nullable MenuItemTabViewDTO tabmenu;
|
||||
|
||||
public WolfSmartsetUnitThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
unitId = getConfigAs(WolfSmartsetUnitConfiguration.class).unitId;
|
||||
logger.debug("UnitThing: Initializing unit '{}'", unitId);
|
||||
clearSavedState();
|
||||
var bridgeHandler = getBridge();
|
||||
if (bridgeHandler != null) {
|
||||
bridgeStatusChanged(bridgeHandler.getStatusInfo());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("UnitThing: Disposing unit '{}'", unitId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
|
||||
if (this.submenu != null && this.tabmenu != null) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING);
|
||||
}
|
||||
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
State state = stateCache.get(channelUID.getId());
|
||||
if (state != null) {
|
||||
updateState(channelUID.getId(), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link SubMenuEntryDTO} for this unit
|
||||
*
|
||||
* @return the {@link SubMenuEntryDTO} for this unit
|
||||
*/
|
||||
public @Nullable SubMenuEntryDTO getSubMenu() {
|
||||
return this.submenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link MenuItemTabViewDTO} for this unit
|
||||
*
|
||||
* @return the {@link MenuItemTabViewDTO} for this unit
|
||||
*/
|
||||
public @Nullable MenuItemTabViewDTO getTabMenu() {
|
||||
return this.tabmenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Instant} of the last valid call of updateValues
|
||||
*
|
||||
* @return the getInstallationDate of the last valid call of updateValues
|
||||
*/
|
||||
public @Nullable Instant getLastRefreshTime() {
|
||||
return this.lastRefreshTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the configuration of this unit and create / update the related channels
|
||||
*
|
||||
* @param submenu the {@link SubMenuEntryDTO} for this unit
|
||||
* @param tabmenu the {@link MenuItemTabViewDTO} for this unit
|
||||
*/
|
||||
public void updateConfiguration(SubMenuEntryDTO submenu, MenuItemTabViewDTO tabmenu) {
|
||||
this.submenu = submenu;
|
||||
this.tabmenu = tabmenu;
|
||||
var bridgeHandler = getBridge();
|
||||
if (bridgeHandler != null) {
|
||||
bridgeStatusChanged(bridgeHandler.getStatusInfo());
|
||||
}
|
||||
lastRefreshTime = null;
|
||||
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
var thingId = thing.getUID();
|
||||
|
||||
paramDescriptionMap.clear();
|
||||
for (var param : tabmenu.parameterDescriptors) {
|
||||
paramDescriptionMap.put(param.valueId, param);
|
||||
var channelId = new ChannelUID(thingId, param.parameterId.toString()); // "bindingId:type:thingId:1")
|
||||
if (thing.getChannel(channelId) == null) {
|
||||
logger.debug("UnitThing: Create channel '{}'", channelId);
|
||||
Channel channel = ChannelBuilder.create(channelId, getItemType(param.controlType)).withLabel(param.name)
|
||||
.withType(getChannelType(param)).build();
|
||||
thingBuilder.withChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
updateThing(thingBuilder.build());
|
||||
|
||||
for (var param : tabmenu.parameterDescriptors) {
|
||||
var channelId = new ChannelUID(thingId, param.parameterId.toString());
|
||||
setState(channelId, WolfSmartsetUtils.undefOrString(param.value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the values of the channels
|
||||
*
|
||||
* @param values {@link GetParameterValuesDTO} representing the new values
|
||||
*/
|
||||
public void updateValues(@Nullable GetParameterValuesDTO values) {
|
||||
var thingId = thing.getUID();
|
||||
if (values != null && values.getValues() != null && values.getValues().size() > 0) {
|
||||
if (!values.getIsNewJobCreated()) {
|
||||
lastRefreshTime = Instant.now();
|
||||
}
|
||||
|
||||
for (var value : values.getValues()) {
|
||||
var param = paramDescriptionMap.get(value.getValueId());
|
||||
if (param != null) {
|
||||
var channelId = new ChannelUID(thingId, param.parameterId.toString());
|
||||
setState(channelId, WolfSmartsetUtils.undefOrString(value.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the state for the channel in stateCache and calls updateState of this Thing
|
||||
*
|
||||
* @param channelId {@link ChannelUID} the id of the channel to update
|
||||
* @param state {@link State} the new state for the channel
|
||||
*/
|
||||
private void setState(ChannelUID channelId, State state) {
|
||||
stateCache.put(channelId.getId(), state);
|
||||
updateState(channelId, state);
|
||||
}
|
||||
|
||||
private ChannelTypeUID getChannelType(ParameterDescriptorDTO parmeter) {
|
||||
if (parmeter.unit == null || parmeter.unit.isBlank()) {
|
||||
if (parmeter.controlType == null) {
|
||||
return new ChannelTypeUID(BINDING_ID, CH_STRING);
|
||||
} else {
|
||||
switch (parmeter.controlType) {
|
||||
case 1:
|
||||
case 3:
|
||||
case 6:
|
||||
case 8:
|
||||
return new ChannelTypeUID(BINDING_ID, CH_NUMBER);
|
||||
case 5:
|
||||
return new ChannelTypeUID(BINDING_ID, CH_CONTACT);
|
||||
case 9:
|
||||
case 10:
|
||||
return new ChannelTypeUID(BINDING_ID, CH_DATETIME);
|
||||
default:
|
||||
return new ChannelTypeUID(BINDING_ID, CH_STRING);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (parmeter.unit) {
|
||||
case "bar":
|
||||
return new ChannelTypeUID(BINDING_ID, CH_PRESSURE);
|
||||
case "%":
|
||||
case "Std":
|
||||
return new ChannelTypeUID(BINDING_ID, CH_NUMBER);
|
||||
case "°C":
|
||||
return new ChannelTypeUID(BINDING_ID, CH_TEMPERATURE);
|
||||
default:
|
||||
return new ChannelTypeUID(BINDING_ID, CH_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getItemType(Integer controlType) {
|
||||
switch (controlType) {
|
||||
case 1:
|
||||
case 3:
|
||||
case 6:
|
||||
case 8:
|
||||
return "Number";
|
||||
case 5:
|
||||
return "Contact";
|
||||
case 9:
|
||||
case 10:
|
||||
return "DateTime";
|
||||
default:
|
||||
return "String";
|
||||
}
|
||||
}
|
||||
|
||||
private void clearSavedState() {
|
||||
stateCache.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.wolfsmartset.internal.handler;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PointType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link WolfSmartsetUtils} contains utility methods used by the
|
||||
* thing handler and the bridge handler.
|
||||
*
|
||||
* @author Bo Biene - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class WolfSmartsetUtils {
|
||||
|
||||
private static final int UNKNOWN_VALUE = -5002;
|
||||
|
||||
/*
|
||||
* Checks to see if a bridge is online.
|
||||
*/
|
||||
public static boolean isBridgeOnline(@Nullable Bridge bridge) {
|
||||
boolean bridgeStatus = false;
|
||||
if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
|
||||
bridgeStatus = true;
|
||||
}
|
||||
return bridgeStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the state to the passed value. If value is null, set the state to UNDEF
|
||||
*/
|
||||
public static State undefOrOnOff(@Nullable Boolean value) {
|
||||
return value == null ? UnDefType.UNDEF : (value.booleanValue() ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
public static State undefOrString(@Nullable String value) {
|
||||
return value == null ? UnDefType.UNDEF : new StringType(value);
|
||||
}
|
||||
|
||||
public static State undefOrDecimal(@Nullable Number value) {
|
||||
return (value == null || isUnknown(value)) ? UnDefType.UNDEF : new DecimalType(value.doubleValue());
|
||||
}
|
||||
|
||||
public static State undefOrQuantity(@Nullable Number value, Unit<?> unit) {
|
||||
return (value == null || isUnknown(value)) ? UnDefType.UNDEF : new QuantityType<>(value, unit);
|
||||
}
|
||||
|
||||
public static State undefOrTemperature(@Nullable Number value) {
|
||||
return (value == null || isUnknown(value)) ? UnDefType.UNDEF
|
||||
: new QuantityType<>(value.doubleValue() / 10.0, ImperialUnits.FAHRENHEIT);
|
||||
}
|
||||
|
||||
public static State undefOrPoint(@Nullable String value) {
|
||||
return value == null ? UnDefType.UNDEF : new PointType(value);
|
||||
}
|
||||
|
||||
public static State undefOrDate(@Nullable Date date, TimeZoneProvider timeZoneProvider) {
|
||||
return date == null ? UnDefType.UNDEF
|
||||
: new DateTimeType(ZonedDateTime.ofInstant(date.toInstant(), timeZoneProvider.getTimeZone()));
|
||||
}
|
||||
|
||||
private static boolean isUnknown(Number value) {
|
||||
return value.intValue() == UNKNOWN_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a QuantityType<Temperature> to the internal format used by the WolfSmartset API.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Integer convertQuantityTypeToWolfSmartsetTemp(Object value) {
|
||||
if (value instanceof QuantityType<?>) {
|
||||
QuantityType<Temperature> convertedTemp = ((QuantityType<Temperature>) value)
|
||||
.toUnit(ImperialUnits.FAHRENHEIT);
|
||||
if (convertedTemp != null) {
|
||||
return Integer.valueOf(convertedTemp.intValue() * 10);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("temperature is not a QuantityType");
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="wolfsmartset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>WolfSmartset Binding</name>
|
||||
<description>This is the binding for WolfSmartset smart systems.</description>
|
||||
|
||||
</binding:binding>
|
@ -0,0 +1,47 @@
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="thing-type:wolfsmartset:account">
|
||||
<parameter name="username" type="text" required="false">
|
||||
<label>Username</label>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="false">
|
||||
<label>Password</label>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="refreshIntervalStructure" type="integer" min="2" required="false" unit="m">
|
||||
<label>Structure Refresh Interval</label>
|
||||
<description>Specifies the refresh interval in minutes</description>
|
||||
<default>10</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="refreshIntervalValues" type="integer" min="2" required="false" unit="s">
|
||||
<label>States Refresh Interval</label>
|
||||
<description>Specifies time in seconds to refresh states</description>
|
||||
<default>15</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="discoveryEnabled" type="boolean" required="false">
|
||||
<label>Background Discovery</label>
|
||||
<description>Enable/disable automatic discovery</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:wolfsmartset:system">
|
||||
<parameter name="systemId" type="text" required="true">
|
||||
<label>System ID</label>
|
||||
<description>System ID assigned to this system by WolfSmartset</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:wolfsmartset:unit">
|
||||
<parameter name="unitId" type="text" required="true">
|
||||
<label>Unit Id</label>
|
||||
<description>Id assigned to this unit (e.g. rs:101)</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="wolfsmartset"
|
||||
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 ACCOUNT -->
|
||||
<bridge-type id="account">
|
||||
<label>WolfSmartset Account</label>
|
||||
<description>Represents an account at WolfSmartset</description>
|
||||
<config-description-ref uri="thing-type:wolfsmartset:account"/>
|
||||
</bridge-type>
|
||||
|
||||
<!-- THING TYPE SYSTEM -->
|
||||
<bridge-type id="system">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="account"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>WolfSmartset System</label>
|
||||
<description>An WolfSmartset system</description>
|
||||
<representation-property>systemId</representation-property>
|
||||
<config-description-ref uri="thing-type:wolfsmartset:system"/>
|
||||
</bridge-type>
|
||||
|
||||
<!-- THING TYPE UNIT -->
|
||||
<thing-type id="unit">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="system"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>WolfSmartset Unit</label>
|
||||
<description>An WolfSmartset remote unit</description>
|
||||
|
||||
<representation-property>unitId</representation-property>
|
||||
<config-description-ref uri="thing-type:wolfsmartset:unit"/>
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="number">
|
||||
<item-type>Number</item-type>
|
||||
<label>Number</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="contact">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Contact</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="string">
|
||||
<item-type>String</item-type>
|
||||
<label>String</label>
|
||||
<state readOnly="true" pattern="%s"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="datetime">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Date Time</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="barometric-pressure">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Pressure</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
@ -360,6 +360,7 @@
|
||||
<module>org.openhab.binding.windcentrale</module>
|
||||
<module>org.openhab.binding.wlanthermo</module>
|
||||
<module>org.openhab.binding.wled</module>
|
||||
<module>org.openhab.binding.wolfsmartset</module>
|
||||
<module>org.openhab.binding.xmltv</module>
|
||||
<module>org.openhab.binding.xmppclient</module>
|
||||
<module>org.openhab.binding.yamahareceiver</module>
|
||||
|
Loading…
Reference in New Issue
Block a user