Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nibeheatpump] Use serial transport #7633

Merged
merged 1 commit into from
May 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions bundles/org.openhab.binding.nibeheatpump/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,4 @@

<name>openHAB Add-ons :: Bundles :: Nibe Heatpump Binding</name>

<properties>
<bnd.importpackage>gnu.io;version="[3.12,6)"</bnd.importpackage>
</properties>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,48 @@

import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.SUPPORTED_THING_TYPES_UIDS;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory;
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory;
import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
import org.openhab.binding.nibeheatpump.internal.handler.NibeHeatPumpHandler;
import org.openhab.binding.nibeheatpump.internal.models.PumpModel;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
* The {@link NibeHeatPumpHandlerFactory} is responsible for creating things and
* thing handlers.
*
* @author Pauli Anttila - Initial contribution
*/
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.nibeheatpump")
public class NibeHeatPumpHandlerFactory extends BaseThingHandlerFactory {

private final SerialPortManager serialPortManager;

@Activate
public NibeHeatPumpHandlerFactory(final @Reference SerialPortManager serialPortManager) {
this.serialPortManager = serialPortManager;
}

@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}

@Override
protected ThingHandler createHandler(Thing thing) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new NibeHeatPumpHandler(thing, parsePumpModel(thing));
return new NibeHeatPumpHandler(thing, parsePumpModel(thing), serialPortManager);
}

return null;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@

import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.core.util.HexUtils;
import org.eclipse.smarthome.io.transport.serial.PortInUseException;
import org.eclipse.smarthome.io.transport.serial.SerialPort;
import org.eclipse.smarthome.io.transport.serial.SerialPortEvent;
import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener;
import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier;
import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException;
import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException;
import org.openhab.binding.nibeheatpump.internal.config.NibeHeatPumpConfiguration;
import org.openhab.binding.nibeheatpump.internal.message.MessageFactory;
Expand All @@ -35,14 +42,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

/**
* Connector for serial port communication.
*
Expand All @@ -55,14 +54,16 @@ public class SerialConnector extends NibeHeatPumpBaseConnector {
private InputStream in;
private OutputStream out;
private SerialPort serialPort;
private final SerialPortManager serialPortManager;
private Thread readerThread;
private NibeHeatPumpConfiguration conf;

private final List<byte[]> readQueue = new ArrayList<>();
private final List<byte[]> writeQueue = new ArrayList<>();

SerialConnector() {
public SerialConnector(SerialPortManager serialPortManager) {
logger.debug("Nibe heatpump Serial Port message listener created");
this.serialPortManager = serialPortManager;
}

@Override
Expand All @@ -73,7 +74,10 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump

conf = configuration;
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(conf.serialPort);
SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(conf.serialPort);
if (portIdentifier == null) {
throw new NibeHeatPumpException("Connection failed, no such port: " + conf.serialPort);
}

serialPort = portIdentifier.open(this.getClass().getName(), 2000);
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
Expand All @@ -88,12 +92,10 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump
if (in.markSupported()) {
in.reset();
}
} catch (NoSuchPortException e) {
throw new NibeHeatPumpException("Connection failed, no such a port", e);
} catch (PortInUseException e) {
throw new NibeHeatPumpException("Connection failed, port in use", e);
throw new NibeHeatPumpException("Connection failed, port in use: " + conf.serialPort, e);
} catch (UnsupportedCommOperationException | IOException e) {
throw new NibeHeatPumpException("Connection failed, reason: {}" + e.getMessage(), e);
throw new NibeHeatPumpException("Connection failed, reason: " + e.getMessage(), e);
}

readQueue.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class SimulatorConnector extends NibeHeatPumpBaseConnector {

private final Map<Integer, Integer> cache = Collections.synchronizedMap(new HashMap<>());

SimulatorConnector() {
public SimulatorConnector() {
logger.debug("Nibe heatpump Test message listener created");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package org.openhab.binding.nibeheatpump.internal.handler;

import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
Expand All @@ -34,17 +36,21 @@
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.RefreshType;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.UnDefType;
import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpCommandResult;
import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException;
import org.openhab.binding.nibeheatpump.internal.config.NibeHeatPumpConfiguration;
import org.openhab.binding.nibeheatpump.internal.connection.ConnectorFactory;
import org.openhab.binding.nibeheatpump.internal.connection.NibeHeatPumpConnector;
import org.openhab.binding.nibeheatpump.internal.connection.NibeHeatPumpEventListener;
import org.openhab.binding.nibeheatpump.internal.connection.SerialConnector;
import org.openhab.binding.nibeheatpump.internal.connection.SimulatorConnector;
import org.openhab.binding.nibeheatpump.internal.connection.UDPConnector;
import org.openhab.binding.nibeheatpump.internal.message.ModbusDataReadOutMessage;
import org.openhab.binding.nibeheatpump.internal.message.ModbusReadRequestMessage;
import org.openhab.binding.nibeheatpump.internal.message.ModbusReadResponseMessage;
Expand All @@ -70,6 +76,7 @@ public class NibeHeatPumpHandler extends BaseThingHandler implements NibeHeatPum
private static final int TIMEOUT = 4500;
private final Logger logger = LoggerFactory.getLogger(NibeHeatPumpHandler.class);
private final PumpModel pumpModel;
private final SerialPortManager serialPortManager;
private final List<Integer> itemsToPoll = Collections.synchronizedList(new ArrayList<>());
private final List<Integer> itemsToEnableWrite = new ArrayList<>();
private final Map<Integer, CacheObject> stateMap = Collections.synchronizedMap(new HashMap<>());
Expand Down Expand Up @@ -135,9 +142,28 @@ && getThing().getStatusInfo().getStatus() == ThingStatus.ONLINE) {
private ScheduledFuture<?> pollingJob;
private long lastUpdateTime = 0;

public NibeHeatPumpHandler(Thing thing, PumpModel pumpModel) {
public NibeHeatPumpHandler(Thing thing, PumpModel pumpModel, SerialPortManager serialPortManager) {
super(thing);
this.pumpModel = pumpModel;
this.serialPortManager = serialPortManager;
}

private NibeHeatPumpConnector getConnector() throws NibeHeatPumpException {
ThingTypeUID type = thing.getThingTypeUID();

if (THING_TYPE_F1X45_UDP.equals(type) || THING_TYPE_F1X55_UDP.equals(type) || THING_TYPE_F750_UDP.equals(type)
|| THING_TYPE_F470_UDP.equals(type)) {
return new UDPConnector();
} else if (THING_TYPE_F1X45_SERIAL.equals(type) || THING_TYPE_F1X55_SERIAL.equals(type)
|| THING_TYPE_F750_SERIAL.equals(type) || THING_TYPE_F470_SERIAL.equals(type)) {
return new SerialConnector(serialPortManager);
} else if (THING_TYPE_F1X45_SIMULATOR.equals(type) || THING_TYPE_F1X55_SIMULATOR.equals(type)
|| THING_TYPE_F750_SIMULATOR.equals(type) || THING_TYPE_F470_SIMULATOR.equals(type)) {
return new SimulatorConnector();
}

String description = String.format("Unknown connector type %s", type);
throw new NibeHeatPumpException(description);
}

@Override
Expand Down Expand Up @@ -260,7 +286,7 @@ public void initialize() {

try {
parseWriteEnabledItems();
connector = ConnectorFactory.getConnector(thing.getThingTypeUID());
connector = getConnector();
} catch (IllegalArgumentException | NibeHeatPumpException e) {
String description = String.format("Illegal configuration, %s", e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.nibeheatpump.internal.handler;

import static org.junit.Assert.assertEquals;
import static org.mockito.MockitoAnnotations.initMocks;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
Expand All @@ -23,10 +24,12 @@
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.Mock;
import org.openhab.binding.nibeheatpump.internal.models.PumpModel;
import org.openhab.binding.nibeheatpump.internal.models.VariableInformation;

Expand All @@ -40,15 +43,15 @@ public class NibeHeatPumpHandlerCommand2NibeTest {
private NibeHeatPumpHandler product; // the class under test
private Method m;
private static String METHOD_NAME = "convertCommandToNibeValue";
private Class[] parameterTypes;
private Class<?>[] parameterTypes;
private Object[] parameters;

private int fCoilAddress;

private Command fCommand;

private int fExpected;

private @Mock SerialPortManager serialPortManager;

@Parameterized.Parameters(name = "{index}: f({0}, {1})={2}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { { 47028, new DecimalType("-1"), (byte) 0xFF },
Expand All @@ -68,7 +71,9 @@ public NibeHeatPumpHandlerCommand2NibeTest(final int coilAddress, final Command

@Before
public void setUp() throws Exception {
product = new NibeHeatPumpHandler(null, PumpModel.F1X55);
initMocks(this);

product = new NibeHeatPumpHandler(null, PumpModel.F1X55, serialPortManager);
parameterTypes = new Class[2];
parameterTypes[0] = VariableInformation.class;
parameterTypes[1] = Command.class;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.nibeheatpump.internal.handler;

import static org.junit.Assert.assertEquals;
import static org.mockito.MockitoAnnotations.initMocks;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
Expand All @@ -21,10 +22,12 @@
import java.util.Collection;

import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.Mock;
import org.openhab.binding.nibeheatpump.internal.models.PumpModel;
import org.openhab.binding.nibeheatpump.internal.models.VariableInformation;

Expand All @@ -50,6 +53,8 @@ public class NibeHeatPumpHandlerNibe2StateTest {
private String fType;
private String fExpected;

private @Mock SerialPortManager serialPortManager;

@Parameterized.Parameters(name = "{index}: f({0}, {1}, {3})={4}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { //
Expand Down Expand Up @@ -93,7 +98,9 @@ public NibeHeatPumpHandlerNibe2StateTest(final int coilAddress, final int value,

@Before
public void setUp() throws Exception {
product = new NibeHeatPumpHandler(null, PumpModel.F1X55);
initMocks(this);

product = new NibeHeatPumpHandler(null, PumpModel.F1X55, serialPortManager);
parameterTypes = new Class[3];
parameterTypes[0] = VariableInformation.class;
parameterTypes[1] = int.class;
Expand Down