diff --git a/CODEOWNERS b/CODEOWNERS index 2393601417b..dc0594108b3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -290,6 +290,7 @@ /bundles/org.openhab.binding.solarwatt/ @sven-carstens /bundles/org.openhab.binding.somfymylink/ @loungeflyz /bundles/org.openhab.binding.somfytahoma/ @octa22 +/bundles/org.openhab.binding.sonnen/ @chingon007 /bundles/org.openhab.binding.sonos/ @kgoderis @lolodomo /bundles/org.openhab.binding.sonyaudio/ @freke /bundles/org.openhab.binding.sonyprojector/ @lolodomo diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 4e06be80604..109c762a36f 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -1441,6 +1441,11 @@ org.openhab.binding.somfytahoma ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.sonnen + ${project.version} + org.openhab.addons.bundles org.openhab.binding.sonos diff --git a/bundles/org.openhab.binding.sonnen/NOTICE b/bundles/org.openhab.binding.sonnen/NOTICE new file mode 100644 index 00000000000..38d625e3492 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.sonnen/README.md b/bundles/org.openhab.binding.sonnen/README.md new file mode 100644 index 00000000000..0e30d5f84bb --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/README.md @@ -0,0 +1,64 @@ +# Sonnen Binding + +The binding for sonnen communicates with a sonnen battery. +More information about the sonnen battery can be found [here](https://sonnen.de/). + +## Supported Things + +| Thing Type | Description | +|---------------|--------------------------------| +| sonnenbattery | Monitoring of a sonnen battery | + + +## Thing Configuration + +Only the parameter `hostIP` is required; this is the IP address of the sonnen battery in your local network. + + +## Channels + +The following channels are yet supported: + + +| Channel | Type | Access| Description| +|---------|-------|-------|------------| +|batteryChargingState|Switch|read|Indicates if the Battery is charging at that moment| +|batteryCharging|Number:Energy|read|Indicates the actual current charging the Battery. Otherwise 0.| +|batteryDischargingState|Switch|read|Indicates if the Battery is discharging at that moment| +|batteryDischarging|Number:Energy|read|Indicates the actual current discharging the Battery. Otherwise 0.| +|batteryFeedIn|Number:Energy|read|Indicates the actual charging current of the Battery in watt| +|batteryDischarging|Number:Energy|read|Indicates the actual current discharging the Battery in watt| +|consumption|Number:Energy|read|Indicates the actual consumption of the consumer in watt| +|gridFeedIn|Number:Energy|read|Indicates the actual current feeding to the Grid in watt.0 if nothing is feeded| +|gridConsumption|Number:Energy|read|Indicates the actual current consumption from the Grid in watt.0 if nothing is received| +|solarProduction|Number:Energy|read|Indicates the actual production of the Solar system in watt| +|batteryLevel|Number|read|Indicates the actual Battery Level in % from 0 - 100| +|flowConsumptionBatteryState|Switch|read|Indicates if there is a current flow from Battery towards Consumption| +|flowConsumptionGridState|Switch|read|Indicates if there is a current flow from Grid towards Consumption| +|flowConsumptionProductionState|Switch|read|Indicates if there is a current flow from Solar Production towards Consumption| +|flowGridBatteryState|Switch|read|Indicates if there is a current flow from Grid towards Battery| +|flowProductionBatteryState|Switch|read|Indicates if there is a current flow from Production towards Battery| +|flowProductionGridState|Switch|read|Indicates if there is a current flow from Production towards Grid| + +## Full Example + +example.things: + +``` +Thing sonnen:sonnenbattery:myBattery "Sonnen Battery" [ hostIP="192.168.0.10"] +``` + +example.items: + +``` +Number:Energy Consumption { channel="sonnen:sonnenbattery:myBattery:consumption" } +Number:Energy GridFeeding { channel="sonnen:sonnenbattery:myBattery:gridFeedIn" } +Number BatteryLevel { channel="sonnen:sonnenbattery:myBattery:batteryLevel" } +Switch FlowConsumptionBattery { channel="sonnen:sonnenbattery:myBattery:flowConsumptionBattery" } +``` + +## Tested Hardware + +The binding was successfully tested with the following sonnen battery: + +- sonnnen eco 8.0 SW Version: 1.6.10.1221979 diff --git a/bundles/org.openhab.binding.sonnen/pom.xml b/bundles/org.openhab.binding.sonnen/pom.xml new file mode 100644 index 00000000000..baffc8c2e78 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 3.3.0-SNAPSHOT + + + org.openhab.binding.sonnen + + openHAB Add-ons :: Bundles :: Sonnen Binding + + diff --git a/bundles/org.openhab.binding.sonnen/src/main/feature/feature.xml b/bundles/org.openhab.binding.sonnen/src/main/feature/feature.xml new file mode 100644 index 00000000000..3a439f43c25 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.sonnen/${project.version} + + diff --git a/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenBindingConstants.java b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenBindingConstants.java new file mode 100644 index 00000000000..09b80a1b042 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenBindingConstants.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sonnen.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link SonnenBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Christian Feininger - Initial contribution + */ +@NonNullByDefault +public class SonnenBindingConstants { + + private static final String BINDING_ID = "sonnen"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_BATTERY = new ThingTypeUID(BINDING_ID, "sonnenbattery"); + + // List of all Channel ids + public static final String CHANNELBATTERYCHARGINGSTATE = "batteryChargingState"; + public static final String CHANNELBATTERYDISCHARGINGSTATE = "batteryDischargingState"; + public static final String CHANNELBATTERYCHARGING = "batteryCharging"; + public static final String CHANNELBATTERYDISCHARGING = "batteryDischarging"; + public static final String CHANNELCONSUMPTION = "consumption"; + public static final String CHANNELGRIDFEEDIN = "gridFeedIn"; + public static final String CHANNELGRIDCONSUMPTION = "gridConsumption"; + public static final String CHANNELSOLARPRODUCTION = "solarProduction"; + public static final String CHANNELBATTERYLEVEL = "batteryLevel"; + public static final String CHANNELFLOWCONSUMPTIONBATTERYSTATE = "flowConsumptionBatteryState"; + public static final String CHANNELFLOWCONSUMPTIONGRIDSTATE = "flowConsumptionGridState"; + public static final String CHANNELFLOWCONSUMPTIONPRODUCTIONSTATE = "flowConsumptionProductionState"; + public static final String CHANNELFLOWGRIDBATTERYSTATE = "flowGridBatteryState"; + public static final String CHANNELFLOWPRODUCTIONBATTERYSTATE = "flowProductionBatteryState"; + public static final String CHANNELFLOWPRODUCTIONGRIDSTATE = "flowProductionGridState"; +} diff --git a/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenConfiguration.java b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenConfiguration.java new file mode 100644 index 00000000000..ffcdf1b51c1 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenConfiguration.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sonnen.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link SonnenConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Christian Feininger - Initial contribution + */ +@NonNullByDefault +public class SonnenConfiguration { + + public @Nullable String hostIP = null; + public int refreshInterval = 30; +} diff --git a/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandler.java b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandler.java new file mode 100644 index 00000000000..657a5f936ec --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandler.java @@ -0,0 +1,261 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sonnen.internal; + +import static org.openhab.binding.sonnen.internal.SonnenBindingConstants.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import javax.measure.quantity.Dimensionless; +import javax.measure.quantity.Power; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.sonnen.internal.communication.SonnenJSONCommunication; +import org.openhab.binding.sonnen.internal.communication.SonnenJsonDataDTO; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link SonnenHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Christian Feininger - Initial contribution + */ +@NonNullByDefault +public class SonnenHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(SonnenHandler.class); + + private SonnenConfiguration config = new SonnenConfiguration(); + + private @Nullable ScheduledFuture refreshJob; + + private SonnenJSONCommunication serviceCommunication; + + private boolean automaticRefreshing = false; + + private Map linkedChannels = new HashMap<>(); + + public SonnenHandler(Thing thing) { + super(thing); + serviceCommunication = new SonnenJSONCommunication(); + } + + @Override + public void initialize() { + logger.debug("Initializing sonnen handler for thing {}", getThing().getUID()); + config = getConfigAs(SonnenConfiguration.class); + if (config.refreshInterval < 0 || config.refreshInterval > 1000) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Parameter 'refresh Rate' msut be in the range 0-1000!"); + return; + } + if (config.hostIP == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "IP Address must be configured!"); + return; + } + + serviceCommunication.setConfig(config); + updateStatus(ThingStatus.UNKNOWN); + scheduler.submit(() -> { + if (updateBatteryData()) { + for (Channel channel : getThing().getChannels()) { + if (isLinked(channel.getUID().getId())) { + channelLinked(channel.getUID()); + } + } + } + }); + } + + /** + * Calls the service to update the battery data + * + * @return true if the update succeeded, false otherwise + */ + private boolean updateBatteryData() { + String error = serviceCommunication.refreshBatteryConnection(); + if (error.isEmpty()) { + if (!ThingStatus.ONLINE.equals(getThing().getStatus())) { + updateStatus(ThingStatus.ONLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error); + } + return error.isEmpty(); + } + + private void verifyLinkedChannel(String channelID) { + if (isLinked(channelID) && !linkedChannels.containsKey(channelID)) { + linkedChannels.put(channelID, true); + } + } + + @Override + public void dispose() { + stopAutomaticRefresh(); + linkedChannels.clear(); + automaticRefreshing = false; + } + + private void stopAutomaticRefresh() { + ScheduledFuture job = refreshJob; + if (job != null) { + job.cancel(true); + } + refreshJob = null; + } + + /** + * Start the job refreshing the oven status + */ + private void startAutomaticRefresh() { + ScheduledFuture job = refreshJob; + if (job == null || job.isCancelled()) { + refreshJob = scheduler.scheduleWithFixedDelay(this::refreshChannels, 0, config.refreshInterval, + TimeUnit.SECONDS); + } + } + + private void refreshChannels() { + updateBatteryData(); + for (Channel channel : getThing().getChannels()) { + updateChannel(channel.getUID().getId()); + } + } + + @Override + public void channelLinked(ChannelUID channelUID) { + if (!automaticRefreshing) { + logger.debug("Start automatic refreshing"); + startAutomaticRefresh(); + automaticRefreshing = true; + } + verifyLinkedChannel(channelUID.getId()); + updateChannel(channelUID.getId()); + } + + @Override + public void channelUnlinked(ChannelUID channelUID) { + linkedChannels.remove(channelUID.getId()); + if (linkedChannels.isEmpty()) { + automaticRefreshing = false; + stopAutomaticRefresh(); + logger.debug("Stop automatic refreshing"); + } + } + + private void updateChannel(String channelId) { + if (isLinked(channelId)) { + State state = null; + SonnenJsonDataDTO data = serviceCommunication.getBatteryData(); + if (data != null) { + switch (channelId) { + case CHANNELBATTERYDISCHARGINGSTATE: + update(OnOffType.from(data.isBatteryDischarging()), channelId); + break; + case CHANNELBATTERYCHARGINGSTATE: + update(OnOffType.from(data.isBatteryCharging()), channelId); + break; + case CHANNELCONSUMPTION: + state = new QuantityType(data.getConsumptionHouse(), Units.WATT); + update(state, channelId); + break; + case CHANNELBATTERYDISCHARGING: + state = new QuantityType(data.getbatteryCurrent() > 0 ? data.getbatteryCurrent() : 0, + Units.WATT); + update(state, channelId); + break; + case CHANNELBATTERYCHARGING: + state = new QuantityType( + data.getbatteryCurrent() <= 0 ? (data.getbatteryCurrent() * -1) : 0, Units.WATT); + update(state, channelId); + break; + case CHANNELGRIDFEEDIN: + state = new QuantityType(data.getGridValue() > 0 ? data.getGridValue() : 0, Units.WATT); + update(state, channelId); + break; + case CHANNELGRIDCONSUMPTION: + state = new QuantityType(data.getGridValue() <= 0 ? (data.getGridValue() * -1) : 0, + Units.WATT); + update(state, channelId); + break; + case CHANNELSOLARPRODUCTION: + state = new QuantityType(data.getSolarProduction(), Units.WATT); + update(state, channelId); + break; + case CHANNELBATTERYLEVEL: + state = new QuantityType(data.getBatteryChargingLevel(), Units.PERCENT); + update(state, channelId); + break; + case CHANNELFLOWCONSUMPTIONBATTERYSTATE: + update(OnOffType.from(data.isFlowConsumptionBattery()), channelId); + break; + case CHANNELFLOWCONSUMPTIONGRIDSTATE: + update(OnOffType.from(data.isFlowConsumptionGrid()), channelId); + break; + case CHANNELFLOWCONSUMPTIONPRODUCTIONSTATE: + update(OnOffType.from(data.isFlowConsumptionProduction()), channelId); + break; + case CHANNELFLOWGRIDBATTERYSTATE: + update(OnOffType.from(data.isFlowGridBattery()), channelId); + break; + case CHANNELFLOWPRODUCTIONBATTERYSTATE: + update(OnOffType.from(data.isFlowProductionBattery()), channelId); + break; + case CHANNELFLOWPRODUCTIONGRIDSTATE: + update(OnOffType.from(data.isFlowProductionGrid()), channelId); + break; + } + } else { + update(null, channelId); + } + } + } + + /** + * Updates the State of the given channel + * + * @param state Given state + * @param channelId the refereed channelID + */ + private void update(@Nullable State state, String channelId) { + logger.debug("Update channel {} with state {}", channelId, (state == null) ? "null" : state.toString()); + updateState(channelId, state != null ? state : UnDefType.UNDEF); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command == RefreshType.REFRESH) { + updateBatteryData(); + updateChannel(channelUID.getId()); + } + } +} diff --git a/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandlerFactory.java b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandlerFactory.java new file mode 100644 index 00000000000..ab8c968756a --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/SonnenHandlerFactory.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sonnen.internal; + +import static org.openhab.binding.sonnen.internal.SonnenBindingConstants.THING_TYPE_BATTERY; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link SonnenHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Christian Feininger - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.sonnen", service = ThingHandlerFactory.class) +public class SonnenHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BATTERY); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_BATTERY.equals(thingTypeUID)) { + return new SonnenHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/communication/SonnenJSONCommunication.java b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/communication/SonnenJSONCommunication.java new file mode 100644 index 00000000000..0d8482db234 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/communication/SonnenJSONCommunication.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sonnen.internal.communication; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.sonnen.internal.SonnenConfiguration; +import org.openhab.core.io.net.http.HttpUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * This class handles the JSON communication with the sonnen battery + * + * @author Christian Feininger - Initial contribution + * + */ +@NonNullByDefault +public class SonnenJSONCommunication { + + private final Logger logger = LoggerFactory.getLogger(SonnenJSONCommunication.class); + private SonnenConfiguration config; + + private Gson gson; + private @Nullable SonnenJsonDataDTO batteryData; + + public SonnenJSONCommunication() { + gson = new Gson(); + config = new SonnenConfiguration(); + } + + /** + * Refreshes the battery connection. + * + * @return an empty string if no error occurred, the error message otherwise. + */ + public String refreshBatteryConnection() { + String result = ""; + String urlStr = "http://" + config.hostIP + "/api/v1/status"; + + try { + String response = HttpUtil.executeUrl("GET", urlStr, 10000); + logger.debug("BatteryData = {}", response); + if (response == null) { + throw new IOException("HttpUtil.executeUrl returned null"); + } + batteryData = gson.fromJson(response, SonnenJsonDataDTO.class); + } catch (IOException | JsonSyntaxException e) { + logger.debug("Error processiong Get request {}: {}", urlStr, e.getMessage()); + result = "Cannot find service on given IP " + config.hostIP + ". Please verify the IP address!"; + batteryData = null; + } + return result; + } + + /** + * Set the config for service to communicate + * + * @param config2 + */ + public void setConfig(SonnenConfiguration config2) { + this.config = config2; + } + + /** + * Returns the actual stored Battery Data + * + * @return JSON Data from the Battery or null if request failed + */ + public @Nullable SonnenJsonDataDTO getBatteryData() { + return this.batteryData; + } +} diff --git a/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/communication/SonnenJsonDataDTO.java b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/communication/SonnenJsonDataDTO.java new file mode 100644 index 00000000000..84c2dae5df6 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/java/org/openhab/binding/sonnen/internal/communication/SonnenJsonDataDTO.java @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sonnen.internal.communication; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link SonnenJsonDataDTO} is the Java class used to map the JSON + * response to a Oven request. + * + * @author Christian Feininger - Initial contribution + */ +public class SonnenJsonDataDTO { + @SerializedName("BatteryCharging") + boolean batteryCharging; + @SerializedName("BatteryDischarging") + boolean batteryDischarging; + @SerializedName("Consumption_W") + int consumptionHouse; + @SerializedName("GridFeedIn_W") + int gridValue; + @SerializedName("Production_W") + int solarProduction; + @SerializedName("USOC") + int batteryChargingLevel; + @SerializedName("FlowConsumptionBattery") + boolean flowConsumptionBattery; + @SerializedName("FlowConsumptionGrid") + boolean flowConsumptionGrid; + @SerializedName("FlowConsumptionProduction") + boolean flowConsumptionProduction; + @SerializedName("FlowGridBattery") + boolean flowGridBattery; + @SerializedName("FlowProductionBattery") + boolean flowProductionBattery; + @SerializedName("FlowProductionGrid") + boolean flowProductionGrid; + @SerializedName("Pac_total_W") + int batteryCurrent; + + /** + * @return the batteryCurrent + */ + public int getbatteryCurrent() { + return batteryCurrent; + } + + /** + * @return the batteryCharging + */ + public boolean isBatteryCharging() { + return batteryCharging; + } + + /** + * @return the batteryDischarging + */ + public boolean isBatteryDischarging() { + return batteryDischarging; + } + + /** + * @return the consumptionHouse + */ + public int getConsumptionHouse() { + return consumptionHouse; + } + + /** + * @return the gridValue. Negative value indicates receiving from Grid. Positive value indicates feeding to Grid. + */ + public int getGridValue() { + return gridValue; + } + + /** + * @return the solarProduction + */ + public int getSolarProduction() { + return solarProduction; + } + + /** + * @return the batteryChargingLevel + */ + public int getBatteryChargingLevel() { + return batteryChargingLevel; + } + + /** + * @return the flowConsumptionBattery + */ + public boolean isFlowConsumptionBattery() { + return flowConsumptionBattery; + } + + /** + * @return the flowConsumptionGrid + */ + public boolean isFlowConsumptionGrid() { + return flowConsumptionGrid; + } + + /** + * @return the flowConsumptionProduction + */ + public boolean isFlowConsumptionProduction() { + return flowConsumptionProduction; + } + + /** + * @return the flowGridBattery + */ + public boolean isFlowGridBattery() { + return flowGridBattery; + } + + /** + * @return the flowProductionBattery + */ + public boolean isFlowProductionBattery() { + return flowProductionBattery; + } + + /** + * @return the flowProductionGrid + */ + public boolean isFlowProductionGrid() { + return flowProductionGrid; + } +} diff --git a/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/binding/binding.xml new file mode 100644 index 00000000000..a24ce4e0cec --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/binding/binding.xml @@ -0,0 +1,9 @@ + + + + Sonnen Binding + This binding communicates with a solar battery from sonnen. + + diff --git a/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/i18n/sonnen.properties b/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/i18n/sonnen.properties new file mode 100644 index 00000000000..d7687f61741 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/i18n/sonnen.properties @@ -0,0 +1,47 @@ +# binding + +binding.sonnen.name = Sonnen Binding +binding.sonnen.description = This binding communicates with a solar battery from sonnen. + +# thing types + +thing-type.sonnen.sonnenbattery.label = Sonnen Battery +thing-type.sonnen.sonnenbattery.description = Monitoring of a sonnen battery. + +# thing types config + +thing-type.config.sonnen.sonnenbattery.hostIP.label = IP Address +thing-type.config.sonnen.sonnenbattery.hostIP.description = Please add the IP Address of your sonnen battery. +thing-type.config.sonnen.sonnenbattery.refreshInterval.label = Refresh Interval +thing-type.config.sonnen.sonnenbattery.refreshInterval.description = How often in seconds the sonnen battery should schedule a refresh after a channel is linked to an item. Valid input is 0 - 1000. + +# channel types + +channel-type.sonnen.batteryCharging.label = Battery Charging +channel-type.sonnen.batteryCharging.description = Indicates the actual current charging the Battery. Otherwise 0. +channel-type.sonnen.batteryChargingState.label = Battery Charging State +channel-type.sonnen.batteryChargingState.description = Indicates if the Battery is charging at that moment. +channel-type.sonnen.batteryDischarging.label = Battery Discharging +channel-type.sonnen.batteryDischarging.description = Indicates the actual current discharging the Battery. Otherwise 0. +channel-type.sonnen.batteryDischargingState.label = Battery Discharging State +channel-type.sonnen.batteryDischargingState.description = Indicates if the Battery is discharging at that moment. +channel-type.sonnen.consumption.label = Consumption +channel-type.sonnen.consumption.description = Indicates the actual consumption of the House. +channel-type.sonnen.flowConsumptionBatteryState.label = Flow Battery Towards Consumption State +channel-type.sonnen.flowConsumptionBatteryState.description = Indicates if there is a current flow from battery towards consumption. +channel-type.sonnen.flowConsumptionGridState.label = Flow Grid Towards Consumption State +channel-type.sonnen.flowConsumptionGridState.description = Indicates if there is a current flow from grid towards consumption. +channel-type.sonnen.flowConsumptionProductionState.label = Flow Production Towards Consumption State +channel-type.sonnen.flowConsumptionProductionState.description = Indicates if there is a current flow from solar production towards consumption. +channel-type.sonnen.flowGridBatteryState.label = Flow Grid Towards Battery State +channel-type.sonnen.flowGridBatteryState.description = Indicates if there is a current flow from grid towards battery. +channel-type.sonnen.flowProductionBatteryState.label = Flow Production Towards Battery State +channel-type.sonnen.flowProductionBatteryState.description = Indicates if there is a current flow from production towards battery. +channel-type.sonnen.flowProductionGridState.label = Flow Production Towards Grid State +channel-type.sonnen.flowProductionGridState.description = Indicates if there is a current flow from production towards grid. +channel-type.sonnen.gridConsumption.label = Grid Consumption +channel-type.sonnen.gridConsumption.description = Indicates the actual current consumption from the the Grid. Otherwise 0. +channel-type.sonnen.gridFeedIn.label = Grid Feed In +channel-type.sonnen.gridFeedIn.description = Indicates the actual current feeding to the Grid. Otherwise 0. +channel-type.sonnen.solarProduction.label = Solar Production +channel-type.sonnen.solarProduction.description = Indicates the actual production of the Solar system. diff --git a/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 00000000000..5821dcf8952 --- /dev/null +++ b/bundles/org.openhab.binding.sonnen/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,131 @@ + + + + + + + Monitoring of a sonnen battery. + + + + + + + + + + + + + + + + + + + + + + network-address + + Please add the IP Address of your sonnen battery. + + + + How often in seconds the sonnen battery should schedule a refresh after a channel is linked to an item. + Valid input is 0 - 1000. + true + 30 + + + + + + + Switch + + Indicates if the Battery is charging at that moment. + + + + Switch + + Indicates if the Battery is discharging at that moment. + + + + Number:Energy + + Indicates the actual current charging the Battery. Otherwise 0. + + + + Number:Energy + + Indicates the actual current discharging the Battery. Otherwise 0. + + + + Number:Energy + + Indicates the actual consumption of the House. + + + + Number:Energy + + Indicates the actual current feeding to the Grid. Otherwise 0. + + + + Number:Energy + + Indicates the actual current consumption from the the Grid. Otherwise 0. + + + + Number:Energy + + Indicates the actual production of the Solar system. + + + + Switch + + Indicates if there is a current flow from battery towards consumption. + + + + Switch + + Indicates if there is a current flow from grid towards consumption. + + + + Switch + + Indicates if there is a current flow from solar production towards consumption. + + + + Switch + + Indicates if there is a current flow from grid towards battery. + + + + Switch + + Indicates if there is a current flow from production towards battery. + + + + Switch + + Indicates if there is a current flow from production towards grid. + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 536eef33390..c45ac553505 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -322,6 +322,7 @@ org.openhab.binding.solarwatt org.openhab.binding.somfymylink org.openhab.binding.somfytahoma + org.openhab.binding.sonnen org.openhab.binding.sonos org.openhab.binding.sonyaudio org.openhab.binding.sonyprojector