diff --git a/bundles/org.openhab.binding.kostalinverter/README.md b/bundles/org.openhab.binding.kostalinverter/README.md index 9a3d8ec7459..b595afc5f9e 100644 --- a/bundles/org.openhab.binding.kostalinverter/README.md +++ b/bundles/org.openhab.binding.kostalinverter/README.md @@ -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%]" { cha String SolarStatus "Solar status [%s]" { channel="kostalinverter:kostalinverter:inverter:status" } ``` + +### Second generation devices (PIKO NEW GENERATION) + +demo.items: + +``` +Number:Power GridOutputPower "PV Output Power" { channel="kostalinverter:piko1020:mypiko1020:gridOutputPower" } +Number:Energy YieldDaySecondGen "PV Output Power Day" { channel="kostalinverter:piko1020:mypiko1020:yieldDaySecondGen" } +Number:Energy YieldTotalSecondGen "PV Output Power Total" { channel="kostalinverter:piko1020:mypiko1020:yieldTotalSecondgen" } +Number:Dimensionless OperatingStatus "Operating Status" { channel="kostalinverter:piko1020:mypiko1020:operatingStatus" } +Number:ElectricPotential GridVoltageL1 "Grid Voltage L1" { channel="kostalinverter:piko1020:mypiko1020:gridVoltageL1" } +Number:ElectricCurrent GridCurrentL1 "Grid Current L1" { channel="kostalinverter:piko1020:mypiko1020:gridCurrentL1" } +Number:Power GridPowerL1 "Grid Power L1" { channel="kostalinverter:piko1020:mypiko1020:gridPowerL1" } +Number:ElectricPotential GridVoltageL2 "Grid Voltage L2" { channel="kostalinverter:piko1020:mypiko1020:gridVoltageL2" } +Number:ElectricCurrent GridCurrentL2 "Grid Current L2" { channel="kostalinverter:piko1020:mypiko1020:gridCurrentL2" } +Number:Power GridPowerL2 "Grid Power L2" { channel="kostalinverter:piko1020:mypiko1020:gridPowerL2" } +Number:ElectricPotential GridVoltageL3 "Grid Voltage L3" { channel="kostalinverter:piko1020:mypiko1020:gridVoltageL3" } +Number:ElectricCurrent GridCurrentL3 "Grid Current L3" { channel="kostalinverter:piko1020:mypiko1020:gridCurrentL3" } +Number:Power GridPowerL3 "Grid Power L3" { channel="kostalinverter:piko1020:mypiko1020:gridPowerL3" } +Number:Power DcPvPower "DC Power Pv" { channel="kostalinverter:piko1020:mypiko1020:dcPowerPV" } +Number:ElectricPotential Dc1Voltage "DC1 Voltage" { channel="kostalinverter:piko1020:mypiko1020:dc1Voltage" } +Number:ElectricCurrent Dc1Current "DC1 Current" { channel="kostalinverter:piko1020:mypiko1020:dc1Current" } +Number:Power Dc1Power "DC1 Power" { channel="kostalinverter:piko1020:mypiko1020:dc1Power" } +Number:ElectricPotential Dc2Voltage "DC2 Voltage" { channel="kostalinverter:piko1020:mypiko1020:dc2Voltage" } +Number:ElectricCurrent Dc2Current "DC2 Current" { channel="kostalinverter:piko1020:mypiko1020:dc2Current" } +Number:Power Dc2Power "DC2 Power" { channel="kostalinverter:piko1020:mypiko1020:dc2Power" } +Number:ElectricPotential Dc3Voltage "DC3 Voltage" { channel="kostalinverter:piko1020:mypiko1020:dc3Voltage" } +Number:ElectricCurrent Dc3Current "DC3 Current" { channel="kostalinverter:piko1020:mypiko1020:dc3Current" } +Number:Power Dc3Power "DC3 Power" { channel="kostalinverter:piko1020:mypiko1020:dc3Power" } +Number:Power AktHomeConsumptionSolar "Akt Home Consumption Solar" { channel="kostalinverter:piko1020:mypiko1020:aktHomeConsumptionSolar" } +Number:Power AktHomeConsumptionBat "Akt Home Consumption Battery" { channel="kostalinverter:piko1020:mypiko1020:aktHomeConsumptionBat" } +Number:Power AktHomeConsumptionGrid "Akt Home Consumption Grid" { channel="kostalinverter:piko1020:mypiko1020:aktHomeConsumptionGrid" } +Number:Power PhaseSelHomeConsumpL1 "Phase Sel Home Consump L1" { channel="kostalinverter:piko1020:mypiko1020:phaseSelHomeConsumpL1" } +Number:Power PhaseSelHomeConsumpL2 "Phase Sel Home Consump L2" { channel="kostalinverter:piko1020:mypiko1020:phaseSelHomeConsumpL2" } +Number:Power PhaseSelHomeConsumpL3 "Phase Sel Home Consump L3" { channel="kostalinverter:piko1020:mypiko1020:phaseSelHomeConsumpL3" } +Number:Frequency GridFreq "Grid Freq" { channel="kostalinverter:piko1020:mypiko1020:gridFreq" } +Number:Angle GridCosPhi "Grid Cos Phi" { channel="kostalinverter:piko1020:mypiko1020:gridCosPhi" } +Number:Energy HomeConsumptionDay "Home Consumption Day" { channel="kostalinverter:piko1020:mypiko1020:homeConsumptionDay" } +Number:Energy OwnConsumptionDay "Own Consumption Day" { channel="kostalinverter:piko1020:mypiko1020:ownConsumptionDay" } +Number:Dimensionless OwnConsRateDay "Own Cons Rate Day { channel="kostalinverter:piko1020:mypiko1020:ownConsRateDay" } +Number:Dimensionless AutonomyDegreeDay "Autonomy Degree Day" { channel="kostalinverter:piko1020:mypiko1020:autonomyDegreeDay" } +Number:Energy HomeConsumptionTotal "Home Consumption Total" { channel="kostalinverter:piko1020:mypiko1020:homeConsumptionTotal" } +Number:Energy OwnConsumptionTotal "Own Consumption Total" { channel="kostalinverter:piko1020:mypiko1020:ownConsumptionTotal" } +Number:Time OperatingTimeTotal "Operating Time Total" { channel="kostalinverter:piko1020:mypiko1020:operatingTimeTotal" } +Number:ElectricCurrent Current "Current" { channel="kostalinverter:piko1020:mypiko1020:current" } +Number:Dimensionless CurrentDir "Current Dir" { channel="kostalinverter:piko1020:mypiko1020:currentDir" } +Number:Dimensionless ChargeCycles "Charge Cycles" { channel="kostalinverter:piko1020:mypiko1020:chargeCycles" } +Number:Temperature BatteryTemperature "BatteryTemperature" { channel="kostalinverter:piko1020:mypiko1020:batteryTemperature" } +Number:Time Loginterval "Log Interval" { channel="kostalinverter:piko1020:mypiko1020:loginterval" } +Number:Dimensionless S0InPulseCnt "S0 InPulse Cnt" { channel="kostalinverter:piko1020:mypiko1020:s0InPulseCnt" } +Number:Dimensionless OwnConsRateTotal "Own Cons Rate Total" { channel="kostalinverter:piko1020:mypiko1020:ownConsRateTotal" } +Number:Dimensionless AutonomyDegreeTotal "Autonomy Degree Total" { channel="kostalinverter:piko1020:mypiko1020:autonomyDegreeTotal" } +Number:ElectricPotential BatteryVoltage "Battery Voltage" { channel="kostalinverter:piko1020:mypiko1020:batteryVoltage" } +Number:Dimensionless BatStateOfCharge "Bat State Of Charge" { channel="kostalinverter:piko1020:mypiko1020:batStateOfCharge" } +Number:Power SelfConsumption "Self Consumption" { channel="kostalinverter:piko1020:mypiko1020:selfConsumption" } +Number:Dimensionless BatteryUsageConsumption "Battery Usage Consumption" { channel="kostalinverter:piko1020:mypiko1020:batteryUsageConsumption" } +Switch SmartBatteryControl "Smart Battery Control" { channel="kostalinverter:piko1020:mypiko1020:smartBatteryControl" } +Number:Dimensionless MaxDepthOfDischarge "Max Depth Of Discharge" { channel="kostalinverter:piko1020:mypiko1020:maxDepthOfDischarge" } +Number:Dimensionless ShadowManagement "Shadow Management" { channel="kostalinverter:piko1020:mypiko1020:shadowManagement" } +Number:Dimensionless ExternalModuleControl "External Module Control" { channel="kostalinverter:piko1020:mypiko1020:externalModuleControl" } + + +``` + ### Third generation devices (PIKO IQ / PLENTICORE plus) demo.items: ``` + Number:Energy MyPlentiCore100WithBattery_DEVICE_LOCAL_DC_POWER { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:deviceLocalDCPower"} Number:Energy MyPlentiCore100WithBattery_DEVICE_LOCAL_HOMECONSUMPTION_FROM_BATTERY { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:deviceLocalHomeconsumptionFromBattery"} Number:Energy MyPlentiCore100WithBattery_DEVICE_LOCAL_HOMECONSUMPTION_FROM_GRID { channel="kostalinverter:PLENTICOREPLUS100WITHBATTERY:MyPlentiCore100WithBattery:deviceLocalHomeconsumptionFromGrid"} @@ -256,3 +424,28 @@ Number:Energy MyPlentiCore100WithBattery_STATISTIC_YIELD_TOTAL Number:Energy MyPlentiCore100WithBattery_STATISTIC_YIELD_YEAR { 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 index 00000000000..f72fc15ae07 Binary files /dev/null and b/bundles/org.openhab.binding.kostalinverter/doc/kostalpiko10_20.jpg differ diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/KostalInverterFactory.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/KostalInverterFactory.java index 79a00e2912f..0210a8ddcca 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/KostalInverterFactory.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/KostalInverterFactory.java @@ -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 index 00000000000..d46f09e4e33 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationBindingConstants.java @@ -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 index 00000000000..dde6f0935e7 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationChannelConfiguration.java @@ -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 getChannelConfiguration() { + final List 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 getChannelConfigurationExt() { + final List 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 getChannelConfigurationExtExt() { + final List 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 getChannelConfigurationConfigurable() { + final List 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 index 00000000000..e5d064e80a9 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationConfigurationHandler.java @@ -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 index 00000000000..cbfc286f8c6 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntries.java @@ -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 index 00000000000..bbcf812ce3f --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationDxsEntriesContainerDTO.java @@ -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 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 index 00000000000..2c0f6561591 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationHandler.java @@ -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 channelConfigs = new ArrayList<>(); + private List channelConfigsExt = new ArrayList<>(); + private List channelConfigsExtExt = new ArrayList<>(); + private List channelConfigsConfigurable = new ArrayList<>(); + private List channelConfigsAll = new ArrayList<>(); + + private List channelPostsTemp = new ArrayList<>(); + private List channelPostsTempExt = new ArrayList<>(); + private List channelPostsTempExtExt = new ArrayList<>(); + private List 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 combineChannelConfigLists( + List... args) { + List combinedChannelConfigLists = new ArrayList<>(); + for (List list : args) { + for (SecondGenerationChannelConfiguration i : list) { + combinedChannelConfigLists.add(i); + } + } + return combinedChannelConfigLists; + } + + // Method to concatenate channelPosts Lists to one List + @SafeVarargs + private final List combinePostsLists(List... args) { + List combinedPostsLists = new ArrayList<>(); + for (List 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 index 00000000000..f7a0588f465 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationInverterConfig.java @@ -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 index 00000000000..f60c39f1c31 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/config/SecondGeneration.xml @@ -0,0 +1,31 @@ + + + + + + IP address of the inverter. + url + + + + The username to the inverter. + + + + The password to the inverter. + password + + + + Refresh Interval in seconds. + 60 + + + + Type of inverter, with/without battery. + + + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/Channels.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/Channels.xml index 68b15b3ce69..304aa0ebc66 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/Channels.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/Channels.xml @@ -32,7 +32,7 @@ Number:Power - Current own comsumption + Current own consumption Energy @@ -46,7 +46,7 @@ Number:Power - Current total homeconsumption + Current total home consumption Energy @@ -484,4 +484,438 @@ Energy + + Number:Power + + Current output power to the grid + Energy + + + + Number:Energy + + Total produced power day + Energy + + + + Number:Energy + + Total produced power + Energy + + + + Number:Dimensionless + + Operating status + Energy + + + + Number:ElectricPotential + + Current output voltage to the grid, L1 + Energy + + + + Number:ElectricCurrent + + Current output amperage to the grid, L1 + Energy + + + + Number:Power + + Current output power to the grid, L1 + Energy + + + + Number:ElectricPotential + + Current output voltage to the grid, L2 + Energy + + + + Number:ElectricCurrent + + Current output amperage to the grid, L2 + Energy + + + + Number:Power + + Current output power to the grid, L2 + Energy + + + + Number:ElectricPotential + + Current output voltage to the grid, L3 + Energy + + + + Number:ElectricCurrent + + Current output amperage to the grid, L3 + Energy + + + + Number:Power + + Current output power to the grid, L3 + Energy + + + + Number:Power + + Current power from solar panels + Energy + + + + Number:ElectricPotential + + Current voltage from solar panels, DC1 + Energy + + + + Number:ElectricCurrent + + Current amperage from solar panels, DC1 + Energy + + + + Number:Power + + Current power from solar panels, DC1 + Energy + + + + Number:ElectricPotential + + Current voltage from solar panels, DC2 + Energy + + + + Number:ElectricCurrent + + Current amperage from solar panels, DC2 + Energy + + + + Number:Power + + Current power from solar panels, DC2 + Energy + + + + Number:ElectricPotential + + Current voltage from solar panels, DC3 + Energy + + + + Number:ElectricCurrent + + Current amperage from solar panels, DC3 + Energy + + + + Number:Power + + Current power from solar panels, DC3 + Energy + + + + Number:Power + + Current consumption from solar panels + Energy + + + + Number:Power + + Current consumption from battery + Energy + + + + Number:Power + + Current consumption from grid + Energy + + + + Number:Power + + Current home consumption, L1 + Energy + + + + Number:Power + + Current home consumption, L2 + Energy + + + + Number:Power + + Current home consumption, L3 + Energy + + + + Number:Frequency + + Current frequency on grid + Energy + + + + Number:Angle + + Current power factor on grid + Energy + + + + Number:Energy + + Total home consumption day + Energy + + + + Number:Energy + + Total own consumption day + Energy + + + + Number:Dimensionless + + Total own consumption rate day + Energy + + + + Number:Dimensionless + + Total autonomy degree day + Energy + + + + Number:Energy + + Total home consumption + Energy + + + + Number:Energy + + Total own consumptionl + Energy + + + + Number:Time + + Total operating time + Energy + + + + Number:ElectricCurrent + + Current + Energy + + + + Number:Dimensionless + + Current direction + Energy + + + + Number:Dimensionless + + Total number of charge cycles + Energy + + + + Number:Temperature + + Current battery temperature + Energy + + + + Number:Time + + Value for log interval + Energy + + + + Number:Dimensionless + + S0-pulse counter + Energy + + + + Number:Dimensionless + + Total own consumption rate + Energy + + + + Number:Dimensionless + + Total autonomy degree + Energy + + + + Number:ElectricalPotential + + Current battery voltage + Energy + + + + Number:Dimensionless + + Current battery charge state + Energy + + + + Number:Power + + Current self consumption + Energy + + + + Number:Power + + Battery usage consumption + Energy + + + + Switch + + Smart battery control + Energy + + + + Number:Dimensionless + + Max depth of discharge + Energy + + + + Number:Dimensionless + + Shadow management + Energy + + + + Number:Dimensionless + + External Module Control + Energy + + + + String + + Set battery usage consumption + Energy + + + + String + + Set battery usage strategy + Energy + + + + Switch + + Set smart battery control + Energy + + + + String + + Set battery charge time from + Energy + + + + String + + Set battery charge time to + Energy + + + + String + + Set max depth of discharge + Energy + + + + String + + Set shadow management + Energy + + + + String + + Set External Module Control + Energy + + 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 index 00000000000..662dfe65537 --- /dev/null +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/OH-INF/thing/PIKO1020.xml @@ -0,0 +1,79 @@ + + + + + Bindings for the KOSTAL PIKO 10-20 + Inverter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH + + + +