From 7b0ba301e706e5a8bc5cff2e90837869f066d188 Mon Sep 17 00:00:00 2001 From: MikeTheTux <44850211+MikeTheTux@users.noreply.github.com> Date: Tue, 11 Jan 2022 22:35:18 +0100 Subject: [PATCH] [guntamatic] Initial contribution: Binding for Guntamatic Heating Systems (#12011) Signed-off-by: Michael Weger --- CODEOWNERS | 1 + bom/openhab-addons/pom.xml | 5 + bundles/org.openhab.binding.guntamatic/NOTICE | 13 + .../org.openhab.binding.guntamatic/README.md | 362 ++++++++++++++ .../org.openhab.binding.guntamatic/pom.xml | 17 + .../src/main/feature/feature.xml | 9 + .../internal/GuntamaticBindingConstants.java | 76 +++ .../GuntamaticChannelTypeProvider.java | 62 +++ .../internal/GuntamaticConfiguration.java | 32 ++ .../internal/GuntamaticHandler.java | 459 +++++++++++++++++ .../internal/GuntamaticHandlerFactory.java | 70 +++ .../main/resources/OH-INF/binding/binding.xml | 9 + .../main/resources/OH-INF/config/config.xml | 32 ++ .../OH-INF/i18n/guntamatic.properties | 158 ++++++ .../resources/OH-INF/thing/thing-types.xml | 470 ++++++++++++++++++ bundles/pom.xml | 1 + 16 files changed, 1776 insertions(+) create mode 100644 bundles/org.openhab.binding.guntamatic/NOTICE create mode 100644 bundles/org.openhab.binding.guntamatic/README.md create mode 100644 bundles/org.openhab.binding.guntamatic/pom.xml create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticBindingConstants.java create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticChannelTypeProvider.java create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticConfiguration.java create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandler.java create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/java/org/openhab/binding/guntamatic/internal/GuntamaticHandlerFactory.java create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/binding/binding.xml create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/config/config.xml create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/i18n/guntamatic.properties create mode 100644 bundles/org.openhab.binding.guntamatic/src/main/resources/OH-INF/thing/thing-types.xml diff --git a/CODEOWNERS b/CODEOWNERS index 438150878bc..ddca1888bb4 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 85c2050235f..f71abb96ae7 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 00000000000..38d625e3492 --- /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 00000000000..3fb9a056d48 --- /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 00000000000..d1d552151a9 --- /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 00000000000..892beec4ab9 --- /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 00000000000..1d52bcff611 --- /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 00000000000..293fecb05ab --- /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 00000000000..e7d599d1ee5 --- /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 00000000000..442c8521ac3 --- /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 00000000000..6ef605aedd0 --- /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 00000000000..f43cc804c78 --- /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 00000000000..7962681b163 --- /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 00000000000..8d3e99cc463 --- /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 00000000000..a47745155c6 --- /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) + + + + + + + + String + + Trigger Extra Warm Water Circle of the Guntamatic Heating System (RECHARGE) + + + + + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 6f3981daa9d..dd18d0850e9 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