Skip to content

Commit

Permalink
[modbus][sunspec] Initial contribution (openhab#6331)
Browse files Browse the repository at this point in the history
* [sunspec] Modbus: SunSpec bundle basic version

SunSpec is an open standard for solar inverters and other related devices to share data about their internal state. The standard is implemented by several vendors like ABB, Fronius, SMA, Schneider Electric, Solaredge, etc.

The goal of this work is to add user friendly support of these devices to openHAB.

The standard is built on the Modbus protocol, so this work is heavily based on the Modbus binding. Also the Bluetooth binding and several of it's solutions were taken as an example how to extend an already existing binding with a new bundle.

Related issue: openhab#3216

This is a stripped down version of a SunSpec bundle aimed to ease reviewing.

Original PW with all the features can be found here:
  https://github.com/openhab/openhab2-addons/pull/4220

This version contains only a limited support for single phase inverters, but no auto discovery or any other fancy features are included.

Other changes from my original PR:
 - migrated to the new build system
 - using NonNull values wherever possible
 - modell classes were moved to a dto package and highly simplified
 - other minor code changes

Signed-off-by: Nagy Attila Gabor <mrbig@sneaker.hu>
  • Loading branch information
mrbig authored and J-N-K committed Jul 14, 2020
1 parent 9d11656 commit 9192c79
Show file tree
Hide file tree
Showing 24 changed files with 1,891 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
/bundles/org.openhab.binding.sonyprojector/ @lolodomo
/bundles/org.openhab.binding.spotify/ @Hilbrand
/bundles/org.openhab.binding.squeezebox/ @digitaldan @mhilbush
/bundles/org.openhab.binding.modbus.sunspec/ @mrbig
/bundles/org.openhab.binding.synopanalyzer/ @clinique
/bundles/org.openhab.binding.systeminfo/ @svilenvul
/bundles/org.openhab.binding.tado/ @dfrommi
Expand Down
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,11 @@
<artifactId>org.openhab.binding.squeezebox</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.modbus.sunspec</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.synopanalyzer</artifactId>
Expand Down
32 changes: 32 additions & 0 deletions bundles/org.openhab.binding.modbus.sunspec/.classpath
Original file line number Diff line number Diff line change
@@ -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-1.8">
<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 changes: 23 additions & 0 deletions bundles/org.openhab.binding.modbus.sunspec/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.modbus.sunspec</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 changes: 13 additions & 0 deletions bundles/org.openhab.binding.modbus.sunspec/NOTICE
Original file line number Diff line number Diff line change
@@ -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/openhab2-addons
297 changes: 297 additions & 0 deletions bundles/org.openhab.binding.modbus.sunspec/README.md

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions bundles/org.openhab.binding.modbus.sunspec/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?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>2.5.4-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.binding.modbus.sunspec</artifactId>

<name>openHAB Add-ons :: Bundles :: SunSpec Bundle</name>

<dependencies>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.modbus</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.io.transport.modbus</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.modbus.sunspec-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>file:${basedirRoot}/bundles/org.openhab.binding.modbus/target/feature/feature.xml</repository>

<feature name="openhab-binding-modbus-sunspec" description="SunSpec Bundle" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-binding-modbus</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.sunspec/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -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.modbus.sunspec.internal;

/**
* Possible values for an inverter's status field
*
* @author Nagy Attila Gábor - Initial contribution
*/
public enum InverterStatus {

OFF(1),
SLEEP(2),
ON(4),
UNKNOWN(-1);

private final int code;

InverterStatus(int code) {
this.code = code;
}

public int code() {
return this.code;
}

public static InverterStatus getByCode(int code) {
switch (code) {
case 1:
return InverterStatus.OFF;
case 2:
return InverterStatus.SLEEP;
case 4:
return InverterStatus.ON;
default:
return InverterStatus.UNKNOWN;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* 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.modbus.sunspec.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link SunSpecConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Nagy Attila Gábor - Initial contribution
*/
@NonNullByDefault
public class SunSpecConfiguration {

/**
* Refresh interval in seconds
*/
public long refresh = 60;

public int maxTries = 3;// backwards compatibility and tests

/**
* Base address of the block to parse. Only used at manual setup
*/
public int address;

/**
* Length of the block to parse. Only used at manual setup
*/
public int length;

/**
* Gets refresh period in milliseconds
*/
public long getRefreshMillis() {
return refresh * 1000;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* 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.modbus.sunspec.internal;

import java.util.Collections;
import java.util.Map;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.openhab.binding.modbus.ModbusBindingConstants;

/**
* The {@link SunSpecConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Nagy Attila Gábor - Initial contribution
*/
@NonNullByDefault
public class SunSpecConstants {

private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_INVERTER_SINGLE_PHASE = new ThingTypeUID(BINDING_ID,
"inverter-single-phase");

// Block types
public static final int COMMON_BLOCK = 1;
public static final int INVERTER_SINGLE_PHASE = 101;

/**
* Map of the supported thing type uids, with their block type id
*/
public static final Map<Integer, ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.singletonMap(INVERTER_SINGLE_PHASE, THING_TYPE_INVERTER_SINGLE_PHASE);

// properties
public static final String PROPERTY_VENDOR = "vendor";
public static final String PROPERTY_MODEL = "model";
public static final String PROPERTY_VERSION = "version";
public static final String PROPERTY_PHASE_COUNT = "phaseCount";
public static final String PROPERTY_SERIAL_NUMBER = "serialNumber";
public static final String PROPERTY_BLOCK_ADDRESS = "blockAddress";
public static final String PROPERTY_BLOCK_LENGTH = "blockLength";
public static final String PROPERTY_UNIQUE_ADDRESS = "uniqueAddress";

// Channel group ids
public static final String GROUP_DEVICE_INFO = "deviceInformation";
public static final String GROUP_AC_GENERAL = "acGeneral";

// List of all Channel ids in device information group
public static final String CHANNEL_PHASE_CONFIGURATION = "phase-configuration";
public static final String CHANNEL_CABINET_TEMPERATURE = "cabinet-temperature";
public static final String CHANNEL_HEATSINK_TEMPERATURE = "heatsink-temperature";
public static final String CHANNEL_TRANSFORMER_TEMPERATURE = "transformer-temperature";
public static final String CHANNEL_OTHER_TEMPERATURE = "other-temperature";
public static final String CHANNEL_STATUS = "status";

// List of channel ids in AC general group for inverter
public static final String CHANNEL_AC_TOTAL_CURRENT = "ac-total-current";
public static final String CHANNEL_AC_POWER = "ac-power";
public static final String CHANNEL_AC_FREQUENCY = "ac-frequency";
public static final String CHANNEL_AC_APPARENT_POWER = "ac-apparent-power";
public static final String CHANNEL_AC_REACTIVE_POWER = "ac-reactive-power";
public static final String CHANNEL_AC_POWER_FACTOR = "ac-power-factor";
public static final String CHANNEL_AC_LIFETIME_ENERGY = "ac-lifetime-energy";

// Expected SunSpec ID This is a magic constant to distinguish SunSpec compatible
// devices from other modbus devices
public static final long SUNSPEC_ID = 0x53756e53;
// Size of SunSpect ID in words
public static final int SUNSPEC_ID_SIZE = 2;
// Size of any block header in words
public static final int MODEL_HEADER_SIZE = 2;
}
Loading

0 comments on commit 9192c79

Please sign in to comment.