mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[sonnen] Initial contribution of new binding for solar battery (#11915)
* Initial contribution of sonnen binding Signed-off-by: chingon007 <tron81@gmx.de>
This commit is contained in:
parent
0fcebcde3f
commit
46ba275edb
@ -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
|
||||
|
@ -1441,6 +1441,11 @@
|
||||
<artifactId>org.openhab.binding.somfytahoma</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.sonnen</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.sonos</artifactId>
|
||||
|
13
bundles/org.openhab.binding.sonnen/NOTICE
Normal file
13
bundles/org.openhab.binding.sonnen/NOTICE
Normal file
@ -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
|
64
bundles/org.openhab.binding.sonnen/README.md
Normal file
64
bundles/org.openhab.binding.sonnen/README.md
Normal file
@ -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
|
17
bundles/org.openhab.binding.sonnen/pom.xml
Normal file
17
bundles/org.openhab.binding.sonnen/pom.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.sonnen</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Sonnen Binding</name>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.sonnen-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-sonnen" description="Sonnen Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.sonnen/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -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";
|
||||
}
|
@ -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;
|
||||
}
|
@ -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<String, Boolean> 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<Power>(data.getConsumptionHouse(), Units.WATT);
|
||||
update(state, channelId);
|
||||
break;
|
||||
case CHANNELBATTERYDISCHARGING:
|
||||
state = new QuantityType<Power>(data.getbatteryCurrent() > 0 ? data.getbatteryCurrent() : 0,
|
||||
Units.WATT);
|
||||
update(state, channelId);
|
||||
break;
|
||||
case CHANNELBATTERYCHARGING:
|
||||
state = new QuantityType<Power>(
|
||||
data.getbatteryCurrent() <= 0 ? (data.getbatteryCurrent() * -1) : 0, Units.WATT);
|
||||
update(state, channelId);
|
||||
break;
|
||||
case CHANNELGRIDFEEDIN:
|
||||
state = new QuantityType<Power>(data.getGridValue() > 0 ? data.getGridValue() : 0, Units.WATT);
|
||||
update(state, channelId);
|
||||
break;
|
||||
case CHANNELGRIDCONSUMPTION:
|
||||
state = new QuantityType<Power>(data.getGridValue() <= 0 ? (data.getGridValue() * -1) : 0,
|
||||
Units.WATT);
|
||||
update(state, channelId);
|
||||
break;
|
||||
case CHANNELSOLARPRODUCTION:
|
||||
state = new QuantityType<Power>(data.getSolarProduction(), Units.WATT);
|
||||
update(state, channelId);
|
||||
break;
|
||||
case CHANNELBATTERYLEVEL:
|
||||
state = new QuantityType<Dimensionless>(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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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<ThingTypeUID> 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="sonnen" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Sonnen Binding</name>
|
||||
<description>This binding communicates with a solar battery from sonnen.</description>
|
||||
|
||||
</binding:binding>
|
@ -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.
|
@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="sonnen"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Sonnen battery Thing Type -->
|
||||
<thing-type id="sonnenbattery">
|
||||
<label>Sonnen Battery</label>
|
||||
<description>Monitoring of a sonnen battery.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="batteryChargingState" typeId="batteryChargingState"/>
|
||||
<channel id="batteryDischargingState" typeId="batteryDischargingState"/>
|
||||
<channel id="batteryCharging" typeId="batteryCharging"/>
|
||||
<channel id="batteryDischarging" typeId="batteryDischarging"/>
|
||||
<channel id="consumption" typeId="consumption"/>
|
||||
<channel id="gridFeedIn" typeId="gridFeedIn"/>
|
||||
<channel id="gridConsumption" typeId="gridConsumption"/>
|
||||
<channel id="solarProduction" typeId="solarProduction"/>
|
||||
<channel id="batteryLevel" typeId="system.battery-level"/>
|
||||
<channel id="flowConsumptionBatteryState" typeId="flowConsumptionBatteryState"/>
|
||||
<channel id="flowConsumptionGridState" typeId="flowConsumptionGridState"/>
|
||||
<channel id="flowConsumptionProductionState" typeId="flowConsumptionProductionState"/>
|
||||
<channel id="flowGridBatteryState" typeId="flowGridBatteryState"/>
|
||||
<channel id="flowProductionBatteryState" typeId="flowProductionBatteryState"/>
|
||||
<channel id="flowProductionGridState" typeId="flowProductionGridState"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="hostIP" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>IP Address</label>
|
||||
<description>Please add the IP Address of your sonnen battery.</description>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" unit="s" min="0" max="1000">
|
||||
<label>Refresh Interval</label>
|
||||
<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.</description>
|
||||
<advanced>true</advanced>
|
||||
<default>30</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- sonnen Channel Type -->
|
||||
<channel-type id="batteryChargingState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Battery Charging State</label>
|
||||
<description>Indicates if the Battery is charging at that moment.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="batteryDischargingState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Battery Discharging State</label>
|
||||
<description>Indicates if the Battery is discharging at that moment.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="batteryCharging">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Battery Charging</label>
|
||||
<description>Indicates the actual current charging the Battery. Otherwise 0.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="batteryDischarging">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Battery Discharging</label>
|
||||
<description>Indicates the actual current discharging the Battery. Otherwise 0.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="consumption">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Consumption</label>
|
||||
<description>Indicates the actual consumption of the House.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="gridFeedIn">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Grid Feed In</label>
|
||||
<description>Indicates the actual current feeding to the Grid. Otherwise 0.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="gridConsumption">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Grid Consumption</label>
|
||||
<description>Indicates the actual current consumption from the the Grid. Otherwise 0.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="solarProduction">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Solar Production</label>
|
||||
<description>Indicates the actual production of the Solar system.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="flowConsumptionBatteryState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flow Battery Towards Consumption State</label>
|
||||
<description>Indicates if there is a current flow from battery towards consumption.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="flowConsumptionGridState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flow Grid Towards Consumption State</label>
|
||||
<description>Indicates if there is a current flow from grid towards consumption.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="flowConsumptionProductionState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flow Production Towards Consumption State</label>
|
||||
<description>Indicates if there is a current flow from solar production towards consumption.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="flowGridBatteryState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flow Grid Towards Battery State</label>
|
||||
<description>Indicates if there is a current flow from grid towards battery.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="flowProductionBatteryState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flow Production Towards Battery State</label>
|
||||
<description>Indicates if there is a current flow from production towards battery.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="flowProductionGridState">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Flow Production Towards Grid State</label>
|
||||
<description>Indicates if there is a current flow from production towards grid.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
@ -322,6 +322,7 @@
|
||||
<module>org.openhab.binding.solarwatt</module>
|
||||
<module>org.openhab.binding.somfymylink</module>
|
||||
<module>org.openhab.binding.somfytahoma</module>
|
||||
<module>org.openhab.binding.sonnen</module>
|
||||
<module>org.openhab.binding.sonos</module>
|
||||
<module>org.openhab.binding.sonyaudio</module>
|
||||
<module>org.openhab.binding.sonyprojector</module>
|
||||
|
Loading…
Reference in New Issue
Block a user