diff --git a/CODEOWNERS b/CODEOWNERS
index 6d8ddc9c790ab..17363df8e07e8 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -226,7 +226,6 @@
/bundles/org.openhab.binding.mycroft/ @dalgwen
/bundles/org.openhab.binding.mybmw/ @weymann @ntruchsess
/bundles/org.openhab.binding.mynice/ @clinique
-/bundles/org.openhab.binding.myq/ @digitaldan
/bundles/org.openhab.binding.mystrom/ @pail23
/bundles/org.openhab.binding.nanoleaf/ @stefan-hoehn
/bundles/org.openhab.binding.neato/ @jjlauterbach
@@ -355,7 +354,6 @@
/bundles/org.openhab.binding.tplinksmarthome/ @Hilbrand
/bundles/org.openhab.binding.tr064/ @J-N-K
/bundles/org.openhab.binding.tradfri/ @cweitkamp @kaikreuzer
-/bundles/org.openhab.binding.twitter/ @computergeek1507
/bundles/org.openhab.binding.unifi/ @mgbowman @Hilbrand
/bundles/org.openhab.binding.unifiedremote/ @GiviMAD
/bundles/org.openhab.binding.upb/ @marcusb
@@ -386,6 +384,7 @@
/bundles/org.openhab.binding.wled/ @Skinah
/bundles/org.openhab.binding.wolfsmartset/ @BoBiene
/bundles/org.openhab.binding.wundergroundupdatereceiver/ @danieldemus
+/bundles/org.openhab.binding.x/ @computergeek1507
/bundles/org.openhab.binding.xmltv/ @clinique
/bundles/org.openhab.binding.xmppclient/ @pavel-gololobov
/bundles/org.openhab.binding.yamahamusiccast/ @coop-git
diff --git a/README.md b/README.md
index f2e089311a8d3..4a0c1a58b70bd 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,6 @@
[![Jenkins Build Status](https://ci.openhab.org/job/openHAB-Addons/badge/icon)](https://ci.openhab.org/job/openHAB-Addons/)
[![EPL-2.0](https://img.shields.io/badge/license-EPL%202-green.svg)](https://opensource.org/licenses/EPL-2.0)
[![Crowdin](https://badges.crowdin.net/openhab-addons/localized.svg)](https://crowdin.com/project/openhab-addons)
-[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=2164344)](https://www.bountysource.com/teams/openhab/issues?tracker_ids=2164344)
This repository contains the official set of add-ons that are implemented on top of openHAB Core APIs.
Add-ons that got accepted in here will be maintained (e.g. adapted to new core APIs)
diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml
index 9f322e518bc05..dadea0ba22ef7 100644
--- a/bom/openhab-addons/pom.xml
+++ b/bom/openhab-addons/pom.xml
@@ -1116,11 +1116,6 @@
org.openhab.binding.mynice${project.version}
-
- org.openhab.addons.bundles
- org.openhab.binding.myq
- ${project.version}
- org.openhab.addons.bundlesorg.openhab.binding.mystrom
@@ -1761,11 +1756,6 @@
org.openhab.binding.tradfri${project.version}
-
- org.openhab.addons.bundles
- org.openhab.binding.twitter
- ${project.version}
- org.openhab.addons.bundlesorg.openhab.binding.unifi
@@ -1921,6 +1911,11 @@
org.openhab.binding.wundergroundupdatereceiver${project.version}
+
+ org.openhab.addons.bundles
+ org.openhab.binding.x
+ ${project.version}
+ org.openhab.addons.bundlesorg.openhab.binding.xmltv
diff --git a/bundles/org.openhab.automation.jsscripting/src/main/resources/OH-INF/i18n/jsscripting_da.properties b/bundles/org.openhab.automation.jsscripting/src/main/resources/OH-INF/i18n/jsscripting_da.properties
index d9089c4992453..ab0d30d15d9d1 100644
--- a/bundles/org.openhab.automation.jsscripting/src/main/resources/OH-INF/i18n/jsscripting_da.properties
+++ b/bundles/org.openhab.automation.jsscripting/src/main/resources/OH-INF/i18n/jsscripting_da.properties
@@ -1,12 +1,15 @@
+# add-on
+
+addon.jsscripting.name = JavaScript Scripting
+addon.jsscripting.description = Dette tilføjer en JS (ECMAScript-2021) script-motor.
+
+# add-on
+
+automation.config.jsscripting.injectionCachingEnabled.label = Cache openHAB JavaScript-bibliotek injektion
+automation.config.jsscripting.injectionCachingEnabled.description = Brug det medfølgende openHAB JavaScript-bibliotek for optimal ydeevne. Deaktivér denne indstilling for at tillade indlæsning af biblioteket fra den lokale brugerkonfigurerede mappe "automation/js/node_modules". Anvendelse af et bibliotek leveret af brugeren, kan resultere i øgede indlæsningstider, specielt på mindre kraftfulde systemer.
+automation.config.jsscripting.injectionCachingEnabled.option.true = Cache injektion af bibliotek
+automation.config.jsscripting.injectionCachingEnabled.option.false = Cache ikke injektion af bibliotek
automation.config.jsscripting.injectionEnabled.label = Brug indbyggede globale variabler
automation.config.jsscripting.injectionEnabled.description = Importer alle variabler fra openHAB JavaScript-biblioteket ind i alle regler for fælles tjenester som items, things, actions, log, etc... Hvis deaktiveret, kan openHAB JavaScript-biblioteket importeres manuelt med "require('openhab')"
automation.config.jsscripting.injectionEnabled.option.true = Brug indbyggede variabler
automation.config.jsscripting.injectionEnabled.option.false = Brug ikke indbyggede variabler
-automation.config.jsscripting.useIncludedLibrary.label = Brug inkluderet openHAB JavaScript-bibliotek
-automation.config.jsscripting.useIncludedLibrary.description = Brug det medfølgende openHAB JavaScript-bibliotek for optimal ydeevne. Deaktivér denne indstilling for at tillade indlæsning af biblioteket fra den lokale brugerkonfigurerede mappe "automation/js/node_modules". Anvendelse af et bibliotek leveret af brugeren, kan resultere i øgede indlæsningstider, specielt på mindre kraftfulde systemer.
-automation.config.jsscripting.useIncludedLibrary.option.true = Brug inkluderet bibliotek
-automation.config.jsscripting.useIncludedLibrary.option.false = Brug ikke inkluderet bibliotek
-
-# service
-
-service.automation.jsscripting.label = JavaScript Scripting
diff --git a/bundles/org.openhab.binding.bluetooth.bluez/README.md b/bundles/org.openhab.binding.bluetooth.bluez/README.md
index 1a11b16491df9..d54fe306d7444 100644
--- a/bundles/org.openhab.binding.bluetooth.bluez/README.md
+++ b/bundles/org.openhab.binding.bluetooth.bluez/README.md
@@ -1,6 +1,7 @@
# Bluetooth BlueZ Adapter
-This extension supports Bluetooth access via BlueZ and DBus on Linux. This is architecture agnostic and uses Unix Sockets.
+This extension supports Bluetooth access via BlueZ and DBus on Linux.
+This is architecture agnostic and uses Unix Sockets.
# Setup
@@ -33,7 +34,7 @@ Restart running services for changes to take effect.
```shell
systemctl restart dbus
systemctl restart bluetooth
-systemctl restart openhab2
+systemctl restart openhab
```
## Supported Things
diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothUtils.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothUtils.java
index 33c9e8b32783e..456c35e7369b1 100644
--- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothUtils.java
+++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothUtils.java
@@ -47,7 +47,10 @@ public class BluetoothUtils {
*/
public static int[] toIntArray(byte[] value) {
int[] ret = new int[value.length];
- System.arraycopy(value, 0, ret, 0, value.length);
+ // System.arraycopy cannot be used as it throws ArrayStoreException
+ for (int i = 0; i < value.length; i++) {
+ ret[i] = value[i];
+ }
return ret;
}
diff --git a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BPUPListener.java b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BPUPListener.java
index 6420772ee7043..fc7b126d1297b 100644
--- a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BPUPListener.java
+++ b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BPUPListener.java
@@ -132,7 +132,7 @@ private void sendBPUPKeepAlive() {
@Nullable
String bondId = response.bondId;
if (bondId == null || !bondId.equalsIgnoreCase(bridgeHandler.getBridgeId())) {
- logger.warn("Response isn't from expected Bridge! Expected: {} Got: {}",
+ logger.trace("Response isn't from expected Bridge! Expected: {} Got: {}",
bridgeHandler.getBridgeId(), bondId);
} else {
bridgeHandler.setBridgeOnline(inPacket.getAddress().getHostAddress());
@@ -200,7 +200,7 @@ private void processPacket(DatagramPacket packet) {
BPUPUpdate update = transformUpdatePacket(packet);
if (update != null) {
if (!update.bondId.equalsIgnoreCase(bridgeHandler.getBridgeId())) {
- logger.warn("Response isn't from expected Bridge! Expected: {} Got: {}", bridgeHandler.getBridgeId(),
+ logger.trace("Response isn't from expected Bridge! Expected: {} Got: {}", bridgeHandler.getBridgeId(),
update.bondId);
}
@@ -235,7 +235,7 @@ private void processPacket(DatagramPacket packet) {
try {
response = this.gsonBuilder.fromJson(responseJson, BPUPUpdate.class);
} catch (JsonParseException e) {
- logger.warn("Error parsing json! {}", e.getMessage());
+ logger.debug("Error parsing json! {}", e.getMessage());
}
return response;
}
@@ -276,7 +276,7 @@ private void datagramSocketHealthRoutine() {
this.socket = s;
logger.trace("Datagram Socket reconnected using port {}.", s.getPort());
} catch (SocketException exception) {
- logger.warn("Problem creating new socket : {}", exception.getLocalizedMessage());
+ logger.trace("Problem creating new socket : {}", exception.getLocalizedMessage());
}
}
}
diff --git a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BondHttpApi.java b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BondHttpApi.java
index 8dedf69df09e9..46423df31802e 100644
--- a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BondHttpApi.java
+++ b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BondHttpApi.java
@@ -194,7 +194,7 @@ public synchronized void executeDeviceAction(String deviceId, BondDeviceAction a
try {
response = request.send();
} catch (Exception e) {
- logger.warn("Unable to execute device action {} against device {}: {}", deviceId, action, e.getMessage());
+ logger.debug("Unable to execute device action {} against device {}: {}", deviceId, action, e.getMessage());
return;
}
diff --git a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/discovery/BondDiscoveryService.java b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/discovery/BondDiscoveryService.java
index c32697ef3b9a7..64551f0cbf854 100644
--- a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/discovery/BondDiscoveryService.java
+++ b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/discovery/BondDiscoveryService.java
@@ -106,7 +106,7 @@ protected synchronized void startScan() {
}
}
} catch (BondException ignored) {
- logger.warn("Error getting devices for discovery: {}", ignored.getMessage());
+ logger.debug("Error getting devices for discovery: {}", ignored.getMessage());
} finally {
removeOlderResults(getTimestampOfLastScan());
}
diff --git a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/handler/BondBridgeHandler.java b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/handler/BondBridgeHandler.java
index 35cd1806c2c0f..104fa9540a237 100644
--- a/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/handler/BondBridgeHandler.java
+++ b/bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/handler/BondBridgeHandler.java
@@ -230,7 +230,7 @@ public void forwardUpdateToThing(BPUPUpdate pushUpdate) {
logger.trace("could not read topic type from push update or type was not state.");
}
} else {
- logger.warn("Can not read device Id from push update.");
+ logger.trace("Cannot read device Id from push update.");
}
}
@@ -283,7 +283,7 @@ public void setBridgeOffline(ThingStatusDetail detail, String description) {
*/
public void setBridgeOnline(String bridgeAddress) {
if (!config.isValid()) {
- logger.warn("Configuration error, cannot set the bridghe online without configuration");
+ logger.warn("Configuration error, cannot set the bridge online without configuration");
return;
} else if (!config.ipAddress.equals(bridgeAddress)) {
logger.debug("IP address of Bond {} has changed to {}", config.serialNumber, bridgeAddress);
diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandler.java
index 8941c8db18e15..a8c5a49c20533 100644
--- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandler.java
+++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandler.java
@@ -93,7 +93,7 @@ protected void initializeServices() throws BoschSHCException {
CHANNEL_ACTIVE_CONFIGURATION_PROFILE),
true);
this.registerService(intrusionDetectionControlStateService, this::updateChannels,
- List.of(CHANNEL_ARMING_STATE));
+ List.of(CHANNEL_ARMING_STATE, CHANNEL_ACTIVE_CONFIGURATION_PROFILE));
this.registerService(surveillanceAlarmService, this::updateChannels, List.of(CHANNEL_ALARM_STATE));
this.registerStatelessService(armActionService);
this.registerStatelessService(disarmActionService);
@@ -110,6 +110,7 @@ private void updateChannels(IntrusionDetectionSystemState systemState) {
private void updateChannels(IntrusionDetectionControlState controlState) {
super.updateState(CHANNEL_ARMING_STATE, new StringType(controlState.value.toString()));
+ super.updateState(CHANNEL_ACTIVE_CONFIGURATION_PROFILE, new StringType(controlState.activeProfile));
}
private void updateChannels(SurveillanceAlarmState surveillanceAlarmState) {
diff --git a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc_it.properties b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc_it.properties
index 8e420b8864687..f9dca7a23b34e 100644
--- a/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc_it.properties
+++ b/bundles/org.openhab.binding.boschshc/src/main/resources/OH-INF/i18n/boschshc_it.properties
@@ -105,6 +105,8 @@ channel-type.boschshc.purity-rating.label = Valutazione Della Purezza
channel-type.boschshc.purity-rating.description = Valutazione della purezza dell'aria.
channel-type.boschshc.purity.label = Purezza
channel-type.boschshc.purity.description = Purezza dell’aria. Un valore più elevato indica un inquinamento più elevato.
+channel-type.boschshc.scenario-triggered.label = Scenario Attivato
+channel-type.boschshc.scenario-triggered.description = Nome dello scenario attivato
channel-type.boschshc.setpoint-temperature.label = Temperatura Impostata
channel-type.boschshc.setpoint-temperature.description = Temperatura desiderata.
channel-type.boschshc.silent-mode.label = Modalità silenziosa
@@ -126,6 +128,8 @@ channel-type.boschshc.temperature-rating.state.option.MEDIUM = Temperatura Media
channel-type.boschshc.temperature-rating.state.option.BAD = Temperatura Pessima
channel-type.boschshc.temperature.label = Temperatura
channel-type.boschshc.temperature.description = Temperatura misurata corrente.
+channel-type.boschshc.trigger-scenario.label = Scena da Attivare
+channel-type.boschshc.trigger-scenario.description = Nome dello scenario da attivare
channel-type.boschshc.valve-tappet-position.label = Posizione utilizzata dalla Valvola
channel-type.boschshc.valve-tappet-position.description = Rapporto aperto corrente (da 0 a 100).
diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java
index 5f69b925ebf5a..1e318efc7c48b 100644
--- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java
+++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java
@@ -161,6 +161,9 @@ void testUpdateChannelsIntrusionDetectionControlState() {
verify(getCallback()).stateUpdated(
new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ARMING_STATE),
new StringType("SYSTEM_ARMING"));
+ verify(getCallback()).stateUpdated(
+ new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_ACTIVE_CONFIGURATION_PROFILE),
+ new StringType("0"));
}
@Test
diff --git a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt_fr.properties b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt_fr.properties
index 531320fd597c0..7391c52fcb622 100644
--- a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt_fr.properties
+++ b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt_fr.properties
@@ -12,6 +12,10 @@ thing-type.chatgpt.account.description = Compte chez OpenAI utilisé pour accéd
thing-type.config.chatgpt.account.apiKey.label = Clé API
thing-type.config.chatgpt.account.apiKey.description = Clé API pour accéder au compte
+thing-type.config.chatgpt.account.apiUrl.label = URL de l'API
+thing-type.config.chatgpt.account.apiUrl.description = L'API du serveur où atteindre le service IA.
+thing-type.config.chatgpt.account.modelUrl.label = URL du modèle
+thing-type.config.chatgpt.account.modelUrl.description = L'url du modèle d'où récupérer les modèles disponibles.
# channel types
@@ -29,7 +33,7 @@ channel-type.config.chatgpt.chat.systemMessage.description = Le message système
channel-type.config.chatgpt.chat.temperature.label = Température
channel-type.config.chatgpt.chat.temperature.description = Des valeurs plus élevées comme 0.8 rendront la sortie plus aléatoire, tandis que des valeurs plus basses comme 0.2 le rendront plus concentré et déterministe.
-# Status messages
+# status messages
-offline.configuration-error=Aucune clé API configurée
-offline.communication-error=Impossible de se connecter à l'API OpenAI
+offline.configuration-error = Aucune clé API configurée
+offline.communication-error = Impossible de se connecter à l'API OpenAI
diff --git a/bundles/org.openhab.binding.energidataservice/README.md b/bundles/org.openhab.binding.energidataservice/README.md
index 8b717e19d9fc4..c28eb0524a008 100644
--- a/bundles/org.openhab.binding.energidataservice/README.md
+++ b/bundles/org.openhab.binding.energidataservice/README.md
@@ -40,22 +40,22 @@ To obtain the Global Location Number of your grid company:
For customers using electricity for heating, a reduced electricity tax rate may apply after consuming the first 4000 kWh within a year.
When you are entitled to reduced electricity tax, this option should be set.
-This will ensure that thing action calculations use the reduced electricity tax rate when price elements are not explicitly provided.
+This will ensure that thing action calculations use the reduced electricity tax rate when price components are not explicitly provided.
It will not impact channels, see [Electricity Tax](#electricity-tax) for further information.
## Channels
### Channel Group `electricity`
-| Channel | Type | Description | Advanced |
-|-------------------------|--------|---------------------------------------------------------------------------------------|----------|
-| spot-price | Number | Current spot price in DKK or EUR per kWh | no |
-| net-tariff | Number | Current net tariff in DKK per kWh. Only available when `gridCompanyGLN` is configured | no |
-| system-tariff | Number | Current system tariff in DKK per kWh | no |
-| electricity-tax | Number | Current electricity tax in DKK per kWh | no |
-| reduced-electricity-tax | Number | Current reduced electricity tax in DKK per kWh. For electric heating customers only | no |
-| transmission-net-tariff | Number | Current transmission net tariff in DKK per kWh | no |
-| hourly-prices | String | JSON array with hourly prices from 24 hours ago and onward | yes |
+| Channel | Type | Description | Advanced |
+|--------------------------|--------|----------------------------------------------------------------------------------------|----------|
+| spot-price | Number | Current spot price in DKK or EUR per kWh | no |
+| grid-tariff | Number | Current grid tariff in DKK per kWh. Only available when `gridCompanyGLN` is configured | no |
+| system-tariff | Number | Current system tariff in DKK per kWh | no |
+| transmission-grid-tariff | Number | Current transmission grid tariff in DKK per kWh | no |
+| electricity-tax | Number | Current electricity tax in DKK per kWh | no |
+| reduced-electricity-tax | Number | Current reduced electricity tax in DKK per kWh. For electric heating customers only | no |
+| hourly-prices | String | JSON array with hourly prices from 24 hours ago and onward | yes |
_Please note:_ There is no channel providing the total price.
Instead, create a group item with `SUM` as aggregate function and add the individual price items as children.
@@ -82,13 +82,13 @@ The recommended persistence strategy is `forecast`, as it ensures a clean histor
Prices from the past 24 hours and all forthcoming prices will be stored.
Any changes that impact published prices (e.g. selecting or deselecting VAT Profile) will result in the replacement of persisted prices within this period.
-#### Net Tariff
+#### Grid Tariff
-Discounts are automatically taken into account for channel `net-tariff` so that it represents the actual price.
+Discounts are automatically taken into account for channel `grid-tariff` so that it represents the actual price.
The tariffs are downloaded using pre-configured filters for the different [Grid Company GLN's](#global-location-number-of-the-grid-company).
If your company is not in the list, or the filters are not working, they can be manually overridden.
-To override filters, the channel `net-tariff` has the following configuration parameters:
+To override filters, the channel `grid-tariff` has the following configuration parameters:
| Name | Type | Description | Default | Required | Advanced |
|-----------------|---------|----------------------------------------------------------------------------------------------------------------------------------|---------|----------|----------|
@@ -145,21 +145,21 @@ The format of the `hourly-prices` JSON array is as follows:
"hourStart": "2023-09-19T18:00:00Z",
"spotPrice": 0.0,
"spotPriceCurrency": "DKK",
- "netTariff": 0.0,
+ "gridTariff": 0.0,
"systemTariff": 0.054,
+ "transmissionGridTariff": 0.058,
"electricityTax": 0.697,
- "reducedElectricityTax": 0.008,
- "transmissionNetTariff": 0.058
+ "reducedElectricityTax": 0.008
},
{
"hourStart": "2023-09-19T19:00:00Z",
"spotPrice": -0.00052,
"spotPriceCurrency": "DKK",
- "netTariff": 0.0,
+ "gridTariff": 0.0,
"systemTariff": 0.054,
+ "transmissionGridTariff": 0.058,
"electricityTax": 0.697,
- "reducedElectricityTax": 0.008,
- "transmissionNetTariff": 0.058
+ "reducedElectricityTax": 0.008
}
]
```
@@ -170,7 +170,7 @@ Historic prices older than 24 hours are removed from the JSON array each hour.
## Thing Actions
Thing actions can be used to perform calculations as well as import prices directly into rules without deserializing JSON from the [hourly-prices](#hourly-prices) channel.
-This is more convenient, much faster, and provides automatic summation of the price elements of interest.
+This is more convenient, much faster, and provides automatic summation of the price components of interest.
Actions use cached data for performing operations.
Since data is only fetched when an item is linked to a channel, there might not be any cached data available.
@@ -327,30 +327,30 @@ var price = actions.calculatePrice(now.toInstant(), now.plusHours(4).toInstant,
| Parameter | Type | Description |
|--------------------|-----------------------------|--------------------------------------------------------|
-| priceElements | `String` | Comma-separated list of price elements to include |
+| priceComponents | `String` | Comma-separated list of price components to include |
**Result:** `Map`
-The parameter `priceElements` is a case-insensitive comma-separated list of price elements to include in the returned hourly prices.
-These elements can be requested:
+The parameter `priceComponents` is a case-insensitive comma-separated list of price components to include in the returned hourly prices.
+These components can be requested:
-| Price element | Description |
-|-----------------------|-------------------------|
-| SpotPrice | Spot price |
-| NetTariff | Net tariff |
-| SystemTariff | System tariff |
-| ElectricityTax | Electricity tax |
-| ReducedElectricityTax | Reduced electricity tax |
-| TransmissionNetTariff | Transmission net tariff |
+| Price component | Description |
+|------------------------|-------------------------|
+| SpotPrice | Spot price |
+| GridTariff | Grid tariff |
+| SystemTariff | System tariff |
+| TransmissionGridTariff | Transmission grid tariff |
+| ElectricityTax | Electricity tax |
+| ReducedElectricityTax | Reduced electricity tax |
-Using `null` as parameter returns the total prices including all price elements.
+Using `null` as parameter returns the total prices including all price components.
If **Reduced Electricity Tax** is set in Thing configuration, `ElectricityTax` will be excluded, otherwise `ReducedElectricityTax`.
This logic ensures consistent and comparable results not affected by artifical changes in the rate for electricity tax two times per year.
Example:
```javascript
-var priceMap = actions.getPrices("SpotPrice,NetTariff")
+var priceMap = actions.getPrices("SpotPrice,GridTariff")
```
## Full Example
@@ -360,7 +360,7 @@ var priceMap = actions.getPrices("SpotPrice,NetTariff")
```java
Thing energidataservice:service:energidataservice "Energi Data Service" [ priceArea="DK1", currencyCode="DKK", gridCompanyGLN="5790001089030" ] {
Channels:
- Number : electricity#net-tariff [ chargeTypeCodes="CD,CD R", start="StartOfYear" ]
+ Number : electricity#grid-tariff [ chargeTypeCodes="CD,CD R", start="StartOfYear" ]
}
```
@@ -369,10 +369,10 @@ Thing energidataservice:service:energidataservice "Energi Data Service" [ priceA
```java
Group:Number:SUM TotalPrice "Current Total Price"
Number SpotPrice "Current Spot Price" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#spot-price" [profile="transform:VAT"] }
-Number NetTariff "Current Net Tariff" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#net-tariff" [profile="transform:VAT"] }
+Number GridTariff "Current Grid Tariff" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#grid-tariff" [profile="transform:VAT"] }
Number SystemTariff "Current System Tariff" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#system-tariff" [profile="transform:VAT"] }
+Number TransmissionGridTariff "Current Transmission Grid Tariff" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#transmission-grid-tariff" [profile="transform:VAT"] }
Number ElectricityTax "Current Electricity Tax" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#electricity-tax" [profile="transform:VAT"] }
-Number TransmissionNetTariff "Current Transmission Tariff" (TotalPrice) { channel="energidataservice:service:energidataservice:electricity#transmission-net-tariff" [profile="transform:VAT"] }
String HourlyPrices "Hourly Prices" { channel="energidataservice:service:energidataservice:electricity#hourly-prices" }
```
@@ -394,8 +394,8 @@ var priceMap = actions.getPrices(null)
var hourStart = now.toInstant().truncatedTo(ChronoUnit.HOURS)
logInfo("Current total price excl. VAT", priceMap.get(hourStart).toString)
-var priceMap = actions.getPrices("SpotPrice,NetTariff");
-logInfo("Current spot price + net tariff excl. VAT", priceMap.get(hourStart).toString)
+var priceMap = actions.getPrices("SpotPrice,GridTariff");
+logInfo("Current spot price + grid tariff excl. VAT", priceMap.get(hourStart).toString)
var price = actions.calculatePrice(Instant.now, now.plusHours(1).toInstant, 150 | W)
logInfo("Total price for using 150 W for the next hour", price.toString)
@@ -457,10 +457,10 @@ utils.javaMapToJsMap(edsActions.getPrices()).forEach((value, key) => {
var hourStart = time.Instant.now().truncatedTo(time.ChronoUnit.HOURS);
console.log("Current total price excl. VAT: " + priceMap.get(hourStart.toString()));
-utils.javaMapToJsMap(edsActions.getPrices("SpotPrice,NetTariff")).forEach((value, key) => {
+utils.javaMapToJsMap(edsActions.getPrices("SpotPrice,GridTariff")).forEach((value, key) => {
priceMap.set(key.toString(), value);
});
-console.log("Current spot price + net tariff excl. VAT: " + priceMap.get(hourStart.toString()));
+console.log("Current spot price + grid tariff excl. VAT: " + priceMap.get(hourStart.toString()));
var price = edsActions.calculatePrice(time.Instant.now(), time.Instant.now().plusSeconds(3600), Quantity("150 W"));
console.log("Total price for using 150 W for the next hour: " + price.toString());
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/DatahubTariff.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/DatahubTariff.java
index b1e360f53c648..f04dc6146a936 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/DatahubTariff.java
+++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/DatahubTariff.java
@@ -23,11 +23,11 @@
*/
@NonNullByDefault
public enum DatahubTariff {
- NET_TARIFF(CHANNEL_NET_TARIFF),
+ GRID_TARIFF(CHANNEL_GRID_TARIFF),
SYSTEM_TARIFF(CHANNEL_SYSTEM_TARIFF),
+ TRANSMISSION_GRID_TARIFF(CHANNEL_TRANSMISSION_GRID_TARIFF),
ELECTRICITY_TAX(CHANNEL_ELECTRICITY_TAX),
- REDUCED_ELECTRICITY_TAX(CHANNEL_REDUCED_ELECTRICITY_TAX),
- TRANSMISSION_NET_TARIFF(CHANNEL_TRANSMISSION_NET_TARIFF);
+ REDUCED_ELECTRICITY_TAX(CHANNEL_REDUCED_ELECTRICITY_TAX);
String channelId;
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/EnergiDataServiceBindingConstants.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/EnergiDataServiceBindingConstants.java
index 210b133adb074..ccc81cb2d93d5 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/EnergiDataServiceBindingConstants.java
+++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/EnergiDataServiceBindingConstants.java
@@ -42,22 +42,22 @@ public class EnergiDataServiceBindingConstants {
// List of all Channel ids
public static final String CHANNEL_SPOT_PRICE = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR
+ "spot-price";
- public static final String CHANNEL_NET_TARIFF = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR
- + "net-tariff";
+ public static final String CHANNEL_GRID_TARIFF = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR
+ + "grid-tariff";
public static final String CHANNEL_SYSTEM_TARIFF = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR
+ "system-tariff";
public static final String CHANNEL_ELECTRICITY_TAX = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR
+ "electricity-tax";
public static final String CHANNEL_REDUCED_ELECTRICITY_TAX = CHANNEL_GROUP_ELECTRICITY
+ ChannelUID.CHANNEL_GROUP_SEPARATOR + "reduced-electricity-tax";
- public static final String CHANNEL_TRANSMISSION_NET_TARIFF = CHANNEL_GROUP_ELECTRICITY
- + ChannelUID.CHANNEL_GROUP_SEPARATOR + "transmission-net-tariff";
+ public static final String CHANNEL_TRANSMISSION_GRID_TARIFF = CHANNEL_GROUP_ELECTRICITY
+ + ChannelUID.CHANNEL_GROUP_SEPARATOR + "transmission-grid-tariff";
public static final String CHANNEL_HOURLY_PRICES = CHANNEL_GROUP_ELECTRICITY + ChannelUID.CHANNEL_GROUP_SEPARATOR
+ "hourly-prices";
- public static final Set ELECTRICITY_CHANNELS = Set.of(CHANNEL_SPOT_PRICE, CHANNEL_NET_TARIFF,
- CHANNEL_SYSTEM_TARIFF, CHANNEL_ELECTRICITY_TAX, CHANNEL_REDUCED_ELECTRICITY_TAX,
- CHANNEL_TRANSMISSION_NET_TARIFF, CHANNEL_HOURLY_PRICES);
+ public static final Set ELECTRICITY_CHANNELS = Set.of(CHANNEL_SPOT_PRICE, CHANNEL_GRID_TARIFF,
+ CHANNEL_SYSTEM_TARIFF, CHANNEL_TRANSMISSION_GRID_TARIFF, CHANNEL_ELECTRICITY_TAX,
+ CHANNEL_REDUCED_ELECTRICITY_TAX, CHANNEL_HOURLY_PRICES);
// List of all properties
public static final String PROPERTY_REMAINING_CALLS = "remainingCalls";
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActions.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActions.java
index c35cbed206ddd..de4f8385a2232 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActions.java
+++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActions.java
@@ -61,21 +61,21 @@ public class EnergiDataServiceActions implements ThingActions {
private @Nullable EnergiDataServiceHandler handler;
- private enum PriceElement {
+ private enum PriceComponent {
SPOT_PRICE("spotprice", null),
- NET_TARIFF("nettariff", DatahubTariff.NET_TARIFF),
+ GRID_TARIFF("gridtariff", DatahubTariff.GRID_TARIFF),
SYSTEM_TARIFF("systemtariff", DatahubTariff.SYSTEM_TARIFF),
+ TRANSMISSION_GRID_TARIFF("transmissiongridtariff", DatahubTariff.TRANSMISSION_GRID_TARIFF),
ELECTRICITY_TAX("electricitytax", DatahubTariff.ELECTRICITY_TAX),
- REDUCED_ELECTRICITY_TAX("reducedelectricitytax", DatahubTariff.REDUCED_ELECTRICITY_TAX),
- TRANSMISSION_NET_TARIFF("transmissionnettariff", DatahubTariff.TRANSMISSION_NET_TARIFF);
+ REDUCED_ELECTRICITY_TAX("reducedelectricitytax", DatahubTariff.REDUCED_ELECTRICITY_TAX);
- private static final Map NAME_MAP = Stream.of(values())
- .collect(Collectors.toMap(PriceElement::toString, Function.identity()));
+ private static final Map NAME_MAP = Stream.of(values())
+ .collect(Collectors.toMap(PriceComponent::toString, Function.identity()));
private String name;
private @Nullable DatahubTariff datahubTariff;
- private PriceElement(String name, @Nullable DatahubTariff datahubTariff) {
+ private PriceComponent(String name, @Nullable DatahubTariff datahubTariff) {
this.name = name;
this.datahubTariff = datahubTariff;
}
@@ -85,8 +85,8 @@ public String toString() {
return name;
}
- public static PriceElement fromString(final String name) {
- PriceElement myEnum = NAME_MAP.get(name.toLowerCase());
+ public static PriceComponent fromString(final String name) {
+ PriceComponent myEnum = NAME_MAP.get(name.toLowerCase());
if (null == myEnum) {
throw new IllegalArgumentException(String.format("'%s' has no corresponding value. Accepted values: %s",
name, Arrays.asList(values())));
@@ -109,30 +109,30 @@ public static PriceElement fromString(final String name) {
boolean isReducedElectricityTax = handler.isReducedElectricityTax();
- return getPrices(Arrays.stream(PriceElement.values())
- .filter(element -> element != (isReducedElectricityTax ? PriceElement.ELECTRICITY_TAX
- : PriceElement.REDUCED_ELECTRICITY_TAX))
+ return getPrices(Arrays.stream(PriceComponent.values())
+ .filter(component -> component != (isReducedElectricityTax ? PriceComponent.ELECTRICITY_TAX
+ : PriceComponent.REDUCED_ELECTRICITY_TAX))
.collect(Collectors.toSet()));
}
@RuleAction(label = "@text/action.get-prices.label", description = "@text/action.get-prices.description")
public @ActionOutput(name = "prices", type = "java.util.Map") Map getPrices(
- @ActionInput(name = "priceElements", label = "@text/action.get-prices.priceElements.label", description = "@text/action.get-prices.priceElements.description") @Nullable String priceElements) {
- if (priceElements == null) {
- logger.warn("Argument 'priceElements' is null");
+ @ActionInput(name = "priceComponents", label = "@text/action.get-prices.priceComponents.label", description = "@text/action.get-prices.priceComponents.description") @Nullable String priceComponents) {
+ if (priceComponents == null) {
+ logger.warn("Argument 'priceComponents' is null");
return Map.of();
}
- Set priceElementsSet;
+ Set priceComponentsSet;
try {
- priceElementsSet = new HashSet(
- Arrays.stream(priceElements.split(",")).map(PriceElement::fromString).toList());
+ priceComponentsSet = new HashSet(
+ Arrays.stream(priceComponents.split(",")).map(PriceComponent::fromString).toList());
} catch (IllegalArgumentException e) {
logger.warn("{}", e.getMessage());
return Map.of();
}
- return getPrices(priceElementsSet);
+ return getPrices(priceComponentsSet);
}
@RuleAction(label = "@text/action.calculate-price.label", description = "@text/action.calculate-price.description")
@@ -233,7 +233,7 @@ public static PriceElement fromString(final String name) {
}
}
- private Map getPrices(Set priceElements) {
+ private Map getPrices(Set priceComponents) {
EnergiDataServiceHandler handler = this.handler;
if (handler == null) {
logger.warn("EnergiDataServiceActions ThingHandler is null.");
@@ -242,8 +242,8 @@ private Map getPrices(Set priceElements) {
Map prices;
boolean spotPricesRequired;
- if (priceElements.contains(PriceElement.SPOT_PRICE)) {
- if (priceElements.size() > 1 && !handler.getCurrency().equals(CURRENCY_DKK)) {
+ if (priceComponents.contains(PriceComponent.SPOT_PRICE)) {
+ if (priceComponents.size() > 1 && !handler.getCurrency().equals(CURRENCY_DKK)) {
logger.warn("Cannot calculate sum when spot price currency is {}", handler.getCurrency());
return Map.of();
}
@@ -254,13 +254,13 @@ private Map getPrices(Set priceElements) {
prices = new HashMap<>();
}
- for (PriceElement priceElement : PriceElement.values()) {
- DatahubTariff datahubTariff = priceElement.getDatahubTariff();
+ for (PriceComponent priceComponent : PriceComponent.values()) {
+ DatahubTariff datahubTariff = priceComponent.getDatahubTariff();
if (datahubTariff == null) {
continue;
}
- if (priceElements.contains(priceElement)) {
+ if (priceComponents.contains(priceComponent)) {
Map tariffMap = handler.getTariffs(datahubTariff);
mergeMaps(prices, tariffMap, !spotPricesRequired);
}
@@ -287,13 +287,13 @@ private void mergeMaps(Map destinationMap, Map getPrices(@Nullable ThingActions actions, @Nullable String priceElements) {
+ public static Map getPrices(@Nullable ThingActions actions, @Nullable String priceComponents) {
if (actions instanceof EnergiDataServiceActions serviceActions) {
- if (priceElements != null && !priceElements.isBlank()) {
- return serviceActions.getPrices(priceElements);
+ if (priceComponents != null && !priceComponents.isBlank()) {
+ return serviceActions.getPrices(priceComponents);
} else {
return serviceActions.getPrices();
}
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/DatahubTariffFilterFactory.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/DatahubTariffFilterFactory.java
index 07a248939d758..63de9d63802c4 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/DatahubTariffFilterFactory.java
+++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/DatahubTariffFilterFactory.java
@@ -71,7 +71,7 @@ public class DatahubTariffFilterFactory {
public static final LocalDate RADIUS_CUTOFF_DATE = LocalDate.of(2023, 1, 1);
public static final LocalDate KONSTANT_CUTOFF_DATE = LocalDate.of(2023, 2, 1);
- public static DatahubTariffFilter getNetTariffByGLN(String globalLocationNumber) {
+ public static DatahubTariffFilter getGridTariffByGLN(String globalLocationNumber) {
switch (globalLocationNumber) {
case GLN_AAL_ELNET:
return new DatahubTariffFilter(Set.of(ChargeTypeCode.of("AAL-NT-05"), ChargeTypeCode.of("AAL-NTR05")),
@@ -167,6 +167,11 @@ public static DatahubTariffFilter getSystemTariff() {
DateQueryParameter.of(ENERGINET_CUTOFF_DATE));
}
+ public static DatahubTariffFilter getTransmissionGridTariff() {
+ return new DatahubTariffFilter(Set.of(), Set.of(NOTE_TRANSMISSION_NET_TARIFF),
+ DateQueryParameter.of(ENERGINET_CUTOFF_DATE));
+ }
+
public static DatahubTariffFilter getElectricityTax() {
return new DatahubTariffFilter(Set.of(), Set.of(NOTE_ELECTRICITY_TAX),
DateQueryParameter.of(ENERGINET_CUTOFF_DATE));
@@ -176,9 +181,4 @@ public static DatahubTariffFilter getReducedElectricityTax() {
return new DatahubTariffFilter(Set.of(), Set.of(NOTE_REDUCED_ELECTRICITY_TAX),
DateQueryParameter.of(LocalDate.of(2021, 2, 1)));
}
-
- public static DatahubTariffFilter getTransmissionNetTariff() {
- return new DatahubTariffFilter(Set.of(), Set.of(NOTE_TRANSMISSION_NET_TARIFF),
- DateQueryParameter.of(ENERGINET_CUTOFF_DATE));
- }
}
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/handler/EnergiDataServiceHandler.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/handler/EnergiDataServiceHandler.java
index 2a71212972c21..ca686821fb6b0 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/handler/EnergiDataServiceHandler.java
+++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/handler/EnergiDataServiceHandler.java
@@ -95,8 +95,9 @@ public class EnergiDataServiceHandler extends BaseThingHandler {
private @Nullable ScheduledFuture> priceUpdateFuture;
private record Price(String hourStart, BigDecimal spotPrice, String spotPriceCurrency,
- @Nullable BigDecimal netTariff, @Nullable BigDecimal systemTariff, @Nullable BigDecimal electricityTax,
- @Nullable BigDecimal reducedElectricityTax, @Nullable BigDecimal transmissionNetTariff) {
+ @Nullable BigDecimal gridTariff, @Nullable BigDecimal systemTariff,
+ @Nullable BigDecimal transmissionGridTariff, @Nullable BigDecimal electricityTax,
+ @Nullable BigDecimal reducedElectricityTax) {
}
public EnergiDataServiceHandler(Thing thing, HttpClient httpClient, TimeZoneProvider timeZoneProvider) {
@@ -236,7 +237,7 @@ private void downloadSpotPrices() throws InterruptedException, DataServiceExcept
private void downloadTariffs(DatahubTariff datahubTariff) throws InterruptedException, DataServiceException {
GlobalLocationNumber globalLocationNumber = switch (datahubTariff) {
- case NET_TARIFF -> config.getGridCompanyGLN();
+ case GRID_TARIFF -> config.getGridCompanyGLN();
default -> config.getEnerginetGLN();
};
if (globalLocationNumber.isEmpty()) {
@@ -247,11 +248,11 @@ private void downloadTariffs(DatahubTariff datahubTariff) throws InterruptedExce
cacheManager.updateTariffs(datahubTariff);
} else {
DatahubTariffFilter filter = switch (datahubTariff) {
- case NET_TARIFF -> getNetTariffFilter();
+ case GRID_TARIFF -> getGridTariffFilter();
case SYSTEM_TARIFF -> DatahubTariffFilterFactory.getSystemTariff();
+ case TRANSMISSION_GRID_TARIFF -> DatahubTariffFilterFactory.getTransmissionGridTariff();
case ELECTRICITY_TAX -> DatahubTariffFilterFactory.getElectricityTax();
case REDUCED_ELECTRICITY_TAX -> DatahubTariffFilterFactory.getReducedElectricityTax();
- case TRANSMISSION_NET_TARIFF -> DatahubTariffFilterFactory.getTransmissionNetTariff();
};
cacheManager.putTariffs(datahubTariff, downloadPriceLists(globalLocationNumber, filter));
}
@@ -267,24 +268,24 @@ private Collection downloadPriceLists(GlobalLocationNumb
return records;
}
- private DatahubTariffFilter getNetTariffFilter() {
- Channel channel = getThing().getChannel(CHANNEL_NET_TARIFF);
+ private DatahubTariffFilter getGridTariffFilter() {
+ Channel channel = getThing().getChannel(CHANNEL_GRID_TARIFF);
if (channel == null) {
- return DatahubTariffFilterFactory.getNetTariffByGLN(config.gridCompanyGLN);
+ return DatahubTariffFilterFactory.getGridTariffByGLN(config.gridCompanyGLN);
}
DatahubPriceConfiguration datahubPriceConfiguration = channel.getConfiguration()
.as(DatahubPriceConfiguration.class);
if (!datahubPriceConfiguration.hasAnyFilterOverrides()) {
- return DatahubTariffFilterFactory.getNetTariffByGLN(config.gridCompanyGLN);
+ return DatahubTariffFilterFactory.getGridTariffByGLN(config.gridCompanyGLN);
}
DateQueryParameter start = datahubPriceConfiguration.getStart();
if (start == null) {
logger.warn("Invalid channel configuration parameter 'start' or 'offset': {} (offset: {})",
datahubPriceConfiguration.start, datahubPriceConfiguration.offset);
- return DatahubTariffFilterFactory.getNetTariffByGLN(config.gridCompanyGLN);
+ return DatahubTariffFilterFactory.getGridTariffByGLN(config.gridCompanyGLN);
}
Set chargeTypeCodes = datahubPriceConfiguration.getChargeTypeCodes();
@@ -295,7 +296,7 @@ private DatahubTariffFilter getNetTariffFilter() {
filter = new DatahubTariffFilter(chargeTypeCodes, notes, start);
} else {
// Only override start date in pre-configured filter.
- filter = new DatahubTariffFilter(DatahubTariffFilterFactory.getNetTariffByGLN(config.gridCompanyGLN),
+ filter = new DatahubTariffFilter(DatahubTariffFilterFactory.getGridTariffByGLN(config.gridCompanyGLN),
start);
}
@@ -341,13 +342,14 @@ private void updateHourlyPrices() {
int i = 0;
for (Entry sourcePrice : sourcePrices) {
Instant hourStart = sourcePrice.getKey();
- BigDecimal netTariff = cacheManager.getTariff(DatahubTariff.NET_TARIFF, hourStart);
+ BigDecimal gridTariff = cacheManager.getTariff(DatahubTariff.GRID_TARIFF, hourStart);
BigDecimal systemTariff = cacheManager.getTariff(DatahubTariff.SYSTEM_TARIFF, hourStart);
+ BigDecimal transmissionGridTariff = cacheManager.getTariff(DatahubTariff.TRANSMISSION_GRID_TARIFF,
+ hourStart);
BigDecimal electricityTax = cacheManager.getTariff(DatahubTariff.ELECTRICITY_TAX, hourStart);
BigDecimal reducedElectricityTax = cacheManager.getTariff(DatahubTariff.REDUCED_ELECTRICITY_TAX, hourStart);
- BigDecimal transmissionNetTariff = cacheManager.getTariff(DatahubTariff.TRANSMISSION_NET_TARIFF, hourStart);
- targetPrices[i++] = new Price(hourStart.toString(), sourcePrice.getValue(), config.currencyCode, netTariff,
- systemTariff, electricityTax, reducedElectricityTax, transmissionNetTariff);
+ targetPrices[i++] = new Price(hourStart.toString(), sourcePrice.getValue(), config.currencyCode, gridTariff,
+ systemTariff, electricityTax, reducedElectricityTax, transmissionGridTariff);
}
updateState(CHANNEL_HOURLY_PRICES, new StringType(gson.toJson(targetPrices)));
}
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice.properties b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice.properties
index f63c3a834742d..ee8aa84ac78c1 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice.properties
+++ b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice.properties
@@ -60,16 +60,16 @@ channel-group-type.energidataservice.electricity.label = Electricity
channel-group-type.energidataservice.electricity.description = Channels related to electricity
channel-group-type.energidataservice.electricity.channel.electricity-tax.label = Electricity Tax
channel-group-type.energidataservice.electricity.channel.electricity-tax.description = Current electricity tax in DKK per kWh.
-channel-group-type.energidataservice.electricity.channel.net-tariff.label = Net Tariff
-channel-group-type.energidataservice.electricity.channel.net-tariff.description = Current net tariff in DKK per kWh.
+channel-group-type.energidataservice.electricity.channel.grid-tariff.label = Grid Tariff
+channel-group-type.energidataservice.electricity.channel.grid-tariff.description = Current grid tariff in DKK per kWh.
channel-group-type.energidataservice.electricity.channel.reduced-electricity-tax.label = Reduced Electricity Tax
channel-group-type.energidataservice.electricity.channel.reduced-electricity-tax.description = Current reduced electricity tax in DKK per kWh. For electric heating customers only.
channel-group-type.energidataservice.electricity.channel.spot-price.label = Spot Price
channel-group-type.energidataservice.electricity.channel.spot-price.description = Current spot price in DKK or EUR per kWh.
channel-group-type.energidataservice.electricity.channel.system-tariff.label = System Tariff
channel-group-type.energidataservice.electricity.channel.system-tariff.description = Current system tariff in DKK per kWh.
-channel-group-type.energidataservice.electricity.channel.transmission-net-tariff.label = Transmission Net Tariff
-channel-group-type.energidataservice.electricity.channel.transmission-net-tariff.description = Current transmission net tariff in DKK per kWh.
+channel-group-type.energidataservice.electricity.channel.transmission-grid-tariff.label = Transmission Grid Tariff
+channel-group-type.energidataservice.electricity.channel.transmission-grid-tariff.description = Current transmission grid tariff in DKK per kWh.
# channel types
@@ -108,5 +108,5 @@ action.calculate-price.label = calculate price
action.calculate-price.description = calculate price for power consumption in period excl. VAT
action.get-prices.label = get prices
action.get-prices.description = get hourly prices excl. VAT
-action.get-prices.priceElements.label = price elements
-action.get-prices.priceElements.description = comma-separated list of price elements to include in sums
+action.get-prices.priceComponents.label = price components
+action.get-prices.priceComponents.description = comma-separated list of price components to include in sums
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_da.properties b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_da.properties
index 71a9d3f8c0f76..9c85d20f2c6fe 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_da.properties
+++ b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_da.properties
@@ -60,16 +60,16 @@ channel-group-type.energidataservice.electricity.label = Elektricitet
channel-group-type.energidataservice.electricity.description = Kanaler relateret til elektricitet
channel-group-type.energidataservice.electricity.channel.electricity-tax.label = Elafgift
channel-group-type.energidataservice.electricity.channel.electricity-tax.description = Nuværende elafgift i DKK pr. kWh.
-channel-group-type.energidataservice.electricity.channel.net-tariff.label = Nettarif
-channel-group-type.energidataservice.electricity.channel.net-tariff.description = Nuværende nettarif i DKK pr. kWh.
+channel-group-type.energidataservice.electricity.channel.grid-tariff.label = Nettarif
+channel-group-type.energidataservice.electricity.channel.grid-tariff.description = Nuværende nettarif i DKK pr. kWh.
channel-group-type.energidataservice.electricity.channel.reduced-electricity-tax.label = Reduceret elafgift
channel-group-type.energidataservice.electricity.channel.reduced-electricity-tax.description = Nuværende reduceret elafgift i DKK pr. kWh. Kun for elvarmekunder.
channel-group-type.energidataservice.electricity.channel.spot-price.label = Spotpris
channel-group-type.energidataservice.electricity.channel.spot-price.description = Nuværende spotpris i DKK eller EUR pr. kWh.
channel-group-type.energidataservice.electricity.channel.system-tariff.label = Systemtarif
channel-group-type.energidataservice.electricity.channel.system-tariff.description = Nuværende systemtarif i DKK pr. kWh.
-channel-group-type.energidataservice.electricity.channel.transmission-net-tariff.label = Transmissionsnettarif
-channel-group-type.energidataservice.electricity.channel.transmission-net-tariff.description = Nuværende transmissionsnettarif i DKK pr. kWh.
+channel-group-type.energidataservice.electricity.channel.transmission-grid-tariff.label = Transmissionsnettarif
+channel-group-type.energidataservice.electricity.channel.transmission-grid-tariff.description = Nuværende transmissionsnettarif i DKK pr. kWh.
# channel types
@@ -108,5 +108,5 @@ action.calculate-price.label = beregn pris
action.calculate-price.description = beregn pris for elforbrug i perioden ekskl. moms
action.get-prices.label = hent priser
action.get-prices.description = hent timepriser ekskl. moms
-action.get-prices.priceElements.label = priselementer
-action.get-prices.priceElements.description = kommasepareret liste over priselementer der skal medregnes i summer
+action.get-prices.priceComponents.label = priskomponenter
+action.get-prices.priceComponents.description = kommasepareret liste over priskomponenter der skal medregnes i summer
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_it.properties b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_it.properties
index 3f1d1c79e2ea6..74f9f9b9acc1d 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_it.properties
+++ b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/i18n/energidataservice_it.properties
@@ -108,5 +108,5 @@ action.calculate-price.label = calcola il prezzo
action.calculate-price.description = calcolare il prezzo per il consumo di energia nel periodo IVA escl.
action.get-prices.label = ottieni prezzi
action.get-prices.description = ottieni prezzi orari IVA escl.
-action.get-prices.priceElements.label = elementi di prezzo
-action.get-prices.priceElements.description = elenco separato da virgole di elementi di prezzo da includere nelle somme
+action.get-prices.priceComponents.label = componenti del prezzo
+action.get-prices.priceComponents.description = elenco separato da virgole dei componenti del prezzo da includere nelle somme
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/channel-groups.xml b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/channel-groups.xml
index c978b03667b3d..83587c1e46a67 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/channel-groups.xml
+++ b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/channel-groups.xml
@@ -12,14 +12,18 @@
Current spot price in DKK or EUR per kWh.
-
-
- Current net tariff in DKK per kWh.
+
+
+ Current grid tariff in DKK per kWh.Current system tariff in DKK per kWh.
+
+
+ Current transmission grid tariff in DKK per kWh.
+ Current electricity tax in DKK per kWh.
@@ -28,10 +32,6 @@
Current reduced electricity tax in DKK per kWh. For electric heating customers only.
-
-
- Current transmission net tariff in DKK per kWh.
-
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/thing-service.xml b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/thing-service.xml
index b69ef51aa8e13..805510a68eab8 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/thing-service.xml
+++ b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/thing/thing-service.xml
@@ -14,7 +14,7 @@
- 1
+ 2
diff --git a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/update/instructions.xml
index 62e288807ab46..ef4dd6bd99184 100644
--- a/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/update/instructions.xml
+++ b/bundles/org.openhab.binding.energidataservice/src/main/resources/OH-INF/update/instructions.xml
@@ -13,6 +13,21 @@
+
+
+ energidataservice:datahub-price
+
+ Current grid tariff in DKK per kWh.
+
+
+ energidataservice:datahub-price
+
+ Current transmission grid tariff in DKK per kWh.
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActionsTest.java b/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActionsTest.java
index 70ec701cb6123..d1ed9ae9d2828 100644
--- a/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActionsTest.java
+++ b/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/action/EnergiDataServiceActionsTest.java
@@ -109,10 +109,10 @@ void getPricesSpotPrice() throws IOException {
}
@Test
- void getPricesNetTariff() throws IOException {
+ void getPricesGridTariff() throws IOException {
mockCommonDatasets(actions);
- Map actual = actions.getPrices("NetTariff");
+ Map actual = actions.getPrices("GridTariff");
assertThat(actual.size(), is(60));
assertThat(actual.get(Instant.parse("2023-02-04T12:00:00Z")), is(equalTo(new BigDecimal("0.432225"))));
assertThat(actual.get(Instant.parse("2023-02-04T16:00:00Z")), is(equalTo(new BigDecimal("1.05619"))));
@@ -139,30 +139,30 @@ void getPricesElectricityTax() throws IOException {
}
@Test
- void getPricesTransmissionNetTariff() throws IOException {
+ void getPricesTransmissionGridTariff() throws IOException {
mockCommonDatasets(actions);
- Map actual = actions.getPrices("TransmissionNetTariff");
+ Map actual = actions.getPrices("TransmissionGridTariff");
assertThat(actual.size(), is(60));
assertThat(actual.get(Instant.parse("2023-02-04T12:00:00Z")), is(equalTo(new BigDecimal("0.058"))));
assertThat(actual.get(Instant.parse("2023-02-04T16:00:00Z")), is(equalTo(new BigDecimal("0.058"))));
}
@Test
- void getPricesSpotPriceNetTariff() throws IOException {
+ void getPricesSpotPriceGridTariff() throws IOException {
mockCommonDatasets(actions);
- Map actual = actions.getPrices("SpotPrice,NetTariff");
+ Map actual = actions.getPrices("SpotPrice,GridTariff");
assertThat(actual.size(), is(35));
assertThat(actual.get(Instant.parse("2023-02-04T12:00:00Z")), is(equalTo(new BigDecimal("1.425065027"))));
assertThat(actual.get(Instant.parse("2023-02-04T16:00:00Z")), is(equalTo(new BigDecimal("2.323870054"))));
}
@Test
- void getPricesSpotPriceNetTariffElectricityTax() throws IOException {
+ void getPricesSpotPriceGridTariffElectricityTax() throws IOException {
mockCommonDatasets(actions);
- Map actual = actions.getPrices("SpotPrice,NetTariff,ElectricityTax");
+ Map actual = actions.getPrices("SpotPrice,GridTariff,ElectricityTax");
assertThat(actual.size(), is(35));
assertThat(actual.get(Instant.parse("2023-02-04T12:00:00Z")), is(equalTo(new BigDecimal("1.433065027"))));
assertThat(actual.get(Instant.parse("2023-02-04T16:00:00Z")), is(equalTo(new BigDecimal("2.331870054"))));
@@ -198,11 +198,11 @@ void getPricesTotalReducedElectricityTax() throws IOException {
}
@Test
- void getPricesTotalAllElements() throws IOException {
+ void getPricesTotalAllComponents() throws IOException {
mockCommonDatasets(actions);
Map actual = actions
- .getPrices("spotprice,nettariff,systemtariff,electricitytax,transmissionnettariff");
+ .getPrices("spotprice,gridtariff,systemtariff,electricitytax,transmissiongridtariff");
assertThat(actual.size(), is(35));
assertThat(actual.get(Instant.parse("2023-02-04T12:00:00Z")), is(equalTo(new BigDecimal("1.545065027"))));
assertThat(actual.get(Instant.parse("2023-02-04T15:00:00Z")), is(equalTo(new BigDecimal("1.708765039"))));
@@ -210,10 +210,10 @@ void getPricesTotalAllElements() throws IOException {
}
@Test
- void getPricesInvalidPriceElement() throws IOException {
+ void getPricesInvalidPriceComponent() throws IOException {
mockCommonDatasets(actions);
- Map actual = actions.getPrices("spotprice,nettarif");
+ Map actual = actions.getPrices("spotprice,gridtarif");
assertThat(actual.size(), is(0));
}
@@ -222,7 +222,7 @@ void getPricesMixedCurrencies() throws IOException {
mockCommonDatasets(actions);
when(handler.getCurrency()).thenReturn(EnergiDataServiceBindingConstants.CURRENCY_EUR);
- Map actual = actions.getPrices("spotprice,nettariff");
+ Map actual = actions.getPrices("spotprice,gridtariff");
assertThat(actual.size(), is(0));
}
@@ -404,8 +404,8 @@ private void mockCommonDatasets(EnergiDataServiceActions actions, String spotPri
PriceListParser priceListParser = new PriceListParser(
Clock.fixed(spotPriceRecords[0].hourStart, EnergiDataServiceBindingConstants.DATAHUB_TIMEZONE));
- DatahubPricelistRecords datahubRecords = getObjectFromJson("NetTariffs.json", DatahubPricelistRecords.class);
- Map netTariffs = priceListParser
+ DatahubPricelistRecords datahubRecords = getObjectFromJson("GridTariffs.json", DatahubPricelistRecords.class);
+ Map gridTariffs = priceListParser
.toHourly(Arrays.stream(datahubRecords.records()).toList());
datahubRecords = getObjectFromJson("SystemTariffs.json", DatahubPricelistRecords.class);
Map systemTariffs = priceListParser
@@ -416,16 +416,16 @@ private void mockCommonDatasets(EnergiDataServiceActions actions, String spotPri
datahubRecords = getObjectFromJson("ReducedElectricityTaxes.json", DatahubPricelistRecords.class);
Map reducedElectricityTaxes = priceListParser
.toHourly(Arrays.stream(datahubRecords.records()).toList());
- datahubRecords = getObjectFromJson("TransmissionNetTariffs.json", DatahubPricelistRecords.class);
- Map transmissionNetTariffs = priceListParser
+ datahubRecords = getObjectFromJson("TransmissionGridTariffs.json", DatahubPricelistRecords.class);
+ Map transmissionGridTariffs = priceListParser
.toHourly(Arrays.stream(datahubRecords.records()).toList());
when(handler.getSpotPrices()).thenReturn(spotPrices);
- when(handler.getTariffs(DatahubTariff.NET_TARIFF)).thenReturn(netTariffs);
+ when(handler.getTariffs(DatahubTariff.GRID_TARIFF)).thenReturn(gridTariffs);
when(handler.getTariffs(DatahubTariff.SYSTEM_TARIFF)).thenReturn(systemTariffs);
+ when(handler.getTariffs(DatahubTariff.TRANSMISSION_GRID_TARIFF)).thenReturn(transmissionGridTariffs);
when(handler.getTariffs(DatahubTariff.ELECTRICITY_TAX)).thenReturn(electricityTaxes);
when(handler.getTariffs(DatahubTariff.REDUCED_ELECTRICITY_TAX)).thenReturn(reducedElectricityTaxes);
- when(handler.getTariffs(DatahubTariff.TRANSMISSION_NET_TARIFF)).thenReturn(transmissionNetTariffs);
when(handler.getCurrency()).thenReturn(EnergiDataServiceBindingConstants.CURRENCY_DKK);
when(handler.isReducedElectricityTax()).thenReturn(isReducedElectricityTax);
actions.setThingHandler(handler);
diff --git a/bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/NetTariffs.json b/bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/GridTariffs.json
similarity index 100%
rename from bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/NetTariffs.json
rename to bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/GridTariffs.json
diff --git a/bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/TransmissionNetTariffs.json b/bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/TransmissionGridTariffs.json
similarity index 100%
rename from bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/TransmissionNetTariffs.json
rename to bundles/org.openhab.binding.energidataservice/src/test/resources/org/openhab/binding/energidataservice/internal/action/TransmissionGridTariffs.json
diff --git a/bundles/org.openhab.binding.hdpowerview/README.md b/bundles/org.openhab.binding.hdpowerview/README.md
index cda450a74d1d4..339069015ed18 100644
--- a/bundles/org.openhab.binding.hdpowerview/README.md
+++ b/bundles/org.openhab.binding.hdpowerview/README.md
@@ -129,12 +129,13 @@ On Generation 3 gateways the signal strength is displayed in dBm (deciBel-milliW
### Channels for Repeaters (Thing type `repeater`)[1/2]
-| Channel | Item Type | Description |
-|-----------------|-----------|---------------------------------------------------------------------------------------------|
-| color | Color | Controls the color of the LED ring. A switch item can be linked: ON = white, OFF = turn off |
-| brightness | Dimmer | Controls the brightness of the LED ring. |
-| identify | String | Flash repeater to identify. Valid values are: `IDENTIFY` |
-| blinkingEnabled | Switch | Blink during commands. |
+| Channel | Item Type | Description |
+|-----------------|-----------|----------------------------------------------------------|
+| color | Color | Controls the color of the LED ring. |
+| color | Dimmer | Controls the brightness of the LED ring. |
+| color | Switch | Switches the LED ring on or off. |
+| identify | String | Flash repeater to identify. Valid values are: `IDENTIFY` |
+| blinkingEnabled | Switch | Blink during commands. |
### Roller Shutter Up/Down Position vs. Open/Close State
@@ -292,7 +293,7 @@ Repeater items[1/2]:
```java
Color Bedroom_Repeater_Color "Bedroom Repeater Color" {channel="hdpowerview:repeater:home:r16384:color"}
-Dimmer Bedroom_Repeater_Brightness "Bedroom Repeater Brightness" {channel="hdpowerview:repeater:home:r16384:brightness"}
+Dimmer Bedroom_Repeater_Brightness "Bedroom Repeater Brightness" {channel="hdpowerview:repeater:home:r16384:color"}
String Bedroom_Repeater_Identify "Bedroom Repeater Identify" {channel="hdpowerview:repeater:home:r16384:identify"}
Switch Bedroom_Repeater_BlinkingEnabled "Bedroom Repeater Blinking Enabled [%s]" {channel="hdpowerview:repeater:home:r16384:blinkingEnabled"}
```
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java
index 6649024bae82c..34d070858e999 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java
@@ -51,7 +51,6 @@ public class HDPowerViewBindingConstants {
public static final String CHANNEL_SHADE_REPEATER_RSSI = "repeaterRssi";
public static final String CHANNEL_REPEATER_COLOR = "color";
- public static final String CHANNEL_REPEATER_BRIGHTNESS = "brightness";
public static final String CHANNEL_REPEATER_IDENTIFY = "identify";
public static final String CHANNEL_REPEATER_BLINKING_ENABLED = "blinkingEnabled";
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java
index 631cfb6ba7540..3d6c33ca92965 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java
@@ -34,6 +34,10 @@ public Color(int brightness, java.awt.Color color) {
this(brightness, color.getRed(), color.getGreen(), color.getBlue());
}
+ public Color(int brightness, Color color) {
+ this(brightness, color.red, color.green, color.blue);
+ }
+
public Color(int brightness, int red, int green, int blue) {
this.brightness = brightness;
this.red = red;
@@ -41,6 +45,10 @@ public Color(int brightness, int red, int green, int blue) {
this.blue = blue;
}
+ public boolean isBlack() {
+ return red == 0 && green == 0 && blue == 0;
+ }
+
@Override
public String toString() {
return String.format("%d.%d.%d/%d%%", red, green, blue, brightness);
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java
index 1d806fb9bf982..a8442a767b6c5 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java
@@ -28,6 +28,7 @@
import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
import org.openhab.core.library.types.HSBType;
+import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StringType;
@@ -37,6 +38,7 @@
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.types.Command;
+import org.openhab.core.types.RefreshType;
import org.openhab.core.types.UnDefType;
import org.openhab.core.util.ColorUtil;
import org.slf4j.Logger;
@@ -54,6 +56,7 @@ public class HDPowerViewRepeaterHandler extends AbstractHubbedThingHandler {
private static final int REFRESH_INTERVAL_MINUTES = 5;
private static final int IDENTITY_PERIOD_SECONDS = 3;
+ private static final int BRIGHTNESS_STEP_PERCENT = 5;
private static final String COMMAND_IDENTIFY = "IDENTIFY";
private @Nullable ScheduledFuture> refreshStatusFuture = null;
@@ -94,40 +97,17 @@ public void handleCommand(ChannelUID channelUID, Command command) {
logger.warn("Missing bridge handler");
return;
}
+ if (command == RefreshType.REFRESH) {
+ scheduleRefreshJob();
+ return;
+ }
HDPowerViewWebTargets webTargets = bridge.getWebTargets();
try {
RepeaterData repeaterData;
switch (channelUID.getId()) {
case CHANNEL_REPEATER_COLOR:
- if (command instanceof HSBType hsbCommand) {
- Color currentColor = webTargets.getRepeater(repeaterId).color;
- if (currentColor != null) {
- var color = new Color(currentColor.brightness, ColorUtil.hsbTosRgb(hsbCommand));
- repeaterData = webTargets.setRepeaterColor(repeaterId, color);
- scheduler.submit(() -> updatePropertyAndStates(repeaterData));
- }
- } else if (command instanceof OnOffType) {
- Color currentColor = webTargets.getRepeater(repeaterId).color;
- if (currentColor != null) {
- var color = command == OnOffType.ON
- ? new Color(currentColor.brightness, java.awt.Color.WHITE)
- : new Color(currentColor.brightness, java.awt.Color.BLACK);
- repeaterData = webTargets.setRepeaterColor(repeaterId, color);
- scheduler.submit(() -> updatePropertyAndStates(repeaterData));
- }
- }
- break;
- case CHANNEL_REPEATER_BRIGHTNESS:
- if (command instanceof PercentType brightnessCommand) {
- Color currentColor = webTargets.getRepeater(repeaterId).color;
- if (currentColor != null) {
- var color = new Color(brightnessCommand.intValue(), currentColor.red, currentColor.green,
- currentColor.blue);
- repeaterData = webTargets.setRepeaterColor(repeaterId, color);
- scheduler.submit(() -> updatePropertyAndStates(repeaterData));
- }
- }
+ handleColorCommand(command, webTargets);
break;
case CHANNEL_REPEATER_IDENTIFY:
if (command instanceof StringType stringCommand) {
@@ -163,6 +143,54 @@ public void handleCommand(ChannelUID channelUID, Command command) {
}
}
+ private void handleColorCommand(Command command, HDPowerViewWebTargets webTargets) throws HubException {
+ if (command instanceof HSBType hsbCommand) {
+ var color = new Color(hsbCommand.getBrightness().intValue(), ColorUtil.hsbTosRgb(hsbCommand));
+ RepeaterData repeaterData = webTargets.setRepeaterColor(repeaterId, color);
+ scheduler.submit(() -> updatePropertyAndStates(repeaterData));
+ return;
+ }
+ Color currentColor = webTargets.getRepeater(repeaterId).color;
+ if (currentColor == null) {
+ return;
+ }
+ Color newColor;
+ if (command instanceof PercentType brightnessCommand) {
+ newColor = applyBrightnessToColor(currentColor, brightnessCommand.intValue());
+ } else if (command instanceof IncreaseDecreaseType increaseDecreaseCommand) {
+ int brightness = switch (increaseDecreaseCommand) {
+ case INCREASE -> currentColor.brightness + BRIGHTNESS_STEP_PERCENT;
+ case DECREASE -> currentColor.brightness - BRIGHTNESS_STEP_PERCENT;
+ };
+ brightness = brightness < 0 ? 0 : brightness > 100 ? 100 : brightness;
+ newColor = applyBrightnessToColor(currentColor, brightness);
+ } else if (command instanceof OnOffType) {
+ // Light is turned off either by RGB black or zero brightness.
+ int brightness;
+ if (command == OnOffType.ON) {
+ // Turn on with maximum brightness level per default,
+ // if no existing brightness level is available.
+ brightness = currentColor.brightness > 0 ? currentColor.brightness : 100;
+ } else {
+ // Turn off by zero brightness to preserve color.
+ brightness = 0;
+ }
+ newColor = applyBrightnessToColor(currentColor, brightness);
+ } else {
+ logger.warn("Unsupported command: {}", command);
+ return;
+ }
+ RepeaterData repeaterData = webTargets.setRepeaterColor(repeaterId, newColor);
+ scheduler.submit(() -> updatePropertyAndStates(repeaterData));
+ }
+
+ private Color applyBrightnessToColor(Color currentColor, int brightness) {
+ // If light is off by RGB black, then reset to white since otherwise brightness
+ // would have no effect; otherwise preserve color.
+ return currentColor.isBlack() ? new Color(brightness, java.awt.Color.WHITE)
+ : new Color(brightness, currentColor);
+ }
+
private void cancelResetIdentifyStateJob() {
ScheduledFuture> scheduledJob = resetIdentifyStateFuture;
if (scheduledJob != null) {
@@ -182,7 +210,7 @@ private void scheduleRefreshJob() {
private void cancelRefreshJob() {
ScheduledFuture> future = this.refreshStatusFuture;
if (future != null) {
- future.cancel(false);
+ future.cancel(true);
}
this.refreshStatusFuture = null;
}
@@ -228,10 +256,17 @@ private void updatePropertyAndStates(RepeaterData repeaterData) {
Color color = repeaterData.color;
if (color != null) {
logger.debug("Repeater color data received: {}", color.toString());
- updateState(CHANNEL_REPEATER_COLOR, HSBType.fromRGB(color.red, color.green, color.red));
- updateState(CHANNEL_REPEATER_BRIGHTNESS, new PercentType(color.brightness));
+ HSBType hsb;
+ if (color.isBlack()) {
+ // Light is off when RGB black, so discard brightness as otherwise it would appear on.
+ hsb = HSBType.BLACK;
+ } else {
+ hsb = HSBType.fromRGB(color.red, color.green, color.blue);
+ hsb = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(color.brightness));
+ }
+ updateState(CHANNEL_REPEATER_COLOR, hsb);
}
- updateState(CHANNEL_REPEATER_BLINKING_ENABLED, repeaterData.blinkEnabled ? OnOffType.ON : OnOffType.OFF);
+ updateState(CHANNEL_REPEATER_BLINKING_ENABLED, OnOffType.from(repeaterData.blinkEnabled));
}
}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties
index fc10667c8eb4a..8785d2082b3fe 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties
@@ -11,8 +11,7 @@ thing-type.hdpowerview.hub.label = PowerView Hub
thing-type.hdpowerview.hub.description = Hunter Douglas (Luxaflex) PowerView Hub
thing-type.hdpowerview.repeater.label = PowerView Repeater
thing-type.hdpowerview.repeater.description = Hunter Douglas (Luxaflex) PowerView Repeater
-thing-type.hdpowerview.repeater.channel.brightness.description = Controls the brightness of the LED ring
-thing-type.hdpowerview.repeater.channel.color.description = Controls the color of the LED ring
+thing-type.hdpowerview.repeater.channel.color.description = Controls the color and brightness of the LED ring
thing-type.hdpowerview.shade.label = PowerView Shade
thing-type.hdpowerview.shade.description = Hunter Douglas (Luxaflex) PowerView Gen 1/2 Shade
thing-type.hdpowerview.shade.channel.hubRssi.label = Hub RSSI
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview_da.properties b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview_da.properties
index 0511e730800ca..ef816c7596e92 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview_da.properties
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview_da.properties
@@ -11,8 +11,7 @@ thing-type.hdpowerview.hub.label = PowerView Hub
thing-type.hdpowerview.hub.description = Luxaflex PowerView Hub
thing-type.hdpowerview.repeater.label = PowerView repeater
thing-type.hdpowerview.repeater.description = Luxaflex PowerView repeater
-thing-type.hdpowerview.repeater.channel.brightness.description = Styrer lysstyrken på LED-ringen
-thing-type.hdpowerview.repeater.channel.color.description = Styrer farven på LED-ringen
+thing-type.hdpowerview.repeater.channel.color.description = Styrer farven og lysstyrken på LED-ringen
thing-type.hdpowerview.shade.label = PowerView gardin
thing-type.hdpowerview.shade.description = Luxaflex PowerView Gen 1/2-gardin
thing-type.hdpowerview.shade.channel.hubRssi.label = Hub RSSI
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml
index c415c5140f19b..60babc67de520 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml
@@ -13,16 +13,14 @@
- Controls the color of the LED ring
-
-
- Controls the brightness of the LED ring
+ Controls the color and brightness of the LED ring
+ 1Hunter Douglas (Luxaflex)PowerView Repeater
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml
index 70a692f2f238d..bf5468878a3ea 100644
--- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml
+++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml
@@ -3,19 +3,9 @@
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
-
+
-
- powerview:shade-position
-
-
- powerview:shade-position
-
- The secondary vertical position (on top-down/bottom-up shades)
-
-
- powerview:shade-vane
-
+
diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonVirtualDatapointHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonVirtualDatapointHandler.java
index 5caa73d36fdf3..589c015c55088 100644
--- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonVirtualDatapointHandler.java
+++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonVirtualDatapointHandler.java
@@ -68,6 +68,7 @@ public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
HmDatapoint vdp = getVirtualDatapoint(channel);
int usPos = dp.getName().indexOf("_");
String pressType = usPos == -1 ? dp.getName() : dp.getName().substring(usPos + 1);
+ boolean usesLongStart = devicesUsingLongStartEvent.contains(deviceSerial);
boolean isLongPressActive = CommonTriggerEvents.LONG_PRESSED.equals(vdp.getValue())
|| LONG_REPEATED_EVENT.equals(vdp.getValue());
if (MiscUtils.isTrueValue(dp.getValue())) {
@@ -78,14 +79,18 @@ public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
break;
}
case "LONG":
- if (isLongPressActive) {
+ if (usesLongStart) {
// HM-IP devices do long press repetitions via LONG instead of CONT events,
// so clear previous value to force re-triggering of event
- vdp.setValue(null);
- vdp.setValue(LONG_REPEATED_EVENT);
+ if (isLongPressActive) {
+ vdp.setValue(null);
+ vdp.setValue(LONG_REPEATED_EVENT);
+ }
} else {
- // HM devices start long press via LONG events
- vdp.setValue(CommonTriggerEvents.LONG_PRESSED);
+ // HM devices start long press via LONG events, but also may keep sending them
+ // alongside CONT repetition events. In case a long press is already active, we just
+ // acknowledge those events by setting the value again, to make sure to not re-trigger events
+ vdp.setValue(isLongPressActive ? LONG_REPEATED_EVENT : CommonTriggerEvents.LONG_PRESSED);
}
break;
case "LONG_START":
@@ -107,10 +112,10 @@ public void handleEvent(VirtualGateway gateway, HmDatapoint dp) {
break;
default:
vdp.setValue(null);
- logger.warn("Unexpected vaule '{}' for PRESS virtual datapoint", pressType);
+ logger.warn("Unexpected value '{}' for PRESS virtual datapoint", pressType);
}
} else {
- String usedStartEvent = devicesUsingLongStartEvent.contains(deviceSerial) ? "LONG_START" : "LONG";
+ String usedStartEvent = usesLongStart ? "LONG_START" : "LONG";
if (usedStartEvent.equals(pressType) && LONG_REPEATED_EVENT.equals(vdp.getValue())) {
// If we're currently processing a repeated long-press event, don't let the initial LONG
// event time out the repetitions, the CONT delay handler will take care of it
diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java
index c7106c5b6cb4b..dc49e38781bf7 100644
--- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java
+++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java
@@ -70,6 +70,12 @@ public void testLongPressHm() throws IOException, HomematicClientException {
HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_CONT", Boolean.TRUE);
mockEventReceiver.eventReceived(contPressDp);
assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
+ assertThat(buttonVirtualDatapoint.getPreviousValue(), nullValue());
+
+ // Receiving another LONG event during the long press should be ignored
+ mockEventReceiver.eventReceived(longPressDp);
+ assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
+ assertThat(buttonVirtualDatapoint.getPreviousValue(), is("LONG_REPEATED"));
HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
mockEventReceiver.eventReceived(releaseDp);
@@ -87,6 +93,7 @@ public void testLongPressHmIp() throws IOException, HomematicClientException {
HmDatapoint contPressDp = createPressDatapointFrom(longPressDp, "PRESS_LONG", Boolean.TRUE);
mockEventReceiver.eventReceived(contPressDp);
assertThat(buttonVirtualDatapoint.getValue(), is("LONG_REPEATED"));
+ assertThat(buttonVirtualDatapoint.getPreviousValue(), nullValue());
HmDatapoint releaseDp = createPressDatapointFrom(longPressDp, "PRESS_LONG_RELEASE", Boolean.TRUE);
mockEventReceiver.eventReceived(releaseDp);
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ApiVersion.java
similarity index 98%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ApiVersion.java
index e15dbd4ddc018..0180aff0a84a6 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ApiVersion.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersionUtils.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ApiVersionUtils.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersionUtils.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ApiVersionUtils.java
index 2e4cbb6c7b65b..f3f91cad77903 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersionUtils.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ApiVersionUtils.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/BridgeConfigUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/BridgeConfigUpdate.java
similarity index 98%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/BridgeConfigUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/BridgeConfigUpdate.java
index 6e30ceeacf662..9a8fac8f1289e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/BridgeConfigUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/BridgeConfigUpdate.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
* Collection of updates to the bridge configuration.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Capabilities.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Capabilities.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Capabilities.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Capabilities.java
index 80c82ad8194cd..e8ac93edb75cf 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Capabilities.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Capabilities.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
* Collection of capabilities for lights.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ColorTemperature.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ColorTemperature.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ColorTemperature.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ColorTemperature.java
index 4dce4b6c24e18..a57043b052489 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ColorTemperature.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ColorTemperature.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
* Collection of color temperature capabilities to control lights.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Command.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Command.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Command.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Command.java
index 520f24e90fabb..b943bf30ead6e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Command.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Command.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import com.google.gson.Gson;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Config.java
similarity index 98%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Config.java
index 1e67ff79b17bc..600294c0e26b2 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Config.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.ArrayList;
import java.util.Date;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ConfigUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ConfigUpdate.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ConfigUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ConfigUpdate.java
index 00c0afb87a3f7..6e32fbdc880d9 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ConfigUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ConfigUpdate.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import static java.util.stream.Collectors.joining;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Control.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Control.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Control.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Control.java
index 36ae345977df5..077dda488fe59 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Control.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Control.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/CreateUserRequest.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/CreateUserRequest.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/CreateUserRequest.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/CreateUserRequest.java
index 2e29b90508261..9e8c431210d7b 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/CreateUserRequest.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/CreateUserRequest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
*
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ErrorResponse.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ErrorResponse.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ErrorResponse.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ErrorResponse.java
index 86e910b6e7a4c..4a99bc6f7c119 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ErrorResponse.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ErrorResponse.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.List;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullConfig.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullConfig.java
index 7e23c63322478..2dadab5f71bfc 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullConfig.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.ArrayList;
import java.util.List;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullGroup.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullGroup.java
index 2bdd1df35a455..b7d89c9dd96d1 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullGroup.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.ArrayList;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullHueObject.java
similarity index 98%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullHueObject.java
index 8189fb6950cde..6483a72c0deb8 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullHueObject.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import static org.openhab.binding.hue.internal.HueBindingConstants.NORMALIZE_ID_REGEX;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullLight.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullLight.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullLight.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullLight.java
index 4e339e421e1b2..a679ddde52008 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullLight.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullLight.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.time.Duration;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullSensor.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullSensor.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullSensor.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullSensor.java
index cd78f43a2f6ec..f0ae7f0e9578b 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullSensor.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/FullSensor.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.Map;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Group.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Group.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Group.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Group.java
index 62a5d581810de..a725be8578f69 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Group.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Group.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
* Basic group information.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/HueObject.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/HueObject.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/HueObject.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/HueObject.java
index 9dabe99359b55..6dc94bb70be9a 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/HueObject.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/HueObject.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.Map;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/LightLevelConfigUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/LightLevelConfigUpdate.java
similarity index 89%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/LightLevelConfigUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/LightLevelConfigUpdate.java
index 4fac25c8137c9..de51dc303d9b6 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/LightLevelConfigUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/LightLevelConfigUpdate.java
@@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
-import static org.openhab.binding.hue.internal.dto.FullSensor.*;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.*;
/**
* Updates the configuration of a light level sensor
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/NewLightsResponse.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/NewLightsResponse.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/NewLightsResponse.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/NewLightsResponse.java
index 50a74aaefae30..05f438d98f0de 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/NewLightsResponse.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/NewLightsResponse.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
* @author Q42 - Initial contribution
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/PresenceConfigUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/PresenceConfigUpdate.java
similarity index 87%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/PresenceConfigUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/PresenceConfigUpdate.java
index eeaae93fdaa06..baad51a5854d0 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/PresenceConfigUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/PresenceConfigUpdate.java
@@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
-import static org.openhab.binding.hue.internal.dto.FullSensor.*;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.*;
/**
* Updates the configuration of a presence sensor
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Scene.java
similarity index 98%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Scene.java
index ee13d71ac6222..03d179006f345 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Scene.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.ArrayList;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Schedule.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Schedule.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Schedule.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Schedule.java
index 6892b3ad0d220..73353c7ed4a70 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Schedule.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Schedule.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.Map;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ScheduleUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ScheduleUpdate.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ScheduleUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ScheduleUpdate.java
index 7fea44816fa0b..4c64837f9f2de 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ScheduleUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/ScheduleUpdate.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.Date;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SearchForLightsRequest.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SearchForLightsRequest.java
index 91174e678a37d..5c3e1abd28406 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SearchForLightsRequest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.List;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SensorConfigUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SensorConfigUpdate.java
similarity index 83%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SensorConfigUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SensorConfigUpdate.java
index 50452c71af67c..f2a5c4a916525 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SensorConfigUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SensorConfigUpdate.java
@@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
-import static org.openhab.binding.hue.internal.dto.FullSensor.CONFIG_ON;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.CONFIG_ON;
/**
* Collection of updates to the sensor configuration.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SetAttributesRequest.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SetAttributesRequest.java
index 09ae2c155ccef..f3f6f4b694c53 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SetAttributesRequest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.List;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SoftwareUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SoftwareUpdate.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SoftwareUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SoftwareUpdate.java
index 461b8589b3b36..de5ffa82d4441 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SoftwareUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SoftwareUpdate.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
/**
* Details of a bridge firmware update.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/State.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/State.java
similarity index 99%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/State.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/State.java
index 8bb646be256bf..2879c9d6f72e0 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/State.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/State.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.Arrays;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/StateUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/StateUpdate.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/StateUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/StateUpdate.java
index 53bd9d48a35d6..8844d1c5b6a88 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/StateUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/StateUpdate.java
@@ -10,10 +10,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
-import org.openhab.binding.hue.internal.dto.State.AlertMode;
-import org.openhab.binding.hue.internal.dto.State.Effect;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.AlertMode;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.Effect;
/**
* Collection of updates to the state of a light.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SuccessResponse.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SuccessResponse.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SuccessResponse.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SuccessResponse.java
index f0eb43d4455c5..d6c53d44cf851 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SuccessResponse.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/SuccessResponse.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.lang.reflect.Type;
import java.util.List;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/TemperatureConfigUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/TemperatureConfigUpdate.java
similarity index 82%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/TemperatureConfigUpdate.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/TemperatureConfigUpdate.java
index ff66933adfd20..38960594f646e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/TemperatureConfigUpdate.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/TemperatureConfigUpdate.java
@@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
-import static org.openhab.binding.hue.internal.dto.FullSensor.CONFIG_LED_INDICATION;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.CONFIG_LED_INDICATION;
/**
* Updates the configuration of a temperature sensor
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/User.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/User.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/User.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/User.java
index 375734d92fedd..17c729239faec 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/User.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/User.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.util.Date;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Util.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Util.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Util.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Util.java
index 9b4dbf4001205..5459813dc0c29 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Util.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip1/Util.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto;
+package org.openhab.binding.hue.internal.api.dto.clip1;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ActionEntry.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ActionEntry.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ActionEntry.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ActionEntry.java
index 835d4918b653f..aa9c9deeb72e8 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ActionEntry.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ActionEntry.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Alerts.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Alerts.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Alerts.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Alerts.java
index 6d8b86bd9b279..1020a99dd2b6e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Alerts.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Alerts.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.List;
import java.util.Objects;
@@ -18,7 +18,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/BridgeConfig.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/BridgeConfig.java
similarity index 92%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/BridgeConfig.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/BridgeConfig.java
index 66d4250ec39dd..c013078d26fb6 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/BridgeConfig.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/BridgeConfig.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Button.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Button.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Button.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Button.java
index c4f75f6730432..f3135dc7690a9 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Button.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Button.java
@@ -10,11 +10,11 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ButtonEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ButtonEventType;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ButtonReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ButtonReport.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ButtonReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ButtonReport.java
index 947c028258f56..a334d21ebc41c 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ButtonReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ButtonReport.java
@@ -10,13 +10,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ButtonEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ButtonEventType;
/**
* DTO for CLIP 2 button report.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ColorTemperature.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ColorTemperature.java
similarity index 98%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ColorTemperature.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ColorTemperature.java
index 4b5fd5a5eb5dc..c41720be2c48c 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ColorTemperature.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ColorTemperature.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ColorXy.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ColorXy.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ColorXy.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ColorXy.java
index 9b909c51bc4d3..7c19f21d3b751 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ColorXy.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ColorXy.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ContactReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ContactReport.java
similarity index 89%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ContactReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ContactReport.java
index 99c8c2a835c0b..7e1743ebed84e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ContactReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ContactReport.java
@@ -10,12 +10,12 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ContactStateType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ContactStateType;
/**
* DTO for CLIP 2 home security alarm contact.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Dimming.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Dimming.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Dimming.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Dimming.java
index c51c80c51e222..b6b847d59964f 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Dimming.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Dimming.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Dynamics.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Dynamics.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Dynamics.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Dynamics.java
index fd898e6739c21..7b912f5d5a8ca 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Dynamics.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Dynamics.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Duration;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Effects.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Effects.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Effects.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Effects.java
index d73020a5e0283..b5050ef4fa6df 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Effects.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Effects.java
@@ -10,14 +10,14 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.List;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Error.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Error.java
similarity index 92%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Error.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Error.java
index 24437682965dc..90ae7ab0e6787 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Error.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Error.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Event.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Event.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Event.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Event.java
index 04d397df97331..c7e9fe2db9081 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Event.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Event.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.lang.reflect.Type;
import java.util.ArrayList;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Gamut2.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Gamut2.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Gamut2.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Gamut2.java
index b218e57fb732b..bd0179f2779f2 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Gamut2.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Gamut2.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/LightLevel.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/LightLevel.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/LightLevel.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/LightLevel.java
index 9921fba9790e7..673e32533b522 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/LightLevel.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/LightLevel.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/LightLevelReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/LightLevelReport.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/LightLevelReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/LightLevelReport.java
index 189c64f4d1bd6..7c14d62410d56 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/LightLevelReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/LightLevelReport.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MetaData.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MetaData.java
similarity index 89%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MetaData.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MetaData.java
index b416619468d33..1c21cd6fa1769 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MetaData.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MetaData.java
@@ -10,11 +10,11 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MirekSchema.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MirekSchema.java
similarity index 96%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MirekSchema.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MirekSchema.java
index 3a3dee205012a..940c4a0399fd9 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MirekSchema.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MirekSchema.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Motion.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Motion.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Motion.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Motion.java
index 3b0ce60c89f06..9b6de00ecd666 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Motion.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Motion.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MotionReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MotionReport.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MotionReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MotionReport.java
index 8146e524ea6ea..c6078eba8ee56 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/MotionReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/MotionReport.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/OnState.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/OnState.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/OnState.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/OnState.java
index 7ab06791af3cd..d0ba4056fad0c 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/OnState.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/OnState.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/PairXy.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/PairXy.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/PairXy.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/PairXy.java
index fa608129e8f8a..bf70fc73e2373 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/PairXy.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/PairXy.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
/**
* DTO that contains an x and y pair of doubles.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Power.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Power.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Power.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Power.java
index 3becfcdd736d0..caa2c21a92e6d 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Power.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Power.java
@@ -10,10 +10,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.clip2.enums.BatteryStateType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.BatteryStateType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.State;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ProductData.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ProductData.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ProductData.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ProductData.java
index 357d272af9055..1d009e0a9594e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ProductData.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ProductData.java
@@ -10,11 +10,11 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Recall.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Recall.java
similarity index 85%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Recall.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Recall.java
index f489e1cdae48b..35af29a2fd769 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Recall.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Recall.java
@@ -10,14 +10,14 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Duration;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SceneRecallAction;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SmartSceneRecallAction;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SceneRecallAction;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SmartSceneRecallAction;
/**
* DTO for scene and smart scene recall.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RelativeRotary.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RelativeRotary.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RelativeRotary.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RelativeRotary.java
index 3de553a83fbf4..e56e0024639b6 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RelativeRotary.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RelativeRotary.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Resource.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Resource.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java
index 2791bbeab535c..04e92905ba6cc 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Resource.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.math.BigDecimal;
import java.math.MathContext;
@@ -26,16 +26,16 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ButtonEventType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ContactStateType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SceneRecallAction;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SmartSceneRecallAction;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SmartSceneState;
-import org.openhab.binding.hue.internal.dto.clip2.enums.TamperStateType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ZigbeeStatus;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ButtonEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ContactStateType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SceneRecallAction;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SmartSceneRecallAction;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SmartSceneState;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.TamperStateType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ZigbeeStatus;
import org.openhab.binding.hue.internal.exceptions.DTOPresentButEmptyException;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ResourceReference.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ResourceReference.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ResourceReference.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ResourceReference.java
index f8baf1c0f1a9d..47298a816f907 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/ResourceReference.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/ResourceReference.java
@@ -10,11 +10,11 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
/**
* DTO that contains an API reference element.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Resources.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resources.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Resources.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resources.java
index ce554136df111..85f01d64f3694 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Resources.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resources.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.ArrayList;
import java.util.List;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RotaryReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RotaryReport.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RotaryReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RotaryReport.java
index 3d2159afb46d1..9b7c1fa6e0006 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RotaryReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RotaryReport.java
@@ -10,13 +10,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.RotationEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.RotationEventType;
/**
* DTO for CLIP 2 relative rotary report.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Rotation.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Rotation.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Rotation.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Rotation.java
index e6e6f18d45186..fa2364bc951d2 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Rotation.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Rotation.java
@@ -10,13 +10,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.DirectionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.DirectionType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RotationEvent.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RotationEvent.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RotationEvent.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RotationEvent.java
index 1712c79878552..8c0e4679bf06e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/RotationEvent.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/RotationEvent.java
@@ -10,13 +10,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.enums.RotationEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.RotationEventType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TamperReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TamperReport.java
similarity index 89%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TamperReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TamperReport.java
index 50d250898adf4..50b30ef1dcb4e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TamperReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TamperReport.java
@@ -10,12 +10,12 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.clip2.enums.TamperStateType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.TamperStateType;
/**
* DTO for CLIP 2 home security tamper switch.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Temperature.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Temperature.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Temperature.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Temperature.java
index 401476a70a798..f86ea8fa17451 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/Temperature.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Temperature.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TemperatureReport.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TemperatureReport.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TemperatureReport.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TemperatureReport.java
index 1833daca65065..83088abaeab61 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TemperatureReport.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TemperatureReport.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Instant;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TimedEffects.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TimedEffects.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TimedEffects.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TimedEffects.java
index e59dc68f470de..60730bdcb49da 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/TimedEffects.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/TimedEffects.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2;
+package org.openhab.binding.hue.internal.api.dto.clip2;
import java.time.Duration;
import java.util.Objects;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ActionType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ActionType.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ActionType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ActionType.java
index 93484e6d2e69c..e11a7e8ebe094 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ActionType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ActionType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/Archetype.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/Archetype.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/Archetype.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/Archetype.java
index 30c0b1c6eaea1..80f0d97914df3 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/Archetype.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/Archetype.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/BatteryStateType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/BatteryStateType.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/BatteryStateType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/BatteryStateType.java
index 959409c46d356..624598cc8e709 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/BatteryStateType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/BatteryStateType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ButtonEventType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ButtonEventType.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ButtonEventType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ButtonEventType.java
index ad2b7f8228f23..6a1287ffebbee 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ButtonEventType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ButtonEventType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ContactStateType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ContactStateType.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ContactStateType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ContactStateType.java
index 2892e77ca18fb..c50ab0d3cf41a 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ContactStateType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ContactStateType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/DirectionType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/DirectionType.java
similarity index 91%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/DirectionType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/DirectionType.java
index 1af54749985f9..4ed4e918eab1c 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/DirectionType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/DirectionType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/EffectType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/EffectType.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/EffectType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/EffectType.java
index 09663a145971c..8709122498204 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/EffectType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/EffectType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import java.util.Set;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ResourceType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ResourceType.java
similarity index 97%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ResourceType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ResourceType.java
index 56c2f0061be3e..2562de2b43657 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ResourceType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ResourceType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import java.util.EnumSet;
import java.util.Set;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/RotationEventType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/RotationEventType.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/RotationEventType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/RotationEventType.java
index 38e1ccd689b65..359dd6235897f 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/RotationEventType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/RotationEventType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SceneRecallAction.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SceneRecallAction.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SceneRecallAction.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SceneRecallAction.java
index 36987c96025b9..c7057d0b734a8 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SceneRecallAction.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SceneRecallAction.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SmartSceneRecallAction.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SmartSceneRecallAction.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SmartSceneRecallAction.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SmartSceneRecallAction.java
index b12c45282fdb5..f2be1d9431af3 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SmartSceneRecallAction.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SmartSceneRecallAction.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SmartSceneState.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SmartSceneState.java
similarity index 93%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SmartSceneState.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SmartSceneState.java
index 470f9fc7dc64c..e54a1f823760a 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/SmartSceneState.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/SmartSceneState.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/TamperStateType.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/TamperStateType.java
similarity index 90%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/TamperStateType.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/TamperStateType.java
index 23199b1af50d3..afa632dfb8927 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/TamperStateType.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/TamperStateType.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ZigbeeStatus.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ZigbeeStatus.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ZigbeeStatus.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ZigbeeStatus.java
index f9c33d1fe515d..b97e812ccb06e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/enums/ZigbeeStatus.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/enums/ZigbeeStatus.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.enums;
+package org.openhab.binding.hue.internal.api.dto.clip2.enums;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/helper/Setters.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java
similarity index 94%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/helper/Setters.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java
index df400725a3165..641a8025718c6 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/clip2/helper/Setters.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.dto.clip2.helper;
+package org.openhab.binding.hue.internal.api.dto.clip2.helper;
import java.math.BigDecimal;
import java.time.Duration;
@@ -21,18 +21,18 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.Alerts;
-import org.openhab.binding.hue.internal.dto.clip2.ColorTemperature;
-import org.openhab.binding.hue.internal.dto.clip2.ColorXy;
-import org.openhab.binding.hue.internal.dto.clip2.Dimming;
-import org.openhab.binding.hue.internal.dto.clip2.Effects;
-import org.openhab.binding.hue.internal.dto.clip2.MetaData;
-import org.openhab.binding.hue.internal.dto.clip2.MirekSchema;
-import org.openhab.binding.hue.internal.dto.clip2.OnState;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
+import org.openhab.binding.hue.internal.api.dto.clip2.Alerts;
+import org.openhab.binding.hue.internal.api.dto.clip2.ColorTemperature;
+import org.openhab.binding.hue.internal.api.dto.clip2.ColorXy;
+import org.openhab.binding.hue.internal.api.dto.clip2.Dimming;
+import org.openhab.binding.hue.internal.api.dto.clip2.Effects;
+import org.openhab.binding.hue.internal.api.dto.clip2.MetaData;
+import org.openhab.binding.hue.internal.api.dto.clip2.MirekSchema;
+import org.openhab.binding.hue.internal.api.dto.clip2.OnState;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.TimedEffects;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.PercentType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/serialization/InstantDeserializer.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/serialization/InstantDeserializer.java
similarity index 95%
rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/serialization/InstantDeserializer.java
rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/serialization/InstantDeserializer.java
index 1843c3c0417eb..510c94418f145 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/serialization/InstantDeserializer.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/serialization/InstantDeserializer.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.hue.internal.serialization;
+package org.openhab.binding.hue.internal.api.serialization;
import java.lang.reflect.Type;
import java.time.Instant;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/Clip2Bridge.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/Clip2Bridge.java
index 9a8abb1cce9b7..da156b655107e 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/Clip2Bridge.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/Clip2Bridge.java
@@ -70,18 +70,18 @@
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise.Completable;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.openhab.binding.hue.internal.dto.CreateUserRequest;
-import org.openhab.binding.hue.internal.dto.SuccessResponse;
-import org.openhab.binding.hue.internal.dto.clip2.BridgeConfig;
-import org.openhab.binding.hue.internal.dto.clip2.Event;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
-import org.openhab.binding.hue.internal.dto.clip2.Resources;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip1.CreateUserRequest;
+import org.openhab.binding.hue.internal.api.dto.clip1.SuccessResponse;
+import org.openhab.binding.hue.internal.api.dto.clip2.BridgeConfig;
+import org.openhab.binding.hue.internal.api.dto.clip2.Event;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resources;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.serialization.InstantDeserializer;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.HttpUnauthorizedException;
import org.openhab.binding.hue.internal.handler.Clip2BridgeHandler;
-import org.openhab.binding.hue.internal.serialization.InstantDeserializer;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.io.net.http.HttpUtil;
import org.slf4j.Logger;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java
index 650af07aa89e9..7efdee40dd67c 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java
@@ -48,28 +48,28 @@
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
-import org.openhab.binding.hue.internal.dto.ApiVersion;
-import org.openhab.binding.hue.internal.dto.ApiVersionUtils;
-import org.openhab.binding.hue.internal.dto.Config;
-import org.openhab.binding.hue.internal.dto.ConfigUpdate;
-import org.openhab.binding.hue.internal.dto.CreateUserRequest;
-import org.openhab.binding.hue.internal.dto.ErrorResponse;
-import org.openhab.binding.hue.internal.dto.FullConfig;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.FullHueObject;
-import org.openhab.binding.hue.internal.dto.FullLight;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.Group;
-import org.openhab.binding.hue.internal.dto.HueObject;
-import org.openhab.binding.hue.internal.dto.NewLightsResponse;
-import org.openhab.binding.hue.internal.dto.Scene;
-import org.openhab.binding.hue.internal.dto.Schedule;
-import org.openhab.binding.hue.internal.dto.ScheduleUpdate;
-import org.openhab.binding.hue.internal.dto.SearchForLightsRequest;
-import org.openhab.binding.hue.internal.dto.SetAttributesRequest;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
-import org.openhab.binding.hue.internal.dto.SuccessResponse;
-import org.openhab.binding.hue.internal.dto.Util;
+import org.openhab.binding.hue.internal.api.dto.clip1.ApiVersion;
+import org.openhab.binding.hue.internal.api.dto.clip1.ApiVersionUtils;
+import org.openhab.binding.hue.internal.api.dto.clip1.Config;
+import org.openhab.binding.hue.internal.api.dto.clip1.ConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.CreateUserRequest;
+import org.openhab.binding.hue.internal.api.dto.clip1.ErrorResponse;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullConfig;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullHueObject;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.Group;
+import org.openhab.binding.hue.internal.api.dto.clip1.HueObject;
+import org.openhab.binding.hue.internal.api.dto.clip1.NewLightsResponse;
+import org.openhab.binding.hue.internal.api.dto.clip1.Scene;
+import org.openhab.binding.hue.internal.api.dto.clip1.Schedule;
+import org.openhab.binding.hue.internal.api.dto.clip1.ScheduleUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.SearchForLightsRequest;
+import org.openhab.binding.hue.internal.api.dto.clip1.SetAttributesRequest;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.SuccessResponse;
+import org.openhab.binding.hue.internal.api.dto.clip1.Util;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.DeviceOffException;
import org.openhab.binding.hue.internal.exceptions.EmptyResponseException;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/console/HueCommandExtension.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/console/HueCommandExtension.java
index b299cf5693ff7..c75ecb0d44fce 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/console/HueCommandExtension.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/console/HueCommandExtension.java
@@ -25,11 +25,11 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.MetaData;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
-import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip2.MetaData;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.AssetNotLoadedException;
import org.openhab.binding.hue.internal.handler.Clip2BridgeHandler;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/Clip2ThingDiscoveryService.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/Clip2ThingDiscoveryService.java
index 829476e36ebcb..1f1f9cb42e675 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/Clip2ThingDiscoveryService.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/Clip2ThingDiscoveryService.java
@@ -25,11 +25,11 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.clip2.MetaData;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
-import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip2.MetaData;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.AssetNotLoadedException;
import org.openhab.binding.hue.internal.handler.Clip2BridgeHandler;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueDeviceDiscoveryService.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueDeviceDiscoveryService.java
index d05a10943372d..ec6ea4ca56d17 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueDeviceDiscoveryService.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueDeviceDiscoveryService.java
@@ -25,10 +25,10 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.FullHueObject;
-import org.openhab.binding.hue.internal.dto.FullLight;
-import org.openhab.binding.hue.internal.dto.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullHueObject;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
import org.openhab.binding.hue.internal.handler.HueBridgeHandler;
import org.openhab.binding.hue.internal.handler.HueGroupHandler;
import org.openhab.binding.hue.internal.handler.HueLightHandler;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java
index 2891cf9e4ea7b..c94d39ef85199 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java
@@ -30,17 +30,17 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hue.internal.api.dto.clip2.MetaData;
+import org.openhab.binding.hue.internal.api.dto.clip2.ProductData;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resources;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
import org.openhab.binding.hue.internal.config.Clip2BridgeConfig;
import org.openhab.binding.hue.internal.connection.Clip2Bridge;
import org.openhab.binding.hue.internal.connection.HueTlsTrustManagerProvider;
import org.openhab.binding.hue.internal.discovery.Clip2ThingDiscoveryService;
-import org.openhab.binding.hue.internal.dto.clip2.MetaData;
-import org.openhab.binding.hue.internal.dto.clip2.ProductData;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
-import org.openhab.binding.hue.internal.dto.clip2.Resources;
-import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.AssetNotLoadedException;
import org.openhab.binding.hue.internal.exceptions.HttpUnauthorizedException;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java
index a436f7f889a4f..aef0ff5bf27ae 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java
@@ -35,26 +35,26 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.hue.internal.action.DynamicsActions;
+import org.openhab.binding.hue.internal.api.dto.clip2.Alerts;
+import org.openhab.binding.hue.internal.api.dto.clip2.ColorXy;
+import org.openhab.binding.hue.internal.api.dto.clip2.Dimming;
+import org.openhab.binding.hue.internal.api.dto.clip2.Effects;
+import org.openhab.binding.hue.internal.api.dto.clip2.Gamut2;
+import org.openhab.binding.hue.internal.api.dto.clip2.MetaData;
+import org.openhab.binding.hue.internal.api.dto.clip2.MirekSchema;
+import org.openhab.binding.hue.internal.api.dto.clip2.ProductData;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resources;
+import org.openhab.binding.hue.internal.api.dto.clip2.TimedEffects;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SceneRecallAction;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.SmartSceneRecallAction;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ZigbeeStatus;
+import org.openhab.binding.hue.internal.api.dto.clip2.helper.Setters;
import org.openhab.binding.hue.internal.config.Clip2ThingConfig;
-import org.openhab.binding.hue.internal.dto.clip2.Alerts;
-import org.openhab.binding.hue.internal.dto.clip2.ColorXy;
-import org.openhab.binding.hue.internal.dto.clip2.Dimming;
-import org.openhab.binding.hue.internal.dto.clip2.Effects;
-import org.openhab.binding.hue.internal.dto.clip2.Gamut2;
-import org.openhab.binding.hue.internal.dto.clip2.MetaData;
-import org.openhab.binding.hue.internal.dto.clip2.MirekSchema;
-import org.openhab.binding.hue.internal.dto.clip2.ProductData;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
-import org.openhab.binding.hue.internal.dto.clip2.Resources;
-import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SceneRecallAction;
-import org.openhab.binding.hue.internal.dto.clip2.enums.SmartSceneRecallAction;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ZigbeeStatus;
-import org.openhab.binding.hue.internal.dto.clip2.helper.Setters;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.AssetNotLoadedException;
import org.openhab.core.i18n.TimeZoneProvider;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java
index 27705e8710fa0..b8cdad3b9fe0d 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java
@@ -15,8 +15,8 @@
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.Scene;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.Scene;
/**
* The {@link GroupStatusListener} is notified when a group status has changed or a group has been removed or added.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java
index 30991dd198e08..5a1f61ef9f0c1 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java
@@ -35,20 +35,20 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
+import org.openhab.binding.hue.internal.api.dto.clip1.ApiVersionUtils;
+import org.openhab.binding.hue.internal.api.dto.clip1.Config;
+import org.openhab.binding.hue.internal.api.dto.clip1.ConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullConfig;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.Scene;
+import org.openhab.binding.hue.internal.api.dto.clip1.State;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.binding.hue.internal.config.HueBridgeConfig;
import org.openhab.binding.hue.internal.connection.HueBridge;
import org.openhab.binding.hue.internal.connection.HueTlsTrustManagerProvider;
import org.openhab.binding.hue.internal.discovery.HueDeviceDiscoveryService;
-import org.openhab.binding.hue.internal.dto.ApiVersionUtils;
-import org.openhab.binding.hue.internal.dto.Config;
-import org.openhab.binding.hue.internal.dto.ConfigUpdate;
-import org.openhab.binding.hue.internal.dto.FullConfig;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.FullLight;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.Scene;
-import org.openhab.binding.hue.internal.dto.State;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.exceptions.DeviceOffException;
import org.openhab.binding.hue.internal.exceptions.EmptyResponseException;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java
index ea9bca0f5e4a5..fe79b34b1974a 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java
@@ -14,12 +14,12 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hue.internal.api.dto.clip1.ConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.binding.hue.internal.discovery.HueDeviceDiscoveryService;
-import org.openhab.binding.hue.internal.dto.ConfigUpdate;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.FullLight;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
/**
* Access to the Hue system for light handlers.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java
index 118edaef33353..8eb767f7ddbbc 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java
@@ -25,11 +25,11 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.ColorTemperature;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.Scene;
-import org.openhab.binding.hue.internal.dto.State;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.ColorTemperature;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.Scene;
+import org.openhab.binding.hue.internal.api.dto.clip1.State;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java
index a574f8f0900ce..9dda779406d26 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java
@@ -24,11 +24,11 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.Capabilities;
-import org.openhab.binding.hue.internal.dto.ColorTemperature;
-import org.openhab.binding.hue.internal.dto.FullLight;
-import org.openhab.binding.hue.internal.dto.State;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.Capabilities;
+import org.openhab.binding.hue.internal.api.dto.clip1.ColorTemperature;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.State;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java
index 8d3210a57ed0c..9f274be669d01 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java
@@ -13,7 +13,7 @@
package org.openhab.binding.hue.internal.handler;
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
-import static org.openhab.binding.hue.internal.dto.FullSensor.*;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.*;
import static org.openhab.core.thing.Thing.*;
import java.time.LocalDateTime;
@@ -27,9 +27,9 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java
index 525d1f4520bca..cefb960886426 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java
@@ -16,12 +16,12 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hue.internal.dto.ColorTemperature;
-import org.openhab.binding.hue.internal.dto.State;
-import org.openhab.binding.hue.internal.dto.State.AlertMode;
-import org.openhab.binding.hue.internal.dto.State.ColorMode;
-import org.openhab.binding.hue.internal.dto.State.Effect;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.ColorTemperature;
+import org.openhab.binding.hue.internal.api.dto.clip1.State;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.AlertMode;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.ColorMode;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.Effect;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStatusListener.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStatusListener.java
index bcdaad913f9bb..7c8be4d58e935 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStatusListener.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStatusListener.java
@@ -13,7 +13,7 @@
package org.openhab.binding.hue.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
/**
* The {@link LightStatusListener} is notified when a light status has changed or a light has been removed or added.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/SensorStatusListener.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/SensorStatusListener.java
index 6a113c1311ff5..c572e5a43cdfe 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/SensorStatusListener.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/SensorStatusListener.java
@@ -13,7 +13,7 @@
package org.openhab.binding.hue.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
/**
* The {@link SensorStatusListener} is notified when a sensor status has changed or a sensor has been removed or added.
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java
index 89a5c88e3f622..f98329b90dc38 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java
@@ -20,8 +20,8 @@
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Thing;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/DimmerSwitchHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/DimmerSwitchHandler.java
index 8adc3ed736a11..7225aa65e7469 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/DimmerSwitchHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/DimmerSwitchHandler.java
@@ -25,8 +25,8 @@
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DecimalType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/GeofencePresenceHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/GeofencePresenceHandler.java
index ac992a7dc507a..5ac1407f75ef9 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/GeofencePresenceHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/GeofencePresenceHandler.java
@@ -13,14 +13,14 @@
package org.openhab.binding.hue.internal.handler.sensors;
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
-import static org.openhab.binding.hue.internal.dto.FullSensor.STATE_PRESENCE;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.STATE_PRESENCE;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.OnOffType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/LightLevelHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/LightLevelHandler.java
index 933fb05c604ec..b6c0156f5d15b 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/LightLevelHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/LightLevelHandler.java
@@ -13,16 +13,16 @@
package org.openhab.binding.hue.internal.handler.sensors;
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
-import static org.openhab.binding.hue.internal.dto.FullSensor.*;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.*;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.LightLevelConfigUpdate;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.LightLevelConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DecimalType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/PresenceHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/PresenceHandler.java
index be50280afedd8..39caa20297866 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/PresenceHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/PresenceHandler.java
@@ -13,15 +13,15 @@
package org.openhab.binding.hue.internal.handler.sensors;
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
-import static org.openhab.binding.hue.internal.dto.FullSensor.*;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.*;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.PresenceConfigUpdate;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.PresenceConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueClient;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TapSwitchHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TapSwitchHandler.java
index 217301cc364d7..81053688bc484 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TapSwitchHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TapSwitchHandler.java
@@ -25,8 +25,8 @@
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DecimalType;
diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TemperatureHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TemperatureHandler.java
index 3a664bff22e87..c2464aafa2321 100644
--- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TemperatureHandler.java
+++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/TemperatureHandler.java
@@ -13,16 +13,16 @@
package org.openhab.binding.hue.internal.handler.sensors;
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
-import static org.openhab.binding.hue.internal.dto.FullSensor.*;
+import static org.openhab.binding.hue.internal.api.dto.clip1.FullSensor.*;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.FullSensor;
-import org.openhab.binding.hue.internal.dto.SensorConfigUpdate;
-import org.openhab.binding.hue.internal.dto.TemperatureConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullSensor;
+import org.openhab.binding.hue.internal.api.dto.clip1.SensorConfigUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.TemperatureConfigUpdate;
import org.openhab.binding.hue.internal.handler.HueSensorHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.QuantityType;
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java
index 7cb58b7a21a3c..53817f81d637b 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java
@@ -16,7 +16,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
-import org.openhab.binding.hue.internal.dto.ApiVersion;
+import org.openhab.binding.hue.internal.api.dto.clip1.ApiVersion;
/**
* @author Samuel Leisering - Initial contribution
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/HueBridgeTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/HueBridgeTest.java
index a207a3c5c8ccf..6b606b4705c76 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/HueBridgeTest.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/HueBridgeTest.java
@@ -25,9 +25,9 @@
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.jupiter.api.Test;
+import org.openhab.binding.hue.internal.api.dto.clip1.Scene;
import org.openhab.binding.hue.internal.config.HueBridgeConfig;
import org.openhab.binding.hue.internal.connection.HueBridge;
-import org.openhab.binding.hue.internal.dto.Scene;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.core.i18n.CommunicationException;
import org.openhab.core.i18n.ConfigurationException;
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java
index 3640bd996a15f..87b5d4192f7cc 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java
@@ -19,10 +19,10 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
-import org.openhab.binding.hue.internal.dto.ColorTemperature;
-import org.openhab.binding.hue.internal.dto.State;
-import org.openhab.binding.hue.internal.dto.State.ColorMode;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.ColorTemperature;
+import org.openhab.binding.hue.internal.api.dto.clip1.State;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.ColorMode;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.binding.hue.internal.handler.LightStateConverter;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java
index 3498c857025b5..2ea2bd57fd7db 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java
@@ -19,9 +19,9 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
-import org.openhab.binding.hue.internal.dto.FullGroup;
-import org.openhab.binding.hue.internal.dto.Scene;
-import org.openhab.binding.hue.internal.dto.State;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullGroup;
+import org.openhab.binding.hue.internal.api.dto.clip1.Scene;
+import org.openhab.binding.hue.internal.api.dto.clip1.State;
/**
* @author HJiang - initial contribution
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/Clip2DtoTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/Clip2DtoTest.java
index 79b32776d512d..a42a26b9a6302 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/Clip2DtoTest.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/Clip2DtoTest.java
@@ -29,39 +29,39 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
-import org.openhab.binding.hue.internal.dto.clip2.ActionEntry;
-import org.openhab.binding.hue.internal.dto.clip2.Alerts;
-import org.openhab.binding.hue.internal.dto.clip2.Button;
-import org.openhab.binding.hue.internal.dto.clip2.ContactReport;
-import org.openhab.binding.hue.internal.dto.clip2.Dimming;
-import org.openhab.binding.hue.internal.dto.clip2.Effects;
-import org.openhab.binding.hue.internal.dto.clip2.Event;
-import org.openhab.binding.hue.internal.dto.clip2.LightLevel;
-import org.openhab.binding.hue.internal.dto.clip2.MetaData;
-import org.openhab.binding.hue.internal.dto.clip2.MirekSchema;
-import org.openhab.binding.hue.internal.dto.clip2.Motion;
-import org.openhab.binding.hue.internal.dto.clip2.Power;
-import org.openhab.binding.hue.internal.dto.clip2.ProductData;
-import org.openhab.binding.hue.internal.dto.clip2.RelativeRotary;
-import org.openhab.binding.hue.internal.dto.clip2.Resource;
-import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
-import org.openhab.binding.hue.internal.dto.clip2.Resources;
-import org.openhab.binding.hue.internal.dto.clip2.Rotation;
-import org.openhab.binding.hue.internal.dto.clip2.RotationEvent;
-import org.openhab.binding.hue.internal.dto.clip2.TamperReport;
-import org.openhab.binding.hue.internal.dto.clip2.Temperature;
-import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
-import org.openhab.binding.hue.internal.dto.clip2.enums.BatteryStateType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ButtonEventType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.DirectionType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.RotationEventType;
-import org.openhab.binding.hue.internal.dto.clip2.enums.ZigbeeStatus;
-import org.openhab.binding.hue.internal.dto.clip2.helper.Setters;
-import org.openhab.binding.hue.internal.serialization.InstantDeserializer;
+import org.openhab.binding.hue.internal.api.dto.clip2.ActionEntry;
+import org.openhab.binding.hue.internal.api.dto.clip2.Alerts;
+import org.openhab.binding.hue.internal.api.dto.clip2.Button;
+import org.openhab.binding.hue.internal.api.dto.clip2.ContactReport;
+import org.openhab.binding.hue.internal.api.dto.clip2.Dimming;
+import org.openhab.binding.hue.internal.api.dto.clip2.Effects;
+import org.openhab.binding.hue.internal.api.dto.clip2.Event;
+import org.openhab.binding.hue.internal.api.dto.clip2.LightLevel;
+import org.openhab.binding.hue.internal.api.dto.clip2.MetaData;
+import org.openhab.binding.hue.internal.api.dto.clip2.MirekSchema;
+import org.openhab.binding.hue.internal.api.dto.clip2.Motion;
+import org.openhab.binding.hue.internal.api.dto.clip2.Power;
+import org.openhab.binding.hue.internal.api.dto.clip2.ProductData;
+import org.openhab.binding.hue.internal.api.dto.clip2.RelativeRotary;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
+import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
+import org.openhab.binding.hue.internal.api.dto.clip2.Resources;
+import org.openhab.binding.hue.internal.api.dto.clip2.Rotation;
+import org.openhab.binding.hue.internal.api.dto.clip2.RotationEvent;
+import org.openhab.binding.hue.internal.api.dto.clip2.TamperReport;
+import org.openhab.binding.hue.internal.api.dto.clip2.Temperature;
+import org.openhab.binding.hue.internal.api.dto.clip2.TimedEffects;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.BatteryStateType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ButtonEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.DirectionType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.RotationEventType;
+import org.openhab.binding.hue.internal.api.dto.clip2.enums.ZigbeeStatus;
+import org.openhab.binding.hue.internal.api.dto.clip2.helper.Setters;
+import org.openhab.binding.hue.internal.api.serialization.InstantDeserializer;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java
index 5f47d7c43cf52..7ba9acd98a170 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java
@@ -23,10 +23,10 @@
import org.eclipse.jdt.annotation.Nullable;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
-import org.openhab.binding.hue.internal.dto.FullConfig;
-import org.openhab.binding.hue.internal.dto.FullLight;
-import org.openhab.binding.hue.internal.dto.State.ColorMode;
-import org.openhab.binding.hue.internal.dto.StateUpdate;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullConfig;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.ColorMode;
+import org.openhab.binding.hue.internal.api.dto.clip1.StateUpdate;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightState.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightState.java
index c0e8b14e2dfe8..c12fc8c10cc1e 100644
--- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightState.java
+++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightState.java
@@ -13,7 +13,7 @@
package org.openhab.binding.hue.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hue.internal.dto.State.ColorMode;
+import org.openhab.binding.hue.internal.api.dto.clip1.State.ColorMode;
/**
* Builder for the current state of a hue light.
diff --git a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
index cab6e79c895c4..e43c05f09aacc 100644
--- a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
+++ b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
@@ -1424,7 +1424,7 @@ void pollingCameraConnection() {
}
logger.debug("About to connect to the IP Camera using the ONVIF PORT at IP: {}:{}", cameraConfig.getIp(),
cameraConfig.getOnvifPort());
- onvifCamera.connect(thing.getThingTypeUID().getId().equals(ONVIF_THING));
+ onvifCamera.connect(supportsOnvifEvents());
return;
}
if ("ffmpeg".equals(snapshotUri)) {
diff --git a/bundles/org.openhab.binding.lifx/README.md b/bundles/org.openhab.binding.lifx/README.md
index 105ddb8d8071a..ba9438a48ced9 100644
--- a/bundles/org.openhab.binding.lifx/README.md
+++ b/bundles/org.openhab.binding.lifx/README.md
@@ -28,6 +28,8 @@ The following table lists the thing types of the supported LIFX devices:
| LIFX+ BR30 | colorirlight |
| | |
| LIFX Beam | colormzlight |
+| LIFX Neon | colormzlight |
+| LIFX String | colormzlight |
| LIFX Z | colormzlight |
| | |
| LIFX Tile | tilelight |
diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java
index d60e03e5e6502..76890e7485cf5 100644
--- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java
+++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java
@@ -141,7 +141,11 @@ public enum LifxProduct {
PRODUCT_135(135, "LIFX GU10", new Features(TR_1500_9000, COLOR)),
PRODUCT_136(136, "LIFX GU10", new Features(TR_1500_9000, COLOR)),
PRODUCT_137(137, "LIFX Candle", new Features(TR_1500_9000, COLOR, MATRIX)),
- PRODUCT_138(138, "LIFX Candle", new Features(TR_1500_9000, COLOR, MATRIX));
+ PRODUCT_138(138, "LIFX Candle", new Features(TR_1500_9000, COLOR, MATRIX)),
+ PRODUCT_141(141, "LIFX Neon", new Features(TR_1500_9000, COLOR, EXTENDED_MULTIZONE, MULTIZONE)),
+ PRODUCT_142(142, "LIFX Neon", new Features(TR_1500_9000, COLOR, EXTENDED_MULTIZONE, MULTIZONE)),
+ PRODUCT_143(143, "LIFX String", new Features(TR_1500_9000, COLOR, EXTENDED_MULTIZONE, MULTIZONE)),
+ PRODUCT_144(144, "LIFX String", new Features(TR_1500_9000, COLOR, EXTENDED_MULTIZONE, MULTIZONE));
/**
* Enumerates the product features.
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java
index b016a6960e0bd..d73a2e4c622c2 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java
@@ -33,12 +33,14 @@
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
import org.openhab.core.thing.type.ChannelDefinition;
import org.openhab.core.thing.type.ChannelDefinitionBuilder;
import org.openhab.core.thing.type.ChannelType;
import org.openhab.core.thing.type.ChannelTypeBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command;
+import org.openhab.core.types.CommandDescription;
import org.openhab.core.types.StateDescriptionFragment;
/**
@@ -130,6 +132,7 @@ public static class Builder {
private boolean retain;
private boolean trigger;
private boolean isAdvanced;
+ private @Nullable AutoUpdatePolicy autoUpdatePolicy;
private @Nullable Integer qos;
private @Nullable Predicate commandFilter;
@@ -203,6 +206,11 @@ public Builder isAdvanced(boolean advanced) {
return this;
}
+ public Builder withAutoUpdatePolicy(@Nullable AutoUpdatePolicy autoUpdatePolicy) {
+ this.autoUpdatePolicy = autoUpdatePolicy;
+ return this;
+ }
+
public Builder commandFilter(@Nullable Predicate commandFilter) {
this.commandFilter = commandFilter;
return this;
@@ -224,7 +232,7 @@ public ComponentChannel build(boolean addToComponent) {
ChannelType type;
ChannelTypeUID channelTypeUID;
- channelUID = new ChannelUID(component.getGroupUID(), channelID);
+ channelUID = component.buildChannelUID(channelID);
channelTypeUID = new ChannelTypeUID(MqttBindingConstants.BINDING_ID,
channelUID.getGroupId() + "_" + channelID);
channelState = new HomeAssistantChannelState(
@@ -237,23 +245,26 @@ public ComponentChannel build(boolean addToComponent) {
isAdvanced = true;
}
+ ChannelTypeBuilder typeBuilder;
if (this.trigger) {
- type = ChannelTypeBuilder.trigger(channelTypeUID, label)
- .withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL))
- .isAdvanced(isAdvanced).build();
+ typeBuilder = ChannelTypeBuilder.trigger(channelTypeUID, label);
} else {
- StateDescriptionFragment description = valueState.createStateDescription(commandTopic == null).build();
- type = ChannelTypeBuilder.state(channelTypeUID, label, channelState.getItemType())
- .withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL))
- .withStateDescriptionFragment(description).isAdvanced(isAdvanced).build();
+ StateDescriptionFragment stateDescription = valueState.createStateDescription(commandTopic == null)
+ .build();
+ CommandDescription commandDescription = valueState.createCommandDescription().build();
+ typeBuilder = ChannelTypeBuilder.state(channelTypeUID, label, channelState.getItemType())
+ .withStateDescriptionFragment(stateDescription).withCommandDescription(commandDescription);
}
+ type = typeBuilder.withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL))
+ .isAdvanced(isAdvanced).build();
Configuration configuration = new Configuration();
configuration.put("config", component.getChannelConfigurationJson());
component.getHaID().toConfig(configuration);
channel = ChannelBuilder.create(channelUID, channelState.getItemType()).withType(channelTypeUID)
- .withKind(type.getKind()).withLabel(label).withConfiguration(configuration).build();
+ .withKind(type.getKind()).withLabel(label).withConfiguration(configuration)
+ .withAutoUpdatePolicy(autoUpdatePolicy).build();
ComponentChannel result = new ComponentChannel(channelUID, channelState, channel, type, channelTypeUID,
channelStateUpdateListener);
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java
index 203218baa75ae..ebe696ee01aa5 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java
@@ -14,6 +14,7 @@
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
@@ -31,8 +32,10 @@
import org.openhab.binding.mqtt.homeassistant.internal.HaID;
import org.openhab.binding.mqtt.homeassistant.internal.component.ComponentFactory.ComponentConfiguration;
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
+import org.openhab.binding.mqtt.homeassistant.internal.config.dto.Device;
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.thing.ChannelGroupUID;
+import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.type.ChannelDefinition;
import org.openhab.core.thing.type.ChannelGroupDefinition;
import org.openhab.core.thing.type.ChannelGroupType;
@@ -54,8 +57,8 @@ public abstract class AbstractComponent
// Component location fields
private final ComponentConfiguration componentConfiguration;
- protected final ChannelGroupTypeUID channelGroupTypeUID;
- protected final ChannelGroupUID channelGroupUID;
+ protected final @Nullable ChannelGroupTypeUID channelGroupTypeUID;
+ protected final @Nullable ChannelGroupUID channelGroupUID;
protected final HaID haID;
// Channels and configuration
@@ -83,10 +86,16 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig
this.haID = componentConfiguration.getHaID();
- String groupId = this.haID.getGroupId(channelConfiguration.getUniqueId());
+ String name = channelConfiguration.getName();
+ if (name != null && !name.isEmpty()) {
+ String groupId = this.haID.getGroupId(channelConfiguration.getUniqueId());
- this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId);
- this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId);
+ this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId);
+ this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId);
+ } else {
+ this.channelGroupTypeUID = null;
+ this.channelGroupUID = null;
+ }
this.configSeen = false;
@@ -142,7 +151,10 @@ public void setConfigSeen() {
* @param channelTypeProvider The channel type provider
*/
public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) {
- channelTypeProvider.setChannelGroupType(getGroupTypeUID(), getType());
+ ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
+ if (groupTypeUID != null) {
+ channelTypeProvider.setChannelGroupType(groupTypeUID, Objects.requireNonNull(getType()));
+ }
channels.values().forEach(v -> v.addChannelTypes(channelTypeProvider));
}
@@ -154,20 +166,31 @@ public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) {
*/
public void removeChannelTypes(MqttChannelTypeProvider channelTypeProvider) {
channels.values().forEach(v -> v.removeChannelTypes(channelTypeProvider));
- channelTypeProvider.removeChannelGroupType(getGroupTypeUID());
+ ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
+ if (groupTypeUID != null) {
+ channelTypeProvider.removeChannelGroupType(groupTypeUID);
+ }
+ }
+
+ public ChannelUID buildChannelUID(String channelID) {
+ final ChannelGroupUID groupUID = channelGroupUID;
+ if (groupUID != null) {
+ return new ChannelUID(groupUID, channelID);
+ }
+ return new ChannelUID(componentConfiguration.getThingUID(), channelID);
}
/**
* Each HomeAssistant component corresponds to a Channel Group Type.
*/
- public ChannelGroupTypeUID getGroupTypeUID() {
+ public @Nullable ChannelGroupTypeUID getGroupTypeUID() {
return channelGroupTypeUID;
}
/**
* The unique id of this component.
*/
- public ChannelGroupUID getGroupUID() {
+ public @Nullable ChannelGroupUID getGroupUID() {
return channelGroupUID;
}
@@ -175,7 +198,16 @@ public ChannelGroupUID getGroupUID() {
* Component (Channel Group) name.
*/
public String getName() {
- return channelConfiguration.getName();
+ String result = channelConfiguration.getName();
+
+ Device device = channelConfiguration.getDevice();
+ if (result == null && device != null) {
+ result = device.getName();
+ }
+ if (result == null) {
+ result = haID.objectID;
+ }
+ return result;
}
/**
@@ -207,11 +239,19 @@ public int getConfigHash() {
/**
* Return the channel group type.
*/
- public ChannelGroupType getType() {
+ public @Nullable ChannelGroupType getType() {
+ ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
+ if (groupTypeUID == null) {
+ return null;
+ }
final List channelDefinitions = channels.values().stream().map(ComponentChannel::type)
.collect(Collectors.toList());
- return ChannelGroupTypeBuilder.instance(channelGroupTypeUID, getName())
- .withChannelDefinitions(channelDefinitions).build();
+ return ChannelGroupTypeBuilder.instance(groupTypeUID, getName()).withChannelDefinitions(channelDefinitions)
+ .build();
+ }
+
+ public List getChannels() {
+ return channels.values().stream().map(ComponentChannel::type).collect(Collectors.toList());
}
/**
@@ -225,8 +265,12 @@ public void resetState() {
/**
* Return the channel group definition for this component.
*/
- public ChannelGroupDefinition getGroupDefinition() {
- return new ChannelGroupDefinition(channelGroupUID.getId(), getGroupTypeUID(), getName(), null);
+ public @Nullable ChannelGroupDefinition getGroupDefinition() {
+ ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID;
+ if (groupTypeUID == null) {
+ return null;
+ }
+ return new ChannelGroupDefinition(channelGroupUID.getId(), groupTypeUID, getName(), null);
}
public HaID getHaID() {
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java
index 8d213e7075cd8..5f60eec5fad53 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java
@@ -74,24 +74,23 @@ public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfig
final String[] stateEnum = { channelConfiguration.stateDisarmed, channelConfiguration.stateArmedHome,
channelConfiguration.stateArmedAway, channelConfiguration.statePending,
channelConfiguration.stateTriggered };
- buildChannel(STATE_CHANNEL_ID, new TextValue(stateEnum), channelConfiguration.getName(),
- componentConfiguration.getUpdateListener())
+ buildChannel(STATE_CHANNEL_ID, new TextValue(stateEnum), getName(), componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())//
.build();
String commandTopic = channelConfiguration.commandTopic;
if (commandTopic != null) {
buildChannel(SWITCH_DISARM_CHANNEL_ID, new TextValue(new String[] { channelConfiguration.payloadDisarm }),
- channelConfiguration.getName(), componentConfiguration.getUpdateListener())
+ getName(), componentConfiguration.getUpdateListener())
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
buildChannel(SWITCH_ARM_HOME_CHANNEL_ID,
- new TextValue(new String[] { channelConfiguration.payloadArmHome }), channelConfiguration.getName(),
+ new TextValue(new String[] { channelConfiguration.payloadArmHome }), getName(),
componentConfiguration.getUpdateListener())
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
buildChannel(SWITCH_ARM_AWAY_CHANNEL_ID,
- new TextValue(new String[] { channelConfiguration.payloadArmAway }), channelConfiguration.getName(),
+ new TextValue(new String[] { channelConfiguration.payloadArmAway }), getName(),
componentConfiguration.getUpdateListener())
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build();
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java
index d5e98c04a66b1..85b575a08341d 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java
@@ -22,6 +22,7 @@
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
import org.openhab.binding.mqtt.homeassistant.internal.listener.ExpireUpdateStateListener;
import org.openhab.binding.mqtt.homeassistant.internal.listener.OffDelayUpdateStateListener;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
import com.google.gson.annotations.SerializedName;
@@ -72,7 +73,8 @@ public BinarySensor(ComponentFactory.ComponentConfiguration componentConfigurati
OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff);
buildChannel(SENSOR_CHANNEL_ID, value, "value", getListener(componentConfiguration, value))
- .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()).build();
+ .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
+ .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
}
private ChannelStateUpdateListener getListener(ComponentFactory.ComponentConfiguration componentConfiguration,
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java
new file mode 100644
index 0000000000000..ad56f3f4e01a1
--- /dev/null
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.homeassistant.internal.component;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.mqtt.generic.values.TextValue;
+import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * An MQTT button, following the https://www.home-assistant.io/integrations/button.mqtt/ specification.
+ *
+ * @author Cody Cutrer - Initial contribution
+ */
+@NonNullByDefault
+public class Button extends AbstractComponent {
+ public static final String BUTTON_CHANNEL_ID = "button";
+
+ /**
+ * Configuration class for MQTT component
+ */
+ static class ChannelConfiguration extends AbstractChannelConfiguration {
+ ChannelConfiguration() {
+ super("MQTT Button");
+ }
+
+ protected @Nullable Boolean optimistic;
+
+ @SerializedName("command_topic")
+ protected @Nullable String commandTopic;
+
+ @SerializedName("payload_press")
+ protected String payloadPress = "PRESS";
+ }
+
+ public Button(ComponentFactory.ComponentConfiguration componentConfiguration) {
+ super(componentConfiguration, ChannelConfiguration.class);
+
+ TextValue value = new TextValue(new String[] { channelConfiguration.payloadPress });
+
+ buildChannel(BUTTON_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
+ .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
+ channelConfiguration.getQos())
+ .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
+ }
+}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java
index c66119ff53bdf..bcf12f36087f7 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java
@@ -43,7 +43,7 @@ public Camera(ComponentFactory.ComponentConfiguration componentConfiguration) {
ImageValue value = new ImageValue();
- buildChannel(CAMERA_CHANNEL_ID, value, channelConfiguration.getName(),
- componentConfiguration.getUpdateListener()).stateTopic(channelConfiguration.topic).build();
+ buildChannel(CAMERA_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
+ .stateTopic(channelConfiguration.topic).build();
}
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java
index a2ad15e81b64a..5e68b56689ade 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java
@@ -286,7 +286,7 @@ private ComponentChannel buildOptionalChannel(String channelId, Value valueState
@Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic,
@Nullable Predicate commandFilter) {
if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) {
- return buildChannel(channelId, valueState, channelConfiguration.getName(), channelStateUpdateListener)
+ return buildChannel(channelId, valueState, getName(), channelStateUpdateListener)
.stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate())
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(),
commandTemplate)
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java
index 9855eec9c49ce..3246c3789480c 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java
@@ -57,6 +57,8 @@ public static AbstractComponent> createComponent(ThingUID thingUID, HaID haID,
return new AlarmControlPanel(componentConfiguration);
case "binary_sensor":
return new BinarySensor(componentConfiguration);
+ case "button":
+ return new Button(componentConfiguration);
case "camera":
return new Camera(componentConfiguration);
case "cover":
@@ -73,6 +75,8 @@ public static AbstractComponent> createComponent(ThingUID thingUID, HaID haID,
return new Lock(componentConfiguration);
case "number":
return new Number(componentConfiguration);
+ case "scene":
+ return new Scene(componentConfiguration);
case "select":
return new Select(componentConfiguration);
case "sensor":
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java
index ecfa3a48c6919..8191f16c2ec6f 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java
@@ -56,8 +56,7 @@ public Cover(ComponentFactory.ComponentConfiguration componentConfiguration) {
RollershutterValue value = new RollershutterValue(channelConfiguration.payloadOpen,
channelConfiguration.payloadClose, channelConfiguration.payloadStop);
- buildChannel(SWITCH_CHANNEL_ID, value, channelConfiguration.getName(),
- componentConfiguration.getUpdateListener())
+ buildChannel(SWITCH_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos())
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java
index 092b898a695f6..676d6ddd2cbc7 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java
@@ -98,8 +98,9 @@ protected void buildChannels() {
.build();
}
- if (channelConfiguration.effectStateTopic != null || channelConfiguration.effectCommandTopic != null) {
- buildChannel(EFFECT_CHANNEL_ID, effectValue, "Lighting effect", this)
+ if (effectValue != null
+ && (channelConfiguration.effectStateTopic != null || channelConfiguration.effectCommandTopic != null)) {
+ buildChannel(EFFECT_CHANNEL_ID, Objects.requireNonNull(effectValue), "Lighting Effect", this)
.stateTopic(channelConfiguration.effectStateTopic, channelConfiguration.effectValueTemplate)
.commandTopic(channelConfiguration.effectCommandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos())
@@ -281,7 +282,7 @@ public void updateChannelState(ChannelUID channel, State state) {
colorValue.update(newOnState);
}
- listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
+ listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID),
state.equals(OnOffType.ON) ? newOnState : HSBType.BLACK);
} else if (brightnessChannel != null) {
listener.updateChannelState(new ChannelUID(channel.getThingUID(), BRIGHTNESS_CHANNEL_ID),
@@ -301,8 +302,7 @@ public void updateChannelState(ChannelUID channel, State state) {
colorValue.update(new HSBType(DecimalType.ZERO, PercentType.ZERO,
(PercentType) brightnessValue.getChannelState()));
}
- listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
- colorValue.getChannelState());
+ listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
} else {
listener.updateChannelState(channel, state);
}
@@ -330,13 +330,11 @@ public void updateChannelState(ChannelUID channel, State state) {
HSBType xyColor = HSBType.fromXY(x, y);
colorValue.update(new HSBType(xyColor.getHue(), xyColor.getSaturation(), brightness));
}
- listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
- colorValue.getChannelState());
+ listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
return;
case RGB_CHANNEL_ID:
colorValue.update((HSBType) state);
- listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID),
- colorValue.getChannelState());
+ listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
break;
case RGBW_CHANNEL_ID:
case RGBWW_CHANNEL_ID:
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java
index 657483fc538a7..e3c914bef2d9e 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java
@@ -65,8 +65,7 @@ public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfigurat
value = new TextValue();
}
- buildChannel(channelConfiguration.type, value, channelConfiguration.getName(),
- componentConfiguration.getUpdateListener())
+ buildChannel(channelConfiguration.type, value, getName(), componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.topic, channelConfiguration.getValueTemplate()).trigger(true).build();
}
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java
index 49be4ee9238c6..7d056ed10ca38 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java
@@ -54,8 +54,7 @@ public Fan(ComponentFactory.ComponentConfiguration componentConfiguration) {
super(componentConfiguration, ChannelConfiguration.class);
OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff);
- buildChannel(SWITCH_CHANNEL_ID, value, channelConfiguration.getName(),
- componentConfiguration.getUpdateListener())
+ buildChannel(SWITCH_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos(), channelConfiguration.commandTemplate)
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java
index 01e8dcb9fe02b..a86f6488de5ba 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java
@@ -20,12 +20,15 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener;
+import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.binding.mqtt.homeassistant.internal.exception.UnsupportedComponentException;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
+import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
+import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
@@ -47,6 +50,7 @@
@NonNullByDefault
public class JSONSchemaLight extends AbstractRawSchemaLight {
private static final BigDecimal SCALE_FACTOR = new BigDecimal("2.55"); // string to not lose precision
+ private static final BigDecimal BIG_DECIMAL_HUNDRED = new BigDecimal(100);
private final Logger logger = LoggerFactory.getLogger(JSONSchemaLight.class);
@@ -67,14 +71,23 @@ protected static class Color {
protected @Nullable Integer transition;
}
+ TextValue colorModeValue;
+
public JSONSchemaLight(ComponentFactory.ComponentConfiguration builder) {
super(builder);
+ colorModeValue = new TextValue();
}
@Override
protected void buildChannels() {
+ List supportedColorModes = channelConfiguration.supportedColorModes;
+ if (supportedColorModes != null && supportedColorModes.contains(LightColorMode.COLOR_MODE_COLOR_TEMP)) {
+ colorModeValue = new TextValue(
+ supportedColorModes.stream().map(LightColorMode::serializedName).toArray(String[]::new));
+ buildChannel(COLOR_MODE_CHANNEL_ID, colorModeValue, "Color Mode", this).isAdvanced(true).build();
+ }
+
if (channelConfiguration.colorMode) {
- List supportedColorModes = channelConfiguration.supportedColorModes;
if (supportedColorModes == null || channelConfiguration.supportedColorModes.isEmpty()) {
throw new UnsupportedComponentException("JSON schema light with color modes '" + getHaID()
+ "' does not define supported_color_modes!");
@@ -83,6 +96,12 @@ protected void buildChannels() {
if (LightColorMode.hasColorChannel(supportedColorModes)) {
hasColorChannel = true;
}
+
+ if (supportedColorModes.contains(LightColorMode.COLOR_MODE_COLOR_TEMP)) {
+ buildChannel(COLOR_TEMP_CHANNEL_ID, colorTempValue, "Color Temperature", this)
+ .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(command -> handleColorTempCommand(command))
+ .build();
+ }
}
if (hasColorChannel) {
@@ -95,6 +114,22 @@ protected void buildChannels() {
onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, onOffValue, "On/Off State", this)
.commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build();
}
+
+ if (effectValue != null) {
+ buildChannel(EFFECT_CHANNEL_ID, Objects.requireNonNull(effectValue), "Lighting Effect", this)
+ .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(command -> handleEffectCommand(command)).build();
+
+ }
+ }
+
+ private boolean handleEffectCommand(Command command) {
+ if (command instanceof StringType) {
+ JSONState json = new JSONState();
+ json.state = "ON";
+ json.effect = command.toString();
+ publishState(json);
+ }
+ return false;
}
@Override
@@ -118,7 +153,7 @@ protected void publishState(HSBType state) {
json.color = new JSONState.Color();
if (channelConfiguration.supportedColorModes.contains(LightColorMode.COLOR_MODE_HS)) {
json.color.h = state.getHue().toBigDecimal();
- json.color.s = state.getSaturation().toBigDecimal();
+ json.color.s = state.getSaturation().toBigDecimal().divide(BIG_DECIMAL_HUNDRED);
} else if (LightColorMode.hasRGB(Objects.requireNonNull(channelConfiguration.supportedColorModes))) {
var rgb = state.toRGB();
json.color.r = rgb[0].toBigDecimal().multiply(SCALE_FACTOR).intValue();
@@ -126,12 +161,16 @@ protected void publishState(HSBType state) {
json.color.b = rgb[2].toBigDecimal().multiply(SCALE_FACTOR).intValue();
} else { // if (channelConfiguration.supportedColorModes.contains(COLOR_MODE_XY))
var xy = state.toXY();
- json.color.x = xy[0].toBigDecimal();
- json.color.y = xy[1].toBigDecimal();
+ json.color.x = xy[0].toBigDecimal().divide(BIG_DECIMAL_HUNDRED);
+ json.color.y = xy[1].toBigDecimal().divide(BIG_DECIMAL_HUNDRED);
}
}
}
+ publishState(json);
+ }
+
+ private void publishState(JSONState json) {
String command = getGson().toJson(json);
logger.debug("Publishing new state '{}' of light {} to MQTT.", command, getName());
rawChannel.getState().publishValue(new StringType(command));
@@ -163,6 +202,30 @@ protected boolean handleCommand(Command command) {
return false;
}
+ private boolean handleColorTempCommand(Command command) {
+ JSONState json = new JSONState();
+
+ if (command instanceof DecimalType) {
+ command = new QuantityType<>(((DecimalType) command).toBigDecimal(), Units.MIRED);
+ }
+ if (command instanceof QuantityType) {
+ QuantityType> mireds = ((QuantityType>) command).toInvertibleUnit(Units.MIRED);
+ if (mireds == null) {
+ logger.warn("Unable to convert {} to mireds", command);
+ return false;
+ }
+ json.state = "ON";
+ json.colorTemp = mireds.toBigDecimal().intValue();
+ } else {
+ return false;
+ }
+
+ String jsonCommand = getGson().toJson(json);
+ logger.debug("Publishing new state '{}' of light {} to MQTT.", jsonCommand, getName());
+ rawChannel.getState().publishValue(new StringType(jsonCommand));
+ return false;
+ }
+
@Override
public void updateChannelState(ChannelUID channel, State state) {
ChannelStateUpdateListener listener = this.channelStateUpdateListener;
@@ -181,33 +244,58 @@ public void updateChannelState(ChannelUID channel, State state) {
return;
}
+ if (effectValue != null) {
+ if (jsonState.effect != null) {
+ effectValue.update(new StringType(jsonState.effect));
+ listener.updateChannelState(buildChannelUID(EFFECT_CHANNEL_ID), effectValue.getChannelState());
+ } else {
+ listener.updateChannelState(buildChannelUID(EFFECT_CHANNEL_ID), UnDefType.NULL);
+ }
+ }
+
+ boolean off = false;
if (jsonState.state != null) {
onOffValue.update(onOffValue.parseCommand(new StringType(jsonState.state)));
+ off = onOffValue.getChannelState().equals(OnOffType.OFF);
if (brightnessValue.getChannelState() instanceof UnDefType) {
- brightnessValue.update(brightnessValue.parseCommand((OnOffType) onOffValue.getChannelState()));
+ brightnessValue.update(off ? PercentType.ZERO : PercentType.HUNDRED);
}
if (colorValue.getChannelState() instanceof UnDefType) {
- colorValue.update(colorValue.parseCommand((OnOffType) onOffValue.getChannelState()));
+ colorValue.update(off ? HSBType.BLACK : HSBType.WHITE);
}
}
+ PercentType brightness;
+ if (off) {
+ brightness = PercentType.ZERO;
+ } else if (brightnessValue.getChannelState() instanceof PercentType percentValue) {
+ brightness = percentValue;
+ } else {
+ brightness = PercentType.HUNDRED;
+ }
+
if (jsonState.brightness != null) {
- brightnessValue.update(
- brightnessValue.parseCommand(new DecimalType(Objects.requireNonNull(jsonState.brightness))));
+ if (!off) {
+ brightness = (PercentType) brightnessValue
+ .parseMessage(new DecimalType(Objects.requireNonNull(jsonState.brightness)));
+ }
+ brightnessValue.update(brightness);
if (colorValue.getChannelState() instanceof HSBType) {
HSBType color = (HSBType) colorValue.getChannelState();
- colorValue.update(new HSBType(color.getHue(), color.getSaturation(),
- (PercentType) brightnessValue.getChannelState()));
+ colorValue.update(new HSBType(color.getHue(), color.getSaturation(), brightness));
} else {
- colorValue.update(new HSBType(DecimalType.ZERO, PercentType.ZERO,
- (PercentType) brightnessValue.getChannelState()));
+ colorValue.update(new HSBType(DecimalType.ZERO, PercentType.ZERO, brightness));
}
}
+ if (jsonState.colorTemp != null) {
+ colorTempValue.update(new QuantityType(Objects.requireNonNull(jsonState.colorTemp), Units.MIRED));
+ listener.updateChannelState(buildChannelUID(COLOR_TEMP_CHANNEL_ID), colorTempValue.getChannelState());
+
+ colorModeValue.update(new StringType(LightColorMode.COLOR_MODE_COLOR_TEMP.serializedName()));
+ }
+
if (jsonState.color != null) {
- PercentType brightness = brightnessValue.getChannelState() instanceof PercentType
- ? (PercentType) brightnessValue.getChannelState()
- : PercentType.HUNDRED;
// This corresponds to "deprecated" color mode handling, since we're not checking which color
// mode is currently active.
// HS is highest priority, then XY, then RGB
@@ -216,21 +304,29 @@ public void updateChannelState(ChannelUID channel, State state) {
if (jsonState.color.h != null && jsonState.color.s != null) {
colorValue.update(new HSBType(new DecimalType(Objects.requireNonNull(jsonState.color.h)),
new PercentType(Objects.requireNonNull(jsonState.color.s)), brightness));
+ colorModeValue.update(new StringType(LightColorMode.COLOR_MODE_HS.serializedName()));
} else if (jsonState.color.x != null && jsonState.color.y != null) {
HSBType newColor = HSBType.fromXY(jsonState.color.x.floatValue(), jsonState.color.y.floatValue());
colorValue.update(new HSBType(newColor.getHue(), newColor.getSaturation(), brightness));
+ colorModeValue.update(new StringType(LightColorMode.COLOR_MODE_XY.serializedName()));
} else if (jsonState.color.r != null && jsonState.color.g != null && jsonState.color.b != null) {
colorValue.update(HSBType.fromRGB(jsonState.color.r, jsonState.color.g, jsonState.color.b));
+ colorModeValue.update(new StringType(LightColorMode.COLOR_MODE_RGB.serializedName()));
}
}
+ if (jsonState.colorMode != null) {
+ colorModeValue.update(new StringType(jsonState.colorMode.serializedName()));
+ }
+
+ listener.updateChannelState(buildChannelUID(COLOR_MODE_CHANNEL_ID), colorModeValue.getChannelState());
+
if (hasColorChannel) {
- listener.updateChannelState(new ChannelUID(getGroupUID(), COLOR_CHANNEL_ID), colorValue.getChannelState());
+ listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState());
} else if (brightnessChannel != null) {
- listener.updateChannelState(new ChannelUID(getGroupUID(), BRIGHTNESS_CHANNEL_ID),
- brightnessValue.getChannelState());
+ listener.updateChannelState(buildChannelUID(BRIGHTNESS_CHANNEL_ID), brightnessValue.getChannelState());
} else {
- listener.updateChannelState(new ChannelUID(getGroupUID(), ON_OFF_CHANNEL_ID), onOffValue.getChannelState());
+ listener.updateChannelState(buildChannelUID(ON_OFF_CHANNEL_ID), onOffValue.getChannelState());
}
}
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java
index 782268cdab047..c0c41ef34a20c 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java
@@ -47,7 +47,7 @@
* three different schemas.
*
* As of now, only on/off, brightness, and RGB are fully implemented and tested.
- * HS and XY are implemented, but not tested. Color temp and effect are only
+ * HS and XY are implemented, but not tested. Color temp is only
* implemented (but not tested) for the default schema.
*
* @author David Graeff - Initial contribution
@@ -246,7 +246,7 @@ static class ChannelConfiguration extends AbstractChannelConfiguration {
protected OnOffValue onOffValue;
protected PercentageValue brightnessValue;
protected final NumberValue colorTempValue;
- protected final TextValue effectValue = new TextValue();
+ protected final @Nullable TextValue effectValue;
protected final ColorValue colorValue = new ColorValue(ColorMode.HSB, null, null, 100);
protected final List hiddenChannels = new ArrayList<>();
@@ -281,6 +281,13 @@ protected Light(ComponentFactory.ComponentConfiguration builder) {
brightnessValue = new PercentageValue(null, new BigDecimal(channelConfiguration.brightnessScale), null, null,
null);
@Nullable
+ List effectList = channelConfiguration.effectList;
+ if (effectList != null) {
+ effectValue = new TextValue(effectList.toArray(new String[0]));
+ } else {
+ effectValue = null;
+ }
+ @Nullable
BigDecimal min = null, max = null;
if (channelConfiguration.minMireds != null) {
min = new BigDecimal(channelConfiguration.minMireds);
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightColorMode.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightColorMode.java
index cb8aa6fb950b7..a7d364ff7544e 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightColorMode.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightColorMode.java
@@ -61,4 +61,13 @@ public static boolean hasColorChannel(List supportedColorModes)
public static boolean hasRGB(List supportedColorModes) {
return WITH_RGB.stream().anyMatch(cm -> supportedColorModes.contains(cm));
}
+
+ public String serializedName() {
+ try {
+ return LightColorMode.class.getDeclaredField(toString()).getAnnotation(SerializedName.class).value();
+ } catch (NoSuchFieldException e) {
+ // can't happen
+ throw new IllegalStateException(e);
+ }
+ }
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java
index b50974a412aa5..ccfab925c9b48 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java
@@ -58,8 +58,8 @@ public Lock(ComponentFactory.ComponentConfiguration componentConfiguration) {
}
buildChannel(SWITCH_CHANNEL_ID,
- new OnOffValue(channelConfiguration.payloadLock, channelConfiguration.payloadUnlock),
- channelConfiguration.getName(), componentConfiguration.getUpdateListener())
+ new OnOffValue(channelConfiguration.payloadLock, channelConfiguration.payloadUnlock), getName(),
+ componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos())
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java
index 947f46cc41a53..10519eb24312c 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java
@@ -82,8 +82,7 @@ public Number(ComponentFactory.ComponentConfiguration componentConfiguration) {
NumberValue value = new NumberValue(channelConfiguration.min, channelConfiguration.max,
channelConfiguration.step, UnitUtils.parseUnit(channelConfiguration.unitOfMeasurement));
- buildChannel(NUMBER_CHANNEL_ID, value, channelConfiguration.getName(),
- componentConfiguration.getUpdateListener())
+ buildChannel(NUMBER_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos(), channelConfiguration.commandTemplate)
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java
new file mode 100644
index 0000000000000..3ad3b1521c514
--- /dev/null
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.homeassistant.internal.component;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.mqtt.generic.values.TextValue;
+import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * A MQTT scene, following the https://www.home-assistant.io/integrations/scene.mqtt/ specification.
+ *
+ * @author Cody Cutrer - Initial contribution
+ */
+@NonNullByDefault
+public class Scene extends AbstractComponent {
+ public static final String SCENE_CHANNEL_ID = "scene";
+
+ /**
+ * Configuration class for MQTT component
+ */
+ static class ChannelConfiguration extends AbstractChannelConfiguration {
+ ChannelConfiguration() {
+ super("MQTT Scene");
+ }
+
+ @SerializedName("command_topic")
+ protected @Nullable String commandTopic;
+
+ @SerializedName("payload_on")
+ protected String payloadOn = "ON";
+ }
+
+ public Scene(ComponentFactory.ComponentConfiguration componentConfiguration) {
+ super(componentConfiguration, ChannelConfiguration.class);
+
+ TextValue value = new TextValue(new String[] { channelConfiguration.payloadOn });
+
+ buildChannel(SCENE_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
+ .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
+ channelConfiguration.getQos())
+ .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
+ }
+}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java
index 9ead86ef8af4b..d49dfbf1a7172 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java
@@ -66,8 +66,7 @@ public Select(ComponentFactory.ComponentConfiguration componentConfiguration) {
TextValue value = new TextValue(channelConfiguration.options);
- buildChannel(SELECT_CHANNEL_ID, value, channelConfiguration.getName(),
- componentConfiguration.getUpdateListener())
+ buildChannel(SELECT_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos(), channelConfiguration.commandTemplate)
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java
index f9f8706b5b108..148a5b5e989ab 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java
@@ -88,8 +88,7 @@ public Sensor(ComponentFactory.ComponentConfiguration componentConfiguration) {
boolean trigger = TRIGGER_ICONS.matcher(icon).matches();
- buildChannel(SENSOR_CHANNEL_ID, value, channelConfiguration.getName(),
- getListener(componentConfiguration, value))
+ buildChannel(SENSOR_CHANNEL_ID, value, getName(), getListener(componentConfiguration, value))
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())//
.trigger(trigger).build();
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java
index 7fd9d6b901fb9..75de1517cf03d 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java
@@ -294,7 +294,7 @@ private ComponentChannel buildOptionalChannel(String channelId, Value valueState
ChannelStateUpdateListener channelStateUpdateListener, @Nullable String commandTemplate,
@Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic) {
if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) {
- return buildChannel(channelId, valueState, channelConfiguration.getName(), channelStateUpdateListener)
+ return buildChannel(channelId, valueState, getName(), channelStateUpdateListener)
.stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate())
.commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(),
commandTemplate)
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/dto/AbstractChannelConfiguration.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/dto/AbstractChannelConfiguration.java
index ae64e5d2445da..dec22608edb28 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/dto/AbstractChannelConfiguration.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/dto/AbstractChannelConfiguration.java
@@ -33,8 +33,9 @@
@NonNullByDefault
public abstract class AbstractChannelConfiguration {
public static final char PARENT_TOPIC_PLACEHOLDER = '~';
+ private static final String DEFAULT_THING_NAME = "Home Assistant Device";
- protected String name;
+ protected @Nullable String name;
protected String icon = "";
protected int qos; // defaults to 0 according to HA specification
@@ -93,6 +94,9 @@ public String getThingName() {
if (result == null) {
result = name;
}
+ if (result == null) {
+ result = DEFAULT_THING_NAME;
+ }
return result;
}
@@ -127,7 +131,7 @@ public Map appendToProperties(Map properties) {
return properties;
}
- public String getName() {
+ public @Nullable String getName() {
return name;
}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java
index 14612c5f67924..99a14d4abd9c4 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java
@@ -18,6 +18,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -44,6 +45,7 @@
import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException;
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelGroupUID;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
@@ -53,7 +55,6 @@
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelDefinition;
import org.openhab.core.thing.type.ChannelGroupDefinition;
-import org.openhab.core.thing.type.ChannelGroupType;
import org.openhab.core.thing.type.ThingType;
import org.openhab.core.thing.util.ThingHelper;
import org.slf4j.Logger;
@@ -93,7 +94,7 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler
protected final DiscoverComponents discoverComponents;
private final Gson gson;
- protected final Map> haComponents = new HashMap<>();
+ protected final Map<@Nullable String, AbstractComponent>> haComponents = new HashMap<>();
protected HandlerConfiguration config = new HandlerConfiguration();
private Set discoveryHomeAssistantIDs = new HashSet<>();
@@ -137,10 +138,6 @@ public void initialize() {
for (Channel channel : thing.getChannels()) {
final String groupID = channel.getUID().getGroupId();
- if (groupID == null) {
- logger.warn("Channel {} has no groupd ID", channel.getLabel());
- continue;
- }
// Already restored component?
@Nullable
AbstractComponent> component = haComponents.get(groupID);
@@ -160,7 +157,12 @@ public void initialize() {
try {
component = ComponentFactory.createComponent(thingUID, haID, channelConfigurationJSON, this, this,
scheduler, gson, transformationServiceProvider);
- haComponents.put(component.getGroupUID().getId(), component);
+ final ChannelGroupUID groupUID = component.getGroupUID();
+ String id = null;
+ if (groupUID != null) {
+ id = groupUID.getId();
+ }
+ haComponents.put(id, component);
component.addChannelTypes(channelTypeProvider);
} catch (ConfigurationException e) {
logger.error("Cannot not restore component {}: {}", thing, e.getMessage());
@@ -228,9 +230,6 @@ protected void stop() {
@Override
public @Nullable ChannelState getChannelState(ChannelUID channelUID) {
String groupID = channelUID.getGroupId();
- if (groupID == null) {
- return null;
- }
AbstractComponent> component;
synchronized (haComponents) { // sync whenever discoverComponents is started
component = haComponents.get(groupID);
@@ -266,7 +265,12 @@ public void accept(List> discoveredComponentsList) {
synchronized (haComponents) { // sync whenever discoverComponents is started
for (AbstractComponent> discovered : discoveredComponentsList) {
- AbstractComponent> known = haComponents.get(discovered.getGroupUID().getId());
+ final ChannelGroupUID groupUID = discovered.getGroupUID();
+ String id = null;
+ if (groupUID != null) {
+ id = groupUID.getId();
+ }
+ AbstractComponent> known = haComponents.get(id);
// Is component already known?
if (known != null) {
if (discovered.getConfigHash() != known.getConfigHash()) {
@@ -282,10 +286,10 @@ public void accept(List> discoveredComponentsList) {
// Add channel and group types to the types registry
discovered.addChannelTypes(channelTypeProvider);
// Add component to the component map
- haComponents.put(discovered.getGroupUID().getId(), discovered);
+ haComponents.put(id, discovered);
// Start component / Subscribe to channel topics
discovered.start(connection, scheduler, 0).exceptionally(e -> {
- logger.warn("Failed to start component {}", discovered.getGroupUID(), e);
+ logger.warn("Failed to start component {}", discovered.getHaID(), e);
return null;
});
@@ -296,7 +300,7 @@ public void accept(List> discoveredComponentsList) {
// We remove all conflicting old channels, they will be re-added below based on the new discovery
logger.debug(
"Received component {} with slightly different config. Making sure we re-create conflicting channels...",
- discovered.getGroupUID());
+ discovered.getHaID());
removeJustRediscoveredChannels(discoveredChannels);
}
@@ -346,9 +350,8 @@ private void updateThingType() {
List channelDefs;
synchronized (haComponents) { // sync whenever discoverComponents is started
groupDefs = haComponents.values().stream().map(AbstractComponent::getGroupDefinition)
- .collect(Collectors.toList());
- channelDefs = haComponents.values().stream().map(AbstractComponent::getType)
- .map(ChannelGroupType::getChannelDefinitions).flatMap(List::stream)
+ .filter(Objects::nonNull).map(Objects::requireNonNull).collect(Collectors.toList());
+ channelDefs = haComponents.values().stream().map(AbstractComponent::getChannels).flatMap(List::stream)
.collect(Collectors.toList());
}
ThingType thingType = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING)
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java
index fc5d8c3cf1369..e2d88086db786 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java
@@ -230,6 +230,15 @@ protected void assertNotPublished(String mqttTopic, String payload) {
ArgumentMatchers.eq(payload.getBytes(StandardCharsets.UTF_8)), anyInt(), anyBoolean());
}
+ /**
+ * Assert that nothing was published on given topic.
+ *
+ * @param mqttTopic Mqtt topic
+ */
+ protected void assertNothingPublished(String mqttTopic) {
+ verify(bridgeConnection, never()).publish(eq(mqttTopic), any(), anyInt(), anyBoolean());
+ }
+
/**
* Publish payload to all subscribers on specified topic.
*
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ButtonTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ButtonTests.java
new file mode 100644
index 0000000000000..9fdce64d12a16
--- /dev/null
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ButtonTests.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.homeassistant.internal.component;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.mqtt.generic.values.TextValue;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
+
+/**
+ * Tests for {@link Button}
+ *
+ * @author Cody Cutrer - Initial contribution
+ */
+@NonNullByDefault
+public class ButtonTests extends AbstractComponentTests {
+ public static final String CONFIG_TOPIC = "button/0x847127fffe11dd6a_auto_lock_zigbee2mqtt";
+
+ @SuppressWarnings("null")
+ @Test
+ public void testButton() {
+ var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
+ {
+ "dev_cla":"restart",
+ "name":"Restart",
+ "entity_category":"config",
+ "cmd_t":"esphome/single-car-gdo/button/restart/command",
+ "avty_t":"esphome/single-car-gdo/status",
+ "uniq_id":"78e36d645710-button-ba0e8e32",
+ "dev":{
+ "ids":"78e36d645710",
+ "name":"Single Car Garage Door Opener",
+ "sw":"esphome v2023.10.4 Nov 1 2023, 09:27:02",
+ "mdl":"esp32dev",
+ "mf":"espressif"}
+ }
+ """);
+
+ assertThat(component.channels.size(), is(1));
+ assertThat(component.getName(), is("Restart"));
+
+ assertChannel(component, Button.BUTTON_CHANNEL_ID, "", "esphome/single-car-gdo/button/restart/command",
+ "Restart", TextValue.class);
+ assertThat(Objects.requireNonNull(component.getChannel(Button.BUTTON_CHANNEL_ID)).getChannel()
+ .getAutoUpdatePolicy(), is(AutoUpdatePolicy.VETO));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> component.getChannel(Button.BUTTON_CHANNEL_ID).getState().publishValue(new StringType("ON")));
+ assertNothingPublished("esphome/single-car-gdo/button/restart/command");
+ component.getChannel(Button.BUTTON_CHANNEL_ID).getState().publishValue(new StringType("PRESS"));
+ assertPublished("esphome/single-car-gdo/button/restart/command", "PRESS");
+ }
+
+ @Override
+ protected Set getConfigTopics() {
+ return Set.of(CONFIG_TOPIC);
+ }
+}
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java
index a5b092b01e779..150d9e4f15f15 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java
@@ -27,11 +27,13 @@
import org.openhab.binding.mqtt.generic.values.ColorValue;
import org.openhab.binding.mqtt.generic.values.OnOffValue;
import org.openhab.binding.mqtt.generic.values.PercentageValue;
+import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
+import org.openhab.core.library.types.StringType;
/**
* Tests for {@link Light} confirming to the default schema
@@ -285,6 +287,40 @@ public void testOnOffOnly() throws InterruptedException {
assertPublished("zigbee2mqtt/light/set/state", "OFF_");
}
+ @Test
+ public void testOnOffWithEffect() throws InterruptedException {
+ // @formatter:off
+ var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
+ "{ " +
+ " \"name\": \"light\", " +
+ " \"state_topic\": \"zigbee2mqtt/light/state\", " +
+ " \"command_topic\": \"zigbee2mqtt/light/set/state\", " +
+ " \"effect_command_topic\": \"zigbee2mqtt/light/set/effect\", " +
+ " \"state_value_template\": \"{{ value_json.power }}\", " +
+ " \"effect_list\": [\"party\", \"rainbow\"]," +
+ " \"effect_state_topic\": \"zigbee2mqtt/light/effect\"" +
+ "}");
+ // @formatter:on
+
+ assertThat(component.channels.size(), is(2));
+ assertThat(component.getName(), is("light"));
+
+ assertChannel(component, Light.ON_OFF_CHANNEL_ID, "zigbee2mqtt/light/state", "zigbee2mqtt/light/set/state",
+ "On/Off State", OnOffValue.class);
+ assertChannel(component, Light.EFFECT_CHANNEL_ID, "zigbee2mqtt/light/effect", "zigbee2mqtt/light/set/effect",
+ "Lighting Effect", TextValue.class);
+
+ publishMessage("zigbee2mqtt/light/state", "{\"power\": \"ON\"}");
+ assertState(component, Light.ON_OFF_CHANNEL_ID, OnOffType.ON);
+ publishMessage("zigbee2mqtt/light/effect", "party");
+ assertState(component, Light.EFFECT_CHANNEL_ID, new StringType("party"));
+ publishMessage("zigbee2mqtt/light/state", "{\"power\": \"OFF\"}");
+ assertState(component, Light.ON_OFF_CHANNEL_ID, OnOffType.OFF);
+
+ sendCommand(component, Light.EFFECT_CHANNEL_ID, new StringType("rainbow"));
+ assertPublished("zigbee2mqtt/light/set/effect", "rainbow");
+ }
+
@Override
protected Set getConfigTopics() {
return Set.of(CONFIG_TOPIC);
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLightTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLightTests.java
index e1c50de28992f..604836dfc4eef 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLightTests.java
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLightTests.java
@@ -119,6 +119,9 @@ public void testBrightnessAndOnOff() throws InterruptedException {
assertState(component, Light.BRIGHTNESS_CHANNEL_ID,
new PercentType(new BigDecimal(128 * 100).divide(new BigDecimal(255), MathContext.DECIMAL128)));
+ publishMessage("zigbee2mqtt/light/state", "{ \"state\": \"OFF\", \"brightness\": 128 }");
+ assertState(component, Light.BRIGHTNESS_CHANNEL_ID, PercentType.ZERO);
+
sendCommand(component, Light.BRIGHTNESS_CHANNEL_ID, PercentType.HUNDRED);
assertPublished("zigbee2mqtt/light/set/state", "{\"state\":\"ON\",\"brightness\":255}");
diff --git a/bundles/org.openhab.binding.myq/NOTICE b/bundles/org.openhab.binding.myq/NOTICE
deleted file mode 100644
index 0ca708bef198a..0000000000000
--- a/bundles/org.openhab.binding.myq/NOTICE
+++ /dev/null
@@ -1,20 +0,0 @@
-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
-
-== Third-party Content
-
-jsoup
-* License: MIT License
-* Project: https://jsoup.org/
-* Source: https://github.com/jhy/jsoup
diff --git a/bundles/org.openhab.binding.myq/README.md b/bundles/org.openhab.binding.myq/README.md
deleted file mode 100644
index 510285cfa6ce8..0000000000000
--- a/bundles/org.openhab.binding.myq/README.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# MyQ Binding
-
-This binding integrates with the [The Chamberlain Group MyQ](https://www.myq.com) cloud service. It allows monitoring and control over [MyQ](https://www.myq.com) enabled garage doors manufactured by LiftMaster, Chamberlain and Craftsman.
-
-## Supported Things
-
-### Account
-
-This represents the MyQ cloud account and uses the same credentials needed when using the MyQ mobile application.
-
-ThingTypeUID: `account`
-
-### Garage Door
-
-This represents a garage door associated with an account. Multiple garage doors are supported.
-
-ThingTypeUID: `garagedoor`
-
-### Lamp
-
-This represents a lamp associated with an account. Multiple lamps are supported.
-
-ThingTypeUID: `lamp`
-
-## Discovery
-
-Once an account has been added, garage doors and lamps will automatically be discovered and added to the inbox.
-
-## Channels
-
-| Channel | Item Type | Thing Type | States |
-|---------------|---------------|------------------|--------------------------------------------------------|
-| status | String | garagedoor | opening, closed, closing, stopped, transition, unknown |
-| rollershutter | Rollershutter | garagedoor | UP, DOWN, 0%, 100% |
-| closeError | Switch | garagedoor | ON (has error), OFF (doesn't have error) |
-| openError | Switch | garagedoor | ON (has error), OFF (doesn't have error) |
-| switch | Switch | garagedoor, lamp | ON (open), OFF (closed) |
-
-## Full Example
-
-### Thing Configuration
-
-```java
-Bridge myq:account:home "MyQ Account" [ username="foo@bar.com", password="secret", refreshInterval=60 ] {
- Thing garagedoor abcd12345 "MyQ Garage Door" [ serialNumber="abcd12345" ]
- Thing lamp efgh6789 "MyQ Lamp" [ serialNumber="efgh6789" ]
-}
-```
-
-### Items
-
-```java
-String MyQGarageDoor1Status "Door Status [%s]" {channel = "myq:garagedoor:home:abcd12345:status"}
-Switch MyQGarageDoor1Switch "Door Switch [%s]" {channel = "myq:garagedoor:home:abcd12345:switch"}
-Switch MyQGarageDoor1CloseError "Door Close Error [%s]" {channel = "myq:garagedoor:home:abcd12345:closeError"}
-Switch MyQGarageDoor1OpenError "Door OpenError [%s]" {channel = "myq:garagedoor:home:abcd12345:openError"}
-Rollershutter MyQGarageDoor1Rollershutter "Door Rollershutter [%s]" {channel = "myq:garagedoor:home:abcd12345:rollershutter"}
-Switch MyQGarageDoorLamp "Lamp [%s]" {channel = "myq:lamp:home:efgh6789:switch"}
-}
-```
-
-### Sitemaps
-
-```perl
-sitemap MyQ label="MyQ Demo Sitemap" {
- Frame label="Garage Door" {
- String item=MyQGarageDoor1Status
- Switch item=MyQGarageDoor1Switch
- Rollershutter item=MyQGarageDoor1Rollershutter
- }
-}
-```
diff --git a/bundles/org.openhab.binding.myq/pom.xml b/bundles/org.openhab.binding.myq/pom.xml
deleted file mode 100644
index 7a776f7f3bb8c..0000000000000
--- a/bundles/org.openhab.binding.myq/pom.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- 4.0.0
-
-
- org.openhab.addons.bundles
- org.openhab.addons.reactor.bundles
- 4.1.0-SNAPSHOT
-
-
- org.openhab.binding.myq
-
- openHAB Add-ons :: Bundles :: MyQ Binding
-
-
-
- org.jsoup
- jsoup
- 1.14.3
- provided
-
-
-
diff --git a/bundles/org.openhab.binding.myq/src/main/feature/feature.xml b/bundles/org.openhab.binding.myq/src/main/feature/feature.xml
deleted file mode 100644
index 0c938aa7afec7..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/feature/feature.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features
-
-
- openhab-runtime-base
- mvn:org.jsoup/jsoup/1.14.3
- mvn:org.openhab.addons.bundles/org.openhab.binding.myq/${project.version}
-
-
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQBindingConstants.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQBindingConstants.java
deleted file mode 100644
index fc31bb39a2847..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQBindingConstants.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal;
-
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.ThingTypeUID;
-
-/**
- * The {@link MyQBindingConstants} class defines common constants, which are
- * used across the whole binding.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQBindingConstants {
-
- public static final String BINDING_ID = "myq";
-
- public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account");
- public static final ThingTypeUID THING_TYPE_GARAGEDOOR = new ThingTypeUID(BINDING_ID, "garagedoor");
- public static final ThingTypeUID THING_TYPE_LAMP = new ThingTypeUID(BINDING_ID, "lamp");
- public static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT, THING_TYPE_GARAGEDOOR,
- THING_TYPE_LAMP);
- public static final Set SUPPORTED_DISCOVERY_THING_TYPES_UIDS = Set.of(THING_TYPE_GARAGEDOOR,
- THING_TYPE_LAMP);
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQDiscoveryService.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQDiscoveryService.java
deleted file mode 100644
index 48863f22893ca..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQDiscoveryService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal;
-
-import static org.openhab.binding.myq.internal.MyQBindingConstants.BINDING_ID;
-
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.myq.internal.dto.DeviceDTO;
-import org.openhab.binding.myq.internal.handler.MyQAccountHandler;
-import org.openhab.core.config.discovery.AbstractDiscoveryService;
-import org.openhab.core.config.discovery.DiscoveryResult;
-import org.openhab.core.config.discovery.DiscoveryResultBuilder;
-import org.openhab.core.config.discovery.DiscoveryService;
-import org.openhab.core.thing.Thing;
-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;
-
-/**
- * The {@link MyQDiscoveryService} is responsible for discovering MyQ things
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
-
- private static final Set SUPPORTED_DISCOVERY_THING_TYPES_UIDS = Set
- .of(MyQBindingConstants.THING_TYPE_GARAGEDOOR, MyQBindingConstants.THING_TYPE_LAMP);
- private @Nullable MyQAccountHandler accountHandler;
-
- public MyQDiscoveryService() {
- super(SUPPORTED_DISCOVERY_THING_TYPES_UIDS, 1, true);
- }
-
- @Override
- public Set getSupportedThingTypes() {
- return SUPPORTED_DISCOVERY_THING_TYPES_UIDS;
- }
-
- @Override
- public void startScan() {
- MyQAccountHandler accountHandler = this.accountHandler;
- if (accountHandler != null) {
- List devices = accountHandler.devicesCache();
- if (devices != null) {
- devices.forEach(device -> {
- ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily);
- if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) {
- ThingUID thingUID = new ThingUID(thingTypeUID, accountHandler.getThing().getUID(),
- device.serialNumber.toLowerCase());
- DiscoveryResult result = DiscoveryResultBuilder.create(thingUID).withLabel("MyQ " + device.name)
- .withProperty(Thing.PROPERTY_SERIAL_NUMBER, thingUID.getId())
- .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER)
- .withBridge(accountHandler.getThing().getUID()).build();
- thingDiscovered(result);
- }
- });
- }
- }
- }
-
- @Override
- public void startBackgroundDiscovery() {
- startScan();
- }
-
- @Override
- public void setThingHandler(ThingHandler handler) {
- if (handler instanceof MyQAccountHandler myqAccountHandler) {
- accountHandler = myqAccountHandler;
- }
- }
-
- @Override
- public @Nullable ThingHandler getThingHandler() {
- return accountHandler;
- }
-
- @Override
- public void activate() {
- super.activate(null);
- }
-
- @Override
- public void deactivate() {
- super.deactivate();
- }
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQHandlerFactory.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQHandlerFactory.java
deleted file mode 100644
index 475c9fc5f15b8..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/MyQHandlerFactory.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal;
-
-import static org.openhab.binding.myq.internal.MyQBindingConstants.*;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jetty.client.HttpClient;
-import org.openhab.binding.myq.internal.handler.MyQAccountHandler;
-import org.openhab.binding.myq.internal.handler.MyQGarageDoorHandler;
-import org.openhab.binding.myq.internal.handler.MyQLampHandler;
-import org.openhab.core.auth.client.oauth2.OAuthFactory;
-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 MyQHandlerFactory} is responsible for creating things and thing
- * handlers.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-@Component(configurationPid = "binding.myq", service = ThingHandlerFactory.class)
-public class MyQHandlerFactory extends BaseThingHandlerFactory {
- private final HttpClient httpClient;
- private OAuthFactory oAuthFactory;
-
- @Activate
- public MyQHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
- final @Reference OAuthFactory oAuthFactory) {
- this.httpClient = httpClientFactory.getCommonHttpClient();
- this.oAuthFactory = oAuthFactory;
- }
-
- @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 (THING_TYPE_ACCOUNT.equals(thingTypeUID)) {
- return new MyQAccountHandler((Bridge) thing, httpClient, oAuthFactory);
- }
-
- if (THING_TYPE_GARAGEDOOR.equals(thingTypeUID)) {
- return new MyQGarageDoorHandler(thing);
- }
-
- if (THING_TYPE_LAMP.equals(thingTypeUID)) {
- return new MyQLampHandler(thing);
- }
-
- return null;
- }
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/config/MyQAccountConfiguration.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/config/MyQAccountConfiguration.java
deleted file mode 100644
index 245261f6a3897..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/config/MyQAccountConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.config;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link MyQAccountConfiguration} class contains fields mapping thing configuration parameters.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQAccountConfiguration {
- public String username = "";
- public String password = "";
- public Integer refreshInterval = 60;
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/config/MyQDeviceConfiguration.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/config/MyQDeviceConfiguration.java
deleted file mode 100644
index 1a5ed875762c8..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/config/MyQDeviceConfiguration.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.config;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link MyQDeviceConfiguration} class contains fields mapping thing configuration parameters.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQDeviceConfiguration {
- public String serialNumber = "";
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/AccountDTO.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/AccountDTO.java
deleted file mode 100644
index 7a74a3968e665..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/AccountDTO.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.dto;
-
-/**
- * The {@link AccountDTO} entity from the MyQ API
- *
- * @author Dan Cunningham - Initial contribution
- */
-public class AccountDTO {
- public String id;
- public String name;
- public String createdBy;
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/AccountsDTO.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/AccountsDTO.java
deleted file mode 100644
index 6346476bdf083..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/AccountsDTO.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.dto;
-
-import java.util.List;
-
-/**
- * The {@link AccountsDTO} entity from the MyQ API
- *
- * @author Dan Cunningham - Initial contribution
- */
-public class AccountsDTO {
- public List accounts;
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DeviceDTO.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DeviceDTO.java
deleted file mode 100644
index 96b7749113fc5..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DeviceDTO.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.dto;
-
-/**
- * The {@link DeviceDTO} entity from the MyQ API
- *
- * @author Dan Cunningham - Initial contribution
- */
-public class DeviceDTO {
- public String href;
- public String serialNumber;
- public String deviceFamily;
- public String devicePlatform;
- public String deviceType;
- public String name;
- public String createdDate;
- public String accountId;
- public DeviceStateDTO state;
- public String parentDevice;
- public String parentDeviceId;
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DeviceStateDTO.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DeviceStateDTO.java
deleted file mode 100644
index 02d306e1acf04..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DeviceStateDTO.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.dto;
-
-/**
- * The {@link DeviceStateDTO} entity from the MyQ API
- *
- * @author Dan Cunningham - Initial contribution
- */
-public class DeviceStateDTO {
-
- public Boolean gdoLockConnected;
- public Boolean attachedWorkLightErrorPresent;
- public String learnStatus;
- public Boolean hasCamera;
- public String lampState;
- public String batteryBackupState;
- public String doorState;
- public String lastUpdate;
- public Boolean isUnattendedOpenAllowed;
- public Boolean isUnattendedCloseAllowed;
- public Integer serviceCycleCount;
- public Integer absoluteCycleCount;
- public Boolean online;
- public String lastStatus;
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DevicesDTO.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DevicesDTO.java
deleted file mode 100644
index 9f1e99789e414..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/dto/DevicesDTO.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.dto;
-
-import java.util.List;
-
-/**
- * The {@link DevicesDTO} entity from the MyQ API
- *
- * @author Dan Cunningham - Initial contribution
- */
-public class DevicesDTO {
- public String href;
- public Integer count;
- public List items;
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQAccountHandler.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQAccountHandler.java
deleted file mode 100644
index 1911c73375685..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQAccountHandler.java
+++ /dev/null
@@ -1,675 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.handler;
-
-import static org.openhab.binding.myq.internal.MyQBindingConstants.*;
-
-import java.io.IOException;
-import java.net.CookieStore;
-import java.net.HttpCookie;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-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.eclipse.jetty.client.HttpContentResponse;
-import org.eclipse.jetty.client.api.ContentProvider;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.api.Response;
-import org.eclipse.jetty.client.api.Result;
-import org.eclipse.jetty.client.util.BufferingResponseListener;
-import org.eclipse.jetty.client.util.FormContentProvider;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.util.Fields;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.openhab.binding.myq.internal.MyQDiscoveryService;
-import org.openhab.binding.myq.internal.config.MyQAccountConfiguration;
-import org.openhab.binding.myq.internal.dto.AccountDTO;
-import org.openhab.binding.myq.internal.dto.AccountsDTO;
-import org.openhab.binding.myq.internal.dto.DeviceDTO;
-import org.openhab.binding.myq.internal.dto.DevicesDTO;
-import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
-import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
-import org.openhab.core.auth.client.oauth2.OAuthClientService;
-import org.openhab.core.auth.client.oauth2.OAuthException;
-import org.openhab.core.auth.client.oauth2.OAuthFactory;
-import org.openhab.core.auth.client.oauth2.OAuthResponseException;
-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.ThingTypeUID;
-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;
-
-import com.google.gson.FieldNamingPolicy;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonSyntaxException;
-
-/**
- * The {@link MyQAccountHandler} is responsible for communicating with the MyQ API based on an account.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenRefreshListener {
- private static final int REQUEST_TIMEOUT_MS = 10_000;
-
- /*
- * MyQ oAuth relate fields
- */
- private static final String CLIENT_SECRET = "VUQ0RFhuS3lQV3EyNUJTdw==";
- private static final String CLIENT_ID = "ANDROID_CGI_MYQ";
- private static final String REDIRECT_URI = "com.myqops://android";
- private static final String SCOPE = "MyQ_Residential offline_access";
- /*
- * MyQ authentication API endpoints
- */
- private static final String LOGIN_BASE_URL = "https://partner-identity.myq-cloud.com";
- private static final String LOGIN_AUTHORIZE_URL = LOGIN_BASE_URL + "/connect/authorize";
- private static final String LOGIN_TOKEN_URL = LOGIN_BASE_URL + "/connect/token";
- // this should never happen, but lets be safe and give up after so many redirects
- private static final int LOGIN_MAX_REDIRECTS = 30;
- /*
- * MyQ device and account API endpoints
- */
- private static final String ACCOUNTS_URL = "https://accounts.myq-cloud.com/api/v6.0/accounts";
- private static final String DEVICES_URL = "https://devices.myq-cloud.com/api/v5.2/Accounts/%s/Devices";
- private static final String CMD_LAMP_URL = "https://account-devices-lamp.myq-cloud.com/api/v5.2/Accounts/%s/lamps/%s/%s";
- private static final String CMD_DOOR_URL = "https://account-devices-gdo.myq-cloud.com/api/v5.2/Accounts/%s/door_openers/%s/%s";
-
- private static final Integer RAPID_REFRESH_SECONDS = 5;
- private final Logger logger = LoggerFactory.getLogger(MyQAccountHandler.class);
- private final Gson gsonLowerCase = new GsonBuilder()
- .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
- private final OAuthFactory oAuthFactory;
- private @Nullable Future> normalPollFuture;
- private @Nullable Future> rapidPollFuture;
- private @Nullable AccountsDTO accounts;
-
- private List devicesCache = new ArrayList();
- private @Nullable OAuthClientService oAuthService;
- private Integer normalRefreshSeconds = 60;
- private HttpClient httpClient;
- private String username = "";
- private String password = "";
- private String userAgent = "";
- // force login, even if we have a token
- private boolean needsLogin = false;
-
- public MyQAccountHandler(Bridge bridge, HttpClient httpClient, final OAuthFactory oAuthFactory) {
- super(bridge);
- this.httpClient = httpClient;
- this.oAuthFactory = oAuthFactory;
- }
-
- @Override
- public void handleCommand(ChannelUID channelUID, Command command) {
- }
-
- @Override
- public void initialize() {
- MyQAccountConfiguration config = getConfigAs(MyQAccountConfiguration.class);
- normalRefreshSeconds = config.refreshInterval;
- username = config.username;
- password = config.password;
- // MyQ can get picky about blocking user agents apparently
- userAgent = ""; // no agent string
- needsLogin = true;
- updateStatus(ThingStatus.UNKNOWN);
- restartPolls(false);
- }
-
- @Override
- public void dispose() {
- stopPolls();
- OAuthClientService oAuthService = this.oAuthService;
- if (oAuthService != null) {
- oAuthService.removeAccessTokenRefreshListener(this);
- oAuthFactory.ungetOAuthService(getThing().toString());
- this.oAuthService = null;
- }
- }
-
- @Override
- public void handleRemoval() {
- oAuthFactory.deleteServiceAndAccessToken(getThing().toString());
- super.handleRemoval();
- }
-
- @Override
- public Collection> getServices() {
- return Set.of(MyQDiscoveryService.class);
- }
-
- @Override
- public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) {
- List localDeviceCaches = devicesCache;
- if (childHandler instanceof MyQDeviceHandler deviceHandler) {
- localDeviceCaches.stream().filter(d -> deviceHandler.getSerialNumber().equalsIgnoreCase(d.serialNumber))
- .findFirst().ifPresent(deviceHandler::handleDeviceUpdate);
- }
- }
-
- @Override
- public void onAccessTokenResponse(AccessTokenResponse tokenResponse) {
- logger.debug("Auth Token Refreshed, expires in {}", tokenResponse.getExpiresIn());
- }
-
- /**
- * Sends a door action to the MyQ API
- *
- * @param device
- * @param action
- */
- public void sendDoorAction(DeviceDTO device, String action) {
- sendAction(device, action, CMD_DOOR_URL);
- }
-
- /**
- * Sends a lamp action to the MyQ API
- *
- * @param device
- * @param action
- */
- public void sendLampAction(DeviceDTO device, String action) {
- sendAction(device, action, CMD_LAMP_URL);
- }
-
- private void sendAction(DeviceDTO device, String action, String urlFormat) {
- if (getThing().getStatus() != ThingStatus.ONLINE) {
- logger.debug("Account offline, ignoring action {}", action);
- return;
- }
-
- try {
- ContentResponse response = sendRequest(
- String.format(urlFormat, device.accountId, device.serialNumber, action), HttpMethod.PUT, null,
- null);
- if (HttpStatus.isSuccess(response.getStatus())) {
- restartPolls(true);
- } else {
- logger.debug("Failed to send action {} : {}", action, response.getContentAsString());
- }
- } catch (InterruptedException | MyQCommunicationException | MyQAuthenticationException e) {
- logger.debug("Could not send action", e);
- }
- }
-
- /**
- * Last known state of MyQ Devices
- *
- * @return cached MyQ devices
- */
- public @Nullable List devicesCache() {
- return devicesCache;
- }
-
- private void stopPolls() {
- stopNormalPoll();
- stopRapidPoll();
- }
-
- private synchronized void stopNormalPoll() {
- stopFuture(normalPollFuture);
- normalPollFuture = null;
- }
-
- private synchronized void stopRapidPoll() {
- stopFuture(rapidPollFuture);
- rapidPollFuture = null;
- }
-
- private void stopFuture(@Nullable Future> future) {
- if (future != null) {
- future.cancel(true);
- }
- }
-
- private synchronized void restartPolls(boolean rapid) {
- stopPolls();
- if (rapid) {
- normalPollFuture = scheduler.scheduleWithFixedDelay(this::normalPoll, 35, normalRefreshSeconds,
- TimeUnit.SECONDS);
- rapidPollFuture = scheduler.scheduleWithFixedDelay(this::rapidPoll, 3, RAPID_REFRESH_SECONDS,
- TimeUnit.SECONDS);
- } else {
- normalPollFuture = scheduler.scheduleWithFixedDelay(this::normalPoll, 0, normalRefreshSeconds,
- TimeUnit.SECONDS);
- }
- }
-
- private void normalPoll() {
- stopRapidPoll();
- fetchData();
- }
-
- private void rapidPoll() {
- fetchData();
- }
-
- private synchronized void fetchData() {
- try {
- if (accounts == null) {
- getAccounts();
- }
- getDevices();
- } catch (MyQCommunicationException e) {
- logger.debug("MyQ communication error", e);
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
- } catch (MyQAuthenticationException e) {
- logger.debug("MyQ authentication error", e);
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
- stopPolls();
- } catch (InterruptedException e) {
- // we were shut down, ignore
- }
- }
-
- /**
- * This attempts to navigate the MyQ oAuth login flow in order to obtain a @AccessTokenResponse
- *
- * @return AccessTokenResponse token
- * @throws InterruptedException
- * @throws MyQCommunicationException
- * @throws MyQAuthenticationException
- */
- private AccessTokenResponse login()
- throws InterruptedException, MyQCommunicationException, MyQAuthenticationException {
- try {
- // make sure we have a fresh session
- URI authUri = new URI(LOGIN_BASE_URL);
- CookieStore store = httpClient.getCookieStore();
- store.get(authUri).forEach(cookie -> {
- store.remove(authUri, cookie);
- });
-
- String codeVerifier = generateCodeVerifier();
-
- ContentResponse loginPageResponse = getLoginPage(codeVerifier);
-
- // load the login page to get cookies and form parameters
- Document loginPage = Jsoup.parse(loginPageResponse.getContentAsString());
- Element form = loginPage.select("form").first();
- Element requestToken = loginPage.select("input[name=__RequestVerificationToken]").first();
- Element returnURL = loginPage.select("input[name=ReturnUrl]").first();
-
- if (form == null || requestToken == null) {
- throw new MyQCommunicationException("Could not load login page");
- }
-
- // url that the form will submit to
- String action = LOGIN_BASE_URL + form.attr("action");
-
- // post our user name and password along with elements from the scraped form
- String location = postLogin(action, requestToken.attr("value"), returnURL.attr("value"));
- if (location == null) {
- throw new MyQAuthenticationException("Could not login with credentials");
- }
-
- // finally complete the oAuth flow and retrieve a JSON oAuth token response
- ContentResponse tokenResponse = getLoginToken(location, codeVerifier);
- String loginToken = tokenResponse.getContentAsString();
-
- try {
- AccessTokenResponse accessTokenResponse = gsonLowerCase.fromJson(loginToken, AccessTokenResponse.class);
- if (accessTokenResponse == null) {
- throw new MyQAuthenticationException("Could not parse token response");
- }
- getOAuthService().importAccessTokenResponse(accessTokenResponse);
- return accessTokenResponse;
- } catch (JsonSyntaxException e) {
- throw new MyQCommunicationException("Invalid Token Response " + loginToken);
- }
- } catch (IOException | ExecutionException | TimeoutException | OAuthException | URISyntaxException e) {
- throw new MyQCommunicationException(e.getMessage());
- }
- }
-
- private void getAccounts() throws InterruptedException, MyQCommunicationException, MyQAuthenticationException {
- ContentResponse response = sendRequest(ACCOUNTS_URL, HttpMethod.GET, null, null);
- accounts = parseResultAndUpdateStatus(response, gsonLowerCase, AccountsDTO.class);
- }
-
- private void getDevices() throws InterruptedException, MyQCommunicationException, MyQAuthenticationException {
- AccountsDTO localAccounts = accounts;
- if (localAccounts == null) {
- return;
- }
-
- List currentDevices = new ArrayList();
-
- for (AccountDTO account : localAccounts.accounts) {
- ContentResponse response = sendRequest(String.format(DEVICES_URL, account.id), HttpMethod.GET, null, null);
- DevicesDTO devices = parseResultAndUpdateStatus(response, gsonLowerCase, DevicesDTO.class);
- currentDevices.addAll(devices.items);
- devices.items.forEach(device -> {
- ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily);
- if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) {
- for (Thing thing : getThing().getThings()) {
- ThingHandler handler = thing.getHandler();
- if (handler != null && ((MyQDeviceHandler) handler).getSerialNumber()
- .equalsIgnoreCase(device.serialNumber)) {
- ((MyQDeviceHandler) handler).handleDeviceUpdate(device);
- }
- }
- }
- });
- }
- devicesCache = currentDevices;
- }
-
- private synchronized ContentResponse sendRequest(String url, HttpMethod method, @Nullable ContentProvider content,
- @Nullable String contentType)
- throws InterruptedException, MyQCommunicationException, MyQAuthenticationException {
- AccessTokenResponse tokenResponse = null;
- // if we don't need to force a login, attempt to use the token we have
- if (!needsLogin) {
- try {
- tokenResponse = getOAuthService().getAccessTokenResponse();
- } catch (OAuthException | IOException | OAuthResponseException e) {
- // ignore error, will try to login below
- logger.debug("Error accessing token, will attempt to login again", e);
- }
- }
-
- // if no token, or we need to login, do so now
- if (tokenResponse == null) {
- tokenResponse = login();
- needsLogin = false;
- }
-
- Request request = httpClient.newRequest(url).method(method).agent(userAgent)
- .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
- .header("Authorization", authTokenHeader(tokenResponse));
- if (content != null & contentType != null) {
- request = request.content(content, contentType);
- }
-
- // use asyc jetty as the API service will response with a 401 error when credentials are wrong,
- // but not a WWW-Authenticate header which causes Jetty to throw a generic execution exception which
- // prevents us from knowing the response code
- logger.trace("Sending {} to {}", request.getMethod(), request.getURI());
- final CompletableFuture futureResult = new CompletableFuture<>();
- request.send(new BufferingResponseListener() {
- @NonNullByDefault({})
- @Override
- public void onComplete(Result result) {
- Response response = result.getResponse();
- futureResult.complete(new HttpContentResponse(response, getContent(), getMediaType(), getEncoding()));
- }
- });
-
- try {
- ContentResponse result = futureResult.get();
- logger.trace("Account Response - status: {} content: {}", result.getStatus(), result.getContentAsString());
- return result;
- } catch (ExecutionException e) {
- throw new MyQCommunicationException(e.getMessage());
- }
- }
-
- private T parseResultAndUpdateStatus(ContentResponse response, Gson parser, Class classOfT)
- throws MyQCommunicationException {
- if (HttpStatus.isSuccess(response.getStatus())) {
- try {
- T responseObject = parser.fromJson(response.getContentAsString(), classOfT);
- if (responseObject != null) {
- if (getThing().getStatus() != ThingStatus.ONLINE) {
- updateStatus(ThingStatus.ONLINE);
- }
- return responseObject;
- } else {
- throw new MyQCommunicationException("Bad response from server");
- }
- } catch (JsonSyntaxException e) {
- throw new MyQCommunicationException("Invalid JSON Response " + response.getContentAsString());
- }
- } else if (response.getStatus() == HttpStatus.UNAUTHORIZED_401) {
- // our tokens no longer work, will need to login again
- needsLogin = true;
- throw new MyQCommunicationException("Token was rejected for request");
- } else {
- throw new MyQCommunicationException(
- "Invalid Response Code " + response.getStatus() + " : " + response.getContentAsString());
- }
- }
-
- /**
- * Returns the MyQ login page which contains form elements and cookies needed to login
- *
- * @param codeVerifier
- * @return
- * @throws InterruptedException
- * @throws ExecutionException
- * @throws TimeoutException
- */
- private ContentResponse getLoginPage(String codeVerifier)
- throws InterruptedException, ExecutionException, TimeoutException {
- try {
- Request request = httpClient.newRequest(LOGIN_AUTHORIZE_URL) //
- .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
- .param("client_id", CLIENT_ID) //
- .param("code_challenge", generateCodeChallange(codeVerifier)) //
- .param("code_challenge_method", "S256") //
- .param("redirect_uri", REDIRECT_URI) //
- .param("response_type", "code") //
- .param("scope", SCOPE) //
- .agent(userAgent).followRedirects(true);
- request.header("Accept", "\"*/*\"");
- request.header("Authorization",
- "Basic " + Base64.getEncoder().encodeToString((CLIENT_ID + ":").getBytes()));
- logger.debug("Sending {} to {}", request.getMethod(), request.getURI());
- ContentResponse response = request.send();
- logger.debug("Login Code {} Response {}", response.getStatus(), response.getContentAsString());
- return response;
- } catch (NoSuchAlgorithmException e) {
- throw new ExecutionException(e.getCause());
- }
- }
-
- /**
- * Sends configured credentials and elements from the login page in order to obtain a redirect location header value
- *
- * @param url
- * @param requestToken
- * @param returnURL
- * @return The location header value
- * @throws InterruptedException
- * @throws ExecutionException
- * @throws TimeoutException
- */
- @Nullable
- private String postLogin(String url, String requestToken, String returnURL)
- throws InterruptedException, ExecutionException, TimeoutException {
- /*
- * on a successful post to this page we will get several redirects, and a final 301 to:
- * com.myqops://ios?code=0123456789&scope=MyQ_Residential%20offline_access&iss=https%3A%2F%2Fpartner-identity.
- * myq-cloud.com
- *
- * We can then take the parameters out of this location and continue the process
- */
- Fields fields = new Fields();
- fields.add("Email", username);
- fields.add("Password", password);
- fields.add("__RequestVerificationToken", requestToken);
- fields.add("ReturnUrl", returnURL);
-
- Request request = httpClient.newRequest(url).method(HttpMethod.POST) //
- .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
- .content(new FormContentProvider(fields)) //
- .agent(userAgent) //
- .followRedirects(false);
- setCookies(request);
-
- logger.debug("Posting Login to {}", url);
- ContentResponse response = request.send();
-
- String location = null;
-
- // follow redirects until we match our REDIRECT_URI or hit a redirect safety limit
- for (int i = 0; i < LOGIN_MAX_REDIRECTS && HttpStatus.isRedirection(response.getStatus()); i++) {
-
- String loc = response.getHeaders().get("location");
- if (logger.isTraceEnabled()) {
- logger.trace("Redirect Login: Code {} Location Header: {} Response {}", response.getStatus(), loc,
- response.getContentAsString());
- }
- if (loc == null) {
- logger.debug("No location value");
- break;
- }
- if (loc.indexOf(REDIRECT_URI) == 0) {
- location = loc;
- break;
- }
- request = httpClient.newRequest(LOGIN_BASE_URL + loc).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
- .agent(userAgent).followRedirects(false);
- setCookies(request);
- response = request.send();
- }
- return location;
- }
-
- /**
- * Final step of the login process to get an oAuth access response token
- *
- * @param redirectLocation
- * @param codeVerifier
- * @return
- * @throws InterruptedException
- * @throws ExecutionException
- * @throws TimeoutException
- */
- private ContentResponse getLoginToken(String redirectLocation, String codeVerifier)
- throws InterruptedException, ExecutionException, TimeoutException {
- try {
- Map params = parseLocationQuery(redirectLocation);
-
- Fields fields = new Fields();
- fields.add("client_id", CLIENT_ID);
- fields.add("client_secret", Base64.getEncoder().encodeToString(CLIENT_SECRET.getBytes()));
- fields.add("code", params.get("code"));
- fields.add("code_verifier", codeVerifier);
- fields.add("grant_type", "authorization_code");
- fields.add("redirect_uri", REDIRECT_URI);
- fields.add("scope", params.get("scope"));
-
- Request request = httpClient.newRequest(LOGIN_TOKEN_URL) //
- .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
- .content(new FormContentProvider(fields)) //
- .method(HttpMethod.POST) //
- .agent(userAgent).followRedirects(true);
- setCookies(request);
- ContentResponse response = request.send();
- if (logger.isTraceEnabled()) {
- logger.trace("Login Code {} Response {}", response.getStatus(), response.getContentAsString());
- }
- return response;
- } catch (URISyntaxException e) {
- throw new ExecutionException(e.getCause());
- }
- }
-
- private OAuthClientService getOAuthService() {
- OAuthClientService oAuthService = this.oAuthService;
- if (oAuthService == null || oAuthService.isClosed()) {
- oAuthService = oAuthFactory.createOAuthClientService(getThing().toString(), LOGIN_TOKEN_URL,
- LOGIN_AUTHORIZE_URL, CLIENT_ID, CLIENT_SECRET, SCOPE, false);
- oAuthService.addAccessTokenRefreshListener(this);
- this.oAuthService = oAuthService;
- }
- return oAuthService;
- }
-
- private String generateCodeVerifier() {
- SecureRandom secureRandom = new SecureRandom();
- byte[] codeVerifier = new byte[32];
- secureRandom.nextBytes(codeVerifier);
- return Base64.getUrlEncoder().withoutPadding().encodeToString(codeVerifier);
- }
-
- private String generateCodeChallange(String codeVerifier) throws NoSuchAlgorithmException {
- byte[] bytes = codeVerifier.getBytes(StandardCharsets.US_ASCII);
- MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
- messageDigest.update(bytes, 0, bytes.length);
- byte[] digest = messageDigest.digest();
- return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
- }
-
- private Map parseLocationQuery(String location) throws URISyntaxException {
- URI uri = new URI(location);
- return Arrays.stream(uri.getQuery().split("&")).map(str -> str.split("="))
- .collect(Collectors.toMap(str -> str[0], str -> str[1]));
- }
-
- private void setCookies(Request request) {
- for (HttpCookie c : httpClient.getCookieStore().getCookies()) {
- request.cookie(c);
- }
- }
-
- private String authTokenHeader(AccessTokenResponse tokenResponse) {
- return tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken();
- }
-
- /**
- * Exception for authenticated related errors
- */
- class MyQAuthenticationException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public MyQAuthenticationException(String message) {
- super(message);
- }
- }
-
- /**
- * Generic exception for non authentication related errors when communicating with the MyQ service.
- */
- class MyQCommunicationException extends IOException {
- private static final long serialVersionUID = 1L;
-
- public MyQCommunicationException(@Nullable String message) {
- super(message);
- }
- }
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQDeviceHandler.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQDeviceHandler.java
deleted file mode 100644
index b216daa4c0c45..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQDeviceHandler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.handler;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.myq.internal.dto.DeviceDTO;
-
-/**
- * The {@link MyQDeviceHandler} is responsible for handling device updates
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public interface MyQDeviceHandler {
- void handleDeviceUpdate(DeviceDTO device);
-
- String getSerialNumber();
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQGarageDoorHandler.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQGarageDoorHandler.java
deleted file mode 100644
index 7f7591600a11c..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQGarageDoorHandler.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.handler;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.myq.internal.MyQBindingConstants;
-import org.openhab.binding.myq.internal.config.MyQDeviceConfiguration;
-import org.openhab.binding.myq.internal.dto.DeviceDTO;
-import org.openhab.core.library.types.OnOffType;
-import org.openhab.core.library.types.PercentType;
-import org.openhab.core.library.types.StringType;
-import org.openhab.core.library.types.UpDownType;
-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.BaseThingHandler;
-import org.openhab.core.thing.binding.BridgeHandler;
-import org.openhab.core.types.Command;
-import org.openhab.core.types.RefreshType;
-import org.openhab.core.types.UnDefType;
-
-/**
- * The {@link MyQGarageDoorHandler} is responsible for handling commands for a garage door thing, which are
- * sent to one of the channels.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceHandler {
- private @Nullable DeviceDTO device;
- private String serialNumber;
-
- public MyQGarageDoorHandler(Thing thing) {
- super(thing);
- serialNumber = getConfigAs(MyQDeviceConfiguration.class).serialNumber;
- }
-
- @Override
- public void initialize() {
- updateStatus(ThingStatus.UNKNOWN);
- }
-
- @Override
- public void handleCommand(ChannelUID channelUID, Command command) {
- if (command instanceof RefreshType) {
- updateState();
- return;
- }
- Bridge bridge = getBridge();
- final DeviceDTO localDevice = device;
- if (bridge != null && localDevice != null) {
- BridgeHandler handler = bridge.getHandler();
- if (handler != null) {
- String cmd = null;
- if (command instanceof OnOffType) {
- cmd = command == OnOffType.ON ? "open" : "close";
- }
- if (command instanceof UpDownType) {
- cmd = command == UpDownType.UP ? "open" : "close";
- }
- if (command instanceof PercentType percentage) {
- cmd = percentage.as(UpDownType.class) == UpDownType.UP ? "open" : "close";
- }
- if (command instanceof StringType) {
- cmd = command.toString();
- }
- if (cmd != null) {
- ((MyQAccountHandler) handler).sendDoorAction(localDevice, cmd);
- }
- }
- }
- }
-
- @Override
- public String getSerialNumber() {
- return serialNumber;
- }
-
- protected void updateState() {
- final DeviceDTO localDevice = device;
- if (localDevice != null) {
- String doorState = localDevice.state.doorState;
- updateState("status", new StringType(doorState));
- switch (doorState) {
- case "open":
- case "opening":
- case "closing":
- case "stopped":
- case "transition":
- updateState("switch", OnOffType.ON);
- updateState("rollershutter", UpDownType.UP);
- break;
- case "closed":
- updateState("switch", OnOffType.OFF);
- updateState("rollershutter", UpDownType.DOWN);
- break;
- default:
- updateState("switch", UnDefType.UNDEF);
- updateState("rollershutter", UnDefType.UNDEF);
- break;
- }
- updateState("closeerror", localDevice.state.isUnattendedCloseAllowed ? OnOffType.OFF : OnOffType.ON);
- updateState("openerror", localDevice.state.isUnattendedOpenAllowed ? OnOffType.OFF : OnOffType.ON);
- }
- }
-
- @Override
- public void handleDeviceUpdate(DeviceDTO device) {
- if (!MyQBindingConstants.THING_TYPE_GARAGEDOOR.getId().equals(device.deviceFamily)) {
- return;
- }
- this.device = device;
- if (device.state.online) {
- updateStatus(ThingStatus.ONLINE);
- updateState();
- } else {
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Device reports as offline");
- }
- }
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQLampHandler.java b/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQLampHandler.java
deleted file mode 100644
index 04cb77b92c03f..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQLampHandler.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.myq.internal.handler;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.myq.internal.MyQBindingConstants;
-import org.openhab.binding.myq.internal.config.MyQDeviceConfiguration;
-import org.openhab.binding.myq.internal.dto.DeviceDTO;
-import org.openhab.core.library.types.OnOffType;
-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.BaseThingHandler;
-import org.openhab.core.thing.binding.BridgeHandler;
-import org.openhab.core.types.Command;
-import org.openhab.core.types.RefreshType;
-
-/**
- * The {@link MyQLampHandler} is responsible for handling commands for a lamp thing, which are
- * sent to one of the channels.
- *
- * @author Dan Cunningham - Initial contribution
- */
-@NonNullByDefault
-public class MyQLampHandler extends BaseThingHandler implements MyQDeviceHandler {
- private @Nullable DeviceDTO device;
- private String serialNumber;
-
- public MyQLampHandler(Thing thing) {
- super(thing);
- serialNumber = getConfigAs(MyQDeviceConfiguration.class).serialNumber;
- }
-
- @Override
- public void initialize() {
- updateStatus(ThingStatus.UNKNOWN);
- }
-
- @Override
- public void handleCommand(ChannelUID channelUID, Command command) {
- if (command instanceof RefreshType) {
- updateState();
- return;
- }
-
- if (command instanceof OnOffType) {
- Bridge bridge = getBridge();
- final DeviceDTO localDevice = device;
- if (bridge != null && localDevice != null) {
- BridgeHandler handler = bridge.getHandler();
- if (handler != null) {
- ((MyQAccountHandler) handler).sendLampAction(localDevice, command == OnOffType.ON ? "on" : "off");
- }
- }
- }
- }
-
- @Override
- public String getSerialNumber() {
- return serialNumber;
- }
-
- protected void updateState() {
- final DeviceDTO localDevice = device;
- if (localDevice != null) {
- String lampState = localDevice.state.lampState;
- updateState("switch", "on".equals(lampState) ? OnOffType.ON : OnOffType.OFF);
- }
- }
-
- @Override
- public void handleDeviceUpdate(DeviceDTO device) {
- if (!MyQBindingConstants.THING_TYPE_LAMP.getId().equals(device.deviceFamily)) {
- return;
- }
- this.device = device;
- if (device.state.online) {
- updateStatus(ThingStatus.ONLINE);
- updateState();
- } else {
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Device reports as offline");
- }
- }
-}
diff --git a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/config/config.xml
deleted file mode 100644
index beaf772f2412f..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/config/config.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
- Account username
-
-
-
- Account password
- password
-
-
-
- Specifies the refresh interval in seconds
- 60
-
-
-
-
-
-
- Serial number of the garage door
-
-
-
-
-
-
- Serial number of the lamp
-
-
-
-
diff --git a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/i18n/myq.properties b/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/i18n/myq.properties
deleted file mode 100644
index 7fafc355e7588..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/i18n/myq.properties
+++ /dev/null
@@ -1,42 +0,0 @@
-# add-on
-
-addon.myq.name = MyQ Binding
-addon.myq.description = The MyQ binding allows monitoring and control of garage doors that are MyQ enabled.
-
-# thing types
-
-thing-type.myq.account.label = MyQ Account
-thing-type.myq.account.description = MyQ Cloud Account
-thing-type.myq.garagedoor.label = MyQ Garage Door
-thing-type.myq.garagedoor.description = MyQ Garage Door
-thing-type.myq.lamp.label = MyQ Lamp
-thing-type.myq.lamp.description = MyQ Lamp
-
-# thing types config
-
-thing-type.config.myq.account.password.label = password
-thing-type.config.myq.account.password.description = Account password
-thing-type.config.myq.account.refreshInterval.label = Refresh Interval
-thing-type.config.myq.account.refreshInterval.description = Specifies the refresh interval in seconds
-thing-type.config.myq.account.username.label = User Name
-thing-type.config.myq.account.username.description = Account username
-thing-type.config.myq.garagedoor.serialNumber.label = Serial Number
-thing-type.config.myq.garagedoor.serialNumber.description = Serial number of the garage door
-thing-type.config.myq.lamp.serialNumber.label = Serial Number
-thing-type.config.myq.lamp.serialNumber.description = Serial number of the lamp
-
-# channel types
-
-channel-type.myq.doorcloseerror.label = Garage Door Close Error
-channel-type.myq.dooropenerror.label = Garage Door Open Error
-channel-type.myq.doorrollershutter.label = Garage Door Rollershutter
-channel-type.myq.doorstatus.label = Garage Door Status
-channel-type.myq.doorstatus.state.option.open = Open
-channel-type.myq.doorstatus.state.option.opening = Opening
-channel-type.myq.doorstatus.state.option.closed = Closed
-channel-type.myq.doorstatus.state.option.closing = Closing
-channel-type.myq.doorstatus.state.option.stopped = Stopped
-channel-type.myq.doorstatus.state.option.transition = Transitioning
-channel-type.myq.doorstatus.state.option.unknown = Unknown
-channel-type.myq.doorswitch.label = Garage Door Switch
-channel-type.myq.lampswitch.label = Lamp Switch
diff --git a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/thing/thing-types.xml
deleted file mode 100644
index 56fb3cb420e94..0000000000000
--- a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/thing/thing-types.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
- MyQ Cloud Account
-
-
-
-
-
-
-
-
- MyQ Garage Door
-
-
-
-
-
-
-
- serialNumber
-
-
-
-
-
-
-
-
- MyQ Lamp
-
-
-
- serialNumber
-
-
-
-
- String
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Switch
-
-
-
- Rollershutter
-
-
-
- Switch
-
-
-
-
- Switch
-
-
-
-
- Switch
-
-
-
diff --git a/bundles/org.openhab.binding.nanoleaf/README.md b/bundles/org.openhab.binding.nanoleaf/README.md
index 5eef9761961cd..8ce55a9bf9bca 100644
--- a/bundles/org.openhab.binding.nanoleaf/README.md
+++ b/bundles/org.openhab.binding.nanoleaf/README.md
@@ -172,7 +172,7 @@ The controller bridge has the following channels:
| rhythmActive | Switch | Activity state of the rhythm module | Yes |
| rhythmMode | Number | Sound source for the rhythm module. 0=Microphone, 1=Aux cable | No |
| state | Image | Shows the current state of your panels with colors. | Yes |
-| swipe | Trigger | [Canvas / Shapes Only] Detects Swipes over the panel.LEFT, RIGHT, UP, DOWN events are supported. | Yes |
+| swipe | Trigger | [Canvas / Shapes Only] Detects Swipes over the panel. LEFT, RIGHT, UP, DOWN events are supported. | Yes |
A lightpanel thing has the following channels:
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/NAHomeStatus.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/NAHomeStatus.java
index 59861c4dd5b4b..5583bc4aef831 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/NAHomeStatus.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/NAHomeStatus.java
@@ -35,24 +35,26 @@ public class HomeStatus extends NAThing {
private @Nullable NAObjectMap modules;
public NAObjectMap getModules() {
- NAObjectMap localModules = modules;
- return localModules != null ? localModules : new NAObjectMap<>();
+ NAObjectMap local = modules;
+ return local != null ? local : new NAObjectMap<>();
}
}
public class Energy extends HomeStatus {
- private NAObjectMap rooms = new NAObjectMap<>();
+ private @Nullable NAObjectMap rooms;
public NAObjectMap getRooms() {
- return rooms;
+ NAObjectMap local = rooms;
+ return local != null ? local : new NAObjectMap<>();
}
}
public class Security extends HomeStatus {
- private NAObjectMap persons = new NAObjectMap<>();
+ private @Nullable NAObjectMap persons;
public NAObjectMap getPersons() {
- return persons;
+ NAObjectMap local = persons;
+ return local != null ? local : new NAObjectMap<>();
}
}
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAObjectMap.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAObjectMap.java
index c4357e6d40a1e..4251c4f439e9b 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAObjectMap.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAObjectMap.java
@@ -33,7 +33,7 @@ public T put(T thing) {
return super.put(thing.getId(), thing);
}
- public Optional getOpt(String key) {
- return Optional.ofNullable(super.get(key));
+ public Optional getOpt(@Nullable String key) {
+ return Optional.ofNullable(key != null ? super.get(key) : null);
}
}
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java
index 1a6c973692b21..85ba84c9078fd 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java
@@ -128,6 +128,26 @@ default Optional recurseUpToHomeHandler(@Nullable CommonInterfa
: recurseUpToHomeHandler(handler.getBridgeHandler());
}
+ /**
+ * Recurses down in the home/module/device tree
+ *
+ * @param bridge
+ * @return the list of childs of the bridge
+ */
+ default List getAllActiveChildren(Bridge bridge) {
+ List result = new ArrayList<>();
+ bridge.getThings().stream().filter(Thing::isEnabled).map(Thing::getHandler).forEach(childHandler -> {
+ if (childHandler != null) {
+ Thing childThing = childHandler.getThing();
+ if (childThing instanceof Bridge bridgeChild) {
+ result.addAll(getAllActiveChildren(bridgeChild));
+ }
+ result.add((CommonInterface) childHandler);
+ }
+ });
+ return result;
+ }
+
default List getActiveChildren() {
Thing thing = getThing();
if (thing instanceof Bridge bridge) {
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EnergyCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EnergyCapability.java
index 832d2252dcd0a..39752014ec589 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EnergyCapability.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EnergyCapability.java
@@ -91,11 +91,19 @@ protected void updateHomeStatus(HomeStatus homeStatus) {
NAObjectMap modules = energyStatus.getModules();
handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
String childId = childHandler.getId();
- rooms.getOpt(childId).ifPresentOrElse(roomData -> childHandler.setNewData(roomData), () -> {
+ logger.trace("childId: {}", childId);
+ rooms.getOpt(childId).ifPresentOrElse(roomData -> {
+ logger.trace("roomData: {}", roomData);
+ childHandler.setNewData(roomData);
+ }, () -> {
modules.getOpt(childId).ifPresent(moduleData -> {
+ logger.trace("moduleData: {}", moduleData);
childHandler.setNewData(moduleData);
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
- .forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
+ .forEach(bridgedModule -> {
+ logger.trace("bridgedModule: {}", bridgedModule);
+ childHandler.setNewData(bridgedModule);
+ });
});
});
});
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java
index f9e281ab5ddaa..4b7a62ef04220 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java
@@ -32,6 +32,7 @@
import org.openhab.binding.netatmo.internal.config.HomeConfiguration;
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
+import org.openhab.core.thing.Bridge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -105,10 +106,14 @@ private boolean hasArea(FeatureArea searched) {
return featureAreas.contains(searched);
}
+ /**
+ * Errored equipments are reported at home level - so we need to explore all the tree to identify modules
+ * depending from a child device.
+ */
@Override
protected void updateErrors(NAError error) {
- handler.getActiveChildren().stream().filter(handler -> handler.getId().equals(error.getId())).findFirst()
- .ifPresent(handler -> handler.setNewData(error));
+ handler.getAllActiveChildren((Bridge) thing).stream().filter(handler -> handler.getId().equals(error.getId()))
+ .findFirst().ifPresent(handler -> handler.setNewData(error));
}
@Override
@@ -123,11 +128,11 @@ protected List updateReadings(HomeApi api) {
}
api.getHomeStatus(id).ifPresent(body -> {
- body.getHomeStatus().ifPresent(homeStatus -> result.add(homeStatus));
+ body.getHomeStatus().ifPresent(result::add);
result.addAll(body.getErrors());
});
} catch (NetatmoException e) {
- logger.warn("Error getting Home informations : {}", e.getMessage());
+ logger.warn("Error getting Home informations: {}", e.getMessage());
}
});
return result;
diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo_fr.properties b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo_fr.properties
index 39b6f2b8718aa..1feaf9cbbc0e9 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo_fr.properties
+++ b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo_fr.properties
@@ -462,6 +462,13 @@ status-bridge-offline = La passerelle n'est pas connectée à l'API Netatmo
device-not-connected = L'objet n'est pas accessible
data-over-limit = Les données semblent assez anciennes
request-time-out = La requête a expiré - va essayer de se reconnecter plus tard
+deserialization-unknown = La désérialisation renvoie un code inconnu
+
+homestatus-unknown-error = Erreur inconnue
+homestatus-internal-error = Erreur interne
+homestatus-parser-error = Erreur d'analyse
+homestatus-command-unknown = Erreur de commande avec module inconnu
+homestatus-invalid-params = Paramètres de commande non valides
# actions
diff --git a/bundles/org.openhab.binding.openwebnet/README.md b/bundles/org.openhab.binding.openwebnet/README.md
index ab2ce17790a8e..472d37c187f01 100644
--- a/bundles/org.openhab.binding.openwebnet/README.md
+++ b/bundles/org.openhab.binding.openwebnet/README.md
@@ -137,6 +137,7 @@ For any manually added device, you must configure:
- dry Contact or IR Interface `99`: add `3` before --> `where="399"`
- energy meter F520/F521 numbered `1`: add `5` before --> `where="51"`
- energy meter F522/F523 numbered `4`: add `7` before and `#0` after --> `where="74#0"`
+ - energy meter F520/F521 the `energyRefreshPeriod` configuration parameter sets the number of minutes (the minimum value is 30, the maximum value is 1440) between refreshes for energy totalizers (default: 30 minutes) --> `energyRefreshPeriod` = 35
- alarm zone `2` --> `where="2"`
- example for Zigbee devices: `where=765432101#9`. The ID of the device (ADDR part) is usually written in hexadecimal on the device itself, for example `ID 0074CBB1`: convert to decimal (`7654321`) and add `01#9` at the end to obtain `where=765432101#9`. For 2-unit switch devices (`zb_on_off_switch2u`), last part should be `00#9`.
@@ -208,15 +209,17 @@ OPEN command to execute: *5*8#134##
### Lighting, Automation, Basic/CEN/CEN+ Scenario Events, Dry Contact / IR Interfaces, Power and Aux channels
-| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write |
+| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write |
|-----------------------------------------|---------------------------------------------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------|:-----------:|
-| `switch` or `switch_01`/`02` for Zigbee | `bus_on_off_switch`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device `ON` and `OFF` | R/W |
-| `brightness` | `bus_dimmer`, `zb_dimmer` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W |
-| `shutter` | `bus_automation` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W |
-| `scenario` | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) |
-| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#scenario-channels) | R (TRIGGER) |
-| `sensor` | `bus_dry_contact_ir` | Switch | Indicates if a Dry Contact Interface is `ON`/`OFF`, or if an IR Sensor is detecting movement (`ON`), or not (`OFF`) | R |
-| `power` | `bus_energy_meter` | Number:Power | The current active power usage from Energy Meter | R |
+| `switch` or `switch_01`/`02` for Zigbee | `bus_on_off_switch`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device `ON` and `OFF` | R/W |
+| `brightness` | `bus_dimmer`, `zb_dimmer` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W |
+| `shutter` | `bus_automation` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W |
+| `scenario` | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) |
+| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#scenario-channels) | R (TRIGGER) |
+| `sensor` | `bus_dry_contact_ir` | Switch | Indicates if a Dry Contact Interface is `ON`/`OFF`, or if an IR Sensor is detecting movement (`ON`), or not (`OFF`) | R |
+| `power` | `bus_energy_meter` | Number:Power | The current active power usage from Energy Meter | R |
+| `energyToday` | `bus_energy_meter` | Number:Energy | Current day energy totalizer | R |
+| `energyThisMonth` | `bus_energy_meter` | Number:Energy | Current month energy totalizer | R |
| `aux` | `bus_aux` | String | Possible commands: `ON`, `OFF`, `TOGGLE`, `STOP`, `UP`, `DOWN`, `ENABLED`, `DISABLED`, `RESET_GEN`, `RESET_BI`, `RESET_TRI`. Only `ON` and `OFF` are supported for now | R/W |
### Alarm channels
@@ -368,6 +371,10 @@ Rollershutter iLR_shutter "Shutter [%.0f %%]" (g
Number:Power iCENTRAL_Ta "Power [%.0f %unit%]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:power" }
Number:Power iCENTRAL_Tb "Power [%.0f %unit%]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:power" }
+Number:Energy iCENTRAL_Ta_day "Energy Day [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:energyToday"}
+Number:Energy iCENTRAL_Tb_day "Energy Day [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:energyToday"}
+Number:Energy iCENTRAL_Ta_month "Energy Month [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:energyThisMonth"}
+Number:Energy iCENTRAL_Tb_month "Energy Month [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:energyThisMonth"}
// 99 zones thermo central unit
Group gCentralUnit "Thermo Central Unit"
@@ -434,8 +441,12 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap"
Frame label="Energy Meters" icon="energy"
{
- Default item=iCENTRAL_Ta label="General" icon="energy" valuecolor=[>3000="red"]
- Default item=iCENTRAL_Tb label="Ground Floor" icon="energy" valuecolor=[>3000="red"]
+ Default item=iCENTRAL_Ta label="General" icon="energy" valuecolor=[>3000="red"]
+ Default item=iCENTRAL_Tb label="Ground Floor" icon="energy" valuecolor=[>3000="red"]
+ Default item=CENTRAL_Ta_day label="General Energy Today" icon="energy" valuecolor=[>3000="blue"]
+ Default item=CENTRAL_Tb_day label="Ground Floor Energy Today" icon="energy" valuecolor=[>3000="blue"]
+ Default item=CENTRAL_Ta_month label="General Energy This Month" icon="energy" valuecolor=[>3000="yellow"]
+ Default item=CENTRAL_Tb_month label="Ground Floor Energy This Month" icon="energy" valuecolor=[>3000="yellow"]
}
Frame label="Living Room Thermo"
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java
index 69e69633494a2..21328a4174925 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java
+++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java
@@ -157,6 +157,8 @@ public class OpenWebNetBindingConstants {
public static final String CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL = "atLeastOneProbeManual";
// energy management
public static final String CHANNEL_POWER = "power";
+ public static final String CHANNEL_ENERGY_TOTALIZER_DAY = "energyToday";
+ public static final String CHANNEL_ENERGY_TOTALIZER_MONTH = "energyThisMonth";
// scenario button channels
public static final String CHANNEL_SCENARIO_BUTTON = "button#";
public static final String CHANNEL_TYPE_CEN_BUTTON_EVENT = "cenButtonEvent";
@@ -180,6 +182,7 @@ public class OpenWebNetBindingConstants {
public static final String CONFIG_PROPERTY_SHUTTER_RUN = "shutterRun";
public static final String CONFIG_PROPERTY_SCENARIO_BUTTONS = "buttons";
public static final String CONFIG_PROPERTY_STANDALONE = "standAlone";
+ public static final String CONFIG_PROPERTY_REFRESH_PERIOD = "energyRefreshPeriod";
// gw config properties
public static final String CONFIG_PROPERTY_HOST = "host";
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java
index 8b7a03e4d9cda..cdb3a638f5c12 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java
+++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java
@@ -12,12 +12,15 @@
*/
package org.openhab.binding.openwebnet.internal.handler;
+import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_ENERGY_TOTALIZER_DAY;
+import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_ENERGY_TOTALIZER_MONTH;
import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_POWER;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import javax.measure.quantity.Energy;
import javax.measure.quantity.Power;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -49,7 +52,7 @@
* device. It extends the abstract {@link OpenWebNetThingHandler}.
*
* @author Massimo Valla - Initial contribution
- * @author Andrea Conte - Energy management
+ * @author Andrea Conte, Giovanni Fabiani - Energy management
*/
@NonNullByDefault
public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler {
@@ -57,8 +60,11 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler {
private final Logger logger = LoggerFactory.getLogger(OpenWebNetEnergyHandler.class);
public static final Set SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.ENERGY_MANAGEMENT_SUPPORTED_THING_TYPES;
- public static final int ENERGY_SUBSCRIPTION_PERIOD = 10; // minutes
- private @Nullable ScheduledFuture> notificationSchedule;
+ private static final int POWER_SUBSCRIPTION_PERIOD = 10; // MINUTES
+ private int energyRefreshPeriod; // MINUTES
+
+ private @Nullable ScheduledFuture> powerSchedule;
+ private @Nullable ScheduledFuture> energySchedule;
public OpenWebNetEnergyHandler(Thing thing) {
super(thing);
@@ -69,6 +75,14 @@ public OpenWebNetEnergyHandler(Thing thing) {
@Override
public void initialize() {
super.initialize();
+ try {
+ Object refreshPeriodConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_REFRESH_PERIOD);
+ energyRefreshPeriod = Integer.parseInt(refreshPeriodConfig.toString());
+ } catch (NumberFormatException e) {
+ logger.debug("NumberFormatException caught while parsing OpenWebNetEnergyHandler configuration: {}",
+ e.getMessage());
+ energyRefreshPeriod = 30;
+ }
// In order to get data from the probe we must send a command over the bus, this could be done only when the
// bridge is online.
@@ -83,6 +97,7 @@ public void initialize() {
if (gw != null && gw.isConnected()) {
// bridge is online
subscribeToActivePowerChanges();
+ subscribeToEnergyTotalizer();
}
}
}
@@ -94,26 +109,27 @@ public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
// subscribe the scheduler only after the bridge is online
if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) {
subscribeToActivePowerChanges();
+ subscribeToEnergyTotalizer();
}
}
private void subscribeToActivePowerChanges() {
- notificationSchedule = scheduler.scheduleWithFixedDelay(() -> {
+ powerSchedule = scheduler.scheduleWithFixedDelay(() -> {
if (isFirstSchedulerLaunch) {
logger.debug(
"subscribeToActivePowerChanges() For WHERE={} subscribing to active power changes notification for the next {}min",
- deviceWhere, ENERGY_SUBSCRIPTION_PERIOD);
+ deviceWhere, POWER_SUBSCRIPTION_PERIOD);
} else {
logger.debug(
"subscribeToActivePowerChanges() Refreshing subscription for the next {}min for WHERE={} to active power changes notification",
- ENERGY_SUBSCRIPTION_PERIOD, deviceWhere);
+ POWER_SUBSCRIPTION_PERIOD, deviceWhere);
}
Where w = deviceWhere;
if (w == null) {
logger.warn("subscribeToActivePowerChanges() WHERE=null. Skipping");
} else {
try {
- send(EnergyManagement.setActivePowerNotificationsTime(w.value(), ENERGY_SUBSCRIPTION_PERIOD));
+ send(EnergyManagement.setActivePowerNotificationsTime(w.value(), POWER_SUBSCRIPTION_PERIOD));
isFirstSchedulerLaunch = false;
} catch (Exception e) {
if (isFirstSchedulerLaunch) {
@@ -127,15 +143,40 @@ private void subscribeToActivePowerChanges() {
}
}
}
- }, 0, ENERGY_SUBSCRIPTION_PERIOD - 1, TimeUnit.MINUTES);
+ }, 0, POWER_SUBSCRIPTION_PERIOD - 1, TimeUnit.MINUTES);
+ }
+
+ private void subscribeToEnergyTotalizer() {
+ Where w = deviceWhere;
+ if (w == null) {
+ logger.warn("subscribeToEnergyTotalizer() WHERE=null. Skipping");
+ return;
+ }
+ energySchedule = scheduler.scheduleWithFixedDelay(() -> {
+ try {
+ send(EnergyManagement.requestCurrentDayTotalizer(w.value()));
+ send(EnergyManagement.requestCurrentMonthTotalizer(w.value()));
+ } catch (Exception e) {
+ logger.warn(
+ "subscribeToEnergyTotalizer() Could not subscribe to totalizers scheduler for WHERE={}. Exception={}",
+ w, e.getMessage());
+ }
+ }, 0, energyRefreshPeriod, TimeUnit.MINUTES);
}
@Override
public void dispose() {
- if (notificationSchedule != null) {
- ScheduledFuture> ns = notificationSchedule;
- ns.cancel(false);
- logger.debug("dispose() scheduler stopped.");
+ ScheduledFuture> sfp = powerSchedule;
+ if (sfp != null) {
+ sfp.cancel(false);
+ powerSchedule = null;
+ logger.debug("dispose() power scheduler stopped.");
+ }
+ ScheduledFuture> sfe = energySchedule;
+ if (sfe != null) {
+ sfe.cancel(false);
+ energySchedule = null;
+ logger.debug("dispose() energy scheduler stopped.");
}
super.dispose();
}
@@ -152,6 +193,8 @@ protected void requestChannelState(ChannelUID channel) {
if (w != null) {
try {
send(EnergyManagement.requestActivePower(w.value()));
+ send(EnergyManagement.requestCurrentDayTotalizer(w.value()));
+ send(EnergyManagement.requestCurrentMonthTotalizer(w.value()));
} catch (OWNException e) {
logger.debug("Exception while requesting state for channel {}: {} ", channel, e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
@@ -163,6 +206,8 @@ protected void requestChannelState(ChannelUID channel) {
protected void refreshDevice(boolean refreshAll) {
logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_POWER));
+ requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ENERGY_TOTALIZER_DAY));
+ requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ENERGY_TOTALIZER_MONTH));
}
@Override
@@ -187,6 +232,10 @@ protected void handleMessage(BaseOpenMessage msg) {
// fix: check for correct DIM (ActivePower / 113)
if (msg.getDim().equals(EnergyManagement.DimEnergyMgmt.ACTIVE_POWER)) {
updateActivePower(msg);
+ } else if (msg.getDim().equals(EnergyManagement.DimEnergyMgmt.PARTIAL_TOTALIZER_CURRENT_DAY)) {
+ updateCurrentDayTotalizer(msg);
+ } else if (msg.getDim().equals(EnergyManagement.DimEnergyMgmt.PARTIAL_TOTALIZER_CURRENT_MONTH)) {
+ updateCurrentMonthTotalizer(msg);
} else {
logger.debug("handleMessage() Ignoring message {} because it's not related to active power value.",
msg);
@@ -198,7 +247,6 @@ protected void handleMessage(BaseOpenMessage msg) {
* Updates energy power state based on an EnergyManagement message received from the OWN network
*
* @param msg the EnergyManagement message received
- * @throws FrameException
*/
private void updateActivePower(BaseOpenMessage msg) {
Integer activePower;
@@ -208,6 +256,48 @@ private void updateActivePower(BaseOpenMessage msg) {
} catch (FrameException e) {
logger.warn("FrameException on frame {}: {}", msg, e.getMessage());
updateState(CHANNEL_POWER, UnDefType.UNDEF);
+ } catch (NumberFormatException e) {
+ logger.warn("NumberFormatException on frame {}: {}", msg, e.getMessage());
+ updateState(CHANNEL_POWER, UnDefType.UNDEF);
+ }
+ }
+
+ /**
+ * Updates current day totalizer
+ *
+ * @param msg the EnergyManagement message received
+ */
+ private void updateCurrentDayTotalizer(BaseOpenMessage msg) {
+ Double currentDayEnergy;
+ try {
+ currentDayEnergy = Double.parseDouble(msg.getDimValues()[0]) / 1000d;
+ updateState(CHANNEL_ENERGY_TOTALIZER_DAY, new QuantityType(currentDayEnergy, Units.KILOWATT_HOUR));
+ } catch (FrameException e) {
+ logger.warn("FrameException on frame {}: {}", msg, e.getMessage());
+ updateState(CHANNEL_ENERGY_TOTALIZER_DAY, UnDefType.UNDEF);
+ } catch (NumberFormatException e) {
+ logger.warn("NumberFormatException on frame {}: {}", msg, e.getMessage());
+ updateState(CHANNEL_ENERGY_TOTALIZER_DAY, UnDefType.UNDEF);
+ }
+ }
+
+ /**
+ * Updates current month totalizer
+ *
+ * @param msg the EnergyManagement message received
+ */
+ private void updateCurrentMonthTotalizer(BaseOpenMessage msg) {
+ Double currentMonthEnergy;
+ try {
+ currentMonthEnergy = Double.parseDouble(msg.getDimValues()[0]) / 1000d;
+ updateState(CHANNEL_ENERGY_TOTALIZER_MONTH,
+ new QuantityType(currentMonthEnergy, Units.KILOWATT_HOUR));
+ } catch (FrameException e) {
+ logger.warn("FrameException on frame {}: {}", msg, e.getMessage());
+ updateState(CHANNEL_ENERGY_TOTALIZER_MONTH, UnDefType.UNDEF);
+ } catch (NumberFormatException e) {
+ logger.warn("NumberFormatException on frame {}: {}", msg, e.getMessage());
+ updateState(CHANNEL_ENERGY_TOTALIZER_MONTH, UnDefType.UNDEF);
}
}
}
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties
index 54e20a79f3177..c73164cc12480 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties
@@ -61,17 +61,19 @@ thing-type.config.openwebnet.bus_automation.where.description = Example: A/PL ad
thing-type.config.openwebnet.bus_aux.where.label = OpenWebNet Address (where)
thing-type.config.openwebnet.bus_aux.where.description = Example: AUX 1 --> where="1"
thing-type.config.openwebnet.bus_cen_scenario_control.buttons.label = Configured Buttons
-thing-type.config.openwebnet.bus_cen_scenario_control.buttons.description = List (comma separated) of buttons numbers [0-31] configured for this scenario device. Example: buttons=1,2,4
+thing-type.config.openwebnet.bus_cen_scenario_control.buttons.description = List (comma separated) of buttons numbers [0-31] configured for this scenario device. Example: buttons="1,2,4"
thing-type.config.openwebnet.bus_cen_scenario_control.where.label = OpenWebNet Address (where)
thing-type.config.openwebnet.bus_cen_scenario_control.where.description = Example: A/PL address: A=1 PL=3 --> where="13". On local bus: where="13#4#01"
thing-type.config.openwebnet.bus_cenplus_scenario_control.buttons.label = Configured Buttons
-thing-type.config.openwebnet.bus_cenplus_scenario_control.buttons.description = List (comma separated) of buttons numbers [0-31] configured for this scenario device, example: buttons=1,2,4
+thing-type.config.openwebnet.bus_cenplus_scenario_control.buttons.description = List (comma separated) of buttons numbers [0-31] configured for this scenario device, example: buttons="1,2,4"
thing-type.config.openwebnet.bus_cenplus_scenario_control.where.label = OpenWebNet Address (where)
thing-type.config.openwebnet.bus_cenplus_scenario_control.where.description = Use 2+N[0-2047]. Example: scenario control 5 --> where="25"
thing-type.config.openwebnet.bus_dimmer.where.label = OpenWebNet Address (where)
thing-type.config.openwebnet.bus_dimmer.where.description = Example: A/PL address: A=1 PL=3 --> where="13". On local bus: where="13#4#01"
thing-type.config.openwebnet.bus_dry_contact_ir.where.label = OpenWebNet Address (where)
thing-type.config.openwebnet.bus_dry_contact_ir.where.description = A "3" must be added before the address. Automation Dry Contacts 3N with N=[1-201]; example N=60 --> where="360". Alarm Dry Contacts and IR sensors 3ZN with Zone Z=[1-9], N=[1-9]; example Z=4, N=5 --> where="345"
+thing-type.config.openwebnet.bus_energy_meter.energyRefreshPeriod.label = Energy Totalizers Refresh Period
+thing-type.config.openwebnet.bus_energy_meter.energyRefreshPeriod.description = Sets the number of minutes between refreshes for energy totalizers (default: 30 minutes)
thing-type.config.openwebnet.bus_energy_meter.where.label = OpenWebNet Address (where)
thing-type.config.openwebnet.bus_energy_meter.where.description = A "5" must be added before the energy meter address: 5N with N=[1-255]. Example energy meter "42" --> where="542"
thing-type.config.openwebnet.bus_gateway.dateTimeSynch.label = Date Time Synchronisation
@@ -185,6 +187,10 @@ channel-type.openwebnet.conditioningValves.state.option.OFF_SPEED_2 = Off speed
channel-type.openwebnet.conditioningValves.state.option.OFF_SPEED_3 = Off speed 3
channel-type.openwebnet.dryContactIR.label = Sensor
channel-type.openwebnet.dryContactIR.description = Dry Contact Interface or IR Interface sensor movement (read only)
+channel-type.openwebnet.energyThisMonth.label = Energy This Month
+channel-type.openwebnet.energyThisMonth.description = Total energy measured for this month
+channel-type.openwebnet.energyToday.label = Energy Today
+channel-type.openwebnet.energyToday.description = Total energy measured for today
channel-type.openwebnet.failureDiscovered.label = Failure Discovered
channel-type.openwebnet.failureDiscovered.description = Central Unit Failure Discovered (read only)
channel-type.openwebnet.function.label = Thermo Function
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet_it.properties b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet_it.properties
index 9e862b1cae901..61cbca514641c 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet_it.properties
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet_it.properties
@@ -61,17 +61,19 @@ thing-type.config.openwebnet.bus_automation.where.description = Esempio\: indiri
thing-type.config.openwebnet.bus_aux.where.label = Indirizzo OpenWebNet (where)
thing-type.config.openwebnet.bus_aux.where.description = Esempio\: AUX 1 --> dove\="1"
thing-type.config.openwebnet.bus_cen_scenario_control.buttons.label = Pulsanti Configurati
-thing-type.config.openwebnet.bus_cen_scenario_control.buttons.description = Elenco (separato da virgola) dei pulsanti numerati [0-31] configurati per questo dispositivo di controllo scenari. Esempio\: buttons\=1,2,4
+thing-type.config.openwebnet.bus_cen_scenario_control.buttons.description = Elenco (separato da virgola) dei pulsanti numero [0-31] configurati per questo dispositivo di scenario. Esempio\: buttons\="1,2,4"
thing-type.config.openwebnet.bus_cen_scenario_control.where.label = Indirizzo OpenWebNet (where)
thing-type.config.openwebnet.bus_cen_scenario_control.where.description = Esempio\: indirizzo A/PL\: A\=1 PL\=3 --> dove\="13". Sul bus locale\: dove\="13\#4\#01"
thing-type.config.openwebnet.bus_cenplus_scenario_control.buttons.label = Pulsanti Configurati
-thing-type.config.openwebnet.bus_cenplus_scenario_control.buttons.description = Elenco (separato da virgola) dei numeri dei pulsanti [0-31] configurati per questo dispositivo di controllo scenari, esempio\: buttons\=1,2,4
+thing-type.config.openwebnet.bus_cenplus_scenario_control.buttons.description = Elenco (separato da virgola) dei numeri di pulsanti [0-31] configurati per questo dispositivo di scenario, esempio\: buttons\="1,2,4"
thing-type.config.openwebnet.bus_cenplus_scenario_control.where.label = Indirizzo OpenWebNet (where)
thing-type.config.openwebnet.bus_cenplus_scenario_control.where.description = Usa 2+N[0-2047]. Esempio\: controllo di scenario 5 --> dove\="25"
thing-type.config.openwebnet.bus_dimmer.where.label = Indirizzo OpenWebNet (where)
thing-type.config.openwebnet.bus_dimmer.where.description = Esempio\: indirizzo A/PL\: A\=1 PL\=3 --> dove\="13". Sul bus locale\: dove\="13\#4\#01"
thing-type.config.openwebnet.bus_dry_contact_ir.where.label = Indirizzo OpenWebNet (where)
thing-type.config.openwebnet.bus_dry_contact_ir.where.description = Un "3" deve essere aggiunto prima dell'indirizzo. Automazione a secco Contatti 3N con N\=[1-201]; esempio N\=60 --> dove\="360". Contatti asciutti di allarme e sensori IR 3ZN con Zona Z\=[1-9], N\=[1-9]; esempio Z\=4, N\=5 --> dove\="345"
+thing-type.config.openwebnet.bus_energy_meter.energyRefreshPeriod.label = Periodo Aggiornamento Totalizzatori Energia
+thing-type.config.openwebnet.bus_energy_meter.energyRefreshPeriod.description = Imposta il numero di minuti tra gli aggiornamenti per i totalizzatori di energia (predefinito\: 30 minuti)
thing-type.config.openwebnet.bus_energy_meter.where.label = Indirizzo OpenWebNet (where)
thing-type.config.openwebnet.bus_energy_meter.where.description = Un "5" deve essere aggiunto prima dell'indirizzo del contatore di energia\: 5N con N\=[1-255]. Esempio di misuratore di energia "42" --> dove\="542"
thing-type.config.openwebnet.bus_gateway.dateTimeSynch.label = Sincronizzazione Data Ora
@@ -185,6 +187,10 @@ channel-type.openwebnet.conditioningValves.state.option.OFF_SPEED_2 = Spento vel
channel-type.openwebnet.conditioningValves.state.option.OFF_SPEED_3 = Spento velocità 3
channel-type.openwebnet.dryContactIR.label = Sensore
channel-type.openwebnet.dryContactIR.description = Interfaccia per sensore a contatto pulito o interfaccia per sensore di movimento infrarosso (sola lettura)
+channel-type.openwebnet.energyThisMonth.label = Energia Questo Mese
+channel-type.openwebnet.energyThisMonth.description = Energia totale misurata per questo mese
+channel-type.openwebnet.energyToday.label = Energia Oggi
+channel-type.openwebnet.energyToday.description = Energia totale misurata per oggi
channel-type.openwebnet.failureDiscovered.label = Guasto
channel-type.openwebnet.failureDiscovered.description = Guasto rilevato per la Centrale (sola lettura)
channel-type.openwebnet.function.label = Funzionamento
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENPlusScenarioControl.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENPlusScenarioControl.xml
index bcebc86de1501..420b38208a519 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENPlusScenarioControl.xml
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENPlusScenarioControl.xml
@@ -26,7 +26,7 @@
List (comma separated) of buttons numbers [0-31] configured for this scenario device, example:
- buttons=1,2,4
+ buttons="1,2,4"
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENScenarioControl.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENScenarioControl.xml
index 1c2d3274ee1d2..375baa1fd3c0c 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENScenarioControl.xml
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusCENScenarioControl.xml
@@ -27,7 +27,8 @@
List (comma separated) of buttons numbers [0-31] configured for this scenario device. Example:
- buttons=1,2,4
+ buttons="1,2,4"
+
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml
index 4dbc8bc787b19..c6aab79e93d89 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml
@@ -15,22 +15,29 @@
+
+ BTicino/LegrandBTI-F52x1830
+ 1ownId
-
A "5" must be added before the energy meter address: 5N with N=[1-255]. Example energy meter "42" -->
where="542"
+
+
+ Sets the number of minutes between refreshes for energy totalizers (default: 30 minutes)
+ 30
+
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml
index d502160cb8181..1d0fba1a1ad9d 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml
@@ -343,6 +343,22 @@
+
+ Number:Energy
+
+ Total energy measured for this month
+ Energy
+
+
+
+
+ Number:Energy
+
+ Total energy measured for today
+ Energy
+
+
+
trigger
diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml
index 900a8bd44c526..87a1a34d12d4c 100644
--- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml
+++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml
@@ -10,4 +10,14 @@
+
+
+
+ openwebnet:energyToday
+
+
+ openwebnet:energyThisMonth
+
+
+
diff --git a/bundles/org.openhab.binding.roku/src/main/java/org/openhab/binding/roku/internal/handler/RokuHandler.java b/bundles/org.openhab.binding.roku/src/main/java/org/openhab/binding/roku/internal/handler/RokuHandler.java
index bb886851704cc..ea9067a272a1a 100644
--- a/bundles/org.openhab.binding.roku/src/main/java/org/openhab/binding/roku/internal/handler/RokuHandler.java
+++ b/bundles/org.openhab.binding.roku/src/main/java/org/openhab/binding/roku/internal/handler/RokuHandler.java
@@ -205,6 +205,8 @@ private void refreshPlayerState() {
} else {
updateState(TIME_TOTAL, UnDefType.UNDEF);
}
+ } catch (NumberFormatException e) {
+ logger.debug("Unable to parse playerInfo integer value. Exception: {}", e.getMessage());
} catch (RokuHttpException e) {
logger.debug("Unable to retrieve Roku media-player info. Exception: {}", e.getMessage(), e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
diff --git a/bundles/org.openhab.binding.shelly/README.md b/bundles/org.openhab.binding.shelly/README.md
index f7daae283a2ab..d007aecebb813 100644
--- a/bundles/org.openhab.binding.shelly/README.md
+++ b/bundles/org.openhab.binding.shelly/README.md
@@ -29,6 +29,8 @@ The binding supports both hardware generations
- Generation 1: The original Shelly devices like the Shelly 1, Shelly 2.5, Shelly Flood etc.
- Generation 2: The new Plus / Pro series of devices
+- Shelly Plus Mini: Shelly Plus devices in compact format
+- Shelly BLU: Bluetooth based series of devices
The binding provides the same feature set across all devices as good as possible and depending on device specific features.
@@ -120,7 +122,7 @@ The binding provides the same feature set across all devices as good as possible
| ----------------- | ------------------------------------------------------ | --------- |
| shellyblubutton | Shelly BLU Button 1 | SBBT |
| shellybludw | Shelly BLU Door/Windows | SBDW |
-
+| shellyblumotion | Shelly BLU Motion | SBMO |
## Binding Configuration
@@ -1176,6 +1178,33 @@ Refer to [Smartify Roller Shutters with openHAB and Shelly](doc/UseCaseSmartRoll
| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
+### Shelly Plus Dimmer 10v (thing-type: shellyplus10v)
+
+| Group | Channel | Type | read-only | Description |
+| ----- | ------------ | -------- | --------- | --------------------------------------------------------------------------------- |
+| relay | brightness | Dimmer | r/w | Currently selected brightness. |
+| | outputName | String | yes | Logical name of this relay output as configured in the Shelly App |
+| | input1 | Switch | yes | ON: Input/Button for input 1 is powered, see general notes on channels |
+| | button1 | Trigger | yes | Event trigger, see section Button Events |
+| | lastEvent1 | String | yes | Last event type (S/SS/SSS/L) for input 1 |
+| | eventCount1 | Number | yes | Counter gets incremented every time the device issues a button event. |
+| | input2 | Switch | yes | ON: Input/Button for channel 2 is powered, see general notes on channels |
+| | button2 | Trigger | yes | Event trigger, see section Button Events |
+| | lastEvent2 | String | yes | Last event type (S/SS/SSS/L) for input 2 |
+| | eventCount2 | Number | yes | Counter gets incremented every time the device issues a button event. |
+| | autoOn | Number | r/w | Relay #1: Sets a timer to turn the device ON after every OFF command; in seconds |
+| | autoOff | Number | r/w | Relay #1: Sets a timer to turn the device OFF after every ON command; in seconds |
+| | timerActive | Switch | yes | Relay #1: ON: An auto-on/off timer is active |
+| meter | currentWatts | Number | yes | Current power consumption in Watts |
+| | lastPower1 | Number | yes | Energy consumption for a round minute, 1 minute ago |
+| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
+| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
+
+`Note: The Dimmer should be calibrated using the device Web UI or Shelly App.`
+
+Using the Thing configuration option `brightnessAutoOn` you could decide if the light is turned on when a brightness > 0 is set.
+`true`: Brightness will be set and device output is powered = light turns on with the new brightness
+`false`: Brightness will be set, but output stays unchanged so light will not be switched on when it's currently off.
### Shelly Plus i4, i4DC (thing-types: shellyplusi4, shellyplusi4dc)
@@ -1449,8 +1478,6 @@ See notes on discovery of Shelly BLU devices above.
| | lowBattery | Switch | yes | Low battery alert (< 20%) |
| device | gatewayDevice | String | yes | Shelly forwarded last status update (BLU gateway), could vary from packet to packet |
-
-
### Shelly BLU Door/Window Sensor (thing-type: shellybludw)
See notes on discovery of Shelly BLU devices above.
@@ -1465,6 +1492,17 @@ See notes on discovery of Shelly BLU devices above.
| | lowBattery | Switch | yes | Low battery alert (< 20%) |
| device | gatewayDevice | String | yes | Shelly forwarded last status update (BLU gateway), could vary from packet to packet |
+### Shelly BLU Motion Sensor (thing-type: shellyblumotion)
+
+See notes on discovery of Shelly BLU devices above.
+
+| Group | Channel | Type | read-only | Description |
+| ------- | ------------- | -------- | --------- | ----------------------------------------------------------------------------------- |
+| sensors | motion | Switch | yes | ON: Motion detected |
+| battery | batteryLevel | Number | yes | Battery Level in % |
+| | lowBattery | Switch | yes | Low battery alert (< 20%) |
+| device | gatewayDevice | String | yes | Shelly forwarded last status update (BLU gateway), could vary from packet to packet |
+
## Shelly Wall Displays
| Group | Channel | Type | read-only | Description |
diff --git a/bundles/org.openhab.binding.shelly/pom.xml b/bundles/org.openhab.binding.shelly/pom.xml
index 61c8dbf6cf88a..429dc71bd521d 100644
--- a/bundles/org.openhab.binding.shelly/pom.xml
+++ b/bundles/org.openhab.binding.shelly/pom.xml
@@ -14,13 +14,4 @@
org.openhab.binding.shellyopenHAB Add-ons :: Bundles :: Shelly Binding Gen1+2
-
-
- org.eclipse.jetty.websocket
- websocket-server
- 9.4.46.v20220331
- compile
-
-
-
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java
index e3300b7766b55..1a8732b0ac386 100755
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java
@@ -103,6 +103,7 @@ public class ShellyBindingConstants {
// Shelly BLU
THING_TYPE_SHELLYBLUBUTTON, //
THING_TYPE_SHELLYBLUDW, //
+ THING_TYPE_SHELLYBLUMOTION, //
THING_TYPE_SHELLYPROTECTED, //
THING_TYPE_SHELLYUNKNOWN);
@@ -119,6 +120,7 @@ public class ShellyBindingConstants {
public static final String PROPERTY_DEV_TYPE = "deviceType";
public static final String PROPERTY_DEV_MODE = "deviceMode";
public static final String PROPERTY_DEV_GEN = "deviceGeneration";
+ public static final String PROPERTY_DEV_AUTH = "deviceAuth";
public static final String PROPERTY_GW_DEVICE = "gatewayDevice";
public static final String PROPERTY_HWREV = "deviceHwRev";
public static final String PROPERTY_HWBATCH = "deviceHwBatch";
@@ -333,7 +335,7 @@ public class ShellyBindingConstants {
public static final int UPDATE_MIN_DELAY = 15;// update every x triggers or when a key was pressed
public static final int UPDATE_SETTINGS_INTERVAL_SECONDS = 60; // check for updates every x sec
public static final int HEALTH_CHECK_INTERVAL_SEC = 300; // Health check interval, 5min
- public static final int VIBRATION_FILTER_SEC = 5; // Absore duplicate vibration events for xx sec
+ public static final int VIBRATION_FILTER_SEC = 5; // Absorb duplicate vibration events for xx sec
public static final String BUNDLE_RESOURCE_SNIPLETS = "sniplets"; // where to find code sniplets in the bundle
public static final String BUNDLE_RESOURCE_SCRIPTS = "scripts"; // where to find scrips in the bundle
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyHandlerFactory.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyHandlerFactory.java
index f0cf33be8bb1d..111f60e4af099 100755
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyHandlerFactory.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyHandlerFactory.java
@@ -119,7 +119,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
ShellyBaseHandler handler = null;
if (thingType.equals(THING_TYPE_SHELLYPROTECTED_STR)) {
- logger.debug("{}: Create new thing of type {} using ShellyProtectedHandler", thing.getLabel(),
+ logger.debug("{}: Create new thing of type {} using ShellyProtectedHandler", thing.getLabel(),
thingTypeUID.toString());
handler = new ShellyProtectedHandler(thing, messages, bindingConfig, thingTable, coapServer, httpClient);
} else if (thingType.equals(THING_TYPE_SHELLYBULB_STR) || thingType.equals(THING_TYPE_SHELLYDUO_STR)
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiException.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiException.java
index 845219bf92c8b..6c6dc2a9588de 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiException.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiException.java
@@ -118,6 +118,10 @@ public boolean isConnectionError() {
|| exType == NoRouteToHostException.class;
}
+ public boolean isNoRouteToHost() {
+ return getCauseClass() == NoRouteToHostException.class;
+ }
+
public boolean isUnknownHost() {
return getCauseClass() == UnknownHostException.class;
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiInterface.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiInterface.java
index 8b7716007d83a..1f9443824e41a 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiInterface.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiInterface.java
@@ -15,6 +15,7 @@
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
@@ -42,7 +43,8 @@ public interface ShellyApiInterface {
ShellySettingsDevice getDeviceInfo() throws ShellyApiException;
- ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiException;
+ ShellyDeviceProfile getDeviceProfile(String thingType, @Nullable ShellySettingsDevice device)
+ throws ShellyApiException;
ShellySettingsStatus getStatus() throws ShellyApiException;
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java
index 7e8f335b2f4b0..e82314ae99109 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java
@@ -24,6 +24,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsGlobal;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsInput;
@@ -47,24 +48,21 @@
@NonNullByDefault
public class ShellyDeviceProfile {
private final Logger logger = LoggerFactory.getLogger(ShellyDeviceProfile.class);
- private static final Pattern VERSION_PATTERN = Pattern.compile("v\\d+\\.\\d+\\.\\d+(-[a-z0-9]*)?");
+ private static final Pattern GEN1_VERSION_PATTERN = Pattern.compile("v\\d+\\.\\d+\\.\\d+(-[a-z0-9]*)?");
+ private static final Pattern GEN2_VERSION_PATTERN = Pattern.compile("\\d+\\.\\d+\\.\\d+(-[a-fh-z0-9]*)?");
public boolean initialized = false; // true when initialized
public String thingName = "";
- public String deviceType = "";
public boolean extFeatures = false;
public String settingsJson = "";
+ public ShellySettingsDevice device = new ShellySettingsDevice();
public ShellySettingsGlobal settings = new ShellySettingsGlobal();
public ShellySettingsStatus status = new ShellySettingsStatus();
- public String hostname = "";
public String name = "";
- public String model = "";
- public String mode = "";
public boolean discoverable = true;
- public boolean auth = false;
public boolean alwaysOn = true;
public boolean isGen2 = false;
public boolean isBlu = false;
@@ -72,7 +70,6 @@ public class ShellyDeviceProfile {
public String hwRev = "";
public String hwBatchId = "";
- public String mac = "";
public String fwVersion = "";
public String fwDate = "";
@@ -118,10 +115,13 @@ public class ShellyDeviceProfile {
public ShellyDeviceProfile() {
}
- public ShellyDeviceProfile initialize(String thingType, String jsonIn) throws ShellyApiException {
+ public ShellyDeviceProfile initialize(String thingType, String jsonIn, @Nullable ShellySettingsDevice device)
+ throws ShellyApiException {
Gson gson = new Gson();
-
initialized = false;
+ if (device != null) {
+ this.device = device;
+ }
initFromThingType(thingType);
@@ -141,36 +141,37 @@ public ShellyDeviceProfile initialize(String thingType, String jsonIn) throws Sh
settings = fromJson(gson, json, ShellySettingsGlobal.class);
// General settings
+ if (getString(device.hostname).isEmpty() && !getString(device.mac).isEmpty()) {
+ device.hostname = device.mac.length() >= 12 ? "shelly-" + device.mac.toUpperCase().substring(6, 11)
+ : "unknown";
+ }
+ device.mode = getString(settings.mode).toLowerCase();
name = getString(settings.name);
- deviceType = getString(settings.device.type);
- mac = getString(settings.device.mac);
- hostname = !getString(settings.device.hostname).isEmpty() ? settings.device.hostname.toLowerCase()
- : mac.length() >= 12 ? "shelly-" + mac.toUpperCase().substring(6, 11) : "unknown";
- mode = getString(settings.mode).toLowerCase();
hwRev = settings.hwinfo != null ? getString(settings.hwinfo.hwRevision) : "";
hwBatchId = settings.hwinfo != null ? getString(settings.hwinfo.batchId.toString()) : "";
- fwDate = substringBefore(settings.fw, "/");
- fwVersion = extractFwVersion(settings.fw);
+ fwDate = substringBefore(device.fw, "-");
+ fwVersion = extractFwVersion(device.fw);
ShellyVersionDTO version = new ShellyVersionDTO();
extFeatures = version.compare(fwVersion, SHELLY_API_FW_110) >= 0;
discoverable = (settings.discoverable == null) || settings.discoverable;
+ String mode = getString(device.mode);
isRoller = mode.equalsIgnoreCase(SHELLY_MODE_ROLLER);
inColor = isLight && mode.equalsIgnoreCase(SHELLY_MODE_COLOR);
- numRelays = !isLight ? getInteger(settings.device.numOutputs) : 0;
+ numRelays = !isLight ? getInteger(device.numOutputs) : 0;
if ((numRelays > 0) && (settings.relays == null)) {
numRelays = 0;
}
hasRelays = (numRelays > 0) || isDimmer;
- numRollers = getInteger(settings.device.numRollers);
+ numRollers = getInteger(device.numRollers);
numInputs = settings.inputs != null ? settings.inputs.size() : hasRelays ? isRoller ? 2 : 1 : 0;
isEMeter = settings.emeters != null;
- numMeters = !isEMeter ? getInteger(settings.device.numMeters) : getInteger(settings.device.numEMeters);
+ numMeters = !isEMeter ? getInteger(device.numMeters) : getInteger(device.numEMeters);
if ((numMeters == 0) && isLight) {
// RGBW2 doesn't report, but has one
- numMeters = inColor ? 1 : getInteger(settings.device.numOutputs);
+ numMeters = inColor ? 1 : getInteger(device.numOutputs);
}
initialized = true;
@@ -196,10 +197,12 @@ public void initFromThingType(String name) {
return;
}
- isBlu = thingType.startsWith("shellyblu"); // e.g. SBBT for BU Button
+ isGen2 = isGeneration2(thingType);
+ isBlu = isBluSeries(thingType); // e.g. SBBT for BLU Button
- isDimmer = deviceType.equalsIgnoreCase(SHELLYDT_DIMMER) || deviceType.equalsIgnoreCase(SHELLYDT_DIMMER2)
- || deviceType.equalsIgnoreCase(SHELLYDT_PLUSDIMMERUS)
+ String type = getString(device.type);
+ isDimmer = type.equalsIgnoreCase(SHELLYDT_DIMMER) || type.equalsIgnoreCase(SHELLYDT_DIMMER2)
+ || type.equalsIgnoreCase(SHELLYDT_PLUSDIMMERUS)
|| thingType.equalsIgnoreCase(THING_TYPE_SHELLYPLUSDIMMERUS_STR);
isBulb = thingType.equals(THING_TYPE_SHELLYBULB_STR);
isDuo = thingType.equals(THING_TYPE_SHELLYDUO_STR) || thingType.equals(THING_TYPE_SHELLYVINTAGE_STR)
@@ -218,7 +221,8 @@ public void initFromThingType(String name) {
isHT = thingType.equals(THING_TYPE_SHELLYHT_STR) || thingType.equals(THING_TYPE_SHELLYPLUSHT_STR);
isDW = thingType.equals(THING_TYPE_SHELLYDOORWIN_STR) || thingType.equals(THING_TYPE_SHELLYDOORWIN2_STR)
|| thingType.equals(THING_TYPE_SHELLYBLUDW_STR);
- isMotion = thingType.startsWith(THING_TYPE_SHELLYMOTION_STR);
+ isMotion = thingType.startsWith(THING_TYPE_SHELLYMOTION_STR)
+ || thingType.equals(THING_TYPE_SHELLYBLUMOTION_STR);
isSense = thingType.equals(THING_TYPE_SHELLYSENSE_STR);
isIX = thingType.equals(THING_TYPE_SHELLYIX3_STR) || thingType.equals(THING_TYPE_SHELLYPLUSI4_STR)
|| thingType.equals(THING_TYPE_SHELLYPLUSI4DC_STR);
@@ -389,7 +393,8 @@ public static String extractFwVersion(@Nullable String version) {
.replace("/v1.12-", "/v1.12.0");
// Extract version from string, e.g. 20210226-091047/v1.10.0-rc2-89-g623b41ec0-master
- Matcher matcher = VERSION_PATTERN.matcher(vers);
+ Matcher matcher = version.startsWith("v") ? GEN1_VERSION_PATTERN.matcher(vers)
+ : GEN2_VERSION_PATTERN.matcher(vers);
if (matcher.find()) {
return matcher.group(0);
}
@@ -397,6 +402,15 @@ public static String extractFwVersion(@Nullable String version) {
return "";
}
+ public static boolean isGeneration2(String thingType) {
+ return thingType.startsWith("shellyplus") || thingType.startsWith("shellypro")
+ || thingType.startsWith("shellymini") || isBluSeries(thingType);
+ }
+
+ public static boolean isBluSeries(String thingType) {
+ return thingType.startsWith("shellyblu");
+ }
+
public boolean coiotEnabled() {
if ((settings.coiot != null) && (settings.coiot.enabled != null)) {
return settings.coiot.enabled;
@@ -405,4 +419,18 @@ public boolean coiotEnabled() {
// If device is not yet intialized or the enabled property is missing we assume that CoIoT is enabled
return true;
}
+
+ public static String buildBluServiceName(String name, String mac) throws IllegalArgumentException {
+ String model = name.contains("-") ? substringBefore(name, "-") : name; // e.g. SBBT-02C or just SBDW
+ switch (model) {
+ case SHELLYDT_BLUBUTTON:
+ return (THING_TYPE_SHELLYBLUBUTTON_STR + "-" + mac).toLowerCase();
+ case SHELLYDT_BLUDW:
+ return (THING_TYPE_SHELLYBLUDW_STR + "-" + mac).toLowerCase();
+ case SHELLYDT_BLUMOTION:
+ return (THING_TYPE_SHELLYBLUMOTION_STR + "-" + mac).toLowerCase();
+ default:
+ throw new IllegalArgumentException("Unsupported BLU device model " + model);
+ }
+ }
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpClient.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpClient.java
index e82dc8bee2358..41fb0181342eb 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpClient.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpClient.java
@@ -69,6 +69,7 @@ public class ShellyHttpClient {
protected int timeoutErrors = 0;
protected int timeoutsRecovered = 0;
private ShellyDeviceProfile profile;
+ protected boolean basicAuth = false;
public ShellyHttpClient(String thingName, ShellyThingInterface thing) {
this(thingName, thing.getThingConfig(), thing.getHttpClient());
@@ -83,9 +84,6 @@ public ShellyHttpClient(String thingName, ShellyThingConfiguration config, HttpC
this.httpClient.setConnectTimeout(SHELLY_API_TIMEOUT_MS);
}
- public void initialize() throws ShellyApiException {
- }
-
public void setConfig(String thingName, ShellyThingConfiguration config) {
this.thingName = thingName;
this.config = config;
@@ -113,6 +111,8 @@ protected String httpRequest(String uri) throws ShellyApiException {
while (retries > 0) {
try {
apiResult = innerRequest(HttpMethod.GET, uri, null, "");
+
+ // If call doesn't throw an exception the device is reachable == no timeout
if (timeout) {
logger.debug("{}: API timeout #{}/{} recovered ({})", thingName, timeoutErrors, timeoutsRecovered,
apiResult.getUrl());
@@ -120,6 +120,12 @@ protected String httpRequest(String uri) throws ShellyApiException {
}
return apiResult.response; // successful
} catch (ShellyApiException e) {
+ if (e.isHttpAccessUnauthorized() && !profile.isGen2 && !basicAuth && !config.password.isEmpty()) {
+ logger.debug("{}: Access is unauthorized, auto-activate basic auth", thingName);
+ basicAuth = true;
+ apiResult = innerRequest(HttpMethod.GET, uri, null, "");
+ }
+
if (e.isConnectionError()
|| (!e.isTimeout() && !apiResult.isHttpServerError()) && !apiResult.isNotFound()
|| profile.hasBattery || (retries == 0)) {
@@ -128,9 +134,11 @@ protected String httpRequest(String uri) throws ShellyApiException {
}
timeout = true;
- retries--;
timeoutErrors++; // count the retries
- logger.debug("{}: API Timeout, retry #{} ({})", thingName, timeoutErrors, e.toString());
+ retries--;
+ if (profile.alwaysOn) {
+ logger.debug("{}: API Timeout, retry #{} ({})", thingName, timeoutErrors, e.toString());
+ }
}
}
throw new ShellyApiException("API Timeout or inconsistent result"); // successful
@@ -164,7 +172,7 @@ private ShellyApiResult innerRequest(HttpMethod method, String uri, @Nullable Sh
authHeader = formatAuthResponse(uri,
buildAuthResponse(uri, auth, SHELLY2_AUTHDEF_USER, config.password));
} else {
- if (!uri.equals(SHELLYRPC_ENDPOINT)) {
+ if (basicAuth) {
String bearer = config.userId + ":" + config.password;
authHeader = HTTP_AUTH_TYPE_BASIC + " " + Base64.getEncoder().encodeToString(bearer.getBytes());
}
@@ -174,7 +182,7 @@ private ShellyApiResult innerRequest(HttpMethod method, String uri, @Nullable Sh
}
}
fillPostData(request, data);
- logger.trace("{}: HTTP {} for {} {}\n{}", thingName, method, url, data, request.getHeaders());
+ logger.trace("{}: HTTP {} {}\n{}\n{}", thingName, method, url, request.getHeaders(), data);
// Do request and get response
ContentResponse contentResponse = request.send();
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java
index c5304fe4e1ce1..d836e728f2c4d 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java
@@ -261,6 +261,10 @@ public class Shelly1ApiJsonDTO {
public static class ShellySettingsDevice {
public String type;
+ public String mode; // Gen 1
+ public String id; // Gen2: service name
+ public String name; // Gen2: configured device name
+ public String profile; // Gen 2
public String mac;
public String hostname;
public String fw;
@@ -563,7 +567,6 @@ public static class ShellySettingsUpdate {
public static class ShellySettingsGlobal {
// https://shelly-api-docs.shelly.cloud/#shelly1pm-settings
- public ShellySettingsDevice device = new ShellySettingsDevice();
@SerializedName("wifi_ap")
public ShellySettingsWiFiAp wifiAp = new ShellySettingsWiFiAp();
@SerializedName("wifi_sta")
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java
index 24f2b7147b2c0..5a599811f6416 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java
@@ -126,6 +126,9 @@ public boolean handleStatusUpdate(List sensorUpdates, CoIotDescrSen
thingHandler.requestUpdates(1, false);
}
break;
+ case "3122": // boost mode, Type=S, Range=0/1
+ updateChannel(updates, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_BCONTROL, getOnOff(value > 0));
+ break;
default:
processed = false;
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java
index b3b88d71f1bff..48eab5fb5c913 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java
@@ -49,6 +49,7 @@
import org.openhab.binding.shelly.internal.handler.ShellyColorUtils;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.openhab.core.library.unit.Units;
+import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -182,10 +183,10 @@ public void processResponse(@Nullable Response response) {
for (Option opt : options) {
if (opt.getNumber() == COIOT_OPTION_GLOBAL_DEVID) {
String devid = opt.getStringValue();
- if (devid.contains("#")) {
+ if (devid.contains("#") && profile.device.mac != null) {
// Format: ##
String macid = substringBetween(devid, "#", "#");
- if (profile.mac.toUpperCase().contains(macid.toUpperCase())) {
+ if (getString(profile.device.mac).toUpperCase().contains(macid.toUpperCase())) {
match = true;
break;
}
@@ -241,7 +242,7 @@ public void processResponse(@Nullable Response response) {
}
if (!coiotBound) {
thingHandler.updateProperties(PROPERTY_COAP_VERSION, sVersion);
- logger.debug("{}: CoIoT Version {} detected", thingName, iVersion);
+ logger.debug("{}: CoIoT Version {} detected", thingName, iVersion);
if (iVersion == COIOT_VERSION_1) {
coiot = new Shelly1CoIoTVersion1(thingName, thingHandler, blkMap, sensorMap);
} else if (iVersion == COIOT_VERSION_2) {
@@ -265,6 +266,13 @@ public void processResponse(@Nullable Response response) {
}
}
+ // Don't change state to online when thing is in status config error
+ // (e.g. auth failed, but device sends COAP packets via multicast)
+ if (thingHandler.getThingStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR) {
+ logger.debug("{}: The device is not configuired correctly, skip Coap packet", thingName);
+ return;
+ }
+
// If we received a CoAP message successful the thing must be online
thingHandler.setThingOnline();
@@ -441,7 +449,7 @@ private void handleStatusUpdate(String devId, String payload, int serial) throws
List sensorUpdates = list.generic;
Map updates = new TreeMap();
- logger.debug("{}: {} CoAP sensor updates received", thingName, sensorUpdates.size());
+ logger.debug("{}: {} CoAP sensor updates received", thingName, sensorUpdates.size());
int failed = 0;
ShellyColorUtils col = new ShellyColorUtils();
for (int i = 0; i < sensorUpdates.size(); i++) {
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java
index 97d83ad7eea73..330b2be360618 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java
@@ -20,20 +20,12 @@
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.ExecutionException;
-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.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
-import org.openhab.binding.shelly.internal.api.ShellyApiResult;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpClient;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
@@ -88,10 +80,26 @@ public Shelly1HttpApi(String thingName, ShellyThingConfiguration config, HttpCli
this.profile = new ShellyDeviceProfile();
}
+ @Override
+ public void initialize() throws ShellyApiException {
+ profile.device = getDeviceInfo();
+ }
+
@Override
public ShellySettingsDevice getDeviceInfo() throws ShellyApiException {
ShellySettingsDevice info = callApi(SHELLY_URL_DEVINFO, ShellySettingsDevice.class);
info.gen = 1;
+ basicAuth = getBool(info.auth);
+
+ if (getString(info.mode).isEmpty()) { // older Gen1 Firmware
+ if (getInteger(info.numRollers) > 0) {
+ info.mode = SHELLY_CLASS_ROLLER;
+ } else if (getInteger(info.numOutputs) > 0) {
+ info.mode = SHELLY_CLASS_RELAY;
+ } else {
+ info.mode = "";
+ }
+ }
return info;
}
@@ -113,7 +121,14 @@ public String getDebugLog(String id) throws ShellyApiException {
* @throws ShellyApiException
*/
@Override
- public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiException {
+ public ShellyDeviceProfile getDeviceProfile(String thingType, @Nullable ShellySettingsDevice device)
+ throws ShellyApiException {
+ if (device != null) {
+ profile.device = device;
+ }
+ if (profile.device.type == null) {
+ profile.device = getDeviceInfo();
+ }
String json = httpRequest(SHELLY_URL_SETTINGS);
if (json.contains("\"type\":\"SHDM-")) {
logger.trace("{}: Detected a Shelly Dimmer: fix Json (replace lights[] tag with dimmers[]", thingName);
@@ -121,10 +136,10 @@ public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiEx
}
// Map settings to device profile for Light and Sense
- profile.initialize(thingType, json);
+ profile.initialize(thingType, json, profile.device);
// 2nd level initialization
- profile.thingName = profile.hostname;
+ profile.thingName = profile.device.hostname;
if (profile.isLight && (profile.numMeters == 0)) {
logger.debug("{}: Get number of meters from light status", thingName);
ShellyStatusLight status = getLightStatus();
@@ -258,7 +273,7 @@ public void setSleepTime(int value) throws ShellyApiException {
@Override
public void setValveTemperature(int valveId, int value) throws ShellyApiException {
- request("/thermostat/" + valveId + "?target_t_enabled=1&target_t=" + value);
+ httpRequest("/thermostat/" + valveId + "?target_t_enabled=1&target_t=" + value);
}
@Override
@@ -273,17 +288,17 @@ public void setValveMode(int valveId, boolean auto) throws ShellyApiException {
@Override
public void setValveProfile(int valveId, int value) throws ShellyApiException {
String uri = "/settings/thermostat/" + valveId + "?";
- request(uri + (value == 0 ? "schedule=0" : "schedule=1&schedule_profile=" + value));
+ httpRequest(uri + (value == 0 ? "schedule=0" : "schedule=1&schedule_profile=" + value));
}
@Override
public void setValvePosition(int valveId, double value) throws ShellyApiException {
- request("/thermostat/" + valveId + "?pos=" + value); // percentage to open the valve
+ httpRequest("/thermostat/" + valveId + "?pos=" + value); // percentage to open the valve
}
@Override
public void setValveBoostTime(int valveId, int value) throws ShellyApiException {
- request("/settings/thermostat/" + valveId + "?boost_minutes=" + value);
+ httpRequest("/settings/thermostat/" + valveId + "?boost_minutes=" + value);
}
@Override
@@ -405,10 +420,10 @@ public String setCloud(boolean enabled) throws ShellyApiException {
*/
@Override
public void setLightMode(String mode) throws ShellyApiException {
- if (!mode.isEmpty() && !profile.mode.equals(mode)) {
+ if (!mode.isEmpty() && !profile.device.mode.equals(mode)) {
setLightSetting(SHELLY_API_MODE, mode);
- profile.mode = mode;
- profile.inColor = profile.isLight && profile.mode.equalsIgnoreCase(SHELLY_MODE_COLOR);
+ profile.device.mode = mode;
+ profile.inColor = profile.isLight && mode.equalsIgnoreCase(SHELLY_MODE_COLOR);
}
}
@@ -641,86 +656,6 @@ private static String mkEventUrl(String eventType) {
return eventType + SHELLY_EVENTURL_SUFFIX;
}
- /**
- * Submit GET request and return response, check for invalid responses
- *
- * @param uri: URI (e.g. "/settings")
- */
- @Override
- public T callApi(String uri, Class classOfT) throws ShellyApiException {
- String json = request(uri);
- return fromJson(gson, json, classOfT);
- }
-
- private String request(String uri) throws ShellyApiException {
- ShellyApiResult apiResult = new ShellyApiResult();
- int retries = 3;
- boolean timeout = false;
- while (retries > 0) {
- try {
- apiResult = innerRequest(HttpMethod.GET, uri);
- if (timeout) {
- logger.debug("{}: API timeout #{}/{} recovered ({})", thingName, timeoutErrors, timeoutsRecovered,
- apiResult.getUrl());
- timeoutsRecovered++;
- }
- return apiResult.response; // successful
- } catch (ShellyApiException e) {
- if ((!e.isTimeout() && !apiResult.isHttpServerError()) || profile.hasBattery || (retries == 0)) {
- // Sensor in sleep mode or API exception for non-battery device or retry counter expired
- throw e; // non-timeout exception
- }
-
- timeout = true;
- retries--;
- timeoutErrors++; // count the retries
- logger.debug("{}: API Timeout, retry #{} ({})", thingName, timeoutErrors, e.toString());
- }
- }
- throw new ShellyApiException("API Timeout or inconsistent result"); // successful
- }
-
- private ShellyApiResult innerRequest(HttpMethod method, String uri) throws ShellyApiException {
- Request request = null;
- String url = "http://" + config.deviceIp + uri;
- ShellyApiResult apiResult = new ShellyApiResult(method.toString(), url);
-
- try {
- request = httpClient.newRequest(url).method(method.toString()).timeout(SHELLY_API_TIMEOUT_MS,
- TimeUnit.MILLISECONDS);
-
- if (!config.userId.isEmpty()) {
- String value = config.userId + ":" + config.password;
- request.header(HTTP_HEADER_AUTH,
- HTTP_AUTH_TYPE_BASIC + " " + Base64.getEncoder().encodeToString(value.getBytes()));
- }
- request.header(HttpHeader.ACCEPT, CONTENT_TYPE_JSON);
- logger.trace("{}: HTTP {} for {}", thingName, method, url);
-
- // Do request and get response
- ContentResponse contentResponse = request.send();
- apiResult = new ShellyApiResult(contentResponse);
- String response = contentResponse.getContentAsString().replace("\t", "").replace("\r\n", "").trim();
- logger.trace("{}: HTTP Response {}: {}", thingName, contentResponse.getStatus(), response);
-
- // validate response, API errors are reported as Json
- if (contentResponse.getStatus() != HttpStatus.OK_200) {
- throw new ShellyApiException(apiResult);
- }
- if (response.isEmpty() || !response.startsWith("{") && !response.startsWith("[") && !url.contains("/debug/")
- && !url.contains("/sta_cache_reset")) {
- throw new ShellyApiException("Unexpected response: " + response);
- }
- } catch (ExecutionException | InterruptedException | TimeoutException | IllegalArgumentException e) {
- ShellyApiException ex = new ShellyApiException(apiResult, e);
- if (!ex.isTimeout()) { // will be handled by the caller
- logger.trace("{}: API call returned exception", thingName, ex);
- }
- throw ex;
- }
- return apiResult;
- }
-
@Override
public String getControlUriPrefix(Integer id) {
String uri = "";
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java
index a8c771fe67ff6..0e687307b74d8 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java
@@ -18,7 +18,6 @@
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@@ -102,52 +101,46 @@ public Shelly2ApiClient(String thingName, ShellyThingConfiguration config, HttpC
super(thingName, config, httpClient);
}
- protected static final Map MAP_INMODE_BTNTYPE = new HashMap<>();
- static {
- MAP_INMODE_BTNTYPE.put(SHELLY2_BTNT_MOMENTARY, SHELLY_BTNT_MOMENTARY);
- MAP_INMODE_BTNTYPE.put(SHELLY2_BTNT_FLIP, SHELLY_BTNT_TOGGLE);
- MAP_INMODE_BTNTYPE.put(SHELLY2_BTNT_FOLLOW, SHELLY_BTNT_EDGE);
- MAP_INMODE_BTNTYPE.put(SHELLY2_BTNT_DETACHED, SHELLY_BTNT_MOMENTARY);
- }
-
- protected static final Map MAP_INPUT_EVENT_TYPE = new HashMap<>();
- static {
- MAP_INPUT_EVENT_TYPE.put(SHELLY2_EVENT_1PUSH, SHELLY_BTNEVENT_1SHORTPUSH);
- MAP_INPUT_EVENT_TYPE.put(SHELLY2_EVENT_2PUSH, SHELLY_BTNEVENT_2SHORTPUSH);
- MAP_INPUT_EVENT_TYPE.put(SHELLY2_EVENT_3PUSH, SHELLY_BTNEVENT_3SHORTPUSH);
- MAP_INPUT_EVENT_TYPE.put(SHELLY2_EVENT_LPUSH, SHELLY_BTNEVENT_LONGPUSH);
- MAP_INPUT_EVENT_TYPE.put(SHELLY2_EVENT_LSPUSH, SHELLY_BTNEVENT_LONGSHORTPUSH);
- MAP_INPUT_EVENT_TYPE.put(SHELLY2_EVENT_SLPUSH, SHELLY_BTNEVENT_SHORTLONGPUSH);
- }
-
- protected static final Map MAP_INPUT_EVENT_ID = new HashMap<>();
- static {
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_BTNUP, SHELLY_EVENT_BTN_OFF);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_BTNDOWN, SHELLY_EVENT_BTN_ON);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_1PUSH, SHELLY_EVENT_SHORTPUSH);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_2PUSH, SHELLY_EVENT_DOUBLE_SHORTPUSH);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_3PUSH, SHELLY_EVENT_TRIPLE_SHORTPUSH);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_LPUSH, SHELLY_EVENT_LONGPUSH);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_LSPUSH, SHELLY_EVENT_LONG_SHORTPUSH);
- MAP_INPUT_EVENT_ID.put(SHELLY2_EVENT_SLPUSH, SHELLY_EVENT_SHORT_LONGTPUSH);
- }
-
- protected static final Map MAP_INPUT_MODE = new HashMap<>();
- static {
- MAP_INPUT_MODE.put(SHELLY2_RMODE_SINGLE, SHELLY_INP_MODE_ONEBUTTON);
- MAP_INPUT_MODE.put(SHELLY2_RMODE_DUAL, SHELLY_INP_MODE_OPENCLOSE);
- MAP_INPUT_MODE.put(SHELLY2_RMODE_DETACHED, SHELLY_INP_MODE_ONEBUTTON);
- }
-
- protected static final Map MAP_ROLLER_STATE = new HashMap<>();
- static {
- MAP_ROLLER_STATE.put(SHELLY2_RSTATE_OPEN, SHELLY_RSTATE_OPEN);
- MAP_ROLLER_STATE.put(SHELLY2_RSTATE_CLOSED, SHELLY_RSTATE_CLOSE);
- MAP_ROLLER_STATE.put(SHELLY2_RSTATE_OPENING, SHELLY2_RSTATE_OPENING); // Gen2-only
- MAP_ROLLER_STATE.put(SHELLY2_RSTATE_CLOSING, SHELLY2_RSTATE_CLOSING); // Gen2-only
- MAP_ROLLER_STATE.put(SHELLY2_RSTATE_STOPPED, SHELLY_RSTATE_STOP);
- MAP_ROLLER_STATE.put(SHELLY2_RSTATE_CALIB, SHELLY2_RSTATE_CALIB); // Gen2-only
- }
+ protected static final Map MAP_INMODE_BTNTYPE = Map.of(//
+ SHELLY2_BTNT_MOMENTARY, SHELLY_BTNT_MOMENTARY, //
+ SHELLY2_BTNT_FLIP, SHELLY_BTNT_TOGGLE, //
+ SHELLY2_BTNT_FOLLOW, SHELLY_BTNT_EDGE, //
+ SHELLY2_BTNT_DETACHED, SHELLY_BTNT_MOMENTARY);
+
+ protected static final Map MAP_INPUT_EVENT_TYPE = Map.of(//
+ SHELLY2_EVENT_1PUSH, SHELLY_BTNEVENT_1SHORTPUSH, //
+ SHELLY2_EVENT_2PUSH, SHELLY_BTNEVENT_2SHORTPUSH, //
+ SHELLY2_EVENT_3PUSH, SHELLY_BTNEVENT_3SHORTPUSH, //
+ SHELLY2_EVENT_LPUSH, SHELLY_BTNEVENT_LONGPUSH, //
+ SHELLY2_EVENT_LSPUSH, SHELLY_BTNEVENT_LONGSHORTPUSH, //
+ SHELLY2_EVENT_SLPUSH, SHELLY_BTNEVENT_SHORTLONGPUSH);
+
+ protected static final Map MAP_INPUT_EVENT_ID = Map.of(//
+ SHELLY2_EVENT_BTNUP, SHELLY_EVENT_BTN_OFF, //
+ SHELLY2_EVENT_BTNDOWN, SHELLY_EVENT_BTN_ON, //
+ SHELLY2_EVENT_1PUSH, SHELLY_EVENT_SHORTPUSH, //
+ SHELLY2_EVENT_2PUSH, SHELLY_EVENT_DOUBLE_SHORTPUSH, //
+ SHELLY2_EVENT_3PUSH, SHELLY_EVENT_TRIPLE_SHORTPUSH, //
+ SHELLY2_EVENT_LPUSH, SHELLY_EVENT_LONGPUSH, //
+ SHELLY2_EVENT_LSPUSH, SHELLY_EVENT_LONG_SHORTPUSH, //
+ SHELLY2_EVENT_SLPUSH, SHELLY_EVENT_SHORT_LONGTPUSH);
+
+ protected static final Map MAP_INPUT_MODE = Map.of(//
+ SHELLY2_RMODE_SINGLE, SHELLY_INP_MODE_ONEBUTTON, //
+ SHELLY2_RMODE_DUAL, SHELLY_INP_MODE_OPENCLOSE, //
+ SHELLY2_RMODE_DETACHED, SHELLY_INP_MODE_ONEBUTTON);
+
+ protected static final Map MAP_ROLLER_STATE = Map.of(//
+ SHELLY2_RSTATE_OPEN, SHELLY_RSTATE_OPEN, //
+ SHELLY2_RSTATE_CLOSED, SHELLY_RSTATE_CLOSE, //
+ SHELLY2_RSTATE_OPENING, SHELLY2_RSTATE_OPENING, // Gen2-only
+ SHELLY2_RSTATE_CLOSING, SHELLY2_RSTATE_CLOSING, // Gen2-only
+ SHELLY2_RSTATE_STOPPED, SHELLY_RSTATE_STOP, //
+ SHELLY2_RSTATE_CALIB, SHELLY2_RSTATE_CALIB); // Gen2-only
+
+ protected static final Map MAP_PROFILE = Map.of(//
+ SHELLY_CLASS_RELAY, SHELLY2_PROFILE_RELAY, //
+ SHELLY_CLASS_ROLLER, SHELLY2_PROFILE_COVER);
protected @Nullable ArrayList<@Nullable ShellySettingsRelay> fillRelaySettings(ShellyDeviceProfile profile,
Shelly2GetConfigResult dc) {
@@ -514,7 +507,7 @@ private boolean updateRollerStatus(ShellySettingsStatus status, @Nullable Shelly
rs.isValid = sm.isValid = emeter.isValid = true;
if (cs.state != null) {
if (!getString(rs.state).equals(cs.state)) {
- logger.debug("{}: Roller status changed from {} to {}, updateChannels={}", thingName, rs.state,
+ logger.debug("{}: Roller status changed from {} to {}, updateChannels={}", thingName, rs.state,
mapValue(MAP_ROLLER_STATE, cs.state), updateChannels);
}
rs.state = mapValue(MAP_ROLLER_STATE, cs.state);
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java
index 672f9e3b8cc96..664eb42807fc0 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java
@@ -82,7 +82,7 @@ public class Shelly2ApiJsonDTO {
// Component types
public static final String SHELLY2_PROFILE_RELAY = "switch";
- public static final String SHELLY2_PROFILE_ROLLER = "cover";
+ public static final String SHELLY2_PROFILE_COVER = "cover";
// Button types/modes
public static final String SHELLY2_BTNT_MOMENTARY = "momentary";
@@ -183,13 +183,14 @@ public static class Shelly2DeviceSettings {
public String id;
public String mac;
public String model;
+ public String profile;
public Integer gen;
@SerializedName("fw_id")
- public String firmware;
+ public String fw;
public String ver;
public String app;
@SerializedName("auth_en")
- public Boolean authEnable;
+ public Boolean auth;
@SerializedName("auth_domain")
public String authDomain;
}
@@ -1084,6 +1085,10 @@ public class Shelly2NotifyEventMessage {
public Integer windowState;
@SerializedName("Rotation")
public Double rotation;
+ @SerializedName("Motion")
+ public Integer motionState;
+ @SerializedName("Temperature")
+ public Double temperature;
public Integer rssi;
public Integer tx_power;
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java
index c1a9b67f84878..c37a9c854c28b 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java
@@ -113,11 +113,6 @@ public Shelly2ApiRpc(String thingName, ShellyThingTable thingTable, ShellyThingI
this.thingName = thingName;
this.thing = thing;
this.thingTable = thingTable;
- try {
- getProfile().initFromThingType(thing.getThingType());
- } catch (ShellyApiException e) {
- logger.info("{}: Shelly2 API initialization failed!", thingName, e);
- }
}
/**
@@ -136,14 +131,13 @@ public Shelly2ApiRpc(String thingName, ShellyThingConfiguration config, HttpClie
@Override
public void initialize() throws ShellyApiException {
- if (!initialized) {
- rpcSocket = new Shelly2RpcSocket(thingName, thingTable, config.deviceIp);
- rpcSocket.addMessageHandler(this);
- initialized = true;
- } else {
+ if (initialized) {
logger.debug("{}: Disconnect Rpc Socket on initialize", thingName);
disconnect();
}
+ rpcSocket = new Shelly2RpcSocket(thingName, thingTable, config.deviceIp);
+ rpcSocket.addMessageHandler(this);
+ initialized = true;
}
@Override
@@ -161,9 +155,17 @@ public void startScan() {
@SuppressWarnings("null")
@Override
- public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiException {
+ public ShellyDeviceProfile getDeviceProfile(String thingType, @Nullable ShellySettingsDevice devInfo)
+ throws ShellyApiException {
ShellyDeviceProfile profile = thing != null ? getProfile() : new ShellyDeviceProfile();
+ if (devInfo != null) {
+ profile.device = devInfo;
+ }
+ if (profile.device.type == null) {
+ profile.device = getDeviceInfo();
+ }
+
Shelly2GetConfigResult dc = apiRequest(SHELLYRPC_METHOD_GETCONFIG, null, Shelly2GetConfigResult.class);
profile.isGen2 = true;
profile.settingsJson = gson.toJson(dc);
@@ -195,29 +197,18 @@ public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiEx
profile.numRelays = profile.settings.relays != null ? profile.settings.relays.size() : 0;
profile.numRollers = profile.settings.rollers != null ? profile.settings.rollers.size() : 0;
profile.hasRelays = profile.numRelays > 0 || profile.numRollers > 0;
- profile.mode = "";
- if (profile.hasRelays) {
- profile.mode = profile.isRoller ? SHELLY_CLASS_ROLLER : SHELLY_CLASS_RELAY;
- }
-
- ShellySettingsDevice device = getDeviceInfo();
- profile.settings.device = device;
- if (!getString(device.fw).isEmpty()) {
- profile.fwDate = substringBefore(device.fw, "/");
- profile.fwVersion = profile.status.update.oldVersion = "v" + substringAfter(device.fw, "/");
+ if (getString(profile.device.mode).isEmpty() && profile.hasRelays) {
+ profile.device.mode = profile.isRoller ? SHELLY_CLASS_ROLLER : SHELLY_CLASS_RELAY;
}
- profile.hostname = device.hostname;
- profile.deviceType = device.type;
- profile.mac = device.mac;
- profile.auth = device.auth;
+ ShellySettingsDevice device = profile.device;
profile.isGen2 = device.gen == 2;
if (config.serviceName.isEmpty()) {
- config.serviceName = getString(profile.hostname);
+ config.serviceName = getString(profile.device.hostname);
}
- profile.fwDate = substringBefore(device.fw, "/");
- profile.fwVersion = substringBefore(ShellyDeviceProfile.extractFwVersion(device.fw.replace("/", "/v")), "-");
- profile.status.update.oldVersion = profile.fwVersion;
+ profile.settings.fw = device.fw;
+ profile.fwDate = substringBefore(substringBefore(device.fw, "/"), "-");
+ profile.fwVersion = profile.status.update.oldVersion = ShellyDeviceProfile.extractFwVersion(device.fw);
profile.status.hasUpdate = profile.status.update.hasUpdate = false;
if (dc.eth != null) {
@@ -319,14 +310,16 @@ public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiEx
asyncApiRequest(SHELLYRPC_METHOD_GETSTATUS); // request periodic status updates from device
try {
- if (config.enableBluGateway != null) {
+ if (profile.alwaysOn && config.enableBluGateway != null) {
logger.debug("{}: BLU Gateway support is {} for this device", thingName,
config.enableBluGateway ? "enabled" : "disabled");
- boolean bluetooth = getBool(profile.settings.bluetooth);
- if (config.enableBluGateway && !bluetooth) {
- logger.info("{}: Bluetooth needs to be enabled to activate BLU Gateway mode", thingName);
+ if (config.enableBluGateway) {
+ boolean bluetooth = getBool(profile.settings.bluetooth);
+ if (config.enableBluGateway && !bluetooth) {
+ logger.info("{}: Bluetooth needs to be enabled to activate BLU Gateway mode", thingName);
+ }
+ installScript(SHELLY2_BLU_GWSCRIPT, config.enableBluGateway && bluetooth);
}
- installScript(SHELLY2_BLU_GWSCRIPT, config.enableBluGateway && bluetooth);
}
} catch (ShellyApiException e) {
logger.debug("{}: Device config failed", thingName, e);
@@ -739,11 +732,13 @@ public ShellySettingsDevice getDeviceInfo() throws ShellyApiException {
Shelly2DeviceSettings device = callApi("/shelly", Shelly2DeviceSettings.class);
ShellySettingsDevice info = new ShellySettingsDevice();
info.hostname = getString(device.id);
- info.fw = getString(device.firmware);
+ info.name = getString(device.name);
+ info.fw = getString(device.fw);
info.type = getString(device.model);
info.mac = getString(device.mac);
- info.auth = getBool(device.authEnable);
+ info.auth = getBool(device.auth);
info.gen = getInteger(device.gen);
+ info.mode = mapValue(MAP_PROFILE, device.profile);
return info;
}
@@ -768,16 +763,16 @@ public ShellySettingsStatus getStatus() throws ShellyApiException {
profile.settings.sleepMode.period = ds.sys.wakeupPeriod / 60;
}
- status.hasUpdate = status.update.hasUpdate = false;
- status.update.oldVersion = getProfile().fwVersion;
if (ds.sys.availableUpdates != null) {
status.update.hasUpdate = ds.sys.availableUpdates.stable != null;
if (ds.sys.availableUpdates.stable != null) {
- status.update.newVersion = "v" + getString(ds.sys.availableUpdates.stable.version);
+ status.update.newVersion = ShellyDeviceProfile
+ .extractFwVersion(getString(ds.sys.availableUpdates.stable.version));
status.hasUpdate = new ShellyVersionDTO().compare(profile.fwVersion, status.update.newVersion) < 0;
}
if (ds.sys.availableUpdates.beta != null) {
- status.update.betaVersion = "v" + getString(ds.sys.availableUpdates.beta.version);
+ status.update.betaVersion = ShellyDeviceProfile
+ .extractFwVersion(getString(ds.sys.availableUpdates.beta.version));
status.hasUpdate = new ShellyVersionDTO().compare(profile.fwVersion, status.update.betaVersion) < 0;
}
}
@@ -1023,7 +1018,7 @@ public ShellySettingsUpdate firmwareUpdate(String fwurl) throws ShellyApiExcepti
Shelly2RpcRequestParams params = new Shelly2RpcRequestParams();
if (prod || beta) {
- params.stage = prod || beta ? "stable" : "beta";
+ params.stage = prod ? "stable" : "beta";
} else {
params.url = fwurl;
}
@@ -1215,6 +1210,9 @@ private void reconnect() throws ShellyApiException {
}
private void disconnect() {
+ if (rpcSocket.isConnected()) {
+ logger.debug("{}: Disconnect Rpc Socket", thingName);
+ }
rpcSocket.disconnect();
}
@@ -1224,8 +1222,10 @@ public Shelly2RpctInterface getRpcHandler() {
@Override
public void close() {
- logger.debug("{}: Closing Rpc API (socket is {}, discovery={})", thingName,
- rpcSocket.isConnected() ? "connected" : "disconnected", discovery);
+ if (initialized || rpcSocket.isConnected()) {
+ logger.debug("{}: Closing Rpc API (socket is {}, discovery={})", thingName,
+ rpcSocket.isConnected() ? "connected" : "disconnected", discovery);
+ }
disconnect();
initialized = false;
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java
index faff2738ee27e..308ab06ed67ce 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java
@@ -206,18 +206,24 @@ public void disconnect() {
if (s.isOpen()) {
logger.debug("{}: Disconnecting WebSocket ({} -> {})", thingName, s.getLocalAddress(),
s.getRemoteAddress());
- s.disconnect();
}
+ s.disconnect();
s.close(StatusCode.NORMAL, "Socket closed");
session = null;
}
- client.stop();
} catch (Exception e) {
if (e.getCause() instanceof InterruptedException) {
logger.debug("{}: Unable to close socket - interrupted", thingName); // e.g. device was rebooted
} else {
logger.debug("{}: Unable to close socket", thingName, e);
}
+ } finally {
+ // make sure client is stopped / thread terminates / socket resource is free up
+ try {
+ client.stop();
+ } catch (Exception e) {
+ logger.debug("{}: Unable to close Web Socket", thingName, e);
+ }
}
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java
index 533d4448e8940..5dbb81609aad5 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java
@@ -15,17 +15,18 @@
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.*;
-import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyInputState;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySensorSleepMode;
+import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySensorTmp;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsInput;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
@@ -110,18 +111,22 @@ public void setConfig(String thingName, ShellyThingConfiguration config) {
public ShellySettingsDevice getDeviceInfo() throws ShellyApiException {
ShellySettingsDevice info = new ShellySettingsDevice();
info.hostname = !config.serviceName.isEmpty() ? config.serviceName : "";
- info.fw = "1234";
- info.type = "SBBT";
+ info.fw = "";
+ info.type = "BLU";
info.mac = config.deviceAddress;
info.auth = false;
- info.gen = 99;
+ info.gen = 2;
return info;
}
@Override
- public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiException {
+ public ShellyDeviceProfile getDeviceProfile(String thingType, @Nullable ShellySettingsDevice devInfo)
+ throws ShellyApiException {
ShellyDeviceProfile profile = thing != null ? getProfile() : new ShellyDeviceProfile();
+ if (devInfo != null) {
+ profile.device = devInfo;
+ }
profile.isBlu = true;
profile.settingsJson = "{}";
profile.thingName = thingName;
@@ -130,18 +135,13 @@ public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiEx
profile.gateway = getThing().getProperty(PROPERTY_GW_DEVICE);
}
- ShellySettingsDevice device = getDeviceInfo();
- profile.settings.device = device;
- profile.hostname = device.hostname;
- profile.deviceType = device.type;
- profile.mac = device.mac;
- profile.auth = device.auth;
+ profile.device = getDeviceInfo();
if (config.serviceName.isEmpty()) {
- config.serviceName = getString(profile.hostname);
+ config.serviceName = getString(profile.device.hostname);
}
- profile.fwDate = substringBefore(device.fw, "/");
- profile.fwVersion = substringBefore(ShellyDeviceProfile.extractFwVersion(device.fw.replace("/", "/v")), "-");
- profile.status.update.oldVersion = profile.fwVersion;
+
+ // for now we have no API to get this information
+ profile.fwDate = profile.fwVersion = profile.status.update.oldVersion = "";
profile.status.hasUpdate = profile.status.update.hasUpdate = false;
if (profile.hasBattery) {
@@ -238,7 +238,7 @@ public void onNotifyEvent(Shelly2RpcNotifyEvent message) {
}
logger.debug("{}: BLU Device discovered", thingName);
if (e.data.name != null) {
- profile.settings.name = buildBluServiceName(e.data.name, e.data.addr);
+ profile.settings.name = ShellyDeviceProfile.buildBluServiceName(e.data.name, e.data.addr);
}
break;
case SHELLY2_EVENT_BLUDATA:
@@ -271,12 +271,22 @@ public void onNotifyEvent(Shelly2RpcNotifyEvent message) {
sensorData.lux.isValid = true;
sensorData.lux.value = (double) e.data.illuminance;
}
+ if (e.data.temperature != null) {
+ if (sensorData.tmp == null) {
+ sensorData.tmp = new ShellySensorTmp();
+ }
+ sensorData.tmp.tC = e.data.temperature;
+ sensorData.tmp.isValid = true;
+ }
if (e.data.rotation != null) {
if (sensorData.accel == null) {
sensorData.accel = new ShellySensorAccel();
}
sensorData.accel.tilt = e.data.rotation.intValue();
}
+ if (e.data.motionState != null) {
+ sensorData.motion = e.data.motionState == 1;
+ }
if (e.data.buttonEvent != null) {
ShellyInputState input = deviceStatus.inputs != null ? deviceStatus.inputs.get(0)
@@ -306,16 +316,4 @@ public void onNotifyEvent(Shelly2RpcNotifyEvent message) {
if (updated) {
}
}
-
- public static String buildBluServiceName(String name, String mac) throws IllegalArgumentException {
- String model = name.contains("-") ? substringBefore(name, "-") : name; // e.g. SBBT-02C or just SBDW
- switch (model) {
- case SHELLYDT_BLUBUTTON:
- return (THING_TYPE_SHELLYBLUBUTTON_STR + "-" + mac).toLowerCase();
- case SHELLYDT_BLUDW:
- return (THING_TYPE_SHELLYBLUDW_STR + "-" + mac).toLowerCase();
- default:
- throw new IllegalArgumentException("Unsupported BLU device model " + model);
- }
- }
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyDiscoveryParticipant.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyDiscoveryParticipant.java
index 863c2b99a8e40..db5da2e1e5e3f 100755
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyDiscoveryParticipant.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyDiscoveryParticipant.java
@@ -13,10 +13,11 @@
package org.openhab.binding.shelly.internal.discovery;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
-import static org.openhab.binding.shelly.internal.util.ShellyUtils.substringBeforeLast;
+import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import static org.openhab.core.thing.Thing.PROPERTY_MODEL_ID;
import java.io.IOException;
+import java.net.Inet4Address;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@@ -30,6 +31,7 @@
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyApiResult;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
+import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1HttpApi;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiRpc;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
@@ -117,9 +119,9 @@ public DiscoveryResult createResult(final ServiceInfo service) {
Map properties = new TreeMap<>();
name = service.getName().toLowerCase();
- String[] hostAddresses = service.getHostAddresses();
+ Inet4Address[] hostAddresses = service.getInet4Addresses();
if ((hostAddresses != null) && (hostAddresses.length > 0)) {
- address = hostAddresses[0];
+ address = substringAfter(hostAddresses[0].toString(), "/");
}
if (address.isEmpty()) {
logger.trace("{}: Shelly device discovered with empty IP address (service-name={})", name, service);
@@ -142,19 +144,27 @@ public DiscoveryResult createResult(final ServiceInfo service) {
config.password = bindingConfig.defaultPassword;
boolean gen2 = "2".equals(service.getPropertyString("gen"));
+ ShellyApiInterface api = null;
+ boolean auth = false;
+ ShellySettingsDevice devInfo;
try {
- ShellyApiInterface api = gen2 ? new Shelly2ApiRpc(name, config, httpClient)
- : new Shelly1HttpApi(name, config, httpClient);
+ api = gen2 ? new Shelly2ApiRpc(name, config, httpClient) : new Shelly1HttpApi(name, config, httpClient);
api.initialize();
- profile = api.getDeviceProfile(thingType);
+ devInfo = api.getDeviceInfo();
+ model = devInfo.type;
+ auth = devInfo.auth;
+ if (devInfo.name != null) {
+ deviceName = devInfo.name;
+ }
+
+ profile = api.getDeviceProfile(thingType, devInfo);
api.close();
logger.debug("{}: Shelly settings : {}", name, profile.settingsJson);
deviceName = profile.name;
- model = profile.deviceType;
- mode = profile.mode;
+ mode = devInfo.mode;
properties = ShellyBaseHandler.fillDeviceProperties(profile);
logger.trace("{}: thingType={}, deviceType={}, mode={}, symbolic name={}", name, thingType,
- profile.deviceType, mode.isEmpty() ? "" : mode, deviceName);
+ devInfo.type, mode.isEmpty() ? "" : mode, deviceName);
// get thing type from device name
thingUID = ShellyThingCreator.getThingUID(name, model, mode, false);
@@ -170,6 +180,10 @@ public DiscoveryResult createResult(final ServiceInfo service) {
}
} catch (IllegalArgumentException e) { // maybe some format description was buggy
logger.debug("{}: Discovery failed!", name, e);
+ } finally {
+ if (api != null) {
+ api.close();
+ }
}
if (thingUID != null) {
@@ -180,12 +194,13 @@ public DiscoveryResult createResult(final ServiceInfo service) {
addProperty(properties, PROPERTY_DEV_TYPE, thingType);
addProperty(properties, PROPERTY_DEV_GEN, gen2 ? "2" : "1");
addProperty(properties, PROPERTY_DEV_MODE, mode);
+ addProperty(properties, PROPERTY_DEV_AUTH, auth ? "yes" : "no");
logger.debug("{}: Adding Shelly {}, UID={}", name, deviceName, thingUID.getAsString());
String thingLabel = deviceName.isEmpty() ? name + " - " + address
: deviceName + " (" + name + "@" + address + ")";
return DiscoveryResultBuilder.create(thingUID).withProperties(properties).withLabel(thingLabel)
- .withRepresentationProperty(PROPERTY_DEV_NAME).build();
+ .withRepresentationProperty(PROPERTY_SERVICE_NAME).build();
}
} catch (IOException | NullPointerException e) {
// maybe some format description was buggy
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java
index 467c23c684f97..3804516327469 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java
@@ -80,6 +80,7 @@ public class ShellyThingCreator {
public static final String SHELLYDT_PLUSHT = "SNSN-0013A";
public static final String SHELLYDT_PLUSSMOKE = "SNSN-0031Z";
public static final String SHELLYDT_PLUSDIMMERUS = "SNDM-0013US";
+ public static final String SHELLYDT_PLUSDIMMER10V = "SNGW-0A11WW010";
public static final String SHELLYDT_PLUSWALLDISPLAY = "SAWD-0A1XX10EU1";
// Shelly Pro Series
@@ -113,6 +114,7 @@ public class ShellyThingCreator {
// Shelly BLU Series
public static final String SHELLYDT_BLUBUTTON = "SBBT";
public static final String SHELLYDT_BLUDW = "SBDW";
+ public static final String SHELLYDT_BLUMOTION = "SBMO";
// Thing names
public static final String THING_TYPE_SHELLY1_STR = "shelly1";
@@ -167,6 +169,7 @@ public class ShellyThingCreator {
public static final String THING_TYPE_SHELLYPLUSPLUGS_STR = "shellyplusplug";
public static final String THING_TYPE_SHELLYPLUSPLUGUS_STR = "shellyplusplugus";
public static final String THING_TYPE_SHELLYPLUSDIMMERUS_STR = "shellypluswdus";
+ public static final String THING_TYPE_SHELLYPLUSDIMMER10V_STR = "shellyplus10v";
// Shelly Wall Display
public static final String THING_TYPE_SHELLYPLUSWALLDISPLAY_STR = "shellywalldisplay";
@@ -191,6 +194,7 @@ public class ShellyThingCreator {
public static final String THING_TYPE_SHELLYBLU_PREFIX = "shellyblu";
public static final String THING_TYPE_SHELLYBLUBUTTON_STR = THING_TYPE_SHELLYBLU_PREFIX + "button";
public static final String THING_TYPE_SHELLYBLUDW_STR = THING_TYPE_SHELLYBLU_PREFIX + "dw";
+ public static final String THING_TYPE_SHELLYBLUMOTION_STR = THING_TYPE_SHELLYBLU_PREFIX + "motion";
// Password protected or unknown device
public static final String THING_TYPE_SHELLYPROTECTED_STR = "shellydevice";
@@ -274,6 +278,10 @@ public class ShellyThingCreator {
THING_TYPE_SHELLYPLUSPLUGUS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSDIMMERUS = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSDIMMERUS_STR);
+ public static final ThingTypeUID THING_TYPE_SHELLYPLUSDIMMER10V = new ThingTypeUID(BINDING_ID,
+ THING_TYPE_SHELLYPLUSDIMMER10V_STR);
+
+ // Shelly Wall Display
public static final ThingTypeUID THING_TYPE_SHELLYPLUSWALLDISPLAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSWALLDISPLAY_STR);
@@ -306,6 +314,8 @@ public class ShellyThingCreator {
public static final ThingTypeUID THING_TYPE_SHELLYBLUBUTTON = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYBLUBUTTON_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBLUDW = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYBLUDW_STR);
+ public static final ThingTypeUID THING_TYPE_SHELLYBLUMOTION = new ThingTypeUID(BINDING_ID,
+ THING_TYPE_SHELLYBLUMOTION_STR);
private static final Map THING_TYPE_MAPPING = new LinkedHashMap<>();
static {
@@ -352,6 +362,7 @@ public class ShellyThingCreator {
THING_TYPE_MAPPING.put(SHELLYDT_PLUSHT, THING_TYPE_SHELLYPLUSHT_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSSMOKE, THING_TYPE_SHELLYPLUSSMOKE_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSDIMMERUS, THING_TYPE_SHELLYPLUSDIMMERUS_STR);
+ THING_TYPE_MAPPING.put(SHELLYDT_PLUSDIMMER10V, THING_TYPE_SHELLYPLUSDIMMER10V_STR);
// Plus Mini Series
THING_TYPE_MAPPING.put(SHELLYDT_MINI1, THING_TYPE_SHELLYMINI1_STR);
@@ -383,6 +394,7 @@ public class ShellyThingCreator {
// BLU Series
THING_TYPE_MAPPING.put(SHELLYDT_BLUBUTTON, THING_TYPE_SHELLYBLUBUTTON_STR);
THING_TYPE_MAPPING.put(SHELLYDT_BLUDW, THING_TYPE_SHELLYBLUDW_STR);
+ THING_TYPE_MAPPING.put(SHELLYDT_BLUMOTION, THING_TYPE_SHELLYBLUMOTION_STR);
// Wall displays
THING_TYPE_MAPPING.put(SHELLYDT_PLUSWALLDISPLAY, THING_TYPE_SHELLYPLUSWALLDISPLAY_STR);
@@ -430,6 +442,8 @@ public class ShellyThingCreator {
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSHT_STR, THING_TYPE_SHELLYPLUSHT_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSSMOKE_STR, THING_TYPE_SHELLYPLUSSMOKE_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSDIMMERUS_STR, THING_TYPE_SHELLYPLUSDIMMERUS_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSDIMMER10V_STR, THING_TYPE_SHELLYPLUSDIMMER10V_STR);
+
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSWALLDISPLAY_STR, THING_TYPE_SHELLYPLUSWALLDISPLAY_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYMINI1_STR, THING_TYPE_SHELLYMINI1_STR);
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java
index 54cd538c1a64c..0daed7b48a0cd 100755
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java
@@ -150,11 +150,8 @@ public ShellyBaseHandler(final Thing thing, final ShellyTranslationProvider tran
Map properties = thing.getProperties();
String gen = getString(properties.get(PROPERTY_DEV_GEN));
String thingType = getThingType();
- if (gen.isEmpty() && thingType.startsWith("shellyplus") || thingType.startsWith("shellypro")) {
- gen = "2";
- }
- gen2 = "2".equals(gen);
- blu = thingType.startsWith("shellyblu");
+ gen2 = "2".equals(gen) || ShellyDeviceProfile.isGeneration2(thingType);
+ blu = ShellyDeviceProfile.isBluSeries(thingType);
this.api = !blu ? !gen2 ? new Shelly1HttpApi(thingName, this) : new Shelly2ApiRpc(thingName, thingTable, this)
: new ShellyBluApi(thingName, thingTable, this);
if (gen2) {
@@ -190,21 +187,7 @@ public void initialize() {
config.eventsSensorReport, config.eventsCoIoT, bindingConfig.autoCoIoT);
start = initializeThing();
} catch (ShellyApiException e) {
- ShellyApiResult res = e.getApiResult();
- String mid = "";
- if (e.isJsonError()) { // invalid JSON format
- mid = "offline.status-error-unexpected-error";
- start = false;
- } else if (isAuthorizationFailed(res)) {
- mid = "offline.conf-error-access-denied";
- start = false;
- } else if (profile.alwaysOn && e.isConnectionError()) {
- mid = "offline.status-error-connect";
- }
- if (!mid.isEmpty()) {
- setThingOffline(ThingStatusDetail.COMMUNICATION_ERROR, mid, e.toString());
- }
- logger.debug("{}: Unable to initialize: {}, retrying later", thingName, e.toString());
+ start = handleApiException(e);
} catch (IllegalArgumentException e) {
logger.debug("{}: Unable to initialize, retrying later", thingName, e);
} finally {
@@ -218,6 +201,43 @@ public void initialize() {
}, 2, TimeUnit.SECONDS);
}
+ private boolean handleApiException(ShellyApiException e) {
+ ShellyApiResult res = e.getApiResult();
+ ThingStatusDetail errorCode = ThingStatusDetail.COMMUNICATION_ERROR;
+ String status = "";
+ boolean retry = true;
+ if (e.isJsonError()) { // invalid JSON format
+ logger.debug("{}: Unable to parse API response: {}; json={}", thingName, res.getUrl(), res.response, e);
+ status = "offline.status-error-unexpected-error";
+ errorCode = ThingStatusDetail.CONFIGURATION_ERROR;
+ retry = false;
+ } else if (res.isHttpAccessUnauthorized()) {
+ status = "offline.conf-error-access-denied";
+ errorCode = ThingStatusDetail.CONFIGURATION_ERROR;
+ retry = false;
+ } else if (isWatchdogExpired()) {
+ status = "offline.status-error-watchdog";
+ } else if (res.httpCode >= 400) {
+ logger.debug("{}: Unexpected API result: {}/{}", thingName, res.httpCode, res.httpReason, e);
+ status = "offline.status-error-unexpected-api-result";
+ retry = false;
+ } else if (profile.alwaysOn && (e.isConnectionError() || res.isHttpTimeout())) {
+ status = "offline.status-error-connect";
+ }
+
+ if (!status.isEmpty()) {
+ setThingOffline(errorCode, status, e.toString());
+ } else {
+ logger.debug("{}: Unable to initialize: {}, retrying later", thingName, e.toString());
+ }
+
+ if (!retry) {
+ api.close();
+ }
+
+ return retry;
+ }
+
@Override
public ShellyThingConfiguration getThingConfig() {
return config;
@@ -276,45 +296,41 @@ public boolean initializeThing() throws ShellyApiException {
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_PENDING,
messages.get("status.unknown.initializing"));
- profile.initFromThingType(thingType); // do some basic initialization
-
// Gen 1 only: Setup CoAP listener to we get the CoAP message, which triggers initialization even the thing
// could not be fully initialized here. In this case the CoAP messages triggers auto-initialization (like the
// Action URL does when enabled)
+ profile.initFromThingType(thingType);
if (coap != null && config.eventsCoIoT && !profile.alwaysOn) {
coap.start(thingName, config);
}
// Initialize API access, exceptions will be catched by initialize()
api.initialize();
- ShellySettingsDevice devInfo = api.getDeviceInfo();
- if (getBool(devInfo.auth) && config.password.isEmpty()) {
+ ShellySettingsDevice device = profile.device = api.getDeviceInfo();
+ if (getBool(device.auth) && config.password.isEmpty()) {
setThingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "offline.conf-error-no-credentials");
return false;
}
if (config.serviceName.isEmpty()) {
- config.serviceName = getString(profile.hostname).toLowerCase();
+ config.serviceName = getString(device.hostname).toLowerCase();
}
api.setConfig(thingName, config);
- ShellyDeviceProfile tmpPrf = api.getDeviceProfile(thingType);
- tmpPrf.isGen2 = gen2;
- tmpPrf.auth = devInfo.auth; // missing in /settings
-
+ ShellyDeviceProfile tmpPrf = api.getDeviceProfile(thingType, profile.device);
+ String mode = getString(tmpPrf.device.mode);
if (this.getThing().getThingTypeUID().equals(THING_TYPE_SHELLYPROTECTED)) {
- changeThingType(thingName, tmpPrf.mode);
+ changeThingType(thingName, mode);
return false; // force re-initialization
}
// Validate device mode
String reqMode = thingType.contains("-") ? substringAfter(thingType, "-") : "";
- if (!reqMode.isEmpty() && !tmpPrf.mode.equals(reqMode)) {
- setThingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "offline.conf-error-wrong-mode", tmpPrf.mode,
- reqMode);
+ if (!reqMode.isEmpty() && !mode.equals(reqMode)) {
+ setThingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "offline.conf-error-wrong-mode", mode, reqMode);
return false;
}
- if (!getString(devInfo.coiot).isEmpty()) {
+ if (!getString(tmpPrf.device.coiot).isEmpty()) {
// New Shelly devices might use a different endpoint for the CoAP listener
- tmpPrf.coiotEndpoint = devInfo.coiot;
+ tmpPrf.coiotEndpoint = tmpPrf.device.coiot;
}
if (tmpPrf.settings.sleepMode != null && !tmpPrf.isTRV) {
// Sensor, usually 12h, H&T in USB mode 10min
@@ -471,10 +487,11 @@ public void handleCommand(ChannelUID channelUID, Command command) {
requestUpdates(1, false);
}
} catch (ShellyApiException e) {
- ShellyApiResult res = e.getApiResult();
- if (isAuthorizationFailed(res)) {
+ if (!handleApiException(e)) {
return;
}
+
+ ShellyApiResult res = e.getApiResult();
if (res.isNotCalibrtated()) {
logger.warn("{}: {}", thingName, messages.get("roller.calibrating"));
} else {
@@ -561,36 +578,7 @@ protected void refreshStatus() {
} catch (ShellyApiException e) {
// http call failed: go offline except for battery devices, which might be in
// sleep mode. Once the next update is successful the device goes back online
- String status = "";
- ShellyApiResult res = e.getApiResult();
- if (profile.alwaysOn && e.isConnectionError()) {
- status = "offline.status-error-connect";
- } else if (res.isHttpAccessUnauthorized()) {
- status = "offline.conf-error-access-denied";
- } else if (isWatchdogStarted()) {
- if (!isWatchdogExpired()) {
- logger.debug("{}: Ignore API Timeout on {} {}, retry later", thingName, res.method, res.url);
- } else {
- if (isThingOnline()) {
- status = "offline.status-error-watchdog";
- }
- }
- } else if (e.isJSONException()) {
- status = "offline.status-error-unexpected-api-result";
- logger.debug("{}: Unable to parse API response: {}; json={}", thingName, res.getUrl(), res.response, e);
- } else if (res.isHttpTimeout()) {
- // Watchdog not started, e.g. device in sleep mode
- if (isThingOnline()) { // ignore when already offline
- status = "offline.status-error-watchdog";
- }
- } else {
- status = "offline.status-error-unexpected-api-result";
- logger.debug("{}: Unexpected API result: {}", thingName, res.response, e);
- }
-
- if (!status.isEmpty()) {
- setThingOffline(ThingStatusDetail.COMMUNICATION_ERROR, status);
- }
+ handleApiException(e);
} catch (NullPointerException | IllegalArgumentException e) {
logger.debug("{}: Unable to refresh status: {}", thingName, messages.get("statusupdate.failed"), e);
} finally {
@@ -607,22 +595,18 @@ protected void refreshStatus() {
private void showThingConfig(ShellyDeviceProfile profile) {
logger.debug("{}: Initializing device {}, type {}, Hardware: Rev: {}, batch {}; Firmware: {} / {}", thingName,
- profile.hostname, profile.deviceType, profile.hwRev, profile.hwBatchId, profile.fwVersion,
+ profile.device.hostname, profile.device.type, profile.hwRev, profile.hwBatchId, profile.fwVersion,
profile.fwDate);
- logger.debug("{}: Shelly settings info for {}: {}", thingName, profile.hostname, profile.settingsJson);
- logger.debug(
- """
- {}: Device \
- hasRelays:{} (numRelays={}),isRoller:{} (numRoller={}),isDimmer:{},numMeter={},isEMeter:{}), ext. Switch Add-On: {}\
- ,isSensor:{},isDS:{},hasBattery:{}{},isSense:{},isMotion:{},isLight:{},isBulb:{},isDuo:{},isRGBW2:{},inColor:{}, BLU Gateway support: {}\
- ,alwaysOn:{}, updatePeriod:{}sec\
- """,
- thingName, profile.hasRelays, profile.numRelays, profile.isRoller, profile.numRollers, profile.isDimmer,
- profile.numMeters, profile.isEMeter, profile.settings.extSwitch != null ? "installed" : "n/a",
- profile.isSensor, profile.isDW, profile.hasBattery,
- profile.hasBattery ? " (low battery threshold=" + config.lowBattery + "%)" : "", profile.isSense,
- profile.isMotion, profile.isLight, profile.isBulb, profile.isDuo, profile.isRGBW2, profile.inColor,
- profile.alwaysOn, profile.updatePeriod, config.enableBluGateway);
+ logger.debug("{}: Shelly settings info for {}: {}", thingName, profile.device.hostname, profile.settingsJson);
+ logger.debug("{}: Device "
+ + "hasRelays:{} (numRelays={}),isRoller:{} (numRoller={}),isDimmer:{},numMeter={},isEMeter:{}), ext. Switch Add-On: {}"
+ + ",isSensor:{},isDS:{},hasBattery:{}{},isSense:{},isMotion:{},isLight:{},isBulb:{},isDuo:{},isRGBW2:{},inColor:{}, BLU Gateway support: {}"
+ + ",alwaysOn:{}, updatePeriod:{}sec", thingName, profile.hasRelays, profile.numRelays, profile.isRoller,
+ profile.numRollers, profile.isDimmer, profile.numMeters, profile.isEMeter,
+ profile.settings.extSwitch != null ? "installed" : "n/a", profile.isSensor, profile.isDW,
+ profile.hasBattery, profile.hasBattery ? " (low battery threshold=" + config.lowBattery + "%)" : "",
+ profile.isSense, profile.isMotion, profile.isLight, profile.isBulb, profile.isDuo, profile.isRGBW2,
+ profile.inColor, profile.alwaysOn, profile.updatePeriod, config.enableBluGateway);
if (profile.status.extTemperature != null || profile.status.extHumidity != null
|| profile.status.extVoltage != null || profile.status.extAnalogInput != null) {
logger.debug("{}: Shelly Add-On detected with at least 1 external sensor", thingName);
@@ -643,7 +627,7 @@ private void addStateOptions(ShellyDeviceProfile prf) {
}
if (prf.isRoller && prf.settings.favorites != null) {
String channelId = mkChannelId(CHANNEL_GROUP_ROL_CONTROL, CHANNEL_ROL_CONTROL_FAV);
- logger.debug("{}: Adding {} roler favorite(s) to channel description", thingName,
+ logger.debug("{}: Adding {} roler favorite(s) to channel description", thingName,
prf.settings.favorites.size());
channelDefinitions.clearStateOptions(channelId);
int fid = 1;
@@ -799,7 +783,7 @@ public void incProtErrors() {
private boolean checkRestarted(ShellySettingsStatus status) {
if (profile.isInitialized() && profile.alwaysOn /* exclude battery powered devices */
&& (status.uptime != null && status.uptime < stats.lastUptime
- || (!profile.status.update.oldVersion.isEmpty()
+ || (profile.status.update != null && !getString(profile.status.update.oldVersion).isEmpty()
&& !status.update.oldVersion.equals(profile.status.update.oldVersion)))) {
logger.debug("{}: Device has been restarted, uptime={}/{}, firmware={}/{}", thingName, stats.lastUptime,
getLong(status.uptime), profile.status.update.oldVersion, status.update.oldVersion);
@@ -1022,11 +1006,16 @@ protected void initializeThingConfig() {
config.serviceName = getString(properties.get(PROPERTY_SERVICE_NAME));
config.localIp = bindingConfig.localIP;
config.localPort = String.valueOf(bindingConfig.httpPort);
- if (config.userId.isEmpty() && !bindingConfig.defaultUserId.isEmpty()) {
+ if (!profile.isGen2 && config.userId.isEmpty() && !bindingConfig.defaultUserId.isEmpty()) {
+ // Gen2 has hard coded user "admin"
config.userId = bindingConfig.defaultUserId;
+ logger.debug("{}: Using default userId {} from binding config", thingName, config.userId);
+ }
+ if (config.password.isEmpty() && !bindingConfig.defaultPassword.isEmpty()) {
config.password = bindingConfig.defaultPassword;
- logger.debug("{}: Using userId {} from bindingConfig", thingName, config.userId);
+ logger.debug("{}: Using default password from bindingConfig (userId={})", thingName, config.userId);
}
+
if (config.updateInterval == 0) {
config.updateInterval = UPDATE_STATUS_INTERVAL_SECONDS * UPDATE_SKIP_COUNT;
}
@@ -1052,13 +1041,18 @@ protected void initializeThingConfig() {
private void checkVersion(ShellyDeviceProfile prf, ShellySettingsStatus status) {
try {
+ if (prf.fwVersion.isEmpty()) {
+ // no fw version available (e.g. BLU device)
+ return;
+ }
ShellyVersionDTO version = new ShellyVersionDTO();
if (version.checkBeta(getString(prf.fwVersion))) {
- logger.info("{}: {}", prf.hostname, messages.get("versioncheck.beta", prf.fwVersion, prf.fwDate));
+ logger.info("{}: {}", prf.device.hostname,
+ messages.get("versioncheck.beta", prf.fwVersion, prf.fwDate));
} else {
String minVersion = !gen2 ? SHELLY_API_MIN_FWVERSION : SHELLY2_API_MIN_FWVERSION;
if (version.compare(prf.fwVersion, minVersion) < 0) {
- logger.warn("{}: {}", prf.hostname,
+ logger.warn("{}: {}", prf.device.hostname,
messages.get("versioncheck.tooold", prf.fwVersion, prf.fwDate, minVersion));
}
}
@@ -1122,23 +1116,6 @@ public void startCoap(ShellyThingConfiguration config, ShellyDeviceProfile profi
}
}
- /**
- * Checks the http response for authorization error.
- * If the authorization failed the binding can't access the device settings and determine the thing type. In this
- * case the thing type shelly-unknown is set.
- *
- * @param result exception details including the http respone
- * @return true if the authorization failed
- */
- protected boolean isAuthorizationFailed(ShellyApiResult result) {
- if (result.isHttpAccessUnauthorized()) {
- // If the device is password protected the API doesn't provide settings to the device settings
- setThingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "offline.conf-error-access-denied");
- return true;
- }
- return false;
- }
-
/**
* Change type of this thing.
*
@@ -1365,11 +1342,11 @@ public void updateProperties(ShellyDeviceProfile profile, ShellySettingsStatus s
properties.put(PROPERTY_SERVICE_NAME, config.serviceName);
String deviceName = getString(profile.settings.name);
properties.put(PROPERTY_SERVICE_NAME, config.serviceName);
- properties.put(PROPERTY_DEV_GEN, "1");
+ properties.put(PROPERTY_DEV_GEN, !profile.isGen2 ? "1" : "2");
+ properties.put(PROPERTY_DEV_AUTH, getBool(profile.device.auth) ? "yes" : "no");
if (!deviceName.isEmpty()) {
properties.put(PROPERTY_DEV_NAME, deviceName);
}
- properties.put(PROPERTY_DEV_GEN, !profile.isGen2 ? "1" : "2");
// add status properties
if (status.wifiSta != null) {
@@ -1442,10 +1419,10 @@ public static Map fillDeviceProperties(ShellyDeviceProfile profi
Map properties = new TreeMap<>();
properties.put(PROPERTY_VENDOR, VENDOR);
if (profile.isInitialized()) {
- properties.put(PROPERTY_MODEL_ID, getString(profile.settings.device.type));
- properties.put(PROPERTY_MAC_ADDRESS, profile.mac);
+ properties.put(PROPERTY_MODEL_ID, getString(profile.device.type));
+ properties.put(PROPERTY_MAC_ADDRESS, profile.device.mac);
properties.put(PROPERTY_FIRMWARE_VERSION, profile.fwVersion + "/" + profile.fwDate);
- properties.put(PROPERTY_DEV_MODE, profile.mode);
+ properties.put(PROPERTY_DEV_MODE, profile.device.mode);
if (profile.hasRelays) {
properties.put(PROPERTY_NUM_RELAYS, String.valueOf(profile.numRelays));
properties.put(PROPERTY_NUM_ROLLERS, String.valueOf(profile.numRollers));
@@ -1473,7 +1450,7 @@ public ShellyDeviceProfile getProfile(boolean forceRefresh) throws ShellyApiExce
try {
refreshSettings |= forceRefresh;
if (refreshSettings) {
- profile = api.getDeviceProfile(thingType);
+ profile = api.getDeviceProfile(thingType, null);
if (!isThingOnline()) {
logger.debug("{}: Device profile re-initialized (thingType={})", thingName, thingType);
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBluSensorHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBluSensorHandler.java
index d79967a0dd728..8e097bf761959 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBluSensorHandler.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBluSensorHandler.java
@@ -13,7 +13,6 @@
package org.openhab.binding.shelly.internal.handler;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
-import static org.openhab.binding.shelly.internal.api2.ShellyBluApi.buildBluServiceName;
import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import static org.openhab.core.thing.Thing.PROPERTY_MODEL_ID;
@@ -23,6 +22,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
+import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2NotifyEvent;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
@@ -54,7 +54,7 @@ public void initialize() {
public static void addBluThing(String gateway, Shelly2NotifyEvent e, ShellyThingTable thingTable) {
String model = substringBefore(getString(e.data.name), "-").toUpperCase();
- String mac = e.data.addr.replace(":", "");
+ String mac = e.data.addr.replaceAll(":", "");
String ttype = "";
logger.debug("{}: Create thing for new BLU device {}: {} / {}", gateway, e.data.name, model, mac);
ThingTypeUID tuid;
@@ -67,11 +67,15 @@ public static void addBluThing(String gateway, Shelly2NotifyEvent e, ShellyThing
ttype = THING_TYPE_SHELLYBLUDW_STR;
tuid = THING_TYPE_SHELLYBLUDW;
break;
+ case SHELLYDT_BLUMOTION:
+ ttype = THING_TYPE_SHELLYBLUMOTION_STR;
+ tuid = THING_TYPE_SHELLYBLUMOTION;
+ break;
default:
logger.debug("{}: Unsupported BLU device model {}, MAC={}", gateway, model, mac);
return;
}
- String serviceName = buildBluServiceName(model, mac);
+ String serviceName = ShellyDeviceProfile.buildBluServiceName(getString(e.data.name), mac);
Map properties = new TreeMap<>();
addProperty(properties, PROPERTY_MODEL_ID, model);
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java
index 28569c9c073c6..fc648d2eb7dd5 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java
@@ -78,7 +78,7 @@ public static boolean updateDeviceStatus(ShellyThingInterface thingHandler, Shel
if (status.tmp != null && getBool(status.tmp.isValid) && !thingHandler.getProfile().isSensor
&& status.tmp.tC != SHELLY_API_INVTEMP) {
thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP,
- toQuantityType(getDouble(status.tmp.tC), DIGITS_NONE, SIUnits.CELSIUS));
+ toQuantityType(getDouble(status.tmp.tC), DIGITS_TEMP, SIUnits.CELSIUS));
} else if (status.temperature != null && status.temperature != SHELLY_API_INVTEMP) {
thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP,
toQuantityType(getDouble(status.temperature), DIGITS_NONE, SIUnits.CELSIUS));
@@ -435,7 +435,10 @@ public static boolean updateSensors(ShellyThingInterface thingHandler, ShellySet
if (t.tmp != null) {
updated |= updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
t.tmp.value, t.tmp.units);
- updated |= updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, CHANNEL_CONTROL_SETTEMP,
+ if (t.targetTemp.unit == null) {
+ t.targetTemp.unit = t.tmp.units;
+ }
+ updated |= updateTempChannel(thingHandler, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SETTEMP,
t.targetTemp.value, t.targetTemp.unit);
}
if (t.pos != null) {
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java
index 8fc49526f68b0..b9a901612bb6d 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java
@@ -82,7 +82,7 @@ public boolean handleDeviceCommand(ChannelUID channelUID, Command command) throw
try {
ShellyColorUtils oldCol = getCurrentColors(lightId);
- oldCol.mode = profile.mode;
+ oldCol.mode = profile.device.mode;
ShellyColorUtils col = new ShellyColorUtils(oldCol);
boolean update = true;
@@ -317,7 +317,7 @@ public boolean updateDeviceStatus(ShellySettingsStatus genericStatus) throws She
}
ShellyStatusLight status = api.getLightStatus();
- logger.trace("{}: Updating light status in {} mode, {} channel(s)", thingName, profile.mode,
+ logger.trace("{}: Updating light status in {} mode, {} channel(s)", thingName, profile.device.mode,
status.lights.size());
// In white mode we have multiple channels
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerActionPage.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerActionPage.java
index ef47191441e1c..f98b0916dff8a 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerActionPage.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerActionPage.java
@@ -376,8 +376,10 @@ public static Map getActions(ShellyDeviceProfile profile) {
boolean gen2 = profile.isGen2;
list.put(ACTION_RES_STATS, "Reset Statistics");
- list.put(ACTION_RESTART, "Reboot Device");
- if (gen2) {
+ if (!profile.isBlu) {
+ list.put(ACTION_RESTART, "Reboot Device");
+ }
+ if (!gen2 || !profile.isBlu) {
list.put(ACTION_PROTECT, "Protect Device");
}
@@ -413,10 +415,13 @@ && getBool(profile.settings.wifiSta.enabled)) {
!profile.settings.bluetooth ? "Enable Bluetooth" : "Disable Bluetooth");
}
- boolean set = profile.settings.cloud != null && getBool(profile.settings.cloud.enabled);
- list.put(set ? ACTION_DISCLOUD : ACTION_ENCLOUD, set ? "Disable Cloud" : "Enable Cloud");
+ if (!profile.isBlu) {
+ boolean set = profile.settings.cloud != null && getBool(profile.settings.cloud.enabled);
+ list.put(set ? ACTION_DISCLOUD : ACTION_ENCLOUD, set ? "Disable Cloud" : "Enable Cloud");
+
+ list.put(ACTION_RESET, "-Factory Reset");
+ }
- list.put(ACTION_RESET, "-Factory Reset");
if (!gen2 && profile.extFeatures) {
list.put(ACTION_OTACHECK, "Check for Update");
boolean debug_enable = getBool(profile.settings.debugEnable);
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerConstants.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerConstants.java
index 4bc16c72db149..fdee5a4c5d3d8 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerConstants.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerConstants.java
@@ -12,6 +12,8 @@
*/
package org.openhab.binding.shelly.internal.manager;
+import static org.openhab.binding.shelly.internal.ShellyBindingConstants.CONFIG_DEVICEIP;
+
import java.nio.charset.StandardCharsets;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -82,6 +84,7 @@ public class ShellyManagerConstants {
public static final String ATTRIBUTE_MESSAGE = "message";
public static final String ATTRIBUTE_TOTAL_DEV = "totalDevices";
public static final String ATTRIBUTE_STATUS_ICON = "iconStatus";
+ public static final String ATTRIBUTE_DEVICEIP = CONFIG_DEVICEIP;
public static final String ATTRIBUTE_DISPLAY_NAME = "displayName";
public static final String ATTRIBUTE_DEV_STATUS = "deviceStatus";
public static final String ATTRIBUTE_DEBUG_MODE = "debugMode";
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOtaPage.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOtaPage.java
index ed7efa891cbdb..d4ce439f1dcf0 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOtaPage.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOtaPage.java
@@ -87,7 +87,7 @@ public ShellyMgrResponse generatePage(String path, Map paramet
String deviceType = getDeviceType(properties);
String uri = !url.isEmpty() && connection.equals(CONNECTION_TYPE_CUSTOM) ? url
- : getFirmwareUrl(config.deviceIp, deviceType, profile.mode, version,
+ : getFirmwareUrl(config.deviceIp, deviceType, profile.device.mode, version,
connection.equals(CONNECTION_TYPE_LOCAL));
if (connection.equalsIgnoreCase(CONNECTION_TYPE_INTERNET)) {
// If target
@@ -100,7 +100,8 @@ public ShellyMgrResponse generatePage(String path, Map paramet
}
} else if (connection.equalsIgnoreCase(CONNECTION_TYPE_LOCAL)) {
// redirect to local server -> http://:/shelly/manager/ota?deviceType=xxx&version=xxx
- String modeParm = !profile.mode.isEmpty() ? "&" + URLPARM_DEVMODE + "=" + profile.mode : "";
+ String modeParm = !profile.device.mode.isEmpty() ? "&" + URLPARM_DEVMODE + "=" + profile.device.mode
+ : "";
url = URLPARM_URL + "=http://" + localIp + ":" + localPort + SHELLY_MGR_OTA_URI + urlEncode(
"?" + URLPARM_DEVTYPE + "=" + deviceType + modeParm + "&" + URLPARM_VERSION + "=" + version);
} else if (connection.equalsIgnoreCase(CONNECTION_TYPE_CUSTOM)) {
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOverviewPage.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOverviewPage.java
index ddc696e80543a..93c8bd1ee0720 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOverviewPage.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOverviewPage.java
@@ -64,7 +64,7 @@ public ShellyMgrResponse generateContent(String path, Map para
String action = getUrlParm(parameters, URLPARM_ACTION).toLowerCase();
String uidParm = getUrlParm(parameters, URLPARM_UID).toLowerCase();
- logger.debug("Generating overview for {} devices", getThingHandlers().size());
+ logger.debug("Generating overview for {} devices", getThingHandlers().size());
String html = "";
Map properties = new HashMap<>();
@@ -117,6 +117,11 @@ public ShellyMgrResponse generateContent(String path, Map para
properties.put(ATTRIBUTE_FIRMWARE_SEL, "");
properties.put(ATTRIBUTE_ACTION_LIST, "");
}
+ if (profile.isBlu) {
+ properties.put(ATTRIBUTE_DISPLAY_NAME, profile.thingName);
+ properties.put(ATTRIBUTE_DEVICEIP, "n/a");
+ properties.put(PROPERTY_WIFI_NETW, "Bluetooth");
+ }
html += loadHTML(OVERVIEW_DEVICE, properties);
}
} catch (ShellyApiException e) {
@@ -143,7 +148,7 @@ private String fillFirmwareHtml(ShellyDeviceProfile profile, String uid, String
try {
if (!profile.isGen2) { // currently there is no public firmware repo for Gen2
logger.debug("{}: Load firmware version list for device type {}", LOG_PREFIX, deviceType);
- FwRepoEntry fw = getFirmwareRepoEntry(deviceType, profile.mode);
+ FwRepoEntry fw = getFirmwareRepoEntry(deviceType, profile.device.mode);
pVersion = extractFwVersion(fw.version);
bVersion = extractFwVersion(fw.betaVer);
@@ -193,10 +198,13 @@ private String fillFirmwareHtml(ShellyDeviceProfile profile, String uid, String
logger.debug("{}: Unable to retrieve firmware list: {}", LOG_PREFIX, e.toString());
}
- html += "\t\t\t\t\t\n";
-
- html += "\t\t\t\t\n\t\t\t";
+ html += "\t\t\t\t\t\n\t\t\t\t\n\t\t\t";
return html;
}
@@ -238,7 +246,9 @@ private boolean applyFilter(ShellyManagerInterface handler, String filter) {
// return handler.getChannelValue(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_UPDATE) == OnOffType.ON;
return getBool(profile.status.hasUpdate);
case FILTER_UNPROTECTED:
- return !profile.auth;
+ if (profile.device.auth != null) {
+ return !profile.device.auth;
+ }
case "*":
default:
return true;
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java
index a70b4472d9f8d..d4196e1a8cb70 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java
@@ -254,7 +254,8 @@ protected Map fillProperties(Map properties, Str
properties.put(ATTRIBUTE_APR_TRESHOLD,
profile.settings.apRoaming != null ? getOption(profile.settings.apRoaming.threshold) : "n/a");
properties.put(ATTRIBUTE_PWD_PROTECT,
- profile.auth ? "enabled, user=" + getString(profile.settings.login.username) : "disabled");
+ getBool(profile.device.auth) ? "enabled, user=" + getString(profile.settings.login.username)
+ : "disabled");
String tz = getString(profile.settings.timezone);
properties.put(ATTRIBUTE_TIMEZONE,
(tz.isEmpty() ? "n/a" : tz) + ", auto-detect: " + getBool(profile.settings.tzautodetect));
@@ -537,7 +538,7 @@ protected static String getDeviceType(Map properties) {
}
protected static String getDeviceIp(Map properties) {
- return getString(properties.get("deviceIp"));
+ return getString(properties.get(ATTRIBUTE_DEVICEIP));
}
protected static String getDeviceName(Map properties) {
diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java
index a83c3b5b7b839..7ecaa6232df2b 100644
--- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java
+++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java
@@ -315,7 +315,7 @@ public static Map createDeviceChannels(final Thing thing, final
addChannel(thing, add, profile.settings.sleepTime != null, CHGR_SENSOR, CHANNEL_SENSOR_SLEEPTIME);
// If device has more than 1 meter the channel accumulatedWatts receives the accumulated value
- boolean accuChannel = profile.numMeters > 1 && !profile.isRoller && !profile.isRGBW2;
+ boolean accuChannel = profile.hasRelays && profile.numMeters > 1 && !profile.isRoller && !profile.isRGBW2;
addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUWATTS);
addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL);
addChannel(thing, add, accuChannel && (status.emeters != null), CHGR_DEVST, CHANNEL_DEVST_ACCURETURNED);
@@ -519,7 +519,7 @@ public static Map createSensorChannels(final Thing thing, final
CHANNEL_SENSOR_VIBRATION);
}
// Create tilt for DW/DW2, for BLU DW create channel even tilt is currently not reported
- if (sdata.accel != null || (profile.isBlu && sdata.lux != null)) {
+ if (sdata.accel != null || (profile.isBlu && profile.isDW && sdata.lux != null)) {
addChannel(thing, newChannels, sdata.accel.tilt != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TILT);
}
@@ -657,20 +657,20 @@ public ShellyChannel(ShellyTranslationProvider messages, String group, String ch
this.typeId = typeId;
groupLabel = getText(PREFIX_GROUP + group + ".label");
- if (groupLabel.contains(PREFIX_GROUP)) {
+ if (groupLabel.startsWith(PREFIX_GROUP)) {
groupLabel = "";
}
groupDescription = getText(PREFIX_GROUP + group + ".description");
- if (groupDescription.contains(PREFIX_GROUP)) {
+ if (groupDescription.startsWith(PREFIX_GROUP)) {
groupDescription = "";
}
label = getText(PREFIX_CHANNEL + typeId.replace(':', '.') + ".label");
- if (label.contains(PREFIX_CHANNEL)) {
+ if (label.startsWith(PREFIX_CHANNEL)) {
label = "";
}
description = getText(PREFIX_CHANNEL + typeId + ".description");
- if (description.contains(PREFIX_CHANNEL)) {
- description = "";
+ if (description.startsWith(PREFIX_CHANNEL)) {
+ description = ""; // no resource found
}
}
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml
index bc212f828b2bb..ceccff2a0acae 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml
@@ -96,10 +96,6 @@
@text/thing-type.config.shelly.deviceIp.descriptionnetwork-address
-
-
- @text/thing-type.config.shelly.userId.description
- @text/thing-type.config.shelly.password.description
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/configblu.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/configblu.xml
index fa888ad7b9f9f..7886954bd6c49 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/configblu.xml
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/configblu.xml
@@ -7,7 +7,7 @@
- @text/thing-type.config.shelly.@text/thing-type.config.shelly.deviceAddress.label.description
+ @text/thing-type.config.shelly.deviceAddress.description
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties
index e42353f1c548d..2c2801bfcbc34 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties
@@ -34,7 +34,7 @@ message.versioncheck.update = INFO: New firmware available: current version: {0}
message.versioncheck.autocoiot = INFO: Firmware is full-filling the minimum version to auto-enable CoIoT
message.init.noipaddress = Unable to detect local IP address. Please make sure that IPv4 is enabled for this interface and check openHAB Network Configuration.
message.command.failed = ERROR: Unable to process command {0} for channel {1}
-message.command.init = Thing not yet initialized, command {0}triggered initialization
+message.command.init = Thing not yet initialized, command {0} triggered initialization
message.status.unknown.initializing = Initializing or device in sleep mode.
message.statusupdate.failed = Unable to update status
message.status.managerstarted = Shelly Manager started at http(s)://{0}:{1}/shelly/manager
@@ -42,7 +42,7 @@ message.event.triggered = Event triggered: {0}
message.event.filtered = Event filtered: {0}
message.coap.init.failed = Unable to start CoIoT: {0}
message.discovery.disabled = Device is marked as non-discoverable, will be skipped
-message.discovery.protected = Device {0} reported 'Access defined' (missing userid/password or incorrect).
+message.discovery.protected = Device {0} is protected and reports 'Access denied', check userId/password.
message.discovery.failed = Device discovery of device with address {0} failed: {1}
message.roller.calibrating = Device is not calibrated, use Shelly App to perform initial roller calibration.
message.roller.favmissing = Roller position favorites are not supported by installed firmware or not configured in the Shelly App
@@ -99,9 +99,10 @@ thing-type.shelly.shellyplusi4dc.description = Shelly Plus i4DC - 4xDC Input Dev
thing-type.shelly.shellyplusht.description = Shelly Plus HT - Humidity and Temperature sensor with display
thing-type.shelly.shellyplussmoke.description = Shelly Plus Smoke - Smoke Detector with Alarm
thing-type.shelly.shellypluswdus.description = Shelly Wall Dimmer US Device
+thing-type.shelly.shellyplus10v.description = Shelly Plus Dimmer 10V
# Wall displays
-thing-type.shelly.shellywalldisplay.description = Shelly Plus Wall Display with sensors and input/output
+thing-type.shelly.shellywalldisplay.description = Shelly Wall Display with sensors and input/output
# Plus Mini Devices
thing-type.shelly.shellyplusmini1.description = Shelly Plus Mini 1 - Single Relay Switch
@@ -120,8 +121,9 @@ thing-type.shelly.shellyproem50.description = Shelly Pro EM-50 - 2xPower Meter +
thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay Switch with Power Meter
# BLU devices
-thing-type.shelly.shellypblubutton.description = Shelly BLU Button
+thing-type.shelly.shellyblubutton.description = Shelly BLU Button 1
thing-type.shelly.shellybludw.description = Shelly BLU Door/Window Sensor
+thing-type.shelly.shellyblumotion.description = Shelly BLU Motion Sensor
# Wall Displays
thing-type.shelly.shellywalldisplay.description = Shelly Wall Display with sensors and input/output
@@ -246,7 +248,7 @@ channel-type.shelly.temperature4.description = Temperature of external Sensor #4
channel-type.shelly.temperature5.label = Temperature 5
channel-type.shelly.temperature6.description = Temperature of external Sensor #5
channel-type.shelly.targetTemp.label = Target Temperature
-channel-type.shelly.targetTemp.description = Target Temperature in C to be reached in auto-temperature mode
+channel-type.shelly.targetTemp.description = Target Temperature in C to be reached in auto-temperature mode
channel-type.shelly.humidity.label = Humidity
channel-type.shelly.humidity.description = Relative humidity (0..100%)
channel-type.shelly.rollerShutter.label = Roller Control (0=open, 100=closed)
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties
index 0021fa688cc69..ac2bb777dcf4d 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties
@@ -34,7 +34,7 @@ message.versioncheck.update = INFO\: Neue Firmware verfügbar\: aktuelle Version
message.versioncheck.autocoiot = INFO\: Die Firmware unterstützt die Anforderung, Auto-CoIoT wurde aktiviert.
message.init.noipaddress = Es konnte keine lokale IP-Adresse ermittelt werden. Bitte sicherstellen, dass IPv4 aktiviert ist und das richtige Interface in der openHAB Netzwerk-Konfiguration ausgewählt ist.
message.command.failed = FEHLER\: Der Befehl {0} für Kanal {1} kann nicht verarbeitet werden
-message.command.init = Thing aktuell nicht initialisiert, der Befehl {0} führt zur Initialisierung
+message.command.init = Gerät ist nicht initialisiert, der Befehl {0} führt zur Initialisierung
message.status.unknown.initializing = Initialisierung oder Gerät im Schlafmodus.
message.statusupdate.failed = Status konnte nicht aktualisiert werden
message.status.managerstarted = Shelly Manager gestartet und erreichbar unter http(s)\://{0}\:{1}/shelly/manager
@@ -42,7 +42,7 @@ message.event.triggered = Event erzeugt\: {0}
message.event.filtered = Ereignis gefiltert\: {0}
message.coap.init.failed = CoAP/CoIoT konnte nicht gestartet werden\: {0}
message.discovery.disabled = Das Gerät ist als "nicht erkennen" markiert und wird nicht übernommen.
-message.discovery.protected = Das Gerät mit der IP-Adresse {0} ist zugriffsgeschützt und keine Zugangsdaten konfiguriert.
+message.discovery.protected = Gerät {0} ist geschützt und meldet ''Zugriff verweigert'', überprüfen Sie User Id und Passwort.
message.discovery.failed = Erkennung des Gerätes mit der IP-Adresse {0} ist fehlgeschlagen\: {1}
message.roller.calibrating = Das Gerät ist nicht kalibriert. Es ist eine Kalibrierung mit der Shelly App erforderlich.
message.roller.favmissing = Positions-Favoriten werden von der installierten Firmwareversion nicht unterstützt (ab 1.9.2), oder sind nicht in der Shelly App konfiguriert.
@@ -120,8 +120,9 @@ thing-type.shelly.shellyproem50.description = Shelly Pro EM-50 - 2xPower Meter +
thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM mit 4 Relais und Strommesser
# BLU devices
-thing-type.shelly.shellypblubutton.description = Shelly BLU Button 1
+thing-type.shelly.shellyblubutton.description = Shelly BLU Button 1
thing-type.shelly.shellybludw.description = Shelly BLU Door/Window Sensor
+thing-type.shelly.shellyblumotion.description = Shelly BLU Motion Sensor
# Wall Displays
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyBlu_sensor.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyBlu_sensor.xml
index c3c8daaeca45d..d809f572807dd 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyBlu_sensor.xml
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyBlu_sensor.xml
@@ -32,4 +32,17 @@
+
+
+ @text/thing-type.shelly.shellyblumotion.description
+ Sensor
+
+
+
+
+
+
+ serviceName
+
+
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_lights.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_lights.xml
index 2269fa96c43d3..92313c5c503ea 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_lights.xml
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_lights.xml
@@ -237,7 +237,7 @@
Dimmer@text/channel-type.shelly.whiteBrightness.description
- DimmableLight
+ Light
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml
index c2ef67421c9a1..0a252956acb5b 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml
@@ -255,7 +255,6 @@
@text/thing-type.shelly.shellydimmer.description
- DimmableLight
@@ -269,7 +268,6 @@
@text/thing-type.shelly.shellydimmer2.description
- DimmableLight
@@ -469,7 +467,7 @@
Dimmer@text/channel-type.shelly.dimmerBrightness.description
- DimmableLight
+ Light
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml
index b66b8137fc01e..1a0d7bb605152 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml
@@ -357,7 +357,19 @@
@text/thing-type.shelly.shellypluswdus.description
- DimmableLight
+
+
+
+
+
+
+ serviceName
+
+
+
+
+
+ @text/thing-type.shelly.shellyplus10v.description
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js b/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js
index c02dbc9532080..c1583a92ec715 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js
@@ -4,7 +4,7 @@
* Version 0.2
*/
-let ALLTERCO_DEVICE_NAME_PREFIX = ["SBBT", "SBDW"];
+let ALLTERCO_DEVICE_NAME_PREFIX = ["SBBT", "SBDW", "SBMO"];
let ALLTERCO_MFD_ID_STR = "0ba9";
let BTHOME_SVC_ID_STR = "fcd2";
@@ -25,9 +25,11 @@ let int24 = 5;
let BTH = [];
BTH[0x00] = { n: "pid", t: uint8 };
BTH[0x01] = { n: "Battery", t: uint8, u: "%" };
+BTH[0x02] = { n: "Temperature", t: int16, f: 0.01 };
BTH[0x05] = { n: "Illuminance", t: uint24, f: 0.01 };
BTH[0x1a] = { n: "Door", t: uint8 };
BTH[0x20] = { n: "Moisture", t: uint8 };
+BTH[0x21] = { n: "Motion", t: uint8 };
BTH[0x2d] = { n: "Window", t: uint8 };
BTH[0x3a] = { n: "Button", t: uint8 };
BTH[0x3f] = { n: "Rotation", t: int16, f: 0.1 };
diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/sniplets/ov_device.html b/bundles/org.openhab.binding.shelly/src/main/resources/sniplets/ov_device.html
index 3465237ea59c2..c395960220ce8 100644
--- a/bundles/org.openhab.binding.shelly/src/main/resources/sniplets/ov_device.html
+++ b/bundles/org.openhab.binding.shelly/src/main/resources/sniplets/ov_device.html
@@ -32,7 +32,7 @@
Device Mode
${deviceMode}
Firmware Version
${firmwareVersion}
Network Name
${serviceName}
-
MAC Address
${macAddress}
+
Device Address
${macAddress}
Discoverable
${discoverable}
WiFi Auto Recovery
${wifiAutoRecovery}
WiFi AP Roaming
${apRoamingMode}
diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/i18n/sonos_fr.properties b/bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/i18n/sonos_fr.properties
index d5a2a5cb9e3b6..733787c51deaf 100644
--- a/bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/i18n/sonos_fr.properties
+++ b/bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/i18n/sonos_fr.properties
@@ -32,6 +32,8 @@ thing-type.sonos.Five.label = Five
thing-type.sonos.Five.description = Représente une enceinte Sonos Five
thing-type.sonos.Move.label = Move
thing-type.sonos.Move.description = Représente une enceinte Sonos Move
+thing-type.sonos.Move2.label = Move 2
+thing-type.sonos.Move2.description = Représente une enceinte Sonos Move 2
thing-type.sonos.One.label = One
thing-type.sonos.One.description = Représente une enceinte Sonos One
thing-type.sonos.OneSL.label = One SL
@@ -89,12 +91,15 @@ channel-type.sonos.codec.description = Nom du codec en cours de décodage
channel-type.sonos.codec.state.option.noSignal = Aucun signal
channel-type.sonos.codec.state.option.silence = Silence
channel-type.sonos.codec.state.option.DTS = DTS
-channel-type.sonos.codec.state.option.dolbyAtmos = Dolby Atmos
+channel-type.sonos.codec.state.option.Atmos = Dolby Atmos
channel-type.sonos.codec.state.option.DD20 = Dolby Digital 2.0
channel-type.sonos.codec.state.option.PCM20 = PCM 2.0
channel-type.sonos.codec.state.option.DD51 = Dolby Digital 5.1
+channel-type.sonos.codec.state.option.DDPlus20 = Dolby Digital Plus 2.0
channel-type.sonos.codec.state.option.DDPlus51 = Dolby Digital Plus 5.1
+channel-type.sonos.codec.state.option.TrueHD51 = Dolby TrueHD 5.1
channel-type.sonos.codec.state.option.PCM51 = PCM 5.1
+channel-type.sonos.codec.state.option.DTS51 = DTS Surround 5.1
channel-type.sonos.coordinator.label = Coordinateur Groupe
channel-type.sonos.coordinator.description = L'identifiant du Sonos qui coordonne le groupe actuel
channel-type.sonos.currentalbum.label = Album
diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug_it.properties b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug_it.properties
new file mode 100644
index 0000000000000..f9754ce43c473
--- /dev/null
+++ b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug_it.properties
@@ -0,0 +1,35 @@
+# add-on
+
+addon.tasmotaplug.name = Binding Spina Tasmota
+addon.tasmotaplug.description = Controlla le Spine Intelligenti Wi-Fi flashate con Tasmota
+
+# thing types
+
+thing-type.tasmotaplug.plug.label = Spina
+thing-type.tasmotaplug.plug.description = Tasmota Spina Smart
+thing-type.tasmotaplug.plug.channel.power.label = Potenza
+thing-type.tasmotaplug.plug.channel.power.description = Controlla il relè smart plug per il primo canale
+thing-type.tasmotaplug.plug.channel.power2.label = Potenza 2
+thing-type.tasmotaplug.plug.channel.power2.description = Controlla il relè smart plug per il secondo canale
+thing-type.tasmotaplug.plug.channel.power3.label = Potenza 3
+thing-type.tasmotaplug.plug.channel.power3.description = Controlla il relè smart plug per il terzo canale
+thing-type.tasmotaplug.plug.channel.power4.label = Potenza 4
+thing-type.tasmotaplug.plug.channel.power4.description = Controlla il relè smart plug per il 4° canale
+
+# thing types config
+
+thing-type.config.tasmotaplug.plug.hostName.label = Nome Host/Indirizzo IP Plug
+thing-type.config.tasmotaplug.plug.hostName.description = Nome host o indirizzo IP della spina
+thing-type.config.tasmotaplug.plug.numChannels.label = Numero dei canali
+thing-type.config.tasmotaplug.plug.numChannels.description = Numero di canali sulla spina Tasmota (1-4) predefinito 1
+thing-type.config.tasmotaplug.plug.password.label = Password
+thing-type.config.tasmotaplug.plug.password.description = Password di Tasmota
+thing-type.config.tasmotaplug.plug.refresh.label = Intervallo di aggiornamento
+thing-type.config.tasmotaplug.plug.refresh.description = Specifica l'intervallo di aggiornamento in secondi
+thing-type.config.tasmotaplug.plug.username.label = Utente
+thing-type.config.tasmotaplug.plug.username.description = Utente Tasmota
+
+# thing status descriptions
+
+offline.communication-error.http-failure = Il codice di risposta di Tasmota http era\: {0}
+offline.configuration-error-hostname = Il nome host della spina deve essere specificato
diff --git a/bundles/org.openhab.binding.tesla/README.md b/bundles/org.openhab.binding.tesla/README.md
index 4387fdc0b51aa..c97448323a809 100644
--- a/bundles/org.openhab.binding.tesla/README.md
+++ b/bundles/org.openhab.binding.tesla/README.md
@@ -182,9 +182,9 @@ Additionally, these advanced channels are available (not all are available on al
| shiftstate | String | Shift State | Indicates the state of the transmission, “P”, “D”, “R”, or “N” |
| sidemirrorheaters | Switch | Side Mirror Heaters | Indicates if the side mirror heaters are switched on |
| smartpreconditioning | Switch | Smart Preconditioning | Indicates if smart preconditioning is switched on |
-| softwareupdateavailable | Switch | Update Available | Car software update available, automatically generated on non-empty "update version" |
-| softwareupdatestatus | String | Update Status | Car software update status, e.g. "downloading_wifi_wait", "installing" |
-| softwareupdateversion | String | Update Version | Car software version to update to, e.g. "2023.32.9" or empty |
+| softwareupdateavailable | Switch | Update Available | Car software or map update available, automatically generated on non-empty "update version" |
+| softwareupdatestatus | String | Update Status | Car software or map update status, e.g. "downloading_wifi_wait", "installing" |
+| softwareupdateversion | String | Update Version | Car software or map version to update to, e.g. "2023.32.9", "EU-2023.32-14783" for map updates, or empty |
| soc | Number | State of Charge | State of Charge, in % |
| state | String | State | “online”, “asleep”, “waking” |
| steeringwheelheater | Switch | Steering Wheel Heater | Turns On/Off the steering wheel heater |
diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties
index cdf0ab7d8c8a3..dd38a0070f1c1 100644
--- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties
+++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties
@@ -323,11 +323,11 @@ channel-type.tesla.smartpreconditioning.description = Indicates if smart precond
channel-type.tesla.soc.label = State of Charge
channel-type.tesla.soc.description = State of Charge, in %
channel-type.tesla.softwareupdateavailable.label = Update Available
-channel-type.tesla.softwareupdateavailable.description = Car software update available
+channel-type.tesla.softwareupdateavailable.description = Car software or map update available
channel-type.tesla.softwareupdatestatus.label = Update Status
-channel-type.tesla.softwareupdatestatus.description = Car software update status
+channel-type.tesla.softwareupdatestatus.description = Car software or map update status
channel-type.tesla.softwareupdateversion.label = Update Version
-channel-type.tesla.softwareupdateversion.description = Car software version to update to
+channel-type.tesla.softwareupdateversion.description = Car software or map version to update to
channel-type.tesla.speed.label = Speed
channel-type.tesla.speed.description = Vehicle speed
channel-type.tesla.state.label = State
diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/channels.xml
index 5facdaffb60fe..e6046793495c2 100644
--- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/channels.xml
+++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/channels.xml
@@ -7,19 +7,19 @@
Switch
- Car software update available
+ Car software or map update availableString
- Car software update status
+ Car software or map update statusString
- Car software version to update to
+ Car software or map version to update to
diff --git a/bundles/org.openhab.binding.twitter/README.md b/bundles/org.openhab.binding.twitter/README.md
deleted file mode 100644
index b0ed2e6abae62..0000000000000
--- a/bundles/org.openhab.binding.twitter/README.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Twitter Binding
-
-The Twitter binding allows your home to Tweet 280 characters at a time. It also supports direct messages and tweeting with media.
-
-## Supported Things
-
-```text
-account - Twitter Account.
-```
-
-## Thing Configuration
-
-The Twitter Account Thing requires you to create a Twitter App in the Twitter Developer Page.
-
-| Property | Default | Required | Description |
-|-------------------|---------|:--------:|-----------------------------------|
-| consumerKey | | Yes | Consumer API Key |
-| consumerSecret | | Yes | Consumer API Secret |
-| accessToken | | Yes | Access Token |
-| accessTokenSecret | | Yes | Access Token Secret |
-| refresh | 30 | No | Tweet refresh interval in minutes |
-
-## Channels
-
-| channel | type | description |
-|------------|--------|------------------------------------------------|
-| lasttweet | String | This channel provides the Latest Tweet message |
-
-## Full Example
-
-twitter.things:
-
-```java
-Thing twitter:account:sampleaccount [ consumerKey="11111", consumerSecret="22222", accessToken="33333", accessTokenSecret="444444" ]
-
-```
-
-twitter.items:
-
-```java
-String sample_tweet "Latest Tweet: [%s]" { channel="twitter:account:sampleaccount:lasttweet" }
-
-```
-
-## Rule Action
-
-This binding includes rule actions for sending tweets and direct messages.
-
-- `boolean success = sendTweet(String text)`
-- `boolean success = sendTweetWithAttachment(String text, String URL)`
-- `boolean success = sendDirectMessage(String recipientID, String text)`
-
-Examples:
-
-```java
-val tweetActions = getActions("twitter","twitter:account:sampleaccount")
-val success = tweetActions.sendTweet("This is A Tweet")
-val success2 = tweetActions.sendTweetWithAttachment("This is A Tweet with a Pic", file:///tmp/201601011031.jpg)
-val success3 = tweetActions.sendTweetWithAttachment("Windows Picture", "D:\\Test.png" )
-val success4 = tweetActions.sendTweetWithAttachment("HTTP Picture", "http://www.mywebsite.com/Test.png" )
-val success5 = tweetActions.sendDirectMessage("1234567", "Wake Up" )
-
-```
diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/addon/addon.xml
deleted file mode 100644
index 8c90697c78f48..0000000000000
--- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/addon/addon.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- binding
- Twitter Binding
- Supports adding Thing for getting the Last Tweet. Send Tweets and Pictures with Actions.
- cloud
-
-
diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties
deleted file mode 100644
index 161cccf2a81be..0000000000000
--- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties
+++ /dev/null
@@ -1,32 +0,0 @@
-# add-on
-
-addon.twitter.name = Twitter Binding
-addon.twitter.description = Supports adding Thing for getting the Last Tweet. Send Tweets and Pictures with Actions.
-
-# thing types
-
-thing-type.twitter.account.label = Twitter Account
-thing-type.twitter.account.description = Account uses for sending Tweets
-
-# thing types config
-
-thing-type.config.twitter.account.accessToken.label = Access Token
-thing-type.config.twitter.account.accessTokenSecret.label = Access Token Secret
-thing-type.config.twitter.account.consumerKey.label = Consumer API Key
-thing-type.config.twitter.account.consumerSecret.label = Consumer API Secret
-thing-type.config.twitter.account.refresh.label = Refresh Time
-thing-type.config.twitter.account.refresh.description = Refresh Time for This Account in Mins
-
-# channel types
-
-channel-type.twitter.lasttweet.label = Last Tweet
-channel-type.twitter.lasttweet.description = Users Last Tweet
-
-# actions
-
-sendAttachmentTweetActionLabel = send a Tweet with attachment
-sendAttachmentTweetActionDescription = Sends a Tweet with an attachment.
-sendDirectMessageActionLabel = send a DirectMessage
-sendDirectMessageActionDescription = Sends a DirectMessage.
-sendTweetActionLabel = send a Tweet
-sendTweetActionDescription = Sends a Tweet.
diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_fr.properties b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_fr.properties
deleted file mode 100644
index 06d82693efbf8..0000000000000
--- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_fr.properties
+++ /dev/null
@@ -1,32 +0,0 @@
-# add-on
-
-addon.twitter.name = Extension Twitter
-addon.twitter.description = Cette extension permet d'obtenir le dernier Tweet ou d'envoyer des Tweets et des images depuis vos règles d'automatisation.
-
-# thing types
-
-thing-type.twitter.account.label = Compte Twitter
-thing-type.twitter.account.description = Compte pour envoyer des Tweets
-
-# thing types config
-
-thing-type.config.twitter.account.accessToken.label = Jeton d'authentification
-thing-type.config.twitter.account.accessTokenSecret.label = Code secret du jeton d'authentification
-thing-type.config.twitter.account.consumerKey.label = Clé d'accès à l'API
-thing-type.config.twitter.account.consumerSecret.label = Code secret pour l'accès à l'API
-thing-type.config.twitter.account.refresh.label = Fréquence de rafraîchissement
-thing-type.config.twitter.account.refresh.description = Fréquence de rafraîchissement de ce compte en minutes
-
-# channel types
-
-channel-type.twitter.lasttweet.label = Dernier Tweet
-channel-type.twitter.lasttweet.description = Dernier Tweet des utilisateurs
-
-# actions
-
-sendAttachmentTweetActionLabel = envoyer un Tweet avec pièce jointe
-sendAttachmentTweetActionDescription = Envoie un Tweet avec pièce jointe.
-sendDirectMessageActionLabel = envoyer un message privé
-sendDirectMessageActionDescription = Envoie un message privé.
-sendTweetActionLabel = envoyer un Tweet
-sendTweetActionDescription = Envoie un Tweet.
diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_ru.properties b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_ru.properties
deleted file mode 100644
index 6991945830740..0000000000000
--- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_ru.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-# actions
-sendTweetActionLabel = отправить твит
-sendTweetActionDescription = Отправляет твит.
-
-sendAttachmentTweetActionLabel = отправить твит с вложением
-sendAttachmentTweetActionDescription = Отправляет твит с вложением.
-
-sendDirectMessageActionLabel = отправить личное сообщение
-sendDirectMessageActionDescription = Отправляет личное сообщение.
diff --git a/bundles/org.openhab.binding.velbus/README.md b/bundles/org.openhab.binding.velbus/README.md
index 2fc0d9fb1b507..873babc8d8f10 100644
--- a/bundles/org.openhab.binding.velbus/README.md
+++ b/bundles/org.openhab.binding.velbus/README.md
@@ -2,8 +2,12 @@
The Velbus binding integrates with a [Velbus](https://www.velbus.eu/) system through a Velbus configuration module (VMBRSUSB, VMB1USB or VMB1RS) or a network connection (TCP/IP).
-The binding has been tested with a USB configuration module for universal mounting (VMB1USB).
For optimal stability, the preferred configuration module is the VMBRSUSB module.
+Consider deploying a TCP bridge – the officially developed [python-velbustcp] or one of the [third party projects][3rd-party-servers] – in between the configuration module and openHAB.
+Doing so allows concurrent access to your Velbus system by both openHAB and the official configuration software.
+
+[python-velbustcp]: https://github.com/velbus/python-velbustcp
+[3rd-party-servers]: https://github.com/StefCoene/velserver/wiki/TCP-server-for-Velbus
The binding exposes basic actions from the Velbus System that can be triggered from the smartphone/tablet interface, as defined by the [Velbus Protocol info sheets](https://github.com/velbus).
@@ -12,129 +16,231 @@ Pushbutton, temperature sensors and input module states are retrieved and made a
## Supported Things
-A Velbus configuration module (e.g. VMBRSUSB) or a network server (e.g. [VelServer](https://github.com/StefCoene/velserver/wiki/TCP-server-for-Velbus)) is required as a "bridge" for accessing any other Velbus devices.
+In addition to the bridge modules mentioned in the section above, the supported Velbus modules are:
-The supported Velbus devices are:
+
+
+| Type | Description |
+|-------------|--------------------------------------------------------------------------------------------|
+| vmb1bl | 1-channel blind control module for din rail |
+| vmb1bls | 1-channel blind control module for universal mounting |
+| vmb1dm | Dimmer module for inductive/resistive and capacitive load |
+| vmb1led | 1-channel 0-10V controlled PWM dimmer for led strips |
+| vmb1ry | 1-channel relay module |
+| vmb1ryno | 1-channel relay module with potential-free changeover contact |
+| vmb1rynos | 1-channel relay module with potential-free changeover contact |
+| vmb1rys | 1-channel relay module with input |
+| vmb1ts | Temperature Sensor Module |
+| vmb2bl | 2-channel blind control module |
+| vmb2ble | 2-channel blind control module with extended possibilities |
+| vmb2pbn | Push-button interface for Niko 1- or 2-fold push-buttons |
+| vmb4an | Analog I/O module |
+| vmb4dc | 4-channel 0/1-10V dimmer controller |
+| vmb4pb | 4 button interface module |
+| vmb4ry | 4-channel relay module |
+| vmb4ryld | 4-channel relay module with voltage outputs |
+| vmb4ryno | 4-channel relay module with potential-free contacts |
+| vmb6in | 6-channel input module |
+| vmb6pbn | Push-button interface module for Niko 4- or 6-fold push-button |
+| vmb7in | 7-channel input module (potentialfree + pulse) |
+| vmb8ir | Infrared remote control receiver module |
+| vmb8pb | 8-Channel Push Button module |
+| vmb8pbu | Push-button interface with 8 channels for universal mounting |
+| vmbdme | Dimmer for electronic/resistive load |
+| vmbdmir | Single channel triac dimmer for resistive and inductive loads |
+| vmbdmi | Single channel triac dimmer for resistive and inductive loads |
+| vmbel1 | Edge-lit one touch button module |
+| vmbel2 | Edge-lit two touch buttons module |
+| vmbel4 | Edge-lit four touch buttons module |
+| vmbelo | Edge-lit touch panel with Oled display |
+| vmbelpir | Edge-lit Motion detector with one touch button |
+| vmbgp1-2 | Glass control module with 1 touch key (Edition 2) |
+| vmbgp1 | Glass control module with 1 touch key |
+| vmbgp2-2 | Glass control module with 2 touch keys (Edition 2) |
+| vmbgp2 | Glass control module with 2 touch keys |
+| vmbgp4-2 | Glass control module with 4 touch keys (Edition 2) |
+| vmbgp4 | Glass control module with 4 touch keys |
+| vmbgp4pir-2 | Glass control module with 4 touch keys and built-in motion and twilight sensor (Edition 2) |
+| vmbgp4pir | Glass control module with 4 touch keys and built-in motion and twilight sensor |
+| vmbgpod-2 | Glass control module with oled display and temperature controller (Edition 2) |
+| vmbgpod | Glass control module with oled display and temperature controller |
+| vmbgpo | Glass control module with oled display |
+| vmbin | 1-channel input module |
+| vmbkp | Keypad interface module |
+| vmbmeteo | Weather station with thermometer, anemometer, rain sensor and light sensor |
+| vmbpirc | Motion and twilight sensor for ceiling mounting |
+| vmbpirm | Mini motion and twilight sensor for recessed or surface mounting |
+| vmbpiro | Outdoor motion, twilight and temperature sensor, Theben |
+| vmbrfr8s | 8 channel RF receiver module |
+| vmbvp1 | Doorbird interface module |
## Discovery
The Velbus bridge cannot be discovered automatically.
-It has to be added manually by defining the serial port of the Velbus Configuration module for the Velbus Serial Bridge or by defining the IP Address and port for the Velbus Network Bridge.
+Configure it manually by defining the serial port of the Velbus Configuration module for the Velbus Serial Bridge or by defining the IP address and port for the Velbus Network Bridge, as described in the [`Thing Configuration`](#thing-configuration) section.
-Once the bridge has been added as a thing, a manual scan can be launched to discover all other supported Velbus devices on the bus.
-These devices will be available in the inbox.
-The discovery scan will also retrieve the channel names of the Velbus devices.
+Once the bridge has been configured with openHAB, a manual scan can be initiated to discover Velbus modules with an assigned address.
+Addresses can be assigned via the official configuration software, and is a required step before a Velbus installation can work correctly.
+
+The discovery scan can take a few minutes to complete.
+Modules discovered during this scan will appear in the inbox. This procedure will also retrieve the channel names of the Velbus devices.
## Thing Configuration
The Velbus bridge needs to be added first.
+### Velbus Serial Bridge
+
For the Velbus Serial Bridge it is necessary to specify the serial port device used for communication.
-On Linux systems, this will usually be either `/dev/ttyS0`, `/dev/ttyUSB0` or `/dev/ttyACM0` (or a higher number than `0` if multiple devices are present).
-On Windows it will be `COM1`, `COM2`, etc.
-In the things file, this might look e.g. like
+On Linux and other UNIX systems, it is recommended to use a more stable symbolic device path such as `/dev/serial/by-id/usb-Velleman_Projects_VMB1USB_Velbus_USB_interface-if00`, as it will always refer at to a Velbus configuration module, and not an arbitrary serial device.
+If this is not a concern or an option, it is valid to refer to the serial device directly with a path such as `/dev/ttyS0`, `/dev/ttyUSB0` or `/dev/ttyACM0` (or a number other than `0` if multiple serial devices are connected.)
+
+On Windows `port` will refer to one of the COM devices such as `COM1`, `COM2`, etc.
+The Device Manager system utility can be used to determine the exact COM port number to use.
+
+In a `.things` file, a USB connection to a Velbus configuration module might be configured like so:
```java
+Bridge velbus:bridge:1 [ port="/dev/serial/by-id/usb-Velleman_Projects_VMB1USB_Velbus_USB_interface-if00" ]
+// or
Bridge velbus:bridge:1 [ port="COM1" ]
```
-For the Velbus Network Bridge it is necessary to specify the IP Address or hostname and the port of the Velbus network server.
-This will usually be either the loopback address `127.0.0.1`, and port number.
-Or the specific IP of the machine `10.0.0.110` , and port number.
+### Velbus Network Bridge
+
+For the Velbus Network Bridge it is necessary to specify the address (either an IP address or a hostname) and the port of a Velbus network server.
-In the things file, this might look like
+In a `.things` file, a network bridge running on the same machine at port 6000 would be configured like so:
```java
-Bridge velbus:networkbridge:1 "Velbus Network Bridge - Loopback" @ "Control" [ address="127.0.0.1", port=6000 ]
+Bridge velbus:networkbridge:1 "Velbus Network Bridge - Loopback" @ "Control" [ address="localhost", port=6000 ]
```
-Optionally, both the serial bridge and the network bridge can also update the realtime clock, date and daylight savings status of the Velbus modules.
-This is achieved by setting the Time Update Interval (in minutes) on the bridge, e.g.:
+### Realtime Clock Synchronization
+
+Optionally, the openHAB Velbus binding can synchronize the realtime clock, date and daylight savings status of the Velbus modules.
+This is achieved by setting the Time Update Interval (in minutes) on the bridge thing. For example:
```java
Bridge velbus:bridge:1 [ port="COM1", timeUpdateInterval="360" ]
```
-The default time update interval is every 360 minutes.
-Setting the interval to 0 minutes or leaving it empty disables the update of the realtime clock, date and daylight savings status of the Velbus modules.
+If `timeUpdateInterval` is not specified, the time will be updated every 360 minutes by default.
+In order to disable this behaviour, set the interval to 0 or an empty string.
-In case of a connection error, the bridges can also try to reconnect automatically.
-You can specify at which interval the bridge should try to reconnect by setting the Reconnection Interval (in seconds), e.g.:
+### Reconnection
+
+In case of a connection error, a Velbus bridge will attempt to reconnect every 15 seconds by default.
+You can modify the bridge reconnection interval by specifying the `reconnectionInterval` parameter (in seconds):
```java
Bridge velbus:bridge:1 [ port="COM1", reconnectionInterval="15" ]
```
-The default reconnection interval is 15 seconds.
+### Velbus modules
-For the other Velbus devices, the thing configuration has the following syntax:
+Adding Velbus modules to your openHAB configuration follows the conventions of your preferred configuration method.
-```java
-Thing velbus::: "Label" @ "Location" [CH1="Kitchen Light", CH2="Living Light"]
-```
+* **UI-based configuration:** Invoke a manual scan from the Things menu in order to start the [discovery process](#discovery).
+Discovered modules can be found in the inbox.
+* **Textual `.thing` configuration** can declare Velbus modules either in a standalone fashion (a bridge is still required):
-or nested in the bridge configuration:
+ ```java
+ Thing velbus::: "Label" @ "Location" [ CH1="Kitchen Light", CH2="Living Light" ]
+ ```
-```java
- "Label" @ "Location" [CH1="Kitchen Light", CH2="Living Light"]
-```
-
-The following thing types are valid for configuration:
+ Or, more concisely, by nesting modules within the `Bridge` they’re connected to:
-```text
-vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbelpir, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro, vmbvp1
-```
+ ```java
+ Bridge velbus:bridge:1 [ port="COM1" ] {
+ "Label" @ "Location" [ CH1="Kitchen Light", CH2="Living Light" ]
+ }
+ ```
-`thingId` is the hexadecimal Velbus address of the thing.
+ Here:
-`"Label"` is an optional label for the thing.
+ * `` is the type of the Velbus module. Refer to the [Supported Things](#supported-things) table for valid `` values;
+ * `` is the hexadecimal address of the Velbus module;
+ * `"Label"` is an optional label for the thing;
+ * `@ "Location"` is an optional specification of the location of the thing;
+ * The `CHx="..."` properties are optional and can be used to specify names of the module channels.
-`@ "Location"` is optional, and represents the location of the thing.
+Individual module `Thing`’s channels can be linked to openHAB items via channel names like `velbus:vmb4ryld:1:0A:CH1`. Here, from left to right, the channel name consistes of the binding name, module type (` = vmb4ryld`), bridge id (`1`), module’s hexadecimal address (` = 0A`) and channel within the module (`CH1`).
-`[CHx="..."]` is optional, and represents the name of channel x, e.g. CH1 specifies the name of channel 1.
+#### Additional properties
-For thing types with builtin sensors (e.g. temperature), the interval at which the sensors should be checked can be set by specifying the Refresh Interval, e.g.:
+Some module types have additional functionality not represented well by the trigger channels.
+A prime example of this is a temperature sensor, measurements of which must be polled.
-```java
-Thing velbus:vmbelo:: [refresh="300"]
-```
+The following table lists these additional properties and the modules that support the corresponding property:
-The default refresh interval for the sensors is 300 seconds.
-Setting the refresh interval to 0 or leaving it empty will prevent the thing from periodically refreshing the sensor values.
+
+
+| Property | Supported modules | Description |
+|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
+| `counter1PulseMultiplier` | `vmb7in` | The pulse multiplier for counter 1 |
+| `counter1Unit` | `vmb7in` | The unit for Counter 1. |
+| `counter2PulseMultiplier` | `vmb7in` | The pulse multiplier for counter 2 |
+| `counter2Unit` | `vmb7in` | The unit for Counter 2. |
+| `counter3PulseMultiplier` | `vmb7in` | The pulse multiplier for counter 3 |
+| `counter3Unit` | `vmb7in` | The unit for Counter 3. |
+| `counter4PulseMultiplier` | `vmb7in` | The pulse multiplier for counter 4 |
+| `counter4Unit` | `vmb7in` | The unit for Counter 4. |
+| `dimspeed` | `vmb1dm`, `vmb1led`, `vmb4dc`, `vmbdme`, `vmbdmi`, `vmbdmir` | The time (in seconds) needed for dimming from 0 to 100%. |
+| `refresh` | `vmb1ts`, `vmb4an`, `vmb7in`, `vmbel1`, `vmbel2`, `vmbel4`, `vmbelpir`, `vmbgp1`, `vmbgp1-2`, `vmbgp2`, `vmbgp2-2`, `vmbgp4`, `vmbgp4-2`, `vmbgp4pir`, `vmbgp4pir-2`, `vmbmeteo`, `vmbpirc`, `vmbpirm`, `vmbpiro` | Refresh interval for sensors or counters (in seconds), default 300. If set to 0 or left empty, no refresh will be scheduled. |
## Channels
@@ -192,7 +298,7 @@ For thing type `vmb4ry` 4 channels are available `CH1` ... `CH4`.
OnOff command types are supported.
Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbelpir`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro` have 8 trigger channels `input:CH1` ... `input:CH8` and one temperature channel `input:CH9`.
-Pressed and Long_Pressed command types are supported on channels `button#CH1` and `button#CH2` for the thing type `vmbelpir`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` and `button#CH2` for the thing type `vmbelpir`.
Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH8` for the thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro`.
The thing types `vmbel1` and `vmbgp1` have one channel to steer the button LED feedback `feedback:CH1`.
The thing types `vmbel2` and `vmbgp2` have two channels to steer the button LED feedback `feedback:CH1` and `feedback:CH2`.
@@ -222,10 +328,14 @@ Go to the Items list, select the Item, add a State Description Metadata, and set
## Full Example
+
+
.things:
```java
-Bridge velbus:bridge:1 [ port="COM1"] {
+Bridge velbus:bridge:1 [ port="COM1" ] {
vmb2ble 01
vmb2pbn 02
vmb6pbn 03
@@ -246,14 +356,14 @@ Bridge velbus:bridge:1 [ port="COM1"] {
.items:
```java
-Switch LivingRoom {channel="velbus:vmb4ryld:1:06:CH1"} # Switch for onOff type action
-Switch KitchenButton {velbus:vmb2pbn:1:05:button#CH1} # Switch for Pressed and Long_Pressed type actions
-Dimmer TVRoom {channel="velbus:vmb4dc:1:07:CH2"} # Changing brightness dimmer type action
-Rollershutter Kitchen {channel="velbus:vmb2ble:1:01"} # Controlling rollershutter or blind type action
-
-Number Temperature_LivingRoom "Temperature [%.1f °C]" channel="velbus:vmbgp1:1:08:CH09"}
-Number Temperature_Corridor "Temperature [%.1f °C]" channel="velbus:vmbgpo:1:0C:CH33"}
-Number Temperature_Outside "Temperature [%.1f °C]" channel="velbus:vmbpiro:1:0E:CH09"}
+Switch LivingRoom { channel="velbus:vmb4ryld:1:06:CH1" } # Switch for onOff type action
+Switch KitchenButton { channel="velbus:vmb2pbn:1:05:button#CH1" } # Switch for Pressed and Long_Pressed type actions
+Dimmer TVRoom { channel="velbus:vmb4dc:1:07:CH2" } # Changing brightness dimmer type action
+Rollershutter Kitchen { channel="velbus:vmb2ble:1:01" } # Controlling rollershutter or blind type action
+
+Number Temperature_LivingRoom "Temperature [%.1f °C]" { channel="velbus:vmbgp1:1:08:CH09" }
+Number Temperature_Corridor "Temperature [%.1f °C]" { channel="velbus:vmbgpo:1:0C:CH33" }
+Number Temperature_Outside "Temperature [%.1f °C]" { channel="velbus:vmbpiro:1:0E:CH09" }
```
.sitemap:
diff --git a/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/config/config.xml
index 24eab60c4db61..cd7ab69b0cab9 100644
--- a/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/config/config.xml
+++ b/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/config/config.xml
@@ -333,7 +333,7 @@
- The pulse multiplier for counter 1
+ The pulse multiplier for counter 1.1
@@ -356,7 +356,7 @@
- The pulse multiplier for counter 2
+ The pulse multiplier for counter 2.1
@@ -379,7 +379,7 @@
- The pulse multiplier for counter 3
+ The pulse multiplier for counter 3.1
@@ -402,7 +402,7 @@
- The pulse multiplier for counter 4
+ The pulse multiplier for counter 4.1
diff --git a/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/i18n/velbus.properties b/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/i18n/velbus.properties
index 5fb7cab2e160e..fba843337328c 100644
--- a/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/i18n/velbus.properties
+++ b/bundles/org.openhab.binding.velbus/src/main/resources/OH-INF/i18n/velbus.properties
@@ -309,7 +309,7 @@ thing-type.config.velbus.7channelDeviceWithCounters.CH7.description = The name o
thing-type.config.velbus.7channelDeviceWithCounters.address.label = Address
thing-type.config.velbus.7channelDeviceWithCounters.address.description = The velbus address of the device
thing-type.config.velbus.7channelDeviceWithCounters.counter1PulseMultiplier.label = Counter 1 Pulse Multiplier
-thing-type.config.velbus.7channelDeviceWithCounters.counter1PulseMultiplier.description = The pulse multiplier for counter 1
+thing-type.config.velbus.7channelDeviceWithCounters.counter1PulseMultiplier.description = The pulse multiplier for counter 1.
thing-type.config.velbus.7channelDeviceWithCounters.counter1PulseMultiplier.option.1 = x1
thing-type.config.velbus.7channelDeviceWithCounters.counter1PulseMultiplier.option.2.5 = x2.5
thing-type.config.velbus.7channelDeviceWithCounters.counter1PulseMultiplier.option.0.05 = x0.05
@@ -320,7 +320,7 @@ thing-type.config.velbus.7channelDeviceWithCounters.counter1Unit.option.kWh = kW
thing-type.config.velbus.7channelDeviceWithCounters.counter1Unit.option.liters = liters
thing-type.config.velbus.7channelDeviceWithCounters.counter1Unit.option.m³ = m³
thing-type.config.velbus.7channelDeviceWithCounters.counter2PulseMultiplier.label = Counter 2 Pulse Multiplier
-thing-type.config.velbus.7channelDeviceWithCounters.counter2PulseMultiplier.description = The pulse multiplier for counter 2
+thing-type.config.velbus.7channelDeviceWithCounters.counter2PulseMultiplier.description = The pulse multiplier for counter 2.
thing-type.config.velbus.7channelDeviceWithCounters.counter2PulseMultiplier.option.1 = x1
thing-type.config.velbus.7channelDeviceWithCounters.counter2PulseMultiplier.option.2.5 = x2.5
thing-type.config.velbus.7channelDeviceWithCounters.counter2PulseMultiplier.option.0.05 = x0.05
@@ -331,7 +331,7 @@ thing-type.config.velbus.7channelDeviceWithCounters.counter2Unit.option.kWh = kW
thing-type.config.velbus.7channelDeviceWithCounters.counter2Unit.option.liters = liters
thing-type.config.velbus.7channelDeviceWithCounters.counter2Unit.option.m³ = m³
thing-type.config.velbus.7channelDeviceWithCounters.counter3PulseMultiplier.label = Counter 3 Pulse Multiplier
-thing-type.config.velbus.7channelDeviceWithCounters.counter3PulseMultiplier.description = The pulse multiplier for counter 3
+thing-type.config.velbus.7channelDeviceWithCounters.counter3PulseMultiplier.description = The pulse multiplier for counter 3.
thing-type.config.velbus.7channelDeviceWithCounters.counter3PulseMultiplier.option.1 = x1
thing-type.config.velbus.7channelDeviceWithCounters.counter3PulseMultiplier.option.2.5 = x2.5
thing-type.config.velbus.7channelDeviceWithCounters.counter3PulseMultiplier.option.0.05 = x0.05
@@ -342,7 +342,7 @@ thing-type.config.velbus.7channelDeviceWithCounters.counter3Unit.option.kWh = kW
thing-type.config.velbus.7channelDeviceWithCounters.counter3Unit.option.liters = liters
thing-type.config.velbus.7channelDeviceWithCounters.counter3Unit.option.m³ = m³
thing-type.config.velbus.7channelDeviceWithCounters.counter4PulseMultiplier.label = Counter 4 Pulse Multiplier
-thing-type.config.velbus.7channelDeviceWithCounters.counter4PulseMultiplier.description = The pulse multiplier for counter 4
+thing-type.config.velbus.7channelDeviceWithCounters.counter4PulseMultiplier.description = The pulse multiplier for counter 4.
thing-type.config.velbus.7channelDeviceWithCounters.counter4PulseMultiplier.option.1 = x1
thing-type.config.velbus.7channelDeviceWithCounters.counter4PulseMultiplier.option.2.5 = x2.5
thing-type.config.velbus.7channelDeviceWithCounters.counter4PulseMultiplier.option.0.05 = x0.05
diff --git a/bundles/org.openhab.binding.twitter/NOTICE b/bundles/org.openhab.binding.x/NOTICE
similarity index 100%
rename from bundles/org.openhab.binding.twitter/NOTICE
rename to bundles/org.openhab.binding.x/NOTICE
diff --git a/bundles/org.openhab.binding.x/README.md b/bundles/org.openhab.binding.x/README.md
new file mode 100644
index 0000000000000..846ee864b1164
--- /dev/null
+++ b/bundles/org.openhab.binding.x/README.md
@@ -0,0 +1,60 @@
+# X Binding
+
+The X (formerly known as Twitter) binding allows your home to post 280 characters at a time. It also supports direct messages and posting with media.
+
+## Supported Things
+
+```text
+account - X Account.
+```
+
+## Thing Configuration
+
+The X Account Thing requires you to create a X App in the X Developer Page.
+
+| Property | Default | Required | Description |
+|-------------------|---------|:--------:|-----------------------------------|
+| consumerKey | | Yes | Consumer API Key |
+| consumerSecret | | Yes | Consumer API Secret |
+| accessToken | | Yes | Access Token |
+| accessTokenSecret | | Yes | Access Token Secret |
+| refresh | 30 | No | Post refresh interval in minutes |
+
+## Channels
+
+| channel | type | description |
+|----------|--------|-----------------------------------------------|
+| lastpost | String | This channel provides the Latest post message |
+
+## Full Example
+
+x.things:
+
+```java
+Thing x:account:sampleaccount [ consumerKey="11111", consumerSecret="22222", accessToken="33333", accessTokenSecret="444444" ]
+```
+
+x.items:
+
+```java
+String sample_post "Latest post: [%s]" { channel="x:account:sampleaccount:lastpost" }
+```
+
+## Rule Action
+
+This binding includes rule actions for sending posts and direct messages.
+
+- `boolean success = sendPost(String text)`
+- `boolean success = sendPostWithAttachment(String text, String URL)`
+- `boolean success = sendDirectMessage(String recipientID, String text)`
+
+Examples:
+
+```java
+val postActions = getActions("x","x:account:sampleaccount")
+val success = postActions.sendPost("This is A Post")
+val success2 = postActions.sendPostWithAttachment("This is A Post with a Pic", file:///tmp/201601011031.jpg)
+val success3 = postActions.sendPostWithAttachment("Windows Picture", "D:\\Test.png" )
+val success4 = postActions.sendPostWithAttachment("HTTP Picture", "http://www.mywebsite.com/Test.png" )
+val success5 = postActions.sendDirectMessage("1234567", "Wake Up" )
+```
diff --git a/bundles/org.openhab.binding.twitter/pom.xml b/bundles/org.openhab.binding.x/pom.xml
similarity index 67%
rename from bundles/org.openhab.binding.twitter/pom.xml
rename to bundles/org.openhab.binding.x/pom.xml
index 00e42c8b7ff4f..f7020d2f91e9e 100644
--- a/bundles/org.openhab.binding.twitter/pom.xml
+++ b/bundles/org.openhab.binding.x/pom.xml
@@ -10,19 +10,19 @@
4.1.0-SNAPSHOT
- org.openhab.binding.twitter
+ org.openhab.binding.x
- openHAB Add-ons :: Bundles :: Twitter Binding
+ openHAB Add-ons :: Bundles :: X Binding
- !android.*,!com.android.org.*,!dalvik.*,!javax.annotation.meta.*,!org.apache.harmony.*,!org.conscrypt.*,!sun.*,!com.google.appengine.api.*
+ !org.slf4j.impl.*,!android.*,!com.android.org.*,!dalvik.*,!javax.annotation.meta.*,!org.apache.harmony.*,!org.conscrypt.*,!sun.*,!com.google.appengine.api.*org.twitter4jtwitter4j-core
- 4.0.7
+ 4.1.2compile
diff --git a/bundles/org.openhab.binding.twitter/src/main/feature/feature.xml b/bundles/org.openhab.binding.x/src/main/feature/feature.xml
similarity index 53%
rename from bundles/org.openhab.binding.twitter/src/main/feature/feature.xml
rename to bundles/org.openhab.binding.x/src/main/feature/feature.xml
index 86048f2829fcf..ffb954879f7c5 100644
--- a/bundles/org.openhab.binding.twitter/src/main/feature/feature.xml
+++ b/bundles/org.openhab.binding.x/src/main/feature/feature.xml
@@ -1,9 +1,9 @@
-
+mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features
-
+ openhab-runtime-base
- mvn:org.openhab.addons.bundles/org.openhab.binding.twitter/${project.version}
+ mvn:org.openhab.addons.bundles/org.openhab.binding.x/${project.version}
diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XBindingConstants.java
similarity index 72%
rename from bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java
rename to bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XBindingConstants.java
index c42baaeb2ba68..d35f5246b6285 100644
--- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java
+++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XBindingConstants.java
@@ -10,25 +10,25 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.twitter.internal;
+package org.openhab.binding.x.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
- * The {@link TwitterBindingConstants} class defines common constants, which are
+ * The {@link XBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Scott Hanson - Initial contribution
*/
@NonNullByDefault
-public class TwitterBindingConstants {
+public class XBindingConstants {
- private static final String BINDING_ID = "twitter";
+ private static final String BINDING_ID = "x";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account");
// List of all Channel ids
- public static final String CHANNEL_LASTTWEET = "lasttweet";
+ public static final String CHANNEL_LASTPOST = "lastpost";
}
diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandler.java
similarity index 64%
rename from bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java
rename to bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandler.java
index 8b962d7902e9f..b262840e2e6f9 100644
--- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java
+++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandler.java
@@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.twitter.internal;
+package org.openhab.binding.x.internal;
-import static org.openhab.binding.twitter.internal.TwitterBindingConstants.CHANNEL_LASTTWEET;
+import static org.openhab.binding.x.internal.XBindingConstants.CHANNEL_LASTPOST;
import java.io.File;
import java.io.FileNotFoundException;
@@ -27,8 +27,8 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.twitter.internal.action.TwitterActions;
-import org.openhab.binding.twitter.internal.config.TwitterConfig;
+import org.openhab.binding.x.internal.action.XActions;
+import org.openhab.binding.x.internal.config.XConfig;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.library.types.RawType;
import org.openhab.core.library.types.StringType;
@@ -41,28 +41,26 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import twitter4j.DirectMessage;
-import twitter4j.ResponseList;
-import twitter4j.Status;
-import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterException;
-import twitter4j.TwitterFactory;
-import twitter4j.auth.AccessToken;
+import twitter4j.v1.DirectMessage;
+import twitter4j.v1.ResponseList;
+import twitter4j.v1.Status;
+import twitter4j.v1.StatusUpdate;
/**
- * The {@link TwitterHandler} is responsible for handling commands, which are
+ * The {@link XHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Scott Hanson - Initial contribution
*/
@NonNullByDefault
-public class TwitterHandler extends BaseThingHandler {
+public class XHandler extends BaseThingHandler {
- private final Logger logger = LoggerFactory.getLogger(TwitterHandler.class);
+ private final Logger logger = LoggerFactory.getLogger(XHandler.class);
- private TwitterConfig config = new TwitterConfig();
+ private XConfig config = new XConfig();
private @Nullable ScheduledFuture> refreshTask;
@@ -71,7 +69,7 @@ public class TwitterHandler extends BaseThingHandler {
private static @Nullable Twitter client = null;
boolean isProperlyConfigured = false;
- public TwitterHandler(Thing thing) {
+ public XHandler(Thing thing) {
super(thing);
}
@@ -82,14 +80,14 @@ public void handleCommand(ChannelUID channelUID, Command command) {
// creates list of available Actions
@Override
public Collection> getServices() {
- return List.of(TwitterActions.class);
+ return List.of(XActions.class);
}
@Override
public void initialize() {
- config = getConfigAs(TwitterConfig.class);
+ config = getConfigAs(XConfig.class);
- // create a New Twitter Client
+ // create a New X/Twitter Client
Twitter localClient = createClient();
client = localClient;
refresh();// Get latest status
@@ -107,7 +105,7 @@ public void dispose() {
}
/**
- * Internal method for Getting Twitter Status
+ * Internal method for Getting X Status
*
*/
private void refresh() {
@@ -117,83 +115,83 @@ private void refresh() {
}
Twitter localClient = client;
if (localClient != null) {
- ResponseList statuses = localClient.getUserTimeline();
+ ResponseList statuses = localClient.v1().timelines().getUserTimeline();
if (!statuses.isEmpty()) {
- updateState(CHANNEL_LASTTWEET, StringType.valueOf(statuses.get(0).getText()));
+ updateState(CHANNEL_LASTPOST, StringType.valueOf(statuses.get(0).getText()));
} else {
logger.debug("No Statuses Found");
}
}
} catch (TwitterException e) {
- logger.debug("Error when trying to refresh Twitter Account: {}", e.getMessage());
+ logger.debug("Error when trying to refresh X Account: {}", e.getMessage());
}
}
/**
- * Internal method for sending a tweet, with or without image
+ * Internal method for sending a post, with or without image
*
- * @param tweetTxt
- * text string to be sent as a Tweet
+ * @param postTxt
+ * text string to be sent as a Post
* @param fileToAttach
* the file to attach. May be null if no attached file.
*
- * @return true, if sending the tweet has been successful and
+ * @return true, if sending the post has been successful and
* false in all other cases.
*/
- private boolean sendTweet(final String tweetTxt, final @Nullable File fileToAttach) {
+ private boolean sendPost(final String postTxt, final @Nullable File fileToAttach) {
if (!checkPrerequisites()) {
return false;
}
- // abbreviate the Tweet to meet the 280 character limit ...
- String abbreviatedTweetTxt = abbreviateString(tweetTxt, CHARACTER_LIMIT);
+ // abbreviate the Post to meet the 280 character limit ...
+ String abbreviatedPostTxt = abbreviateString(postTxt, CHARACTER_LIMIT);
try {
Twitter localClient = client;
if (localClient != null) {
- // send the Tweet
- StatusUpdate status = new StatusUpdate(abbreviatedTweetTxt);
+ // send the Post
+ StatusUpdate status = StatusUpdate.of(abbreviatedPostTxt);
if (fileToAttach != null && fileToAttach.isFile()) {
- status.setMedia(fileToAttach);
+ status = status.media(fileToAttach);
}
- Status updatedStatus = localClient.updateStatus(status);
- logger.debug("Successfully sent Tweet '{}'", updatedStatus.getText());
- updateState(CHANNEL_LASTTWEET, StringType.valueOf(updatedStatus.getText()));
+ Status updatedStatus = localClient.v1().tweets().updateStatus(status);
+ logger.debug("Successfully sent Post '{}'", updatedStatus.getText());
+ updateState(CHANNEL_LASTPOST, StringType.valueOf(updatedStatus.getText()));
return true;
}
} catch (TwitterException e) {
- logger.warn("Failed to send Tweet '{}' because of : {}", abbreviatedTweetTxt, e.getLocalizedMessage());
+ logger.warn("Failed to send Post '{}' because of : {}", abbreviatedPostTxt, e.getLocalizedMessage());
}
return false;
}
/**
- * Sends a standard Tweet.
+ * Sends a standard Post.
*
- * @param tweetTxt
- * text string to be sent as a Tweet
+ * @param postTxt
+ * text string to be sent as a Post
*
- * @return true, if sending the tweet has been successful and
+ * @return true, if sending the post has been successful and
* false in all other cases.
*/
- public boolean sendTweet(String tweetTxt) {
+ public boolean sendPost(String postTxt) {
if (!checkPrerequisites()) {
return false;
}
- return sendTweet(tweetTxt, (File) null);
+ return sendPost(postTxt, (File) null);
}
/**
- * Sends a Tweet with an image
+ * Sends a Post with an image
*
- * @param tweetTxt
- * text string to be sent as a Tweet
- * @param tweetPicture
+ * @param postTxt
+ * text string to be sent as a Post
+ * @param postPicture
* the path of the picture that needs to be attached (either an url,
* either a path pointing to a local file)
*
- * @return true, if sending the tweet has been successful and
+ * @return true, if sending the post has been successful and
* false in all other cases.
*/
- public boolean sendTweet(String tweetTxt, String tweetPicture) {
+ public boolean sendPost(String postTxt, String postPicture) {
if (!checkPrerequisites()) {
return false;
}
@@ -201,18 +199,18 @@ public boolean sendTweet(String tweetTxt, String tweetPicture) {
// prepare the image attachment
File fileToAttach = null;
boolean deleteTemporaryFile = false;
- if (tweetPicture.startsWith("http://") || tweetPicture.startsWith("https://")) {
+ if (postPicture.startsWith("http://") || postPicture.startsWith("https://")) {
try {
// we have a remote url and need to download the remote file to a temporary location
Path tDir = Files.createTempDirectory("TempDirectory");
- String path = tDir + File.separator + "openhab-twitter-remote_attached_file" + "."
- + getExtension(tweetPicture);
+ String path = tDir + File.separator + "openhab-x-remote_attached_file" + "."
+ + getExtension(postPicture);
- // URL url = new URL(tweetPicture);
+ // URL url = new URL(postPicture);
fileToAttach = new File(path);
deleteTemporaryFile = true;
- RawType rawPicture = HttpUtil.downloadImage(tweetPicture);
+ RawType rawPicture = HttpUtil.downloadImage(postPicture);
if (rawPicture != null) {
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(rawPicture.getBytes(), 0, rawPicture.getBytes().length);
@@ -222,24 +220,24 @@ public boolean sendTweet(String tweetTxt, String tweetPicture) {
logger.debug("Could not write {} to temp dir. {}", path, ex.getMessage());
}
} else {
- logger.debug("Could not download tweet file from {}", tweetPicture);
+ logger.debug("Could not download post file from {}", postPicture);
}
} catch (IOException ex) {
- logger.debug("Could not write {} to temp dir. {}", tweetPicture, ex.getMessage());
+ logger.debug("Could not write {} to temp dir. {}", postPicture, ex.getMessage());
}
} else {
// we have a local file and can just use it directly
- fileToAttach = new File(tweetPicture);
+ fileToAttach = new File(postPicture);
}
if (fileToAttach != null && fileToAttach.isFile()) {
- logger.debug("Image '{}' correctly found, will be included in tweet", tweetPicture);
+ logger.debug("Image '{}' correctly found, will be included in post", postPicture);
} else {
- logger.warn("Image '{}' not found, will only tweet text", tweetPicture);
+ logger.warn("Image '{}' not found, will only post text", postPicture);
}
- // send the Tweet
- boolean result = sendTweet(tweetTxt, fileToAttach);
+ // send the Post
+ boolean result = sendPost(postTxt, fileToAttach);
// delete temp file (if needed)
if (deleteTemporaryFile) {
if (fileToAttach != null) {
@@ -272,10 +270,11 @@ public boolean sendDirectMessage(String recipientId, String messageTxt) {
try {
Twitter localClient = client;
if (localClient != null) {
- // abbreviate the Tweet to meet the allowed character limit ...
+ // abbreviate the Post to meet the allowed character limit ...
String abbreviatedMessageTxt = abbreviateString(messageTxt, CHARACTER_LIMIT);
// send the direct message
- DirectMessage message = localClient.sendDirectMessage(recipientId, abbreviatedMessageTxt);
+ DirectMessage message = localClient.v1().directMessages().sendDirectMessage(recipientId,
+ abbreviatedMessageTxt);
logger.debug("Successfully sent direct message '{}' to @'{}'", message.getText(),
message.getRecipientId());
return true;
@@ -287,18 +286,18 @@ public boolean sendDirectMessage(String recipientId, String messageTxt) {
}
/**
- * check if twitter account was created with prerequisites
- *
- * @return true, if twitter account was initialized
+ * check if X account was created with prerequisites
+ *
+ * @return true, if X account was initialized
* false in all other cases.
*/
private boolean checkPrerequisites() {
if (client == null) {
- logger.debug("Twitter client is not yet configured > execution aborted!");
+ logger.debug("X client is not yet configured > execution aborted!");
return false;
}
if (!isProperlyConfigured) {
- logger.debug("Twitter client is not yet configured > execution aborted!");
+ logger.debug("X client is not yet configured > execution aborted!");
return false;
}
return true;
@@ -310,9 +309,9 @@ private boolean checkPrerequisites() {
* @return a new instance of a Twitter4J Twitter client.
*/
private twitter4j.Twitter createClient() {
- twitter4j.Twitter client = TwitterFactory.getSingleton();
- client.setOAuthConsumer(config.consumerKey, config.consumerSecret);
- client.setOAuthAccessToken(new AccessToken(config.accessToken, config.accessTokenSecret));
+ Twitter client = Twitter.newBuilder().oAuthConsumer(config.consumerKey, config.consumerSecret)
+ .oAuthAccessToken(config.accessToken, config.accessTokenSecret).build();
+
return client;
}
diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandlerFactory.java
similarity index 76%
rename from bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java
rename to bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandlerFactory.java
index d27f76f7bd945..50a9341d2525a 100644
--- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java
+++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandlerFactory.java
@@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.twitter.internal;
+package org.openhab.binding.x.internal;
-import static org.openhab.binding.twitter.internal.TwitterBindingConstants.THING_TYPE_ACCOUNT;
+import static org.openhab.binding.x.internal.XBindingConstants.THING_TYPE_ACCOUNT;
import java.util.Set;
@@ -26,14 +26,14 @@
import org.osgi.service.component.annotations.Component;
/**
- * The {@link TwitterHandlerFactory} is responsible for creating things and thing
+ * The {@link XHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Scott Hanson - Initial contribution
*/
@NonNullByDefault
-@Component(configurationPid = "binding.twitter", service = ThingHandlerFactory.class)
-public class TwitterHandlerFactory extends BaseThingHandlerFactory {
+@Component(configurationPid = "binding.x", service = ThingHandlerFactory.class)
+public class XHandlerFactory extends BaseThingHandlerFactory {
private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT);
@@ -47,7 +47,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (THING_TYPE_ACCOUNT.equals(thingTypeUID)) {
- return new TwitterHandler(thing);
+ return new XHandler(thing);
}
return null;
diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/action/XActions.java
similarity index 60%
rename from bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java
rename to bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/action/XActions.java
index 12a56c3574161..8133645ddf4f5 100644
--- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java
+++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/action/XActions.java
@@ -10,11 +10,11 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.twitter.internal.action;
+package org.openhab.binding.x.internal.action;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.twitter.internal.TwitterHandler;
+import org.openhab.binding.x.internal.XHandler;
import org.openhab.core.automation.annotation.ActionInput;
import org.openhab.core.automation.annotation.ActionOutput;
import org.openhab.core.automation.annotation.RuleAction;
@@ -25,53 +25,53 @@
import org.slf4j.LoggerFactory;
/**
- * The {@link TwitterActions} class defines rule actions for sending tweet
+ * The {@link XActions} class defines rule actions for sending post
*
* @author Scott Hanson - Initial contribution
*/
-@ThingActionsScope(name = "twitter")
+@ThingActionsScope(name = "x")
@NonNullByDefault
-public class TwitterActions implements ThingActions {
+public class XActions implements ThingActions {
- private final Logger logger = LoggerFactory.getLogger(TwitterActions.class);
+ private final Logger logger = LoggerFactory.getLogger(XActions.class);
- private @Nullable TwitterHandler handler;
+ private @Nullable XHandler handler;
- @RuleAction(label = "@text/sendTweetActionLabel", description = "@text/sendTweetActionDescription")
- public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendTweet(
+ @RuleAction(label = "@text/sendPostActionLabel", description = "@text/sendPostActionDescription")
+ public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPost(
@ActionInput(name = "text") @Nullable String text) {
if (text == null) {
- logger.warn("Cannot send Tweet as text is missing.");
+ logger.warn("Cannot send Post as text is missing.");
return false;
}
- final TwitterHandler handler = this.handler;
+ final XHandler handler = this.handler;
if (handler == null) {
- logger.debug("Handler is null, cannot tweet.");
+ logger.debug("Handler is null, cannot post.");
return false;
} else {
- return handler.sendTweet(text);
+ return handler.sendPost(text);
}
}
- @RuleAction(label = "@text/sendAttachmentTweetActionLabel", description = "@text/sendAttachmentTweetActionDescription")
- public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendTweetWithAttachment(
+ @RuleAction(label = "@text/sendAttachmentPostActionLabel", description = "@text/sendAttachmentPostActionDescription")
+ public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPostWithAttachment(
@ActionInput(name = "text") @Nullable String text, @ActionInput(name = "url") @Nullable String urlString) {
if (text == null) {
- logger.warn("Cannot send Tweet as text is missing.");
+ logger.warn("Cannot send Post as text is missing.");
return false;
}
if (urlString == null) {
- logger.warn("Cannot send Tweet as urlString is missing.");
+ logger.warn("Cannot send Post as urlString is missing.");
return false;
}
- final TwitterHandler handler = this.handler;
+ final XHandler handler = this.handler;
if (handler == null) {
- logger.debug("Handler is null, cannot tweet.");
+ logger.debug("Handler is null, cannot post.");
return false;
} else {
- return handler.sendTweet(text, urlString);
+ return handler.sendPost(text, urlString);
}
}
@@ -88,32 +88,32 @@ public class TwitterActions implements ThingActions {
return false;
}
- final TwitterHandler handler = this.handler;
+ final XHandler handler = this.handler;
if (handler == null) {
- logger.debug("Handler is null, cannot tweet.");
+ logger.debug("Handler is null, cannot post.");
return false;
} else {
return handler.sendDirectMessage(recipient, text);
}
}
- public static boolean sendTweet(ThingActions actions, @Nullable String text) {
- return ((TwitterActions) actions).sendTweet(text);
+ public static boolean sendPost(ThingActions actions, @Nullable String text) {
+ return ((XActions) actions).sendPost(text);
}
- public static boolean sendTweetWithAttachment(ThingActions actions, @Nullable String text,
+ public static boolean sendPostWithAttachment(ThingActions actions, @Nullable String text,
@Nullable String urlString) {
- return ((TwitterActions) actions).sendTweetWithAttachment(text, urlString);
+ return ((XActions) actions).sendPostWithAttachment(text, urlString);
}
public static boolean sendDirectMessage(ThingActions actions, @Nullable String recipient, @Nullable String text) {
- return ((TwitterActions) actions).sendDirectMessage(recipient, text);
+ return ((XActions) actions).sendDirectMessage(recipient, text);
}
@Override
public void setThingHandler(@Nullable ThingHandler handler) {
- if (handler instanceof TwitterHandler twitterHandler) {
- this.handler = twitterHandler;
+ if (handler instanceof XHandler xHandler) {
+ this.handler = xHandler;
}
}
diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/config/XConfig.java
similarity index 80%
rename from bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java
rename to bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/config/XConfig.java
index 529bee31a858a..73e11d9dd7547 100644
--- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java
+++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/config/XConfig.java
@@ -10,18 +10,18 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.twitter.internal.config;
+package org.openhab.binding.x.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
- * The {@link TwitterConfig} class contains fields mapping thing configuration parameters.
+ * The {@link XConfig} class contains fields mapping thing configuration parameters.
*
* @author Scott Hanson - Initial contribution
*/
@NonNullByDefault
-public class TwitterConfig {
+public class XConfig {
public String consumerKey = "";
public String consumerSecret = "";
public String accessToken = "";
diff --git a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/addon/addon.xml
similarity index 56%
rename from bundles/org.openhab.binding.myq/src/main/resources/OH-INF/addon/addon.xml
rename to bundles/org.openhab.binding.x/src/main/resources/OH-INF/addon/addon.xml
index a63b7da74fde1..acb27648087c2 100644
--- a/bundles/org.openhab.binding.myq/src/main/resources/OH-INF/addon/addon.xml
+++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/addon/addon.xml
@@ -1,11 +1,11 @@
-binding
- MyQ Binding
- The MyQ binding allows monitoring and control of garage doors that are MyQ enabled.
+ X Binding
+ Supports adding Thing for getting the Last Post. Send Posts and Pictures with Actions.cloud
diff --git a/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x.properties b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x.properties
new file mode 100644
index 0000000000000..66bc6924ed3df
--- /dev/null
+++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x.properties
@@ -0,0 +1,32 @@
+# add-on
+
+addon.x.name = X Binding
+addon.x.description = Supports adding Thing for getting the Last Post. Send Posts and Pictures with Actions.
+
+# thing types
+
+thing-type.x.account.label = X Account
+thing-type.x.account.description = Account uses for sending posts
+
+# thing types config
+
+thing-type.config.x.account.accessToken.label = Access Token
+thing-type.config.x.account.accessTokenSecret.label = Access Token Secret
+thing-type.config.x.account.consumerKey.label = Consumer API Key
+thing-type.config.x.account.consumerSecret.label = Consumer API Secret
+thing-type.config.x.account.refresh.label = Refresh Time
+thing-type.config.x.account.refresh.description = Refresh Time for This Account in Mins
+
+# channel types
+
+channel-type.x.lastpost.label = Last Post
+channel-type.x.lastpost.description = Users Last Post
+
+# actions
+
+sendAttachmentPostActionLabel = send a Post with attachment
+sendAttachmentPostActionDescription = Sends a Post with an attachment.
+sendDirectMessageActionLabel = send a DirectMessage
+sendDirectMessageActionDescription = Sends a DirectMessage.
+sendPostActionLabel = send a Post
+sendPostActionDescription = Sends a Post.
diff --git a/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x_it.properties b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x_it.properties
new file mode 100644
index 0000000000000..016fe4d68bba6
--- /dev/null
+++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x_it.properties
@@ -0,0 +1,32 @@
+# add-on
+
+addon.x.name = Binding X
+addon.x.description = Supporta l'aggiunta di Thing per ottenere l'ultimo Post. Invia messaggi e immagini con azioni.
+
+# thing types
+
+thing-type.x.account.label = Account X
+thing-type.x.account.description = Account utilizzato per inviare messaggi
+
+# thing types config
+
+thing-type.config.x.account.accessToken.label = Token Accesso
+thing-type.config.x.account.accessTokenSecret.label = Segreto per Token di Accesso
+thing-type.config.x.account.consumerKey.label = Chiave API utente
+thing-type.config.x.account.consumerSecret.label = Segreti API utente
+thing-type.config.x.account.refresh.label = Tempo di aggiornamento
+thing-type.config.x.account.refresh.description = Aggiorna il tempo per questo account in Minuti
+
+# channel types
+
+channel-type.x.lastpost.label = Ultimo Post
+channel-type.x.lastpost.description = Ultimo Post Utenti
+
+# actions
+
+sendAttachmentPostActionLabel = invia un Post con allegato
+sendAttachmentPostActionDescription = Invia un Post con un allegato.
+sendDirectMessageActionLabel = invia un DirectMessage
+sendDirectMessageActionDescription = Invia un DirectMessage.
+sendPostActionLabel = invia un Post
+sendPostActionDescription = Invia un Messaggio.
diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/thing/thing-types.xml
similarity index 78%
rename from bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml
rename to bundles/org.openhab.binding.x/src/main/resources/OH-INF/thing/thing-types.xml
index 1ec1355e99059..d18df8f5e1c0c 100644
--- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml
+++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/thing/thing-types.xml
@@ -1,15 +1,14 @@
-
-
- Account uses for sending Tweets
+
+ Account uses for sending posts
-
+
@@ -38,10 +37,10 @@
-
+ String
-
- Users Last Tweet
+
+ Users Last Post
diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java
index 358bd778a2eb2..ee2ba5190facb 100644
--- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java
+++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java
@@ -286,6 +286,7 @@ private void commit() {
if (!influxDBRepository.write(points)) {
logger.warn("Re-queuing {} elements, failed to write batch.", points.size());
pointsQueue.addAll(points);
+ influxDBRepository.disconnect();
} else {
logger.trace("Wrote {} elements to database", points.size());
}
diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java
index 862ecf4c2ba31..77ef198009a2b 100644
--- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java
+++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java
@@ -44,6 +44,7 @@
import com.influxdb.client.InfluxDBClientOptions;
import com.influxdb.client.QueryApi;
import com.influxdb.client.WriteApi;
+import com.influxdb.client.domain.HealthCheck;
import com.influxdb.client.domain.Ready;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
@@ -76,7 +77,8 @@ public InfluxDB2RepositoryImpl(InfluxDBConfiguration configuration,
@Override
public boolean isConnected() {
- return client != null;
+ InfluxDBClient client = this.client;
+ return client != null && client.health().getStatus() == HealthCheck.StatusEnum.PASS;
}
@Override
diff --git a/bundles/org.openhab.persistence.influxdb/src/main/resources/OH-INF/i18n/influxdb_fr.properties b/bundles/org.openhab.persistence.influxdb/src/main/resources/OH-INF/i18n/influxdb_fr.properties
index 747f9aa6c35b8..7cc337b02b6ed 100644
--- a/bundles/org.openhab.persistence.influxdb/src/main/resources/OH-INF/i18n/influxdb_fr.properties
+++ b/bundles/org.openhab.persistence.influxdb/src/main/resources/OH-INF/i18n/influxdb_fr.properties
@@ -1,3 +1,10 @@
+# add-on
+
+addon.influxdb.name = Persistance InfluxDB
+addon.influxdb.description = Il s'agit du service de persistance pour InfluxDB.
+
+# add-on
+
persistence.config.influxdb.addCategoryTag.label = Ajouter balise catégory
persistence.config.influxdb.addCategoryTag.description = La catégorie de l'élément doit-elle être incluse en tant que balise "category" ? Si aucune catégorie n'est définie, "n/a" sera utilisé.
persistence.config.influxdb.addLabelTag.label = Ajouter balise label
@@ -28,7 +35,3 @@ persistence.config.influxdb.version.label = Version de la base de données
persistence.config.influxdb.version.description = Version de InfluxDB
persistence.config.influxdb.version.option.V1 = InfluxDB 1
persistence.config.influxdb.version.option.V2 = InfluxDB 2
-
-# service
-
-service.persistence.influxdb.label = Service d'historisation InfluxDB
diff --git a/bundles/org.openhab.persistence.jpa/src/main/resources/OH-INF/i18n/jpa_fr.properties b/bundles/org.openhab.persistence.jpa/src/main/resources/OH-INF/i18n/jpa_fr.properties
new file mode 100644
index 0000000000000..531c3c7a61746
--- /dev/null
+++ b/bundles/org.openhab.persistence.jpa/src/main/resources/OH-INF/i18n/jpa_fr.properties
@@ -0,0 +1,17 @@
+# add-on
+
+addon.jpa.name = Persistance JPA
+addon.jpa.description = Il s'agit du service de persistance pour JPA.
+
+# add-on config
+
+persistence.config.jpa.driver.label = Pilote de base de données
+persistence.config.jpa.driver.description = Le nom de la classe du pilote JDBC pour la connexion. Exemples\: com.mysql.jdbc.Driver org.apache.derby.jdbc.ClientDriver org.mariadb.jdbc.Driver org.postgresql.Driver
+persistence.config.jpa.password.label = Mot de passe de la base de données
+persistence.config.jpa.password.description = Le mot de passe de l'utilisateur de la base de données pour la connexion.
+persistence.config.jpa.syncmappings.label = Synchroniser les mappings
+persistence.config.jpa.syncmappings.description = La configuration des mappings de synchronisation OpenJPA.
+persistence.config.jpa.url.label = URL de la base de données
+persistence.config.jpa.url.description = URL de connexion JDBC. Exemples\: jdbc\:derby\://hab.local\:1527/openhab;create\=true jdbc\:mariadb\://localhost\:3306/openhab jdbc\:mysql\://localhost\:3306/openhab jdbc\:postgresql\://hab.local\:5432/openhab
+persistence.config.jpa.user.label = Utilisateur de la base de données
+persistence.config.jpa.user.description = Le nom d'utilisateur de la base de données pour la connexion.
diff --git a/bundles/pom.xml b/bundles/pom.xml
index e992b98ac4dfc..bc0ef858994b9 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -258,7 +258,6 @@
org.openhab.binding.mybmworg.openhab.binding.mycroftorg.openhab.binding.mynice
- org.openhab.binding.myqorg.openhab.binding.mystromorg.openhab.binding.nanoleaforg.openhab.binding.neato
@@ -387,7 +386,6 @@
org.openhab.binding.tplinksmarthomeorg.openhab.binding.tr064org.openhab.binding.tradfri
- org.openhab.binding.twitterorg.openhab.binding.unifiorg.openhab.binding.unifiedremoteorg.openhab.binding.upnpcontrol
@@ -419,6 +417,7 @@
org.openhab.binding.wledorg.openhab.binding.wolfsmartsetorg.openhab.binding.wundergroundupdatereceiver
+ org.openhab.binding.xorg.openhab.binding.xmltvorg.openhab.binding.xmppclientorg.openhab.binding.yamahamusiccast
diff --git a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java
index 6be21f452cc4d..b1cac633dbcca 100644
--- a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java
+++ b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java
@@ -32,10 +32,10 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.openhab.binding.hue.internal.api.dto.clip1.FullLight;
import org.openhab.binding.hue.internal.config.HueBridgeConfig;
import org.openhab.binding.hue.internal.connection.HueBridge;
import org.openhab.binding.hue.internal.discovery.HueDeviceDiscoveryService;
-import org.openhab.binding.hue.internal.dto.FullLight;
import org.openhab.binding.hue.internal.exceptions.ApiException;
import org.openhab.binding.hue.internal.handler.HueBridgeHandler;
import org.openhab.core.config.core.Configuration;
diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java
index 4bf6be8374ce3..c514b3159e4ee 100644
--- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java
+++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java
@@ -22,6 +22,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
@@ -160,7 +161,8 @@ public void parseHATree() throws Exception {
ComponentDiscovered cd = (haID, c) -> {
haComponents.put(c.getGroupUID().getId(), c);
c.addChannelTypes(channelTypeProvider);
- channelTypeProvider.setChannelGroupType(c.getGroupTypeUID(), c.getType());
+ channelTypeProvider.setChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()),
+ Objects.requireNonNull(c.getType()));
latch.countDown();
};
diff --git a/tools/static-code-analysis/checkstyle/ruleset.properties b/tools/static-code-analysis/checkstyle/ruleset.properties
index acac1eb1ac612..491f7c9101753 100644
--- a/tools/static-code-analysis/checkstyle/ruleset.properties
+++ b/tools/static-code-analysis/checkstyle/ruleset.properties
@@ -1,6 +1,6 @@
checkstyle.headerCheck.content=^/\\*\\*$\\n^ \\* Copyright \\(c\\) {0}-{1} Contributors to the openHAB project$\\n^ \\*$\\n^ \\* See the NOTICE file\\(s\\) distributed with this work for additional$\\n^ \\* information.$\\n^ \\*$\\n^ \\* This program and the accompanying materials are made available under the$\\n^ \\* terms of the Eclipse Public License 2\\.0 which is available at$\\n^ \\* http://www.eclipse.org/legal/epl\\-2\\.0$\\n^ \\*$\\n^ \\* SPDX-License-Identifier: EPL-2.0$
checkstyle.headerCheck.values=2010,2023
-checkstyle.forbiddenPackageUsageCheck.forbiddenPackages=com.google.common,gnu.io,javax.comm,org.apache.commons,org.joda.time,org.junit.Assert,org.junit.Test,si.uom,tech.units
+checkstyle.forbiddenPackageUsageCheck.forbiddenPackages=com.fazecast.jSerialComm,com.google.common,gnu.io,javax.comm,org.apache.commons,org.joda.time,org.junit.Assert,org.junit.Test,purejavacomm,si.uom,tech.units
checkstyle.forbiddenPackageUsageCheck.exceptions=
checkstyle.requiredFilesCheck.files=pom.xml
checkstyle.karafAddonFeatureCheck.featureNameMappings=-transform-:-transformation-,-io-:-misc-