]> git.basschouten.com Git - openhab-addons.git/commitdiff
[freeathome] Rename binding from freeathomesystem (#16718)
authorlsiepel <leosiepel@gmail.com>
Sun, 5 May 2024 20:50:06 +0000 (22:50 +0200)
committerGitHub <noreply@github.com>
Sun, 5 May 2024 20:50:06 +0000 (22:50 +0200)
* Remove 'System' from the binding name

Signed-off-by: Leo Siepel <leosiepel@gmail.com>
72 files changed:
CODEOWNERS
bundles/org.openhab.binding.freeathome/NOTICE [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/README.md [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/pom.xml [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeDiscoveryService.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeHandlerFactory.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeBridgeHandlerConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeDeviceHandlerConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapoint.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapointGroup.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceChannel.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceDescription.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeBridgeHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceStateListener.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProvider.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProviderImpl.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProvider.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProviderImpl.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FidTranslationUtils.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeGeneralException.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeHttpCommunicationException.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PIdContainerClass.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PidTranslationUtils.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/UidUtils.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BinaryValueStateConverter.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BooleanValueStateConverter.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/DecimalValueStateConverter.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ShuttercontrolValueStateConverter.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ValueStateConverter.java [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/addon/addon.xml [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/i18n/freeathomesystem.properties [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/thing/bridge-type.xml [new file with mode: 0644]
bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/thing/thing-type.xml [new file with mode: 0644]
bundles/org.openhab.binding.freeathomesystem/NOTICE [deleted file]
bundles/org.openhab.binding.freeathomesystem/README.md [deleted file]
bundles/org.openhab.binding.freeathomesystem/pom.xml [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/feature/feature.xml [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemBindingConstants.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemDiscoveryService.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemHandlerFactory.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeBridgeHandlerConfiguration.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeDeviceHandlerConfiguration.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapoint.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapointGroup.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceChannel.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceDescription.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeBridgeHandler.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceHandler.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceStateListener.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProvider.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProviderImpl.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProvider.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProviderImpl.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FidTranslationUtils.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeGeneralException.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeHttpCommunicationException.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PIdContainerClass.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PidTranslationUtils.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/UidUtils.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BinaryValueStateConverter.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BooleanValueStateConverter.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/DecimalValueStateConverter.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ShuttercontrolValueStateConverter.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ValueStateConverter.java [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/addon/addon.xml [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/i18n/freeathomesystem.properties [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/thing/bridge-type.xml [deleted file]
bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/thing/thing-type.xml [deleted file]
bundles/pom.xml

index 837752664f4556cdf6e38a8c64bbb9daf4609635..274522c5055a4d1701bde2e016795b47ab343bd2 100644 (file)
 /bundles/org.openhab.binding.folderwatcher/ @goopilot
 /bundles/org.openhab.binding.folding/ @fa2k
 /bundles/org.openhab.binding.foobot/ @airboxlab @Hilbrand
-/bundles/org.openhab.binding.freeathomesystem/ @andrasU
+/bundles/org.openhab.binding.freeathome/ @andrasU
 /bundles/org.openhab.binding.freebox/ @lolodomo
 /bundles/org.openhab.binding.freeboxos/ @clinique
 /bundles/org.openhab.binding.freecurrency/ @J-N-K
diff --git a/bundles/org.openhab.binding.freeathome/NOTICE b/bundles/org.openhab.binding.freeathome/NOTICE
new file mode 100644 (file)
index 0000000..38d625e
--- /dev/null
@@ -0,0 +1,13 @@
+This content is produced and maintained by the openHAB project.
+
+* Project home: https://www.openhab.org
+
+== Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License 2.0 which is available at
+https://www.eclipse.org/legal/epl-2.0/.
+
+== Source Code
+
+https://github.com/openhab/openhab-addons
diff --git a/bundles/org.openhab.binding.freeathome/README.md b/bundles/org.openhab.binding.freeathome/README.md
new file mode 100644 (file)
index 0000000..b2a309e
--- /dev/null
@@ -0,0 +1,143 @@
+# ABB/Busch-free@home Smart Home binding
+
+openHAB ABB/Busch-free@home binding based on the offical free@home local API.
+
+# Description
+
+This binding allows you to connect your free@home Smart Home system from ABB / Busch-Jaeger to openHAB and to control and observe most of the components.
+It requires a System Access Point with version 2.6.1 or higher.
+
+# Supported Devices
+
+**Network Gateway / System Access Point**
+
+ - ABB / Busch-Jaeger System Access Point 2.0
+
+**Sensors and Actuators**
+
+ - Switch Actuator Sensor with single and multiple channels (wired and wireless)
+ - Dimming Actuator Sensor with single and multiple channels (wired, wireless and flex)
+ - Motion detection with and without actuator (wired, wireless and flex)
+ - Switch Actuator 4-channel
+ - Dimming Actuator 4- and 6-channel
+ - Door opener actuator
+ - Door ring sensor
+ - Hue devices (untested)
+
+**Blinds and Windows**
+
+ - Shutter Actuator with single and multiple channels (wired and wireless)
+ - Blind Actuator  with single and multiple channels (wired and wireless)
+ - Attic window actuator
+ - Awning actuator
+
+**Room Temperature Control**
+
+ - Room temperature controller master without fan
+ - Room temperature controller master with fan
+ - Room temperature controller slave
+
+**Other devices** (e.g. movement detector, ring sensor and door opener)
+
+ - IP-touch panel (function: door opener, door ring sensor)
+ - Virtual devices (e.g. virtual switch, RTC and detectors)
+
+**Information about virtual devices**
+Virtual device in the free@home smart-home system needs continuous keep-alive signal otherwise the free@home device is marked as unresponsive.
+This keep-alive signal must be provided by a user script or set the TTL value of the virtual device to "-1" during the creation of the virtual device.
+
+# Tested SysAP Versions
+
+| Version | Supported |
+|---------|-----------|
+| 2.6.1   | yes       |
+| 2.6.3   | yes       |
+| 3.1.1   | yes       |
+
+# Setup / Installation
+
+## Prerequisites
+
+To make use of this Binding first the local free@home API has to be activated.
+The API is disabled by default.
+
+1. Open the free@home next app
+1. Browse to "Settings ⇨ free@home settings ⇨ local API and activate the checkbox
+
+## Setup and Discovery
+
+The free@home bridge shall be added manually.
+Once it is added as a Thing with correct credentials, the scan of free@home devices will be possible.
+
+## free@home components as openHAB Things
+
+The ABB/Busch free@home system is calling its smart home components as free@home devices.
+The free@home system devices can have one or multiple channels depending the device's features.
+During the scanning process the openHAB binding will detect only the devices IDs.
+The device features will be detected at the point in time, when a openHAB Thing is created.
+At the of the creation the free@home binding will automatically create the relevant channels without any further configuration.
+If a free@home system device has multiple smart-home channels (e.g. 4x DIN/rail Actuator), the newly created Thing will get all relevant channels to operate all actuators existing inside the free@home device.
+
+## Sensors and Actuators of free@home Devices as Things in openHAB
+
+The free@home system supports sensors and actuators.
+The connection of sensors and actuators are done on the free@home system dashboard.
+If a Thing channel is a free@home device sensor channel, this channel is read only.
+
+## Bridge Configuration
+
+There are several settings for a bridge:
+
+| Parameter                | Description                             |
+|--------------------------|-----------------------------------------|
+| **ipAddress** (required) | Network address of the free@home SysAP  |
+| **username** (required)  | Valid user name for the free@home SysAP |
+| **password** (required)  | Password of the user                    |
+
+## Examples for .things
+
+Things are all discovered automatically and visible on the openHAB UI after pushing the scan button
+
+In order to manually configure a Thing:
+
+```java
+Bridge freeathome:bridge:mysysap [ ipAddress="...", username="...", password="..." ]
+{
+    Thing device    ABB700000001
+    Thing device    ABB700000012
+}
+```
+
+The only parameter needed to create a Thing is the free@home device ID, which you can find as sticker on the device.
+The creation of the openHAB channels to operate the free@home device is happening automatically based on the device features detected online.
+
+## Examples for .items
+
+Sample for the free@home thermostat device
+
+```java
+Switch Livingroom_Thermostat_Switch                       "Thermostat Siwtch"               <temperature>  (Livingroom)                              { channel="freeathome:device:312095ad75:ABB700000001:ch0000#controller-on-off-request" }
+Switch LivingRoom_Thermostat_EcoOnOff                     "Thermostat Eco Activation"       <switch>       (Livingroom)                              { channel="freeathome:device:312095ad75:ABB700000001:ch0000#eco-mode-on-off-request" }
+Number LivingRoom_Thermostat_MeasuredTemperature          "Measured Temperature"            <temperature>  (Livingroom)  ["Temperature"]             { channel="freeathome:device:312095ad75:ABB700000001:ch0000#measured-temperature" }
+Number LivingRoom_Thermostat_SetpointTemperature          "Setpoint Temperature"            <temperature>  (Livingroom)  ["Setpoint", "Temperature"] { channel="freeathome:device:312095ad75:ABB700000001:ch0000#absolute-setpoint-temperature" }
+Number LivingRoom_ThermostatHeatingActive                 "Thermostat Heating Active"       <temperature>  (Livingroom)  ["Status"]                  { channel="freeathome:device:312095ad75:ABB700000001:ch0000#heating-active" }
+Number LivingRoom_ThermostatHeatingDemand                 "Thermostat Heating Demand"       <temperature>  (Livingroom)  ["Status"]                  { channel="freeathome:device:312095ad75:ABB700000001:ch0000#status-indication" }
+```
+
+Sample for the free@home device for switch
+
+```java
+Switch Livingroom_Switch                    "Livingroom Switch"       <switch>  (Livingroom)  ["Light"]   { channel="freeathome:device:312095ad75:ABB700000012:ch0000#switch-on-off" }
+Switch Livingroom_Lamp                      "Livingroom Lamp"         <switch>  (Livingroom)  ["Light"]   { channel="freeathome:device:312095ad75:ABB700000012:ch0006#switch-on-off" }
+Switch Livingroom_Aux                       "Livingroom Aux Switch"   <switch>  (Livingroom)  ["Light"]   { channel="freeathome:device:312095ad75:ABB700000012:ch000b#switch-on-off" }
+```
+
+# Communities
+
+[openHAB community of this binding](https://community.openhab.org/t/abb-busch-jager-free-home-official-rest-api/141698)
+
+[Busch-Jaeger Community](https://community.busch-jaeger.de/)
+
+[free@home user group Facebook DE](https://www.facebook.com/groups/738242583015188)
+
+[free@home user group Facebook EN](https://www.facebook.com/groups/452502972031360)
diff --git a/bundles/org.openhab.binding.freeathome/pom.xml b/bundles/org.openhab.binding.freeathome/pom.xml
new file mode 100644 (file)
index 0000000..8d473a5
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.openhab.addons.bundles</groupId>
+    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+    <version>4.2.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.binding.freeathome</artifactId>
+
+  <name>openHAB Add-ons :: Bundles :: FreeAtHome Binding</name>
+
+</project>
diff --git a/bundles/org.openhab.binding.freeathome/src/main/feature/feature.xml b/bundles/org.openhab.binding.freeathome/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..19446fc
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.freeathome-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+       <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+       <feature name="openhab-binding-freeathome" description="FreeAtHome Binding" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.freeathome/${project.version}</bundle>
+       </feature>
+</features>
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeBindingConstants.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeBindingConstants.java
new file mode 100644 (file)
index 0000000..ea41635
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link FreeAtHomeBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Andras Uhrin - Initial contribution
+ */
+@NonNullByDefault
+public class FreeAtHomeBindingConstants {
+
+    public static final String CONFIG_DESCRIPTION_URI_THING_PREFIX = "thing-type";
+
+    public static final String BINDING_ID = "freeathome";
+
+    // List of all Thing Type UIDs
+    public static final String BRIDGE_TYPE_ID = "gateway";
+    public static final String DEVICE_TYPE_ID = "device";
+
+    // List of all Thing Type UIDs
+    public static final ThingTypeUID BRIDGE_TYPE_UID = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_ID);
+    public static final ThingTypeUID DEVICE_TYPE_UID = new ThingTypeUID(BINDING_ID, DEVICE_TYPE_ID);
+
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(BRIDGE_TYPE_UID, DEVICE_TYPE_UID);
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeDiscoveryService.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeDiscoveryService.java
new file mode 100644 (file)
index 0000000..18988e2
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDeviceDescription;
+import org.openhab.binding.freeathome.internal.handler.FreeAtHomeBridgeHandler;
+import org.openhab.binding.freeathome.internal.util.FreeAtHomeHttpCommunicationException;
+import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService;
+import org.openhab.core.config.discovery.DiscoveryResult;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.ThingUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link FreeAtHomeDiscoveryService} is responsible for performing discovery of things
+ *
+ * @author Andras Uhrin - Initial contribution
+ */
+@NonNullByDefault
+public class FreeAtHomeDiscoveryService extends AbstractThingHandlerDiscoveryService<FreeAtHomeBridgeHandler> {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDiscoveryService.class);
+    private @Nullable ScheduledFuture<?> backgroundDiscoveryJob = null;
+
+    private static final long BACKGROUND_DISCOVERY_DELAY = 1L;
+    private boolean isScanTerminated;
+
+    Runnable runnable = new Runnable() {
+        @Override
+        public void run() {
+            ThingUID bridgeUID = thingHandler.getThing().getUID();
+
+            List<String> deviceList;
+
+            try {
+                deviceList = thingHandler.getDeviceDeviceList();
+
+                for (int i = 0; (i < deviceList.size()) && !isScanTerminated; i++) {
+                    FreeAtHomeDeviceDescription device = thingHandler.getFreeatHomeDeviceDescription(deviceList.get(i));
+
+                    ThingUID uid = new ThingUID(FreeAtHomeBindingConstants.DEVICE_TYPE_UID, bridgeUID, device.deviceId);
+                    Map<String, Object> properties = new HashMap<>(1);
+                    properties.put("deviceId", device.deviceId);
+                    properties.put("interface", device.interfaceType);
+
+                    String deviceLabel = device.deviceLabel;
+
+                    DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(uid).withLabel(deviceLabel)
+                            .withRepresentationProperty("deviceId").withBridge(bridgeUID).withProperties(properties)
+                            .build();
+
+                    thingDiscovered(discoveryResult);
+
+                    logger.debug("Thing discovered - DeviceId: {} - Device label: {}", device.getDeviceId(),
+                            device.getDeviceLabel());
+                }
+
+                stopScan();
+            } catch (FreeAtHomeHttpCommunicationException e) {
+                logger.debug("Communication error in device discovery with the bridge: {}",
+                        thingHandler.getThing().getLabel());
+            } catch (RuntimeException e) {
+                logger.debug("Scanning interrupted");
+            }
+        }
+    };
+
+    public FreeAtHomeDiscoveryService(int timeout) {
+        super(FreeAtHomeBridgeHandler.class, FreeAtHomeBindingConstants.SUPPORTED_THING_TYPES_UIDS, timeout, false);
+    }
+
+    public FreeAtHomeDiscoveryService() {
+        this(90);
+    }
+
+    @Override
+    public Set<ThingTypeUID> getSupportedThingTypes() {
+        return Set.of(FreeAtHomeBindingConstants.BRIDGE_TYPE_UID);
+    }
+
+    @Override
+    protected void startScan() {
+        if (backgroundDiscoveryJob == null) {
+            this.removeOlderResults(Instant.now().toEpochMilli());
+
+            isScanTerminated = false;
+            backgroundDiscoveryJob = scheduler.schedule(runnable, BACKGROUND_DISCOVERY_DELAY, TimeUnit.SECONDS);
+        }
+    }
+
+    @Override
+    protected synchronized void stopScan() {
+        super.stopScan();
+
+        isScanTerminated = true;
+
+        ScheduledFuture<?> localDiscoveryJob = backgroundDiscoveryJob;
+
+        if (localDiscoveryJob != null) {
+            localDiscoveryJob.cancel(true);
+        }
+
+        backgroundDiscoveryJob = null;
+
+        removeOlderResults(Instant.now().toEpochMilli());
+    }
+
+    @Override
+    public void deactivate() {
+        removeOlderResults(Instant.now().toEpochMilli());
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeHandlerFactory.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeHandlerFactory.java
new file mode 100644 (file)
index 0000000..a12d960
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal;
+
+import static org.openhab.binding.freeathome.internal.FreeAtHomeBindingConstants.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.binding.freeathome.internal.handler.FreeAtHomeBridgeHandler;
+import org.openhab.binding.freeathome.internal.handler.FreeAtHomeDeviceHandler;
+import org.openhab.binding.freeathome.internal.type.FreeAtHomeChannelTypeProvider;
+import org.openhab.binding.freeathome.internal.type.FreeAtHomeThingTypeProvider;
+import org.openhab.core.i18n.LocaleProvider;
+import org.openhab.core.i18n.TranslationProvider;
+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.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link FreeAtHomeHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Andras Uhrin - Initial contribution
+ */
+@NonNullByDefault
+@Component(configurationPid = "binding.freeathome", service = ThingHandlerFactory.class)
+public class FreeAtHomeHandlerFactory extends BaseThingHandlerFactory {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeHandlerFactory.class);
+
+    private final HttpClient httpClient;
+    private final FreeAtHomeChannelTypeProvider channelTypeProvider;
+    private final TranslationProvider i18nProvider;
+    private final LocaleProvider localeProvider;
+
+    @Activate
+    public FreeAtHomeHandlerFactory(@Reference FreeAtHomeThingTypeProvider thingTypeProvider,
+            @Reference FreeAtHomeChannelTypeProvider channelTypeProvider, @Reference TranslationProvider i18nProvider,
+            @Reference LocaleProvider localeProvider, @Reference HttpClientFactory httpClientFactory,
+            ComponentContext componentContext) {
+        super.activate(componentContext);
+        this.channelTypeProvider = channelTypeProvider;
+        this.i18nProvider = i18nProvider;
+        this.localeProvider = localeProvider;
+
+        // create httpClient
+        httpClient = httpClientFactory.createHttpClient(FreeAtHomeBindingConstants.BINDING_ID);
+
+        // Configure client
+        httpClient.setFollowRedirects(false);
+        httpClient.setMaxConnectionsPerDestination(1);
+        httpClient.setMaxRequestsQueuedPerDestination(50);
+
+        // Set timeouts
+        httpClient.setIdleTimeout(-1);
+        httpClient.setConnectTimeout(5000);
+
+        try {
+            // Start HttpClient.
+            httpClient.start();
+        } catch (Exception ex) {
+            logger.error("Could not create HttpClient: {}", ex.getMessage());
+
+            throw new IllegalStateException("Could not create HttpClient", ex);
+        }
+    }
+
+    @Deactivate
+    public void deactivate() {
+        try {
+            httpClient.stop();
+        } catch (Exception ex) {
+            logger.warn("Failed to stop HttpClient: {}", ex.getMessage());
+        }
+    }
+
+    @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 (BRIDGE_TYPE_UID.equals(thingTypeUID)) {
+            return new FreeAtHomeBridgeHandler((Bridge) thing, httpClient);
+        } else if (DEVICE_TYPE_UID.equals(thingTypeUID)) {
+            return new FreeAtHomeDeviceHandler(thing, channelTypeProvider, i18nProvider, localeProvider);
+        }
+
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeBridgeHandlerConfiguration.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeBridgeHandlerConfiguration.java
new file mode 100644 (file)
index 0000000..a0e5867
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.configuration;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link FreeAtHomeBridgeHandlerConfiguration} class contains fields mapping thing configuration parameters.
+ *
+ * @author Andras Uhrin - Initial contribution
+ */
+@NonNullByDefault
+public class FreeAtHomeBridgeHandlerConfiguration {
+
+    /**
+     * Bridgeconfiguration parameter.
+     */
+    public String ipAddress = "";
+    public String username = "";
+    public String password = "";
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeDeviceHandlerConfiguration.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeDeviceHandlerConfiguration.java
new file mode 100644 (file)
index 0000000..4c31659
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.configuration;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link FreeAtHomeDeviceHandlerConfiguration} class contains fields mapping device configuration parameters.
+ *
+ * @author Andras Uhrin - Initial contribution
+ */
+@NonNullByDefault
+public class FreeAtHomeDeviceHandlerConfiguration {
+    public String deviceId = "";
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapoint.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapoint.java
new file mode 100644 (file)
index 0000000..ceb92a8
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.datamodel;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonObject;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeDatapoint {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDatapoint.class);
+
+    enum DatapointDirection {
+        UNKNOWN,
+        INPUT,
+        OUTPUT,
+        INPUTOUTPUT,
+        INPUT_AS_OUTPUT
+    };
+
+    public String channelId = "";
+    private String datapointId = "";
+
+    DatapointDirection searchForDatapoint(DatapointDirection direction, int neededPairingIDFunction, String channelId,
+            JsonObject jsonObjectOfChannel) {
+        DatapointDirection resultingDirection = DatapointDirection.UNKNOWN;
+        boolean foundId = false;
+        JsonObject localDatapoints = null;
+
+        switch (direction) {
+            case INPUT: {
+                localDatapoints = jsonObjectOfChannel.getAsJsonObject("inputs");
+                resultingDirection = DatapointDirection.INPUT;
+                break;
+            }
+            case INPUT_AS_OUTPUT: {
+                localDatapoints = jsonObjectOfChannel.getAsJsonObject("inputs");
+                resultingDirection = DatapointDirection.OUTPUT;
+                break;
+            }
+            case OUTPUT: {
+                localDatapoints = jsonObjectOfChannel.getAsJsonObject("outputs");
+                resultingDirection = DatapointDirection.OUTPUT;
+                break;
+            }
+            default: {
+                localDatapoints = jsonObjectOfChannel.getAsJsonObject("outputs");
+                resultingDirection = DatapointDirection.OUTPUT;
+                break;
+            }
+        }
+
+        Set<String> keys = localDatapoints.keySet();
+
+        Iterator<String> iter = keys.iterator();
+
+        // Scan datapoints for pairingID IDs
+        while (iter.hasNext() && !foundId) {
+            String datapointId = iter.next();
+
+            JsonObject datapointJsonObject = localDatapoints.getAsJsonObject(datapointId);
+
+            int pairingIDFunction = datapointJsonObject.get("pairingID").getAsInt();
+
+            if (pairingIDFunction == neededPairingIDFunction) {
+                this.channelId = channelId;
+                this.datapointId = datapointId;
+
+                logger.debug("Datapoint is found - channel {} - datapoint {}", this.channelId, this.datapointId);
+
+                foundId = true;
+            }
+        }
+
+        // id not found, add dummy
+        if (!foundId) {
+            this.channelId = "";
+            this.datapointId = "";
+            resultingDirection = DatapointDirection.UNKNOWN;
+
+            logger.debug("Needed datapoint is not found - channel {} - pairingId {}", channelId,
+                    neededPairingIDFunction);
+        }
+
+        return resultingDirection;
+    }
+
+    public String getChannelIdforDatapoint() {
+        return channelId;
+    }
+
+    public String getDatapointId() {
+        return datapointId;
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapointGroup.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapointGroup.java
new file mode 100644 (file)
index 0000000..e2642fb
--- /dev/null
@@ -0,0 +1,262 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.datamodel;
+
+import static org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDatapoint.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.freeathome.internal.util.FreeAtHomeGeneralException;
+import org.openhab.binding.freeathome.internal.util.PidTranslationUtils;
+import org.openhab.binding.freeathome.internal.valuestateconverter.BooleanValueStateConverter;
+import org.openhab.binding.freeathome.internal.valuestateconverter.DecimalValueStateConverter;
+import org.openhab.binding.freeathome.internal.valuestateconverter.ShuttercontrolValueStateConverter;
+import org.openhab.binding.freeathome.internal.valuestateconverter.ValueStateConverter;
+import org.openhab.core.library.CoreItemFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonObject;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeDatapointGroup {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDatapointGroup.class);
+
+    public enum DatapointGroupDirection {
+        UNDEFINED,
+        INPUT,
+        OUTPUT,
+        INPUTOUTPUT
+    }
+
+    private DatapointGroupDirection datapointGroupDirection;
+    private int pairingId;
+
+    private String functionString = "";
+    private @Nullable FreeAtHomeDatapoint inputDatapoint;
+    private @Nullable FreeAtHomeDatapoint outputDatapoint;
+
+    FreeAtHomeDatapointGroup() {
+        datapointGroupDirection = DatapointGroupDirection.UNDEFINED;
+        inputDatapoint = null;
+        outputDatapoint = null;
+    }
+
+    boolean addDatapointToGroup(DatapointDirection direction, int neededPairingId, String channelId,
+            JsonObject jsonObjectOfChannel) {
+        FreeAtHomeDatapoint newDatapoint = new FreeAtHomeDatapoint();
+
+        DatapointDirection resultingDirection = newDatapoint.searchForDatapoint(direction, neededPairingId, channelId,
+                jsonObjectOfChannel);
+
+        if (resultingDirection != DatapointDirection.UNKNOWN) {
+            switch (resultingDirection) {
+                case INPUT: {
+                    inputDatapoint = newDatapoint;
+
+                    pairingId = neededPairingId;
+
+                    break;
+                }
+                case OUTPUT: {
+                    outputDatapoint = newDatapoint;
+
+                    if (inputDatapoint == null) {
+                        pairingId = neededPairingId;
+                    }
+
+                    break;
+                }
+                case INPUTOUTPUT:
+                case INPUT_AS_OUTPUT:
+                case UNKNOWN:
+                    break;
+            }
+        }
+
+        if (inputDatapoint != null && outputDatapoint != null) {
+            datapointGroupDirection = DatapointGroupDirection.INPUTOUTPUT;
+        } else {
+            if (inputDatapoint == null && outputDatapoint != null) {
+                datapointGroupDirection = DatapointGroupDirection.OUTPUT;
+            } else {
+                if (inputDatapoint != null && outputDatapoint == null) {
+                    datapointGroupDirection = DatapointGroupDirection.INPUT;
+                } else {
+                    datapointGroupDirection = DatapointGroupDirection.UNDEFINED;
+                }
+            }
+        }
+
+        return resultingDirection != DatapointDirection.UNKNOWN;
+    }
+
+    public void applyChangesForVirtualDevice() {
+        // The input and output datapoints are meant from the device point of view. Because the virtual devices are
+        // outside of the free@home system the input and output datapoint must be switched
+        @Nullable
+        FreeAtHomeDatapoint localDatapoint = inputDatapoint;
+
+        inputDatapoint = outputDatapoint;
+        outputDatapoint = localDatapoint;
+
+        if (inputDatapoint != null && outputDatapoint != null) {
+            datapointGroupDirection = DatapointGroupDirection.INPUTOUTPUT;
+        } else {
+            if (inputDatapoint == null && outputDatapoint != null) {
+                datapointGroupDirection = DatapointGroupDirection.OUTPUT;
+            } else {
+                if (inputDatapoint != null && outputDatapoint == null) {
+                    datapointGroupDirection = DatapointGroupDirection.INPUT;
+                } else {
+                    datapointGroupDirection = DatapointGroupDirection.UNDEFINED;
+                }
+            }
+        }
+
+        return;
+    }
+
+    public @Nullable FreeAtHomeDatapoint getInputDatapoint() {
+        return inputDatapoint;
+    }
+
+    public @Nullable FreeAtHomeDatapoint getOutputDatapoint() {
+        return outputDatapoint;
+    }
+
+    public DatapointGroupDirection getDirection() {
+        return datapointGroupDirection;
+    }
+
+    public boolean isDecimal() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.PID_VALUETYPE_DECIMAL
+                .equals(PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId)));
+    }
+
+    public boolean isInteger() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.PID_VALUETYPE_INTEGER
+                .equals(PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId)));
+    }
+
+    public boolean isReadOnly() {
+        return (DatapointGroupDirection.INPUTOUTPUT == datapointGroupDirection) ? false
+                : ((DatapointGroupDirection.INPUT == datapointGroupDirection) ? false : true);
+    }
+
+    public int getMax() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.getMax(String.format("0x%04X", pairingId));
+    }
+
+    public int getMin() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.getMin(String.format("0x%04X", pairingId));
+    }
+
+    public String getLabel() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.getShortTextForPairingId(String.format("0x%04X", pairingId));
+    }
+
+    public String getDescription() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.getDescriptionTextForPairingId(String.format("0x%04X", pairingId));
+    }
+
+    public String getValueType() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
+    }
+
+    public String getTypePattern() throws FreeAtHomeGeneralException {
+        String pattern = "";
+
+        functionString = PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
+
+        switch (functionString) {
+            case PidTranslationUtils.PID_VALUETYPE_DECIMAL:
+                pattern = "%.1f";
+                break;
+            case PidTranslationUtils.PID_VALUETYPE_INTEGER:
+                pattern = "%d";
+                break;
+            default:
+                pattern = "";
+                logger.debug("Type pattern not found for PairingID {} - using default",
+                        String.format("0x%04X", pairingId));
+                break;
+        }
+
+        return pattern;
+    }
+
+    public ValueStateConverter getValueStateConverter() throws FreeAtHomeGeneralException {
+        ValueStateConverter valueStateConverter = new BooleanValueStateConverter();
+
+        functionString = PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
+
+        switch (functionString) {
+            case PidTranslationUtils.PID_VALUETYPE_BOOLEAN:
+                valueStateConverter = new BooleanValueStateConverter();
+                break;
+            case PidTranslationUtils.PID_VALUETYPE_DECIMAL:
+            case PidTranslationUtils.PID_VALUETYPE_INTEGER:
+                valueStateConverter = new DecimalValueStateConverter();
+                break;
+            case PidTranslationUtils.PID_VALUETYPE_STRING:
+                break;
+            case PidTranslationUtils.PID_VALUETYPE_SHUTTERMOVEMENT:
+                valueStateConverter = new ShuttercontrolValueStateConverter();
+                break;
+            default:
+                valueStateConverter = new DecimalValueStateConverter();
+                logger.debug("Value converter not found for PairingID {} - using default",
+                        String.format("0x%04X", pairingId));
+                break;
+        }
+
+        return valueStateConverter;
+    }
+
+    public String getOpenHabItemType() throws FreeAtHomeGeneralException {
+        String itemTypeString = "";
+
+        functionString = PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
+
+        switch (functionString) {
+            case PidTranslationUtils.PID_VALUETYPE_BOOLEAN:
+                itemTypeString = CoreItemFactory.SWITCH;
+                break;
+            case PidTranslationUtils.PID_VALUETYPE_DECIMAL:
+            case PidTranslationUtils.PID_VALUETYPE_INTEGER:
+                itemTypeString = CoreItemFactory.NUMBER;
+                break;
+            case PidTranslationUtils.PID_VALUETYPE_SHUTTERMOVEMENT:
+                itemTypeString = CoreItemFactory.ROLLERSHUTTER;
+                break;
+            default:
+                itemTypeString = CoreItemFactory.NUMBER;
+                logger.debug("Item type constant not found for PairingID {} - using default",
+                        String.format("0x%04X", pairingId));
+                break;
+        }
+
+        return itemTypeString;
+    }
+
+    public String getOpenHabCategory() throws FreeAtHomeGeneralException {
+        return PidTranslationUtils.getCategoryForPairingId(String.format("0x%04X", pairingId));
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceChannel.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceChannel.java
new file mode 100644 (file)
index 0000000..b5ec512
--- /dev/null
@@ -0,0 +1,543 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.datamodel;
+
+import static org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDatapoint.*;
+import static org.openhab.binding.freeathome.internal.util.FidTranslationUtils.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.freeathome.internal.util.FidTranslationUtils;
+import org.openhab.binding.freeathome.internal.util.FreeAtHomeGeneralException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonObject;
+
+/**
+ * The {@link FreeAtHomeDeviceChannel} holding the information of device channels
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeDeviceChannel {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDeviceChannel.class);
+
+    private String channelLabel = "";
+    private String channelId = "";
+    private String channelFunctionID = "";
+
+    private List<FreeAtHomeDatapointGroup> datapointGroups = new ArrayList<>();
+
+    public boolean createChannelFromJson(String deviceLabel, String channelId, JsonObject jsonObjectOfChannels,
+            boolean isScene, boolean isRule) {
+        JsonObject channelObject = jsonObjectOfChannels.getAsJsonObject(channelId);
+
+        channelFunctionID = channelObject.get("functionID").getAsString();
+
+        // check whether this is a valid channel
+        if (channelFunctionID.isEmpty()) {
+            // invalid channel found
+            logger.info("Invalid channel function ID found - Devicelabel: {} Channel: {}", deviceLabel, channelId);
+
+            return false;
+        }
+
+        if (!channelFunctionID.isEmpty()) {
+            channelLabel = channelObject.get("displayName").getAsString();
+
+            if (channelLabel.isEmpty()) {
+                channelLabel = deviceLabel;
+            }
+        }
+
+        if (isScene) {
+            channelFunctionID = channelFunctionID.substring(0, channelFunctionID.length() - 1) + "0";
+        }
+
+        switch (Integer.parseInt(channelFunctionID, 16)) {
+            case FID_PANEL_SWITCH_SENSOR:
+            case FID_SWITCH_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Switch sensor channel found - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_PANEL_DIMMING_SENSOR:
+            case FID_DIMMING_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Dimming sensor channel found - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 17, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_TRIGGER:
+            case FID_SWITCH_ACTUATOR: {
+                this.channelId = channelId;
+
+                logger.debug("Switch actuator channel created - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 1, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_MOVEMENT_DETECTOR_FLEX:
+            case FID_MOVEMENT_DETECTOR: {
+                this.channelId = channelId;
+
+                logger.debug("Movement detector channel found - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 6, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 7, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1027, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT_AS_OUTPUT, 256, channelId,
+                        channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN:
+            case FID_RADIATOR_ACTUATOR_MASTER: {
+                this.channelId = channelId;
+
+                if (Integer.parseInt(channelFunctionID, 16) == FID_RADIATOR_ACTUATOR_MASTER) {
+                    logger.debug("Radiator actuator channel - Channel FID: {}", channelFunctionID);
+                } else {
+                    logger.debug("Room temperature actuator channel - Channel FID: {}", channelFunctionID);
+                }
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 304, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 333, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 331, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 54, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 51, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 320, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 68, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 58, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 56, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 66, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                // Additional channel for RTC device
+                if (Integer.parseInt(channelFunctionID, 16) == FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN) {
+                    newDatapointGroup = new FreeAtHomeDatapointGroup();
+                    newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 48, channelId, channelObject);
+                    datapointGroups.add(newDatapointGroup);
+                }
+
+                break;
+            }
+            case FID_WINDOW_DOOR_POSITION_SENSOR:
+            case FID_WINDOW_DOOR_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Window/Door position sensor channel created - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 53, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 41, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_SCENE_TRIGGER: {
+                this.channelId = channelId;
+
+                logger.debug("Scene trigger channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 4, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_RULE_SWITCH: {
+                this.channelId = channelId;
+
+                logger.debug("Rule channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 61698, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 61697, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_DES_DOOR_OPENER_ACTUATOR: {
+                this.channelId = channelId;
+
+                logger.debug("Door opener actuator channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 2, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_DES_LEVEL_CALL_SENSOR:
+            case FID_DES_DOOR_RINGING_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Door ring sensor channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 2, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_DES_LIGHT_SWITCH_ACTUATOR: {
+                this.channelId = channelId;
+
+                logger.debug("DES light switch channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 2, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_DIMMING_ACTUATOR_FLEX:
+            case FID_DIMMING_ACTUATOR: {
+                this.channelId = channelId;
+
+                logger.debug("Dimming actuator channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 272, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 17, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 1, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AWNING_ACTUATOR:
+            case FID_ATTIC_WINDOW_ACTUATOR:
+            case FID_BLIND_ACTUATOR:
+            case FID_SHUTTER_ACTUATOR: {
+                this.channelId = channelId;
+
+                logger.debug("Shutter actuator channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 32, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 288, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 33, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 288, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 289, channelId, channelObject);
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 35, channelId, channelObject);
+
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_BRIGHTNESS_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Brightness sensor channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1026, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1027, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_RAIN_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Rain sensor channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 39, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1029, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1030, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_TEMPERATURE_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Temperature sensor channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                if (newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 38, channelId, channelObject)) {
+                    datapointGroups.add(newDatapointGroup);
+                }
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                if (newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1024, channelId, channelObject)) {
+                    datapointGroups.add(newDatapointGroup);
+                }
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                if (newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 304, channelId, channelObject)) {
+                    datapointGroups.add(newDatapointGroup);
+                }
+
+                break;
+            }
+            case FID_WIND_SENSOR: {
+                this.channelId = channelId;
+
+                logger.debug("Wind sensor channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 37, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1025, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1028, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_CO: {
+                this.channelId = channelId;
+
+                logger.debug("AQS CO channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1564, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_CO2: {
+                this.channelId = channelId;
+
+                logger.debug("AQS CO2 channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1563, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_HUMIDITY: {
+                this.channelId = channelId;
+
+                logger.debug("AQS Humidity channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 337, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_PRESSURE: {
+                this.channelId = channelId;
+
+                logger.debug("AQS Pressure channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1562, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_NO2: {
+                this.channelId = channelId;
+
+                logger.debug("AQS NO2 channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1565, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_O3: {
+                this.channelId = channelId;
+
+                logger.debug("AQS O3 channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1566, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_PM10: {
+                this.channelId = channelId;
+
+                logger.debug("AQS PM10 channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1567, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_VOC: {
+                this.channelId = channelId;
+
+                logger.debug("AQS VOC channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1569, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            case FID_AIRQUALITYSENSOR_PM25: {
+                this.channelId = channelId;
+
+                logger.debug("AQS PM25 channel - Channel FID: {}", channelFunctionID);
+
+                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
+                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1568, channelId, channelObject);
+                datapointGroups.add(newDatapointGroup);
+
+                break;
+            }
+            default: {
+                logger.debug("Unknown channel found - Channel FID: {}", channelFunctionID);
+
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public String getChannelIdforDatapoint() {
+        return channelId;
+    }
+
+    public String getChannelLabel() {
+        return channelLabel;
+    }
+
+    public String getChannelId() {
+        return channelId;
+    }
+
+    public String getFunctionId() {
+        return channelFunctionID;
+    }
+
+    public @Nullable String getFunctionIdText() throws FreeAtHomeGeneralException {
+        String functionIdText = FidTranslationUtils
+                .getFunctionIdText(String.format("0x%04X", Integer.parseInt(channelFunctionID, 16)));
+        return functionIdText;
+    }
+
+    public int getNumberOfDatapointGroup() {
+        return datapointGroups.size();
+    }
+
+    public FreeAtHomeDatapointGroup getDatapointGroup(int idx) {
+        return datapointGroups.get(idx);
+    }
+
+    public void applyChangesForVirtualDevice() {
+        for (FreeAtHomeDatapointGroup localDatapointGroup : datapointGroups) {
+            localDatapointGroup.applyChangesForVirtualDevice();
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceDescription.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceDescription.java
new file mode 100644 (file)
index 0000000..d9a4dd7
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.datamodel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+/**
+ * The {@link FreeAtHomeDeviceDescription} is responsible for determining the device type
+ * based on the received json string
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeDeviceDescription {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDeviceDescription.class);
+
+    // interface strings
+    public static final String DEVICE_INTERFACE_UNKNOWN_TYPE = "unknown";
+    public static final String DEVICE_INTERFACE_WIRELESS_TYPE = "wireless";
+    public static final String DEVICE_INTERFACE_VIRTUAL_TYPE = "virtual";
+    public static final String DEVICE_INTERFACE_WIRED_TYPE = "wired";
+    public static final String DEVICE_INTERFACE_HUE_TYPE = "hue";
+
+    public String deviceLabel = "";
+    public String deviceId = "";
+    public String interfaceType = "";
+    public boolean validDevice = false;
+
+    private boolean sceneIsDetected;
+    private boolean ruleIsDetected;
+
+    public List<FreeAtHomeDeviceChannel> listOfChannels = new ArrayList<>();
+
+    public FreeAtHomeDeviceDescription() {
+        validDevice = false;
+    }
+
+    public FreeAtHomeDeviceDescription(JsonObject jsonObject, String id) {
+        // set the device ID
+        deviceId = id;
+
+        // set the device invalid at first
+        validDevice = false;
+
+        sceneIsDetected = id.toLowerCase().startsWith("ffff48");
+        ruleIsDetected = id.toLowerCase().startsWith("ffff4a");
+
+        JsonObject jsonObjectOfId = jsonObject.getAsJsonObject(id);
+
+        if (jsonObjectOfId == null) {
+            return;
+        }
+
+        JsonElement jsonObjectOfInterface = jsonObjectOfId.get("interface");
+
+        if (jsonObjectOfInterface != null) {
+            String interfaceString = jsonObjectOfInterface.getAsString();
+
+            if (interfaceString.toLowerCase().startsWith("vdev:")) {
+                interfaceType = DEVICE_INTERFACE_VIRTUAL_TYPE;
+            } else if (interfaceString.toLowerCase().startsWith("hue")) {
+                interfaceType = DEVICE_INTERFACE_HUE_TYPE;
+            } else if (interfaceString.toLowerCase().startsWith("rf")) {
+                interfaceType = DEVICE_INTERFACE_WIRELESS_TYPE;
+            } else if (interfaceString.toLowerCase().startsWith("tp")) {
+                interfaceType = DEVICE_INTERFACE_WIRED_TYPE;
+            } else {
+                interfaceType = DEVICE_INTERFACE_UNKNOWN_TYPE;
+            }
+        } else {
+            interfaceType = DEVICE_INTERFACE_UNKNOWN_TYPE;
+        }
+
+        JsonElement jsonObjectOfDeviceLabel = jsonObjectOfId.get("displayName");
+
+        if (jsonObjectOfDeviceLabel == null) {
+            this.deviceLabel = "NoName";
+        } else {
+            this.deviceLabel = jsonObjectOfDeviceLabel.getAsString();
+        }
+
+        if (this.deviceLabel.isEmpty()) {
+            this.deviceLabel = "NoName";
+        }
+
+        JsonObject jsonObjectOfChannels = jsonObjectOfId.getAsJsonObject("channels");
+
+        logger.debug("Detecting device features - device id: {} - device label: {}", this.deviceId, this.deviceLabel);
+
+        if (jsonObjectOfChannels != null) {
+            // Scan channels for functions
+            for (String nextChannel : jsonObjectOfChannels.keySet()) {
+                FreeAtHomeDeviceChannel newChannel = new FreeAtHomeDeviceChannel();
+
+                if (newChannel.createChannelFromJson(deviceLabel, nextChannel, jsonObjectOfChannels, sceneIsDetected,
+                        ruleIsDetected)) {
+                    if (interfaceType == DEVICE_INTERFACE_VIRTUAL_TYPE) {
+                        newChannel.applyChangesForVirtualDevice();
+                    }
+
+                    listOfChannels.add(newChannel);
+                }
+            }
+        }
+    }
+
+    public boolean isRule() {
+        return ruleIsDetected;
+    }
+
+    public boolean isScene() {
+        return sceneIsDetected;
+    }
+
+    public boolean isVirtual() {
+        return interfaceType == DEVICE_INTERFACE_VIRTUAL_TYPE;
+    }
+
+    public int getNumberOfChannels() {
+        return listOfChannels.size();
+    }
+
+    public FreeAtHomeDeviceChannel getChannel(int idx) {
+        return listOfChannels.get(idx);
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public String getDeviceLabel() {
+        return deviceLabel;
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeBridgeHandler.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeBridgeHandler.java
new file mode 100644 (file)
index 0000000..cf719f0
--- /dev/null
@@ -0,0 +1,897 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.handler;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.AuthenticationStore;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.util.BasicAuthentication;
+import org.eclipse.jetty.client.util.StringContentProvider;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.StatusCode;
+import org.eclipse.jetty.websocket.api.WebSocketListener;
+import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
+import org.openhab.binding.freeathome.internal.FreeAtHomeDiscoveryService;
+import org.openhab.binding.freeathome.internal.configuration.FreeAtHomeBridgeHandlerConfiguration;
+import org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDeviceDescription;
+import org.openhab.binding.freeathome.internal.util.FreeAtHomeHttpCommunicationException;
+import org.openhab.core.thing.Bridge;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.binding.BaseBridgeHandler;
+import org.openhab.core.thing.binding.ThingHandlerService;
+import org.openhab.core.types.Command;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+
+/**
+ * The {@link FreeAtHomeBridgeHandler} is responsible for handling the free@home bridge and
+ * its main communication.
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeBridgeHandler extends BaseBridgeHandler implements WebSocketListener {
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeBridgeHandler.class);
+
+    private Map<String, FreeAtHomeDeviceHandler> mapEventListeners = new ConcurrentHashMap<>();
+
+    // Clients for the network communication
+    private HttpClient httpClient;
+    private @Nullable WebSocketClient websocketClient = null;
+    private FreeAtHomeWebsocketMonitorThread socketMonitor = new FreeAtHomeWebsocketMonitorThread();
+    private @Nullable QueuedThreadPool jettyThreadPool = null;
+    private volatile @Nullable Session websocketSession = null;
+
+    private String sysApUID = "00000000-0000-0000-0000-000000000000";
+    private String ipAddress = "";
+    private String username = "";
+    private String password = "";
+
+    private String baseUrl = "";
+
+    private String authField = "";
+
+    private Lock lock = new ReentrantLock();
+    private AtomicBoolean httpConnectionOK = new AtomicBoolean(false);
+    private Condition websocketSessionEstablished = lock.newCondition();
+
+    int numberOfComponents = 0;
+
+    private static final int BRIDGE_WEBSOCKET_RECONNECT_DELAY = 60;
+    private static final int BRIDGE_WEBSOCKET_TIMEOUT = 90;
+    private static final int BRIDGE_WEBSOCKET_KEEPALIVE = 50;
+    private static final String BRIDGE_URL_GETDEVICELIST = "/rest/devicelist";
+
+    public FreeAtHomeBridgeHandler(Bridge thing, HttpClient client) {
+        super(thing);
+
+        httpClient = client;
+    }
+
+    /**
+     * stub method for handlCommand
+     */
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        logger.warn("Unknown handle command for the bridge - channellUID {}, command {}", channelUID, command);
+    }
+
+    @Override
+    public Collection<Class<? extends ThingHandlerService>> getServices() {
+        return List.of(FreeAtHomeDiscoveryService.class);
+    }
+
+    /**
+     * Method to get the device list
+     */
+    public List<String> getDeviceDeviceList() throws FreeAtHomeHttpCommunicationException {
+        List<String> listOfComponentId = new ArrayList<String>();
+        boolean ret = false;
+
+        listOfComponentId.clear();
+
+        String url = baseUrl + BRIDGE_URL_GETDEVICELIST;
+
+        // Perform a simple GET and wait for the response.
+        try {
+            HttpClient client = httpClient;
+
+            Request req = client.newRequest(url);
+
+            if (req == null) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Invalid request object in getDeviceDeviceList with the URL [ " + url + " ]");
+            }
+
+            ContentResponse response = req.send();
+
+            // Get component List
+            String componentListString = new String(response.getContent());
+
+            JsonElement jsonTree = JsonParser.parseString(componentListString);
+
+            // check the output
+            if (!jsonTree.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Invalid jsonObject in getDeviceDeviceList with the URL [ " + url + " ]");
+            }
+
+            JsonObject jsonObject = jsonTree.getAsJsonObject();
+
+            // Get the main object
+            JsonElement listOfComponents = jsonObject.get(sysApUID);
+
+            if (listOfComponents == null) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Devices Section is missing in getDeviceDeviceList with the URL [ " + url + " ]");
+            }
+
+            JsonArray array = listOfComponents.getAsJsonArray();
+
+            this.numberOfComponents = array.size();
+
+            for (int i = 0; i < array.size(); i++) {
+                JsonElement basicElement = array.get(i);
+
+                listOfComponentId.add(basicElement.getAsString());
+            }
+
+            ret = true;
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            logger.debug("Error to build up the Component list [ {} ]", e.getMessage());
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted [ " + e.getMessage() + " ]");
+        } catch (ExecutionException | TimeoutException e) {
+            logger.debug("Error to build up the Component list [ {} ]", e.getMessage());
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted in getDeviceList [ " + e.getMessage() + " ]");
+        }
+
+        // Scan finished but error. clear the list
+        if (!ret) {
+            listOfComponentId.clear();
+        }
+
+        return listOfComponentId;
+    }
+
+    /**
+     * Method to send http request to get the device description
+     */
+    public FreeAtHomeDeviceDescription getFreeatHomeDeviceDescription(String id)
+            throws FreeAtHomeHttpCommunicationException {
+        FreeAtHomeDeviceDescription device = new FreeAtHomeDeviceDescription();
+
+        String url = baseUrl + "/rest/device/" + sysApUID + "/" + id;
+        try {
+            HttpClient client = httpClient;
+            Request req = client.newRequest(url);
+
+            if (req == null) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Invalid request object in getDatapoint with the URL [ " + url + " ]");
+            }
+
+            ContentResponse response;
+            response = req.send();
+
+            // Get component List
+            String deviceString = new String(response.getContent());
+
+            JsonReader reader = new JsonReader(new StringReader(deviceString));
+            reader.setLenient(true);
+            JsonElement jsonTree = JsonParser.parseReader(reader);
+
+            if (!jsonTree.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "No data is received by getDatapoint with the URL [ " + url + " ]");
+            }
+
+            if (!jsonTree.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Invalid jsonObject in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
+            }
+
+            // check the output
+            JsonObject jsonObject = jsonTree.getAsJsonObject();
+
+            if (!jsonObject.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Main jsonObject is invalid in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
+            }
+
+            jsonObject = jsonObject.getAsJsonObject(sysApUID);
+
+            if (!jsonObject.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "jsonObject is invalid in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
+            }
+
+            jsonObject = jsonObject.getAsJsonObject("devices");
+
+            if (!jsonObject.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Devices Section is missing in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
+            }
+
+            device = new FreeAtHomeDeviceDescription(jsonObject, id);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            logger.debug("No communication possible to get device list - Communication interrupt [ {} ]",
+                    e.getMessage());
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted [ " + e.getMessage() + " ]");
+        } catch (ExecutionException | TimeoutException e) {
+            logger.debug("No communication possible to get device list - Communication interrupt [ {} ]",
+                    e.getMessage());
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted in getDeviceList [ " + e.getMessage() + " ]");
+        }
+
+        return device;
+    }
+
+    /**
+     * Method to get datapoint values for devices
+     */
+    public String getDatapoint(String deviceId, String channel, String datapoint)
+            throws FreeAtHomeHttpCommunicationException {
+        String url = baseUrl + "/rest/datapoint/" + sysApUID + "/" + deviceId + "." + channel + "." + datapoint;
+
+        try {
+            Request req = httpClient.newRequest(url);
+
+            logger.debug("Get datapoint by url: {}", url);
+
+            if (req == null) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Invalid request object in getDatapoint with the URL [ " + url + " ]");
+            }
+
+            ContentResponse response = req.send();
+
+            if (response.getStatus() != 200) {
+                throw new FreeAtHomeHttpCommunicationException(response.getStatus(), response.getReason());
+            }
+
+            String deviceString = new String(response.getContent());
+
+            JsonReader reader = new JsonReader(new StringReader(deviceString));
+            reader.setLenient(true);
+            JsonElement jsonTree = JsonParser.parseReader(reader);
+
+            if (!jsonTree.isJsonObject()) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "No data is received by getDatapoint with the URL [ " + url + " ]");
+            }
+
+            JsonObject jsonObject = jsonTree.getAsJsonObject();
+
+            jsonObject = jsonObject.getAsJsonObject(sysApUID);
+            JsonArray jsonValueArray = jsonObject.getAsJsonArray("values");
+
+            JsonElement element = jsonValueArray.get(0);
+            String value = element.getAsString();
+
+            if (value.isEmpty()) {
+                value = "0";
+            }
+
+            return value;
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted [ " + e.getMessage() + " ]");
+        } catch (ExecutionException | TimeoutException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication timout or execution interrupted [ " + e.getMessage() + " ]");
+        } catch (JsonParseException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Invalid JSON file is received by getDatapoint with the URL [ " + e.getMessage() + " ]");
+        }
+    }
+
+    /**
+     * Method to set datapoint values in channels
+     */
+    public boolean setDatapoint(String deviceId, String channel, String datapoint, String valueString)
+            throws FreeAtHomeHttpCommunicationException {
+        String url = baseUrl + "/rest/datapoint/" + sysApUID + "/" + deviceId + "." + channel + "." + datapoint;
+
+        try {
+            Request req = httpClient.newRequest(url);
+
+            if (req == null) {
+                throw new FreeAtHomeHttpCommunicationException(0,
+                        "Invalid request object in getDatapoint with the URL [ " + url + " ]");
+            }
+
+            req.content(new StringContentProvider(valueString));
+            req.method(HttpMethod.PUT);
+
+            logger.debug("Set datapoint by url: {} value: {}", url, valueString);
+
+            ContentResponse response = req.send();
+
+            if (response.getStatus() != 200) {
+                throw new FreeAtHomeHttpCommunicationException(response.getStatus(), response.getReason());
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted [ " + e.getMessage() + " ]");
+        } catch (ExecutionException | TimeoutException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+
+            throw new FreeAtHomeHttpCommunicationException(0,
+                    "Http communication interrupted [ " + e.getMessage() + " ]");
+        }
+
+        return true;
+    }
+
+    /**
+     * Method to process socket events
+     */
+    public void setDatapointOnWebsocketFeedback(String receivedText) {
+        JsonReader reader = new JsonReader(new StringReader(receivedText));
+        reader.setLenient(true);
+        JsonElement jsonTree = JsonParser.parseReader(reader);
+
+        // check the output
+        if (jsonTree.isJsonObject()) {
+            JsonObject jsonObject = jsonTree.getAsJsonObject();
+
+            jsonObject = jsonObject.getAsJsonObject(sysApUID);
+            jsonObject = jsonObject.getAsJsonObject("datapoints");
+
+            Set<String> keys = jsonObject.keySet();
+
+            Iterator<String> iter = keys.iterator();
+
+            while (iter.hasNext()) {
+                String eventDatapointID = iter.next();
+
+                JsonElement element = jsonObject.get(eventDatapointID);
+                String value = element.getAsString();
+
+                String[] parts = eventDatapointID.split("/");
+
+                FreeAtHomeDeviceHandler deviceHandler = mapEventListeners.get(parts[0]);
+
+                if (deviceHandler != null) {
+                    deviceHandler.onDeviceStateChanged(eventDatapointID, value);
+                }
+
+                logger.debug("Socket event processed: event-datapoint-ID {} value {}", eventDatapointID, value);
+            }
+        }
+    }
+
+    public void markDeviceRemovedOnWebsocketFeedback(String receivedText) {
+        JsonReader reader = new JsonReader(new StringReader(receivedText));
+        reader.setLenient(true);
+        JsonElement jsonTree = JsonParser.parseReader(reader);
+
+        // check the output
+        if (jsonTree.isJsonObject()) {
+            JsonObject jsonObject = jsonTree.getAsJsonObject();
+
+            jsonObject = jsonObject.getAsJsonObject(sysApUID);
+            JsonArray jsonArray = jsonObject.getAsJsonArray("devicesRemoved");
+
+            for (JsonElement element : jsonArray) {
+                FreeAtHomeDeviceHandler deviceHandler = mapEventListeners.get(element.getAsString());
+
+                if (deviceHandler != null) {
+                    deviceHandler.onDeviceRemoved();
+
+                    logger.debug("Device removal processed");
+                }
+            }
+        }
+    }
+
+    public void registerDeviceStateListener(String deviceID, FreeAtHomeDeviceHandler deviceHandler) {
+        mapEventListeners.put(deviceID, deviceHandler);
+    }
+
+    public void unregisterDeviceStateListener(String deviceID) {
+        mapEventListeners.remove(deviceID);
+    }
+
+    /**
+     * Method to open Http connection
+     */
+    public boolean openHttpConnection() {
+        boolean ret = false;
+
+        try {
+            // Add authentication credentials.
+            AuthenticationStore auth = httpClient.getAuthenticationStore();
+
+            URI uri1 = new URI(baseUrl);
+            auth.addAuthenticationResult(new BasicAuthentication.BasicResult(uri1, username, password));
+
+            String url = baseUrl + BRIDGE_URL_GETDEVICELIST;
+
+            Request req = httpClient.newRequest(url);
+            ContentResponse res = req.send();
+
+            // check status
+            if (res.getStatus() == HttpStatus.OK_200) {
+                // response OK
+                httpConnectionOK.set(true);
+
+                ret = true;
+
+                logger.debug("HTTP connection to SysAP is OK");
+            } else {
+                // response NOK, set error
+                httpConnectionOK.set(false);
+
+                ret = false;
+            }
+        } catch (URISyntaxException | InterruptedException | ExecutionException | TimeoutException ex) {
+            logger.debug("Initial HTTP connection to SysAP is not successful");
+
+            ret = false;
+        }
+
+        return ret;
+    }
+
+    /**
+     * Method to connect the websocket session
+     */
+    public boolean connectWebsocketSession() {
+        boolean ret = false;
+
+        URI uri = URI.create("ws://" + ipAddress + "/fhapi/v1/api/ws");
+
+        String authString = username + ":" + password;
+
+        // create base64 encoder
+        Base64.Encoder bas64Encoder = Base64.getEncoder();
+
+        // Encoding string using encoder object
+        String authStringEnc = bas64Encoder.encodeToString(authString.getBytes());
+
+        authField = "Basic " + authStringEnc;
+
+        WebSocketClient localWebsocketClient = websocketClient;
+
+        try {
+            // Start socket client
+            if (localWebsocketClient != null) {
+                localWebsocketClient.setMaxTextMessageBufferSize(8 * 1024);
+                localWebsocketClient.setMaxIdleTimeout(BRIDGE_WEBSOCKET_TIMEOUT * 60 * 1000);
+                localWebsocketClient.setConnectTimeout(BRIDGE_WEBSOCKET_TIMEOUT * 60 * 1000);
+                localWebsocketClient.start();
+                ClientUpgradeRequest request = new ClientUpgradeRequest();
+                request.setHeader("Authorization", authField);
+                request.setTimeout(BRIDGE_WEBSOCKET_TIMEOUT, TimeUnit.MINUTES);
+                localWebsocketClient.connect(this, uri, request);
+
+                logger.debug("Websocket connection to SysAP is OK, timeout: {}", BRIDGE_WEBSOCKET_TIMEOUT);
+
+                ret = true;
+            } else {
+                ret = false;
+            }
+        } catch (Exception e) {
+            logger.debug("Error by opening Websocket connection [{}]", e.getMessage());
+
+            if (localWebsocketClient != null) {
+                try {
+                    localWebsocketClient.stop();
+
+                    ret = false;
+                } catch (Exception e1) {
+                    logger.debug("Error by opening Websocket connection [{}]", e1.getMessage());
+
+                    ret = false;
+                }
+            } else {
+                ret = false;
+            }
+        }
+
+        return ret;
+    }
+
+    /**
+     * Method to close the websocket connection
+     */
+    public void closeWebSocketConnection() {
+        socketMonitor.interrupt();
+
+        QueuedThreadPool localThreadPool = jettyThreadPool;
+
+        if (localThreadPool != null) {
+            try {
+                localThreadPool.stop();
+            } catch (Exception e1) {
+                logger.debug("Error by closing Websocket connection [{}]", e1.getMessage());
+            }
+            jettyThreadPool = null;
+        }
+
+        WebSocketClient localWebSocketClient = websocketClient;
+
+        if (localWebSocketClient != null) {
+            try {
+                localWebSocketClient.stop();
+            } catch (Exception e2) {
+                logger.debug("Error by closing Websocket connection [{}]", e2.getMessage());
+            }
+            websocketClient = null;
+        }
+    }
+
+    /**
+     * Method to open the websocket connection
+     */
+    public boolean openWebSocketConnection() {
+        boolean ret = false;
+
+        QueuedThreadPool localThreadPool = jettyThreadPool;
+
+        if (localThreadPool == null) {
+            jettyThreadPool = new QueuedThreadPool();
+
+            localThreadPool = jettyThreadPool;
+
+            if (localThreadPool != null) {
+                localThreadPool.setName(FreeAtHomeBridgeHandler.class.getSimpleName());
+                localThreadPool.setDaemon(true);
+                localThreadPool.setStopTimeout(0);
+
+                ret = true;
+            }
+        }
+
+        WebSocketClient localWebSocketClient = websocketClient;
+
+        if (localWebSocketClient == null) {
+            websocketClient = new WebSocketClient(httpClient);
+
+            localWebSocketClient = websocketClient;
+
+            if (localWebSocketClient != null) {
+                localWebSocketClient.setExecutor(jettyThreadPool);
+
+                socketMonitor.start();
+
+                ret = true;
+            } else {
+                ret = false;
+            }
+        } else {
+            ret = true;
+        }
+
+        return ret;
+    }
+
+    /**
+     * Method to initialize the bridge
+     */
+    @Override
+    public void initialize() {
+        httpConnectionOK.set(false);
+
+        // load configuration
+        FreeAtHomeBridgeHandlerConfiguration locConfig = getConfigAs(FreeAtHomeBridgeHandlerConfiguration.class);
+
+        ipAddress = locConfig.ipAddress;
+        if (ipAddress.isBlank()) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.ip-address-missing");
+            return;
+        }
+
+        password = locConfig.password;
+        if (password.isBlank()) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.password-missing");
+            return;
+        }
+
+        username = locConfig.username;
+        if (username.isBlank()) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.username-missing");
+            return;
+        }
+
+        // build base URL
+        baseUrl = "http://" + ipAddress + "/fhapi/v1/api";
+
+        updateStatus(ThingStatus.UNKNOWN);
+
+        scheduler.execute(() -> {
+            boolean thingReachable = true;
+
+            // Open Http connection
+            if (!openHttpConnection()) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "@text/comm-error.http-wrongpass-or-ip");
+
+                thingReachable = false;
+            }
+
+            // Open the websocket connection for immediate status updates
+            if (!openWebSocketConnection()) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "@text/comm-error.not-able-open-websocketconnection");
+
+                thingReachable = false;
+            }
+
+            if (thingReachable) {
+                updateStatus(ThingStatus.ONLINE);
+            }
+        });
+    }
+
+    /**
+     * Method to dispose
+     */
+    @Override
+    public void dispose() {
+        // let run out the thread
+        socketMonitor.interrupt();
+
+        closeWebSocketConnection();
+    }
+
+    /**
+     * Thread that maintains connection via Websocket.
+     */
+    private class FreeAtHomeWebsocketMonitorThread extends Thread {
+
+        // initial delay to initiate connection
+        private AtomicInteger reconnectDelay = new AtomicInteger();
+
+        public FreeAtHomeWebsocketMonitorThread() {
+        }
+
+        @Override
+        public void run() {
+            // set initial connect delay to 0
+            reconnectDelay.set(0);
+
+            try {
+                while (!isInterrupted()) {
+                    if (httpConnectionOK.get()) {
+                        if (connectSession()) {
+                            while (isSocketConnectionAlive()) {
+                                TimeUnit.SECONDS.sleep(BRIDGE_WEBSOCKET_KEEPALIVE);
+
+                                logger.debug("Sending keep-alive message {}", System.currentTimeMillis());
+                                sendWebsocketKeepAliveMessage("keep-alive");
+                            }
+                        }
+                        logger.debug("Socket connection closed");
+                        reconnectDelay.set(BRIDGE_WEBSOCKET_RECONNECT_DELAY);
+                    } else {
+                        TimeUnit.SECONDS.sleep(BRIDGE_WEBSOCKET_RECONNECT_DELAY);
+                    }
+                }
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "@text/comm-error.general-websocket-issue");
+            } catch (IOException e) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "@text/comm-error.websocket-keep-alive-error");
+            }
+        }
+
+        private boolean connectSession() throws InterruptedException {
+            int delay = reconnectDelay.get();
+
+            if (delay > 0) {
+                logger.debug("Delaying (re)connect request by {} seconds.", reconnectDelay);
+                TimeUnit.SECONDS.sleep(delay);
+            }
+
+            logger.debug("Server connecting to websocket");
+
+            if (!connectWebsocketSession()) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "@text/comm-error.general-websocket-issue");
+
+                reconnectDelay.set(BRIDGE_WEBSOCKET_RECONNECT_DELAY);
+
+                return false;
+            }
+
+            if (websocketSession == null) {
+                lock.lock();
+                try {
+                    websocketSessionEstablished.await();
+                } finally {
+                    lock.unlock();
+                }
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * Send keep-alive message to SysAp
+     */
+    public void sendWebsocketKeepAliveMessage(String message) throws IOException {
+        Session localSession = websocketSession;
+
+        if (localSession != null) {
+            localSession.getRemote().sendString(message);
+        }
+    }
+
+    /**
+     * Get socket alive state
+     * 
+     * @throws InterruptedException
+     */
+    public boolean isSocketConnectionAlive() throws InterruptedException {
+        Session localSession = websocketSession;
+
+        return (localSession != null) ? localSession.isOpen() : false;
+    }
+
+    /**
+     * Socket closed. Report the state
+     */
+    @Override
+    public void onWebSocketClose(int statusCode, @Nullable String reason) {
+        websocketSession = null;
+        logger.debug("Socket Closed: [ {} ] {}", statusCode, reason);
+    }
+
+    /**
+     * Socket connected. store the session for later use
+     */
+    @Override
+    public void onWebSocketConnect(@Nullable Session session) {
+        Session localSession = session;
+
+        if (localSession != null) {
+            websocketSession = localSession;
+
+            localSession.setIdleTimeout(-1);
+
+            logger.debug("Socket Connected - Timeout {} - sesson: {}", localSession.getIdleTimeout(), session);
+        } else {
+            logger.debug("Socket Connected - Timeout (invalid) - sesson: (invalid)");
+        }
+
+        lock.lock();
+        try {
+            websocketSessionEstablished.signal();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Error caused. Report the state
+     */
+    @Override
+    public void onWebSocketError(@Nullable Throwable cause) {
+        websocketSession = null;
+
+        if (cause != null) {
+            logger.debug("Socket Error: {}", cause.getLocalizedMessage());
+        } else {
+            logger.debug("Socket Error: unknown");
+        }
+    }
+
+    /**
+     * Binary message received. It shall not happen with the free@home SysAp
+     */
+    @Override
+    @NonNullByDefault({})
+    public void onWebSocketBinary(byte[] payload, int offset, int len) {
+        logger.debug("Binary message received via websocket");
+    }
+
+    /**
+     * Text message received. Processing will be started
+     */
+    @Override
+    public void onWebSocketText(@Nullable String message) {
+        if (message != null) {
+            if (message.toLowerCase(Locale.US).contains("bye")) {
+                Session localSession = websocketSession;
+
+                if (localSession != null) {
+                    localSession.close(StatusCode.NORMAL, "Thanks");
+                }
+
+                logger.debug("Websocket connection closed: {} ", message);
+            } else {
+                logger.debug("Received websocket text: {} ", message);
+
+                setDatapointOnWebsocketFeedback(message);
+
+                markDeviceRemovedOnWebsocketFeedback(message);
+            }
+        } else {
+            logger.debug("Invalid message string");
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceHandler.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceHandler.java
new file mode 100644 (file)
index 0000000..2165ae3
--- /dev/null
@@ -0,0 +1,635 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.handler;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.freeathome.internal.configuration.FreeAtHomeDeviceHandlerConfiguration;
+import org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDatapoint;
+import org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDatapointGroup;
+import org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDeviceChannel;
+import org.openhab.binding.freeathome.internal.datamodel.FreeAtHomeDeviceDescription;
+import org.openhab.binding.freeathome.internal.type.FreeAtHomeChannelTypeProvider;
+import org.openhab.binding.freeathome.internal.util.FreeAtHomeGeneralException;
+import org.openhab.binding.freeathome.internal.util.FreeAtHomeHttpCommunicationException;
+import org.openhab.binding.freeathome.internal.util.UidUtils;
+import org.openhab.binding.freeathome.internal.valuestateconverter.ValueStateConverter;
+import org.openhab.core.i18n.LocaleProvider;
+import org.openhab.core.i18n.TranslationProvider;
+import org.openhab.core.library.types.StopMoveType;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.thing.Bridge;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.ThingUID;
+import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.builder.ChannelBuilder;
+import org.openhab.core.thing.binding.builder.ThingBuilder;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
+import org.openhab.core.thing.type.ChannelKind;
+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.RefreshType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.StateDescriptionFragmentBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link FreeAtHomeDeviceHandler} is responsible for handling the generic free@home device main communication
+ * and thing updates
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeDeviceHandler extends BaseThingHandler implements FreeAtHomeDeviceStateListener {
+
+    private static final String CHANNEL_URI = "channel-type:freeathome:config";
+
+    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDeviceHandler.class);
+    private FreeAtHomeDeviceDescription device = new FreeAtHomeDeviceDescription();
+    private FreeAtHomeChannelTypeProvider channelTypeProvider;
+    private TranslationProvider i18nProvider;
+    private Locale locale;
+    private Bundle bundle;
+
+    private Map<ChannelUID, FreeAtHomeDatapointGroup> mapChannelUID = new HashMap<ChannelUID, FreeAtHomeDatapointGroup>();
+    private Map<String, ChannelUID> mapEventToChannelUID = new HashMap<String, ChannelUID>();
+
+    public FreeAtHomeDeviceHandler(Thing thing, FreeAtHomeChannelTypeProvider channelTypeProvider,
+            TranslationProvider i18nProvider, LocaleProvider localeProvider) {
+        super(thing);
+
+        this.channelTypeProvider = channelTypeProvider;
+        this.i18nProvider = i18nProvider;
+        this.bundle = FrameworkUtil.getBundle(getClass());
+        this.locale = localeProvider.getLocale();
+    }
+
+    @Override
+    public void initialize() {
+        updateStatus(ThingStatus.UNKNOWN);
+
+        scheduler.execute(() -> {
+            FreeAtHomeDeviceHandlerConfiguration config = getConfigAs(FreeAtHomeDeviceHandlerConfiguration.class);
+
+            Bridge bridge = this.getBridge();
+            String locDeviceId = config.deviceId;
+
+            if (bridge != null) {
+                ThingHandler handler = bridge.getHandler();
+
+                if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
+                    if (!locDeviceId.isBlank()) {
+                        try {
+                            device = bridgeHandler.getFreeatHomeDeviceDescription(locDeviceId);
+
+                            updateChannels();
+                        } catch (FreeAtHomeHttpCommunicationException e) {
+                            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                                    "@text/comm-error.error-in-sysap-com");
+                        } catch (FreeAtHomeGeneralException e) {
+                            logger.debug("General error in the binding - during initialization {}",
+                                    device.getDeviceId());
+
+                            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                                    "@text/conf-error.general-binding-error");
+                        }
+
+                        // register device for status updates
+                        bridgeHandler.registerDeviceStateListener(device.getDeviceId(), this);
+
+                        updateStatus(ThingStatus.ONLINE);
+
+                        logger.debug("Device created - device id: {}", device.getDeviceId());
+                    } else {
+                        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                                "@text/conf-error.invalid-deviceconfig");
+
+                        logger.debug("Device cannot be created: device ID is null!");
+                    }
+                }
+            } else {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
+                        "@text/conf-error.bridge-not-configured");
+
+                logger.debug("Device cannot be created: no bridge is configured!");
+                return;
+            }
+        });
+    }
+
+    @Override
+    public void dispose() {
+        Bridge bridge = this.getBridge();
+
+        // Unregister device and specific channel for event based state updated
+        if (bridge != null) {
+            ThingHandler handler = bridge.getHandler();
+
+            if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
+                bridgeHandler.unregisterDeviceStateListener(device.getDeviceId());
+            }
+        }
+
+        // Remove mapping tables
+        mapChannelUID.clear();
+
+        mapEventToChannelUID.clear();
+
+        logger.debug("Device removed - device id: {}", device.getDeviceId());
+    }
+
+    private void handleRefreshCommand(FreeAtHomeBridgeHandler freeAtHomeBridge, FreeAtHomeDatapointGroup dpg,
+            ChannelUID channelUID) {
+        String valueStr = "0";
+        String channelID = "ch000";
+        String datapointID = "0";
+
+        // Check whether it is a INPUT only datapoint group
+
+        if (dpg.getDirection() == FreeAtHomeDatapointGroup.DatapointGroupDirection.INPUT) {
+            FreeAtHomeDatapoint datapoint = dpg.getInputDatapoint();
+
+            if (datapoint != null) {
+                channelID = datapoint.channelId;
+                datapointID = datapoint.getDatapointId();
+            }
+        } else {
+            FreeAtHomeDatapoint datapoint = dpg.getOutputDatapoint();
+
+            if (datapoint != null) {
+                channelID = datapoint.channelId;
+                datapointID = datapoint.getDatapointId();
+            }
+        }
+
+        try {
+            valueStr = freeAtHomeBridge.getDatapoint(device.getDeviceId(), channelID, datapointID);
+
+            ValueStateConverter vsc = dpg.getValueStateConverter();
+
+            updateState(channelUID, vsc.convertToState(valueStr));
+        } catch (FreeAtHomeHttpCommunicationException e) {
+            logger.debug("Communication error during refresh command {} - at channel {} - Error string {}",
+                    device.getDeviceId(), channelUID.getAsString(), e.getMessage());
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+        } catch (FreeAtHomeGeneralException e) {
+            logger.debug("General error in the binding - during REFRESH command {} - at channel {} - Error string {}",
+                    device.getDeviceId(), channelUID.getAsString(), e.getMessage());
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.general-binding-error");
+        }
+    }
+
+    private void handleSetCommand(FreeAtHomeBridgeHandler freeAtHomeBridge, FreeAtHomeDatapointGroup dpg,
+            ChannelUID channelUID, Command command) {
+        State state = null;
+        String valueString = "0";
+
+        // initial error handling. look for the data point group validity
+        FreeAtHomeDatapoint datapoint = dpg.getInputDatapoint();
+
+        if (datapoint == null) {
+            logger.debug("Invalid parameter in handleSetCommand - DeviceId - {} - at channel {}", device.getDeviceId(),
+                    channelUID.getAsString());
+
+            return;
+        }
+
+        try {
+            ValueStateConverter vsc = dpg.getValueStateConverter();
+
+            if (command instanceof StopMoveType) {
+                valueString = "0";
+            } else {
+                state = ((State) command);
+                valueString = vsc.convertToValueString(state);
+            }
+
+            freeAtHomeBridge.setDatapoint(device.getDeviceId(), datapoint.channelId, datapoint.getDatapointId(),
+                    valueString);
+
+            if (!device.isScene()) {
+                if (state != null) {
+                    updateState(channelUID, state);
+                } else {
+                    updateState(channelUID, new StringType("STOP"));
+                }
+            }
+        } catch (FreeAtHomeHttpCommunicationException e) {
+            logger.debug(
+                    "Communication error during set command {} - at channel {} - full command {} - Error string {}",
+                    device.getDeviceId(), channelUID.getAsString(), command.toFullString(), e.getMessage());
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+        } catch (FreeAtHomeGeneralException e) {
+            logger.debug("General error in the binding - during SET command {} - at channel {} - Error string {}",
+                    device.getDeviceId(), channelUID.getAsString(), e.getMessage());
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.general-binding-error");
+        }
+    }
+
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        FreeAtHomeBridgeHandler freeAtHomeBridge = null;
+
+        Bridge bridge = this.getBridge();
+
+        if (bridge != null) {
+            ThingHandler handler = bridge.getHandler();
+
+            if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
+                freeAtHomeBridge = bridgeHandler;
+            }
+        }
+
+        if (freeAtHomeBridge != null) {
+            updateStatus(ThingStatus.ONLINE);
+        } else {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
+                    "@text/conf-error.invalid-bridge");
+            return;
+        }
+
+        FreeAtHomeDatapointGroup dpg = mapChannelUID.get(channelUID);
+
+        // is the datapointgroup invalid
+        if (dpg == null) {
+            logger.debug("Handle command for device (but invalid datapointgroup) {} - at channel {} - full command {}",
+                    device.getDeviceId(), channelUID.getAsString(), command.toFullString());
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.invalid-deviceconfig");
+        } else {
+            if (command instanceof RefreshType) {
+                handleRefreshCommand(freeAtHomeBridge, dpg, channelUID);
+            } else {
+                handleSetCommand(freeAtHomeBridge, dpg, channelUID, command);
+            }
+
+            logger.debug("Handle command for device {} - at channel {} - full command {}", device.getDeviceId(),
+                    channelUID.getAsString(), command.toFullString());
+        }
+    }
+
+    public void onDeviceRemoved() {
+        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.GONE);
+    }
+
+    public void onDeviceStateChanged(String event, String valueString) {
+        // Get the channle UID belonging to this event
+        ChannelUID channelUID = mapEventToChannelUID.get(event);
+
+        try {
+            if (channelUID != null) {
+                // get the value State Converter for the channel
+                FreeAtHomeDatapointGroup dpg = mapChannelUID.get(channelUID);
+
+                if (dpg != null) {
+                    State state;
+                    state = dpg.getValueStateConverter().convertToState(valueString);
+
+                    // Handle state change
+                    handleEventBasedUpdate(channelUID, state);
+
+                    // if it is virtual device, give a feedback to free@home also
+                    if (isThingHandlesVirtualDevice()) {
+                        feedbackForVirtualDevice(channelUID, valueString);
+                    }
+                }
+            }
+        } catch (FreeAtHomeGeneralException e) {
+            logger.debug("General error in the binding during onDeviceStateChange");
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.general-binding-error");
+        }
+    }
+
+    private void handleEventBasedUpdate(ChannelUID channelUID, State state) {
+        this.updateState(channelUID, state);
+    }
+
+    private void feedbackForVirtualDevice(ChannelUID channelUID, String valueString) {
+        FreeAtHomeBridgeHandler freeAtHomeBridge = null;
+
+        FreeAtHomeDatapointGroup dpg = mapChannelUID.get(channelUID);
+
+        Bridge bridge = this.getBridge();
+
+        if (bridge != null) {
+            ThingHandler handler = bridge.getHandler();
+
+            if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
+                freeAtHomeBridge = bridgeHandler;
+            }
+        }
+
+        if (freeAtHomeBridge == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "@text/gen-error.no-bridge-avail");
+            return;
+        }
+
+        if (dpg == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.datapointgroup-invalid");
+            return;
+        }
+
+        FreeAtHomeDatapoint inputDatapoint = dpg.getInputDatapoint();
+
+        if (inputDatapoint == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "@text/conf-error.inputdatapoint-invalid");
+            return;
+        }
+
+        if ((dpg.getDirection() != FreeAtHomeDatapointGroup.DatapointGroupDirection.INPUT)
+                || (dpg.getDirection() != FreeAtHomeDatapointGroup.DatapointGroupDirection.INPUTOUTPUT)) {
+            logger.debug("Handle feedback for virtual device {} - at channel {} - but wrong config",
+                    device.getDeviceId(), channelUID.getAsString());
+        }
+
+        try {
+            freeAtHomeBridge.setDatapoint(device.getDeviceId(), inputDatapoint.channelId,
+                    inputDatapoint.getDatapointId(), valueString);
+
+            updateStatus(ThingStatus.ONLINE);
+
+            logger.debug("Handle feedback for virtual device {} - at channel {} - value {}", device.getDeviceId(),
+                    channelUID.getAsString(), valueString);
+        } catch (FreeAtHomeHttpCommunicationException e) {
+            logger.debug("Communication error during set command {} - at channel {} - value {} - Error string {}",
+                    device.getDeviceId(), channelUID.getAsString(), valueString, e.getMessage());
+
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.not-able-open-httpconnection");
+        }
+    }
+
+    public ChannelTypeUID createChannelTypeForDatapointgroup(FreeAtHomeDatapointGroup dpg,
+            ChannelTypeUID channelTypeUID) throws FreeAtHomeGeneralException {
+        StateDescriptionFragmentBuilder stateFragment = StateDescriptionFragmentBuilder.create();
+
+        stateFragment.withReadOnly(dpg.isReadOnly());
+        stateFragment.withPattern(dpg.getTypePattern());
+
+        if (dpg.isDecimal() || dpg.isInteger()) {
+            BigDecimal min = new BigDecimal(dpg.getMin());
+            BigDecimal max = new BigDecimal(dpg.getMax());
+            stateFragment.withMinimum(min).withMaximum(max);
+        }
+
+        try {
+            URI configDescriptionUriChannel = new URI(CHANNEL_URI);
+
+            ChannelTypeBuilder<?> channelTypeBuilder = ChannelTypeBuilder
+                    .state(channelTypeUID,
+                            String.format("%s-%s-%s-%s", dpg.getLabel(), dpg.getOpenHabItemType(),
+                                    dpg.getOpenHabCategory(), "type"),
+                            dpg.getOpenHabItemType())
+                    .withCategory(dpg.getOpenHabCategory()).withStateDescriptionFragment(stateFragment.build());
+
+            ChannelType channelType = channelTypeBuilder.isAdvanced(false)
+                    .withConfigDescriptionURI(configDescriptionUriChannel)
+                    .withDescription(String.format("Type for channel - %s ", dpg.getLabel())).build();
+
+            channelTypeProvider.addChannelType(channelType);
+
+            logger.debug("Channel type created {} - label: {} - category: {}", channelTypeUID.getAsString(),
+                    dpg.getLabel(), dpg.getOpenHabCategory());
+        } catch (URISyntaxException e) {
+            logger.debug("Channel config URI cannot created for datapoint - datapoint group: {}", dpg.getLabel());
+        }
+
+        return channelTypeUID;
+    }
+
+    public void updateChannels() throws FreeAtHomeGeneralException {
+        // define update policy
+        AutoUpdatePolicy policy = AutoUpdatePolicy.DEFAULT;
+
+        if (device.isScene()) {
+            policy = AutoUpdatePolicy.VETO;
+        }
+
+        // Initialize channels
+        List<Channel> thingChannels = new ArrayList<>(this.getThing().getChannels());
+
+        if (thingChannels.isEmpty()) {
+            ThingBuilder thingBuilder = editThing();
+
+            ThingUID thingUID = thing.getUID();
+
+            for (int i = 0; i < device.getNumberOfChannels(); i++) {
+                FreeAtHomeDeviceChannel channel = device.getChannel(i);
+
+                for (int j = 0; j < channel.getNumberOfDatapointGroup(); j++) {
+                    FreeAtHomeDatapointGroup dpg = channel.getDatapointGroup(j);
+                    Map<String, String> channelProps = new HashMap<>();
+
+                    FreeAtHomeDatapoint inputDatapoint = dpg.getInputDatapoint();
+                    FreeAtHomeDatapoint outputDatapoint = dpg.getOutputDatapoint();
+
+                    if (inputDatapoint != null) {
+                        channelProps.put("input", inputDatapoint.getDatapointId());
+                    }
+
+                    if (outputDatapoint != null) {
+                        channelProps.put("output", outputDatapoint.getDatapointId());
+                    }
+
+                    ChannelTypeUID channelTypeUID = UidUtils.generateChannelTypeUID(dpg.getValueType(),
+                            dpg.isReadOnly());
+
+                    if (channelTypeProvider.getChannelType(channelTypeUID, null) == null) {
+                        channelTypeUID = createChannelTypeForDatapointgroup(dpg, channelTypeUID);
+                    }
+
+                    ChannelUID channelUID = new ChannelUID(thingUID, channel.getChannelId(),
+                            dpg.getLabel().substring(4));
+
+                    String channelLabel = String.format("%s",
+                            i18nProvider.getText(bundle, dpg.getLabel(), "-", locale));
+
+                    String channelDescription = String.format("(%s) %s", channel.getChannelLabel(),
+                            i18nProvider.getText(bundle, dpg.getDescription(), "-", locale));
+
+                    Channel thingChannel = ChannelBuilder.create(channelUID)
+                            .withAcceptedItemType(dpg.getOpenHabItemType()).withKind(ChannelKind.STATE)
+                            .withProperties(channelProps).withLabel(capitalizeWordsInLabel(channelLabel))
+                            .withDescription(channelDescription).withType(channelTypeUID).withAutoUpdatePolicy(policy)
+                            .build();
+                    thingChannels.add(thingChannel);
+
+                    logger.debug("Thing channel created - device: {} - channelUID: {} - channel label: {}",
+                            device.getDeviceId() + device.getDeviceLabel(), channelUID.getAsString(), channelLabel);
+
+                    // in case of output channel, register it for updates
+                    if (outputDatapoint != null) {
+                        String eventDatapointID = new String(device.getDeviceId() + "/" + channel.getChannelId() + "/"
+                                + outputDatapoint.getDatapointId());
+
+                        mapEventToChannelUID.put(eventDatapointID, channelUID);
+                    }
+
+                    // add the datapoint group to the mapping channel
+                    mapChannelUID.put(channelUID, dpg);
+
+                    if (dpg.getInputDatapoint() == null) {
+                        logger.debug(
+                                "Thing channel registered - device:  {} - channelUID: {} - channel label: {} - category: {}",
+                                device.getDeviceId() + device.getDeviceLabel(), channelUID.getAsString(),
+                                dpg.getLabel(), dpg.getOpenHabCategory());
+                    } else {
+                        logger.debug(
+                                "Thing channel registered - device: {} - channelUID: {} - channel label: {} - category: {}",
+                                device.getDeviceId() + device.getDeviceLabel(), channelUID.getAsString(),
+                                dpg.getLabel(), dpg.getOpenHabCategory());
+                    }
+                }
+
+                thingBuilder.withChannels(thingChannels);
+
+                updateThing(thingBuilder.build());
+            }
+        } else {
+            reloadChannelTypes();
+        }
+
+        thingChannels.forEach(channel -> {
+            if (isLinked(channel.getUID())) {
+                channelLinked(channel.getUID());
+            }
+        });
+    }
+
+    private void reloadChannelTypes() throws FreeAtHomeGeneralException {
+        Bridge bridge = this.getBridge();
+
+        ThingUID thingUID = thing.getUID();
+
+        try {
+            if (bridge != null) {
+                ThingHandler handler = bridge.getHandler();
+
+                if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
+                    device = bridgeHandler.getFreeatHomeDeviceDescription(device.getDeviceId());
+                }
+            }
+        } catch (FreeAtHomeHttpCommunicationException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+        }
+
+        for (int i = 0; i < device.getNumberOfChannels(); i++) {
+            FreeAtHomeDeviceChannel channel = device.getChannel(i);
+
+            for (int j = 0; j < channel.getNumberOfDatapointGroup(); j++) {
+                FreeAtHomeDatapointGroup dpg = channel.getDatapointGroup(j);
+
+                ChannelTypeUID channelTypeUID = UidUtils.generateChannelTypeUID(dpg.getValueType(), dpg.isReadOnly());
+
+                if (channelTypeProvider.getChannelType(channelTypeUID, null) == null) {
+                    channelTypeUID = createChannelTypeForDatapointgroup(dpg, channelTypeUID);
+                }
+
+                ChannelUID channelUID = new ChannelUID(thingUID, channel.getChannelId());
+
+                FreeAtHomeDatapoint outputDatapoint = dpg.getOutputDatapoint();
+
+                // in case of output channel, register it for updates
+                if (outputDatapoint != null) {
+                    String eventDatapointID = new String(device.getDeviceId() + "/" + channel.getChannelId() + "/"
+                            + outputDatapoint.getDatapointId());
+
+                    mapEventToChannelUID.put(eventDatapointID, channelUID);
+                }
+
+                // add the datapoint group to the mapping channel
+                mapChannelUID.put(channelUID, dpg);
+
+                logger.debug("Thing channelType reloaded - Device: {} - channelTypeUID: {}",
+                        device.getDeviceId() + device.getDeviceLabel(), channelTypeUID.getAsString());
+            }
+        }
+    }
+
+    public void removeChannels() {
+        Bridge bridge = this.getBridge();
+
+        try {
+            if (bridge != null) {
+                ThingHandler handler = bridge.getHandler();
+
+                if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
+                    device = bridgeHandler.getFreeatHomeDeviceDescription(device.getDeviceId());
+                }
+            }
+        } catch (FreeAtHomeHttpCommunicationException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                    "@text/comm-error.error-in-sysap-com");
+        }
+
+        mapChannelUID.clear();
+
+        mapEventToChannelUID.clear();
+    }
+
+    private String capitalizeWordsInLabel(String label) {
+        // splliting up words using split function
+        String[] words = label.split(" ");
+
+        for (int i = 0; i < words.length; i++) {
+
+            // taking letter individually from sentences
+            String firstLetter = words[i].substring(0, 1);
+            String restOfWord = words[i].substring(1);
+
+            // making first letter uppercase using toUpperCase function
+            firstLetter = firstLetter.toUpperCase();
+            words[i] = firstLetter + restOfWord;
+        }
+
+        // joining the words together to make a sentence
+        return String.join(" ", words);
+    }
+
+    private boolean isThingHandlesVirtualDevice() {
+        return device.isVirtual();
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceStateListener.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceStateListener.java
new file mode 100644 (file)
index 0000000..2f4b758
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link FreeAtHomeDeviceStateListener} is responsible for response the device state changes from SysAp
+ * and thing updates
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public interface FreeAtHomeDeviceStateListener {
+    void onDeviceRemoved();
+
+    void onDeviceStateChanged(String event, String valueString);
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProvider.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProvider.java
new file mode 100644 (file)
index 0000000..29af322
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.type;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.type.ChannelType;
+import org.openhab.core.thing.type.ChannelTypeProvider;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public interface FreeAtHomeChannelTypeProvider extends ChannelTypeProvider {
+
+    public void addChannelType(ChannelType channelType);
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProviderImpl.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProviderImpl.java
new file mode 100644 (file)
index 0000000..b7c173b
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.type;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.thing.type.ChannelType;
+import org.openhab.core.thing.type.ChannelTypeProvider;
+import org.openhab.core.thing.type.ChannelTypeUID;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@Component(service = { FreeAtHomeChannelTypeProvider.class, ChannelTypeProvider.class })
+@NonNullByDefault
+public class FreeAtHomeChannelTypeProviderImpl implements FreeAtHomeChannelTypeProvider {
+
+    private final Map<ChannelTypeUID, ChannelType> channelTypesByUID = new HashMap<>();
+
+    @Override
+    public Collection<ChannelType> getChannelTypes(@Nullable Locale locale) {
+        Collection<ChannelType> result = new ArrayList<>();
+
+        for (ChannelTypeUID uid : channelTypesByUID.keySet()) {
+            ChannelType channelType = channelTypesByUID.get(uid);
+
+            if (channelType != null) {
+                result.add(channelType);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public @Nullable ChannelType getChannelType(@Nullable ChannelTypeUID channelTypeUID, @Nullable Locale locale) {
+        return channelTypesByUID.get(channelTypeUID);
+    }
+
+    @Override
+    public void addChannelType(@Nullable ChannelType channelType) {
+        if (channelType != null) {
+            channelTypesByUID.put(channelType.getUID(), channelType);
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProvider.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProvider.java
new file mode 100644 (file)
index 0000000..87e71c3
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.type;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.binding.ThingTypeProvider;
+import org.openhab.core.thing.type.ThingType;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public interface FreeAtHomeThingTypeProvider extends ThingTypeProvider {
+
+    /**
+     * Adds the ThingType to this provider.
+     */
+    public void addThingType(ThingType thingType);
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProviderImpl.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProviderImpl.java
new file mode 100644 (file)
index 0000000..bc037e9
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.type;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.ThingTypeProvider;
+import org.openhab.core.thing.type.ThingType;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+
+@Component(service = { FreeAtHomeThingTypeProvider.class, ThingTypeProvider.class })
+@NonNullByDefault
+public class FreeAtHomeThingTypeProviderImpl implements FreeAtHomeThingTypeProvider {
+    private final Map<ThingTypeUID, ThingType> thingTypesByUID = new HashMap<>();
+
+    @Override
+    public Collection<ThingType> getThingTypes(@Nullable Locale locale) {
+        Map<ThingTypeUID, ThingType> copy = new HashMap<>(thingTypesByUID);
+        return copy.values();
+    }
+
+    @Override
+    public @Nullable ThingType getThingType(ThingTypeUID thingTypeUID, @Nullable Locale locale) {
+        return thingTypesByUID.get(thingTypeUID);
+    }
+
+    @Override
+    public void addThingType(@Nullable ThingType thingType) {
+        if (thingType != null) {
+            thingTypesByUID.put(thingType.getUID(), thingType);
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FidTranslationUtils.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FidTranslationUtils.java
new file mode 100644 (file)
index 0000000..0788111
--- /dev/null
@@ -0,0 +1,362 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.util;
+
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link FidTranslationUtils} having constant values for json parsing
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FidTranslationUtils {
+
+    public static final int FID_UNKNOWN = 0xFFFFAAFF; // Unknown
+
+    // free@home constants
+    public static final int FID_SWITCH_SENSOR = 0x0000; // Control element
+    public static final int FID_DIMMING_SENSOR = 0x0001; // Dimming sensor
+    public static final int FID_BLIND_SENSOR = 0x0003; // Blind sensor
+    public static final int FID_STAIRCASE_LIGHT_SENSOR = 0x0004; // Stairwell light sensor
+    public static final int FID_FORCE_ON_OFF_SENSOR = 0x0005; // Force On/Off sensor
+    public static final int FID_SCENE_SENSOR = 0x0006; // Scene sensor
+    public static final int FID_SWITCH_ACTUATOR = 0x0007; // Switch actuator
+    public static final int FID_SHUTTER_ACTUATOR = 0x0009; // Blind actuator
+    public static final int FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITH_FAN = 0x000A; // Room temperature controller
+                                                                                      // with fan speed level
+    public static final int FID_ROOM_TEMPERATURE_CONTROLLER_SLAVE = 0x000B; // Room temperature controller extension
+                                                                            // unit
+    public static final int FID_WIND_ALARM_SENSOR = 0x000C; // Wind Alarm
+    public static final int FID_FROST_ALARM_SENSOR = 0x000D; // Frost Alarm
+    public static final int FID_RAIN_ALARM_SENSOR = 0x000E; // Rain Alarm
+    public static final int FID_WINDOW_DOOR_SENSOR = 0x000F; // Window sensor
+    public static final int FID_MOVEMENT_DETECTOR = 0x0011; // Movement Detector
+    public static final int FID_DIMMING_ACTUATOR = 0x0012; // Dim actuator
+    public static final int FID_RADIATOR_ACTUATOR = 0x0014; // Radiator
+    public static final int FID_UNDERFLOOR_HEATING = 0x0015; // Underfloor heating
+    public static final int FID_FAN_COIL = 0x0016; // Fan Coil
+    public static final int FID_TWO_LEVEL_CONTROLLER = 0x0017; // Two-level controller
+    public static final int FID_DES_DOOR_OPENER_ACTUATOR = 0x001A; // Door opener
+    public static final int FID_PROXY = 0x001B; // Proxy
+    public static final int FID_DES_LEVEL_CALL_ACTUATOR = 0x001D; // Door Map.entry System Call Level Actuator
+    public static final int FID_DES_LEVEL_CALL_SENSOR = 0x001E; // Door Map.entry System Call Level Sensor
+    public static final int FID_DES_DOOR_RINGING_SENSOR = 0x001F; // Door call
+    public static final int FID_DES_AUTOMATIC_DOOR_OPENER_ACTUATOR = 0x0020; // Automatic door opener
+    public static final int FID_DES_LIGHT_SWITCH_ACTUATOR = 0x0021; // Corridor light
+    public static final int FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN = 0x0023; // Room temperature controller
+    public static final int FID_COOLING_ACTUATOR = 0x0024; // Cooling mode
+    public static final int FID_HEATING_ACTUATOR = 0x0027; // Heating mode
+    public static final int FID_FORCE_UP_DOWN_SENSOR = 0x0028; // Force-position blind
+    public static final int FID_HEATING_COOLING_ACTUATOR = 0x0029; // Auto. heating/cooling mode
+    public static final int FID_HEATING_COOLING_SENSOR = 0x002A; // Switchover heating/cooling
+    public static final int FID_DES_DEVICE_SETTINGS = 0x002B; // Device settings
+    public static final int FID_RGB_W_ACTUATOR = 0x002E; // Dim actuator
+    public static final int FID_RGB_ACTUATOR = 0x002F; // Dim actuator
+    public static final int FID_PANEL_SWITCH_SENSOR = 0x0030; // Control element
+    public static final int FID_PANEL_DIMMING_SENSOR = 0x0031; // Dimming sensor
+    public static final int FID_PANEL_BLIND_SENSOR = 0x0033; // Blind sensor
+    public static final int FID_PANEL_STAIRCASE_LIGHT_SENSOR = 0x0034; // Stairwell light sensor
+    public static final int FID_PANEL_FORCE_ON_OFF_SENSOR = 0x0035; // Force On/Off sensor
+    public static final int FID_PANEL_FORCE_UP_DOWN_SENSOR = 0x0036; // Force-position blind
+    public static final int FID_PANEL_SCENE_SENSOR = 0x0037; // Scene sensor
+    public static final int FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE = 0x0038; // Room temperature controller
+                                                                                  // extension unit
+    public static final int FID_PANEL_FAN_COIL_SENSOR = 0x0039; // Fan coil sensor
+    public static final int FID_PANEL_RGB_CT_SENSOR = 0x003A; // RGB + warm white/cold white sensor
+    public static final int FID_PANEL_RGB_SENSOR = 0x003B; // RGB sensor
+    public static final int FID_PANEL_CT_SENSOR = 0x003C; // Warm white/cold white sensor
+    public static final int FID_ADDITIONAL_HEATING_ACTUATOR = 0x003D; // Add. stage for heating mode
+    public static final int FID_RADIATOR_ACTUATOR_MASTER = 0x003E; // Radiator thermostate
+    public static final int FID_RADIATOR_ACTUATOR_SLAVE = 0x003F; // Room temperature controller extension unit
+    public static final int FID_BRIGHTNESS_SENSOR = 0x0041; // Brightness sensor
+    public static final int FID_RAIN_SENSOR = 0x0042; // Rain sensor
+    public static final int FID_TEMPERATURE_SENSOR = 0x0043; // Temperature sensor
+    public static final int FID_WIND_SENSOR = 0x0044; // Wind sensor
+    public static final int FID_TRIGGER = 0x0045; // Trigger
+    public static final int FID_FCA_2_PIPE_HEATING = 0x0047; // Heating mode
+    public static final int FID_FCA_2_PIPE_COOLING = 0x0048; // Cooling mode
+    public static final int FID_FCA_2_PIPE_HEATING_COOLING = 0x0049; // Auto. heating/cooling mode
+    public static final int FID_FCA_4_PIPE_HEATING_AND_COOLING = 0x004A; // Two valves for heating and cooling
+    public static final int FID_WINDOW_DOOR_ACTUATOR = 0x004B; // Window/Door
+    public static final int FID_INVERTER_INFO = 0x004E; // ABC
+    public static final int FID_METER_INFO = 0x004F; // ABD
+    public static final int FID_BATTERY_INFO = 0x0050; // ACD
+    public static final int FID_PANEL_TIMER_PROGRAM_SWITCH_SENSOR = 0x0051; // Timer program switch sensor
+    public static final int FID_DOMUSTECH_ZONE = 0x0055; // Zone
+    public static final int FID_CENTRAL_HEATING_ACTUATOR = 0x0056; // Central heating actuator
+    public static final int FID_CENTRAL_COOLING_ACTUATOR = 0x0057; // Central cooling actuator
+    public static final int FID_HOUSE_KEEPING = 0x0059; // Housekeeping
+    public static final int FID_MEDIA_PLAYER = 0x005A; // Media Player
+    public static final int FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE_FOR_BATTERY_DEVICE = 0x005B; // Panel Room
+                                                                                                     // Temperature
+                                                                                                     // Controller Slave
+                                                                                                     // For Battery
+                                                                                                     // Device
+    public static final int FID_PANEL_MEDIA_PLAYER_SENSOR = 0x0060; // Media Player Sensor
+    public static final int FID_BLIND_ACTUATOR = 0x0061; // Roller blind actuator
+    public static final int FID_ATTIC_WINDOW_ACTUATOR = 0x0062; // Attic window actuator
+    public static final int FID_AWNING_ACTUATOR = 0x0063; // Awning actuator
+    public static final int FID_WINDOW_DOOR_POSITION_SENSOR = 0x0064; // WindowDoor Position Sensor
+    public static final int FID_WINDOW_DOOR_POSITION_ACTUATOR = 0x0065; // Window/Door position
+    public static final int FID_MEDIA_PLAYBACK_CONTROL_SENSOR = 0x0066; // Media playback control sensor
+    public static final int FID_MEDIA_VOLUME_SENSOR = 0x0067; // Media volume sensor
+    public static final int FID_DISHWASHER = 0x0068; // Dishwasher
+    public static final int FID_LAUNDRY = 0x0069; // Laundry
+    public static final int FID_DRYER = 0x006A; // Dryer
+    public static final int FID_OVEN = 0x006B; // Oven
+    public static final int FID_FRIDGE = 0x006C; // Fridge
+    public static final int FID_FREEZER = 0x006D; // Freezer
+    public static final int FID_HOOD = 0x006E; // Hood
+    public static final int FID_COFFEE_MACHINE = 0x006F; // Coffee machine
+    public static final int FID_FRIDGE_FREEZER = 0x0070; // Fridge/Freezer
+    public static final int FID_TIMER_PROGRAM_OR_ALERT_SWITCH_SENSOR = 0x0071; // Timer program switch sensor
+    public static final int FID_CEILING_FAN_ACTUATOR = 0x0073; // Ceiling fan actuator
+    public static final int FID_CEILING_FAN_SENSOR = 0x0074; // Ceiling fan sensor
+    public static final int FID_SPLIT_UNIT_GATEWAY = 0x0075; // Room temperature controller with fan speed level
+    public static final int FID_ZONE = 0x0076; // Zone
+    public static final int FID_24H_ZONE = 0x0077; // Safety
+    public static final int FID_EXTERNAL_IR_SENSOR_BX80 = 0x0078; // External IR Sensor BX80
+    public static final int FID_EXTERNAL_IR_SENSOR_VXI = 0x0079; // External IR Sensor VXI
+    public static final int FID_EXTERNAL_IR_SENSOR_MINI = 0x007A; // External IR Sensor Mini
+    public static final int FID_EXTERNAL_IR_SENSOR_HIGH_ALTITUDE = 0x007B; // External IR Sensor High Altitude
+    public static final int FID_EXTERNAL_IR_SENSOR_CURTAIN = 0x007C; // External IR Sensor Curtain
+    public static final int FID_SMOKE_DETECTOR = 0x007D; // Smoke Detector
+    public static final int FID_CARBON_MONOXIDE_SENSOR = 0x007E; // Carbon Monoxide Sensor
+    public static final int FID_METHANE_DETECTOR = 0x007F; // Methane Detector
+    public static final int FID_GAS_SENSOR_LPG = 0x0080; // Gas Sensor LPG
+    public static final int FID_FLOOD_DETECTION = 0x0081; // Flood Detection
+    public static final int FID_DOMUS_CENTRAL_UNIT_NEXTGEN = 0x0082; // secure@home Central Unit
+    public static final int FID_THERMOSTAT = 0x0083; // Thermostat
+    public static final int FID_PANEL_DOMUS_ZONE_SENSOR = 0x0084; // secure@home Zone Sensor
+    public static final int FID_THERMOSTAT_SLAVE = 0x0085; // Slave thermostat
+    public static final int FID_DOMUS_SECURE_INTEGRATION = 0x0086; // secure@home Integration Logic
+    public static final int FID_ADDITIONAL_COOLING_ACTUATOR = 0x0087; // Add. stage for cooling mode
+    public static final int FID_TWO_LEVEL_HEATING_ACTUATOR = 0x0088; // Two Level Heating Actuator
+    public static final int FID_TWO_LEVEL_COOLING_ACTUATOR = 0x0089; // Two Level Cooling Actuator
+    public static final int FID_GLOBAL_ZONE = 0x008E; // Zone
+    public static final int FID_VOLUME_UP_SENSOR = 0x008F; // Volume up
+    public static final int FID_VOLUME_DOWN_SENSOR = 0x0090; // Volume down
+    public static final int FID_PLAY_PAUSE_SENSOR = 0x0091; // Play/pause
+    public static final int FID_NEXT_FAVORITE_SENSOR = 0x0092; // Next favorite
+    public static final int FID_NEXT_SONG_SENSOR = 0x0093; // Next song
+    public static final int FID_PREVIOUS_SONG_SENSOR = 0x0094; // Previous song
+    public static final int FID_HOME_APPLIANCE_SENSOR = 0x0095; // Home appliance sensor
+    public static final int FID_HEAT_SENSOR = 0x0096; // Heat sensor
+    public static final int FID_ZONE_SWITCHING = 0x0097; // Zone switching
+    public static final int FID_SECURE_AT_HOME_FUNCTION = 0x0098; // Button function
+    public static final int FID_COMPLEX_CONFIGURATION = 0x0099; // Advanced configuration
+    public static final int FID_DOMUS_CENTRAL_UNIT_BASIC = 0x009A; // secure@home Central Unit Basic
+    public static final int FID_DOMUS_REPEATER = 0x009B; // Repeater
+    public static final int FID_DOMUS_SCENE_TRIGGER = 0x009C; // Remote scene control
+    public static final int FID_DOMUSWINDOWCONTACT = 0x009D; // Window sensor
+    public static final int FID_DOMUSMOVEMENTDETECTOR = 0x009E; // Movement Detector
+    public static final int FID_DOMUSCURTAINDETECTOR = 0x009F; // External IR Sensor Curtain
+    public static final int FID_DOMUSSMOKEDETECTOR = 0x00A0; // Smoke Detector
+    public static final int FID_DOMUSFLOODDETECTOR = 0x00A1; // Flood Detection
+    public static final int FID_PANEL_SUG_SENSOR = 0x00A3; // Sensor for air-conditioning unit
+    public static final int FID_TWO_LEVEL_HEATING_COOLING_ACTUATOR = 0x00A4; // Two-point controller for heating or
+                                                                             // cooling
+    public static final int FID_PANEL_THERMOSTAT_CONTROLLER_SLAVE = 0x00A5; // Slave thermostat
+    public static final int FID_WALLBOX = 0x00A6; // Wallbox
+    public static final int FID_PANEL_WALLBOX = 0x00A7; // Wallbox
+    public static final int FID_DOOR_LOCK_CONTROL = 0x00A8; // Door lock control
+    public static final int FID_VRV_GATEWAY = 0x00AA; // Room temperature controller with fan speed level
+
+    public static final int FID_SCENE_TRIGGER = 0x4800; // Scene trigger
+    public static final int FID_RULE_SWITCH = 0x4A00; // Scene trigger
+
+    // FID added based on tests
+    public static final int FID_AIRQUALITYSENSOR_PRESSURE = 0x0E017;
+    public static final int FID_AIRQUALITYSENSOR_CO2 = 0x0E018;
+    public static final int FID_AIRQUALITYSENSOR_CO = 0x0E019;
+    public static final int FID_AIRQUALITYSENSOR_NO2 = 0x0E01A;
+    public static final int FID_AIRQUALITYSENSOR_O3 = 0x0E01B;
+    public static final int FID_AIRQUALITYSENSOR_PM10 = 0x0E01C;
+    public static final int FID_AIRQUALITYSENSOR_PM25 = 0x0E01D;
+    public static final int FID_AIRQUALITYSENSOR_VOC = 0x0E01E;
+    public static final int FID_AIRQUALITYSENSOR_HUMIDITY = 0x0B03F;
+
+    public static final int FID_MOVEMENT_DETECTOR_FLEX = 0x1090;
+    public static final int FID_DIMMING_ACTUATOR_FLEX = 0x1810;
+
+    private static final Map<String, String> MAP_FUNCTION_ID = Map.ofEntries(Map.entry("0x0000", "fid-control-element"), // FID_SWITCH_SENSOR
+            Map.entry("0x0001", "fid-dimming-sensor"), // FID_DIMMING_SENSOR
+            Map.entry("0x0003", "fid-blind-sensor"), // FID_BLIND_SENSOR
+            Map.entry("0x0004", "fid-stairwell-light-sensor"), // FID_STAIRCASE_LIGHT_SENSOR
+            Map.entry("0x0005", "fid-force-on/off-sensor"), // FID_FORCE_ON_OFF_SENSOR
+            Map.entry("0x0006", "fid-scene-sensor"), // FID_SCENE_SENSOR
+            Map.entry("0x0007", "fid-switch-actuator"), // FID_SWITCH_ACTUATOR
+            Map.entry("0x0009", "fid-blind-actuator"), // FID_SHUTTER_ACTUATOR
+            Map.entry("0x000A", "fid-room-temperature-controller-with-fan-speed-level"), // FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITH_FAN
+            Map.entry("0x000B", "fid-room-temperature-controller-extension-unit"), // FID_ROOM_TEMPERATURE_CONTROLLER_SLAVE
+            Map.entry("0x000C", "fid-wind-alarm"), // FID_WIND_ALARM_SENSOR
+            Map.entry("0x000D", "fid-frost-alarm"), // FID_FROST_ALARM_SENSOR
+            Map.entry("0x000E", "fid-rain-alarm"), // FID_RAIN_ALARM_SENSOR
+            Map.entry("0x000F", "fid-window-sensor"), // FID_WINDOW_DOOR_SENSOR
+            Map.entry("0x0011", "fid-movement-detector"), // FID_MOVEMENT_DETECTOR
+            Map.entry("0x0012", "fid-dim-actuator"), // FID_DIMMING_ACTUATOR
+            Map.entry("0x0014", "fid-radiator"), // FID_RADIATOR_ACTUATOR
+            Map.entry("0x0015", "fid-underfloor-heating"), // FID_UNDERFLOOR_HEATING
+            Map.entry("0x0016", "fid-fan-coil"), // FID_FAN_COIL
+            Map.entry("0x0017", "fid-two-level-controller"), // FID_TWO_LEVEL_CONTROLLER
+            Map.entry("0x001A", "fid-door-opener"), // FID_DES_DOOR_OPENER_ACTUATOR
+            Map.entry("0x001B", "fid-proxy"), // FID_PROXY
+            Map.entry("0x001D", "fid-door-map.entry-system-call-level-actuator"), // FID_DES_LEVEL_CALL_ACTUATOR
+            Map.entry("0x001E", "fid-door-map.entry-system-call-level-sensor"), // FID_DES_LEVEL_CALL_SENSOR
+            Map.entry("0x001F", "fid-door-call"), // FID_DES_DOOR_RINGING_SENSOR
+            Map.entry("0x0020", "fid-automatic-door-opener"), // FID_DES_AUTOMATIC_DOOR_OPENER_ACTUATOR
+            Map.entry("0x0021", "fid-corridor-light"), // FID_DES_LIGHT_SWITCH_ACTUATOR
+            Map.entry("0x0023", "fid-room-temperature-controller"), // FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN
+            Map.entry("0x0024", "fid-cooling-mode"), // FID_COOLING_ACTUATOR
+            Map.entry("0x0027", "fid-heating-mode"), // FID_HEATING_ACTUATOR
+            Map.entry("0x0028", "fid-force-position-blind"), // FID_FORCE_UP_DOWN_SENSOR
+            Map.entry("0x0029", "fid-auto.-heating/cooling-mode"), // FID_HEATING_COOLING_ACTUATOR
+            Map.entry("0x002A", "fid-switchover-heating/cooling"), // FID_HEATING_COOLING_SENSOR
+            Map.entry("0x002B", "fid-device-settings"), // FID_DES_DEVICE_SETTINGS
+            Map.entry("0x002E", "fid-dim-actuator"), // FID_RGB_W_ACTUATOR
+            Map.entry("0x002F", "fid-dim-actuator"), // FID_RGB_ACTUATOR
+            Map.entry("0x0030", "fid-control-element"), // FID_PANEL_SWITCH_SENSOR
+            Map.entry("0x0031", "fid-dimming-sensor"), // FID_PANEL_DIMMING_SENSOR
+            Map.entry("0x0033", "fid-blind-sensor"), // FID_PANEL_BLIND_SENSOR
+            Map.entry("0x0034", "fid-stairwell-light-sensor"), // FID_PANEL_STAIRCASE_LIGHT_SENSOR
+            Map.entry("0x0035", "fid-force-on/off-sensor"), // FID_PANEL_FORCE_ON_OFF_SENSOR
+            Map.entry("0x0036", "fid-force-position-blind"), // FID_PANEL_FORCE_UP_DOWN_SENSOR
+            Map.entry("0x0037", "fid-scene-sensor"), // FID_PANEL_SCENE_SENSOR
+            Map.entry("0x0038", "fid-room-temperature-controller-extension-unit"), // FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE
+            Map.entry("0x0039", "fid-fan-coil-sensor"), // FID_PANEL_FAN_COIL_SENSOR
+            Map.entry("0x003A", "fid-rgb-+-warm-white/cold-white-sensor"), // FID_PANEL_RGB_CT_SENSOR
+            Map.entry("0x003B", "fid-rgb-sensor"), // FID_PANEL_RGB_SENSOR
+            Map.entry("0x003C", "fid-warm-white/cold-white-sensor"), // FID_PANEL_CT_SENSOR
+            Map.entry("0x003D", "fid-add.-stage-for-heating-mode"), // FID_ADDITIONAL_HEATING_ACTUATOR
+            Map.entry("0x003E", "fid-radiator-thermostate"), // FID_RADIATOR_ACTUATOR_MASTER
+            Map.entry("0x003F", "fid-room-temperature-controller-extension-unit"), // FID_RADIATOR_ACTUATOR_SLAVE
+            Map.entry("0x0041", "fid-brightness-sensor"), // FID_BRIGHTNESS_SENSOR
+            Map.entry("0x0042", "fid-rain-sensor"), // FID_RAIN_SENSOR
+            Map.entry("0x0043", "fid-temperature-sensor"), // FID_TEMPERATURE_SENSOR
+            Map.entry("0x0044", "fid-wind-sensor"), // FID_WIND_SENSOR
+            Map.entry("0x0045", "fid-trigger"), // FID_TRIGGER
+            Map.entry("0x0047", "fid-heating-mode"), // FID_FCA_2_PIPE_HEATING
+            Map.entry("0x0048", "fid-cooling-mode"), // FID_FCA_2_PIPE_COOLING
+            Map.entry("0x0049", "fid-auto.-heating/cooling-mode"), // FID_FCA_2_PIPE_HEATING_COOLING
+            Map.entry("0x004A", "fid-two-valves-for-heating-and-cooling"), // FID_FCA_4_PIPE_HEATING_AND_COOLING
+            Map.entry("0x004B", "fid-window/door"), // FID_WINDOW_DOOR_ACTUATOR
+            Map.entry("0x004E", "fid-abc"), // FID_INVERTER_INFO
+            Map.entry("0x004F", "fid-abd"), // FID_METER_INFO
+            Map.entry("0x0050", "fid-acd"), // FID_BATTERY_INFO
+            Map.entry("0x0051", "fid-timer-program-switch-sensor"), // FID_PANEL_TIMER_PROGRAM_SWITCH_SENSOR
+            Map.entry("0x0055", "fid-zone"), // FID_DOMUSTECH_ZONE
+            Map.entry("0x0056", "fid-central-heating-actuator"), // FID_CENTRAL_HEATING_ACTUATOR
+            Map.entry("0x0057", "fid-central-cooling-actuator"), // FID_CENTRAL_COOLING_ACTUATOR
+            Map.entry("0x0059", "fid-housekeeping"), // FID_HOUSE_KEEPING
+            Map.entry("0x005A", "fid-media-player"), // FID_MEDIA_PLAYER
+            Map.entry("0x005B", "fid-panel-room-temperature-controller-slave-for-battery-device"), // FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE_FOR_BATTERY_DEVICE
+            Map.entry("0x0060", "fid-media-player-sensor"), // FID_PANEL_MEDIA_PLAYER_SENSOR
+            Map.entry("0x0061", "fid-roller-blind-actuator"), // FID_BLIND_ACTUATOR
+            Map.entry("0x0062", "fid-attic-window-actuator"), // FID_ATTIC_WINDOW_ACTUATOR
+            Map.entry("0x0063", "fid-awning-actuator"), // FID_AWNING_ACTUATOR
+            Map.entry("0x0064", "fid-windowdoor-position-sensor"), // FID_WINDOW_DOOR_POSITION_SENSOR
+            Map.entry("0x0065", "fid-window/door-position"), // FID_WINDOW_DOOR_POSITION_ACTUATOR
+            Map.entry("0x0066", "fid-media-playback-control-sensor"), // FID_MEDIA_PLAYBACK_CONTROL_SENSOR
+            Map.entry("0x0067", "fid-media-volume-sensor"), // FID_MEDIA_VOLUME_SENSOR
+            Map.entry("0x0068", "fid-dishwasher"), // FID_DISHWASHER
+            Map.entry("0x0069", "fid-laundry"), // FID_LAUNDRY
+            Map.entry("0x006A", "fid-dryer"), // FID_DRYER
+            Map.entry("0x006B", "fid-oven"), // FID_OVEN
+            Map.entry("0x006C", "fid-fridge"), // FID_FRIDGE
+            Map.entry("0x006D", "fid-freezer"), // FID_FREEZER
+            Map.entry("0x006E", "fid-hood"), // FID_HOOD
+            Map.entry("0x006F", "fid-coffee-machine"), // FID_COFFEE_MACHINE
+            Map.entry("0x0070", "fid-fridge/freezer"), // FID_FRIDGE_FREEZER
+            Map.entry("0x0071", "fid-timer-program-switch-sensor"), // FID_TIMER_PROGRAM_OR_ALERT_SWITCH_SENSOR
+            Map.entry("0x0073", "fid-ceiling-fan-actuator"), // FID_CEILING_FAN_ACTUATOR
+            Map.entry("0x0074", "fid-ceiling-fan-sensor"), // FID_CEILING_FAN_SENSOR
+            Map.entry("0x0075", "fid-room-temperature-controller-with-fan-speed-level"), // FID_SPLIT_UNIT_GATEWAY
+            Map.entry("0x0076", "fid-zone"), // FID_ZONE
+            Map.entry("0x0077", "fid-safety"), // FID_24H_ZONE
+            Map.entry("0x0078", "fid-external-ir-sensor-bx80"), // FID_EXTERNAL_IR_SENSOR_BX80
+            Map.entry("0x0079", "fid-external-ir-sensor-vxi"), // FID_EXTERNAL_IR_SENSOR_VXI
+            Map.entry("0x007A", "fid-external-ir-sensor-mini"), // FID_EXTERNAL_IR_SENSOR_MINI
+            Map.entry("0x007B", "fid-external-ir-sensor-high-altitude"), // FID_EXTERNAL_IR_SENSOR_HIGH_ALTITUDE
+            Map.entry("0x007C", "fid-external-ir-sensor-curtain"), // FID_EXTERNAL_IR_SENSOR_CURTAIN
+            Map.entry("0x007D", "fid-smoke-detector"), // FID_SMOKE_DETECTOR
+            Map.entry("0x007E", "fid-carbon-monoxide-sensor"), // FID_CARBON_MONOXIDE_SENSOR
+            Map.entry("0x007F", "fid-methane-detector"), // FID_METHANE_DETECTOR
+            Map.entry("0x0080", "fid-gas-sensor-lpg"), // FID_GAS_SENSOR_LPG
+            Map.entry("0x0081", "fid-flood-detection"), // FID_FLOOD_DETECTION
+            Map.entry("0x0082", "fid-secure@home-central-unit"), // FID_DOMUS_CENTRAL_UNIT_NEXTGEN
+            Map.entry("0x0083", "fid-thermostat"), // FID_THERMOSTAT
+            Map.entry("0x0084", "fid-secure@home-zone-sensor"), // FID_PANEL_DOMUS_ZONE_SENSOR
+            Map.entry("0x0085", "fid-slave-thermostat"), // FID_THERMOSTAT_SLAVE
+            Map.entry("0x0086", "fid-secure@home-integration-logic"), // FID_DOMUS_SECURE_INTEGRATION
+            Map.entry("0x0087", "fid-add.-stage-for-cooling-mode"), // FID_ADDITIONAL_COOLING_ACTUATOR
+            Map.entry("0x0088", "fid-two-level-heating-actuator"), // FID_TWO_LEVEL_HEATING_ACTUATOR
+            Map.entry("0x0089", "fid-two-level-cooling-actuator"), // FID_TWO_LEVEL_COOLING_ACTUATOR
+            Map.entry("0x008E", "fid-zone"), // FID_GLOBAL_ZONE
+            Map.entry("0x008F", "fid-volume-up"), // FID_VOLUME_UP_SENSOR
+            Map.entry("0x0090", "fid-volume-down"), // FID_VOLUME_DOWN_SENSOR
+            Map.entry("0x0091", "fid-play/pause"), // FID_PLAY_PAUSE_SENSOR
+            Map.entry("0x0092", "fid-next-favorite"), // FID_NEXT_FAVORITE_SENSOR
+            Map.entry("0x0093", "fid-next-song"), // FID_NEXT_SONG_SENSOR
+            Map.entry("0x0094", "fid-previous-song"), // FID_PREVIOUS_SONG_SENSOR
+            Map.entry("0x0095", "fid-home-appliance-sensor"), // FID_HOME_APPLIANCE_SENSOR
+            Map.entry("0x0096", "fid-heat-sensor"), // FID_HEAT_SENSOR
+            Map.entry("0x0097", "fid-zone-switching"), // FID_ZONE_SWITCHING
+            Map.entry("0x0098", "fid-button-function"), // FID_SECURE_AT_HOME_FUNCTION
+            Map.entry("0x0099", "fid-advanced-configuration"), // FID_COMPLEX_CONFIGURATION
+            Map.entry("0x009A", "fid-secure@home-central-unit-basic"), // FID_DOMUS_CENTRAL_UNIT_BASIC
+            Map.entry("0x009B", "fid-repeater"), // FID_DOMUS_REPEATER
+            Map.entry("0x009C", "fid-remote-scene-control"), // FID_DOMUS_SCENE_TRIGGER
+            Map.entry("0x009D", "fid-window-sensor"), // FID_DOMUSWINDOWCONTACT
+            Map.entry("0x009E", "fid-movement-detector"), // FID_DOMUSMOVEMENTDETECTOR
+            Map.entry("0x009F", "fid-external-ir-sensor-curtain"), // FID_DOMUSCURTAINDETECTOR
+            Map.entry("0x00A0", "fid-smoke-detector"), // FID_DOMUSSMOKEDETECTOR
+            Map.entry("0x00A1", "fid-flood-detection"), // FID_DOMUSFLOODDETECTOR
+            Map.entry("0x00A3", "fid-sensor-for-air-conditioning-unit"), // FID_PANEL_SUG_SENSOR
+            Map.entry("0x00A4", "fid-two-point-controller-for-heating-or-cooling"), // FID_TWO_LEVEL_HEATING_COOLING_ACTUATOR
+            Map.entry("0x00A5", "fid-slave-thermostat"), // FID_PANEL_THERMOSTAT_CONTROLLER_SLAVE
+            Map.entry("0x00A6", "fid-wallbox"), // FID_WALLBOX
+            Map.entry("0x00A7", "fid-wallbox"), // FID_PANEL_WALLBOX
+            Map.entry("0x00A8", "fid-door-lock-control"), // FID_DOOR_LOCK_CONTROL
+            Map.entry("0x00AA", "fid-room-temperature-controller-with-fan-speed-level"), // FID_VRV_GATEWAY
+            Map.entry("0x4800", "fid-scene-trigger"), // FID_SCENE_TRIGGER
+            Map.entry("0x4A00", "fid-rule-switch"), // FID_RULE_SWITCH
+            Map.entry("0xE017", "fid-air-quality-sensor-pressure"), // FID_AIRQUALITYSENSOR_PRESSURE
+            Map.entry("0xE018", "fid-air-quality-sensor-co2"), // FID_AIRQUALITYSENSOR_CO2
+            Map.entry("0xE019", "fid-air-quality-sensor-co"), // FID_AIRQUALITYSENSOR_CO
+            Map.entry("0xE01A", "fid-air-quality-sensor-no2"), // FID_AIRQUALITYSENSOR_NO2
+            Map.entry("0xE01B", "fid-air-quality-sensor-o3"), // FID_AIRQUALITYSENSOR_O3
+            Map.entry("0xE01C", "fid-air-quality-sensor-pm10"), // FID_AIRQUALITYSENSOR_PM10
+            Map.entry("0xE01D", "fid-air-quality-sensor-pm25"), // FID_AIRQUALITYSENSOR_PM25
+            Map.entry("0xE01E", "fid-air-quality-sensor-voc"), // FID_AIRQUALITYSENSOR_VOC
+            Map.entry("0xB03F", "fid-air-quality-sensor-humidity"), // FID_AIRQUALITYSENSOR_HUMIDITY
+            Map.entry("0x1090", "fid-movement-detector-flex"), // FID_MOVEMENT_DETECTOR_FLEX
+            Map.entry("0x1810", "fid-dim-actuator-flex") // FID_SWITCH_ACTUATOR_FLEX
+    );
+
+    @Nullable
+    public static String getFunctionIdText(String Key) throws FreeAtHomeGeneralException {
+        String result = MAP_FUNCTION_ID.get(Key);
+
+        if (result != null) {
+            return MAP_FUNCTION_ID.get(Key);
+        } else {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "FID is not in the translation table", Key));
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeGeneralException.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeGeneralException.java
new file mode 100644 (file)
index 0000000..ca51112
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.util;
+
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link FreeAtHomeGeneralException} is responsible for handling general exceptions in the free@home binding
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeGeneralException extends Exception {
+    private static final long serialVersionUID = -835448863173642860L;
+    private String errorMessage = "Unknown_Exception";
+    private int errorCode = 0;
+
+    public FreeAtHomeGeneralException(int errorCode, String message) {
+        super(message);
+
+        this.errorMessage = message;
+        this.errorCode = errorCode;
+    }
+
+    public @Nullable String getMessage() {
+        return this.errorMessage;
+    }
+
+    public int getErrorCode() {
+        return this.errorCode;
+    }
+
+    @Override
+    public String toString() {
+        return "FreeAtHomeHttpCommunicationException [errorMessage=" + errorMessage + ", errorCode=" + errorCode + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(errorCode, errorMessage);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        FreeAtHomeGeneralException other = (FreeAtHomeGeneralException) obj;
+
+        return errorCode == other.errorCode && Objects.equals(errorMessage, other.errorMessage);
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeHttpCommunicationException.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeHttpCommunicationException.java
new file mode 100644 (file)
index 0000000..44e377e
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.util;
+
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link FreeAtHomeHttpCommunicationException} is responsible for handling the communication exception to the SysAp
+ * via HTTP link
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class FreeAtHomeHttpCommunicationException extends Exception {
+    private static final long serialVersionUID = -817364286035448863L;
+    private String errorMessage = "Unknown_Exception";
+    private int errorCode;
+
+    public FreeAtHomeHttpCommunicationException(int errorCode, String message) {
+        super(message);
+
+        this.errorMessage = message;
+        this.errorCode = errorCode;
+    }
+
+    public @Nullable String getMessage() {
+        return this.errorMessage;
+    }
+
+    public int getErrorCode() {
+        return this.errorCode;
+    }
+
+    @Override
+    public String toString() {
+        return "FreeAtHomeHttpCommunicationException [errorMessage=" + errorMessage + ", errorCode=" + errorCode + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(errorCode, errorMessage);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        FreeAtHomeHttpCommunicationException other = (FreeAtHomeHttpCommunicationException) obj;
+
+        return errorCode == other.errorCode && Objects.equals(errorMessage, other.errorMessage);
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PIdContainerClass.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PIdContainerClass.java
new file mode 100644 (file)
index 0000000..c2b9150
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.util;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link PIdContainerClass} is a helper class for pairing IDs
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class PIdContainerClass {
+    String valueType;
+    String category;
+    int min;
+    int max;
+    String label;
+    String description;
+
+    PIdContainerClass(String pValueType, String pCategory, String pMin, String pMax, String pLabel,
+            String pDescription) {
+        this.valueType = pValueType;
+
+        this.category = pCategory;
+
+        if (pMax.isEmpty()) {
+            this.min = 0;
+        } else {
+            this.min = Integer.parseInt(pMin);
+        }
+
+        if (pMax.isEmpty()) {
+            this.max = 100;
+        } else {
+            this.max = Integer.parseInt(pMax);
+        }
+
+        this.label = pLabel;
+
+        this.description = pDescription;
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PidTranslationUtils.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PidTranslationUtils.java
new file mode 100644 (file)
index 0000000..54b9e7c
--- /dev/null
@@ -0,0 +1,829 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.util;
+
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link PidTranslationUtils} supporting the translation from pairing IDs into openHAB types
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class PidTranslationUtils {
+    public static final String PID_VALUETYPE_UNKNOWN = "unknown";
+    public static final String PID_VALUETYPE_BOOLEAN = "boolean";
+    public static final String PID_VALUETYPE_DECIMAL = "decimal";
+    public static final String PID_VALUETYPE_INTEGER = "integer";
+    public static final String PID_VALUETYPE_STRING = "string";
+    public static final String PID_VALUETYPE_SHUTTERMOVEMENT = "shuttermovement";
+    public static final String PID_VALUETYPE_ENUM = "enum";
+
+    public static final String CATEGORY_UNDEFINED = "-";
+    public static final String CATEGORY_BATTERY = "Battery";
+    public static final String CATEGORY_ALARM = "Alarm";
+    public static final String CATEGORY_HUMIDITY = "Humidity";
+    public static final String CATEGORY_TEMPERATURE = "Temperature";
+    public static final String CATEGORY_MOTION = "Motion";
+    public static final String CATEGORY_PRESSURE = "Pressure";
+    public static final String CATEGORY_SMOKE = "Smoke";
+    public static final String CATEGORY_WATER = "Water";
+    public static final String CATEGORY_WIND = "Wind";
+    public static final String CATEGORY_RAIN = "Rain";
+    public static final String CATEGORY_ENERGY = "Energy";
+    public static final String CATEGORY_BLINDS = "Blinds";
+    public static final String CATEGORY_CONTACT = "Contact";
+    public static final String CATEGORY_SWITCH = "Switch";
+
+    private static final Map<String, PIdContainerClass> MAP_PAIRING_ID = Map.ofEntries(
+            Map.entry("0x0001",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "0", "1", "pid-switch-on-off",
+                            "pid-switch-on-off-text")),
+            Map.entry("0x0002",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-timed-start-stop",
+                            "pid-timed-start-stop-text")),
+            Map.entry("0x0003",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-force-position",
+                            "pid-force-position-text")),
+            Map.entry("0x0004",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-scene-control",
+                            "pid-scene-control-text")),
+            Map.entry("0x0006",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_MOTION, "", "",
+                            "pid-movement-under-consideration-of-brightness",
+                            "pid-movement-under-consideration-of-brightness-text")),
+            Map.entry("0x0007",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_MOTION, "", "", "pid-presence",
+                            "pid-presence-text")),
+            Map.entry("0x0010",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-relative-set-value",
+                            "pid-relative-set-value-text")),
+            Map.entry("0x0011",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-absolute-set-value",
+                            "pid-absolute-set-value-text")),
+            Map.entry("0x0012",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-night",
+                            "pid-night-text")),
+            Map.entry("0x0013",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-invalid-string-id",
+                            "pid-invalid-string-id-text")),
+            Map.entry("0x0015",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-rgb-color",
+                            "pid-rgb-color-text")),
+            Map.entry("0x0016",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-color-temperature",
+                            "pid-color-temperature-text")),
+            Map.entry("0x0017",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-hsv",
+                            "pid-hsv-text")),
+            Map.entry("0x0018",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-hue",
+                            "pid-hue-text")),
+            Map.entry("0x0019",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-saturation",
+                            "pid-saturation-text")),
+            Map.entry("0x0020",
+                    new PIdContainerClass(PID_VALUETYPE_SHUTTERMOVEMENT, CATEGORY_BLINDS, "", "", "pid-move-up-down",
+                            "pid-move-up-down-text")),
+            Map.entry("0x0021",
+                    new PIdContainerClass(PID_VALUETYPE_SHUTTERMOVEMENT, CATEGORY_BLINDS, "", "", "pid-adjust-up-down",
+                            "pid-adjust-up-down-text")),
+            Map.entry("0x0023",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_BLINDS, "0", "100",
+                            "pid-set-absolute-position-blinds", "pid-set-absolute-position-blinds-text")),
+            Map.entry("0x0024",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_BLINDS, "0", "100",
+                            "pid-set-absolute-position-slats", "pid-set-absolute-position-slats-text")),
+            Map.entry("0x0025",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_WIND, "", "", "pid-wind-alarm",
+                            "pid-wind-alarm-text")),
+            Map.entry("0x0026",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_TEMPERATURE, "", "", "pid-frost-alarm",
+                            "pid-frost-alarm-text")),
+            Map.entry("0x0027",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_RAIN, "", "", "pid-rain-alarm",
+                            "pid-rain-alarm-text")),
+            Map.entry("0x0028",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-force-position-blind",
+                            "pid-force-position-blind-text")),
+            Map.entry("0x0029",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-window-door-position",
+                            "pid-window-door-position-text")),
+            Map.entry("0x0030",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-actuating-value-heating", "pid-actuating-value-heating-text")),
+            Map.entry("0x0031",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-fan-level-heating",
+                            "pid-fan-level-heating-text")),
+            Map.entry("0x0032",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-actuating-value-cooling", "pid-actuating-value-cooling-text")),
+            Map.entry("0x0033",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
+                            "pid-set-value-temperature", "pid-set-value-temperature-text")),
+            Map.entry("0x0034",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
+                            "pid-relative-set-point-temperature", "pid-relative-set-point-temperature-text")),
+            Map.entry("0x0035",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-window-door",
+                            "pid-window-door-text")),
+            Map.entry("0x0036",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-status-indication",
+                            "pid-status-indication-text")),
+            Map.entry("0x0037",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
+                            "pid-fan-manual-heating-on-off", "pid-fan-manual-heating-on-off-text")),
+            Map.entry("0x0038",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-controller-on-off",
+                            "pid-controller-on-off-text")),
+            Map.entry("0x0039",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
+                            "pid-relative-set-point-request", "pid-relative-set-point-request-text")),
+            Map.entry("0x003A",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-eco-mode-on-off-request",
+                            "pid-eco-mode-on-off-request-text")),
+            Map.entry("0x003B",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
+                            "pid-comfort-temperature", "pid-comfort-temperature-text")),
+            Map.entry("0x0040",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-fan-level-request",
+                            "pid-fan-level-request-text")),
+            Map.entry("0x0041",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
+                            "pid-fan-manual-on-off-request", "pid-fan-manual-on-off-request-text")),
+            Map.entry("0x0042",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
+                            "pid-controller-on-off-request", "pid-controller-on-off-request-text")),
+            Map.entry("0x0044",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-eco-mode-on-off-request",
+                            "pid-eco-mode-on-off-request-text")),
+            Map.entry("0x0100",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-info-on-off",
+                            "pid-info-on-off-text")),
+            Map.entry("0x0101",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-force-position-info",
+                            "pid-force-position-info-text")),
+            Map.entry("0x0105",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-sysap-infoonoff",
+                            "pid-sysap-infoonoff-text")),
+            Map.entry("0x0106",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-sysap-infoforce",
+                            "pid-sysap-infoforce-text")),
+            Map.entry("0x0110",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-actual-dimming-value", "pid-info-actual-dimming-value-text")),
+            Map.entry("0x0111",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-info-error",
+                            "pid-info-error-text")),
+            Map.entry("0x0115",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                            "pid-sysap-infocurrentdimmingvalue", "pid-sysap-infocurrentdimmingvalue-text")),
+            Map.entry("0x0116",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-sysap-infoerror",
+                            "pid-sysap-infoerror-text")),
+            Map.entry("0x0118",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-color-temperature", "pid-info-color-temperature-text")),
+            Map.entry("0x011A",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-sysap-info-color-temperature", "pid-sysap-info-color-temperature-text")),
+            Map.entry("0x011B",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-hsv",
+                            "pid-info-hsv-text")),
+            Map.entry("0x011C",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-sysap-info-hsv",
+                            "pid-sysap-info-hsv-text")),
+            Map.entry("0x011D",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-color-mode",
+                            "pid-info-color-mode-text")),
+            Map.entry("0x011E",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-sysap-info-color-mode", "pid-sysap-info-color-mode-text")),
+            Map.entry("0x0120",
+                    new PIdContainerClass(PID_VALUETYPE_SHUTTERMOVEMENT, CATEGORY_BLINDS, "", "",
+                            "pid-info-move-up-down", "pid-info-move-up-down-text")),
+            Map.entry("0x0121",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_BLINDS, "", "",
+                            "pid-current-absolute-position-blinds-percentage",
+                            "pid-current-absolute-position-blinds-percentage-text")),
+            Map.entry("0x0122",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-current-absolute-position-slats-percentage",
+                            "pid-current-absolute-position-slats-percentage-text")),
+            Map.entry("0x0125",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-sysap-infomoveupdown",
+                            "pid-sysap-infomoveupdown-text")),
+            Map.entry("0x0126",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-sysap-infocurrentabsoluteblindspercentage",
+                            "pid-sysap-infocurrentabsoluteblindspercentage-text")),
+            Map.entry("0x0127",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-sysap-infocurrentabsoluteslatspercentage",
+                            "pid-sysap-infocurrentabsoluteslatspercentage-text")),
+            Map.entry("0x0130",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
+                            "pid-measured-temperature", "pid-measured-temperature-text")),
+            Map.entry("0x0131",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-value-heating",
+                            "pid-info-value-heating-text")),
+            Map.entry("0x0132",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-info-value-cooling",
+                            "pid-info-value-cooling-text")),
+            Map.entry("0x0135",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-switchover-heating-cooling", "pid-switchover-heating-cooling-text")),
+            Map.entry("0x0136",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-actuating-fan-stage-heating", "pid-actuating-fan-stage-heating-text")),
+            Map.entry("0x0140",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
+                            "pid-absolute-setpoint-temperature", "pid-absolute-setpoint-temperature-text")),
+            Map.entry("0x0141",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-additional-heating-value-info", "pid-additional-heating-value-info-text")),
+            Map.entry("0x0142",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-additional-cooling-value-info", "pid-additional-cooling-value-info-text")),
+            Map.entry("0x0143",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-control-value-additional-heating", "pid-control-value-additional-heating-text")),
+            Map.entry("0x0144",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-control-value-additional-cooling", "pid-control-value-additional-cooling-text")),
+            Map.entry("0x0145",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-actuating-fan-stage-heating", "pid-info-actuating-fan-stage-heating-text")),
+            Map.entry("0x0146",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-actuating-fan-manual-on-off-heating",
+                            "pid-info-actuating-fan-manual-on-off-heating-text")),
+            Map.entry("0x0147",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-actuating-fan-stage-cooling", "pid-actuating-fan-stage-cooling-text")),
+            Map.entry("0x0149",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-info-fan-stage-cooling", "pid-info-fan-stage-cooling-text")),
+            Map.entry("0x014A",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_TEMPERATURE, "", "",
+                            "pid-info-fan-manual-on-off-cooling", "pid-info-fan-manual-on-off-cooling-text")),
+            Map.entry("0x014B",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-heating-active",
+                            "pid-heating-active-text")),
+            Map.entry("0x014C",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-cooling-active",
+                            "pid-cooling-active-text")),
+            Map.entry("0x014D",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-heating-demand",
+                            "pid-heating-demand-text")),
+            Map.entry("0x014E",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-cooling-demand",
+                            "pid-cooling-demand-text")),
+            Map.entry("0x014F",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-heating-demand-feedback-signal", "pid-heating-demand-feedback-signal-text")),
+            Map.entry("0x0150",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
+                            "pid-cooling-demand-feedback-signal", "pid-cooling-demand-feedback-signal-text")),
+            Map.entry("0x0151",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_HUMIDITY, "", "", "pid-humidity",
+                            "pid-humidity-text")),
+            Map.entry("0x0152",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-aux-on-off-request",
+                            "pid-aux-on-off-request-text")),
+            Map.entry("0x0153",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-aux-on-off-response",
+                            "pid-aux-on-off-response-text")),
+            Map.entry("0x0154",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-heating-on-off-request",
+                            "pid-heating-on-off-request-text")),
+            Map.entry("0x0155",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-cooling-on-off-request",
+                            "pid-cooling-on-off-request-text")),
+            Map.entry("0x0156",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-operation-mode",
+                            "pid-operation-mode-text")),
+            Map.entry("0x0157",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-swing-h-v",
+                            "pid-swing-h-v-text")),
+            Map.entry("0x0158",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-supported-features",
+                            "pid-supported-features-text")),
+            Map.entry("0x0159",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-extended-status-indication", "pid-extended-status-indication-text")),
+            Map.entry("0x015A",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-extended-status-indication", "pid-extended-status-indication-text")),
+            Map.entry("0x015B",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-aux-heating-on-off-request", "pid-aux-heating-on-off-request-text")),
+            Map.entry("0x015C",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-emergency-heating-on-off-request", "pid-emergency-heating-on-off-request-text")),
+            Map.entry("0x0160",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-relative-fan-speed-control", "pid-relative-fan-speed-control-text")),
+            Map.entry("0x0161",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-absolute-fan-speed-control", "pid-absolute-fan-speed-control-text")),
+            Map.entry("0x0162",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-absolute-fan-speed", "pid-info-absolute-fan-speed-text")),
+            Map.entry("0x0163",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-sysap-infoactualfanspeed", "pid-sysap-infoactualfanspeed-text")),
+            Map.entry("0x01A0",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-notification-flags",
+                            "pid-notification-flags-text")),
+            Map.entry("0x0280",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-power-rc",
+                            "pid-power-rc-text")),
+            Map.entry("0x0281",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-power-rh",
+                            "pid-power-rh-text")),
+            Map.entry("0x0282",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proximity-status",
+                            "pid-proximity-status-text")),
+            Map.entry("0x0290",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-brightness-sensor",
+                            "pid-brightness-sensor-text")),
+            Map.entry("0x0291",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-last-touch",
+                            "pid-last-touch-text")),
+            Map.entry("0x0292",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-led-backlighting-night-mode", "pid-led-backlighting-night-mode-text")),
+            Map.entry("0x02C0",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-locator-beep",
+                            "pid-locator-beep-text")),
+            Map.entry("0x02C1",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-switch-test-alarm",
+                            "pid-switch-test-alarm-text")),
+            Map.entry("0x02C3",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-fire-alarm-active",
+                            "pid-fire-alarm-active-text")),
+            Map.entry("0x0400",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "", "",
+                            "pid-outside-temperature", "pid-outside-temperature-text")),
+            Map.entry("0x0401",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_WIND, "", "", "pid-wind-force",
+                            "pid-wind-force-text")),
+            Map.entry("0x0402",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-brightness-alarm",
+                            "pid-brightness-alarm-text")),
+            Map.entry("0x0403",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_UNDEFINED, "", "", "pid-lux-value",
+                            "pid-lux-value-text")),
+            Map.entry("0x0404",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_WIND, "", "", "pid-wind-speed",
+                            "pid-wind-speed-text")),
+            Map.entry("0x0405",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_RAIN, "", "", "pid-rain-detection",
+                            "pid-rain-detection-text")),
+            Map.entry("0x0406",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_RAIN, "", "", "pid-rain-sensor-frequency",
+                            "pid-rain-sensor-frequency-text")),
+            Map.entry("0x0440",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play",
+                            "pid-play-text")),
+            Map.entry("0x0441",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-pause",
+                            "pid-pause-text")),
+            Map.entry("0x0442",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-next",
+                            "pid-next-text")),
+            Map.entry("0x0443",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-previous",
+                            "pid-previous-text")),
+            Map.entry("0x0444",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play-mode",
+                            "pid-play-mode-text")),
+            Map.entry("0x0445",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-mute",
+                            "pid-mute-text")),
+            Map.entry("0x0446",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-relative-volume-control", "pid-relative-volume-control-text")),
+            Map.entry("0x0447",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-absolute-volume-control", "pid-absolute-volume-control-text")),
+            Map.entry("0x0448",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-group-membership",
+                            "pid-group-membership-text")),
+            Map.entry("0x0449",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play-favorite",
+                            "pid-play-favorite-text")),
+            Map.entry("0x044A",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play-next-favorite",
+                            "pid-play-next-favorite-text")),
+            Map.entry("0x0460",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-playback-status",
+                            "pid-playback-status-text")),
+            Map.entry("0x0461",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-current-item-metadata-info", "pid-current-item-metadata-info-text")),
+            Map.entry("0x0462",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-mute",
+                            "pid-info-mute-text")),
+            Map.entry("0x0463",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-actual-volume",
+                            "pid-info-actual-volume-text")),
+            Map.entry("0x0464",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-allowed-playback-actions", "pid-allowed-playback-actions-text")),
+            Map.entry("0x0465",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-group-membership", "pid-info-group-membership-text")),
+            Map.entry("0x0466",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-playing-favorite", "pid-info-playing-favorite-text")),
+            Map.entry("0x0467",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-absolute-group-volume-control", "pid-absolute-group-volume-control-text")),
+            Map.entry("0x0468",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-absolute-group-volume", "pid-info-absolute-group-volume-text")),
+            Map.entry("0x0469",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-media-source",
+                            "pid-media-source-text")),
+            Map.entry("0x04A0",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-solar-power-production", "pid-solar-power-production-text")),
+            Map.entry("0x04A1",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-inverter-output-power", "pid-inverter-output-power-text")),
+            Map.entry("0x04A2",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-solar-energy-(today)",
+                            "pid-solar-energy-(today)-text")),
+            Map.entry("0x04A3",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-injected-energy-(today)", "pid-injected-energy-(today)-text")),
+            Map.entry("0x04A4",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-purchased-energy-(today)", "pid-purchased-energy-(today)-text")),
+            Map.entry("0x04A5",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-inverter-alarm",
+                            "pid-inverter-alarm-text")),
+            Map.entry("0x04A6",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-self-consumption",
+                            "pid-self-consumption-text")),
+            Map.entry("0x04A7",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-self-sufficiency",
+                            "pid-self-sufficiency-text")),
+            Map.entry("0x04A8",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-home-power-consumption", "pid-home-power-consumption-text")),
+            Map.entry("0x04A9",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-power-to-grid",
+                            "pid-power-to-grid-text")),
+            Map.entry("0x04AA",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-consumed-energy-(today)", "pid-consumed-energy-(today)-text")),
+            Map.entry("0x04AB",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-meter-alarm",
+                            "pid-meter-alarm-text")),
+            Map.entry("0x04AC",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-battery-level",
+                            "pid-battery-level-text")),
+            Map.entry("0x04AD",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-battery-power",
+                            "pid-battery-power-text")),
+            Map.entry("0x04B0",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-boost",
+                            "pid-boost-text")),
+            Map.entry("0x04B1",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-stop-charging-reuqest", "pid-stop-charging-reuqest-text")),
+            Map.entry("0x04B2",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-enable-charging-reuqest", "pid-enable-charging-reuqest-text")),
+            Map.entry("0x04B3",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-boost",
+                            "pid-info-boost-text")),
+            Map.entry("0x04B4",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-wallbox-status",
+                            "pid-info-wallbox-status-text")),
+            Map.entry("0x04B5",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-charging",
+                            "pid-info-charging-text")),
+            Map.entry("0x04B6",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-charging-enabled", "pid-info-charging-enabled-text")),
+            Map.entry("0x04B7",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-installed-power",
+                            "pid-info-installed-power-text")),
+            Map.entry("0x04B8",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-transmitted-energy", "pid-info-transmitted-energy-text")),
+            Map.entry("0x04B9",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-car-range",
+                            "pid-info-car-range-text")),
+            Map.entry("0x04BA",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-charging-duration", "pid-info-charging-duration-text")),
+            Map.entry("0x04BB",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-current-limit",
+                            "pid-info-current-limit-text")),
+            Map.entry("0x04BC",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-current-limit-for-group", "pid-info-current-limit-for-group-text")),
+            Map.entry("0x04BD",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-album-cover-url",
+                            "pid-album-cover-url-text")),
+            Map.entry("0x0501",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-secure@home-central-unit", "pid-secure@home-central-unit-text")),
+            Map.entry("0x0502",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-domusdisarmcounter",
+                            "pid-domusdisarmcounter-text")),
+            Map.entry("0x0504",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-intrusion-alarm",
+                            "pid-intrusion-alarm-text")),
+            Map.entry("0x0505",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-safety-alarm",
+                            "pid-safety-alarm-text")),
+            Map.entry("0x0507",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-infoconfigurationstatus", "pid-infoconfigurationstatus-text")),
+            Map.entry("0x0508",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-enable-configuration",
+                            "pid-enable-configuration-text")),
+            Map.entry("0x0509",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-disarming-led",
+                            "pid-disarming-led-text")),
+            Map.entry("0x050A",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-aes-key",
+                            "pid-aes-key-text")),
+            Map.entry("0x050B",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-zone-status",
+                            "pid-zone-status-text")),
+            Map.entry("0x050E",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-time",
+                            "pid-time-text")),
+            Map.entry("0x0600",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-start-stop",
+                            "pid-start-stop-text")),
+            Map.entry("0x0601",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-pause-resume",
+                            "pid-pause-resume-text")),
+            Map.entry("0x0602",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-select-program",
+                            "pid-select-program-text")),
+            Map.entry("0x0603",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-delayed-start-time",
+                            "pid-delayed-start-time-text")),
+            Map.entry("0x0604",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-status",
+                            "pid-info-status-text")),
+            Map.entry("0x0605",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-remote-start-enabled", "pid-info-remote-start-enabled-text")),
+            Map.entry("0x0606",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-program",
+                            "pid-info-program-text")),
+            Map.entry("0x0607",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-finish-time",
+                            "pid-info-finish-time-text")),
+            Map.entry("0x0608",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-delayed-start",
+                            "pid-info-delayed-start-text")),
+            Map.entry("0x0609",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-door",
+                            "pid-info-door-text")),
+            Map.entry("0x060A",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-door-alarm",
+                            "pid-info-door-alarm-text")),
+            Map.entry("0x060B",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-switch-supercool",
+                            "pid-switch-supercool-text")),
+            Map.entry("0x060C",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-switch-superfreeze",
+                            "pid-switch-superfreeze-text")),
+            Map.entry("0x060D",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-switch-supercool", "pid-info-switch-supercool-text")),
+            Map.entry("0x060E",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-info-switch-superfreeze", "pid-info-switch-superfreeze-text")),
+            Map.entry("0x060F",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-measured-temperature",
+                            "pid-measured-temperature-text")),
+            Map.entry("0x0610",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-measured-temperature",
+                            "pid-measured-temperature-text")),
+            Map.entry("0x0611",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-set-value-temperature", "pid-set-value-temperature-text")),
+            Map.entry("0x0612",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-set-value-temperature", "pid-set-value-temperature-text")),
+            Map.entry("0x0613",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-change-operation",
+                            "pid-change-operation-text")),
+            Map.entry("0x0614",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-detailed-status-info",
+                            "pid-detailed-status-info-text")),
+            Map.entry("0x0615",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-remaining-time",
+                            "pid-info-remaining-time-text")),
+            Map.entry("0x0616",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-time-of-last-status-change", "pid-time-of-last-status-change-text")),
+            Map.entry("0x0618",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-lock-unlock-door-command", "pid-lock-unlock-door-command-text")),
+            Map.entry("0x0619",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-locked-unlocked",
+                            "pid-info-locked-unlocked-text")),
+            Map.entry("0xF001",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-time",
+                            "pid-time-text")),
+            Map.entry("0xF002",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-date",
+                            "pid-date-text")),
+            Map.entry("0xF003",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-notification",
+                            "pid-notification-text")),
+            Map.entry("0xF101",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-switch-entity-on-off",
+                            "pid-switch-entity-on-off-text")),
+            Map.entry("0xF102",
+                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
+                            "pid-info-switch-entity-on-off", "pid-info-switch-entity-on-off-text")),
+            Map.entry("0xF104",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-consistency-tag",
+                            "pid-consistency-tag-text")),
+            Map.entry("0xF105",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-battery-status",
+                            "pid-battery-status-text")),
+            Map.entry("0xF106",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-stay-awake",
+                            "pid-stay-awake-text")),
+            Map.entry("0xF107",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy-switch",
+                            "pid-proxy-switch-text")),
+            Map.entry("0xF108",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy1",
+                            "pid-proxy1-text")),
+            Map.entry("0xF109",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy2",
+                            "pid-proxy2-text")),
+            Map.entry("0xF10A",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy4",
+                            "pid-proxy4-text")),
+            Map.entry("0xF10B",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-cyclic-sleep-time",
+                            "pid-cyclic-sleep-time-text")),
+            Map.entry("0xF10C",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-presence",
+                            "pid-presence-text")),
+            Map.entry("0xF10D",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-measured-temperature-1", "pid-measured-temperature-1-text")),
+            Map.entry("0xF10E",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-standby-statistics",
+                            "pid-standby-statistics-text")),
+            Map.entry("0xF10F",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-heartbeat-delay",
+                            "pid-heartbeat-delay-text")),
+            Map.entry("0xF110",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-heartbeat-delay",
+                            "pid-info-heartbeat-delay-text")),
+            Map.entry("0xFF01",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-measured-temperature-1", "pid-measured-temperature-1-text")),
+            Map.entry("0xFF02",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-measured-temperature-2", "pid-measured-temperature-2-text")),
+            Map.entry("0xFF03",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-measured-temperature-3", "pid-measured-temperature-3-text")),
+            Map.entry("0xFF04",
+                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
+                            "pid-measured-temperature-4", "pid-measured-temperature-4-text")),
+            Map.entry("0x061A",
+                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_PRESSURE, "", "",
+                            "pid-air-quality-pressure-value", "pid-air-quality-pressure-value-text")),
+            Map.entry("0x061B",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                            "pid-air-quality-co2-value", "pid-air-quality-co2-value-text")),
+            Map.entry("0x061C",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-air-quality-co-value",
+                            "pid-air-quality-co-value-text")),
+            Map.entry("0x061D",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                            "pid-air-quality-no2-value", "pid-air-quality-no2-value-text")),
+            Map.entry("0x061E",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-air-quality-o3-value",
+                            "pid-air-quality-o3-value-text")),
+            Map.entry("0x061F",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                            "pid-air-quality-pm10-value", "pid-air-quality-pm10-value-text")),
+            Map.entry("0x0620",
+                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                            "pid-air-quality-pm25-value", "pid-air-quality-pm25-value-text")),
+            Map.entry("0x0621", new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
+                    "pid-air-quality-voc-value", "pid-air-quality-voc-value-text")));
+
+    public static String getShortTextForPairingId(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.label;
+    }
+
+    public static String getDescriptionTextForPairingId(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.description;
+    }
+
+    public static String getValueTypeForPairingId(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.valueType;
+    }
+
+    public static String getItemTypeForPairingId(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.category;
+    }
+
+    public static String getCategoryForPairingId(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.category;
+    }
+
+    public static String getPatternForPairingId(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.category;
+    }
+
+    public static int getMax(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.max;
+    }
+
+    public static int getMin(String Key) throws FreeAtHomeGeneralException {
+        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
+
+        if (desc == null) {
+            throw new FreeAtHomeGeneralException(0,
+                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
+        }
+
+        return desc.min;
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/UidUtils.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/util/UidUtils.java
new file mode 100644 (file)
index 0000000..0617054
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.util;
+
+import static org.openhab.binding.freeathome.internal.FreeAtHomeBindingConstants.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.type.ChannelTypeUID;
+
+/**
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class UidUtils {
+
+    public static ChannelTypeUID generateChannelTypeUID(String valueType, boolean isReadOnly) {
+        String channelNameString;
+
+        if (isReadOnly) {
+            channelNameString = valueType + "-ro";
+        } else {
+            channelNameString = valueType;
+        }
+
+        return new ChannelTypeUID(BINDING_ID, channelNameString);
+    }
+
+    public static ThingTypeUID generateThingUID() {
+        return new ThingTypeUID(BINDING_ID, DEVICE_TYPE_ID);
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BinaryValueStateConverter.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BinaryValueStateConverter.java
new file mode 100644 (file)
index 0000000..5a68659
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.valuestateconverter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.types.State;
+
+/**
+ * The {@link BinaryValueStateConverter} is a value converter for integer values with a specific mask
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class BinaryValueStateConverter implements ValueStateConverter {
+
+    private int maskValue;
+
+    public BinaryValueStateConverter(int mask) {
+        maskValue = mask;
+    }
+
+    @Override
+    public State convertToState(String value) {
+        int intValue = Integer.decode(value);
+        int result;
+
+        result = intValue & maskValue;
+
+        if (maskValue == result) {
+            return OnOffType.ON;
+        } else {
+            return OnOffType.OFF;
+        }
+    }
+
+    @Override
+    public String convertToValueString(State state) {
+        if (state.equals(OnOffType.ON)) {
+            return "1";
+        }
+
+        if (state.equals(OnOffType.OFF)) {
+            return "0";
+        }
+
+        return "";
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BooleanValueStateConverter.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BooleanValueStateConverter.java
new file mode 100644 (file)
index 0000000..0128412
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.valuestateconverter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.types.State;
+
+/**
+ * The {@link DecimalValueStateConverter} is a value converter for boolean values
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class BooleanValueStateConverter implements ValueStateConverter {
+
+    @Override
+    public State convertToState(String value) {
+        return OnOffType.from(value);
+    }
+
+    @Override
+    public String convertToValueString(State state) {
+        if (state.equals(OnOffType.ON)) {
+            return "1";
+        }
+
+        if (state.equals(OnOffType.OFF)) {
+            return "0";
+        }
+
+        return "";
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/DecimalValueStateConverter.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/DecimalValueStateConverter.java
new file mode 100644 (file)
index 0000000..fd24727
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.valuestateconverter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.types.State;
+
+/**
+ * The {@link DecimalValueStateConverter} is a value converter for decimal values
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class DecimalValueStateConverter implements ValueStateConverter {
+
+    @Override
+    public State convertToState(String value) {
+        return new DecimalType(value);
+    }
+
+    @Override
+    public String convertToValueString(State state) {
+        return ((DecimalType) state).toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ShuttercontrolValueStateConverter.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ShuttercontrolValueStateConverter.java
new file mode 100644 (file)
index 0000000..4b8ed03
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.valuestateconverter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.library.types.StopMoveType;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.library.types.UpDownType;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.State;
+
+/**
+ * The {@link ShuttercontrolValueStateConverter} is a value converter for shutter movement
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class ShuttercontrolValueStateConverter implements ValueStateConverter {
+
+    @Override
+    public State convertToState(String value) {
+        State ret = UpDownType.DOWN;
+
+        switch (value) {
+            default:
+            case "0":
+                ret = new StringType("STOP");
+                break;
+            case "2":
+                ret = UpDownType.UP;
+                break;
+            case "3":
+                ret = UpDownType.DOWN;
+                break;
+        }
+
+        return ret;
+    }
+
+    @Override
+    public String convertToValueString(State state) {
+        String valueString = "0";
+        String stateString = "STOP";
+
+        if (state instanceof UpDownType) {
+            stateString = ((UpDownType) state).toString();
+        }
+
+        if (((Command) state) instanceof StopMoveType) {
+            stateString = "STOP";
+        }
+
+        switch (stateString) {
+            default:
+            case "STOP":
+                valueString = "0";
+                break;
+            case "UP":
+                valueString = "0";
+                break;
+            case "DOWN":
+                valueString = "1";
+                break;
+        }
+
+        return valueString;
+    }
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ValueStateConverter.java b/bundles/org.openhab.binding.freeathome/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ValueStateConverter.java
new file mode 100644 (file)
index 0000000..3c25e9c
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2024 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.freeathome.internal.valuestateconverter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.types.State;
+
+/**
+ * The {@link ValueStateConverter} base class for the value state converters
+ *
+ * @author Andras Uhrin - Initial contribution
+ *
+ */
+@NonNullByDefault
+public interface ValueStateConverter {
+    public State convertToState(String value);
+
+    public String convertToValueString(State state);
+}
diff --git a/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/addon/addon.xml
new file mode 100644 (file)
index 0000000..3733278
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<addon:addon id="freeathome" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
+
+       <type>binding</type>
+       <name>FreeAtHome Binding</name>
+       <description>This is the binding for free@home system.</description>
+       <connection>local</connection>
+</addon:addon>
diff --git a/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/i18n/freeathomesystem.properties b/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/i18n/freeathomesystem.properties
new file mode 100644 (file)
index 0000000..fb2ae8d
--- /dev/null
@@ -0,0 +1,652 @@
+# add-on
+
+addon.freeathome.name = FreeAtHome Binding
+addon.freeathome.description = This is the binding for free@home system.
+
+# thing types
+
+thing-type.freeathome.device.label = free@home Device
+thing-type.freeathome.device.description = This represents the generic free@home device
+thing-type.freeathome.gateway.label = free@home Gateway
+thing-type.freeathome.gateway.description = This gateway represents the free@home Gateway
+
+# thing types config
+
+thing-type.config.freeathome.device.deviceId.label = Device Id
+thing-type.config.freeathome.device.deviceId.description = This is the unique id of the free@home device (Please do not modify after the Thing is generated)
+thing-type.config.freeathome.gateway.group.identification.label = SysAP Setting
+thing-type.config.freeathome.gateway.group.identification.description = SysAP network address and user settings
+thing-type.config.freeathome.gateway.ipAddress.label = Sysap IP Address
+thing-type.config.freeathome.gateway.ipAddress.description = IP Address of the Busch-Jaeger Gateway
+thing-type.config.freeathome.gateway.password.label = Password
+thing-type.config.freeathome.gateway.password.description = Password for gateway
+thing-type.config.freeathome.gateway.username.label = User Name
+thing-type.config.freeathome.gateway.username.description = The login name
+
+# localized error text
+
+comm-error.not-able-open-httpconnection = Cannot open http connection, wrong password
+comm-error.http-wrongpass-or-ip = Cannot open http connection, wrong password or IP address
+comm-error.not-able-open-websocketconnection = Cannot open websocket connection
+comm-error.general-websocket-issue = General issue in websocket connection
+comm-error.websocket-keep-alive-error = Websocket keep alive error
+comm-error.wrong-credentials = Wrong credentials for SysAP
+comm-error.error-in-sysap-com = Error in SysAp communication
+conf-error.general-binding-error = General binding error!
+conf-error.datapointgroup-invalid = Datapoint group is not valid!
+conf-error.inputdatapoint-invalid = Input Datapoint is not valid!
+conf-error.invalid-deviceconfig = Invalid device configuration!
+conf-error.invalid-bridge = Invalid bridge!
+conf-error.bridge-not-configured = Bridge not configured!
+conf-error.ip-address-missing = IP address is not specified!
+conf-error.username-missing = User name is not specified!
+conf-error.password-missing = Password is not specified!
+conf-error.device-desc-null = Device description is NULL!
+gen-error.no-bridge-avail = No bridge available!
+
+# localized info text for function id
+
+fid-dimming-sensor = Dimming sensor
+fid-blind-sensor = Blind sensor
+fid-stairwell-light-sensor = Stairwell light sensor
+fid-force-on/off-sensor = Force On/Off sensor
+fid-scene-sensor = Scene sensor
+fid-switch-actuator = Switch actuator
+fid-blind-actuator = Blind actuator
+fid-room-temperature-controller-with-fan-speed-level = Room temperature controller with fan speed level
+fid-room-temperature-controller-extension-unit = Room temperature controller extension unit
+fid-wind-alarm = Wind Alarm
+fid-frost-alarm = Frost Alarm
+fid-rain-alarm = Rain Alarm
+fid-window-sensor = Window sensor
+fid-movement-detector = Movement Detector
+fid-dim-actuator = Dim actuator
+fid-radiator = Radiator
+fid-underfloor-heating = Underfloor heating
+fid-fan-coil = Fan Coil
+fid-two-level-controller = Two-level controller
+fid-door-opener = Door opener
+fid-proxy = Proxy
+fid-door-map.entry-system-call-level-actuator = Door Map.entry System Call Level Actuator
+fid-door-map.entry-system-call-level-sensor = Door Map.entry System Call Level Sensor
+fid-door-call = Door call
+fid-automatic-door-opener = Automatic door opener
+fid-corridor-light = Corridor light
+fid-room-temperature-controller = Room temperature controller
+fid-cooling-mode = Cooling mode
+fid-heating-mode = Heating mode
+fid-force-position-blind = Force-position blind
+fid-auto.-heating/cooling-mode = Auto. heating/cooling mode
+fid-switchover-heating/cooling = Switchover heating/cooling
+fid-device-settings = Device settings
+fid-dim-actuator = Dim actuator
+fid-dim-actuator = Dim actuator
+fid-control-element = Control element
+fid-dimming-sensor = Dimming sensor
+fid-blind-sensor = Blind sensor
+fid-stairwell-light-sensor = Stairwell light sensor
+fid-force-on/off-sensor = Force On/Off sensor
+fid-force-position-blind = Force-position blind
+fid-scene-sensor = Scene sensor
+fid-room-temperature-controller-extension-unit = Room temperature controller extension unit
+fid-fan-coil-sensor = Fan coil sensor
+fid-rgb-+-warm-white/cold-white-sensor = RGB + warm white/cold white sensor
+fid-rgb-sensor = RGB sensor
+fid-warm-white/cold-white-sensor = Warm white/cold white sensor
+fid-add.-stage-for-heating-mode = Add. stage for heating mode
+fid-radiator-thermostate = Radiator thermostate
+fid-room-temperature-controller-extension-unit = Room temperature controller extension unit
+fid-brightness-sensor = Brightness sensor
+fid-rain-sensor = Rain sensor
+fid-temperature-sensor = Temperature sensor
+fid-wind-sensor = Wind sensor
+fid-trigger = Trigger
+fid-heating-mode = Heating mode
+fid-cooling-mode = Cooling mode
+fid-auto.-heating/cooling-mode = Auto. heating/cooling mode
+fid-two-valves-for-heating-and-cooling = Two valves for heating and cooling
+fid-window/door = Window/Door
+fid-abc = ABC
+fid-abd = ABD
+fid-acd = ACD
+fid-timer-program-switch-sensor = Timer program switch sensor
+fid-zone = Zone
+fid-central-heating-actuator = Central heating actuator
+fid-central-cooling-actuator = Central cooling actuator
+fid-housekeeping = Housekeeping
+fid-media-player = Media Player
+fid-panel-room-temperature-controller-slave-for-battery-device = Panel Room Temperature Controller Slave For Battery Device
+fid-media-player-sensor = Media Player Sensor
+fid-roller-blind-actuator = Roller blind actuator
+fid-attic-window-actuator = Attic window actuator
+fid-awning-actuator = Awning actuator
+fid-windowdoor-position-sensor = WindowDoor Position Sensor
+fid-window/door-position = Window/Door position
+fid-media-playback-control-sensor = Media playback control sensor
+fid-media-volume-sensor = Media volume sensor
+fid-dishwasher = Dishwasher
+fid-laundry = Laundry
+fid-dryer = Dryer
+fid-oven = Oven
+fid-fridge = Fridge
+fid-freezer = Freezer
+fid-hood = Hood
+fid-coffee-machine = Coffee machine
+fid-fridge/freezer = Fridge/Freezer
+fid-timer-program-switch-sensor = Timer program switch sensor
+fid-ceiling-fan-actuator = Ceiling fan actuator
+fid-ceiling-fan-sensor = Ceiling fan sensor
+fid-room-temperature-controller-with-fan-speed-level = Room temperature controller with fan speed level
+fid-zone = Zone
+fid-safety = Safety
+fid-external-ir-sensor-bx80 = External IR Sensor BX80
+fid-external-ir-sensor-vxi = External IR Sensor VXI
+fid-external-ir-sensor-mini = External IR Sensor Mini
+fid-external-ir-sensor-high-altitude = External IR Sensor High Altitude
+fid-external-ir-sensor-curtain = External IR Sensor Curtain
+fid-smoke-detector = Smoke Detector
+fid-carbon-monoxide-sensor = Carbon Monoxide Sensor
+fid-methane-detector = Methane Detector
+fid-gas-sensor-lpg = Gas Sensor LPG
+fid-flood-detection = Flood Detection
+fid-secure@home-central-unit = secure@home Central Unit
+fid-thermostat = Thermostat
+fid-secure@home-zone-sensor = secure@home Zone Sensor
+fid-slave-thermostat = Slave thermostat
+fid-secure@home-integration-logic = secure@home Integration Logic
+fid-add.-stage-for-cooling-mode = Add. stage for cooling mode
+fid-two-level-heating-actuator = Two Level Heating Actuator
+fid-two-level-cooling-actuator = Two Level Cooling Actuator
+fid-zone = Zone
+fid-volume-up = Volume up
+fid-volume-down = Volume down
+fid-play/pause = Play/pause
+fid-next-favorite = Next favorite
+fid-next-song = Next song
+fid-previous-song = Previous song
+fid-home-appliance-sensor = Home appliance sensor
+fid-heat-sensor = Heat sensor
+fid-zone-switching = Zone switching
+fid-button-function = Button function
+fid-advanced-configuration = Advanced configuration
+fid-secure@home-central-unit-basic = secure@home Central Unit Basic
+fid-repeater = Repeater
+fid-remote-scene-control = Remote scene control
+fid-window-sensor = Window sensor
+fid-movement-detector = Movement Detector
+fid-external-ir-sensor-curtain = External IR Sensor Curtain
+fid-smoke-detector = Smoke Detector
+fid-flood-detection = Flood Detection
+fid-sensor-for-air-conditioning-unit = Sensor for air-conditioning unit
+fid-two-point-controller-for-heating-or-cooling = Two-point controller for heating or cooling
+fid-slave-thermostat = Slave thermostat
+fid-wallbox = Wallbox
+fid-door-lock-control = Door lock control
+fid-room-temperature-controller-with-fan-speed-level = Room temperature controller with fan speed level
+fid-scene-trigger = Scene trigger
+fid-rule-switch = Rule Switch
+fid-air-quality-sensor-pressure = Air quality sensor Pressure
+fid-air-quality-sensor-co2 = Air quality sensor CO2
+fid-air-quality-sensor-co = Air quality sensor CO
+fid-air-quality-sensor-no2 = Air quality sensor NO2
+fid-air-quality-sensor-o3 = Air quality sensor O3
+fid-air-quality-sensor-pm10 = Air quality sensor PM10
+fid-air-quality-sensor-pm25 = Air quality sensor PM25
+fid-air-quality-sensor-voc = Air quality sensor VOC
+fid-air-quality-sensor-humidity = Air quality sensor humidity
+fid-movement-detector-fle = Movement detector (flex)
+fid-dim-actuator-flex = Dim actuator (flex)
+
+# localized info text for pairing id
+
+pid-switch-on-off = Switch
+pid-timed-start-stop = Timed Start/Stop
+pid-force-position = Force-position
+pid-scene-control = Scene Control
+pid-movement-under-consideration-of-brightness = Movement under consideration of brightness
+pid-presence = Presence
+pid-relative-set-value = Relative Set Value
+pid-absolute-set-value = Set Value
+pid-night = Night
+pid-invalid-string-id = invalid string id
+pid-rgb-color = RGB color
+pid-color-temperature = Color Temperature
+pid-hsv = HSV
+pid-hue = HUE
+pid-saturation = Saturation
+pid-move-up-down = Move Up/Down
+pid-adjust-up-down = Adjust Up/Down
+pid-set-absolute-position-blinds = Blinds Position
+pid-set-absolute-position-slats = Slats Position
+pid-wind-alarm = Wind Alarm
+pid-frost-alarm = Frost Alarm
+pid-rain-alarm = Rain Alarm
+pid-force-position-blind = Force-position blind
+pid-window-door-position = Window/Door position
+pid-actuating-value-heating = Actuating Value Heating
+pid-fan-level-heating = Fan Level Heating
+pid-actuating-value-cooling = Actuating Value Cooling
+pid-set-value-temperature = Set Value Temperature
+pid-relative-set-point-temperature = Relative Setpoint Temperature
+pid-window-door = Window/Door
+pid-status-indication = Status
+pid-fan-manual-heating-on-off = Fan Manual Heating
+pid-controller-on-off = Controller
+pid-relative-set-point-request = Relative Setpoint Request
+pid-eco-mode-on-off-request = Eco mode
+pid-comfort-temperature = Comfort Temperature
+pid-fan-level-request = Fan Level
+pid-fan-manual-on-off-request = Fan Switch
+pid-controller-on-off-request = Controller Switch
+pid-eco-mode-on-off-request = Eco mode
+pid-info-on-off = Status info
+pid-force-position-info = Force-position
+pid-sysap-infoonoff = SysAP-InfoOnOff
+pid-sysap-infoforce = SysAP-InfoForce
+pid-info-actual-dimming-value = Dimming Value
+pid-info-error = Error INfo
+pid-sysap-infocurrentdimmingvalue = SysAP-InfoCurrentDimmingValue
+pid-sysap-infoerror = SysAP-InfoError
+pid-info-color-temperature = Color Temperature
+pid-sysap-info-color-temperature = SysAP-Info Color Temperature
+pid-info-hsv = HSV
+pid-sysap-info-hsv = SysAP Info HSV
+pid-info-color-mode = Color Mode
+pid-sysap-info-color-mode = SysAP Info Color Mode
+pid-info-move-up-down = Move Up/Down
+pid-current-absolute-position-blinds-percentage = Blinds Position
+pid-current-absolute-position-slats-percentage = Slats Position
+pid-sysap-infomoveupdown = SysAP-InfoMoveUpDown
+pid-sysap-infocurrentabsoluteblindspercentage = SysAP-InfoCurrentAbsoluteBlindsPercentage
+pid-sysap-infocurrentabsoluteslatspercentage = SysAP-InfoCurrentAbsoluteSlatsPercentage
+pid-measured-temperature = Measured Temperature
+pid-info-value-heating = Heating Value
+pid-info-value-cooling = cooling Value
+pid-switchover-heating-cooling = Switchover heating/cooling
+pid-actuating-fan-stage-heating = Fan Heating Control
+pid-absolute-setpoint-temperature = Setpoint temperature
+pid-additional-heating-value-info = Additional heating Info
+pid-additional-cooling-value-info = Additional cooling Info
+pid-control-value-additional-heating = Additional heating Control
+pid-control-value-additional-cooling = Additional cooling  Control
+pid-info-actuating-fan-stage-heating = Fan Heating Info
+pid-info-actuating-fan-manual-on-off-heating = Fan Manual On/Off Heating
+pid-actuating-fan-stage-cooling = Fan Cooling Control
+pid-info-fan-stage-cooling = Fan Cooling Info
+pid-info-fan-manual-on-off-cooling = Fan Manual On/Off Cooling
+pid-heating-active = Heating active
+pid-cooling-active = Cooling active
+pid-heating-demand = Heating demand
+pid-cooling-demand = Cooling demand
+pid-heating-demand-feedback-signal = Heating demand feedback
+pid-cooling-demand-feedback-signal = Cooling demand feedback
+pid-humidity = Humidity
+pid-aux-on-off-request = Aux Switch
+pid-aux-on-off-response = Aux Swicth response
+pid-heating-on-off-request = Heating
+pid-cooling-on-off-request = Cooling
+pid-operation-mode = Operation mode
+pid-swing-h-v = Swing H/V
+pid-supported-features = Features
+pid-extended-status-indication = Extended Status Indication
+pid-extended-status-indication = Extended Status Indication
+pid-aux-heating-on-off-request = Aux Heating
+pid-emergency-heating-on-off-request = Emergency Heating
+pid-relative-fan-speed-control = Relative fan speed
+pid-absolute-fan-speed-control = Fan speed
+pid-info-absolute-fan-speed = Fan speed feedback
+pid-sysap-infoactualfanspeed = SysAP-InfoActualFanSpeed
+pid-notification-flags = Notification flags
+pid-power-rc = Power RC
+pid-power-rh = Power RH
+pid-proximity-status = Proximity status
+pid-brightness-sensor = Brightness
+pid-last-touch = Last touch
+pid-led-backlighting-night-mode = LED backlighting
+pid-locator-beep = Locator beep
+pid-switch-test-alarm = Switch test alarm
+pid-fire-alarm-active = Fire alarm
+pid-outside-temperature = Outside temperature
+pid-wind-force = Wind force
+pid-brightness-alarm = Brightness alarm
+pid-lux-value = Lux value
+pid-wind-speed = Wind speed
+pid-rain-detection = Rain detection
+pid-rain-sensor-frequency = Rain sensor frequency
+pid-play = Play
+pid-pause = Pause
+pid-next = Next
+pid-previous = Previous
+pid-play-mode = Play mode
+pid-mute = Mute
+pid-relative-volume-control = Relative volume control
+pid-absolute-volume-control = Absolute volume control
+pid-group-membership = Group membership
+pid-play-favorite = Play favorite
+pid-play-next-favorite = Play next favorite
+pid-playback-status = Playback status
+pid-current-item-metadata-info = Current item metadata
+pid-info-mute = Mute Info
+pid-info-actual-volume = Actual volume
+pid-allowed-playback-actions = Playback actions
+pid-info-group-membership = Group membership Info
+pid-info-playing-favorite = Playing favorite Info
+pid-absolute-group-volume-control = Group Volume
+pid-info-absolute-group-volume = Group Volume INfo
+pid-media-source = Media source
+pid-solar-power-production = Power production
+pid-inverter-output-power = Inverter output power
+pid-solar-energy-(today) = Solar energy (today)
+pid-injected-energy-(today) = Injected energy (today)
+pid-purchased-energy-(today) = Purchased energy (today)
+pid-inverter-alarm = Inverter alarm
+pid-self-consumption = Self-consumption
+pid-self-sufficiency = Self-sufficiency
+pid-home-power-consumption = Home power consumption
+pid-power-to-grid = Power to grid
+pid-consumed-energy-(today) = Consumed energy (today)
+pid-meter-alarm = Meter alarm
+pid-battery-level = Battery level
+pid-battery-power = Battery power
+pid-boost = Boost
+pid-stop-charging-reuqest = Stop charging
+pid-enable-charging-reuqest = Enable charging
+pid-info-boost = Boost Info
+pid-info-wallbox-status = Wallbox status
+pid-info-charging = Charging INfo
+pid-info-charging-enabled = Charging enabled
+pid-info-installed-power = Installed power
+pid-info-transmitted-energy = Transmitted energy
+pid-info-car-range = Car range
+pid-info-charging-duration = Charging duration
+pid-info-current-limit = Current limit
+pid-info-current-limit-for-group = Current limit for group
+pid-album-cover-url = Cover
+pid-secure@home-central-unit = secure@home Central Unit
+pid-domusdisarmcounter = DomusDisarmCounter
+pid-intrusion-alarm = Intrusion Alarm
+pid-safety-alarm = Safety Alarm
+pid-infoconfigurationstatus = InfoConfigurationStatus
+pid-enable-configuration = Enable configuration
+pid-disarming-led = Disarming LED
+pid-aes-key = AES Key
+pid-zone-status = Zone status
+pid-time = Time
+pid-start-stop = Start / Stop
+pid-pause-resume = Pause / Resume
+pid-select-program = Select program
+pid-delayed-start-time = Delayed start time
+pid-info-status = Status
+pid-info-remote-start-enabled = Remote start enabled
+pid-info-program = Program
+pid-info-finish-time = Finish time
+pid-info-delayed-start = Delayed start
+pid-info-door = Door
+pid-info-door-alarm = Door alarm
+pid-switch-supercool = Supercool Info
+pid-switch-superfreeze = Superfreeze Info
+pid-info-switch-supercool = Supercool switch
+pid-info-switch-superfreeze = Superfreeze switch
+pid-measured-temperature = Measured Temperature
+pid-set-value-temperature = Set Value Temperature
+pid-change-operation = Operation
+pid-detailed-status-info = Status
+pid-info-remaining-time = Remaining time
+pid-time-of-last-status-change = Time of last change
+pid-lock-unlock-door-command = Door lock
+pid-info-locked-unlocked = Door Status
+pid-time = Time
+pid-date = Date
+pid-notification = Notification
+pid-switch-entity-on-off = Switch
+pid-info-switch-entity-on-off = Switch feedback
+pid-consistency-tag = Consistency Tag
+pid-battery-status = Battery Status
+pid-stay-awake = Stay awake!
+pid-proxy-switch = Proxy switch
+pid-proxy1 = Proxy 1Byte
+pid-proxy2 = Proxy 2Byte
+pid-proxy4 = Proxy 4Byte
+pid-cyclic-sleep-time = Sleep time
+pid-presence = Presence
+pid-measured-temperature-1 = Measured temperature
+pid-standby-statistics = Standby Statistics
+pid-heartbeat-delay = Heartbeat delay
+pid-info-heartbeat-delay = Heartbeat delay
+pid-measured-temperature-1 = Measured temperature
+pid-measured-temperature-2 = Measured temperature
+pid-measured-temperature-3 = Measured temperature
+pid-measured-temperature-4 = Measured temperature
+pid-air-quality-pressure-value = Pressure value
+pid-air-quality-co2-value = CO2 value
+pid-air-quality-co-value = CO value
+pid-air-quality-no2-value = NO2 value
+pid-air-quality-o3-value = O3 value
+pid-air-quality-pm10-value = PM10 value
+pid-air-quality-pm25-value = PM25 value
+pid-air-quality-voc-value = VOC value
+
+# localized info text for pairing id description
+
+pid-switch-on-off-text = Actual value of the switch
+pid-timed-start-stop-text = Switch for staircase lightning or movement detection
+pid-force-position-text = Forces value dependent high priority on or off state
+pid-scene-control-text = Recall or learn the set value related to encoded scene number
+pid-movement-under-consideration-of-brightness-text = Activation of an autonomous switch off function triggered by an movement detector
+pid-presence-text = Presence triggered by a movement detector to be used by other devices
+pid-relative-set-value-text = Relative dimming value
+pid-absolute-set-value-text = Controls the set value
+pid-night-text = Toggle between day and night (where day = 0 / night = 1)
+pid-invalid-string-id-text = Resets load failures / short circuits / etc
+pid-rgb-color-text = RGB Color value of the light
+pid-color-temperature-text = Color temperature value of the light
+pid-hue-text = Hue value of the light
+pid-saturation-text = Saturation value of the light
+pid-move-up-down-text = Moves sunblind up and down
+pid-adjust-up-down-text = Stops the sunblind and to step it up/down
+pid-set-absolute-position-blinds-text = Moves the sunblinds into a specified position
+pid-set-absolute-position-slats-text = Moves the slats into a specified position
+pid-rain-alarm-text = State of the rain sensor (sent cyclically and on COV)
+pid-force-position-blind-text = Forces value dependent high priority up or down state
+pid-window-door-position-text = Delivers position for Window/Door (Open / Tilted / Closed)
+pid-actuating-value-heating-text = Determines the through flow volume of the control valve
+pid-fan-level-heating-text = Display value of the fan coil speed. (0=off / 1=lowest - 5=fastest)
+pid-actuating-value-cooling-text = Determines the through flow volume of the control valve
+pid-set-value-temperature-text = Defines the displayed set point temperature of the system
+pid-relative-set-point-temperature-text = Defines the relative set point temperature of the system
+pid-window-door-text = Status indication - Open = 1 / closed = 0
+pid-status-indication-text = States indication - on/off heating/cool
+pid-fan-manual-heating-on-off-text = Switches Fan in manual control mode (master to slave)
+pid-controller-on-off-text = Switches controller on or off. Off means protection mode
+pid-relative-set-point-request-text = Request for a new relative set point value
+pid-eco-mode-on-off-request-text = Switches eco mode on or off
+pid-comfort-temperature-text = Sends the current comfort temperature
+pid-fan-level-request-text = Request for a new manual fan stage
+pid-fan-manual-on-off-request-text = WARNING: DO NOT USE!!!! Request for switching fan in manual/auto mode
+pid-controller-on-off-request-text = Request for switching controller on or off. Off means protection mode
+pid-eco-mode-on-off-request-text = Indicates ECO mode
+pid-info-on-off-text = Reflects the binary state of the actuator
+pid-force-position-info-text = Indicates the cause of forced operation (0 = not forced)
+pid-sysap-infoonoff-text = Reflects the binary state of the actuator group
+pid-sysap-infoforce-text = Indicates whether the actuator group is forced (1) or not forced (0)
+pid-info-actual-dimming-value-text = Reflects the actual value of the actuator
+pid-info-error-text = Indicates load failures / short circuits / etc
+pid-sysap-infocurrentdimmingvalue-text = Reflects the actual value of the actuator group
+pid-sysap-infoerror-text = Indicates load failures / short circuits / etc
+pid-info-color-temperature-text = Color temperature
+pid-sysap-info-color-temperature-text = Color temperature
+pid-info-hsv-text = Hue (2 Byte) Saturation (1 Byte)
+pid-sysap-info-hsv-text = Hue (2 Byte) Saturation (1 Byte)
+pid-info-color-mode-text = Hsv or color mode
+pid-sysap-info-color-mode-text = Hsv or color mode info
+pid-info-move-up-down-text = Indicates the status of moving and last moving direction
+pid-current-absolute-position-blinds-percentage-text = Indicate the current position of the sunblinds in percentage
+pid-current-absolute-position-slats-percentage-text = Indicate the current position of the slats in percentage
+pid-sysap-infomoveupdown-text = Indicates the status of moving and last moving direction of the actuator group
+pid-sysap-infocurrentabsoluteblindspercentage-text = Indicate the current position of the sunblinds in percentage of the actuator group
+pid-sysap-infocurrentabsoluteslatspercentage-text = Indicate the current position of the slats in percentage of the actuator group
+pid-measured-temperature-text = Indicates the actual measured temperature
+pid-info-value-heating-text = States the current flow volume of the control valve
+pid-info-value-cooling-text = States the current flow volume of the control valve
+pid-switchover-heating-cooling-text = Switch between heating and cooling: heating = 0 / cooling = 1
+pid-actuating-fan-stage-heating-text = Requests a new manual fan stage from actuator in heating mode
+pid-absolute-setpoint-temperature-text = Set point temperature input for timer
+pid-additional-heating-value-info-text = Heating feedback
+pid-additional-cooling-value-info-text = Cooling feedback
+pid-info-actuating-fan-stage-heating-text = Feedback from actuating fan stage
+pid-info-actuating-fan-manual-on-off-heating-text = Feedback from actuating fan stage (manual on/off)
+pid-actuating-fan-stage-cooling-text = Requests a new manual fan stage from actuator in cooling mode
+pid-info-fan-stage-cooling-text = Feedback for current fan stage in cooling mode
+pid-info-fan-manual-on-off-cooling-text = Feedback for manual fan control cooling mode
+pid-heating-active-text = Heating active
+pid-cooling-active-text = Cooling active
+pid-heating-demand-text = Heating demand
+pid-cooling-demand-text = Cooling demand
+pid-heating-demand-feedback-signal-text = Heating demand feedback signal
+pid-cooling-demand-feedback-signal-text = Cooling demand feedback signal
+pid-humidity-text = Measured Humidity
+pid-aux-on-off-request-text = Aux On/Off
+pid-aux-on-off-response-text = Aux On/Off response
+pid-heating-on-off-request-text = Heating On/Off
+pid-cooling-on-off-request-text = Cooling On/Off
+pid-operation-mode-text = Operation mode
+pid-swing-h-v-text = Swing H/V
+pid-supported-features-text = Supported features
+pid-extended-status-indication-text = Extended Status Indication
+pid-aux-heating-on-off-request-text = Aux Heating On Off Reques
+pid-emergency-heating-on-off-request-text = Emergency Heating On Off Request
+pid-relative-fan-speed-control-text = Relative control of the set value
+pid-absolute-fan-speed-control-text = Absolute control of the set value
+pid-info-absolute-fan-speed-text = Reflects the actual value of the actuator
+pid-sysap-infoactualfanspeed-text = Reflects the actual value of the actuator
+pid-notification-flags-text = Notifications of RF devices (e. g. Battery low)
+pid-power-rc-text = Bool Value 1
+pid-power-rh-text = Bool Value 2
+pid-proximity-status-text = Bool Value 3
+pid-brightness-sensor-text = Scaling Value 1
+pid-last-touch-text = Scaling Value 2
+pid-led-backlighting-night-mode-text = Scaling Value 3
+pid-locator-beep-text = Locator Beep
+pid-switch-test-alarm-text = Switch Test Alarm
+pid-fire-alarm-active-text = Fire-Alarm Active
+pid-outside-temperature-text = Outdoor Temperature
+pid-wind-force-text = Wind force
+pid-brightness-alarm-text = Brightness alarm
+pid-lux-value-text = Weatherstation brightness level
+pid-wind-speed-text = Wind speed
+pid-wind-alarm-text = Triggers if the wind speed is higher than the threshold
+pid-frost-alarm-text = Triggers if the temperature is lower than the threshold
+pid-rain-detection-text = Rain detection
+pid-rain-sensor-frequency-text = Rain sensor frequency
+pid-play-text = Start playing
+pid-pause-text = Pause/Stop playing
+pid-next-text = Play next title
+pid-previous-text = Play previous title
+pid-play-mode-text = Play mode (shuffle / repeat)
+pid-relative-volume-control-text = Relative volume control. See also relative dimming
+pid-absolute-volume-control-text = Set player volume
+pid-group-membership-text = Group membership
+pid-play-favorite-text = Play favorite
+pid-play-next-favorite-text = Play next favorite
+pid-playback-status-text = Playback status
+pid-current-item-metadata-info-text = Current item metadata info
+pid-info-mute-text = Info mute
+pid-info-actual-volume-text = Info actual volume
+pid-allowed-playback-actions-text = Allowed playback actions
+pid-info-playing-favorite-text = Info playing favorite
+pid-absolute-group-volume-control-text = Group Volume Control
+pid-info-absolute-group-volume-text = Info Group Volume
+pid-media-source-text = Media source
+pid-solar-power-production-text = Power from the sun
+pid-inverter-output-power-text = Output power of inverter (pbatt+Psun)
+pid-solar-energy-(today)-text = Produced Energy
+pid-injected-energy-(today)-text = Energy into the grid
+pid-purchased-energy-(today)-text = Energy from the grid
+pid-inverter-alarm-text = Inverter is working in stand alone mode
+pid-self-consumption-text = production PV/ Total consumption
+pid-self-sufficiency-text = Consumption from PV/ Total consumption
+pid-home-power-consumption-text = Power in home (PV and grid)
+pid-power-to-grid-text = Power from and to the grid: Purchased (less than 0), Injection (more than 0)
+pid-consumed-energy-(today)-text = Energy bought from grid per day
+pid-meter-alarm-text = Meter communication loss
+pid-battery-level-text = Battery level
+pid-battery-power-text = Batter power: Discharge (less then 0), Charge (more then 0)
+pid-boost-text = Boos status - 1: Boost enable request, 0: boost disable request
+pid-stop-charging-reuqest-text = Stop charging request - 1: Stop charging session requested, 0: n/a, will be resetted when cable is unplugged
+pid-enable-charging-reuqest-text = Enable charging - 1: Enable charging when cable is plugged in, 0: Disable next charging session but charge until cable is plugged
+pid-info-boost-text = Boots info - 1: Boost enabled, 0: boost disabled
+pid-info-wallbox-status-text = Wallbox status 00000001: car plugged in, 00000002: Authorization granted, 00000004: Not charging, battery fully loaded, 40000000: charging stopped due to blackout prevention, 80000000: Ground fault error
+pid-info-charging-text = Charging status - 1: Charging, 0: Not charging
+pid-info-charging-enabled-text = Charging status - 1: Charging enabled for next session, 0: Charging disabled for next session
+pid-info-installed-power-text = Installed power (e.g. 20 kW)
+pid-info-transmitted-energy-text = Energy transmitted so far per session (in Wh)
+pid-info-car-range-text = Car range in km per sessions
+pid-info-charging-duration-text = Start of charging session (in minutes in UTC)
+pid-info-current-limit-text = Limit for charger (in kW)
+pid-info-current-limit-for-group-text = Limit for group of charger (in kW)
+pid-album-cover-url-text = Album cover URL
+pid-secure@home-central-unit-text = Encrypted control datapoint for domus alarm center
+pid-domusdisarmcounter-text = Info about the next counter to disarm the system
+pid-intrusion-alarm-text = Intrusion alarm active
+pid-safety-alarm-text = Safety Alarm active
+pid-infoconfigurationstatus-text = Domus alarm device negative feedback and configuration info.
+pid-enable-configuration-text = Encrypted control datapoint for entering configuration mode
+pid-disarming-led-text = Arm/Disarm a Zone
+pid-aes-key-text = Manufacturer ID + Serial + AES Key
+pid-zone-status-text = Zone status
+pid-time-text = Absolute number of seconds when the zone will be armed
+pid-start-stop-text = Starts / Stops operation
+pid-pause-resume-text = Pause / Resume
+pid-select-program-text = Select program
+pid-delayed-start-time-text = Delayed start time
+pid-info-status-text = Info status
+pid-info-remote-start-enabled-text = Info remote start enabled
+pid-info-program-text = Info program
+pid-info-finish-time-text = Info finish time
+pid-info-delayed-start-text = Info delayed start
+pid-info-door-text = Info door
+pid-info-door-alarm-text = Info door alarm
+pid-switch-supercool-text = Switch supercool
+pid-switch-superfreeze-text = Switch superfreeze
+pid-info-switch-supercool-text = Info switch supercool
+pid-info-switch-superfreeze-text = Info switch superfreeze
+pid-measured-temperature-text = Measured Temperature
+pid-measured-temperature-text = Measured Temperature
+pid-set-value-temperature-text = Set Value Temperature
+pid-set-value-temperature-text = Set Value Temperature
+pid-change-operation-text = Change operation
+pid-detailed-status-info-text = Detailed status info
+pid-info-remaining-time-text = Remaining time till status change (start, finish, etc.)
+pid-time-of-last-status-change-text = Time of last status change (start, finish, etc.)
+pid-lock-unlock-door-command-text = Lock/Unlock door command (1 Bit)
+pid-info-locked-unlocked-text = Info Lock/Unlock door(1 Bit)
+pid-time-text = Current local time
+pid-date-text = Current local date
+pid-notification-text = Notification from message center
+pid-switch-entity-on-off-text = Entity control e.g. activate an alert or timer program
+pid-info-switch-entity-on-off-text = Reflects the active state of an entity e.g. alert or timer program
+pid-consistency-tag-text = Notifications of RF devices (e. g. Battery low)
+pid-battery-status-text = Notifications of RF devices (e. g. Battery low)
+pid-stay-awake-text = Notifications of RF devices (e. g. Battery low)
+pid-proxy-switch-text = Proxy switch
+pid-proxy1-text = Proxy, 1 byte
+pid-proxy2-text = Proxy, 2 byte
+pid-proxy4-text = Proxy, 4 byte
+pid-cyclic-sleep-time-text = Time of sleep cycles
+pid-presence-text = SysAP presence
+pid-measured-temperature-1-text = SysAP temperature
+pid-standby-statistics-text = Statistics about standby usage for battery devices
+pid-heartbeat-delay-text = Time period between two heartbeats
+pid-info-heartbeat-delay-text = Time period between two heartbeats
+pid-measured-temperature-1-text = For debug purposes
+pid-measured-temperature-2-text = For debug purposes
+pid-measured-temperature-3-text = For debug purposes
+pid-measured-temperature-4-text = For debug purposes
+pid-air-quality-pressure-value-text = Air quality sensor value - Pressure value
+pid-air-quality-co2-value-text = Air quality sensor value - CO2 value
+pid-air-quality-co-value-text = Air quality sensor value - CO value
+pid-air-quality-no2-value-text = Air quality sensor value - NO2 value
+pid-air-quality-o3-value-text = Air quality sensor value - O3 value
+pid-air-quality-pm10-value-text = Air quality sensor value - PM10 value
+pid-air-quality-pm25-value-text = Air quality sensor value - PM25 value
+pid-air-quality-voc-value-text = Air quality sensor value - VOC value
diff --git a/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/thing/bridge-type.xml b/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/thing/bridge-type.xml
new file mode 100644 (file)
index 0000000..243f4fd
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="freeathome"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <bridge-type id="gateway">
+               <label>free@home Gateway</label>
+               <description>This gateway represents the free@home Gateway</description>
+
+               <config-description>
+                       <parameter-group name="identification">
+                               <label>SysAP Setting</label>
+                               <description>SysAP network address and user settings</description>
+                               <advanced>false</advanced>
+                       </parameter-group>
+
+                       <parameter name="ipAddress" type="text" required="true" groupName="identification">
+                               <context>network-address</context>
+                               <label>Sysap IP Address</label>
+                               <description>IP Address of the Busch-Jaeger Gateway</description>
+                       </parameter>
+                       <parameter name="username" type="text" required="true" groupName="identification">
+                               <label>User Name</label>
+                               <description>The login name</description>
+                       </parameter>
+                       <parameter name="password" type="text" required="true" groupName="identification">
+                               <label>Password</label>
+                               <context>password</context>
+                               <description>Password for gateway</description>
+                       </parameter>
+
+               </config-description>
+       </bridge-type>
+</thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/thing/thing-type.xml b/bundles/org.openhab.binding.freeathome/src/main/resources/OH-INF/thing/thing-type.xml
new file mode 100644 (file)
index 0000000..be0fbe3
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="freeathome"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+       <thing-type id="device" listed="false">
+               <supported-bridge-type-refs>
+                       <bridge-type-ref id="gateway"/>
+               </supported-bridge-type-refs>
+               <label>free@home Device</label>
+               <description>This represents the generic free@home device</description>
+               <properties>
+                       <property name="vendor">Busch&amp;Jäger - ABB</property>
+                       <property name="modelId">Generic free@home Device</property>
+               </properties>
+               <representation-property>deviceId</representation-property>
+               <config-description>
+                       <parameter name="deviceId" type="text" required="true">
+                               <label>Device Id</label>
+                               <description>This is the unique id of the free@home device (Please do not modify after the Thing is generated)</description>
+                       </parameter>
+               </config-description>
+       </thing-type>
+</thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.freeathomesystem/NOTICE b/bundles/org.openhab.binding.freeathomesystem/NOTICE
deleted file mode 100644 (file)
index 38d625e..0000000
+++ /dev/null
@@ -1,13 +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
diff --git a/bundles/org.openhab.binding.freeathomesystem/README.md b/bundles/org.openhab.binding.freeathomesystem/README.md
deleted file mode 100644 (file)
index de9940c..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-# ABB/Busch-free@home Smart Home binding
-
-openHAB ABB/Busch-free@home binding based on the offical free@home local API.
-
-# Description
-
-This binding allows you to connect your free@home Smart Home system from ABB / Busch-Jaeger to openHAB and to control and observe most of the components.
-It requires a System Access Point with version 2.6.1 or higher.
-
-# Supported Devices
-
-**Network Gateway / System Access Point**
-
- - ABB / Busch-Jaeger System Access Point 2.0
-
-**Sensors and Actuators**
-
- - Switch Actuator Sensor with single and multiple channels (wired and wireless)
- - Dimming Actuator Sensor with single and multiple channels (wired, wireless and flex)
- - Motion detection with and without actuator (wired, wireless and flex)
- - Switch Actuator 4-channel
- - Dimming Actuator 4- and 6-channel
- - Door opener actuator
- - Door ring sensor
- - Hue devices (untested)
-
-**Blinds and Windows**
-
- - Shutter Actuator with single and multiple channels (wired and wireless)
- - Blind Actuator  with single and multiple channels (wired and wireless)
- - Attic window actuator
- - Awning actuator
-
-**Room Temperature Control**
-
- - Room temperature controller master without fan
- - Room temperature controller master with fan
- - Room temperature controller slave
-
-**Other devices** (e.g. movement detector, ring sensor and door opener)
-
- - IP-touch panel (function: door opener, door ring sensor)
- - Virtual devices (e.g. virtual switch, RTC and detectors)
-
-**Information about virtual devices**
-Virtual device in the free@home smart-home system needs continuous keep-alive signal otherwise the free@home device is marked as unresponsive.
-This keep-alive signal must be provided by a user script or set the TTL value of the virtual device to "-1" during the creation of the virtual device.
-
-# Tested SysAP Versions
-
-| Version | Supported |
-|---------|-----------|
-| 2.6.1   | yes       |
-| 2.6.3   | yes       |
-| 3.1.1   | yes       |
-
-# Setup / Installation
-
-## Prerequisites
-
-To make use of this Binding first the local free@home API has to be activated.
-The API is disabled by default.
-
-1. Open the free@home next app
-1. Browse to "Settings ⇨ free@home settings ⇨ local API and activate the checkbox
-
-## Setup and Discovery
-
-The free@home bridge shall be added manually.
-Once it is added as a Thing with correct credentials, the scan of free@home devices will be possible.
-
-## free@home components as openHAB Things
-
-The ABB/Busch free@home system is calling its smart home components as free@home devices.
-The free@home system devices can have one or multiple channels depending the device's features.
-During the scanning process the openHAB binding will detect only the devices IDs.
-The device features will be detected at the point in time, when a openHAB Thing is created.
-At the of the creation the free@home binding will automatically create the relevant channels without any further configuration.
-If a free@home system device has multiple smart-home channels (e.g. 4x DIN/rail Actuator), the newly created Thing will get all relevant channels to operate all actuators existing inside the free@home device.
-
-## Sensors and Actuators of free@home Devices as Things in openHAB
-
-The free@home system supports sensors and actuators.
-The connection of sensors and actuators are done on the free@home system dashboard.
-If a Thing channel is a free@home device sensor channel, this channel is read only.
-
-## Bridge Configuration
-
-There are several settings for a bridge:
-
-| Parameter                | Description                             |
-|--------------------------|-----------------------------------------|
-| **ipAddress** (required) | Network address of the free@home SysAP  |
-| **username** (required)  | Valid user name for the free@home SysAP |
-| **password** (required)  | Password of the user                    |
-
-## Examples for .things
-
-Things are all discovered automatically and visible on the openHAB UI after pushing the scan button
-
-In order to manually configure a Thing:
-
-```java
-Bridge freeathomesystem:bridge:mysysap [ ipAddress="...", username="...", password="..." ]
-{
-    Thing device    ABB700000001
-    Thing device    ABB700000012
-}
-```
-
-The only parameter needed to create a Thing is the free@home device ID, which you can find as sticker on the device.
-The creation of the openHAB channels to operate the free@home device is happening automatically based on the device features detected online.
-
-## Examples for .items
-
-Sample for the free@home thermostat device
-
-```java
-Switch Livingroom_Thermostat_Switch                       "Thermostat Siwtch"               <temperature>  (Livingroom)                              { channel="freeathomesystem:device:312095ad75:ABB700000001:ch0000#controller-on-off-request" }
-Switch LivingRoom_Thermostat_EcoOnOff                     "Thermostat Eco Activation"       <switch>       (Livingroom)                              { channel="freeathomesystem:device:312095ad75:ABB700000001:ch0000#eco-mode-on-off-request" }
-Number LivingRoom_Thermostat_MeasuredTemperature          "Measured Temperature"            <temperature>  (Livingroom)  ["Temperature"]             { channel="freeathomesystem:device:312095ad75:ABB700000001:ch0000#measured-temperature" }
-Number LivingRoom_Thermostat_SetpointTemperature          "Setpoint Temperature"            <temperature>  (Livingroom)  ["Setpoint", "Temperature"] { channel="freeathomesystem:device:312095ad75:ABB700000001:ch0000#absolute-setpoint-temperature" }
-Number LivingRoom_ThermostatHeatingActive                 "Thermostat Heating Active"       <temperature>  (Livingroom)  ["Status"]                  { channel="freeathomesystem:device:312095ad75:ABB700000001:ch0000#heating-active" }
-Number LivingRoom_ThermostatHeatingDemand                 "Thermostat Heating Demand"       <temperature>  (Livingroom)  ["Status"]                  { channel="freeathomesystem:device:312095ad75:ABB700000001:ch0000#status-indication" }
-```
-
-Sample for the free@home device for switch
-
-```java
-Switch Livingroom_Switch                    "Livingroom Switch"       <switch>  (Livingroom)  ["Light"]   { channel="freeathomesystem:device:312095ad75:ABB700000012:ch0000#switch-on-off" }
-Switch Livingroom_Lamp                      "Livingroom Lamp"         <switch>  (Livingroom)  ["Light"]   { channel="freeathomesystem:device:312095ad75:ABB700000012:ch0006#switch-on-off" }
-Switch Livingroom_Aux                       "Livingroom Aux Switch"   <switch>  (Livingroom)  ["Light"]   { channel="freeathomesystem:device:312095ad75:ABB700000012:ch000b#switch-on-off" }
-```
-
-# Communities
-
-[openHAB community of this binding](https://community.openhab.org/t/abb-busch-jager-free-home-official-rest-api/141698)
-
-[Busch-Jaeger Community](https://community.busch-jaeger.de/)
-
-[free@home user group Facebook DE](https://www.facebook.com/groups/738242583015188)
-
-[free@home user group Facebook EN](https://www.facebook.com/groups/452502972031360)
diff --git a/bundles/org.openhab.binding.freeathomesystem/pom.xml b/bundles/org.openhab.binding.freeathomesystem/pom.xml
deleted file mode 100644 (file)
index dc49e47..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.openhab.addons.bundles</groupId>
-    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
-    <version>4.2.0-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>org.openhab.binding.freeathomesystem</artifactId>
-
-  <name>openHAB Add-ons :: Bundles :: FreeAtHomeSystem Binding</name>
-
-</project>
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/feature/feature.xml b/bundles/org.openhab.binding.freeathomesystem/src/main/feature/feature.xml
deleted file mode 100644 (file)
index 323d77d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<features name="org.openhab.binding.freeathomesystem-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
-       <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
-
-       <feature name="openhab-binding-freeathomesystem" description="FreeAtHomeSystem Binding" version="${project.version}">
-               <feature>openhab-runtime-base</feature>
-               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.freeathomesystem/${project.version}</bundle>
-       </feature>
-</features>
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemBindingConstants.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemBindingConstants.java
deleted file mode 100644 (file)
index 359cc2c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal;
-
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.ThingTypeUID;
-
-/**
- * The {@link FreeAtHomeSystemBindingConstants} class defines common constants, which are
- * used across the whole binding.
- *
- * @author Andras Uhrin - Initial contribution
- */
-@NonNullByDefault
-public class FreeAtHomeSystemBindingConstants {
-
-    public static final String CONFIG_DESCRIPTION_URI_THING_PREFIX = "thing-type";
-
-    public static final String BINDING_ID = "freeathomesystem";
-
-    // List of all Thing Type UIDs
-    public static final String BRIDGE_TYPE_ID = "gateway";
-    public static final String DEVICE_TYPE_ID = "device";
-
-    // List of all Thing Type UIDs
-    public static final ThingTypeUID BRIDGE_TYPE_UID = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_ID);
-    public static final ThingTypeUID DEVICE_TYPE_UID = new ThingTypeUID(BINDING_ID, DEVICE_TYPE_ID);
-
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(BRIDGE_TYPE_UID, DEVICE_TYPE_UID);
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemDiscoveryService.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemDiscoveryService.java
deleted file mode 100644 (file)
index db1ff2c..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal;
-
-import java.time.Instant;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDeviceDescription;
-import org.openhab.binding.freeathomesystem.internal.handler.FreeAtHomeBridgeHandler;
-import org.openhab.binding.freeathomesystem.internal.util.FreeAtHomeHttpCommunicationException;
-import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService;
-import org.openhab.core.config.discovery.DiscoveryResult;
-import org.openhab.core.config.discovery.DiscoveryResultBuilder;
-import org.openhab.core.thing.ThingTypeUID;
-import org.openhab.core.thing.ThingUID;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The {@link FreeAtHomeSystemDiscoveryService} is responsible for performing discovery of things
- *
- * @author Andras Uhrin - Initial contribution
- */
-@NonNullByDefault
-public class FreeAtHomeSystemDiscoveryService extends AbstractThingHandlerDiscoveryService<FreeAtHomeBridgeHandler> {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeSystemDiscoveryService.class);
-    private @Nullable ScheduledFuture<?> backgroundDiscoveryJob = null;
-
-    private static final long BACKGROUND_DISCOVERY_DELAY = 1L;
-    private boolean isScanTerminated;
-
-    Runnable runnable = new Runnable() {
-        @Override
-        public void run() {
-            ThingUID bridgeUID = thingHandler.getThing().getUID();
-
-            List<String> deviceList;
-
-            try {
-                deviceList = thingHandler.getDeviceDeviceList();
-
-                for (int i = 0; (i < deviceList.size()) && !isScanTerminated; i++) {
-                    FreeAtHomeDeviceDescription device = thingHandler.getFreeatHomeDeviceDescription(deviceList.get(i));
-
-                    ThingUID uid = new ThingUID(FreeAtHomeSystemBindingConstants.DEVICE_TYPE_UID, bridgeUID,
-                            device.deviceId);
-                    Map<String, Object> properties = new HashMap<>(1);
-                    properties.put("deviceId", device.deviceId);
-                    properties.put("interface", device.interfaceType);
-
-                    String deviceLabel = device.deviceLabel;
-
-                    DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(uid).withLabel(deviceLabel)
-                            .withRepresentationProperty("deviceId").withBridge(bridgeUID).withProperties(properties)
-                            .build();
-
-                    thingDiscovered(discoveryResult);
-
-                    logger.debug("Thing discovered - DeviceId: {} - Device label: {}", device.getDeviceId(),
-                            device.getDeviceLabel());
-                }
-
-                stopScan();
-            } catch (FreeAtHomeHttpCommunicationException e) {
-                logger.debug("Communication error in device discovery with the bridge: {}",
-                        thingHandler.getThing().getLabel());
-            } catch (RuntimeException e) {
-                logger.debug("Scanning interrupted");
-            }
-        }
-    };
-
-    public FreeAtHomeSystemDiscoveryService(int timeout) {
-        super(FreeAtHomeBridgeHandler.class, FreeAtHomeSystemBindingConstants.SUPPORTED_THING_TYPES_UIDS, timeout,
-                false);
-    }
-
-    public FreeAtHomeSystemDiscoveryService() {
-        this(90);
-    }
-
-    @Override
-    public Set<ThingTypeUID> getSupportedThingTypes() {
-        return Set.of(FreeAtHomeSystemBindingConstants.BRIDGE_TYPE_UID);
-    }
-
-    @Override
-    protected void startScan() {
-        if (backgroundDiscoveryJob == null) {
-            this.removeOlderResults(Instant.now().toEpochMilli());
-
-            isScanTerminated = false;
-            backgroundDiscoveryJob = scheduler.schedule(runnable, BACKGROUND_DISCOVERY_DELAY, TimeUnit.SECONDS);
-        }
-    }
-
-    @Override
-    protected synchronized void stopScan() {
-        super.stopScan();
-
-        isScanTerminated = true;
-
-        ScheduledFuture<?> localDiscoveryJob = backgroundDiscoveryJob;
-
-        if (localDiscoveryJob != null) {
-            localDiscoveryJob.cancel(true);
-        }
-
-        backgroundDiscoveryJob = null;
-
-        removeOlderResults(Instant.now().toEpochMilli());
-    }
-
-    @Override
-    public void deactivate() {
-        removeOlderResults(Instant.now().toEpochMilli());
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemHandlerFactory.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/FreeAtHomeSystemHandlerFactory.java
deleted file mode 100644 (file)
index 10df82c..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal;
-
-import static org.openhab.binding.freeathomesystem.internal.FreeAtHomeSystemBindingConstants.*;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jetty.client.HttpClient;
-import org.openhab.binding.freeathomesystem.internal.handler.FreeAtHomeBridgeHandler;
-import org.openhab.binding.freeathomesystem.internal.handler.FreeAtHomeDeviceHandler;
-import org.openhab.binding.freeathomesystem.internal.type.FreeAtHomeChannelTypeProvider;
-import org.openhab.binding.freeathomesystem.internal.type.FreeAtHomeThingTypeProvider;
-import org.openhab.core.i18n.LocaleProvider;
-import org.openhab.core.i18n.TranslationProvider;
-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.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The {@link FreeAtHomeSystemHandlerFactory} is responsible for creating things and thing
- * handlers.
- *
- * @author Andras Uhrin - Initial contribution
- */
-@NonNullByDefault
-@Component(configurationPid = "binding.freeathomesystem", service = ThingHandlerFactory.class)
-public class FreeAtHomeSystemHandlerFactory extends BaseThingHandlerFactory {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeSystemHandlerFactory.class);
-
-    private final HttpClient httpClient;
-    private final FreeAtHomeChannelTypeProvider channelTypeProvider;
-    private final TranslationProvider i18nProvider;
-    private final LocaleProvider localeProvider;
-
-    @Activate
-    public FreeAtHomeSystemHandlerFactory(@Reference FreeAtHomeThingTypeProvider thingTypeProvider,
-            @Reference FreeAtHomeChannelTypeProvider channelTypeProvider, @Reference TranslationProvider i18nProvider,
-            @Reference LocaleProvider localeProvider, @Reference HttpClientFactory httpClientFactory,
-            ComponentContext componentContext) {
-        super.activate(componentContext);
-        this.channelTypeProvider = channelTypeProvider;
-        this.i18nProvider = i18nProvider;
-        this.localeProvider = localeProvider;
-
-        // create httpClient
-        httpClient = httpClientFactory.createHttpClient(FreeAtHomeSystemBindingConstants.BINDING_ID);
-
-        // Configure client
-        httpClient.setFollowRedirects(false);
-        httpClient.setMaxConnectionsPerDestination(1);
-        httpClient.setMaxRequestsQueuedPerDestination(50);
-
-        // Set timeouts
-        httpClient.setIdleTimeout(-1);
-        httpClient.setConnectTimeout(5000);
-
-        try {
-            // Start HttpClient.
-            httpClient.start();
-        } catch (Exception ex) {
-            logger.error("Could not create HttpClient: {}", ex.getMessage());
-
-            throw new IllegalStateException("Could not create HttpClient", ex);
-        }
-    }
-
-    @Deactivate
-    public void deactivate() {
-        try {
-            httpClient.stop();
-        } catch (Exception ex) {
-            logger.warn("Failed to stop HttpClient: {}", ex.getMessage());
-        }
-    }
-
-    @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 (BRIDGE_TYPE_UID.equals(thingTypeUID)) {
-            return new FreeAtHomeBridgeHandler((Bridge) thing, httpClient);
-        } else if (DEVICE_TYPE_UID.equals(thingTypeUID)) {
-            return new FreeAtHomeDeviceHandler(thing, channelTypeProvider, i18nProvider, localeProvider);
-        }
-
-        return null;
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeBridgeHandlerConfiguration.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeBridgeHandlerConfiguration.java
deleted file mode 100644 (file)
index 0d44df4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.configuration;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link FreeAtHomeBridgeHandlerConfiguration} class contains fields mapping thing configuration parameters.
- *
- * @author Andras Uhrin - Initial contribution
- */
-@NonNullByDefault
-public class FreeAtHomeBridgeHandlerConfiguration {
-
-    /**
-     * Bridgeconfiguration parameter.
-     */
-    public String ipAddress = "";
-    public String username = "";
-    public String password = "";
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeDeviceHandlerConfiguration.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/configuration/FreeAtHomeDeviceHandlerConfiguration.java
deleted file mode 100644 (file)
index 8a84a5c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.configuration;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link FreeAtHomeDeviceHandlerConfiguration} class contains fields mapping device configuration parameters.
- *
- * @author Andras Uhrin - Initial contribution
- */
-@NonNullByDefault
-public class FreeAtHomeDeviceHandlerConfiguration {
-    public String deviceId = "";
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapoint.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapoint.java
deleted file mode 100644 (file)
index e21f9dc..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.datamodel;
-
-import java.util.Iterator;
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.JsonObject;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeDatapoint {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDatapoint.class);
-
-    enum DatapointDirection {
-        UNKNOWN,
-        INPUT,
-        OUTPUT,
-        INPUTOUTPUT,
-        INPUT_AS_OUTPUT
-    };
-
-    public String channelId = "";
-    private String datapointId = "";
-
-    DatapointDirection searchForDatapoint(DatapointDirection direction, int neededPairingIDFunction, String channelId,
-            JsonObject jsonObjectOfChannel) {
-        DatapointDirection resultingDirection = DatapointDirection.UNKNOWN;
-        boolean foundId = false;
-        JsonObject localDatapoints = null;
-
-        switch (direction) {
-            case INPUT: {
-                localDatapoints = jsonObjectOfChannel.getAsJsonObject("inputs");
-                resultingDirection = DatapointDirection.INPUT;
-                break;
-            }
-            case INPUT_AS_OUTPUT: {
-                localDatapoints = jsonObjectOfChannel.getAsJsonObject("inputs");
-                resultingDirection = DatapointDirection.OUTPUT;
-                break;
-            }
-            case OUTPUT: {
-                localDatapoints = jsonObjectOfChannel.getAsJsonObject("outputs");
-                resultingDirection = DatapointDirection.OUTPUT;
-                break;
-            }
-            default: {
-                localDatapoints = jsonObjectOfChannel.getAsJsonObject("outputs");
-                resultingDirection = DatapointDirection.OUTPUT;
-                break;
-            }
-        }
-
-        Set<String> keys = localDatapoints.keySet();
-
-        Iterator<String> iter = keys.iterator();
-
-        // Scan datapoints for pairingID IDs
-        while (iter.hasNext() && !foundId) {
-            String datapointId = iter.next();
-
-            JsonObject datapointJsonObject = localDatapoints.getAsJsonObject(datapointId);
-
-            int pairingIDFunction = datapointJsonObject.get("pairingID").getAsInt();
-
-            if (pairingIDFunction == neededPairingIDFunction) {
-                this.channelId = channelId;
-                this.datapointId = datapointId;
-
-                logger.debug("Datapoint is found - channel {} - datapoint {}", this.channelId, this.datapointId);
-
-                foundId = true;
-            }
-        }
-
-        // id not found, add dummy
-        if (!foundId) {
-            this.channelId = "";
-            this.datapointId = "";
-            resultingDirection = DatapointDirection.UNKNOWN;
-
-            logger.debug("Needed datapoint is not found - channel {} - pairingId {}", channelId,
-                    neededPairingIDFunction);
-        }
-
-        return resultingDirection;
-    }
-
-    public String getChannelIdforDatapoint() {
-        return channelId;
-    }
-
-    public String getDatapointId() {
-        return datapointId;
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapointGroup.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDatapointGroup.java
deleted file mode 100644 (file)
index efea0d6..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.datamodel;
-
-import static org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDatapoint.*;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.freeathomesystem.internal.util.FreeAtHomeGeneralException;
-import org.openhab.binding.freeathomesystem.internal.util.PidTranslationUtils;
-import org.openhab.binding.freeathomesystem.internal.valuestateconverter.BooleanValueStateConverter;
-import org.openhab.binding.freeathomesystem.internal.valuestateconverter.DecimalValueStateConverter;
-import org.openhab.binding.freeathomesystem.internal.valuestateconverter.ShuttercontrolValueStateConverter;
-import org.openhab.binding.freeathomesystem.internal.valuestateconverter.ValueStateConverter;
-import org.openhab.core.library.CoreItemFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.JsonObject;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeDatapointGroup {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDatapointGroup.class);
-
-    public enum DatapointGroupDirection {
-        UNDEFINED,
-        INPUT,
-        OUTPUT,
-        INPUTOUTPUT
-    }
-
-    private DatapointGroupDirection datapointGroupDirection;
-    private int pairingId;
-
-    private String functionString = "";
-    private @Nullable FreeAtHomeDatapoint inputDatapoint;
-    private @Nullable FreeAtHomeDatapoint outputDatapoint;
-
-    FreeAtHomeDatapointGroup() {
-        datapointGroupDirection = DatapointGroupDirection.UNDEFINED;
-        inputDatapoint = null;
-        outputDatapoint = null;
-    }
-
-    boolean addDatapointToGroup(DatapointDirection direction, int neededPairingId, String channelId,
-            JsonObject jsonObjectOfChannel) {
-        FreeAtHomeDatapoint newDatapoint = new FreeAtHomeDatapoint();
-
-        DatapointDirection resultingDirection = newDatapoint.searchForDatapoint(direction, neededPairingId, channelId,
-                jsonObjectOfChannel);
-
-        if (resultingDirection != DatapointDirection.UNKNOWN) {
-            switch (resultingDirection) {
-                case INPUT: {
-                    inputDatapoint = newDatapoint;
-
-                    pairingId = neededPairingId;
-
-                    break;
-                }
-                case OUTPUT: {
-                    outputDatapoint = newDatapoint;
-
-                    if (inputDatapoint == null) {
-                        pairingId = neededPairingId;
-                    }
-
-                    break;
-                }
-                case INPUTOUTPUT:
-                case INPUT_AS_OUTPUT:
-                case UNKNOWN:
-                    break;
-            }
-        }
-
-        if (inputDatapoint != null && outputDatapoint != null) {
-            datapointGroupDirection = DatapointGroupDirection.INPUTOUTPUT;
-        } else {
-            if (inputDatapoint == null && outputDatapoint != null) {
-                datapointGroupDirection = DatapointGroupDirection.OUTPUT;
-            } else {
-                if (inputDatapoint != null && outputDatapoint == null) {
-                    datapointGroupDirection = DatapointGroupDirection.INPUT;
-                } else {
-                    datapointGroupDirection = DatapointGroupDirection.UNDEFINED;
-                }
-            }
-        }
-
-        return resultingDirection != DatapointDirection.UNKNOWN;
-    }
-
-    public void applyChangesForVirtualDevice() {
-        // The input and output datapoints are meant from the device point of view. Because the virtual devices are
-        // outside of the free@home system the input and output datapoint must be switched
-        @Nullable
-        FreeAtHomeDatapoint localDatapoint = inputDatapoint;
-
-        inputDatapoint = outputDatapoint;
-        outputDatapoint = localDatapoint;
-
-        if (inputDatapoint != null && outputDatapoint != null) {
-            datapointGroupDirection = DatapointGroupDirection.INPUTOUTPUT;
-        } else {
-            if (inputDatapoint == null && outputDatapoint != null) {
-                datapointGroupDirection = DatapointGroupDirection.OUTPUT;
-            } else {
-                if (inputDatapoint != null && outputDatapoint == null) {
-                    datapointGroupDirection = DatapointGroupDirection.INPUT;
-                } else {
-                    datapointGroupDirection = DatapointGroupDirection.UNDEFINED;
-                }
-            }
-        }
-
-        return;
-    }
-
-    public @Nullable FreeAtHomeDatapoint getInputDatapoint() {
-        return inputDatapoint;
-    }
-
-    public @Nullable FreeAtHomeDatapoint getOutputDatapoint() {
-        return outputDatapoint;
-    }
-
-    public DatapointGroupDirection getDirection() {
-        return datapointGroupDirection;
-    }
-
-    public boolean isDecimal() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.PID_VALUETYPE_DECIMAL
-                .equals(PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId)));
-    }
-
-    public boolean isInteger() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.PID_VALUETYPE_INTEGER
-                .equals(PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId)));
-    }
-
-    public boolean isReadOnly() {
-        return (DatapointGroupDirection.INPUTOUTPUT == datapointGroupDirection) ? false
-                : ((DatapointGroupDirection.INPUT == datapointGroupDirection) ? false : true);
-    }
-
-    public int getMax() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.getMax(String.format("0x%04X", pairingId));
-    }
-
-    public int getMin() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.getMin(String.format("0x%04X", pairingId));
-    }
-
-    public String getLabel() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.getShortTextForPairingId(String.format("0x%04X", pairingId));
-    }
-
-    public String getDescription() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.getDescriptionTextForPairingId(String.format("0x%04X", pairingId));
-    }
-
-    public String getValueType() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
-    }
-
-    public String getTypePattern() throws FreeAtHomeGeneralException {
-        String pattern = "";
-
-        functionString = PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
-
-        switch (functionString) {
-            case PidTranslationUtils.PID_VALUETYPE_DECIMAL:
-                pattern = "%.1f";
-                break;
-            case PidTranslationUtils.PID_VALUETYPE_INTEGER:
-                pattern = "%d";
-                break;
-            default:
-                pattern = "";
-                logger.debug("Type pattern not found for PairingID {} - using default",
-                        String.format("0x%04X", pairingId));
-                break;
-        }
-
-        return pattern;
-    }
-
-    public ValueStateConverter getValueStateConverter() throws FreeAtHomeGeneralException {
-        ValueStateConverter valueStateConverter = new BooleanValueStateConverter();
-
-        functionString = PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
-
-        switch (functionString) {
-            case PidTranslationUtils.PID_VALUETYPE_BOOLEAN:
-                valueStateConverter = new BooleanValueStateConverter();
-                break;
-            case PidTranslationUtils.PID_VALUETYPE_DECIMAL:
-            case PidTranslationUtils.PID_VALUETYPE_INTEGER:
-                valueStateConverter = new DecimalValueStateConverter();
-                break;
-            case PidTranslationUtils.PID_VALUETYPE_STRING:
-                break;
-            case PidTranslationUtils.PID_VALUETYPE_SHUTTERMOVEMENT:
-                valueStateConverter = new ShuttercontrolValueStateConverter();
-                break;
-            default:
-                valueStateConverter = new DecimalValueStateConverter();
-                logger.debug("Value converter not found for PairingID {} - using default",
-                        String.format("0x%04X", pairingId));
-                break;
-        }
-
-        return valueStateConverter;
-    }
-
-    public String getOpenHabItemType() throws FreeAtHomeGeneralException {
-        String itemTypeString = "";
-
-        functionString = PidTranslationUtils.getValueTypeForPairingId(String.format("0x%04X", pairingId));
-
-        switch (functionString) {
-            case PidTranslationUtils.PID_VALUETYPE_BOOLEAN:
-                itemTypeString = CoreItemFactory.SWITCH;
-                break;
-            case PidTranslationUtils.PID_VALUETYPE_DECIMAL:
-            case PidTranslationUtils.PID_VALUETYPE_INTEGER:
-                itemTypeString = CoreItemFactory.NUMBER;
-                break;
-            case PidTranslationUtils.PID_VALUETYPE_SHUTTERMOVEMENT:
-                itemTypeString = CoreItemFactory.ROLLERSHUTTER;
-                break;
-            default:
-                itemTypeString = CoreItemFactory.NUMBER;
-                logger.debug("Item type constant not found for PairingID {} - using default",
-                        String.format("0x%04X", pairingId));
-                break;
-        }
-
-        return itemTypeString;
-    }
-
-    public String getOpenHabCategory() throws FreeAtHomeGeneralException {
-        return PidTranslationUtils.getCategoryForPairingId(String.format("0x%04X", pairingId));
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceChannel.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceChannel.java
deleted file mode 100644 (file)
index ef75942..0000000
+++ /dev/null
@@ -1,543 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.datamodel;
-
-import static org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDatapoint.*;
-import static org.openhab.binding.freeathomesystem.internal.util.FidTranslationUtils.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.freeathomesystem.internal.util.FidTranslationUtils;
-import org.openhab.binding.freeathomesystem.internal.util.FreeAtHomeGeneralException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.JsonObject;
-
-/**
- * The {@link FreeAtHomeDeviceChannel} holding the information of device channels
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeDeviceChannel {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDeviceChannel.class);
-
-    private String channelLabel = "";
-    private String channelId = "";
-    private String channelFunctionID = "";
-
-    private List<FreeAtHomeDatapointGroup> datapointGroups = new ArrayList<>();
-
-    public boolean createChannelFromJson(String deviceLabel, String channelId, JsonObject jsonObjectOfChannels,
-            boolean isScene, boolean isRule) {
-        JsonObject channelObject = jsonObjectOfChannels.getAsJsonObject(channelId);
-
-        channelFunctionID = channelObject.get("functionID").getAsString();
-
-        // check whether this is a valid channel
-        if (channelFunctionID.isEmpty()) {
-            // invalid channel found
-            logger.info("Invalid channel function ID found - Devicelabel: {} Channel: {}", deviceLabel, channelId);
-
-            return false;
-        }
-
-        if (!channelFunctionID.isEmpty()) {
-            channelLabel = channelObject.get("displayName").getAsString();
-
-            if (channelLabel.isEmpty()) {
-                channelLabel = deviceLabel;
-            }
-        }
-
-        if (isScene) {
-            channelFunctionID = channelFunctionID.substring(0, channelFunctionID.length() - 1) + "0";
-        }
-
-        switch (Integer.parseInt(channelFunctionID, 16)) {
-            case FID_PANEL_SWITCH_SENSOR:
-            case FID_SWITCH_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Switch sensor channel found - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_PANEL_DIMMING_SENSOR:
-            case FID_DIMMING_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Dimming sensor channel found - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 17, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_TRIGGER:
-            case FID_SWITCH_ACTUATOR: {
-                this.channelId = channelId;
-
-                logger.debug("Switch actuator channel created - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 1, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_MOVEMENT_DETECTOR_FLEX:
-            case FID_MOVEMENT_DETECTOR: {
-                this.channelId = channelId;
-
-                logger.debug("Movement detector channel found - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 6, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 7, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1027, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT_AS_OUTPUT, 256, channelId,
-                        channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN:
-            case FID_RADIATOR_ACTUATOR_MASTER: {
-                this.channelId = channelId;
-
-                if (Integer.parseInt(channelFunctionID, 16) == FID_RADIATOR_ACTUATOR_MASTER) {
-                    logger.debug("Radiator actuator channel - Channel FID: {}", channelFunctionID);
-                } else {
-                    logger.debug("Room temperature actuator channel - Channel FID: {}", channelFunctionID);
-                }
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 304, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 333, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 331, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 54, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 51, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 320, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 68, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 58, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 56, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 66, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                // Additional channel for RTC device
-                if (Integer.parseInt(channelFunctionID, 16) == FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN) {
-                    newDatapointGroup = new FreeAtHomeDatapointGroup();
-                    newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 48, channelId, channelObject);
-                    datapointGroups.add(newDatapointGroup);
-                }
-
-                break;
-            }
-            case FID_WINDOW_DOOR_POSITION_SENSOR:
-            case FID_WINDOW_DOOR_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Window/Door position sensor channel created - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 53, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 41, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_SCENE_TRIGGER: {
-                this.channelId = channelId;
-
-                logger.debug("Scene trigger channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 4, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_RULE_SWITCH: {
-                this.channelId = channelId;
-
-                logger.debug("Rule channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 61698, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 61697, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_DES_DOOR_OPENER_ACTUATOR: {
-                this.channelId = channelId;
-
-                logger.debug("Door opener actuator channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 2, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_DES_LEVEL_CALL_SENSOR:
-            case FID_DES_DOOR_RINGING_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Door ring sensor channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 2, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_DES_LIGHT_SWITCH_ACTUATOR: {
-                this.channelId = channelId;
-
-                logger.debug("DES light switch channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 2, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_DIMMING_ACTUATOR_FLEX:
-            case FID_DIMMING_ACTUATOR: {
-                this.channelId = channelId;
-
-                logger.debug("Dimming actuator channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 272, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 17, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 256, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 1, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AWNING_ACTUATOR:
-            case FID_ATTIC_WINDOW_ACTUATOR:
-            case FID_BLIND_ACTUATOR:
-            case FID_SHUTTER_ACTUATOR: {
-                this.channelId = channelId;
-
-                logger.debug("Shutter actuator channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 32, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 288, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 33, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 288, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 289, channelId, channelObject);
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.INPUT, 35, channelId, channelObject);
-
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_BRIGHTNESS_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Brightness sensor channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1026, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1027, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_RAIN_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Rain sensor channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 39, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1029, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1030, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_TEMPERATURE_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Temperature sensor channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                if (newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 38, channelId, channelObject)) {
-                    datapointGroups.add(newDatapointGroup);
-                }
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                if (newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1024, channelId, channelObject)) {
-                    datapointGroups.add(newDatapointGroup);
-                }
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                if (newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 304, channelId, channelObject)) {
-                    datapointGroups.add(newDatapointGroup);
-                }
-
-                break;
-            }
-            case FID_WIND_SENSOR: {
-                this.channelId = channelId;
-
-                logger.debug("Wind sensor channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 37, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1025, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1028, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_CO: {
-                this.channelId = channelId;
-
-                logger.debug("AQS CO channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1564, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_CO2: {
-                this.channelId = channelId;
-
-                logger.debug("AQS CO2 channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1563, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_HUMIDITY: {
-                this.channelId = channelId;
-
-                logger.debug("AQS Humidity channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 337, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_PRESSURE: {
-                this.channelId = channelId;
-
-                logger.debug("AQS Pressure channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1562, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_NO2: {
-                this.channelId = channelId;
-
-                logger.debug("AQS NO2 channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1565, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_O3: {
-                this.channelId = channelId;
-
-                logger.debug("AQS O3 channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1566, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_PM10: {
-                this.channelId = channelId;
-
-                logger.debug("AQS PM10 channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1567, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_VOC: {
-                this.channelId = channelId;
-
-                logger.debug("AQS VOC channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1569, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            case FID_AIRQUALITYSENSOR_PM25: {
-                this.channelId = channelId;
-
-                logger.debug("AQS PM25 channel - Channel FID: {}", channelFunctionID);
-
-                FreeAtHomeDatapointGroup newDatapointGroup = new FreeAtHomeDatapointGroup();
-                newDatapointGroup.addDatapointToGroup(DatapointDirection.OUTPUT, 1568, channelId, channelObject);
-                datapointGroups.add(newDatapointGroup);
-
-                break;
-            }
-            default: {
-                logger.debug("Unknown channel found - Channel FID: {}", channelFunctionID);
-
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public String getChannelIdforDatapoint() {
-        return channelId;
-    }
-
-    public String getChannelLabel() {
-        return channelLabel;
-    }
-
-    public String getChannelId() {
-        return channelId;
-    }
-
-    public String getFunctionId() {
-        return channelFunctionID;
-    }
-
-    public @Nullable String getFunctionIdText() throws FreeAtHomeGeneralException {
-        String functionIdText = FidTranslationUtils
-                .getFunctionIdText(String.format("0x%04X", Integer.parseInt(channelFunctionID, 16)));
-        return functionIdText;
-    }
-
-    public int getNumberOfDatapointGroup() {
-        return datapointGroups.size();
-    }
-
-    public FreeAtHomeDatapointGroup getDatapointGroup(int idx) {
-        return datapointGroups.get(idx);
-    }
-
-    public void applyChangesForVirtualDevice() {
-        for (FreeAtHomeDatapointGroup localDatapointGroup : datapointGroups) {
-            localDatapointGroup.applyChangesForVirtualDevice();
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceDescription.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/datamodel/FreeAtHomeDeviceDescription.java
deleted file mode 100644 (file)
index 2b50a83..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.datamodel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-/**
- * The {@link FreeAtHomeDeviceDescription} is responsible for determining the device type
- * based on the received json string
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeDeviceDescription {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDeviceDescription.class);
-
-    // interface strings
-    public static final String DEVICE_INTERFACE_UNKNOWN_TYPE = "unknown";
-    public static final String DEVICE_INTERFACE_WIRELESS_TYPE = "wireless";
-    public static final String DEVICE_INTERFACE_VIRTUAL_TYPE = "virtual";
-    public static final String DEVICE_INTERFACE_WIRED_TYPE = "wired";
-    public static final String DEVICE_INTERFACE_HUE_TYPE = "hue";
-
-    public String deviceLabel = "";
-    public String deviceId = "";
-    public String interfaceType = "";
-    public boolean validDevice = false;
-
-    private boolean sceneIsDetected;
-    private boolean ruleIsDetected;
-
-    public List<FreeAtHomeDeviceChannel> listOfChannels = new ArrayList<>();
-
-    public FreeAtHomeDeviceDescription() {
-        validDevice = false;
-    }
-
-    public FreeAtHomeDeviceDescription(JsonObject jsonObject, String id) {
-        // set the device ID
-        deviceId = id;
-
-        // set the device invalid at first
-        validDevice = false;
-
-        sceneIsDetected = id.toLowerCase().startsWith("ffff48");
-        ruleIsDetected = id.toLowerCase().startsWith("ffff4a");
-
-        JsonObject jsonObjectOfId = jsonObject.getAsJsonObject(id);
-
-        if (jsonObjectOfId == null) {
-            return;
-        }
-
-        JsonElement jsonObjectOfInterface = jsonObjectOfId.get("interface");
-
-        if (jsonObjectOfInterface != null) {
-            String interfaceString = jsonObjectOfInterface.getAsString();
-
-            if (interfaceString.toLowerCase().startsWith("vdev:")) {
-                interfaceType = DEVICE_INTERFACE_VIRTUAL_TYPE;
-            } else if (interfaceString.toLowerCase().startsWith("hue")) {
-                interfaceType = DEVICE_INTERFACE_HUE_TYPE;
-            } else if (interfaceString.toLowerCase().startsWith("rf")) {
-                interfaceType = DEVICE_INTERFACE_WIRELESS_TYPE;
-            } else if (interfaceString.toLowerCase().startsWith("tp")) {
-                interfaceType = DEVICE_INTERFACE_WIRED_TYPE;
-            } else {
-                interfaceType = DEVICE_INTERFACE_UNKNOWN_TYPE;
-            }
-        } else {
-            interfaceType = DEVICE_INTERFACE_UNKNOWN_TYPE;
-        }
-
-        JsonElement jsonObjectOfDeviceLabel = jsonObjectOfId.get("displayName");
-
-        if (jsonObjectOfDeviceLabel == null) {
-            this.deviceLabel = "NoName";
-        } else {
-            this.deviceLabel = jsonObjectOfDeviceLabel.getAsString();
-        }
-
-        if (this.deviceLabel.isEmpty()) {
-            this.deviceLabel = "NoName";
-        }
-
-        JsonObject jsonObjectOfChannels = jsonObjectOfId.getAsJsonObject("channels");
-
-        logger.debug("Detecting device features - device id: {} - device label: {}", this.deviceId, this.deviceLabel);
-
-        if (jsonObjectOfChannels != null) {
-            // Scan channels for functions
-            for (String nextChannel : jsonObjectOfChannels.keySet()) {
-                FreeAtHomeDeviceChannel newChannel = new FreeAtHomeDeviceChannel();
-
-                if (newChannel.createChannelFromJson(deviceLabel, nextChannel, jsonObjectOfChannels, sceneIsDetected,
-                        ruleIsDetected)) {
-                    if (interfaceType == DEVICE_INTERFACE_VIRTUAL_TYPE) {
-                        newChannel.applyChangesForVirtualDevice();
-                    }
-
-                    listOfChannels.add(newChannel);
-                }
-            }
-        }
-    }
-
-    public boolean isRule() {
-        return ruleIsDetected;
-    }
-
-    public boolean isScene() {
-        return sceneIsDetected;
-    }
-
-    public boolean isVirtual() {
-        return interfaceType == DEVICE_INTERFACE_VIRTUAL_TYPE;
-    }
-
-    public int getNumberOfChannels() {
-        return listOfChannels.size();
-    }
-
-    public FreeAtHomeDeviceChannel getChannel(int idx) {
-        return listOfChannels.get(idx);
-    }
-
-    public String getDeviceId() {
-        return deviceId;
-    }
-
-    public String getDeviceLabel() {
-        return deviceLabel;
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeBridgeHandler.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeBridgeHandler.java
deleted file mode 100644 (file)
index 73a7426..0000000
+++ /dev/null
@@ -1,897 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.handler;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.AuthenticationStore;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.util.BasicAuthentication;
-import org.eclipse.jetty.client.util.StringContentProvider;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.eclipse.jetty.websocket.api.Session;
-import org.eclipse.jetty.websocket.api.StatusCode;
-import org.eclipse.jetty.websocket.api.WebSocketListener;
-import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
-import org.eclipse.jetty.websocket.client.WebSocketClient;
-import org.openhab.binding.freeathomesystem.internal.FreeAtHomeSystemDiscoveryService;
-import org.openhab.binding.freeathomesystem.internal.configuration.FreeAtHomeBridgeHandlerConfiguration;
-import org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDeviceDescription;
-import org.openhab.binding.freeathomesystem.internal.util.FreeAtHomeHttpCommunicationException;
-import org.openhab.core.thing.Bridge;
-import org.openhab.core.thing.ChannelUID;
-import org.openhab.core.thing.ThingStatus;
-import org.openhab.core.thing.ThingStatusDetail;
-import org.openhab.core.thing.binding.BaseBridgeHandler;
-import org.openhab.core.thing.binding.ThingHandlerService;
-import org.openhab.core.types.Command;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonParser;
-import com.google.gson.stream.JsonReader;
-
-/**
- * The {@link FreeAtHomeBridgeHandler} is responsible for handling the free@home bridge and
- * its main communication.
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeBridgeHandler extends BaseBridgeHandler implements WebSocketListener {
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeBridgeHandler.class);
-
-    private Map<String, FreeAtHomeDeviceHandler> mapEventListeners = new ConcurrentHashMap<>();
-
-    // Clients for the network communication
-    private HttpClient httpClient;
-    private @Nullable WebSocketClient websocketClient = null;
-    private FreeAtHomeWebsocketMonitorThread socketMonitor = new FreeAtHomeWebsocketMonitorThread();
-    private @Nullable QueuedThreadPool jettyThreadPool = null;
-    private volatile @Nullable Session websocketSession = null;
-
-    private String sysApUID = "00000000-0000-0000-0000-000000000000";
-    private String ipAddress = "";
-    private String username = "";
-    private String password = "";
-
-    private String baseUrl = "";
-
-    private String authField = "";
-
-    private Lock lock = new ReentrantLock();
-    private AtomicBoolean httpConnectionOK = new AtomicBoolean(false);
-    private Condition websocketSessionEstablished = lock.newCondition();
-
-    int numberOfComponents = 0;
-
-    private static final int BRIDGE_WEBSOCKET_RECONNECT_DELAY = 60;
-    private static final int BRIDGE_WEBSOCKET_TIMEOUT = 90;
-    private static final int BRIDGE_WEBSOCKET_KEEPALIVE = 50;
-    private static final String BRIDGE_URL_GETDEVICELIST = "/rest/devicelist";
-
-    public FreeAtHomeBridgeHandler(Bridge thing, HttpClient client) {
-        super(thing);
-
-        httpClient = client;
-    }
-
-    /**
-     * stub method for handlCommand
-     */
-    @Override
-    public void handleCommand(ChannelUID channelUID, Command command) {
-        logger.warn("Unknown handle command for the bridge - channellUID {}, command {}", channelUID, command);
-    }
-
-    @Override
-    public Collection<Class<? extends ThingHandlerService>> getServices() {
-        return List.of(FreeAtHomeSystemDiscoveryService.class);
-    }
-
-    /**
-     * Method to get the device list
-     */
-    public List<String> getDeviceDeviceList() throws FreeAtHomeHttpCommunicationException {
-        List<String> listOfComponentId = new ArrayList<String>();
-        boolean ret = false;
-
-        listOfComponentId.clear();
-
-        String url = baseUrl + BRIDGE_URL_GETDEVICELIST;
-
-        // Perform a simple GET and wait for the response.
-        try {
-            HttpClient client = httpClient;
-
-            Request req = client.newRequest(url);
-
-            if (req == null) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Invalid request object in getDeviceDeviceList with the URL [ " + url + " ]");
-            }
-
-            ContentResponse response = req.send();
-
-            // Get component List
-            String componentListString = new String(response.getContent());
-
-            JsonElement jsonTree = JsonParser.parseString(componentListString);
-
-            // check the output
-            if (!jsonTree.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Invalid jsonObject in getDeviceDeviceList with the URL [ " + url + " ]");
-            }
-
-            JsonObject jsonObject = jsonTree.getAsJsonObject();
-
-            // Get the main object
-            JsonElement listOfComponents = jsonObject.get(sysApUID);
-
-            if (listOfComponents == null) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Devices Section is missing in getDeviceDeviceList with the URL [ " + url + " ]");
-            }
-
-            JsonArray array = listOfComponents.getAsJsonArray();
-
-            this.numberOfComponents = array.size();
-
-            for (int i = 0; i < array.size(); i++) {
-                JsonElement basicElement = array.get(i);
-
-                listOfComponentId.add(basicElement.getAsString());
-            }
-
-            ret = true;
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            logger.debug("Error to build up the Component list [ {} ]", e.getMessage());
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted [ " + e.getMessage() + " ]");
-        } catch (ExecutionException | TimeoutException e) {
-            logger.debug("Error to build up the Component list [ {} ]", e.getMessage());
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted in getDeviceList [ " + e.getMessage() + " ]");
-        }
-
-        // Scan finished but error. clear the list
-        if (!ret) {
-            listOfComponentId.clear();
-        }
-
-        return listOfComponentId;
-    }
-
-    /**
-     * Method to send http request to get the device description
-     */
-    public FreeAtHomeDeviceDescription getFreeatHomeDeviceDescription(String id)
-            throws FreeAtHomeHttpCommunicationException {
-        FreeAtHomeDeviceDescription device = new FreeAtHomeDeviceDescription();
-
-        String url = baseUrl + "/rest/device/" + sysApUID + "/" + id;
-        try {
-            HttpClient client = httpClient;
-            Request req = client.newRequest(url);
-
-            if (req == null) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Invalid request object in getDatapoint with the URL [ " + url + " ]");
-            }
-
-            ContentResponse response;
-            response = req.send();
-
-            // Get component List
-            String deviceString = new String(response.getContent());
-
-            JsonReader reader = new JsonReader(new StringReader(deviceString));
-            reader.setLenient(true);
-            JsonElement jsonTree = JsonParser.parseReader(reader);
-
-            if (!jsonTree.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "No data is received by getDatapoint with the URL [ " + url + " ]");
-            }
-
-            if (!jsonTree.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Invalid jsonObject in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
-            }
-
-            // check the output
-            JsonObject jsonObject = jsonTree.getAsJsonObject();
-
-            if (!jsonObject.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Main jsonObject is invalid in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
-            }
-
-            jsonObject = jsonObject.getAsJsonObject(sysApUID);
-
-            if (!jsonObject.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "jsonObject is invalid in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
-            }
-
-            jsonObject = jsonObject.getAsJsonObject("devices");
-
-            if (!jsonObject.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Devices Section is missing in getFreeatHomeDeviceDescription with the URL [ " + url + " ]");
-            }
-
-            device = new FreeAtHomeDeviceDescription(jsonObject, id);
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            logger.debug("No communication possible to get device list - Communication interrupt [ {} ]",
-                    e.getMessage());
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted [ " + e.getMessage() + " ]");
-        } catch (ExecutionException | TimeoutException e) {
-            logger.debug("No communication possible to get device list - Communication interrupt [ {} ]",
-                    e.getMessage());
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted in getDeviceList [ " + e.getMessage() + " ]");
-        }
-
-        return device;
-    }
-
-    /**
-     * Method to get datapoint values for devices
-     */
-    public String getDatapoint(String deviceId, String channel, String datapoint)
-            throws FreeAtHomeHttpCommunicationException {
-        String url = baseUrl + "/rest/datapoint/" + sysApUID + "/" + deviceId + "." + channel + "." + datapoint;
-
-        try {
-            Request req = httpClient.newRequest(url);
-
-            logger.debug("Get datapoint by url: {}", url);
-
-            if (req == null) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Invalid request object in getDatapoint with the URL [ " + url + " ]");
-            }
-
-            ContentResponse response = req.send();
-
-            if (response.getStatus() != 200) {
-                throw new FreeAtHomeHttpCommunicationException(response.getStatus(), response.getReason());
-            }
-
-            String deviceString = new String(response.getContent());
-
-            JsonReader reader = new JsonReader(new StringReader(deviceString));
-            reader.setLenient(true);
-            JsonElement jsonTree = JsonParser.parseReader(reader);
-
-            if (!jsonTree.isJsonObject()) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "No data is received by getDatapoint with the URL [ " + url + " ]");
-            }
-
-            JsonObject jsonObject = jsonTree.getAsJsonObject();
-
-            jsonObject = jsonObject.getAsJsonObject(sysApUID);
-            JsonArray jsonValueArray = jsonObject.getAsJsonArray("values");
-
-            JsonElement element = jsonValueArray.get(0);
-            String value = element.getAsString();
-
-            if (value.isEmpty()) {
-                value = "0";
-            }
-
-            return value;
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted [ " + e.getMessage() + " ]");
-        } catch (ExecutionException | TimeoutException e) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication timout or execution interrupted [ " + e.getMessage() + " ]");
-        } catch (JsonParseException e) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Invalid JSON file is received by getDatapoint with the URL [ " + e.getMessage() + " ]");
-        }
-    }
-
-    /**
-     * Method to set datapoint values in channels
-     */
-    public boolean setDatapoint(String deviceId, String channel, String datapoint, String valueString)
-            throws FreeAtHomeHttpCommunicationException {
-        String url = baseUrl + "/rest/datapoint/" + sysApUID + "/" + deviceId + "." + channel + "." + datapoint;
-
-        try {
-            Request req = httpClient.newRequest(url);
-
-            if (req == null) {
-                throw new FreeAtHomeHttpCommunicationException(0,
-                        "Invalid request object in getDatapoint with the URL [ " + url + " ]");
-            }
-
-            req.content(new StringContentProvider(valueString));
-            req.method(HttpMethod.PUT);
-
-            logger.debug("Set datapoint by url: {} value: {}", url, valueString);
-
-            ContentResponse response = req.send();
-
-            if (response.getStatus() != 200) {
-                throw new FreeAtHomeHttpCommunicationException(response.getStatus(), response.getReason());
-            }
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted [ " + e.getMessage() + " ]");
-        } catch (ExecutionException | TimeoutException e) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-
-            throw new FreeAtHomeHttpCommunicationException(0,
-                    "Http communication interrupted [ " + e.getMessage() + " ]");
-        }
-
-        return true;
-    }
-
-    /**
-     * Method to process socket events
-     */
-    public void setDatapointOnWebsocketFeedback(String receivedText) {
-        JsonReader reader = new JsonReader(new StringReader(receivedText));
-        reader.setLenient(true);
-        JsonElement jsonTree = JsonParser.parseReader(reader);
-
-        // check the output
-        if (jsonTree.isJsonObject()) {
-            JsonObject jsonObject = jsonTree.getAsJsonObject();
-
-            jsonObject = jsonObject.getAsJsonObject(sysApUID);
-            jsonObject = jsonObject.getAsJsonObject("datapoints");
-
-            Set<String> keys = jsonObject.keySet();
-
-            Iterator<String> iter = keys.iterator();
-
-            while (iter.hasNext()) {
-                String eventDatapointID = iter.next();
-
-                JsonElement element = jsonObject.get(eventDatapointID);
-                String value = element.getAsString();
-
-                String[] parts = eventDatapointID.split("/");
-
-                FreeAtHomeDeviceHandler deviceHandler = mapEventListeners.get(parts[0]);
-
-                if (deviceHandler != null) {
-                    deviceHandler.onDeviceStateChanged(eventDatapointID, value);
-                }
-
-                logger.debug("Socket event processed: event-datapoint-ID {} value {}", eventDatapointID, value);
-            }
-        }
-    }
-
-    public void markDeviceRemovedOnWebsocketFeedback(String receivedText) {
-        JsonReader reader = new JsonReader(new StringReader(receivedText));
-        reader.setLenient(true);
-        JsonElement jsonTree = JsonParser.parseReader(reader);
-
-        // check the output
-        if (jsonTree.isJsonObject()) {
-            JsonObject jsonObject = jsonTree.getAsJsonObject();
-
-            jsonObject = jsonObject.getAsJsonObject(sysApUID);
-            JsonArray jsonArray = jsonObject.getAsJsonArray("devicesRemoved");
-
-            for (JsonElement element : jsonArray) {
-                FreeAtHomeDeviceHandler deviceHandler = mapEventListeners.get(element.getAsString());
-
-                if (deviceHandler != null) {
-                    deviceHandler.onDeviceRemoved();
-
-                    logger.debug("Device removal processed");
-                }
-            }
-        }
-    }
-
-    public void registerDeviceStateListener(String deviceID, FreeAtHomeDeviceHandler deviceHandler) {
-        mapEventListeners.put(deviceID, deviceHandler);
-    }
-
-    public void unregisterDeviceStateListener(String deviceID) {
-        mapEventListeners.remove(deviceID);
-    }
-
-    /**
-     * Method to open Http connection
-     */
-    public boolean openHttpConnection() {
-        boolean ret = false;
-
-        try {
-            // Add authentication credentials.
-            AuthenticationStore auth = httpClient.getAuthenticationStore();
-
-            URI uri1 = new URI(baseUrl);
-            auth.addAuthenticationResult(new BasicAuthentication.BasicResult(uri1, username, password));
-
-            String url = baseUrl + BRIDGE_URL_GETDEVICELIST;
-
-            Request req = httpClient.newRequest(url);
-            ContentResponse res = req.send();
-
-            // check status
-            if (res.getStatus() == HttpStatus.OK_200) {
-                // response OK
-                httpConnectionOK.set(true);
-
-                ret = true;
-
-                logger.debug("HTTP connection to SysAP is OK");
-            } else {
-                // response NOK, set error
-                httpConnectionOK.set(false);
-
-                ret = false;
-            }
-        } catch (URISyntaxException | InterruptedException | ExecutionException | TimeoutException ex) {
-            logger.debug("Initial HTTP connection to SysAP is not successful");
-
-            ret = false;
-        }
-
-        return ret;
-    }
-
-    /**
-     * Method to connect the websocket session
-     */
-    public boolean connectWebsocketSession() {
-        boolean ret = false;
-
-        URI uri = URI.create("ws://" + ipAddress + "/fhapi/v1/api/ws");
-
-        String authString = username + ":" + password;
-
-        // create base64 encoder
-        Base64.Encoder bas64Encoder = Base64.getEncoder();
-
-        // Encoding string using encoder object
-        String authStringEnc = bas64Encoder.encodeToString(authString.getBytes());
-
-        authField = "Basic " + authStringEnc;
-
-        WebSocketClient localWebsocketClient = websocketClient;
-
-        try {
-            // Start socket client
-            if (localWebsocketClient != null) {
-                localWebsocketClient.setMaxTextMessageBufferSize(8 * 1024);
-                localWebsocketClient.setMaxIdleTimeout(BRIDGE_WEBSOCKET_TIMEOUT * 60 * 1000);
-                localWebsocketClient.setConnectTimeout(BRIDGE_WEBSOCKET_TIMEOUT * 60 * 1000);
-                localWebsocketClient.start();
-                ClientUpgradeRequest request = new ClientUpgradeRequest();
-                request.setHeader("Authorization", authField);
-                request.setTimeout(BRIDGE_WEBSOCKET_TIMEOUT, TimeUnit.MINUTES);
-                localWebsocketClient.connect(this, uri, request);
-
-                logger.debug("Websocket connection to SysAP is OK, timeout: {}", BRIDGE_WEBSOCKET_TIMEOUT);
-
-                ret = true;
-            } else {
-                ret = false;
-            }
-        } catch (Exception e) {
-            logger.debug("Error by opening Websocket connection [{}]", e.getMessage());
-
-            if (localWebsocketClient != null) {
-                try {
-                    localWebsocketClient.stop();
-
-                    ret = false;
-                } catch (Exception e1) {
-                    logger.debug("Error by opening Websocket connection [{}]", e1.getMessage());
-
-                    ret = false;
-                }
-            } else {
-                ret = false;
-            }
-        }
-
-        return ret;
-    }
-
-    /**
-     * Method to close the websocket connection
-     */
-    public void closeWebSocketConnection() {
-        socketMonitor.interrupt();
-
-        QueuedThreadPool localThreadPool = jettyThreadPool;
-
-        if (localThreadPool != null) {
-            try {
-                localThreadPool.stop();
-            } catch (Exception e1) {
-                logger.debug("Error by closing Websocket connection [{}]", e1.getMessage());
-            }
-            jettyThreadPool = null;
-        }
-
-        WebSocketClient localWebSocketClient = websocketClient;
-
-        if (localWebSocketClient != null) {
-            try {
-                localWebSocketClient.stop();
-            } catch (Exception e2) {
-                logger.debug("Error by closing Websocket connection [{}]", e2.getMessage());
-            }
-            websocketClient = null;
-        }
-    }
-
-    /**
-     * Method to open the websocket connection
-     */
-    public boolean openWebSocketConnection() {
-        boolean ret = false;
-
-        QueuedThreadPool localThreadPool = jettyThreadPool;
-
-        if (localThreadPool == null) {
-            jettyThreadPool = new QueuedThreadPool();
-
-            localThreadPool = jettyThreadPool;
-
-            if (localThreadPool != null) {
-                localThreadPool.setName(FreeAtHomeBridgeHandler.class.getSimpleName());
-                localThreadPool.setDaemon(true);
-                localThreadPool.setStopTimeout(0);
-
-                ret = true;
-            }
-        }
-
-        WebSocketClient localWebSocketClient = websocketClient;
-
-        if (localWebSocketClient == null) {
-            websocketClient = new WebSocketClient(httpClient);
-
-            localWebSocketClient = websocketClient;
-
-            if (localWebSocketClient != null) {
-                localWebSocketClient.setExecutor(jettyThreadPool);
-
-                socketMonitor.start();
-
-                ret = true;
-            } else {
-                ret = false;
-            }
-        } else {
-            ret = true;
-        }
-
-        return ret;
-    }
-
-    /**
-     * Method to initialize the bridge
-     */
-    @Override
-    public void initialize() {
-        httpConnectionOK.set(false);
-
-        // load configuration
-        FreeAtHomeBridgeHandlerConfiguration locConfig = getConfigAs(FreeAtHomeBridgeHandlerConfiguration.class);
-
-        ipAddress = locConfig.ipAddress;
-        if (ipAddress.isBlank()) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.ip-address-missing");
-            return;
-        }
-
-        password = locConfig.password;
-        if (password.isBlank()) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.password-missing");
-            return;
-        }
-
-        username = locConfig.username;
-        if (username.isBlank()) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.username-missing");
-            return;
-        }
-
-        // build base URL
-        baseUrl = "http://" + ipAddress + "/fhapi/v1/api";
-
-        updateStatus(ThingStatus.UNKNOWN);
-
-        scheduler.execute(() -> {
-            boolean thingReachable = true;
-
-            // Open Http connection
-            if (!openHttpConnection()) {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                        "@text/comm-error.http-wrongpass-or-ip");
-
-                thingReachable = false;
-            }
-
-            // Open the websocket connection for immediate status updates
-            if (!openWebSocketConnection()) {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                        "@text/comm-error.not-able-open-websocketconnection");
-
-                thingReachable = false;
-            }
-
-            if (thingReachable) {
-                updateStatus(ThingStatus.ONLINE);
-            }
-        });
-    }
-
-    /**
-     * Method to dispose
-     */
-    @Override
-    public void dispose() {
-        // let run out the thread
-        socketMonitor.interrupt();
-
-        closeWebSocketConnection();
-    }
-
-    /**
-     * Thread that maintains connection via Websocket.
-     */
-    private class FreeAtHomeWebsocketMonitorThread extends Thread {
-
-        // initial delay to initiate connection
-        private AtomicInteger reconnectDelay = new AtomicInteger();
-
-        public FreeAtHomeWebsocketMonitorThread() {
-        }
-
-        @Override
-        public void run() {
-            // set initial connect delay to 0
-            reconnectDelay.set(0);
-
-            try {
-                while (!isInterrupted()) {
-                    if (httpConnectionOK.get()) {
-                        if (connectSession()) {
-                            while (isSocketConnectionAlive()) {
-                                TimeUnit.SECONDS.sleep(BRIDGE_WEBSOCKET_KEEPALIVE);
-
-                                logger.debug("Sending keep-alive message {}", System.currentTimeMillis());
-                                sendWebsocketKeepAliveMessage("keep-alive");
-                            }
-                        }
-                        logger.debug("Socket connection closed");
-                        reconnectDelay.set(BRIDGE_WEBSOCKET_RECONNECT_DELAY);
-                    } else {
-                        TimeUnit.SECONDS.sleep(BRIDGE_WEBSOCKET_RECONNECT_DELAY);
-                    }
-                }
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                        "@text/comm-error.general-websocket-issue");
-            } catch (IOException e) {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                        "@text/comm-error.websocket-keep-alive-error");
-            }
-        }
-
-        private boolean connectSession() throws InterruptedException {
-            int delay = reconnectDelay.get();
-
-            if (delay > 0) {
-                logger.debug("Delaying (re)connect request by {} seconds.", reconnectDelay);
-                TimeUnit.SECONDS.sleep(delay);
-            }
-
-            logger.debug("Server connecting to websocket");
-
-            if (!connectWebsocketSession()) {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                        "@text/comm-error.general-websocket-issue");
-
-                reconnectDelay.set(BRIDGE_WEBSOCKET_RECONNECT_DELAY);
-
-                return false;
-            }
-
-            if (websocketSession == null) {
-                lock.lock();
-                try {
-                    websocketSessionEstablished.await();
-                } finally {
-                    lock.unlock();
-                }
-            }
-
-            return true;
-        }
-    }
-
-    /**
-     * Send keep-alive message to SysAp
-     */
-    public void sendWebsocketKeepAliveMessage(String message) throws IOException {
-        Session localSession = websocketSession;
-
-        if (localSession != null) {
-            localSession.getRemote().sendString(message);
-        }
-    }
-
-    /**
-     * Get socket alive state
-     * 
-     * @throws InterruptedException
-     */
-    public boolean isSocketConnectionAlive() throws InterruptedException {
-        Session localSession = websocketSession;
-
-        return (localSession != null) ? localSession.isOpen() : false;
-    }
-
-    /**
-     * Socket closed. Report the state
-     */
-    @Override
-    public void onWebSocketClose(int statusCode, @Nullable String reason) {
-        websocketSession = null;
-        logger.debug("Socket Closed: [ {} ] {}", statusCode, reason);
-    }
-
-    /**
-     * Socket connected. store the session for later use
-     */
-    @Override
-    public void onWebSocketConnect(@Nullable Session session) {
-        Session localSession = session;
-
-        if (localSession != null) {
-            websocketSession = localSession;
-
-            localSession.setIdleTimeout(-1);
-
-            logger.debug("Socket Connected - Timeout {} - sesson: {}", localSession.getIdleTimeout(), session);
-        } else {
-            logger.debug("Socket Connected - Timeout (invalid) - sesson: (invalid)");
-        }
-
-        lock.lock();
-        try {
-            websocketSessionEstablished.signal();
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Error caused. Report the state
-     */
-    @Override
-    public void onWebSocketError(@Nullable Throwable cause) {
-        websocketSession = null;
-
-        if (cause != null) {
-            logger.debug("Socket Error: {}", cause.getLocalizedMessage());
-        } else {
-            logger.debug("Socket Error: unknown");
-        }
-    }
-
-    /**
-     * Binary message received. It shall not happen with the free@home SysAp
-     */
-    @Override
-    @NonNullByDefault({})
-    public void onWebSocketBinary(byte[] payload, int offset, int len) {
-        logger.debug("Binary message received via websocket");
-    }
-
-    /**
-     * Text message received. Processing will be started
-     */
-    @Override
-    public void onWebSocketText(@Nullable String message) {
-        if (message != null) {
-            if (message.toLowerCase(Locale.US).contains("bye")) {
-                Session localSession = websocketSession;
-
-                if (localSession != null) {
-                    localSession.close(StatusCode.NORMAL, "Thanks");
-                }
-
-                logger.debug("Websocket connection closed: {} ", message);
-            } else {
-                logger.debug("Received websocket text: {} ", message);
-
-                setDatapointOnWebsocketFeedback(message);
-
-                markDeviceRemovedOnWebsocketFeedback(message);
-            }
-        } else {
-            logger.debug("Invalid message string");
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceHandler.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceHandler.java
deleted file mode 100644 (file)
index b5a6d64..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.handler;
-
-import java.math.BigDecimal;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.freeathomesystem.internal.configuration.FreeAtHomeDeviceHandlerConfiguration;
-import org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDatapoint;
-import org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDatapointGroup;
-import org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDeviceChannel;
-import org.openhab.binding.freeathomesystem.internal.datamodel.FreeAtHomeDeviceDescription;
-import org.openhab.binding.freeathomesystem.internal.type.FreeAtHomeChannelTypeProvider;
-import org.openhab.binding.freeathomesystem.internal.util.FreeAtHomeGeneralException;
-import org.openhab.binding.freeathomesystem.internal.util.FreeAtHomeHttpCommunicationException;
-import org.openhab.binding.freeathomesystem.internal.util.UidUtils;
-import org.openhab.binding.freeathomesystem.internal.valuestateconverter.ValueStateConverter;
-import org.openhab.core.i18n.LocaleProvider;
-import org.openhab.core.i18n.TranslationProvider;
-import org.openhab.core.library.types.StopMoveType;
-import org.openhab.core.library.types.StringType;
-import org.openhab.core.thing.Bridge;
-import org.openhab.core.thing.Channel;
-import org.openhab.core.thing.ChannelUID;
-import org.openhab.core.thing.Thing;
-import org.openhab.core.thing.ThingStatus;
-import org.openhab.core.thing.ThingStatusDetail;
-import org.openhab.core.thing.ThingUID;
-import org.openhab.core.thing.binding.BaseThingHandler;
-import org.openhab.core.thing.binding.ThingHandler;
-import org.openhab.core.thing.binding.builder.ChannelBuilder;
-import org.openhab.core.thing.binding.builder.ThingBuilder;
-import org.openhab.core.thing.type.AutoUpdatePolicy;
-import org.openhab.core.thing.type.ChannelKind;
-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.RefreshType;
-import org.openhab.core.types.State;
-import org.openhab.core.types.StateDescriptionFragmentBuilder;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The {@link FreeAtHomeDeviceHandler} is responsible for handling the generic free@home device main communication
- * and thing updates
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeDeviceHandler extends BaseThingHandler implements FreeAtHomeDeviceStateListener {
-
-    private static final String CHANNEL_URI = "channel-type:freeathomesystem:config";
-
-    private final Logger logger = LoggerFactory.getLogger(FreeAtHomeDeviceHandler.class);
-    private FreeAtHomeDeviceDescription device = new FreeAtHomeDeviceDescription();
-    private FreeAtHomeChannelTypeProvider channelTypeProvider;
-    private TranslationProvider i18nProvider;
-    private Locale locale;
-    private Bundle bundle;
-
-    private Map<ChannelUID, FreeAtHomeDatapointGroup> mapChannelUID = new HashMap<ChannelUID, FreeAtHomeDatapointGroup>();
-    private Map<String, ChannelUID> mapEventToChannelUID = new HashMap<String, ChannelUID>();
-
-    public FreeAtHomeDeviceHandler(Thing thing, FreeAtHomeChannelTypeProvider channelTypeProvider,
-            TranslationProvider i18nProvider, LocaleProvider localeProvider) {
-        super(thing);
-
-        this.channelTypeProvider = channelTypeProvider;
-        this.i18nProvider = i18nProvider;
-        this.bundle = FrameworkUtil.getBundle(getClass());
-        this.locale = localeProvider.getLocale();
-    }
-
-    @Override
-    public void initialize() {
-        updateStatus(ThingStatus.UNKNOWN);
-
-        scheduler.execute(() -> {
-            FreeAtHomeDeviceHandlerConfiguration config = getConfigAs(FreeAtHomeDeviceHandlerConfiguration.class);
-
-            Bridge bridge = this.getBridge();
-            String locDeviceId = config.deviceId;
-
-            if (bridge != null) {
-                ThingHandler handler = bridge.getHandler();
-
-                if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
-                    if (!locDeviceId.isBlank()) {
-                        try {
-                            device = bridgeHandler.getFreeatHomeDeviceDescription(locDeviceId);
-
-                            updateChannels();
-                        } catch (FreeAtHomeHttpCommunicationException e) {
-                            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                                    "@text/comm-error.error-in-sysap-com");
-                        } catch (FreeAtHomeGeneralException e) {
-                            logger.debug("General error in the binding - during initialization {}",
-                                    device.getDeviceId());
-
-                            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                                    "@text/conf-error.general-binding-error");
-                        }
-
-                        // register device for status updates
-                        bridgeHandler.registerDeviceStateListener(device.getDeviceId(), this);
-
-                        updateStatus(ThingStatus.ONLINE);
-
-                        logger.debug("Device created - device id: {}", device.getDeviceId());
-                    } else {
-                        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                                "@text/conf-error.invalid-deviceconfig");
-
-                        logger.debug("Device cannot be created: device ID is null!");
-                    }
-                }
-            } else {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
-                        "@text/conf-error.bridge-not-configured");
-
-                logger.debug("Device cannot be created: no bridge is configured!");
-                return;
-            }
-        });
-    }
-
-    @Override
-    public void dispose() {
-        Bridge bridge = this.getBridge();
-
-        // Unregister device and specific channel for event based state updated
-        if (bridge != null) {
-            ThingHandler handler = bridge.getHandler();
-
-            if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
-                bridgeHandler.unregisterDeviceStateListener(device.getDeviceId());
-            }
-        }
-
-        // Remove mapping tables
-        mapChannelUID.clear();
-
-        mapEventToChannelUID.clear();
-
-        logger.debug("Device removed - device id: {}", device.getDeviceId());
-    }
-
-    private void handleRefreshCommand(FreeAtHomeBridgeHandler freeAtHomeBridge, FreeAtHomeDatapointGroup dpg,
-            ChannelUID channelUID) {
-        String valueStr = "0";
-        String channelID = "ch000";
-        String datapointID = "0";
-
-        // Check whether it is a INPUT only datapoint group
-
-        if (dpg.getDirection() == FreeAtHomeDatapointGroup.DatapointGroupDirection.INPUT) {
-            FreeAtHomeDatapoint datapoint = dpg.getInputDatapoint();
-
-            if (datapoint != null) {
-                channelID = datapoint.channelId;
-                datapointID = datapoint.getDatapointId();
-            }
-        } else {
-            FreeAtHomeDatapoint datapoint = dpg.getOutputDatapoint();
-
-            if (datapoint != null) {
-                channelID = datapoint.channelId;
-                datapointID = datapoint.getDatapointId();
-            }
-        }
-
-        try {
-            valueStr = freeAtHomeBridge.getDatapoint(device.getDeviceId(), channelID, datapointID);
-
-            ValueStateConverter vsc = dpg.getValueStateConverter();
-
-            updateState(channelUID, vsc.convertToState(valueStr));
-        } catch (FreeAtHomeHttpCommunicationException e) {
-            logger.debug("Communication error during refresh command {} - at channel {} - Error string {}",
-                    device.getDeviceId(), channelUID.getAsString(), e.getMessage());
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-        } catch (FreeAtHomeGeneralException e) {
-            logger.debug("General error in the binding - during REFRESH command {} - at channel {} - Error string {}",
-                    device.getDeviceId(), channelUID.getAsString(), e.getMessage());
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.general-binding-error");
-        }
-    }
-
-    private void handleSetCommand(FreeAtHomeBridgeHandler freeAtHomeBridge, FreeAtHomeDatapointGroup dpg,
-            ChannelUID channelUID, Command command) {
-        State state = null;
-        String valueString = "0";
-
-        // initial error handling. look for the data point group validity
-        FreeAtHomeDatapoint datapoint = dpg.getInputDatapoint();
-
-        if (datapoint == null) {
-            logger.debug("Invalid parameter in handleSetCommand - DeviceId - {} - at channel {}", device.getDeviceId(),
-                    channelUID.getAsString());
-
-            return;
-        }
-
-        try {
-            ValueStateConverter vsc = dpg.getValueStateConverter();
-
-            if (command instanceof StopMoveType) {
-                valueString = "0";
-            } else {
-                state = ((State) command);
-                valueString = vsc.convertToValueString(state);
-            }
-
-            freeAtHomeBridge.setDatapoint(device.getDeviceId(), datapoint.channelId, datapoint.getDatapointId(),
-                    valueString);
-
-            if (!device.isScene()) {
-                if (state != null) {
-                    updateState(channelUID, state);
-                } else {
-                    updateState(channelUID, new StringType("STOP"));
-                }
-            }
-        } catch (FreeAtHomeHttpCommunicationException e) {
-            logger.debug(
-                    "Communication error during set command {} - at channel {} - full command {} - Error string {}",
-                    device.getDeviceId(), channelUID.getAsString(), command.toFullString(), e.getMessage());
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-        } catch (FreeAtHomeGeneralException e) {
-            logger.debug("General error in the binding - during SET command {} - at channel {} - Error string {}",
-                    device.getDeviceId(), channelUID.getAsString(), e.getMessage());
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.general-binding-error");
-        }
-    }
-
-    @Override
-    public void handleCommand(ChannelUID channelUID, Command command) {
-        FreeAtHomeBridgeHandler freeAtHomeBridge = null;
-
-        Bridge bridge = this.getBridge();
-
-        if (bridge != null) {
-            ThingHandler handler = bridge.getHandler();
-
-            if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
-                freeAtHomeBridge = bridgeHandler;
-            }
-        }
-
-        if (freeAtHomeBridge != null) {
-            updateStatus(ThingStatus.ONLINE);
-        } else {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
-                    "@text/conf-error.invalid-bridge");
-            return;
-        }
-
-        FreeAtHomeDatapointGroup dpg = mapChannelUID.get(channelUID);
-
-        // is the datapointgroup invalid
-        if (dpg == null) {
-            logger.debug("Handle command for device (but invalid datapointgroup) {} - at channel {} - full command {}",
-                    device.getDeviceId(), channelUID.getAsString(), command.toFullString());
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.invalid-deviceconfig");
-        } else {
-            if (command instanceof RefreshType) {
-                handleRefreshCommand(freeAtHomeBridge, dpg, channelUID);
-            } else {
-                handleSetCommand(freeAtHomeBridge, dpg, channelUID, command);
-            }
-
-            logger.debug("Handle command for device {} - at channel {} - full command {}", device.getDeviceId(),
-                    channelUID.getAsString(), command.toFullString());
-        }
-    }
-
-    public void onDeviceRemoved() {
-        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.GONE);
-    }
-
-    public void onDeviceStateChanged(String event, String valueString) {
-        // Get the channle UID belonging to this event
-        ChannelUID channelUID = mapEventToChannelUID.get(event);
-
-        try {
-            if (channelUID != null) {
-                // get the value State Converter for the channel
-                FreeAtHomeDatapointGroup dpg = mapChannelUID.get(channelUID);
-
-                if (dpg != null) {
-                    State state;
-                    state = dpg.getValueStateConverter().convertToState(valueString);
-
-                    // Handle state change
-                    handleEventBasedUpdate(channelUID, state);
-
-                    // if it is virtual device, give a feedback to free@home also
-                    if (isThingHandlesVirtualDevice()) {
-                        feedbackForVirtualDevice(channelUID, valueString);
-                    }
-                }
-            }
-        } catch (FreeAtHomeGeneralException e) {
-            logger.debug("General error in the binding during onDeviceStateChange");
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.general-binding-error");
-        }
-    }
-
-    private void handleEventBasedUpdate(ChannelUID channelUID, State state) {
-        this.updateState(channelUID, state);
-    }
-
-    private void feedbackForVirtualDevice(ChannelUID channelUID, String valueString) {
-        FreeAtHomeBridgeHandler freeAtHomeBridge = null;
-
-        FreeAtHomeDatapointGroup dpg = mapChannelUID.get(channelUID);
-
-        Bridge bridge = this.getBridge();
-
-        if (bridge != null) {
-            ThingHandler handler = bridge.getHandler();
-
-            if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
-                freeAtHomeBridge = bridgeHandler;
-            }
-        }
-
-        if (freeAtHomeBridge == null) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "@text/gen-error.no-bridge-avail");
-            return;
-        }
-
-        if (dpg == null) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.datapointgroup-invalid");
-            return;
-        }
-
-        FreeAtHomeDatapoint inputDatapoint = dpg.getInputDatapoint();
-
-        if (inputDatapoint == null) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                    "@text/conf-error.inputdatapoint-invalid");
-            return;
-        }
-
-        if ((dpg.getDirection() != FreeAtHomeDatapointGroup.DatapointGroupDirection.INPUT)
-                || (dpg.getDirection() != FreeAtHomeDatapointGroup.DatapointGroupDirection.INPUTOUTPUT)) {
-            logger.debug("Handle feedback for virtual device {} - at channel {} - but wrong config",
-                    device.getDeviceId(), channelUID.getAsString());
-        }
-
-        try {
-            freeAtHomeBridge.setDatapoint(device.getDeviceId(), inputDatapoint.channelId,
-                    inputDatapoint.getDatapointId(), valueString);
-
-            updateStatus(ThingStatus.ONLINE);
-
-            logger.debug("Handle feedback for virtual device {} - at channel {} - value {}", device.getDeviceId(),
-                    channelUID.getAsString(), valueString);
-        } catch (FreeAtHomeHttpCommunicationException e) {
-            logger.debug("Communication error during set command {} - at channel {} - value {} - Error string {}",
-                    device.getDeviceId(), channelUID.getAsString(), valueString, e.getMessage());
-
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.not-able-open-httpconnection");
-        }
-    }
-
-    public ChannelTypeUID createChannelTypeForDatapointgroup(FreeAtHomeDatapointGroup dpg,
-            ChannelTypeUID channelTypeUID) throws FreeAtHomeGeneralException {
-        StateDescriptionFragmentBuilder stateFragment = StateDescriptionFragmentBuilder.create();
-
-        stateFragment.withReadOnly(dpg.isReadOnly());
-        stateFragment.withPattern(dpg.getTypePattern());
-
-        if (dpg.isDecimal() || dpg.isInteger()) {
-            BigDecimal min = new BigDecimal(dpg.getMin());
-            BigDecimal max = new BigDecimal(dpg.getMax());
-            stateFragment.withMinimum(min).withMaximum(max);
-        }
-
-        try {
-            URI configDescriptionUriChannel = new URI(CHANNEL_URI);
-
-            ChannelTypeBuilder<?> channelTypeBuilder = ChannelTypeBuilder
-                    .state(channelTypeUID,
-                            String.format("%s-%s-%s-%s", dpg.getLabel(), dpg.getOpenHabItemType(),
-                                    dpg.getOpenHabCategory(), "type"),
-                            dpg.getOpenHabItemType())
-                    .withCategory(dpg.getOpenHabCategory()).withStateDescriptionFragment(stateFragment.build());
-
-            ChannelType channelType = channelTypeBuilder.isAdvanced(false)
-                    .withConfigDescriptionURI(configDescriptionUriChannel)
-                    .withDescription(String.format("Type for channel - %s ", dpg.getLabel())).build();
-
-            channelTypeProvider.addChannelType(channelType);
-
-            logger.debug("Channel type created {} - label: {} - category: {}", channelTypeUID.getAsString(),
-                    dpg.getLabel(), dpg.getOpenHabCategory());
-        } catch (URISyntaxException e) {
-            logger.debug("Channel config URI cannot created for datapoint - datapoint group: {}", dpg.getLabel());
-        }
-
-        return channelTypeUID;
-    }
-
-    public void updateChannels() throws FreeAtHomeGeneralException {
-        // define update policy
-        AutoUpdatePolicy policy = AutoUpdatePolicy.DEFAULT;
-
-        if (device.isScene()) {
-            policy = AutoUpdatePolicy.VETO;
-        }
-
-        // Initialize channels
-        List<Channel> thingChannels = new ArrayList<>(this.getThing().getChannels());
-
-        if (thingChannels.isEmpty()) {
-            ThingBuilder thingBuilder = editThing();
-
-            ThingUID thingUID = thing.getUID();
-
-            for (int i = 0; i < device.getNumberOfChannels(); i++) {
-                FreeAtHomeDeviceChannel channel = device.getChannel(i);
-
-                for (int j = 0; j < channel.getNumberOfDatapointGroup(); j++) {
-                    FreeAtHomeDatapointGroup dpg = channel.getDatapointGroup(j);
-                    Map<String, String> channelProps = new HashMap<>();
-
-                    FreeAtHomeDatapoint inputDatapoint = dpg.getInputDatapoint();
-                    FreeAtHomeDatapoint outputDatapoint = dpg.getOutputDatapoint();
-
-                    if (inputDatapoint != null) {
-                        channelProps.put("input", inputDatapoint.getDatapointId());
-                    }
-
-                    if (outputDatapoint != null) {
-                        channelProps.put("output", outputDatapoint.getDatapointId());
-                    }
-
-                    ChannelTypeUID channelTypeUID = UidUtils.generateChannelTypeUID(dpg.getValueType(),
-                            dpg.isReadOnly());
-
-                    if (channelTypeProvider.getChannelType(channelTypeUID, null) == null) {
-                        channelTypeUID = createChannelTypeForDatapointgroup(dpg, channelTypeUID);
-                    }
-
-                    ChannelUID channelUID = new ChannelUID(thingUID, channel.getChannelId(),
-                            dpg.getLabel().substring(4));
-
-                    String channelLabel = String.format("%s",
-                            i18nProvider.getText(bundle, dpg.getLabel(), "-", locale));
-
-                    String channelDescription = String.format("(%s) %s", channel.getChannelLabel(),
-                            i18nProvider.getText(bundle, dpg.getDescription(), "-", locale));
-
-                    Channel thingChannel = ChannelBuilder.create(channelUID)
-                            .withAcceptedItemType(dpg.getOpenHabItemType()).withKind(ChannelKind.STATE)
-                            .withProperties(channelProps).withLabel(capitalizeWordsInLabel(channelLabel))
-                            .withDescription(channelDescription).withType(channelTypeUID).withAutoUpdatePolicy(policy)
-                            .build();
-                    thingChannels.add(thingChannel);
-
-                    logger.debug("Thing channel created - device: {} - channelUID: {} - channel label: {}",
-                            device.getDeviceId() + device.getDeviceLabel(), channelUID.getAsString(), channelLabel);
-
-                    // in case of output channel, register it for updates
-                    if (outputDatapoint != null) {
-                        String eventDatapointID = new String(device.getDeviceId() + "/" + channel.getChannelId() + "/"
-                                + outputDatapoint.getDatapointId());
-
-                        mapEventToChannelUID.put(eventDatapointID, channelUID);
-                    }
-
-                    // add the datapoint group to the mapping channel
-                    mapChannelUID.put(channelUID, dpg);
-
-                    if (dpg.getInputDatapoint() == null) {
-                        logger.debug(
-                                "Thing channel registered - device:  {} - channelUID: {} - channel label: {} - category: {}",
-                                device.getDeviceId() + device.getDeviceLabel(), channelUID.getAsString(),
-                                dpg.getLabel(), dpg.getOpenHabCategory());
-                    } else {
-                        logger.debug(
-                                "Thing channel registered - device: {} - channelUID: {} - channel label: {} - category: {}",
-                                device.getDeviceId() + device.getDeviceLabel(), channelUID.getAsString(),
-                                dpg.getLabel(), dpg.getOpenHabCategory());
-                    }
-                }
-
-                thingBuilder.withChannels(thingChannels);
-
-                updateThing(thingBuilder.build());
-            }
-        } else {
-            reloadChannelTypes();
-        }
-
-        thingChannels.forEach(channel -> {
-            if (isLinked(channel.getUID())) {
-                channelLinked(channel.getUID());
-            }
-        });
-    }
-
-    private void reloadChannelTypes() throws FreeAtHomeGeneralException {
-        Bridge bridge = this.getBridge();
-
-        ThingUID thingUID = thing.getUID();
-
-        try {
-            if (bridge != null) {
-                ThingHandler handler = bridge.getHandler();
-
-                if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
-                    device = bridgeHandler.getFreeatHomeDeviceDescription(device.getDeviceId());
-                }
-            }
-        } catch (FreeAtHomeHttpCommunicationException e) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-        }
-
-        for (int i = 0; i < device.getNumberOfChannels(); i++) {
-            FreeAtHomeDeviceChannel channel = device.getChannel(i);
-
-            for (int j = 0; j < channel.getNumberOfDatapointGroup(); j++) {
-                FreeAtHomeDatapointGroup dpg = channel.getDatapointGroup(j);
-
-                ChannelTypeUID channelTypeUID = UidUtils.generateChannelTypeUID(dpg.getValueType(), dpg.isReadOnly());
-
-                if (channelTypeProvider.getChannelType(channelTypeUID, null) == null) {
-                    channelTypeUID = createChannelTypeForDatapointgroup(dpg, channelTypeUID);
-                }
-
-                ChannelUID channelUID = new ChannelUID(thingUID, channel.getChannelId());
-
-                FreeAtHomeDatapoint outputDatapoint = dpg.getOutputDatapoint();
-
-                // in case of output channel, register it for updates
-                if (outputDatapoint != null) {
-                    String eventDatapointID = new String(device.getDeviceId() + "/" + channel.getChannelId() + "/"
-                            + outputDatapoint.getDatapointId());
-
-                    mapEventToChannelUID.put(eventDatapointID, channelUID);
-                }
-
-                // add the datapoint group to the mapping channel
-                mapChannelUID.put(channelUID, dpg);
-
-                logger.debug("Thing channelType reloaded - Device: {} - channelTypeUID: {}",
-                        device.getDeviceId() + device.getDeviceLabel(), channelTypeUID.getAsString());
-            }
-        }
-    }
-
-    public void removeChannels() {
-        Bridge bridge = this.getBridge();
-
-        try {
-            if (bridge != null) {
-                ThingHandler handler = bridge.getHandler();
-
-                if (handler instanceof FreeAtHomeBridgeHandler bridgeHandler) {
-                    device = bridgeHandler.getFreeatHomeDeviceDescription(device.getDeviceId());
-                }
-            }
-        } catch (FreeAtHomeHttpCommunicationException e) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "@text/comm-error.error-in-sysap-com");
-        }
-
-        mapChannelUID.clear();
-
-        mapEventToChannelUID.clear();
-    }
-
-    private String capitalizeWordsInLabel(String label) {
-        // splliting up words using split function
-        String[] words = label.split(" ");
-
-        for (int i = 0; i < words.length; i++) {
-
-            // taking letter individually from sentences
-            String firstLetter = words[i].substring(0, 1);
-            String restOfWord = words[i].substring(1);
-
-            // making first letter uppercase using toUpperCase function
-            firstLetter = firstLetter.toUpperCase();
-            words[i] = firstLetter + restOfWord;
-        }
-
-        // joining the words together to make a sentence
-        return String.join(" ", words);
-    }
-
-    private boolean isThingHandlesVirtualDevice() {
-        return device.isVirtual();
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceStateListener.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/handler/FreeAtHomeDeviceStateListener.java
deleted file mode 100644 (file)
index 6a5d886..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.handler;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link FreeAtHomeDeviceStateListener} is responsible for response the device state changes from SysAp
- * and thing updates
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public interface FreeAtHomeDeviceStateListener {
-    void onDeviceRemoved();
-
-    void onDeviceStateChanged(String event, String valueString);
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProvider.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProvider.java
deleted file mode 100644 (file)
index b89e68d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.type;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.type.ChannelType;
-import org.openhab.core.thing.type.ChannelTypeProvider;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public interface FreeAtHomeChannelTypeProvider extends ChannelTypeProvider {
-
-    public void addChannelType(ChannelType channelType);
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProviderImpl.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeChannelTypeProviderImpl.java
deleted file mode 100644 (file)
index a9cdf31..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.type;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.thing.type.ChannelType;
-import org.openhab.core.thing.type.ChannelTypeProvider;
-import org.openhab.core.thing.type.ChannelTypeUID;
-import org.osgi.service.component.annotations.Component;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@Component(service = { FreeAtHomeChannelTypeProvider.class, ChannelTypeProvider.class })
-@NonNullByDefault
-public class FreeAtHomeChannelTypeProviderImpl implements FreeAtHomeChannelTypeProvider {
-
-    private final Map<ChannelTypeUID, ChannelType> channelTypesByUID = new HashMap<>();
-
-    @Override
-    public Collection<ChannelType> getChannelTypes(@Nullable Locale locale) {
-        Collection<ChannelType> result = new ArrayList<>();
-
-        for (ChannelTypeUID uid : channelTypesByUID.keySet()) {
-            ChannelType channelType = channelTypesByUID.get(uid);
-
-            if (channelType != null) {
-                result.add(channelType);
-            }
-        }
-
-        return result;
-    }
-
-    @Override
-    public @Nullable ChannelType getChannelType(@Nullable ChannelTypeUID channelTypeUID, @Nullable Locale locale) {
-        return channelTypesByUID.get(channelTypeUID);
-    }
-
-    @Override
-    public void addChannelType(@Nullable ChannelType channelType) {
-        if (channelType != null) {
-            channelTypesByUID.put(channelType.getUID(), channelType);
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProvider.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProvider.java
deleted file mode 100644 (file)
index c2c1193..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.type;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.binding.ThingTypeProvider;
-import org.openhab.core.thing.type.ThingType;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public interface FreeAtHomeThingTypeProvider extends ThingTypeProvider {
-
-    /**
-     * Adds the ThingType to this provider.
-     */
-    public void addThingType(ThingType thingType);
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProviderImpl.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/type/FreeAtHomeThingTypeProviderImpl.java
deleted file mode 100644 (file)
index 807933a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.type;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.thing.ThingTypeUID;
-import org.openhab.core.thing.binding.ThingTypeProvider;
-import org.openhab.core.thing.type.ThingType;
-import org.osgi.service.component.annotations.Component;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-
-@Component(service = { FreeAtHomeThingTypeProvider.class, ThingTypeProvider.class })
-@NonNullByDefault
-public class FreeAtHomeThingTypeProviderImpl implements FreeAtHomeThingTypeProvider {
-    private final Map<ThingTypeUID, ThingType> thingTypesByUID = new HashMap<>();
-
-    @Override
-    public Collection<ThingType> getThingTypes(@Nullable Locale locale) {
-        Map<ThingTypeUID, ThingType> copy = new HashMap<>(thingTypesByUID);
-        return copy.values();
-    }
-
-    @Override
-    public @Nullable ThingType getThingType(ThingTypeUID thingTypeUID, @Nullable Locale locale) {
-        return thingTypesByUID.get(thingTypeUID);
-    }
-
-    @Override
-    public void addThingType(@Nullable ThingType thingType) {
-        if (thingType != null) {
-            thingTypesByUID.put(thingType.getUID(), thingType);
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FidTranslationUtils.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FidTranslationUtils.java
deleted file mode 100644 (file)
index 96ff6bc..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.util;
-
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * The {@link FidTranslationUtils} having constant values for json parsing
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FidTranslationUtils {
-
-    public static final int FID_UNKNOWN = 0xFFFFAAFF; // Unknown
-
-    // free@home constants
-    public static final int FID_SWITCH_SENSOR = 0x0000; // Control element
-    public static final int FID_DIMMING_SENSOR = 0x0001; // Dimming sensor
-    public static final int FID_BLIND_SENSOR = 0x0003; // Blind sensor
-    public static final int FID_STAIRCASE_LIGHT_SENSOR = 0x0004; // Stairwell light sensor
-    public static final int FID_FORCE_ON_OFF_SENSOR = 0x0005; // Force On/Off sensor
-    public static final int FID_SCENE_SENSOR = 0x0006; // Scene sensor
-    public static final int FID_SWITCH_ACTUATOR = 0x0007; // Switch actuator
-    public static final int FID_SHUTTER_ACTUATOR = 0x0009; // Blind actuator
-    public static final int FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITH_FAN = 0x000A; // Room temperature controller
-                                                                                      // with fan speed level
-    public static final int FID_ROOM_TEMPERATURE_CONTROLLER_SLAVE = 0x000B; // Room temperature controller extension
-                                                                            // unit
-    public static final int FID_WIND_ALARM_SENSOR = 0x000C; // Wind Alarm
-    public static final int FID_FROST_ALARM_SENSOR = 0x000D; // Frost Alarm
-    public static final int FID_RAIN_ALARM_SENSOR = 0x000E; // Rain Alarm
-    public static final int FID_WINDOW_DOOR_SENSOR = 0x000F; // Window sensor
-    public static final int FID_MOVEMENT_DETECTOR = 0x0011; // Movement Detector
-    public static final int FID_DIMMING_ACTUATOR = 0x0012; // Dim actuator
-    public static final int FID_RADIATOR_ACTUATOR = 0x0014; // Radiator
-    public static final int FID_UNDERFLOOR_HEATING = 0x0015; // Underfloor heating
-    public static final int FID_FAN_COIL = 0x0016; // Fan Coil
-    public static final int FID_TWO_LEVEL_CONTROLLER = 0x0017; // Two-level controller
-    public static final int FID_DES_DOOR_OPENER_ACTUATOR = 0x001A; // Door opener
-    public static final int FID_PROXY = 0x001B; // Proxy
-    public static final int FID_DES_LEVEL_CALL_ACTUATOR = 0x001D; // Door Map.entry System Call Level Actuator
-    public static final int FID_DES_LEVEL_CALL_SENSOR = 0x001E; // Door Map.entry System Call Level Sensor
-    public static final int FID_DES_DOOR_RINGING_SENSOR = 0x001F; // Door call
-    public static final int FID_DES_AUTOMATIC_DOOR_OPENER_ACTUATOR = 0x0020; // Automatic door opener
-    public static final int FID_DES_LIGHT_SWITCH_ACTUATOR = 0x0021; // Corridor light
-    public static final int FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN = 0x0023; // Room temperature controller
-    public static final int FID_COOLING_ACTUATOR = 0x0024; // Cooling mode
-    public static final int FID_HEATING_ACTUATOR = 0x0027; // Heating mode
-    public static final int FID_FORCE_UP_DOWN_SENSOR = 0x0028; // Force-position blind
-    public static final int FID_HEATING_COOLING_ACTUATOR = 0x0029; // Auto. heating/cooling mode
-    public static final int FID_HEATING_COOLING_SENSOR = 0x002A; // Switchover heating/cooling
-    public static final int FID_DES_DEVICE_SETTINGS = 0x002B; // Device settings
-    public static final int FID_RGB_W_ACTUATOR = 0x002E; // Dim actuator
-    public static final int FID_RGB_ACTUATOR = 0x002F; // Dim actuator
-    public static final int FID_PANEL_SWITCH_SENSOR = 0x0030; // Control element
-    public static final int FID_PANEL_DIMMING_SENSOR = 0x0031; // Dimming sensor
-    public static final int FID_PANEL_BLIND_SENSOR = 0x0033; // Blind sensor
-    public static final int FID_PANEL_STAIRCASE_LIGHT_SENSOR = 0x0034; // Stairwell light sensor
-    public static final int FID_PANEL_FORCE_ON_OFF_SENSOR = 0x0035; // Force On/Off sensor
-    public static final int FID_PANEL_FORCE_UP_DOWN_SENSOR = 0x0036; // Force-position blind
-    public static final int FID_PANEL_SCENE_SENSOR = 0x0037; // Scene sensor
-    public static final int FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE = 0x0038; // Room temperature controller
-                                                                                  // extension unit
-    public static final int FID_PANEL_FAN_COIL_SENSOR = 0x0039; // Fan coil sensor
-    public static final int FID_PANEL_RGB_CT_SENSOR = 0x003A; // RGB + warm white/cold white sensor
-    public static final int FID_PANEL_RGB_SENSOR = 0x003B; // RGB sensor
-    public static final int FID_PANEL_CT_SENSOR = 0x003C; // Warm white/cold white sensor
-    public static final int FID_ADDITIONAL_HEATING_ACTUATOR = 0x003D; // Add. stage for heating mode
-    public static final int FID_RADIATOR_ACTUATOR_MASTER = 0x003E; // Radiator thermostate
-    public static final int FID_RADIATOR_ACTUATOR_SLAVE = 0x003F; // Room temperature controller extension unit
-    public static final int FID_BRIGHTNESS_SENSOR = 0x0041; // Brightness sensor
-    public static final int FID_RAIN_SENSOR = 0x0042; // Rain sensor
-    public static final int FID_TEMPERATURE_SENSOR = 0x0043; // Temperature sensor
-    public static final int FID_WIND_SENSOR = 0x0044; // Wind sensor
-    public static final int FID_TRIGGER = 0x0045; // Trigger
-    public static final int FID_FCA_2_PIPE_HEATING = 0x0047; // Heating mode
-    public static final int FID_FCA_2_PIPE_COOLING = 0x0048; // Cooling mode
-    public static final int FID_FCA_2_PIPE_HEATING_COOLING = 0x0049; // Auto. heating/cooling mode
-    public static final int FID_FCA_4_PIPE_HEATING_AND_COOLING = 0x004A; // Two valves for heating and cooling
-    public static final int FID_WINDOW_DOOR_ACTUATOR = 0x004B; // Window/Door
-    public static final int FID_INVERTER_INFO = 0x004E; // ABC
-    public static final int FID_METER_INFO = 0x004F; // ABD
-    public static final int FID_BATTERY_INFO = 0x0050; // ACD
-    public static final int FID_PANEL_TIMER_PROGRAM_SWITCH_SENSOR = 0x0051; // Timer program switch sensor
-    public static final int FID_DOMUSTECH_ZONE = 0x0055; // Zone
-    public static final int FID_CENTRAL_HEATING_ACTUATOR = 0x0056; // Central heating actuator
-    public static final int FID_CENTRAL_COOLING_ACTUATOR = 0x0057; // Central cooling actuator
-    public static final int FID_HOUSE_KEEPING = 0x0059; // Housekeeping
-    public static final int FID_MEDIA_PLAYER = 0x005A; // Media Player
-    public static final int FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE_FOR_BATTERY_DEVICE = 0x005B; // Panel Room
-                                                                                                     // Temperature
-                                                                                                     // Controller Slave
-                                                                                                     // For Battery
-                                                                                                     // Device
-    public static final int FID_PANEL_MEDIA_PLAYER_SENSOR = 0x0060; // Media Player Sensor
-    public static final int FID_BLIND_ACTUATOR = 0x0061; // Roller blind actuator
-    public static final int FID_ATTIC_WINDOW_ACTUATOR = 0x0062; // Attic window actuator
-    public static final int FID_AWNING_ACTUATOR = 0x0063; // Awning actuator
-    public static final int FID_WINDOW_DOOR_POSITION_SENSOR = 0x0064; // WindowDoor Position Sensor
-    public static final int FID_WINDOW_DOOR_POSITION_ACTUATOR = 0x0065; // Window/Door position
-    public static final int FID_MEDIA_PLAYBACK_CONTROL_SENSOR = 0x0066; // Media playback control sensor
-    public static final int FID_MEDIA_VOLUME_SENSOR = 0x0067; // Media volume sensor
-    public static final int FID_DISHWASHER = 0x0068; // Dishwasher
-    public static final int FID_LAUNDRY = 0x0069; // Laundry
-    public static final int FID_DRYER = 0x006A; // Dryer
-    public static final int FID_OVEN = 0x006B; // Oven
-    public static final int FID_FRIDGE = 0x006C; // Fridge
-    public static final int FID_FREEZER = 0x006D; // Freezer
-    public static final int FID_HOOD = 0x006E; // Hood
-    public static final int FID_COFFEE_MACHINE = 0x006F; // Coffee machine
-    public static final int FID_FRIDGE_FREEZER = 0x0070; // Fridge/Freezer
-    public static final int FID_TIMER_PROGRAM_OR_ALERT_SWITCH_SENSOR = 0x0071; // Timer program switch sensor
-    public static final int FID_CEILING_FAN_ACTUATOR = 0x0073; // Ceiling fan actuator
-    public static final int FID_CEILING_FAN_SENSOR = 0x0074; // Ceiling fan sensor
-    public static final int FID_SPLIT_UNIT_GATEWAY = 0x0075; // Room temperature controller with fan speed level
-    public static final int FID_ZONE = 0x0076; // Zone
-    public static final int FID_24H_ZONE = 0x0077; // Safety
-    public static final int FID_EXTERNAL_IR_SENSOR_BX80 = 0x0078; // External IR Sensor BX80
-    public static final int FID_EXTERNAL_IR_SENSOR_VXI = 0x0079; // External IR Sensor VXI
-    public static final int FID_EXTERNAL_IR_SENSOR_MINI = 0x007A; // External IR Sensor Mini
-    public static final int FID_EXTERNAL_IR_SENSOR_HIGH_ALTITUDE = 0x007B; // External IR Sensor High Altitude
-    public static final int FID_EXTERNAL_IR_SENSOR_CURTAIN = 0x007C; // External IR Sensor Curtain
-    public static final int FID_SMOKE_DETECTOR = 0x007D; // Smoke Detector
-    public static final int FID_CARBON_MONOXIDE_SENSOR = 0x007E; // Carbon Monoxide Sensor
-    public static final int FID_METHANE_DETECTOR = 0x007F; // Methane Detector
-    public static final int FID_GAS_SENSOR_LPG = 0x0080; // Gas Sensor LPG
-    public static final int FID_FLOOD_DETECTION = 0x0081; // Flood Detection
-    public static final int FID_DOMUS_CENTRAL_UNIT_NEXTGEN = 0x0082; // secure@home Central Unit
-    public static final int FID_THERMOSTAT = 0x0083; // Thermostat
-    public static final int FID_PANEL_DOMUS_ZONE_SENSOR = 0x0084; // secure@home Zone Sensor
-    public static final int FID_THERMOSTAT_SLAVE = 0x0085; // Slave thermostat
-    public static final int FID_DOMUS_SECURE_INTEGRATION = 0x0086; // secure@home Integration Logic
-    public static final int FID_ADDITIONAL_COOLING_ACTUATOR = 0x0087; // Add. stage for cooling mode
-    public static final int FID_TWO_LEVEL_HEATING_ACTUATOR = 0x0088; // Two Level Heating Actuator
-    public static final int FID_TWO_LEVEL_COOLING_ACTUATOR = 0x0089; // Two Level Cooling Actuator
-    public static final int FID_GLOBAL_ZONE = 0x008E; // Zone
-    public static final int FID_VOLUME_UP_SENSOR = 0x008F; // Volume up
-    public static final int FID_VOLUME_DOWN_SENSOR = 0x0090; // Volume down
-    public static final int FID_PLAY_PAUSE_SENSOR = 0x0091; // Play/pause
-    public static final int FID_NEXT_FAVORITE_SENSOR = 0x0092; // Next favorite
-    public static final int FID_NEXT_SONG_SENSOR = 0x0093; // Next song
-    public static final int FID_PREVIOUS_SONG_SENSOR = 0x0094; // Previous song
-    public static final int FID_HOME_APPLIANCE_SENSOR = 0x0095; // Home appliance sensor
-    public static final int FID_HEAT_SENSOR = 0x0096; // Heat sensor
-    public static final int FID_ZONE_SWITCHING = 0x0097; // Zone switching
-    public static final int FID_SECURE_AT_HOME_FUNCTION = 0x0098; // Button function
-    public static final int FID_COMPLEX_CONFIGURATION = 0x0099; // Advanced configuration
-    public static final int FID_DOMUS_CENTRAL_UNIT_BASIC = 0x009A; // secure@home Central Unit Basic
-    public static final int FID_DOMUS_REPEATER = 0x009B; // Repeater
-    public static final int FID_DOMUS_SCENE_TRIGGER = 0x009C; // Remote scene control
-    public static final int FID_DOMUSWINDOWCONTACT = 0x009D; // Window sensor
-    public static final int FID_DOMUSMOVEMENTDETECTOR = 0x009E; // Movement Detector
-    public static final int FID_DOMUSCURTAINDETECTOR = 0x009F; // External IR Sensor Curtain
-    public static final int FID_DOMUSSMOKEDETECTOR = 0x00A0; // Smoke Detector
-    public static final int FID_DOMUSFLOODDETECTOR = 0x00A1; // Flood Detection
-    public static final int FID_PANEL_SUG_SENSOR = 0x00A3; // Sensor for air-conditioning unit
-    public static final int FID_TWO_LEVEL_HEATING_COOLING_ACTUATOR = 0x00A4; // Two-point controller for heating or
-                                                                             // cooling
-    public static final int FID_PANEL_THERMOSTAT_CONTROLLER_SLAVE = 0x00A5; // Slave thermostat
-    public static final int FID_WALLBOX = 0x00A6; // Wallbox
-    public static final int FID_PANEL_WALLBOX = 0x00A7; // Wallbox
-    public static final int FID_DOOR_LOCK_CONTROL = 0x00A8; // Door lock control
-    public static final int FID_VRV_GATEWAY = 0x00AA; // Room temperature controller with fan speed level
-
-    public static final int FID_SCENE_TRIGGER = 0x4800; // Scene trigger
-    public static final int FID_RULE_SWITCH = 0x4A00; // Scene trigger
-
-    // FID added based on tests
-    public static final int FID_AIRQUALITYSENSOR_PRESSURE = 0x0E017;
-    public static final int FID_AIRQUALITYSENSOR_CO2 = 0x0E018;
-    public static final int FID_AIRQUALITYSENSOR_CO = 0x0E019;
-    public static final int FID_AIRQUALITYSENSOR_NO2 = 0x0E01A;
-    public static final int FID_AIRQUALITYSENSOR_O3 = 0x0E01B;
-    public static final int FID_AIRQUALITYSENSOR_PM10 = 0x0E01C;
-    public static final int FID_AIRQUALITYSENSOR_PM25 = 0x0E01D;
-    public static final int FID_AIRQUALITYSENSOR_VOC = 0x0E01E;
-    public static final int FID_AIRQUALITYSENSOR_HUMIDITY = 0x0B03F;
-
-    public static final int FID_MOVEMENT_DETECTOR_FLEX = 0x1090;
-    public static final int FID_DIMMING_ACTUATOR_FLEX = 0x1810;
-
-    private static final Map<String, String> MAP_FUNCTION_ID = Map.ofEntries(Map.entry("0x0000", "fid-control-element"), // FID_SWITCH_SENSOR
-            Map.entry("0x0001", "fid-dimming-sensor"), // FID_DIMMING_SENSOR
-            Map.entry("0x0003", "fid-blind-sensor"), // FID_BLIND_SENSOR
-            Map.entry("0x0004", "fid-stairwell-light-sensor"), // FID_STAIRCASE_LIGHT_SENSOR
-            Map.entry("0x0005", "fid-force-on/off-sensor"), // FID_FORCE_ON_OFF_SENSOR
-            Map.entry("0x0006", "fid-scene-sensor"), // FID_SCENE_SENSOR
-            Map.entry("0x0007", "fid-switch-actuator"), // FID_SWITCH_ACTUATOR
-            Map.entry("0x0009", "fid-blind-actuator"), // FID_SHUTTER_ACTUATOR
-            Map.entry("0x000A", "fid-room-temperature-controller-with-fan-speed-level"), // FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITH_FAN
-            Map.entry("0x000B", "fid-room-temperature-controller-extension-unit"), // FID_ROOM_TEMPERATURE_CONTROLLER_SLAVE
-            Map.entry("0x000C", "fid-wind-alarm"), // FID_WIND_ALARM_SENSOR
-            Map.entry("0x000D", "fid-frost-alarm"), // FID_FROST_ALARM_SENSOR
-            Map.entry("0x000E", "fid-rain-alarm"), // FID_RAIN_ALARM_SENSOR
-            Map.entry("0x000F", "fid-window-sensor"), // FID_WINDOW_DOOR_SENSOR
-            Map.entry("0x0011", "fid-movement-detector"), // FID_MOVEMENT_DETECTOR
-            Map.entry("0x0012", "fid-dim-actuator"), // FID_DIMMING_ACTUATOR
-            Map.entry("0x0014", "fid-radiator"), // FID_RADIATOR_ACTUATOR
-            Map.entry("0x0015", "fid-underfloor-heating"), // FID_UNDERFLOOR_HEATING
-            Map.entry("0x0016", "fid-fan-coil"), // FID_FAN_COIL
-            Map.entry("0x0017", "fid-two-level-controller"), // FID_TWO_LEVEL_CONTROLLER
-            Map.entry("0x001A", "fid-door-opener"), // FID_DES_DOOR_OPENER_ACTUATOR
-            Map.entry("0x001B", "fid-proxy"), // FID_PROXY
-            Map.entry("0x001D", "fid-door-map.entry-system-call-level-actuator"), // FID_DES_LEVEL_CALL_ACTUATOR
-            Map.entry("0x001E", "fid-door-map.entry-system-call-level-sensor"), // FID_DES_LEVEL_CALL_SENSOR
-            Map.entry("0x001F", "fid-door-call"), // FID_DES_DOOR_RINGING_SENSOR
-            Map.entry("0x0020", "fid-automatic-door-opener"), // FID_DES_AUTOMATIC_DOOR_OPENER_ACTUATOR
-            Map.entry("0x0021", "fid-corridor-light"), // FID_DES_LIGHT_SWITCH_ACTUATOR
-            Map.entry("0x0023", "fid-room-temperature-controller"), // FID_ROOM_TEMPERATURE_CONTROLLER_MASTER_WITHOUT_FAN
-            Map.entry("0x0024", "fid-cooling-mode"), // FID_COOLING_ACTUATOR
-            Map.entry("0x0027", "fid-heating-mode"), // FID_HEATING_ACTUATOR
-            Map.entry("0x0028", "fid-force-position-blind"), // FID_FORCE_UP_DOWN_SENSOR
-            Map.entry("0x0029", "fid-auto.-heating/cooling-mode"), // FID_HEATING_COOLING_ACTUATOR
-            Map.entry("0x002A", "fid-switchover-heating/cooling"), // FID_HEATING_COOLING_SENSOR
-            Map.entry("0x002B", "fid-device-settings"), // FID_DES_DEVICE_SETTINGS
-            Map.entry("0x002E", "fid-dim-actuator"), // FID_RGB_W_ACTUATOR
-            Map.entry("0x002F", "fid-dim-actuator"), // FID_RGB_ACTUATOR
-            Map.entry("0x0030", "fid-control-element"), // FID_PANEL_SWITCH_SENSOR
-            Map.entry("0x0031", "fid-dimming-sensor"), // FID_PANEL_DIMMING_SENSOR
-            Map.entry("0x0033", "fid-blind-sensor"), // FID_PANEL_BLIND_SENSOR
-            Map.entry("0x0034", "fid-stairwell-light-sensor"), // FID_PANEL_STAIRCASE_LIGHT_SENSOR
-            Map.entry("0x0035", "fid-force-on/off-sensor"), // FID_PANEL_FORCE_ON_OFF_SENSOR
-            Map.entry("0x0036", "fid-force-position-blind"), // FID_PANEL_FORCE_UP_DOWN_SENSOR
-            Map.entry("0x0037", "fid-scene-sensor"), // FID_PANEL_SCENE_SENSOR
-            Map.entry("0x0038", "fid-room-temperature-controller-extension-unit"), // FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE
-            Map.entry("0x0039", "fid-fan-coil-sensor"), // FID_PANEL_FAN_COIL_SENSOR
-            Map.entry("0x003A", "fid-rgb-+-warm-white/cold-white-sensor"), // FID_PANEL_RGB_CT_SENSOR
-            Map.entry("0x003B", "fid-rgb-sensor"), // FID_PANEL_RGB_SENSOR
-            Map.entry("0x003C", "fid-warm-white/cold-white-sensor"), // FID_PANEL_CT_SENSOR
-            Map.entry("0x003D", "fid-add.-stage-for-heating-mode"), // FID_ADDITIONAL_HEATING_ACTUATOR
-            Map.entry("0x003E", "fid-radiator-thermostate"), // FID_RADIATOR_ACTUATOR_MASTER
-            Map.entry("0x003F", "fid-room-temperature-controller-extension-unit"), // FID_RADIATOR_ACTUATOR_SLAVE
-            Map.entry("0x0041", "fid-brightness-sensor"), // FID_BRIGHTNESS_SENSOR
-            Map.entry("0x0042", "fid-rain-sensor"), // FID_RAIN_SENSOR
-            Map.entry("0x0043", "fid-temperature-sensor"), // FID_TEMPERATURE_SENSOR
-            Map.entry("0x0044", "fid-wind-sensor"), // FID_WIND_SENSOR
-            Map.entry("0x0045", "fid-trigger"), // FID_TRIGGER
-            Map.entry("0x0047", "fid-heating-mode"), // FID_FCA_2_PIPE_HEATING
-            Map.entry("0x0048", "fid-cooling-mode"), // FID_FCA_2_PIPE_COOLING
-            Map.entry("0x0049", "fid-auto.-heating/cooling-mode"), // FID_FCA_2_PIPE_HEATING_COOLING
-            Map.entry("0x004A", "fid-two-valves-for-heating-and-cooling"), // FID_FCA_4_PIPE_HEATING_AND_COOLING
-            Map.entry("0x004B", "fid-window/door"), // FID_WINDOW_DOOR_ACTUATOR
-            Map.entry("0x004E", "fid-abc"), // FID_INVERTER_INFO
-            Map.entry("0x004F", "fid-abd"), // FID_METER_INFO
-            Map.entry("0x0050", "fid-acd"), // FID_BATTERY_INFO
-            Map.entry("0x0051", "fid-timer-program-switch-sensor"), // FID_PANEL_TIMER_PROGRAM_SWITCH_SENSOR
-            Map.entry("0x0055", "fid-zone"), // FID_DOMUSTECH_ZONE
-            Map.entry("0x0056", "fid-central-heating-actuator"), // FID_CENTRAL_HEATING_ACTUATOR
-            Map.entry("0x0057", "fid-central-cooling-actuator"), // FID_CENTRAL_COOLING_ACTUATOR
-            Map.entry("0x0059", "fid-housekeeping"), // FID_HOUSE_KEEPING
-            Map.entry("0x005A", "fid-media-player"), // FID_MEDIA_PLAYER
-            Map.entry("0x005B", "fid-panel-room-temperature-controller-slave-for-battery-device"), // FID_PANEL_ROOM_TEMPERATURE_CONTROLLER_SLAVE_FOR_BATTERY_DEVICE
-            Map.entry("0x0060", "fid-media-player-sensor"), // FID_PANEL_MEDIA_PLAYER_SENSOR
-            Map.entry("0x0061", "fid-roller-blind-actuator"), // FID_BLIND_ACTUATOR
-            Map.entry("0x0062", "fid-attic-window-actuator"), // FID_ATTIC_WINDOW_ACTUATOR
-            Map.entry("0x0063", "fid-awning-actuator"), // FID_AWNING_ACTUATOR
-            Map.entry("0x0064", "fid-windowdoor-position-sensor"), // FID_WINDOW_DOOR_POSITION_SENSOR
-            Map.entry("0x0065", "fid-window/door-position"), // FID_WINDOW_DOOR_POSITION_ACTUATOR
-            Map.entry("0x0066", "fid-media-playback-control-sensor"), // FID_MEDIA_PLAYBACK_CONTROL_SENSOR
-            Map.entry("0x0067", "fid-media-volume-sensor"), // FID_MEDIA_VOLUME_SENSOR
-            Map.entry("0x0068", "fid-dishwasher"), // FID_DISHWASHER
-            Map.entry("0x0069", "fid-laundry"), // FID_LAUNDRY
-            Map.entry("0x006A", "fid-dryer"), // FID_DRYER
-            Map.entry("0x006B", "fid-oven"), // FID_OVEN
-            Map.entry("0x006C", "fid-fridge"), // FID_FRIDGE
-            Map.entry("0x006D", "fid-freezer"), // FID_FREEZER
-            Map.entry("0x006E", "fid-hood"), // FID_HOOD
-            Map.entry("0x006F", "fid-coffee-machine"), // FID_COFFEE_MACHINE
-            Map.entry("0x0070", "fid-fridge/freezer"), // FID_FRIDGE_FREEZER
-            Map.entry("0x0071", "fid-timer-program-switch-sensor"), // FID_TIMER_PROGRAM_OR_ALERT_SWITCH_SENSOR
-            Map.entry("0x0073", "fid-ceiling-fan-actuator"), // FID_CEILING_FAN_ACTUATOR
-            Map.entry("0x0074", "fid-ceiling-fan-sensor"), // FID_CEILING_FAN_SENSOR
-            Map.entry("0x0075", "fid-room-temperature-controller-with-fan-speed-level"), // FID_SPLIT_UNIT_GATEWAY
-            Map.entry("0x0076", "fid-zone"), // FID_ZONE
-            Map.entry("0x0077", "fid-safety"), // FID_24H_ZONE
-            Map.entry("0x0078", "fid-external-ir-sensor-bx80"), // FID_EXTERNAL_IR_SENSOR_BX80
-            Map.entry("0x0079", "fid-external-ir-sensor-vxi"), // FID_EXTERNAL_IR_SENSOR_VXI
-            Map.entry("0x007A", "fid-external-ir-sensor-mini"), // FID_EXTERNAL_IR_SENSOR_MINI
-            Map.entry("0x007B", "fid-external-ir-sensor-high-altitude"), // FID_EXTERNAL_IR_SENSOR_HIGH_ALTITUDE
-            Map.entry("0x007C", "fid-external-ir-sensor-curtain"), // FID_EXTERNAL_IR_SENSOR_CURTAIN
-            Map.entry("0x007D", "fid-smoke-detector"), // FID_SMOKE_DETECTOR
-            Map.entry("0x007E", "fid-carbon-monoxide-sensor"), // FID_CARBON_MONOXIDE_SENSOR
-            Map.entry("0x007F", "fid-methane-detector"), // FID_METHANE_DETECTOR
-            Map.entry("0x0080", "fid-gas-sensor-lpg"), // FID_GAS_SENSOR_LPG
-            Map.entry("0x0081", "fid-flood-detection"), // FID_FLOOD_DETECTION
-            Map.entry("0x0082", "fid-secure@home-central-unit"), // FID_DOMUS_CENTRAL_UNIT_NEXTGEN
-            Map.entry("0x0083", "fid-thermostat"), // FID_THERMOSTAT
-            Map.entry("0x0084", "fid-secure@home-zone-sensor"), // FID_PANEL_DOMUS_ZONE_SENSOR
-            Map.entry("0x0085", "fid-slave-thermostat"), // FID_THERMOSTAT_SLAVE
-            Map.entry("0x0086", "fid-secure@home-integration-logic"), // FID_DOMUS_SECURE_INTEGRATION
-            Map.entry("0x0087", "fid-add.-stage-for-cooling-mode"), // FID_ADDITIONAL_COOLING_ACTUATOR
-            Map.entry("0x0088", "fid-two-level-heating-actuator"), // FID_TWO_LEVEL_HEATING_ACTUATOR
-            Map.entry("0x0089", "fid-two-level-cooling-actuator"), // FID_TWO_LEVEL_COOLING_ACTUATOR
-            Map.entry("0x008E", "fid-zone"), // FID_GLOBAL_ZONE
-            Map.entry("0x008F", "fid-volume-up"), // FID_VOLUME_UP_SENSOR
-            Map.entry("0x0090", "fid-volume-down"), // FID_VOLUME_DOWN_SENSOR
-            Map.entry("0x0091", "fid-play/pause"), // FID_PLAY_PAUSE_SENSOR
-            Map.entry("0x0092", "fid-next-favorite"), // FID_NEXT_FAVORITE_SENSOR
-            Map.entry("0x0093", "fid-next-song"), // FID_NEXT_SONG_SENSOR
-            Map.entry("0x0094", "fid-previous-song"), // FID_PREVIOUS_SONG_SENSOR
-            Map.entry("0x0095", "fid-home-appliance-sensor"), // FID_HOME_APPLIANCE_SENSOR
-            Map.entry("0x0096", "fid-heat-sensor"), // FID_HEAT_SENSOR
-            Map.entry("0x0097", "fid-zone-switching"), // FID_ZONE_SWITCHING
-            Map.entry("0x0098", "fid-button-function"), // FID_SECURE_AT_HOME_FUNCTION
-            Map.entry("0x0099", "fid-advanced-configuration"), // FID_COMPLEX_CONFIGURATION
-            Map.entry("0x009A", "fid-secure@home-central-unit-basic"), // FID_DOMUS_CENTRAL_UNIT_BASIC
-            Map.entry("0x009B", "fid-repeater"), // FID_DOMUS_REPEATER
-            Map.entry("0x009C", "fid-remote-scene-control"), // FID_DOMUS_SCENE_TRIGGER
-            Map.entry("0x009D", "fid-window-sensor"), // FID_DOMUSWINDOWCONTACT
-            Map.entry("0x009E", "fid-movement-detector"), // FID_DOMUSMOVEMENTDETECTOR
-            Map.entry("0x009F", "fid-external-ir-sensor-curtain"), // FID_DOMUSCURTAINDETECTOR
-            Map.entry("0x00A0", "fid-smoke-detector"), // FID_DOMUSSMOKEDETECTOR
-            Map.entry("0x00A1", "fid-flood-detection"), // FID_DOMUSFLOODDETECTOR
-            Map.entry("0x00A3", "fid-sensor-for-air-conditioning-unit"), // FID_PANEL_SUG_SENSOR
-            Map.entry("0x00A4", "fid-two-point-controller-for-heating-or-cooling"), // FID_TWO_LEVEL_HEATING_COOLING_ACTUATOR
-            Map.entry("0x00A5", "fid-slave-thermostat"), // FID_PANEL_THERMOSTAT_CONTROLLER_SLAVE
-            Map.entry("0x00A6", "fid-wallbox"), // FID_WALLBOX
-            Map.entry("0x00A7", "fid-wallbox"), // FID_PANEL_WALLBOX
-            Map.entry("0x00A8", "fid-door-lock-control"), // FID_DOOR_LOCK_CONTROL
-            Map.entry("0x00AA", "fid-room-temperature-controller-with-fan-speed-level"), // FID_VRV_GATEWAY
-            Map.entry("0x4800", "fid-scene-trigger"), // FID_SCENE_TRIGGER
-            Map.entry("0x4A00", "fid-rule-switch"), // FID_RULE_SWITCH
-            Map.entry("0xE017", "fid-air-quality-sensor-pressure"), // FID_AIRQUALITYSENSOR_PRESSURE
-            Map.entry("0xE018", "fid-air-quality-sensor-co2"), // FID_AIRQUALITYSENSOR_CO2
-            Map.entry("0xE019", "fid-air-quality-sensor-co"), // FID_AIRQUALITYSENSOR_CO
-            Map.entry("0xE01A", "fid-air-quality-sensor-no2"), // FID_AIRQUALITYSENSOR_NO2
-            Map.entry("0xE01B", "fid-air-quality-sensor-o3"), // FID_AIRQUALITYSENSOR_O3
-            Map.entry("0xE01C", "fid-air-quality-sensor-pm10"), // FID_AIRQUALITYSENSOR_PM10
-            Map.entry("0xE01D", "fid-air-quality-sensor-pm25"), // FID_AIRQUALITYSENSOR_PM25
-            Map.entry("0xE01E", "fid-air-quality-sensor-voc"), // FID_AIRQUALITYSENSOR_VOC
-            Map.entry("0xB03F", "fid-air-quality-sensor-humidity"), // FID_AIRQUALITYSENSOR_HUMIDITY
-            Map.entry("0x1090", "fid-movement-detector-flex"), // FID_MOVEMENT_DETECTOR_FLEX
-            Map.entry("0x1810", "fid-dim-actuator-flex") // FID_SWITCH_ACTUATOR_FLEX
-    );
-
-    @Nullable
-    public static String getFunctionIdText(String Key) throws FreeAtHomeGeneralException {
-        String result = MAP_FUNCTION_ID.get(Key);
-
-        if (result != null) {
-            return MAP_FUNCTION_ID.get(Key);
-        } else {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "FID is not in the translation table", Key));
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeGeneralException.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeGeneralException.java
deleted file mode 100644 (file)
index c490db2..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.util;
-
-import java.util.Objects;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * The {@link FreeAtHomeGeneralException} is responsible for handling general exceptions in the free@home binding
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeGeneralException extends Exception {
-    private static final long serialVersionUID = -835448863173642860L;
-    private String errorMessage = "Unknown_Exception";
-    private int errorCode = 0;
-
-    public FreeAtHomeGeneralException(int errorCode, String message) {
-        super(message);
-
-        this.errorMessage = message;
-        this.errorCode = errorCode;
-    }
-
-    public @Nullable String getMessage() {
-        return this.errorMessage;
-    }
-
-    public int getErrorCode() {
-        return this.errorCode;
-    }
-
-    @Override
-    public String toString() {
-        return "FreeAtHomeHttpCommunicationException [errorMessage=" + errorMessage + ", errorCode=" + errorCode + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(errorCode, errorMessage);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-
-        FreeAtHomeGeneralException other = (FreeAtHomeGeneralException) obj;
-
-        return errorCode == other.errorCode && Objects.equals(errorMessage, other.errorMessage);
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeHttpCommunicationException.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/FreeAtHomeHttpCommunicationException.java
deleted file mode 100644 (file)
index cfea139..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.util;
-
-import java.util.Objects;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * The {@link FreeAtHomeHttpCommunicationException} is responsible for handling the communication exception to the SysAp
- * via HTTP link
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class FreeAtHomeHttpCommunicationException extends Exception {
-    private static final long serialVersionUID = -817364286035448863L;
-    private String errorMessage = "Unknown_Exception";
-    private int errorCode;
-
-    public FreeAtHomeHttpCommunicationException(int errorCode, String message) {
-        super(message);
-
-        this.errorMessage = message;
-        this.errorCode = errorCode;
-    }
-
-    public @Nullable String getMessage() {
-        return this.errorMessage;
-    }
-
-    public int getErrorCode() {
-        return this.errorCode;
-    }
-
-    @Override
-    public String toString() {
-        return "FreeAtHomeHttpCommunicationException [errorMessage=" + errorMessage + ", errorCode=" + errorCode + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(errorCode, errorMessage);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-
-        FreeAtHomeHttpCommunicationException other = (FreeAtHomeHttpCommunicationException) obj;
-
-        return errorCode == other.errorCode && Objects.equals(errorMessage, other.errorMessage);
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PIdContainerClass.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PIdContainerClass.java
deleted file mode 100644 (file)
index e534a11..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.util;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link PIdContainerClass} is a helper class for pairing IDs
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class PIdContainerClass {
-    String valueType;
-    String category;
-    int min;
-    int max;
-    String label;
-    String description;
-
-    PIdContainerClass(String pValueType, String pCategory, String pMin, String pMax, String pLabel,
-            String pDescription) {
-        this.valueType = pValueType;
-
-        this.category = pCategory;
-
-        if (pMax.isEmpty()) {
-            this.min = 0;
-        } else {
-            this.min = Integer.parseInt(pMin);
-        }
-
-        if (pMax.isEmpty()) {
-            this.max = 100;
-        } else {
-            this.max = Integer.parseInt(pMax);
-        }
-
-        this.label = pLabel;
-
-        this.description = pDescription;
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PidTranslationUtils.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/PidTranslationUtils.java
deleted file mode 100644 (file)
index 3e5b05f..0000000
+++ /dev/null
@@ -1,829 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.util;
-
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link PidTranslationUtils} supporting the translation from pairing IDs into openHAB types
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class PidTranslationUtils {
-    public static final String PID_VALUETYPE_UNKNOWN = "unknown";
-    public static final String PID_VALUETYPE_BOOLEAN = "boolean";
-    public static final String PID_VALUETYPE_DECIMAL = "decimal";
-    public static final String PID_VALUETYPE_INTEGER = "integer";
-    public static final String PID_VALUETYPE_STRING = "string";
-    public static final String PID_VALUETYPE_SHUTTERMOVEMENT = "shuttermovement";
-    public static final String PID_VALUETYPE_ENUM = "enum";
-
-    public static final String CATEGORY_UNDEFINED = "-";
-    public static final String CATEGORY_BATTERY = "Battery";
-    public static final String CATEGORY_ALARM = "Alarm";
-    public static final String CATEGORY_HUMIDITY = "Humidity";
-    public static final String CATEGORY_TEMPERATURE = "Temperature";
-    public static final String CATEGORY_MOTION = "Motion";
-    public static final String CATEGORY_PRESSURE = "Pressure";
-    public static final String CATEGORY_SMOKE = "Smoke";
-    public static final String CATEGORY_WATER = "Water";
-    public static final String CATEGORY_WIND = "Wind";
-    public static final String CATEGORY_RAIN = "Rain";
-    public static final String CATEGORY_ENERGY = "Energy";
-    public static final String CATEGORY_BLINDS = "Blinds";
-    public static final String CATEGORY_CONTACT = "Contact";
-    public static final String CATEGORY_SWITCH = "Switch";
-
-    private static final Map<String, PIdContainerClass> MAP_PAIRING_ID = Map.ofEntries(
-            Map.entry("0x0001",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "0", "1", "pid-switch-on-off",
-                            "pid-switch-on-off-text")),
-            Map.entry("0x0002",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-timed-start-stop",
-                            "pid-timed-start-stop-text")),
-            Map.entry("0x0003",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-force-position",
-                            "pid-force-position-text")),
-            Map.entry("0x0004",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-scene-control",
-                            "pid-scene-control-text")),
-            Map.entry("0x0006",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_MOTION, "", "",
-                            "pid-movement-under-consideration-of-brightness",
-                            "pid-movement-under-consideration-of-brightness-text")),
-            Map.entry("0x0007",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_MOTION, "", "", "pid-presence",
-                            "pid-presence-text")),
-            Map.entry("0x0010",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-relative-set-value",
-                            "pid-relative-set-value-text")),
-            Map.entry("0x0011",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-absolute-set-value",
-                            "pid-absolute-set-value-text")),
-            Map.entry("0x0012",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-night",
-                            "pid-night-text")),
-            Map.entry("0x0013",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-invalid-string-id",
-                            "pid-invalid-string-id-text")),
-            Map.entry("0x0015",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-rgb-color",
-                            "pid-rgb-color-text")),
-            Map.entry("0x0016",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-color-temperature",
-                            "pid-color-temperature-text")),
-            Map.entry("0x0017",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-hsv",
-                            "pid-hsv-text")),
-            Map.entry("0x0018",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-hue",
-                            "pid-hue-text")),
-            Map.entry("0x0019",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-saturation",
-                            "pid-saturation-text")),
-            Map.entry("0x0020",
-                    new PIdContainerClass(PID_VALUETYPE_SHUTTERMOVEMENT, CATEGORY_BLINDS, "", "", "pid-move-up-down",
-                            "pid-move-up-down-text")),
-            Map.entry("0x0021",
-                    new PIdContainerClass(PID_VALUETYPE_SHUTTERMOVEMENT, CATEGORY_BLINDS, "", "", "pid-adjust-up-down",
-                            "pid-adjust-up-down-text")),
-            Map.entry("0x0023",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_BLINDS, "0", "100",
-                            "pid-set-absolute-position-blinds", "pid-set-absolute-position-blinds-text")),
-            Map.entry("0x0024",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_BLINDS, "0", "100",
-                            "pid-set-absolute-position-slats", "pid-set-absolute-position-slats-text")),
-            Map.entry("0x0025",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_WIND, "", "", "pid-wind-alarm",
-                            "pid-wind-alarm-text")),
-            Map.entry("0x0026",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_TEMPERATURE, "", "", "pid-frost-alarm",
-                            "pid-frost-alarm-text")),
-            Map.entry("0x0027",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_RAIN, "", "", "pid-rain-alarm",
-                            "pid-rain-alarm-text")),
-            Map.entry("0x0028",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-force-position-blind",
-                            "pid-force-position-blind-text")),
-            Map.entry("0x0029",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-window-door-position",
-                            "pid-window-door-position-text")),
-            Map.entry("0x0030",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-actuating-value-heating", "pid-actuating-value-heating-text")),
-            Map.entry("0x0031",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-fan-level-heating",
-                            "pid-fan-level-heating-text")),
-            Map.entry("0x0032",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-actuating-value-cooling", "pid-actuating-value-cooling-text")),
-            Map.entry("0x0033",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
-                            "pid-set-value-temperature", "pid-set-value-temperature-text")),
-            Map.entry("0x0034",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
-                            "pid-relative-set-point-temperature", "pid-relative-set-point-temperature-text")),
-            Map.entry("0x0035",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-window-door",
-                            "pid-window-door-text")),
-            Map.entry("0x0036",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-status-indication",
-                            "pid-status-indication-text")),
-            Map.entry("0x0037",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
-                            "pid-fan-manual-heating-on-off", "pid-fan-manual-heating-on-off-text")),
-            Map.entry("0x0038",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-controller-on-off",
-                            "pid-controller-on-off-text")),
-            Map.entry("0x0039",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
-                            "pid-relative-set-point-request", "pid-relative-set-point-request-text")),
-            Map.entry("0x003A",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-eco-mode-on-off-request",
-                            "pid-eco-mode-on-off-request-text")),
-            Map.entry("0x003B",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
-                            "pid-comfort-temperature", "pid-comfort-temperature-text")),
-            Map.entry("0x0040",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-fan-level-request",
-                            "pid-fan-level-request-text")),
-            Map.entry("0x0041",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
-                            "pid-fan-manual-on-off-request", "pid-fan-manual-on-off-request-text")),
-            Map.entry("0x0042",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
-                            "pid-controller-on-off-request", "pid-controller-on-off-request-text")),
-            Map.entry("0x0044",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-eco-mode-on-off-request",
-                            "pid-eco-mode-on-off-request-text")),
-            Map.entry("0x0100",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-info-on-off",
-                            "pid-info-on-off-text")),
-            Map.entry("0x0101",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-force-position-info",
-                            "pid-force-position-info-text")),
-            Map.entry("0x0105",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-sysap-infoonoff",
-                            "pid-sysap-infoonoff-text")),
-            Map.entry("0x0106",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-sysap-infoforce",
-                            "pid-sysap-infoforce-text")),
-            Map.entry("0x0110",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-actual-dimming-value", "pid-info-actual-dimming-value-text")),
-            Map.entry("0x0111",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-info-error",
-                            "pid-info-error-text")),
-            Map.entry("0x0115",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                            "pid-sysap-infocurrentdimmingvalue", "pid-sysap-infocurrentdimmingvalue-text")),
-            Map.entry("0x0116",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-sysap-infoerror",
-                            "pid-sysap-infoerror-text")),
-            Map.entry("0x0118",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-color-temperature", "pid-info-color-temperature-text")),
-            Map.entry("0x011A",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-sysap-info-color-temperature", "pid-sysap-info-color-temperature-text")),
-            Map.entry("0x011B",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-hsv",
-                            "pid-info-hsv-text")),
-            Map.entry("0x011C",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-sysap-info-hsv",
-                            "pid-sysap-info-hsv-text")),
-            Map.entry("0x011D",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-color-mode",
-                            "pid-info-color-mode-text")),
-            Map.entry("0x011E",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-sysap-info-color-mode", "pid-sysap-info-color-mode-text")),
-            Map.entry("0x0120",
-                    new PIdContainerClass(PID_VALUETYPE_SHUTTERMOVEMENT, CATEGORY_BLINDS, "", "",
-                            "pid-info-move-up-down", "pid-info-move-up-down-text")),
-            Map.entry("0x0121",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_BLINDS, "", "",
-                            "pid-current-absolute-position-blinds-percentage",
-                            "pid-current-absolute-position-blinds-percentage-text")),
-            Map.entry("0x0122",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-current-absolute-position-slats-percentage",
-                            "pid-current-absolute-position-slats-percentage-text")),
-            Map.entry("0x0125",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-sysap-infomoveupdown",
-                            "pid-sysap-infomoveupdown-text")),
-            Map.entry("0x0126",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-sysap-infocurrentabsoluteblindspercentage",
-                            "pid-sysap-infocurrentabsoluteblindspercentage-text")),
-            Map.entry("0x0127",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-sysap-infocurrentabsoluteslatspercentage",
-                            "pid-sysap-infocurrentabsoluteslatspercentage-text")),
-            Map.entry("0x0130",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
-                            "pid-measured-temperature", "pid-measured-temperature-text")),
-            Map.entry("0x0131",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-value-heating",
-                            "pid-info-value-heating-text")),
-            Map.entry("0x0132",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-info-value-cooling",
-                            "pid-info-value-cooling-text")),
-            Map.entry("0x0135",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-switchover-heating-cooling", "pid-switchover-heating-cooling-text")),
-            Map.entry("0x0136",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-actuating-fan-stage-heating", "pid-actuating-fan-stage-heating-text")),
-            Map.entry("0x0140",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "7", "30",
-                            "pid-absolute-setpoint-temperature", "pid-absolute-setpoint-temperature-text")),
-            Map.entry("0x0141",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-additional-heating-value-info", "pid-additional-heating-value-info-text")),
-            Map.entry("0x0142",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-additional-cooling-value-info", "pid-additional-cooling-value-info-text")),
-            Map.entry("0x0143",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-control-value-additional-heating", "pid-control-value-additional-heating-text")),
-            Map.entry("0x0144",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-control-value-additional-cooling", "pid-control-value-additional-cooling-text")),
-            Map.entry("0x0145",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-actuating-fan-stage-heating", "pid-info-actuating-fan-stage-heating-text")),
-            Map.entry("0x0146",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-actuating-fan-manual-on-off-heating",
-                            "pid-info-actuating-fan-manual-on-off-heating-text")),
-            Map.entry("0x0147",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-actuating-fan-stage-cooling", "pid-actuating-fan-stage-cooling-text")),
-            Map.entry("0x0149",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-info-fan-stage-cooling", "pid-info-fan-stage-cooling-text")),
-            Map.entry("0x014A",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_TEMPERATURE, "", "",
-                            "pid-info-fan-manual-on-off-cooling", "pid-info-fan-manual-on-off-cooling-text")),
-            Map.entry("0x014B",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-heating-active",
-                            "pid-heating-active-text")),
-            Map.entry("0x014C",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-cooling-active",
-                            "pid-cooling-active-text")),
-            Map.entry("0x014D",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-heating-demand",
-                            "pid-heating-demand-text")),
-            Map.entry("0x014E",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "", "pid-cooling-demand",
-                            "pid-cooling-demand-text")),
-            Map.entry("0x014F",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-heating-demand-feedback-signal", "pid-heating-demand-feedback-signal-text")),
-            Map.entry("0x0150",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_TEMPERATURE, "", "",
-                            "pid-cooling-demand-feedback-signal", "pid-cooling-demand-feedback-signal-text")),
-            Map.entry("0x0151",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_HUMIDITY, "", "", "pid-humidity",
-                            "pid-humidity-text")),
-            Map.entry("0x0152",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-aux-on-off-request",
-                            "pid-aux-on-off-request-text")),
-            Map.entry("0x0153",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-aux-on-off-response",
-                            "pid-aux-on-off-response-text")),
-            Map.entry("0x0154",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-heating-on-off-request",
-                            "pid-heating-on-off-request-text")),
-            Map.entry("0x0155",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-cooling-on-off-request",
-                            "pid-cooling-on-off-request-text")),
-            Map.entry("0x0156",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-operation-mode",
-                            "pid-operation-mode-text")),
-            Map.entry("0x0157",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-swing-h-v",
-                            "pid-swing-h-v-text")),
-            Map.entry("0x0158",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-supported-features",
-                            "pid-supported-features-text")),
-            Map.entry("0x0159",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-extended-status-indication", "pid-extended-status-indication-text")),
-            Map.entry("0x015A",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-extended-status-indication", "pid-extended-status-indication-text")),
-            Map.entry("0x015B",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-aux-heating-on-off-request", "pid-aux-heating-on-off-request-text")),
-            Map.entry("0x015C",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-emergency-heating-on-off-request", "pid-emergency-heating-on-off-request-text")),
-            Map.entry("0x0160",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-relative-fan-speed-control", "pid-relative-fan-speed-control-text")),
-            Map.entry("0x0161",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-absolute-fan-speed-control", "pid-absolute-fan-speed-control-text")),
-            Map.entry("0x0162",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-absolute-fan-speed", "pid-info-absolute-fan-speed-text")),
-            Map.entry("0x0163",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-sysap-infoactualfanspeed", "pid-sysap-infoactualfanspeed-text")),
-            Map.entry("0x01A0",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-notification-flags",
-                            "pid-notification-flags-text")),
-            Map.entry("0x0280",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-power-rc",
-                            "pid-power-rc-text")),
-            Map.entry("0x0281",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-power-rh",
-                            "pid-power-rh-text")),
-            Map.entry("0x0282",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proximity-status",
-                            "pid-proximity-status-text")),
-            Map.entry("0x0290",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-brightness-sensor",
-                            "pid-brightness-sensor-text")),
-            Map.entry("0x0291",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-last-touch",
-                            "pid-last-touch-text")),
-            Map.entry("0x0292",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-led-backlighting-night-mode", "pid-led-backlighting-night-mode-text")),
-            Map.entry("0x02C0",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-locator-beep",
-                            "pid-locator-beep-text")),
-            Map.entry("0x02C1",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-switch-test-alarm",
-                            "pid-switch-test-alarm-text")),
-            Map.entry("0x02C3",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-fire-alarm-active",
-                            "pid-fire-alarm-active-text")),
-            Map.entry("0x0400",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_TEMPERATURE, "", "",
-                            "pid-outside-temperature", "pid-outside-temperature-text")),
-            Map.entry("0x0401",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_WIND, "", "", "pid-wind-force",
-                            "pid-wind-force-text")),
-            Map.entry("0x0402",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_UNDEFINED, "", "", "pid-brightness-alarm",
-                            "pid-brightness-alarm-text")),
-            Map.entry("0x0403",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_UNDEFINED, "", "", "pid-lux-value",
-                            "pid-lux-value-text")),
-            Map.entry("0x0404",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_WIND, "", "", "pid-wind-speed",
-                            "pid-wind-speed-text")),
-            Map.entry("0x0405",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_RAIN, "", "", "pid-rain-detection",
-                            "pid-rain-detection-text")),
-            Map.entry("0x0406",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_RAIN, "", "", "pid-rain-sensor-frequency",
-                            "pid-rain-sensor-frequency-text")),
-            Map.entry("0x0440",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play",
-                            "pid-play-text")),
-            Map.entry("0x0441",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-pause",
-                            "pid-pause-text")),
-            Map.entry("0x0442",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-next",
-                            "pid-next-text")),
-            Map.entry("0x0443",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-previous",
-                            "pid-previous-text")),
-            Map.entry("0x0444",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play-mode",
-                            "pid-play-mode-text")),
-            Map.entry("0x0445",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-mute",
-                            "pid-mute-text")),
-            Map.entry("0x0446",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-relative-volume-control", "pid-relative-volume-control-text")),
-            Map.entry("0x0447",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-absolute-volume-control", "pid-absolute-volume-control-text")),
-            Map.entry("0x0448",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-group-membership",
-                            "pid-group-membership-text")),
-            Map.entry("0x0449",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play-favorite",
-                            "pid-play-favorite-text")),
-            Map.entry("0x044A",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-play-next-favorite",
-                            "pid-play-next-favorite-text")),
-            Map.entry("0x0460",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-playback-status",
-                            "pid-playback-status-text")),
-            Map.entry("0x0461",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-current-item-metadata-info", "pid-current-item-metadata-info-text")),
-            Map.entry("0x0462",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-mute",
-                            "pid-info-mute-text")),
-            Map.entry("0x0463",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-actual-volume",
-                            "pid-info-actual-volume-text")),
-            Map.entry("0x0464",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-allowed-playback-actions", "pid-allowed-playback-actions-text")),
-            Map.entry("0x0465",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-group-membership", "pid-info-group-membership-text")),
-            Map.entry("0x0466",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-playing-favorite", "pid-info-playing-favorite-text")),
-            Map.entry("0x0467",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-absolute-group-volume-control", "pid-absolute-group-volume-control-text")),
-            Map.entry("0x0468",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-absolute-group-volume", "pid-info-absolute-group-volume-text")),
-            Map.entry("0x0469",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-media-source",
-                            "pid-media-source-text")),
-            Map.entry("0x04A0",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-solar-power-production", "pid-solar-power-production-text")),
-            Map.entry("0x04A1",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-inverter-output-power", "pid-inverter-output-power-text")),
-            Map.entry("0x04A2",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-solar-energy-(today)",
-                            "pid-solar-energy-(today)-text")),
-            Map.entry("0x04A3",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-injected-energy-(today)", "pid-injected-energy-(today)-text")),
-            Map.entry("0x04A4",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-purchased-energy-(today)", "pid-purchased-energy-(today)-text")),
-            Map.entry("0x04A5",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-inverter-alarm",
-                            "pid-inverter-alarm-text")),
-            Map.entry("0x04A6",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-self-consumption",
-                            "pid-self-consumption-text")),
-            Map.entry("0x04A7",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-self-sufficiency",
-                            "pid-self-sufficiency-text")),
-            Map.entry("0x04A8",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-home-power-consumption", "pid-home-power-consumption-text")),
-            Map.entry("0x04A9",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-power-to-grid",
-                            "pid-power-to-grid-text")),
-            Map.entry("0x04AA",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-consumed-energy-(today)", "pid-consumed-energy-(today)-text")),
-            Map.entry("0x04AB",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-meter-alarm",
-                            "pid-meter-alarm-text")),
-            Map.entry("0x04AC",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-battery-level",
-                            "pid-battery-level-text")),
-            Map.entry("0x04AD",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-battery-power",
-                            "pid-battery-power-text")),
-            Map.entry("0x04B0",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-boost",
-                            "pid-boost-text")),
-            Map.entry("0x04B1",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-stop-charging-reuqest", "pid-stop-charging-reuqest-text")),
-            Map.entry("0x04B2",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-enable-charging-reuqest", "pid-enable-charging-reuqest-text")),
-            Map.entry("0x04B3",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-boost",
-                            "pid-info-boost-text")),
-            Map.entry("0x04B4",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-wallbox-status",
-                            "pid-info-wallbox-status-text")),
-            Map.entry("0x04B5",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-charging",
-                            "pid-info-charging-text")),
-            Map.entry("0x04B6",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-charging-enabled", "pid-info-charging-enabled-text")),
-            Map.entry("0x04B7",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-installed-power",
-                            "pid-info-installed-power-text")),
-            Map.entry("0x04B8",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-transmitted-energy", "pid-info-transmitted-energy-text")),
-            Map.entry("0x04B9",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-car-range",
-                            "pid-info-car-range-text")),
-            Map.entry("0x04BA",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-charging-duration", "pid-info-charging-duration-text")),
-            Map.entry("0x04BB",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-current-limit",
-                            "pid-info-current-limit-text")),
-            Map.entry("0x04BC",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-current-limit-for-group", "pid-info-current-limit-for-group-text")),
-            Map.entry("0x04BD",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-album-cover-url",
-                            "pid-album-cover-url-text")),
-            Map.entry("0x0501",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-secure@home-central-unit", "pid-secure@home-central-unit-text")),
-            Map.entry("0x0502",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-domusdisarmcounter",
-                            "pid-domusdisarmcounter-text")),
-            Map.entry("0x0504",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-intrusion-alarm",
-                            "pid-intrusion-alarm-text")),
-            Map.entry("0x0505",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-safety-alarm",
-                            "pid-safety-alarm-text")),
-            Map.entry("0x0507",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-infoconfigurationstatus", "pid-infoconfigurationstatus-text")),
-            Map.entry("0x0508",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-enable-configuration",
-                            "pid-enable-configuration-text")),
-            Map.entry("0x0509",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-disarming-led",
-                            "pid-disarming-led-text")),
-            Map.entry("0x050A",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-aes-key",
-                            "pid-aes-key-text")),
-            Map.entry("0x050B",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-zone-status",
-                            "pid-zone-status-text")),
-            Map.entry("0x050E",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-time",
-                            "pid-time-text")),
-            Map.entry("0x0600",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-start-stop",
-                            "pid-start-stop-text")),
-            Map.entry("0x0601",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-pause-resume",
-                            "pid-pause-resume-text")),
-            Map.entry("0x0602",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-select-program",
-                            "pid-select-program-text")),
-            Map.entry("0x0603",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-delayed-start-time",
-                            "pid-delayed-start-time-text")),
-            Map.entry("0x0604",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-status",
-                            "pid-info-status-text")),
-            Map.entry("0x0605",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-remote-start-enabled", "pid-info-remote-start-enabled-text")),
-            Map.entry("0x0606",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-program",
-                            "pid-info-program-text")),
-            Map.entry("0x0607",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-finish-time",
-                            "pid-info-finish-time-text")),
-            Map.entry("0x0608",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-delayed-start",
-                            "pid-info-delayed-start-text")),
-            Map.entry("0x0609",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-door",
-                            "pid-info-door-text")),
-            Map.entry("0x060A",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-door-alarm",
-                            "pid-info-door-alarm-text")),
-            Map.entry("0x060B",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-switch-supercool",
-                            "pid-switch-supercool-text")),
-            Map.entry("0x060C",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-switch-superfreeze",
-                            "pid-switch-superfreeze-text")),
-            Map.entry("0x060D",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-switch-supercool", "pid-info-switch-supercool-text")),
-            Map.entry("0x060E",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-info-switch-superfreeze", "pid-info-switch-superfreeze-text")),
-            Map.entry("0x060F",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-measured-temperature",
-                            "pid-measured-temperature-text")),
-            Map.entry("0x0610",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-measured-temperature",
-                            "pid-measured-temperature-text")),
-            Map.entry("0x0611",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-set-value-temperature", "pid-set-value-temperature-text")),
-            Map.entry("0x0612",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-set-value-temperature", "pid-set-value-temperature-text")),
-            Map.entry("0x0613",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-change-operation",
-                            "pid-change-operation-text")),
-            Map.entry("0x0614",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-detailed-status-info",
-                            "pid-detailed-status-info-text")),
-            Map.entry("0x0615",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-remaining-time",
-                            "pid-info-remaining-time-text")),
-            Map.entry("0x0616",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-time-of-last-status-change", "pid-time-of-last-status-change-text")),
-            Map.entry("0x0618",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-lock-unlock-door-command", "pid-lock-unlock-door-command-text")),
-            Map.entry("0x0619",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-locked-unlocked",
-                            "pid-info-locked-unlocked-text")),
-            Map.entry("0xF001",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-time",
-                            "pid-time-text")),
-            Map.entry("0xF002",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-date",
-                            "pid-date-text")),
-            Map.entry("0xF003",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-notification",
-                            "pid-notification-text")),
-            Map.entry("0xF101",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "", "pid-switch-entity-on-off",
-                            "pid-switch-entity-on-off-text")),
-            Map.entry("0xF102",
-                    new PIdContainerClass(PID_VALUETYPE_BOOLEAN, CATEGORY_SWITCH, "", "",
-                            "pid-info-switch-entity-on-off", "pid-info-switch-entity-on-off-text")),
-            Map.entry("0xF104",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-consistency-tag",
-                            "pid-consistency-tag-text")),
-            Map.entry("0xF105",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-battery-status",
-                            "pid-battery-status-text")),
-            Map.entry("0xF106",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-stay-awake",
-                            "pid-stay-awake-text")),
-            Map.entry("0xF107",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy-switch",
-                            "pid-proxy-switch-text")),
-            Map.entry("0xF108",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy1",
-                            "pid-proxy1-text")),
-            Map.entry("0xF109",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy2",
-                            "pid-proxy2-text")),
-            Map.entry("0xF10A",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-proxy4",
-                            "pid-proxy4-text")),
-            Map.entry("0xF10B",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-cyclic-sleep-time",
-                            "pid-cyclic-sleep-time-text")),
-            Map.entry("0xF10C",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-presence",
-                            "pid-presence-text")),
-            Map.entry("0xF10D",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-measured-temperature-1", "pid-measured-temperature-1-text")),
-            Map.entry("0xF10E",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-standby-statistics",
-                            "pid-standby-statistics-text")),
-            Map.entry("0xF10F",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-heartbeat-delay",
-                            "pid-heartbeat-delay-text")),
-            Map.entry("0xF110",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "", "pid-info-heartbeat-delay",
-                            "pid-info-heartbeat-delay-text")),
-            Map.entry("0xFF01",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-measured-temperature-1", "pid-measured-temperature-1-text")),
-            Map.entry("0xFF02",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-measured-temperature-2", "pid-measured-temperature-2-text")),
-            Map.entry("0xFF03",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-measured-temperature-3", "pid-measured-temperature-3-text")),
-            Map.entry("0xFF04",
-                    new PIdContainerClass(PID_VALUETYPE_UNKNOWN, CATEGORY_UNDEFINED, "", "",
-                            "pid-measured-temperature-4", "pid-measured-temperature-4-text")),
-            Map.entry("0x061A",
-                    new PIdContainerClass(PID_VALUETYPE_DECIMAL, CATEGORY_PRESSURE, "", "",
-                            "pid-air-quality-pressure-value", "pid-air-quality-pressure-value-text")),
-            Map.entry("0x061B",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                            "pid-air-quality-co2-value", "pid-air-quality-co2-value-text")),
-            Map.entry("0x061C",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-air-quality-co-value",
-                            "pid-air-quality-co-value-text")),
-            Map.entry("0x061D",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                            "pid-air-quality-no2-value", "pid-air-quality-no2-value-text")),
-            Map.entry("0x061E",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "", "pid-air-quality-o3-value",
-                            "pid-air-quality-o3-value-text")),
-            Map.entry("0x061F",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                            "pid-air-quality-pm10-value", "pid-air-quality-pm10-value-text")),
-            Map.entry("0x0620",
-                    new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                            "pid-air-quality-pm25-value", "pid-air-quality-pm25-value-text")),
-            Map.entry("0x0621", new PIdContainerClass(PID_VALUETYPE_INTEGER, CATEGORY_UNDEFINED, "", "",
-                    "pid-air-quality-voc-value", "pid-air-quality-voc-value-text")));
-
-    public static String getShortTextForPairingId(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.label;
-    }
-
-    public static String getDescriptionTextForPairingId(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.description;
-    }
-
-    public static String getValueTypeForPairingId(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.valueType;
-    }
-
-    public static String getItemTypeForPairingId(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.category;
-    }
-
-    public static String getCategoryForPairingId(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.category;
-    }
-
-    public static String getPatternForPairingId(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.category;
-    }
-
-    public static int getMax(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.max;
-    }
-
-    public static int getMin(String Key) throws FreeAtHomeGeneralException {
-        PIdContainerClass desc = MAP_PAIRING_ID.get(Key);
-
-        if (desc == null) {
-            throw new FreeAtHomeGeneralException(0,
-                    String.format("%s - Key:%s", "PID is not in the translation table", Key));
-        }
-
-        return desc.min;
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/UidUtils.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/util/UidUtils.java
deleted file mode 100644 (file)
index 9b7f4ce..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.util;
-
-import static org.openhab.binding.freeathomesystem.internal.FreeAtHomeSystemBindingConstants.*;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.ThingTypeUID;
-import org.openhab.core.thing.type.ChannelTypeUID;
-
-/**
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class UidUtils {
-
-    public static ChannelTypeUID generateChannelTypeUID(String valueType, boolean isReadOnly) {
-        String channelNameString;
-
-        if (isReadOnly) {
-            channelNameString = valueType + "-ro";
-        } else {
-            channelNameString = valueType;
-        }
-
-        return new ChannelTypeUID(BINDING_ID, channelNameString);
-    }
-
-    public static ThingTypeUID generateThingUID() {
-        return new ThingTypeUID(BINDING_ID, DEVICE_TYPE_ID);
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BinaryValueStateConverter.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BinaryValueStateConverter.java
deleted file mode 100644 (file)
index 7fc2d63..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.valuestateconverter;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.library.types.OnOffType;
-import org.openhab.core.types.State;
-
-/**
- * The {@link BinaryValueStateConverter} is a value converter for integer values with a specific mask
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class BinaryValueStateConverter implements ValueStateConverter {
-
-    private int maskValue;
-
-    public BinaryValueStateConverter(int mask) {
-        maskValue = mask;
-    }
-
-    @Override
-    public State convertToState(String value) {
-        int intValue = Integer.decode(value);
-        int result;
-
-        result = intValue & maskValue;
-
-        if (maskValue == result) {
-            return OnOffType.ON;
-        } else {
-            return OnOffType.OFF;
-        }
-    }
-
-    @Override
-    public String convertToValueString(State state) {
-        if (state.equals(OnOffType.ON)) {
-            return "1";
-        }
-
-        if (state.equals(OnOffType.OFF)) {
-            return "0";
-        }
-
-        return "";
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BooleanValueStateConverter.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/BooleanValueStateConverter.java
deleted file mode 100644 (file)
index e07a519..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.valuestateconverter;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.library.types.OnOffType;
-import org.openhab.core.types.State;
-
-/**
- * The {@link DecimalValueStateConverter} is a value converter for boolean values
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class BooleanValueStateConverter implements ValueStateConverter {
-
-    @Override
-    public State convertToState(String value) {
-        return OnOffType.from(value);
-    }
-
-    @Override
-    public String convertToValueString(State state) {
-        if (state.equals(OnOffType.ON)) {
-            return "1";
-        }
-
-        if (state.equals(OnOffType.OFF)) {
-            return "0";
-        }
-
-        return "";
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/DecimalValueStateConverter.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/DecimalValueStateConverter.java
deleted file mode 100644 (file)
index 5945c18..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.valuestateconverter;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.library.types.DecimalType;
-import org.openhab.core.types.State;
-
-/**
- * The {@link DecimalValueStateConverter} is a value converter for decimal values
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class DecimalValueStateConverter implements ValueStateConverter {
-
-    @Override
-    public State convertToState(String value) {
-        return new DecimalType(value);
-    }
-
-    @Override
-    public String convertToValueString(State state) {
-        return ((DecimalType) state).toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ShuttercontrolValueStateConverter.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ShuttercontrolValueStateConverter.java
deleted file mode 100644 (file)
index 66996dc..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.valuestateconverter;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.library.types.StopMoveType;
-import org.openhab.core.library.types.StringType;
-import org.openhab.core.library.types.UpDownType;
-import org.openhab.core.types.Command;
-import org.openhab.core.types.State;
-
-/**
- * The {@link ShuttercontrolValueStateConverter} is a value converter for shutter movement
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public class ShuttercontrolValueStateConverter implements ValueStateConverter {
-
-    @Override
-    public State convertToState(String value) {
-        State ret = UpDownType.DOWN;
-
-        switch (value) {
-            default:
-            case "0":
-                ret = new StringType("STOP");
-                break;
-            case "2":
-                ret = UpDownType.UP;
-                break;
-            case "3":
-                ret = UpDownType.DOWN;
-                break;
-        }
-
-        return ret;
-    }
-
-    @Override
-    public String convertToValueString(State state) {
-        String valueString = "0";
-        String stateString = "STOP";
-
-        if (state instanceof UpDownType) {
-            stateString = ((UpDownType) state).toString();
-        }
-
-        if (((Command) state) instanceof StopMoveType) {
-            stateString = "STOP";
-        }
-
-        switch (stateString) {
-            default:
-            case "STOP":
-                valueString = "0";
-                break;
-            case "UP":
-                valueString = "0";
-                break;
-            case "DOWN":
-                valueString = "1";
-                break;
-        }
-
-        return valueString;
-    }
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ValueStateConverter.java b/bundles/org.openhab.binding.freeathomesystem/src/main/java/org/openhab/binding/freeathomesystem/internal/valuestateconverter/ValueStateConverter.java
deleted file mode 100644 (file)
index 80187ff..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.freeathomesystem.internal.valuestateconverter;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.types.State;
-
-/**
- * The {@link ValueStateConverter} base class for the value state converters
- *
- * @author Andras Uhrin - Initial contribution
- *
- */
-@NonNullByDefault
-public interface ValueStateConverter {
-    public State convertToState(String value);
-
-    public String convertToValueString(State state);
-}
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/addon/addon.xml
deleted file mode 100644 (file)
index ccfa0e3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<addon:addon id="freeathomesystem" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
-       xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
-
-       <type>binding</type>
-       <name>FreeAtHomeSystem Binding</name>
-       <description>This is the binding for free@home system.</description>
-       <connection>local</connection>
-</addon:addon>
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/i18n/freeathomesystem.properties b/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/i18n/freeathomesystem.properties
deleted file mode 100644 (file)
index 9b021ff..0000000
+++ /dev/null
@@ -1,652 +0,0 @@
-# add-on
-
-addon.freeathomesystem.name = FreeAtHomeSystem Binding
-addon.freeathomesystem.description = This is the binding for free@home system.
-
-# thing types
-
-thing-type.freeathomesystem.device.label = free@home Device
-thing-type.freeathomesystem.device.description = This represents the generic free@home device
-thing-type.freeathomesystem.gateway.label = free@home Gateway
-thing-type.freeathomesystem.gateway.description = This gateway represents the free@home Gateway
-
-# thing types config
-
-thing-type.config.freeathomesystem.device.deviceId.label = Device Id
-thing-type.config.freeathomesystem.device.deviceId.description = This is the unique id of the free@home device (Please do not modify after the Thing is generated)
-thing-type.config.freeathomesystem.gateway.group.identification.label = SysAP Setting
-thing-type.config.freeathomesystem.gateway.group.identification.description = SysAP network address and user settings
-thing-type.config.freeathomesystem.gateway.ipAddress.label = Sysap IP Address
-thing-type.config.freeathomesystem.gateway.ipAddress.description = IP Address of the Busch-Jaeger Gateway
-thing-type.config.freeathomesystem.gateway.password.label = Password
-thing-type.config.freeathomesystem.gateway.password.description = Password for gateway
-thing-type.config.freeathomesystem.gateway.username.label = User Name
-thing-type.config.freeathomesystem.gateway.username.description = The login name
-
-# localized error text
-
-comm-error.not-able-open-httpconnection = Cannot open http connection, wrong password
-comm-error.http-wrongpass-or-ip = Cannot open http connection, wrong password or IP address
-comm-error.not-able-open-websocketconnection = Cannot open websocket connection
-comm-error.general-websocket-issue = General issue in websocket connection
-comm-error.websocket-keep-alive-error = Websocket keep alive error
-comm-error.wrong-credentials = Wrong credentials for SysAP
-comm-error.error-in-sysap-com = Error in SysAp communication
-conf-error.general-binding-error = General binding error!
-conf-error.datapointgroup-invalid = Datapoint group is not valid!
-conf-error.inputdatapoint-invalid = Input Datapoint is not valid!
-conf-error.invalid-deviceconfig = Invalid device configuration!
-conf-error.invalid-bridge = Invalid bridge!
-conf-error.bridge-not-configured = Bridge not configured!
-conf-error.ip-address-missing = IP address is not specified!
-conf-error.username-missing = User name is not specified!
-conf-error.password-missing = Password is not specified!
-conf-error.device-desc-null = Device description is NULL!
-gen-error.no-bridge-avail = No bridge available!
-
-# localized info text for function id
-
-fid-dimming-sensor = Dimming sensor
-fid-blind-sensor = Blind sensor
-fid-stairwell-light-sensor = Stairwell light sensor
-fid-force-on/off-sensor = Force On/Off sensor
-fid-scene-sensor = Scene sensor
-fid-switch-actuator = Switch actuator
-fid-blind-actuator = Blind actuator
-fid-room-temperature-controller-with-fan-speed-level = Room temperature controller with fan speed level
-fid-room-temperature-controller-extension-unit = Room temperature controller extension unit
-fid-wind-alarm = Wind Alarm
-fid-frost-alarm = Frost Alarm
-fid-rain-alarm = Rain Alarm
-fid-window-sensor = Window sensor
-fid-movement-detector = Movement Detector
-fid-dim-actuator = Dim actuator
-fid-radiator = Radiator
-fid-underfloor-heating = Underfloor heating
-fid-fan-coil = Fan Coil
-fid-two-level-controller = Two-level controller
-fid-door-opener = Door opener
-fid-proxy = Proxy
-fid-door-map.entry-system-call-level-actuator = Door Map.entry System Call Level Actuator
-fid-door-map.entry-system-call-level-sensor = Door Map.entry System Call Level Sensor
-fid-door-call = Door call
-fid-automatic-door-opener = Automatic door opener
-fid-corridor-light = Corridor light
-fid-room-temperature-controller = Room temperature controller
-fid-cooling-mode = Cooling mode
-fid-heating-mode = Heating mode
-fid-force-position-blind = Force-position blind
-fid-auto.-heating/cooling-mode = Auto. heating/cooling mode
-fid-switchover-heating/cooling = Switchover heating/cooling
-fid-device-settings = Device settings
-fid-dim-actuator = Dim actuator
-fid-dim-actuator = Dim actuator
-fid-control-element = Control element
-fid-dimming-sensor = Dimming sensor
-fid-blind-sensor = Blind sensor
-fid-stairwell-light-sensor = Stairwell light sensor
-fid-force-on/off-sensor = Force On/Off sensor
-fid-force-position-blind = Force-position blind
-fid-scene-sensor = Scene sensor
-fid-room-temperature-controller-extension-unit = Room temperature controller extension unit
-fid-fan-coil-sensor = Fan coil sensor
-fid-rgb-+-warm-white/cold-white-sensor = RGB + warm white/cold white sensor
-fid-rgb-sensor = RGB sensor
-fid-warm-white/cold-white-sensor = Warm white/cold white sensor
-fid-add.-stage-for-heating-mode = Add. stage for heating mode
-fid-radiator-thermostate = Radiator thermostate
-fid-room-temperature-controller-extension-unit = Room temperature controller extension unit
-fid-brightness-sensor = Brightness sensor
-fid-rain-sensor = Rain sensor
-fid-temperature-sensor = Temperature sensor
-fid-wind-sensor = Wind sensor
-fid-trigger = Trigger
-fid-heating-mode = Heating mode
-fid-cooling-mode = Cooling mode
-fid-auto.-heating/cooling-mode = Auto. heating/cooling mode
-fid-two-valves-for-heating-and-cooling = Two valves for heating and cooling
-fid-window/door = Window/Door
-fid-abc = ABC
-fid-abd = ABD
-fid-acd = ACD
-fid-timer-program-switch-sensor = Timer program switch sensor
-fid-zone = Zone
-fid-central-heating-actuator = Central heating actuator
-fid-central-cooling-actuator = Central cooling actuator
-fid-housekeeping = Housekeeping
-fid-media-player = Media Player
-fid-panel-room-temperature-controller-slave-for-battery-device = Panel Room Temperature Controller Slave For Battery Device
-fid-media-player-sensor = Media Player Sensor
-fid-roller-blind-actuator = Roller blind actuator
-fid-attic-window-actuator = Attic window actuator
-fid-awning-actuator = Awning actuator
-fid-windowdoor-position-sensor = WindowDoor Position Sensor
-fid-window/door-position = Window/Door position
-fid-media-playback-control-sensor = Media playback control sensor
-fid-media-volume-sensor = Media volume sensor
-fid-dishwasher = Dishwasher
-fid-laundry = Laundry
-fid-dryer = Dryer
-fid-oven = Oven
-fid-fridge = Fridge
-fid-freezer = Freezer
-fid-hood = Hood
-fid-coffee-machine = Coffee machine
-fid-fridge/freezer = Fridge/Freezer
-fid-timer-program-switch-sensor = Timer program switch sensor
-fid-ceiling-fan-actuator = Ceiling fan actuator
-fid-ceiling-fan-sensor = Ceiling fan sensor
-fid-room-temperature-controller-with-fan-speed-level = Room temperature controller with fan speed level
-fid-zone = Zone
-fid-safety = Safety
-fid-external-ir-sensor-bx80 = External IR Sensor BX80
-fid-external-ir-sensor-vxi = External IR Sensor VXI
-fid-external-ir-sensor-mini = External IR Sensor Mini
-fid-external-ir-sensor-high-altitude = External IR Sensor High Altitude
-fid-external-ir-sensor-curtain = External IR Sensor Curtain
-fid-smoke-detector = Smoke Detector
-fid-carbon-monoxide-sensor = Carbon Monoxide Sensor
-fid-methane-detector = Methane Detector
-fid-gas-sensor-lpg = Gas Sensor LPG
-fid-flood-detection = Flood Detection
-fid-secure@home-central-unit = secure@home Central Unit
-fid-thermostat = Thermostat
-fid-secure@home-zone-sensor = secure@home Zone Sensor
-fid-slave-thermostat = Slave thermostat
-fid-secure@home-integration-logic = secure@home Integration Logic
-fid-add.-stage-for-cooling-mode = Add. stage for cooling mode
-fid-two-level-heating-actuator = Two Level Heating Actuator
-fid-two-level-cooling-actuator = Two Level Cooling Actuator
-fid-zone = Zone
-fid-volume-up = Volume up
-fid-volume-down = Volume down
-fid-play/pause = Play/pause
-fid-next-favorite = Next favorite
-fid-next-song = Next song
-fid-previous-song = Previous song
-fid-home-appliance-sensor = Home appliance sensor
-fid-heat-sensor = Heat sensor
-fid-zone-switching = Zone switching
-fid-button-function = Button function
-fid-advanced-configuration = Advanced configuration
-fid-secure@home-central-unit-basic = secure@home Central Unit Basic
-fid-repeater = Repeater
-fid-remote-scene-control = Remote scene control
-fid-window-sensor = Window sensor
-fid-movement-detector = Movement Detector
-fid-external-ir-sensor-curtain = External IR Sensor Curtain
-fid-smoke-detector = Smoke Detector
-fid-flood-detection = Flood Detection
-fid-sensor-for-air-conditioning-unit = Sensor for air-conditioning unit
-fid-two-point-controller-for-heating-or-cooling = Two-point controller for heating or cooling
-fid-slave-thermostat = Slave thermostat
-fid-wallbox = Wallbox
-fid-door-lock-control = Door lock control
-fid-room-temperature-controller-with-fan-speed-level = Room temperature controller with fan speed level
-fid-scene-trigger = Scene trigger
-fid-rule-switch = Rule Switch
-fid-air-quality-sensor-pressure = Air quality sensor Pressure
-fid-air-quality-sensor-co2 = Air quality sensor CO2
-fid-air-quality-sensor-co = Air quality sensor CO
-fid-air-quality-sensor-no2 = Air quality sensor NO2
-fid-air-quality-sensor-o3 = Air quality sensor O3
-fid-air-quality-sensor-pm10 = Air quality sensor PM10
-fid-air-quality-sensor-pm25 = Air quality sensor PM25
-fid-air-quality-sensor-voc = Air quality sensor VOC
-fid-air-quality-sensor-humidity = Air quality sensor humidity
-fid-movement-detector-fle = Movement detector (flex)
-fid-dim-actuator-flex = Dim actuator (flex)
-
-# localized info text for pairing id
-
-pid-switch-on-off = Switch
-pid-timed-start-stop = Timed Start/Stop
-pid-force-position = Force-position
-pid-scene-control = Scene Control
-pid-movement-under-consideration-of-brightness = Movement under consideration of brightness
-pid-presence = Presence
-pid-relative-set-value = Relative Set Value
-pid-absolute-set-value = Set Value
-pid-night = Night
-pid-invalid-string-id = invalid string id
-pid-rgb-color = RGB color
-pid-color-temperature = Color Temperature
-pid-hsv = HSV
-pid-hue = HUE
-pid-saturation = Saturation
-pid-move-up-down = Move Up/Down
-pid-adjust-up-down = Adjust Up/Down
-pid-set-absolute-position-blinds = Blinds Position
-pid-set-absolute-position-slats = Slats Position
-pid-wind-alarm = Wind Alarm
-pid-frost-alarm = Frost Alarm
-pid-rain-alarm = Rain Alarm
-pid-force-position-blind = Force-position blind
-pid-window-door-position = Window/Door position
-pid-actuating-value-heating = Actuating Value Heating
-pid-fan-level-heating = Fan Level Heating
-pid-actuating-value-cooling = Actuating Value Cooling
-pid-set-value-temperature = Set Value Temperature
-pid-relative-set-point-temperature = Relative Setpoint Temperature
-pid-window-door = Window/Door
-pid-status-indication = Status
-pid-fan-manual-heating-on-off = Fan Manual Heating
-pid-controller-on-off = Controller
-pid-relative-set-point-request = Relative Setpoint Request
-pid-eco-mode-on-off-request = Eco mode
-pid-comfort-temperature = Comfort Temperature
-pid-fan-level-request = Fan Level
-pid-fan-manual-on-off-request = Fan Switch
-pid-controller-on-off-request = Controller Switch
-pid-eco-mode-on-off-request = Eco mode
-pid-info-on-off = Status info
-pid-force-position-info = Force-position
-pid-sysap-infoonoff = SysAP-InfoOnOff
-pid-sysap-infoforce = SysAP-InfoForce
-pid-info-actual-dimming-value = Dimming Value
-pid-info-error = Error INfo
-pid-sysap-infocurrentdimmingvalue = SysAP-InfoCurrentDimmingValue
-pid-sysap-infoerror = SysAP-InfoError
-pid-info-color-temperature = Color Temperature
-pid-sysap-info-color-temperature = SysAP-Info Color Temperature
-pid-info-hsv = HSV
-pid-sysap-info-hsv = SysAP Info HSV
-pid-info-color-mode = Color Mode
-pid-sysap-info-color-mode = SysAP Info Color Mode
-pid-info-move-up-down = Move Up/Down
-pid-current-absolute-position-blinds-percentage = Blinds Position
-pid-current-absolute-position-slats-percentage = Slats Position
-pid-sysap-infomoveupdown = SysAP-InfoMoveUpDown
-pid-sysap-infocurrentabsoluteblindspercentage = SysAP-InfoCurrentAbsoluteBlindsPercentage
-pid-sysap-infocurrentabsoluteslatspercentage = SysAP-InfoCurrentAbsoluteSlatsPercentage
-pid-measured-temperature = Measured Temperature
-pid-info-value-heating = Heating Value
-pid-info-value-cooling = cooling Value
-pid-switchover-heating-cooling = Switchover heating/cooling
-pid-actuating-fan-stage-heating = Fan Heating Control
-pid-absolute-setpoint-temperature = Setpoint temperature
-pid-additional-heating-value-info = Additional heating Info
-pid-additional-cooling-value-info = Additional cooling Info
-pid-control-value-additional-heating = Additional heating Control
-pid-control-value-additional-cooling = Additional cooling  Control
-pid-info-actuating-fan-stage-heating = Fan Heating Info
-pid-info-actuating-fan-manual-on-off-heating = Fan Manual On/Off Heating
-pid-actuating-fan-stage-cooling = Fan Cooling Control
-pid-info-fan-stage-cooling = Fan Cooling Info
-pid-info-fan-manual-on-off-cooling = Fan Manual On/Off Cooling
-pid-heating-active = Heating active
-pid-cooling-active = Cooling active
-pid-heating-demand = Heating demand
-pid-cooling-demand = Cooling demand
-pid-heating-demand-feedback-signal = Heating demand feedback
-pid-cooling-demand-feedback-signal = Cooling demand feedback
-pid-humidity = Humidity
-pid-aux-on-off-request = Aux Switch
-pid-aux-on-off-response = Aux Swicth response
-pid-heating-on-off-request = Heating
-pid-cooling-on-off-request = Cooling
-pid-operation-mode = Operation mode
-pid-swing-h-v = Swing H/V
-pid-supported-features = Features
-pid-extended-status-indication = Extended Status Indication
-pid-extended-status-indication = Extended Status Indication
-pid-aux-heating-on-off-request = Aux Heating
-pid-emergency-heating-on-off-request = Emergency Heating
-pid-relative-fan-speed-control = Relative fan speed
-pid-absolute-fan-speed-control = Fan speed
-pid-info-absolute-fan-speed = Fan speed feedback
-pid-sysap-infoactualfanspeed = SysAP-InfoActualFanSpeed
-pid-notification-flags = Notification flags
-pid-power-rc = Power RC
-pid-power-rh = Power RH
-pid-proximity-status = Proximity status
-pid-brightness-sensor = Brightness
-pid-last-touch = Last touch
-pid-led-backlighting-night-mode = LED backlighting
-pid-locator-beep = Locator beep
-pid-switch-test-alarm = Switch test alarm
-pid-fire-alarm-active = Fire alarm
-pid-outside-temperature = Outside temperature
-pid-wind-force = Wind force
-pid-brightness-alarm = Brightness alarm
-pid-lux-value = Lux value
-pid-wind-speed = Wind speed
-pid-rain-detection = Rain detection
-pid-rain-sensor-frequency = Rain sensor frequency
-pid-play = Play
-pid-pause = Pause
-pid-next = Next
-pid-previous = Previous
-pid-play-mode = Play mode
-pid-mute = Mute
-pid-relative-volume-control = Relative volume control
-pid-absolute-volume-control = Absolute volume control
-pid-group-membership = Group membership
-pid-play-favorite = Play favorite
-pid-play-next-favorite = Play next favorite
-pid-playback-status = Playback status
-pid-current-item-metadata-info = Current item metadata
-pid-info-mute = Mute Info
-pid-info-actual-volume = Actual volume
-pid-allowed-playback-actions = Playback actions
-pid-info-group-membership = Group membership Info
-pid-info-playing-favorite = Playing favorite Info
-pid-absolute-group-volume-control = Group Volume
-pid-info-absolute-group-volume = Group Volume INfo
-pid-media-source = Media source
-pid-solar-power-production = Power production
-pid-inverter-output-power = Inverter output power
-pid-solar-energy-(today) = Solar energy (today)
-pid-injected-energy-(today) = Injected energy (today)
-pid-purchased-energy-(today) = Purchased energy (today)
-pid-inverter-alarm = Inverter alarm
-pid-self-consumption = Self-consumption
-pid-self-sufficiency = Self-sufficiency
-pid-home-power-consumption = Home power consumption
-pid-power-to-grid = Power to grid
-pid-consumed-energy-(today) = Consumed energy (today)
-pid-meter-alarm = Meter alarm
-pid-battery-level = Battery level
-pid-battery-power = Battery power
-pid-boost = Boost
-pid-stop-charging-reuqest = Stop charging
-pid-enable-charging-reuqest = Enable charging
-pid-info-boost = Boost Info
-pid-info-wallbox-status = Wallbox status
-pid-info-charging = Charging INfo
-pid-info-charging-enabled = Charging enabled
-pid-info-installed-power = Installed power
-pid-info-transmitted-energy = Transmitted energy
-pid-info-car-range = Car range
-pid-info-charging-duration = Charging duration
-pid-info-current-limit = Current limit
-pid-info-current-limit-for-group = Current limit for group
-pid-album-cover-url = Cover
-pid-secure@home-central-unit = secure@home Central Unit
-pid-domusdisarmcounter = DomusDisarmCounter
-pid-intrusion-alarm = Intrusion Alarm
-pid-safety-alarm = Safety Alarm
-pid-infoconfigurationstatus = InfoConfigurationStatus
-pid-enable-configuration = Enable configuration
-pid-disarming-led = Disarming LED
-pid-aes-key = AES Key
-pid-zone-status = Zone status
-pid-time = Time
-pid-start-stop = Start / Stop
-pid-pause-resume = Pause / Resume
-pid-select-program = Select program
-pid-delayed-start-time = Delayed start time
-pid-info-status = Status
-pid-info-remote-start-enabled = Remote start enabled
-pid-info-program = Program
-pid-info-finish-time = Finish time
-pid-info-delayed-start = Delayed start
-pid-info-door = Door
-pid-info-door-alarm = Door alarm
-pid-switch-supercool = Supercool Info
-pid-switch-superfreeze = Superfreeze Info
-pid-info-switch-supercool = Supercool switch
-pid-info-switch-superfreeze = Superfreeze switch
-pid-measured-temperature = Measured Temperature
-pid-set-value-temperature = Set Value Temperature
-pid-change-operation = Operation
-pid-detailed-status-info = Status
-pid-info-remaining-time = Remaining time
-pid-time-of-last-status-change = Time of last change
-pid-lock-unlock-door-command = Door lock
-pid-info-locked-unlocked = Door Status
-pid-time = Time
-pid-date = Date
-pid-notification = Notification
-pid-switch-entity-on-off = Switch
-pid-info-switch-entity-on-off = Switch feedback
-pid-consistency-tag = Consistency Tag
-pid-battery-status = Battery Status
-pid-stay-awake = Stay awake!
-pid-proxy-switch = Proxy switch
-pid-proxy1 = Proxy 1Byte
-pid-proxy2 = Proxy 2Byte
-pid-proxy4 = Proxy 4Byte
-pid-cyclic-sleep-time = Sleep time
-pid-presence = Presence
-pid-measured-temperature-1 = Measured temperature
-pid-standby-statistics = Standby Statistics
-pid-heartbeat-delay = Heartbeat delay
-pid-info-heartbeat-delay = Heartbeat delay
-pid-measured-temperature-1 = Measured temperature
-pid-measured-temperature-2 = Measured temperature
-pid-measured-temperature-3 = Measured temperature
-pid-measured-temperature-4 = Measured temperature
-pid-air-quality-pressure-value = Pressure value
-pid-air-quality-co2-value = CO2 value
-pid-air-quality-co-value = CO value
-pid-air-quality-no2-value = NO2 value
-pid-air-quality-o3-value = O3 value
-pid-air-quality-pm10-value = PM10 value
-pid-air-quality-pm25-value = PM25 value
-pid-air-quality-voc-value = VOC value
-
-# localized info text for pairing id description
-
-pid-switch-on-off-text = Actual value of the switch
-pid-timed-start-stop-text = Switch for staircase lightning or movement detection
-pid-force-position-text = Forces value dependent high priority on or off state
-pid-scene-control-text = Recall or learn the set value related to encoded scene number
-pid-movement-under-consideration-of-brightness-text = Activation of an autonomous switch off function triggered by an movement detector
-pid-presence-text = Presence triggered by a movement detector to be used by other devices
-pid-relative-set-value-text = Relative dimming value
-pid-absolute-set-value-text = Controls the set value
-pid-night-text = Toggle between day and night (where day = 0 / night = 1)
-pid-invalid-string-id-text = Resets load failures / short circuits / etc
-pid-rgb-color-text = RGB Color value of the light
-pid-color-temperature-text = Color temperature value of the light
-pid-hue-text = Hue value of the light
-pid-saturation-text = Saturation value of the light
-pid-move-up-down-text = Moves sunblind up and down
-pid-adjust-up-down-text = Stops the sunblind and to step it up/down
-pid-set-absolute-position-blinds-text = Moves the sunblinds into a specified position
-pid-set-absolute-position-slats-text = Moves the slats into a specified position
-pid-rain-alarm-text = State of the rain sensor (sent cyclically and on COV)
-pid-force-position-blind-text = Forces value dependent high priority up or down state
-pid-window-door-position-text = Delivers position for Window/Door (Open / Tilted / Closed)
-pid-actuating-value-heating-text = Determines the through flow volume of the control valve
-pid-fan-level-heating-text = Display value of the fan coil speed. (0=off / 1=lowest - 5=fastest)
-pid-actuating-value-cooling-text = Determines the through flow volume of the control valve
-pid-set-value-temperature-text = Defines the displayed set point temperature of the system
-pid-relative-set-point-temperature-text = Defines the relative set point temperature of the system
-pid-window-door-text = Status indication - Open = 1 / closed = 0
-pid-status-indication-text = States indication - on/off heating/cool
-pid-fan-manual-heating-on-off-text = Switches Fan in manual control mode (master to slave)
-pid-controller-on-off-text = Switches controller on or off. Off means protection mode
-pid-relative-set-point-request-text = Request for a new relative set point value
-pid-eco-mode-on-off-request-text = Switches eco mode on or off
-pid-comfort-temperature-text = Sends the current comfort temperature
-pid-fan-level-request-text = Request for a new manual fan stage
-pid-fan-manual-on-off-request-text = WARNING: DO NOT USE!!!! Request for switching fan in manual/auto mode
-pid-controller-on-off-request-text = Request for switching controller on or off. Off means protection mode
-pid-eco-mode-on-off-request-text = Indicates ECO mode
-pid-info-on-off-text = Reflects the binary state of the actuator
-pid-force-position-info-text = Indicates the cause of forced operation (0 = not forced)
-pid-sysap-infoonoff-text = Reflects the binary state of the actuator group
-pid-sysap-infoforce-text = Indicates whether the actuator group is forced (1) or not forced (0)
-pid-info-actual-dimming-value-text = Reflects the actual value of the actuator
-pid-info-error-text = Indicates load failures / short circuits / etc
-pid-sysap-infocurrentdimmingvalue-text = Reflects the actual value of the actuator group
-pid-sysap-infoerror-text = Indicates load failures / short circuits / etc
-pid-info-color-temperature-text = Color temperature
-pid-sysap-info-color-temperature-text = Color temperature
-pid-info-hsv-text = Hue (2 Byte) Saturation (1 Byte)
-pid-sysap-info-hsv-text = Hue (2 Byte) Saturation (1 Byte)
-pid-info-color-mode-text = Hsv or color mode
-pid-sysap-info-color-mode-text = Hsv or color mode info
-pid-info-move-up-down-text = Indicates the status of moving and last moving direction
-pid-current-absolute-position-blinds-percentage-text = Indicate the current position of the sunblinds in percentage
-pid-current-absolute-position-slats-percentage-text = Indicate the current position of the slats in percentage
-pid-sysap-infomoveupdown-text = Indicates the status of moving and last moving direction of the actuator group
-pid-sysap-infocurrentabsoluteblindspercentage-text = Indicate the current position of the sunblinds in percentage of the actuator group
-pid-sysap-infocurrentabsoluteslatspercentage-text = Indicate the current position of the slats in percentage of the actuator group
-pid-measured-temperature-text = Indicates the actual measured temperature
-pid-info-value-heating-text = States the current flow volume of the control valve
-pid-info-value-cooling-text = States the current flow volume of the control valve
-pid-switchover-heating-cooling-text = Switch between heating and cooling: heating = 0 / cooling = 1
-pid-actuating-fan-stage-heating-text = Requests a new manual fan stage from actuator in heating mode
-pid-absolute-setpoint-temperature-text = Set point temperature input for timer
-pid-additional-heating-value-info-text = Heating feedback
-pid-additional-cooling-value-info-text = Cooling feedback
-pid-info-actuating-fan-stage-heating-text = Feedback from actuating fan stage
-pid-info-actuating-fan-manual-on-off-heating-text = Feedback from actuating fan stage (manual on/off)
-pid-actuating-fan-stage-cooling-text = Requests a new manual fan stage from actuator in cooling mode
-pid-info-fan-stage-cooling-text = Feedback for current fan stage in cooling mode
-pid-info-fan-manual-on-off-cooling-text = Feedback for manual fan control cooling mode
-pid-heating-active-text = Heating active
-pid-cooling-active-text = Cooling active
-pid-heating-demand-text = Heating demand
-pid-cooling-demand-text = Cooling demand
-pid-heating-demand-feedback-signal-text = Heating demand feedback signal
-pid-cooling-demand-feedback-signal-text = Cooling demand feedback signal
-pid-humidity-text = Measured Humidity
-pid-aux-on-off-request-text = Aux On/Off
-pid-aux-on-off-response-text = Aux On/Off response
-pid-heating-on-off-request-text = Heating On/Off
-pid-cooling-on-off-request-text = Cooling On/Off
-pid-operation-mode-text = Operation mode
-pid-swing-h-v-text = Swing H/V
-pid-supported-features-text = Supported features
-pid-extended-status-indication-text = Extended Status Indication
-pid-aux-heating-on-off-request-text = Aux Heating On Off Reques
-pid-emergency-heating-on-off-request-text = Emergency Heating On Off Request
-pid-relative-fan-speed-control-text = Relative control of the set value
-pid-absolute-fan-speed-control-text = Absolute control of the set value
-pid-info-absolute-fan-speed-text = Reflects the actual value of the actuator
-pid-sysap-infoactualfanspeed-text = Reflects the actual value of the actuator
-pid-notification-flags-text = Notifications of RF devices (e. g. Battery low)
-pid-power-rc-text = Bool Value 1
-pid-power-rh-text = Bool Value 2
-pid-proximity-status-text = Bool Value 3
-pid-brightness-sensor-text = Scaling Value 1
-pid-last-touch-text = Scaling Value 2
-pid-led-backlighting-night-mode-text = Scaling Value 3
-pid-locator-beep-text = Locator Beep
-pid-switch-test-alarm-text = Switch Test Alarm
-pid-fire-alarm-active-text = Fire-Alarm Active
-pid-outside-temperature-text = Outdoor Temperature
-pid-wind-force-text = Wind force
-pid-brightness-alarm-text = Brightness alarm
-pid-lux-value-text = Weatherstation brightness level
-pid-wind-speed-text = Wind speed
-pid-wind-alarm-text = Triggers if the wind speed is higher than the threshold
-pid-frost-alarm-text = Triggers if the temperature is lower than the threshold
-pid-rain-detection-text = Rain detection
-pid-rain-sensor-frequency-text = Rain sensor frequency
-pid-play-text = Start playing
-pid-pause-text = Pause/Stop playing
-pid-next-text = Play next title
-pid-previous-text = Play previous title
-pid-play-mode-text = Play mode (shuffle / repeat)
-pid-relative-volume-control-text = Relative volume control. See also relative dimming
-pid-absolute-volume-control-text = Set player volume
-pid-group-membership-text = Group membership
-pid-play-favorite-text = Play favorite
-pid-play-next-favorite-text = Play next favorite
-pid-playback-status-text = Playback status
-pid-current-item-metadata-info-text = Current item metadata info
-pid-info-mute-text = Info mute
-pid-info-actual-volume-text = Info actual volume
-pid-allowed-playback-actions-text = Allowed playback actions
-pid-info-playing-favorite-text = Info playing favorite
-pid-absolute-group-volume-control-text = Group Volume Control
-pid-info-absolute-group-volume-text = Info Group Volume
-pid-media-source-text = Media source
-pid-solar-power-production-text = Power from the sun
-pid-inverter-output-power-text = Output power of inverter (pbatt+Psun)
-pid-solar-energy-(today)-text = Produced Energy
-pid-injected-energy-(today)-text = Energy into the grid
-pid-purchased-energy-(today)-text = Energy from the grid
-pid-inverter-alarm-text = Inverter is working in stand alone mode
-pid-self-consumption-text = production PV/ Total consumption
-pid-self-sufficiency-text = Consumption from PV/ Total consumption
-pid-home-power-consumption-text = Power in home (PV and grid)
-pid-power-to-grid-text = Power from and to the grid: Purchased (less than 0), Injection (more than 0)
-pid-consumed-energy-(today)-text = Energy bought from grid per day
-pid-meter-alarm-text = Meter communication loss
-pid-battery-level-text = Battery level
-pid-battery-power-text = Batter power: Discharge (less then 0), Charge (more then 0)
-pid-boost-text = Boos status - 1: Boost enable request, 0: boost disable request
-pid-stop-charging-reuqest-text = Stop charging request - 1: Stop charging session requested, 0: n/a, will be resetted when cable is unplugged
-pid-enable-charging-reuqest-text = Enable charging - 1: Enable charging when cable is plugged in, 0: Disable next charging session but charge until cable is plugged
-pid-info-boost-text = Boots info - 1: Boost enabled, 0: boost disabled
-pid-info-wallbox-status-text = Wallbox status 00000001: car plugged in, 00000002: Authorization granted, 00000004: Not charging, battery fully loaded, 40000000: charging stopped due to blackout prevention, 80000000: Ground fault error
-pid-info-charging-text = Charging status - 1: Charging, 0: Not charging
-pid-info-charging-enabled-text = Charging status - 1: Charging enabled for next session, 0: Charging disabled for next session
-pid-info-installed-power-text = Installed power (e.g. 20 kW)
-pid-info-transmitted-energy-text = Energy transmitted so far per session (in Wh)
-pid-info-car-range-text = Car range in km per sessions
-pid-info-charging-duration-text = Start of charging session (in minutes in UTC)
-pid-info-current-limit-text = Limit for charger (in kW)
-pid-info-current-limit-for-group-text = Limit for group of charger (in kW)
-pid-album-cover-url-text = Album cover URL
-pid-secure@home-central-unit-text = Encrypted control datapoint for domus alarm center
-pid-domusdisarmcounter-text = Info about the next counter to disarm the system
-pid-intrusion-alarm-text = Intrusion alarm active
-pid-safety-alarm-text = Safety Alarm active
-pid-infoconfigurationstatus-text = Domus alarm device negative feedback and configuration info.
-pid-enable-configuration-text = Encrypted control datapoint for entering configuration mode
-pid-disarming-led-text = Arm/Disarm a Zone
-pid-aes-key-text = Manufacturer ID + Serial + AES Key
-pid-zone-status-text = Zone status
-pid-time-text = Absolute number of seconds when the zone will be armed
-pid-start-stop-text = Starts / Stops operation
-pid-pause-resume-text = Pause / Resume
-pid-select-program-text = Select program
-pid-delayed-start-time-text = Delayed start time
-pid-info-status-text = Info status
-pid-info-remote-start-enabled-text = Info remote start enabled
-pid-info-program-text = Info program
-pid-info-finish-time-text = Info finish time
-pid-info-delayed-start-text = Info delayed start
-pid-info-door-text = Info door
-pid-info-door-alarm-text = Info door alarm
-pid-switch-supercool-text = Switch supercool
-pid-switch-superfreeze-text = Switch superfreeze
-pid-info-switch-supercool-text = Info switch supercool
-pid-info-switch-superfreeze-text = Info switch superfreeze
-pid-measured-temperature-text = Measured Temperature
-pid-measured-temperature-text = Measured Temperature
-pid-set-value-temperature-text = Set Value Temperature
-pid-set-value-temperature-text = Set Value Temperature
-pid-change-operation-text = Change operation
-pid-detailed-status-info-text = Detailed status info
-pid-info-remaining-time-text = Remaining time till status change (start, finish, etc.)
-pid-time-of-last-status-change-text = Time of last status change (start, finish, etc.)
-pid-lock-unlock-door-command-text = Lock/Unlock door command (1 Bit)
-pid-info-locked-unlocked-text = Info Lock/Unlock door(1 Bit)
-pid-time-text = Current local time
-pid-date-text = Current local date
-pid-notification-text = Notification from message center
-pid-switch-entity-on-off-text = Entity control e.g. activate an alert or timer program
-pid-info-switch-entity-on-off-text = Reflects the active state of an entity e.g. alert or timer program
-pid-consistency-tag-text = Notifications of RF devices (e. g. Battery low)
-pid-battery-status-text = Notifications of RF devices (e. g. Battery low)
-pid-stay-awake-text = Notifications of RF devices (e. g. Battery low)
-pid-proxy-switch-text = Proxy switch
-pid-proxy1-text = Proxy, 1 byte
-pid-proxy2-text = Proxy, 2 byte
-pid-proxy4-text = Proxy, 4 byte
-pid-cyclic-sleep-time-text = Time of sleep cycles
-pid-presence-text = SysAP presence
-pid-measured-temperature-1-text = SysAP temperature
-pid-standby-statistics-text = Statistics about standby usage for battery devices
-pid-heartbeat-delay-text = Time period between two heartbeats
-pid-info-heartbeat-delay-text = Time period between two heartbeats
-pid-measured-temperature-1-text = For debug purposes
-pid-measured-temperature-2-text = For debug purposes
-pid-measured-temperature-3-text = For debug purposes
-pid-measured-temperature-4-text = For debug purposes
-pid-air-quality-pressure-value-text = Air quality sensor value - Pressure value
-pid-air-quality-co2-value-text = Air quality sensor value - CO2 value
-pid-air-quality-co-value-text = Air quality sensor value - CO value
-pid-air-quality-no2-value-text = Air quality sensor value - NO2 value
-pid-air-quality-o3-value-text = Air quality sensor value - O3 value
-pid-air-quality-pm10-value-text = Air quality sensor value - PM10 value
-pid-air-quality-pm25-value-text = Air quality sensor value - PM25 value
-pid-air-quality-voc-value-text = Air quality sensor value - VOC value
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/thing/bridge-type.xml b/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/thing/bridge-type.xml
deleted file mode 100644 (file)
index 28b214e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<thing:thing-descriptions bindingId="freeathomesystem"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
-       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
-
-       <bridge-type id="gateway">
-               <label>free@home Gateway</label>
-               <description>This gateway represents the free@home Gateway</description>
-
-               <config-description>
-                       <parameter-group name="identification">
-                               <label>SysAP Setting</label>
-                               <description>SysAP network address and user settings</description>
-                               <advanced>false</advanced>
-                       </parameter-group>
-
-                       <parameter name="ipAddress" type="text" required="true" groupName="identification">
-                               <context>network-address</context>
-                               <label>Sysap IP Address</label>
-                               <description>IP Address of the Busch-Jaeger Gateway</description>
-                       </parameter>
-                       <parameter name="username" type="text" required="true" groupName="identification">
-                               <label>User Name</label>
-                               <description>The login name</description>
-                       </parameter>
-                       <parameter name="password" type="text" required="true" groupName="identification">
-                               <label>Password</label>
-                               <context>password</context>
-                               <description>Password for gateway</description>
-                       </parameter>
-
-               </config-description>
-       </bridge-type>
-</thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/thing/thing-type.xml b/bundles/org.openhab.binding.freeathomesystem/src/main/resources/OH-INF/thing/thing-type.xml
deleted file mode 100644 (file)
index fe71521..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<thing:thing-descriptions bindingId="freeathomesystem"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
-       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
-       <thing-type id="device" listed="false">
-               <supported-bridge-type-refs>
-                       <bridge-type-ref id="gateway"/>
-               </supported-bridge-type-refs>
-               <label>free@home Device</label>
-               <description>This represents the generic free@home device</description>
-               <properties>
-                       <property name="vendor">Busch&amp;Jäger - ABB</property>
-                       <property name="modelId">Generic free@home Device</property>
-               </properties>
-               <representation-property>deviceId</representation-property>
-               <config-description>
-                       <parameter name="deviceId" type="text" required="true">
-                               <label>Device Id</label>
-                               <description>This is the unique id of the free@home device (Please do not modify after the Thing is generated)</description>
-                       </parameter>
-               </config-description>
-       </thing-type>
-</thing:thing-descriptions>
index 0db4af22a903a8771e156219c6ba6aacba6e24d9..ba250d14dab9056812f64f0bf842768891cb1a87 100644 (file)
     <module>org.openhab.binding.folderwatcher</module>
     <module>org.openhab.binding.folding</module>
     <module>org.openhab.binding.foobot</module>
-    <module>org.openhab.binding.freeathomesystem</module>
+    <module>org.openhab.binding.freeathome</module>
     <module>org.openhab.binding.freebox</module>
     <module>org.openhab.binding.freeboxos</module>
     <module>org.openhab.binding.freecurrency</module>