diff --git a/CODEOWNERS b/CODEOWNERS
index 438150878bc27..ddca1888bb4e7 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -110,6 +110,7 @@
/bundles/org.openhab.binding.gpstracker/ @gbicskei
/bundles/org.openhab.binding.gree/ @markus7017
/bundles/org.openhab.binding.groheondus/ @FlorianSW
+/bundles/org.openhab.binding.guntamatic/ @MikeTheTux
/bundles/org.openhab.binding.haassohnpelletstove/ @chingon007
/bundles/org.openhab.binding.harmonyhub/ @digitaldan
/bundles/org.openhab.binding.haywardomnilogic/ @matchews
diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml
index 85c2050235f01..f71abb96ae7d1 100644
--- a/bom/openhab-addons/pom.xml
+++ b/bom/openhab-addons/pom.xml
@@ -541,6 +541,11 @@
org.openhab.binding.groheondus
${project.version}
+
+ org.openhab.addons.bundles
+ org.openhab.binding.guntamatic
+ ${project.version}
+
org.openhab.addons.bundles
org.openhab.binding.haassohnpelletstove
diff --git a/bundles/org.openhab.binding.guntamatic/NOTICE b/bundles/org.openhab.binding.guntamatic/NOTICE
new file mode 100644
index 0000000000000..38d625e349232
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/NOTICE
@@ -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.guntamatic/README.md b/bundles/org.openhab.binding.guntamatic/README.md
new file mode 100644
index 0000000000000..3fb9a056d4827
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/README.md
@@ -0,0 +1,362 @@
+# Guntamatic Binding
+
+The Guntamatic Binding can be used to monitor and control [Guntamatic Heating Systems](https://www.guntamatic.com/en/).
+
+## Supported Things
+
+The Guntamatic Binding was developed and tested using Guntamatic Biostar 15kW Pellets Heating System, running Firmware 3.2d.
+It should work for all other Guntamatic Heating Systems as well, that support the same web interface.
+
+## Things
+
+Guntamatic Heating Systems supported as Thing Types:
+
+| Name | Thing Type ID | Status |
+|---------------|---------------|-----------------------------------|
+| Biostar | `biostar` | tested via 15kW, firmware 3.2d |
+| Powerchip | `powerchip` | untested |
+| Powercorn | `powercorn` | untested |
+| Biocom | `biocom` | untested |
+| Pro | `pro` | untested |
+| Therm | `therm` | untested |
+
+### Thing Configuration
+
+| Parameter | Description | Default |
+|------------------|-----------------------------------------------------------------------------|-----------------|
+| `hostname` | Hostname or IP address of the Guntamatic Heating System | |
+| `key` | Optional, but required to read protected parameters and to control the Guntamatic Heating System.
The key needs to be requested from Guntamatic support, e.g. via https://www.guntamatic.com/en/contact/. | |
+| `refreshInterval` | Interval the Guntamatic Heating System is polled in seconds | `60` |
+| `encoding` | Code page used by the Guntamatic Heating System | `windows-1252` |
+
+### Properties
+
+| Property | Description |
+|---------------------|---------------------------------------------------------------|
+| `extraWwHeat` | Parameter used by `controlExtraWwHeat` channels |
+| `boilerApproval` | Parameter used by `controlBoilerApproval` channel |
+| `heatCircProgram` | Parameter used by `controlHeatCircProgram` channels |
+| `program` | Parameter used by `controlProgram` channel |
+| `wwHeat` | Parameter used by `controlWwHeat` channels |
+
+## Channels
+
+### Control Channels
+
+The Guntamatic Heating System can be controlled using the following channels:
+
+| Channel | Description | Type | Unit | Security Access Level | ReadOnly | Advanced |
+|-----------------------|-----------------------------------------------------------|-------|:---------:|:-------------------------:|:--------:|:--------:|
+| `controlBoilerApproval` | Set Boiler Approval (`AUTO`, `OFF`, `ON`) | `String` | | π W1 | R/W | true |
+| `controlProgram` | Set Program (`OFF`, `NORMAL`, `WARMWATER`, `MANUAL`) | `String` | | π W1 | R/W | false |
+| `controlHeatCircProgram0` | Set Heat Circle 0 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram1` | Set Heat Circle 1 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram2` | Set Heat Circle 2 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram3` | Set Heat Circle 3 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram4` | Set Heat Circle 4 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram5` | Set Heat Circle 5 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram6` | Set Heat Circle 6 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram7` | Set Heat Circle 7 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlHeatCircProgram8` | Set Heat Circle 8 Program (`OFF`, `NORMAL`, `HEAT`, `LOWER`) | `String` | | π W1 | R/W | true |
+| `controlWwHeat0` | Trigger Warm Water Circle 0 (`RECHARGE`) | `String` | | π W1 | R/W | true |
+| `controlWwHeat1` | Trigger Warm Water Circle 1 (`RECHARGE`) | `String` | | π W1 | R/W | true |
+| `controlWwHeat2` | Trigger Warm Water Circle 2 (`RECHARGE`) | `String` | | π W1 | R/W | true |
+| `controlExtraWwHeat0` | Trigger Extra Warm Water Circle 0 (`RECHARGE`) | `String` | | π W1 | R/W | true |
+| `controlExtraWwHeat1` | Trigger Extra Warm Water Circle 1 (`RECHARGE`) | `String` | | π W1 | R/W | true |
+| `controlExtraWwHeat2` | Trigger Extra Warm Water Circle 2 (`RECHARGE`) | `String` | | π W1 | R/W | true |
+
+#### Response of Control Channels
+
+- `{"ack":"confirmation message"}` ... in case of success
+- `{"err":"error message"}` ... in case of error
+
+### Monitoring Channels
+
+The Binding dynamically generates Channels, derived from the data provided from the actual Guntamatic Heating System.
+
+Example list of Channels using a Guntamatic Biostar 15kW Pellets Heating System running firmware 3.2d and Guntamatic System Language configured to English:
+
+| Channel | Description | Type | Unit | Security Access Level | ReadOnly | Advanced |
+|-----------------------|-----------------------------------------------------------|-------|:---------:|:-------------------------:|:--------:|:--------:|
+| `running` | Running | `String` | | π W0 | R/O | false |
+| `outsideTemp` | Outside Temp. | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `blrTargetTemp` | Blr.Target Temp | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `boilerTemperature` | Boiler Temperature | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flueGasUtilisation` | Flue gas utilisation | `Number:Dimensionless` | `%` | π W1 | R/O | false |
+| `output` | Output | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+| `returnTemp` | Return temp | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `co2Target` | CO2 Target | `Number:Dimensionless` | `%` | π W1 | R/O | false |
+| `co2Content` | CO2 Content | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+| `returnTempTarget` | Return temp target | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `statusCode` | Status code | `Number` | | π W1 | R/O | false |
+| `efficiency` | Efficiency | `Number:Dimensionless` | `%` | π W1 | R/O | false |
+| `extractorSystem` | Extractor System | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+| `feedTurbine` | Feed Turbine | `String` | | π W1 | R/O | false |
+| `dischargeMotor` | Discharge motor | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+| `g1Target` | G1 Target | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+| `bufferTop` | Buffer Top | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bufferMid` | Buffer Mid | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bufferBtm` | Buffer Btm | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `pumpHp0` | Pump HP0 | `Switch` | | π W0 | R/O | false |
+| `dhw0` | DHW 0 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bDhw0` | B DHW 0 | `Switch` | | π W0 | R/O | false |
+| `dhw1` | DHW 1 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bDhw1` | B DHW 1 | `Switch` | | π W0 | R/O | false |
+| `dhw2` | DHW 2 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bDhw2` | B DHW 2 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc0` | Room Temp:HC 0 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `heatCirc0` | Heat Circ. 0 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc1` | Room Temp:HC 1 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowTarget1` | Flow Target 1 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `flowIs1` | Flow is 1 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `mixer1` | Mixer 1 | `String` | | π W1 | R/O | false |
+| `heatCirc1` | Heat Circ. 1 | `Switch` | | π W1 | R/O | false |
+| `roomTempHc2` | Room Temp:HC 2 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowTarget2` | Flow Target 2 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `flowIs2` | Flow is 2 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `mixer2` | Mixer 2 | `String` | | π W1 | R/O | false |
+| `heatCirc2` | Heat Circ. 2 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc3` | Room Temp:HC 3 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `heatCirc3` | Heat Circ. 3 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc4` | Room Temp:HC 4 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowTarget4` | Flow Target 4 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `flowIs4` | Flow is 4 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `mixer4` | Mixer 4 | `String` | | π W1 | R/O | false |
+| `heatCirc4` | Heat Circ. 4 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc5` | Room Temp:HC 5 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowTarget5` | Flow Target 5 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `flowIs5` | Flow is 5 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `mixer5` | Mixer 5 | `String` | | π W1 | R/O | false |
+| `heatCirc5` | Heat Circ. 5 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc6` | Room Temp:HC 6 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `heatCirc6` | Heat Circ. 6 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc7` | Room Temp:HC 7 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowTarget7` | Flow Target 7 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `flowIs7` | Flow is 7 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `mixer7` | Mixer 7 | `String` | | π W1 | R/O | false |
+| `heatCirc7` | Heat Circ. 7 | `Switch` | | π W0 | R/O | false |
+| `roomTempHc8` | Room Temp:HC 8 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowTarget8` | Flow Target 8 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `flowIs8` | Flow is 8 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `mixer8` | Mixer 8 | `String` | | π W1 | R/O | false |
+| `heatCirc8` | Heat Circ. 8 | `Switch` | | π W0 | R/O | false |
+| `fuelLevel` | Fuel Level | `String` | | π W1 | R/O | false |
+| `stb` | STB | `String` | | π W1 | R/O | false |
+| `tks` | TKS | `String` | | π W1 | R/O | false |
+| `boilerApproval` | Boiler approval | `Switch` | | π W1 | R/O | false |
+| `programme` | Programme | `String` | | π W0 | R/O | false |
+| `programHc0` | Program HC0 | `String` | | π W0 | R/O | false |
+| `programHc1` | Program HC1 | `String` | | π W0 | R/O | false |
+| `programHc2` | Program HC2 | `String` | | π W0 | R/O | false |
+| `programHc3` | Program HC3 | `String` | | π W0 | R/O | false |
+| `programHc4` | Program HC4 | `String` | | π W0 | R/O | false |
+| `programHc5` | Program HC5 | `String` | | π W0 | R/O | false |
+| `programHc6` | Program HC6 | `String` | | π W0 | R/O | false |
+| `programHc7` | Program HC7 | `String` | | π W0 | R/O | false |
+| `programHc8` | Program HC8 | `String` | | π W0 | R/O | false |
+| `interuption0` | Interuption 0 | `String` | | π W0 | R/O | false |
+| `interuption1` | Interuption 1 | `String` | | π W0 | R/O | false |
+| `serial` | Serial | `Number` | | π W0 | R/O | false |
+| `version` | Version | `String` | | π W0 | R/O | false |
+| `runningTime` | Running Time | `Number:Time` | `h` | π W0 | R/O | false |
+| `serviceHrs` | Service Hrs | `Number:Time` | `d` | π W0 | R/O | false |
+| `emptyAshIn` | Empty ash in | `Number:Time` | `h` | π W0 | R/O | false |
+| `flowIs0` | Flow is 0 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowIs3` | Flow is 3 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `flowIs6` | Flow is 6 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `fuelCounter` | Fuel counter | `Number:Volume` | `mΒ³` | π W1 | R/O | false |
+| `bufferLoad` | Buffer load. | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+| `bufferTop0` | Buffer Top 0 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `bufferBtm0` | Buffer Btm 0 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `bufferTop1` | Buffer Top 1 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `bufferBtm1` | Buffer Btm 1 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `bufferTop2` | Buffer Top 2 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `bufferBtm2` | Buffer Btm 2 | `Number:Temperature` | `Β°C` | π W1 | R/O | false |
+| `bExtraWw0` | B extra-WW. 0 | `Switch` | | π W1 | R/O | false |
+| `bExtraWw1` | B extra-WW. 1 | `Switch` | | π W1 | R/O | false |
+| `bExtraWw2` | B extra-WW. 2 | `Switch` | | π W1 | R/O | false |
+| `auxiliaryPump0` | Auxiliary pump 0 | `Switch` | | π W1 | R/O | false |
+| `auxiliaryPump1` | Auxiliary pump 1 | `Switch` | | π W1 | R/O | false |
+| `auxiliaryPump2` | Auxiliary pump 2 | `Switch` | | π W1 | R/O | false |
+| `boilersConditionNo` | BoilerΒ΄s condition no. | `String` | | π W1 | R/O | false |
+| `bufferT5` | Buffer T5 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bufferT6` | Buffer T6 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `bufferT7` | Buffer T7 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `extraWw0` | Extra-WW. 0 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `extraWw1` | Extra-WW. 1 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `extraWw2` | Extra-WW. 2 | `Number:Temperature` | `Β°C` | π W0 | R/O | false |
+| `grate` | Grate | `Number:Dimensionless` | `%` | π W0 | R/O | false |
+
+#### Security Access Levels
+
+- π W0 ... Open
+- π W1 ... End Customer Key
+- π W2 ... Service Partner
+
+## Full Example
+
+**Thing File**
+
+```java
+Thing guntamatic:biostar:mybiostar "Guntamatic Biostar" [ hostname="192.168.1.100", key="0123456789ABCDEF0123456789ABCDEF0123", refreshInterval=60, encoding="windows-1252" ]
+```
+
+**Item File**
+
+```java
+String Biostar_ControlBoilerApproval "Set Boiler Approval" { channel="guntamatic:biostar:mybiostar:controlBoilerApproval" }
+String Biostar_ControlProgram "Set Program" { channel="guntamatic:biostar:mybiostar:controlProgram" }
+String Biostar_ControlHeatCircProgram0 "Set Heat Circle 0 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram0" }
+String Biostar_ControlHeatCircProgram1 "Set Heat Circle 1 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram1" }
+String Biostar_ControlHeatCircProgram2 "Set Heat Circle 2 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram2" }
+String Biostar_ControlHeatCircProgram3 "Set Heat Circle 3 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram3" }
+String Biostar_ControlHeatCircProgram4 "Set Heat Circle 4 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram4" }
+String Biostar_ControlHeatCircProgram5 "Set Heat Circle 5 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram5" }
+String Biostar_ControlHeatCircProgram6 "Set Heat Circle 6 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram6" }
+String Biostar_ControlHeatCircProgram7 "Set Heat Circle 7 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram7" }
+String Biostar_ControlHeatCircProgram8 "Set Heat Circle 8 Program" { channel="guntamatic:biostar:mybiostar:controlHeatCircProgram8" }
+String Biostar_ControlWwHeat0 "Trigger Warm Water Circle 0" { channel="guntamatic:biostar:mybiostar:controlWwHeat0" }
+String Biostar_ControlWwHeat1 "Trigger Warm Water Circle 1" { channel="guntamatic:biostar:mybiostar:controlWwHeat1" }
+String Biostar_ControlWwHeat2 "Trigger Warm Water Circle 2" { channel="guntamatic:biostar:mybiostar:controlWwHeat2" }
+String Biostar_ControlExtraWwHeat0 "Trigger Extra Warm Water Circle 0" { channel="guntamatic:biostar:mybiostar:controlExtraWwHeat0" }
+String Biostar_ControlExtraWwHeat1 "Trigger Extra Warm Water Circle 1" { channel="guntamatic:biostar:mybiostar:controlExtraWwHeat1" }
+String Biostar_ControlExtraWwHeat2 "Trigger Extra Warm Water Circle 2" { channel="guntamatic:biostar:mybiostar:controlExtraWwHeat2" }
+String Biostar_Running "Running" { channel="guntamatic:biostar:mybiostar:running" }
+Number:Temperature Biostar_OutsideTemp "Outside Temp." { channel="guntamatic:biostar:mybiostar:outsideTemp" }
+Number:Temperature Biostar_BlrTargetTemp "Blr.Target Temp" { channel="guntamatic:biostar:mybiostar:blrTargetTemp" }
+Number:Temperature Biostar_BoilerTemperature "Boiler Temperature" { channel="guntamatic:biostar:mybiostar:boilerTemperature" }
+Number:Dimensionless Biostar_FlueGasUtilisation "Flue gas utilisation" { channel="guntamatic:biostar:mybiostar:flueGasUtilisation" }
+Number:Dimensionless Biostar_Output "Output" { channel="guntamatic:biostar:mybiostar:output" }
+Number:Temperature Biostar_ReturnTemp "Return temp" { channel="guntamatic:biostar:mybiostar:returnTemp" }
+Number:Dimensionless Biostar_Co2Target "CO2 Target" { channel="guntamatic:biostar:mybiostar:co2Target" }
+Number:Dimensionless Biostar_Co2Content "CO2 Content" { channel="guntamatic:biostar:mybiostar:co2Content" }
+Number:Temperature Biostar_ReturnTempTarget "Return temp target" { channel="guntamatic:biostar:mybiostar:returnTempTarget" }
+Number Biostar_StatusCode "Status code" { channel="guntamatic:biostar:mybiostar:statusCode" }
+Number:Dimensionless Biostar_Efficiency "Efficiency" { channel="guntamatic:biostar:mybiostar:efficiency" }
+Number:Dimensionless Biostar_ExtractorSystem "Extractor System" { channel="guntamatic:biostar:mybiostar:extractorSystem" }
+String Biostar_FeedTurbine "Feed Turbine" { channel="guntamatic:biostar:mybiostar:feedTurbine" }
+Number:Dimensionless Biostar_DischargeMotor "Discharge motor" { channel="guntamatic:biostar:mybiostar:dischargeMotor" }
+Number:Dimensionless Biostar_G1Target "G1 Target" { channel="guntamatic:biostar:mybiostar:g1Target" }
+Number:Temperature Biostar_BufferTop "Buffer Top" { channel="guntamatic:biostar:mybiostar:bufferTop" }
+Number:Temperature Biostar_BufferMid "Buffer Mid" { channel="guntamatic:biostar:mybiostar:bufferMid" }
+Number:Temperature Biostar_BufferBtm "Buffer Btm" { channel="guntamatic:biostar:mybiostar:bufferBtm" }
+Switch Biostar_PumpHp0 "Pump HP0" { channel="guntamatic:biostar:mybiostar:pumpHp0" }
+Number:Temperature Biostar_Dhw0 "DHW 0" { channel="guntamatic:biostar:mybiostar:dhw0" }
+Switch Biostar_BDhw0 "B DHW 0" { channel="guntamatic:biostar:mybiostar:bDhw0" }
+Number:Temperature Biostar_Dhw1 "DHW 1" { channel="guntamatic:biostar:mybiostar:dhw1" }
+Switch Biostar_BDhw1 "B DHW 1" { channel="guntamatic:biostar:mybiostar:bDhw1" }
+Number:Temperature Biostar_Dhw2 "DHW 2" { channel="guntamatic:biostar:mybiostar:dhw2" }
+Switch Biostar_BDhw2 "B DHW 2" { channel="guntamatic:biostar:mybiostar:bDhw2" }
+Number:Temperature Biostar_RoomTempHc0 "Room Temp:HC 0" { channel="guntamatic:biostar:mybiostar:roomTempHc0" }
+Switch Biostar_HeatCirc0 "Heat Circ. 0" { channel="guntamatic:biostar:mybiostar:heatCirc0" }
+Number:Temperature Biostar_RoomTempHc1 "Room Temp:HC 1" { channel="guntamatic:biostar:mybiostar:roomTempHc1" }
+Number:Temperature Biostar_FlowTarget1 "Flow Target 1" { channel="guntamatic:biostar:mybiostar:flowTarget1" }
+Number:Temperature Biostar_FlowIs1 "Flow is 1" { channel="guntamatic:biostar:mybiostar:flowIs1" }
+String Biostar_Mixer1 "Mixer 1" { channel="guntamatic:biostar:mybiostar:mixer1" }
+Switch Biostar_HeatCirc1 "Heat Circ. 1" { channel="guntamatic:biostar:mybiostar:heatCirc1" }
+Number:Temperature Biostar_RoomTempHc2 "Room Temp:HC 2" { channel="guntamatic:biostar:mybiostar:roomTempHc2" }
+Number:Temperature Biostar_FlowTarget2 "Flow Target 2" { channel="guntamatic:biostar:mybiostar:flowTarget2" }
+Number:Temperature Biostar_FlowIs2 "Flow is 2" { channel="guntamatic:biostar:mybiostar:flowIs2" }
+String Biostar_Mixer2 "Mixer 2" { channel="guntamatic:biostar:mybiostar:mixer2" }
+Switch Biostar_HeatCirc2 "Heat Circ. 2" { channel="guntamatic:biostar:mybiostar:heatCirc2" }
+Number:Temperature Biostar_RoomTempHc3 "Room Temp:HC 3" { channel="guntamatic:biostar:mybiostar:roomTempHc3" }
+Switch Biostar_HeatCirc3 "Heat Circ. 3" { channel="guntamatic:biostar:mybiostar:heatCirc3" }
+Number:Temperature Biostar_RoomTempHc4 "Room Temp:HC 4" { channel="guntamatic:biostar:mybiostar:roomTempHc4" }
+Number:Temperature Biostar_FlowTarget4 "Flow Target 4" { channel="guntamatic:biostar:mybiostar:flowTarget4" }
+Number:Temperature Biostar_FlowIs4 "Flow is 4" { channel="guntamatic:biostar:mybiostar:flowIs4" }
+String Biostar_Mixer4 "Mixer 4" { channel="guntamatic:biostar:mybiostar:mixer4" }
+Switch Biostar_HeatCirc4 "Heat Circ. 4" { channel="guntamatic:biostar:mybiostar:heatCirc4" }
+Number:Temperature Biostar_RoomTempHc5 "Room Temp:HC 5" { channel="guntamatic:biostar:mybiostar:roomTempHc5" }
+Number:Temperature Biostar_FlowTarget5 "Flow Target 5" { channel="guntamatic:biostar:mybiostar:flowTarget5" }
+Number:Temperature Biostar_FlowIs5 "Flow is 5" { channel="guntamatic:biostar:mybiostar:flowIs5" }
+String Biostar_Mixer5 "Mixer 5" { channel="guntamatic:biostar:mybiostar:mixer5" }
+Switch Biostar_HeatCirc5 "Heat Circ. 5" { channel="guntamatic:biostar:mybiostar:heatCirc5" }
+Number:Temperature Biostar_RoomTempHc6 "Room Temp:HC 6" { channel="guntamatic:biostar:mybiostar:roomTempHc6" }
+Switch Biostar_HeatCirc6 "Heat Circ. 6" { channel="guntamatic:biostar:mybiostar:heatCirc6" }
+Number:Temperature Biostar_RoomTempHc7 "Room Temp:HC 7" { channel="guntamatic:biostar:mybiostar:roomTempHc7" }
+Number:Temperature Biostar_FlowTarget7 "Flow Target 7" { channel="guntamatic:biostar:mybiostar:flowTarget7" }
+Number:Temperature Biostar_FlowIs7 "Flow is 7" { channel="guntamatic:biostar:mybiostar:flowIs7" }
+String Biostar_Mixer7 "Mixer 7" { channel="guntamatic:biostar:mybiostar:mixer7" }
+Switch Biostar_HeatCirc7 "Heat Circ. 7" { channel="guntamatic:biostar:mybiostar:heatCirc7" }
+Number:Temperature Biostar_RoomTempHc8 "Room Temp:HC 8" { channel="guntamatic:biostar:mybiostar:roomTempHc8" }
+Number:Temperature Biostar_FlowTarget8 "Flow Target 8" { channel="guntamatic:biostar:mybiostar:flowTarget8" }
+Number:Temperature Biostar_FlowIs8 "Flow is 8" { channel="guntamatic:biostar:mybiostar:flowIs8" }
+String Biostar_Mixer8 "Mixer 8" { channel="guntamatic:biostar:mybiostar:mixer8" }
+Switch Biostar_HeatCirc8 "Heat Circ. 8" { channel="guntamatic:biostar:mybiostar:heatCirc8" }
+String Biostar_FuelLevel "Fuel Level" { channel="guntamatic:biostar:mybiostar:fuelLevel" }
+String Biostar_Stb "STB" { channel="guntamatic:biostar:mybiostar:stb" }
+String Biostar_Tks "TKS" { channel="guntamatic:biostar:mybiostar:tks" }
+Switch Biostar_BoilerApproval "Boiler approval" { channel="guntamatic:biostar:mybiostar:boilerApproval" }
+String Biostar_Programme "Programme" { channel="guntamatic:biostar:mybiostar:programme" }
+String Biostar_ProgramHc0 "Program HC0" { channel="guntamatic:biostar:mybiostar:programHc0" }
+String Biostar_ProgramHc1 "Program HC1" { channel="guntamatic:biostar:mybiostar:programHc1" }
+String Biostar_ProgramHc2 "Program HC2" { channel="guntamatic:biostar:mybiostar:programHc2" }
+String Biostar_ProgramHc3 "Program HC3" { channel="guntamatic:biostar:mybiostar:programHc3" }
+String Biostar_ProgramHc4 "Program HC4" { channel="guntamatic:biostar:mybiostar:programHc4" }
+String Biostar_ProgramHc5 "Program HC5" { channel="guntamatic:biostar:mybiostar:programHc5" }
+String Biostar_ProgramHc6 "Program HC6" { channel="guntamatic:biostar:mybiostar:programHc6" }
+String Biostar_ProgramHc7 "Program HC7" { channel="guntamatic:biostar:mybiostar:programHc7" }
+String Biostar_ProgramHc8 "Program HC8" { channel="guntamatic:biostar:mybiostar:programHc8" }
+String Biostar_Interuption0 "Interuption 0" { channel="guntamatic:biostar:mybiostar:interuption0" }
+String Biostar_Interuption1 "Interuption 1" { channel="guntamatic:biostar:mybiostar:interuption1" }
+Number Biostar_Serial "Serial" { channel="guntamatic:biostar:mybiostar:serial" }
+String Biostar_Version "Version" { channel="guntamatic:biostar:mybiostar:version" }
+Number:Time Biostar_RunningTime "Running Time" { channel="guntamatic:biostar:mybiostar:runningTime" }
+Number:Time Biostar_ServiceHrs "Service Hrs" { channel="guntamatic:biostar:mybiostar:serviceHrs" }
+Number:Time Biostar_EmptyAshIn "Empty ash in" { channel="guntamatic:biostar:mybiostar:emptyAshIn" }
+Number:Temperature Biostar_FlowIs0 "Flow is 0" { channel="guntamatic:biostar:mybiostar:flowIs0" }
+Number:Temperature Biostar_FlowIs3 "Flow is 3" { channel="guntamatic:biostar:mybiostar:flowIs3" }
+Number:Temperature Biostar_FlowIs6 "Flow is 6" { channel="guntamatic:biostar:mybiostar:flowIs6" }
+Number:Volume Biostar_FuelCounter "Fuel counter" { channel="guntamatic:biostar:mybiostar:fuelCounter" }
+Number:Dimensionless Biostar_BufferLoad "Buffer load." { channel="guntamatic:biostar:mybiostar:bufferLoad" }
+Number:Temperature Biostar_BufferTop0 "Buffer Top 0" { channel="guntamatic:biostar:mybiostar:bufferTop0" }
+Number:Temperature Biostar_BufferBtm0 "Buffer Btm 0" { channel="guntamatic:biostar:mybiostar:bufferBtm0" }
+Number:Temperature Biostar_BufferTop1 "Buffer Top 1" { channel="guntamatic:biostar:mybiostar:bufferTop1" }
+Number:Temperature Biostar_BufferBtm1 "Buffer Btm 1" { channel="guntamatic:biostar:mybiostar:bufferBtm1" }
+Number:Temperature Biostar_BufferTop2 "Buffer Top 2" { channel="guntamatic:biostar:mybiostar:bufferTop2" }
+Number:Temperature Biostar_BufferBtm2 "Buffer Btm 2" { channel="guntamatic:biostar:mybiostar:bufferBtm2" }
+Switch Biostar_BExtraWw0 "B extra-WW. 0" { channel="guntamatic:biostar:mybiostar:bExtraWw0" }
+Switch Biostar_BExtraWw1 "B extra-WW. 1" { channel="guntamatic:biostar:mybiostar:bExtraWw1" }
+Switch Biostar_BExtraWw2 "B extra-WW. 2" { channel="guntamatic:biostar:mybiostar:bExtraWw2" }
+Switch Biostar_AuxiliaryPump0 "Auxiliary pump 0" { channel="guntamatic:biostar:mybiostar:auxiliaryPump0" }
+Switch Biostar_AuxiliaryPump1 "Auxiliary pump 1" { channel="guntamatic:biostar:mybiostar:auxiliaryPump1" }
+Switch Biostar_AuxiliaryPump2 "Auxiliary pump 2" { channel="guntamatic:biostar:mybiostar:auxiliaryPump2" }
+String Biostar_BoilersConditionNo "BoilerΒ΄s condition no." { channel="guntamatic:biostar:mybiostar:boilersConditionNo" }
+Number:Temperature Biostar_BufferT5 "Buffer T5" { channel="guntamatic:biostar:mybiostar:bufferT5" }
+Number:Temperature Biostar_BufferT6 "Buffer T6" { channel="guntamatic:biostar:mybiostar:bufferT6" }
+Number:Temperature Biostar_BufferT7 "Buffer T7" { channel="guntamatic:biostar:mybiostar:bufferT7" }
+Number:Temperature Biostar_ExtraWw0 "Extra-WW. 0" { channel="guntamatic:biostar:mybiostar:extraWw0" }
+Number:Temperature Biostar_ExtraWw1 "Extra-WW. 1" { channel="guntamatic:biostar:mybiostar:extraWw1" }
+Number:Temperature Biostar_ExtraWw2 "Extra-WW. 2" { channel="guntamatic:biostar:mybiostar:extraWw2" }
+Number:Dimensionless Biostar_Grate "Grate" { channel="guntamatic:biostar:mybiostar:grate" }
+```
+
+**Rule**
+
+```javascript
+rule "Example Guntamatic Rule"
+when
+ Item Season changed
+then
+ if ( (Season.state != NULL) && (Season.state != UNDEF) )
+ {
+ if ( Season.state.toString == "WINTER" )
+ {
+ Biostar_ControlProgram.sendCommand("NORMAL")
+ }
+ else
+ {
+ Biostar_ControlProgram.sendCommand("OFF")
+ }
+ }
+end
+```
+
+## Your feedback is required
+
+The Guntamatic Binding was developed and tested using Guntamatic Biostar 15kW Pellets Heating System, running Firmware 3.2d.
+Please provide feedback (π as well as π) when using the Binding for other Guntamatic Heating Systems.
+
+Forum topic for feedback:
+
+ - [openHAB community #128451](https://community.openhab.org/t/guntamatic-new-binding-for-guntamatic-heating-systems-biostar-powerchip-powercorn-biocom-pro-therm/128451 "openHAB community #128451")
diff --git a/bundles/org.openhab.binding.guntamatic/pom.xml b/bundles/org.openhab.binding.guntamatic/pom.xml
new file mode 100644
index 0000000000000..d1d552151a909
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/pom.xml
@@ -0,0 +1,17 @@
+
+
+
+ 4.0.0
+
+
+ org.openhab.addons.bundles
+ org.openhab.addons.reactor.bundles
+ 3.3.0-SNAPSHOT
+
+
+ org.openhab.binding.guntamatic
+
+ openHAB Add-ons :: Bundles :: Guntamatic Binding
+
+
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/feature/feature.xml b/bundles/org.openhab.binding.guntamatic/src/main/feature/feature.xml
new file mode 100644
index 0000000000000..892beec4ab948
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/feature/feature.xml
@@ -0,0 +1,9 @@
+
+
+ mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features
+
+
+ openhab-runtime-base
+ mvn:org.openhab.addons.bundles/org.openhab.binding.guntamatic/${project.version}
+
+
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticBindingConstants.java b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticBindingConstants.java
new file mode 100644
index 0000000000000..1d52bcff61134
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticBindingConstants.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2010-2022 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.guntamatic.internal;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link GuntamaticBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Weger Michael - Initial contribution
+ */
+@NonNullByDefault
+public class GuntamaticBindingConstants {
+
+ public static final String BINDING_ID = "guntamatic";
+
+ // List of all Thing Type UIDs
+ public static final ThingTypeUID THING_TYPE_BIOSTAR = new ThingTypeUID(BINDING_ID, "biostar");
+ public static final ThingTypeUID THING_TYPE_POWERCHIP = new ThingTypeUID(BINDING_ID, "powerchip");
+ public static final ThingTypeUID THING_TYPE_POWERCORN = new ThingTypeUID(BINDING_ID, "powercorn");
+ public static final ThingTypeUID THING_TYPE_BIOCOM = new ThingTypeUID(BINDING_ID, "biocom");
+ public static final ThingTypeUID THING_TYPE_PRO = new ThingTypeUID(BINDING_ID, "pro");
+ public static final ThingTypeUID THING_TYPE_THERM = new ThingTypeUID(BINDING_ID, "therm");
+
+ // List of all Channel ids
+ public static final String CHANNEL_CONTROLBOILERAPPROVAL = "controlBoilerApproval";
+ public static final String CHANNEL_CONTROLPROGRAM = "controlProgram";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM0 = "controlHeatCircProgram0";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM1 = "controlHeatCircProgram1";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM2 = "controlHeatCircProgram2";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM3 = "controlHeatCircProgram3";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM4 = "controlHeatCircProgram4";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM5 = "controlHeatCircProgram5";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM6 = "controlHeatCircProgram6";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM7 = "controlHeatCircProgram7";
+ public static final String CHANNEL_CONTROLHEATCIRCPROGRAM8 = "controlHeatCircProgram8";
+ public static final String CHANNEL_CONTROLWWHEAT0 = "controlWwHeat0";
+ public static final String CHANNEL_CONTROLWWHEAT1 = "controlWwHeat1";
+ public static final String CHANNEL_CONTROLWWHEAT2 = "controlWwHeat2";
+ public static final String CHANNEL_CONTROLEXTRAWWHEAT0 = "controlExtraWwHeat0";
+ public static final String CHANNEL_CONTROLEXTRAWWHEAT1 = "controlExtraWwHeat1";
+ public static final String CHANNEL_CONTROLEXTRAWWHEAT2 = "controlExtraWwHeat2";
+
+ public static final List CHANNELIDS = Arrays.asList(CHANNEL_CONTROLBOILERAPPROVAL, CHANNEL_CONTROLPROGRAM,
+ CHANNEL_CONTROLHEATCIRCPROGRAM0, CHANNEL_CONTROLHEATCIRCPROGRAM1, CHANNEL_CONTROLHEATCIRCPROGRAM2,
+ CHANNEL_CONTROLHEATCIRCPROGRAM3, CHANNEL_CONTROLHEATCIRCPROGRAM4, CHANNEL_CONTROLHEATCIRCPROGRAM5,
+ CHANNEL_CONTROLHEATCIRCPROGRAM6, CHANNEL_CONTROLHEATCIRCPROGRAM7, CHANNEL_CONTROLHEATCIRCPROGRAM8,
+ CHANNEL_CONTROLWWHEAT0, CHANNEL_CONTROLWWHEAT1, CHANNEL_CONTROLWWHEAT2, CHANNEL_CONTROLEXTRAWWHEAT0,
+ CHANNEL_CONTROLEXTRAWWHEAT1, CHANNEL_CONTROLEXTRAWWHEAT2);
+
+ public static final String PARAMETER_BOILERAPPROVAL = "boilerApproval";
+ public static final String PARAMETER_PROGRAM = "program";
+ public static final String PARAMETER_HEATCIRCPROGRAM = "heatCircProgram";
+ public static final String PARAMETER_WWHEAT = "wwHeat";
+ public static final String PARAMETER_EXTRAWWHEAT = "extraWwHeat";
+
+ public static final String DAQDATA_URL = "/daqdata.cgi";
+ public static final String DAQDESC_URL = "/daqdesc.cgi";
+ public static final String DAQEXTDESC_URL = "/ext/daqdesc.cgi";
+ public static final String PARSET_URL = "/ext/parset.cgi";
+}
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticChannelTypeProvider.java b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticChannelTypeProvider.java
new file mode 100644
index 0000000000000..293fecb05ab24
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticChannelTypeProvider.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2010-2022 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.guntamatic.internal;
+
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+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.ChannelTypeBuilder;
+import org.openhab.core.thing.type.ChannelTypeProvider;
+import org.openhab.core.thing.type.ChannelTypeUID;
+import org.openhab.core.thing.type.StateChannelTypeBuilder;
+import org.openhab.core.types.StateDescriptionFragmentBuilder;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Provide channelTypes for Guntamatic Heating Systems
+ *
+ * @author Weger Michael - Initial contribution
+ */
+@Component(service = { ChannelTypeProvider.class, GuntamaticChannelTypeProvider.class })
+@NonNullByDefault
+public class GuntamaticChannelTypeProvider implements ChannelTypeProvider {
+ private final Map channelTypes = new ConcurrentHashMap<>();
+
+ @Override
+ public Collection getChannelTypes(@Nullable Locale locale) {
+ return channelTypes.values();
+ }
+
+ @Override
+ public @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID, @Nullable Locale locale) {
+ return channelTypes.get(channelTypeUID.getAsString()); // returns null if not found
+ }
+
+ public void addChannelType(ChannelTypeUID channelTypeUID, String label, String itemType, String description,
+ boolean advanced, String pattern) {
+ StateDescriptionFragmentBuilder stateDescriptionFragmentBuilder = StateDescriptionFragmentBuilder.create()
+ .withReadOnly(true);
+ if (!pattern.isEmpty()) {
+ stateDescriptionFragmentBuilder.withPattern(pattern);
+ }
+ StateChannelTypeBuilder stateChannelTypeBuilder = ChannelTypeBuilder.state(channelTypeUID, label, itemType)
+ .withDescription(description).isAdvanced(advanced)
+ .withStateDescriptionFragment(stateDescriptionFragmentBuilder.build());
+ channelTypes.put(channelTypeUID.getAsString(), stateChannelTypeBuilder.build());
+ }
+}
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticConfiguration.java b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticConfiguration.java
new file mode 100644
index 0000000000000..e7d599d1ee5b3
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticConfiguration.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2010-2022 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.guntamatic.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link GuntamaticConfiguration} class contains fields mapping thing configuration parameters.
+ *
+ * @author Weger Michael - Initial contribution
+ */
+@NonNullByDefault
+public class GuntamaticConfiguration {
+
+ /**
+ * Configuration parameters
+ */
+ public String hostname = "";
+ public String key = "";
+ public int refreshInterval = 60;
+ public String encoding = "windows-1252";
+}
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandler.java b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandler.java
new file mode 100644
index 0000000000000..442c8521ac300
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandler.java
@@ -0,0 +1,459 @@
+/**
+ * Copyright (c) 2010-2022 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.guntamatic.internal;
+
+import static org.openhab.binding.guntamatic.internal.GuntamaticBindingConstants.*;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.measure.Unit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.http.HttpStatus;
+import org.openhab.core.library.CoreItemFactory;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.library.unit.ImperialUnits;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.Units;
+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.binding.BaseThingHandler;
+import org.openhab.core.thing.binding.builder.ChannelBuilder;
+import org.openhab.core.thing.binding.builder.ThingBuilder;
+import org.openhab.core.thing.type.ChannelKind;
+import org.openhab.core.thing.type.ChannelTypeUID;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.State;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+
+/**
+ * The {@link GuntamaticHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Weger Michael - Initial contribution
+ */
+@NonNullByDefault
+public class GuntamaticHandler extends BaseThingHandler {
+
+ private static final String NUMBER_TEMPERATURE = CoreItemFactory.NUMBER + ":Temperature";
+ private static final String NUMBER_VOLUME = CoreItemFactory.NUMBER + ":Volume";
+ private static final String NUMBER_TIME = CoreItemFactory.NUMBER + ":Time";
+ private static final String NUMBER_DIMENSIONLESS = CoreItemFactory.NUMBER + ":Dimensionless";
+
+ private static final Map> MAP_UNIT = Map.of("%", Units.PERCENT, "Β°C", SIUnits.CELSIUS, "Β°F",
+ ImperialUnits.FAHRENHEIT, "m3", SIUnits.CUBIC_METRE, "d", Units.DAY, "h", Units.HOUR);
+ private static final Map, String> MAP_UNIT_ITEMTYPE = Map.of(Units.PERCENT, NUMBER_DIMENSIONLESS,
+ SIUnits.CELSIUS, NUMBER_TEMPERATURE, ImperialUnits.FAHRENHEIT, NUMBER_TEMPERATURE, SIUnits.CUBIC_METRE,
+ NUMBER_VOLUME, Units.DAY, NUMBER_TIME, Units.HOUR, NUMBER_TIME);
+
+ private final Logger logger = LoggerFactory.getLogger(GuntamaticHandler.class);
+ private final HttpClient httpClient;
+
+ private @Nullable ScheduledFuture> pollingFuture = null;
+
+ private GuntamaticConfiguration config = new GuntamaticConfiguration();
+ private Boolean channelsInitialized = false;
+ private GuntamaticChannelTypeProvider guntamaticChannelTypeProvider;
+ private Map channels = new HashMap<>();
+ private Map types = new HashMap<>();
+ private Map> units = new HashMap<>();
+
+ public GuntamaticHandler(Thing thing, HttpClient httpClient,
+ GuntamaticChannelTypeProvider guntamaticChannelTypeProvider) {
+ super(thing);
+ this.httpClient = httpClient;
+ this.guntamaticChannelTypeProvider = guntamaticChannelTypeProvider;
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ if (!(command instanceof RefreshType)) {
+ if (!config.key.isBlank()) {
+ String param;
+ String channelID = channelUID.getId();
+ switch (channelID) {
+ case CHANNEL_CONTROLBOILERAPPROVAL:
+ param = getThing().getProperties().get(PARAMETER_BOILERAPPROVAL);
+ break;
+ case CHANNEL_CONTROLPROGRAM:
+ param = getThing().getProperties().get(PARAMETER_PROGRAM);
+ break;
+ case CHANNEL_CONTROLHEATCIRCPROGRAM0:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM1:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM2:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM3:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM4:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM5:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM6:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM7:
+ case CHANNEL_CONTROLHEATCIRCPROGRAM8:
+ param = getThing().getProperties().get(PARAMETER_HEATCIRCPROGRAM).replace("x",
+ channelID.substring(channelID.length() - 1));
+ break;
+ case CHANNEL_CONTROLWWHEAT0:
+ case CHANNEL_CONTROLWWHEAT1:
+ case CHANNEL_CONTROLWWHEAT2:
+ param = getThing().getProperties().get(PARAMETER_WWHEAT).replace("x",
+ channelID.substring(channelID.length() - 1));
+ break;
+ case CHANNEL_CONTROLEXTRAWWHEAT0:
+ case CHANNEL_CONTROLEXTRAWWHEAT1:
+ case CHANNEL_CONTROLEXTRAWWHEAT2:
+ param = getThing().getProperties().get(PARAMETER_EXTRAWWHEAT).replace("x",
+ channelID.substring(channelID.length() - 1));
+ break;
+ default:
+ return;
+ }
+ String response = sendGetRequest(PARSET_URL, "syn=" + param, "value=" + command.toString());
+ if (response != null) {
+ State newState = new StringType(response);
+ updateState(channelID, newState);
+ }
+ } else {
+ logger.warn("A 'key' needs to be configured in order to control the Guntamatic Heating System");
+ }
+ }
+ }
+
+ private void parseAndUpdate(String html) {
+ String[] daqdata = html.split("\\n");
+
+ for (Integer i : channels.keySet()) {
+ String channel = channels.get(i);
+ Unit> unit = units.get(i);
+ if ((channel != null) && (i < daqdata.length)) {
+ String value = daqdata[i];
+ Channel chn = thing.getChannel(channel);
+ if ((chn != null) && (value != null)) {
+ value = value.trim();
+ String typeName = chn.getAcceptedItemType();
+ try {
+ State newState = null;
+ if (typeName != null) {
+ switch (typeName) {
+ case CoreItemFactory.SWITCH:
+ // Guntamatic uses German OnOff when configured to German and English OnOff for
+ // all other languages
+ if ("ON".equals(value) || "EIN".equals(value)) {
+ newState = OnOffType.ON;
+ } else if ("OFF".equals(value) || "AUS".equals(value)) {
+ newState = OnOffType.OFF;
+ }
+ break;
+ case CoreItemFactory.NUMBER:
+ newState = new DecimalType(value);
+ break;
+ case NUMBER_DIMENSIONLESS:
+ case NUMBER_TEMPERATURE:
+ case NUMBER_VOLUME:
+ case NUMBER_TIME:
+ if (unit != null) {
+ newState = new QuantityType<>(Double.parseDouble(value), unit);
+ }
+ break;
+ case CoreItemFactory.STRING:
+ newState = new StringType(value);
+ break;
+ default:
+ break;
+ }
+ }
+ if (newState != null) {
+ updateState(channel, newState);
+ } else {
+ logger.warn("Data for unknown typeName '{}' or unknown unit received", typeName);
+ }
+ } catch (NumberFormatException e) {
+ logger.warn("NumberFormatException: {}", ((e.getMessage() != null) ? e.getMessage() : ""));
+ }
+ }
+ } else {
+ logger.warn("Data for not intialized ChannelId '{}' received", i);
+ }
+ }
+ }
+
+ private void parseAndJsonInit(String html) {
+ try {
+ // remove non JSON compliant, empty element ",,"
+ JsonArray json = JsonParser.parseString(html.replace(",,", ",")).getAsJsonArray();
+ for (int i = 1; i < json.size(); i++) {
+ JsonObject points = json.get(i).getAsJsonObject();
+ if (points.has("id") && points.has("type")) {
+ int id = points.get("id").getAsInt();
+ String type = points.get("type").getAsString();
+ types.put(id, type);
+ }
+ }
+ } catch (JsonParseException | IllegalStateException | ClassCastException e) {
+ logger.warn("Invalid JSON data will be ignored: '{}'", html.replace(",,", ","));
+ }
+ }
+
+ private void parseAndInit(String html) {
+ String[] daqdesc = html.split("\\n");
+ List channelList = new ArrayList<>();
+
+ for (String channelID : CHANNELIDS) {
+ Channel channel = thing.getChannel(channelID);
+ if (channel == null) {
+ logger.warn("Static Channel '{}' is not present: remove and re-add Thing", channelID);
+ } else {
+ channelList.add(channel);
+ }
+ }
+
+ for (int i = 0; i < daqdesc.length; i++) {
+ String[] param = daqdesc[i].split(";");
+ String label = param[0].replace("C02", "CO2");
+
+ if (!"reserved".equals(label)) {
+ String channel = toLowerCamelCase(replaceUmlaut(label));
+ label = label.substring(0, 1).toUpperCase() + label.substring(1);
+
+ String unitStr = ((param.length == 1) || param[1].isBlank()) ? "" : param[1].trim();
+ Unit> unit = guessUnit(unitStr);
+
+ boolean channelInitialized = channels.containsValue(channel);
+ if (!channelInitialized) {
+ String itemType;
+ String pattern;
+ String type = types.get(i);
+ if (type == null) {
+ type = "";
+ }
+
+ if ("boolean".equals(type)) {
+ itemType = CoreItemFactory.SWITCH;
+ pattern = "";
+ } else if ("integer".equals(type)) {
+ itemType = guessItemType(unit);
+ pattern = "%d";
+ if (unit != null) {
+ pattern += " %unit%";
+ }
+ } else if ("float".equals(type)) {
+ itemType = guessItemType(unit);
+ pattern = "%.2f";
+ if (unit != null) {
+ pattern += " %unit%";
+ }
+ } else if ("string".equals(type)) {
+ itemType = CoreItemFactory.STRING;
+ pattern = "%s";
+ } else {
+ if (unitStr.isBlank()) {
+ itemType = CoreItemFactory.STRING;
+ pattern = "%s";
+ } else {
+ itemType = guessItemType(unit);
+ pattern = "%.2f";
+ if (unit != null) {
+ pattern += " %unit%";
+ }
+ }
+ }
+
+ ChannelTypeUID channelTypeUID = new ChannelTypeUID(BINDING_ID, channel);
+ guntamaticChannelTypeProvider.addChannelType(channelTypeUID, channel, itemType,
+ "Guntamatic " + label, false, pattern);
+ Channel newChannel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channel), itemType)
+ .withType(channelTypeUID).withKind(ChannelKind.STATE).withLabel(label).build();
+ channelList.add(newChannel);
+ channels.put(i, channel);
+ if (unit != null) {
+ units.put(i, unit);
+ }
+
+ logger.debug(
+ "Supported Channel: Idx: '{}', Name: '{}'/'{}', Type: '{}'/'{}', Unit: '{}', Pattern '{}' ",
+ String.format("%03d", i), label, channel, type, itemType, unitStr, pattern);
+ }
+ }
+ }
+ ThingBuilder thingBuilder = editThing();
+ thingBuilder.withChannels(channelList);
+ updateThing(thingBuilder.build());
+ channelsInitialized = true;
+ }
+
+ private @Nullable Unit> guessUnit(String unit) {
+ Unit> finalUnit = MAP_UNIT.get(unit);
+ if (!unit.isBlank() && (finalUnit == null)) {
+ logger.warn("Unsupported unit '{}' detected", unit);
+ }
+ return finalUnit;
+ }
+
+ private String guessItemType(@Nullable Unit> unit) {
+ String itemType = (unit != null) ? MAP_UNIT_ITEMTYPE.get(unit) : CoreItemFactory.NUMBER;
+ if (itemType == null) {
+ itemType = CoreItemFactory.NUMBER;
+ logger.warn("Unsupported unit '{}' detected: using native '{}' type", unit, itemType);
+ }
+ return itemType;
+ }
+
+ private static String replaceUmlaut(String input) {
+ // replace all lower Umlauts
+ String output = input.replace("ΓΌ", "ue").replace("ΓΆ", "oe").replace("Γ€", "ae").replace("Γ", "ss");
+
+ // first replace all capital umlaute in a non-capitalized context (e.g. Γbung)
+ output = output.replaceAll("Γ(?=[a-zÀâüà ])", "Ue").replaceAll("Γ(?=[a-zÀâüà ])", "Oe")
+ .replaceAll("Γ(?=[a-zÀâüà ])", "Ae");
+
+ // now replace all the other capital umlaute
+ output = output.replace("Γ", "UE").replace("Γ", "OE").replace("Γ", "AE");
+
+ return output;
+ }
+
+ private String toLowerCamelCase(String input) {
+ char delimiter = ' ';
+ String output = input.replace("Β΄", "").replaceAll("[^\\w]", String.valueOf(delimiter));
+
+ StringBuilder builder = new StringBuilder();
+ boolean nextCharLow = true;
+
+ for (int i = 0; i < output.length(); i++) {
+ char currentChar = output.charAt(i);
+ if (delimiter == currentChar) {
+ nextCharLow = false;
+ } else if (nextCharLow) {
+ builder.append(Character.toLowerCase(currentChar));
+ } else {
+ builder.append(Character.toUpperCase(currentChar));
+ nextCharLow = true;
+ }
+ }
+ return builder.toString();
+ }
+
+ private @Nullable String sendGetRequest(String url, String... params) {
+ String errorReason = "";
+ String req = "http://" + config.hostname + url;
+
+ if (!config.key.isBlank()) {
+ req += "?key=" + config.key;
+ }
+
+ for (int i = 0; i < params.length; i++) {
+ if ((i == 0) && config.key.isBlank()) {
+ req += "?";
+ } else {
+ req += "&";
+ }
+ req += params[i];
+ }
+
+ Request request = httpClient.newRequest(req);
+ request.method(HttpMethod.GET).timeout(30, TimeUnit.SECONDS).header(HttpHeader.ACCEPT_ENCODING, "gzip");
+
+ try {
+ ContentResponse contentResponse = request.send();
+ if (HttpStatus.OK_200 == contentResponse.getStatus()) {
+ if (!this.getThing().getStatus().equals(ThingStatus.ONLINE)) {
+ updateStatus(ThingStatus.ONLINE);
+ }
+ try {
+ String response = new String(contentResponse.getContent(), Charset.forName(config.encoding));
+ if (url.equals(DAQEXTDESC_URL)) {
+ parseAndJsonInit(response);
+ } else if (url.equals(DAQDATA_URL)) {
+ parseAndUpdate(response);
+ } else if (url.equals(DAQDESC_URL)) {
+ parseAndInit(response);
+ }
+ // PARSET_URL via return
+ return response;
+ } catch (IllegalArgumentException e) {
+ errorReason = String.format("IllegalArgumentException: %s",
+ ((e.getMessage() != null) ? e.getMessage() : ""));
+ }
+ } else {
+ errorReason = String.format("Guntamatic request failed with %d: %s", contentResponse.getStatus(),
+ ((contentResponse.getReason() != null) ? contentResponse.getReason() : ""));
+ }
+ } catch (TimeoutException e) {
+ errorReason = "TimeoutException: Guntamatic was not reachable on your network";
+ } catch (ExecutionException e) {
+ errorReason = String.format("ExecutionException: %s", ((e.getMessage() != null) ? e.getMessage() : ""));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ errorReason = String.format("InterruptedException: %s", ((e.getMessage() != null) ? e.getMessage() : ""));
+ }
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorReason);
+ return null;
+ }
+
+ private void pollGuntamatic() {
+ if (!channelsInitialized) {
+ if (!config.key.isBlank()) {
+ sendGetRequest(DAQEXTDESC_URL);
+ }
+ sendGetRequest(DAQDESC_URL);
+ } else {
+ sendGetRequest(DAQDATA_URL);
+ }
+ }
+
+ @Override
+ public void initialize() {
+ config = getConfigAs(GuntamaticConfiguration.class);
+ if (config.hostname.isBlank()) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid hostname configuration");
+ } else {
+ updateStatus(ThingStatus.UNKNOWN);
+ pollingFuture = scheduler.scheduleWithFixedDelay(this::pollGuntamatic, 1, config.refreshInterval,
+ TimeUnit.SECONDS);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ final ScheduledFuture> job = pollingFuture;
+ if (job != null) {
+ job.cancel(true);
+ pollingFuture = null;
+ }
+ channelsInitialized = false;
+ }
+}
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandlerFactory.java b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandlerFactory.java
new file mode 100644
index 0000000000000..6ef605aedd094
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandlerFactory.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2010-2022 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.guntamatic.internal;
+
+import static org.openhab.binding.guntamatic.internal.GuntamaticBindingConstants.*;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.core.io.net.http.HttpClientFactory;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.BaseThingHandlerFactory;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * The {@link GuntamaticHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Weger Michael - Initial contribution
+ */
+@NonNullByDefault
+@Component(configurationPid = "binding.guntamatic", service = ThingHandlerFactory.class)
+public class GuntamaticHandlerFactory extends BaseThingHandlerFactory {
+
+ private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BIOSTAR, THING_TYPE_POWERCHIP,
+ THING_TYPE_POWERCORN, THING_TYPE_BIOCOM, THING_TYPE_PRO, THING_TYPE_THERM);
+
+ private final HttpClient httpClient;
+ private GuntamaticChannelTypeProvider guntamaticChannelTypeProvider;
+
+ @Activate
+ public GuntamaticHandlerFactory(@Reference HttpClientFactory httpClientFactory,
+ @Reference GuntamaticChannelTypeProvider guntamaticChannelTypeProvider) {
+ this.httpClient = httpClientFactory.getCommonHttpClient();
+ this.guntamaticChannelTypeProvider = guntamaticChannelTypeProvider;
+ }
+
+ @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 (supportsThingType(thingTypeUID)) {
+ return new GuntamaticHandler(thing, httpClient, guntamaticChannelTypeProvider);
+ }
+
+ return null;
+ }
+}
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/binding/binding.xml
new file mode 100644
index 0000000000000..f43cc804c78e5
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/binding/binding.xml
@@ -0,0 +1,9 @@
+
+
+
+ Guntamatic Binding
+ Binding for Guntamatic Heating Systems.
+
+
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/config/config.xml
new file mode 100644
index 0000000000000..7962681b163c8
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/config/config.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ network-address
+
+ Hostname or IP address of the Guntamatic Heating System
+
+
+ password
+
+ Optional, but required to read protected parameters and to control the Guntamatic Heating System.
+ The key
+ needs to be reqested from Guntamatic support.
+
+
+ 60
+
+ Interval the Guntamatic Heating System is polled in seconds. Default: 60s
+
+
+ windows-1252
+
+ Code page used by the Guntamatic Heating System. Default: 'windows-1252'
+
+
+
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/i18n/guntamatic.properties b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/i18n/guntamatic.properties
new file mode 100644
index 0000000000000..8d3e99cc4632c
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/i18n/guntamatic.properties
@@ -0,0 +1,158 @@
+# binding
+
+binding.guntamatic.name = Guntamatic Binding
+binding.guntamatic.description = Binding for Guntamatic Heating Systems.
+
+# thing types
+
+thing-type.guntamatic.biocom.label = Guntamatic Biocom
+thing-type.guntamatic.biocom.description = Guntamatic Biocom Heating System. Untested! Please provide Feedback!
+thing-type.guntamatic.biocom.channel.controlBoilerApproval.label = Set Boiler Approval
+thing-type.guntamatic.biocom.channel.controlExtraWwHeat0.label = Trigger Extra Warm Water Circle 0
+thing-type.guntamatic.biocom.channel.controlExtraWwHeat1.label = Trigger Extra Warm Water Circle 1
+thing-type.guntamatic.biocom.channel.controlExtraWwHeat2.label = Trigger Extra Warm Water Circle 2
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram0.label = Set Heat Circle 0 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram1.label = Set Heat Circle 1 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram2.label = Set Heat Circle 2 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram3.label = Set Heat Circle 3 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram4.label = Set Heat Circle 4 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram5.label = Set Heat Circle 5 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram6.label = Set Heat Circle 6 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram7.label = Set Heat Circle 7 Program
+thing-type.guntamatic.biocom.channel.controlHeatCircProgram8.label = Set Heat Circle 8 Program
+thing-type.guntamatic.biocom.channel.controlProgram.label = Set Program
+thing-type.guntamatic.biocom.channel.controlWwHeat0.label = Trigger Warm Water Circle 0
+thing-type.guntamatic.biocom.channel.controlWwHeat1.label = Trigger Warm Water Circle 1
+thing-type.guntamatic.biocom.channel.controlWwHeat2.label = Trigger Warm Water Circle 2
+thing-type.guntamatic.biostar.label = Guntamatic Biostar
+thing-type.guntamatic.biostar.description = Guntamatic Biostar Heating System
+thing-type.guntamatic.biostar.channel.controlBoilerApproval.label = Set Boiler Approval
+thing-type.guntamatic.biostar.channel.controlExtraWwHeat0.label = Trigger Extra Warm Water Circle 0
+thing-type.guntamatic.biostar.channel.controlExtraWwHeat1.label = Trigger Extra Warm Water Circle 1
+thing-type.guntamatic.biostar.channel.controlExtraWwHeat2.label = Trigger Extra Warm Water Circle 2
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram0.label = Set Heat Circle 0 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram1.label = Set Heat Circle 1 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram2.label = Set Heat Circle 2 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram3.label = Set Heat Circle 3 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram4.label = Set Heat Circle 4 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram5.label = Set Heat Circle 5 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram6.label = Set Heat Circle 6 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram7.label = Set Heat Circle 7 Program
+thing-type.guntamatic.biostar.channel.controlHeatCircProgram8.label = Set Heat Circle 8 Program
+thing-type.guntamatic.biostar.channel.controlProgram.label = Set Program
+thing-type.guntamatic.biostar.channel.controlWwHeat0.label = Trigger Warm Water Circle 0
+thing-type.guntamatic.biostar.channel.controlWwHeat1.label = Trigger Warm Water Circle 1
+thing-type.guntamatic.biostar.channel.controlWwHeat2.label = Trigger Warm Water Circle 2
+thing-type.guntamatic.powerchip.label = Guntamatic Powerchip
+thing-type.guntamatic.powerchip.description = Guntamatic Powerchip Heating System. Untested! Please provide Feedback!
+thing-type.guntamatic.powerchip.channel.controlBoilerApproval.label = Set Boiler Approval
+thing-type.guntamatic.powerchip.channel.controlExtraWwHeat0.label = Trigger Extra Warm Water Circle 0
+thing-type.guntamatic.powerchip.channel.controlExtraWwHeat1.label = Trigger Extra Warm Water Circle 1
+thing-type.guntamatic.powerchip.channel.controlExtraWwHeat2.label = Trigger Extra Warm Water Circle 2
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram0.label = Set Heat Circle 0 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram1.label = Set Heat Circle 1 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram2.label = Set Heat Circle 2 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram3.label = Set Heat Circle 3 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram4.label = Set Heat Circle 4 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram5.label = Set Heat Circle 5 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram6.label = Set Heat Circle 6 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram7.label = Set Heat Circle 7 Program
+thing-type.guntamatic.powerchip.channel.controlHeatCircProgram8.label = Set Heat Circle 8 Program
+thing-type.guntamatic.powerchip.channel.controlProgram.label = Set Program
+thing-type.guntamatic.powerchip.channel.controlWwHeat0.label = Trigger Warm Water Circle 0
+thing-type.guntamatic.powerchip.channel.controlWwHeat1.label = Trigger Warm Water Circle 1
+thing-type.guntamatic.powerchip.channel.controlWwHeat2.label = Trigger Warm Water Circle 2
+thing-type.guntamatic.powercorn.label = Guntamatic Powercorn
+thing-type.guntamatic.powercorn.description = Guntamatic Powercorn Heating System. Untested! Please provide Feedback!
+thing-type.guntamatic.powercorn.channel.controlBoilerApproval.label = Set Boiler Approval
+thing-type.guntamatic.powercorn.channel.controlExtraWwHeat0.label = Trigger Extra Warm Water Circle 0
+thing-type.guntamatic.powercorn.channel.controlExtraWwHeat1.label = Trigger Extra Warm Water Circle 1
+thing-type.guntamatic.powercorn.channel.controlExtraWwHeat2.label = Trigger Extra Warm Water Circle 2
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram0.label = Set Heat Circle 0 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram1.label = Set Heat Circle 1 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram2.label = Set Heat Circle 2 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram3.label = Set Heat Circle 3 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram4.label = Set Heat Circle 4 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram5.label = Set Heat Circle 5 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram6.label = Set Heat Circle 6 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram7.label = Set Heat Circle 7 Program
+thing-type.guntamatic.powercorn.channel.controlHeatCircProgram8.label = Set Heat Circle 8 Program
+thing-type.guntamatic.powercorn.channel.controlProgram.label = Set Program
+thing-type.guntamatic.powercorn.channel.controlWwHeat0.label = Trigger Warm Water Circle 0
+thing-type.guntamatic.powercorn.channel.controlWwHeat1.label = Trigger Warm Water Circle 1
+thing-type.guntamatic.powercorn.channel.controlWwHeat2.label = Trigger Warm Water Circle 2
+thing-type.guntamatic.pro.label = Guntamatic Pro
+thing-type.guntamatic.pro.description = Guntamatic Pro Heating System. Untested! Please provide Feedback!
+thing-type.guntamatic.pro.channel.controlBoilerApproval.label = Set Boiler Approval
+thing-type.guntamatic.pro.channel.controlExtraWwHeat0.label = Trigger Extra Warm Water Circle 0
+thing-type.guntamatic.pro.channel.controlExtraWwHeat1.label = Trigger Extra Warm Water Circle 1
+thing-type.guntamatic.pro.channel.controlExtraWwHeat2.label = Trigger Extra Warm Water Circle 2
+thing-type.guntamatic.pro.channel.controlHeatCircProgram0.label = Set Heat Circle 0 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram1.label = Set Heat Circle 1 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram2.label = Set Heat Circle 2 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram3.label = Set Heat Circle 3 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram4.label = Set Heat Circle 4 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram5.label = Set Heat Circle 5 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram6.label = Set Heat Circle 6 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram7.label = Set Heat Circle 7 Program
+thing-type.guntamatic.pro.channel.controlHeatCircProgram8.label = Set Heat Circle 8 Program
+thing-type.guntamatic.pro.channel.controlProgram.label = Set Program
+thing-type.guntamatic.pro.channel.controlWwHeat0.label = Trigger Warm Water Circle 0
+thing-type.guntamatic.pro.channel.controlWwHeat1.label = Trigger Warm Water Circle 1
+thing-type.guntamatic.pro.channel.controlWwHeat2.label = Trigger Warm Water Circle 2
+thing-type.guntamatic.therm.label = Guntamatic Therm
+thing-type.guntamatic.therm.description = Guntamatic Therm Heating System. Untested! Please provide Feedback!
+thing-type.guntamatic.therm.channel.controlBoilerApproval.label = Set Boiler Approval
+thing-type.guntamatic.therm.channel.controlExtraWwHeat0.label = Trigger Extra Warm Water Circle 0
+thing-type.guntamatic.therm.channel.controlExtraWwHeat1.label = Trigger Extra Warm Water Circle 1
+thing-type.guntamatic.therm.channel.controlExtraWwHeat2.label = Trigger Extra Warm Water Circle 2
+thing-type.guntamatic.therm.channel.controlHeatCircProgram0.label = Set Heat Circle 0 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram1.label = Set Heat Circle 1 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram2.label = Set Heat Circle 2 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram3.label = Set Heat Circle 3 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram4.label = Set Heat Circle 4 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram5.label = Set Heat Circle 5 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram6.label = Set Heat Circle 6 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram7.label = Set Heat Circle 7 Program
+thing-type.guntamatic.therm.channel.controlHeatCircProgram8.label = Set Heat Circle 8 Program
+thing-type.guntamatic.therm.channel.controlProgram.label = Set Program
+thing-type.guntamatic.therm.channel.controlWwHeat0.label = Trigger Warm Water Circle 0
+thing-type.guntamatic.therm.channel.controlWwHeat1.label = Trigger Warm Water Circle 1
+thing-type.guntamatic.therm.channel.controlWwHeat2.label = Trigger Warm Water Circle 2
+
+# thing types config
+
+thing-type.config.guntamatic.heatingsystem.encoding.label = Encoding
+thing-type.config.guntamatic.heatingsystem.encoding.description = Code page used by the Guntamatic Heating System. Default: 'windows-1252'
+thing-type.config.guntamatic.heatingsystem.hostname.label = Hostname
+thing-type.config.guntamatic.heatingsystem.hostname.description = Hostname or IP address of the Guntamatic Heating System
+thing-type.config.guntamatic.heatingsystem.key.label = Key
+thing-type.config.guntamatic.heatingsystem.key.description = Optional, but required to read protected parameters and to control the Guntamatic Heating System. The key needs to be reqested from Guntamatic support.
+thing-type.config.guntamatic.heatingsystem.refreshInterval.label = Refresh Interval
+thing-type.config.guntamatic.heatingsystem.refreshInterval.description = Interval the Guntamatic Heating System is polled in seconds. Default: 60s
+
+# channel types
+
+channel-type.guntamatic.controlBoilerApproval.label = Set Boiler Approval
+channel-type.guntamatic.controlBoilerApproval.description = Set Boiler Approval of the Guntamatic Heating System (AUTO, OFF, ON)
+channel-type.guntamatic.controlBoilerApproval.state.option.0 = AUTO
+channel-type.guntamatic.controlBoilerApproval.state.option.1 = OFF
+channel-type.guntamatic.controlBoilerApproval.state.option.2 = ON
+channel-type.guntamatic.controlExtraWwHeat.label = Trigger Extra Warm Water Circle
+channel-type.guntamatic.controlExtraWwHeat.description = Trigger Extra Warm Water Circle of the Guntamatic Heating System (RECHARGE)
+channel-type.guntamatic.controlExtraWwHeat.state.option.0 = RECHARGE
+channel-type.guntamatic.controlHeatCircProgram.label = Set Heat Circle Program
+channel-type.guntamatic.controlHeatCircProgram.description = Set Heat Circle of the Guntamatic Heating System (OFF, NORMAL, HEAT, LOWER)
+channel-type.guntamatic.controlHeatCircProgram.state.option.0 = OFF
+channel-type.guntamatic.controlHeatCircProgram.state.option.1 = NORMAL
+channel-type.guntamatic.controlHeatCircProgram.state.option.2 = HEAT
+channel-type.guntamatic.controlHeatCircProgram.state.option.3 = LOWER
+channel-type.guntamatic.controlProgram.label = Set Program
+channel-type.guntamatic.controlProgram.description = Set Program of the Guntamatic Heating System (OFF, NORMAL, WARMWATER, MANUAL)
+channel-type.guntamatic.controlProgram.state.option.0 = OFF
+channel-type.guntamatic.controlProgram.state.option.1 = NORMAL
+channel-type.guntamatic.controlProgram.state.option.2 = WARMWATER
+channel-type.guntamatic.controlProgram.state.option.8 = MANUAL
+channel-type.guntamatic.controlWwHeat.label = Trigger Warm Water Circle
+channel-type.guntamatic.controlWwHeat.description = Trigger Warm Water Circle of the Guntamatic Heating System (RECHARGE)
+channel-type.guntamatic.controlWwHeat.state.option.0 = RECHARGE
diff --git a/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/thing/thing-types.xml
new file mode 100644
index 0000000000000..a47745155c658
--- /dev/null
+++ b/bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/thing/thing-types.xml
@@ -0,0 +1,470 @@
+
+
+
+
+
+
+ Guntamatic Biostar Heating System
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ K0010
+ PR001
+ HKx01
+ BKx06
+ ZKx06
+
+
+
+
+
+
+ Guntamatic Powerchip Heating System. Untested! Please provide Feedback!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PK002
+ PR001
+ HKx01
+ BKx06
+ ZKx06
+
+
+
+
+
+
+ Guntamatic Powercorn Heating System. Untested! Please provide Feedback!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PK002
+ PR001
+ HKx01
+ BKx06
+ ZKx06
+
+
+
+
+
+
+ Guntamatic Biocom Heating System. Untested! Please provide Feedback!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PK002
+ PR001
+ HKx01
+ BKx06
+ ZKx06
+
+
+
+
+
+
+ Guntamatic Pro Heating System. Untested! Please provide Feedback!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PK002
+ PR001
+ HKx01
+ BKx06
+ ZKx06
+
+
+
+
+
+
+ Guntamatic Therm Heating System. Untested! Please provide Feedback!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ K0010
+ PR001
+ HKx01
+ BKx06
+ ZKx06
+
+
+
+
+
+
+ String
+
+ Set Program of the Guntamatic Heating System (OFF, NORMAL, WARMWATER, MANUAL)
+
+
+
+
+
+
+
+
+
+
+ String
+
+ Set Boiler Approval of the Guntamatic Heating System (AUTO, OFF, ON)
+
+
+
+
+
+
+
+
+
+ String
+
+ Set Heat Circle of the Guntamatic Heating System (OFF, NORMAL, HEAT, LOWER)
+
+
+
+
+
+
+
+
+
+
+ String
+
+ Trigger Warm Water Circle of the Guntamatic Heating System (RECHARGE)
+
+
+
+
+
+
+
+
+
diff --git a/bundles/pom.xml b/bundles/pom.xml
index 6f3981daa9d02..dd18d0850e93f 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -142,6 +142,7 @@
org.openhab.binding.gpstracker
org.openhab.binding.gree
org.openhab.binding.groheondus
+ org.openhab.binding.guntamatic
org.openhab.binding.haassohnpelletstove
org.openhab.binding.harmonyhub
org.openhab.binding.haywardomnilogic