[powermax] Add null annotations (#11275)

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
lolodomo 2021-10-10 10:04:37 +02:00 committed by GitHub
parent 2b5431df00
commit 99f595450a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 723 additions and 484 deletions

View File

@ -12,21 +12,24 @@
*/
package org.openhab.binding.powermax.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link PowermaxIpConfiguration} is responsible for holding
* configuration informations associated to a Powermax IP thing type
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxIpConfiguration {
public String ip;
public Integer tcpPort;
public Integer motionOffDelay;
public Boolean allowArming;
public Boolean allowDisarming;
public String pinCode;
public Boolean forceStandardMode;
public String panelType;
public Boolean autoSyncTime;
public String ip = "";
public int tcpPort = 0;
public int motionOffDelay = 3;
public boolean allowArming = false;
public boolean allowDisarming = false;
public String pinCode = "";
public boolean forceStandardMode = false;
public String panelType = "PowerMaxPro";
public boolean autoSyncTime = false;
}

View File

@ -12,20 +12,23 @@
*/
package org.openhab.binding.powermax.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link PowermaxSerialConfiguration} is responsible for holding
* configuration informations associated to a Powermax serial thing type
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxSerialConfiguration {
public String serialPort;
public Integer motionOffDelay;
public Boolean allowArming;
public Boolean allowDisarming;
public String pinCode;
public Boolean forceStandardMode;
public String panelType;
public Boolean autoSyncTime;
public String serialPort = "";
public int motionOffDelay = 3;
public boolean allowArming = false;
public boolean allowDisarming = false;
public String pinCode = "";
public boolean forceStandardMode = false;
public String panelType = "PowerMaxPro";
public boolean autoSyncTime = false;
}

View File

@ -12,15 +12,18 @@
*/
package org.openhab.binding.powermax.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link PowermaxX10Configuration} is responsible for holding
* configuration informations associated to a Powermax IP thing type
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxX10Configuration {
public static final String DEVICE_NUMBER = "deviceNumber";
public Integer deviceNumber;
public int deviceNumber = -1;
}

View File

@ -12,15 +12,18 @@
*/
package org.openhab.binding.powermax.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link PowermaxZoneConfiguration} is responsible for holding
* configuration informations associated to a Powermax IP thing type
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxZoneConfiguration {
public static final String ZONE_NUMBER = "zoneNumber";
public Integer zoneNumber;
public int zoneNumber = -1;
}

View File

@ -18,6 +18,8 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.message.PowermaxBaseMessage;
import org.openhab.binding.powermax.internal.message.PowermaxMessageEvent;
import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener;
@ -30,17 +32,19 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public abstract class PowermaxConnector implements PowermaxConnectorInterface {
private final Logger logger = LoggerFactory.getLogger(PowermaxConnector.class);
private InputStream input;
private OutputStream output;
protected final String readerThreadName;
private final List<PowermaxMessageEventListener> listeners = new ArrayList<>();
private @Nullable InputStream input;
private @Nullable OutputStream output;
private boolean connected;
protected String readerThreadName;
private Thread readerThread;
private @Nullable Thread readerThread;
private long waitingForResponse;
private List<PowermaxMessageEventListener> listeners = new ArrayList<>();
public PowermaxConnector(String readerThreadName) {
this.readerThreadName = readerThreadName;
@ -58,26 +62,29 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
protected void cleanup(boolean closeStreams) {
logger.debug("cleanup(): cleaning up Connection");
if (readerThread != null) {
readerThread.interrupt();
Thread thread = readerThread;
if (thread != null) {
thread.interrupt();
try {
readerThread.join();
thread.join();
} catch (InterruptedException e) {
}
}
if (closeStreams) {
if (output != null) {
OutputStream out = output;
if (out != null) {
try {
output.close();
out.close();
} catch (IOException e) {
logger.debug("Error while closing the output stream: {}", e.getMessage());
}
}
if (input != null) {
InputStream in = input;
if (in != null) {
try {
input.close();
in.close();
} catch (IOException e) {
logger.debug("Error while closing the input stream: {}", e.getMessage());
}
@ -107,16 +114,20 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
/**
* Handles a communication failure
*/
public void handleCommunicationFailure(String message) {
public void handleCommunicationFailure(@Nullable String message) {
close();
listeners.forEach(listener -> listener.onCommunicationFailure(message));
listeners.forEach(listener -> listener.onCommunicationFailure(message != null ? message : ""));
}
@Override
public void sendMessage(byte[] data) {
try {
output.write(data);
output.flush();
OutputStream out = output;
if (out == null) {
throw new IOException("output stream is undefined");
}
out.write(data);
out.flush();
} catch (IOException e) {
logger.debug("sendMessage(): Writing error: {}", e.getMessage(), e);
handleCommunicationFailure(e.getMessage());
@ -125,7 +136,11 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
@Override
public int read(byte[] buffer) throws IOException {
return input.read(buffer);
InputStream in = input;
if (in == null) {
throw new IOException("input stream is undefined");
}
return in.read(buffer);
}
@Override
@ -141,7 +156,7 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
/**
* @return the input stream
*/
public InputStream getInput() {
public @Nullable InputStream getInput() {
return input;
}
@ -150,14 +165,14 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
*
* @param input the input stream
*/
public void setInput(InputStream input) {
public void setInput(@Nullable InputStream input) {
this.input = input;
}
/**
* @return the output stream
*/
public OutputStream getOutput() {
public @Nullable OutputStream getOutput() {
return output;
}
@ -166,7 +181,7 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
*
* @param output the output stream
*/
public void setOutput(OutputStream output) {
public void setOutput(@Nullable OutputStream output) {
this.output = output;
}
@ -190,7 +205,7 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
/**
* @return the thread that handles the message reading
*/
public Thread getReaderThread() {
public @Nullable Thread getReaderThread() {
return readerThread;
}

View File

@ -14,6 +14,7 @@ package org.openhab.binding.powermax.internal.connector;
import java.io.IOException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener;
/**
@ -21,6 +22,7 @@ import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListene
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public interface PowermaxConnectorInterface {
/**

View File

@ -16,6 +16,7 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.powermax.internal.message.PowermaxCommManager;
import org.openhab.binding.powermax.internal.message.PowermaxReceiveType;
import org.openhab.core.util.HexUtils;
@ -27,14 +28,15 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxReaderThread extends Thread {
private final Logger logger = LoggerFactory.getLogger(PowermaxReaderThread.class);
private static final int READ_BUFFER_SIZE = 20;
private static final int MAX_MSG_SIZE = 0xC0;
private PowermaxConnector connector;
private final Logger logger = LoggerFactory.getLogger(PowermaxReaderThread.class);
private final PowermaxConnector connector;
/**
* Constructor

View File

@ -13,7 +13,11 @@
package org.openhab.binding.powermax.internal.connector;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.io.transport.serial.SerialPort;
import org.openhab.core.io.transport.serial.SerialPortEvent;
import org.openhab.core.io.transport.serial.SerialPortEventListener;
@ -27,6 +31,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxSerialConnector extends PowermaxConnector implements SerialPortEventListener {
private final Logger logger = LoggerFactory.getLogger(PowermaxSerialConnector.class);
@ -34,7 +39,7 @@ public class PowermaxSerialConnector extends PowermaxConnector implements Serial
private final String serialPortName;
private final int baudRate;
private final SerialPortManager serialPortManager;
private SerialPort serialPort;
private @Nullable SerialPort serialPort;
/**
* Constructor
@ -50,7 +55,6 @@ public class PowermaxSerialConnector extends PowermaxConnector implements Serial
this.serialPortManager = serialPortManager;
this.serialPortName = serialPortName;
this.baudRate = baudRate;
this.serialPort = null;
}
@Override
@ -65,26 +69,31 @@ public class PowermaxSerialConnector extends PowermaxConnector implements Serial
SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
serialPort = commPort;
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.enableReceiveThreshold(1);
serialPort.enableReceiveTimeout(250);
commPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
commPort.enableReceiveThreshold(1);
commPort.enableReceiveTimeout(250);
setInput(serialPort.getInputStream());
setOutput(serialPort.getOutputStream());
InputStream inputStream = commPort.getInputStream();
setInput(inputStream);
OutputStream outputStream = commPort.getOutputStream();
setOutput(outputStream);
getOutput().flush();
if (getInput().markSupported()) {
getInput().reset();
if (outputStream != null) {
outputStream.flush();
}
if (inputStream != null && inputStream.markSupported()) {
inputStream.reset();
}
// RXTX serial port library causes high CPU load
// Start event listener, which will just sleep and slow down event
// loop
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
commPort.addEventListener(this);
commPort.notifyOnDataAvailable(true);
setReaderThread(new PowermaxReaderThread(this, readerThreadName));
getReaderThread().start();
PowermaxReaderThread readerThread = new PowermaxReaderThread(this, readerThreadName);
setReaderThread(readerThread);
readerThread.start();
setConnected(true);
}
@ -93,14 +102,15 @@ public class PowermaxSerialConnector extends PowermaxConnector implements Serial
public void close() {
logger.debug("close(): Closing Serial Connection");
if (serialPort != null) {
serialPort.removeEventListener();
SerialPort commPort = serialPort;
if (commPort != null) {
commPort.removeEventListener();
}
super.cleanup(true);
if (serialPort != null) {
serialPort.close();
if (commPort != null) {
commPort.close();
}
serialPort = null;

View File

@ -18,6 +18,8 @@ import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -26,6 +28,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxTcpConnector extends PowermaxConnector {
private final Logger logger = LoggerFactory.getLogger(PowermaxTcpConnector.class);
@ -33,7 +36,7 @@ public class PowermaxTcpConnector extends PowermaxConnector {
private final String ipAddress;
private final int tcpPort;
private final int connectTimeout;
private Socket tcpSocket;
private @Nullable Socket tcpSocket;
/**
* Constructor.
@ -54,16 +57,18 @@ public class PowermaxTcpConnector extends PowermaxConnector {
public void open() throws Exception {
logger.debug("open(): Opening TCP Connection");
tcpSocket = new Socket();
tcpSocket.setSoTimeout(250);
Socket socket = new Socket();
tcpSocket = socket;
socket.setSoTimeout(250);
SocketAddress socketAddress = new InetSocketAddress(ipAddress, tcpPort);
tcpSocket.connect(socketAddress, connectTimeout);
socket.connect(socketAddress, connectTimeout);
setInput(tcpSocket.getInputStream());
setOutput(tcpSocket.getOutputStream());
setInput(socket.getInputStream());
setOutput(socket.getOutputStream());
setReaderThread(new PowermaxReaderThread(this, readerThreadName));
getReaderThread().start();
PowermaxReaderThread readerThread = new PowermaxReaderThread(this, readerThreadName);
setReaderThread(readerThread);
readerThread.start();
setConnected(true);
}
@ -74,9 +79,10 @@ public class PowermaxTcpConnector extends PowermaxConnector {
super.cleanup(false);
if (tcpSocket != null) {
Socket socket = tcpSocket;
if (socket != null) {
try {
tcpSocket.close();
socket.close();
} catch (IOException e) {
logger.debug("Error while closing the socket: {}", e.getMessage());
}

View File

@ -15,7 +15,9 @@ package org.openhab.binding.powermax.internal.console;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.powermax.internal.handler.PowermaxBridgeHandler;
import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.openhab.core.io.console.Console;
import org.openhab.core.io.console.extensions.AbstractConsoleCommandExtension;
import org.openhab.core.io.console.extensions.ConsoleCommandExtension;
@ -23,6 +25,7 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingRegistry;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandler;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@ -31,6 +34,7 @@ import org.osgi.service.component.annotations.Reference;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
@Component(service = ConsoleCommandExtension.class)
public class PowermaxCommandExtension extends AbstractConsoleCommandExtension {
@ -38,10 +42,12 @@ public class PowermaxCommandExtension extends AbstractConsoleCommandExtension {
private static final String DOWNLOAD_SETUP = "download_setup";
private static final String BRIDGE_STATE = "bridge_state";
private ThingRegistry thingRegistry;
private final ThingRegistry thingRegistry;
public PowermaxCommandExtension() {
@Activate
public PowermaxCommandExtension(final @Reference ThingRegistry thingRegistry) {
super("powermax", "Interact with the Powermax binding.");
this.thingRegistry = thingRegistry;
}
@Override
@ -83,8 +89,11 @@ public class PowermaxCommandExtension extends AbstractConsoleCommandExtension {
console.println("Command '" + args[1] + "' handled.");
break;
case BRIDGE_STATE:
for (String line : handler.getCurrentState().toString().split("\n")) {
console.println(line);
PowermaxState state = handler.getCurrentState();
if (state != null) {
for (String line : state.toString().split("\n")) {
console.println(line);
}
}
break;
default:
@ -104,13 +113,4 @@ public class PowermaxCommandExtension extends AbstractConsoleCommandExtension {
buildCommandUsage("<bridgeUID> " + DOWNLOAD_SETUP, "download setup"),
buildCommandUsage("<bridgeUID> " + BRIDGE_STATE, "show current state") });
}
@Reference
protected void setThingRegistry(ThingRegistry thingRegistry) {
this.thingRegistry = thingRegistry;
}
protected void unsetThingRegistry(ThingRegistry thingRegistry) {
this.thingRegistry = null;
}
}

View File

@ -48,10 +48,10 @@ import org.slf4j.LoggerFactory;
public class PowermaxDiscoveryService extends AbstractDiscoveryService
implements PowermaxPanelSettingsListener, ThingHandlerService {
private final Logger logger = LoggerFactory.getLogger(PowermaxDiscoveryService.class);
private static final int SEARCH_TIME = 5;
private final Logger logger = LoggerFactory.getLogger(PowermaxDiscoveryService.class);
private @Nullable PowermaxBridgeHandler bridgeHandler;
/**

View File

@ -23,6 +23,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.config.PowermaxIpConfiguration;
import org.openhab.binding.powermax.internal.config.PowermaxSerialConfiguration;
import org.openhab.binding.powermax.internal.discovery.PowermaxDiscoveryService;
@ -36,6 +38,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.openhab.binding.powermax.internal.state.PowermaxStateContainer.Value;
import org.openhab.binding.powermax.internal.state.PowermaxStateEvent;
import org.openhab.binding.powermax.internal.state.PowermaxStateEventListener;
import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.library.types.OnOffType;
@ -59,18 +62,12 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxBridgeHandler extends BaseBridgeHandler implements PowermaxStateEventListener {
private final Logger logger = LoggerFactory.getLogger(PowermaxBridgeHandler.class);
private final SerialPortManager serialPortManager;
private final TimeZoneProvider timeZoneProvider;
private static final long ONE_MINUTE = TimeUnit.MINUTES.toMillis(1);
private static final long FIVE_MINUTES = TimeUnit.MINUTES.toMillis(5);
/** Default delay in milliseconds to reset a motion detection */
private static final long DEFAULT_MOTION_OFF_DELAY = TimeUnit.MINUTES.toMillis(3);
private static final int NB_EVENT_LOG = 10;
private static final PowermaxPanelType DEFAULT_PANEL_TYPE = PowermaxPanelType.POWERMAX_PRO;
@ -79,9 +76,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
private static final int MAX_DOWNLOAD_ATTEMPTS = 3;
private ScheduledFuture<?> globalJob;
private final Logger logger = LoggerFactory.getLogger(PowermaxBridgeHandler.class);
private List<PowermaxPanelSettingsListener> listeners = new CopyOnWriteArrayList<>();
private final SerialPortManager serialPortManager;
private final TimeZoneProvider timeZoneProvider;
private final List<PowermaxPanelSettingsListener> listeners = new CopyOnWriteArrayList<>();
private @Nullable ScheduledFuture<?> globalJob;
/** The delay in milliseconds to reset a motion detection */
private long motionOffDelay;
@ -96,7 +98,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
private PowermaxState currentState;
/** The object in charge of the communication with the Powermax alarm system */
private PowermaxCommManager commManager;
private @Nullable PowermaxCommManager commManager;
private int remainingDownloadAttempts;
@ -104,6 +106,8 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
super(thing);
this.serialPortManager = serialPortManager;
this.timeZoneProvider = timeZoneProvider;
this.pinCode = "";
this.currentState = new PowermaxState(new PowermaxPanelSettings(DEFAULT_PANEL_TYPE), timeZoneProvider);
}
@Override
@ -111,12 +115,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
return Collections.singleton(PowermaxDiscoveryService.class);
}
public PowermaxState getCurrentState() {
return currentState;
public @Nullable PowermaxState getCurrentState() {
PowermaxCommManager localCommManager = commManager;
return (localCommManager == null) ? null : currentState;
}
public PowermaxPanelSettings getPanelSettings() {
return (commManager == null) ? null : commManager.getPanelSettings();
public @Nullable PowermaxPanelSettings getPanelSettings() {
PowermaxCommManager localCommManager = commManager;
return (localCommManager == null) ? null : localCommManager.getPanelSettings();
}
@Override
@ -137,7 +143,8 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
}
if (errorMsg == null) {
if (globalJob == null || globalJob.isCancelled()) {
ScheduledFuture<?> job = globalJob;
if (job == null || job.isCancelled()) {
// Delay the startup in case the handler is restarted immediately
globalJob = scheduler.scheduleWithFixedDelay(() -> {
try {
@ -146,7 +153,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
updateRingingState();
if (isConnected()) {
checkKeepAlive();
commManager.retryDownloadSetup(remainingDownloadAttempts);
retryDownloadSetup();
} else {
tryReconnect();
}
@ -160,30 +167,27 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
}
}
private String initializeBridgeSerial(PowermaxSerialConfiguration config, String threadName) {
private @Nullable String initializeBridgeSerial(PowermaxSerialConfiguration config, String threadName) {
String errorMsg = null;
if (config.serialPort != null && !config.serialPort.trim().isEmpty()
&& !config.serialPort.trim().startsWith("rfc2217")) {
motionOffDelay = getMotionOffDelaySetting(config.motionOffDelay, DEFAULT_MOTION_OFF_DELAY);
boolean allowArming = getBooleanSetting(config.allowArming, false);
boolean allowDisarming = getBooleanSetting(config.allowDisarming, false);
String serialPort = config.serialPort.trim();
if (!serialPort.isEmpty() && !serialPort.startsWith("rfc2217")) {
motionOffDelay = config.motionOffDelay * ONE_MINUTE;
pinCode = config.pinCode;
forceStandardMode = getBooleanSetting(config.forceStandardMode, false);
forceStandardMode = config.forceStandardMode;
PowermaxPanelType panelType = getPanelTypeSetting(config.panelType, DEFAULT_PANEL_TYPE);
boolean autoSyncTime = getBooleanSetting(config.autoSyncTime, false);
PowermaxArmMode.DISARMED.setAllowedCommand(allowDisarming);
PowermaxArmMode.ARMED_HOME.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_AWAY.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(allowArming);
PowermaxArmMode.DISARMED.setAllowedCommand(config.allowDisarming);
PowermaxArmMode.ARMED_HOME.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_AWAY.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(config.allowArming);
commManager = new PowermaxCommManager(config.serialPort, panelType, forceStandardMode, autoSyncTime,
commManager = new PowermaxCommManager(serialPort, panelType, forceStandardMode, config.autoSyncTime,
serialPortManager, threadName, timeZoneProvider);
} else {
if (config.serialPort != null && config.serialPort.trim().startsWith("rfc2217")) {
if (serialPort.startsWith("rfc2217")) {
errorMsg = "Please use the IP Connection thing type for a serial over IP connection.";
} else {
errorMsg = "serialPort setting must be defined in thing configuration";
@ -192,26 +196,24 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
return errorMsg;
}
private String initializeBridgeIp(PowermaxIpConfiguration config, String threadName) {
private @Nullable String initializeBridgeIp(PowermaxIpConfiguration config, String threadName) {
String errorMsg = null;
if (config.ip != null && !config.ip.trim().isEmpty() && config.tcpPort != null) {
motionOffDelay = getMotionOffDelaySetting(config.motionOffDelay, DEFAULT_MOTION_OFF_DELAY);
boolean allowArming = getBooleanSetting(config.allowArming, false);
boolean allowDisarming = getBooleanSetting(config.allowDisarming, false);
String ip = config.ip.trim();
if (!ip.isEmpty() && config.tcpPort > 0) {
motionOffDelay = config.motionOffDelay * ONE_MINUTE;
pinCode = config.pinCode;
forceStandardMode = getBooleanSetting(config.forceStandardMode, false);
forceStandardMode = config.forceStandardMode;
PowermaxPanelType panelType = getPanelTypeSetting(config.panelType, DEFAULT_PANEL_TYPE);
boolean autoSyncTime = getBooleanSetting(config.autoSyncTime, false);
PowermaxArmMode.DISARMED.setAllowedCommand(allowDisarming);
PowermaxArmMode.ARMED_HOME.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_AWAY.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(allowArming);
PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(allowArming);
PowermaxArmMode.DISARMED.setAllowedCommand(config.allowDisarming);
PowermaxArmMode.ARMED_HOME.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_AWAY.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(config.allowArming);
PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(config.allowArming);
commManager = new PowermaxCommManager(config.ip, config.tcpPort, panelType, forceStandardMode, autoSyncTime,
commManager = new PowermaxCommManager(ip, config.tcpPort, panelType, forceStandardMode, config.autoSyncTime,
threadName, timeZoneProvider);
} else {
errorMsg = "ip and port settings must be defined in thing configuration";
@ -222,8 +224,9 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
@Override
public void dispose() {
logger.debug("Handler disposed for thing {}", getThing().getUID());
if (globalJob != null && !globalJob.isCancelled()) {
globalJob.cancel(true);
ScheduledFuture<?> job = globalJob;
if (job != null && !job.isCancelled()) {
job.cancel(true);
globalJob = null;
}
closeConnection();
@ -236,13 +239,15 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* than the value defined by the variable motionOffDelay
*/
private void updateMotionSensorState() {
long now = System.currentTimeMillis();
if (currentState != null) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager != null) {
long now = System.currentTimeMillis();
boolean update = false;
PowermaxState updateState = commManager.createNewState();
PowermaxPanelSettings panelSettings = getPanelSettings();
PowermaxState updateState = localCommManager.createNewState();
PowermaxPanelSettings panelSettings = localCommManager.getPanelSettings();
for (int i = 1; i <= panelSettings.getNbZones(); i++) {
if (panelSettings.getZoneSettings(i) != null && panelSettings.getZoneSettings(i).isMotionSensor()
PowermaxZoneSettings zoneSettings = panelSettings.getZoneSettings(i);
if (zoneSettings != null && zoneSettings.isMotionSensor()
&& currentState.getZone(i).isLastTripBeforeTime(now - motionOffDelay)) {
update = true;
updateState.getZone(i).tripped.setValue(false);
@ -259,12 +264,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* Turn off the Ringing flag when the bell time expires
*/
private void updateRingingState() {
if (currentState != null && Boolean.TRUE.equals(currentState.ringing.getValue())) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager != null && Boolean.TRUE.equals(currentState.ringing.getValue())) {
long now = System.currentTimeMillis();
long bellTime = getPanelSettings().getBellTime() * ONE_MINUTE;
long bellTime = localCommManager.getPanelSettings().getBellTime() * ONE_MINUTE;
if ((currentState.ringingSince.getValue() + bellTime) < now) {
PowermaxState updateState = commManager.createNewState();
Long ringingSince = currentState.ringingSince.getValue();
if (ringingSince != null && (ringingSince + bellTime) < now) {
PowermaxState updateState = localCommManager.createNewState();
updateState.ringing.setValue(false);
updateChannelsFromAlarmState(RINGING, updateState);
currentState.merge(updateState);
@ -276,25 +283,33 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* Check that we're actively communicating with the panel
*/
private void checkKeepAlive() {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
return;
}
long now = System.currentTimeMillis();
if (Boolean.TRUE.equals(currentState.powerlinkMode.getValue())
&& (currentState.lastKeepAlive.getValue() != null)
&& ((now - currentState.lastKeepAlive.getValue()) > ONE_MINUTE)) {
Long lastKeepAlive = currentState.lastKeepAlive.getValue();
Long lastMessageTime = currentState.lastMessageTime.getValue();
if (Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) && (lastKeepAlive != null)
&& ((now - lastKeepAlive) > ONE_MINUTE)) {
// In Powerlink mode: let Powermax know we are alive
commManager.sendRestoreMessage();
localCommManager.sendRestoreMessage();
currentState.lastKeepAlive.setValue(now);
} else if (!Boolean.TRUE.equals(currentState.downloadMode.getValue())
&& (currentState.lastMessageTime.getValue() != null)
&& ((now - currentState.lastMessageTime.getValue()) > FIVE_MINUTES)) {
} else if (!Boolean.TRUE.equals(currentState.downloadMode.getValue()) && (lastMessageTime != null)
&& ((now - lastMessageTime) > FIVE_MINUTES)) {
// In Standard mode: ping the panel every so often to detect disconnects
commManager.sendMessage(PowermaxSendType.STATUS);
localCommManager.sendMessage(PowermaxSendType.STATUS);
}
}
private void tryReconnect() {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
return;
}
logger.info("Trying to connect or reconnect...");
closeConnection();
currentState = commManager.createNewState();
currentState = localCommManager.createNewState();
try {
openConnection();
logger.debug("openConnection(): connected");
@ -305,7 +320,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
updateChannelsFromAlarmState(MODE, currentState);
processPanelSettings();
} else {
commManager.startDownload();
localCommManager.startDownload();
}
} catch (Exception e) {
logger.debug("openConnection(): {}", e.getMessage(), e);
@ -320,9 +335,10 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* @return true if the connection has been opened
*/
private synchronized void openConnection() throws Exception {
if (commManager != null) {
commManager.addEventListener(this);
commManager.open();
PowermaxCommManager localCommManager = commManager;
if (localCommManager != null) {
localCommManager.addEventListener(this);
localCommManager.open();
}
remainingDownloadAttempts = MAX_DOWNLOAD_ATTEMPTS;
}
@ -331,15 +347,24 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* Close TCP or Serial connection to the Powermax Alarm Panel and remove the Event Listener
*/
private synchronized void closeConnection() {
if (commManager != null) {
commManager.close();
commManager.removeEventListener(this);
PowermaxCommManager localCommManager = commManager;
if (localCommManager != null) {
localCommManager.close();
localCommManager.removeEventListener(this);
}
logger.debug("closeConnection(): disconnected");
}
private boolean isConnected() {
return commManager == null ? false : commManager.isConnected();
PowermaxCommManager localCommManager = commManager;
return localCommManager == null ? false : localCommManager.isConnected();
}
private void retryDownloadSetup() {
PowermaxCommManager localCommManager = commManager;
if (localCommManager != null) {
localCommManager.retryDownloadSetup(remainingDownloadAttempts);
}
}
@Override
@ -347,7 +372,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
logger.debug("Received command {} from channel {}", command, channelUID.getId());
if (command instanceof RefreshType) {
updateChannelsFromAlarmState(channelUID.getId(), currentState);
updateChannelsFromAlarmState(channelUID.getId(), getCurrentState());
} else {
switch (channelUID.getId()) {
case ARM_MODE:
@ -384,62 +409,81 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
}
private void armCommand(PowermaxArmMode armMode) {
if (!isConnected()) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
logger.debug("Powermax alarm binding not correctly initialized. Arm command is ignored.");
} else if (!isConnected()) {
logger.debug("Powermax alarm binding not connected. Arm command is ignored.");
} else {
commManager.requestArmMode(armMode,
Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) ? getPanelSettings().getFirstPinCode()
localCommManager.requestArmMode(armMode,
Boolean.TRUE.equals(currentState.powerlinkMode.getValue())
? localCommManager.getPanelSettings().getFirstPinCode()
: pinCode);
}
}
private void pgmCommand(Command command) {
if (!isConnected()) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
logger.debug("Powermax alarm binding not correctly initialized. PGM command is ignored.");
} else if (!isConnected()) {
logger.debug("Powermax alarm binding not connected. PGM command is ignored.");
} else {
commManager.sendPGMX10(command, null);
localCommManager.sendPGMX10(command, null);
}
}
public void x10Command(Byte deviceNr, Command command) {
if (!isConnected()) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
logger.debug("Powermax alarm binding not correctly initialized. X10 command is ignored.");
} else if (!isConnected()) {
logger.debug("Powermax alarm binding not connected. X10 command is ignored.");
} else {
commManager.sendPGMX10(command, deviceNr);
localCommManager.sendPGMX10(command, deviceNr);
}
}
public void zoneBypassed(byte zoneNr, boolean bypassed) {
if (!isConnected()) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
logger.debug("Powermax alarm binding not correctly initialized. Zone bypass command is ignored.");
} else if (!isConnected()) {
logger.debug("Powermax alarm binding not connected. Zone bypass command is ignored.");
} else if (!Boolean.TRUE.equals(currentState.powerlinkMode.getValue())) {
logger.debug("Powermax alarm binding: Bypass option only supported in Powerlink mode");
} else if (!getPanelSettings().isBypassEnabled()) {
} else if (!localCommManager.getPanelSettings().isBypassEnabled()) {
logger.debug("Powermax alarm binding: Bypass option not enabled in panel settings");
} else {
commManager.sendZoneBypass(bypassed, zoneNr, getPanelSettings().getFirstPinCode());
localCommManager.sendZoneBypass(bypassed, zoneNr, localCommManager.getPanelSettings().getFirstPinCode());
}
}
private void downloadEventLog() {
if (!isConnected()) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
logger.debug("Powermax alarm binding not correctly initialized. Event logs command is ignored.");
} else if (!isConnected()) {
logger.debug("Powermax alarm binding not connected. Event logs command is ignored.");
} else {
commManager.requestEventLog(
Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) ? getPanelSettings().getFirstPinCode()
: pinCode);
localCommManager.requestEventLog(Boolean.TRUE.equals(currentState.powerlinkMode.getValue())
? localCommManager.getPanelSettings().getFirstPinCode()
: pinCode);
}
}
public void downloadSetup() {
if (!isConnected()) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
logger.debug("Powermax alarm binding not correctly initialized. Download setup command is ignored.");
} else if (!isConnected()) {
logger.debug("Powermax alarm binding not connected. Download setup command is ignored.");
} else if (!Boolean.TRUE.equals(currentState.powerlinkMode.getValue())) {
logger.debug("Powermax alarm binding: download setup only supported in Powerlink mode");
} else if (commManager.isDownloadRunning()) {
} else if (localCommManager.isDownloadRunning()) {
logger.debug("Powermax alarm binding: download setup not started as one is in progress");
} else {
commManager.startDownload();
localCommManager.startDownload();
if (currentState.lastKeepAlive.getValue() != null) {
currentState.lastKeepAlive.setValue(System.currentTimeMillis());
}
@ -447,11 +491,17 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
}
public String getInfoSetup() {
return (getPanelSettings() == null) ? "" : getPanelSettings().getInfo();
PowermaxPanelSettings panelSettings = getPanelSettings();
return (panelSettings == null) ? "" : panelSettings.getInfo();
}
@Override
public void onNewStateEvent(EventObject event) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
return;
}
PowermaxStateEvent stateEvent = (PowermaxStateEvent) event;
PowermaxState updateState = stateEvent.getState();
@ -459,7 +509,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
&& Boolean.TRUE.equals(updateState.downloadSetupRequired.getValue())) {
// After Enrolling Powerlink or if a reset is required
logger.debug("Powermax alarm binding: Reset");
commManager.startDownload();
localCommManager.startDownload();
updateState.downloadSetupRequired.setValue(false);
if (currentState.lastKeepAlive.getValue() != null) {
currentState.lastKeepAlive.setValue(System.currentTimeMillis());
@ -469,12 +519,13 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
// Were are in standard mode but received a keep alive message
// so we switch in PowerLink mode
logger.debug("Powermax alarm binding: Switching to Powerlink mode");
commManager.startDownload();
localCommManager.startDownload();
}
boolean doProcessSettings = (updateState.powerlinkMode.getValue() != null);
getPanelSettings().getZoneRange().forEach(i -> {
PowermaxPanelSettings panelSettings = localCommManager.getPanelSettings();
panelSettings.getZoneRange().forEach(i -> {
if (Boolean.TRUE.equals(updateState.getZone(i).armed.getValue())
&& Boolean.TRUE.equals(currentState.getZone(i).bypassed.getValue())) {
updateState.getZone(i).armed.setValue(false);
@ -485,7 +536,6 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
updateChannelsFromAlarmState(updateState);
currentState.merge(updateState);
PowermaxPanelSettings panelSettings = getPanelSettings();
if (!updateState.getUpdatedZoneNames().isEmpty()) {
for (Integer zoneIdx : updateState.getUpdatedZoneNames().keySet()) {
if (panelSettings.getZoneSettings(zoneIdx) != null) {
@ -499,7 +549,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
if (doProcessSettings) {
// There is a change of mode (standard or Powerlink)
processPanelSettings();
commManager.exitDownload();
localCommManager.exitDownload();
}
}
@ -510,9 +560,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
}
private void processPanelSettings() {
if (commManager.processPanelSettings(Boolean.TRUE.equals(currentState.powerlinkMode.getValue()))) {
PowermaxCommManager localCommManager = commManager;
if (localCommManager == null) {
return;
}
if (localCommManager.processPanelSettings(Boolean.TRUE.equals(currentState.powerlinkMode.getValue()))) {
for (PowermaxPanelSettingsListener listener : listeners) {
listener.onPanelSettingsUpdated(getPanelSettings());
listener.onPanelSettingsUpdated(localCommManager.getPanelSettings());
}
remainingDownloadAttempts = 0;
} else {
@ -525,10 +580,10 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
updatePropertiesFromPanelSettings();
if (Boolean.TRUE.equals(currentState.powerlinkMode.getValue())) {
logger.info("Powermax alarm binding: running in Powerlink mode");
commManager.sendRestoreMessage();
localCommManager.sendRestoreMessage();
} else {
logger.info("Powermax alarm binding: running in Standard mode");
commManager.getInfosWhenInStandardMode();
localCommManager.getInfosWhenInStandardMode();
}
}
@ -537,7 +592,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
*
* @param state: the alarm system state
*/
private void updateChannelsFromAlarmState(PowermaxState state) {
private void updateChannelsFromAlarmState(@Nullable PowermaxState state) {
updateChannelsFromAlarmState(null, state);
}
@ -547,7 +602,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* @param channel: filter on a particular channel; if null, consider all channels
* @param state: the alarm system state
*/
private synchronized void updateChannelsFromAlarmState(String channel, PowermaxState state) {
private synchronized void updateChannelsFromAlarmState(@Nullable String channel, @Nullable PowermaxState state) {
if (state == null || !isConnected()) {
return;
}
@ -555,17 +610,16 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
for (Value<?> value : state.getValues()) {
String vChannel = value.getChannel();
if (((channel == null) || channel.equals(vChannel)) && (vChannel != null) && isLinked(vChannel)
&& (value.getValue() != null)) {
if (((channel == null) || channel.equals(vChannel)) && isLinked(vChannel) && (value.getValue() != null)) {
updateState(vChannel, value.getState());
}
}
for (int i = 1; i <= NB_EVENT_LOG; i++) {
String channel2 = String.format(EVENT_LOG, i);
if (((channel == null) || channel.equals(channel2)) && isLinked(channel2)
&& (state.getEventLog(i) != null)) {
updateState(channel2, new StringType(state.getEventLog(i)));
String log = state.getEventLog(i);
if (((channel == null) || channel.equals(channel2)) && isLinked(channel2) && (log != null)) {
updateState(channel2, new StringType(log));
}
}
@ -574,14 +628,13 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
PowermaxThingHandler handler = (PowermaxThingHandler) thing.getHandler();
if (handler != null) {
if (thing.getThingTypeUID().equals(THING_TYPE_ZONE)) {
// All of the zone state objects will have the same list of values.
// The use of getZone(1) here is just to get any PowermaxZoneState
// and use it to get the list of zone channels.
for (Value<?> value : state.getZone(1).getValues()) {
String channelId = value.getChannel();
if ((channelId != null) && ((channel == null) || channel.equals(channelId))) {
if ((channel == null) || channel.equals(channelId)) {
handler.updateChannelFromAlarmState(channelId, state);
}
}
@ -606,11 +659,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
* Update properties to match the alarm panel settings
*/
private void updatePropertiesFromPanelSettings() {
PowermaxPanelSettings panelSettings = getPanelSettings();
if (panelSettings == null) {
return;
}
String value;
Map<String, String> properties = editProperties();
PowermaxPanelSettings panelSettings = getPanelSettings();
value = (panelSettings.getPanelType() != null) ? panelSettings.getPanelType().getLabel() : null;
if (value != null && !value.isEmpty()) {
value = panelSettings.getPanelType().getLabel();
if (!value.isEmpty()) {
properties.put(Thing.PROPERTY_MODEL_ID, value);
}
value = panelSettings.getPanelSerial();
@ -640,25 +696,13 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
return listeners.remove(listener);
}
private boolean getBooleanSetting(Boolean value, boolean defaultValue) {
return value != null ? value.booleanValue() : defaultValue;
}
private long getMotionOffDelaySetting(Integer value, long defaultValue) {
return value != null ? value.intValue() * ONE_MINUTE : defaultValue;
}
private PowermaxPanelType getPanelTypeSetting(String value, PowermaxPanelType defaultValue) {
PowermaxPanelType result;
if (value != null) {
try {
result = PowermaxPanelType.fromLabel(value);
} catch (IllegalArgumentException e) {
result = defaultValue;
logger.debug("Powermax alarm binding: panel type not configured correctly");
}
} else {
try {
result = PowermaxPanelType.fromLabel(value);
} catch (IllegalArgumentException e) {
result = defaultValue;
logger.debug("Powermax alarm binding: panel type not configured correctly");
}
return result;
}

View File

@ -14,6 +14,7 @@ package org.openhab.binding.powermax.internal.handler;
import static org.openhab.binding.powermax.internal.PowermaxBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.config.PowermaxX10Configuration;
import org.openhab.binding.powermax.internal.config.PowermaxZoneConfiguration;
@ -44,16 +45,17 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPanelSettingsListener {
private final Logger logger = LoggerFactory.getLogger(PowermaxThingHandler.class);
private static final int ZONE_NR_MIN = 1;
private static final int ZONE_NR_MAX = 64;
private static final int X10_NR_MIN = 1;
private static final int X10_NR_MAX = 16;
private PowermaxBridgeHandler bridgeHandler;
private final Logger logger = LoggerFactory.getLogger(PowermaxThingHandler.class);
private @Nullable PowermaxBridgeHandler bridgeHandler;
public PowermaxThingHandler(Thing thing) {
super(thing);
@ -77,7 +79,7 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
initializeThingState((bridge == null) ? null : bridge.getHandler(), bridgeStatusInfo.getStatus());
}
private void initializeThingState(ThingHandler bridgeHandler, ThingStatus bridgeStatus) {
private void initializeThingState(@Nullable ThingHandler bridgeHandler, @Nullable ThingStatus bridgeStatus) {
if (bridgeHandler != null && bridgeStatus != null) {
if (bridgeStatus == ThingStatus.ONLINE) {
boolean validConfig = false;
@ -85,8 +87,7 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) {
PowermaxZoneConfiguration config = getConfigAs(PowermaxZoneConfiguration.class);
if (config.zoneNumber != null && config.zoneNumber >= ZONE_NR_MIN
&& config.zoneNumber <= ZONE_NR_MAX) {
if (config.zoneNumber >= ZONE_NR_MIN && config.zoneNumber <= ZONE_NR_MAX) {
validConfig = true;
} else {
errorMsg = "zoneNumber setting must be defined in thing configuration and set between "
@ -94,8 +95,7 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
}
} else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) {
PowermaxX10Configuration config = getConfigAs(PowermaxX10Configuration.class);
if (config.deviceNumber != null && config.deviceNumber >= X10_NR_MIN
&& config.deviceNumber <= X10_NR_MAX) {
if (config.deviceNumber >= X10_NR_MIN && config.deviceNumber <= X10_NR_MAX) {
validConfig = true;
} else {
errorMsg = "deviceNumber setting must be defined in thing configuration and set between "
@ -106,9 +106,10 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
if (validConfig) {
updateStatus(ThingStatus.UNKNOWN);
logger.debug("Set handler status to UNKNOWN for thing {} (bridge ONLINE)", getThing().getUID());
this.bridgeHandler = (PowermaxBridgeHandler) bridgeHandler;
this.bridgeHandler.registerPanelSettingsListener(this);
onPanelSettingsUpdated(this.bridgeHandler.getPanelSettings());
PowermaxBridgeHandler powermaxBridgeHandler = (PowermaxBridgeHandler) bridgeHandler;
this.bridgeHandler = powermaxBridgeHandler;
powermaxBridgeHandler.registerPanelSettingsListener(this);
onPanelSettingsUpdated(powermaxBridgeHandler.getPanelSettings());
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg);
}
@ -133,8 +134,9 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
@Override
public void dispose() {
logger.debug("Handler disposed for thing {}", getThing().getUID());
if (bridgeHandler != null) {
bridgeHandler.unregisterPanelSettingsListener(this);
PowermaxBridgeHandler powermaxBridgeHandler = bridgeHandler;
if (powermaxBridgeHandler != null) {
powermaxBridgeHandler.unregisterPanelSettingsListener(this);
}
super.dispose();
}
@ -143,15 +145,18 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Received command {} from channel {}", command, channelUID.getId());
if (bridgeHandler == null) {
PowermaxBridgeHandler powermaxBridgeHandler = bridgeHandler;
if (powermaxBridgeHandler == null) {
return;
} else if (command instanceof RefreshType) {
updateChannelFromAlarmState(channelUID.getId(), bridgeHandler.getCurrentState());
updateChannelFromAlarmState(channelUID.getId(), powermaxBridgeHandler.getCurrentState());
} else {
switch (channelUID.getId()) {
case BYPASSED:
if (command instanceof OnOffType) {
bridgeHandler.zoneBypassed(getConfigAs(PowermaxZoneConfiguration.class).zoneNumber.byteValue(),
powermaxBridgeHandler.zoneBypassed(
Byte.valueOf(
(byte) (getConfigAs(PowermaxZoneConfiguration.class).zoneNumber & 0x000000FF)),
command.equals(OnOffType.ON));
} else {
logger.debug("Command of type {} while OnOffType is expected. Command is ignored.",
@ -159,7 +164,9 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
}
break;
case X10_STATUS:
bridgeHandler.x10Command(getConfigAs(PowermaxX10Configuration.class).deviceNumber.byteValue(),
powermaxBridgeHandler.x10Command(
Byte.valueOf(
(byte) (getConfigAs(PowermaxX10Configuration.class).deviceNumber & 0x000000FF)),
command);
break;
default:
@ -175,13 +182,13 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
* @param channel: the channel
* @param state: the alarm system state
*/
public void updateChannelFromAlarmState(String channel, PowermaxState state) {
if (state == null || channel == null || !isLinked(channel)) {
public void updateChannelFromAlarmState(String channel, @Nullable PowermaxState state) {
if (state == null || !isLinked(channel)) {
return;
}
if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) {
int num = getConfigAs(PowermaxZoneConfiguration.class).zoneNumber.intValue();
int num = getConfigAs(PowermaxZoneConfiguration.class).zoneNumber;
for (Value<?> value : state.getZone(num).getValues()) {
String vChannel = value.getChannel();
@ -191,9 +198,10 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
}
}
} else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) {
int num = getConfigAs(PowermaxX10Configuration.class).deviceNumber.intValue();
if (channel.equals(X10_STATUS) && (state.getPGMX10DeviceStatus(num) != null)) {
updateState(X10_STATUS, state.getPGMX10DeviceStatus(num) ? OnOffType.ON : OnOffType.OFF);
int num = getConfigAs(PowermaxX10Configuration.class).deviceNumber;
Boolean status = state.getPGMX10DeviceStatus(num);
if (channel.equals(X10_STATUS) && (status != null)) {
updateState(X10_STATUS, status ? OnOffType.ON : OnOffType.OFF);
}
}
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
/**
@ -19,6 +21,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxAckMessage extends PowermaxBaseMessage {
/**
@ -32,14 +35,15 @@ public class PowermaxAckMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
PowermaxState updatedState = null;
if (commManager.getLastSendMsg().getSendType() == PowermaxSendType.EXIT) {
PowermaxBaseMessage lastSendMsg = commManager.getLastSendMsg();
if (lastSendMsg != null && lastSendMsg.getSendType() == PowermaxSendType.EXIT) {
updatedState = commManager.createNewState();
updatedState.powerlinkMode.setValue(true);
updatedState.downloadMode.setValue(false);

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.openhab.core.util.HexUtils;
@ -23,14 +24,15 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxBaseMessage.class);
private byte[] rawData;
private final byte[] rawData;
private int code;
private PowermaxSendType sendType;
private PowermaxReceiveType receiveType;
private @Nullable PowermaxSendType sendType;
private @Nullable PowermaxReceiveType receiveType;
private Object messageType;
/**
@ -39,9 +41,9 @@ public class PowermaxBaseMessage {
* @param message the message as a buffer of bytes
*/
public PowermaxBaseMessage(byte[] message) {
this.sendType = null;
this.rawData = message;
this.messageType = "UNKNOWN";
decodeMessage(message);
decodeMessage();
}
/**
@ -59,40 +61,41 @@ public class PowermaxBaseMessage {
* @param sendType the type of a message to be sent
* @param param the dynamic part of a message to be sent; null if no dynamic part
*/
public PowermaxBaseMessage(PowermaxSendType sendType, byte[] param) {
public PowermaxBaseMessage(PowermaxSendType sendType, byte @Nullable [] param) {
this.sendType = sendType;
this.messageType = "UNKNOWN";
byte[] message = new byte[sendType.getMessage().length + 3];
this.rawData = new byte[sendType.getMessage().length + 3];
int index = 0;
message[index++] = 0x0D;
rawData[index++] = 0x0D;
for (int i = 0; i < sendType.getMessage().length; i++) {
if ((param != null) && (sendType.getParamPosition() != null) && (i >= sendType.getParamPosition())
&& (i < (sendType.getParamPosition() + param.length))) {
message[index++] = param[i - sendType.getParamPosition()];
Integer paramPosition = sendType.getParamPosition();
if ((param != null) && (paramPosition != null) && (i >= paramPosition)
&& (i < (paramPosition + param.length))) {
rawData[index++] = param[i - paramPosition];
} else {
message[index++] = sendType.getMessage()[i];
rawData[index++] = sendType.getMessage()[i];
}
}
message[index++] = 0x00;
message[index++] = 0x0A;
decodeMessage(message);
rawData[index++] = 0x00;
rawData[index++] = 0x0A;
decodeMessage();
}
/**
* Extract information from the buffer of bytes and set class attributes
*
* @param data the message as a buffer of bytes
*/
private void decodeMessage(byte[] data) {
rawData = data;
private void decodeMessage() {
code = rawData[1] & 0x000000FF;
PowermaxReceiveType localReceiveType;
try {
receiveType = PowermaxReceiveType.fromCode((byte) code);
localReceiveType = PowermaxReceiveType.fromCode((byte) code);
} catch (IllegalArgumentException e) {
receiveType = null;
localReceiveType = null;
}
receiveType = localReceiveType;
messageType = sendType != null ? sendType : receiveType != null ? receiveType : "UNKNOWN";
PowermaxSendType localSendType = sendType;
messageType = localSendType != null ? localSendType : localReceiveType != null ? localReceiveType : "UNKNOWN";
}
/**
@ -100,7 +103,7 @@ public class PowermaxBaseMessage {
*
* @return a new state containing all changes driven by the message
*/
public final PowermaxState handleMessage(PowermaxCommManager commManager) {
public final @Nullable PowermaxState handleMessage(@Nullable PowermaxCommManager commManager) {
// Send an ACK if needed
if (isAckRequired() && commManager != null) {
commManager.sendAck(this, (byte) 0x02);
@ -119,7 +122,7 @@ public class PowermaxBaseMessage {
return newState;
}
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
return null;
}
@ -140,18 +143,18 @@ public class PowermaxBaseMessage {
/**
* @return the type of the message to be sent
*/
public PowermaxSendType getSendType() {
public @Nullable PowermaxSendType getSendType() {
return sendType;
}
public void setSendType(PowermaxSendType sendType) {
public void setSendType(@Nullable PowermaxSendType sendType) {
this.sendType = sendType;
}
/**
* @return the type of the received message
*/
public PowermaxReceiveType getReceiveType() {
public @Nullable PowermaxReceiveType getReceiveType() {
return receiveType;
}
@ -159,7 +162,8 @@ public class PowermaxBaseMessage {
* @return true if the received message requires the sending of an ACK
*/
public boolean isAckRequired() {
return receiveType == null || receiveType.isAckRequired();
PowermaxReceiveType localReceiveType = receiveType;
return localReceiveType == null || localReceiveType.isAckRequired();
}
// Debugging helpers

View File

@ -23,6 +23,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.connector.PowermaxConnector;
import org.openhab.binding.powermax.internal.connector.PowermaxSerialConnector;
import org.openhab.binding.powermax.internal.connector.PowermaxTcpConnector;
@ -49,47 +51,49 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxCommManager implements PowermaxMessageEventListener {
private final Logger logger = LoggerFactory.getLogger(PowermaxCommManager.class);
private static final int DEFAULT_TCP_PORT = 80;
private static final int TCP_CONNECTION_TIMEOUT = 5000;
private static final int DEFAULT_BAUD_RATE = 9600;
private static final int WAITING_DELAY_FOR_RESPONSE = 750;
private static final long DELAY_BETWEEN_SETUP_DOWNLOADS = TimeUnit.SECONDS.toMillis(45);
private final Logger logger = LoggerFactory.getLogger(PowermaxCommManager.class);
private final ScheduledExecutorService scheduler;
/** The object to store the current settings of the Powermax alarm system */
private PowermaxPanelSettings panelSettings;
/** Panel type used when in standard mode */
private PowermaxPanelType panelType;
private boolean forceStandardMode;
private boolean autoSyncTime;
private final TimeZoneProvider timeZoneProvider;
private List<PowermaxStateEventListener> listeners = new ArrayList<>();
/** The object to store the current settings of the Powermax alarm system */
private final PowermaxPanelSettings panelSettings;
/** Panel type used when in standard mode */
private final PowermaxPanelType panelType;
private final boolean forceStandardMode;
private final boolean autoSyncTime;
private final List<PowermaxStateEventListener> listeners = new ArrayList<>();
/** The serial or TCP connecter used to communicate with the Powermax alarm system */
private PowermaxConnector connector;
private final PowermaxConnector connector;
/** The last message sent to the the Powermax alarm system */
private PowermaxBaseMessage lastSendMsg;
private @Nullable PowermaxBaseMessage lastSendMsg;
/** The message queue of messages to be sent to the the Powermax alarm system */
private ConcurrentLinkedQueue<PowermaxBaseMessage> msgQueue = new ConcurrentLinkedQueue<>();
/** The time in milliseconds the last download of the panel setup was requested */
private Long lastTimeDownloadRequested;
private long lastTimeDownloadRequested;
/** The boolean indicating if the download of the panel setup is in progress or not */
private boolean downloadRunning;
/** The time in milliseconds used to set time and date */
private Long syncTimeCheck;
private long syncTimeCheck;
/**
* Constructor for Serial Connection
@ -110,13 +114,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
this.timeZoneProvider = timeZoneProvider;
this.panelSettings = new PowermaxPanelSettings(panelType);
this.scheduler = ThreadPoolManager.getScheduledPool(threadName + "-sender");
String serialPort = (sPort != null && !sPort.trim().isEmpty()) ? sPort.trim() : null;
if (serialPort != null) {
connector = new PowermaxSerialConnector(serialPortManager, serialPort, DEFAULT_BAUD_RATE,
threadName + "-reader");
} else {
connector = null;
}
this.connector = new PowermaxSerialConnector(serialPortManager, sPort.trim(), DEFAULT_BAUD_RATE,
threadName + "-reader");
}
/**
@ -138,13 +137,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
this.timeZoneProvider = timeZoneProvider;
this.panelSettings = new PowermaxPanelSettings(panelType);
this.scheduler = ThreadPoolManager.getScheduledPool(threadName + "-sender");
String ipAddress = (ip != null && !ip.trim().isEmpty()) ? ip.trim() : null;
int tcpPort = (port > 0) ? port : DEFAULT_TCP_PORT;
if (ipAddress != null) {
connector = new PowermaxTcpConnector(ipAddress, tcpPort, TCP_CONNECTION_TIMEOUT, threadName + "-reader");
} else {
connector = null;
}
this.connector = new PowermaxTcpConnector(ip.trim(), port > 0 ? port : DEFAULT_TCP_PORT, TCP_CONNECTION_TIMEOUT,
threadName + "-reader");
}
/**
@ -154,9 +148,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
*/
public synchronized void addEventListener(PowermaxStateEventListener listener) {
listeners.add(listener);
if (connector != null) {
connector.addEventListener(this);
}
connector.addEventListener(this);
}
/**
@ -165,9 +157,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
* @param listener the listener to be removed
*/
public synchronized void removeEventListener(PowermaxStateEventListener listener) {
if (connector != null) {
connector.removeEventListener(this);
}
connector.removeEventListener(this);
listeners.remove(listener);
}
@ -177,9 +167,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
* @return true if connected or false if not
*/
public void open() throws Exception {
if (connector != null) {
connector.open();
}
connector.open();
lastSendMsg = null;
msgQueue = new ConcurrentLinkedQueue<>();
}
@ -190,10 +178,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
* @return true if connected or false if not
*/
public boolean close() {
if (connector != null) {
connector.close();
}
lastTimeDownloadRequested = null;
connector.close();
lastTimeDownloadRequested = 0;
downloadRunning = false;
return isConnected();
}
@ -202,7 +188,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
* @return true if connected to the Powermax alarm system or false if not
*/
public boolean isConnected() {
return (connector != null) && connector.isConnected();
return connector.isConnected();
}
/**
@ -220,7 +206,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
* @return true if no problem encountered to get all the settings; false if not
*/
public boolean processPanelSettings(boolean powerlinkMode) {
return panelSettings.process(powerlinkMode, panelType, powerlinkMode ? syncTimeCheck : null);
return panelSettings.process(powerlinkMode, panelType, powerlinkMode ? syncTimeCheck : 0);
}
/**
@ -233,7 +219,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
/**
* @return the last message sent to the Powermax alarm system
*/
public synchronized PowermaxBaseMessage getLastSendMsg() {
public synchronized @Nullable PowermaxBaseMessage getLastSendMsg() {
return lastSendMsg;
}
@ -261,8 +247,9 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
updateState.lastMessageTime.setValue(System.currentTimeMillis());
if (updateState.getUpdateSettings() != null) {
panelSettings.updateRawSettings(updateState.getUpdateSettings());
byte[] buffer = updateState.getUpdateSettings();
if (buffer != null) {
panelSettings.updateRawSettings(buffer);
}
if (!updateState.getUpdatedZoneNames().isEmpty()) {
for (Integer zoneIdx : updateState.getUpdatedZoneNames().keySet()) {
@ -349,7 +336,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
boolean done = false;
if (!armMode.isAllowedCommand()) {
logger.debug("Powermax alarm binding: requested arm mode {} rejected", armMode.getShortName());
} else if ((pinCode == null) || (pinCode.length() != 4)) {
} else if (pinCode.length() != 4) {
logger.debug("Powermax alarm binding: requested arm mode {} rejected due to invalid PIN code",
armMode.getShortName());
} else {
@ -376,7 +363,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
*
* @return true if the message was sent or false if not
*/
public boolean sendPGMX10(Command action, Byte device) {
public boolean sendPGMX10(Command action, @Nullable Byte device) {
logger.debug("sendPGMX10(): action = {}, device = {}", action, device);
boolean done = false;
@ -418,7 +405,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
boolean done = false;
if ((pinCode == null) || (pinCode.length() != 4)) {
if (pinCode.length() != 4) {
logger.debug("Powermax alarm binding: zone bypass rejected due to invalid PIN code");
} else if ((zone < 1) || (zone > panelSettings.getNbZones())) {
logger.debug("Powermax alarm binding: invalid zone number: {}", zone);
@ -483,10 +470,10 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
} else {
logger.info(
"Powermax alarm binding: time not synchronized; please correct the date/time of your openHAB server");
syncTimeCheck = null;
syncTimeCheck = 0;
}
} else {
syncTimeCheck = null;
syncTimeCheck = 0;
}
return done;
}
@ -503,7 +490,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
boolean done = false;
if ((pinCode == null) || (pinCode.length() != 4)) {
if (pinCode.length() != 4) {
logger.debug("Powermax alarm binding: requested event log rejected due to invalid PIN code");
} else {
try {
@ -543,7 +530,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
public void retryDownloadSetup(int remainingAttempts) {
long now = System.currentTimeMillis();
if ((remainingAttempts > 0) && !isDownloadRunning() && ((lastTimeDownloadRequested == null)
if ((remainingAttempts > 0) && !isDownloadRunning() && ((lastTimeDownloadRequested == 0)
|| ((now - lastTimeDownloadRequested) >= DELAY_BETWEEN_SETUP_DOWNLOADS))) {
// We wait at least 45 seconds before each retry to download the panel setup
logger.debug("Powermax alarm binding: try again downloading setup");
@ -569,9 +556,9 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
}
/**
* @return the time in milliseconds the last download of the panel setup was requested or null if not yet requested
* @return the time in milliseconds the last download of the panel setup was requested or 0 if not yet requested
*/
public Long getLastTimeDownloadRequested() {
public long getLastTimeDownloadRequested() {
return lastTimeDownloadRequested;
}
@ -607,7 +594,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
return sendMessage(new PowermaxBaseMessage(msgType), false, waitTime);
}
private synchronized boolean sendMessage(PowermaxBaseMessage msg, boolean immediate, int waitTime) {
private synchronized boolean sendMessage(@Nullable PowermaxBaseMessage msg, boolean immediate, int waitTime) {
return sendMessage(msg, immediate, waitTime, false);
}
@ -622,7 +609,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
* @return true if the message was sent or the sending is delayed; false in other cases
*/
@SuppressWarnings("PMD.CompareObjectsWithEquals")
private synchronized boolean sendMessage(PowermaxBaseMessage msg, boolean immediate, int waitTime,
private synchronized boolean sendMessage(@Nullable PowermaxBaseMessage msg, boolean immediate, int waitTime,
boolean doNotLog) {
if ((waitTime > 0) && (msg != null)) {
logger.debug("sendMessage(): delay ({} s) sending message (type {})", waitTime, msg.getSendType());

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -21,6 +23,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxDeniedMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxDeniedMessage.class);
@ -36,14 +39,15 @@ public class PowermaxDeniedMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
PowermaxState updatedState = null;
PowermaxSendType lastSendType = commManager.getLastSendMsg().getSendType();
PowermaxBaseMessage lastSendMsg = commManager.getLastSendMsg();
PowermaxSendType lastSendType = lastSendMsg == null ? null : lastSendMsg.getSendType();
if (lastSendType == PowermaxSendType.EVENTLOG || lastSendType == PowermaxSendType.ARM
|| lastSendType == PowermaxSendType.BYPASS) {
logger.debug("Powermax alarm binding: invalid PIN code");

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
/**
@ -19,6 +21,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage {
/**
@ -32,7 +35,7 @@ public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings;
import org.openhab.binding.powermax.internal.state.PowermaxState;
@ -20,6 +22,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxEventLogMessage extends PowermaxBaseMessage {
/**
@ -33,7 +36,7 @@ public class PowermaxEventLogMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxPanelType;
import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.slf4j.Logger;
@ -22,6 +24,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxInfoMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxInfoMessage.class);
@ -37,7 +40,7 @@ public class PowermaxInfoMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -16,11 +16,14 @@ import static java.util.Map.entry;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Constants used in Powermax messages
*
* @author Ron Isaacson - Initial contribution
*/
@NonNullByDefault
public class PowermaxMessageConstants {
private PowermaxMessageConstants() {

View File

@ -14,15 +14,18 @@ package org.openhab.binding.powermax.internal.message;
import java.util.EventObject;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Event for messages received from the Visonic alarm panel
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxMessageEvent extends EventObject {
private static final long serialVersionUID = 1L;
private PowermaxBaseMessage message;
private final PowermaxBaseMessage message;
public PowermaxMessageEvent(Object source, PowermaxBaseMessage message) {
super(source);

View File

@ -15,11 +15,14 @@ package org.openhab.binding.powermax.internal.message;
import java.util.EventListener;
import java.util.EventObject;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Powermax Alarm Event Listener interface. Handles incoming Powermax Alarm message events
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public interface PowermaxMessageEventListener extends EventListener {
/**

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.message.PowermaxMessageConstants.PowermaxSysEvent;
import org.openhab.binding.powermax.internal.state.PowermaxState;
@ -20,6 +22,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxPanelMessage extends PowermaxBaseMessage {
/**
@ -33,7 +36,7 @@ public class PowermaxPanelMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
/**
@ -19,6 +21,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxPowerMasterMessage extends PowermaxBaseMessage {
/**
@ -32,7 +35,7 @@ public class PowermaxPowerMasterMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -21,6 +23,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxPowerlinkMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxPowerlinkMessage.class);
@ -36,7 +39,7 @@ public class PowermaxPowerlinkMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Used to map received messages from the Visonic alarm panel to a ENUM value
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermaxReceiveType {
ACK((byte) 0x02, 0, false),
@ -36,9 +39,9 @@ public enum PowermaxReceiveType {
POWERMASTER((byte) 0xB0, 0, true),
F1((byte) 0xF1, 9, false);
private byte code;
private int length;
private boolean ackRequired;
private final byte code;
private final int length;
private final boolean ackRequired;
private PowermaxReceiveType(byte code, int length, boolean ackRequired) {
this.code = code;

View File

@ -12,11 +12,15 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* Used to map messages to be sent to the Visonic alarm panel to a ENUM value
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermaxSendType {
INIT(new byte[] { (byte) 0xAB, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, null, null),
@ -107,11 +111,12 @@ public enum PowermaxSendType {
POWERMASTER_ZONE_TYPE1(new byte[] { (byte) 0xB0, 0x01, 0x2D, 0x02, 0x05, 0x00, 0x43 }, null,
PowermaxReceiveType.POWERMASTER);
private byte[] message;
private Integer paramPosition;
private PowermaxReceiveType expectedResponseType;
private final byte[] message;
private final @Nullable Integer paramPosition;
private final @Nullable PowermaxReceiveType expectedResponseType;
private PowermaxSendType(byte[] message, Integer paramPosition, PowermaxReceiveType expectedResponseType) {
private PowermaxSendType(byte[] message, @Nullable Integer paramPosition,
@Nullable PowermaxReceiveType expectedResponseType) {
this.message = message;
this.paramPosition = paramPosition;
this.expectedResponseType = expectedResponseType;
@ -127,14 +132,14 @@ public enum PowermaxSendType {
/**
* @return the position of the parameter in the message buffer
*/
public Integer getParamPosition() {
public @Nullable Integer getParamPosition() {
return paramPosition;
}
/**
* @return the ENUM value of the expected message as response
*/
public PowermaxReceiveType getExpectedResponseType() {
public @Nullable PowermaxReceiveType getExpectedResponseType() {
return expectedResponseType;
}
}

View File

@ -14,6 +14,8 @@ package org.openhab.binding.powermax.internal.message;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -23,6 +25,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxSettingsMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxSettingsMessage.class);
@ -38,7 +41,7 @@ public class PowermaxSettingsMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -16,6 +16,8 @@ import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxArmMode;
import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings;
import org.openhab.binding.powermax.internal.state.PowermaxSensorType;
@ -27,6 +29,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxStatusMessage extends PowermaxBaseMessage {
private static byte[] zoneBytes(byte zones1, byte zones9, byte zones17, byte zones25) {
@ -68,7 +71,7 @@ public class PowermaxStatusMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
/**
@ -19,6 +21,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxTimeoutMessage extends PowermaxBaseMessage {
/**
@ -32,7 +35,7 @@ public class PowermaxTimeoutMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager != null) {
commManager.sendMessage(PowermaxSendType.EXIT);
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
/**
@ -19,6 +21,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxZonesNameMessage extends PowermaxBaseMessage {
/**
@ -32,7 +35,7 @@ public class PowermaxZonesNameMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.powermax.internal.message;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.state.PowermaxState;
/**
@ -19,6 +21,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxZonesTypeMessage extends PowermaxBaseMessage {
/**
@ -32,7 +35,7 @@ public class PowermaxZonesTypeMessage extends PowermaxBaseMessage {
}
@Override
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* All defined sensor types for Master panels
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermasterSensorType {
SENSOR_TYPE_1((byte) 0x01, "Motion"),
@ -26,8 +29,8 @@ public enum PowermasterSensorType {
SENSOR_TYPE_5((byte) 0x2A, "Magnet"),
SENSOR_TYPE_6((byte) 0xFE, "Wired");
private byte code;
private String label;
private final byte code;
private final String label;
private PowermasterSensorType(byte code, String label) {
this.code = code;

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* All defined arm modes
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermaxArmMode {
DISARMED(0, "Disarmed", "Disarmed", false, (byte) 0x00, false),
@ -42,11 +45,11 @@ public enum PowermaxArmMode {
ARMED_HOME_INSTANT(20, "Armed Home Instant", "StayInstant", true, (byte) 0x14, false),
ARMED_AWAY_INSTANT(21, "Armed Away Instant", "ArmedInstant", true, (byte) 0x15, false);
private int code;
private String name;
private String shortName;
private boolean armed;
private byte commandCode;
private final int code;
private final String name;
private final String shortName;
private final boolean armed;
private final byte commandCode;
private boolean allowedCommand;
private PowermaxArmMode(int code, String name, String shortName, boolean armed, byte commandCode,

View File

@ -18,6 +18,8 @@ import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.stream.IntStream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.message.PowermaxMessageConstants;
import org.openhab.binding.powermax.internal.message.PowermaxSendType;
import org.slf4j.Logger;
@ -28,13 +30,14 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxPanelSettings {
private final Logger logger = LoggerFactory.getLogger(PowermaxPanelSettings.class);
/** Number of PGM and X10 devices managed by the system */
private static final int NB_PGM_X10_DEVICES = 16;
private final Logger logger = LoggerFactory.getLogger(PowermaxPanelSettings.class);
/** Raw buffers for settings */
private Byte[][] rawSettings;
@ -45,15 +48,15 @@ public class PowermaxPanelSettings {
private boolean quickArm;
private boolean bypassEnabled;
private boolean partitionsEnabled;
private String[] pinCodes;
private String panelEprom;
private String panelSoftware;
private String panelSerial;
private String @Nullable [] pinCodes;
private @Nullable String panelEprom;
private @Nullable String panelSoftware;
private @Nullable String panelSerial;
private PowermaxZoneSettings[] zoneSettings;
private PowermaxX10Settings[] x10Settings;
private boolean[] keypad1wEnrolled;
private boolean[] keypad2wEnrolled;
private boolean[] sirensEnrolled;
private boolean @Nullable [] keypad1wEnrolled;
private boolean @Nullable [] keypad2wEnrolled;
private boolean @Nullable [] sirensEnrolled;
/**
* Constructor
@ -108,21 +111,21 @@ public class PowermaxPanelSettings {
/**
* @return the panel EEPROM version
*/
public String getPanelEprom() {
public @Nullable String getPanelEprom() {
return panelEprom;
}
/**
* @return the panel software version
*/
public String getPanelSoftware() {
public @Nullable String getPanelSoftware() {
return panelSoftware;
}
/**
* @return the panel serial ID
*/
public String getPanelSerial() {
public @Nullable String getPanelSerial() {
return panelSerial;
}
@ -147,7 +150,7 @@ public class PowermaxPanelSettings {
*
* @return the settings of the zone
*/
public PowermaxZoneSettings getZoneSettings(int zone) {
public @Nullable PowermaxZoneSettings getZoneSettings(int zone) {
return ((zone < 1) || (zone > zoneSettings.length)) ? null : zoneSettings[zone - 1];
}
@ -158,7 +161,7 @@ public class PowermaxPanelSettings {
*
* @return the name of the zone
*/
public String getZoneName(int zone) {
public @Nullable String getZoneName(int zone) {
PowermaxZoneSettings zoneSettings = getZoneSettings(zone);
return (zoneSettings == null) ? null : zoneSettings.getName();
}
@ -204,7 +207,7 @@ public class PowermaxPanelSettings {
*
* @return the settings of the X10 device
*/
public PowermaxX10Settings getX10Settings(int idx) {
public @Nullable PowermaxX10Settings getX10Settings(int idx) {
return ((idx < 1) || (idx >= x10Settings.length)) ? null : x10Settings[idx];
}
@ -214,8 +217,9 @@ public class PowermaxPanelSettings {
* @return true if the 1 way keypad is enrolled; false if not
*/
public boolean isKeypad1wEnrolled(int idx) {
return ((keypad1wEnrolled == null) || (idx < 1) || (idx >= keypad1wEnrolled.length)) ? false
: keypad1wEnrolled[idx - 1];
boolean @Nullable [] localKeypad1wEnrolled = keypad1wEnrolled;
return ((localKeypad1wEnrolled == null) || (idx < 1) || (idx >= localKeypad1wEnrolled.length)) ? false
: localKeypad1wEnrolled[idx - 1];
}
/**
@ -224,8 +228,9 @@ public class PowermaxPanelSettings {
* @return true if the 2 way keypad is enrolled; false if not
*/
public boolean isKeypad2wEnrolled(int idx) {
return ((keypad2wEnrolled == null) || (idx < 1) || (idx >= keypad2wEnrolled.length)) ? false
: keypad2wEnrolled[idx - 1];
boolean @Nullable [] localKeypad2wEnrolled = keypad2wEnrolled;
return ((localKeypad2wEnrolled == null) || (idx < 1) || (idx >= localKeypad2wEnrolled.length)) ? false
: localKeypad2wEnrolled[idx - 1];
}
/**
@ -234,19 +239,21 @@ public class PowermaxPanelSettings {
* @return true if the siren is enrolled; false if not
*/
public boolean isSirenEnrolled(int idx) {
return ((sirensEnrolled == null) || (idx < 1) || (idx >= sirensEnrolled.length)) ? false
: sirensEnrolled[idx - 1];
boolean @Nullable [] localSirensEnrolled = sirensEnrolled;
return ((localSirensEnrolled == null) || (idx < 1) || (idx >= localSirensEnrolled.length)) ? false
: localSirensEnrolled[idx - 1];
}
/**
* @return the PIN code of the first user of null if unknown (standard mode)
* @return the PIN code of the first user of an empty string if unknown (standard mode)
*/
public String getFirstPinCode() {
return (pinCodes == null) ? null : pinCodes[0];
String @Nullable [] localPinCodes = pinCodes;
return (localPinCodes == null || localPinCodes.length == 0) ? "" : localPinCodes[0];
}
public void updateRawSettings(byte[] data) {
if ((data == null) || (data.length < 3)) {
if (data.length < 3) {
return;
}
int start = 0;
@ -276,14 +283,14 @@ public class PowermaxPanelSettings {
}
}
private byte[] readSettings(PowermaxSendType msgType, int start, int end) {
private byte @Nullable [] readSettings(PowermaxSendType msgType, int start, int end) {
byte[] message = msgType.getMessage();
int page = message[2] & 0x000000FF;
int index = message[1] & 0x000000FF;
return readSettings(page, index + start, index + end);
}
private byte[] readSettings(int page, int start, int end) {
private byte @Nullable [] readSettings(int page, int start, int end) {
int pageMin = page + start / 0x100;
int indexPageMin = start % 0x100;
int pageMax = page + end / 0x100;
@ -332,7 +339,7 @@ public class PowermaxPanelSettings {
return result;
}
private String readSettingsAsString(PowermaxSendType msgType, int start, int end) {
private @Nullable String readSettingsAsString(PowermaxSendType msgType, int start, int end) {
byte[] message = msgType.getMessage();
int page = message[2] & 0x000000FF;
int index = message[1] & 0x000000FF;
@ -381,12 +388,11 @@ public class PowermaxPanelSettings {
*
* @param PowerlinkMode true if in Powerlink mode or false if in standard mode
* @param defaultPanelType the default panel type to consider if not found in the raw buffers
* @param timeSet the time in milliseconds used to set time and date; null if no sync time requested
* @param timeSet the time in milliseconds used to set time and date; 0 if no sync time requested
*
* @return true if no problem encountered to get all the settings; false if not
*/
@SuppressWarnings("null")
public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType, Long timeSet) {
public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType, long timeSet) {
logger.debug("Process settings Powerlink {}", PowerlinkMode);
boolean result = true;
@ -424,15 +430,15 @@ public class PowermaxPanelSettings {
quickArm = false;
bypassEnabled = false;
partitionsEnabled = false;
pinCodes = new String[userCnt];
String[] localPinCodes = new String[userCnt];
panelEprom = null;
panelSoftware = null;
panelSerial = null;
zoneSettings = new PowermaxZoneSettings[zoneCnt];
x10Settings = new PowermaxX10Settings[NB_PGM_X10_DEVICES];
keypad1wEnrolled = new boolean[keypad1wCnt];
keypad2wEnrolled = new boolean[keypad2wCnt];
sirensEnrolled = new boolean[sirenCnt];
boolean[] localKeypad1wEnrolled = new boolean[keypad1wCnt];
boolean[] localKeypad2wEnrolled = new boolean[keypad2wCnt];
boolean[] localSirensEnrolled = new boolean[sirenCnt];
if (PowerlinkMode) {
// Check time and date
@ -453,7 +459,7 @@ public class PowermaxPanelSettings {
cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND)));
// Check if time sync was OK
if (timeSet != null) {
if (timeSet > 0) {
long delta = (timeRead - timeSet) / 1000;
if (delta <= 5) {
logger.debug("Powermax alarm binding: time sync OK (delta {} s)", delta);
@ -528,7 +534,8 @@ public class PowermaxPanelSettings {
2 * userCnt - 1);
if (data != null) {
for (int i = 0; i < userCnt; i++) {
pinCodes[i] = String.format("%02X%02X", data[i * 2] & 0x000000FF, data[i * 2 + 1] & 0x000000FF);
localPinCodes[i] = String.format("%02X%02X", data[i * 2] & 0x000000FF,
data[i * 2 + 1] & 0x000000FF);
}
} else {
logger.debug("Cannot get PIN codes");
@ -606,22 +613,26 @@ public class PowermaxPanelSettings {
boolean zoneEnrolled;
byte zoneInfo;
byte sensorTypeCode;
String sensorTypeStr;
if (panelType.isPowerMaster()) {
zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(dataMr, i * 10 + 4, i * 10 + 9), zero5);
zoneInfo = data[i];
sensorTypeCode = dataMr[i * 10 + 5];
try {
PowermasterSensorType sensorType = PowermasterSensorType.fromCode(sensorTypeCode);
sensorTypeStr = sensorType.getLabel();
} catch (IllegalArgumentException e) {
if (dataMr != null) {
zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(dataMr, i * 10 + 4, i * 10 + 9), zero5);
byte sensorTypeCode = dataMr[i * 10 + 5];
try {
PowermasterSensorType sensorType = PowermasterSensorType.fromCode(sensorTypeCode);
sensorTypeStr = sensorType.getLabel();
} catch (IllegalArgumentException e) {
sensorTypeStr = null;
}
} else {
zoneEnrolled = false;
sensorTypeStr = null;
}
} else {
zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3);
zoneInfo = data[i * 4 + 3];
sensorTypeCode = data[i * 4 + 2];
byte sensorTypeCode = data[i * 4 + 2];
try {
PowermaxSensorType sensorType = PowermaxSensorType
.fromCode((byte) (sensorTypeCode & 0x0000000F));
@ -686,7 +697,8 @@ public class PowermaxPanelSettings {
byte[] zero5 = new byte[] { 0, 0, 0, 0, 0 };
for (int i = 0; i < keypad2wCnt; i++) {
keypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), zero5);
localKeypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9),
zero5);
}
} else {
logger.debug("Cannot get 2 way keypad settings");
@ -698,7 +710,8 @@ public class PowermaxPanelSettings {
byte[] zero5 = new byte[] { 0, 0, 0, 0, 0 };
for (int i = 0; i < sirenCnt; i++) {
sirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), zero5);
localSirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9),
zero5);
}
} else {
logger.debug("Cannot get siren settings");
@ -711,7 +724,7 @@ public class PowermaxPanelSettings {
byte[] zero2 = new byte[] { 0, 0 };
for (int i = 0; i < keypad1wCnt; i++) {
keypad1wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 2), zero2);
localKeypad1wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 2), zero2);
}
} else {
logger.debug("Cannot get 1 way keypad settings");
@ -723,7 +736,7 @@ public class PowermaxPanelSettings {
byte[] zero3 = new byte[] { 0, 0, 0 };
for (int i = 0; i < keypad2wCnt; i++) {
keypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3);
localKeypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3);
}
} else {
logger.debug("Cannot get 2 way keypad settings");
@ -735,7 +748,7 @@ public class PowermaxPanelSettings {
byte[] zero3 = new byte[] { 0, 0, 0 };
for (int i = 0; i < sirenCnt; i++) {
sirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3);
localSirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3);
}
} else {
logger.debug("Cannot get siren settings");
@ -758,6 +771,11 @@ public class PowermaxPanelSettings {
}
}
pinCodes = localPinCodes;
keypad1wEnrolled = localKeypad1wEnrolled;
keypad2wEnrolled = localKeypad2wEnrolled;
sirensEnrolled = localSirensEnrolled;
return result;
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Used to store main characteristics of each Visonic alarm panel type in an ENUM
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermaxPanelType {
POWERMAX((byte) 0, "PowerMax", 1, 250, 8, 8, 2, 2, 8, 0, 28, 2, 0),
@ -29,19 +32,19 @@ public enum PowermaxPanelType {
POWERMASTER_10((byte) 7, "PowerMaster10", 3, 250, 8, 0, 8, 4, 8, 8, 29, 1, 5),
POWERMASTER_30((byte) 8, "PowerMaster30", 3, 1000, 32, 0, 32, 8, 48, 32, 62, 2, 5);
private byte code;
private String label;
private int partitions;
private int events;
private int keyfobs;
private int keypads1w;
private int keypads2w;
private int sirens;
private int userCodes;
private int prontags;
private int wireless;
private int wired;
private int customZones;
private final byte code;
private final String label;
private final int partitions;
private final int events;
private final int keyfobs;
private final int keypads1w;
private final int keypads2w;
private final int sirens;
private final int userCodes;
private final int prontags;
private final int wireless;
private final int wired;
private final int customZones;
private PowermaxPanelType(byte code, String label, int partitions, int events, int keyfobs, int keypads1w,
int keypads2w, int sirens, int userCodes, int prontags, int wireless, int wired, int customZones) {

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* All defined sensor types for all panels except Master panels
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermaxSensorType {
MOTION_SENSOR_1((byte) 0x03, "Motion"),
@ -29,8 +32,8 @@ public enum PowermaxSensorType {
MOTION_SENSOR_3((byte) 0x0C, "Motion"),
WIRED_SENSOR((byte) 0x0F, "Wired");
private byte code;
private String label;
private final byte code;
private final String label;
private PowermaxSensorType(byte code, String label) {
this.code = code;

View File

@ -19,11 +19,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.powermax.internal.message.PowermaxMessageConstants;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -32,6 +34,7 @@ import org.slf4j.LoggerFactory;
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxState extends PowermaxStateContainer {
private final Logger logger = LoggerFactory.getLogger(PowermaxState.class);
@ -58,19 +61,31 @@ public class PowermaxState extends PowermaxStateContainer {
public DynamicValue<Boolean> isArmed = new DynamicValue<>(this, SYSTEM_ARMED, () -> {
return isArmed();
}, () -> {
return isArmed() ? OnOffType.ON : OnOffType.OFF;
Boolean isArmed = isArmed();
if (isArmed == null) {
return UnDefType.NULL;
}
return isArmed ? OnOffType.ON : OnOffType.OFF;
});
public DynamicValue<String> panelMode = new DynamicValue<>(this, MODE, () -> {
return getPanelMode();
}, () -> {
return new StringType(getPanelMode());
String mode = getPanelMode();
if (mode == null) {
return UnDefType.NULL;
}
return new StringType(mode);
});
public DynamicValue<String> shortArmMode = new DynamicValue<>(this, ARM_MODE, () -> {
return getShortArmMode();
}, () -> {
return new StringType(getShortArmMode());
String mode = getShortArmMode();
if (mode == null) {
return UnDefType.NULL;
}
return new StringType(mode);
});
public DynamicValue<String> activeAlerts = new DynamicValue<>(this, ACTIVE_ALERTS, () -> {
@ -82,14 +97,18 @@ public class PowermaxState extends PowermaxStateContainer {
public DynamicValue<Boolean> pgmStatus = new DynamicValue<>(this, PGM_STATUS, () -> {
return getPGMX10DeviceStatus(0);
}, () -> {
return getPGMX10DeviceStatus(0) ? OnOffType.ON : OnOffType.OFF;
Boolean status = getPGMX10DeviceStatus(0);
if (status == null) {
return UnDefType.NULL;
}
return status ? OnOffType.ON : OnOffType.OFF;
});
private PowermaxPanelSettings panelSettings;
private PowermaxZoneState[] zones;
private Boolean[] pgmX10DevicesStatus;
private byte[] updateSettings;
private String[] eventLog;
private byte @Nullable [] updateSettings;
private String @Nullable [] eventLog;
private Map<Integer, Byte> updatedZoneNames;
private Map<Integer, Integer> updatedZoneInfos;
private List<PowermaxActiveAlert> activeAlertList;
@ -163,7 +182,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return the status (true or false)
*/
public Boolean getPGMX10DeviceStatus(int device) {
public @Nullable Boolean getPGMX10DeviceStatus(int device) {
return ((device < 0) || (device >= pgmX10DevicesStatus.length)) ? null : pgmX10DevicesStatus[device];
}
@ -173,7 +192,7 @@ public class PowermaxState extends PowermaxStateContainer {
* @param device the index of the PGM/X10 device (0 s for PGM; for X10 device is index 1)
* @param status true or false
*/
public void setPGMX10DeviceStatus(int device, Boolean status) {
public void setPGMX10DeviceStatus(int device, @Nullable Boolean status) {
if ((device >= 0) && (device < pgmX10DevicesStatus.length)) {
this.pgmX10DevicesStatus[device] = status;
}
@ -184,7 +203,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return the raw buffer as a table of bytes
*/
public byte[] getUpdateSettings() {
public byte @Nullable [] getUpdateSettings() {
return updateSettings;
}
@ -203,7 +222,8 @@ public class PowermaxState extends PowermaxStateContainer {
* @return the number of entries
*/
public int getEventLogSize() {
return (eventLog == null) ? 0 : eventLog.length;
String @Nullable [] localEventLog = eventLog;
return (localEventLog == null) ? 0 : localEventLog.length;
}
/**
@ -222,8 +242,10 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return the entry value (event)
*/
public String getEventLog(int index) {
return ((index < 1) || (index > getEventLogSize())) ? null : eventLog[index - 1];
public @Nullable String getEventLog(int index) {
String @Nullable [] localEventLog = eventLog;
return ((localEventLog == null) || (index < 1) || (index > getEventLogSize())) ? null
: localEventLog[index - 1];
}
/**
@ -233,8 +255,9 @@ public class PowermaxState extends PowermaxStateContainer {
* @param event the entry value (event)
*/
public void setEventLog(int index, String event) {
if ((index >= 1) && (index <= getEventLogSize())) {
this.eventLog[index - 1] = event;
String @Nullable [] localEventLog = eventLog;
if ((localEventLog != null) && (index >= 1) && (index <= getEventLogSize())) {
localEventLog[index - 1] = event;
}
}
@ -329,7 +352,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return either Download or Powerlink or Standard
*/
public String getPanelMode() {
public @Nullable String getPanelMode() {
String mode = null;
if (Boolean.TRUE.equals(downloadMode.getValue())) {
mode = "Download";
@ -346,7 +369,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return true or false
*/
public Boolean isArmed() {
public @Nullable Boolean isArmed() {
return isArmed(armMode.getValue());
}
@ -357,7 +380,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return true or false; null if mode is unexpected
*/
private static Boolean isArmed(String armMode) {
private static @Nullable Boolean isArmed(@Nullable String armMode) {
Boolean result = null;
if (armMode != null) {
try {
@ -375,7 +398,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return the short description
*/
public String getShortArmMode() {
public @Nullable String getShortArmMode() {
return getShortArmMode(armMode.getValue());
}
@ -386,7 +409,7 @@ public class PowermaxState extends PowermaxStateContainer {
*
* @return the short name or null if mode is unexpected
*/
private static String getShortArmMode(String armMode) {
private static @Nullable String getShortArmMode(@Nullable String armMode) {
String result = null;
if (armMode != null) {
try {
@ -420,8 +443,8 @@ public class PowermaxState extends PowermaxStateContainer {
}
for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
if ((getPGMX10DeviceStatus(i) != null)
&& getPGMX10DeviceStatus(i).equals(otherState.getPGMX10DeviceStatus(i))) {
Boolean status = getPGMX10DeviceStatus(i);
if ((status != null) && status.equals(otherState.getPGMX10DeviceStatus(i))) {
setPGMX10DeviceStatus(i, null);
}
}
@ -462,8 +485,9 @@ public class PowermaxState extends PowermaxStateContainer {
}
for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
if (update.getPGMX10DeviceStatus(i) != null) {
setPGMX10DeviceStatus(i, update.getPGMX10DeviceStatus(i));
Boolean status = update.getPGMX10DeviceStatus(i);
if (status != null) {
setPGMX10DeviceStatus(i, status);
}
}
@ -480,8 +504,9 @@ public class PowermaxState extends PowermaxStateContainer {
setEventLogSize(update.getEventLogSize());
}
for (int i = 1; i <= getEventLogSize(); i++) {
if (update.getEventLog(i) != null) {
setEventLog(i, update.getEventLog(i));
String log = update.getEventLog(i);
if (log != null) {
setEventLog(i, log);
}
}
@ -495,7 +520,7 @@ public class PowermaxState extends PowermaxStateContainer {
String str = "Bridge state:";
for (Value<?> value : getValues()) {
if ((value.getChannel() != null) && (value.getValue() != null)) {
if (value.getValue() != null) {
String channel = value.getChannel();
String vStr = value.getValue().toString();
String state = value.getState().toString();
@ -508,15 +533,16 @@ public class PowermaxState extends PowermaxStateContainer {
}
for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
if (getPGMX10DeviceStatus(i) != null) {
Boolean status = getPGMX10DeviceStatus(i);
if (status != null) {
str += String.format("\n - %s status = %s", (i == 0) ? "PGM device" : String.format("X10 device %d", i),
getPGMX10DeviceStatus(i) ? "ON" : "OFF");
status ? "ON" : "OFF");
}
}
for (int i = 1; i <= zones.length; i++) {
for (Value<?> value : zones[i - 1].getValues()) {
if ((value.getChannel() != null) && (value.getValue() != null)) {
if (value.getValue() != null) {
String channel = value.getChannel();
String vStr = value.getValue().toString();
String state = value.getState().toString();
@ -530,13 +556,13 @@ public class PowermaxState extends PowermaxStateContainer {
}
for (int i = 1; i <= getEventLogSize(); i++) {
if (getEventLog(i) != null) {
str += "\n - event log " + i + " = " + getEventLog(i);
String log = getEventLog(i);
if (log != null) {
str += "\n - event log " + i + " = " + log;
}
}
String alarms = getActiveAlerts();
str += "\n - active alarms/alerts = " + (alarms == null ? "null" : alarms);
str += "\n - active alarms/alerts = " + getActiveAlerts();
return str;
}

View File

@ -18,18 +18,21 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* Base class for extensible state objects
*
* @author Ron Isaacson - Initial contribution
*/
@NonNullByDefault
public abstract class PowermaxStateContainer {
protected final TimeZoneProvider timeZoneProvider;
@ -46,7 +49,7 @@ public abstract class PowermaxStateContainer {
parent.getValues().add(this);
}
public T getValue() {
public @Nullable T getValue() {
return value;
}
@ -67,10 +70,10 @@ public abstract class PowermaxStateContainer {
}
public class DynamicValue<T> extends Value<T> {
Supplier<T> valueFunction;
Supplier<@Nullable T> valueFunction;
Supplier<State> stateFunction;
public DynamicValue(PowermaxStateContainer parent, String channel, Supplier<T> valueFunction,
public DynamicValue(PowermaxStateContainer parent, String channel, Supplier<@Nullable T> valueFunction,
Supplier<State> stateFunction) {
super(parent, channel);
this.valueFunction = valueFunction;
@ -80,7 +83,7 @@ public abstract class PowermaxStateContainer {
// Note: setValue() is still valid, but the saved value will be ignored
@Override
public T getValue() {
public @Nullable T getValue() {
return valueFunction.get();
}
@ -106,7 +109,8 @@ public abstract class PowermaxStateContainer {
@Override
public State getState() {
return value ? trueState : falseState;
Boolean val = value;
return val == null ? UnDefType.NULL : (val ? trueState : falseState);
}
}
@ -117,7 +121,8 @@ public abstract class PowermaxStateContainer {
@Override
public State getState() {
return new StringType(value);
String val = value;
return val == null ? UnDefType.NULL : new StringType(val);
}
}
@ -128,7 +133,11 @@ public abstract class PowermaxStateContainer {
@Override
public State getState() {
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(value), timeZoneProvider.getTimeZone());
Long val = value;
if (val == null) {
return UnDefType.NULL;
}
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(val), timeZoneProvider.getTimeZone());
return new DateTimeType(zoned);
}
}

View File

@ -14,15 +14,18 @@ package org.openhab.binding.powermax.internal.state;
import java.util.EventObject;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Event for state received from the Visonic alarm panel
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxStateEvent extends EventObject {
private static final long serialVersionUID = 1L;
private PowermaxState state;
private final PowermaxState state;
public PowermaxStateEvent(Object source, PowermaxState state) {
super(source);

View File

@ -15,11 +15,14 @@ package org.openhab.binding.powermax.internal.state;
import java.util.EventListener;
import java.util.EventObject;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Powermax Alarm state Listener interface. Handles Powermax Alarm state events
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public interface PowermaxStateEventListener extends EventListener {
/**

View File

@ -12,17 +12,21 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* A class to store the settings of an X10 device
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxX10Settings {
private String name;
private boolean enabled;
private final @Nullable String name;
private final boolean enabled;
public PowermaxX10Settings(String name, boolean enabled) {
public PowermaxX10Settings(@Nullable String name, boolean enabled) {
this.name = name;
this.enabled = enabled;
}
@ -30,7 +34,7 @@ public class PowermaxX10Settings {
/**
* @return the name of the X10 device
*/
public String getName() {
public @Nullable String getName() {
return name;
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* All panel zone names
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public enum PowermaxZoneName {
ZONE_0(0, "Attic"),
@ -52,7 +55,7 @@ public enum PowermaxZoneName {
ZONE_30(30, "Custom 5"),
ZONE_31(31, "Not Installed");
private int id;
private final int id;
private String name;
private PowermaxZoneName(int id, String name) {

View File

@ -12,11 +12,15 @@
*/
package org.openhab.binding.powermax.internal.state;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* A class to store the settings of a zone
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxZoneSettings {
// Note: PowermaxStatusMessage contains hardcoded references to some of these strings
@ -27,14 +31,16 @@ public class PowermaxZoneSettings {
private static final String[] ZONE_CHIMES = { "Off", "Melody", "Zone" };
private String name;
private String type;
private String chime;
private String sensorType;
private boolean[] partitions;
private final @Nullable String chime;
private final boolean[] partitions;
private @Nullable String name;
private @Nullable String type;
private @Nullable String sensorType;
private boolean alwaysInAlarm;
public PowermaxZoneSettings(String name, byte type, byte chime, String sensorType, boolean[] partitions) {
public PowermaxZoneSettings(@Nullable String name, byte type, byte chime, @Nullable String sensorType,
boolean[] partitions) {
this.name = name;
this.type = ((type & 0x000000FF) < ZONE_TYPES.length) ? ZONE_TYPES[type & 0x000000FF] : null;
this.chime = ((chime & 0x000000FF) < ZONE_CHIMES.length) ? ZONE_CHIMES[chime & 0x000000FF] : null;
@ -48,7 +54,8 @@ public class PowermaxZoneSettings {
* @return the zone name
*/
public String getName() {
return (name == null) ? "Unknown" : name;
String localName = name;
return (localName == null) ? "Unknown" : localName;
}
/**
@ -56,7 +63,7 @@ public class PowermaxZoneSettings {
*
* @param name the zone name
*/
public void setName(String name) {
public void setName(@Nullable String name) {
this.name = name;
}
@ -64,7 +71,8 @@ public class PowermaxZoneSettings {
* @return the zone type
*/
public String getType() {
return (type == null) ? "Unknown" : type;
String localType = type;
return (localType == null) ? "Unknown" : localType;
}
/**
@ -79,14 +87,16 @@ public class PowermaxZoneSettings {
}
public String getChime() {
return (chime == null) ? "Unknown" : chime;
String localChime = chime;
return (localChime == null) ? "Unknown" : localChime;
}
/**
* @return the sensor type of this zone
*/
public String getSensorType() {
return (sensorType == null) ? "Unknown" : sensorType;
String localSensorType = sensorType;
return (localSensorType == null) ? "Unknown" : localSensorType;
}
/**

View File

@ -14,14 +14,17 @@ package org.openhab.binding.powermax.internal.state;
import static org.openhab.binding.powermax.internal.PowermaxBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.types.UnDefType;
/**
* A class to store the state of a zone
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class PowermaxZoneState extends PowermaxStateContainer {
public BooleanValue tripped = new BooleanValue(this, TRIPPED, OpenClosedType.OPEN, OpenClosedType.CLOSED);
@ -41,7 +44,7 @@ public class PowermaxZoneState extends PowermaxStateContainer {
}, () -> {
Boolean isArmed = armed.getValue();
if (isArmed == null) {
return null;
return UnDefType.NULL;
}
return isArmed ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
});
@ -51,7 +54,7 @@ public class PowermaxZoneState extends PowermaxStateContainer {
}
public boolean isLastTripBeforeTime(long refTime) {
return Boolean.TRUE.equals(tripped.getValue()) && (lastTripped.getValue() != null)
&& (lastTripped.getValue() < refTime);
Long lastTrippedValue = lastTripped.getValue();
return Boolean.TRUE.equals(tripped.getValue()) && (lastTrippedValue != null) && (lastTrippedValue < refTime);
}
}