* [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>
/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
| 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
|-----------------------|-----------|--------------------------------------------------------------------------|
| 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 |
| 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
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" }
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
+++ /dev/null
-/**
- * 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;
- }
-}
*
* 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
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";
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";
}
*/
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;
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;
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;
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;
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 {
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;
}
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));
}
}
}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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) + '}';
+ }
+}
* 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 + "]";
}
}
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
*/
+++ /dev/null
-/**
- * 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 + "]";
- }
-}
--- /dev/null
+/**
+ * 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) + "]";
+ }
+}
*/
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 + "]";
}
}
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) + "]";
}
}
--- /dev/null
+/**
+ * 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 + '\'' + '}';
+ }
+}
--- /dev/null
+/**
+ * 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)
+ + '}';
+ }
+}
<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>
--- /dev/null
+/**
+ * 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));
+ }
+}