]> git.basschouten.com Git - openhab-addons.git/commitdiff
[senechome] issue #10679: Extend with additional channels; refactor and various impro...
authoreguib <eguib@web.de>
Sat, 29 May 2021 12:29:20 +0000 (14:29 +0200)
committerGitHub <noreply@github.com>
Sat, 29 May 2021 12:29:20 +0000 (14:29 +0200)
* [senechome] Extend with additional channels; refactor; improve error handling (#10679). Merged PR 9535 (rename batteryState to system state)

- charge/discharge energy/current/voltage/min/maxCellVoltage/load cycles per battery pack
- current/power/voltage per MPP
- liveHouseConsumption/livePowerGenerator
- battery,case,MCU temperature
- wallbox1: state, charging power/current, liveEnergy
- improve error handling, catch malformed JSON exception to prevent crashing the binding
- merged PR: 9535 (rename batteryState to systemState)
- renamed SenecHomeLimitation to SenecHomePower and added more channels
- refactored SenecHomeHandler to reduce code duplication (added some nice helper methods)

Signed-off-by: Erwin Guib <eguib@web.de>
19 files changed:
CODEOWNERS
bundles/org.openhab.binding.senechome/README.md
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecBatteryStatus.java [deleted file]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeApi.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeBindingConstants.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecSystemStatus.java [new file with mode: 0644]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecWallboxStatus.java [new file with mode: 0644]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeBattery.java [new file with mode: 0644]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeEnergy.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeGrid.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeLimitation.java [deleted file]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomePower.java [new file with mode: 0644]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeStatistics.java
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeTemperature.java [new file with mode: 0644]
bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeWallbox.java [new file with mode: 0644]
bundles/org.openhab.binding.senechome/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.senechome/src/test/java/org/openhab/binding/senechome/internal/SenecHomeHandlerTest.java [new file with mode: 0644]

index bed0f44786a315974a60acd2aaafb7ca1b4177ab..ca38e94d9a3e5c22bc98acc7f2a04cdfb957006c 100644 (file)
 /bundles/org.openhab.binding.samsungtv/ @paulianttila
 /bundles/org.openhab.binding.satel/ @druciak
 /bundles/org.openhab.binding.semsportal/ @itb3
-/bundles/org.openhab.binding.senechome/ @vctender @KorbinianP
+/bundles/org.openhab.binding.senechome/ @vctender @KorbinianP @eguib
 /bundles/org.openhab.binding.seneye/ @nikotanghe
 /bundles/org.openhab.binding.sensebox/ @hakan42
 /bundles/org.openhab.binding.sensibo/ @seime
index 49fc88900a2427bed3ac991386c1e37d4ccfcfac..9e8075fbac276c908b000b02cf64961af6c61070 100644 (file)
@@ -11,8 +11,13 @@ Examples: Lights, pool filters, wash machines, ...
 
 | Thing type id        | Name                                          |
 |----------------------|-----------------------------------------------|
-| senechome            | Senec Home Lithium Battery, V2.0, V2.1 and V3 |
+| senechome            | Senec Home Lithium Battery, V2.0, V2.1, V3 and V3duo |
 
+**Note:** Not all channels are available for all Senec Home types. E.g. 
+
+* only V3, V3duo have a power generator and thus MPPs (V3 has 2 MPP, V3duo has 3 MPP)
+* not equipped battery packs will return 0 for all ...Pack channels
+* currently channels for the first wallbox are implemented (senec could handle 4 wallboxes)
 
 ## Thing Configuration
 
@@ -34,12 +39,23 @@ The property `limitationTresholdValue` is used as threshold for channel `powerLi
 |-----------------------|-----------|--------------------------------------------------------------------------|
 | powerLimitation       | percent   | How much is your pv generator limited (0% if not limited anyway)         |
 | powerLimitationState  | ON/OFF    | Power limitation active (based on configuration)                         |
+| currentMPP1           | ampere    | PV generator current on MPP1                                             |
+| currentMPP2           | ampere    | PV generator current on MPP2                                             |
+| currentMPP3           | ampere    | PV generator current on MPP3                                             |
+| powerMPP1             | watt      | PV generator power on MPP1                                               |
+| powerMPP2             | watt      | PV generator power on MPP2                                               |
+| powerMPP3             | watt      | PV generator power on MPP3                                               |
+| voltageMPP1           | volt      | PV generator voltage on MPP1                                             |
+| voltageMPP2           | volt      | PV generator voltage on MPP2                                             |
+| voltageMPP3           | volt      | PV generator voltage on MPP3                                             |
 | houseConsumption      | watt      | Current power consumption of your house/living                           |
 | energyProduction      | watt      | Energy generated by your pv / inverter                                   |
-| batteryPower          | watt      | Energy processed by batterie itself, for example while charging          |
+| batteryPower          | watt      | Energy processed by battery negative discharge, positive charge          |
+| batteryCurrent        | ampere    | Battery current negative discharge, positive charge                      |
+| batteryVoltage        | volt      | Battery Voltage                                                          |
 | batteryFuelCharge     | percent   | Fuel charge of your battery (0 - 100%)                                   |
-| batteryState          |           | Text describing current action of battery (e.g. CHARGE)                  |
-| batteryStateValue     |           | Value describing current action of battery (e.g. 14)                     |
+| systemState           |           | Text describing current action of the senec home system (e.g. CHARGE)    |
+| systemStateValue      |           | Value describing current action of the senec home system (e.g. 14)       |
 | gridPower             | watt      | Grid power level, negative for supply, positive values for drawing power |
 | gridPowerDraw         | watt      | Absolute power level of power draw, zero while supplying                 |
 | gridPowerSupply       | watt      | Absolute power level of power supply, zero while drawing                 |
@@ -53,11 +69,50 @@ The property `limitationTresholdValue` is used as threshold for channel `powerLi
 | gridVoltagePhase2     | volt      | Grid voltage on Phase 2                                                  |
 | gridVoltagePhase3     | volt      | Grid voltage on Phase 3                                                  |
 | gridFrequency         | hertz     | Grid frequency                                                           |
-| SenecBatteryVoltage   | volt      | Battery Voltage                                                          |
-| SenecLiveBatCharge    | watt hour | Live Bat Charge                                                          |
-| SenecLiveBatDischarge | watt hour | Live Bat Discharge                                                       |
-| SenecLiveGridImport   | watt hour | Live Grid Import                                                         |
-| SenecLiveGridExport   | watt hour | Live Grid Export                                                         |
+| liveBatCharge         | kilo watt hour | Live Total Bat Charge                                               |
+| liveBatDischarge      | kilo watt hour | Live Total Bat Discharge                                            |
+| liveGridImport        | kilo watt hour | Live Total Grid Import                                              |
+| liveGridExport        | kilo watt hour | Live Total Grid Export                                              |
+| liveHouseConsumption  | kilo watt hour | Live Total House Consumption (without WB)                           |
+| livePowerGenerator    | kilo watt hour | Live Total PV generator generated energy                            |
+| liveEnergyWallbox1    | kilo watt hour | Live Total Wallbox 1 charged energy                                 |
+| chargedEnergyPack1    | kilo watt hour | total charged energy battery pack 1                                 |
+| chargedEnergyPack2    | kilo watt hour | total charged energy battery pack 2                                 |
+| chargedEnergyPack3    | kilo watt hour | total charged energy battery pack 3                                 |
+| chargedEnergyPack4    | kilo watt hour | total charged energy battery pack 4                                 |
+| dischargedEnergyPack1 | kilo watt hour | total discharged energy battery pack 1                              |
+| dischargedEnergyPack2 | kilo watt hour | total discharged energy battery pack 2                              |
+| dischargedEnergyPack3 | kilo watt hour | total discharged energy battery pack 3                              |
+| dischargedEnergyPack4 | kilo watt hour | total discharged energy battery pack 4                              |
+| cyclesPack1           |           | battery charge/discharge cycles pack 1                                   |
+| cyclesPack2           |           | battery charge/discharge cycles pack 2                                   |
+| cyclesPack3           |           | battery charge/discharge cycles pack 3                                   |
+| cyclesPack4           |           | battery charge/discharge cycles pack 4                                   |
+| currentPack1          | ampere    | battery current pack 1                                                   |
+| currentPack2          | ampere    | battery current pack 2                                                   |
+| currentPack3          | ampere    | battery current pack 3                                                   |
+| currentPack4          | ampere    | battery current pack 4                                                   |
+| voltagePack1          | volt      | battery voltage pack 1                                                   |
+| voltagePack2          | volt      | battery voltage pack 2                                                   |
+| voltagePack3          | volt      | battery voltage pack 3                                                   |
+| voltagePack4          | volt      | battery voltage pack 4                                                   |
+| maxCellVoltagePack1   | volt      | maximum cell voltage battery pack 1                                      |
+| maxCellVoltagePack2   | volt      | maximum cell voltage battery pack 2                                      |
+| maxCellVoltagePack3   | volt      | maximum cell voltage battery pack 3                                      |
+| maxCellVoltagePack4   | volt      | maximum cell voltage battery pack 4                                      |
+| minCellVoltagePack1   | volt      | minimum cell voltage battery pack 1                                      |
+| minCellVoltagePack2   | volt      | minimum cell voltage battery pack 2                                      |
+| minCellVoltagePack3   | volt      | minimum cell voltage battery pack 3                                      |
+| minCellVoltagePack4   | volt      | minimum cell voltage battery pack 4                                      |
+| batteryTemperature    | celsius   | battery temperature (maximum of all battery packs)                       |
+| caseTemperature       | celsius   | case temperature                                                         |
+| mcuTemperature        | celsius   | MCU (main control unit) temperature                                      |
+| wallbox1State         |           | Wallbox 1 state as Text (e.g. Charging)                                  |
+| wallbox1StateValue    |           | Wallbox 1 state as value (e.g. 194)                                      |
+| wallbox1ChargingCurrentPhase1 | ampere | Wallbox 1 charging current Phase 1                                  |
+| wallbox1ChargingCurrentPhase2 | ampere | Wallbox 1 charging current Phase 2                                  |
+| wallbox1ChargingCurrentPhase3 | ampere | Wallbox 1 charging current Phase 3                                  |
+| wallbox1ChargingPower         | watt   | Wallbox 1 charging power                                            |
 
 ## Items
 
@@ -70,8 +125,8 @@ Number SenecHouseConsumption     "Current power consumption [%d W]"           <e
 Number SenecEnergyProduction     "Energy generated by pv [%d W]"              <energy> { channel="senechome:senechome:pvbattery:energyProduction" }
 Number SenecBatteryPower         "Energy processed by battery [%d W]"         <energy> { channel="senechome:senechome:pvbattery:batteryPower" }
 Number SenecBatteryFuelCharge    "State of Charge [%d %%]"              <batterylevel> { channel="senechome:senechome:pvbattery:batteryFuelCharge" }
-String SenecBatteryState         "Current action [%s]"                          <text> { channel="senechome:senechome:pvbattery:batteryState" }
-Number SenecBatteryStateValue    "Current action [%d]"                          <text> { channel="senechome:senechome:pvbattery:batteryStateValue" }
+String SenecSystemState          "Current system state [%s]"                    <text> { channel="senechome:senechome:pvbattery:systemState" }
+Number SenecSystemStateValue     "Current system state [%d]"                    <text> { channel="senechome:senechome:pvbattery:systemStateValue" }
 Number SenecGridPower            "Grid power level [%d W]"                    <energy> { channel="senechome:senechome:pvbattery:gridPower" }
 Number SenecGridPowerDraw        "Power draw from grid [%d W]"                <energy> { channel="senechome:senechome:pvbattery:gridPowerDraw" }
 Number SenecGridPowerSupply      "Power supply to grid [%d W]"                <energy> { channel="senechome:senechome:pvbattery:gridPowerSupply" }
@@ -105,8 +160,8 @@ Text label="Power Grid"{
         Default item=SenecEnergyProduction
         Default item=SenecBatteryPower
         Default item=SenecBatteryFuelCharge
-        Default item=SenecBatteryState
-        Default item=SenecBatteryStateValue
+        Default item=SenecSystemState
+        Default item=SenecSystemStateValue
         Default item=SenecGridPower
         Default item=SenecGridPowerDraw
         Default item=SenecGridPowerSupply
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecBatteryStatus.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecBatteryStatus.java
deleted file mode 100644 (file)
index cd39184..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * 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.senechome.internal;
-
-/**
- * The {@link SenecBatteryStatus} class defines available Senec specific
- * battery states.
- *
- * @author Steven Schwarznau - Initial contribution
- *
- */
-public enum SenecBatteryStatus {
-
-    INITIALSTATE(0, "INITIAL STATE"),
-    ERROR_INVERTER_COMMUNICATION(1, "ERROR INVERTER COMMUNICATION"),
-    ERROR_ELECTRICY_METER(2, "ERROR ELECTRICY METER"),
-    RIPPLE_CONTROL_RECEIVER(3, "RIPPLE CONTROL RECEIVER"),
-    INITIAL_CHARGE(4, "INITIAL CHARGE"),
-    MAINTENANCE_CHARGE(5, "MAINTENANCE CHARGE"),
-    MAINTENANCE_READY(6, "MAINTENANCE READY"),
-    MAINTENANCE_REQUIRED(7, "MAINTENANCE REQUIRED"),
-    MAN_SAFETY_CHARGE(8, "MAN. SAFETY CHARGE"),
-    SAFETY_CHARGE_READY(9, "SAFETY CHARGE READY"),
-    FULL_CHARGE(10, "FULL CHARGE"),
-    EQUALIZATION_CHARGE(11, "EQUALIZATION: CHARGE"),
-    DESULFATATION_CHARGE(12, "DESULFATATION: CHARGE"),
-    BATTERY_FULL(13, "BATTERY FULL"),
-    CHARGE(14, "CHARGE"),
-    BATTERY_EMPTY(15, "BATTERY EMPTY"),
-    DISCHARGE(16, "DISCHARGE"),
-    PV_AND_DISCHARGE(17, "PV + DISCHARGE"),
-    GRID_AND_DISCHARGE(18, "GRID + DISCHARGE"),
-    PASSIVE(19, "PASSIVE"),
-    OFF(20, "OFF"),
-    OWN_CONSUMPTION(21, "OWN CONSUMPTION"),
-    RESTART(22, "RESTART"),
-    MAN_EQUALIZATION_CHARGE(23, "MAN. EQUALIZATION: CHARGE"),
-    MAN_DESULFATATION_CHARGE(24, "MAN. DESULFATATION: CHARGE"),
-    SAFETY_CHARGE(25, "SAFETY CHARGE"),
-    BATTERY_PROTECTION_MODE(26, "BATTERY PROTECTION MODE"),
-    EG_ERROR(27, "EG ERROR"),
-    EG_CHARGE(28, "EG CHARGE"),
-    EG_DISCHARGE(29, "EG DISCHARGE"),
-    EG_PASSIVE(30, "EG PASSIVE"),
-    EG_PROHIBIT_CHARGE(31, "EG PROHIBIT CHARGE"),
-    EG_PROHIBIT_DISCHARGE(32, "EG PROHIBIT DISCHARGE"),
-    EMERGANCY_CHARGE(33, "EMERGANCY CHARGE"),
-    SOFTWARE_UPDATE(34, "SOFTWARE UPDATE"),
-    NSP_ERROR(35, "NSP ERROR"),
-    NSP_ERROR_GRID(36, "NSP ERROR: GRID"),
-    NSP_ERROR_HARDWRE(37, "NSP ERROR: HARDWRE"),
-    NO_SERVER_CONNECTION(38, "NO SERVER CONNECTION"),
-    BMS_ERROR(39, "BMS ERROR"),
-    MAINTENANCE_FILTER(40, "MAINTENANCE: FILTER"),
-    SLEEPING_MODE(41, "SLEEPING MODE"),
-    WAITING_EXCESS(42, "WAITING EXCESS"),
-    CAPACITY_TEST_CHARGE(43, "CAPACITY TEST: CHARGE"),
-    CAPACITY_TEST_DISCHARGE(44, "CAPACITY TEST: DISCHARGE"),
-    MAN_DESULFATATION_WAIT(45, "MAN. DESULFATATION: WAIT"),
-    MAN_DESULFATATION_READY(46, "MAN. DESULFATATION: READY"),
-    MAN_DESULFATATION_ERROR(47, "MAN. DESULFATATION: ERROR"),
-    EQUALIZATION_WAIT(48, "EQUALIZATION: WAIT"),
-    EMERGANCY_CHARGE_ERROR(49, "EMERGANCY CHARGE: ERROR"),
-    MAN_EQUALIZATION_WAIT(50, "MAN. EQUALIZATION: WAIT"),
-    MAN_EQUALIZATION_ERROR(51, "MAN. EQUALIZATION: ERROR"),
-    MAN_EQUALIZATION_READY(52, "MAN: EQUALIZATION: READY"),
-    AUTO_DESULFATATION_WAIT(53, "AUTO. DESULFATATION: WAIT"),
-    ABSORPTION_PHASE(54, "ABSORPTION PHASE"),
-    DCSWITCH_OFF(55, "DC-SWITCH OFF"),
-    PEAKSHAVING_WAIT(56, "PEAK-SHAVING: WAIT"),
-    ERROR_BATTERY_INVERTER(57, "ERROR BATTERY INVERTER"),
-    NPUERROR(58, "NPU-ERROR"),
-    BMS_OFFLINE(59, "BMS OFFLINE"),
-    MAINTENANCE_CHARGE_ERROR(60, "MAINTENANCE CHARGE ERROR"),
-    MAN_SAFETY_CHARGE_ERROR(61, "MAN. SAFETY CHARGE ERROR"),
-    SAFETY_CHARGE_ERROR(62, "SAFETY CHARGE ERROR"),
-    NO_CONNECTION_TO_MASTER(63, "NO CONNECTION TO MASTER"),
-    LITHIUM_SAFE_MODE_ACTIVE(64, "LITHIUM SAFE MODE ACTIVE"),
-    LITHIUM_SAFE_MODE_DONE(65, "LITHIUM SAFE MODE DONE"),
-    BATTERY_VOLTAGE_ERROR(66, "BATTERY VOLTAGE ERROR"),
-    BMS_DC_SWITCHED_OFF(67, "BMS DC SWITCHED OFF"),
-    GRID_INITIALIZATION(68, "GRID INITIALIZATION"),
-    GRID_STABILIZATION(69, "GRID STABILIZATION"),
-    REMOTE_SHUTDOWN(70, "REMOTE SHUTDOWN"),
-    OFFPEAKCHARGE(71, "OFFPEAK-CHARGE"),
-    ERROR_HALFBRIDGE(72, "ERROR HALFBRIDGE"),
-    BMS_ERROR_OPERATING_TEMPERATURE(73, "BMS: ERROR OPERATING TEMPERATURE"),
-    FACOTRY_SETTINGS_NOT_FOUND(74, "FACOTRY SETTINGS NOT FOUND"),
-    BACKUP_POWER_MODE_ACTIVE(75, "BACKUP POWER MODE - ACTIVE"),
-    BACKUP_POWER_MODE_BATTERY_EMPTY(76, "BACKUP POWER MODE - BATTERY EMPTY"),
-    BACKUP_POWER_MODE_ERROR(77, "BACKUP POWER MODE ERROR"),
-    INITIALISING(78, "INITIALISING"),
-    INSTALLATION_MODE(79, "INSTALLATION MODE"),
-    GRID_OFFLINE(80, "GRID OFFLINE"),
-    BMS_UPDATE_NEEDED(81, "BMS UPDATE NEEDED"),
-    BMS_CONFIGURATION_NEEDED(82, "BMS CONFIGURATION NEEDED"),
-    INSULATION_TEST(83, "INSULATION TEST"),
-    SELFTEST(84, "SELFTEST"),
-    EXTERNAL_CONTROL(85, "EXTERNAL CONTROL"),
-    ERROR_TEMPERATURESENSOR(86, "ERROR: TEMPERATURESENSOR"),
-    GRID_OPERATOR_CHARGE_PROHIBITED(87, "GRID OPERATOR: CHARGE PROHIBITED"),
-    GRID_OPERATOR_DISCHARGE_PROHIBITED(88, "GRID OPERATOR: DISCHARGE PROHIBITED"),
-    SPARE_CAPACITY(89, "SPARE CAPACITY"),
-    SELFTEST_ERROR(90, "SELFTEST ERROR"),
-    EARTH_FAULT(91, "EARTH FAULT"),
-    UNKNOWN(-1, "UNKNOWN");
-
-    private int code;
-    private String description;
-
-    SenecBatteryStatus(int index, String description) {
-        this.code = index;
-        this.description = description;
-    }
-
-    public int getCode() {
-        return code;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public static SenecBatteryStatus fromCode(int code) {
-        for (SenecBatteryStatus state : SenecBatteryStatus.values()) {
-            if (state.code == code) {
-                return state;
-            }
-        }
-        return SenecBatteryStatus.UNKNOWN;
-    }
-
-    public static String descriptionFromCode(int code) {
-        for (SenecBatteryStatus state : SenecBatteryStatus.values()) {
-            if (state.code == code) {
-                return state.description;
-            }
-        }
-        return SenecBatteryStatus.UNKNOWN.description;
-    }
-}
index afdd61a268aef11294b641a76de89b236a5bcc6c..6f6e02fb7643810af05fc95c9b28018c4d2350b7 100644 (file)
@@ -65,7 +65,6 @@ public class SenecHomeApi {
      *
      * To receive new values, just modify the Json objects and add them to the thing channels
      *
-     * @param hostname Hostname or ip address of senec battery
      * @return Instance of SenecHomeResponse
      * @throws MalformedURLException Configuration/URL is wrong
      * @throws IOException Communication failed
index a06e62e3dee99a7096262a51fbb095f7acf73c98..253678e035ae1220f1dc765a2593faefc49d6842 100644 (file)
@@ -27,14 +27,30 @@ public class SenecHomeBindingConstants {
     private static final String THING_BASE_ID = "senechome";
     public static final ThingTypeUID THING_TYPE_SENEC_HOME_BATTERY = new ThingTypeUID(BINDING_ID, THING_BASE_ID);
 
+    // SenecHomePower
     public static final String CHANNEL_SENEC_POWER_LIMITATION = "powerLimitation";
     public static final String CHANNEL_SENEC_POWER_LIMITATION_STATE = "powerLimitationState";
-    public static final String CHANNEL_SENEC_BATTERY_STATE = "batteryState";
-    public static final String CHANNEL_SENEC_BATTERY_STATE_VALUE = "batteryStateValue";
+    public static final String CHANNEL_SENEC_CURRENT_MPP1 = "currentMpp1";
+    public static final String CHANNEL_SENEC_CURRENT_MPP2 = "currentMpp2";
+    public static final String CHANNEL_SENEC_CURRENT_MPP3 = "currentMpp3";
+    public static final String CHANNEL_SENEC_POWER_MPP1 = "powerMpp1";
+    public static final String CHANNEL_SENEC_POWER_MPP2 = "powerMpp2";
+    public static final String CHANNEL_SENEC_POWER_MPP3 = "powerMpp3";
+    public static final String CHANNEL_SENEC_VOLTAGE_MPP1 = "voltageMpp1";
+    public static final String CHANNEL_SENEC_VOLTAGE_MPP2 = "voltageMpp2";
+    public static final String CHANNEL_SENEC_VOLTAGE_MPP3 = "voltageMpp3";
+
+    // SenecHomeEnergy
+    public static final String CHANNEL_SENEC_SYSTEM_STATE = "systemState";
+    public static final String CHANNEL_SENEC_SYSTEM_STATE_VALUE = "systemStateValue";
     public static final String CHANNEL_SENEC_POWER_CONSUMPTION = "houseConsumption";
     public static final String CHANNEL_SENEC_ENERGY_PRODUCTION = "energyProduction";
     public static final String CHANNEL_SENEC_BATTERY_POWER = "batteryPower";
     public static final String CHANNEL_SENEC_BATTERY_FUEL_CHARGE = "batteryFuelCharge";
+    public static final String CHANNEL_SENEC_BATTERY_VOLTAGE = "batteryVoltage";
+    public static final String CHANNEL_SENEC_BATTERY_CURRENT = "batteryCurrent";
+
+    // SenecHomeGrid
     public static final String CHANNEL_SENEC_GRID_POWER = "gridPower";
     public static final String CHANNEL_SENEC_GRID_POWER_SUPPLY = "gridPowerSupply";
     public static final String CHANNEL_SENEC_GRID_POWER_DRAW = "gridPowerDraw";
@@ -48,9 +64,56 @@ public class SenecHomeBindingConstants {
     public static final String CHANNEL_SENEC_GRID_VOLTAGE_PH2 = "gridVoltagePhase2";
     public static final String CHANNEL_SENEC_GRID_VOLTAGE_PH3 = "gridVoltagePhase3";
     public static final String CHANNEL_SENEC_GRID_FREQUENCY = "gridFrequency";
+
+    // SenecHomeStatistics
     public static final String CHANNEL_SENEC_LIVE_BAT_CHARGE = "liveBatCharge";
     public static final String CHANNEL_SENEC_LIVE_BAT_DISCHARGE = "liveBatDischarge";
     public static final String CHANNEL_SENEC_LIVE_GRID_IMPORT = "liveGridImport";
     public static final String CHANNEL_SENEC_LIVE_GRID_EXPORT = "liveGridExport";
-    public static final String CHANNEL_SENEC_BATTERY_VOLTAGE = "batteryVoltage";
+    public static final String CHANNEL_SENEC_LIVE_HOUSE_CONSUMPTION = "liveHouseConsumption";
+    public static final String CHANNEL_SENEC_LIVE_POWER_GENERATOR = "livePowerGenerator";
+    public static final String CHANNEL_SENEC_LIVE_ENERGY_WALLBOX1 = "liveEnergyWallbox1";
+
+    // SenecHomeBattery
+    public static final String CHANNEL_SENEC_CHARGED_ENERGY_PACK1 = "chargedEnergyPack1";
+    public static final String CHANNEL_SENEC_CHARGED_ENERGY_PACK2 = "chargedEnergyPack2";
+    public static final String CHANNEL_SENEC_CHARGED_ENERGY_PACK3 = "chargedEnergyPack3";
+    public static final String CHANNEL_SENEC_CHARGED_ENERGY_PACK4 = "chargedEnergyPack4";
+    public static final String CHANNEL_SENEC_DISCHARGED_ENERGY_PACK1 = "dischargedEnergyPack1";
+    public static final String CHANNEL_SENEC_DISCHARGED_ENERGY_PACK2 = "dischargedEnergyPack2";
+    public static final String CHANNEL_SENEC_DISCHARGED_ENERGY_PACK3 = "dischargedEnergyPack3";
+    public static final String CHANNEL_SENEC_DISCHARGED_ENERGY_PACK4 = "dischargedEnergyPack4";
+    public static final String CHANNEL_SENEC_CYCLES_PACK1 = "cyclesPack1";
+    public static final String CHANNEL_SENEC_CYCLES_PACK2 = "cyclesPack2";
+    public static final String CHANNEL_SENEC_CYCLES_PACK3 = "cyclesPack3";
+    public static final String CHANNEL_SENEC_CYCLES_PACK4 = "cyclesPack4";
+    public static final String CHANNEL_SENEC_CURRENT_PACK1 = "currentPack1";
+    public static final String CHANNEL_SENEC_CURRENT_PACK2 = "currentPack2";
+    public static final String CHANNEL_SENEC_CURRENT_PACK3 = "currentPack3";
+    public static final String CHANNEL_SENEC_CURRENT_PACK4 = "currentPack4";
+    public static final String CHANNEL_SENEC_VOLTAGE_PACK1 = "voltagePack1";
+    public static final String CHANNEL_SENEC_VOLTAGE_PACK2 = "voltagePack2";
+    public static final String CHANNEL_SENEC_VOLTAGE_PACK3 = "voltagePack3";
+    public static final String CHANNEL_SENEC_VOLTAGE_PACK4 = "voltagePack4";
+    public static final String CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK1 = "maxCellVoltagePack1";
+    public static final String CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK2 = "maxCellVoltagePack2";
+    public static final String CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK3 = "maxCellVoltagePack3";
+    public static final String CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK4 = "maxCellVoltagePack4";
+    public static final String CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK1 = "minCellVoltagePack1";
+    public static final String CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK2 = "minCellVoltagePack2";
+    public static final String CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK3 = "minCellVoltagePack3";
+    public static final String CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK4 = "minCellVoltagePack4";
+
+    // SenecHomeTemperature
+    public static final String CHANNEL_SENEC_BATTERY_TEMPERATURE = "batteryTemperature";
+    public static final String CHANNEL_SENEC_CASE_TEMPERATURE = "caseTemperature";
+    public static final String CHANNEL_SENEC_MCU_TEMPERATURE = "mcuTemperature";
+
+    // SenecHomeWallbox
+    public static final String CHANNEL_SENEC_WALLBOX1_STATE = "wallbox1State";
+    public static final String CHANNEL_SENEC_WALLBOX1_STATE_VALUE = "wallbox1StateValue";
+    public static final String CHANNEL_SENEC_WALLBOX1_CHARGING_CURRENT_PH1 = "wallbox1ChargingCurrentPhase1";
+    public static final String CHANNEL_SENEC_WALLBOX1_CHARGING_CURRENT_PH2 = "wallbox1ChargingCurrentPhase2";
+    public static final String CHANNEL_SENEC_WALLBOX1_CHARGING_CURRENT_PH3 = "wallbox1ChargingCurrentPhase3";
+    public static final String CHANNEL_SENEC_WALLBOX1_CHARGING_POWER = "wallbox1ChargingPower";
 }
index e70a97abae5ca85ed269413116bbae9f5c2257ba..26d9239928af8f74baba3044b2472dae7e47d3ba 100644 (file)
@@ -12,6 +12,7 @@
  */
 package org.openhab.binding.senechome.internal;
 
+import static org.openhab.binding.senechome.internal.SenecHomeBindingConstants.*;
 import static org.openhab.core.types.RefreshType.REFRESH;
 
 import java.io.IOException;
@@ -23,13 +24,10 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
 
-import javax.measure.quantity.Dimensionless;
-import javax.measure.quantity.ElectricCurrent;
-import javax.measure.quantity.ElectricPotential;
-import javax.measure.quantity.Energy;
-import javax.measure.quantity.Frequency;
-import javax.measure.quantity.Power;
+import javax.measure.Quantity;
+import javax.measure.Unit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -40,6 +38,7 @@ import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.types.StringType;
+import org.openhab.core.library.unit.SIUnits;
 import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelUID;
@@ -51,21 +50,35 @@ import org.openhab.core.types.Command;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.gson.JsonSyntaxException;
+import com.google.gson.JsonParseException;
 
 /**
  * The {@link SenecHomeHandler} is responsible for handling commands, which are
  * sent to one of the channels.
  *
  * @author Steven Schwarznau - Initial contribution
+ * @author Erwin Guib - added more channels, added some convenience methods to reduce code duplication
  */
 @NonNullByDefault
 public class SenecHomeHandler extends BaseThingHandler {
-
     private final Logger logger = LoggerFactory.getLogger(SenecHomeHandler.class);
-    private final static String VALUE_TYPE_INT = "u3";
-    private final static String VALUE_TYPE_UNSIGNED_INT = "u8";
-    private final static String VALUE_TYPE_FLOAT = "fl";
+
+    // divisor to transform from milli to kilo UNIT (e.g. mW => kW)
+    private static final BigDecimal DIVISOR_MILLI_TO_KILO = BigDecimal.valueOf(1000000);
+    // divisor to transform from milli to "iso" UNIT (e.g. mV => V)
+    private static final BigDecimal DIVISOR_MILLI_TO_ISO = BigDecimal.valueOf(1000);
+    // divisor to transform from "iso" to kilo UNIT (e.g. W => kW)
+    private static final BigDecimal DIVISOR_ISO_TO_KILO = BigDecimal.valueOf(1000);
+    // ix (x=1,3,8) types => hex encoded integer value
+    private static final String VALUE_TYPE_INT1 = "i1";
+    public static final String VALUE_TYPE_INT3 = "i3";
+    public static final String VALUE_TYPE_INT8 = "i8";
+    // ux (x=1,3,6,8) types => hex encoded unsigned value
+    private static final String VALUE_TYPE_DECIMAL = "u";
+    // fl => hex encoded float
+    private static final String VALUE_TYPE_FLOAT = "fl";
+    // st => string
+    // public static final String VALUE_TYPE_STRING = "st";
 
     private @Nullable ScheduledFuture<?> refreshJob;
     private @Nullable PowerLimitationStatusDTO limitationStatus = null;
@@ -126,160 +139,146 @@ public class SenecHomeHandler extends BaseThingHandler {
             response = senecHomeApi.getStatistics();
             logger.trace("received {}", response);
 
-            BigDecimal pvLimitation = new BigDecimal(100).subtract(getSenecValue(response.limitation.powerLimitation))
+            BigDecimal pvLimitation = new BigDecimal(100).subtract(getSenecValue(response.power.powerLimitation))
                     .setScale(0, RoundingMode.HALF_UP);
+            updateState(CHANNEL_SENEC_POWER_LIMITATION, new QuantityType<>(pvLimitation, Units.PERCENT));
 
-            updateState(SenecHomeBindingConstants.CHANNEL_SENEC_POWER_LIMITATION,
-                    new QuantityType<Dimensionless>(pvLimitation, Units.PERCENT));
-
-            Channel channelLimitationState = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_POWER_LIMITATION_STATE);
+            Channel channelLimitationState = getThing().getChannel(CHANNEL_SENEC_POWER_LIMITATION_STATE);
             if (channelLimitationState != null) {
                 updatePowerLimitationStatus(channelLimitationState,
                         (100 - pvLimitation.intValue()) <= config.limitationTresholdValue, config.limitationDuration);
             }
-
-            Channel channelConsumption = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_POWER_CONSUMPTION);
-            if (channelConsumption != null) {
-                updateState(channelConsumption.getUID(),
-                        new QuantityType<Power>(
-                                getSenecValue(response.energy.homePowerConsumption).setScale(2, RoundingMode.HALF_UP),
-                                Units.WATT));
+            if (response.power.currentPerMpp != null) {
+                updateQtyState(CHANNEL_SENEC_CURRENT_MPP1, response.power.currentPerMpp[0], 2, Units.AMPERE);
+                updateQtyState(CHANNEL_SENEC_CURRENT_MPP2, response.power.currentPerMpp[1], 2, Units.AMPERE);
+                if (response.power.currentPerMpp.length > 2) {
+                    // only Home V3 duo
+                    updateQtyState(CHANNEL_SENEC_CURRENT_MPP3, response.power.currentPerMpp[2], 2, Units.AMPERE);
+                }
             }
-
-            Channel channelEnergyProduction = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_ENERGY_PRODUCTION);
-            if (channelEnergyProduction != null) {
-                updateState(channelEnergyProduction.getUID(), new QuantityType<Power>(
-                        getSenecValue(response.energy.inverterPowerGeneration).setScale(0, RoundingMode.HALF_UP),
-                        Units.WATT));
+            if (response.power.powerPerMpp != null) {
+                updateQtyState(CHANNEL_SENEC_POWER_MPP1, response.power.powerPerMpp[0], 2, Units.WATT);
+                updateQtyState(CHANNEL_SENEC_POWER_MPP2, response.power.powerPerMpp[1], 2, Units.WATT);
+                if (response.power.powerPerMpp.length > 2) {
+                    updateQtyState(CHANNEL_SENEC_POWER_MPP3, response.power.powerPerMpp[2], 2, Units.WATT);
+                }
             }
-
-            Channel channelBatteryPower = getThing().getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_BATTERY_POWER);
-            if (channelBatteryPower != null) {
-                updateState(channelBatteryPower.getUID(), new QuantityType<Power>(
-                        getSenecValue(response.energy.batteryPower).setScale(2, RoundingMode.HALF_UP), Units.WATT));
+            if (response.power.voltagePerMpp != null) {
+                updateQtyState(CHANNEL_SENEC_VOLTAGE_MPP1, response.power.voltagePerMpp[0], 2, Units.VOLT);
+                updateQtyState(CHANNEL_SENEC_VOLTAGE_MPP2, response.power.voltagePerMpp[1], 2, Units.VOLT);
+                if (response.power.voltagePerMpp.length > 2) {
+                    updateQtyState(CHANNEL_SENEC_VOLTAGE_MPP3, response.power.voltagePerMpp[2], 2, Units.VOLT);
+                }
             }
 
-            Channel channelBatteryFuelCharge = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_BATTERY_FUEL_CHARGE);
-            if (channelBatteryFuelCharge != null) {
-                updateState(channelBatteryFuelCharge.getUID(),
-                        new QuantityType<Dimensionless>(
-                                getSenecValue(response.energy.batteryFuelCharge).setScale(0, RoundingMode.HALF_UP),
-                                Units.PERCENT));
+            updateQtyState(CHANNEL_SENEC_POWER_CONSUMPTION, response.energy.housePowerConsumption, 2, Units.WATT);
+            updateQtyState(CHANNEL_SENEC_ENERGY_PRODUCTION, response.energy.inverterPowerGeneration, 2, Units.WATT);
+            updateQtyState(CHANNEL_SENEC_BATTERY_POWER, response.energy.batteryPower, 2, Units.WATT);
+            updateQtyState(CHANNEL_SENEC_BATTERY_CURRENT, response.energy.batteryCurrent, 2, Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_BATTERY_VOLTAGE, response.energy.batteryVoltage, 2, Units.VOLT);
+            updateStringStateFromInt(CHANNEL_SENEC_SYSTEM_STATE, response.energy.systemState,
+                    SenecSystemStatus::descriptionFromCode);
+            updateDecimalState(CHANNEL_SENEC_SYSTEM_STATE_VALUE, response.energy.systemState);
+            updateQtyState(CHANNEL_SENEC_BATTERY_FUEL_CHARGE, response.energy.batteryFuelCharge, 0, Units.PERCENT);
+
+            updateGridPowerValues(getSenecValue(response.grid.currentGridValue));
+            updateQtyState(CHANNEL_SENEC_GRID_CURRENT_PH1, response.grid.currentGridCurrentPerPhase[0], 2,
+                    Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_GRID_CURRENT_PH2, response.grid.currentGridCurrentPerPhase[1], 2,
+                    Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_GRID_CURRENT_PH3, response.grid.currentGridCurrentPerPhase[2], 2,
+                    Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_GRID_POWER_PH1, response.grid.currentGridPowerPerPhase[0], 2, Units.WATT);
+            updateQtyState(CHANNEL_SENEC_GRID_POWER_PH2, response.grid.currentGridPowerPerPhase[1], 2, Units.WATT);
+            updateQtyState(CHANNEL_SENEC_GRID_POWER_PH3, response.grid.currentGridPowerPerPhase[2], 2, Units.WATT);
+
+            updateQtyState(CHANNEL_SENEC_GRID_VOLTAGE_PH1, response.grid.currentGridVoltagePerPhase[0], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_GRID_VOLTAGE_PH2, response.grid.currentGridVoltagePerPhase[1], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_GRID_VOLTAGE_PH3, response.grid.currentGridVoltagePerPhase[2], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_GRID_FREQUENCY, response.grid.currentGridFrequency, 2, Units.HERTZ);
+
+            updateQtyState(CHANNEL_SENEC_LIVE_BAT_CHARGE, response.statistics.liveBatCharge, 2, Units.KILOWATT_HOUR);
+            updateQtyState(CHANNEL_SENEC_LIVE_BAT_DISCHARGE, response.statistics.liveBatDischarge, 2,
+                    Units.KILOWATT_HOUR);
+            updateQtyState(CHANNEL_SENEC_LIVE_GRID_IMPORT, response.statistics.liveGridImport, 2, Units.KILOWATT_HOUR);
+            updateQtyState(CHANNEL_SENEC_LIVE_GRID_EXPORT, response.statistics.liveGridExport, 2, Units.KILOWATT_HOUR);
+            updateQtyState(CHANNEL_SENEC_LIVE_HOUSE_CONSUMPTION, response.statistics.liveHouseConsumption, 2,
+                    Units.KILOWATT_HOUR);
+            updateQtyState(CHANNEL_SENEC_LIVE_POWER_GENERATOR, response.statistics.livePowerGenerator, 2,
+                    Units.KILOWATT_HOUR);
+            if (response.statistics.liveWallboxEnergy != null) {
+                updateQtyState(CHANNEL_SENEC_LIVE_ENERGY_WALLBOX1, response.statistics.liveWallboxEnergy[0], 2,
+                        Units.KILOWATT_HOUR, DIVISOR_ISO_TO_KILO);
             }
 
-            Channel channelGridCurrentPhase1 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_CURRENT_PH1);
-            updateState(channelGridCurrentPhase1.getUID(), new QuantityType<ElectricCurrent>(
-                    getSenecValue(response.grid.currentGridCurrentPerPhase[0]).setScale(2, RoundingMode.HALF_UP),
-                    Units.AMPERE));
-
-            Channel channelGridCurrentPhase2 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_CURRENT_PH2);
-            updateState(channelGridCurrentPhase2.getUID(), new QuantityType<ElectricCurrent>(
-                    getSenecValue(response.grid.currentGridCurrentPerPhase[1]).setScale(2, RoundingMode.HALF_UP),
-                    Units.AMPERE));
-
-            Channel channelGridCurrentPhase3 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_CURRENT_PH3);
-            updateState(channelGridCurrentPhase3.getUID(), new QuantityType<ElectricCurrent>(
-                    getSenecValue(response.grid.currentGridCurrentPerPhase[2]).setScale(2, RoundingMode.HALF_UP),
-                    Units.AMPERE));
-
-            Channel channelGridPowerPhase1 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_POWER_PH1);
-            updateState(channelGridPowerPhase1.getUID(),
-                    new QuantityType<Power>(
-                            getSenecValue(response.grid.currentGridPowerPerPhase[0]).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT));
-
-            Channel channelGridPowerPhase2 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_POWER_PH2);
-            updateState(channelGridPowerPhase2.getUID(),
-                    new QuantityType<Power>(
-                            getSenecValue(response.grid.currentGridPowerPerPhase[1]).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT));
-
-            Channel channelGridPowerPhase3 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_POWER_PH3);
-            updateState(channelGridPowerPhase3.getUID(),
-                    new QuantityType<Power>(
-                            getSenecValue(response.grid.currentGridPowerPerPhase[2]).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT));
-
-            Channel channelGridVoltagePhase1 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_VOLTAGE_PH1);
-            updateState(channelGridVoltagePhase1.getUID(), new QuantityType<ElectricPotential>(
-                    getSenecValue(response.grid.currentGridVoltagePerPhase[0]).setScale(2, RoundingMode.HALF_UP),
-                    Units.VOLT));
-
-            Channel channelGridVoltagePhase2 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_VOLTAGE_PH2);
-            updateState(channelGridVoltagePhase2.getUID(), new QuantityType<ElectricPotential>(
-                    getSenecValue(response.grid.currentGridVoltagePerPhase[1]).setScale(2, RoundingMode.HALF_UP),
-                    Units.VOLT));
-
-            Channel channelGridVoltagePhase3 = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_VOLTAGE_PH3);
-            updateState(channelGridVoltagePhase3.getUID(), new QuantityType<ElectricPotential>(
-                    getSenecValue(response.grid.currentGridVoltagePerPhase[2]).setScale(2, RoundingMode.HALF_UP),
-                    Units.VOLT));
-
-            Channel channelGridFrequency = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_FREQUENCY);
-            updateState(channelGridFrequency.getUID(), new QuantityType<Frequency>(
-                    getSenecValue(response.grid.currentGridFrequency).setScale(2, RoundingMode.HALF_UP), Units.HERTZ));
-
-            Channel channelBatteryStateValue = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_BATTERY_STATE_VALUE);
-            updateState(channelBatteryStateValue.getUID(),
-                    new DecimalType(getSenecValue(response.energy.batteryState).intValue()));
-
-            Channel channelLiveBatCharge = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_LIVE_BAT_CHARGE);
-            updateState(channelLiveBatCharge.getUID(),
-                    new QuantityType<Energy>(
-                            getSenecValue(response.statistics.liveBatCharge).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT_HOUR));
-
-            Channel channelLiveBatDischarge = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_LIVE_BAT_DISCHARGE);
-            updateState(channelLiveBatDischarge.getUID(),
-                    new QuantityType<Energy>(
-                            getSenecValue(response.statistics.liveBatDischarge).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT_HOUR));
-
-            Channel channelLiveGridImport = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_LIVE_GRID_IMPORT);
-            updateState(channelLiveGridImport.getUID(),
-                    new QuantityType<Energy>(
-                            getSenecValue(response.statistics.liveGridImport).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT_HOUR));
-
-            Channel channelLiveGridExport = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_LIVE_GRID_EXPORT);
-            updateState(channelLiveGridExport.getUID(),
-                    new QuantityType<Energy>(
-                            getSenecValue(response.statistics.liveGridExport).setScale(2, RoundingMode.HALF_UP),
-                            Units.WATT_HOUR));
-
-            Channel channelBatteryVoltage = getThing()
-                    .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_BATTERY_VOLTAGE);
-            updateState(channelBatteryVoltage.getUID(), new QuantityType<ElectricPotential>(
-                    getSenecValue(response.energy.batteryVoltage).setScale(2, RoundingMode.HALF_UP), Units.VOLT));
-
-            Channel channelBatteryState = getThing().getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_BATTERY_STATE);
-            if (channelBatteryState != null) {
-                updateBatteryState(channelBatteryState, getSenecValue(response.energy.batteryState).intValue());
+            updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK1, response.battery.chargedEnergy[0], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK2, response.battery.chargedEnergy[1], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK3, response.battery.chargedEnergy[2], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK4, response.battery.chargedEnergy[3], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK1, response.battery.dischargedEnergy[0], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK2, response.battery.dischargedEnergy[1], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK3, response.battery.dischargedEnergy[2], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK4, response.battery.dischargedEnergy[3], 2,
+                    Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
+            updateDecimalState(CHANNEL_SENEC_CYCLES_PACK1, response.battery.cycles[0]);
+            updateDecimalState(CHANNEL_SENEC_CYCLES_PACK2, response.battery.cycles[1]);
+            updateDecimalState(CHANNEL_SENEC_CYCLES_PACK3, response.battery.cycles[2]);
+            updateDecimalState(CHANNEL_SENEC_CYCLES_PACK4, response.battery.cycles[3]);
+            updateQtyState(CHANNEL_SENEC_CURRENT_PACK1, response.battery.current[0], 2, Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_CURRENT_PACK2, response.battery.current[1], 2, Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_CURRENT_PACK3, response.battery.current[2], 2, Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_CURRENT_PACK4, response.battery.current[3], 2, Units.AMPERE);
+            updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK1, response.battery.voltage[0], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK2, response.battery.voltage[1], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK3, response.battery.voltage[2], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK4, response.battery.voltage[3], 2, Units.VOLT);
+            updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK1, response.battery.maxCellVoltage[0], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK2, response.battery.maxCellVoltage[1], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK3, response.battery.maxCellVoltage[2], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK4, response.battery.maxCellVoltage[3], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK1, response.battery.minCellVoltage[0], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK2, response.battery.minCellVoltage[1], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK3, response.battery.minCellVoltage[2], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+            updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK4, response.battery.minCellVoltage[3], 3, Units.VOLT,
+                    DIVISOR_MILLI_TO_ISO);
+
+            if (response.temperature != null) {
+                updateQtyState(CHANNEL_SENEC_BATTERY_TEMPERATURE, response.temperature.batteryTemperature, 0,
+                        SIUnits.CELSIUS);
+                updateQtyState(CHANNEL_SENEC_CASE_TEMPERATURE, response.temperature.caseTemperature, 0,
+                        SIUnits.CELSIUS);
+                updateQtyState(CHANNEL_SENEC_MCU_TEMPERATURE, response.temperature.mcuTemperature, 0, SIUnits.CELSIUS);
             }
 
-            updateGridPowerValues(getSenecValue(response.grid.currentGridValue));
+            if (response.wallbox != null && response.wallbox.state != null) {
+                updateStringStateFromInt(CHANNEL_SENEC_WALLBOX1_STATE, response.wallbox.state[0],
+                        SenecWallboxStatus::descriptionFromCode);
+                updateDecimalState(CHANNEL_SENEC_WALLBOX1_STATE_VALUE, response.wallbox.state[0]);
+                updateQtyState(CHANNEL_SENEC_WALLBOX1_CHARGING_CURRENT_PH1, response.wallbox.l1ChargingCurrent[0], 2,
+                        Units.AMPERE);
+                updateQtyState(CHANNEL_SENEC_WALLBOX1_CHARGING_CURRENT_PH2, response.wallbox.l2ChargingCurrent[0], 2,
+                        Units.AMPERE);
+                updateQtyState(CHANNEL_SENEC_WALLBOX1_CHARGING_CURRENT_PH3, response.wallbox.l3ChargingCurrent[0], 2,
+                        Units.AMPERE);
+                updateQtyState(CHANNEL_SENEC_WALLBOX1_CHARGING_POWER, response.wallbox.chargingPower[0], 2, Units.WATT);
+            }
 
             updateStatus(ThingStatus.ONLINE);
-        } catch (JsonSyntaxException | IOException | InterruptedException | TimeoutException | ExecutionException e) {
+        } catch (JsonParseException | IOException | InterruptedException | TimeoutException | ExecutionException e) {
             if (response == null) {
                 logger.trace("Faulty response: is null");
             } else {
@@ -293,19 +292,73 @@ public class SenecHomeHandler extends BaseThingHandler {
         return Boolean.TRUE;
     }
 
+    protected void updateStringStateFromInt(String channelName, String senecValue,
+            Function<Integer, String> converter) {
+        Channel channel = getThing().getChannel(channelName);
+        if (channel != null) {
+            Integer value = getSenecValue(senecValue).intValue();
+            updateState(channel.getUID(), new StringType(converter.apply(value)));
+        }
+    }
+
+    protected void updateDecimalState(String channelName, String senecValue) {
+        Channel channel = getThing().getChannel(channelName);
+        if (channel != null) {
+            BigDecimal value = getSenecValue(senecValue);
+            updateState(channel.getUID(), new DecimalType(value.intValue()));
+        }
+    }
+
+    protected <Q extends Quantity<Q>> void updateQtyState(String channelName, String senecValue, int scale,
+            Unit<Q> unit) {
+        updateQtyState(channelName, senecValue, scale, unit, null);
+    }
+
+    protected <Q extends Quantity<Q>> void updateQtyState(String channelName, String senecValue, int scale,
+            Unit<Q> unit, @Nullable BigDecimal divisor) {
+        Channel channel = getThing().getChannel(channelName);
+        if (channel == null) {
+            return;
+        }
+        BigDecimal value = getSenecValue(senecValue);
+        if (divisor != null) {
+            value = value.divide(divisor, scale, RoundingMode.HALF_UP);
+        } else {
+            value = value.setScale(scale, RoundingMode.HALF_UP);
+        }
+        updateState(channel.getUID(), new QuantityType<Q>(value, unit));
+    }
+
     protected BigDecimal getSenecValue(String value) {
         String[] type = value.split("_");
 
-        if (VALUE_TYPE_INT.equalsIgnoreCase(type[0])) {
-            return new BigDecimal(Integer.valueOf(type[1], 16));
-        } else if (VALUE_TYPE_UNSIGNED_INT.equalsIgnoreCase(type[0])) {
-            return new BigDecimal(Integer.valueOf(type[1], 16));
-        } else if (VALUE_TYPE_FLOAT.equalsIgnoreCase(type[0])) {
-            return parseFloatValue(type[1]);
-        } else {
-            logger.warn("Unknown value type [{}]", type[0]);
+        if (type[0] != null) {
+            if (type[0].startsWith(VALUE_TYPE_DECIMAL)) {
+                return new BigDecimal(Long.valueOf(type[1], 16));
+            } else if (type[0].startsWith(VALUE_TYPE_INT1)) {
+                Integer val = Integer.valueOf(type[1], 16);
+                if ((val & 0x8000) > 0) {
+                    val = val - 0x10000;
+                }
+                return new BigDecimal(val);
+            } else if (type[0].startsWith(VALUE_TYPE_INT3)) {
+                Long val = Long.valueOf(type[1], 16);
+                if ((Math.abs(val & 0x80000000)) > 0) {
+                    val = val - 0x100000000L;
+                }
+                return new BigDecimal(val);
+            } else if (type[0].startsWith(VALUE_TYPE_INT8)) {
+                Long val = Long.valueOf(type[1], 16);
+                if ((val & 0x80) > 0) {
+                    val = val - 0x100;
+                }
+                return new BigDecimal(val);
+            } else if (VALUE_TYPE_FLOAT.equalsIgnoreCase(type[0])) {
+                return parseFloatValue(type[1]);
+            }
         }
 
+        logger.warn("Unknown value type [{}]", type[0]);
         return BigDecimal.ZERO;
     }
 
@@ -349,29 +402,25 @@ public class SenecHomeHandler extends BaseThingHandler {
         updateState(channel.getUID(), status ? OnOffType.ON : OnOffType.OFF);
     }
 
-    protected void updateBatteryState(Channel channel, int code) {
-        updateState(channel.getUID(), new StringType(SenecBatteryStatus.descriptionFromCode(code)));
-    }
-
     protected void updateGridPowerValues(BigDecimal gridTotalValue) {
         BigDecimal gridTotal = gridTotalValue.setScale(2, RoundingMode.HALF_UP);
 
         Channel channelGridPower = getThing().getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_POWER);
         if (channelGridPower != null) {
-            updateState(channelGridPower.getUID(), new QuantityType<Power>(gridTotal, Units.WATT));
+            updateState(channelGridPower.getUID(), new QuantityType<>(gridTotal, Units.WATT));
         }
 
         Channel channelGridPowerSupply = getThing()
                 .getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_POWER_SUPPLY);
         if (channelGridPowerSupply != null) {
             BigDecimal gridSupply = gridTotal.compareTo(BigDecimal.ZERO) < 0 ? gridTotal.abs() : BigDecimal.ZERO;
-            updateState(channelGridPowerSupply.getUID(), new QuantityType<Power>(gridSupply, Units.WATT));
+            updateState(channelGridPowerSupply.getUID(), new QuantityType<>(gridSupply, Units.WATT));
         }
 
         Channel channelGridPowerDraw = getThing().getChannel(SenecHomeBindingConstants.CHANNEL_SENEC_GRID_POWER_DRAW);
         if (channelGridPowerDraw != null) {
             BigDecimal gridDraw = gridTotal.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : gridTotal.abs();
-            updateState(channelGridPowerDraw.getUID(), new QuantityType<Power>(gridDraw, Units.WATT));
+            updateState(channelGridPowerDraw.getUID(), new QuantityType<>(gridDraw, Units.WATT));
         }
     }
 }
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecSystemStatus.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecSystemStatus.java
new file mode 100644 (file)
index 0000000..9426a06
--- /dev/null
@@ -0,0 +1,151 @@
+/**
+ * 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.senechome.internal;
+
+/**
+ * The {@link SenecSystemStatus} class defines available Senec specific
+ * system states.
+ *
+ * @author Steven Schwarznau - Initial contribution
+ *
+ */
+public enum SenecSystemStatus {
+
+    INITIALSTATE(0, "INITIAL STATE"),
+    ERROR_INVERTER_COMMUNICATION(1, "ERROR INVERTER COMMUNICATION"),
+    ERROR_ELECTRICY_METER(2, "ERROR ELECTRICY METER"),
+    RIPPLE_CONTROL_RECEIVER(3, "RIPPLE CONTROL RECEIVER"),
+    INITIAL_CHARGE(4, "INITIAL CHARGE"),
+    MAINTENANCE_CHARGE(5, "MAINTENANCE CHARGE"),
+    MAINTENANCE_READY(6, "MAINTENANCE READY"),
+    MAINTENANCE_REQUIRED(7, "MAINTENANCE REQUIRED"),
+    MAN_SAFETY_CHARGE(8, "MAN. SAFETY CHARGE"),
+    SAFETY_CHARGE_READY(9, "SAFETY CHARGE READY"),
+    FULL_CHARGE(10, "FULL CHARGE"),
+    EQUALIZATION_CHARGE(11, "EQUALIZATION: CHARGE"),
+    DESULFATATION_CHARGE(12, "DESULFATATION: CHARGE"),
+    BATTERY_FULL(13, "BATTERY FULL"),
+    CHARGE(14, "CHARGE"),
+    BATTERY_EMPTY(15, "BATTERY EMPTY"),
+    DISCHARGE(16, "DISCHARGE"),
+    PV_AND_DISCHARGE(17, "PV + DISCHARGE"),
+    GRID_AND_DISCHARGE(18, "GRID + DISCHARGE"),
+    PASSIVE(19, "PASSIVE"),
+    OFF(20, "OFF"),
+    OWN_CONSUMPTION(21, "OWN CONSUMPTION"),
+    RESTART(22, "RESTART"),
+    MAN_EQUALIZATION_CHARGE(23, "MAN. EQUALIZATION: CHARGE"),
+    MAN_DESULFATATION_CHARGE(24, "MAN. DESULFATATION: CHARGE"),
+    SAFETY_CHARGE(25, "SAFETY CHARGE"),
+    BATTERY_PROTECTION_MODE(26, "BATTERY PROTECTION MODE"),
+    EG_ERROR(27, "EG ERROR"),
+    EG_CHARGE(28, "EG CHARGE"),
+    EG_DISCHARGE(29, "EG DISCHARGE"),
+    EG_PASSIVE(30, "EG PASSIVE"),
+    EG_PROHIBIT_CHARGE(31, "EG PROHIBIT CHARGE"),
+    EG_PROHIBIT_DISCHARGE(32, "EG PROHIBIT DISCHARGE"),
+    EMERGANCY_CHARGE(33, "EMERGANCY CHARGE"),
+    SOFTWARE_UPDATE(34, "SOFTWARE UPDATE"),
+    NSP_ERROR(35, "NSP ERROR"),
+    NSP_ERROR_GRID(36, "NSP ERROR: GRID"),
+    NSP_ERROR_HARDWRE(37, "NSP ERROR: HARDWRE"),
+    NO_SERVER_CONNECTION(38, "NO SERVER CONNECTION"),
+    BMS_ERROR(39, "BMS ERROR"),
+    MAINTENANCE_FILTER(40, "MAINTENANCE: FILTER"),
+    SLEEPING_MODE(41, "SLEEPING MODE"),
+    WAITING_EXCESS(42, "WAITING EXCESS"),
+    CAPACITY_TEST_CHARGE(43, "CAPACITY TEST: CHARGE"),
+    CAPACITY_TEST_DISCHARGE(44, "CAPACITY TEST: DISCHARGE"),
+    MAN_DESULFATATION_WAIT(45, "MAN. DESULFATATION: WAIT"),
+    MAN_DESULFATATION_READY(46, "MAN. DESULFATATION: READY"),
+    MAN_DESULFATATION_ERROR(47, "MAN. DESULFATATION: ERROR"),
+    EQUALIZATION_WAIT(48, "EQUALIZATION: WAIT"),
+    EMERGANCY_CHARGE_ERROR(49, "EMERGANCY CHARGE: ERROR"),
+    MAN_EQUALIZATION_WAIT(50, "MAN. EQUALIZATION: WAIT"),
+    MAN_EQUALIZATION_ERROR(51, "MAN. EQUALIZATION: ERROR"),
+    MAN_EQUALIZATION_READY(52, "MAN: EQUALIZATION: READY"),
+    AUTO_DESULFATATION_WAIT(53, "AUTO. DESULFATATION: WAIT"),
+    ABSORPTION_PHASE(54, "ABSORPTION PHASE"),
+    DCSWITCH_OFF(55, "DC-SWITCH OFF"),
+    PEAKSHAVING_WAIT(56, "PEAK-SHAVING: WAIT"),
+    ERROR_BATTERY_INVERTER(57, "ERROR BATTERY INVERTER"),
+    NPUERROR(58, "NPU-ERROR"),
+    BMS_OFFLINE(59, "BMS OFFLINE"),
+    MAINTENANCE_CHARGE_ERROR(60, "MAINTENANCE CHARGE ERROR"),
+    MAN_SAFETY_CHARGE_ERROR(61, "MAN. SAFETY CHARGE ERROR"),
+    SAFETY_CHARGE_ERROR(62, "SAFETY CHARGE ERROR"),
+    NO_CONNECTION_TO_MASTER(63, "NO CONNECTION TO MASTER"),
+    LITHIUM_SAFE_MODE_ACTIVE(64, "LITHIUM SAFE MODE ACTIVE"),
+    LITHIUM_SAFE_MODE_DONE(65, "LITHIUM SAFE MODE DONE"),
+    BATTERY_VOLTAGE_ERROR(66, "BATTERY VOLTAGE ERROR"),
+    BMS_DC_SWITCHED_OFF(67, "BMS DC SWITCHED OFF"),
+    GRID_INITIALIZATION(68, "GRID INITIALIZATION"),
+    GRID_STABILIZATION(69, "GRID STABILIZATION"),
+    REMOTE_SHUTDOWN(70, "REMOTE SHUTDOWN"),
+    OFFPEAKCHARGE(71, "OFFPEAK-CHARGE"),
+    ERROR_HALFBRIDGE(72, "ERROR HALFBRIDGE"),
+    BMS_ERROR_OPERATING_TEMPERATURE(73, "BMS: ERROR OPERATING TEMPERATURE"),
+    FACOTRY_SETTINGS_NOT_FOUND(74, "FACOTRY SETTINGS NOT FOUND"),
+    BACKUP_POWER_MODE_ACTIVE(75, "BACKUP POWER MODE - ACTIVE"),
+    BACKUP_POWER_MODE_BATTERY_EMPTY(76, "BACKUP POWER MODE - BATTERY EMPTY"),
+    BACKUP_POWER_MODE_ERROR(77, "BACKUP POWER MODE ERROR"),
+    INITIALISING(78, "INITIALISING"),
+    INSTALLATION_MODE(79, "INSTALLATION MODE"),
+    GRID_OFFLINE(80, "GRID OFFLINE"),
+    BMS_UPDATE_NEEDED(81, "BMS UPDATE NEEDED"),
+    BMS_CONFIGURATION_NEEDED(82, "BMS CONFIGURATION NEEDED"),
+    INSULATION_TEST(83, "INSULATION TEST"),
+    SELFTEST(84, "SELFTEST"),
+    EXTERNAL_CONTROL(85, "EXTERNAL CONTROL"),
+    ERROR_TEMPERATURESENSOR(86, "ERROR: TEMPERATURESENSOR"),
+    GRID_OPERATOR_CHARGE_PROHIBITED(87, "GRID OPERATOR: CHARGE PROHIBITED"),
+    GRID_OPERATOR_DISCHARGE_PROHIBITED(88, "GRID OPERATOR: DISCHARGE PROHIBITED"),
+    SPARE_CAPACITY(89, "SPARE CAPACITY"),
+    SELFTEST_ERROR(90, "SELFTEST ERROR"),
+    EARTH_FAULT(91, "EARTH FAULT"),
+    UNKNOWN(-1, "UNKNOWN");
+
+    private int code;
+    private String description;
+
+    SenecSystemStatus(int index, String description) {
+        this.code = index;
+        this.description = description;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public static SenecSystemStatus fromCode(int code) {
+        for (SenecSystemStatus state : SenecSystemStatus.values()) {
+            if (state.code == code) {
+                return state;
+            }
+        }
+        return SenecSystemStatus.UNKNOWN;
+    }
+
+    public static String descriptionFromCode(int code) {
+        for (SenecSystemStatus state : SenecSystemStatus.values()) {
+            if (state.code == code) {
+                return state.description;
+            }
+        }
+        return SenecSystemStatus.UNKNOWN.description;
+    }
+}
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecWallboxStatus.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecWallboxStatus.java
new file mode 100644 (file)
index 0000000..495c950
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * 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.senechome.internal;
+
+/**
+ * Enum with available Senec specific wallbox states.
+ *
+ * @author Erwin Guib - Initial Contribution
+ */
+public enum SenecWallboxStatus {
+    WAIT_FOR_EV(0xA1, "Waiting for EV"),
+    EV_ASKING_CHARGE(0xB1, "EV asking for charge"),
+    EV_CHARGE_PERMISSION(0xB2, "EV has charge permission"),
+    EV_CHARGING(0xC2, "Charging"),
+    EV_CHARGING_REDUCED_CURRENT_ERROR(0xC3, "Charging reduced current (error F16, F17)"),
+    EV_CHARGING_REDUCED_CURRENT_IMBALANCE(0xC4, "Charging reduced current (imbalance F15)"),
+    DISABLED(0xE0, "Wallbox disabled"),
+    TEST_PRODUCTION(0xE1, "production test"),
+    EVCC_PROGRAM(0xE2, "EVCC program mode"),
+    BUS_IDLE(0xE3, "Bus idle"),
+    UNEXPECTED_CLOSED_CONTACT(0xF1, "unexpected closed contact (welded)"),
+    INTERNAL_ERROR(0xF2, "Internal error"),
+    DC_RESIDUAL_CURRENT(0xF3, "DC residual current detected"),
+    UPSTREAM_COM_TIMEOUT(0xF4, "Upstream communication timeout"),
+    LOCK_SOCKET_FAILED(0xF5, "Lock of socket failed"),
+    CS_OUT_OF_RANGE(0xF6, "CS out of range"),
+    EV_HIGH_TEMP(0xF7, "State D requested by EV"),
+    CP_OUT_OF_RANGE(0xF8, "CP out of range"),
+    OVERCURRENT(0xF9, "Overcurrent detected"),
+    TEMP_OUT_OF_LIMITS(0xFA, "Temperature outside limits"),
+    UNEXPECTED_OPEN_CONTACT(0xFB, "unexpected opened contact"),
+    RESERVED_1(0xFC, "Reserved State"),
+    RESERVED_2(0xFD, "Reserved State"),
+    UNKNOWN(-1, "UNKNOWN");
+
+    private final int code;
+    private final String description;
+
+    SenecWallboxStatus(int index, String description) {
+        this.code = index;
+        this.description = description;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public static SenecWallboxStatus fromCode(int code) {
+        for (SenecWallboxStatus state : SenecWallboxStatus.values()) {
+            if (state.code == code) {
+                return state;
+            }
+        }
+        return SenecWallboxStatus.UNKNOWN;
+    }
+
+    public static String descriptionFromCode(int code) {
+        for (SenecWallboxStatus state : SenecWallboxStatus.values()) {
+            if (state.code == code) {
+                return state.description;
+            }
+        }
+        return SenecWallboxStatus.UNKNOWN.description;
+    }
+}
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeBattery.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeBattery.java
new file mode 100644 (file)
index 0000000..cf209e2
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * 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.senechome.internal.json;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Battery related data from section "BMS".
+ *
+ * @author Erwin Guib - Initial Contribution
+ */
+public class SenecHomeBattery implements Serializable {
+
+    public static final long serialVersionUID = -2850415059107677832L;
+
+    /**
+     * Total charged energy per battery pack (mWh).
+     */
+    public @SerializedName("CHARGED_ENERGY") String[] chargedEnergy;
+
+    /**
+     * Total discharged energy per battery pack (mWh).
+     */
+    public @SerializedName("DISCHARGED_ENERGY") String[] dischargedEnergy;
+
+    /**
+     * Number of load cycles per battery pack.
+     */
+    public @SerializedName("CYCLES") String[] cycles;
+
+    /**
+     * Current per battery pack (A).
+     */
+    public @SerializedName("CURRENT") String[] current;
+
+    /**
+     * Voltage per battery pack (V).
+     */
+    public @SerializedName("VOLTAGE") String[] voltage;
+
+    /**
+     * Maximum cell voltage per battery pack (mV).
+     */
+    public @SerializedName("MAX_CELL_VOLTAGE") String[] maxCellVoltage;
+
+    /**
+     * Minimum cell voltage per battery pack (mV).
+     */
+    public @SerializedName("MIN_CELL_VOLTAGE") String[] minCellVoltage;
+
+    @Override
+    public String toString() {
+        return "SenecHomeBattery{" + "chargedEnergy=" + Arrays.toString(chargedEnergy) + ", dischargedEnergy="
+                + Arrays.toString(dischargedEnergy) + ", cycles=" + Arrays.toString(cycles) + ", current="
+                + Arrays.toString(current) + ", voltage=" + Arrays.toString(voltage) + ", maxCellVoltage="
+                + Arrays.toString(maxCellVoltage) + ", minCellVoltage=" + Arrays.toString(minCellVoltage) + '}';
+    }
+}
index a1937c7c10cedddbf5aa69ea82f4f8cfc2a64d97..82471eacfbb9c903dc76bfb32b1b8855f4c1a759 100644 (file)
@@ -20,23 +20,55 @@ import com.google.gson.annotations.SerializedName;
  * Json model of senec home devices: This sub model contains values of current workload, i. e. current consumption and
  * battery charge.
  *
+ * Section is "ENERGY"
+ *
  * @author Steven Schwarznau - Initial Contribution
  */
 public class SenecHomeEnergy implements Serializable {
 
-    private static final long serialVersionUID = -6171687327416551070L;
+    private static final long serialVersionUID = -5491226594672777034L;
+
+    /**
+     * House power consumption (W).
+     */
+    public @SerializedName("GUI_HOUSE_POW") String housePowerConsumption;
 
-    public @SerializedName("GUI_HOUSE_POW") String homePowerConsumption;
+    /**
+     * Total inverter power (W).
+     * Named "energyProduction" on channel/thing-type side.
+     */
     public @SerializedName("GUI_INVERTER_POWER") String inverterPowerGeneration;
+
+    /**
+     * Battery power in W (+values loading, -values unloading)
+     */
     public @SerializedName("GUI_BAT_DATA_POWER") String batteryPower;
-    public @SerializedName("GUI_BAT_DATA_FUEL_CHARGE") String batteryFuelCharge;
-    public @SerializedName("STAT_STATE") String batteryState;
+
+    /**
+     * Battery current (A).
+     */
+    public @SerializedName("GUI_BAT_DATA_CURRENT") String batteryCurrent;
+
+    /**
+     * Battery voltage (V).
+     */
     public @SerializedName("GUI_BAT_DATA_VOLTAGE") String batteryVoltage;
 
+    /**
+     * Battery charge rate (%).
+     */
+    public @SerializedName("GUI_BAT_DATA_FUEL_CHARGE") String batteryFuelCharge;
+
+    /**
+     * Encoded system state.
+     */
+    public @SerializedName("STAT_STATE") String systemState;
+
     @Override
     public String toString() {
-        return "SenecHomeEnergy [homePowerConsumption=" + homePowerConsumption + ", inverterPowerGeneration="
-                + inverterPowerGeneration + ", batteryPower=" + batteryPower + ", batteryFuelCharge="
-                + batteryFuelCharge + ", batteryState=" + batteryState + ", batteryVoltage" + batteryVoltage + "]";
+        return "SenecHomeEnergy [housePowerConsumption=" + housePowerConsumption + ", inverterPowerGeneration="
+                + inverterPowerGeneration + ", batteryPower=" + batteryPower + ", batteryVoltage=" + batteryVoltage
+                + ", batteryCurrent=" + batteryCurrent + ", batteryFuelCharge=" + batteryFuelCharge + ", systemState="
+                + systemState + "]";
     }
 }
index 1c9794a4127801291984e2cffbc91bf146bbee14..1464c107412df81b628226d10365321dfb67a1bc 100644 (file)
@@ -17,7 +17,9 @@ import java.io.Serializable;
 import com.google.gson.annotations.SerializedName;
 
 /**
- * Json model of senec home devices: This sub model provides the current power statistics by the inverter.
+ * Json model of senec home devices: This sub model contains grid related power values.
+ *
+ * Section "PM1OBJ1" (Enfluri Netz Werte)
  *
  * @author Steven Schwarznau - Initial Contribution
  */
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeLimitation.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeLimitation.java
deleted file mode 100644 (file)
index 832a331..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.senechome.internal.json;
-
-import java.io.Serializable;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * Json model of senec home devices: This sub model contains grid related power values.
- *
- * @author Steven Schwarznau - Initial Contribution
- */
-public class SenecHomeLimitation implements Serializable {
-
-    private static final long serialVersionUID = -8990871346958824085L;
-
-    public @SerializedName("POWER_RATIO") String powerLimitation;
-
-    @Override
-    public String toString() {
-        return "SenecHomePower [powerLimitation=" + powerLimitation + "]";
-    }
-}
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomePower.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomePower.java
new file mode 100644 (file)
index 0000000..152b350
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * 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.senechome.internal.json;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Json model of senec home devices: This sub model provides the current power statistics by the inverter.
+ *
+ * Section "PV1" in Senec JSON.
+ *
+ * @author Steven Schwarznau - Initial Contribution
+ */
+public class SenecHomePower implements Serializable {
+
+    private static final long serialVersionUID = -7092741166288342343L;
+
+    /**
+     * Power limitation (%).
+     */
+    public @SerializedName("POWER_RATIO") String powerLimitation;
+
+    /**
+     * Current DC current per MPP (A).
+     */
+    public @SerializedName("MPP_CUR") String[] currentPerMpp;
+
+    /**
+     * Current DC power per MPP (W)
+     */
+    public @SerializedName("MPP_POWER") String[] powerPerMpp;
+
+    /**
+     * Current DC tension per MPP (V).
+     */
+    public @SerializedName("MPP_VOL") String[] voltagePerMpp;
+
+    @Override
+    public String toString() {
+        return "SenecHomePower [powerLimitation=" + powerLimitation + ", mppCur=" + Arrays.toString(currentPerMpp)
+                + ", mppPower=" + Arrays.toString(powerPerMpp) + ", mppVol=" + Arrays.toString(voltagePerMpp) + "]";
+    }
+}
index e59721a8cc0c4ce52779906481c9b9bd0e18b05b..8d5b306af580c1f6339e3f49c1a4e35a239dd09f 100644 (file)
@@ -23,16 +23,19 @@ import com.google.gson.annotations.SerializedName;
  */
 public class SenecHomeResponse implements Serializable {
 
-    private static final long serialVersionUID = 5302080655053778494L;
+    private static final long serialVersionUID = -2672622188872750438L;
 
-    public @SerializedName("PV1") SenecHomeLimitation limitation = new SenecHomeLimitation();
+    public @SerializedName("PV1") SenecHomePower power = new SenecHomePower();
     public @SerializedName("ENERGY") SenecHomeEnergy energy = new SenecHomeEnergy();
     public @SerializedName("PM1OBJ1") SenecHomeGrid grid = new SenecHomeGrid();
     public @SerializedName("STATISTIC") SenecHomeStatistics statistics = new SenecHomeStatistics();
+    public @SerializedName("BMS") SenecHomeBattery battery = new SenecHomeBattery();
+    public @SerializedName("TEMPMEASURE") SenecHomeTemperature temperature = new SenecHomeTemperature();
+    public @SerializedName("WALLBOX") SenecHomeWallbox wallbox = new SenecHomeWallbox();
 
     @Override
     public String toString() {
-        return "SenecHomeResponse [limitation=" + limitation + ", energy=" + energy + ", grid=" + grid + ", statistics="
-                + statistics + "]";
+        return "SenecHomeResponse [power=" + power + ", energy=" + energy + ", grid=" + grid + ", statistics="
+                + statistics + "battery" + battery + "temperature" + temperature + "wallbox" + wallbox + "]";
     }
 }
index 4d10f3fa141e6c66beadc8eb636b331c9bef2b60..8c450361dc74eca374a92d9be22717582a0460b7 100644 (file)
 package org.openhab.binding.senechome.internal.json;
 
 import java.io.Serializable;
+import java.util.Arrays;
 
 import com.google.gson.annotations.SerializedName;
 
 /**
  * Json model of senec home devices: This sub model provides the current statistics by the inverter.
  *
+ * Section "STATISTIC" in Senec JSON.
+ *
  * @author Korbinian Probst - Initial Contribution
  */
 public class SenecHomeStatistics implements Serializable {
 
-    private static final long serialVersionUID = -7479338432170375451L;
+    private static final long serialVersionUID = -1102310892637495823L;
 
     /**
-     * total Wh charged to the battery
+     * total Wh charged to the battery (kWh)
      */
     public @SerializedName("LIVE_BAT_CHARGE") String liveBatCharge;
 
     /**
-     * total Wh discharged from the battery
+     * total Wh discharged from the battery (kWh)
      */
     public @SerializedName("LIVE_BAT_DISCHARGE") String liveBatDischarge;
 
     /**
-     * total Wh imported from grid
+     * total Wh imported from grid (kWh)
      */
     public @SerializedName("LIVE_GRID_IMPORT") String liveGridImport;
 
     /**
-     * total Wh supplied to the grid
+     * total Wh supplied to the grid (kWh)
      */
     public @SerializedName("LIVE_GRID_EXPORT") String liveGridExport;
 
+    /**
+     * Total house consumption (kWh)
+     */
+    public @SerializedName("LIVE_HOUSE_CONS") String liveHouseConsumption;
+
+    /**
+     * Total Wh produced (kWh)
+     */
+    public @SerializedName("LIVE_PV_GEN") String livePowerGenerator;
+
+    /**
+     * Total Wh provided to Wallbox (Wh)
+     */
+    public @SerializedName("LIVE_WB_ENERGY") String[] liveWallboxEnergy;
+
     @Override
     public String toString() {
-        return "SenecHomeStatistics [liveBatCharge=" + liveBatCharge + ", liveBatDischarge= " + liveBatDischarge
-                + ", liveGridImport= " + liveGridImport + ", liveGridExport= " + liveGridExport + "]";
+        return "SenecHomeStatistics [liveBatCharge=" + liveBatCharge + ", liveBatDischarge=" + liveBatDischarge
+                + ", liveGridImport=" + liveGridImport + ", liveGridExport=" + liveGridExport
+                + ", liveHouseConsumption=" + liveHouseConsumption + ", livePowerGen=" + livePowerGenerator
+                + ", liveWallboxEnergy=" + Arrays.toString(liveWallboxEnergy) + "]";
     }
 }
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeTemperature.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeTemperature.java
new file mode 100644 (file)
index 0000000..ba41e1a
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * 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.senechome.internal.json;
+
+import java.io.Serializable;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Senec Temperature information from "TEMPMEASURE" section.
+ *
+ * @author Erwin Guib - Initial Contribution
+ */
+public class SenecHomeTemperature implements Serializable {
+
+    private static final long serialVersionUID = 5300207918289980752L;
+
+    /**
+     * Battery temperature (°C).
+     */
+    public @SerializedName("BATTERY_TEMP") String batteryTemperature;
+
+    /**
+     * Case temperature (°C).
+     */
+    public @SerializedName("CASE_TEMP") String caseTemperature;
+
+    /**
+     * MCU Temperature (°C).
+     */
+    public @SerializedName("MCU_TEMP") String mcuTemperature;
+
+    @Override
+    public String toString() {
+        return "SenecHomeTemperature{" + "batteryTemperature='" + batteryTemperature + '\'' + ", caseTemperature='"
+                + caseTemperature + '\'' + ", mcuTemperature='" + mcuTemperature + '\'' + '}';
+    }
+}
diff --git a/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeWallbox.java b/bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeWallbox.java
new file mode 100644 (file)
index 0000000..a117e8b
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * 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.senechome.internal.json;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Senec wallbox specific data from "WALLBOX" section.
+ *
+ * @author Erwin Guib - Initial Contribution
+ */
+public class SenecHomeWallbox implements Serializable {
+
+    private static final long serialVersionUID = -664163242812451235L;
+
+    /**
+     * Encoded wallbox state.
+     */
+    public @SerializedName("STATE") String[] state;
+
+    /**
+     * L1 Charging current per wallbox (A).
+     */
+    public @SerializedName("L1_CHARGING_CURRENT") String[] l1ChargingCurrent;
+
+    /**
+     * L2 Charging current per wallbox (A).
+     */
+    public @SerializedName("L2_CHARGING_CURRENT") String[] l2ChargingCurrent;
+
+    /**
+     * L3 Charging current per wallbox (A).
+     */
+    public @SerializedName("L3_CHARGING_CURRENT") String[] l3ChargingCurrent;
+
+    /**
+     * Charging power per wallbox (W).
+     */
+    public @SerializedName("APPARENT_CHARGING_POWER") String[] chargingPower;
+
+    @Override
+    public String toString() {
+        return "SenecWallbox{" + "l1ChargingCurrent=" + Arrays.toString(l1ChargingCurrent) + ", l2ChargingCurrent="
+                + Arrays.toString(l2ChargingCurrent) + ", l3ChargingCurrent=" + Arrays.toString(l3ChargingCurrent)
+                + '}';
+    }
+}
index e05d8d2301ebfa6a5b9ab2063a00d0b716f8d94d..4e9e51b594d1f4bcbf7982408115b00e3eed1334 100644 (file)
                <description>Senec Home</description>
 
                <channels>
+                       <!-- SenecHomePower -->
                        <channel id="powerLimitation" typeId="powerLimitation"/>
                        <channel id="powerLimitationState" typeId="powerLimitationState"/>
+                       <channel id="currentMpp1" typeId="currentMpp1"/>
+                       <channel id="currentMpp2" typeId="currentMpp2"/>
+                       <channel id="currentMpp3" typeId="currentMpp3"/>
+                       <channel id="powerMpp1" typeId="powerMpp1"/>
+                       <channel id="powerMpp2" typeId="powerMpp2"/>
+                       <channel id="powerMpp3" typeId="powerMpp3"/>
+                       <channel id="voltageMpp1" typeId="voltageMpp1"/>
+                       <channel id="voltageMpp2" typeId="voltageMpp2"/>
+                       <channel id="voltageMpp3" typeId="voltageMpp3"/>
+
+                       <!-- SenecHomeEnergy -->
                        <channel id="houseConsumption" typeId="houseConsumption"/>
                        <channel id="energyProduction" typeId="energyProduction"/>
                        <channel id="batteryPower" typeId="batteryPower"/>
+                       <channel id="batteryCurrent" typeId="batteryCurrent"/>
+                       <channel id="batteryVoltage" typeId="batteryVoltage"/>
                        <channel id="batteryFuelCharge" typeId="batteryFuelCharge"/>
-                       <channel id="batteryState" typeId="batteryState"/>
-                       <channel id="batteryStateValue" typeId="batteryStateValue"/>
+                       <channel id="systemState" typeId="systemState"/>
+                       <channel id="systemStateValue" typeId="systemStateValue"/>
+
+                       <!-- SenecHomeGrid -->
                        <channel id="gridPower" typeId="gridPower"/>
                        <channel id="gridPowerSupply" typeId="gridPowerSupply"/>
                        <channel id="gridPowerDraw" typeId="gridPowerDraw"/>
                        <channel id="gridVoltagePhase2" typeId="gridVoltagePhase2"/>
                        <channel id="gridVoltagePhase3" typeId="gridVoltagePhase3"/>
                        <channel id="gridFrequency" typeId="gridFrequency"/>
-                       <channel id="batteryVoltage" typeId="batteryVoltage"/>
+
+                       <!-- SenecHomeStatistics -->
                        <channel id="liveBatCharge" typeId="liveBatCharge"/>
                        <channel id="liveBatDischarge" typeId="liveBatDischarge"/>
                        <channel id="liveGridImport" typeId="liveGridImport"/>
                        <channel id="liveGridExport" typeId="liveGridExport"/>
+                       <channel id="liveHouseConsumption" typeId="liveHouseConsumption"/>
+                       <channel id="livePowerGenerator" typeId="livePowerGenerator"/>
+                       <channel id="liveEnergyWallbox1" typeId="liveEnergyWallbox1"/>
+
+                       <!-- SenecHomeBattery -->
+                       <channel id="chargedEnergyPack1" typeId="chargedEnergyPack1"/>
+                       <channel id="chargedEnergyPack2" typeId="chargedEnergyPack2"/>
+                       <channel id="chargedEnergyPack3" typeId="chargedEnergyPack3"/>
+                       <channel id="chargedEnergyPack4" typeId="chargedEnergyPack4"/>
+                       <channel id="dischargedEnergyPack1" typeId="dischargedEnergyPack1"/>
+                       <channel id="dischargedEnergyPack2" typeId="dischargedEnergyPack2"/>
+                       <channel id="dischargedEnergyPack3" typeId="dischargedEnergyPack3"/>
+                       <channel id="dischargedEnergyPack4" typeId="dischargedEnergyPack4"/>
+                       <channel id="cyclesPack1" typeId="cyclesPack1"/>
+                       <channel id="cyclesPack2" typeId="cyclesPack2"/>
+                       <channel id="cyclesPack3" typeId="cyclesPack3"/>
+                       <channel id="cyclesPack4" typeId="cyclesPack4"/>
+                       <channel id="currentPack1" typeId="currentPack1"/>
+                       <channel id="currentPack2" typeId="currentPack2"/>
+                       <channel id="currentPack3" typeId="currentPack3"/>
+                       <channel id="currentPack4" typeId="currentPack4"/>
+                       <channel id="voltagePack1" typeId="voltagePack1"/>
+                       <channel id="voltagePack2" typeId="voltagePack2"/>
+                       <channel id="voltagePack3" typeId="voltagePack3"/>
+                       <channel id="voltagePack4" typeId="voltagePack4"/>
+                       <channel id="maxCellVoltagePack1" typeId="maxCellVoltagePack1"/>
+                       <channel id="maxCellVoltagePack2" typeId="maxCellVoltagePack2"/>
+                       <channel id="maxCellVoltagePack3" typeId="maxCellVoltagePack3"/>
+                       <channel id="maxCellVoltagePack4" typeId="maxCellVoltagePack4"/>
+                       <channel id="minCellVoltagePack1" typeId="minCellVoltagePack1"/>
+                       <channel id="minCellVoltagePack2" typeId="minCellVoltagePack2"/>
+                       <channel id="minCellVoltagePack3" typeId="minCellVoltagePack3"/>
+                       <channel id="minCellVoltagePack4" typeId="minCellVoltagePack4"/>
+
+                       <!-- SenecHomeTemperature -->
+                       <channel id="batteryTemperature" typeId="batteryTemperature"/>
+                       <channel id="caseTemperature" typeId="caseTemperature"/>
+                       <channel id="mcuTemperature" typeId="mcuTemperature"/>
+
+                       <!-- SenecHomeWallbox -->
+                       <channel id="wallbox1State" typeId="wallbox1State"/>
+                       <channel id="wallbox1StateValue" typeId="wallbox1StateValue"/>
+                       <channel id="wallbox1ChargingCurrentPhase1" typeId="wallbox1ChargingCurrentPhase1"/>
+                       <channel id="wallbox1ChargingCurrentPhase2" typeId="wallbox1ChargingCurrentPhase2"/>
+                       <channel id="wallbox1ChargingCurrentPhase3" typeId="wallbox1ChargingCurrentPhase3"/>
+                       <channel id="wallbox1ChargingPower" typeId="wallbox1ChargingPower"/>
                </channels>
 
                <config-description>
        <channel-type id="powerLimitation">
                <item-type>Number:Dimensionless</item-type>
                <label>Power Limitation</label>
-               <category>Energy</category>
+               <category>Number</category>
                <state readOnly="true" pattern="%.0f %unit%"/>
        </channel-type>
-
        <channel-type id="powerLimitationState">
                <item-type>Switch</item-type>
                <label>Limitation State</label>
-               <category>Energy</category>
+               <category>Text</category>
                <state readOnly="true"/>
        </channel-type>
+       <channel-type id="currentMpp1">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current MPP1</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="currentMpp2">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current MPP2</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="currentMpp3">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current MPP3</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="powerMpp1">
+               <item-type>Number:Power</item-type>
+               <label>Power MPP1</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="powerMpp2">
+               <item-type>Number:Power</item-type>
+               <label>Power MPP2</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="powerMpp3">
+               <item-type>Number:Power</item-type>
+               <label>Power MPP3</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltageMpp1">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage MPP1</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltageMpp2">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage MPP2</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltageMpp3">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage MPP3</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+
 
        <channel-type id="houseConsumption">
                <item-type>Number:Power</item-type>
-               <label>Home Power Consumption</label>
+               <label>House Power Consumption</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="energyProduction">
+               <item-type>Number:Power</item-type>
+               <label>Solar Production</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="batteryPower">
                <item-type>Number:Power</item-type>
                <label>Battery Power</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
+       <channel-type id="batteryCurrent">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Battery Current</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="batteryVoltage">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Battery Voltage</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
        <channel-type id="batteryFuelCharge">
                <item-type>Number:Dimensionless</item-type>
                <label>Battery Fuel</label>
-               <category>Battery</category>
+               <category>BatteryLevel</category>
                <state readOnly="true" pattern="%.0f %unit%"/>
        </channel-type>
-
-       <channel-type id="batteryState">
+       <channel-type id="systemState">
                <item-type>String</item-type>
-               <label>Battery State</label>
-               <category>Battery</category>
+               <label>System State</label>
+               <category>Text</category>
                <state readOnly="true" pattern="%s"/>
        </channel-type>
-
-       <channel-type id="batteryStateValue">
+       <channel-type id="systemStateValue">
                <item-type>Number</item-type>
-               <label>Battery State Value</label>
-               <category>Battery</category>
+               <label>System State Value</label>
+               <category>Number</category>
                <state readOnly="true" pattern="%d"/>
        </channel-type>
 
-       <channel-type id="energyProduction">
-               <item-type>Number:Power</item-type>
-               <label>Solar Production</label>
-               <category>Energy</category>
-               <state readOnly="true" pattern="%.0f %unit%"/>
-       </channel-type>
 
        <channel-type id="gridPower">
                <item-type>Number:Power</item-type>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridPowerSupply">
                <item-type>Number:Power</item-type>
                <label>Grid Supply</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridPowerDraw">
                <item-type>Number:Power</item-type>
                <label>Grid Draw</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridPowerPhase1">
                <item-type>Number:Power</item-type>
                <label>Grid Power Phase 1</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridPowerPhase2">
                <item-type>Number:Power</item-type>
                <label>Grid Power Phase 2</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridPowerPhase3">
                <item-type>Number:Power</item-type>
                <label>Grid Power Phase 3</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridCurrentPhase1">
                <item-type>Number:ElectricCurrent</item-type>
                <label>Grid Current Phase 1</label>
                <category>Current</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridCurrentPhase2">
                <item-type>Number:ElectricCurrent</item-type>
                <label>Grid Current Phase 2</label>
                <category>Current</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridCurrentPhase3">
                <item-type>Number:ElectricCurrent</item-type>
                <label>Grid Current Phase 3</label>
                <category>Current</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridVoltagePhase1">
                <item-type>Number:ElectricPotential</item-type>
                <label>Grid Voltage Phase 1</label>
                <category>Voltage</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridVoltagePhase2">
                <item-type>Number:ElectricPotential</item-type>
                <label>Grid Voltage Phase 2</label>
                <category>Voltage</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridVoltagePhase3">
                <item-type>Number:ElectricPotential</item-type>
                <label>Grid Voltage Phase 3</label>
                <category>Voltage</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="gridFrequency">
                <item-type>Number:Frequency</item-type>
                <label>Grid Frequency</label>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
 
+
        <channel-type id="liveBatCharge">
                <item-type>Number:Energy</item-type>
                <label>Live Bat Charge</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="liveBatDischarge">
                <item-type>Number:Energy</item-type>
                <label>Live Bat Discharge</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="liveGridImport">
                <item-type>Number:Energy</item-type>
                <label>Live Grid Import</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
-
        <channel-type id="liveGridExport">
                <item-type>Number:Energy</item-type>
                <label>Live Grid Export</label>
                <category>Energy</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
+       <channel-type id="liveHouseConsumption">
+               <item-type>Number:Energy</item-type>
+               <label>Live House Consumption</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="livePowerGenerator">
+               <item-type>Number:Energy</item-type>
+               <label>Live Power Generator</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="liveEnergyWallbox1">
+               <item-type>Number:Energy</item-type>
+               <label>Live Wallbox 1 charged Energy</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
 
-       <channel-type id="batteryVoltage">
+
+       <channel-type id="chargedEnergyPack1" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total charged energy battery pack 1</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="chargedEnergyPack2" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total charged energy battery pack 2</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="chargedEnergyPack3" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total charged energy battery pack 3</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="chargedEnergyPack4" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total charged energy battery pack 4</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="dischargedEnergyPack1" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total discharged energy battery pack 1</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="dischargedEnergyPack2" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total discharged energy battery pack 2</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="dischargedEnergyPack3" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total discharged energy battery pack 3</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="dischargedEnergyPack4" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Total discharged energy battery pack 4</label>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="cyclesPack1" advanced="true">
+               <item-type>Number</item-type>
+               <label>Cycles battery pack 1</label>
+               <category>Number</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="cyclesPack2" advanced="true">
+               <item-type>Number</item-type>
+               <label>Cycles battery pack 2</label>
+               <category>Number</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="cyclesPack3" advanced="true">
+               <item-type>Number</item-type>
+               <label>Cycles battery pack 3</label>
+               <category>Number</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="cyclesPack4" advanced="true">
+               <item-type>Number</item-type>
+               <label>Cycles battery pack 4</label>
+               <category>Number</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="currentPack1" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current battery pack 1</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="currentPack2" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current battery pack 2</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="currentPack3" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current battery pack 3</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="currentPack4" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current battery pack 4</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltagePack1" advanced="true">
                <item-type>Number:ElectricPotential</item-type>
-               <label>Battery Voltage</label>
+               <label>Voltage battery pack 1</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltagePack2" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage battery pack 2</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltagePack3" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage battery pack 3</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="voltagePack4" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage battery pack 4</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="maxCellVoltagePack1" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Maximum cell voltage battery pack 1</label>
                <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="maxCellVoltagePack2" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Maximum cell voltage battery pack 2</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="maxCellVoltagePack3" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Maximum cell voltage battery pack 3</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="maxCellVoltagePack4" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Maximum cell voltage battery pack 4</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="minCellVoltagePack1" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Minimum cell voltage battery pack 1</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="minCellVoltagePack2" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Minimum cell voltage battery pack 2</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="minCellVoltagePack3" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Minimum cell voltage battery pack 3</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+       <channel-type id="minCellVoltagePack4" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Minimum cell voltage battery pack 4</label>
+               <category>Voltage</category>
+               <state readOnly="true" pattern="%.3f %unit%"/>
+       </channel-type>
+
+
+       <channel-type id="batteryTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Battery Temperature</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="caseTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Case Temperature</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+       <channel-type id="mcuTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>MCU Temperature</label>
+               <category>Temperature</category>
+               <state readOnly="true" pattern="%.0f %unit%"/>
+       </channel-type>
+
+
+       <channel-type id="wallbox1State">
+               <item-type>String</item-type>
+               <label>Wallbox 1 State</label>
+               <category>Text</category>
+               <state readOnly="true" pattern="%s"/>
+       </channel-type>
+       <channel-type id="wallbox1StateValue">
+               <item-type>Number</item-type>
+               <label>Wallbox 1 State Value</label>
+               <category>Number</category>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="wallbox1ChargingCurrentPhase1" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Wallbox 1 charging Current Phase 1</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="wallbox1ChargingCurrentPhase2" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Wallbox 1 charging Current Phase 2</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="wallbox1ChargingCurrentPhase3" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Wallbox 1 charging Current Phase 3</label>
+               <category>Current</category>
+               <state readOnly="true" pattern="%.2f %unit%"/>
+       </channel-type>
+       <channel-type id="wallbox1ChargingPower">
+               <item-type>Number:Energy</item-type>
+               <label>Wallbox 1 charging Power</label>
+               <category>Power</category>
                <state readOnly="true" pattern="%.2f %unit%"/>
        </channel-type>
 </thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.senechome/src/test/java/org/openhab/binding/senechome/internal/SenecHomeHandlerTest.java b/bundles/org.openhab.binding.senechome/src/test/java/org/openhab/binding/senechome/internal/SenecHomeHandlerTest.java
new file mode 100644 (file)
index 0000000..d338f5e
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * 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.senechome.internal;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.openhab.core.thing.Thing;
+
+/**
+ * Test for senec value parsing. All test data are from "original" senec (using vars.html).
+ *
+ * @author Erwin Guib - Initial Contribution
+ */
+@RunWith(MockitoJUnitRunner.class)
+class SenecHomeHandlerTest {
+
+    protected static Object[][] data() {
+        return new Object[][] {
+                // unsigned
+                { "u1_0002", BigDecimal.valueOf(2) }, //
+                { "u1_07DB", BigDecimal.valueOf(2011) }, //
+                { "u3_0000194C", BigDecimal.valueOf(6476) }, //
+                { "u3_817E00E0", BigDecimal.valueOf(2172518624L) }, //
+                { "u6_0000000000000001", BigDecimal.valueOf(1) }, //
+                { "u6_00000000000C75D9", BigDecimal.valueOf(816601) }, //
+                { "u8_64", BigDecimal.valueOf(100) }, //
+                // int
+                { "i1_00FA", BigDecimal.valueOf(250) }, //
+                { "i3_00000078", BigDecimal.valueOf(120) }, //
+                { "i3_609F8480", BigDecimal.valueOf(1621066880) }, //
+                { "i3_FFFFFFFF", BigDecimal.valueOf(-1) }, //
+                { "i8_18", BigDecimal.valueOf(24) }, //
+                // string (unknown)
+                { "st_HMI: 3.15.32 PU: 4.1.89", BigDecimal.valueOf(0) } };
+    }
+
+    protected static Object[][] floatData() {
+        return new Object[][] {
+                // float
+                { "fl_41C80000", BigDecimal.valueOf(25), 0 }, //
+                { "fl_4247632F", BigDecimal.valueOf(49.85), 2 }, //
+                { "fl_C5AB6F0B", BigDecimal.valueOf(-5485.88), 2 }, //
+                { "fl_4248CCCD", BigDecimal.valueOf(50.2), 1 }, //
+        };
+    }
+
+    @Mock
+    Thing mockThing;
+
+    @Mock
+    HttpClient mockHttpClient;
+
+    SenecHomeHandler cut = new SenecHomeHandler(mockThing, mockHttpClient);
+
+    @ParameterizedTest
+    @MethodSource("data")
+    void getSenecValue(String value, Object expectedResult) {
+        Assertions.assertEquals(expectedResult, cut.getSenecValue(value));
+    }
+
+    @ParameterizedTest
+    @MethodSource("floatData")
+    void getSenecValueFloat(String value, Object expectedResult, int scale) {
+        Assertions.assertEquals(expectedResult, cut.getSenecValue(value).setScale(scale, RoundingMode.HALF_UP));
+    }
+}