[modbus] Modbus register array backed by bytes and other simplifications (#8865)
Signed-off-by: Sami Salonen <ssalonen@gmail.com>
This commit is contained in:
@@ -12,11 +12,12 @@
|
||||
*/
|
||||
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;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link DataConverter} Helper class to convert bytes from modbus into desired data format
|
||||
@@ -25,27 +26,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
*/
|
||||
@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
|
||||
@@ -53,28 +33,12 @@ public class DataConverter {
|
||||
* @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 double getUDoubleValue(ValueBuffer wrap, double factor) {
|
||||
return round(wrap.getUInt16() * factor, 2);
|
||||
}
|
||||
|
||||
public static String getString(byte[] bArray) {
|
||||
return new String(bArray, StandardCharsets.US_ASCII).trim();
|
||||
return ModbusBitUtilities.extractStringFromBytes(bArray, 0, bArray.length, StandardCharsets.US_ASCII).trim();
|
||||
}
|
||||
|
||||
public static int toInt(BitSet bitSet) {
|
||||
@@ -93,8 +57,7 @@ public class DataConverter {
|
||||
}
|
||||
|
||||
long factor = (long) Math.pow(10, places);
|
||||
value = value * factor;
|
||||
long tmp = Math.round(value);
|
||||
long tmp = Math.round(value * factor);
|
||||
return (double) tmp / factor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,13 @@ 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;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
|
||||
/**
|
||||
* The {@link EmergencyBlock} Data object for E3DC Info Block
|
||||
@@ -55,7 +55,7 @@ public class EmergencyBlock implements Data {
|
||||
*/
|
||||
public EmergencyBlock(byte[] bArray) {
|
||||
// uint16 status register 40084 - possible Status Strings are defined in Constants above
|
||||
int status = DataConverter.getUInt16Value(ByteBuffer.wrap(bArray));
|
||||
int status = ModbusBitUtilities.extractUInt16(bArray, 0);
|
||||
if (status >= 0 && status < 5) {
|
||||
epStatus = EP_STATUS_ARRAY[status];
|
||||
} else {
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
*/
|
||||
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;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link InfoBlock} Data object for E3DC Info Block
|
||||
@@ -43,7 +42,7 @@ public class InfoBlock implements Data {
|
||||
*/
|
||||
public InfoBlock(byte[] bArray) {
|
||||
// index handling to calculate the correct start index
|
||||
ByteBuffer wrapper = ByteBuffer.wrap(bArray);
|
||||
ValueBuffer wrapper = ValueBuffer.wrap(bArray);
|
||||
|
||||
// first uint16 = 2 bytes - decode magic byte
|
||||
byte[] magicBytes = new byte[2];
|
||||
@@ -52,11 +51,11 @@ public class InfoBlock implements Data {
|
||||
// first uint16 = 2 bytes - decode magic byte
|
||||
|
||||
// unit8 (Modbus Major Version) + uint8 Modbus minor Version
|
||||
String modbusVersion = wrapper.get() + "." + wrapper.get();
|
||||
String modbusVersion = wrapper.getSInt8() + "." + wrapper.getSInt8();
|
||||
this.modbusVersion = new StringType(modbusVersion);
|
||||
|
||||
// unit16 - supported registers
|
||||
short supportedRegisters = wrapper.getShort();
|
||||
short supportedRegisters = wrapper.getSInt16();
|
||||
this.supportedRegisters = new DecimalType(supportedRegisters);
|
||||
|
||||
byte[] buffer = new byte[32];
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
*/
|
||||
package org.openhab.binding.modbus.e3dc.internal.dto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Power;
|
||||
|
||||
@@ -21,6 +19,7 @@ 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;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link PowerBlock} Data object for E3DC Info Block
|
||||
@@ -49,10 +48,10 @@ public class PowerBlock implements Data {
|
||||
*/
|
||||
public PowerBlock(byte[] bArray) {
|
||||
// index handling to calculate the correct start index
|
||||
ByteBuffer wrap = ByteBuffer.wrap(bArray);
|
||||
ValueBuffer wrap = ValueBuffer.wrap(bArray);
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
long pvPowerSupplyL = DataConverter.getInt32Swap(wrap);
|
||||
long pvPowerSupplyL = wrap.getSInt32Swap();
|
||||
|
||||
/*
|
||||
* int32_swap value don't provide negative values!
|
||||
@@ -60,7 +59,7 @@ public class PowerBlock implements Data {
|
||||
* Negative value - Battery is discharging = Power supplier
|
||||
*/
|
||||
pvPowerSupply = QuantityType.valueOf(pvPowerSupplyL, SmartHomeUnits.WATT);
|
||||
long batteryPower = DataConverter.getInt32Swap(wrap);
|
||||
long batteryPower = wrap.getSInt32Swap();
|
||||
if (batteryPower > 0) {
|
||||
// Battery is charging so Power is consumed by Battery
|
||||
batteryPowerSupply = QuantityType.valueOf(0, SmartHomeUnits.WATT);
|
||||
@@ -72,7 +71,7 @@ public class PowerBlock implements Data {
|
||||
}
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
long householdPowerConsumptionL = DataConverter.getInt32Swap(wrap);
|
||||
long householdPowerConsumptionL = wrap.getSInt32Swap();
|
||||
householdPowerConsumption = QuantityType.valueOf(householdPowerConsumptionL, SmartHomeUnits.WATT);
|
||||
|
||||
/*
|
||||
@@ -80,7 +79,7 @@ public class PowerBlock implements Data {
|
||||
* Positive value - Power provided towards Grid = Power consumer
|
||||
* Negative value - Power requested from Grid = Power supplier
|
||||
*/
|
||||
long gridPower = DataConverter.getInt32Swap(wrap);
|
||||
long gridPower = wrap.getSInt32Swap();
|
||||
if (gridPower > 0) {
|
||||
// Power is provided by Grid
|
||||
gridPowerSupply = QuantityType.valueOf(gridPower, SmartHomeUnits.WATT);
|
||||
@@ -92,19 +91,19 @@ public class PowerBlock implements Data {
|
||||
}
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
externalPowerSupply = QuantityType.valueOf(DataConverter.getInt32Swap(wrap), SmartHomeUnits.WATT);
|
||||
externalPowerSupply = QuantityType.valueOf(wrap.getSInt32Swap(), SmartHomeUnits.WATT);
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
wallboxPowerConsumption = QuantityType.valueOf(DataConverter.getInt32Swap(wrap), SmartHomeUnits.WATT);
|
||||
wallboxPowerConsumption = QuantityType.valueOf(wrap.getSInt32Swap(), SmartHomeUnits.WATT);
|
||||
|
||||
// int32_swap value = 4 byte
|
||||
wallboxPVPowerConsumption = QuantityType.valueOf(DataConverter.getInt32Swap(wrap), SmartHomeUnits.WATT);
|
||||
wallboxPVPowerConsumption = QuantityType.valueOf(wrap.getSInt32Swap(), 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);
|
||||
autarky = QuantityType.valueOf(wrap.getSInt8(), SmartHomeUnits.PERCENT);
|
||||
selfConsumption = QuantityType.valueOf(wrap.getSInt8(), SmartHomeUnits.PERCENT);
|
||||
|
||||
// uint16 for Battery State of Charge
|
||||
batterySOC = QuantityType.valueOf(wrap.getShort(), SmartHomeUnits.PERCENT);
|
||||
batterySOC = QuantityType.valueOf(wrap.getSInt16(), SmartHomeUnits.PERCENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
*/
|
||||
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;
|
||||
@@ -22,6 +20,7 @@ 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;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link StringBlock} Data object for E3DC Info Block
|
||||
@@ -46,17 +45,17 @@ public class StringBlock implements Data {
|
||||
* @param bArray - Modbus Registers as bytes from 40096 to 40104
|
||||
*/
|
||||
public StringBlock(byte[] bArray) {
|
||||
ByteBuffer wrap = ByteBuffer.wrap(bArray);
|
||||
ValueBuffer wrap = ValueBuffer.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);
|
||||
string1Volt = QuantityType.valueOf(wrap.getUInt16(), SmartHomeUnits.VOLT);
|
||||
string2Volt = QuantityType.valueOf(wrap.getUInt16(), SmartHomeUnits.VOLT);
|
||||
string3Volt = QuantityType.valueOf(wrap.getUInt16(), 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);
|
||||
string1Watt = QuantityType.valueOf(wrap.getUInt16(), SmartHomeUnits.WATT);
|
||||
string2Watt = QuantityType.valueOf(wrap.getUInt16(), SmartHomeUnits.WATT);
|
||||
string3Watt = QuantityType.valueOf(wrap.getUInt16(), SmartHomeUnits.WATT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ 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;
|
||||
@@ -59,17 +58,10 @@ public class Parser {
|
||||
}
|
||||
|
||||
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);
|
||||
setArray(opt.get().getBytes());
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
avgDuration += duration;
|
||||
|
||||
Reference in New Issue
Block a user