When Implement a custom battery, no data shows

Hi,
I wanna implement a custom battery which communicate with modbus, but I got an error:

2025-01-22T10:37:37,524 [_cycle  ] INFO  [onent.AbstractOpenemsComponent] [uzenergyBattery0] Activate io.openems.edge.uz.battery1
2025-01-22T10:37:37,529 [_cycle  ] ERROR [.battery1.UzenergyBattery1Impl] bundle io.openems.edge.uzenergy:1.0.0.202501221028 (245)[io.openems.edge.uzenergy.battery1.UzenergyBattery1Impl(139)] : The activate method has thrown an exception
java.lang.IllegalArgumentException: StartAddress for Modbus Element wrong. Got [8451/0x2103] Expected [8450/0x2102]
        at io.openems.edge.bridge.modbus.api.task.AbstractTask.<init>(AbstractTask.java:55) ~[?:?]
        at io.openems.edge.bridge.modbus.api.task.AbstractReadTask.<init>(AbstractReadTask.java:39) ~[?:?]
        at io.openems.edge.bridge.modbus.api.task.AbstractReadRegistersTask.<init>(AbstractReadRegistersTask.java:23) ~[?:?]
        at io.openems.edge.bridge.modbus.api.task.FC3ReadRegistersTask.<init>(FC3ReadRegistersTask.java:29) ~[?:?]
        at io.openems.edge.bridge.modbus.api.task.FC3ReadRegistersTask.<init>(FC3ReadRegistersTask.java:23) ~[?:?]
        at io.openems.edge.uzenergy.battery1.UzenergyBattery1Impl.defineModbusProtocol(UzenergyBattery1Impl.java:217) ~[?:?]
        at io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent.getModbusProtocol(AbstractOpenemsModbusComponent.java:238) ~[?:?]
        at io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent.activate(AbstractOpenemsModbusComponent.java:120) ~[?:?]
        at io.openems.edge.uzenergy.battery1.UzenergyBattery1Impl.activate(UzenergyBattery1Impl.java:91) ~[?:?]
        at jdk.internal.reflect.GeneratedMethodAccessor11.invoke(Unknown Source) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:569) ~[?:?]
        at org.apache.felix.scr.impl.inject.methods.BaseMethod.invokeMethod(BaseMethod.java:257) ~[?:?]
        at org.apache.felix.scr.impl.inject.methods.BaseMethod.access$500(BaseMethod.java:41) ~[?:?]
        at org.apache.felix.scr.impl.inject.methods.BaseMethod$Resolved.invoke(BaseMethod.java:701) ~[?:?]
        at org.apache.felix.scr.impl.inject.methods.BaseMethod.invoke(BaseMethod.java:544) ~[?:?]
        at org.apache.felix.scr.impl.inject.methods.ActivateMethod.invoke(ActivateMethod.java:317) ~[?:?]
        at org.apache.felix.scr.impl.inject.methods.ActivateMethod.invoke(ActivateMethod.java:307) ~[?:?]
        at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:354) ~[?:?]
        at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:115) ~[?:?]
        at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:1002) ~[?:?]
        at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:975) ~[?:?]
        at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:920) ~[?:?]
        at org.apache.felix.framework.ServiceRegistrationImpl.getFactoryUnchecked(ServiceRegistrationImpl.java:349) ~[?:?]
        at org.apache.felix.framework.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:249) ~[?:?]
        at org.apache.felix.framework.ServiceRegistry.getService(ServiceRegistry.java:362) ~[?:?]
        at org.apache.felix.framework.Felix.getService(Felix.java:3984) ~[?:?]
        at org.apache.felix.framework.BundleContextImpl.getService(BundleContextImpl.java:450) ~[?:?]
        at org.apache.felix.eventadmin.impl.handler.EventHandlerProxy.obtain(EventHandlerProxy.java:296) ~[?:?]
        at org.apache.felix.eventadmin.impl.handler.EventHandlerProxy.sendEvent(EventHandlerProxy.java:424) ~[?:?]
        at org.apache.felix.eventadmin.impl.tasks.HandlerTask.runWithoutDenylistTiming(HandlerTask.java:82) ~[?:?]
        at org.apache.felix.eventadmin.impl.tasks.SyncDeliverTasks.execute(SyncDeliverTasks.java:107) ~[?:?]
        at org.apache.felix.eventadmin.impl.handler.EventAdminImpl.sendEvent(EventAdminImpl.java:155) ~[?:?]
        at org.apache.felix.eventadmin.impl.security.EventAdminSecurityDecorator.sendEvent(EventAdminSecurityDecorator.java:96) ~[?:?]
        at io.openems.common.event.EventBuilder.send(EventBuilder.java:68) ~[?:?]
        at io.openems.edge.core.cycle.CycleWorker.forever(CycleWorker.java:50) ~[?:?]
        at io.openems.common.worker.AbstractWorker$1.run(AbstractWorker.java:156) ~[?:?]
2025-01-22T10:37:37,550 [tchQueue] ERROR [Events.Framework              ] FrameworkEvent ERROR
org.osgi.framework.ServiceException: Service factory returned null. (Component: io.openems.edge.uzenergy.battery1 (139))
        at org.apache.felix.framework.ServiceRegistrationImpl.getFactoryUnchecked(ServiceRegistrationImpl.java:385) ~[?:?]
        at org.apache.felix.framework.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:249) ~[?:?]
        at org.apache.felix.framework.ServiceRegistry.getService(ServiceRegistry.java:362) ~[?:?]
        at org.apache.felix.framework.Felix.getService(Felix.java:3984) ~[?:?]
        at org.apache.felix.framework.BundleContextImpl.getService(BundleContextImpl.java:450) ~[?:?]
        at org.apache.felix.eventadmin.impl.handler.EventHandlerProxy.obtain(EventHandlerProxy.java:296) ~[?:?]
        at org.apache.felix.eventadmin.impl.handler.EventHandlerProxy.sendEvent(EventHandlerProxy.java:424) ~[?:?]
        at org.apache.felix.eventadmin.impl.tasks.HandlerTask.runWithoutDenylistTiming(HandlerTask.java:82) ~[?:?]
        at org.apache.felix.eventadmin.impl.tasks.SyncDeliverTasks.execute(SyncDeliverTasks.java:107) ~[?:?]
        at org.apache.felix.eventadmin.impl.handler.EventAdminImpl.sendEvent(EventAdminImpl.java:155) ~[?:?]
        at org.apache.felix.eventadmin.impl.security.EventAdminSecurityDecorator.sendEvent(EventAdminSecurityDecorator.java:96) ~[?:?]
        at io.openems.common.event.EventBuilder.send(EventBuilder.java:68) ~[?:?]
        at io.openems.edge.core.cycle.CycleWorker.forever(CycleWorker.java:50) ~[?:?]
        at io.openems.common.worker.AbstractWorker$1.run(AbstractWorker.java:156) ~[?:?]

It’s a simple implementation of SymmetricEss, only to get data from battery and display in dashboard.
my code is as follow:

public class UzenergySymmetricEssImpl extends AbstractOpenemsModbusComponent implements SymmetricEss, ModbusComponent, 
		ModbusSlave, UzenergySymmetricEss, EventHandler {

protected ModbusProtocol defineModbusProtocol() {
		return new ModbusProtocol(this, //
				new FC3ReadRegistersTask(0x0101, Priority.LOW, 
						m(SymmetricEss.ChannelId.GRID_MODE, new UnsignedWordElement(0x106), 
								new ElementToChannelConverter(value -> {
									var intValue = TypeUtils.<Integer>getAsType(OpenemsType.INTEGER, value);
									if (intValue != null) {
										switch (intValue) {
										case 1:
											return GridMode.OFF_GRID;
										case 2:
											return GridMode.ON_GRID;
										}
									}
									return GridMode.UNDEFINED;
								})
						)),
				new FC3ReadRegistersTask(0x0200, Priority.LOW, //
						m(SymmetricEss.ChannelId.ACTIVE_POWER, new SignedWordElement(0x0228), SCALE_FACTOR_2), //
						m(SymmetricEss.ChannelId.REACTIVE_POWER, new SignedWordElement(0x0211), SCALE_FACTOR_2), //
						m(SymmetricEss.ChannelId.MAX_APPARENT_POWER, new UnsignedWordElement(0x0232), SCALE_FACTOR_2) //
				),
				new FC3ReadRegistersTask(0x1400, Priority.LOW, //
						m(SymmetricEss.ChannelId.SOC, new UnsignedWordElement(0x1402))
				)
			);
	}
@Designate(ocd = Config.class, factory = true)
@Component(//
		name = "io.openems.edge.uzenergy.battery1", //
		immediate = true, //
		configurationPolicy = ConfigurationPolicy.REQUIRE //
)
@EventTopics({ //
		EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE //
})
public class UzenergyBattery1Impl extends AbstractOpenemsModbusComponent implements UzenergyBattery1, Battery, 
		ModbusComponent, ModbusSlave, EventHandler{

....
	@Override
	protected ModbusProtocol defineModbusProtocol() {
		return new ModbusProtocol(this, new FC3ReadRegistersTask(0x2100, Priority.HIGH, //
						m(new UnsignedWordElement(0x2100).onUpdateCallback(this.onRegister0x2100Update)) //
								.m(Battery.ChannelId.VOLTAGE, SCALE_FACTOR_MINUS_1) // [V]
								.build(), //
						m(new SignedWordElement(0x2101)) //
								.m(Battery.ChannelId.CURRENT, SCALE_FACTOR_MINUS_1) // [A]
								.build(), //
						m(Battery.ChannelId.SOC, new UnsignedWordElement(0x2103)), //
						m(new UnsignedWordElement(0x2104)) //
								.m(Battery.ChannelId.SOH, DIRECT_1_TO_1) // [%]
								.build(), //
						m(new UnsignedWordElement(0x2106)) //
								.m(Battery.ChannelId.MAX_CELL_VOLTAGE, DIRECT_1_TO_1) //
								.build(), //
						m(new UnsignedWordElement(0x2108)) //
								.m(Battery.ChannelId.MIN_CELL_VOLTAGE, DIRECT_1_TO_1) //
								.build(), //
						m(new SignedWordElement(0x210A)) //
								.m(Battery.ChannelId.MAX_CELL_TEMPERATURE, SCALE_FACTOR_MINUS_1) //
								.build(), //
						m(new SignedWordElement(0x210C)) //
								.m(Battery.ChannelId.MIN_CELL_TEMPERATURE, SCALE_FACTOR_MINUS_1) //
								.build()) //
				);
	}
cofig of battery:
@ObjectClassDefinition(//
		name = "io.openems.edge.uzenergy.ess", //
		description = "Implements the io.openems.edge.uzenergy.ess system")
@interface Config {

	@AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component")
	String id() default "ess0";

	@AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID")
	String alias() default "";

	@AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?")
	boolean enabled() default true;
	@AttributeDefinition(name = "Modbus-ID", description = "ID of Modbus bridge.")
	String modbus_id() default "modbus0";

	String battery_id();
	
//	@AttributeDefinition(name = "Modbus target filter", description = "This is auto-generated by 'Modbus-ID'.")
//	String Modbus_target() default "(enabled=true)";
	String webconsole_configurationFactory_nameHint() default "io.openems.edge.uzenergy [{id}]";


}

Hello and welcome to OpenEMS,

first of all i just wanted to ask you which Battery you are trying to Implement? Is it possible for you to make your Repo open and create a PR for it later on aswell?

The issue is, that you miss some Registers which need “DummyRegisters” like here:

1 Like

Good afternoon,
I’m greatly appreciated for your quickly rely and it helps me a lot. The problem solved by add a DummyRegisterElement in battery protocal ‘new DummyRegisterElement(2102);’ after current register.

But it was stuck in getting response or sending request to serial port.

2025-01-22T12:46:26,567 [68b45fb)] INFO  [onent.AbstractOpenemsComponent] [uzenergyBattery0] Deactivate io.openems.edge.uzenergy.battery1
2025-01-22T12:46:26,608 [68b45fb)] INFO  [onent.AbstractOpenemsComponent] [uzenergyBattery0] Activate io.openems.edge.uzenergy.battery1
2025-01-22T12:46:28,132 [modbus0 ] ERROR [e.modbus.api.task.AbstractTask] Execute failed FC3ReadHoldingRegisters [uzenergyBattery0;unitid=1;priority=HIGH;ref=8448/0x2100;length=13] ModbusIOException: I/O exception - failed to read response for request [01 03 21 00 00 0D] - Cannot read from serial port

I read the product manual, it should send ‘7e 00 01 2f 00 fe 0d’ to battery to get response. Then I wrote an example to get data, it returned [buffer=====7E 00 01 58 01 10 0C FC 0C FC 0C FC 0C FC 0C FC 0C FC 0C FC 0C FC 0C FC 0C FB 0C FC 0C FB 0C FC 0C FC 0C FA 0C FE 02 01 75 30 03 01 26 48 04 01 27 10 05 06 00 49 00 49 00 48 00 48 40 4C 20 4C 06 05 00 00 00 00 00 00 02 00 00 00 07 01 00 BD 08 01 14 C6 09 01 27 10 0A 01 00 00 FE 0D 00 00 00 00 00 00]. How can I get the battery soc, activePower etc. to show them in dashboard.

package com;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;

public class TestFazecast {

	public static void main(String[] args) throws Exception {
		SerialPort[] ports = SerialPort.getCommPorts();
		byte[] bytes = new byte[7];
		bytes[0] = (byte) Integer.parseInt("7e", 16);
		bytes[1] = (byte) Integer.parseInt("00", 16);
		bytes[2] = (byte) Integer.parseInt("01", 16);
		bytes[3] = (byte) Integer.parseInt("2f", 16);
		bytes[4] = (byte) Integer.parseInt("00", 16);
		bytes[5] = (byte) Integer.parseInt("fe", 16);
		bytes[6] = (byte) Integer.parseInt("0d", 16);
		
		int i = 0;

		SerialPort serialPort = SerialPort.getCommPort("/dev/ttyS3");
		System.out.println("serialPort=======" + serialPort.toString());
			SerialParameters parameters = new SerialParameters();
			
			if (serialPort != null) {
	            serialPort.setComPortParameters(parameters.getBaudRate(), parameters.getDatabits(), parameters.getStopbits(), parameters.getParity());
	            serialPort.setFlowControl(parameters.getFlowControlIn() | parameters.getFlowControlOut());
	            serialPort.setRs485ModeParameters(parameters.getRs485Mode(), parameters.getRs485TxEnableActiveHigh(), parameters.getRs485EnableTermination(), parameters.getRs485RxDuringTx(), parameters.getRs485DelayBeforeTxMicroseconds(), parameters.getRs485DelayAfterTxMicroseconds());
	        }
			serialPort.openPort();
			serialPort.addDataListener(new SerialPortDataListener() {
	            @Override
	            public int getListeningEvents() {
	                return SerialPort.LISTENING_EVENT_PORT_DISCONNECTED;
	            }

	            @Override
	            public void serialEvent(SerialPortEvent event) {
	                if (event.getEventType() == SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) {
	                    serialPort.closePort();
//	                	transport.notifyListenersDisconnected();
	                }
	            }
	        });
			System.out.println("8====" +serialPort.writeBytes(bytes, 8));
			
			System.out.println("7====" + serialPort.writeBytes(bytes, 7));
			byte[] buffer = new byte[100];
			int bytesToRead = 100;

			// 打开port
			try {
				boolean a1 = serialPort.openPort();
				System.out.println("is close =====" + a1);

			} catch (Exception e) {
				System.out.println(String.format("Cannot open port %s - %s", serialPort.getSystemPortName(), e.getMessage()));
			}

			// 查看bit available
			if (serialPort.bytesAvailable() > 0) {
				System.out.println("serialPort.bytesAvailable()====" + serialPort.bytesAvailable());
			}
			
			// 读取port中的数据
			Thread.sleep(200);
			Integer a = serialPort == null ? 0 : serialPort.readBytes(buffer, bytesToRead);
			System.out.println("a2====" + Integer.toHexString(a));
			toHex(buffer);
			
			InputStream inputStream = serialPort.getInputStream();
			try {
				System.out.println("inputstream====" + inputStream.read(new byte[100], 0, 100));
			} catch (IOException e) {
				e.printStackTrace();
			}
			boolean a1 = serialPort.closePort();
			System.out.println("is close =====" + a1);

	}
	
	public static void toHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02X ", b));
		}
		System.out.println("buffer=====" + sb.toString());
	}
	
	public static int readByte(SerialPort commPort) throws IOException {
        if (commPort != null && commPort.isOpen()) {
            byte[] buffer = new byte[1];
            int cnt = commPort.readBytes(buffer, 1);
            if (cnt != 1) {
                throw new IOException("CANNOT_READ_FROM_SERIAL_PORT");
            }
            else {
                return buffer[0] & 0xff;
            }
        }
        else {
            throw new IOException("COMM_PORT_IS_NOT_VALID_OR_NOT_OPEN");
        }
    }
	
	public synchronized boolean isOpen(SerialPort serialPort) {
        return serialPort != null && serialPort.isOpen();
    }
	public static void readEcho(int len, SerialPort commPort) throws IOException {
        byte[] echoBuf = new byte[len];
        echoBuf[0] = (byte) Integer.parseInt("7e", 16);
        echoBuf[1] = (byte) Integer.parseInt("00", 16);
        echoBuf[2] = (byte) Integer.parseInt("01", 16);
        echoBuf[3] = (byte) Integer.parseInt("2f", 16);
        echoBuf[4] = (byte) Integer.parseInt("00", 16);
        echoBuf[5] = (byte) Integer.parseInt("fe", 16);
        echoBuf[6] = (byte) Integer.parseInt("0d", 16);
        int echoLen = commPort.readBytes(echoBuf, len);
        System.out.println("Echo: {"+ ModbusUtil.toHex(echoBuf, 0, echoLen) + "}");
        if (echoLen != len) {
        	System.out.println("Error: Transmit echo not received");
            throw new IOException("Echo not received");
        }
    }
}
class ModbusUtil {
	public static String toHex(byte[] data, int off, int end) {
        //double size, two bytes (hex range) for one byte
        StringBuilder buf = new StringBuilder(data.length * 2);
        if (end > data.length) {
            end = data.length;
        }
        for (int i = off; i < end; i++) {
            //don't forget the second hex digit
            if (((int)data[i] & 0xff) < 0x10) {
                buf.append("0");
            }
            buf.append(Long.toString((int)data[i] & 0xff, 16).toUpperCase());
            if (i < end - 1) {
                buf.append(" ");
            }
        }
        return buf.toString();
    }
}

class SerialParameters {
	private static final boolean DEFAULT_RS485_MODE = false;
    private static final boolean DEFAULT_RS485_TX_ENABLE_ACTIVE_HIGH = true;
    private static final boolean DEFAULT_RS485_ENABLE_TERMINATION = false;
    private static final boolean DEFAULT_RS485_TX_DURING_RX = false;
    private static final int DEFAULT_RS485_DELAY_BEFORE_TX_MICROSECONDS = 1000;
    private static final int DEFAULT_RS485_DELAY_AFTER_TX_MICROSECONDS = 1000;

    //instance attributes
    private String portName;
    private int baudRate;
    private int flowControlIn;
    private int flowControlOut;
    private int databits;
    private int stopbits;
    private int parity;
    private String encoding;
    private boolean echo;
    private int openDelay;
    private boolean rs485Mode;
    private boolean rs485TxEnableActiveHigh;
    private boolean rs485EnableTermination;
    private boolean rs485RxDuringTx;
    private int rs485DelayBeforeTxMicroseconds;
    private int rs485DelayAfterTxMicroseconds;

    /**
     * Constructs a new <tt>SerialParameters</tt> instance with
     * default values.
     */
    public SerialParameters() {
        portName = "/dev/ttyS3";
        baudRate = 9600;
        flowControlIn = AbstractSerialConnection.FLOW_CONTROL_DISABLED;
        flowControlOut = AbstractSerialConnection.FLOW_CONTROL_DISABLED;
        databits = 8;
        stopbits = AbstractSerialConnection.ONE_STOP_BIT;
        parity = AbstractSerialConnection.NO_PARITY;
        // Historically, the encoding has been null which got converted to RTU
        // by SerialConnection.open(). Let's make it more explicit which serial
        // protocol will be used by default.
        encoding = "rtu";
        echo = false;
        openDelay = AbstractSerialConnection.OPEN_DELAY;
        rs485Mode = DEFAULT_RS485_MODE;
        rs485TxEnableActiveHigh = DEFAULT_RS485_TX_ENABLE_ACTIVE_HIGH;
        rs485DelayBeforeTxMicroseconds = DEFAULT_RS485_DELAY_BEFORE_TX_MICROSECONDS;
        rs485DelayAfterTxMicroseconds = DEFAULT_RS485_DELAY_AFTER_TX_MICROSECONDS;
    }

	public String getPortName() {
		return portName;
	}

	public void setPortName(String portName) {
		this.portName = portName;
	}

	public int getBaudRate() {
		return baudRate;
	}

	public void setBaudRate(int baudRate) {
		this.baudRate = baudRate;
	}

	public int getDatabits() {
		return databits;
	}

	public void setDatabits(int databits) {
		this.databits = databits;
	}

	public int getOpenDelay() {
		return openDelay;
	}

	public void setOpenDelay(int openDelay) {
		this.openDelay = openDelay;
	}

	public boolean isRs485Mode() {
		return rs485Mode;
	}

	public void setRs485Mode(boolean rs485Mode) {
		this.rs485Mode = rs485Mode;
	}

	public boolean isRs485TxEnableActiveHigh() {
		return rs485TxEnableActiveHigh;
	}

	public void setRs485TxEnableActiveHigh(boolean rs485TxEnableActiveHigh) {
		this.rs485TxEnableActiveHigh = rs485TxEnableActiveHigh;
	}

	public boolean isRs485EnableTermination() {
		return rs485EnableTermination;
	}

	public void setRs485EnableTermination(boolean rs485EnableTermination) {
		this.rs485EnableTermination = rs485EnableTermination;
	}

	public boolean isRs485RxDuringTx() {
		return rs485RxDuringTx;
	}

	public void setRs485RxDuringTx(boolean rs485RxDuringTx) {
		this.rs485RxDuringTx = rs485RxDuringTx;
	}

	public int getRs485DelayBeforeTxMicroseconds() {
		return rs485DelayBeforeTxMicroseconds;
	}

	public void setRs485DelayBeforeTxMicroseconds(int rs485DelayBeforeTxMicroseconds) {
		this.rs485DelayBeforeTxMicroseconds = rs485DelayBeforeTxMicroseconds;
	}

	public int getRs485DelayAfterTxMicroseconds() {
		return rs485DelayAfterTxMicroseconds;
	}

	public void setRs485DelayAfterTxMicroseconds(int rs485DelayAfterTxMicroseconds) {
		this.rs485DelayAfterTxMicroseconds = rs485DelayAfterTxMicroseconds;
	}

	public int getFlowControlIn() {
		return flowControlIn;
	}

	public void setFlowControlIn(int flowControlIn) {
		this.flowControlIn = flowControlIn;
	}

	public int getFlowControlOut() {
		return flowControlOut;
	}

	public void setFlowControlOut(int flowControlOut) {
		this.flowControlOut = flowControlOut;
	}

	public int getStopbits() {
		return stopbits;
	}

	public void setStopbits(int stopbits) {
		this.stopbits = stopbits;
	}

	public int getParity() {
		return parity;
	}

	public void setParity(int parity) {
		this.parity = parity;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public boolean isEcho() {
		return echo;
	}

	public void setEcho(boolean echo) {
		this.echo = echo;
	}
	public boolean getRs485Mode() {
        return rs485Mode;
    }
	public boolean getRs485TxEnableActiveHigh() {
        return rs485TxEnableActiveHigh;
    }
	public boolean getRs485EnableTermination() {
        return rs485EnableTermination;
    }
	public boolean getRs485RxDuringTx() {
        return rs485RxDuringTx;
    }
}


abstract class AbstractSerialConnection {

    /**
     * Parity values
     */
    public static final int NO_PARITY = SerialPort.NO_PARITY;
    public static final int ODD_PARITY = SerialPort.ODD_PARITY;
    public static final int EVEN_PARITY = SerialPort.EVEN_PARITY;
    public static final int MARK_PARITY = SerialPort.MARK_PARITY;
    public static final int SPACE_PARITY = SerialPort.SPACE_PARITY;

    /**
     * Stop bits values
     */
    public static final int ONE_STOP_BIT = SerialPort.ONE_STOP_BIT;
    public static final int ONE_POINT_FIVE_STOP_BITS = SerialPort.ONE_POINT_FIVE_STOP_BITS;
    public static final int TWO_STOP_BITS = SerialPort.TWO_STOP_BITS;

    /**
     * Flow control values
     */
    public static final int FLOW_CONTROL_DISABLED = SerialPort.FLOW_CONTROL_DISABLED;
    public static final int FLOW_CONTROL_RTS_ENABLED = SerialPort.FLOW_CONTROL_RTS_ENABLED;
    public static final int FLOW_CONTROL_CTS_ENABLED = SerialPort.FLOW_CONTROL_CTS_ENABLED;
    public static final int FLOW_CONTROL_DSR_ENABLED = SerialPort.FLOW_CONTROL_DSR_ENABLED;
    public static final int FLOW_CONTROL_DTR_ENABLED = SerialPort.FLOW_CONTROL_DTR_ENABLED;
    public static final int FLOW_CONTROL_XONXOFF_IN_ENABLED = SerialPort.FLOW_CONTROL_XONXOFF_IN_ENABLED;
    public static final int FLOW_CONTROL_XONXOFF_OUT_ENABLED = SerialPort.FLOW_CONTROL_XONXOFF_OUT_ENABLED;

    /**
     * Open delay (msec)
     */
    public static final int OPEN_DELAY = 0;

    /**
     * Timeout
     */
    public static final int TIMEOUT_NONBLOCKING = SerialPort.TIMEOUT_NONBLOCKING;
   	public static final int TIMEOUT_READ_SEMI_BLOCKING = SerialPort.TIMEOUT_READ_SEMI_BLOCKING;
   	public static final int TIMEOUT_READ_BLOCKING = SerialPort.TIMEOUT_READ_BLOCKING;
   	public static final int TIMEOUT_WRITE_BLOCKING = SerialPort.TIMEOUT_WRITE_BLOCKING;
   	public static final int TIMEOUT_SCANNER = SerialPort.TIMEOUT_SCANNER;

    /**
     * Opens the port and throws an error if it cannot for some reason
     *
     * @throws IOException If the port is not available or cannot be opened
     */
    public abstract void open() throws IOException;

    /**
     * Returns the <tt>ModbusTransport</tt> instance to be used for receiving
     * and sending messages.
     *
     * @return a <tt>ModbusTransport</tt> instance
     */
//    public abstract AbstractModbusTransport getModbusTransport();

    /**
     * Read a specified number of bytes from the serial port
     *
     * @param buffer      Buffer to recieve bytes from the port
     * @param bytesToRead Number of bytes to read
     * @return number of currently bytes read
     */
    public abstract int readBytes(byte[] buffer, int bytesToRead);

    /**
     * Write a specified number of bytes to the serial port
     *
     * @param buffer       Bytes to send to the port
     * @param bytesToWrite How many bytes to send
     * @return number of currently bytes written
     */
    public abstract int writeBytes(byte[] buffer, int bytesToWrite);

    /**
     * Bytes available to read
     *
     * @return number of bytes currently available to read
     */
    public abstract int bytesAvailable();

    /**
     * Close the port and clean up associated elements
     */
    public abstract void close();

    /**
     * Returns current baud rate
     *
     * @return Baud rate
     */
    public abstract int getBaudRate();

    /**
     * Returns current data bits value
     *
     * @return Number of data bits
     */
    public abstract int getNumDataBits();

    /**
     * Returns current stop bits
     *
     * @return Number of stop bits
     */
    public abstract int getNumStopBits();

    /**
     * Returns current parity
     *
     * @return Parity type
     */
    public abstract int getParity();

    /**
     * Returns a name of the port
     *
     * @return a <tt>String</tt> instance
     */
    public abstract String getPortName();

    /**
     * Returns a descriptive name of the port
     *
     * @return a <tt>String</tt> instance
     */
    public abstract String getDescriptivePortName();

    /**
     * Set port timeouts
     *
     * @param newTimeoutMode  Timeout mode
     * @param newReadTimeout  Read timeout (milliseconds)
     * @param newWriteTimeout Write timeout (milliseconds)
     */
    public abstract void setComPortTimeouts(int newTimeoutMode, int newReadTimeout, int newWriteTimeout);

    /**
     * Reports the open status of the port
     *
     * @return true if port is open, false if port is closed
     */
    public abstract boolean isOpen();

    /**
     * Returns the timeout for this connection
     *
     * @return the timeout as <tt>int</tt> milliseconds
     */
    public abstract int getTimeout();

    /**
     * Sets the timeout for this connection.
     *
     * @param timeout the timeout as <tt>int</tt> milliseconds
     */
    public abstract void setTimeout(int timeout);

    /**
     * Returns a set of all the available comm port names
     *
     * @return Set of comm port names
     */
    public abstract Set<String> getCommPorts();

}

I am very sorry to tell you but working on a “non visible” Project it is hard for me to help you further.

Also I want to tell you, that it would be great, if you could join our Association, if you use OpenEMS Commercially :slight_smile:

Greetings.