]> git.basschouten.com Git - openhab-addons.git/commitdiff
[kostalinverter] Add Second Generation (Piko10-20) type inverters (#8574)
authorbasse04 <orjan.backsell@gmail.com>
Thu, 4 Feb 2021 22:17:04 +0000 (23:17 +0100)
committerGitHub <noreply@github.com>
Thu, 4 Feb 2021 22:17:04 +0000 (23:17 +0100)
* Binding redesigned 20200923 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter], regarded OH3.
[WIP]

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20200923 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter] regarded oH3
[WIP]

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20200923 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter] regarded oH3
[WIP]

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20200923 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter] regarded oH3
[WIP]

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20200924 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter] regarded oH3
[WIP]

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20200924 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
Changes made in
org.openhab.binding.internal.kostal.inverter.secondgeneration.SecondGenerationHandler.java
found by Travis tests.

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201007 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
Done changes in:
Channels.xml
PIKO1020.xml
README.md
SecondGeneration.xml
SecondGenerationChannelConfiguration.java

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201008 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201012 by Örjan Backsell, regarded to @fwolter
requested changes

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201028 by Örjan Backsell, regarded to @cpmeister
requested changes.

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201105 by Örjan Backsell

Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20200923 by Örjan Backsell

'
Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
'
Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201111 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201117 by Örjan Backsell

'
Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter]
[WIP]
'

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201119 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201125 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201130 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201130, 1630 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201202 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201204 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Redesigned 20201204 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20201010 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20210112 by Örjan Backsell

'
Signed-off-by: basse04 orjan.backsell@gmail.com
Also-by: Christian Schneider <>
Also-by: René Stakemeier <>
Also-by: Christoph Weitkamp <>
This is the upgraded version of Kostal Inverter extended with
functionality for the Inverter type of Second generation PIKO 10-20
[kostalinverter]
'

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20210114 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20210119 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding (KostalInverterFactory.java)redesigned 20210119 by Örjan
Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20210125 by Örjan Backsell

* Binding redesigned 20200923 by Örjan Backsell

(KostalInverterFactory.java)

Signed-off-by: basse04 <orjan.backsell@gmail.com>
* Binding redesigned 20210125 by Örjan Backsell

Signed-off-by: basse04 <orjan.backsell@gmail.com>
13 files changed:
bundles/org.openhab.binding.kostalinverter/README.md
bundles/org.openhab.binding.kostalinverter/doc/kostalpiko10_20.jpg [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/KostalInverterFactory.java
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationChannelConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationConfigurationHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntries.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntriesContainerDTO.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationInverterConfig.java [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/config/SecondGeneration.xml [new file with mode: 0644]
bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/Channels.xml
bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/PIKO1020.xml [new file with mode: 0644]

index 9a3d8ec745919577b0e3cbb836ea93a889f617c3..b595afc5f9e7aecdad3d657614b906f0c13edafc 100644 (file)
@@ -4,13 +4,19 @@ Scrapes the web interface of the inverter for the metrics of the supported chann
 
 ![Kostal Pico](doc/kostalpico.jpg)
 
+![Kostal Piko 10-20](doc/kostalpiko10_20.jpg)
+
 ![Kostal PLENTICORE / PIKI IQ](doc/plenticore.jpg)
 
 ## Supported Things
 
 ### First generation devices (PIKO)
 
-Tested with Kostal Inverter PIKO but might work with other inverters from kostal too.
+Tested with Kostal Inverter PIKO but might work with other inverters from Kostal too.
+
+### Second generation devices (PIKO 10-20, PIKO NEW GENERATION)
+
+Tested with Kostal Inverter PIKO 10-20, PIKO NEW GENERATION.
 
 ### Third generation devices (PIKO IQ / PLENTICORE plus)
 
@@ -59,6 +65,78 @@ None
 -   l3Voltage
 -   l3Power
 
+### Second generation devices (PIKO 10-20, PIKO NEW GENERATION)
+
+| Channel Type ID                          | Item Type                | Description                                                                      | Read Write |
+|------------------------------------------|--------------------------|----------------------------------------------------------------------------------|:----------:|    
+| device-local-grid-output-power           | Number:Power             | Current output power to the grid                                                 |     R      |              
+| statistic-yield-day-second-gen           | Number:Energy            | Total produced power today                                                       |     R      |                
+| statistic-yield-total-second-gen         | Number:Energy            | Total produced power                                                             |     R      |
+| device-local-operating-status            | Number:Dimensionless     | Current operating status, 0 = Standby, 3 = WO-IDLE                               |     R      |
+| device-local-grid-voltage-l1             | Number:ElectricPotential | Current output voltage to the grid, L1                                           |     R      |
+| device-local-grid-current-l1             | Number:ElectricCurrent   | Current output current to the grid, L1                                           |     R      |
+| device-local-grid-power-l1               | Number:Power             | Current output power to the grid, L1                                             |     R      |
+| device-local-grid-voltage-l2             | Number:ElectricPotential | Current output voltage to the grid, L2                                           |     R      |
+| device-local-grid-current-l2             | Number:ElectricCurrent   | Current output current to the grid, L2                                           |     R      |
+| device-local-grid-power-l2               | Number:Power             | Current output power to the grid, L2                                             |     R      |
+| device-local-grid-voltage-l3             | Number:ElectricPotential | Current output voltage to the grid, L3                                           |     R      |
+| device-local-grid-current-l3             | Number:ElectricCurrent   | Current output current to the grid, L3                                           |     R      |
+| device-local-grid-power-l3               | Number:Power             | Current output power to the grid, L3                                             |     R      |
+| device-local-dc-power-pv                 | Number:Power             | Current power from all solar panels                                              |     R      |
+| device-local-dc1-voltage                 | Number:ElectricPotential | Current voltage from solar panels, Dc1                                           |     R      |
+| device-local-dc1-current                 | Number:ElectricCurrent   | Current current from solar panels, Dc1                                           |     R      |
+| device-local-dc1-power                   | Number:Power             | Current power from solar panels, Dc1                                             |     R      |
+| device-local-dc2-voltage                 | Number:ElectricPotential | Current voltage from solar panels, Dc2                                           |     R      |
+| device-local-dc2-current                 | Number:ElectricCurrent   | Current current from solar panels, Dc2                                           |     R      |
+| device-local-dc2-power                   | Number:Power             | Current power from solar panels, Dc2                                             |     R      |
+| device-local-dc3-voltage                 | Number:ElectricPotential | Current voltage from solar panels, Dc3                                           |     R      |
+| device-local-dc3-current                 | Number:ElectricCurrent   | Current current from solar panels, Dc3                                           |     R      |
+| device-local-dc3-power                   | Number:Power             | Current power from solar panels, Dc3                                             |     R      |
+| device-local-akt-home-consumption-solar  | Number:Power             | Current consumption from solar panels                                            |     R      |
+| device-local-akt-home-consumption-bat    | Number:Power             | Current consumption from battery                                                 |     R      |
+| device-local-akt-home-consumption-grid   | Number:Power             | Current consumption from grid                                                    |     R      |
+| device-local-phase-sel-home-consump-l1   | Number:Power             | Current home consumption, L1                                                     |     R      |
+| device-local-phase-sel-home-consump-l2   | Number:Power             | Current home consumption, L2                                                     |     R      |
+| device-local-phase-sel-home-consump-l3   | Number:Power             | Current home consumption, L3                                                     |     R      |
+| device-local-grid-freq                   | Number:Frequency         | Current frequency on grid                                                        |     R      |
+| device-local-grid-cos-phi                | Number:Angle             | Current power factor on grid                                                     |     R      |
+| statistic-home-consumption-day           | Number:Energy            | Total home consumption today                                                     |     R      |
+| statistic-own-consumption-day            | Number:Energy            | Total own consumption today                                                      |     R      |
+| statistic-own-cons-rate-day              | Number:Dimensionless     | Total own consumption rate today                                                 |     R      |
+| statistic-autonomy-degree-day            | Number:Dimensionless     | Total autonomy degree today                                                      |     R      |
+| statistic-home-consumption-total         | Number:Energy            | Total home consumption                                                           |     R      |
+| statistic-own-consumption-total          | Number:Energy            | Total own consumption                                                            |     R      |
+| statistic-operating-time-total           | Number:Time              | Total operating time                                                             |     R      |
+| device-local-current                     | Number:ElectricCurrent   | Current                                                                          |     R      |
+| device-local-current-dir                 | Number:Dimensionless     | Current direction of loading/unloading the battery                               |     R      |
+| device-local-charge-cycles               | Number:Dimensionless     | Total number of charge cycles                                                    |     R      |       
+| device-local-battery-temperature         | Number:Temperature       | Battery current temperature                                                      |     R      |
+| device-local-loginterval                 | Number:Time              | Value for loginterval                                                            |     R      |
+| device-local-s0-inpulse-cnt              | Number:Dimensionless     | S0-pulse counter                                                                 |     R      | 
+| statistic-own-cons-rate-total            | Number:Dimensionless     | Total own comsumption rate                                                       |     R      |
+| statistic-autonomy-degree-total          | Number:Dimensionless     | Total autonomy degree                                                            |     R      |
+| device-local-battery-voltage             | Number:ElectricPotential | Battery current voltage                                                          |     R      |
+| device-local-bat-state-of-charge         | Number:Dimensionless     | Battery current charge state                                                     |     R      |
+| device-local-self-consumption            | Number:Power             | Current self consumption                                                         |     R      |
+| device-local-battery-usage-consumption   | Number:Power             | Battery usage consumption                                                        |     R      |
+| device-local-smart-battery-control       | Switch                   | Smart battery control                                                            |     R      |
+| device-local-shadow-management           | Number:Dimensionless     | Shadow management                                                                |     R      |
+| device-local-external-module-control     | Number:Dimensionless     | External module control                                                          |     R      |
+
+The following Channels are writeable
+
+| Channel Type ID                          | Item Type                | Description                                                                      | Read Write |
+|------------------------------------------|--------------------------|----------------------------------------------------------------------------------|:----------:|    
+| device-local-battery-usage-consumption-set| String                  | Battery usage consumption level for power-consumption from battery, value = 100 (W)                                                                                                                                                         |     W      |
+| device-local-battery-usage-strategy-set  | String                   | Battery usage strategy, Value = 1 = Automatic, Value = 2 = Automatic economical  |     W      |             
+| device-local-smart-battery-control-set   | Switch                   | Smart battery control, Value = OFF / ON                                          |     W      |
+| device-local-battery-charge-time-from-set| String                   | Battery charge time from, Value = 00:00                                          |     W      |
+| device-local-battery-charge-time-to-set  | String                   | Battery charge time to, Value = 23:59                                            |     W      |
+| device-local-max-depth-of-discharge-set  | String                   | Max depth of discharge (SoC), Value = 10                                         |     W      |
+| device-local-shadow-management-set       | String                   | Shadow management, Value = 0 = No shadow management enabled, Value = 1 = Shadow management enabled for DC-Input String 1, Value = 2 = Shadow  management enabled for DC-Input String 2,  Value = 3 = Shadow management enabled for DC-Input String 1 and 2               |     W      |
+| device-local-external-module-control-set | String                   | External module control, Value = 0 = Not Activated, Value = 1 = Activated                                        |     W      |
+
+
 ### Third generation devices (PIKO IQ / PLENTICORE plus)
 
 | Channel Type ID                          | Item Type                | Description                                                                      | Read Write |
@@ -148,6 +226,31 @@ If the thing goes online then the connection to the web interface is successful.
 In case it is offline you should see an error message.
 You optionally can define a `userName` and a `password` parameter if the access to the webinterface is protected and a desired `refreshInterval` (the time interval between updates, default 60 seconds).
 
+
+### Second generation devices (PIKO 10-20, PIKO NEW GENERATION)
+
+Second generation inverters require 5 mandatory parameters:
+
+| Parameter                | Description                                            | Type    |  Unit   | Default value | Example value |
+|--------------------------|--------------------------------------------------------|---------|---------|---------------|---------------|
+| url                      | Host name or IP address of your device                 | Text    | ---     | ---           | 192.168.0.2   |
+| username                 | Username for your inverter                             | Text    | ---     | ---           | myUsername    |
+| password                 | Password for your inverter                             | Text    | ---     | ---           | myPassword    |
+| refreshInterval          | Pollingintervall of your inverter                      | Integer | Seconds | 60            | 60            |
+| hasBattery               | Type of PIKO 10-20 inverter, with or without battery   | boolean | ---     | --            | false/true    |   
+
+demo.things
+
+```
+
+Thing kostalinverter:piko1020:mypiko1020 [ url="http://'inverter-ip'", username="'myUsername'", password="'myPassword'", refreshInterval=60, hasBattery=false]
+
+```
+
+You can define which type of PIKO10-20 inverter you will connect to with parameter hasBattery.
+
+
+
 ### Third generation devices (PIKO IQ / PLENTICORE plus)
 
 All third generation inverters require to define 3 mandatory configuration parameters:
@@ -182,11 +285,76 @@ Number:Energy SolarTotalEnergy "Solar total energy [%.3f %unit%]" <energy> { cha
 String SolarStatus "Solar status [%s]" <energy> { channel="kostalinverter:kostalinverter:inverter:status" }
 ```
 
+
+### Second generation devices (PIKO NEW GENERATION)
+
+demo.items:
+
+```
+Number:Power                GridOutputPower             "PV Output Power"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridOutputPower" }
+Number:Energy               YieldDaySecondGen           "PV Output Power Day"                       <energy> { channel="kostalinverter:piko1020:mypiko1020:yieldDaySecondGen" }
+Number:Energy               YieldTotalSecondGen         "PV Output Power Total"                     <energy> { channel="kostalinverter:piko1020:mypiko1020:yieldTotalSecondgen" }  
+Number:Dimensionless        OperatingStatus             "Operating Status"                          <energy> { channel="kostalinverter:piko1020:mypiko1020:operatingStatus" }
+Number:ElectricPotential    GridVoltageL1               "Grid Voltage L1"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridVoltageL1" }
+Number:ElectricCurrent      GridCurrentL1               "Grid Current L1"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridCurrentL1" }
+Number:Power                GridPowerL1                 "Grid Power L1"                             <energy> { channel="kostalinverter:piko1020:mypiko1020:gridPowerL1" }
+Number:ElectricPotential    GridVoltageL2               "Grid Voltage L2"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridVoltageL2" }
+Number:ElectricCurrent      GridCurrentL2               "Grid Current L2"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridCurrentL2" }
+Number:Power                GridPowerL2                 "Grid Power L2"                             <energy> { channel="kostalinverter:piko1020:mypiko1020:gridPowerL2" }
+Number:ElectricPotential    GridVoltageL3               "Grid Voltage L3"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridVoltageL3" }
+Number:ElectricCurrent      GridCurrentL3               "Grid Current L3"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:gridCurrentL3" }
+Number:Power                GridPowerL3                 "Grid Power L3"                             <energy> { channel="kostalinverter:piko1020:mypiko1020:gridPowerL3" }
+Number:Power                DcPvPower                   "DC Power Pv"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dcPowerPV" }
+Number:ElectricPotential    Dc1Voltage                  "DC1 Voltage"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dc1Voltage" }
+Number:ElectricCurrent      Dc1Current                  "DC1 Current"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dc1Current" }
+Number:Power                Dc1Power                    "DC1 Power"                                 <energy> { channel="kostalinverter:piko1020:mypiko1020:dc1Power" }
+Number:ElectricPotential    Dc2Voltage                  "DC2 Voltage"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dc2Voltage" }
+Number:ElectricCurrent      Dc2Current                  "DC2 Current"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dc2Current" }
+Number:Power                Dc2Power                    "DC2 Power"                                 <energy> { channel="kostalinverter:piko1020:mypiko1020:dc2Power" }
+Number:ElectricPotential    Dc3Voltage                  "DC3 Voltage"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dc3Voltage" }
+Number:ElectricCurrent      Dc3Current                  "DC3 Current"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:dc3Current" }
+Number:Power                Dc3Power                    "DC3 Power"                                 <energy> { channel="kostalinverter:piko1020:mypiko1020:dc3Power" }
+Number:Power                AktHomeConsumptionSolar     "Akt Home Consumption Solar"                <energy> { channel="kostalinverter:piko1020:mypiko1020:aktHomeConsumptionSolar" }
+Number:Power                AktHomeConsumptionBat       "Akt Home Consumption Battery"              <energy> { channel="kostalinverter:piko1020:mypiko1020:aktHomeConsumptionBat" }
+Number:Power                AktHomeConsumptionGrid      "Akt Home Consumption Grid"                 <energy> { channel="kostalinverter:piko1020:mypiko1020:aktHomeConsumptionGrid" }
+Number:Power                PhaseSelHomeConsumpL1       "Phase Sel Home Consump L1"                 <energy> { channel="kostalinverter:piko1020:mypiko1020:phaseSelHomeConsumpL1" }
+Number:Power                PhaseSelHomeConsumpL2       "Phase Sel Home Consump L2"                 <energy> { channel="kostalinverter:piko1020:mypiko1020:phaseSelHomeConsumpL2" }
+Number:Power                PhaseSelHomeConsumpL3       "Phase Sel Home Consump L3"                 <energy> { channel="kostalinverter:piko1020:mypiko1020:phaseSelHomeConsumpL3" }
+Number:Frequency            GridFreq                    "Grid Freq"                                 <energy> { channel="kostalinverter:piko1020:mypiko1020:gridFreq" }
+Number:Angle                GridCosPhi                  "Grid Cos Phi"                              <energy> { channel="kostalinverter:piko1020:mypiko1020:gridCosPhi" }
+Number:Energy               HomeConsumptionDay          "Home Consumption Day"                      <energy> { channel="kostalinverter:piko1020:mypiko1020:homeConsumptionDay" } 
+Number:Energy               OwnConsumptionDay           "Own Consumption Day"                       <energy> { channel="kostalinverter:piko1020:mypiko1020:ownConsumptionDay" } 
+Number:Dimensionless        OwnConsRateDay              "Own Cons Rate Day                          <energy> { channel="kostalinverter:piko1020:mypiko1020:ownConsRateDay" } 
+Number:Dimensionless        AutonomyDegreeDay           "Autonomy Degree Day"                       <energy> { channel="kostalinverter:piko1020:mypiko1020:autonomyDegreeDay" }
+Number:Energy               HomeConsumptionTotal        "Home Consumption Total"                    <energy> { channel="kostalinverter:piko1020:mypiko1020:homeConsumptionTotal" } 
+Number:Energy               OwnConsumptionTotal         "Own Consumption Total"                     <energy> { channel="kostalinverter:piko1020:mypiko1020:ownConsumptionTotal" } 
+Number:Time                 OperatingTimeTotal          "Operating Time Total"                      <energy> { channel="kostalinverter:piko1020:mypiko1020:operatingTimeTotal" }
+Number:ElectricCurrent      Current                     "Current"                                   <energy> { channel="kostalinverter:piko1020:mypiko1020:current" }
+Number:Dimensionless        CurrentDir                  "Current Dir"                               <energy> { channel="kostalinverter:piko1020:mypiko1020:currentDir" }
+Number:Dimensionless        ChargeCycles                "Charge Cycles"                             <energy> { channel="kostalinverter:piko1020:mypiko1020:chargeCycles" }
+Number:Temperature          BatteryTemperature          "BatteryTemperature"                        <energy> { channel="kostalinverter:piko1020:mypiko1020:batteryTemperature" }
+Number:Time                 Loginterval                 "Log Interval"                              <energy> { channel="kostalinverter:piko1020:mypiko1020:loginterval" }
+Number:Dimensionless        S0InPulseCnt                "S0 InPulse Cnt"                            <energy> { channel="kostalinverter:piko1020:mypiko1020:s0InPulseCnt" }
+Number:Dimensionless        OwnConsRateTotal            "Own Cons Rate Total"                       <energy> { channel="kostalinverter:piko1020:mypiko1020:ownConsRateTotal" } 
+Number:Dimensionless        AutonomyDegreeTotal         "Autonomy Degree Total"                     <energy> { channel="kostalinverter:piko1020:mypiko1020:autonomyDegreeTotal" } 
+Number:ElectricPotential    BatteryVoltage              "Battery Voltage"                           <energy> { channel="kostalinverter:piko1020:mypiko1020:batteryVoltage" }
+Number:Dimensionless        BatStateOfCharge            "Bat State Of Charge"                       <energy> { channel="kostalinverter:piko1020:mypiko1020:batStateOfCharge" }
+Number:Power                SelfConsumption             "Self Consumption"                          <energy> { channel="kostalinverter:piko1020:mypiko1020:selfConsumption" }
+Number:Dimensionless        BatteryUsageConsumption     "Battery Usage Consumption"                 <energy> { channel="kostalinverter:piko1020:mypiko1020:batteryUsageConsumption" }
+Switch                      SmartBatteryControl         "Smart Battery Control"                     <energy> { channel="kostalinverter:piko1020:mypiko1020:smartBatteryControl" }
+Number:Dimensionless        MaxDepthOfDischarge         "Max Depth Of Discharge"                    <energy> { channel="kostalinverter:piko1020:mypiko1020:maxDepthOfDischarge" }
+Number:Dimensionless        ShadowManagement            "Shadow Management"                         <energy> { channel="kostalinverter:piko1020:mypiko1020:shadowManagement" }
+Number:Dimensionless        ExternalModuleControl       "External Module Control"                   <energy> { channel="kostalinverter:piko1020:mypiko1020:externalModuleControl" }           
+
+
+```
+
 ### Third generation devices (PIKO IQ / PLENTICORE plus)
 
 demo.items:
 
 ```
+
 Number:Energy                MyPlentiCore100WithBattery_DEVICE_LOCAL_DC_POWER                         <energy> { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:deviceLocalDCPower"}
 Number:Energy                MyPlentiCore100WithBattery_DEVICE_LOCAL_HOMECONSUMPTION_FROM_BATTERY     <energy> { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:deviceLocalHomeconsumptionFromBattery"}
 Number:Energy                MyPlentiCore100WithBattery_DEVICE_LOCAL_HOMECONSUMPTION_FROM_GRID        <energy> { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:deviceLocalHomeconsumptionFromGrid"}
@@ -256,3 +424,28 @@ Number:Energy                MyPlentiCore100WithBattery_STATISTIC_YIELD_TOTAL
 Number:Energy                MyPlentiCore100WithBattery_STATISTIC_YIELD_YEAR                          <energy> { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:statisticYieldYear"}
 
 ```
+
+
+### Rules
+
+Second generation devices (PIKO 10-20, PIKO NEW GENERATION)
+
+```
+
+Ex. Set Smart battery control OFF with cron trigger:
+
+triggers:
+   id: "1"
+    configuration:
+      cronExpression: 0 0/2 * * * ? *
+    type: timer.GenericCronTrigger
+conditions: []
+actions:
+   inputs: {}
+    id: "2"
+    configuration:
+      type: application/vnd.openhab.dsl.rule
+      script: KOSTALPIKO1020_SmartBatteryControlSet.sendCommand("OFF")
+    type: script.ScriptAction
+    
+
diff --git a/bundles/org.openhab.binding.kostalinverter/doc/kostalpiko10_20.jpg b/bundles/org.openhab.binding.kostalinverter/doc/kostalpiko10_20.jpg
new file mode 100644 (file)
index 0000000..f72fc15
Binary files /dev/null and b/bundles/org.openhab.binding.kostalinverter/doc/kostalpiko10_20.jpg differ
index 79a00e2912f82447557a49bb751024764ecc5984..0210a8ddccab31c4a9cdcd9adb8787d18fc6e508 100644 (file)
@@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.client.HttpClient;
 import org.openhab.binding.kostalinverter.internal.firstgeneration.WebscrapeHandler;
+import org.openhab.binding.kostalinverter.internal.secondgeneration.SecondGenerationHandler;
 import org.openhab.binding.kostalinverter.internal.thirdgeneration.ThirdGenerationHandler;
 import org.openhab.binding.kostalinverter.internal.thirdgeneration.ThirdGenerationInverterTypes;
 import org.openhab.core.io.net.http.HttpClientFactory;
@@ -36,6 +37,7 @@ import org.osgi.service.component.annotations.Reference;
 /**
  * @author Christian Schneider - Initial contribution (as WebscrapeHandlerFactory.java)
  * @author René Stakemeier - extension for the third generation of KOSTAL inverters
+ * @author Örjan Backsell - extension for the second generation of KOSTAL inverters
  */
 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.kostalinverter")
 @NonNullByDefault
@@ -72,6 +74,8 @@ public class KostalInverterFactory extends BaseThingHandlerFactory {
 
     public static final ThingTypeUID FIRST_GENERATION_INVERTER = new ThingTypeUID("kostalinverter", "kostalinverter");
 
+    public static final ThingTypeUID SECOND_GENERATION_INVERTER = new ThingTypeUID("kostalinverter", "piko1020");
+
     private final HttpClient httpClient;
 
     @Activate
@@ -81,7 +85,7 @@ public class KostalInverterFactory extends BaseThingHandlerFactory {
 
     @Override
     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
-        return thingTypeUID.equals(FIRST_GENERATION_INVERTER)
+        return thingTypeUID.equals(FIRST_GENERATION_INVERTER) || thingTypeUID.equals(SECOND_GENERATION_INVERTER)
                 || SUPPORTED_THIRD_GENERATION_THING_TYPES_UIDS.keySet().contains(thingTypeUID);
     }
 
@@ -91,6 +95,10 @@ public class KostalInverterFactory extends BaseThingHandlerFactory {
         if (FIRST_GENERATION_INVERTER.equals(thing.getThingTypeUID())) {
             return new WebscrapeHandler(thing);
         }
+        // second generation
+        if (SECOND_GENERATION_INVERTER.equals(thing.getThingTypeUID())) {
+            return new SecondGenerationHandler(thing, httpClient);
+        }
         // third generation
         ThirdGenerationInverterTypes inverterType = SUPPORTED_THIRD_GENERATION_THING_TYPES_UIDS
                 .get(thing.getThingTypeUID());
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationBindingConstants.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationBindingConstants.java
new file mode 100644 (file)
index 0000000..d46f09e
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link SecondGenerationBindingConstants} class defines channel constants, which are
+ * used in the second generation part of the binding.
+ *
+ * @author Örjan Backsell - Initial contribution Piko1020, Piko New Generation
+ */
+
+@NonNullByDefault
+public class SecondGenerationBindingConstants {
+
+    private static final String BINDING_ID = "kostalinverter";
+
+    // List of all Thing Type UIDs
+    public static final ThingTypeUID SECOND_GENERATION_INVERTER = new ThingTypeUID(BINDING_ID, "piko1020");
+
+    // List of all Channel ids
+    public static final String CHANNEL_GRIDOUTPUTPOWER = "gridOutputPower";
+    public static final String CHANNEL_YIELD_DAY_SECOND_GEN = "yieldDaySecondGen";
+    public static final String CHANNEL_YIELD_TOTAL_SECOND_GEN = "yieldTotalSecondGen";
+    public static final String CHANNEL_OPERATING_STATUS = "operatingStatus";
+    public static final String CHANNEL_GRIDVOLTAGEL1 = "gridVoltageL1";
+    public static final String CHANNEL_GRIDCURRENTL1 = "gridCurrentL1";
+    public static final String CHANNEL_GRIDPOWERL1 = "gridPowerL1";
+    public static final String CHANNEL_GRIDVOLTAGEL2 = "gridVoltageL2";
+    public static final String CHANNEL_GRIDCURRENTL2 = "gridCurrentL2";
+    public static final String CHANNEL_GRIDPOWERL2 = "gridPowerL2";
+    public static final String CHANNEL_GRIDVOLTAGEL3 = "gridVoltageL3";
+    public static final String CHANNEL_GRIDCURRENTL3 = "gridCurrentL3";
+    public static final String CHANNEL_GRIDPOWERL3 = "gridPowerL3";
+    public static final String CHANNEL_DCPOWERPV = "dcPowerPV";
+    public static final String CHANNEL_DC1VOLTAGE = "dc1Voltage";
+    public static final String CHANNEL_DC1CURRENT = "dc1Current";
+    public static final String CHANNEL_DC1POWER = "dc1Power";
+    public static final String CHANNEL_DC2VOLTAGE = "dc2Voltage";
+    public static final String CHANNEL_DC2CURRENT = "dc2Current";
+    public static final String CHANNEL_DC2POWER = "dc2Power";
+    public static final String CHANNEL_DC3VOLTAGE = "dc3Voltage";
+    public static final String CHANNEL_DC3CURRENT = "dc3Current";
+    public static final String CHANNEL_DC3POWER = "dc3Power";
+
+    public static final String CHANNEL_AKTHOMECONSUMTIONSOLAR = "aktHomeConsumptionSolar";
+    public static final String CHANNEL_AKTHOMECONSUMPTIONBAT = "aktHomeConsumptionBat";
+    public static final String CHANNEL_AKTHOMECONSUMPTIONGRID = "aktHomeConsumptionGrid";
+    public static final String CHANNEL_PHASESELHOMECONSUMPL1 = "phaseSelHomeConsumpL1";
+    public static final String CHANNEL_PHASESELHOMECONSUMPL2 = "phaseSelHomeConsumpL2";
+    public static final String CHANNEL_PHASESELHOMECONSUMPL3 = "phaseSelHomeConsumpL3";
+    public static final String CHANNEL_GRIDFREQ = "gridFreq";
+    public static final String CHANNEL_GRIDCOSPHI = "gridCosPhi";
+    public static final String CHANNEL_HOMECONSUMPTION_DAY = "homeConsumptionDay";
+    public static final String CHANNEL_OWNCONSUMPTION_DAY = "ownConsumptionDay";
+    public static final String CHANNEL_OWNCONSRATE_DAY = "ownConsRateDay";
+    public static final String CHANNEL_AUTONOMYDEGREE_DAY = "autonomyDegreeDay";
+    public static final String CHANNEL_HOMECONSUMPTION_TOTAL = "homeConsumptionTotal";
+    public static final String CHANNEL_OWNCONSUMPTION_TOTAL = "ownConsumptionTotal";
+    public static final String CHANNEL_OPERATINGTIME_TOTAL = "operatingTimeTotal";
+    public static final String CHANNEL_CURRENT = "current";
+    public static final String CHANNEL_CURRENTDIR = "currentDir";
+    public static final String CHANNEL_CHARGECYCLES = "chargeCycles";
+    public static final String CHANNEL_BATTERYTEMPERATURE = "batteryTemperature";
+    public static final String CHANNEL_LOGINTERVAL = "loginterval";
+    public static final String CHANNEL_S0INPULSECNT = "s0InPulseCnt";
+    public static final String CHANNEL_OWNCONSRATE_TOTAL = "ownConsRateTotal";
+    public static final String CHANNEL_AUTONOMYDEGREE_TOTAL = "autonomyDegreeTotal";
+
+    public static final String CHANNEL_BATTERYVOLTAGE = "batteryVoltage";
+    public static final String CHANNEL_BATSTATEOFCHARGE = "batStateOfCharge";
+    public static final String CHANNEL_SELFCONSUMPTION = "selfConsumption";
+
+    public static final String CHANNEL_BATTERYUSAGECONSUMPTION = "batteryUsageConsumption";
+    public static final String CHANNEL_SMARTBATTERYCONTROL = "smartBatteryControl";
+    public static final String CHANNEL_MAXDEPTHOFDISCHARGE = "maxDepthOfDischarge";
+    public static final String CHANNEL_SHADOWMANAGEMENT = "shadowManagement";
+    public static final String CHANNEL_EXTERNALMODULECONTROL = "externalModuleControl";
+
+    public static final String CHANNEL_BATTERYUSAGECONSUMPTIONSET = "batteryUsageConsumptionSet";
+    public static final String CHANNEL_BATTERYUSAGESTRATEGYSET = "batteryUsageStrategySet";
+    public static final String CHANNEL_SMARTBATTERYCONTROLSET = "smartBatteryControlSet";
+    public static final String CHANNEL_BATTERYCHARGETIMEFROMSET = "batteryChargeTimeFromSet";
+    public static final String CHANNEL_BATTERYCHARGETIMETOSET = "batteryChargeTimeToSet";
+    public static final String CHANNEL_MAXDEPTHOFDISCHARGESET = "maxDepthOfDischargeSet";
+    public static final String CHANNEL_SHADOWMANAGEMENTSET = "shadowManagementSet";
+    public static final String CHANNEL_EXTERNALMODULECONTROLSET = "externalModuleControlSet";
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationChannelConfiguration.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationChannelConfiguration.java
new file mode 100644 (file)
index 0000000..dde6f09
--- /dev/null
@@ -0,0 +1,185 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.measure.Unit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.Units;
+
+/**
+ * The {@link SecondGenerationChannelConfiguration} class defines methods, which set up channel configuration,
+ * used in the second generation part of the binding.
+ *
+ *
+ * @author Christian Schneider - Initial contribution
+ * @author Christoph Weitkamp - Incorporated new QuantityType (Units of Measurement)
+ * @author Örjan Backsell - Added channels for (Piko1020, Piko New Generation)
+ */
+
+@NonNullByDefault
+public class SecondGenerationChannelConfiguration {
+    public String id;
+    public String tag;
+    public int num;
+    public Unit<?> unit;
+    public String dxsEntries;
+
+    public SecondGenerationChannelConfiguration(String id, String tag, int num, Unit<?> unit, String dxsEntries) {
+        this.id = id;
+        this.tag = tag;
+        this.num = num;
+        this.unit = unit;
+        this.dxsEntries = dxsEntries;
+    }
+
+    public static List<SecondGenerationChannelConfiguration> getChannelConfiguration() {
+        final List<SecondGenerationChannelConfiguration> channelConfiguration = new ArrayList<>();
+
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDOUTPUTPOWER, "td", 4, Units.WATT, "67109120"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_YIELD_DAY_SECOND_GEN, "td", 7, Units.WATT_HOUR, "251658754"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_YIELD_TOTAL_SECOND_GEN, "td", 10, Units.KILOWATT_HOUR,
+                "251658753"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_OPERATING_STATUS, "td", 13, Units.ONE, "16780032"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDVOLTAGEL1, "td", 16, Units.VOLT, "67109378"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDCURRENTL1, "td", 19, Units.AMPERE, "67109377"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDPOWERL1, "td", 22, Units.WATT, "67109379"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDVOLTAGEL2, "td", 25, Units.VOLT, "67109634"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDCURRENTL2, "td", 28, Units.AMPERE, "67109633"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDPOWERL2, "td", 31, Units.WATT, "67109635"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDVOLTAGEL3, "td", 34, Units.VOLT, "67109890"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDCURRENTL3, "td", 37, Units.AMPERE, "67109889"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDPOWERL3, "td", 40, Units.WATT, "67109891"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DCPOWERPV, "td", 43, Units.WATT, "33556736"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC1VOLTAGE, "td", 46, Units.VOLT, "33555202"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC1CURRENT, "td", 49, Units.AMPERE, "33555201"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC1POWER, "td", 52, Units.WATT, "33555203"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC2VOLTAGE, "td", 55, Units.VOLT, "33555458"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC2CURRENT, "td", 58, Units.AMPERE, "33555457"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC2POWER, "td", 61, Units.WATT, "33555459"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC3VOLTAGE, "td", 64, Units.VOLT, "33555714"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC3CURRENT, "td", 67, Units.AMPERE, "33555713"));
+        channelConfiguration.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_DC3POWER, "td", 70, Units.WATT, "33555715"));
+
+        return channelConfiguration;
+    }
+
+    public static List<SecondGenerationChannelConfiguration> getChannelConfigurationExt() {
+        final List<SecondGenerationChannelConfiguration> channelConfigurationExt = new ArrayList<>();
+
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_AKTHOMECONSUMTIONSOLAR, "td", 73, Units.WATT, "83886336"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_AKTHOMECONSUMPTIONBAT, "td", 76, Units.WATT, "83886592"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_AKTHOMECONSUMPTIONGRID, "td", 79, Units.WATT, "83886848"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_PHASESELHOMECONSUMPL1, "td", 82, Units.WATT, "83887106"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_PHASESELHOMECONSUMPL2, "td", 85, Units.WATT, "83887362"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_PHASESELHOMECONSUMPL3, "td", 88, Units.WATT, "83887618"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDFREQ, "td", 91, Units.HERTZ, "67110400"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_GRIDCOSPHI, "td", 94, Units.DEGREE_ANGLE, "67110656"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_HOMECONSUMPTION_DAY, "td", 97, Units.WATT_HOUR, "251659010"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_OWNCONSUMPTION_DAY, "td", 100, Units.WATT_HOUR, "251659266"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_OWNCONSRATE_DAY, "td", 103, Units.PERCENT, "251659278"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_AUTONOMYDEGREE_DAY, "td", 106, Units.PERCENT, "251659279"));
+        channelConfigurationExt.add(
+                new SecondGenerationChannelConfiguration(SecondGenerationBindingConstants.CHANNEL_HOMECONSUMPTION_TOTAL,
+                        "td", 109, Units.WATT_HOUR, "251659009"));
+        channelConfigurationExt.add(
+                new SecondGenerationChannelConfiguration(SecondGenerationBindingConstants.CHANNEL_OWNCONSUMPTION_TOTAL,
+                        "td", 112, Units.WATT_HOUR, "251659265"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_OPERATINGTIME_TOTAL, "td", 115, Units.HOUR, "251658496"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_CURRENT, "td", 118, Units.AMPERE, "33556238"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_CURRENTDIR, "td", 121, Units.ONE, "33556230"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_CHARGECYCLES, "td", 124, Units.ONE, "33556228"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_BATTERYTEMPERATURE, "td", 127, SIUnits.CELSIUS, "33556227"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_LOGINTERVAL, "td", 130, Units.MINUTE, "150995968"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_S0INPULSECNT, "td", 133, Units.ONE, "184549632"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_OWNCONSRATE_TOTAL, "td", 136, Units.PERCENT, "251659280"));
+        channelConfigurationExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_AUTONOMYDEGREE_TOTAL, "td", 139, Units.PERCENT, "251659281"));
+
+        return channelConfigurationExt;
+    }
+
+    public static List<SecondGenerationChannelConfiguration> getChannelConfigurationExtExt() {
+        final List<SecondGenerationChannelConfiguration> channelConfigurationExtExt = new ArrayList<>();
+
+        channelConfigurationExtExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_BATTERYVOLTAGE, "td", 142, Units.VOLT, "33556226"));
+        channelConfigurationExtExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_BATSTATEOFCHARGE, "td", 145, Units.PERCENT, "33556229"));
+        channelConfigurationExtExt.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_SELFCONSUMPTION, "td", 148, Units.WATT, "83888128"));
+        return channelConfigurationExtExt;
+    }
+
+    public static List<SecondGenerationChannelConfiguration> getChannelConfigurationConfigurable() {
+        final List<SecondGenerationChannelConfiguration> channelConfigurationConfigurable = new ArrayList<>();
+        channelConfigurationConfigurable.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_BATTERYUSAGECONSUMPTION, "td", 151, Units.WATT, "33556249"));
+        channelConfigurationConfigurable.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_SMARTBATTERYCONTROL, "td", 154, Units.ONE, "33556484"));
+        channelConfigurationConfigurable.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_MAXDEPTHOFDISCHARGE, "td", 157, Units.ONE, "33556247"));
+        channelConfigurationConfigurable.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_SHADOWMANAGEMENT, "td", 160, Units.ONE, "33556483"));
+        channelConfigurationConfigurable.add(new SecondGenerationChannelConfiguration(
+                SecondGenerationBindingConstants.CHANNEL_EXTERNALMODULECONTROL, "td", 163, Units.ONE, "33556482"));
+        return channelConfigurationConfigurable;
+    }
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationConfigurationHandler.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationConfigurationHandler.java
new file mode 100644 (file)
index 0000000..e5d064e
--- /dev/null
@@ -0,0 +1,161 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.util.StringContentProvider;
+import org.eclipse.jetty.http.HttpHeader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * The {@link SecondGenerationConfigurationHandler} is responsible for configuration changes,
+ * regarded to second generation part of the binding.
+ *
+ * @author Örjan Backsell - Initial contribution Piko1020, Piko New Generation
+ */
+@NonNullByDefault
+public class SecondGenerationConfigurationHandler {
+
+    public static void executeConfigurationChanges(HttpClient httpClient, String url, String username, String password,
+            String dxsId, String value)
+            throws InterruptedException, ExecutionException, TimeoutException, NoSuchAlgorithmException {
+        String urlLogin = url + "/api/login.json?";
+        String salt = "";
+        String sessionId = "";
+
+        Logger logger = LoggerFactory.getLogger(SecondGenerationConfigurationHandler.class);
+
+        String getAuthenticateResponse = httpClient.GET(urlLogin).getContentAsString();
+
+        try {
+            JsonObject getAuthenticateResponseJsonObject = (JsonObject) new JsonParser()
+                    .parse(transformJsonResponse(getAuthenticateResponse));
+
+            sessionId = extractSessionId(getAuthenticateResponseJsonObject);
+
+            JsonObject authenticateJsonObject = new JsonParser().parse(getAuthenticateResponse.toString())
+                    .getAsJsonObject();
+            salt = authenticateJsonObject.get("salt").getAsString();
+
+            String saltedPassword = new StringBuilder(password).append(salt).toString();
+            MessageDigest mDigest = MessageDigest.getInstance("SHA1");
+
+            byte[] mDigestedPassword = mDigest.digest(saltedPassword.getBytes(StandardCharsets.UTF_8));
+            StringBuilder loginPostStringBuilder = new StringBuilder();
+            for (int i = 0; i < mDigestedPassword.length; i++) {
+                loginPostStringBuilder.append(Integer.toString((mDigestedPassword[i] & 0xff) + 0x100, 16).substring(1));
+            }
+            String saltedmDigestedPwd = Base64.getEncoder().encodeToString(mDigest.digest(saltedPassword.getBytes()));
+
+            String loginPostJsonData = "{\"mode\":1,\"userId\":\"" + username + "\",\"pwh\":\"" + saltedmDigestedPwd
+                    + "\"}";
+
+            Request loginPostJsonResponse = httpClient.POST(urlLogin + "?sessionId=" + sessionId);
+            loginPostJsonResponse.header(HttpHeader.CONTENT_TYPE, "application/json");
+            loginPostJsonResponse.content(new StringContentProvider(loginPostJsonData));
+            ContentResponse loginPostJsonDataContentResponse = loginPostJsonResponse.send();
+
+            String loginPostResponse = new String(loginPostJsonDataContentResponse.getContent(),
+                    StandardCharsets.UTF_8);
+
+            JsonObject loginPostJsonObject = (JsonObject) new JsonParser()
+                    .parse(transformJsonResponse(loginPostResponse));
+
+            sessionId = extractSessionId(loginPostJsonObject);
+
+            // Part for sending data to Inverter
+            String postJsonData = "{\"dxsEntries\":[{\"dxsId\":" + dxsId + ",\"value\":" + value + "}]}";
+
+            Request postJsonDataRequest = httpClient.POST(url + "/api/dxs.json?sessionId=" + sessionId);
+            postJsonDataRequest.header(HttpHeader.CONTENT_TYPE, "application/json");
+            postJsonDataRequest.content(new StringContentProvider(postJsonData));
+            postJsonDataRequest.send();
+        } catch (JsonIOException getAuthenticateResponseException) {
+            logger.debug("Could not read the response: {}", getAuthenticateResponseException.getMessage());
+        }
+    }
+
+    static String transformJsonResponse(String jsonResponse) {
+        // Method transformJsonResponse converts response,due to missing [] in ContentResponse
+        // postJsonDataContentResponse.
+
+        int sessionStartPosition = jsonResponse.indexOf("session");
+        int statusStartPosition = jsonResponse.indexOf("status");
+
+        StringBuilder transformStringBuilder = new StringBuilder();
+
+        transformStringBuilder.append(jsonResponse);
+
+        transformStringBuilder.insert(sessionStartPosition + 9, '[');
+        int roleIdStartPosition = jsonResponse.indexOf("roleId");
+        transformStringBuilder.insert(roleIdStartPosition + 11, ']');
+
+        transformStringBuilder.insert(statusStartPosition + 10, '[');
+        int codeStartPosition = jsonResponse.indexOf("code");
+        transformStringBuilder.insert(codeStartPosition + 11, ']');
+
+        String transformJsonObject = transformStringBuilder.toString();
+
+        return transformJsonObject;
+    }
+
+    // Method extractSessionId extracts sessionId from JsonObject
+    static String extractSessionId(JsonObject extractJsonObjectSessionId) {
+        Logger sessionIdLogger = LoggerFactory.getLogger(SecondGenerationConfigurationHandler.class);
+        String extractSessionId = "";
+        JsonArray extractJsonArraySessionId = extractJsonObjectSessionId.getAsJsonArray("session");
+
+        int size = extractJsonArraySessionId.size();
+        if (size > 0) {
+            extractSessionId = extractJsonArraySessionId.get(size - 1).getAsJsonObject().get("sessionId").getAsString();
+        }
+        if (extractSessionId == "0") {
+            sessionIdLogger.debug(" Login Post Json Reponse not OK! , inverter answered with sessionId like: {}",
+                    extractSessionId);
+        }
+        return extractSessionId;
+    }
+
+    // Method extractCode extracts code from JsonObject
+    static String extractCode(JsonObject extractJsonObjectCode) {
+        Logger codeLogger = LoggerFactory.getLogger(SecondGenerationConfigurationHandler.class);
+        String extractCode = "";
+        JsonArray extractJsonArrayCode = extractJsonObjectCode.getAsJsonArray("status");
+
+        int size = extractJsonArrayCode.size();
+        if (size > 0) {
+            extractCode = extractJsonArrayCode.get(size - 1).getAsJsonObject().get("code").getAsString();
+        }
+        if (extractCode != "0") {
+            codeLogger.debug(" Login Post Json Reponse not OK! , inverter answered with status code like: {}",
+                    extractCode);
+        }
+        return extractCode;
+    }
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntries.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntries.java
new file mode 100644 (file)
index 0000000..cbfc286
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link SecondGenerationDxsEntries} class defines methods, which are
+ * used in the second generation part of the binding.
+ *
+ * @author Örjan Backsell - Initial contribution Piko1020, Piko New Generation
+ */
+@NonNullByDefault
+public class SecondGenerationDxsEntries {
+    private String dxsId = "";
+    private String value = "";
+
+    public String getId() {
+        return dxsId;
+    }
+
+    public String getName() {
+        return value;
+    }
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntriesContainerDTO.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntriesContainerDTO.java
new file mode 100644 (file)
index 0000000..bbcf812
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import java.util.List;
+
+/**
+ * The {@link SecondGenerationDxsEntriesContainer} class defines an Container, which is
+ * used in the second generation part of the binding.
+ *
+ * @author Örjan Backsell - Initial contribution Piko1020, Piko New Generation
+ */
+
+public class SecondGenerationDxsEntriesContainerDTO {
+    public List<SecondGenerationDxsEntries> dxsEntries;
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationHandler.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationHandler.java
new file mode 100644 (file)
index 0000000..2c0f656
--- /dev/null
@@ -0,0 +1,401 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+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.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.types.StringType;
+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.types.Command;
+import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * The {@link SecondGenerationHandler} is responsible for handling commands, which are
+ * sent to one of the channels, and initiation and refreshing regarded to second generation part of the binding.
+ *
+ *
+ * @author Christian Schneider - Initial contribution
+ * @author Christoph Weitkamp - Incorporated new QuantityType (Units of Measurement)
+ * @author Örjan Backsell - Redesigned regarding Piko1020, Piko New Generation
+ */
+@NonNullByDefault
+public class SecondGenerationHandler extends BaseThingHandler {
+
+    private final Logger logger = LoggerFactory.getLogger(SecondGenerationHandler.class);
+
+    private @Nullable ScheduledFuture<?> secondGenerationPoller;
+
+    private final HttpClient httpClient;
+
+    private List<SecondGenerationChannelConfiguration> channelConfigs = new ArrayList<>();
+    private List<SecondGenerationChannelConfiguration> channelConfigsExt = new ArrayList<>();
+    private List<SecondGenerationChannelConfiguration> channelConfigsExtExt = new ArrayList<>();
+    private List<SecondGenerationChannelConfiguration> channelConfigsConfigurable = new ArrayList<>();
+    private List<SecondGenerationChannelConfiguration> channelConfigsAll = new ArrayList<>();
+
+    private List<String> channelPostsTemp = new ArrayList<>();
+    private List<String> channelPostsTempExt = new ArrayList<>();
+    private List<String> channelPostsTempExtExt = new ArrayList<>();
+    private List<String> channelPostsTempAll = new ArrayList<>();
+
+    private SecondGenerationInverterConfig inverterConfig = new SecondGenerationInverterConfig();
+    private Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+    public SecondGenerationHandler(Thing thing, HttpClient httpClient) {
+        super(thing);
+        this.httpClient = httpClient;
+    }
+
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        String url = inverterConfig.url;
+        String username = inverterConfig.username;
+        String password = inverterConfig.password;
+        String valueConfiguration = "";
+        String dxsEntriesConf = "";
+
+        if (inverterConfig.hasBattery) {
+            switch (channelUID.getId()) {
+                case SecondGenerationBindingConstants.CHANNEL_BATTERYUSAGECONSUMPTIONSET:
+                    valueConfiguration = command.toString();
+                    dxsEntriesConf = "33556249";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfiguration);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_BATTERYUSAGESTRATEGYSET:
+                    valueConfiguration = command.toString();
+                    dxsEntriesConf = "83888896";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfiguration);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_SMARTBATTERYCONTROLSET:
+                    if (command.toString().equals("ON")) {
+                        valueConfiguration = "true";
+                    }
+                    if (command.toString().equals("OFF")) {
+                        valueConfiguration = "false";
+                    }
+                    dxsEntriesConf = "33556484";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfiguration);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_BATTERYCHARGETIMEFROMSET:
+                    valueConfiguration = command.toString();
+                    String valueConfigurationFromTransformed = String.valueOf(stringToSeconds(valueConfiguration));
+                    dxsEntriesConf = "33556239";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfigurationFromTransformed);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_BATTERYCHARGETIMETOSET:
+                    valueConfiguration = command.toString();
+                    String valueConfigurationToTransformed = String.valueOf(stringToSeconds(valueConfiguration));
+                    dxsEntriesConf = "33556240";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfigurationToTransformed);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_MAXDEPTHOFDISCHARGESET:
+                    valueConfiguration = command.toString();
+                    dxsEntriesConf = "33556247";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfiguration);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_SHADOWMANAGEMENTSET:
+                    valueConfiguration = command.toString();
+                    dxsEntriesConf = "33556483";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfiguration);
+                    break;
+                case SecondGenerationBindingConstants.CHANNEL_EXTERNALMODULECONTROLSET:
+                    valueConfiguration = command.toString();
+                    dxsEntriesConf = "33556482";
+                    preSetExecuteConfigurationChanges(httpClient, url, username, password, dxsEntriesConf,
+                            valueConfiguration);
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public void initialize() {
+        // Set channel configuration parameters
+        channelConfigs = SecondGenerationChannelConfiguration.getChannelConfiguration();
+        channelConfigsExt = SecondGenerationChannelConfiguration.getChannelConfigurationExt();
+        channelConfigsExtExt = SecondGenerationChannelConfiguration.getChannelConfigurationExtExt();
+        channelConfigsConfigurable = SecondGenerationChannelConfiguration.getChannelConfigurationConfigurable();
+
+        // Set inverter configuration parameters
+        final SecondGenerationInverterConfig inverterConfig = getConfigAs(SecondGenerationInverterConfig.class);
+        this.inverterConfig = inverterConfig;
+
+        // Temporary value during initializing
+        updateStatus(ThingStatus.UNKNOWN);
+
+        // Start update as configured
+        secondGenerationPoller = scheduler.scheduleWithFixedDelay(() -> {
+            try {
+                refresh();
+                updateStatus(ThingStatus.ONLINE);
+            } catch (RuntimeException scheduleWithFixedDelayException) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        scheduleWithFixedDelayException.getClass().getName() + ":"
+                                + scheduleWithFixedDelayException.getMessage());
+            } catch (InterruptedException interruptedException) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        interruptedException.getClass().getName() + ":" + interruptedException.getMessage());
+            } catch (ExecutionException executionException) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        executionException.getClass().getName() + ":" + executionException.getMessage());
+            } catch (TimeoutException timeoutException) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        timeoutException.getClass().getName() + ":" + timeoutException.getMessage());
+            }
+        }, 0, SecondGenerationInverterConfig.REFRESHINTERVAL_SEC, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void dispose() {
+        final ScheduledFuture<?> secondGenerationLocalPoller = secondGenerationPoller;
+
+        if (secondGenerationLocalPoller != null) {
+            secondGenerationLocalPoller.cancel(true);
+            secondGenerationPoller = null;
+        }
+    }
+
+    private void refresh() throws InterruptedException, ExecutionException, TimeoutException {
+        // Build posts for dxsEntries part
+        String dxsEntriesCall = inverterConfig.url + "/api/dxs.json?dxsEntries=" + channelConfigs.get(0).dxsEntries;
+        for (int i = 1; i < channelConfigs.size(); i++) {
+            dxsEntriesCall += ("&dxsEntries=" + channelConfigs.get(i).dxsEntries);
+        }
+        String jsonDxsEntriesResponse = callURL(dxsEntriesCall);
+        SecondGenerationDxsEntriesContainerDTO dxsEntriesContainer = gson.fromJson(jsonDxsEntriesResponse,
+                SecondGenerationDxsEntriesContainerDTO.class);
+
+        String[] channelPosts = new String[23];
+        int channelPostsCounter = 0;
+        for (SecondGenerationDxsEntries dxsentries : dxsEntriesContainer.dxsEntries) {
+            channelPosts[channelPostsCounter] = dxsentries.getName();
+            channelPostsCounter++;
+        }
+        channelPostsTemp = List.of(channelPosts);
+
+        // Build posts for dxsEntriesExt part
+        String dxsEntriesCallExt = inverterConfig.url + "/api/dxs.json?dxsEntries="
+                + channelConfigsExt.get(0).dxsEntries;
+        for (int i = 1; i < channelConfigs.size(); i++) {
+            dxsEntriesCallExt += ("&dxsEntries=" + channelConfigsExt.get(i).dxsEntries);
+        }
+        String jsonDxsEntriesResponseExt = callURL(dxsEntriesCallExt);
+        SecondGenerationDxsEntriesContainerDTO dxsEntriesContainerExt = gson.fromJson(jsonDxsEntriesResponseExt,
+                SecondGenerationDxsEntriesContainerDTO.class);
+        String[] channelPostsExt = new String[23];
+        int channelPostsCounterExt = 0;
+        for (SecondGenerationDxsEntries dxsentriesExt : dxsEntriesContainerExt.dxsEntries) {
+            channelPostsExt[channelPostsCounterExt] = dxsentriesExt.getName();
+            channelPostsCounterExt++;
+        }
+        channelPostsTempExt = List.of(channelPostsExt);
+
+        // Build posts for dxsEntriesExtExt part
+        String dxsEntriesCallExtExt = inverterConfig.url + "/api/dxs.json?dxsEntries="
+                + channelConfigsExtExt.get(0).dxsEntries;
+        for (int i = 1; i < channelConfigsExtExt.size(); i++) {
+            dxsEntriesCallExtExt += ("&dxsEntries=" + channelConfigsExtExt.get(i).dxsEntries);
+        }
+        String jsonDxsEntriesResponseExtExt = callURL(dxsEntriesCallExtExt);
+        SecondGenerationDxsEntriesContainerDTO dxsEntriesContainerExtExt = gson.fromJson(jsonDxsEntriesResponseExtExt,
+                SecondGenerationDxsEntriesContainerDTO.class);
+        String[] channelPostsExtExt = new String[3];
+        int channelPostsCounterExtExt = 0;
+        for (SecondGenerationDxsEntries dxsentriesExtExt : dxsEntriesContainerExtExt.dxsEntries) {
+            channelPostsExtExt[channelPostsCounterExtExt] = dxsentriesExtExt.getName();
+            channelPostsCounterExtExt++;
+        }
+        channelPostsTempExtExt = List.of(channelPostsExtExt);
+
+        // Concatenate posts for all parts except configurable channels
+        channelPostsTempAll = combinePostsLists(channelPostsTemp, channelPostsTempExt, channelPostsTempExtExt);
+        String[] channelPostsTempAll1 = channelPostsTempAll.toArray(new String[0]);
+
+        // Build posts for dxsEntriesConfigureable part
+        String dxsEntriesCallConfigurable = inverterConfig.url + "/api/dxs.json?dxsEntries="
+                + channelConfigsConfigurable.get(0).dxsEntries;
+        for (int i = 1; i < channelConfigsConfigurable.size(); i++) {
+            dxsEntriesCallConfigurable += ("&dxsEntries=" + channelConfigsConfigurable.get(i).dxsEntries);
+        }
+        String jsonDxsEntriesResponseConfigurable = callURL(dxsEntriesCallConfigurable);
+        SecondGenerationDxsEntriesContainerDTO dxsEntriesContainerConfigurable = gson
+                .fromJson(jsonDxsEntriesResponseConfigurable, SecondGenerationDxsEntriesContainerDTO.class);
+        String[] channelPostsConfigurable = new String[5];
+        int channelPostsCounterConfigurable = 0;
+        for (SecondGenerationDxsEntries dxsentriesConfigurable : dxsEntriesContainerConfigurable.dxsEntries) {
+            channelPostsConfigurable[channelPostsCounterConfigurable] = dxsentriesConfigurable.getName();
+            channelPostsCounterConfigurable++;
+        }
+
+        // Create and update actual values for non-configurable channels
+        if (!inverterConfig.hasBattery) {
+            channelConfigsAll = combineChannelConfigLists(channelConfigs, channelConfigsExt, channelConfigsExtExt);
+            int channelValuesCounterAll = 0;
+            for (SecondGenerationChannelConfiguration cConfig : channelConfigsAll) {
+                String channel = cConfig.id;
+                updateState(channel, getState(channelPostsTempAll1[channelValuesCounterAll], cConfig.unit));
+                channelValuesCounterAll++;
+            }
+        }
+        // Create and update actual values for all channels
+        if (inverterConfig.hasBattery) {
+            // Part for updating non-configurable channels
+            channelConfigsAll = combineChannelConfigLists(channelConfigs, channelConfigsExt, channelConfigsExtExt);
+            // Update the non-configurable channels
+            int channelValuesCounterAll = 0;
+            for (SecondGenerationChannelConfiguration cConfig : channelConfigsAll) {
+                String channel = cConfig.id;
+                updateState(channel, getState(channelPostsTempAll1[channelValuesCounterAll], cConfig.unit));
+                channelValuesCounterAll++;
+            }
+
+            // Part for updating configurable channels
+            int channelValuesCounterConfigurable = 0;
+            for (SecondGenerationChannelConfiguration cConfig : channelConfigsConfigurable) {
+                String channel = cConfig.id;
+                String value = channelPostsConfigurable[channelValuesCounterConfigurable];
+                int dxsEntriesCheckCounter = 3;
+                if (cConfig.dxsEntries.equals("33556484")) {
+                    dxsEntriesCheckCounter = 1;
+                }
+                if (cConfig.dxsEntries.equals("33556482")) {
+                    dxsEntriesCheckCounter = 2;
+                }
+                switch (dxsEntriesCheckCounter) {
+                    case 1:
+                        if (value.equals("false")) {
+                            updateState(channel, OnOffType.OFF);
+                        }
+                        if (value.equals("true")) {
+                            updateState(channel, OnOffType.ON);
+                        }
+                        channelValuesCounterConfigurable++;
+                        break;
+                    case 2:
+                        if (value.equals("false")) {
+                            State stateFalse = new StringType("0");
+                            updateState(channel, stateFalse);
+                        }
+                        if (value.equals("true")) {
+                            State stateTrue = new StringType("1");
+                            updateState(channel, stateTrue);
+                        }
+                        channelValuesCounterConfigurable++;
+                        break;
+                    case 3:
+                        State stateOther = getState(channelPostsConfigurable[channelValuesCounterConfigurable],
+                                cConfig.unit);
+                        updateState(channel, stateOther);
+                        channelValuesCounterConfigurable++;
+                        break;
+                }
+            }
+        }
+    }
+
+    // Help method of handleCommand to with SecondGenerationConfigurationHandler.executeConfigurationChanges method send
+    // configuration changes.
+    private final void preSetExecuteConfigurationChanges(HttpClient httpClient, String url, String username,
+            String password, String dxsEntriesConf, String valueConfiguration) {
+        try {
+            SecondGenerationConfigurationHandler.executeConfigurationChanges(httpClient, url, username, password,
+                    dxsEntriesConf, valueConfiguration);
+        } catch (Exception handleCommandException) {
+            logger.debug("Handle command for {} on channel {}: {}: {}: {}: {}", thing.getUID(), httpClient, url,
+                    dxsEntriesConf, valueConfiguration, handleCommandException.getMessage());
+        }
+    }
+
+    // Method callURL connect to inverter for value scraping
+    private final String callURL(String dxsEntriesCall)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        String jsonDxsResponse = httpClient.GET(dxsEntriesCall).getContentAsString();
+        return jsonDxsResponse;
+    }
+
+    // Method getState is used for non-configurable values
+    private State getState(String value, @Nullable Unit<?> unit) {
+        if (unit == null) {
+            return new StringType(value);
+        } else {
+            try {
+                return new QuantityType<>(new BigDecimal(value), unit);
+            } catch (NumberFormatException getStateException) {
+                logger.debug("Error parsing value '{}: {}'", value, getStateException.getMessage());
+                return UnDefType.UNDEF;
+            }
+        }
+    }
+
+    // Method stringToSeconds transform given time in 00:16 syntax to seconds syntax
+    private static long stringToSeconds(String stringTime) {
+        long secondsMin = Long.parseLong(stringTime.substring(3, 5)) * 60;
+        long secondsHrs = Long.parseLong(stringTime.substring(0, 2)) * 3600;
+        return secondsMin + secondsHrs;
+    }
+
+    // Method to concatenate channelConfigs Lists to one List
+    @SafeVarargs
+    private final List<SecondGenerationChannelConfiguration> combineChannelConfigLists(
+            List<SecondGenerationChannelConfiguration>... args) {
+        List<SecondGenerationChannelConfiguration> combinedChannelConfigLists = new ArrayList<>();
+        for (List<SecondGenerationChannelConfiguration> list : args) {
+            for (SecondGenerationChannelConfiguration i : list) {
+                combinedChannelConfigLists.add(i);
+            }
+        }
+        return combinedChannelConfigLists;
+    }
+
+    // Method to concatenate channelPosts Lists to one List
+    @SafeVarargs
+    private final List<String> combinePostsLists(List<String>... args) {
+        List<String> combinedPostsLists = new ArrayList<>();
+        for (List<String> list : args) {
+            for (String i : list) {
+                combinedPostsLists.add(i);
+            }
+        }
+        return combinedPostsLists;
+    }
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationInverterConfig.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationInverterConfig.java
new file mode 100644 (file)
index 0000000..f7a0588
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.kostalinverter.internal.secondgeneration;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link SecondGenerationInverterConfig} class defines constants, which are
+ * used in the second generation part of the binding.
+ *
+ * @author Christian Schneider - Initial contribution
+ * @author Örjan Backsell - Added parameters for configuration options Piko1020, Piko New Generation
+ *
+ */
+
+@NonNullByDefault
+public class SecondGenerationInverterConfig {
+    public static final long REFRESHINTERVAL_SEC = 60;
+
+    public String url = "";
+    public String username = "";
+    public String password = "";
+    public String dxsIdConf = "";
+    public String valueConf = "";
+    public boolean hasBattery;
+}
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/config/SecondGeneration.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/config/SecondGeneration.xml
new file mode 100644 (file)
index 0000000..f60c39f
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<config-description:config-descriptions
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
+       <config-description uri="thing-type:kostalpiko1020_config">
+               <parameter name="url" type="text" required="true">
+                       <label>IP Address</label>
+                       <description>IP address of the inverter.</description>
+                       <context>url</context>
+               </parameter>
+               <parameter name="username" type="text" required="true">
+                       <label>Username</label>
+                       <description>The username to the inverter.</description>
+               </parameter>
+               <parameter name="password" type="text" required="true">
+                       <label>Password</label>
+                       <description>The password to the inverter.</description>
+                       <context>password</context>
+               </parameter>
+               <parameter name="refreshInterval" type="integer" min="1" unit="s" required="true">
+                       <label>Refresh Interval</label>
+                       <description>Refresh Interval in seconds.</description>
+                       <default>60</default>
+               </parameter>
+               <parameter name="hasBattery" type="boolean" required="true">
+                       <label>Inverter Type</label>
+                       <description>Type of inverter, with/without battery.</description>
+               </parameter>
+       </config-description>
+</config-description:config-descriptions>
index 68b15b3ce69d3fa7be95055da2173ad1b9c520b0..304aa0ebc6644fea36b1c7998b32d700b6bc18fc 100644 (file)
@@ -32,7 +32,7 @@
        <channel-type id="device-local-ownconsumption">
                <item-type>Number:Power</item-type>
                <label>Own Consumption</label>
-               <description>Current own comsumption</description>
+               <description>Current own consumption</description>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
@@ -46,7 +46,7 @@
        <channel-type id="device-local-homeconsumption-total">
                <item-type>Number:Power</item-type>
                <label>Home Consumption</label>
-               <description>Current total homeconsumption</description>
+               <description>Current total home consumption</description>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
+       <channel-type id="device-local-grid-output-power">
+               <item-type>Number:Power</item-type>
+               <label>Grid Output Power</label>
+               <description>Current output power to the grid</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-yield-day-second-gen">
+               <item-type>Number:Energy</item-type>
+               <label>Yield Day</label>
+               <description>Total produced power day</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-yield-total-second-gen">
+               <item-type>Number:Energy</item-type>
+               <label>Yield Total</label>
+               <description>Total produced power</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-operating-status">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Operating Status</label>
+               <description>Operating status</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="device-local-grid-voltage-l1">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Grid Voltage L1</label>
+               <description>Current output voltage to the grid, L1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-current-l1">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Grid Amperage L1</label>
+               <description>Current output amperage to the grid, L1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f  %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-power-l1">
+               <item-type>Number:Power</item-type>
+               <label>Grid Power L1</label>
+               <description>Current output power to the grid, L1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-voltage-l2">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Grid Voltage L2</label>
+               <description>Current output voltage to the grid, L2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-current-l2">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Grid Amperage L2</label>
+               <description>Current output amperage to the grid, L2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-power-l2">
+               <item-type>Number:Power</item-type>
+               <label>Grid Power L2</label>
+               <description>Current output power to the grid, L2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-voltage-l3">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Grid Voltage L3</label>
+               <description>Current output voltage to the grid, L3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-current-l3">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Grid Amperage L3</label>
+               <description>Current output amperage to the grid, L3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-power-l3">
+               <item-type>Number:Power</item-type>
+               <label>Grid Power L3</label>
+               <description>Current output power to the grid, L3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc-power-pv">
+               <item-type>Number:Power</item-type>
+               <label>DC Power PV</label>
+               <description>Current power from solar panels</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc1-voltage">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>DC1 Voltage</label>
+               <description>Current voltage from solar panels, DC1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc1-current">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>DC1 Amperage</label>
+               <description>Current amperage from solar panels, DC1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc1-power">
+               <item-type>Number:Power</item-type>
+               <label>DC1 Power</label>
+               <description>Current power from solar panels, DC1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc2-voltage">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>DC2 Voltage</label>
+               <description>Current voltage from solar panels, DC2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc2-current">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>DC2 Amperage</label>
+               <description>Current amperage from solar panels, DC2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc2-power">
+               <item-type>Number:Power</item-type>
+               <label>DC2 Power</label>
+               <description>Current power from solar panels, DC2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc3-voltage">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>DC3 Voltage</label>
+               <description>Current voltage from solar panels, DC3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc3-current">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>DC3 Amperage</label>
+               <description>Current amperage from solar panels, DC3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-dc3-power">
+               <item-type>Number:Power</item-type>
+               <label>DC3 Power</label>
+               <description>Current power from solar panels, DC3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-akt-home-consumption-solar">
+               <item-type>Number:Power</item-type>
+               <label>Home Consumption PV</label>
+               <description>Current consumption from solar panels</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-akt-home-consumption-bat">
+               <item-type>Number:Power</item-type>
+               <label>Home Consumption Bat</label>
+               <description>Current consumption from battery</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-akt-home-consumption-grid">
+               <item-type>Number:Power</item-type>
+               <label>Home Consumption Grid</label>
+               <description>Current consumption from grid</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-phase-sel-home-consump-l1">
+               <item-type>Number:Power</item-type>
+               <label>Home Consumption L1</label>
+               <description>Current home consumption, L1</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-phase-sel-home-consump-l2">
+               <item-type>Number:Power</item-type>
+               <label>Home Consumption L2</label>
+               <description>Current home consumption, L2</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-phase-sel-home-consump-l3">
+               <item-type>Number:Power</item-type>
+               <label>Home Consumption L3</label>
+               <description>Current home consumption, L3</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-freq">
+               <item-type>Number:Frequency</item-type>
+               <label>Grid Freq</label>
+               <description>Current frequency on grid</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-grid-cos-phi">
+               <item-type>Number:Angle</item-type>
+               <label>Grid Cos Phi</label>
+               <description>Current power factor on grid</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-home-consumption-day">
+               <item-type>Number:Energy</item-type>
+               <label>Home Consumption Day</label>
+               <description>Total home consumption day</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-own-consumption-day">
+               <item-type>Number:Energy</item-type>
+               <label>Own Consumption Day</label>
+               <description>Total own consumption day</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-own-cons-rate-day">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Own Cons Rate Day</label>
+               <description>Total own consumption rate day</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-autonomy-degree-day">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Autonomy Degree Day</label>
+               <description>Total autonomy degree day</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-home-consumption-total">
+               <item-type>Number:Energy</item-type>
+               <label>Home Consumption Total</label>
+               <description>Total home consumption</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-own-consumption-total">
+               <item-type>Number:Energy</item-type>
+               <label>Own Consumption Total</label>
+               <description>Total own consumptionl</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-operating-time-total">
+               <item-type>Number:Time</item-type>
+               <label>Operating Time Total</label>
+               <description>Total operating time</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-current">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current</label>
+               <description>Current</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-current-dir">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Current Dir</label>
+               <description>Current direction</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="device-local-charge-cycles">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Charge Cycles</label>
+               <description>Total number of charge cycles</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="device-local-battery-temperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Battery Temperature</label>
+               <description>Current battery temperature</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-loginterval">
+               <item-type>Number:Time</item-type>
+               <label>Loginterval</label>
+               <description>Value for log interval</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-s0-inpulse-cnt">
+               <item-type>Number:Dimensionless</item-type>
+               <label>S0 Inpulse Cnt</label>
+               <description>S0-pulse counter</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="statistic-own-cons-rate-total">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Own Cons Rate Total</label>
+               <description>Total own consumption rate</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="statistic-autonomy-degree-total">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Autonomy Degree Total</label>
+               <description>Total autonomy degree</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-battery-voltage">
+               <item-type>Number:ElectricalPotential</item-type>
+               <label>Battery Voltage</label>
+               <description>Current battery voltage</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-bat-state-of-charge">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Bat State of Charge</label>
+               <description>Current battery charge state</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-self-consumption">
+               <item-type>Number:Power</item-type>
+               <label>Self Consumption</label>
+               <description>Current self consumption</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-battery-usage-consumption">
+               <item-type>Number:Power</item-type>
+               <label>Battery Usage Consumption</label>
+               <description>Battery usage consumption</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="device-local-smart-battery-control">
+               <item-type>Switch</item-type>
+               <label>Smart Battery Control</label>
+               <description>Smart battery control</description>
+               <category>Energy</category>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="device-local-max-depth-of-discharge">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Max Depth of Discharge</label>
+               <description>Max depth of discharge</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="device-local-shadow-management">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Shadow Management</label>
+               <description>Shadow management</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="device-local-external-module-control">
+               <item-type>Number:Dimensionless</item-type>
+               <label>External Module Control</label>
+               <description>External Module Control</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="device-local-battery-usage-consumption-set">
+               <item-type>String</item-type>
+               <label>Battery Usage Consumption Set</label>
+               <description>Set battery usage consumption</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-battery-usage-strategy-set">
+               <item-type>String</item-type>
+               <label>Battery Usage Strategy Set</label>
+               <description>Set battery usage strategy</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-smart-battery-control-set">
+               <item-type>Switch</item-type>
+               <label>Smart Battery Control Set</label>
+               <description>Set smart battery control</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-battery-charge-time-from-set">
+               <item-type>String</item-type>
+               <label>Battery Charge Time from Set</label>
+               <description>Set battery charge time from</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-battery-charge-time-to-set">
+               <item-type>String</item-type>
+               <label>Battery Charge Time to Set</label>
+               <description>Set battery charge time to</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-max-depth-of-discharge-set">
+               <item-type>String</item-type>
+               <label>Max Depth of Discharge Set</label>
+               <description>Set max depth of discharge</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-shadow-management-set">
+               <item-type>String</item-type>
+               <label>Shadow Management Set</label>
+               <description>Set shadow management</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="device-local-external-module-control-set">
+               <item-type>String</item-type>
+               <label>External Module Control Set</label>
+               <description>Set External Module Control</description>
+               <category>Energy</category>
+               <state readOnly="false"/>
+       </channel-type>
 </thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/PIKO1020.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/PIKO1020.xml
new file mode 100644 (file)
index 0000000..662dfe6
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="kostalinverter"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+       <thing-type id="piko1020">
+               <label>KOSTAL PIKO 10-20</label>
+               <description>Bindings for the KOSTAL PIKO 10-20</description>
+               <category>Inverter</category>
+               <channels>
+                       <channel typeId="device-local-grid-output-power" id="gridOutputPower"/>
+                       <channel typeId="statistic-yield-day-second-gen" id="yieldDaySecondGen"/>
+                       <channel typeId="statistic-yield-total-second-gen" id="yieldTotalSecondGen"/>
+                       <channel typeId="device-local-operating-status" id="operatingStatus"/>
+                       <channel typeId="device-local-grid-voltage-l1" id="gridVoltageL1"/>
+                       <channel typeId="device-local-grid-current-l1" id="gridCurrentL1"/>
+                       <channel typeId="device-local-grid-power-l1" id="gridPowerL1"/>
+                       <channel typeId="device-local-grid-voltage-l2" id="gridVoltageL2"/>
+                       <channel typeId="device-local-grid-current-l2" id="gridCurrentL2"/>
+                       <channel typeId="device-local-grid-power-l2" id="gridPowerL2"/>
+                       <channel typeId="device-local-grid-voltage-l3" id="gridVoltageL3"/>
+                       <channel typeId="device-local-grid-current-l3" id="gridCurrentL3"/>
+                       <channel typeId="device-local-grid-power-l3" id="gridPowerL3"/>
+                       <channel typeId="device-local-dc-power-pv" id="dcPowerPV"/>
+                       <channel typeId="device-local-dc1-voltage" id="dc1Voltage"/>
+                       <channel typeId="device-local-dc1-current" id="dc1Current"/>
+                       <channel typeId="device-local-dc1-power" id="dc1Power"/>
+                       <channel typeId="device-local-dc2-voltage" id="dc2Voltage"/>
+                       <channel typeId="device-local-dc2-current" id="dc2Current"/>
+                       <channel typeId="device-local-dc2-power" id="dc2Power"/>
+                       <channel typeId="device-local-dc3-voltage" id="dc3Voltage"/>
+                       <channel typeId="device-local-dc3-current" id="dc3Current"/>
+                       <channel typeId="device-local-dc3-power" id="dc3Power"/>
+                       <channel typeId="device-local-akt-home-consumption-solar" id="aktHomeConsumptionSolar"/>
+                       <channel typeId="device-local-akt-home-consumption-bat" id="aktHomeConsumptionBat"/>
+                       <channel typeId="device-local-akt-home-consumption-grid" id="aktHomeConsumptionGrid"/>
+                       <channel typeId="device-local-phase-sel-home-consump-l1" id="phaseSelHomeConsumpL1"/>
+                       <channel typeId="device-local-phase-sel-home-consump-l2" id="phaseSelHomeConsumpL2"/>
+                       <channel typeId="device-local-phase-sel-home-consump-l3" id="phaseSelHomeConsumpL3"/>
+                       <channel typeId="device-local-grid-freq" id="gridFreq"/>
+                       <channel typeId="device-local-grid-cos-phi" id="gridCosPhi"/>
+                       <channel typeId="statistic-home-consumption-day" id="homeConsumptionDay"/>
+                       <channel typeId="statistic-own-consumption-day" id="ownConsumptionDay"/>
+                       <channel typeId="statistic-own-cons-rate-day" id="ownConsRateDay"/>
+                       <channel typeId="statistic-autonomy-degree-day" id="autonomyDegreeDay"/>
+                       <channel typeId="statistic-home-consumption-total" id="homeConsumptionTotal"/>
+                       <channel typeId="statistic-own-consumption-total" id="ownConsumptionTotal"/>
+                       <channel typeId="statistic-operating-time-total" id="operatingTimeTotal"/>
+                       <channel typeId="device-local-current" id="current"/>
+                       <channel typeId="device-local-current-dir" id="currentDir"/>
+                       <channel typeId="device-local-charge-cycles" id="chargeCycles"/>
+                       <channel typeId="device-local-battery-temperature" id="batteryTemperature"/>
+                       <channel typeId="device-local-loginterval" id="loginterval"/>
+                       <channel typeId="device-local-s0-inpulse-cnt" id="s0InPulseCnt"/>
+                       <channel typeId="statistic-own-cons-rate-total" id="ownConsRateTotal"/>
+                       <channel typeId="statistic-autonomy-degree-total" id="autonomyDegreeTotal"/>
+                       <channel typeId="device-local-battery-voltage" id="batteryVoltage"/>
+                       <channel typeId="device-local-bat-state-of-charge" id="batStateOfCharge"/>
+                       <channel typeId="device-local-self-consumption" id="selfConsumption"/>
+                       <channel typeId="device-local-battery-usage-consumption" id="batteryUsageConsumption"/>
+                       <channel typeId="device-local-smart-battery-control" id="smartBatteryControl"/>
+                       <channel typeId="device-local-max-depth-of-discharge" id="maxDepthOfDischarge"/>
+                       <channel typeId="device-local-shadow-management" id="shadowManagement"/>
+                       <channel typeId="device-local-external-module-control" id="externalModuleControl"/>
+                       <channel typeId="device-local-battery-usage-consumption-set" id="batteryUsageConsumptionSet"/>
+                       <channel typeId="device-local-battery-usage-strategy-set" id="batteryUsageStrategySet"/>
+                       <channel typeId="device-local-smart-battery-control-set" id="smartBatteryControlSet"/>
+                       <channel typeId="device-local-battery-charge-time-from-set" id="batteryChargeTimeFromSet"/>
+                       <channel typeId="device-local-battery-charge-time-to-set" id="batteryChargeTimeToSet"/>
+                       <channel typeId="device-local-max-depth-of-discharge-set" id="maxDepthOfDischargeSet"/>
+                       <channel typeId="device-local-shadow-management-set" id="shadowManagementSet"/>
+                       <channel typeId="device-local-external-module-control-set" id="externalModuleControlSet"/>
+               </channels>
+               <properties>
+                       <property name="vendor">KOSTAL Solar Electric GmbH</property>
+               </properties>
+               <config-description-ref uri="thing-type:kostalpiko1020_config"/>
+       </thing-type>
+</thing:thing-descriptions>