*/
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;
}
*/
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;
}
*/
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;
}
*/
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;
}
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;
*
* @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;
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());
}
/**
* 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());
@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
/**
* @return the input stream
*/
- public InputStream getInput() {
+ public @Nullable InputStream getInput() {
return input;
}
*
* @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;
}
*
* @param output the output stream
*/
- public void setOutput(OutputStream output) {
+ public void setOutput(@Nullable OutputStream output) {
this.output = output;
}
/**
* @return the thread that handles the message reading
*/
- public Thread getReaderThread() {
+ public @Nullable Thread getReaderThread() {
return readerThread;
}
import java.io.IOException;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public interface PowermaxConnectorInterface {
/**
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;
*
* @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
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxSerialConnector extends PowermaxConnector implements SerialPortEventListener {
private final Logger logger = LoggerFactory.getLogger(PowermaxSerialConnector.class);
private final String serialPortName;
private final int baudRate;
private final SerialPortManager serialPortManager;
- private SerialPort serialPort;
+ private @Nullable SerialPort serialPort;
/**
* Constructor
this.serialPortManager = serialPortManager;
this.serialPortName = serialPortName;
this.baudRate = baudRate;
- this.serialPort = null;
}
@Override
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);
}
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;
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxTcpConnector extends PowermaxConnector {
private final Logger logger = LoggerFactory.getLogger(PowermaxTcpConnector.class);
private final String ipAddress;
private final int tcpPort;
private final int connectTimeout;
- private Socket tcpSocket;
+ private @Nullable Socket tcpSocket;
/**
* Constructor.
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);
}
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());
}
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;
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
@Component(service = ConsoleCommandExtension.class)
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
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:
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;
- }
}
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;
/**
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;
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;
*
* @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;
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;
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;
super(thing);
this.serialPortManager = serialPortManager;
this.timeZoneProvider = timeZoneProvider;
+ this.pinCode = "";
+ this.currentState = new PowermaxState(new PowermaxPanelSettings(DEFAULT_PANEL_TYPE), timeZoneProvider);
}
@Override
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
}
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 {
updateRingingState();
if (isConnected()) {
checkKeepAlive();
- commManager.retryDownloadSetup(remainingDownloadAttempts);
+ retryDownloadSetup();
} else {
tryReconnect();
}
}
}
- 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";
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";
@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();
* 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);
* 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);
* 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");
updateChannelsFromAlarmState(MODE, currentState);
processPanelSettings();
} else {
- commManager.startDownload();
+ localCommManager.startDownload();
}
} catch (Exception e) {
logger.debug("openConnection(): {}", e.getMessage(), e);
* @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;
}
* 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
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:
}
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());
}
}
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();
&& 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());
// 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);
updateChannelsFromAlarmState(updateState);
currentState.merge(updateState);
- PowermaxPanelSettings panelSettings = getPanelSettings();
if (!updateState.getUpdatedZoneNames().isEmpty()) {
for (Integer zoneIdx : updateState.getUpdatedZoneNames().keySet()) {
if (panelSettings.getZoneSettings(zoneIdx) != null) {
if (doProcessSettings) {
// There is a change of mode (standard or Powerlink)
processPanelSettings();
- commManager.exitDownload();
+ localCommManager.exitDownload();
}
}
}
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 {
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();
}
}
*
* @param state: the alarm system state
*/
- private void updateChannelsFromAlarmState(PowermaxState state) {
+ private void updateChannelsFromAlarmState(@Nullable PowermaxState state) {
updateChannelsFromAlarmState(null, state);
}
* @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;
}
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));
}
}
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);
}
}
* 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();
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;
}
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;
*
* @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);
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;
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 "
}
} 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 "
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);
}
@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();
}
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.",
}
break;
case X10_STATUS:
- bridgeHandler.x10Command(getConfigAs(PowermaxX10Configuration.class).deviceNumber.byteValue(),
+ powermaxBridgeHandler.x10Command(
+ Byte.valueOf(
+ (byte) (getConfigAs(PowermaxX10Configuration.class).deviceNumber & 0x000000FF)),
command);
break;
default:
* @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();
}
}
} 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);
}
}
}
*/
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;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
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);
*/
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;
*
* @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;
/**
* @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();
}
/**
* @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";
}
/**
*
* @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);
return newState;
}
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
return null;
}
/**
* @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;
}
* @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
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;
*
* @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;
+ private final TimeZoneProvider timeZoneProvider;
+
/** The object to store the current settings of the Powermax alarm system */
- private PowermaxPanelSettings panelSettings;
+ private final PowermaxPanelSettings panelSettings;
/** Panel type used when in standard mode */
- private PowermaxPanelType panelType;
+ private final PowermaxPanelType panelType;
- private boolean forceStandardMode;
- private boolean autoSyncTime;
- private final TimeZoneProvider timeZoneProvider;
+ private final boolean forceStandardMode;
+ private final boolean autoSyncTime;
- private List<PowermaxStateEventListener> listeners = new ArrayList<>();
+ 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
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");
}
/**
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");
}
/**
*/
public synchronized void addEventListener(PowermaxStateEventListener listener) {
listeners.add(listener);
- if (connector != null) {
- connector.addEventListener(this);
- }
+ connector.addEventListener(this);
}
/**
* @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);
}
* @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<>();
}
* @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();
}
* @return true if connected to the Powermax alarm system or false if not
*/
public boolean isConnected() {
- return (connector != null) && connector.isConnected();
+ return connector.isConnected();
}
/**
* @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);
}
/**
/**
* @return the last message sent to the Powermax alarm system
*/
- public synchronized PowermaxBaseMessage getLastSendMsg() {
+ public synchronized @Nullable PowermaxBaseMessage getLastSendMsg() {
return lastSendMsg;
}
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()) {
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 {
*
* @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;
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);
} 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;
}
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 {
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");
}
/**
- * @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;
}
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);
}
* @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());
*/
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxDeniedMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxDeniedMessage.class);
}
@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");
*/
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;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage {
/**
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxEventLogMessage extends PowermaxBaseMessage {
/**
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxInfoMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxInfoMessage.class);
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
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() {
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);
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 {
/**
*/
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxPanelMessage extends PowermaxBaseMessage {
/**
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxPowerMasterMessage extends PowermaxBaseMessage {
/**
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxPowerlinkMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxPowerlinkMessage.class);
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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),
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;
*/
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),
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;
/**
* @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;
}
}
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxSettingsMessage extends PowermaxBaseMessage {
private final Logger logger = LoggerFactory.getLogger(PowermaxSettingsMessage.class);
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxStatusMessage extends PowermaxBaseMessage {
private static byte[] zoneBytes(byte zones1, byte zones9, byte zones17, byte zones25) {
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
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);
}
*/
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;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxZonesNameMessage extends PowermaxBaseMessage {
/**
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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;
/**
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxZonesTypeMessage extends PowermaxBaseMessage {
/**
}
@Override
- protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
+ protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
if (commManager == null) {
return null;
}
*/
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"),
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;
*/
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),
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,
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;
*
* @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;
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
/**
* @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;
}
*
* @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];
}
*
* @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();
}
*
* @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];
}
* @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];
}
/**
* @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];
}
/**
* @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;
}
}
- 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;
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;
*
* @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;
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
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);
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");
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));
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");
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");
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");
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");
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");
}
}
+ pinCodes = localPinCodes;
+ keypad1wEnrolled = localKeypad1wEnrolled;
+ keypad2wEnrolled = localKeypad2wEnrolled;
+ sirensEnrolled = localSirensEnrolled;
+
return result;
}
*/
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),
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) {
*/
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"),
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;
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;
*
* @author Laurent Garnier - Initial contribution
*/
+@NonNullByDefault
public class PowermaxState extends PowermaxStateContainer {
private final Logger logger = LoggerFactory.getLogger(PowermaxState.class);
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, () -> {
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;
*
* @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];
}
* @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;
}
*
* @return the raw buffer as a table of bytes
*/
- public byte[] getUpdateSettings() {
+ public byte @Nullable [] getUpdateSettings() {
return updateSettings;
}
* @return the number of entries
*/
public int getEventLogSize() {
- return (eventLog == null) ? 0 : eventLog.length;
+ String @Nullable [] localEventLog = eventLog;
+ return (localEventLog == null) ? 0 : localEventLog.length;
}
/**
*
* @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];
}
/**
* @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;
}
}
*
* @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";
*
* @return true or false
*/
- public Boolean isArmed() {
+ public @Nullable Boolean isArmed() {
return isArmed(armMode.getValue());
}
*
* @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 {
*
* @return the short description
*/
- public String getShortArmMode() {
+ public @Nullable String getShortArmMode() {
return getShortArmMode(armMode.getValue());
}
*
* @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 {
}
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);
}
}
}
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);
}
}
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);
}
}
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();
}
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();
}
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;
}
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;
parent.getValues().add(this);
}
- public T getValue() {
+ public @Nullable T getValue() {
return value;
}
}
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;
// Note: setValue() is still valid, but the saved value will be ignored
@Override
- public T getValue() {
+ public @Nullable T getValue() {
return valueFunction.get();
}
@Override
public State getState() {
- return value ? trueState : falseState;
+ Boolean val = value;
+ return val == null ? UnDefType.NULL : (val ? trueState : falseState);
}
}
@Override
public State getState() {
- return new StringType(value);
+ String val = value;
+ return val == null ? UnDefType.NULL : new StringType(val);
}
}
@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);
}
}
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);
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 {
/**
*/
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;
}
/**
* @return the name of the X10 device
*/
- public String getName() {
+ public @Nullable String getName() {
return name;
}
*/
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"),
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) {
*/
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
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;
* @return the zone name
*/
public String getName() {
- return (name == null) ? "Unknown" : name;
+ String localName = name;
+ return (localName == null) ? "Unknown" : localName;
}
/**
*
* @param name the zone name
*/
- public void setName(String name) {
+ public void setName(@Nullable String name) {
this.name = name;
}
* @return the zone type
*/
public String getType() {
- return (type == null) ? "Unknown" : type;
+ String localType = type;
+ return (localType == null) ? "Unknown" : localType;
}
/**
}
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;
}
/**
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);
}, () -> {
Boolean isArmed = armed.getValue();
if (isArmed == null) {
- return null;
+ return UnDefType.NULL;
}
return isArmed ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
});
}
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);
}
}