added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.modbus.e3dc/.classpath
Normal file
32
bundles/org.openhab.binding.modbus.e3dc/.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.modbus.e3dc/.project
Normal file
23
bundles/org.openhab.binding.modbus.e3dc/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.modbus.e3dc</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.modbus.e3dc/NOTICE
Normal file
13
bundles/org.openhab.binding.modbus.e3dc/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
|
||||
371
bundles/org.openhab.binding.modbus.e3dc/README.md
Normal file
371
bundles/org.openhab.binding.modbus.e3dc/README.md
Normal file
@@ -0,0 +1,371 @@
|
||||
# E3DC Binding
|
||||
|
||||
<img align="right" src="./doc/E3DC_logo.png"/>
|
||||
|
||||
Integrates the Home Power Plants from E3/DC GmbH into openHAB. See [E3DC Website](https://www.e3dc.com/) to find more informations about the device.
|
||||
The Power Plant handles all your Electrical Energy Resources like Photovoltaic Producers, Battery Storage, Wallbox Power Supply, Household Consumption and even more.
|
||||
E3DC devices are integrated into the Modbus Binding.
|
||||
|
||||
See chapter [Thing Configuration](#thing-configuration) how to set them up or check the [full example Things](#things) for manual setup.
|
||||
|
||||
|
||||
## Supported Things
|
||||
|
||||
First you need a Bridge which establishes the basic connection towards your E3DC device
|
||||
|
||||
| Name | Thing Type ID | Description |
|
||||
|-----------------------|---------------|------------------------------------------------------------------------------------------------------|
|
||||
| E3DC Home Power Plant | e3dc | Provides Power values, String Details, Emergency Power Status and general Information of your E3DC Home Power Plant |
|
||||
| E3DC Wallbox | e3dc-wallbox | Provides your Wallbox Settings. Switches like "Sunmode" or "1-Phase Charging" can be changed |
|
||||
|
||||
|
||||
## Discovery
|
||||
|
||||
There's no discovery. Modbus registers are available for all devices.
|
||||
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
As mentioned earlier in the [Binding Description](#e3dc-binding) the needed Things can be found in the **Modbus Binding** and have to be added manually without Discovery
|
||||
|
||||
<img align="right" src="./doc/E3DC_Modbus_Settings.png"/>
|
||||
|
||||
1. Create _Modbus TCP Bridge_ with matching Settings of your E3DC Device
|
||||
|
||||
* IP Address
|
||||
* Device ID
|
||||
* Port ID
|
||||
|
||||
2. Create _E3DC Home Power Plant_ and attach it to the previous installed _Modbus TCP Bridge_. Configuration requires an approriate Data Refresh Interval with more than 1000 Milliseconds
|
||||
|
||||
3. If you have a Wallbox attached add _E3DC Wallbox_ Thing with your previous installed _E3DC Home Power Plant_ as Bridge. Configuration requires a Wallbox ID between 0 and 7.
|
||||
|
||||
Check the [full example Things](#things) for manual setup.
|
||||
|
||||
### Modbus TCP Slave
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------------|---------|-------------------------------------------------------------------------|
|
||||
| host | text | IP Address of your device |
|
||||
| port | integer | TCP Port of your E3DC device Modbus Settings.. Default is 502 |
|
||||
| deviceid | integer | Modbus ID of your E3DC device Modbus Settings. Default is 1 |
|
||||
|
||||
### E3DC Home Power Plant
|
||||
|
||||
Select as Bridge your previously created Modbus TCP Slave.
|
||||
| Parameter | Type | Description |
|
||||
|-----------------|---------|-------------------------------------------------------------------------|
|
||||
| refresh | integer | Refresh Rate of E3DC values in Milliseconds |
|
||||
|
||||
|
||||
### E3DC Wallbox
|
||||
|
||||
Select as Bridge your previously created E3DC Home Power Plant.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------------|---------|-----------------------------------------------------------------------------|
|
||||
| wallboxId | integer | E3DC supports up to 8 Wallboxes - select a value from 0 to 7 |
|
||||
|
||||
## Channels
|
||||
|
||||
The E3DC device offers quite an amount of channels. For clustering 4 Channel Groups are used:
|
||||
|
||||
### Channel Group _Information Block_
|
||||
|
||||
| Channel Label | Channel Group ID | Channel ID | Type | Description |
|
||||
|-----------------------|------------------|---------------------|--------|---------------------------------------------------|
|
||||
| Modbus-ID | info | modbus-id | String | Modbus ID / Magic Byte of E3DC |
|
||||
| Modbus Firmware | info | modbus-firmware | String | Version of Modbus Firmware |
|
||||
| Supported Registers | info | supported-registers | Number | Number of registers supported by Modbus |
|
||||
| Manufacturer Name | info | manufacturer-name | String | Name of the Device Manufacturer |
|
||||
| E3DC Model Name | info | model-name | String | Name of the E3DC Model |
|
||||
| E3DC Firmware Release | info | firmware-release | String | Firmware installed on this particular E3DC Device |
|
||||
| E3DC Serial Number | info | serial-number | String | Serial Number of this particular E3DC Device |
|
||||
|
||||
|
||||
### Channel Group _Power Block_
|
||||
|
||||
| Channel Label | Channel Group ID | Channel ID | Type | Description |
|
||||
|-------------------------------|-------------------|------------------------------|------------------------|------------------------------|
|
||||
| PV Output | power | pv-power-supply | Number:Power | Photovoltaic Power Production |
|
||||
| Battery Discharge | power | battery-power-supply | Number:Power | Battery discharges and provides Power |
|
||||
| Battery Charge | power | battery-power-consumption | Number:Power | Battery charges and consumes Power |
|
||||
| Household Consumption | power | household-power-consumption | Number:Power | Household consuming Power |
|
||||
| Grid Power Consumption | power | grid-power-consumption | Number:Power | Grid Power is needed in order to satisfy your overall Power consumption |
|
||||
| Grid Power Supply | power | grid-power-supply | Number:Power | More Photovoltaic Power is produced than needed. Additional Power is provided towards the Grid |
|
||||
| External Power Supply | power | external-power-supply | Number:Power | Power produced by an external device which is attached to your E3DC device |
|
||||
| Wallbox Power Consumption | power | wallbox-power-consumption | Number:Power | Power consumption of attached Wallboxes |
|
||||
| Wallbox PV Power Consumption | power | wallbox-pv-power-consumption | Number:Power | Photovoltaic Power consumption (PV plus Battery) of attached Wallboxes |
|
||||
| Autarky | power | autarky-channel | Number:Dimensionless | Your current Autarky Level in Percent |
|
||||
| Self Consumption | power | self-consumption | Number:Dimensionless | Your current Photovoltaic Self Consumption Level in Percent |
|
||||
| Battery State Of Charge | power | battery-soc | Number:Dimensionless | Charge Level of your attached Battery in Percent |
|
||||
|
||||
|
||||
### Channel Group _String Details Block_
|
||||
|
||||
| Channel Label | Channel Group ID | Channel ID | Type | Description |
|
||||
|-----------------------|------------------|--------------------|---------------------------|------------------------------|
|
||||
| String 1 Potential | strings | string1-dc-voltage | Number:ElectricPotential | Voltage on String 1 |
|
||||
| String 2 Potential | strings | string2-dc-voltage | Number:ElectricPotential | Voltage on String 2 |
|
||||
| String 3 Potential | strings | string3-dc-voltage | Number:ElectricPotential | Voltage on String 3 |
|
||||
| String 1 Current | strings | string1-dc-current | Number:ElectricCurrent | Current on String 1 |
|
||||
| String 2 Current | strings | string2-dc-current | Number:ElectricCurrent | Current on String 2 |
|
||||
| String 3 Current | strings | string3-dc-current | Number:ElectricCurrent | Current on String 3 |
|
||||
| String 1 Power | strings | string1-dc-output | Number:Power | Power produced by String 1 |
|
||||
| String 2 Power | strings | string2-dc-output | Number:Power | Power produced by String 2 |
|
||||
| String 3 Power | strings | string3-dc-output | Number:Power | Power produced by String 3 |
|
||||
|
||||
|
||||
### Channel _EMS Block_
|
||||
|
||||
| Channel Label | Channel Group ID | Channel ID | Type | Description |
|
||||
|---------------------------------------------|------------------|----------------------------|----------------|------------------------------|
|
||||
| Emergency Power Status | emergency | emergency-power-status | String | Possible values: EP not supported, EP active, EP not active, EP not available, EP Switch in wrong position, EP Status unknown |
|
||||
| Battery Charging Locked | emergency | battery-charging-lock | Switch | Battery charging is locked |
|
||||
| Battery Discharging Locked | emergency | battery-discharging-lock | Switch | Battery discharging is locked |
|
||||
| Emergency Power Possible | emergency | emergency-power-possible | Switch | Emergency Power Supply is possible |
|
||||
| Weather Predicted Battery Charging | emergency | weather-predicted-charging | Switch | Weather Predicted Battery Charging is activated |
|
||||
| Regulation Status Of Max Grid Power Supply | emergency | regulation-status | Switch | Grid Power Supply is currently regulated |
|
||||
| Charge Lock time Active | emergency | charge-lock-time | Switch | Charge Lock Time is currently active |
|
||||
| Discharge Lock time Active | emergency | discharge-lock-time | Switch | Discharge Lock Time is currently active |
|
||||
|
||||
### E3DC Wallbox Channels
|
||||
|
||||
Some of the Wallbox Settings can be changed. See the Access column if the actual value is Read/Write (RW) or Read Only (RO)
|
||||
|
||||
| Channel Label | Channel ID | Type | Access | Description |
|
||||
|--------------------------|---------------------|---------|--------|------------------------------|
|
||||
| Wallbox Available | wb-available | Switch | RO | Indicates if the Wallbox is attached. Check your Wallbox ID in offline case |
|
||||
| Sun Mode | wb-sunmode | Switch | RW | Activate / Deactivate Sun Mode. Off case takes Grid Power to ensure highest possible charging. |
|
||||
| Wallbox Charging Aborted | wb-charging-aborted | Switch | RW | Wallbox charging is aborted |
|
||||
| Wallbox Charging | wb-charging | Switch | RO | Wallbox is charging |
|
||||
| Jack Locked | wb-jack-locked | Switch | RO | Jack is locked |
|
||||
| Jack Plugged | wb-jack-plugged | Switch | RO | Jack is plugged |
|
||||
| Schuko Socket On | wb-schuko-on | Switch | RW | If your Wallbox has an additional Schuko Socket it provides state ON or OFF |
|
||||
| Schuko Socket Plugged | wb-schuko-plugged | Switch | RO | If your Wallbox has an additional Schuko Socket it provides plugged state ON or OFF |
|
||||
| Schuko Socket Locked | wb-schuko-locked | Switch | RO | If your Wallbox has an additional Schuko Socket it provides locked state ON or OFF |
|
||||
| Schuko 16A Relay On | wb-schuko-relay-16a | Switch | RO | Schuko 16A Relay is ON |
|
||||
| 16A Relay On | wb-relay-16a | Switch | RO | Wallbox 16A Relay is ON |
|
||||
| 32A Relay On | wb-relay-32a | Switch | RO | Wallbox 32A Relay is ON |
|
||||
| 1-Phase Charging | 1-Phase Active | Switch | RW | 1-phase charging is activated. If OFF 3-phase charging is activated |
|
||||
|
||||
## Full Example
|
||||
|
||||
Following example provides the full configuration. If you enter the correct Connection Data, IP Address, Device ID and Port number in the thing configuration you should be fine.
|
||||
|
||||
### Things
|
||||
|
||||
```
|
||||
Bridge modbus:tcp:device "E3DC Modbus TCP" [ host="192.168.178.56", port=502, id=1 ] {
|
||||
Bridge e3dc powerplant "E3DC Power Plant" [ refresh=2500 ] {
|
||||
Thing e3dc-wallbox wallbox0 "E3DC Wallbox" [ wallboxId=0]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Items
|
||||
|
||||
```
|
||||
String E3DC_ModbusId "E3DC Modbus ID" (e3dc) { channel="modbus:e3dc:device:powerplant:info#modbus-id" }
|
||||
String E3DC_ModbusFirmware "E3DC Modbus Firmware" (e3dc) { channel="modbus:e3dc:device:powerplant:info#modbus-firmware" }
|
||||
Number E3DC_SupportedRegisters "E3DC Supported Registers" (e3dc) { channel="modbus:e3dc:device:powerplant:info#supported-registers" }
|
||||
String E3DC_Manufacturer "E3DC Manufacturer" (e3dc) { channel="modbus:e3dc:device:powerplant:info#manufacturer-name" }
|
||||
String E3DC_ModelName "E3DC Model" (e3dc) { channel="modbus:e3dc:device:powerplant:info#model-name" }
|
||||
String E3DC_Firmware "E3DC Modbus ID" (e3dc) { channel="modbus:e3dc:device:powerplant:info#firmware-release" }
|
||||
String E3DC_SerialNumber "E3DC Modbus ID" (e3dc) { channel="modbus:e3dc:device:powerplant:info#serial-number" }
|
||||
|
||||
Number:Power E3DC_PVPower "E3DC PV Power" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#pv-power-supply" }
|
||||
Number:Power E3DC_BatteryDischarge "E3DC Battery Discharge" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#battery-power-supply" }
|
||||
Number:Power E3DC_BatteryCharge "E3DC Battery Charge" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#battery-power-consumption" }
|
||||
Number:Power E3DC_Household "E3DC Household Consumption" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#household-power-consumption" }
|
||||
Number:Power E3DC_GridConsumption "E3DC Grid Consumption" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#grid-power-consumption" }
|
||||
Number:Power E3DC_GridSupply "E3DC Grid Supply " (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#grid-power-supply" }
|
||||
Number:Power E3DC_ExternalSupply "E3DC External Supply" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#external-power-supply" }
|
||||
Number:Power E3DC_WallboxConsumption "E3DC Wallbox Consumption" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#wallbox-power-consumption" }
|
||||
Number:Power E3DC_WallboxPVConsumption "E3DC Wallbox PV Consumption" (e3dc) { channel="modbus:e3dc:device:powerplant:power#wallbox-pv-power-consumption" }
|
||||
Number:Dimensionless E3DC_AutarkyLevel "E3DC Autarky Level" (e3dc) { channel="modbus:e3dc:device:powerplant:power#autarky" }
|
||||
Number:Dimensionless E3DC_SelfConsumptionLevel "E3DC Self Consumption Level" (e3dc) { channel="modbus:e3dc:device:powerplant:power#self-consumption" }
|
||||
Number:Dimensionless E3DC_BatterySOC "E3DC Battery SOC" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:power#battery-soc" }
|
||||
|
||||
Switch E3DC_WB_Available "E3DC WB available" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-available" }
|
||||
Switch E3DC_WB_Sunmode "E3DC WB Sunmode" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-sunmode" }
|
||||
Switch E3DC_WB_ChargingAborted "E3DC WB Charging Aborted" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-charging-aborted" }
|
||||
Switch E3DC_WB_Charging "E3DC WB Charging" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-charging" }
|
||||
Switch E3DC_WB_JackLocked "E3DC WB Jack Locked" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-jack-locked" }
|
||||
Switch E3DC_WB_JackPlugged "E3DC WB Jack Plugged" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-jack-plugged" }
|
||||
Switch E3DC_WB_SchukoOn "E3DC WB Schuko On" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-schuko-on" }
|
||||
Switch E3DC_WB_SchukoPlugged "E3DC WB Schuko Plugged" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-schuko-plugged" }
|
||||
Switch E3DC_WB_SchukoLocked "E3DC WB Schuko Locked" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-schuko-locked" }
|
||||
Switch E3DC_WB_Schuko_Relay16A "E3DC WB Schuko 16A Relay" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-schuko-relay-16a" }
|
||||
Switch E3DC_WB_Relay16A "E3DC WB 16A Relay" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-relay-16a" }
|
||||
Switch E3DC_WB_Relay32A "E3DC WB 32A Relay" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-relay-32a" }
|
||||
Switch E3DC_WB_1PhaseCharging "E3DC WB 1-Phase Charging" (e3dc) { channel="modbus:e3dc-wallbox:device:powerplant:wallbox0:wb-1phase" }
|
||||
|
||||
Number:ElectricPotential E3DC_String1V "E3DC String 1 Volt" (e3dc) { channel="modbus:e3dc:device:powerplant:strings#string1-dc-voltage" }
|
||||
Number:ElectricPotential E3DC_String2V "E3DC String 2 Volt" (e3dc) { channel="modbus:e3dc:device:powerplant:strings#string2-dc-voltage" }
|
||||
Number:ElectricPotential E3DC_String3V "E3DC String 3 Volt" (e3dc) { channel="modbus:e3dc:device:powerplant:strings#string3-dc-voltage" }
|
||||
Number:ElectricCurrent E3DC_String1A "E3DC String 1 Ampere" (e3dc) { channel="modbus:e3dc:device:powerplant:strings#string1-dc-current" }
|
||||
Number:ElectricCurrent E3DC_String2A "E3DC String 2 Ampere" (e3dc) { channel="modbus:e3dc:device:powerplant:strings#string2-dc-current" }
|
||||
Number:ElectricCurrent E3DC_String3A "E3DC String 3 Ampere" (e3dc) { channel="modbus:e3dc:device:powerplant:strings#string3-dc-current" }
|
||||
Number:Power E3DC_String1W "E3DC String 1 Watt" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:strings#string1-dc-output" }
|
||||
Number:Power E3DC_String2W "E3DC String 2 Watt" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:strings#string2-dc-output" }
|
||||
Number:Power E3DC_String3W "E3DC String 3 Watt" (e3dc,persist) { channel="modbus:e3dc:device:powerplant:strings#string3-dc-output" }
|
||||
|
||||
String E3DC_EMS_Status "E3DC EMS Status" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#emergency-power-status" }
|
||||
Switch E3DC_EMS_BatteryChargingLock "E3DC EMS Battery Charging Locked" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#battery-charging-lock" }
|
||||
Switch E3DC_EMS_BatteryDischargingLock "E3DC EMS Battery Discharging Locked" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#battery-discharging-lock" }
|
||||
Switch E3DC_EMS_EmergencyPowerPossible "E3DC EMS Emergency Power possible" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#emergency-power-possible" }
|
||||
Switch E3DC_EMS_WeatherPredictedCharging "E3DC EMS Weather Predicted Charging" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#weather-predicted-charging" }
|
||||
Switch E3DC_EMS_RegulationStatus "E3DC EMS Regulation Status" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#regulation-status" }
|
||||
Switch E3DC_EMS_ChargeLockTime "E3DC EMS Charge Lock Time" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#charge-lock-time" }
|
||||
Switch E3DC_EMS_DischargeLockTime "E3DC EMS Discharge Lock TIme" (e3dc) { channel="modbus:e3dc:device:powerplant:emergency#discharge-lock-time" }
|
||||
```
|
||||
|
||||
### Sitemap
|
||||
|
||||
```
|
||||
sitemap E3DC label="E3DC Binding Sitemap" {
|
||||
Frame label="Info" {
|
||||
Text item=E3DC_ModbusId label="Modbus-ID [%s]"
|
||||
Text item=E3DC_ModbusFirmware label="Modbus Firmware [%s]"
|
||||
Text item=E3DC_SupportedRegisters label="Registers [%s]"
|
||||
Text item=E3DC_Manufacturer label="Manufacturer [%s]"
|
||||
Text item=E3DC_ModelName label="Model Name [%s]"
|
||||
Text item=E3DC_Firmware label="Firmware [%s]"
|
||||
Text item=E3DC_SerialNumber label="Serial Number[%s]"
|
||||
}
|
||||
|
||||
Frame label="Power Producer" {
|
||||
Text item=E3DC_PVPower label="PV Power [%d %unit%]"
|
||||
Text item=E3DC_BatteryDischarge label="Battery Discharge [%d %unit%]"
|
||||
Text item=E3DC_GridSupply label="Power from Grid [%d %unit%]"
|
||||
Text item=E3DC_ExternalSupply label="External Supply [%d %unit%]"
|
||||
}
|
||||
Frame label="Power Consumer" {
|
||||
Text item=E3DC_Household label="Household [%d %unit%]"
|
||||
Text item=E3DC_BatteryCharge label="Battery Charge [%d %unit%]"
|
||||
Text item=E3DC_GridConsumption label="Power to Grid [%d %unit%]"
|
||||
Text item=E3DC_WallboxConsumption label="Wallbox [%d %unit%]"
|
||||
Text item=E3DC_WallboxPVConsumption label="Wallbox PV [%d %unit%]"
|
||||
}
|
||||
Frame label="Power Measures" {
|
||||
Text item=E3DC_AutarkyLevel label="Autarky [%d %%]"
|
||||
Text item=E3DC_SelfConsumptionLevel label="Self Consumption [%d %%]"
|
||||
Text item=E3DC_BatterySOC label="SOC [%d %%]"
|
||||
}
|
||||
|
||||
Frame label="Wallbox" {
|
||||
Switch item=E3DC_WB_Available label="Available [%s]"
|
||||
Switch item=E3DC_WB_Sunmode label="Sunmode [%s]"
|
||||
Switch item=E3DC_WB_ChargingAborted label="Charging Aborted[%s]"
|
||||
Switch item=E3DC_WB_Charging label="Charging [%s]"
|
||||
Switch item=E3DC_WB_JackLocked label="Jack locked [%s]"
|
||||
Switch item=E3DC_WB_JackPlugged label="Jack plugged [%s]"
|
||||
Switch item=E3DC_WB_SchukoOn label="Schuko On [%s]"
|
||||
Switch item=E3DC_WB_SchukoPlugged label="Schuko plugged [%s]"
|
||||
Switch item=E3DC_WB_SchukoLocked label="Schuko locked [%s]"
|
||||
Switch item=E3DC_WB_Schuko_Relay16A label="Schuko Relay 16A [%s]"
|
||||
Switch item=E3DC_WB_Relay16A label="Relay 16A [%s]"
|
||||
Switch item=E3DC_WB_Relay32A label="Relay 32A [%s]"
|
||||
Switch item=E3DC_WB_1PhaseCharging label="1-Phase charging [%s]"
|
||||
}
|
||||
|
||||
Frame label="String 1 Details" {
|
||||
Text item=E3DC_String1V label="Volt [%d %unit%]"
|
||||
Text item=E3DC_String1A label="Ampere [%.2f %unit%]"
|
||||
Text item=E3DC_String1W label="Watt [%d %unit%]"
|
||||
}
|
||||
Frame label="String 2 Details" {
|
||||
Text item=E3DC_String2V label="Volt [%d %unit%]"
|
||||
Text item=E3DC_String2A label="Ampere [%.2f %unit%]"
|
||||
Text item=E3DC_String2W label="Watt [%d %unit%]"
|
||||
}
|
||||
Frame label="String 3 Details" {
|
||||
Text item=E3DC_String3V label="Volt [%d %unit%]"
|
||||
Text item=E3DC_String3A label="Ampere [%.2f %unit%]"
|
||||
Text item=E3DC_String3W label="Watt [%d %unit%]"
|
||||
}
|
||||
|
||||
Frame label="EMS" {
|
||||
Text item=E3DC_EMS_Status label="Status [%s]"
|
||||
Switch item=E3DC_EMS_BatteryChargingLock label="Battery Charging Lock [%s]"
|
||||
Switch item=E3DC_EMS_BatteryDischargingLock label="Battery Discharging Lock [%s]"
|
||||
Switch item=E3DC_EMS_EmergencyPowerPossible label="Emergency Power Possible [%s]"
|
||||
Switch item=E3DC_EMS_WeatherPredictedCharging label="Weather Predicted Charging [%s]"
|
||||
Switch item=E3DC_EMS_RegulationStatus label="Regulation [%s]"
|
||||
Switch item=E3DC_EMS_ChargeLockTime label="Charge Lock Times [%s]"
|
||||
Switch item=E3DC_EMS_DischargeLockTime label="Discharge Lock Times [%s]"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Going further
|
||||
|
||||
Setup and configured everything the right way? Congratulations, you've now the recent E3DC values on your table. Don't stop and go ahead!
|
||||
|
||||
### Persistence
|
||||
|
||||
You can see in the example item configuration, that I added some items to the "persist". Feel free to choose your own group name but this opens the possibility
|
||||
to store the items in a database. See following *.persist file configuration how this can be established.
|
||||
|
||||
```
|
||||
Strategies {
|
||||
everyMinute : "0 * * * * ?"
|
||||
everyHour : "0 0 * * * ?"
|
||||
everyDay : "0 0 0 * * ?"
|
||||
default = everyChange
|
||||
}
|
||||
|
||||
Items {
|
||||
// persist items on every change and every minute - used for E3DC
|
||||
persist : strategy = everyChange, everyMinute
|
||||
}
|
||||
```
|
||||
|
||||
### Visualization
|
||||
|
||||
After the timeline is available in your database you can continue with Visualization. I like the Grafana approach and I used the
|
||||
[InfluxDB & Grafana Tutorial](https://community.openhab.org/t/influxdb-grafana-persistence-and-graphing/13761)
|
||||
from the Community to set this up.
|
||||
I prepared my machine and I'm quite pleased with the results.
|
||||
|
||||
<img style="float: right;" src="doc/GrafanaPV.png">
|
||||
|
||||
In the above picture there are two graphs
|
||||
|
||||
* The top one shows the Photovoltaic Production of my 2 attached Strings. You can clearly see when the sky wasn't bright the production goes down
|
||||
* The bottom graph show the producers & consumers.
|
||||
* Battery in blue charging during the day, discharging at night
|
||||
* Household consumption in green
|
||||
* Wallbox consumption in orange
|
||||
* Grid consumption / supply in yellow
|
||||
|
||||
### Cross Connections
|
||||
|
||||
With the above setup you have now a great visualization and overview regarding your electric production and consumption. Now use the Power of openHAB and cross
|
||||
connect your data. For example you can use the
|
||||
[OpenweatherMap API Binding](https://www.openhab.org/addons/bindings/openweathermap/)
|
||||
the cloudiness in Percent. With a modified *.persist file I store the cloudiness forecast also in the database
|
||||
|
||||
```
|
||||
Strategies {
|
||||
everyMinute : "0 * * * * ?"
|
||||
everyHour : "0 0 * * * ?"
|
||||
everyDay : "0 0 0 * * ?"
|
||||
default = everyChange
|
||||
}
|
||||
|
||||
Items {
|
||||
// persist items on every change and every minute - used for E3DC
|
||||
persist : strategy = everyChange, everyMinute
|
||||
LocalWeatherAndForecast_Current_BewLkung : strategy = everyChange,everyHour
|
||||
}
|
||||
```
|
||||
|
||||
Having these values in the timeline you're able to cross check how the forecast influences the Photovoltaic Production.
|
||||
|
||||
<img style="float: right;" src="doc/GrafanaCloudiness.png">
|
||||
|
||||
I personally would like to have
|
||||
more steering control of the E3DC to react on such forecast e.g. "stop charging the car if it gets too cloudy"
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
bundles/org.openhab.binding.modbus.e3dc/doc/E3DC_logo.png
Normal file
BIN
bundles/org.openhab.binding.modbus.e3dc/doc/E3DC_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
174
bundles/org.openhab.binding.modbus.e3dc/doc/E3DC_logo.svg
Normal file
174
bundles/org.openhab.binding.modbus.e3dc/doc/E3DC_logo.svg
Normal file
@@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="357.98874"
|
||||
height="209.74985"
|
||||
viewBox="0 0 357.98874 209.74985"
|
||||
id="svg2"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="logoFARBE.svg">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="944"
|
||||
inkscape:window-height="1002"
|
||||
id="namedview30"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.96371746"
|
||||
inkscape:cx="178.99437"
|
||||
inkscape:cy="103.83728"
|
||||
inkscape:window-x="960"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<clipPath
|
||||
id="clipPath3058">
|
||||
<path
|
||||
d="m 0,0 2863.91,0 0,1678 L 0,1678 0,0 z"
|
||||
id="path3060" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clipPath18"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<path
|
||||
id="path20"
|
||||
d="m 0,0 2863.9,0 0,1678 L 0,1678 0,0 Z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="g10"
|
||||
transform="matrix(1.25,0,0,-1.25,0,277.74985)">
|
||||
<g
|
||||
id="g12"
|
||||
transform="matrix(0.1,0,0,0.1,0,54.4)">
|
||||
<g
|
||||
id="g14">
|
||||
<g
|
||||
id="g16"
|
||||
clip-path="url(#clipPath18)"
|
||||
style="fill-rule:nonzero">
|
||||
<path
|
||||
id="path22"
|
||||
d="m 1742.7,916.66 c -57.27,189.25 -186.71,325.74 -312.71,398.73 -263.04,148.69 -458.92,77.73 -451.69,77.64 -3.473,-18.3 188.74,29.09 424.88,-120.73 88.55,-56.9 176.97,-147.64 234.77,-266.31 19.74,-188.63 -164.02,-223.1 -214.26,-67.459 -57.96,179.55 -104.94,258.75 -173.84,249.53 -65.78,-7.13 -121.42,-183.59 -145.87,-259.48 -24.5,-75.94 -84.6,-294.63 -129.68,-393.35 -45.08,-98.68 -115.14,-142.36 -182.38,-140.66 -67.234,1.7 -120.82,45.993 -178.62,154.31 -19.129,3.457 -71.215,12.238 -71.215,12.238 27.344,-137.96 145.75,-291.33 264.21,-289.68 118.48,1.649 177.05,81.739 239.3,252.63 62.24,170.92 110.76,347.4 219.15,351.37 87.25,5.273 100.6,-108.04 124.21,-190.72 23.57,-82.734 66.78,-235.72 180.06,-236.36 43.81,0 77.03,27.821 101.56,64.723 -19.1,-57.92 -46.4,-114.24 -82.6,-166.39 -117.1,-169.47 -306.4,-267.49 -483.8,-279.23 -178.74,-15.43 -339.1,45.08 -447.68,126.05 -221.84,169.23 -247.77,364.82 -262.23,355.46 -4.02,6.38 1.17,-201.18 231.31,-395.68 112.55,-92.451 286.37,-164.98 483.4,-151.77 195.77,9.0312 408.12,115.93 538,304.29 130.46,187.88 155.12,424.46 95.59,610.8"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#66c430" />
|
||||
<path
|
||||
id="path24"
|
||||
d="m 367.15,633.2 -346.39,0 C 8.734,633.2 0,641.94 0,653.97 l 0,734.3 c 0,12.02 8.7344,20.76 20.762,20.76 l 346.39,0 c 12.016,0 20.762,-8.74 20.762,-20.76 l 0,-45.89 c 0,-12.03 -8.746,-20.77 -20.762,-20.77 l -274.27,0 0,-251.32 252.42,0 c 12.015,0 20.765,-8.74 20.765,-20.76 l 0,-45.9 c 0,-12.017 -8.75,-20.759 -20.765,-20.759 l -252.42,0 0,-262.24 274.27,0 c 12.016,0 20.762,-8.75 20.762,-20.77 l 0,-45.89 c 0,-12.028 -8.746,-20.77 -20.762,-20.77"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path26"
|
||||
d="m 690.6,622.28 c -86.328,0 -159.54,20.758 -159.54,20.758 -13.106,3.281 -20.766,9.84 -20.766,21.852 l 0,49.171 c 0,12.028 8.75,16.399 20.766,14.211 0,0 95.062,-18.574 157.35,-18.574 90.696,0 138.78,46.981 138.78,123.47 l 0,46.992 c 0,76.477 -48.086,112.55 -131.13,112.55 l -110.36,0 c -12.015,0 -20.761,8.739 -20.761,20.759 l 0,45.9 c 0,12.01 8.746,20.76 20.761,20.76 l 88.504,0 c 83.047,0 131.13,36.05 131.13,112.54 l 0,24.04 c 0,76.49 -45.891,115.83 -123.48,115.83 -62.278,0 -150.79,-18.57 -150.79,-18.57 -12.016,-2.19 -20.766,3.28 -20.766,15.3 l 0,49.16 c 0,12.03 5.473,17.49 20.766,20.76 0,0 64.472,20.76 152.98,20.76 137.68,0 214.17,-62.28 214.17,-203.24 l 0,-24.04 c 0,-71.02 -28.406,-119.1 -75.391,-149.7 59.008,-28.41 97.258,-81.943 97.258,-162.81 l 0,-46.992 c 0,-143.14 -81.965,-210.89 -229.48,-210.89"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path28"
|
||||
d="m 2272.9,1157.7 c 0,84.14 -39.34,163.9 -147.51,163.9 l -147.53,0 0,-600.98 147.53,0 c 108.17,0 147.51,79.762 147.51,163.9 l 0,273.18 z m -147.51,-524.51 -219.64,0 c -12.03,0 -20.76,8.742 -20.76,20.77 l 0,734.3 c 0,12.02 8.73,20.76 20.76,20.76 l 219.64,0 c 167.17,0 240.38,-105.99 240.38,-251.32 l 0,-273.18 c 0,-145.34 -73.21,-251.33 -240.38,-251.33"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path30"
|
||||
d="m 2837.8,633.2 c 0,0 -60.09,-10.918 -114.73,-10.918 -159.54,0 -231.65,105.99 -231.65,251.32 l 0,295.02 c 0,145.34 71.02,251.32 231.65,251.32 59,0 114.73,-12.01 114.73,-12.01 13.12,-3.28 19.67,-8.75 19.67,-20.76 l 0,-48.08 c 0,-12.03 -8.74,-17.49 -20.75,-16.4 0,0 -61.2,9.84 -110.37,9.84 -102.72,0 -142.06,-79.77 -142.06,-163.91 l 0,-295.02 c 0,-84.136 38.24,-163.91 142.06,-163.91 43.71,0 110.37,9.832 110.37,9.832 12.01,1.098 20.75,-4.379 20.75,-16.39 l 0,-49.172 c 0,-12.028 -6.55,-17.481 -19.67,-20.77"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path32"
|
||||
d="m 1059.6,1500.7 -78.255,0 c -2.71,0 -4.683,1.97 -4.683,4.69 l 0,165.88 c 0,2.71 1.973,4.68 4.683,4.68 l 78.255,0 c 2.72,0 4.7,-1.97 4.7,-4.68 l 0,-10.37 c 0,-2.72 -1.98,-4.69 -4.7,-4.69 l -61.958,0 0,-56.78 57.018,0 c 2.72,0 4.7,-1.97 4.7,-4.69 l 0,-10.36 c 0,-2.72 -1.98,-4.69 -4.7,-4.69 l -57.018,0 0,-59.25 61.958,0 c 2.72,0 4.7,-1.97 4.7,-4.69 l 0,-10.36 c 0,-2.72 -1.98,-4.69 -4.7,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path34"
|
||||
d="m 1210.1,1500.7 -13.08,0 c -2.72,0 -4.45,2.22 -5.69,4.69 l -64.18,124.65 0,-124.65 c 0,-2.72 -1.97,-4.69 -4.68,-4.69 l -11.61,0 c -2.72,0 -4.69,1.97 -4.69,4.69 l 0,165.88 c 0,2.71 1.97,4.68 4.69,4.68 l 12.85,0 c 3.2,0 4.43,-1.72 5.67,-4.19 l 64.43,-125.15 0,124.66 c 0,2.71 1.97,4.68 4.69,4.68 l 11.6,0 c 2.72,0 4.69,-1.97 4.69,-4.68 l 0,-165.88 c 0,-2.72 -1.97,-4.69 -4.69,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path36"
|
||||
d="m 1344.5,1500.7 -78.26,0 c -2.71,0 -4.68,1.97 -4.68,4.69 l 0,165.88 c 0,2.71 1.97,4.68 4.68,4.68 l 78.26,0 c 2.72,0 4.69,-1.97 4.69,-4.68 l 0,-10.37 c 0,-2.72 -1.97,-4.69 -4.69,-4.69 l -61.96,0 0,-56.78 57.02,0 c 2.72,0 4.69,-1.97 4.69,-4.69 l 0,-10.36 c 0,-2.72 -1.97,-4.69 -4.69,-4.69 l -57.02,0 0,-59.25 61.96,0 c 2.72,0 4.69,-1.97 4.69,-4.69 l 0,-10.36 c 0,-2.72 -1.97,-4.69 -4.69,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path38"
|
||||
d="m 1440.5,1656.2 -28.38,0 0,-61.71 28.38,0 c 21.99,0 33.34,11.84 33.34,30.85 0,19.01 -11.35,30.86 -33.34,30.86 z m 55.8,-155.51 -15.3,0 c -2.97,0 -4.7,2.46 -6.18,4.69 l -41.21,69.36 -21.49,0 0,-69.36 c 0,-2.72 -1.97,-4.69 -4.69,-4.69 l -11.6,0 c -2.71,0 -4.69,1.97 -4.69,4.69 l 0,165.88 c 0,2.71 1.98,4.68 4.69,4.68 l 44.67,0 c 35.56,0 54.32,-17.77 54.32,-50.6 0,-27.4 -12.83,-44.18 -37.52,-49.11 l 42.2,-70.85 c 1.49,-2.23 -0.49,-4.69 -3.2,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path40"
|
||||
d="m 1591,1498.2 c -37.77,0 -54.3,23.94 -54.3,56.78 l 0,61.71 c 0,37.51 18.76,61.7 59.24,61.7 21.97,0 39.99,-5.67 39.99,-5.67 2.96,-0.74 4.44,-1.98 4.44,-4.69 l 0,-11.11 c 0,-2.72 -1.98,-4.2 -4.7,-3.71 0,0 -22.21,5.44 -39.73,5.44 -27.39,0 -38.27,-18.27 -38.27,-41.96 l 0,-61.71 c 0,-19.01 8.89,-37.04 33.33,-37.04 20.74,0 33.33,6.91 33.33,6.91 l 0,52.34 -32.34,0 c -2.72,0 -4.69,1.98 -4.69,4.69 l 0,10.37 c 0,2.72 1.97,4.69 4.69,4.69 l 48.63,0 c 2.72,0 4.69,-1.97 4.69,-4.69 l 0,-79.24 c 0,0 -16.55,-14.81 -54.31,-14.81"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path42"
|
||||
d="m 1745.2,1561.2 0,-55.78 c 0,-2.72 -1.97,-4.69 -4.69,-4.69 l -11.6,0 c -2.72,0 -4.7,1.97 -4.7,4.69 l 0,55.78 -49.61,109.86 c -1.24,2.46 0.49,4.92 3.21,4.92 l 14.07,0 c 2.71,0 4.93,-2.22 5.92,-4.68 l 37.03,-85.41 36.78,85.41 c 0.98,2.46 3.21,4.68 5.93,4.68 l 14.07,0 c 2.72,0 4.43,-2.46 3.21,-4.92 L 1745.2,1561.2"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path44"
|
||||
d="m 1951.9,1498.2 c -19,0 -38.02,5.18 -38.02,5.18 -3.2,0.74 -4.68,2.23 -4.68,4.93 l 0,11.36 c 0,2.72 1.48,4.2 4.68,3.71 0,0 21.49,-5.44 36.05,-5.44 18.76,0 32.09,7.67 32.09,27.66 l 0,7.41 c 0,16.52 -8.88,21.71 -23.46,26.9 l -16.04,5.68 c -16.54,5.92 -32.08,15.04 -32.08,41.46 l 0,6.17 c 0,30.12 20.72,45.17 50.1,45.17 18.27,0 35.3,-4.19 35.3,-4.19 3.21,-0.74 4.69,-2.22 4.69,-4.94 l 0,-10.86 c 0,-2.71 -1.48,-4.2 -4.69,-3.69 0,0 -18.76,3.94 -34.8,3.94 -18.77,0 -29.63,-8.15 -29.63,-25.43 l 0,-6.17 c 0,-12.09 8.4,-18.02 19.75,-21.97 l 15.8,-5.68 c 18.02,-6.41 36.04,-16.29 36.04,-46.39 l 0,-7.41 c 0,-34.81 -20.74,-47.4 -51.1,-47.4"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path46"
|
||||
d="m 2138.9,1656.2 -39.01,0 0,-150.82 c 0,-2.72 -1.97,-4.69 -4.69,-4.69 l -11.6,0 c -2.72,0 -4.69,1.97 -4.69,4.69 l 0,150.82 -39.26,0 c -2.71,0 -4.68,1.97 -4.68,4.69 l 0,10.37 c 0,2.71 1.97,4.68 4.68,4.68 l 99.25,0 c 2.71,0 4.68,-1.97 4.68,-4.68 l 0,-10.37 c 0,-2.72 -1.97,-4.69 -4.68,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path48"
|
||||
d="m 2258.3,1621.6 c 0,19.01 -8.89,37.03 -33.33,37.03 -24.45,0 -33.33,-18.02 -33.33,-37.03 l 0,-66.64 c 0,-19.01 8.88,-37.04 33.33,-37.04 24.44,0 33.33,18.03 33.33,37.04 l 0,66.64 z m -33.33,-123.42 c -37.76,0 -54.31,23.94 -54.31,56.78 l 0,66.64 c 0,32.83 16.55,56.77 54.31,56.77 37.76,0 54.3,-23.94 54.3,-56.77 l 0,-66.64 c 0,-32.84 -16.54,-56.78 -54.3,-56.78"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path50"
|
||||
d="m 2375.4,1656.2 -28.38,0 0,-61.71 28.38,0 c 21.99,0 33.33,11.84 33.33,30.85 0,19.01 -11.34,30.86 -33.33,30.86 z m 55.81,-155.51 -15.31,0 c -2.97,0 -4.7,2.46 -6.18,4.69 l -41.21,69.36 -21.49,0 0,-69.36 c 0,-2.72 -1.97,-4.69 -4.69,-4.69 l -11.6,0 c -2.71,0 -4.69,1.97 -4.69,4.69 l 0,165.88 c 0,2.71 1.98,4.68 4.69,4.68 l 44.67,0 c 35.56,0 54.32,-17.77 54.32,-50.6 0,-27.4 -12.83,-44.18 -37.51,-49.11 l 42.19,-70.85 c 1.49,-2.23 -0.49,-4.69 -3.19,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path52"
|
||||
d="m 2525.4,1642.1 -27.16,-87.13 54.07,0 -26.91,87.13 z m 60.97,-141.44 -13.58,0 c -2.71,0 -4.44,1.97 -5.17,4.69 l -9.14,29.86 -66.4,0 -9.14,-29.86 c -0.74,-2.72 -2.47,-4.69 -5.19,-4.69 l -13.57,0 c -2.72,0 -4.2,1.97 -3.45,4.69 l 52.57,165.88 c 0.74,2.71 2.71,4.68 5.43,4.68 l 13.08,0 c 2.72,0 4.7,-1.97 5.44,-4.68 l 52.57,-165.88 c 0.75,-2.72 -0.74,-4.69 -3.45,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path54"
|
||||
d="m 2675.2,1498.2 c -37.77,0 -54.31,23.94 -54.31,56.78 l 0,61.71 c 0,37.51 18.77,61.7 59.25,61.7 21.97,0 39.99,-5.67 39.99,-5.67 2.96,-0.74 4.43,-1.98 4.43,-4.69 l 0,-11.11 c 0,-2.72 -1.97,-4.2 -4.69,-3.71 0,0 -22.21,5.44 -39.73,5.44 -27.4,0 -38.27,-18.27 -38.27,-41.96 l 0,-61.71 c 0,-19.01 8.88,-37.04 33.33,-37.04 20.73,0 33.33,6.91 33.33,6.91 l 0,52.34 -32.35,0 c -2.71,0 -4.69,1.98 -4.69,4.69 l 0,10.37 c 0,2.72 1.98,4.69 4.69,4.69 l 48.64,0 c 2.71,0 4.68,-1.97 4.68,-4.69 l 0,-79.24 c 0,0 -16.54,-14.81 -54.3,-14.81"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
<path
|
||||
id="path56"
|
||||
d="m 2859.2,1500.7 -78.25,0 c -2.73,0 -4.7,1.97 -4.7,4.69 l 0,165.88 c 0,2.71 1.97,4.68 4.7,4.68 l 78.25,0 c 2.71,0 4.69,-1.97 4.69,-4.68 l 0,-10.37 c 0,-2.72 -1.98,-4.69 -4.69,-4.69 l -61.96,0 0,-56.78 57.02,0 c 2.71,0 4.68,-1.97 4.68,-4.69 l 0,-10.36 c 0,-2.72 -1.97,-4.69 -4.68,-4.69 l -57.02,0 0,-59.25 61.96,0 c 2.71,0 4.69,-1.97 4.69,-4.69 l 0,-10.36 c 0,-2.72 -1.98,-4.69 -4.69,-4.69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5b5f63" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
BIN
bundles/org.openhab.binding.modbus.e3dc/doc/GrafanaPV.png
Normal file
BIN
bundles/org.openhab.binding.modbus.e3dc/doc/GrafanaPV.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
31
bundles/org.openhab.binding.modbus.e3dc/pom.xml
Normal file
31
bundles/org.openhab.binding.modbus.e3dc/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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.e3dc</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: E3DC Modbus 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>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.e3dc-${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>
|
||||
|
||||
<feature name="openhab-binding-modbus-e3dc" description="E3DC Modbus 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.e3dc/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* 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.e3dc.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.ModbusBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link E3DCBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = ModbusBindingConstants.BINDING_ID;
|
||||
|
||||
// Supported Thing Types
|
||||
public static final ThingTypeUID THING_TYPE_E3DC = new ThingTypeUID(BINDING_ID, "e3dc");
|
||||
public static final ThingTypeUID THING_TYPE_E3DC_WALLBOX = new ThingTypeUID(BINDING_ID, "e3dc-wallbox");
|
||||
|
||||
// Channels for Info Block
|
||||
public static final String MODBUS_ID_CHANNEL = "modbus-id";
|
||||
public static final String MODBUS_FIRMWARE_CHANNEL = "modbus-firmware";
|
||||
public static final String SUPPORTED_REGISTERS_CHANNEL = "supported-registers";
|
||||
public static final String MANUFACTURER_NAME_CHANNEL = "manufacturer-name";
|
||||
public static final String MODEL_NAME_CHANNEL = "model-name";
|
||||
public static final String SERIAL_NUMBER_CHANNEL = "serial-number";
|
||||
public static final String FIRMWARE_RELEASE_CHANNEL = "firmware-release";
|
||||
|
||||
// Channels for Power Block
|
||||
public static final String PV_POWER_SUPPLY_CHANNEL = "pv-power-supply";
|
||||
public static final String BATTERY_POWER_SUPPLY_CHANNEL = "battery-power-supply";
|
||||
public static final String BATTERY_POWER_CONSUMPTION = "battery-power-consumption";
|
||||
public static final String HOUSEHOLD_POWER_CONSUMPTION_CHANNEL = "household-power-consumption";
|
||||
public static final String GRID_POWER_CONSUMPTION_CHANNEL = "grid-power-consumption";
|
||||
public static final String GRID_POWER_SUPPLY_CHANNEL = "grid-power-supply";
|
||||
public static final String EXTERNAL_POWER_SUPPLY_CHANNEL = "external-power-supply";
|
||||
public static final String WALLBOX_POWER_CONSUMPTION_CHANNEL = "wallbox-power-consumption";
|
||||
public static final String WALLBOX_PV_POWER_CONSUMPTION_CHANNEL = "wallbox-pv-power-consumption";
|
||||
public static final String AUTARKY_CHANNEL = "autarky";
|
||||
public static final String SELF_CONSUMPTION_CHANNEL = "self-consumption";
|
||||
public static final String BATTERY_STATE_OF_CHARGE_CHANNEL = "battery-soc";
|
||||
|
||||
// Channels for Wallbox Block
|
||||
public static final String WB_AVAILABLE_CHANNEL = "wb-available";
|
||||
public static final String WB_SUNMODE_CHANNEL = "wb-sunmode";
|
||||
public static final String WB_CHARGING_ABORTED_CHANNEL = "wb-charging-aborted";
|
||||
public static final String WB_CHARGING_CHANNEL = "wb-charging";
|
||||
public static final String WB_JACK_LOCKED_CHANNEL = "wb-jack-locked";
|
||||
public static final String WB_JACK_PLUGGED_CHANNEL = "wb-jack-plugged";
|
||||
public static final String WB_SCHUKO_ON_CHANNEL = "wb-schuko-on";
|
||||
public static final String WB_SCHUKO_PLUGGED_CHANNEL = "wb-schuko-plugged";
|
||||
public static final String WB_SCHUKO_LOCKED_CHANNEL = "wb-schuko-locked";
|
||||
public static final String WB_SCHUKO_RELAY_16A_CHANNEL = "wb-schuko-relay-16a";
|
||||
public static final String WB_RELAY_16A_CHANNEL = "wb-relay-16a";
|
||||
public static final String WB_RELAY_32A_CHANNEL = "wb-relay-32a";
|
||||
public static final String WB_1PHASE_CHANNEL = "wb-1phase";
|
||||
|
||||
// Channels for String details
|
||||
public static final String STRING1_DC_VOLTAGE_CHANNEL = "string1-dc-voltage";
|
||||
public static final String STRING1_DC_CURRENT_CHANNEL = "string1-dc-current";
|
||||
public static final String STRING1_DC_OUTPUT_CHANNEL = "string1-dc-output";
|
||||
public static final String STRING2_DC_VOLTAGE_CHANNEL = "string2-dc-voltage";
|
||||
public static final String STRING2_DC_CURRENT_CHANNEL = "string2-dc-current";
|
||||
public static final String STRING2_DC_OUTPUT_CHANNEL = "string2-dc-output";
|
||||
public static final String STRING3_DC_VOLTAGE_CHANNEL = "string3-dc-voltage";
|
||||
public static final String STRING3_DC_CURRENT_CHANNEL = "string3-dc-current";
|
||||
public static final String STRING3_DC_OUTPUT_CHANNEL = "string3-dc-output";
|
||||
|
||||
// Channels for Emergency Status
|
||||
public static final String EMERGENCY_POWER_STATUS = "emergency-power-status";
|
||||
public static final String BATTERY_CHARGING_LOCKED = "battery-charging-lock";
|
||||
public static final String BATTERY_DISCHARGING_LOCKED = "battery-discharging-lock";
|
||||
public static final String EMERGENCY_POWER_POSSIBLE = "emergency-power-possible";
|
||||
public static final String WEATHER_PREDICTED_CHARGING = "weather-predicted-charging";
|
||||
public static final String REGULATION_STATUS = "regulation-status";
|
||||
public static final String CHARGE_LOCK_TIME = "charge-lock-time";
|
||||
public static final String DISCHARGE_LOCK_TIME = "discharge-lock-time";
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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.e3dc.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link E3DCConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCConfiguration {
|
||||
|
||||
/**
|
||||
* Data refresh interval
|
||||
*/
|
||||
public int refresh = 2000;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.e3dc.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.e3dc.internal.handler.E3DCThingHandler;
|
||||
import org.openhab.binding.modbus.e3dc.internal.handler.E3DCWallboxThingHandler;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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 E3DCHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.e3dc", service = ThingHandlerFactory.class)
|
||||
public class E3DCHandlerFactory extends BaseThingHandlerFactory {
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return (thingTypeUID.equals(E3DCBindingConstants.THING_TYPE_E3DC)
|
||||
|| thingTypeUID.equals(E3DCBindingConstants.THING_TYPE_E3DC_WALLBOX));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (E3DCBindingConstants.THING_TYPE_E3DC.equals(thingTypeUID)) {
|
||||
return new E3DCThingHandler((Bridge) thing);
|
||||
} else if (E3DCBindingConstants.THING_TYPE_E3DC_WALLBOX.equals(thingTypeUID)) {
|
||||
return new E3DCWallboxThingHandler(thing);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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.e3dc.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link E3DCWallboxConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCWallboxConfiguration {
|
||||
|
||||
/**
|
||||
* Wallbox ID
|
||||
*/
|
||||
public int wallboxId = -1;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 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.e3dc.internal.dto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link DataConverter} Helper class to convert bytes from modbus into desired data format
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DataConverter {
|
||||
private static final long MAX_INT32 = (long) Math.pow(2, Integer.SIZE);
|
||||
|
||||
/**
|
||||
* Get unit16 value from 2 bytes
|
||||
*
|
||||
* @param wrap
|
||||
* @return int
|
||||
*/
|
||||
public static int getUInt16Value(ByteBuffer wrap) {
|
||||
return Short.toUnsignedInt(wrap.getShort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unit32 value from 4 bytes
|
||||
*
|
||||
* @param wrap
|
||||
* @return long
|
||||
*/
|
||||
public static long getLongValue(ByteBuffer wrap) {
|
||||
return Integer.toUnsignedLong(wrap.getInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get double value from 2 bytes with correction factor
|
||||
*
|
||||
* @param wrap
|
||||
* @return double
|
||||
*/
|
||||
public static double getUDoubleValue(ByteBuffer wrap, double factor) {
|
||||
return round(getUInt16Value(wrap) * factor, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion done according to E3DC Modbus Specification V1.7
|
||||
*
|
||||
* @param wrap
|
||||
* @return decoded long value, Long.MIN_VALUE otherwise
|
||||
*/
|
||||
public static long getInt32Swap(ByteBuffer wrap) {
|
||||
long a = getUInt16Value(wrap);
|
||||
long b = getUInt16Value(wrap);
|
||||
if (b < 32768) {
|
||||
return b * 65536 + a;
|
||||
} else {
|
||||
return (MAX_INT32 - b * 65536 - a) * -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getString(byte[] bArray) {
|
||||
return new String(bArray, StandardCharsets.US_ASCII).trim();
|
||||
}
|
||||
|
||||
public static int toInt(BitSet bitSet) {
|
||||
int intValue = 0;
|
||||
for (int bit = 0; bit < bitSet.length(); bit++) {
|
||||
if (bitSet.get(bit)) {
|
||||
intValue |= (1 << bit);
|
||||
}
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
|
||||
public static double round(double value, int places) {
|
||||
if (places < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
long factor = (long) Math.pow(10, places);
|
||||
value = value * factor;
|
||||
long tmp = Math.round(value);
|
||||
return (double) tmp / factor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.e3dc.internal.dto;
|
||||
|
||||
import static org.openhab.binding.modbus.e3dc.internal.modbus.E3DCModbusConstans.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
||||
/**
|
||||
* The {@link EmergencyBlock} Data object for E3DC Info Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EmergencyBlock implements Data {
|
||||
public StringType epStatus = EP_UNKOWN;
|
||||
public OnOffType batteryChargingLocked = OnOffType.OFF;
|
||||
public OnOffType batteryDischargingLocked = OnOffType.OFF;
|
||||
public OnOffType epPossible = OnOffType.OFF;
|
||||
public OnOffType weatherPredictedCharging = OnOffType.OFF;
|
||||
public OnOffType regulationStatus = OnOffType.OFF;
|
||||
public OnOffType chargeLockTime = OnOffType.OFF;
|
||||
public OnOffType dischargeLockTime = OnOffType.OFF;
|
||||
|
||||
// Possible Status definitions according to chapter 3.1.2, Register 40084, page 14 & 15
|
||||
public static final StringType EP_NOT_SUPPORTED = StringType.valueOf("EP not supported");
|
||||
public static final StringType EP_ACTIVE = StringType.valueOf("EP active");
|
||||
public static final StringType EP_NOT_ACTIVE = StringType.valueOf("EP not active");
|
||||
public static final StringType EP_POSSIBLE = StringType.valueOf("EP possible");
|
||||
public static final StringType EP_SWITCH = StringType.valueOf("EP Switch in wrong position");
|
||||
public static final StringType EP_UNKOWN = StringType.valueOf("EP Status unknown");
|
||||
public static final StringType[] EP_STATUS_ARRAY = new StringType[] { EP_NOT_SUPPORTED, EP_ACTIVE, EP_NOT_ACTIVE,
|
||||
EP_POSSIBLE, EP_SWITCH };
|
||||
|
||||
/**
|
||||
* For decoding see Modbus Register Mapping Chapter 3.1.2 page 14 & 15
|
||||
*
|
||||
* @param bArray - Modbus Registers as bytes from 40084 to 40085
|
||||
*/
|
||||
public EmergencyBlock(byte[] bArray) {
|
||||
// uint16 status register 40084 - possible Status Strings are defined in Constants above
|
||||
int status = DataConverter.getUInt16Value(ByteBuffer.wrap(bArray));
|
||||
if (status >= 0 && status < 5) {
|
||||
epStatus = EP_STATUS_ARRAY[status];
|
||||
} else {
|
||||
epStatus = EP_UNKOWN;
|
||||
}
|
||||
|
||||
// uint16 status register 40085 shall be handled as Bits - check cahpter 3.1.3 page 17
|
||||
byte[] emsStatusBytes = new byte[] { bArray[3], bArray[2] };
|
||||
BitSet bs = BitSet.valueOf(emsStatusBytes);
|
||||
batteryChargingLocked = OnOffType.from(bs.get(EMS_CHARGING_LOCK_BIT));
|
||||
batteryDischargingLocked = OnOffType.from(bs.get(EMS_DISCHARGING_LOCK_BIT));
|
||||
epPossible = OnOffType.from(bs.get(EMS_DISCHARGING_LOCK_BIT));
|
||||
weatherPredictedCharging = OnOffType.from(bs.get(EMS_WEATHER_CHARGING_BIT));
|
||||
regulationStatus = OnOffType.from(bs.get(EMS_REGULATION_BIT));
|
||||
chargeLockTime = OnOffType.from(bs.get(EMS_CHARGE_LOCKTIME_BIT));
|
||||
dischargeLockTime = OnOffType.from(bs.get(EMS_DISCHARGE_LOCKTIME_BIT));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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.e3dc.internal.dto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
|
||||
/**
|
||||
* The {@link InfoBlock} Data object for E3DC Info Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class InfoBlock implements Data {
|
||||
private static final StringType EMPTY = new StringType("NULL");
|
||||
public StringType modbusId = EMPTY;
|
||||
public StringType modbusVersion = EMPTY;
|
||||
public DecimalType supportedRegisters = new DecimalType(-1);
|
||||
public StringType manufacturer = EMPTY;
|
||||
public StringType modelName = EMPTY;
|
||||
public StringType serialNumber = EMPTY;
|
||||
public StringType firmware = EMPTY;
|
||||
|
||||
/**
|
||||
* For decoding see Modbus Register Mapping Chapter 3.1.1 page 14
|
||||
*
|
||||
* @param bArray - Modbus Registers as bytes from 40001 to 40067
|
||||
*/
|
||||
public InfoBlock(byte[] bArray) {
|
||||
// index handling to calculate the correct start index
|
||||
ByteBuffer wrapper = ByteBuffer.wrap(bArray);
|
||||
|
||||
// first uint16 = 2 bytes - decode magic byte
|
||||
byte[] magicBytes = new byte[2];
|
||||
wrapper.get(magicBytes);
|
||||
this.modbusId = new StringType(HexUtils.bytesToHex(magicBytes));
|
||||
// first uint16 = 2 bytes - decode magic byte
|
||||
|
||||
// unit8 (Modbus Major Version) + uint8 Modbus minor Version
|
||||
String modbusVersion = wrapper.get() + "." + wrapper.get();
|
||||
this.modbusVersion = new StringType(modbusVersion);
|
||||
|
||||
// unit16 - supported registers
|
||||
short supportedRegisters = wrapper.getShort();
|
||||
this.supportedRegisters = new DecimalType(supportedRegisters);
|
||||
|
||||
byte[] buffer = new byte[32];
|
||||
// 16 registers with uint16 = 32 bytes to decode a proper String
|
||||
wrapper.get(buffer);
|
||||
String manufacturer = DataConverter.getString(buffer);
|
||||
this.manufacturer = new StringType(manufacturer);
|
||||
|
||||
// 16 registers with uint16 = 32 bytes to decode a proper String
|
||||
wrapper.get(buffer);
|
||||
String model = DataConverter.getString(buffer);
|
||||
this.modelName = new StringType(model);
|
||||
|
||||
// 16 registers with uint16 = 32 bytes to decode a proper String
|
||||
wrapper.get(buffer);
|
||||
String serialNumber = DataConverter.getString(buffer);
|
||||
this.serialNumber = new StringType(serialNumber);
|
||||
|
||||
// 16 registers with uint16 = 32 bytes to decode a proper String
|
||||
wrapper.get(buffer);
|
||||
String firmware = DataConverter.getString(buffer);
|
||||
this.firmware = new StringType(firmware);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.e3dc.internal.dto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Power;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
|
||||
/**
|
||||
* The {@link PowerBlock} Data object for E3DC Info Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowerBlock implements Data {
|
||||
public QuantityType<Power> pvPowerSupply;
|
||||
public QuantityType<Power> batteryPowerSupply;
|
||||
public QuantityType<Power> batteryPowerConsumption;
|
||||
public QuantityType<Power> householdPowerConsumption;
|
||||
public QuantityType<Power> gridPowerConsumpition;
|
||||
public QuantityType<Power> gridPowerSupply;
|
||||
public QuantityType<Power> externalPowerSupply;
|
||||
public QuantityType<Power> wallboxPowerConsumption;
|
||||
public QuantityType<Power> wallboxPVPowerConsumption;
|
||||
public QuantityType<Dimensionless> autarky;
|
||||
public QuantityType<Dimensionless> selfConsumption;
|
||||
public QuantityType<Dimensionless> batterySOC;
|
||||
|
||||
/**
|
||||
* For decoding see Modbus Register Mapping Chapter 3.1.2 page 14
|
||||
*
|
||||
* @param bArray - Modbus Registers as bytes from 40067 to 40083
|
||||
*/
|
||||
public PowerBlock(byte[] bArray) {
|
||||
// index handling to calculate the correct start index
|
||||
ByteBuffer wrap = ByteBuffer.wrap(bArray);
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
long pvPowerSupplyL = DataConverter.getInt32Swap(wrap);
|
||||
|
||||
/*
|
||||
* int32_swap value don't provide negative values!
|
||||
* Positive value - Battery is charging = Power consumer
|
||||
* Negative value - Battery is discharging = Power supplier
|
||||
*/
|
||||
pvPowerSupply = QuantityType.valueOf(pvPowerSupplyL, SmartHomeUnits.WATT);
|
||||
long batteryPower = DataConverter.getInt32Swap(wrap);
|
||||
if (batteryPower > 0) {
|
||||
// Battery is charging so Power is consumed by Battery
|
||||
batteryPowerSupply = QuantityType.valueOf(0, SmartHomeUnits.WATT);
|
||||
batteryPowerConsumption = QuantityType.valueOf(batteryPower, SmartHomeUnits.WATT);
|
||||
} else {
|
||||
// Battery is discharging so Power is provided by Battery
|
||||
batteryPowerSupply = QuantityType.valueOf(batteryPower * -1, SmartHomeUnits.WATT);
|
||||
batteryPowerConsumption = QuantityType.valueOf(0, SmartHomeUnits.WATT);
|
||||
}
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
long householdPowerConsumptionL = DataConverter.getInt32Swap(wrap);
|
||||
householdPowerConsumption = QuantityType.valueOf(householdPowerConsumptionL, SmartHomeUnits.WATT);
|
||||
|
||||
/*
|
||||
* int32_swap value don't provide negative values!
|
||||
* Positive value - Power provided towards Grid = Power consumer
|
||||
* Negative value - Power requested from Grid = Power supplier
|
||||
*/
|
||||
long gridPower = DataConverter.getInt32Swap(wrap);
|
||||
if (gridPower > 0) {
|
||||
// Power is provided by Grid
|
||||
gridPowerSupply = QuantityType.valueOf(gridPower, SmartHomeUnits.WATT);
|
||||
gridPowerConsumpition = QuantityType.valueOf(0, SmartHomeUnits.WATT);
|
||||
} else {
|
||||
// Power is consumed by Grid
|
||||
gridPowerConsumpition = QuantityType.valueOf(gridPower * -1, SmartHomeUnits.WATT);
|
||||
gridPowerSupply = QuantityType.valueOf(0, SmartHomeUnits.WATT);
|
||||
}
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
externalPowerSupply = QuantityType.valueOf(DataConverter.getInt32Swap(wrap), SmartHomeUnits.WATT);
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
wallboxPowerConsumption = QuantityType.valueOf(DataConverter.getInt32Swap(wrap), SmartHomeUnits.WATT);
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
wallboxPVPowerConsumption = QuantityType.valueOf(DataConverter.getInt32Swap(wrap), SmartHomeUnits.WATT);
|
||||
|
||||
// unit8 + uint8 - one register with split value for Autarky & Self Consumption
|
||||
autarky = QuantityType.valueOf(wrap.get(), SmartHomeUnits.PERCENT);
|
||||
selfConsumption = QuantityType.valueOf(wrap.get(), SmartHomeUnits.PERCENT);
|
||||
|
||||
// uint16 for Battery State of Charge
|
||||
batterySOC = QuantityType.valueOf(wrap.getShort(), SmartHomeUnits.PERCENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.e3dc.internal.dto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.measure.quantity.ElectricCurrent;
|
||||
import javax.measure.quantity.ElectricPotential;
|
||||
import javax.measure.quantity.Power;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
|
||||
/**
|
||||
* The {@link StringBlock} Data object for E3DC Info Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class StringBlock implements Data {
|
||||
public QuantityType<ElectricPotential> string1Volt;
|
||||
public QuantityType<ElectricPotential> string2Volt;
|
||||
public QuantityType<ElectricPotential> string3Volt;
|
||||
public QuantityType<ElectricCurrent> string1Ampere;
|
||||
public QuantityType<ElectricCurrent> string2Ampere;
|
||||
public QuantityType<ElectricCurrent> string3Ampere;
|
||||
public QuantityType<Power> string1Watt;
|
||||
public QuantityType<Power> string2Watt;
|
||||
public QuantityType<Power> string3Watt;
|
||||
|
||||
/**
|
||||
* For decoding see Modbus Register Mapping Chapter 3.1.2 page 14-16
|
||||
*
|
||||
* @param bArray - Modbus Registers as bytes from 40096 to 40104
|
||||
*/
|
||||
public StringBlock(byte[] bArray) {
|
||||
ByteBuffer wrap = ByteBuffer.wrap(bArray);
|
||||
// straight forward - for each String the values Volt, Ampere and then Watt. All unt16 = 2 bytes values
|
||||
string1Volt = QuantityType.valueOf(DataConverter.getUInt16Value(wrap), SmartHomeUnits.VOLT);
|
||||
string2Volt = QuantityType.valueOf(DataConverter.getUInt16Value(wrap), SmartHomeUnits.VOLT);
|
||||
string3Volt = QuantityType.valueOf(DataConverter.getUInt16Value(wrap), SmartHomeUnits.VOLT);
|
||||
// E3DC Modbus Spec chapter 3.1.2, page 16 - Ampere values shall be handled with factor 0.01
|
||||
string1Ampere = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.01), SmartHomeUnits.AMPERE);
|
||||
string2Ampere = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.01), SmartHomeUnits.AMPERE);
|
||||
string3Ampere = QuantityType.valueOf(DataConverter.getUDoubleValue(wrap, 0.01), SmartHomeUnits.AMPERE);
|
||||
string1Watt = QuantityType.valueOf(DataConverter.getUInt16Value(wrap), SmartHomeUnits.WATT);
|
||||
string2Watt = QuantityType.valueOf(DataConverter.getUInt16Value(wrap), SmartHomeUnits.WATT);
|
||||
string3Watt = QuantityType.valueOf(DataConverter.getUInt16Value(wrap), SmartHomeUnits.WATT);
|
||||
}
|
||||
}
|
||||
@@ -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.modbus.e3dc.internal.dto;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
|
||||
/**
|
||||
* The {@link WallboxArray} Data object for E3DC Info Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WallboxArray implements Data {
|
||||
private byte[] wbArray;
|
||||
|
||||
/**
|
||||
* For decoding see Modbus Register Mapping Chapter 3.1.2 page 15
|
||||
* The Registers for Wallbox Control are declared as uint16 but shall be handled as Bit registers => see chapter
|
||||
* 3.1.5 page 19
|
||||
*
|
||||
* @param bArray - Modbus Registers as bytes from 40088 to 40095
|
||||
*/
|
||||
public WallboxArray(byte[] bArray) {
|
||||
wbArray = bArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 2 bytes according to the Wallbox ID.
|
||||
*
|
||||
* @param id Wallbox ID valid from 0 - 7
|
||||
* @return WallboxBlock initialized with the Modbus registers from the given ID
|
||||
*/
|
||||
public Optional<WallboxBlock> getWallboxBlock(int id) {
|
||||
if (id >= 0 && id < 8) {
|
||||
int byteIndex = id * 2;
|
||||
return Optional.of(new WallboxBlock(new byte[] { wbArray[byteIndex + 1], wbArray[byteIndex * 2] }));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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.e3dc.internal.dto;
|
||||
|
||||
import static org.openhab.binding.modbus.e3dc.internal.modbus.E3DCModbusConstans.*;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
||||
/**
|
||||
* The {@link WallboxBlock} Data object for E3DC Info Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class WallboxBlock implements Data {
|
||||
private BitSet bitSet;
|
||||
public OnOffType wbAvailable = OnOffType.OFF;
|
||||
public OnOffType wbSunmode = OnOffType.OFF;
|
||||
public OnOffType wbChargingAborted = OnOffType.OFF;
|
||||
public OnOffType wbCharging = OnOffType.OFF;
|
||||
public OnOffType wbJackLocked = OnOffType.OFF;
|
||||
public OnOffType wbJackPlugged = OnOffType.OFF;
|
||||
public OnOffType wbSchukoOn = OnOffType.OFF;
|
||||
public OnOffType wbSchukoPlugged = OnOffType.OFF;
|
||||
public OnOffType wbSchukoLocked = OnOffType.OFF;
|
||||
public OnOffType wbSchukoRelay16 = OnOffType.OFF;
|
||||
public OnOffType wbRelay16 = OnOffType.OFF;
|
||||
public OnOffType wbRelay32 = OnOffType.OFF;
|
||||
public OnOffType wb1phase = OnOffType.OFF;
|
||||
|
||||
/**
|
||||
* For decoding see Modbus Register Mapping Chapter 3.1.2 page 15
|
||||
* The Registers for Wallbox Control are declared as uint16 but shall be handled as Bit registers => see chapter
|
||||
* 3.1.5 page 19
|
||||
*
|
||||
* @param bArray - one Modbus Registers according to Wallbox ID
|
||||
*/
|
||||
public WallboxBlock(byte[] bArray) {
|
||||
bitSet = BitSet.valueOf(bArray);
|
||||
wbAvailable = OnOffType.from(bitSet.get(WB_AVAILABLE_BIT));
|
||||
wbSunmode = OnOffType.from(bitSet.get(WB_SUNMODE_BIT));
|
||||
wbChargingAborted = OnOffType.from(bitSet.get(WB_CHARGING_ABORTED_BIT));
|
||||
wbCharging = OnOffType.from(bitSet.get(WB_CHARGING_BIT));
|
||||
wbJackLocked = OnOffType.from(bitSet.get(WB_JACK_LOCKED_BIT));
|
||||
wbJackPlugged = OnOffType.from(bitSet.get(WB_JACK_PLUGGED_BIT));
|
||||
wbSchukoOn = OnOffType.from(bitSet.get(WB_SCHUKO_ON_BIT));
|
||||
wbSchukoPlugged = OnOffType.from(bitSet.get(WB_SCHUKO_PLUGGED_BIT));
|
||||
wbSchukoLocked = OnOffType.from(bitSet.get(WB_SCHUKO_LOCKED_BIT));
|
||||
wbSchukoRelay16 = OnOffType.from(bitSet.get(WB_SCHUKO_RELAY16A_BIT));
|
||||
wbRelay16 = OnOffType.from(bitSet.get(WB_RELAY_16A_BIT));
|
||||
wbRelay32 = OnOffType.from(bitSet.get(WB_RELAY_32A_BIT));
|
||||
wb1phase = OnOffType.from(bitSet.get(WB_1PHASE_BIT));
|
||||
}
|
||||
|
||||
public BitSet getBitSet() {
|
||||
return bitSet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,450 @@
|
||||
/**
|
||||
* 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.e3dc.internal.handler;
|
||||
|
||||
import static org.openhab.binding.modbus.e3dc.internal.E3DCBindingConstants.*;
|
||||
import static org.openhab.binding.modbus.e3dc.internal.modbus.E3DCModbusConstans.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.e3dc.internal.E3DCConfiguration;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.EmergencyBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.InfoBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.PowerBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.StringBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
|
||||
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.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
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.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link E3DCThingHandler} Basic modbus connection towards the E3DC device
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCThingHandler extends BaseBridgeHandler {
|
||||
public enum ReadStatus {
|
||||
NOT_RECEIVED,
|
||||
READ_SUCCESS,
|
||||
READ_FAILED
|
||||
}
|
||||
|
||||
static final String INFO_DATA_READ_ERROR = "Information And Data Modbus Read Errors";
|
||||
static final String INFO_READ_ERROR = "Information Modbus Read Error";
|
||||
static final String DATA_READ_ERROR = "Data Modbus Read Error";
|
||||
|
||||
static final String INFO_GROUP = "info";
|
||||
static final String EMERGENCY_GROUP = "emergency";
|
||||
static final String POWER_GROUP = "power";
|
||||
static final String STRINGS_GROUP = "strings";
|
||||
|
||||
private ChannelUID modbusIdChannel;
|
||||
private ChannelUID modbusVersionChannel;
|
||||
private ChannelUID supportedRegistersChannel;
|
||||
private ChannelUID manufacturerChannel;
|
||||
private ChannelUID modelNameChannel;
|
||||
private ChannelUID serialNumberChannel;
|
||||
private ChannelUID firmwareChannel;
|
||||
|
||||
private ChannelUID epStatusChannel;
|
||||
private ChannelUID batteryChargingLockedChannel;
|
||||
private ChannelUID batteryDischargingLockedChannel;
|
||||
private ChannelUID epPossibleChannel;
|
||||
private ChannelUID weatherPredictedChargingChannel;
|
||||
private ChannelUID regulationStatusChannel;
|
||||
private ChannelUID chargeLockTimeChannel;
|
||||
private ChannelUID dischargeLockTimeChannel;
|
||||
|
||||
private ChannelUID pvPowerSupplyChannel;
|
||||
private ChannelUID batteryPowerSupplyChannel;
|
||||
private ChannelUID batteryPowerConsumptionChannel;
|
||||
private ChannelUID householdPowerConsumptionChannel;
|
||||
private ChannelUID gridPowerConsumpitionChannel;
|
||||
private ChannelUID gridPowerSupplyChannel;
|
||||
private ChannelUID externalPowerSupplyChannel;
|
||||
private ChannelUID wallboxPowerConsumptionChannel;
|
||||
private ChannelUID wallboxPVPowerConsumptionChannel;
|
||||
private ChannelUID autarkyChannel;
|
||||
private ChannelUID selfConsumptionChannel;
|
||||
private ChannelUID batterySOCChannel;
|
||||
|
||||
private ChannelUID string1AmpereChannel;
|
||||
private ChannelUID string1VoltChannel;
|
||||
private ChannelUID string1WattChannel;
|
||||
private ChannelUID string2AmpereChannel;
|
||||
private ChannelUID string2VoltChannel;
|
||||
private ChannelUID string2WattChannel;
|
||||
private ChannelUID string3AmpereChannel;
|
||||
private ChannelUID string3VoltChannel;
|
||||
private ChannelUID string3WattChannel;
|
||||
|
||||
private final ArrayList<E3DCWallboxThingHandler> listeners = new ArrayList<E3DCWallboxThingHandler>();
|
||||
private final Logger logger = LoggerFactory.getLogger(E3DCThingHandler.class);
|
||||
private final Parser dataParser = new Parser(DataType.DATA);
|
||||
private ReadStatus dataRead = ReadStatus.NOT_RECEIVED;
|
||||
private final Parser infoParser = new Parser(DataType.INFO);
|
||||
private ReadStatus infoRead = ReadStatus.NOT_RECEIVED;
|
||||
private @Nullable PollTask infoPoller;
|
||||
private @Nullable PollTask dataPoller;
|
||||
private @Nullable E3DCConfiguration config;
|
||||
|
||||
/**
|
||||
* Communication interface to the slave endpoint we're connecting to
|
||||
*/
|
||||
protected volatile @Nullable ModbusCommunicationInterface comms = null;
|
||||
private int slaveId;
|
||||
|
||||
public E3DCThingHandler(Bridge thing) {
|
||||
super(thing);
|
||||
|
||||
modbusIdChannel = channelUID(thing, INFO_GROUP, MODBUS_ID_CHANNEL);
|
||||
modbusVersionChannel = channelUID(thing, INFO_GROUP, MODBUS_FIRMWARE_CHANNEL);
|
||||
supportedRegistersChannel = channelUID(thing, INFO_GROUP, SUPPORTED_REGISTERS_CHANNEL);
|
||||
manufacturerChannel = channelUID(thing, INFO_GROUP, MANUFACTURER_NAME_CHANNEL);
|
||||
modelNameChannel = channelUID(thing, INFO_GROUP, MODEL_NAME_CHANNEL);
|
||||
serialNumberChannel = channelUID(thing, INFO_GROUP, SERIAL_NUMBER_CHANNEL);
|
||||
firmwareChannel = channelUID(thing, INFO_GROUP, FIRMWARE_RELEASE_CHANNEL);
|
||||
|
||||
epStatusChannel = channelUID(thing, EMERGENCY_GROUP, EMERGENCY_POWER_STATUS);
|
||||
batteryChargingLockedChannel = channelUID(thing, EMERGENCY_GROUP, BATTERY_CHARGING_LOCKED);
|
||||
batteryDischargingLockedChannel = channelUID(thing, EMERGENCY_GROUP, BATTERY_DISCHARGING_LOCKED);
|
||||
epPossibleChannel = channelUID(thing, EMERGENCY_GROUP, EMERGENCY_POWER_POSSIBLE);
|
||||
weatherPredictedChargingChannel = channelUID(thing, EMERGENCY_GROUP, WEATHER_PREDICTED_CHARGING);
|
||||
regulationStatusChannel = channelUID(thing, EMERGENCY_GROUP, REGULATION_STATUS);
|
||||
chargeLockTimeChannel = channelUID(thing, EMERGENCY_GROUP, CHARGE_LOCK_TIME);
|
||||
dischargeLockTimeChannel = channelUID(thing, EMERGENCY_GROUP, DISCHARGE_LOCK_TIME);
|
||||
|
||||
pvPowerSupplyChannel = channelUID(thing, POWER_GROUP, PV_POWER_SUPPLY_CHANNEL);
|
||||
batteryPowerSupplyChannel = channelUID(thing, POWER_GROUP, BATTERY_POWER_SUPPLY_CHANNEL);
|
||||
batteryPowerConsumptionChannel = channelUID(thing, POWER_GROUP, BATTERY_POWER_CONSUMPTION);
|
||||
householdPowerConsumptionChannel = channelUID(thing, POWER_GROUP, HOUSEHOLD_POWER_CONSUMPTION_CHANNEL);
|
||||
gridPowerConsumpitionChannel = channelUID(thing, POWER_GROUP, GRID_POWER_CONSUMPTION_CHANNEL);
|
||||
gridPowerSupplyChannel = channelUID(thing, POWER_GROUP, GRID_POWER_SUPPLY_CHANNEL);
|
||||
externalPowerSupplyChannel = channelUID(thing, POWER_GROUP, EXTERNAL_POWER_SUPPLY_CHANNEL);
|
||||
wallboxPowerConsumptionChannel = channelUID(thing, POWER_GROUP, WALLBOX_POWER_CONSUMPTION_CHANNEL);
|
||||
wallboxPVPowerConsumptionChannel = channelUID(thing, POWER_GROUP, WALLBOX_PV_POWER_CONSUMPTION_CHANNEL);
|
||||
autarkyChannel = channelUID(thing, POWER_GROUP, AUTARKY_CHANNEL);
|
||||
selfConsumptionChannel = channelUID(thing, POWER_GROUP, SELF_CONSUMPTION_CHANNEL);
|
||||
batterySOCChannel = channelUID(thing, POWER_GROUP, BATTERY_STATE_OF_CHARGE_CHANNEL);
|
||||
|
||||
string1AmpereChannel = channelUID(thing, STRINGS_GROUP, STRING1_DC_CURRENT_CHANNEL);
|
||||
string1VoltChannel = channelUID(thing, STRINGS_GROUP, STRING1_DC_VOLTAGE_CHANNEL);
|
||||
string1WattChannel = channelUID(thing, STRINGS_GROUP, STRING1_DC_OUTPUT_CHANNEL);
|
||||
string2AmpereChannel = channelUID(thing, STRINGS_GROUP, STRING2_DC_CURRENT_CHANNEL);
|
||||
string2VoltChannel = channelUID(thing, STRINGS_GROUP, STRING2_DC_VOLTAGE_CHANNEL);
|
||||
string2WattChannel = channelUID(thing, STRINGS_GROUP, STRING2_DC_OUTPUT_CHANNEL);
|
||||
string3AmpereChannel = channelUID(thing, STRINGS_GROUP, STRING3_DC_CURRENT_CHANNEL);
|
||||
string3VoltChannel = channelUID(thing, STRINGS_GROUP, STRING3_DC_VOLTAGE_CHANNEL);
|
||||
string3WattChannel = channelUID(thing, STRINGS_GROUP, STRING3_DC_OUTPUT_CHANNEL);
|
||||
}
|
||||
|
||||
public @Nullable ModbusCommunicationInterface getComms() {
|
||||
return comms;
|
||||
}
|
||||
|
||||
public int getSlaveId() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// no control of E3DC device possible yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
scheduler.execute(() -> {
|
||||
E3DCConfiguration localConfig = getConfigAs(E3DCConfiguration.class);
|
||||
config = localConfig;
|
||||
ModbusCommunicationInterface localComms = connectEndpoint();
|
||||
if (localComms != null) {
|
||||
// register low speed info poller
|
||||
ModbusReadRequestBlueprint infoRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, INFO_REG_START, INFO_REG_SIZE, 3);
|
||||
infoPoller = localComms.registerRegularPoll(infoRequest, INFO_POLL_REFRESH_TIME_MS, 0,
|
||||
this::handleInfoResult, this::handleInfoFailure);
|
||||
|
||||
ModbusReadRequestBlueprint dataRequest = new ModbusReadRequestBlueprint(slaveId,
|
||||
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, POWER_REG_START,
|
||||
REGISTER_LENGTH - INFO_REG_SIZE, 3);
|
||||
if (config != null) {
|
||||
dataPoller = localComms.registerRegularPoll(dataRequest, localConfig.refresh, 0,
|
||||
this::handleDataResult, this::handleDataFailure);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"E3DC Configuration missing");
|
||||
}
|
||||
} // else state handling performed in connectEndPoint function
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the modbus endpoint
|
||||
*/
|
||||
private @Nullable ModbusCommunicationInterface connectEndpoint() {
|
||||
if (comms != null) {
|
||||
return comms;
|
||||
}
|
||||
|
||||
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));
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
slaveId = slaveEndpointThingHandler.getSlaveId();
|
||||
comms = slaveEndpointThingHandler.getCommunicationInterface();
|
||||
} catch (EndpointNotInitializedException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Slave Endpoint not initialized"));
|
||||
return null;
|
||||
}
|
||||
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));
|
||||
return null;
|
||||
} else {
|
||||
return comms;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel UID for the specified group and channel id
|
||||
*
|
||||
* @param string the channel group
|
||||
* @param string the channel id in that group
|
||||
* @return the globally unique channel uid
|
||||
*/
|
||||
private ChannelUID channelUID(Thing t, String group, String id) {
|
||||
return new ChannelUID(t.getUID(), group, id);
|
||||
}
|
||||
|
||||
void handleInfoResult(AsyncModbusReadResult result) {
|
||||
if (infoRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
infoRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
infoParser.handle(result);
|
||||
Optional<Data> blockOpt = infoParser.parse(DataType.INFO);
|
||||
if (blockOpt.isPresent()) {
|
||||
InfoBlock block = (InfoBlock) blockOpt.get();
|
||||
updateState(modbusIdChannel, block.modbusId);
|
||||
updateState(modbusVersionChannel, block.modbusVersion);
|
||||
updateState(supportedRegistersChannel, block.supportedRegisters);
|
||||
updateState(manufacturerChannel, block.manufacturer);
|
||||
updateState(modelNameChannel, block.modelName);
|
||||
updateState(serialNumberChannel, block.serialNumber);
|
||||
updateState(firmwareChannel, block.firmware);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", DataType.INFO, dataParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void handleInfoFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (infoRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
infoRead = ReadStatus.READ_FAILED;
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void handleDataResult(AsyncModbusReadResult result) {
|
||||
if (dataRead != ReadStatus.READ_SUCCESS) {
|
||||
// update status only if bit switches
|
||||
dataRead = ReadStatus.READ_SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
dataParser.handle(result);
|
||||
// Update channels in emergency group
|
||||
{
|
||||
Optional<Data> blockOpt = dataParser.parse(DataType.EMERGENCY);
|
||||
if (blockOpt.isPresent()) {
|
||||
EmergencyBlock block = (EmergencyBlock) blockOpt.get();
|
||||
updateState(epStatusChannel, block.epStatus);
|
||||
updateState(batteryChargingLockedChannel, block.batteryChargingLocked);
|
||||
updateState(batteryDischargingLockedChannel, block.batteryDischargingLocked);
|
||||
updateState(epPossibleChannel, block.epPossible);
|
||||
updateState(weatherPredictedChargingChannel, block.weatherPredictedCharging);
|
||||
updateState(regulationStatusChannel, block.regulationStatus);
|
||||
updateState(chargeLockTimeChannel, block.chargeLockTime);
|
||||
updateState(dischargeLockTimeChannel, block.dischargeLockTime);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", DataType.EMERGENCY, dataParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Update channels in power group
|
||||
{
|
||||
Optional<Data> blockOpt = dataParser.parse(DataType.POWER);
|
||||
if (blockOpt.isPresent()) {
|
||||
PowerBlock block = (PowerBlock) blockOpt.get();
|
||||
updateState(pvPowerSupplyChannel, block.pvPowerSupply);
|
||||
updateState(batteryPowerSupplyChannel, block.batteryPowerSupply);
|
||||
updateState(batteryPowerConsumptionChannel, block.batteryPowerConsumption);
|
||||
updateState(householdPowerConsumptionChannel, block.householdPowerConsumption);
|
||||
updateState(gridPowerConsumpitionChannel, block.gridPowerConsumpition);
|
||||
updateState(gridPowerSupplyChannel, block.gridPowerSupply);
|
||||
updateState(externalPowerSupplyChannel, block.externalPowerSupply);
|
||||
updateState(wallboxPowerConsumptionChannel, block.wallboxPowerConsumption);
|
||||
updateState(wallboxPVPowerConsumptionChannel, block.wallboxPVPowerConsumption);
|
||||
updateState(autarkyChannel, block.autarky);
|
||||
updateState(selfConsumptionChannel, block.selfConsumption);
|
||||
updateState(batterySOCChannel, block.batterySOC);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", DataType.POWER, dataParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Update channels in strings group
|
||||
{
|
||||
Optional<Data> blockOpt = dataParser.parse(DataType.STRINGS);
|
||||
if (blockOpt.isPresent()) {
|
||||
StringBlock block = (StringBlock) blockOpt.get();
|
||||
updateState(string1AmpereChannel, block.string1Ampere);
|
||||
updateState(string1VoltChannel, block.string1Volt);
|
||||
updateState(string1WattChannel, block.string1Watt);
|
||||
updateState(string2AmpereChannel, block.string2Ampere);
|
||||
updateState(string2VoltChannel, block.string2Volt);
|
||||
updateState(string2WattChannel, block.string2Watt);
|
||||
updateState(string3AmpereChannel, block.string3Ampere);
|
||||
updateState(string3VoltChannel, block.string3Volt);
|
||||
updateState(string3WattChannel, block.string3Watt);
|
||||
} else {
|
||||
logger.debug("Unable to get {} from provider {}", DataType.STRINGS, dataParser.toString());
|
||||
}
|
||||
}
|
||||
|
||||
listeners.forEach(l -> {
|
||||
l.handle(result);
|
||||
});
|
||||
}
|
||||
|
||||
void handleDataFailure(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (dataRead != ReadStatus.READ_FAILED) {
|
||||
// update status only if bit switches
|
||||
dataRead = ReadStatus.READ_FAILED;
|
||||
updateStatus();
|
||||
}
|
||||
listeners.forEach(l -> {
|
||||
l.handleError(result);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ModbusCommunicationInterface localComms = comms;
|
||||
if (localComms != null) {
|
||||
PollTask localInfoPoller = infoPoller;
|
||||
if (localInfoPoller != null) {
|
||||
localComms.unregisterRegularPoll(localInfoPoller);
|
||||
}
|
||||
PollTask localDataPoller = dataPoller;
|
||||
if (localDataPoller != null) {
|
||||
localComms.unregisterRegularPoll(localDataPoller);
|
||||
}
|
||||
}
|
||||
// Comms will be close()'d by endpoint thing handler
|
||||
comms = null;
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
logger.debug("Status update: Info {} Data {} ", infoRead, dataRead);
|
||||
if (infoRead != ReadStatus.NOT_RECEIVED && dataRead != ReadStatus.NOT_RECEIVED) {
|
||||
if (infoRead == dataRead) {
|
||||
// both reads are ok or else both failed
|
||||
if (infoRead == ReadStatus.READ_SUCCESS) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, INFO_DATA_READ_ERROR);
|
||||
}
|
||||
} else {
|
||||
// either info or data read failed - update status with details
|
||||
if (infoRead == ReadStatus.READ_FAILED) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, INFO_READ_ERROR);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, DATA_READ_ERROR);
|
||||
}
|
||||
}
|
||||
} // else - one status isn't received yet - wait until both Modbus polls returns either success or error
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) {
|
||||
listeners.add((E3DCWallboxThingHandler) childHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) {
|
||||
listeners.remove(childHandler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* 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.e3dc.internal.handler;
|
||||
|
||||
import static org.openhab.binding.modbus.e3dc.internal.E3DCBindingConstants.*;
|
||||
import static org.openhab.binding.modbus.e3dc.internal.modbus.E3DCModbusConstans.*;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.e3dc.internal.E3DCWallboxConfiguration;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.DataConverter;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.WallboxArray;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.WallboxBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
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.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link E3DCWallboxThingHandler} Basic modbus connection towards the E3DC device
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCWallboxThingHandler extends BaseThingHandler {
|
||||
public enum ReadWriteSuccess {
|
||||
NOT_RECEIVED,
|
||||
SUCCESS,
|
||||
FAILED
|
||||
}
|
||||
|
||||
private static final String READ_WRITE_ERROR = "Modbus Data Read/Write Error";
|
||||
private static final String READ_ERROR = "Modbus Read Error";
|
||||
private static final String WRITE_ERROR = "Modbus Write Error";
|
||||
|
||||
ChannelUID wbAvailableChannel;
|
||||
ChannelUID wbSunmodeChannel;
|
||||
ChannelUID wbChargingAbortedChannel;
|
||||
ChannelUID wbChargingChannel;
|
||||
ChannelUID wbJackLockedChannel;
|
||||
ChannelUID wbJackPluggedChannel;
|
||||
ChannelUID wbSchukoOnChannel;
|
||||
ChannelUID wbSchukoPluggedChannel;
|
||||
ChannelUID wbSchukoLockedChannel;
|
||||
ChannelUID wbSchukoRelay16Channel;
|
||||
ChannelUID wbRelay16Channel;
|
||||
ChannelUID wbRelay32Channel;
|
||||
ChannelUID wb1phaseChannel;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(E3DCWallboxThingHandler.class);
|
||||
private final Parser dataParser = new Parser(DataType.DATA);
|
||||
private ReadWriteSuccess dataRead = ReadWriteSuccess.NOT_RECEIVED;
|
||||
private ReadWriteSuccess dataWrite = ReadWriteSuccess.NOT_RECEIVED;
|
||||
private volatile BitSet currentBitSet = new BitSet(16);
|
||||
private @Nullable E3DCWallboxConfiguration config;
|
||||
private @Nullable E3DCThingHandler bridgeHandler;
|
||||
|
||||
public E3DCWallboxThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
wbAvailableChannel = new ChannelUID(thing.getUID(), WB_AVAILABLE_CHANNEL);
|
||||
wbSunmodeChannel = new ChannelUID(thing.getUID(), WB_SUNMODE_CHANNEL);
|
||||
wbChargingAbortedChannel = new ChannelUID(thing.getUID(), WB_CHARGING_ABORTED_CHANNEL);
|
||||
wbChargingChannel = new ChannelUID(thing.getUID(), WB_CHARGING_CHANNEL);
|
||||
wbJackLockedChannel = new ChannelUID(thing.getUID(), WB_JACK_LOCKED_CHANNEL);
|
||||
wbJackPluggedChannel = new ChannelUID(thing.getUID(), WB_JACK_PLUGGED_CHANNEL);
|
||||
wbSchukoOnChannel = new ChannelUID(thing.getUID(), WB_SCHUKO_ON_CHANNEL);
|
||||
wbSchukoPluggedChannel = new ChannelUID(thing.getUID(), WB_SCHUKO_PLUGGED_CHANNEL);
|
||||
wbSchukoLockedChannel = new ChannelUID(thing.getUID(), WB_SCHUKO_LOCKED_CHANNEL);
|
||||
wbSchukoRelay16Channel = new ChannelUID(thing.getUID(), WB_SCHUKO_RELAY_16A_CHANNEL);
|
||||
wbRelay16Channel = new ChannelUID(thing.getUID(), WB_RELAY_16A_CHANNEL);
|
||||
wbRelay32Channel = new ChannelUID(thing.getUID(), WB_RELAY_32A_CHANNEL);
|
||||
wb1phaseChannel = new ChannelUID(thing.getUID(), WB_1PHASE_CHANNEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
config = getConfigAs(E3DCWallboxConfiguration.class);
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler != null) {
|
||||
bridgeHandler = ((E3DCThingHandler) handler);
|
||||
} else {
|
||||
logger.warn("Thing Handler null");
|
||||
}
|
||||
} else {
|
||||
logger.warn("Bridge null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType) {
|
||||
int writeValue = 0;
|
||||
synchronized (this) {
|
||||
if (channelUID.getIdWithoutGroup().equals(WB_SUNMODE_CHANNEL)) {
|
||||
currentBitSet.set(WB_SUNMODE_BIT, command.equals(OnOffType.ON));
|
||||
} else if (channelUID.getIdWithoutGroup().equals(WB_CHARGING_ABORTED_CHANNEL)) {
|
||||
currentBitSet.set(WB_CHARGING_ABORTED_BIT, command.equals(OnOffType.ON));
|
||||
} else if (channelUID.getIdWithoutGroup().equals(WB_SCHUKO_ON_CHANNEL)) {
|
||||
currentBitSet.set(WB_SCHUKO_ON_BIT, command.equals(OnOffType.ON));
|
||||
} else if (channelUID.getIdWithoutGroup().equals(WB_1PHASE_CHANNEL)) {
|
||||
currentBitSet.set(WB_1PHASE_BIT, command.equals(OnOffType.ON));
|
||||
}
|
||||
writeValue = DataConverter.toInt(currentBitSet);
|
||||
logger.debug("Wallbox write {}", writeValue);
|
||||
}
|
||||
OptionalInt wallboxId = getWallboxId(config);
|
||||
if (wallboxId.isPresent()) {
|
||||
wallboxSet(wallboxId.getAsInt(), writeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallbox Settings can be changed with one Integer
|
||||
*
|
||||
* @param wallboxId needed to calculate right register
|
||||
* @param writeValue integer to be written
|
||||
*/
|
||||
public void wallboxSet(int wallboxId, int writeValue) {
|
||||
E3DCThingHandler localBridgeHandler = bridgeHandler;
|
||||
if (localBridgeHandler != null) {
|
||||
ModbusCommunicationInterface comms = localBridgeHandler.getComms();
|
||||
if (comms != null) {
|
||||
ModbusRegisterArray regArray = new ModbusRegisterArray(writeValue);
|
||||
ModbusWriteRegisterRequestBlueprint writeBluePrint = new ModbusWriteRegisterRequestBlueprint(
|
||||
localBridgeHandler.getSlaveId(), WALLBOX_REG_START + wallboxId, regArray, false, 3);
|
||||
comms.submitOneTimeWrite(writeBluePrint, result -> {
|
||||
if (dataWrite != ReadWriteSuccess.SUCCESS) {
|
||||
dataWrite = ReadWriteSuccess.SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
logger.debug("E3DC Modbus write response! {}", result.getResponse().toString());
|
||||
}, failure -> {
|
||||
if (dataWrite != ReadWriteSuccess.FAILED) {
|
||||
dataWrite = ReadWriteSuccess.FAILED;
|
||||
updateStatus();
|
||||
}
|
||||
logger.warn("E3DC Modbus write error! {}", failure.getRequest().toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private OptionalInt getWallboxId(@Nullable E3DCWallboxConfiguration c) {
|
||||
if (c != null) {
|
||||
return OptionalInt.of(c.wallboxId);
|
||||
} else {
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void handle(AsyncModbusReadResult result) {
|
||||
if (dataRead != ReadWriteSuccess.SUCCESS) {
|
||||
dataRead = ReadWriteSuccess.SUCCESS;
|
||||
updateStatus();
|
||||
}
|
||||
dataParser.handle(result);
|
||||
Optional<Data> wbArrayOpt = dataParser.parse(DataType.WALLBOX);
|
||||
if (wbArrayOpt.isPresent()) {
|
||||
WallboxArray wbArray = (WallboxArray) wbArrayOpt.get();
|
||||
OptionalInt wallboxId = getWallboxId(config);
|
||||
if (wallboxId.isPresent()) {
|
||||
Optional<WallboxBlock> blockOpt = wbArray.getWallboxBlock(wallboxId.getAsInt());
|
||||
if (blockOpt.isPresent()) {
|
||||
WallboxBlock block = blockOpt.get();
|
||||
synchronized (this) {
|
||||
currentBitSet = block.getBitSet();
|
||||
}
|
||||
updateState(wbAvailableChannel, block.wbAvailable);
|
||||
updateState(wbSunmodeChannel, block.wbSunmode);
|
||||
updateState(wbChargingAbortedChannel, block.wbChargingAborted);
|
||||
updateState(wbChargingChannel, block.wbCharging);
|
||||
updateState(wbJackLockedChannel, block.wbJackLocked);
|
||||
updateState(wbJackPluggedChannel, block.wbJackPlugged);
|
||||
updateState(wbSchukoOnChannel, block.wbSchukoOn);
|
||||
updateState(wbSchukoPluggedChannel, block.wbSchukoPlugged);
|
||||
updateState(wbSchukoLockedChannel, block.wbSchukoLocked);
|
||||
updateState(wbSchukoRelay16Channel, block.wbSchukoRelay16);
|
||||
updateState(wbRelay16Channel, block.wbRelay16);
|
||||
updateState(wbRelay32Channel, block.wbRelay32);
|
||||
updateState(wb1phaseChannel, block.wb1phase);
|
||||
} else {
|
||||
logger.debug("Unable to get ID {} from WallboxArray", wallboxId);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Wallbox ID {} not valid", wallboxId);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Unable to get {} from Bridge", DataType.WALLBOX);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleError(AsyncModbusFailure<ModbusReadRequestBlueprint> result) {
|
||||
if (dataRead != ReadWriteSuccess.FAILED) {
|
||||
dataRead = ReadWriteSuccess.FAILED;
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
if (dataWrite == ReadWriteSuccess.NOT_RECEIVED) {
|
||||
// read success / write not happened yet => go online / offline
|
||||
if (dataRead == ReadWriteSuccess.SUCCESS) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, READ_ERROR);
|
||||
}
|
||||
} else {
|
||||
if (dataRead == dataWrite) {
|
||||
// read and write same status - either go online or offline
|
||||
if (dataRead == ReadWriteSuccess.SUCCESS) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, READ_WRITE_ERROR);
|
||||
}
|
||||
} else {
|
||||
// either read or write failed - go offline with detailed status
|
||||
if (dataRead == ReadWriteSuccess.SUCCESS) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, WRITE_ERROR);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, READ_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.e3dc.internal.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link Data} Marker Interface for delivered Modbus Data
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface Data {
|
||||
public enum DataType {
|
||||
INFO,
|
||||
POWER,
|
||||
WALLBOX,
|
||||
EMERGENCY,
|
||||
STRINGS,
|
||||
DATA // marks all types besides INFO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.e3dc.internal.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link E3DCModbusConstans} Variables for register handling.
|
||||
* The numbers are taken from E3DC Modbus Spec Chapter 3.1 page 14 ff
|
||||
* Registers start from 0 (not 1!) so from the documented registers subtract 1
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCModbusConstans {
|
||||
// "String" registers at the beginning shall be read with very low frequency - 1 hour
|
||||
public static final int INFO_POLL_REFRESH_TIME_MS = 60 * 60 * 1000;
|
||||
|
||||
// Constants where a certain Block starts and block size. Note: General offset is -1 so INFO_REG from E3DC Modbus
|
||||
// Spec starts at 1 but it's Register 0!
|
||||
public static final int INFO_REG_START = 0;
|
||||
public static final int INFO_REG_SIZE = 67;
|
||||
public static final int POWER_REG_START = 67;
|
||||
public static final int POWER_REG_SIZE = 16;
|
||||
public static final int EMS_REG_START = 83;
|
||||
public static final int EMS_REG_SIZE = 2;
|
||||
public static final int WALLBOX_REG_START = 87;
|
||||
public static final int WALLBOX_REG_SIZE = 8;
|
||||
public static final int STRINGS_REG_START = 95;
|
||||
public static final int STRINGS_REG_SIZE = 9;
|
||||
public static final int REGISTER_LENGTH = 104;
|
||||
|
||||
/*
|
||||
* Some Registers are numbers but needs to be decoded into Bits
|
||||
*/
|
||||
|
||||
// Wallbox Bit Definitions according to chapter 3.1.5 page 15
|
||||
public static final int WB_AVAILABLE_BIT = 0;
|
||||
public static final int WB_SUNMODE_BIT = 1;
|
||||
public static final int WB_CHARGING_ABORTED_BIT = 2;
|
||||
public static final int WB_CHARGING_BIT = 3;
|
||||
public static final int WB_JACK_LOCKED_BIT = 4;
|
||||
public static final int WB_JACK_PLUGGED_BIT = 5;
|
||||
public static final int WB_SCHUKO_ON_BIT = 6;
|
||||
public static final int WB_SCHUKO_PLUGGED_BIT = 7;
|
||||
public static final int WB_SCHUKO_LOCKED_BIT = 8;
|
||||
public static final int WB_SCHUKO_RELAY16A_BIT = 9;
|
||||
public static final int WB_RELAY_16A_BIT = 10;
|
||||
public static final int WB_RELAY_32A_BIT = 11;
|
||||
public static final int WB_1PHASE_BIT = 12;
|
||||
|
||||
// EMS Bit Definitions according to chapter 3.1.3 page 17
|
||||
public static final int EMS_CHARGING_LOCK_BIT = 0;
|
||||
public static final int EMS_DISCHARGING_LOCK_BIT = 1;
|
||||
public static final int EMS_AVAILABLE_BIT = 2;
|
||||
public static final int EMS_WEATHER_CHARGING_BIT = 3;
|
||||
public static final int EMS_REGULATION_BIT = 4;
|
||||
public static final int EMS_CHARGE_LOCKTIME_BIT = 5;
|
||||
public static final int EMS_DISCHARGE_LOCKTIME_BIT = 6;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* 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.e3dc.internal.modbus;
|
||||
|
||||
import static org.openhab.binding.modbus.e3dc.internal.modbus.E3DCModbusConstans.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.EmergencyBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.InfoBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.PowerBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.StringBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.WallboxArray;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusRegister;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link InfoBlockCallback} class receives callbacks from modbus poller
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Parser {
|
||||
private static final int MEASURE_COUNT = 100;
|
||||
private final Logger logger = LoggerFactory.getLogger(Parser.class);
|
||||
private DataType callbackType;
|
||||
private byte[] bArray;
|
||||
private int size;
|
||||
private int counter = 0;
|
||||
private long maxDuration = Long.MIN_VALUE;
|
||||
private long minDuration = Long.MAX_VALUE;
|
||||
private long avgDuration = 0;
|
||||
|
||||
public Parser(DataType type) {
|
||||
callbackType = type;
|
||||
if (type.equals(DataType.INFO)) {
|
||||
size = INFO_REG_SIZE * 2;
|
||||
bArray = new byte[size];
|
||||
} else {
|
||||
size = (REGISTER_LENGTH - INFO_REG_SIZE) * 2;
|
||||
bArray = new byte[size];
|
||||
}
|
||||
}
|
||||
|
||||
public void handle(AsyncModbusReadResult result) {
|
||||
byte[] newArray = new byte[size];
|
||||
long startTime = System.currentTimeMillis();
|
||||
Optional<ModbusRegisterArray> opt = result.getRegisters();
|
||||
if (opt.isPresent()) {
|
||||
ModbusRegisterArray registers = opt.get();
|
||||
int i = 0;
|
||||
for (ModbusRegister reg : registers) {
|
||||
System.arraycopy(reg.getBytes(), 0, newArray, i, 2);
|
||||
i += 2;
|
||||
}
|
||||
setArray(newArray);
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
avgDuration += duration;
|
||||
minDuration = Math.min(minDuration, duration);
|
||||
maxDuration = Math.max(maxDuration, duration);
|
||||
counter++;
|
||||
if (counter % MEASURE_COUNT == 0) {
|
||||
logger.debug("Min {} Max {} Avg {}", minDuration, maxDuration, avgDuration / MEASURE_COUNT);
|
||||
avgDuration = 0;
|
||||
minDuration = Long.MAX_VALUE;
|
||||
maxDuration = Long.MIN_VALUE;
|
||||
}
|
||||
} else {
|
||||
logger.warn("Modbus read result doesn't return expected registers");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setArray(byte[] b) {
|
||||
if (b.length != size) {
|
||||
logger.warn("Wrong byte size received. Should be {} but is {}. Data maybe corrupted!", size, b.length);
|
||||
}
|
||||
bArray = b.clone();
|
||||
}
|
||||
|
||||
public Optional<Data> parse(DataType type) {
|
||||
synchronized (bArray) {
|
||||
if (type.equals(DataType.INFO) && callbackType.equals(DataType.INFO)) {
|
||||
return Optional.of(new InfoBlock(Arrays.copyOfRange(bArray, INFO_REG_START, INFO_REG_SIZE * 2)));
|
||||
} else if (type.equals(DataType.POWER) && callbackType.equals(DataType.DATA)) {
|
||||
int start = (POWER_REG_START - INFO_REG_SIZE) * 2;
|
||||
int end = start + POWER_REG_SIZE * 2;
|
||||
return Optional.of(new PowerBlock(Arrays.copyOfRange(bArray, start, end)));
|
||||
} else if (type.equals(DataType.EMERGENCY) && callbackType.equals(DataType.DATA)) {
|
||||
int start = (EMS_REG_START - INFO_REG_SIZE) * 2;
|
||||
int end = start + EMS_REG_SIZE * 2;
|
||||
return Optional.of(new EmergencyBlock(Arrays.copyOfRange(bArray, start, end)));
|
||||
} else if (type.equals(DataType.WALLBOX) && callbackType.equals(DataType.DATA)) {
|
||||
int start = (WALLBOX_REG_START - INFO_REG_SIZE) * 2;
|
||||
int end = start + WALLBOX_REG_SIZE * 2;
|
||||
return Optional.of(new WallboxArray(Arrays.copyOfRange(bArray, start, end)));
|
||||
} else if (type.equals(DataType.STRINGS) && callbackType.equals(DataType.DATA)) {
|
||||
int start = (STRINGS_REG_START - INFO_REG_SIZE) * 2;
|
||||
int end = start + STRINGS_REG_SIZE * 2;
|
||||
return Optional.of(new StringBlock(Arrays.copyOfRange(bArray, start, end)));
|
||||
}
|
||||
}
|
||||
logger.warn("Wrong Block requested. Request is {} but type is {}", type, callbackType);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.getClass().getName()).append(":").append(callbackType);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
# thing types
|
||||
thing-type.modbus.e3dc.label = E3DC Hauskraftwerk
|
||||
thing-type.modbus.e3dc.description = Zeigt die Leistungswerte, String Details, Notstrom Zustand und generelle Details zu Ihrem E3DC Hauskraftwerk
|
||||
thing-type.modbus.e3dc-wallbox.label = E3DC Wallbox
|
||||
thing-type.modbus.e3dc-wallbox.description = Zeigt die Einstellungen der verbundenen Wallbox. Schalter wie "Sonnenmodus" oder "1-phasiges Laden" können geändert werden
|
||||
|
||||
# thing type config description
|
||||
thing-type.config.modbus.e3dc.refresh.label = Zyklische Abfragezeit
|
||||
thing-type.config.modbus.e3dc.refresh.description = Intervall in Millisekunden, wie oft die Werte abgerufen werden sollen
|
||||
thing-type.config.modbus.e3dc-wallbox.wallboxId.label = Wallbox-Nummer
|
||||
thing-type.config.modbus.e3dc-wallbox.wallboxId.description = Das E3DC Gerät unterstützt bis zu 8 Wallboxen - Wählen Sie einen Wert zwischen 0 und 7
|
||||
|
||||
# Channel group types
|
||||
channel-group-type.modbus.info-values.label = Informationen
|
||||
channel-group-type.modbus.info-values.description = Basisinformationen zum E3DC Hauskraftwerk wie Modellname, Seriennummer und Software-Versionen
|
||||
channel-group-type.modbus.power-values.label = Leistungswerte
|
||||
channel-group-type.modbus.power-values.description = Elektrische Werte der angeschlossenen Erzeuger (Photovoltaik, Batterie, ...) und Verbraucher (Haushaltsverbrauch, Wallbox,...)
|
||||
channel-group-type.modbus.string-values.label = String Details
|
||||
channel-group-type.modbus.string-values.description = Detaillierte Werte der angeschlossenen Photovoltaik Strings. Zeigt die einzelnen Werte jedes angeschlossenen Strings
|
||||
channel-group-type.modbus.emergency-values.label = Notstrom Einstellungen
|
||||
channel-group-type.modbus.emergency-values.description = Status und Werte der Notstromversorgung wie Batterie Lade- und Entladesperren, Einspeise-Abregelung
|
||||
|
||||
# Wallbox Channels
|
||||
channel-type.modbus.wb-available-channel.label = Vorhanden
|
||||
channel-type.modbus.wb-sunmode-channel.label = Sonnenmodus
|
||||
channel-type.modbus.wb-charging-aborted-channel.label = Laden Abgebrochen
|
||||
channel-type.modbus.wb-charging-channel.label = Auto lädt
|
||||
channel-type.modbus.wb-jack-locked-channel.label = Ladekabel Verriegelt
|
||||
channel-type.modbus.wb-jack-plugged-channel.label = Ladekabel Gesteckt
|
||||
channel-type.modbus.wb-schuko-on-channel.label = Schuko-Steckdose An
|
||||
channel-type.modbus.wb-schuko-plugged-channel.label = Schuko-Stecker Gesteckt
|
||||
channel-type.modbus.wb-schuko-locked-channel.label = Schuko-Stecker Verriegelt
|
||||
channel-type.modbus.wb-schuko-relay-16a-channel.label = Schuko-Steckdose 16A Relais An
|
||||
channel-type.modbus.wb-relay-16a-channel.label = 16A Relais An
|
||||
channel-type.modbus.wb-relay-32a-channel.label = 32A Relais An
|
||||
channel-type.modbus.wb-1phase-channel.label = 1-phasiges Laden An
|
||||
|
||||
# Emergency Channels
|
||||
channel-type.modbus.emergency-power-status-channel.label = Notstrom Status
|
||||
channel-type.modbus.battery-charging-lock-channel.label = Batterie Laden Gesperrt
|
||||
channel-type.modbus.battery-discharging-lock-channel.label = Batterie Entladen Gesperrt
|
||||
channel-type.modbus.emergency-power-possible-channel.label = Notstrom Versorgung Möglich
|
||||
channel-type.modbus.weather-predicted-charging-channel.label = Wetterbasiertes Laden
|
||||
channel-type.modbus.regulation-status-channel.label = Einspeise Abregelung
|
||||
channel-type.modbus.charge-lock-time-channel.label = Batterie Ladesperrzeiten Aktiv
|
||||
channel-type.modbus.discharge-lock-time-channel.label = Batterie Entladesperrzeiten Aktiv
|
||||
|
||||
# Info Channels
|
||||
channel-type.modbus.modbus-id-channel.label = Modbus ID
|
||||
channel-type.modbus.modbus-firmware-channel.label = Modbus Firmware
|
||||
channel-type.modbus.supported-registers-channel.label = Unterstützte Register
|
||||
channel-type.modbus.manufacturer-name-channel.label = Hersteller
|
||||
channel-type.modbus.model-name-channel.label = Modellname
|
||||
channel-type.modbus.serial-number-channel.label = Seriennummer
|
||||
channel-type.modbus.firmware-release-channel.label = Firmware
|
||||
|
||||
# Power Channels
|
||||
channel-type.modbus.pv-power-supply-channel.label = Photovoltaik Leistung
|
||||
channel-type.modbus.battery-power-supply-channel.label = Batterie Entladen
|
||||
channel-type.modbus.battery-power-consumption-channel.label = Batterie Laden
|
||||
channel-type.modbus.household-power-consumption-channel.label = Haushalt Verbrauch
|
||||
channel-type.modbus.grid-power-consumption-channel.label = Stromnetz Verbrauch
|
||||
channel-type.modbus.grid-power-supply-channel.label = Stromnetz Einspeisung
|
||||
channel-type.modbus.external-power-supply-channel.label = Externer Stromproduzent
|
||||
channel-type.modbus.wallbox-power-consumption-channel.label = Wallbox Ladestrom
|
||||
channel-type.modbus.wallbox-pv-power-consumption-channel.label = Wallbox Photovoltaik Ladestrom
|
||||
channel-type.modbus.autarky-channel.label = Autarkie in Prozent
|
||||
channel-type.modbus.self-consumption-channel.label = Eigenverbrauch in Prozent
|
||||
channel-type.modbus.battery-soc-channel.label = Batterie Ladestand in Prozent
|
||||
|
||||
# String Channels
|
||||
channel-type.modbus.string1-dc-voltage-channel.label = String 1 Spannung
|
||||
channel-type.modbus.string2-dc-voltage-channel.label = String 2 Spannung
|
||||
channel-type.modbus.string3-dc-voltage-channel.label = String 3 Spannung
|
||||
channel-type.modbus.string1-dc-current-channel.label = String 1 Stromstärke
|
||||
channel-type.modbus.string2-dc-current-channel.label = String 2 Stromstärke
|
||||
channel-type.modbus.string3-dc-current-channel.label = String 3 Stromstärke
|
||||
channel-type.modbus.string1-dc-output-channel.label = String 1 Leistung
|
||||
channel-type.modbus.string2-dc-output-channel.label = String 2 Leistung
|
||||
channel-type.modbus.string3-dc-output-channel.label = String 3 Leistung
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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">
|
||||
<bridge-type id="e3dc">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="tcp"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>E3DC Home Power Plant</label>
|
||||
<description>Provide Power values, String Details, Emergency Power Status and general Information of your E3DC Home
|
||||
Power Plant</description>
|
||||
<channel-groups>
|
||||
<channel-group id="info" typeId="info-values"/>
|
||||
<channel-group id="power" typeId="power-values"/>
|
||||
<channel-group id="strings" typeId="string-values"/>
|
||||
<channel-group id="emergency" typeId="emergency-values"/>
|
||||
</channel-groups>
|
||||
<config-description>
|
||||
<parameter name="refresh" type="integer" min="1000" unit="ms">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh Rate of E3DC values in Milliseconds</description>
|
||||
<default>2000</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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">
|
||||
<channel-group-type id="emergency-values">
|
||||
<label>EMS Settings</label>
|
||||
<description>Provides values of Emergency Power Status (EMS) and regulations like Battery charging / discharging
|
||||
restrictions</description>
|
||||
<channels>
|
||||
<channel id="emergency-power-status" typeId="emergency-power-status-channel"/>
|
||||
<channel id="battery-charging-lock" typeId="battery-charging-lock-channel"/>
|
||||
<channel id="battery-discharging-lock" typeId="battery-discharging-lock-channel"/>
|
||||
<channel id="emergency-power-possible" typeId="emergency-power-possible-channel"/>
|
||||
<channel id="weather-predicted-charging" typeId="weather-predicted-charging-channel"/>
|
||||
<channel id="regulation-status" typeId="regulation-status-channel"/>
|
||||
<channel id="charge-lock-time" typeId="charge-lock-time-channel"/>
|
||||
<channel id="discharge-lock-time" typeId="discharge-lock-time-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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">
|
||||
<channel-type id="emergency-power-status-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Emergency Power Status</label>
|
||||
<description>Indicates if Emergency Power Supply is possible or not, active or inactive</description>
|
||||
</channel-type>
|
||||
<channel-type id="battery-charging-lock-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Battery Charge Locked</label>
|
||||
<description>Battery charging is locked</description>
|
||||
</channel-type>
|
||||
<channel-type id="battery-discharging-lock-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Battery Discharge Locked</label>
|
||||
<description>Battery discharging is locked</description>
|
||||
</channel-type>
|
||||
<channel-type id="emergency-power-possible-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Emergency Power Possible</label>
|
||||
<description>Emergency Power Supply is possible</description>
|
||||
</channel-type>
|
||||
<channel-type id="weather-predicted-charging-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Weather Predicted Battery Charging</label>
|
||||
<description>Weather Predicted Battery Charging is activated</description>
|
||||
</channel-type>
|
||||
<channel-type id="regulation-status-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Grid Power Supply Regulation</label>
|
||||
<description>Grid Power Supply is currently regulated</description>
|
||||
</channel-type>
|
||||
<channel-type id="charge-lock-time-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Charge Lock Time Active</label>
|
||||
<description>Charge Lock Time is currently active</description>
|
||||
</channel-type>
|
||||
<channel-type id="discharge-lock-time-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Discharge Lock Time Active</label>
|
||||
<description>Discharge Lock Time is currently active</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?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">
|
||||
<channel-group-type id="info-values">
|
||||
<label>Information</label>
|
||||
<description>Basic Information of your E3DC Device like Model Name, Serial Number and Software Versions</description>
|
||||
<channels>
|
||||
<channel id="modbus-id" typeId="modbus-id-channel"/>
|
||||
<channel id="modbus-firmware" typeId="modbus-firmware-channel"/>
|
||||
<channel id="supported-registers" typeId="supported-registers-channel"/>
|
||||
<channel id="manufacturer-name" typeId="manufacturer-name-channel"/>
|
||||
<channel id="model-name" typeId="model-name-channel"/>
|
||||
<channel id="serial-number" typeId="serial-number-channel"/>
|
||||
<channel id="firmware-release" typeId="firmware-release-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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">
|
||||
<channel-type id="modbus-id-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Modbus-ID</label>
|
||||
<description>Modbus ID / Magic Byte of E3DC</description>
|
||||
</channel-type>
|
||||
<channel-type id="modbus-firmware-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Modbus Firmware</label>
|
||||
<description>Version of Modbus Firmware</description>
|
||||
</channel-type>
|
||||
<channel-type id="supported-registers-channel">
|
||||
<item-type>Number</item-type>
|
||||
<label>Supported Registers</label>
|
||||
<description>Number of registers supported by Modbus</description>
|
||||
</channel-type>
|
||||
<channel-type id="manufacturer-name-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Manufacturer Name</label>
|
||||
<description>Name of the Device Manufacturer</description>
|
||||
</channel-type>
|
||||
<channel-type id="model-name-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Model Name</label>
|
||||
<description>Name of the E3DC Model</description>
|
||||
</channel-type>
|
||||
<channel-type id="firmware-release-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Firmware Release</label>
|
||||
<description>Firmware installed on this particular E3DC Device</description>
|
||||
</channel-type>
|
||||
<channel-type id="serial-number-channel">
|
||||
<item-type>String</item-type>
|
||||
<label>Serial Number</label>
|
||||
<description>Serial Number of this particular E3DC Device</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?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">
|
||||
<channel-group-type id="power-values">
|
||||
<label>Power Values</label>
|
||||
<description>Provides values of your attached electrical Producers (Photovoltaic, Battery, ... and Consumers
|
||||
(Household, Wallbox, ...)</description>
|
||||
<channels>
|
||||
<channel id="pv-power-supply" typeId="pv-power-supply-channel"/>
|
||||
<channel id="battery-power-supply" typeId="battery-power-supply-channel"/>
|
||||
<channel id="battery-power-consumption" typeId="battery-power-consumption-channel"/>
|
||||
<channel id="household-power-consumption" typeId="household-power-consumption-channel"/>
|
||||
<channel id="grid-power-consumption" typeId="grid-power-consumption-channel"/>
|
||||
<channel id="grid-power-supply" typeId="grid-power-supply-channel"/>
|
||||
<channel id="external-power-supply" typeId="external-power-supply-channel"/>
|
||||
<channel id="wallbox-power-consumption" typeId="wallbox-power-consumption-channel"/>
|
||||
<channel id="wallbox-pv-power-consumption" typeId="wallbox-pv-power-consumption-channel"/>
|
||||
<channel id="autarky" typeId="autarky-channel"/>
|
||||
<channel id="self-consumption" typeId="self-consumption-channel"/>
|
||||
<channel id="battery-soc" typeId="battery-soc-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?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">
|
||||
<channel-type id="pv-power-supply-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>PV Output</label>
|
||||
<description>Photovoltaic Power Production</description>
|
||||
</channel-type>
|
||||
<channel-type id="battery-power-supply-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Battery Discharge</label>
|
||||
<description>Battery discharges and provides Power</description>
|
||||
</channel-type>
|
||||
<channel-type id="battery-power-consumption-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Battery Charge</label>
|
||||
<description>Battery charges and consumes Power</description>
|
||||
</channel-type>
|
||||
<channel-type id="household-power-consumption-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Household Consumption</label>
|
||||
<description>Household consuming Power</description>
|
||||
</channel-type>
|
||||
<channel-type id="grid-power-consumption-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Grid Power Consumption</label>
|
||||
<description>Grid Power is needed in order to satisfy your overall Power consumption</description>
|
||||
</channel-type>
|
||||
<channel-type id="grid-power-supply-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Grid Power Supply</label>
|
||||
<description>More Photovoltaic Power is produced than needed. Additional Power is provided towards the Grid</description>
|
||||
</channel-type>
|
||||
<channel-type id="external-power-supply-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>External Power Supply</label>
|
||||
<description>Power produced by an external device which is attached to your E3DC device</description>
|
||||
</channel-type>
|
||||
<channel-type id="wallbox-power-consumption-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Wallbox Power Consumption</label>
|
||||
<description>Power consumption of attached Wallboxes</description>
|
||||
</channel-type>
|
||||
<channel-type id="wallbox-pv-power-consumption-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Wallbox PV Power Consumption</label>
|
||||
<description>Photovoltaic Power consumption (PV plus Battery) of attached Wallboxes</description>
|
||||
</channel-type>
|
||||
<channel-type id="autarky-channel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Autarky</label>
|
||||
<description>Your current Autarky Level in Percent</description>
|
||||
</channel-type>
|
||||
<channel-type id="self-consumption-channel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Self Consumtion</label>
|
||||
<description>Your current Photovoltaic Self Consumption Level in Percent</description>
|
||||
</channel-type>
|
||||
<channel-type id="battery-soc-channel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Battery State Of Charge</label>
|
||||
<description>Charge Level of your attached Battery in Percent</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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">
|
||||
<channel-group-type id="string-values">
|
||||
<label>String Details</label>
|
||||
<description>Provide detailed values of your attached Photovoltaic Strings. Evaluate how much Power each String
|
||||
provides</description>
|
||||
<channels>
|
||||
<channel id="string1-dc-voltage" typeId="string1-dc-voltage-channel"/>
|
||||
<channel id="string2-dc-voltage" typeId="string2-dc-voltage-channel"/>
|
||||
<channel id="string3-dc-voltage" typeId="string3-dc-voltage-channel"/>
|
||||
<channel id="string1-dc-current" typeId="string1-dc-current-channel"/>
|
||||
<channel id="string2-dc-current" typeId="string2-dc-current-channel"/>
|
||||
<channel id="string3-dc-current" typeId="string3-dc-current-channel"/>
|
||||
<channel id="string1-dc-output" typeId="string1-dc-output-channel"/>
|
||||
<channel id="string2-dc-output" typeId="string2-dc-output-channel"/>
|
||||
<channel id="string3-dc-output" typeId="string3-dc-output-channel"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?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">
|
||||
<channel-type id="string1-dc-voltage-channel">
|
||||
<item-type>Number:ElectricPotential</item-type>
|
||||
<label>String 1 Potential</label>
|
||||
<description>Voltage on String 1</description>
|
||||
</channel-type>
|
||||
<channel-type id="string2-dc-voltage-channel">
|
||||
<item-type>Number:ElectricPotential</item-type>
|
||||
<label>String 2 Potential</label>
|
||||
<description>Voltage on String 2</description>
|
||||
</channel-type>
|
||||
<channel-type id="string3-dc-voltage-channel">
|
||||
<item-type>Number:ElectricPotential</item-type>
|
||||
<label>String 3 Potential</label>
|
||||
<description>Voltage on String 3</description>
|
||||
</channel-type>
|
||||
<channel-type id="string1-dc-current-channel">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>String 1 Current</label>
|
||||
<description>Current on String 1</description>
|
||||
</channel-type>
|
||||
<channel-type id="string2-dc-current-channel">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>String 2 Current</label>
|
||||
<description>Current on String 2</description>
|
||||
</channel-type>
|
||||
<channel-type id="string3-dc-current-channel">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>String 3 Current</label>
|
||||
<description>Current on String 3</description>
|
||||
</channel-type>
|
||||
<channel-type id="string1-dc-output-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>String 1 Power</label>
|
||||
<description>Power produced by String 1</description>
|
||||
</channel-type>
|
||||
<channel-type id="string2-dc-output-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>String 2 Power</label>
|
||||
<description>Power produced by String 2</description>
|
||||
</channel-type>
|
||||
<channel-type id="string3-dc-output-channel">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>String 3 Power</label>
|
||||
<description>Power produced by String 3</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?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">
|
||||
<thing-type id="e3dc-wallbox">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="e3dc"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>E3DC Wallbox</label>
|
||||
<description>Provide your Wallbox Settings. Switches like "Sunmode" or "1-Phase Charging" can be changed</description>
|
||||
<channels>
|
||||
<channel id="wb-available" typeId="wb-available-channel"/>
|
||||
<channel id="wb-sunmode" typeId="wb-sunmode-channel"/>
|
||||
<channel id="wb-charging-aborted" typeId="wb-charging-aborted-channel"/>
|
||||
<channel id="wb-charging" typeId="wb-charging-channel"/>
|
||||
<channel id="wb-jack-locked" typeId="wb-jack-locked-channel"/>
|
||||
<channel id="wb-jack-plugged" typeId="wb-jack-plugged-channel"/>
|
||||
<channel id="wb-schuko-on" typeId="wb-schuko-on-channel"/>
|
||||
<channel id="wb-schuko-plugged" typeId="wb-schuko-plugged-channel"/>
|
||||
<channel id="wb-schuko-locked" typeId="wb-schuko-locked-channel"/>
|
||||
<channel id="wb-schuko-relay-16a" typeId="wb-schuko-relay-16a-channel"/>
|
||||
<channel id="wb-relay-16a" typeId="wb-relay-16a-channel"/>
|
||||
<channel id="wb-relay-32a" typeId="wb-relay-32a-channel"/>
|
||||
<channel id="wb-1phase" typeId="wb-1phase-channel"/>
|
||||
</channels>
|
||||
<config-description>
|
||||
<parameter name="wallboxId" type="integer" min="0" max="7" required="true">
|
||||
<label>Wallbox ID</label>
|
||||
<description>E3DC supports up to 8 Wallboxes - select a value from 0 to 7</description>
|
||||
<default>0</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?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">
|
||||
<channel-type id="wb-available-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Available</label>
|
||||
<description>Indicates if the Wallbox is attached. Check your Wallbox ID in offline case</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-sunmode-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Sun Mode</label>
|
||||
<description>Activate / Deactivate Sun Mode. Off case takes Grid Power to ensure highest possible charging</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-charging-aborted-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Charging Aborted</label>
|
||||
<description>Wallbox charging is aborted</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-charging-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Charging</label>
|
||||
<description>Wallbox is charging</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-jack-locked-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Jack Locked</label>
|
||||
<description>Jack is locked</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-jack-plugged-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Jack Plugged</label>
|
||||
<description>Jack is plugged</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-schuko-on-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Schuko Socket On</label>
|
||||
<description>If your Wallbox has an additional Schuko Socket it provides state ON or OFF</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-schuko-plugged-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Schuko Socket Plugged</label>
|
||||
<description>If your Wallbox has an additional Schuko Socket it provides plugged state ON or OFF</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-schuko-locked-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Schuko Socket Locked</label>
|
||||
<description>If your Wallbox has an additional Schuko Socket it provides locked state ON or OFF</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-schuko-relay-16a-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Schuko 16A Relay On</label>
|
||||
<description>Schuko 16A Relay is ON</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-relay-16a-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>16A Relay On</label>
|
||||
<description>Wallbox 16A Relay is ON</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-relay-32a-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>32A Relay On</label>
|
||||
<description>Wallbox 32A Relay is ON</description>
|
||||
</channel-type>
|
||||
<channel-type id="wb-1phase-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>1-Phase Charging</label>
|
||||
<description>1-phase charging is activated. If OFF 3-phase charging is activated</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 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.e3dc.dto;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.EmergencyBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.PowerBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.StringBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.WallboxArray;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.WallboxBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
||||
/**
|
||||
* The {@link DataBlockTest} Test Data Transfer Objects of frequent Data Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
public class DataBlockTest {
|
||||
private Parser mc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
byte[] dataBlock = new byte[] { 0, -14, 0, 0, -2, -47, -1, -1, 2, 47, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 99, 99, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
125, 2, 21, 0, 0, 0, 27, 0, 26, 0, 0, 0, 103, 0, -117, 0, 0 };
|
||||
mc = new Parser(DataType.DATA);
|
||||
mc.setArray(dataBlock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPowerBlock() {
|
||||
Optional<Data> dataOpt = mc.parse(DataType.POWER);
|
||||
assertTrue(dataOpt.isPresent());
|
||||
PowerBlock b = (PowerBlock) dataOpt.get();
|
||||
assertEquals("PV Supply", "242.0 W", b.pvPowerSupply.toString());
|
||||
assertEquals("Grid Supply", "14.0 W", b.gridPowerSupply.toString());
|
||||
assertEquals("Grid Consumption", "0.0 W", b.gridPowerConsumpition.toString());
|
||||
assertEquals("Battery Supply", "303.0 W", b.batteryPowerSupply.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidWallboxBlock() {
|
||||
Optional<Data> wba = mc.parse(DataType.WALLBOX);
|
||||
assertTrue(wba.isPresent());
|
||||
WallboxArray a = (WallboxArray) wba.get();
|
||||
assertNotNull(a);
|
||||
Optional<WallboxBlock> o = a.getWallboxBlock(0);
|
||||
WallboxBlock b = o.get();
|
||||
assertNotNull(b);
|
||||
assertEquals("Wallbox available", OnOffType.ON, b.wbAvailable);
|
||||
assertEquals("Wallbox Sunmode", OnOffType.ON, b.wbSunmode);
|
||||
assertEquals("Wallbox 1phase", OnOffType.OFF, b.wb1phase);
|
||||
assertEquals("Wallbox charging", OnOffType.OFF, b.wbCharging);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidEmergency() {
|
||||
Optional<Data> dataOpt = mc.parse(DataType.EMERGENCY);
|
||||
assertTrue(dataOpt.isPresent());
|
||||
EmergencyBlock b = (EmergencyBlock) dataOpt.get();
|
||||
assertEquals("EMS Status", EmergencyBlock.EP_NOT_SUPPORTED, b.epStatus.toFullString());
|
||||
assertEquals("Battery charging locked", OnOffType.OFF, b.batteryChargingLocked);
|
||||
assertEquals("Battery discharging locked", OnOffType.OFF, b.batteryDischargingLocked);
|
||||
assertEquals("EP possible", OnOffType.OFF, b.epPossible);
|
||||
assertEquals("Weather Predicted charging", OnOffType.OFF, b.weatherPredictedCharging);
|
||||
assertEquals("Regulation Status", OnOffType.OFF, b.regulationStatus);
|
||||
assertEquals("Charge Lock Time", OnOffType.OFF, b.chargeLockTime);
|
||||
assertEquals("Discharge Lock Time", OnOffType.OFF, b.dischargeLockTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidStringDetailsStringBlock() {
|
||||
Optional<Data> dataOpt = mc.parse(DataType.STRINGS);
|
||||
assertTrue(dataOpt.isPresent());
|
||||
StringBlock b = (StringBlock) dataOpt.get();
|
||||
assertEquals("String 1 V", 381, b.string1Volt.intValue());
|
||||
assertEquals("String 1 V", "V", b.string1Volt.getUnit().toString());
|
||||
assertEquals("String 2 V", 533, b.string2Volt.intValue());
|
||||
assertEquals("String 1 V", "V", b.string2Volt.getUnit().toString());
|
||||
assertEquals("String 3 V", 0, b.string3Volt.intValue());
|
||||
assertEquals("String 1 V", "V", b.string3Volt.getUnit().toString());
|
||||
|
||||
assertEquals("String 1 A", 0.27, b.string1Ampere.doubleValue(), 0.01);
|
||||
assertEquals("String 1 A", "A", b.string1Ampere.getUnit().toString());
|
||||
assertEquals("String 2 A", 0.26, b.string2Ampere.doubleValue(), 0.01);
|
||||
assertEquals("String 2 A", "A", b.string2Ampere.getUnit().toString());
|
||||
assertEquals("String 3 A", 0, b.string3Ampere.doubleValue(), 0.01);
|
||||
assertEquals("String 3 A", "A", b.string3Ampere.getUnit().toString());
|
||||
|
||||
assertEquals("String 1 W", 103, b.string1Watt.intValue());
|
||||
assertEquals("String 1 W", "W", b.string1Watt.getUnit().toString());
|
||||
assertEquals("String 2 W", 139, b.string2Watt.intValue());
|
||||
assertEquals("String 2 W", "W", b.string2Watt.getUnit().toString());
|
||||
assertEquals("String 3 W", 0, b.string3Watt.intValue());
|
||||
assertEquals("String 3 W", "W", b.string3Watt.getUnit().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidInfoblock() {
|
||||
Optional<Data> infoOpt = mc.parse(DataType.INFO);
|
||||
assertFalse(infoOpt.isPresent());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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.e3dc.dto;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.InfoBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
|
||||
/**
|
||||
* The {@link InfoTest} Test Data Transfer Objects of Information Block
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
public class InfoTest {
|
||||
private Parser mc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
byte[] infoBlock = new byte[] { -29, -36, 1, 2, 0, -120, 69, 51, 47, 68, 67, 32, 71, 109, 98, 72, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 48, 32, 69, 32, 65, 73, 79, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 78, 73, 78, 73, 84, 73, 65, 76, 73, 90, 69, 68,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 48, 95, 50, 48, 50, 48, 95, 48, 52, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
mc = new Parser(DataType.INFO);
|
||||
mc.setArray(infoBlock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testvalidInformationBlock() {
|
||||
Optional<Data> infoOpt = mc.parse(DataType.INFO);
|
||||
assertTrue(infoOpt.isPresent());
|
||||
InfoBlock b = (InfoBlock) infoOpt.get();
|
||||
assertNotNull(b);
|
||||
assertEquals("MagicByte", "E3DC", b.modbusId.toString());
|
||||
assertEquals("Model", "S10 E AIO", b.modelName.toString());
|
||||
assertEquals("Firmware", "S10_2020_04", b.firmware.toString());
|
||||
assertEquals("Manufacturer", "E3/DC GmbH", b.manufacturer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongQuery() {
|
||||
Optional<Data> dataOpt = mc.parse(DataType.POWER);
|
||||
assertFalse(dataOpt.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidBlockSize() {
|
||||
byte[] infoBlock = new byte[] { -29, -36, 1, 2, 0, -120, 69, 51, 47, 68, 67, 32, 71, 109, 98, 72, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 48, 32, 69, 32, 65, 73, 79, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 78, 73, 78, 73, 84, 73, 65, 76, 73, 90, 69, 68,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 48, 95, 50, 48, 50, 48, 95, 48 };
|
||||
Parser mc = new Parser(DataType.INFO);
|
||||
mc.setArray(infoBlock);
|
||||
Optional<Data> infoOpt = mc.parse(DataType.INFO);
|
||||
InfoBlock b = (InfoBlock) infoOpt.get();
|
||||
// block still valid but data maybe corrupted => logged in warnings
|
||||
assertTrue(infoOpt.isPresent());
|
||||
assertNotNull(b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 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.e3dc.internal.handler;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegister;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* The {@link E3DCHandlerStateTest} Test State handling of Handler if different results occurs
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class E3DCHandlerStateTest {
|
||||
ThingStatusInfo unknownStatus = new ThingStatusInfo(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, null);
|
||||
ThingStatusInfo onlineStatus = new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null);
|
||||
ThingStatusInfo offlineStatus = new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
E3DCThingHandler.DATA_READ_ERROR);
|
||||
|
||||
@Test
|
||||
public void testStatusChain() {
|
||||
Bridge bridge = mock(Bridge.class);
|
||||
ThingUID uid = new ThingUID("modbus", "e3dc", "powerplant");
|
||||
when(bridge.getUID()).thenReturn(uid);
|
||||
ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
|
||||
E3DCThingHandler handler = new E3DCThingHandler(bridge);
|
||||
handler.setCallback(callback);
|
||||
|
||||
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("refresh", 2000);
|
||||
Configuration config = new Configuration(map);
|
||||
when(bridge.getConfiguration()).thenReturn(config);
|
||||
handler.initialize();
|
||||
verify(callback).statusUpdated(ArgumentMatchers.eq((Thing) bridge), ArgumentMatchers.eq(unknownStatus));
|
||||
// Initializing is ongoing - now simulate info and data callback
|
||||
|
||||
handler.handleInfoResult(getInfoResult());
|
||||
verify(callback).statusUpdated(ArgumentMatchers.eq((Thing) bridge), ArgumentMatchers.eq(unknownStatus));
|
||||
handler.handleDataResult(getDataResult());
|
||||
verify(callback, times(1)).statusUpdated(ArgumentMatchers.eq((Thing) bridge),
|
||||
ArgumentMatchers.eq(onlineStatus));
|
||||
// we are ONLINE!
|
||||
|
||||
// call it a few times - ensure at the end of the test that "ONLINE" status is raised only 2 times and not all
|
||||
// the time
|
||||
handler.handleDataResult(getDataResult());
|
||||
handler.handleDataResult(getDataResult());
|
||||
handler.handleDataResult(getDataResult());
|
||||
|
||||
// simulate one wrong data result
|
||||
handler.handleDataFailure(getFailResult());
|
||||
verify(callback).statusUpdated(ArgumentMatchers.eq((Thing) bridge), ArgumentMatchers.eq(offlineStatus));
|
||||
|
||||
// // go online again
|
||||
handler.handleDataResult(getDataResult());
|
||||
verify(callback, times(2)).statusUpdated(ArgumentMatchers.eq((Thing) bridge),
|
||||
ArgumentMatchers.eq(onlineStatus));
|
||||
}
|
||||
|
||||
private AsyncModbusReadResult getInfoResult() {
|
||||
byte[] infoBlockBytes = new byte[] { -29, -36, 1, 2, 0, -120, 69, 51, 47, 68, 67, 32, 71, 109, 98, 72, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 48, 32, 69, 32, 65, 73, 79, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 78, 73, 78, 73, 84, 73, 65, 76, 73, 90, 69,
|
||||
68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 48, 95, 50, 48, 50, 48, 95, 48, 52,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
ByteBuffer infoWrap = ByteBuffer.wrap(infoBlockBytes);
|
||||
ModbusRegister[] infoBlock = new ModbusRegister[infoBlockBytes.length / 2];
|
||||
for (int i = 0; i < infoBlock.length; i++) {
|
||||
infoBlock[i] = new ModbusRegister(infoWrap.get(), infoWrap.get());
|
||||
}
|
||||
ModbusReadRequestBlueprint readRequest = mock(ModbusReadRequestBlueprint.class);
|
||||
return new AsyncModbusReadResult(readRequest, new ModbusRegisterArray(infoBlock));
|
||||
}
|
||||
|
||||
private AsyncModbusReadResult getDataResult() {
|
||||
byte[] dataBlockBytes = new byte[] { 0, -14, 0, 0, -2, -47, -1, -1, 2, 47, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 99, 99, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 125, 2, 21, 0, 0, 0, 27, 0, 26, 0, 0, 0, 103, 0, -117, 0, 0 };
|
||||
ByteBuffer dataWrap = ByteBuffer.wrap(dataBlockBytes);
|
||||
ModbusRegister[] dataBlock = new ModbusRegister[dataBlockBytes.length / 2];
|
||||
for (int i = 0; i < dataBlock.length; i++) {
|
||||
dataBlock[i] = new ModbusRegister(dataWrap.get(), dataWrap.get());
|
||||
}
|
||||
ModbusReadRequestBlueprint readRequest = mock(ModbusReadRequestBlueprint.class);
|
||||
return new AsyncModbusReadResult(readRequest, new ModbusRegisterArray(dataBlock));
|
||||
}
|
||||
|
||||
private AsyncModbusFailure<ModbusReadRequestBlueprint> getFailResult() {
|
||||
ModbusReadRequestBlueprint readRequest = mock(ModbusReadRequestBlueprint.class);
|
||||
return new AsyncModbusFailure<ModbusReadRequestBlueprint>(readRequest, new Exception("Something failed!"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.e3dc.modbus;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
|
||||
/**
|
||||
* The {@link ParserNameTest} Tests for ModbusCallbacks
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ParserNameTest {
|
||||
|
||||
@Test
|
||||
public void testDebugNames() {
|
||||
Parser mcInfo = new Parser(DataType.INFO);
|
||||
assertEquals("Debug Name Info", "org.openhab.binding.modbus.e3dc.internal.modbus.Parser:INFO",
|
||||
mcInfo.toString());
|
||||
|
||||
Parser mcPower = new Parser(DataType.DATA);
|
||||
assertEquals("Debug Name Power", "org.openhab.binding.modbus.e3dc.internal.modbus.Parser:DATA",
|
||||
mcPower.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.e3dc.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.DataConverter;
|
||||
|
||||
/**
|
||||
* The {@link DataConverterTest} Test data conversions
|
||||
*
|
||||
* @author Bernd Weymann - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DataConverterTest {
|
||||
|
||||
@Test
|
||||
public void testE3DCSwapValueNegative() {
|
||||
// Reg 69 value 65098 bytes [-2, 74]
|
||||
// Reg 70 value 65535 bytes [-1, -1]
|
||||
byte[] b = new byte[] { -2, -74, -1, -1 };
|
||||
assertEquals("Negative Value", -330, DataConverter.getInt32Swap(ByteBuffer.wrap(b)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitset() {
|
||||
byte[] b = new byte[] { 3, 16 };
|
||||
BitSet s = BitSet.valueOf(b);
|
||||
assertEquals("Bit0", true, s.get(0));
|
||||
assertEquals("Bit1", true, s.get(1));
|
||||
assertEquals("Bit2", false, s.get(2));
|
||||
assertEquals("Bit3", false, s.get(3));
|
||||
assertEquals("Bit4", false, s.get(4));
|
||||
assertEquals("Bit5", false, s.get(5));
|
||||
assertEquals("Bit6", false, s.get(6));
|
||||
assertEquals("Bit7", false, s.get(7));
|
||||
assertEquals("Bit8", false, s.get(8));
|
||||
assertEquals("Bit9", false, s.get(9));
|
||||
assertEquals("Bit10", false, s.get(10));
|
||||
assertEquals("Bit11", false, s.get(11));
|
||||
assertEquals("Bit12", true, s.get(12));
|
||||
assertEquals("Bit13", false, s.get(13));
|
||||
assertEquals("Bit14", false, s.get(14));
|
||||
assertEquals("Bit15", false, s.get(15));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user