[wolfsmartset] Initial contribution (#10751)
Signed-off-by: Bo Biene <openhab.github@biene.eu>
This commit is contained in:
@@ -326,6 +326,7 @@
|
|||||||
/bundles/org.openhab.binding.windcentrale/ @marcelrv
|
/bundles/org.openhab.binding.windcentrale/ @marcelrv
|
||||||
/bundles/org.openhab.binding.wlanthermo/ @CSchlipp
|
/bundles/org.openhab.binding.wlanthermo/ @CSchlipp
|
||||||
/bundles/org.openhab.binding.wled/ @Skinah
|
/bundles/org.openhab.binding.wled/ @Skinah
|
||||||
|
/bundles/org.openhab.binding.wolfsmartset/ @BoBiene
|
||||||
/bundles/org.openhab.binding.xmltv/ @clinique
|
/bundles/org.openhab.binding.xmltv/ @clinique
|
||||||
/bundles/org.openhab.binding.xmppclient/ @pavel-gololobov
|
/bundles/org.openhab.binding.xmppclient/ @pavel-gololobov
|
||||||
/bundles/org.openhab.binding.yamahareceiver/ @davidgraeff @zarusz
|
/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.windcentrale</module>
|
||||||
<module>org.openhab.binding.wlanthermo</module>
|
<module>org.openhab.binding.wlanthermo</module>
|
||||||
<module>org.openhab.binding.wled</module>
|
<module>org.openhab.binding.wled</module>
|
||||||
|
<module>org.openhab.binding.wolfsmartset</module>
|
||||||
<module>org.openhab.binding.xmltv</module>
|
<module>org.openhab.binding.xmltv</module>
|
||||||
<module>org.openhab.binding.xmppclient</module>
|
<module>org.openhab.binding.xmppclient</module>
|
||||||
<module>org.openhab.binding.yamahareceiver</module>
|
<module>org.openhab.binding.yamahareceiver</module>
|
||||||
|
|||||||
Reference in New Issue
Block a user