added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.smaenergymeter/.classpath
Normal file
32
bundles/org.openhab.binding.smaenergymeter/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.smaenergymeter/.project
Normal file
23
bundles/org.openhab.binding.smaenergymeter/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.smaenergymeter</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.smaenergymeter/NOTICE
Normal file
13
bundles/org.openhab.binding.smaenergymeter/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
|
||||
46
bundles/org.openhab.binding.smaenergymeter/README.md
Normal file
46
bundles/org.openhab.binding.smaenergymeter/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# SMA Energy Meter Binding
|
||||
|
||||
This Binding is used to display the measured values of a SMA Energy Meter device.
|
||||
It shows purchased and grid feed-in power and energy.
|
||||
|
||||
## Supported Things
|
||||
|
||||
This Binding supports SMA Energy Meter devices.
|
||||
|
||||
## Discovery
|
||||
|
||||
The Energy Meter is discovered by receiving data on the default multicast IP address.
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
No binding configuration required.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
Usually no manual configuration is required, as the multicast IP address and the port remain on their factory set values.
|
||||
Optionally, a refresh interval (in seconds) can be defined.
|
||||
|
||||
## Channels
|
||||
|
||||
| Channel | Description |
|
||||
|-------------|------------------------|
|
||||
| powerIn | Purchased power |
|
||||
| powerInL1 | Purchased power L3 |
|
||||
| powerInL2 | Purchased power L2 |
|
||||
| powerInL3 | Purchased power L3 |
|
||||
| powerOut | Grid feed-in power |
|
||||
| powerOutL1 | Grid feed-in power L1 |
|
||||
| powerOutL2 | Grid feed-in power L2 |
|
||||
| powerOutL3 | Grid feed-in power L3 |
|
||||
| energyIn | Purchased energy |
|
||||
| energyInL1 | Purchased energy L1 |
|
||||
| energyInL2 | Purchased energy L2 |
|
||||
| energyInL3 | Purchased energy L3 |
|
||||
| energyOut | Grid feed-in energy |
|
||||
| energyOutL1 | Grid feed-in energy L1 |
|
||||
| energyOutL2 | Grid feed-in energy L2 |
|
||||
| energyOutL3 | Grid feed-in energy L3 |
|
||||
|
||||
## Full example
|
||||
|
||||
N/A
|
||||
17
bundles/org.openhab.binding.smaenergymeter/pom.xml
Normal file
17
bundles/org.openhab.binding.smaenergymeter/pom.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.smaenergymeter</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: SMA EnergyMeter Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.smaenergymeter-${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-smaenergymeter" description="SMA Energy Monitor Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.smaenergymeter/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link SMAEnergyMeterBinding} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SMAEnergyMeterBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "smaenergymeter";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_ENERGY_METER = new ThingTypeUID(BINDING_ID, "energymeter");
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_ENERGY_METER);
|
||||
|
||||
// List of all Channel IDs
|
||||
public static final String CHANNEL_POWER_IN = "powerIn";
|
||||
public static final String CHANNEL_POWER_OUT = "powerOut";
|
||||
public static final String CHANNEL_ENERGY_IN = "energyIn";
|
||||
public static final String CHANNEL_ENERGY_OUT = "energyOut";
|
||||
public static final String CHANNEL_POWER_IN_L1 = "powerInL1";
|
||||
public static final String CHANNEL_POWER_OUT_L1 = "powerOutL1";
|
||||
public static final String CHANNEL_ENERGY_IN_L1 = "energyInL1";
|
||||
public static final String CHANNEL_ENERGY_OUT_L1 = "energyOutL1";
|
||||
public static final String CHANNEL_POWER_IN_L2 = "powerInL2";
|
||||
public static final String CHANNEL_POWER_OUT_L2 = "powerOutL2";
|
||||
public static final String CHANNEL_ENERGY_IN_L2 = "energyInL2";
|
||||
public static final String CHANNEL_ENERGY_OUT_L2 = "energyOutL2";
|
||||
public static final String CHANNEL_POWER_IN_L3 = "powerInL3";
|
||||
public static final String CHANNEL_POWER_OUT_L3 = "powerOutL3";
|
||||
public static final String CHANNEL_ENERGY_IN_L3 = "energyInL3";
|
||||
public static final String CHANNEL_ENERGY_OUT_L3 = "energyOutL3";
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal;
|
||||
|
||||
import static org.openhab.binding.smaenergymeter.internal.SMAEnergyMeterBindingConstants.*;
|
||||
|
||||
import org.openhab.binding.smaenergymeter.internal.handler.SMAEnergyMeterHandler;
|
||||
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 SMAEnergyMeterHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.smaenergymeter")
|
||||
public class SMAEnergyMeterHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(THING_TYPE_ENERGY_METER)) {
|
||||
return new SMAEnergyMeterHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal.configuration;
|
||||
|
||||
/**
|
||||
* The {@link EnergyMeterConfig} class holds the configuration properties of the binding.
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
public class EnergyMeterConfig {
|
||||
|
||||
private String mcastGroup;
|
||||
private Integer port;
|
||||
private Integer pollingPeriod;
|
||||
|
||||
public String getMcastGroup() {
|
||||
return mcastGroup;
|
||||
}
|
||||
|
||||
public void setMcastGroup(String mcastGroup) {
|
||||
this.mcastGroup = mcastGroup;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Integer getPollingPeriod() {
|
||||
return pollingPeriod;
|
||||
}
|
||||
|
||||
public void setPollingPeriod(Integer pollingPeriod) {
|
||||
this.pollingPeriod = pollingPeriod;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.smaenergymeter.internal.SMAEnergyMeterBindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.smaenergymeter.internal.handler.EnergyMeter;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SMAEnergyMeterDiscoveryService} class implements a service
|
||||
* for discovering the SMA Energy Meter.
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.smaenergymeter")
|
||||
public class SMAEnergyMeterDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SMAEnergyMeterDiscoveryService.class);
|
||||
|
||||
public SMAEnergyMeterDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, 15, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
logger.debug("Start SMAEnergyMeter background discovery");
|
||||
scheduler.schedule(this::discover, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
logger.debug("Start SMAEnergyMeter scan");
|
||||
discover();
|
||||
}
|
||||
|
||||
private synchronized void discover() {
|
||||
logger.debug("Try to discover a SMA Energy Meter device");
|
||||
|
||||
EnergyMeter energyMeter = new EnergyMeter(EnergyMeter.DEFAULT_MCAST_GRP, EnergyMeter.DEFAULT_MCAST_PORT);
|
||||
try {
|
||||
energyMeter.update();
|
||||
} catch (IOException e) {
|
||||
logger.debug("No SMA Energy Meter found.");
|
||||
logger.debug("Diagnostic: ", e);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Adding a new SMA Engergy Meter with S/N '{}' to inbox", energyMeter.getSerialNumber());
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(Thing.PROPERTY_VENDOR, "SMA");
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, energyMeter.getSerialNumber());
|
||||
ThingUID uid = new ThingUID(THING_TYPE_ENERGY_METER, energyMeter.getSerialNumber());
|
||||
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withLabel("SMA Energy Meter").build();
|
||||
thingDiscovered(result);
|
||||
|
||||
logger.debug("Thing discovered '{}'", result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* The {@link EnergyMeter} class is responsible for communication with the SMA device
|
||||
* and extracting the data fields out of the received telegrams.
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
public class EnergyMeter {
|
||||
|
||||
private String multicastGroup;
|
||||
private int port;
|
||||
|
||||
private String serialNumber;
|
||||
private Date lastUpdate;
|
||||
|
||||
private final FieldDTO powerIn;
|
||||
private final FieldDTO energyIn;
|
||||
private final FieldDTO powerOut;
|
||||
private final FieldDTO energyOut;
|
||||
private final FieldDTO powerInL1;
|
||||
private final FieldDTO energyInL1;
|
||||
private final FieldDTO powerOutL1;
|
||||
private final FieldDTO energyOutL1;
|
||||
private final FieldDTO powerInL2;
|
||||
private final FieldDTO energyInL2;
|
||||
private final FieldDTO powerOutL2;
|
||||
private final FieldDTO energyOutL2;
|
||||
private final FieldDTO powerInL3;
|
||||
private final FieldDTO energyInL3;
|
||||
private final FieldDTO powerOutL3;
|
||||
private final FieldDTO energyOutL3;
|
||||
|
||||
public static final String DEFAULT_MCAST_GRP = "239.12.255.254";
|
||||
public static final int DEFAULT_MCAST_PORT = 9522;
|
||||
|
||||
public EnergyMeter(String multicastGroup, int port) {
|
||||
this.multicastGroup = multicastGroup;
|
||||
this.port = port;
|
||||
|
||||
powerIn = new FieldDTO(0x20, 4, 10);
|
||||
energyIn = new FieldDTO(0x28, 8, 3600000);
|
||||
powerOut = new FieldDTO(0x34, 4, 10);
|
||||
energyOut = new FieldDTO(0x3C, 8, 3600000);
|
||||
|
||||
powerInL1 = new FieldDTO(0xA8, 4, 10);
|
||||
energyInL1 = new FieldDTO(0xB0, 8, 3600000); // +8
|
||||
powerOutL1 = new FieldDTO(0xBC, 4, 10); // + C
|
||||
energyOutL1 = new FieldDTO(0xC4, 8, 3600000); // +8
|
||||
|
||||
powerInL2 = new FieldDTO(0x138, 4, 10);
|
||||
energyInL2 = new FieldDTO(0x140, 8, 3600000); // +8
|
||||
powerOutL2 = new FieldDTO(0x14C, 4, 10); // + C
|
||||
energyOutL2 = new FieldDTO(0x154, 8, 3600000); // +8
|
||||
|
||||
powerInL3 = new FieldDTO(0x1C8, 4, 10);
|
||||
energyInL3 = new FieldDTO(0x1D0, 8, 3600000); // +8
|
||||
powerOutL3 = new FieldDTO(0x1DC, 4, 10); // + C
|
||||
energyOutL3 = new FieldDTO(0x1E4, 8, 3600000); // +8
|
||||
}
|
||||
|
||||
public void update() throws IOException {
|
||||
byte[] bytes = new byte[608];
|
||||
try (MulticastSocket socket = new MulticastSocket(port)) {
|
||||
socket.setSoTimeout(5000);
|
||||
InetAddress address = InetAddress.getByName(multicastGroup);
|
||||
socket.joinGroup(address);
|
||||
|
||||
DatagramPacket msgPacket = new DatagramPacket(bytes, bytes.length);
|
||||
socket.receive(msgPacket);
|
||||
|
||||
String sma = new String(Arrays.copyOfRange(bytes, 0x00, 0x03));
|
||||
if (!sma.equals("SMA")) {
|
||||
throw new IOException("Not a SMA telegram." + sma);
|
||||
}
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.wrap(Arrays.copyOfRange(bytes, 0x14, 0x18));
|
||||
serialNumber = String.valueOf(buffer.getInt());
|
||||
|
||||
powerIn.updateValue(bytes);
|
||||
energyIn.updateValue(bytes);
|
||||
powerOut.updateValue(bytes);
|
||||
energyOut.updateValue(bytes);
|
||||
|
||||
powerInL1.updateValue(bytes);
|
||||
energyInL1.updateValue(bytes);
|
||||
powerOutL1.updateValue(bytes);
|
||||
energyOutL1.updateValue(bytes);
|
||||
|
||||
powerInL2.updateValue(bytes);
|
||||
energyInL2.updateValue(bytes);
|
||||
powerOutL2.updateValue(bytes);
|
||||
energyOutL2.updateValue(bytes);
|
||||
|
||||
powerInL3.updateValue(bytes);
|
||||
energyInL3.updateValue(bytes);
|
||||
powerOutL3.updateValue(bytes);
|
||||
energyOutL3.updateValue(bytes);
|
||||
|
||||
lastUpdate = new Date(System.currentTimeMillis());
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public Date getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
|
||||
public DecimalType getPowerIn() {
|
||||
return new DecimalType(powerIn.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerOut() {
|
||||
return new DecimalType(powerOut.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyIn() {
|
||||
return new DecimalType(energyIn.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyOut() {
|
||||
return new DecimalType(energyOut.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerInL1() {
|
||||
return new DecimalType(powerInL1.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerOutL1() {
|
||||
return new DecimalType(powerOutL1.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyInL1() {
|
||||
return new DecimalType(energyInL1.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyOutL1() {
|
||||
return new DecimalType(energyOutL1.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerInL2() {
|
||||
return new DecimalType(powerInL2.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerOutL2() {
|
||||
return new DecimalType(powerOutL2.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyInL2() {
|
||||
return new DecimalType(energyInL2.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyOutL2() {
|
||||
return new DecimalType(energyOutL2.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerInL3() {
|
||||
return new DecimalType(powerInL3.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getPowerOutL3() {
|
||||
return new DecimalType(powerOutL3.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyInL3() {
|
||||
return new DecimalType(energyInL3.getValue());
|
||||
}
|
||||
|
||||
public DecimalType getEnergyOutL3() {
|
||||
return new DecimalType(energyOutL3.getValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal.handler;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* The {@link FieldDTO} class holds the data for a single field (i.e. the power purchased).
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
public class FieldDTO {
|
||||
|
||||
private final int address;
|
||||
private final int length;
|
||||
private final int divisor;
|
||||
private float value;
|
||||
|
||||
public FieldDTO(int address, int length, int divisor) {
|
||||
this.address = address;
|
||||
if ((length != 4) && (length != 8)) {
|
||||
throw new IllegalArgumentException("length should be 4 or 8 bytes");
|
||||
}
|
||||
this.length = length;
|
||||
this.divisor = divisor;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void updateValue(byte[] bytes) {
|
||||
if (length == 4) {
|
||||
value = (float) bytesToUInt16(Arrays.copyOfRange(bytes, address, address + 4)) / divisor;
|
||||
} else {
|
||||
value = (float) bytesToUInt32(Arrays.copyOfRange(bytes, address, address + 8)) / divisor;
|
||||
}
|
||||
}
|
||||
|
||||
private int bytesToUInt16(byte[] bytes) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
return buffer.getInt();
|
||||
}
|
||||
|
||||
private long bytesToUInt32(byte[] bytes) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
return buffer.getLong();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.smaenergymeter.internal.handler;
|
||||
|
||||
import static org.openhab.binding.smaenergymeter.internal.SMAEnergyMeterBindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.smaenergymeter.internal.configuration.EnergyMeterConfig;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SMAEnergyMeterHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Osman Basha - Initial contribution
|
||||
*/
|
||||
public class SMAEnergyMeterHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SMAEnergyMeterHandler.class);
|
||||
private EnergyMeter energyMeter;
|
||||
private ScheduledFuture<?> pollingJob;
|
||||
|
||||
public SMAEnergyMeterHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command == RefreshType.REFRESH) {
|
||||
logger.debug("Refreshing {}", channelUID);
|
||||
updateData();
|
||||
} else {
|
||||
logger.warn("This binding is a read-only binding and cannot handle commands");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing SMAEnergyMeter handler '{}'", getThing().getUID());
|
||||
|
||||
EnergyMeterConfig config = getConfigAs(EnergyMeterConfig.class);
|
||||
|
||||
int port = (config.getPort() == null) ? EnergyMeter.DEFAULT_MCAST_PORT : config.getPort();
|
||||
energyMeter = new EnergyMeter(config.getMcastGroup(), port);
|
||||
try {
|
||||
energyMeter.update();
|
||||
|
||||
updateProperty(Thing.PROPERTY_VENDOR, "SMA");
|
||||
updateProperty(Thing.PROPERTY_SERIAL_NUMBER, energyMeter.getSerialNumber());
|
||||
logger.debug("Found a SMA Energy Meter with S/N '{}'", energyMeter.getSerialNumber());
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
int pollingPeriod = (config.getPollingPeriod() == null) ? 30 : config.getPollingPeriod();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::updateData, 0, pollingPeriod, TimeUnit.SECONDS);
|
||||
logger.debug("Polling job scheduled to run every {} sec. for '{}'", pollingPeriod, getThing().getUID());
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Disposing SMAEnergyMeter handler '{}'", getThing().getUID());
|
||||
|
||||
if (pollingJob != null) {
|
||||
pollingJob.cancel(true);
|
||||
pollingJob = null;
|
||||
}
|
||||
energyMeter = null;
|
||||
}
|
||||
|
||||
private synchronized void updateData() {
|
||||
logger.debug("Update SMAEnergyMeter data '{}'", getThing().getUID());
|
||||
|
||||
try {
|
||||
energyMeter.update();
|
||||
|
||||
updateState(CHANNEL_POWER_IN, energyMeter.getPowerIn());
|
||||
updateState(CHANNEL_POWER_OUT, energyMeter.getPowerOut());
|
||||
updateState(CHANNEL_ENERGY_IN, energyMeter.getEnergyIn());
|
||||
updateState(CHANNEL_ENERGY_OUT, energyMeter.getEnergyOut());
|
||||
|
||||
updateState(CHANNEL_POWER_IN_L1, energyMeter.getPowerInL1());
|
||||
updateState(CHANNEL_POWER_OUT_L1, energyMeter.getPowerOutL1());
|
||||
updateState(CHANNEL_ENERGY_IN_L1, energyMeter.getEnergyInL1());
|
||||
updateState(CHANNEL_ENERGY_OUT_L1, energyMeter.getEnergyOutL1());
|
||||
|
||||
updateState(CHANNEL_POWER_IN_L2, energyMeter.getPowerInL2());
|
||||
updateState(CHANNEL_POWER_OUT_L2, energyMeter.getPowerOutL2());
|
||||
updateState(CHANNEL_ENERGY_IN_L2, energyMeter.getEnergyInL2());
|
||||
updateState(CHANNEL_ENERGY_OUT_L2, energyMeter.getEnergyOutL2());
|
||||
|
||||
updateState(CHANNEL_POWER_IN_L3, energyMeter.getPowerInL3());
|
||||
updateState(CHANNEL_POWER_OUT_L3, energyMeter.getPowerOutL3());
|
||||
updateState(CHANNEL_ENERGY_IN_L3, energyMeter.getEnergyInL3());
|
||||
updateState(CHANNEL_ENERGY_OUT_L3, energyMeter.getEnergyOutL3());
|
||||
|
||||
if (getThing().getStatus().equals(ThingStatus.OFFLINE)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="smaenergymeter" 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>SMA Energy Meter Binding</name>
|
||||
<description>Binding for a SMA Energy Meter.</description>
|
||||
<author>Osman Basha</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,18 @@
|
||||
# binding
|
||||
binding.smaenergymeter.name = SMA Energy Meter Binding
|
||||
binding.smaenergymeter.description = Binding für einen SMA Energy Meter.
|
||||
|
||||
# thing types
|
||||
thing-type.smaenergymeter.energymeter.label = SMA Energy Meter
|
||||
thing-type.config.smaenergymeter.energymeter.mcastGroup.label = Multicast-Gruppe
|
||||
thing-type.config.smaenergymeter.energymeter.mcastGroup.description = IP-Adresse der Multicast-Gruppe
|
||||
thing-type.config.smaenergymeter.energymeter.port.label = Port
|
||||
thing-type.config.smaenergymeter.energymeter.port.description = Portnummer der Multicast-Gruppe
|
||||
thing-type.config.smaenergymeter.energymeter.pollingPeriod.label = Abfrageintervall
|
||||
thing-type.config.smaenergymeter.energymeter.pollingPeriod.description = Daten-Abfrageintervall in Sek.
|
||||
|
||||
# channel types
|
||||
channel-type.smaenergymeter.powerInType.label = Bezogene Leistung
|
||||
channel-type.smaenergymeter.powerOutType.label = Eingespeise Leistung
|
||||
channel-type.smaenergymeter.energyInType.label = Bezogene Energie
|
||||
channel-type.smaenergymeter.energyOutType.label = Eingespeiste Energie
|
||||
@@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="smaenergymeter"
|
||||
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">
|
||||
|
||||
<thing-type id="energymeter">
|
||||
<label>SMA Energy Meter</label>
|
||||
|
||||
<channels>
|
||||
<channel id="powerIn" typeId="powerInType"/>
|
||||
<channel id="powerOut" typeId="powerOutType"/>
|
||||
<channel id="energyIn" typeId="energyInType"/>
|
||||
<channel id="energyOut" typeId="energyOutType"/>
|
||||
<channel id="powerInL1" typeId="powerInTypeL1"/>
|
||||
<channel id="powerOutL1" typeId="powerOutTypeL1"/>
|
||||
<channel id="energyInL1" typeId="energyInTypeL1"/>
|
||||
<channel id="energyOutL1" typeId="energyOutTypeL1"/>
|
||||
<channel id="powerInL2" typeId="powerInTypeL2"/>
|
||||
<channel id="powerOutL2" typeId="powerOutTypeL2"/>
|
||||
<channel id="energyInL2" typeId="energyInTypeL2"/>
|
||||
<channel id="energyOutL2" typeId="energyOutTypeL2"/>
|
||||
<channel id="powerInL3" typeId="powerInTypeL3"/>
|
||||
<channel id="powerOutL3" typeId="powerOutTypeL3"/>
|
||||
<channel id="energyInL3" typeId="energyInTypeL3"/>
|
||||
<channel id="energyOutL3" typeId="energyOutTypeL3"/>
|
||||
</channels>
|
||||
|
||||
<properties>
|
||||
<property name="vendor">Vendor</property>
|
||||
<property name="serialNumber">Serial Number</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="mcastGroup" type="text" required="true">
|
||||
<label>Multicast Group</label>
|
||||
<description>IP address of the multicast group</description>
|
||||
<default>239.12.255.254</default>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" required="false" min="1024" max="49151">
|
||||
<label>Port</label>
|
||||
<description>Port of the multicast group</description>
|
||||
<default>9522</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="pollingPeriod" type="integer" required="false">
|
||||
<label>Polling Period</label>
|
||||
<description>Polling period for refreshing the data in s</description>
|
||||
<default>30</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="powerInType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Power</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerOutType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Power</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyInType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Energy</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyOutType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Energy</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerInTypeL1">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Power L1</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerOutTypeL1">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Power L1</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyInTypeL1">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Energy L1</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyOutTypeL1">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Energy L1</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerInTypeL2">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Power L2</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerOutTypeL2">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Power L2</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyInTypeL2">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Energy L2</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyOutTypeL2">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Energy L2</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerInTypeL3">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Power L3</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="powerOutTypeL3">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Power L3</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f W" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyInTypeL3">
|
||||
<item-type>Number</item-type>
|
||||
<label>Purchased Energy L3</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="energyOutTypeL3">
|
||||
<item-type>Number</item-type>
|
||||
<label>Grid Feed-in Energy L3</label>
|
||||
<category>Energy</category>
|
||||
<state pattern="%.2f kWh" readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user