added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,60 @@
<?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="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path=".apt_generated">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path=".apt_generated_tests">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.modbus.studer</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>

View 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

View File

@@ -0,0 +1,142 @@
# Studer
This extension adds support for the Studer protocol.
Studer Innotec, founded in 1987 by Roland Studer, is an ISO certified company that develops and manufactures inverters, inverter/chargers and MPPT solar charge controllers to communicate over the Modbus protocol entirely in Switzerland
For a list of certified products see this page: https://www.studer-innotec.com/
## Supported Things
This bundle adds the following thing type to the Modbus binding.
Note, that the things will show up under the Modbus binding.
| Thing Type IDs | Description | Picture |
|----------------|----------------------------------------------------------------------------------------------------------------------|-------------------------------------|
| bsp | For BSP that offer a highly precise measuring for Xtender, VarioTrack and VarioString systems | ![BSP](doc/bsp.png) |
| xtender | For the Xtender models for system capacities from 0.5kVA to 72kVA that allow for the optimal use of available energy | ![Xtender](doc/xtender.png) |
| variotrack | For the VarioTrack models of MPPT solar charge controllers for systems with solar PV capacity from 1 - 75kWp | ![VarioTrack](doc/variotrack.png) |
| variostring | For the VarioString models of MPPT solar charge controllers for systems with solar PV capacity from 4 | ![VarioString](doc/variostring.png) |
## Thing Configuration
You need first to set up a Serial Modbus bridge according to the Modbus documentation.
Things in this extension will use the selected bridge to connect to the device.
For defining a thing textually, you have to find out the start address of the model block and the length of it.
While the length is usually fixed, the address is not.
Please refer to your device's vendor documentation how model blocks are laid for your equipment.
The following parameters are valid for all thing types:
| Parameter | Type | Required | Default if omitted | Description |
|-----------|---------|----------|-------------------------|----------------------------------------------------------------------------|
| address | integer | yes | `first slave of device` | Address of slave |
| refresh | integer | yes | 5 | Poll interval in seconds. Increase this if you encounter connection errors |
## Channels
The following Channels, and their associated channel types are shown below divided by device.
#### BSP
All channels read for a BSP device
| Channel | Type | Description |
| ------------------ | ------------------------ | --------------------- |
| power | Number:Power | Power |
| batteryVoltage | Number:ElectricPotential | Battery voltage |
| batteryCurrent | Number:ElectricCurrent | Battery current |
| stateOfCharge | Number:Dimensionless | State of Charge |
| batteryTemperature | Number:Temperature | Battery temperature |
#### Xtender
All channels read for a Xtender device
| Channel | Type | Description |
| ----------------- | ------------------------ | ----------------------- |
| inputVoltage | Number:ElectricPotential | Input voltage |
| inputCurrent | Number:ElectricCurrent | Input current |
| inputActivePower | Number:Power | Input active power |
| inputFrequency | Number:Frequency | Input frequency |
| outputVoltage | Number:ElectricPotential | Output voltage |
| outputCurrent | Number:ElectricCurrent | Output current |
| outputActivePower | Number:Power | Output active power |
| outputFrequency | Number:Frequency | Output frequency |
| operatingState | String | Operating state |
| stateInverter | String | State of the inverter |
#### VarioTrack
All channels read for a VarioTrack device
| Channel | Type | Description |
| -------------------- | ------------------------ | ----------------------------------------- |
| modelVarioTrack | String | Model of VarioTrack |
| voltagePVGenerator | Number:ElectricPotential | Voltage of the PV generator |
| powerPVGenerator | Number:Power | Power of the PV generator |
| productionCurrentDay | Number:Energy | Production in (kWh) for the current day |
| batteryVoltage | Number:ElectricPotential | Battery voltage |
| batteryCurrent | Number:ElectricCurrent | Battery current |
| operatingMode | String | Operating mode |
| stateVarioTrack | String | State of the VarioTrack |
#### VarioString
All channels read for a VarioString device
| Channel | Type | Description |
| ----------------------- | ------------------------ | --------------------------------------------- |
| PVVoltage | Number:ElectricPotential | PV voltage |
| PVCurrent | Number:ElectricCurrent | PV current |
| PVPower | Number:Power | PV power |
| ProductionPVCurrentDay | Number:Energy | Production PV in (kWh) for the current day |
| PV1Voltage | Number:ElectricPotential | PV1 voltage |
| PV1Current | Number:ElectricCurrent | PV1 current |
| PV1Power | Number:Power | PV1 power |
| ProductionPV1CurrentDay | Number:Energy | Production PV1 in (kWh) for the current day |
| PV2Voltage | Number:ElectricPotential | PV2 voltage |
| PV2Current | Number:ElectricCurrent | PV2 current |
| PV2Power | Number:Power | PV2 power |
| ProductionPV2CurrentDay | Number:Energy | Production PV2 in (kWh) for the current day |
| batteryVoltage | Number:ElectricPotential | Battery voltage |
| batteryCurrent | Number:ElectricCurrent | Battery current |
| PVMode | String | PV operating mode |
| PV1Mode | String | PV1 operating mode |
| PV2Mode | String | PV2 operating mode |
| stateVarioString | String | State of the VarioString |
## Example
### Thing Configuration
```
Bridge modbus:serial:bridge [port="/dev/ttyUSB0",baud=9600,dataBits=8,parity="even",stopBits="1.0",encoding="rtu"]
Thing modbus:xtender:bridge:xtenderdevice "Xtender" (modbus:serial:modbusbridge) [ slaveAddress=10, refresh=5 ]
```
Note: Make sure that refresh and slave address are numerical, without quotes.
### Item Configuration
```
Number XtenderStuderThing_InputVoltage "Input Voltage [%.2f %unit%]"
{channel="modbus:xtender:bridge:xtenderdevice:inputVoltage"}
Number XtenderStuderThing_InputCurrent "Input Current [%.2f %unit%]" {channel="modbus:xtender:bridge:xtenderdevice:inputCurrent"}
String XtenderStuderThing_StateInverter "State: [%s]" {channel="modbus:xtender:bridge:xtenderdevice:stateInverter"}
```
### Sitemap Configuration
```
Text item=XtenderStuderThing_InputVoltage
Text item=XtenderStuderThing_InputCurrent
Text item=XtenderStuderThing_StateInverter
Chart item=XtenderStuderThing_InputVoltage period=D refresh=600000
Chart item=XtenderStuderThing_InputCurrent period=D refresh=30000
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -0,0 +1,30 @@
<?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.modbus.studer</artifactId>
<name>openHAB Add-ons :: Bundles :: Studer Binding</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>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.modbus.studer-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-bindings-modbus-studer" description="Studer Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-modbus</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.studer/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,229 @@
/**
* 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.studer.internal;
import static org.openhab.core.library.unit.MetricPrefix.KILO;
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
import static org.openhab.core.library.unit.SmartHomeUnits.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.modbus.ModbusBindingConstants;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link StuderBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Giovanni Mirulla - Initial contribution
*/
@NonNullByDefault
public class StuderBindingConstants {
private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_BSP = new ThingTypeUID(BINDING_ID, "bsp");
public static final ThingTypeUID THING_TYPE_XTENDER = new ThingTypeUID(BINDING_ID, "xtender");
public static final ThingTypeUID THING_TYPE_VARIOTRACK = new ThingTypeUID(BINDING_ID, "variotrack");
public static final ThingTypeUID THING_TYPE_VARIOSTRING = new ThingTypeUID(BINDING_ID, "variostring");
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = new HashSet<>();
static {
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_BSP);
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_XTENDER);
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_VARIOTRACK);
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_VARIOSTRING);
}
// List of all Channel ids
public static final String CHANNEL_POWER = "power";
public static final String CHANNEL_BATTERY_VOLTAGE = "batteryVoltage";
public static final String CHANNEL_BATTERY_CURRENT = "batteryCurrent";
public static final String CHANNEL_STATE_OF_CHARGE = "stateOfCharge";
public static final String CHANNEL_BATTERY_TEMPERATURE = "batteryTemperature";
public static final String CHANNEL_INPUT_VOLTAGE = "inputVoltage";
public static final String CHANNEL_INPUT_CURRENT = "inputCurrent";
public static final String CHANNEL_INPUT_ACTIVE_POWER = "inputActivePower";
public static final String CHANNEL_INPUT_FREQUENCY = "inputFrequency";
public static final String CHANNEL_OUTPUT_VOLTAGE = "outputVoltage";
public static final String CHANNEL_OUTPUT_CURRENT = "outputCurrent";
public static final String CHANNEL_OUTPUT_ACTIVE_POWER = "outputActivePower";
public static final String CHANNEL_OUTPUT_FREQUENCY = "outputFrequency";
public static final String CHANNEL_OPERATING_STATE = "operatingState";
public static final String CHANNEL_STATE_INVERTER = "stateInverter";
public static final String CHANNEL_MODEL_VARIOTRACK = "modelVarioTrack";
public static final String CHANNEL_VOLTAGE_PV_GENERATOR = "voltagePVGenerator";
public static final String CHANNEL_POWER_PV_GENERATOR = "powerPVGenerator";
public static final String CHANNEL_PRODUCTION_CURRENT_DAY = "productionCurrentDay";
public static final String CHANNEL_OPERATING_MODE = "operatingMode";
public static final String CHANNEL_STATE_VARIOTRACK = "stateVarioTrack";
public static final String CHANNEL_PV_VOLTAGE = "PVVoltage";
public static final String CHANNEL_PV_CURRENT = "PVCurrent";
public static final String CHANNEL_PV_POWER = "PVPower";
public static final String CHANNEL_PRODUCTION_PV_CURRENT_DAY = "ProductionPVCurrentDay";
public static final String CHANNEL_PV_OPERATING_MODE = "PVMode";
public static final String CHANNEL_PV1_VOLTAGE = "PV1Voltage";
public static final String CHANNEL_PV1_CURRENT = "PV1Current";
public static final String CHANNEL_PV1_POWER = "PV1Power";
public static final String CHANNEL_PRODUCTION_PV1_CURRENT_DAY = "ProductionPV1CurrentDay";
public static final String CHANNEL_PV1_OPERATING_MODE = "PV1Mode";
public static final String CHANNEL_PV2_VOLTAGE = "PV2Voltage";
public static final String CHANNEL_PV2_CURRENT = "PV2Current";
public static final String CHANNEL_PV2_POWER = "PV2Power";
public static final String CHANNEL_PRODUCTION_PV2_CURRENT_DAY = "ProductionPV2CurrentDay";
public static final String CHANNEL_PV2_OPERATING_MODE = "PV2Mode";
public static final String CHANNEL_STATE_VARIOSTRING = "stateVarioString";
/**
* Map of the supported BSP channel with their registers
*/
public static final Map<Integer, String> CHANNELS_BSP = new HashMap<>();
static {
CHANNELS_BSP.put(6, CHANNEL_POWER);
CHANNELS_BSP.put(0, CHANNEL_BATTERY_VOLTAGE);
CHANNELS_BSP.put(2, CHANNEL_BATTERY_CURRENT);
CHANNELS_BSP.put(4, CHANNEL_STATE_OF_CHARGE);
CHANNELS_BSP.put(58, CHANNEL_BATTERY_TEMPERATURE);
}
/**
* Map of the supported BSP channel with their unit
*/
public static final Map<Integer, Unit<?>> UNIT_CHANNELS_BSP = new HashMap<>();
static {
UNIT_CHANNELS_BSP.put(6, WATT);
UNIT_CHANNELS_BSP.put(0, VOLT);
UNIT_CHANNELS_BSP.put(2, AMPERE);
UNIT_CHANNELS_BSP.put(4, PERCENT);
UNIT_CHANNELS_BSP.put(58, CELSIUS);
}
/**
* Map of the supported Xtender channel with their registers
*/
public static final Map<Integer, String> CHANNELS_XTENDER = new HashMap<>();
static {
CHANNELS_XTENDER.put(22, CHANNEL_INPUT_VOLTAGE);
CHANNELS_XTENDER.put(24, CHANNEL_INPUT_CURRENT);
CHANNELS_XTENDER.put(274, CHANNEL_INPUT_ACTIVE_POWER);
CHANNELS_XTENDER.put(168, CHANNEL_INPUT_FREQUENCY);
CHANNELS_XTENDER.put(42, CHANNEL_OUTPUT_VOLTAGE);
CHANNELS_XTENDER.put(44, CHANNEL_OUTPUT_CURRENT);
CHANNELS_XTENDER.put(272, CHANNEL_OUTPUT_ACTIVE_POWER);
CHANNELS_XTENDER.put(170, CHANNEL_OUTPUT_FREQUENCY);
CHANNELS_XTENDER.put(56, CHANNEL_OPERATING_STATE);
CHANNELS_XTENDER.put(98, CHANNEL_STATE_INVERTER);
}
/**
* Map of the supported Xtender channel with their unit
*/
public static final Map<Integer, Unit<?>> UNIT_CHANNELS_XTENDER = new HashMap<>();
static {
UNIT_CHANNELS_XTENDER.put(22, VOLT);
UNIT_CHANNELS_XTENDER.put(24, AMPERE);
UNIT_CHANNELS_XTENDER.put(274, KILO(WATT));
UNIT_CHANNELS_XTENDER.put(168, HERTZ);
UNIT_CHANNELS_XTENDER.put(42, VOLT);
UNIT_CHANNELS_XTENDER.put(44, AMPERE);
UNIT_CHANNELS_XTENDER.put(272, KILO(WATT));
UNIT_CHANNELS_XTENDER.put(170, HERTZ);
}
/**
* Map of the supported VarioTrack channel with their registers
*/
public static final Map<Integer, String> CHANNELS_VARIOTRACK = new HashMap<>();
static {
CHANNELS_VARIOTRACK.put(30, CHANNEL_MODEL_VARIOTRACK);
CHANNELS_VARIOTRACK.put(4, CHANNEL_VOLTAGE_PV_GENERATOR);
CHANNELS_VARIOTRACK.put(8, CHANNEL_POWER_PV_GENERATOR);
CHANNELS_VARIOTRACK.put(14, CHANNEL_PRODUCTION_CURRENT_DAY);
CHANNELS_VARIOTRACK.put(0, CHANNEL_BATTERY_VOLTAGE);
CHANNELS_VARIOTRACK.put(2, CHANNEL_BATTERY_CURRENT);
CHANNELS_VARIOTRACK.put(32, CHANNEL_OPERATING_MODE);
CHANNELS_VARIOTRACK.put(138, CHANNEL_STATE_VARIOTRACK);
}
/**
* Map of the supported VarioTrack channel with their unit
*/
public static final Map<Integer, Unit<?>> UNIT_CHANNELS_VARIOTRACK = new HashMap<>();
static {
UNIT_CHANNELS_VARIOTRACK.put(4, VOLT);
UNIT_CHANNELS_VARIOTRACK.put(8, KILO(WATT));
UNIT_CHANNELS_VARIOTRACK.put(14, KILOWATT_HOUR);
UNIT_CHANNELS_VARIOTRACK.put(0, VOLT);
UNIT_CHANNELS_VARIOTRACK.put(2, AMPERE);
}
/**
* Map of the supported VarioString channel with their registers
*/
public static final Map<Integer, String> CHANNELS_VARIOSTRING = new HashMap<>();
static {
CHANNELS_VARIOSTRING.put(0, CHANNEL_BATTERY_VOLTAGE);
CHANNELS_VARIOSTRING.put(2, CHANNEL_BATTERY_CURRENT);
CHANNELS_VARIOSTRING.put(8, CHANNEL_PV_VOLTAGE);
CHANNELS_VARIOSTRING.put(14, CHANNEL_PV_CURRENT);
CHANNELS_VARIOSTRING.put(20, CHANNEL_PV_POWER);
CHANNELS_VARIOSTRING.put(34, CHANNEL_PRODUCTION_PV_CURRENT_DAY);
CHANNELS_VARIOSTRING.put(26, CHANNEL_PV_OPERATING_MODE);
CHANNELS_VARIOSTRING.put(10, CHANNEL_PV1_VOLTAGE);
CHANNELS_VARIOSTRING.put(16, CHANNEL_PV1_CURRENT);
CHANNELS_VARIOSTRING.put(22, CHANNEL_PV1_POWER);
CHANNELS_VARIOSTRING.put(36, CHANNEL_PRODUCTION_PV1_CURRENT_DAY);
CHANNELS_VARIOSTRING.put(28, CHANNEL_PV1_OPERATING_MODE);
CHANNELS_VARIOSTRING.put(12, CHANNEL_PV2_VOLTAGE);
CHANNELS_VARIOSTRING.put(18, CHANNEL_PV2_CURRENT);
CHANNELS_VARIOSTRING.put(24, CHANNEL_PV2_POWER);
CHANNELS_VARIOSTRING.put(38, CHANNEL_PRODUCTION_PV2_CURRENT_DAY);
CHANNELS_VARIOSTRING.put(30, CHANNEL_PV2_OPERATING_MODE);
CHANNELS_VARIOSTRING.put(216, CHANNEL_STATE_VARIOSTRING);
}
/**
* Map of the supported VarioString channel with their unit
*/
public static final Map<Integer, Unit<?>> UNIT_CHANNELS_VARIOSTRING = new HashMap<>();
static {
UNIT_CHANNELS_VARIOSTRING.put(0, VOLT);
UNIT_CHANNELS_VARIOSTRING.put(2, AMPERE);
UNIT_CHANNELS_VARIOSTRING.put(8, VOLT);
UNIT_CHANNELS_VARIOSTRING.put(14, AMPERE);
UNIT_CHANNELS_VARIOSTRING.put(20, KILO(WATT));
UNIT_CHANNELS_VARIOSTRING.put(34, KILOWATT_HOUR);
UNIT_CHANNELS_VARIOSTRING.put(10, VOLT);
UNIT_CHANNELS_VARIOSTRING.put(16, AMPERE);
UNIT_CHANNELS_VARIOSTRING.put(22, KILO(WATT));
UNIT_CHANNELS_VARIOSTRING.put(36, KILOWATT_HOUR);
UNIT_CHANNELS_VARIOSTRING.put(12, VOLT);
UNIT_CHANNELS_VARIOSTRING.put(18, AMPERE);
UNIT_CHANNELS_VARIOSTRING.put(24, KILO(WATT));
UNIT_CHANNELS_VARIOSTRING.put(38, KILOWATT_HOUR);
}
// List of all parameters
public static final String SLAVE_ADDRESS = "slaveAddress";
public static final String REFRESH = "refresh";
}

View File

@@ -0,0 +1,36 @@
/**
* 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.studer.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link StuderConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Giovanni Mirulla - Initial contribution
*/
@NonNullByDefault
public class StuderConfiguration {
/**
* Address of slave device
*/
public int slaveAddress = 0;
/**
* Refresh interval in seconds
*/
public int refresh = 5;
/**
* Max tries for one register
*/
public int maxTries = 3;
}

View File

@@ -0,0 +1,442 @@
/**
* 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.studer.internal;
import static org.openhab.binding.modbus.studer.internal.StuderBindingConstants.*;
import java.util.ArrayList;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
import org.openhab.binding.modbus.studer.internal.StuderParser.ModeXtender;
import org.openhab.binding.modbus.studer.internal.StuderParser.VSMode;
import org.openhab.binding.modbus.studer.internal.StuderParser.VTMode;
import org.openhab.binding.modbus.studer.internal.StuderParser.VTType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.Bridge;
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.ThingStatusInfo;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.UnDefType;
import org.openhab.io.transport.modbus.AsyncModbusFailure;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
import org.openhab.io.transport.modbus.ModbusRegisterArray;
import org.openhab.io.transport.modbus.PollTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link StuderHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Giovanni Mirulla - Initial contribution
*/
@NonNullByDefault
public class StuderHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(StuderHandler.class);
private @Nullable StuderConfiguration config;
/**
* Array of tasks used to poll the device
*/
private ArrayList<PollTask> pollTasks = new ArrayList<PollTask>();
/**
* Communication interface to the slave endpoint we're connecting to
*/
protected volatile @Nullable ModbusCommunicationInterface comms = null;
/**
* Importing parser methods and enums
*/
final StuderParser parser = new StuderParser();
/**
* Support variable for type of thing
*/
protected ThingTypeUID type;
/**
* Array of registers of Studer slave to read, we store this once initialization is complete
*/
private Integer[] registers = new Integer[0];
/**
* Instances of this handler
*
* @param thing the thing to handle
* @param type the type of thing to handle
* @param slaveAddress the address of thing
* @param refreshSec the address of thing
*/
public StuderHandler(Thing thing) {
super(thing);
this.type = thing.getThingTypeUID();
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
// Currently we do not support any commands
}
/**
* Initialization:
* Load the config object
* Connect to the slave bridge
* Get registers to poll
* Start the periodic polling
*/
@Override
public void initialize() {
config = getConfigAs(StuderConfiguration.class);
logger.debug("Initializing thing with configuration: {}", thing.getConfiguration());
startUp();
}
/*
* This method starts the operation of this handler
* Connect to the slave bridge
* Get registers to poll
* Start the periodic polling
*/
private void startUp() {
connectEndpoint();
if (comms == null || config == null) {
logger.debug("Invalid endpoint/config/manager ref for studer handler");
return;
}
if (!pollTasks.isEmpty()) {
return;
}
if (type.equals(THING_TYPE_BSP)) {
Set<Integer> keys = CHANNELS_BSP.keySet();
registers = keys.toArray(new Integer[keys.size()]);
} else if (type.equals(THING_TYPE_XTENDER)) {
Set<Integer> keys = CHANNELS_XTENDER.keySet();
registers = keys.toArray(new Integer[keys.size()]);
} else if (type.equals(THING_TYPE_VARIOTRACK)) {
Set<Integer> keys = CHANNELS_VARIOTRACK.keySet();
registers = keys.toArray(new Integer[keys.size()]);
} else if (type.equals(THING_TYPE_VARIOSTRING)) {
Set<Integer> keys = CHANNELS_VARIOSTRING.keySet();
registers = keys.toArray(new Integer[keys.size()]);
}
for (int r : registers) {
registerPollTask(r);
}
}
/**
* Dispose the binding correctly
*/
@Override
public void dispose() {
tearDown();
}
/**
* Unregister the poll tasks and release the endpoint reference
*/
private void tearDown() {
unregisterPollTasks();
unregisterEndpoint();
}
/**
* Get the endpoint handler from the bridge this handler is connected to
* Checks that we're connected to the right type of bridge
*
* @return the endpoint handler or null if the bridge does not exist
*/
private @Nullable ModbusEndpointThingHandler getEndpointThingHandler() {
Bridge bridge = getBridge();
if (bridge == null) {
logger.debug("Bridge is null");
return null;
}
if (bridge.getStatus() != ThingStatus.ONLINE) {
logger.debug("Bridge is not online");
return null;
}
ThingHandler handler = bridge.getHandler();
if (handler == null) {
logger.debug("Bridge handler is null");
return null;
}
if (handler instanceof ModbusEndpointThingHandler) {
ModbusEndpointThingHandler slaveEndpoint = (ModbusEndpointThingHandler) handler;
return slaveEndpoint;
} else {
logger.debug("Unexpected bridge handler: {}", handler);
return null;
}
}
/**
* Get a reference to the modbus endpoint
*/
private void connectEndpoint() {
if (comms != null) {
return;
}
ModbusEndpointThingHandler slaveEndpointThingHandler = getEndpointThingHandler();
if (slaveEndpointThingHandler == null) {
@SuppressWarnings("null")
String label = Optional.ofNullable(getBridge()).map(b -> b.getLabel()).orElse("<null>");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
String.format("Bridge '%s' is offline", label));
logger.debug("No bridge handler available -- aborting init for {}", label);
return;
}
comms = slaveEndpointThingHandler.getCommunicationInterface();
if (comms == null) {
@SuppressWarnings("null")
String label = Optional.ofNullable(getBridge()).map(b -> b.getLabel()).orElse("<null>");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
String.format("Bridge '%s' not completely initialized", label));
logger.debug("Bridge not initialized fully (no endpoint) -- aborting init for {}", this);
return;
}
}
/**
* Remove the endpoint if exists
*/
private void unregisterEndpoint() {
// Comms will be close()'d by endpoint thing handler
comms = null;
}
private synchronized void unregisterPollTasks() {
if (pollTasks.isEmpty()) {
return;
}
logger.debug("Unregistering polling from ModbusManager");
ModbusCommunicationInterface mycomms = comms;
if (mycomms != null) {
for (PollTask t : pollTasks) {
mycomms.unregisterRegularPoll(t);
}
pollTasks.clear();
}
}
/**
* Register poll task
* This is where we set up our regular poller
*/
private synchronized void registerPollTask(int registerNumber) {
if (pollTasks.size() >= registers.length) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
throw new IllegalStateException("New pollTask invalid");
}
ModbusCommunicationInterface mycomms = comms;
StuderConfiguration studerConfig = config;
if (studerConfig == null || mycomms == null) {
throw new IllegalStateException("registerPollTask called without proper configuration");
}
logger.debug("Setting up regular polling");
ModbusReadRequestBlueprint request = new ModbusReadRequestBlueprint(studerConfig.slaveAddress,
ModbusReadFunctionCode.READ_INPUT_REGISTERS, registerNumber, 2, studerConfig.maxTries);
long refreshMillis = studerConfig.refresh * 1000;
PollTask pollTask = mycomms.registerRegularPoll(request, refreshMillis, 1000, result -> {
if (result.getRegisters().isPresent()) {
ModbusRegisterArray reg = result.getRegisters().get();
handlePolledData(registerNumber, reg);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
return;
}
if (getThing().getStatus() != ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
}
}, this::handleError);
pollTasks.add(pollTask);
}
/**
* This method is called each time new data has been polled from the modbus slave
* The register array is first parsed, then each of the channels are updated
* to the new values
*
* @param n register readed
* @param registers byte array read from the modbus slave
*/
protected void handlePolledData(int registerNumber, ModbusRegisterArray registers) {
String hexString = registers.toHexString().toString();
Float quantity = parser.hexToFloat(hexString);
if (quantity != null) {
if (type.equals(THING_TYPE_BSP)) {
updateState(CHANNELS_BSP.get(registerNumber),
new QuantityType<>(quantity, UNIT_CHANNELS_BSP.get(registerNumber)));
} else if (type.equals(THING_TYPE_XTENDER)) {
handlePolledDataXtender(registerNumber, quantity);
} else if (type.equals(THING_TYPE_VARIOTRACK)) {
handlePolledDataVarioTrack(registerNumber, quantity);
} else if (type.equals(THING_TYPE_VARIOSTRING)) {
handlePolledDataVarioString(registerNumber, quantity);
}
}
resetCommunicationError();
}
/**
* This method is called each time new data has been polled from the VarioString slave
* The register array is first parsed, then each of the channels are updated
* to the new values
*/
protected void handlePolledDataVarioString(int registerNumber, Float quantity) {
switch (CHANNELS_VARIOSTRING.get(registerNumber)) {
case CHANNEL_PV_OPERATING_MODE:
case CHANNEL_PV1_OPERATING_MODE:
case CHANNEL_PV2_OPERATING_MODE:
VSMode vsmode = StuderParser.getVSModeByCode(quantity.intValue());
if (vsmode == VSMode.UNKNOWN) {
updateState(CHANNELS_VARIOSTRING.get(registerNumber), UnDefType.UNDEF);
} else {
updateState(CHANNELS_VARIOSTRING.get(registerNumber), new StringType(vsmode.name()));
}
break;
case CHANNEL_STATE_VARIOSTRING:
OnOffType vsstate = StuderParser.getStateByCode(quantity.intValue());
updateState(CHANNELS_VARIOSTRING.get(registerNumber), vsstate);
break;
default:
updateState(CHANNELS_VARIOSTRING.get(registerNumber),
new QuantityType<>(quantity, UNIT_CHANNELS_VARIOSTRING.get(registerNumber)));
}
}
/**
* This method is called each time new data has been polled from the VarioTrack slave
* The register array is first parsed, then each of the channels are updated
* to the new values
*/
protected void handlePolledDataVarioTrack(int registerNumber, Float quantity) {
switch (CHANNELS_VARIOTRACK.get(registerNumber)) {
case CHANNEL_MODEL_VARIOTRACK:
VTType type = StuderParser.getVTTypeByCode(quantity.intValue());
if (type == VTType.UNKNOWN) {
updateState(CHANNELS_VARIOTRACK.get(registerNumber), UnDefType.UNDEF);
} else {
updateState(CHANNELS_VARIOTRACK.get(registerNumber), new StringType(type.name()));
}
break;
case CHANNEL_OPERATING_MODE:
VTMode vtmode = StuderParser.getVTModeByCode(quantity.intValue());
if (vtmode == VTMode.UNKNOWN) {
updateState(CHANNELS_VARIOTRACK.get(registerNumber), UnDefType.UNDEF);
} else {
updateState(CHANNELS_VARIOTRACK.get(registerNumber), new StringType(vtmode.name()));
}
break;
case CHANNEL_STATE_VARIOTRACK:
OnOffType vtstate = StuderParser.getStateByCode(quantity.intValue());
updateState(CHANNELS_VARIOTRACK.get(registerNumber), vtstate);
break;
default:
updateState(CHANNELS_VARIOTRACK.get(registerNumber),
new QuantityType<>(quantity, UNIT_CHANNELS_VARIOTRACK.get(registerNumber)));
}
}
/**
* This method is called each time new data has been polled from the Xtender slave
* The register array is first parsed, then each of the channels are updated
* to the new values
*/
protected void handlePolledDataXtender(int registerNumber, Float quantity) {
switch (CHANNELS_XTENDER.get(registerNumber)) {
case CHANNEL_OPERATING_STATE:
ModeXtender mode = StuderParser.getModeXtenderByCode(quantity.intValue());
if (mode == ModeXtender.UNKNOWN) {
updateState(CHANNELS_XTENDER.get(registerNumber), UnDefType.UNDEF);
} else {
updateState(CHANNELS_XTENDER.get(registerNumber), new StringType(mode.name()));
}
break;
case CHANNEL_STATE_INVERTER:
OnOffType xtstate = StuderParser.getStateByCode(quantity.intValue());
updateState(CHANNELS_XTENDER.get(registerNumber), xtstate);
break;
default:
updateState(CHANNELS_XTENDER.get(registerNumber),
new QuantityType<>(quantity, UNIT_CHANNELS_XTENDER.get(registerNumber)));
}
}
/**
* Handle errors received during communication
*/
protected void handleError(AsyncModbusFailure<ModbusReadRequestBlueprint> failure) {
// Ignore all incoming data and errors if configuration is not correct
if (hasConfigurationError() || getThing().getStatus() == ThingStatus.OFFLINE) {
return;
}
String msg = failure.getCause().getMessage();
String cls = failure.getCause().getClass().getName();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
String.format("Error with read: %s: %s", cls, msg));
}
/**
* Returns true, if we're in a CONFIGURATION_ERROR state
*
* @return
*/
protected boolean hasConfigurationError() {
ThingStatusInfo statusInfo = getThing().getStatusInfo();
return statusInfo.getStatus() == ThingStatus.OFFLINE
&& statusInfo.getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR;
}
/**
* Reset communication status to ONLINE if we're in an OFFLINE state
*/
protected void resetCommunicationError() {
ThingStatusInfo statusInfo = thing.getStatusInfo();
if (ThingStatus.OFFLINE.equals(statusInfo.getStatus())
&& ThingStatusDetail.COMMUNICATION_ERROR.equals(statusInfo.getStatusDetail())) {
updateStatus(ThingStatus.ONLINE);
}
}
}

View File

@@ -0,0 +1,45 @@
/**
* 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.studer.internal;
import static org.openhab.binding.modbus.studer.internal.StuderBindingConstants.SUPPORTED_THING_TYPES_UIDS;
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 StuderHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Giovanni Mirulla - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.studer", service = ThingHandlerFactory.class)
public class StuderHandlerFactory extends BaseThingHandlerFactory {
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
return new StuderHandler(thing);
}
}

View File

@@ -0,0 +1,218 @@
/**
* 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.studer.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.types.OnOffType;
/**
* The {@link StuderParser} class with helper method
* and possible values for mode and state
*
* @author Giovanni Mirulla - Initial contribution
*/
@NonNullByDefault
public class StuderParser {
public enum ModeXtender {
INVALID(0),
INVERTER(1),
CHARGER(2),
BOOST(3),
INJECTION(4),
UNKNOWN(-1);
private final int code;
ModeXtender(int code) {
this.code = code;
}
public int code() {
return this.code;
}
}
public static ModeXtender getModeXtenderByCode(int code) {
switch (code) {
case 0:
return ModeXtender.INVALID;
case 1:
return ModeXtender.INVERTER;
case 2:
return ModeXtender.CHARGER;
case 3:
return ModeXtender.BOOST;
case 4:
return ModeXtender.INJECTION;
default:
return ModeXtender.UNKNOWN;
}
}
public static OnOffType getStateByCode(int code) {
switch (code) {
case 0:
return OnOffType.OFF;
case 1:
return OnOffType.ON;
default:
return OnOffType.OFF;
}
}
public enum VTType {
VT80(0),
VT65(1),
UNKNOWN(-1);
private final int code;
VTType(int code) {
this.code = code;
}
public int code() {
return this.code;
}
}
public static VTType getVTTypeByCode(int code) {
switch (code) {
case 0:
return VTType.VT80;
case 1:
return VTType.VT65;
default:
return VTType.UNKNOWN;
}
}
public enum VTMode {
NIGHT(0),
STARTUP(1),
CHARGER(3),
SECURITY(5),
OFF(6),
CHARGE(8),
CHARGEV(9),
CHARGEI(10),
CHARGET(11),
CHIBSP(12),
UNKNOWN(-1);
private final int code;
VTMode(int code) {
this.code = code;
}
public int code() {
return this.code;
}
}
public static VTMode getVTModeByCode(int code) {
switch (code) {
case 0:
return VTMode.NIGHT;
case 1:
return VTMode.STARTUP;
case 3:
return VTMode.CHARGER;
case 5:
return VTMode.SECURITY;
case 6:
return VTMode.OFF;
case 8:
return VTMode.CHARGE;
case 9:
return VTMode.CHARGEV;
case 10:
return VTMode.CHARGEI;
case 11:
return VTMode.CHARGET;
case 12:
return VTMode.CHIBSP;
default:
return VTMode.UNKNOWN;
}
}
public enum VSMode {
NIGHT(0),
SECURITY(1),
OFF(2),
CHARGE(3),
CHARGEV(4),
CHARGEI(5),
CHARGEP(6),
CHARGEIPV(7),
CHARGET(8),
CHIBSP(10),
UNKNOWN(-1);
private final int code;
VSMode(int code) {
this.code = code;
}
public int code() {
return this.code;
}
}
public static VSMode getVSModeByCode(int code) {
switch (code) {
case 0:
return VSMode.NIGHT;
case 1:
return VSMode.SECURITY;
case 2:
return VSMode.OFF;
case 3:
return VSMode.CHARGE;
case 4:
return VSMode.CHARGEV;
case 5:
return VSMode.CHARGEI;
case 6:
return VSMode.CHARGEP;
case 7:
return VSMode.CHARGEIPV;
case 8:
return VSMode.CHARGET;
case 10:
return VSMode.CHIBSP;
default:
return VSMode.UNKNOWN;
}
}
/**
* Convert an hex string to float
*
* @param hex string to convert from
* @return the converted float
*/
public @Nullable Float hexToFloat(String hex) {
String t = hex.replaceAll(" ", "");
float f = Float.intBitsToFloat((int) Long.parseLong(t, 16));
if (Float.isNaN(f)) {
return null;
} else {
return f;
}
}
}

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<!-- Power Channel Type -->
<channel-type id="Pbat">
<item-type>Number:Power</item-type>
<label>Power</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- State of charge Channel Type -->
<channel-type id="SOC">
<item-type>Number:Dimensionless</item-type>
<label>State of Charge</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Battery temperature Channel Type -->
<channel-type id="Tbat">
<item-type>Number:Temperature</item-type>
<label>Battery Temperature</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<!-- Battery voltage Channel Type -->
<channel-type id="Ubat">
<item-type>Number:ElectricPotential</item-type>
<label>Battery Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Battery current Channel Type -->
<channel-type id="Ibat">
<item-type>Number:ElectricCurrent</item-type>
<label>Battery Current</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<!-- Model of VarioTrack Channel Type -->
<channel-type id="Type">
<item-type>String</item-type>
<label>Model of VarioTrack</label>
<state readOnly="true">
<options>
<option value="VT80">VT-80</option>
<option value="VT65">VT-65</option>
</options>
</state>
</channel-type>
<!-- Voltage of the PV generator Channel Type -->
<channel-type id="Upv">
<item-type>Number:ElectricPotential</item-type>
<label>PV Generator Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Power of the PV generator Channel Type -->
<channel-type id="Psol">
<item-type>Number:Power</item-type>
<label>Power of the PV Generator</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Production in (kWh) for the current day Channel Type -->
<channel-type id="Ed">
<item-type>Number:Energy</item-type>
<label>Current Day Production</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Operating state Channel Type -->
<channel-type id="Mode">
<item-type>String</item-type>
<label>Operating Mode</label>
<state readOnly="true">
<options>
<option value="NIGHT">Night</option>
<option value="STARTUP">StartUp</option>
<option value="UNKNOWN">---</option>
<option value="CHARGER">Charger</option>
<option value="SECURITY">Security</option>
<option value="OFF">OFF</option>
<option value="CHARGE">Charge</option>
<option value="CHARGEV">Charge V</option>
<option value="CHARGEI">Charge I</option>
<option value="CHARGET">Charge T</option>
<option value="CHIBSP">Ch. Ibsp</option>
</options>
</state>
</channel-type>
<!-- State of the VarioTrack Channel Type -->
<channel-type id="VTstate">
<item-type>Switch</item-type>
<label>State of the VarioTrack</label>
<state readOnly="true"></state>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<!-- PV voltage Channel Type -->
<channel-type id="Upv0">
<item-type>Number:ElectricPotential</item-type>
<label>PV Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV current Channel Type -->
<channel-type id="Ipv0">
<item-type>Number:ElectricCurrent</item-type>
<label>PV Current</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV Power Channel Type -->
<channel-type id="Ppv0">
<item-type>Number:Power</item-type>
<label>PV Power</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Production PV in (kWh) for the current day Channel Type -->
<channel-type id="Ed0">
<item-type>Number:Energy</item-type>
<label>PV Current Day Production</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV operating mode Channel Type -->
<channel-type id="Mod0">
<item-type>String</item-type>
<label>PV Operating State</label>
<state readOnly="true">
<options>
<option value="NIGHT">Night</option>
<option value="SECURITY">Security</option>
<option value="OFF">OFF</option>
<option value="CHARGE">Charge</option>
<option value="CHARGEV">Charge V</option>
<option value="CHARGEI">Charge I</option>
<option value="CHARGEP">Charge P</option>
<option value="CHARGEIPV">Charge Ipv</option>
<option value="CHARGET">Charge T</option>
<option value="UNKNOWN">---</option>
<option value="CHIBSP">Ch. Ibsp</option>
</options>
</state>
</channel-type>
<!-- PV1 voltage Channel Type -->
<channel-type id="Upv1">
<item-type>Number:ElectricPotential</item-type>
<label>PV1 Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV1 current Channel Type -->
<channel-type id="Ipv1">
<item-type>Number:ElectricCurrent</item-type>
<label>PV1 Current</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV1 Power Channel Type -->
<channel-type id="Ppv1">
<item-type>Number:Power</item-type>
<label>PV1 Power</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Production PV1 in (kWh) for the current day Channel Type -->
<channel-type id="Ed1">
<item-type>Number:Energy</item-type>
<label>PV1 Current Day Production</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV1 operating mode Channel Type -->
<channel-type id="Mod1">
<item-type>String</item-type>
<label>PV1 Operating State</label>
<state readOnly="true">
<options>
<option value="NIGHT">Night</option>
<option value="SECURITY">Security</option>
<option value="OFF">OFF</option>
<option value="CHARGE">Charge</option>
<option value="CHARGEV">Charge V</option>
<option value="CHARGEI">Charge I</option>
<option value="CHARGEP">Charge P</option>
<option value="CHARGEIPV">Charge Ipv</option>
<option value="CHARGET">Charge T</option>
<option value="UNKNOWN">---</option>
<option value="CHIBSP">Ch. Ibsp</option>
</options>
</state>
</channel-type>
<!-- PV2 voltage Channel Type -->
<channel-type id="Upv2">
<item-type>Number:ElectricPotential</item-type>
<label>PV2 Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV2 current Channel Type -->
<channel-type id="Ipv2">
<item-type>Number:ElectricCurrent</item-type>
<label>PV2 Current</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV2 Power Channel Type -->
<channel-type id="Ppv2">
<item-type>Number:Power</item-type>
<label>PV2 Power</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Production PV2 in (kWh) for the current day Channel Type -->
<channel-type id="Ed2">
<item-type>Number:Energy</item-type>
<label>PV2 Current Day Production</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- PV operating mode Channel Type -->
<channel-type id="Mod2">
<item-type>String</item-type>
<label>PV2 Operating State</label>
<state readOnly="true">
<options>
<option value="NIGHT">Night</option>
<option value="SECURITY">Security</option>
<option value="OFF">OFF</option>
<option value="CHARGE">Charge</option>
<option value="CHARGEV">Charge V</option>
<option value="CHARGEI">Charge I</option>
<option value="CHARGEP">Charge P</option>
<option value="CHARGEIPV">Charge Ipv</option>
<option value="CHARGET">Charge T</option>
<option value="UNKNOWN">---</option>
<option value="CHIBSP">Ch. Ibsp</option>
</options>
</state>
</channel-type>
<!-- State of the VarioString Channel Type -->
<channel-type id="VSstate">
<item-type>Switch</item-type>
<label>State of the VarioString</label>
<state readOnly="true"></state>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<!-- Input voltage Channel Type -->
<channel-type id="Uin">
<item-type>Number:ElectricPotential</item-type>
<label>Input Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Input current Channel Type -->
<channel-type id="Iin">
<item-type>Number:ElectricCurrent</item-type>
<label>Input Current</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Input active power Channel Type -->
<channel-type id="Pina">
<item-type>Number:Power</item-type>
<label>Input Active Power</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Input frequency Channel Type -->
<channel-type id="Fin">
<item-type>Number:Frequency</item-type>
<label>Input Frequency</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Output voltage Channel Type -->
<channel-type id="Uout">
<item-type>Number:ElectricPotential</item-type>
<label>Output Voltage</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Output current Channel Type -->
<channel-type id="Iout">
<item-type>Number:ElectricCurrent</item-type>
<label>Output Current</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Output active power Channel Type -->
<channel-type id="Pouta">
<item-type>Number:Power</item-type>
<label>Output Active Power</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Output frequency Channel Type -->
<channel-type id="Fout">
<item-type>Number:Frequency</item-type>
<label>Output Frequency</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<!-- Operating state Channel Type -->
<channel-type id="Mode">
<item-type>String</item-type>
<label>Operating State</label>
<state readOnly="true">
<options>
<option value="INVALID">Invalid value</option>
<option value="INVERTER">Inverter</option>
<option value="CHARGER">Charger</option>
<option value="BOOST">Boost</option>
<option value="INJECTION">Injection</option>
</options>
</state>
</channel-type>
<!-- State of the inverter Channel Type -->
<channel-type id="XTstate">
<item-type>String</item-type>
<label>State of the Inverter</label>
<state readOnly="true">
<options>
<option value="OFF">OFF</option>
<option value="ON">ON</option>
</options>
</state>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="modbus"
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">
<!-- BSP Thing Type -->
<thing-type id="bsp">
<supported-bridge-type-refs>
<bridge-type-ref id="serial"/>
</supported-bridge-type-refs>
<label>BSP Studer</label>
<description>Thing for Studer BSP Device</description>
<channels>
<channel id="batteryVoltage" typeId="Ubat"/>
<channel id="batteryCurrent" typeId="Ibat"/>
<channel id="power" typeId="Pbat"/>
<channel id="stateOfCharge" typeId="SOC"/>
<channel id="batteryTemperature" typeId="Tbat"/>
</channels>
<config-description>
<parameter name="slaveAddress" type="integer" min="60" max="61">
<label>Slave Address</label>
<description>Slave address of BSP device</description>
<default>60</default>
</parameter>
<parameter name="refresh" type="integer" min="1" unit="s">
<label>Refresh Interval</label>
<description>Poll interval</description>
<default>5</default>
<advanced>true</advanced>
</parameter>
</config-description>
</thing-type>
<!-- Xtender Thing Type -->
<thing-type id="xtender">
<supported-bridge-type-refs>
<bridge-type-ref id="serial"/>
</supported-bridge-type-refs>
<label>Xtender Studer</label>
<description>Thing for Studer Xtender Device</description>
<channels>
<channel id="inputVoltage" typeId="Uin"/>
<channel id="inputCurrent" typeId="Iin"/>
<channel id="inputActivePower" typeId="Pina"/>
<channel id="inputFrequency" typeId="Fin"/>
<channel id="outputVoltage" typeId="Uout"/>
<channel id="outputCurrent" typeId="Iout"/>
<channel id="outputActivePower" typeId="Pouta"/>
<channel id="outputFrequency" typeId="Fout"/>
<channel id="operatingState" typeId="Mode"/>
<channel id="stateInverter" typeId="XTstate"/>
</channels>
<config-description>
<parameter name="slaveAddress" type="integer" min="10" max="19">
<label>Slave Address</label>
<description>Slave address of Xtender device</description>
<default>10</default>
</parameter>
<parameter name="refresh" type="integer" min="1" unit="s">
<label>Refresh Interval</label>
<description>Poll interval</description>
<default>5</default>
<advanced>true</advanced>
</parameter>
</config-description>
</thing-type>
<!-- VarioTrack Thing Type -->
<thing-type id="variotrack">
<supported-bridge-type-refs>
<bridge-type-ref id="serial"/>
</supported-bridge-type-refs>
<label>VarioTrack Studer</label>
<description>Thing for Studer VarioTrack Device</description>
<channels>
<channel id="batteryVoltage" typeId="Ubat"/>
<channel id="batteryCurrent" typeId="Ibat"/>
<channel id="modelVarioTrack" typeId="Type"/>
<channel id="voltagePVGenerator" typeId="Upv"/>
<channel id="powerPVGenerator" typeId="Psol"/>
<channel id="productionCurrentDay" typeId="Ed"/>
<channel id="operatingMode" typeId="Mode"/>
<channel id="stateVarioTrack" typeId="VTstate"/>
</channels>
<config-description>
<parameter name="slaveAddress" type="integer" min="20" max="35">
<label>Slave Address</label>
<description>Slave address of VarioTrack device</description>
<default>20</default>
</parameter>
<parameter name="refresh" type="integer" min="1" unit="s">
<label>Refresh Interval</label>
<description>Poll interval</description>
<default>5</default>
<advanced>true</advanced>
</parameter>
</config-description>
</thing-type>
<!-- VarioString Thing Type -->
<thing-type id="variostring">
<supported-bridge-type-refs>
<bridge-type-ref id="serial"/>
</supported-bridge-type-refs>
<label>VarioString Studer</label>
<description>Thing for Studer VarioString Device</description>
<channels>
<channel id="batteryVoltage" typeId="Ubat"/>
<channel id="batteryCurrent" typeId="Ibat"/>
<channel id="PVVoltage" typeId="Upv0"/>
<channel id="PVCurrent" typeId="Ipv0"/>
<channel id="PVPower" typeId="Ppv0"/>
<channel id="ProductionPVCurrentDay" typeId="Ed0"/>
<channel id="PVMode" typeId="Mod0"/>
<channel id="PV1Voltage" typeId="Upv1"/>
<channel id="PV1Current" typeId="Ipv1"/>
<channel id="PV1Power" typeId="Ppv1"/>
<channel id="ProductionPV1CurrentDay" typeId="Ed1"/>
<channel id="PV1Mode" typeId="Mod1"/>
<channel id="PV2Voltage" typeId="Upv2"/>
<channel id="PV2Current" typeId="Ipv2"/>
<channel id="PV2Power" typeId="Ppv2"/>
<channel id="ProductionPV2CurrentDay" typeId="Ed2"/>
<channel id="PV2Mode" typeId="Mod2"/>
<channel id="stateVarioString" typeId="VSstate"/>
</channels>
<config-description>
<parameter name="slaveAddress" type="integer" min="40" max="55">
<label>Slave Address</label>
<description>Slave address of VarioString device</description>
<default>40</default>
</parameter>
<parameter name="refresh" type="integer" min="1" unit="s">
<label>Refresh Interval</label>
<description>Poll interval</description>
<default>5</default>
<advanced>true</advanced>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>