From 0722bd71f5e2e7e6606653aede6bb53954947228 Mon Sep 17 00:00:00 2001 From: robnielsen Date: Wed, 4 Nov 2020 14:05:01 -0600 Subject: [PATCH] [insteon] remove all @SuppressWarnings("null") (#8937) Signed-off-by: Rob Nielsen --- .../insteon/internal/InsteonBinding.java | 43 +++++--- .../command/InsteonCommandExtension.java | 19 ++-- .../internal/device/CommandHandler.java | 52 +++------- .../internal/device/DeviceFeature.java | 32 +++--- .../insteon/internal/device/DeviceType.java | 11 +-- .../internal/device/DeviceTypeLoader.java | 35 ++++--- .../internal/device/FeatureTemplate.java | 28 ++++-- .../internal/device/InsteonDevice.java | 30 ++++-- .../internal/device/MessageDispatcher.java | 9 +- .../internal/device/MessageHandler.java | 54 +++------- .../internal/device/ModemDBBuilder.java | 8 +- .../insteon/internal/device/PollHandler.java | 6 +- .../internal/device/RequestQueueManager.java | 31 +++--- .../binding/insteon/internal/device/X10.java | 28 +++--- .../insteon/internal/driver/IOStream.java | 16 ++- .../insteon/internal/driver/Poller.java | 29 ++++-- .../binding/insteon/internal/driver/Port.java | 98 ++++++++----------- .../internal/driver/SerialIOStream.java | 39 +++++--- .../insteon/internal/driver/TcpIOStream.java | 22 +++-- .../internal/driver/hub/HubIOStream.java | 28 ++++-- .../handler/InsteonDeviceHandler.java | 83 +++++++++++++--- .../handler/InsteonNetworkHandler.java | 73 ++++++++++---- .../insteon/internal/message/DataType.java | 17 ++-- .../insteon/internal/message/Field.java | 23 +++-- .../binding/insteon/internal/message/Msg.java | 63 ++++-------- .../internal/message/MsgDefinition.java | 3 +- .../internal/message/XMLMessageReader.java | 23 ++--- .../binding/insteon/internal/utils/Utils.java | 7 +- .../src/main/resources/device_features.xml | 4 +- 29 files changed, 511 insertions(+), 403 deletions(-) diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java index ff6e5a0a9..593dc6782 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java @@ -106,15 +106,14 @@ import org.xml.sax.SAXException; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings({ "null", "unused" }) public class InsteonBinding { private static final int DEAD_DEVICE_COUNT = 10; private final Logger logger = LoggerFactory.getLogger(InsteonBinding.class); private Driver driver; - private ConcurrentHashMap devices = new ConcurrentHashMap<>(); - private ConcurrentHashMap bindingConfigs = new ConcurrentHashMap<>(); + private Map devices = new ConcurrentHashMap<>(); + private Map bindingConfigs = new ConcurrentHashMap<>(); private PortListener portListener = new PortListener(); private int devicePollIntervalMilliseconds = 300000; private int deadDeviceTimeout = -1; @@ -123,8 +122,8 @@ public class InsteonBinding { private int x10HouseUnit = -1; private InsteonNetworkHandler handler; - public InsteonBinding(InsteonNetworkHandler handler, @Nullable InsteonNetworkConfiguration config, - @Nullable SerialPortManager serialPortManager, ScheduledExecutorService scheduler) { + public InsteonBinding(InsteonNetworkHandler handler, InsteonNetworkConfiguration config, + SerialPortManager serialPortManager, ScheduledExecutorService scheduler) { this.handler = handler; String port = config.getPort(); @@ -142,8 +141,13 @@ public class InsteonBinding { String additionalDevices = config.getAdditionalDevices(); if (additionalDevices != null) { try { - DeviceTypeLoader.instance().loadDeviceTypesXML(additionalDevices); - logger.debug("read additional device definitions from {}", additionalDevices); + DeviceTypeLoader instance = DeviceTypeLoader.instance(); + if (instance != null) { + instance.loadDeviceTypesXML(additionalDevices); + logger.debug("read additional device definitions from {}", additionalDevices); + } else { + logger.warn("device type loader instance is null"); + } } catch (ParserConfigurationException | SAXException | IOException e) { logger.warn("error reading additional devices from {}", additionalDevices, e); } @@ -201,6 +205,10 @@ public class InsteonBinding { InsteonAddress address = bindingConfig.getAddress(); InsteonDevice dev = getDevice(address); + if (dev == null) { + logger.warn("device for address {} is null", address); + return; + } @Nullable DeviceFeature f = dev.getFeature(bindingConfig.getFeature()); if (f == null || f.isFeatureGroup()) { @@ -209,7 +217,7 @@ public class InsteonBinding { Collections.sort(names); for (String name : names) { DeviceFeature feature = dev.getFeature(name); - if (!feature.isFeatureGroup()) { + if (feature != null && !feature.isFeatureGroup()) { if (buf.length() > 0) { buf.append(", "); } @@ -249,8 +257,16 @@ public class InsteonBinding { handler.updateState(channelUID, state); } - public InsteonDevice makeNewDevice(InsteonAddress addr, String productKey, Map deviceConfigMap) { - DeviceType dt = DeviceTypeLoader.instance().getDeviceType(productKey); + public @Nullable InsteonDevice makeNewDevice(InsteonAddress addr, String productKey, + Map deviceConfigMap) { + DeviceTypeLoader instance = DeviceTypeLoader.instance(); + if (instance == null) { + return null; + } + DeviceType dt = instance.getDeviceType(productKey); + if (dt == null) { + return null; + } InsteonDevice dev = InsteonDevice.makeDevice(dt); dev.setAddress(addr); dev.setProductKey(productKey); @@ -361,10 +377,16 @@ public class InsteonBinding { private String getLinkInfo(Map dbes, InsteonAddress a, boolean prefix) { ModemDBEntry dbe = dbes.get(a); + if (dbe == null) { + return ""; + } List controls = dbe.getControls(); List responds = dbe.getRespondsTo(); Port port = dbe.getPort(); + if (port == null) { + return ""; + } String deviceName = port.getDeviceName(); String s = deviceName.startsWith("/hub") ? "hub" : "plm"; StringBuilder buf = new StringBuilder(); @@ -433,7 +455,6 @@ public class InsteonBinding { * Handles messages that come in from the ports. * Will only process one message at a time. */ - @NonNullByDefault private class PortListener implements MsgListener, DriverListener { @Override public void msg(Msg msg) { diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/command/InsteonCommandExtension.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/command/InsteonCommandExtension.java index e782894a9..ea626c567 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/command/InsteonCommandExtension.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/command/InsteonCommandExtension.java @@ -182,6 +182,7 @@ public class InsteonCommandExtension extends AbstractConsoleCommandExtension imp public void msg(Msg msg) { if (monitorAllDevices || monitoredAddresses.contains(msg.getAddr("fromAddress"))) { String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()); + Console console = this.console; if (console != null) { console.println(date + " " + msg.toString()); } @@ -218,7 +219,7 @@ public class InsteonCommandExtension extends AbstractConsoleCommandExtension imp private void startMonitoring(Console console, String addr) { if (addr.equalsIgnoreCase("all")) { - if (monitorAllDevices != true) { + if (!monitorAllDevices) { monitorAllDevices = true; monitoredAddresses.clear(); console.println("Started monitoring all devices."); @@ -240,7 +241,7 @@ public class InsteonCommandExtension extends AbstractConsoleCommandExtension imp } } - if (monitoring == false) { + if (!monitoring) { getInsteonBinding().getDriver().addMsgListener(this); this.console = console; @@ -249,7 +250,7 @@ public class InsteonCommandExtension extends AbstractConsoleCommandExtension imp } private void stopMonitoring(Console console, String addr) { - if (monitoring == false) { + if (!monitoring) { console.println("Not mointoring any devices."); return; } @@ -277,7 +278,7 @@ public class InsteonCommandExtension extends AbstractConsoleCommandExtension imp } } - if (monitorAllDevices == false && monitoredAddresses.isEmpty()) { + if (!monitorAllDevices && monitoredAddresses.isEmpty()) { getInsteonBinding().getDriver().removeListener(this); this.console = null; monitoring = false; @@ -335,18 +336,12 @@ public class InsteonCommandExtension extends AbstractConsoleCommandExtension imp } } - @SuppressWarnings("null") private InsteonBinding getInsteonBinding() { + InsteonNetworkHandler handler = this.handler; if (handler == null) { throw new IllegalArgumentException("No Insteon network bridge configured."); } - @Nullable - InsteonBinding insteonBinding = handler.getInsteonBinding(); - if (insteonBinding == null) { - throw new IllegalArgumentException("Insteon binding is null."); - } - - return insteonBinding; + return handler.getInsteonBinding(); } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/CommandHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/CommandHandler.java index d5d0072d3..cb2e871aa 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/CommandHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/CommandHandler.java @@ -44,11 +44,9 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public abstract class CommandHandler { private static final Logger logger = LoggerFactory.getLogger(CommandHandler.class); DeviceFeature feature; // related DeviceFeature - @Nullable Map parameters = new HashMap<>(); /** @@ -114,22 +112,24 @@ public abstract class CommandHandler { protected int getMaxLightLevel(InsteonChannelConfiguration conf, int defaultLevel) { Map params = conf.getParameters(); - if (conf.getFeature().contains("dimmer") && params.containsKey("dimmermax")) { - String item = conf.getChannelName(); + if (conf.getFeature().contains("dimmer")) { String dimmerMax = params.get("dimmermax"); - try { - int i = Integer.parseInt(dimmerMax); - if (i > 1 && i <= 99) { - int level = (int) Math.ceil((i * 255.0) / 100); // round up - if (level < defaultLevel) { - logger.debug("item {}: using dimmermax value of {}", item, dimmerMax); - return level; + if (dimmerMax != null) { + String item = conf.getChannelName(); + try { + int i = Integer.parseInt(dimmerMax); + if (i > 1 && i <= 99) { + int level = (int) Math.ceil((i * 255.0) / 100); // round up + if (level < defaultLevel) { + logger.debug("item {}: using dimmermax value of {}", item, dimmerMax); + return level; + } + } else { + logger.warn("item {}: dimmermax must be between 1-99 inclusive: {}", item, dimmerMax); } - } else { - logger.warn("item {}: dimmermax must be between 1-99 inclusive: {}", item, dimmerMax); + } catch (NumberFormatException e) { + logger.warn("item {}: invalid int value for dimmermax: {}", item, dimmerMax); } - } catch (NumberFormatException e) { - logger.warn("item {}: invalid int value for dimmermax: {}", item, dimmerMax); } } @@ -157,7 +157,6 @@ public abstract class CommandHandler { return iv; } - @NonNullByDefault public static class WarnCommandHandler extends CommandHandler { WarnCommandHandler(DeviceFeature f) { super(f); @@ -169,7 +168,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class NoOpCommandHandler extends CommandHandler { NoOpCommandHandler(DeviceFeature f) { super(f); @@ -181,7 +179,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class LightOnOffCommandHandler extends CommandHandler { LightOnOffCommandHandler(DeviceFeature f) { super(f); @@ -227,7 +224,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class FastOnOffCommandHandler extends CommandHandler { FastOnOffCommandHandler(DeviceFeature f) { super(f); @@ -256,7 +252,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class RampOnOffCommandHandler extends RampCommandHandler { RampOnOffCommandHandler(DeviceFeature f) { super(f); @@ -296,7 +291,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class ManualChangeCommandHandler extends CommandHandler { ManualChangeCommandHandler(DeviceFeature f) { super(f); @@ -327,7 +321,6 @@ public abstract class CommandHandler { /** * Sends ALLLink broadcast commands to group */ - @NonNullByDefault public static class GroupBroadcastCommandHandler extends CommandHandler { GroupBroadcastCommandHandler(DeviceFeature f) { super(f); @@ -358,7 +351,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class LEDOnOffCommandHandler extends CommandHandler { LEDOnOffCommandHandler(DeviceFeature f) { super(f); @@ -386,7 +378,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class X10OnOffCommandHandler extends CommandHandler { X10OnOffCommandHandler(DeviceFeature f) { super(f); @@ -415,7 +406,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class X10PercentCommandHandler extends CommandHandler { X10PercentCommandHandler(DeviceFeature f) { super(f); @@ -454,7 +444,6 @@ public abstract class CommandHandler { private final int[] x10CodeForLevel = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; } - @NonNullByDefault public static class X10IncreaseDecreaseCommandHandler extends CommandHandler { X10IncreaseDecreaseCommandHandler(DeviceFeature f) { super(f); @@ -484,7 +473,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class IOLincOnOffCommandHandler extends CommandHandler { IOLincOnOffCommandHandler(DeviceFeature f) { super(f); @@ -526,7 +514,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class IncreaseDecreaseCommandHandler extends CommandHandler { IncreaseDecreaseCommandHandler(DeviceFeature f) { super(f); @@ -552,7 +539,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class PercentHandler extends CommandHandler { PercentHandler(DeviceFeature f) { super(f); @@ -582,7 +568,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault private abstract static class RampCommandHandler extends CommandHandler { private static double[] halfRateRampTimes = new double[] { 0.1, 0.3, 2, 6.5, 19, 23.5, 28, 32, 38.5, 47, 90, 150, 210, 270, 360, 480 }; @@ -647,7 +632,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class RampPercentHandler extends RampCommandHandler { RampPercentHandler(DeviceFeature f) { @@ -681,7 +665,6 @@ public abstract class CommandHandler { } } - @NonNullByDefault public static class PowerMeterCommandHandler extends CommandHandler { PowerMeterCommandHandler(DeviceFeature f) { super(f); @@ -728,7 +711,6 @@ public abstract class CommandHandler { * First used for setting thermostat parameters. */ - @NonNullByDefault public static class NumberCommandHandler extends CommandHandler { NumberCommandHandler(DeviceFeature f) { super(f); @@ -792,7 +774,6 @@ public abstract class CommandHandler { /** * Handler to set the thermostat system mode */ - @NonNullByDefault public static class ThermostatSystemModeCommandHandler extends NumberCommandHandler { ThermostatSystemModeCommandHandler(DeviceFeature f) { super(f); @@ -821,7 +802,6 @@ public abstract class CommandHandler { /** * Handler to set the thermostat fan mode */ - @NonNullByDefault public static class ThermostatFanModeCommandHandler extends NumberCommandHandler { ThermostatFanModeCommandHandler(DeviceFeature f) { super(f); @@ -844,7 +824,6 @@ public abstract class CommandHandler { /** * Handler to set the fanlinc fan mode */ - @NonNullByDefault public static class FanLincFanCommandHandler extends NumberCommandHandler { FanLincFanCommandHandler(DeviceFeature f) { super(f); @@ -883,6 +862,7 @@ public abstract class CommandHandler { Class c = Class.forName(cname); @SuppressWarnings("unchecked") Class dc = (Class) c; + @Nullable T ch = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f); ch.setParameters(params); return ch; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java index 0d1f20e9a..76d340425 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java @@ -62,7 +62,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class DeviceFeature { public static enum QueryStatus { NEVER_QUERIED, @@ -80,8 +79,8 @@ public class DeviceFeature { private int directAckTimeout = 6000; private QueryStatus queryStatus = QueryStatus.NEVER_QUERIED; - private @Nullable MessageHandler defaultMsgHandler = new MessageHandler.DefaultMsgHandler(this); - private @Nullable CommandHandler defaultCommandHandler = new CommandHandler.WarnCommandHandler(this); + private MessageHandler defaultMsgHandler = new MessageHandler.DefaultMsgHandler(this); + private CommandHandler defaultCommandHandler = new CommandHandler.WarnCommandHandler(this); private @Nullable PollHandler pollHandler = null; private @Nullable MessageDispatcher dispatcher = null; @@ -135,7 +134,7 @@ public class DeviceFeature { return directAckTimeout; } - public @Nullable MessageHandler getDefaultMsgHandler() { + public MessageHandler getDefaultMsgHandler() { return defaultMsgHandler; } @@ -164,11 +163,11 @@ public class DeviceFeature { dispatcher = md; } - public void setDefaultCommandHandler(@Nullable CommandHandler ch) { + public void setDefaultCommandHandler(CommandHandler ch) { defaultCommandHandler = ch; } - public void setDefaultMsgHandler(@Nullable MessageHandler mh) { + public void setDefaultMsgHandler(MessageHandler mh) { defaultMsgHandler = mh; } @@ -264,11 +263,12 @@ public class DeviceFeature { * @return true if dispatch successful */ public boolean handleMessage(Msg msg) { + MessageDispatcher dispatcher = this.dispatcher; if (dispatcher == null) { logger.warn("{} no dispatcher for msg {}", name, msg); return false; } - return (dispatcher.dispatch(msg)); + return dispatcher.dispatch(msg); } /** @@ -280,9 +280,11 @@ public class DeviceFeature { public void handleCommand(InsteonChannelConfiguration c, Command cmd) { Class key = cmd.getClass(); CommandHandler h = commandHandlers.containsKey(key) ? commandHandlers.get(key) : defaultCommandHandler; - logger.trace("{} uses {} to handle command {} for {}", getName(), h.getClass().getSimpleName(), - key.getSimpleName(), getDevice().getAddress()); - h.handleCommand(c, cmd, getDevice()); + if (h != null) { + logger.trace("{} uses {} to handle command {} for {}", getName(), h.getClass().getSimpleName(), + key.getSimpleName(), getDevice().getAddress()); + h.handleCommand(c, cmd, getDevice()); + } } /** @@ -291,6 +293,7 @@ public class DeviceFeature { * @return the poll message */ public @Nullable Msg makePollMsg() { + PollHandler pollHandler = this.pollHandler; if (pollHandler == null) { return null; } @@ -387,8 +390,9 @@ public class DeviceFeature { public static DeviceFeature makeDeviceFeature(String s) { DeviceFeature f = null; synchronized (features) { - if (features.containsKey(s)) { - f = features.get(s).build(); + FeatureTemplate ft = features.get(s); + if (ft != null) { + f = ft.build(); } else { logger.warn("unimplemented feature requested: {}", s); } @@ -436,6 +440,8 @@ public class DeviceFeature { static { // read features from xml file and store them in a map InputStream input = DeviceFeature.class.getResourceAsStream("/device_features.xml"); - readFeatureTemplates(input); + if (input != null) { + readFeatureTemplates(input); + } } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java index da2f3fd7b..0a92f7845 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java @@ -14,6 +14,7 @@ package org.openhab.binding.insteon.internal.device; import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -26,13 +27,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class DeviceType { private String productKey; private String model = ""; private String description = ""; - private HashMap features = new HashMap<>(); - private HashMap featureGroups = new HashMap<>(); + private Map features = new HashMap<>(); + private Map featureGroups = new HashMap<>(); /** * Constructor @@ -48,7 +48,7 @@ public class DeviceType { * * @return all features that this device type supports */ - public HashMap getFeatures() { + public Map getFeatures() { return features; } @@ -57,7 +57,7 @@ public class DeviceType { * * @return all feature groups of this device type */ - public HashMap getFeatureGroups() { + public Map getFeatureGroups() { return featureGroups; } @@ -127,7 +127,6 @@ public class DeviceType { * * @author Bernd Pfrommer - Initial contribution */ - @NonNullByDefault public static class FeatureGroup { private String name; private String type; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceTypeLoader.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceTypeLoader.java index 295985a1c..79b368dd2 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceTypeLoader.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceTypeLoader.java @@ -17,6 +17,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; @@ -42,11 +43,10 @@ import org.xml.sax.SAXException; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class DeviceTypeLoader { private static final Logger logger = LoggerFactory.getLogger(DeviceTypeLoader.class); - private HashMap deviceTypes = new HashMap<>(); - private @Nullable static DeviceTypeLoader deviceTypeLoader = null; + private Map deviceTypes = new HashMap<>(); + private static DeviceTypeLoader deviceTypeLoader = new DeviceTypeLoader(); private DeviceTypeLoader() { } // private so nobody can call it @@ -66,7 +66,7 @@ public class DeviceTypeLoader { * * @return currently known device types */ - public HashMap getDeviceTypes() { + public Map getDeviceTypes() { return (deviceTypes); } @@ -202,20 +202,23 @@ public class DeviceTypeLoader { */ @Nullable public static synchronized DeviceTypeLoader instance() { - if (deviceTypeLoader == null) { - deviceTypeLoader = new DeviceTypeLoader(); + if (deviceTypeLoader.getDeviceTypes().isEmpty()) { InputStream input = DeviceTypeLoader.class.getResourceAsStream("/device_types.xml"); - try { - deviceTypeLoader.loadDeviceTypesXML(input); - } catch (ParserConfigurationException e) { - logger.warn("parser config error when reading device types xml file: ", e); - } catch (SAXException e) { - logger.warn("SAX exception when reading device types xml file: ", e); - } catch (IOException e) { - logger.warn("I/O exception when reading device types xml file: ", e); + if (input != null) { + try { + deviceTypeLoader.loadDeviceTypesXML(input); + } catch (ParserConfigurationException e) { + logger.warn("parser config error when reading device types xml file: ", e); + } catch (SAXException e) { + logger.warn("SAX exception when reading device types xml file: ", e); + } catch (IOException e) { + logger.warn("I/O exception when reading device types xml file: ", e); + } + logger.debug("loaded {} devices: ", deviceTypeLoader.getDeviceTypes().size()); + deviceTypeLoader.logDeviceTypes(); + } else { + logger.warn("unable to get device types xml file as a resource"); } - logger.debug("loaded {} devices: ", deviceTypeLoader.getDeviceTypes().size()); - deviceTypeLoader.logDeviceTypes(); } return deviceTypeLoader; } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/FeatureTemplate.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/FeatureTemplate.java index 28d55dd03..5ac39d07e 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/FeatureTemplate.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/FeatureTemplate.java @@ -13,6 +13,7 @@ package org.openhab.binding.insteon.internal.device; import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -28,7 +29,6 @@ import org.openhab.core.types.Command; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class FeatureTemplate { private String name; private String timeout; @@ -37,8 +37,8 @@ public class FeatureTemplate { private @Nullable HandlerEntry pollHandler = null; private @Nullable HandlerEntry defaultMsgHandler = null; private @Nullable HandlerEntry defaultCmdHandler = null; - private HashMap messageHandlers = new HashMap<>(); - private HashMap, HandlerEntry> commandHandlers = new HashMap<>(); + private Map messageHandlers = new HashMap<>(); + private Map, HandlerEntry> commandHandlers = new HashMap<>(); public FeatureTemplate(String name, boolean isStatus, String timeout) { this.name = name; @@ -80,7 +80,7 @@ public class FeatureTemplate { * * @return a Hashmap from Integer to String representing the command codes and the associated message handlers */ - public HashMap getMessageHandlers() { + public Map getMessageHandlers() { return messageHandlers; } @@ -91,7 +91,7 @@ public class FeatureTemplate { * @see #getMessageHandlers() * @return a HashMap from Command Classes to CommandHandler names */ - public HashMap, HandlerEntry> getCommandHandlers() { + public Map, HandlerEntry> getCommandHandlers() { return commandHandlers; } @@ -141,19 +141,29 @@ public class FeatureTemplate { DeviceFeature f = new DeviceFeature(name); f.setStatusFeature(isStatus); f.setTimeout(timeout); + HandlerEntry dispatcher = this.dispatcher; if (dispatcher != null) { f.setMessageDispatcher(MessageDispatcher.makeHandler(dispatcher.getName(), dispatcher.getParams(), f)); } + HandlerEntry pollHandler = this.pollHandler; if (pollHandler != null) { f.setPollHandler(PollHandler.makeHandler(pollHandler, f)); } + HandlerEntry defaultCmdHandler = this.defaultCmdHandler; if (defaultCmdHandler != null) { - f.setDefaultCommandHandler( - CommandHandler.makeHandler(defaultCmdHandler.getName(), defaultCmdHandler.getParams(), f)); + CommandHandler h = CommandHandler.makeHandler(defaultCmdHandler.getName(), defaultCmdHandler.getParams(), + f); + if (h != null) { + f.setDefaultCommandHandler(h); + } } + HandlerEntry defaultMsgHandler = this.defaultMsgHandler; if (defaultMsgHandler != null) { - f.setDefaultMsgHandler( - MessageHandler.makeHandler(defaultMsgHandler.getName(), defaultMsgHandler.getParams(), f)); + MessageHandler h = MessageHandler.makeHandler(defaultMsgHandler.getName(), defaultMsgHandler.getParams(), + f); + if (h != null) { + f.setDefaultMsgHandler(h); + } } for (Entry mH : messageHandlers.entrySet()) { f.addMessageHandler(mH.getKey(), diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java index aafe924c1..c101e54f3 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java @@ -46,7 +46,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class InsteonDevice { private final Logger logger = LoggerFactory.getLogger(InsteonDevice.class); @@ -134,6 +133,7 @@ public class InsteonDevice { } public boolean hasProductKey(String key) { + String productKey = this.productKey; return productKey != null && productKey.equals(key); } @@ -275,7 +275,12 @@ public class InsteonDevice { mrequestQueue.add(e); } } - RequestQueueManager.instance().addQueue(this, now + delay); + RequestQueueManager instance = RequestQueueManager.instance(); + if (instance != null) { + instance.addQueue(this, now + delay); + } else { + logger.warn("request queue manager is null"); + } if (!l.isEmpty()) { lastTimePolled = now; @@ -440,6 +445,7 @@ public class InsteonDevice { if (mrequestQueue.isEmpty()) { return 0L; } + DeviceFeature featureQueried = this.featureQueried; if (featureQueried != null) { // A feature has been queried, but // the response has not been digested yet. @@ -453,6 +459,9 @@ public class InsteonDevice { } } QEntry qe = mrequestQueue.poll(); // take it off the queue! + if (qe == null) { + return 0L; + } if (!qe.getMsg().isBroadcast()) { logger.debug("qe taken off direct: {} {}", qe.getFeature(), qe.getMsg()); lastQueryTime = timeNow; @@ -505,14 +514,22 @@ public class InsteonDevice { m.setQuietTime(QUIET_TIME_DIRECT_MESSAGE); } logger.trace("enqueing direct message with delay {}", delay); - RequestQueueManager.instance().addQueue(this, now + delay); + RequestQueueManager instance = RequestQueueManager.instance(); + if (instance != null) { + instance.addQueue(this, now + delay); + } else { + logger.warn("request queue manger instance is null"); + } } private void writeMessage(Msg m) throws IOException { - driver.writeMessage(m); + Driver driver = this.driver; + if (driver != null) { + driver.writeMessage(m); + } } - private void instantiateFeatures(@Nullable DeviceType dt) { + private void instantiateFeatures(DeviceType dt) { for (Entry fe : dt.getFeatures().entrySet()) { DeviceFeature f = DeviceFeature.makeDeviceFeature(fe.getValue()); if (f == null) { @@ -596,7 +613,7 @@ public class InsteonDevice { * @param dt device type after which to model the device * @return newly created device */ - public static InsteonDevice makeDevice(@Nullable DeviceType dt) { + public static InsteonDevice makeDevice(DeviceType dt) { InsteonDevice dev = new InsteonDevice(); dev.instantiateFeatures(dt); return dev; @@ -607,7 +624,6 @@ public class InsteonDevice { * * @author Bernd Pfrommer - Initial contribution */ - @NonNullByDefault public static class QEntry implements Comparable { private DeviceFeature feature; private Msg msg; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java index b83dd75b5..1c7486aa5 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java @@ -31,7 +31,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public abstract class MessageDispatcher { private static final Logger logger = LoggerFactory.getLogger(MessageDispatcher.class); @@ -128,7 +127,6 @@ public abstract class MessageDispatcher { // // - @NonNullByDefault public static class DefaultDispatcher extends MessageDispatcher { DefaultDispatcher(DeviceFeature f) { super(f); @@ -194,7 +192,6 @@ public abstract class MessageDispatcher { } } - @NonNullByDefault public static class DefaultGroupDispatcher extends MessageDispatcher { DefaultGroupDispatcher(DeviceFeature f) { super(f); @@ -263,7 +260,6 @@ public abstract class MessageDispatcher { } } - @NonNullByDefault public static class PollGroupDispatcher extends MessageDispatcher { PollGroupDispatcher(DeviceFeature f) { super(f); @@ -290,7 +286,6 @@ public abstract class MessageDispatcher { } } - @NonNullByDefault public static class SimpleDispatcher extends MessageDispatcher { SimpleDispatcher(DeviceFeature f) { super(f); @@ -328,7 +323,6 @@ public abstract class MessageDispatcher { } } - @NonNullByDefault public static class X10Dispatcher extends MessageDispatcher { X10Dispatcher(DeviceFeature f) { super(f); @@ -355,7 +349,6 @@ public abstract class MessageDispatcher { } } - @NonNullByDefault public static class PassThroughDispatcher extends MessageDispatcher { PassThroughDispatcher(DeviceFeature f) { super(f); @@ -376,7 +369,6 @@ public abstract class MessageDispatcher { /** * Drop all incoming messages silently */ - @NonNullByDefault public static class NoOpDispatcher extends MessageDispatcher { NoOpDispatcher(DeviceFeature f) { super(f); @@ -404,6 +396,7 @@ public abstract class MessageDispatcher { Class c = Class.forName(cname); @SuppressWarnings("unchecked") Class dc = (Class) c; + @Nullable T ch = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f); ch.setParameters(params); return ch; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java index 625d4ad40..62e61c74f 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java @@ -50,7 +50,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public abstract class MessageHandler { private static final Logger logger = LoggerFactory.getLogger(MessageHandler.class); @@ -147,7 +146,8 @@ public abstract class MessageHandler { * @return value of parameter (or default if not found) */ protected @Nullable String getStringParameter(String key, @Nullable String def) { - return (parameters.get(key) == null ? def : parameters.get(key)); + String str = parameters.get(key); + return str != null ? str : def; } /** @@ -334,7 +334,6 @@ public abstract class MessageHandler { // // - @NonNullByDefault public static class DefaultMsgHandler extends MessageHandler { DefaultMsgHandler(DeviceFeature p) { super(p); @@ -346,7 +345,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class NoOpMsgHandler extends MessageHandler { NoOpMsgHandler(DeviceFeature p) { super(p); @@ -358,7 +356,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class LightOnDimmerHandler extends MessageHandler { LightOnDimmerHandler(DeviceFeature p) { super(p); @@ -388,7 +385,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class LightOffDimmerHandler extends MessageHandler { LightOffDimmerHandler(DeviceFeature p) { super(p); @@ -404,7 +400,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class LightOnSwitchHandler extends MessageHandler { LightOnSwitchHandler(DeviceFeature p) { super(p); @@ -422,7 +417,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class LightOffSwitchHandler extends MessageHandler { LightOffSwitchHandler(DeviceFeature p) { super(p); @@ -445,7 +439,6 @@ public abstract class MessageHandler { * handler and the command handler will need to be extended to support * those devices. */ - @NonNullByDefault public static class RampDimmerHandler extends MessageHandler { private int onCmd; private int offCmd; @@ -505,7 +498,6 @@ public abstract class MessageHandler { * else if command2 == 0x00 then the light has been turned off */ - @NonNullByDefault public static class SwitchRequestReplyHandler extends MessageHandler { SwitchRequestReplyHandler(DeviceFeature p) { super(p); @@ -573,7 +565,6 @@ public abstract class MessageHandler { * Handles Dimmer replies to status requests. * In the dimmers case the command2 byte represents the light level from 0-255 */ - @NonNullByDefault public static class DimmerRequestReplyHandler extends MessageHandler { DimmerRequestReplyHandler(DeviceFeature p) { super(p); @@ -609,7 +600,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class DimmerStopManualChangeHandler extends MessageHandler { DimmerStopManualChangeHandler(DeviceFeature p) { super(p); @@ -631,7 +621,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class StartManualChangeHandler extends MessageHandler { StartManualChangeHandler(DeviceFeature p) { super(p); @@ -658,7 +647,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class StopManualChangeHandler extends MessageHandler { StopManualChangeHandler(DeviceFeature p) { super(p); @@ -678,7 +666,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class InfoRequestReplyHandler extends MessageHandler { InfoRequestReplyHandler(DeviceFeature p) { super(p); @@ -714,7 +701,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class MotionSensorDataReplyHandler extends MessageHandler { MotionSensorDataReplyHandler(DeviceFeature p) { super(p); @@ -780,7 +766,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class MotionSensor2AlternateHeartbeatHandler extends MessageHandler { MotionSensor2AlternateHeartbeatHandler(DeviceFeature p) { super(p); @@ -792,6 +777,10 @@ public abstract class MessageHandler { try { // group 0x0B (11) - alternate heartbeat group InsteonAddress toAddr = msg.getAddr("toAddress"); + if (toAddr == null) { + logger.warn("toAddr is null"); + return; + } int batteryLevel = toAddr.getHighByte() & 0xff; int lightLevel = toAddr.getMiddleByte() & 0xff; int temperatureLevel = msg.getByte("command2") & 0xff; @@ -823,7 +812,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class HiddenDoorSensorDataReplyHandler extends MessageHandler { HiddenDoorSensorDataReplyHandler(DeviceFeature p) { super(p); @@ -859,7 +847,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class PowerMeterUpdateHandler extends MessageHandler { PowerMeterUpdateHandler(DeviceFeature p) { super(p); @@ -899,7 +886,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class PowerMeterResetHandler extends MessageHandler { PowerMeterResetHandler(DeviceFeature p) { super(p); @@ -918,7 +904,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class LastTimeHandler extends MessageHandler { LastTimeHandler(DeviceFeature p) { super(p); @@ -930,7 +915,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class ContactRequestReplyHandler extends MessageHandler { ContactRequestReplyHandler(DeviceFeature p) { super(p); @@ -955,7 +939,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class ClosedContactHandler extends MessageHandler { ClosedContactHandler(DeviceFeature p) { super(p); @@ -967,7 +950,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class OpenedContactHandler extends MessageHandler { OpenedContactHandler(DeviceFeature p) { super(p); @@ -979,7 +961,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class OpenedOrClosedContactHandler extends MessageHandler { OpenedOrClosedContactHandler(DeviceFeature p) { super(p); @@ -1020,7 +1001,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class ClosedSleepingContactHandler extends MessageHandler { ClosedSleepingContactHandler(DeviceFeature p) { super(p); @@ -1039,7 +1019,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class OpenedSleepingContactHandler extends MessageHandler { OpenedSleepingContactHandler(DeviceFeature p) { super(p); @@ -1066,7 +1045,6 @@ public abstract class MessageHandler { * Then connect this handler to the ACK, such that the device will be polled, and * the settings updated. */ - @NonNullByDefault public static class TriggerPollMsgHandler extends MessageHandler { TriggerPollMsgHandler(DeviceFeature p) { super(p); @@ -1081,7 +1059,6 @@ public abstract class MessageHandler { /** * Flexible handler to extract numerical data from messages. */ - @NonNullByDefault public static class NumberMsgHandler extends MessageHandler { NumberMsgHandler(DeviceFeature p) { super(p); @@ -1120,8 +1097,8 @@ public abstract class MessageHandler { } private int extractValue(Msg msg, int group) throws FieldException { - String lowByte = getStringParameter("low_byte", ""); - if (lowByte.equals("")) { + String lowByte = getStringParameter("low_byte", null); + if (lowByte == null) { logger.warn("{} handler misconfigured, missing low_byte!", nm()); return 0; } @@ -1131,8 +1108,8 @@ public abstract class MessageHandler { } else { value = msg.getByte(lowByte) & 0xFF; } - String highByte = getStringParameter("high_byte", ""); - if (!highByte.equals("")) { + String highByte = getStringParameter("high_byte", null); + if (highByte != null) { value |= (msg.getByte(highByte) & 0xFF) << 8; } return (value); @@ -1143,7 +1120,6 @@ public abstract class MessageHandler { * Convert system mode field to number 0...4. Insteon has two different * conventions for numbering, we use the one of the status update messages */ - @NonNullByDefault public static class ThermostatSystemModeMsgHandler extends NumberMsgHandler { ThermostatSystemModeMsgHandler(DeviceFeature p) { super(p); @@ -1172,7 +1148,6 @@ public abstract class MessageHandler { /** * Handle reply to system mode change command */ - @NonNullByDefault public static class ThermostatSystemModeReplyHandler extends NumberMsgHandler { ThermostatSystemModeReplyHandler(DeviceFeature p) { super(p); @@ -1201,7 +1176,6 @@ public abstract class MessageHandler { /** * Handle reply to fan mode change command */ - @NonNullByDefault public static class ThermostatFanModeReplyHandler extends NumberMsgHandler { ThermostatFanModeReplyHandler(DeviceFeature p) { super(p); @@ -1224,7 +1198,6 @@ public abstract class MessageHandler { /** * Handle reply to fanlinc fan speed change command */ - @NonNullByDefault public static class FanLincFanReplyHandler extends NumberMsgHandler { FanLincFanReplyHandler(DeviceFeature p) { super(p); @@ -1252,7 +1225,6 @@ public abstract class MessageHandler { * Process X10 messages that are generated when another controller * changes the state of an X10 device. */ - @NonNullByDefault public static class X10OnHandler extends MessageHandler { X10OnHandler(DeviceFeature p) { super(p); @@ -1266,7 +1238,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class X10OffHandler extends MessageHandler { X10OffHandler(DeviceFeature p) { super(p); @@ -1280,7 +1251,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class X10BrightHandler extends MessageHandler { X10BrightHandler(DeviceFeature p) { super(p); @@ -1293,7 +1263,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class X10DimHandler extends MessageHandler { X10DimHandler(DeviceFeature p) { super(p); @@ -1306,7 +1275,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class X10OpenHandler extends MessageHandler { X10OpenHandler(DeviceFeature p) { super(p); @@ -1320,7 +1288,6 @@ public abstract class MessageHandler { } } - @NonNullByDefault public static class X10ClosedHandler extends MessageHandler { X10ClosedHandler(DeviceFeature p) { super(p); @@ -1349,6 +1316,7 @@ public abstract class MessageHandler { Class c = Class.forName(cname); @SuppressWarnings("unchecked") Class dc = (Class) c; + @Nullable T mh = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f); mh.setParameters(params); return mh; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java index 0029dcb63..712e43031 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java @@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class ModemDBBuilder implements MsgListener { private static final int MESSAGE_TIMEOUT = 30000; @@ -65,8 +64,11 @@ public class ModemDBBuilder implements MsgListener { job = scheduler.scheduleWithFixedDelay(() -> { if (isComplete()) { logger.trace("modem db builder finished"); - job.cancel(false); - job = null; + ScheduledFuture job = this.job; + if (job != null) { + job.cancel(false); + } + this.job = null; } else { if (System.currentTimeMillis() - lastMessageTimestamp > MESSAGE_TIMEOUT) { String s = ""; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/PollHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/PollHandler.java index 14464b221..1f677c584 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/PollHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/PollHandler.java @@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public abstract class PollHandler { private static final Logger logger = LoggerFactory.getLogger(PollHandler.class); DeviceFeature feature; @@ -87,7 +86,6 @@ public abstract class PollHandler { * most query messages. Provide the suitable parameters in * the device features file. */ - @NonNullByDefault public static class FlexPollHandler extends PollHandler { FlexPollHandler(DeviceFeature f) { super(f); @@ -124,7 +122,6 @@ public abstract class PollHandler { } } - @NonNullByDefault public static class NoPollHandler extends PollHandler { NoPollHandler(DeviceFeature f) { super(f); @@ -144,12 +141,13 @@ public abstract class PollHandler { * @return the handler which was created */ @Nullable - public static T makeHandler(@Nullable HandlerEntry ph, DeviceFeature f) { + public static T makeHandler(HandlerEntry ph, DeviceFeature f) { String cname = PollHandler.class.getName() + "$" + ph.getName(); try { Class c = Class.forName(cname); @SuppressWarnings("unchecked") Class dc = (Class) c; + @Nullable T phc = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f); phc.setParameters(ph.getParams()); return phc; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/RequestQueueManager.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/RequestQueueManager.java index 4b9f29ff0..0d2dfbb7c 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/RequestQueueManager.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/RequestQueueManager.java @@ -15,6 +15,7 @@ package org.openhab.binding.insteon.internal.device; import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; +import java.util.Queue; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -36,20 +37,25 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class RequestQueueManager { private static @Nullable RequestQueueManager instance = null; private final Logger logger = LoggerFactory.getLogger(RequestQueueManager.class); private @Nullable Thread queueThread = null; - private PriorityQueue requestQueues = new PriorityQueue<>(); + private Queue requestQueues = new PriorityQueue<>(); private Map requestQueueHash = new HashMap<>(); private boolean keepRunning = true; private RequestQueueManager() { queueThread = new Thread(new RequestQueueReader()); - queueThread.setName("Insteon Request Queue Reader"); - queueThread.setDaemon(true); - queueThread.start(); + setParamsAndStart(queueThread); + } + + private void setParamsAndStart(@Nullable Thread thread) { + if (thread != null) { + thread.setName("Insteon Request Queue Reader"); + thread.setDaemon(true); + thread.start(); + } } /** @@ -90,6 +96,7 @@ public class RequestQueueManager { */ private void stopThread() { logger.debug("stopping thread"); + Thread queueThread = this.queueThread; if (queueThread != null) { synchronized (requestQueues) { keepRunning = false; @@ -102,11 +109,10 @@ public class RequestQueueManager { } catch (InterruptedException e) { logger.warn("got interrupted waiting for thread exit ", e); } - queueThread = null; + this.queueThread = null; } } - @NonNullByDefault class RequestQueueReader implements Runnable { @Override public void run() { @@ -114,8 +120,8 @@ public class RequestQueueManager { synchronized (requestQueues) { while (keepRunning) { try { - while (keepRunning && !requestQueues.isEmpty()) { - RequestQueue q = requestQueues.peek(); + RequestQueue q; + while (keepRunning && (q = requestQueues.peek()) != null) { long now = System.currentTimeMillis(); long expTime = q.getExpirationTime(); InsteonDevice dev = q.getDevice(); @@ -161,7 +167,6 @@ public class RequestQueueManager { } } - @NonNullByDefault public static class RequestQueue implements Comparable { private InsteonDevice device; private long expirationTime; @@ -189,18 +194,18 @@ public class RequestQueueManager { } } - @NonNullByDefault public static synchronized @Nullable RequestQueueManager instance() { if (instance == null) { instance = new RequestQueueManager(); } - return (instance); + return instance; } public static synchronized void destroyInstance() { + RequestQueueManager instance = RequestQueueManager.instance; if (instance != null) { instance.stopThread(); - instance = null; + RequestQueueManager.instance = null; } } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/X10.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/X10.java index 90b8317fb..3b7af60e5 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/X10.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/X10.java @@ -17,7 +17,6 @@ import java.util.Map; import java.util.Map.Entry; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; /** * This class has utilities related to the X10 protocol. @@ -26,7 +25,6 @@ import org.eclipse.jdt.annotation.Nullable; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class X10 { /** * Enumerates the X10 command codes. @@ -120,8 +118,12 @@ public class X10 { * @return coded house byte */ public static int houseStringToCode(String s) { - Integer i = findKey(houseCodeToString, s); - return (i == null) ? 0xf : i; + for (Entry entry : houseCodeToString.entrySet()) { + if (s.equals(entry.getValue())) { + return entry.getKey(); + } + } + return 0xf; } /** @@ -132,23 +134,17 @@ public class X10 { */ public static int unitStringToCode(String s) { try { - Integer key = Integer.parseInt(s); - Integer i = findKey(unitCodeToInt, key); - return i; + int i = Integer.parseInt(s); + for (Entry entry : unitCodeToInt.entrySet()) { + if (i == entry.getValue()) { + return entry.getKey(); + } + } } catch (NumberFormatException e) { } return 0xf; } - private static @Nullable T findKey(Map map, E value) { - for (Entry entry : map.entrySet()) { - if (value.equals(entry.getValue())) { - return entry.getKey(); - } - } - return null; - } - /** * Map between 4-bit X10 code and the house code. */ diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java index 34fc953ce..1ad378107 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java @@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public abstract class IOStream { private static final Logger logger = LoggerFactory.getLogger(IOStream.class); protected @Nullable InputStream in = null; @@ -59,7 +58,12 @@ public abstract class IOStream { public int read(byte[] b, int offset, int readSize) throws InterruptedException, IOException { int len = 0; while (!stopped && len < 1) { - len = in.read(b, offset, readSize); + InputStream in = this.in; + if (in != null) { + len = in.read(b, offset, readSize); + } else { + throw new IOException("in is null"); + } if (len == -1) { throw new EOFException(); } @@ -77,7 +81,12 @@ public abstract class IOStream { * @param b byte array to write */ public void write(byte @Nullable [] b) throws IOException { - out.write(b); + OutputStream out = this.out; + if (out != null) { + out.write(b); + } else { + throw new IOException("out is null"); + } } /** @@ -156,7 +165,6 @@ public abstract class IOStream { return new TcpIOStream(hp.host, hp.port); } - @NonNullByDefault private static class HostPort { public String host = "localhost"; public int port = -1; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java index e675f1c83..ba44bd5b8 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java @@ -41,7 +41,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class Poller { private static final long MIN_MSEC_BETWEEN_POLLS = 2000L; @@ -107,9 +106,15 @@ public class Poller { public void start() { if (pollThread == null) { pollThread = new Thread(new PollQueueReader()); - pollThread.setName("Insteon Poll Queue Reader"); - pollThread.setDaemon(true); - pollThread.start(); + setParamsAndStart(pollThread); + } + } + + private void setParamsAndStart(@Nullable Thread thread) { + if (thread != null) { + thread.setName("Insteon Poll Queue Reader"); + thread.setDaemon(true); + thread.start(); } } @@ -124,9 +129,10 @@ public class Poller { pollQueue.notify(); } try { + Thread pollThread = this.pollThread; if (pollThread != null) { pollThread.join(); - pollThread = null; + this.pollThread = null; } keepRunning = true; } catch (InterruptedException e) { @@ -194,7 +200,6 @@ public class Poller { return expTime; } - @NonNullByDefault private class PollQueueReader implements Runnable { @Override public void run() { @@ -246,9 +251,14 @@ public class Poller { * @param now the current time */ private void processQueue(long now) { - PQEntry pqe = pollQueue.pollFirst(); - pqe.getDevice().doPoll(0); - addToPollQueue(pqe.getDevice(), now + pqe.getDevice().getPollInterval()); + processQueue(now, pollQueue.pollFirst()); + } + + private void processQueue(long now, @Nullable PQEntry pqe) { + if (pqe != null) { + pqe.getDevice().doPoll(0); + addToPollQueue(pqe.getDevice(), now + pqe.getDevice().getPollInterval()); + } } } @@ -259,7 +269,6 @@ public class Poller { * @author Bernd Pfrommer - Initial contribution * */ - @NonNullByDefault private static class PQEntry implements Comparable { private InsteonDevice dev; private long expirationTime; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java index f803183e2..86c09adfe 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java @@ -15,7 +15,7 @@ package org.openhab.binding.insteon.internal.driver; import java.io.IOException; import java.util.ArrayList; import java.util.Map; -import java.util.Random; +import java.util.Map.Entry; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicBoolean; @@ -57,7 +57,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class Port { private final Logger logger = LoggerFactory.getLogger(Port.class); @@ -153,9 +152,9 @@ public class Port { public void clearModemDB() { logger.debug("clearing modem db!"); Map dbes = getDriver().lockModemDBEntries(); - for (InsteonAddress addr : dbes.keySet()) { - if (!dbes.get(addr).isModem()) { - dbes.remove(addr); + for (Entry entry : dbes.entrySet()) { + if (!entry.getValue().isModem()) { + dbes.remove(entry.getKey()); } } getDriver().unlockModemDBEntries(); @@ -178,13 +177,9 @@ public class Port { } ioStream.start(); readThread = new Thread(reader); - readThread.setName("Insteon " + logName + " Reader"); - readThread.setDaemon(true); - readThread.start(); + setParamsAndStart(readThread, "Reader"); writeThread = new Thread(writer); - writeThread.setName("Insteon " + logName + " Writer"); - writeThread.setDaemon(true); - writeThread.start(); + setParamsAndStart(writeThread, "Writer"); if (!mdbb.isComplete()) { modem.initialize(); @@ -195,6 +190,14 @@ public class Port { disconnected.set(false); } + private void setParamsAndStart(@Nullable Thread thread, String type) { + if (thread != null) { + thread.setName("Insteon " + logName + " " + type); + thread.setDaemon(true); + thread.start(); + } + } + /** * Stops all threads */ @@ -208,9 +211,11 @@ public class Port { ioStream.stop(); ioStream.close(); + Thread readThread = this.readThread; if (readThread != null) { readThread.interrupt(); } + Thread writeThread = this.writeThread; if (writeThread != null) { writeThread.interrupt(); } @@ -230,8 +235,8 @@ public class Port { } catch (InterruptedException e) { logger.debug("got interrupted waiting for write thread to exit."); } - readThread = null; - writeThread = null; + this.readThread = null; + this.writeThread = null; logger.debug("all threads for port {} stopped.", logName); } @@ -286,12 +291,10 @@ public class Port { * * @author Bernd Pfrommer - Initial contribution */ - @NonNullByDefault class IOStreamReader implements Runnable { private ReplyType reply = ReplyType.GOT_ACK; private Object replyLock = new Object(); - private boolean dropRandomBytes = false; // set to true for fault injection /** * Helper function for implementing synchronization between reader and writer @@ -306,12 +309,8 @@ public class Port { public void run() { logger.debug("starting reader..."); byte[] buffer = new byte[2 * readSize]; - Random rng = new Random(); try { for (int len = -1; (len = ioStream.read(buffer, 0, readSize)) > 0;) { - if (dropRandomBytes && rng.nextInt(100) < 20) { - len = dropBytes(buffer, len); - } msgFactory.addData(buffer, len); processMessages(); } @@ -365,29 +364,6 @@ public class Port { } } - /** - * Drops bytes randomly from buffer to simulate errors seen - * from the InsteonHub using the raw interface - * - * @param buffer byte buffer from which to drop bytes - * @param len original number of valid bytes in buffer - * @return length of byte buffer after dropping from it - */ - private int dropBytes(byte[] buffer, int len) { - final int dropRate = 2; // in percent - Random rng = new Random(); - ArrayList l = new ArrayList<>(); - for (int i = 0; i < len; i++) { - if (rng.nextInt(100) >= dropRate) { - l.add(buffer[i]); - } - } - for (int i = 0; i < l.size(); i++) { - buffer[i] = l.get(i); - } - return (l.size()); - } - @SuppressWarnings("unchecked") private void toAllListeners(Msg msg) { // When we deliver the message, the recipient @@ -442,7 +418,6 @@ public class Port { * * @author Bernd Pfrommer - Initial contribution */ - @NonNullByDefault class IOStreamWriter implements Runnable { private static final int WAIT_TIME = 200; // milliseconds @@ -492,11 +467,11 @@ public class Port { /** * Class to get info about the modem */ - @NonNullByDefault class Modem implements MsgListener { private @Nullable InsteonDevice device = null; InsteonAddress getAddress() { + InsteonDevice device = this.device; return (device == null) ? new InsteonAddress() : (device.getAddress()); } @@ -514,18 +489,19 @@ public class Port { if (msg.getByte("Cmd") == 0x60) { // add the modem to the device list InsteonAddress a = new InsteonAddress(msg.getAddress("IMAddress")); - DeviceType dt = DeviceTypeLoader.instance().getDeviceType(InsteonDeviceHandler.PLM_PRODUCT_KEY); - if (dt == null) { - logger.warn("unknown modem product key: {} for modem: {}.", - InsteonDeviceHandler.PLM_PRODUCT_KEY, a); + DeviceTypeLoader instance = DeviceTypeLoader.instance(); + if (instance != null) { + DeviceType dt = instance.getDeviceType(InsteonDeviceHandler.PLM_PRODUCT_KEY); + if (dt == null) { + logger.warn("unknown modem product key: {} for modem: {}.", + InsteonDeviceHandler.PLM_PRODUCT_KEY, a); + } else { + device = InsteonDevice.makeDevice(dt); + initDevice(a, device); + mdbb.updateModemDB(a, Port.this, null, true); + } } else { - device = InsteonDevice.makeDevice(dt); - device.setAddress(a); - device.setProductKey(InsteonDeviceHandler.PLM_PRODUCT_KEY); - device.setDriver(driver); - device.setIsModem(true); - logger.debug("found modem {} in device_types: {}", a, device.toString()); - mdbb.updateModemDB(a, Port.this, null, true); + logger.warn("device type loader instance is null"); } // can unsubscribe now removeListener(this); @@ -535,6 +511,18 @@ public class Port { } } + private void initDevice(InsteonAddress a, @Nullable InsteonDevice device) { + if (device != null) { + device.setAddress(a); + device.setProductKey(InsteonDeviceHandler.PLM_PRODUCT_KEY); + device.setDriver(driver); + device.setIsModem(true); + logger.debug("found modem {} in device_types: {}", a, device.toString()); + } else { + logger.warn("device is null"); + } + } + public void initialize() { try { Msg m = Msg.makeMessage("GetIMInfo"); diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/SerialIOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/SerialIOStream.java index e417a2836..7965f119f 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/SerialIOStream.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/SerialIOStream.java @@ -13,6 +13,8 @@ package org.openhab.binding.insteon.internal.driver; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -32,7 +34,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class SerialIOStream extends IOStream { private final Logger logger = LoggerFactory.getLogger(SerialIOStream.class); private @Nullable SerialPort port = null; @@ -82,6 +83,11 @@ public class SerialIOStream extends IOStream { } try { + SerialPortManager serialPortManager = this.serialPortManager; + if (serialPortManager == null) { + logger.warn("serial port manager is null."); + return false; + } SerialPortIdentifier spi = serialPortManager.getIdentifier(devName); if (spi == null) { logger.warn("{} is not a valid serial port.", devName); @@ -89,13 +95,7 @@ public class SerialIOStream extends IOStream { } port = spi.open(appName, 1000); - port.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); - logger.debug("setting {} baud rate to {}", devName, baudRate); - port.enableReceiveThreshold(1); - port.enableReceiveTimeout(1000); - in = port.getInputStream(); - out = port.getOutputStream(); + open(port); logger.debug("successfully opened port {}", devName); return true; } catch (IOException e) { @@ -109,29 +109,46 @@ public class SerialIOStream extends IOStream { return false; } + private void open(@Nullable SerialPort port) throws UnsupportedCommOperationException, IOException { + if (port != null) { + port.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); + logger.debug("setting {} baud rate to {}", devName, baudRate); + port.enableReceiveThreshold(1); + port.enableReceiveTimeout(1000); + in = port.getInputStream(); + out = port.getOutputStream(); + } else { + logger.warn("port is null"); + } + } + @Override public void close() { + InputStream in = this.in; if (in != null) { try { in.close(); } catch (IOException e) { logger.warn("failed to close input stream", e); } - in = null; + this.in = null; } + OutputStream out = this.out; if (out != null) { try { out.close(); } catch (IOException e) { logger.warn("failed to close output stream", e); } - out = null; + this.out = null; } + SerialPort port = this.port; if (port != null) { port.close(); - port = null; + this.port = null; } } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java index 792e449d0..fa9e91d3e 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java @@ -13,6 +13,8 @@ package org.openhab.binding.insteon.internal.driver; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; @@ -30,7 +32,6 @@ import org.slf4j.LoggerFactory; * */ @NonNullByDefault -@SuppressWarnings("null") public class TcpIOStream extends IOStream { private final Logger logger = LoggerFactory.getLogger(TcpIOStream.class); @@ -57,8 +58,7 @@ public class TcpIOStream extends IOStream { } try { socket = new Socket(host, port); - in = socket.getInputStream(); - out = socket.getOutputStream(); + open(socket); } catch (UnknownHostException e) { logger.warn("unknown host name: {}", host); return (false); @@ -69,33 +69,43 @@ public class TcpIOStream extends IOStream { return true; } + private void open(@Nullable Socket socket) throws IOException { + if (socket != null) { + in = socket.getInputStream(); + out = socket.getOutputStream(); + } + } + @Override public void close() { + InputStream in = this.in; if (in != null) { try { in.close(); } catch (IOException e) { logger.warn("failed to close input stream", e); } - in = null; + this.in = null; } + OutputStream out = this.out; if (out != null) { try { out.close(); } catch (IOException e) { logger.warn("failed to close output stream", e); } - out = null; + this.out = null; } + Socket socket = this.socket; if (socket != null) { try { socket.close(); } catch (IOException e) { logger.warn("failed to close the socket", e); } - socket = null; + this.socket = null; } } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java index ad8d0cd9d..83b3f7a60 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java @@ -37,7 +37,6 @@ import org.slf4j.LoggerFactory; * */ @NonNullByDefault -@SuppressWarnings("null") public class HubIOStream extends IOStream implements Runnable { private final Logger logger = LoggerFactory.getLogger(HubIOStream.class); @@ -96,13 +95,19 @@ public class HubIOStream extends IOStream implements Runnable { polling = true; pollThread = new Thread(this); - pollThread.setName("Insteon Hub Poller"); - pollThread.setDaemon(true); - pollThread.start(); + setParamsAndStart(pollThread); return true; } + private void setParamsAndStart(@Nullable Thread thread) { + if (thread != null) { + thread.setName("Insteon Hub Poller"); + thread.setDaemon(true); + thread.start(); + } + } + @Override public void close() { polling = false; @@ -111,22 +116,24 @@ public class HubIOStream extends IOStream implements Runnable { pollThread = null; } + InputStream in = this.in; if (in != null) { try { in.close(); } catch (IOException e) { logger.warn("failed to close input stream", e); } - in = null; + this.in = null; } + OutputStream out = this.out; if (out != null) { try { out.close(); } catch (IOException e) { logger.warn("failed to close output stream", e); } - out = null; + this.out = null; } } @@ -235,7 +242,12 @@ public class HubIOStream extends IOStream implements Runnable { } if (msg.length() != 0) { ByteBuffer buf = ByteBuffer.wrap(hexStringToByteArray(msg.toString())); - ((HubInputStream) in).handle(buf); + InputStream in = this.in; + if (in != null) { + ((HubInputStream) in).handle(buf); + } else { + logger.warn("in is null"); + } } bufferIdx = nIdx; } @@ -344,7 +356,6 @@ public class HubIOStream extends IOStream implements Runnable { * @author Daniel Pfrommer - Initial contribution * */ - @NonNullByDefault public class HubInputStream extends InputStream { // A buffer to keep bytes while we are waiting for the inputstream to read @@ -381,7 +392,6 @@ public class HubIOStream extends IOStream implements Runnable { * @author Daniel Pfrommer - Initial contribution * */ - @NonNullByDefault public class HubOutputStream extends OutputStream { private ByteArrayOutputStream out = new ByteArrayOutputStream(); diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonDeviceHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonDeviceHandler.java index 7cca65d20..d1505fb0a 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonDeviceHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonDeviceHandler.java @@ -34,12 +34,14 @@ import org.openhab.binding.insteon.internal.device.DeviceFeature; import org.openhab.binding.insteon.internal.device.DeviceTypeLoader; import org.openhab.binding.insteon.internal.device.InsteonAddress; import org.openhab.binding.insteon.internal.device.InsteonDevice; +import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.thing.binding.ThingHandlerCallback; import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.slf4j.Logger; @@ -56,7 +58,6 @@ import com.google.gson.reflect.TypeToken; * @author Rob Nielsen - Initial contribution */ @NonNullByDefault -@SuppressWarnings("null") public class InsteonDeviceHandler extends BaseThingHandler { private static final Set ALL_CHANNEL_IDS = Collections.unmodifiableSet(Stream.of( @@ -142,6 +143,14 @@ public class InsteonDeviceHandler extends BaseThingHandler { return; } + InsteonDeviceConfiguration config = this.config; + if (config == null) { + String msg = "Insteon device configuration is null."; + logger.warn("{} {}", thing.getUID().getAsString(), msg); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + return; + } String address = config.getAddress(); if (!InsteonAddress.isValid(address)) { String msg = "Unable to start Insteon device, the insteon or X10 address '" + address @@ -152,8 +161,17 @@ public class InsteonDeviceHandler extends BaseThingHandler { return; } + DeviceTypeLoader instance = DeviceTypeLoader.instance(); + if (instance == null) { + String msg = "Device type loader is null."; + logger.warn("{} {}", thing.getUID().getAsString(), msg); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + return; + } + String productKey = config.getProductKey(); - if (DeviceTypeLoader.instance().getDeviceType(productKey) == null) { + if (instance.getDeviceType(productKey) == null) { String msg = "Unable to start Insteon device, invalid product key '" + productKey + "'."; logger.warn("{} {}", thing.getUID().getAsString(), msg); @@ -190,6 +208,23 @@ public class InsteonDeviceHandler extends BaseThingHandler { } InsteonDevice device = insteonBinding.makeNewDevice(insteonAddress, productKey, deviceConfigMap); + if (device == null) { + String msg = "Unable to create a device with the product key '" + productKey + "' with the address'" + + address + "'."; + logger.warn("{} {}", thing.getUID().getAsString(), msg); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + return; + } + + ThingHandlerCallback callback = getCallback(); + if (callback == null) { + String msg = "Unable to get thing handler callback."; + logger.warn("{} {}", thing.getUID().getAsString(), msg); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + return; + } StringBuilder channelList = new StringBuilder(); List channels = new ArrayList<>(); @@ -256,7 +291,7 @@ public class InsteonDeviceHandler extends BaseThingHandler { ChannelTypeUID channelTypeUID = new ChannelTypeUID( InsteonBindingConstants.BINDING_ID, InsteonBindingConstants.SWITCH); - Channel channel = getCallback() + Channel channel = callback .createChannelBuilder(channelUID, channelTypeUID).withLabel(id) .build(); @@ -285,7 +320,7 @@ public class InsteonDeviceHandler extends BaseThingHandler { channelId); Channel channel = thing.getChannel(channelUID); if (channel == null) { - channel = getCallback().createChannelBuilder(channelUID, channelTypeUID).build(); + channel = callback.createChannelBuilder(channelUID, channelTypeUID).build(); } addChannel(channel, channelId, channels, channelList); @@ -343,15 +378,18 @@ public class InsteonDeviceHandler extends BaseThingHandler { @Override public void dispose() { - String address = config.getAddress(); - if (getBridge() != null && InsteonAddress.isValid(address)) { - getInsteonBinding().removeDevice(new InsteonAddress(address)); + InsteonDeviceConfiguration config = this.config; + if (config != null) { + String address = config.getAddress(); + if (getBridge() != null && InsteonAddress.isValid(address)) { + getInsteonBinding().removeDevice(new InsteonAddress(address)); - logger.debug("removed {} address = {}", getThing().getUID().getAsString(), address); + logger.debug("removed {} address = {}", getThing().getUID().getAsString(), address); + } + + getInsteonNetworkHandler().disposed(getThing().getUID()); } - getInsteonNetworkHandler().disposed(getThing().getUID()); - super.dispose(); } @@ -370,6 +408,10 @@ public class InsteonDeviceHandler extends BaseThingHandler { Map params = new HashMap<>(); Channel channel = getThing().getChannel(channelUID.getId()); + if (channel == null) { + logger.warn("channel is null"); + return; + } Map channelProperties = channel.getConfiguration().getProperties(); for (String key : channelProperties.keySet()) { @@ -381,11 +423,16 @@ public class InsteonDeviceHandler extends BaseThingHandler { params.put(key, s); } else { logger.warn("not a string or big decimal value key '{}' value '{}' {}", key, value, - value.getClass().getName()); + value != null ? value.getClass().getName() : "unknown"); } } String feature = channelUID.getId().toLowerCase(); + InsteonDeviceConfiguration config = this.config; + if (config == null) { + logger.warn("insteon device config is null"); + return; + } String productKey = config.getProductKey(); if (productKey.equals(HIDDEN_DOOR_SENSOR_PRODUCT_KEY)) { if (feature.equalsIgnoreCase(InsteonBindingConstants.BATTERY_LEVEL)) { @@ -461,11 +508,19 @@ public class InsteonDeviceHandler extends BaseThingHandler { logger.debug("channel {} unlinked ", channelUID.getAsString()); } - private @Nullable InsteonNetworkHandler getInsteonNetworkHandler() { - return (InsteonNetworkHandler) getBridge().getHandler(); + private InsteonNetworkHandler getInsteonNetworkHandler() { + Bridge bridge = getBridge(); + if (bridge == null) { + throw new IllegalArgumentException("insteon network bridge is null"); + } + InsteonNetworkHandler handler = (InsteonNetworkHandler) bridge.getHandler(); + if (handler == null) { + throw new IllegalArgumentException("insteon network handler is null"); + } + return handler; } - private @Nullable InsteonBinding getInsteonBinding() { + private InsteonBinding getInsteonBinding() { return getInsteonNetworkHandler().getInsteonBinding(); } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java index 25b716360..3f9d18880 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java @@ -45,7 +45,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Initial contribution */ @NonNullByDefault -@SuppressWarnings("null") public class InsteonNetworkHandler extends BaseBridgeHandler { private static final int LOG_DEVICE_STATISTICS_DELAY_IN_SECONDS = 600; private static final int RETRY_DELAY_IN_SECONDS = 30; @@ -82,6 +81,23 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { updateStatus(ThingStatus.UNKNOWN); scheduler.execute(() -> { + InsteonNetworkConfiguration config = this.config; + if (config == null) { + String msg = "Initialization failed, configuration is null."; + logger.warn(msg); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + return; + } + SerialPortManager serialPortManager = this.serialPortManager; + if (serialPortManager == null) { + String msg = "Initialization failed, serial port manager is null."; + logger.warn(msg); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + + return; + } insteonBinding = new InsteonBinding(this, config, serialPortManager, scheduler); // hold off on starting to poll until devices that already are defined as things are added. @@ -91,7 +107,8 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { // check to see if it has been at least SETTLE_TIME_IN_SECONDS since last device was created if (System.currentTimeMillis() - lastInsteonDeviceCreatedTimestamp > SETTLE_TIME_IN_SECONDS * 1000) { // settle time has expired start polling - if (insteonBinding.startPolling()) { + InsteonBinding insteonBinding = this.insteonBinding; + if (insteonBinding != null && insteonBinding.startPolling()) { pollingJob = scheduler.scheduleWithFixedDelay(() -> { insteonBinding.logDeviceStatistics(); }, 0, LOG_DEVICE_STATISTICS_DELAY_IN_SECONDS, TimeUnit.SECONDS); @@ -107,8 +124,11 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); } - settleJob.cancel(false); - settleJob = null; + ScheduledFuture settleJob = this.settleJob; + if (settleJob != null) { + settleJob.cancel(false); + } + this.settleJob = null; } }, SETTLE_TIME_IN_SECONDS, 1, TimeUnit.SECONDS); }); @@ -118,24 +138,28 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { public void dispose() { logger.debug("Shutting down Insteon bridge"); + ScheduledFuture pollingJob = this.pollingJob; if (pollingJob != null) { pollingJob.cancel(true); - pollingJob = null; + this.pollingJob = null; } + ScheduledFuture reconnectJob = this.reconnectJob; if (reconnectJob != null) { reconnectJob.cancel(true); - reconnectJob = null; + this.reconnectJob = null; } + ScheduledFuture settleJob = this.settleJob; if (settleJob != null) { settleJob.cancel(true); - settleJob = null; + this.settleJob = null; } + InsteonBinding insteonBinding = this.insteonBinding; if (insteonBinding != null) { insteonBinding.shutdown(); - insteonBinding = null; + this.insteonBinding = null; } deviceInfo.clear(); @@ -151,10 +175,14 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { public void bindingDisconnected() { reconnectJob = scheduler.scheduleWithFixedDelay(() -> { - if (insteonBinding.reconnect()) { + InsteonBinding insteonBinding = this.insteonBinding; + if (insteonBinding != null && insteonBinding.reconnect()) { updateStatus(ThingStatus.ONLINE); - reconnectJob.cancel(false); - reconnectJob = null; + ScheduledFuture reconnectJob = this.reconnectJob; + if (reconnectJob != null) { + reconnectJob.cancel(false); + } + this.reconnectJob = null; } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port disconnected."); } @@ -165,8 +193,13 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { lastInsteonDeviceCreatedTimestamp = System.currentTimeMillis(); } - public @Nullable InsteonBinding getInsteonBinding() { - return insteonBinding; + public InsteonBinding getInsteonBinding() { + InsteonBinding insteonBinding = this.insteonBinding; + if (insteonBinding != null) { + return insteonBinding; + } else { + throw new IllegalArgumentException("insteon binding is null"); + } } public void setInsteonDeviceDiscoveryService(InsteonDeviceDiscoveryService insteonDeviceDiscoveryService) { @@ -175,7 +208,10 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { public void addMissingDevices(List missing) { scheduler.execute(() -> { - insteonDeviceDiscoveryService.addInsteonDevices(missing, getThing().getUID()); + InsteonDeviceDiscoveryService insteonDeviceDiscoveryService = this.insteonDeviceDiscoveryService; + if (insteonDeviceDiscoveryService != null) { + insteonDeviceDiscoveryService.addInsteonDevices(missing, getThing().getUID()); + } }); } @@ -188,9 +224,12 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { } public void displayLocalDatabase(Console console) { - Map databaseInfo = insteonBinding.getDatabaseInfo(); - console.println("local database contains " + databaseInfo.size() + " entries"); - display(console, databaseInfo); + InsteonBinding insteonBinding = this.insteonBinding; + if (insteonBinding != null) { + Map databaseInfo = insteonBinding.getDatabaseInfo(); + console.println("local database contains " + databaseInfo.size() + " entries"); + display(console, databaseInfo); + } } public void initialized(ThingUID uid, String msg) { diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/DataType.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/DataType.java index 4b2315c44..56ccbed72 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/DataType.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/DataType.java @@ -13,9 +13,9 @@ package org.openhab.binding.insteon.internal.message; import java.util.HashMap; +import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; /** * Defines the data types that can be used in the fields of a message. @@ -31,10 +31,10 @@ public enum DataType { ADDRESS("address", 3), INVALID("INVALID", -1); - private static HashMap typeMap = new HashMap<>(); + private static Map typeMap = new HashMap<>(); - private int size = -1; // number of bytes consumed - private String name = ""; + private int size; + private String name; static { typeMap.put(BYTE.getName(), BYTE); @@ -74,7 +74,12 @@ public enum DataType { * @param name the string to translate to a type * @return the data type corresponding to the name string, or null if not found */ - public static @Nullable DataType getDataType(String name) { - return typeMap.get(name); + public static DataType getDataType(String name) { + DataType dataType = typeMap.get(name); + if (dataType != null) { + return dataType; + } else { + throw new IllegalArgumentException("Unable to find data type for " + name); + } } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Field.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Field.java index 3197a2163..db68b44f9 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Field.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Field.java @@ -28,11 +28,10 @@ import org.openhab.binding.insteon.internal.utils.Utils; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public final class Field { private final String name; private final int offset; - private final @Nullable DataType type; + private final DataType type; public String getName() { return name; @@ -42,11 +41,11 @@ public final class Field { return offset; } - public @Nullable DataType getType() { + public DataType getType() { return type; } - public Field(String name, @Nullable DataType type, int off) { + public Field(String name, DataType type, int off) { this.name = name; this.type = type; this.offset = off; @@ -74,7 +73,7 @@ public final class Field { return getName() + " Type: " + getType() + " Offset " + getOffset(); } - public String toString(byte @Nullable [] array) { + public String toString(byte[] array) { String s = name + ":"; try { switch (type) { @@ -96,7 +95,7 @@ public final class Field { return s; } - public void set(byte @Nullable [] array, Object o) throws FieldException { + public void set(byte[] array, Object o) throws FieldException { switch (getType()) { case BYTE: setByte(array, (Byte) o); @@ -121,7 +120,7 @@ public final class Field { * @param b the value you want to set the byte to * @throws FieldException */ - public void setByte(byte @Nullable [] array, byte b) throws FieldException { + public void setByte(byte[] array, byte b) throws FieldException { check(array.length, DataType.BYTE); array[offset] = b; } @@ -133,7 +132,7 @@ public final class Field { * @param array the destination array * @param i the integer value to set */ - public void setInt(byte @Nullable [] array, int i) throws FieldException { + public void setInt(byte[] array, int i) throws FieldException { check(array.length, DataType.INT); array[offset] = (byte) ((i >>> 24) & 0xFF); array[offset + 1] = (byte) ((i >>> 16) & 0xFF); @@ -149,7 +148,7 @@ public final class Field { * @param adr the insteon address value to set */ - public void setAddress(byte @Nullable [] array, InsteonAddress adr) throws FieldException { + public void setAddress(byte[] array, InsteonAddress adr) throws FieldException { check(array.length, DataType.ADDRESS); adr.storeBytes(array, offset); } @@ -160,7 +159,7 @@ public final class Field { * @param array the array to fetch from * @return the byte value of the field */ - public byte getByte(byte @Nullable [] array) throws FieldException { + public byte getByte(byte[] array) throws FieldException { check(array.length, DataType.BYTE); return array[offset]; } @@ -171,7 +170,7 @@ public final class Field { * @param array the array to fetch from * @return the int value of the field */ - public int getInt(byte @Nullable [] array) throws FieldException { + public int getInt(byte[] array) throws FieldException { check(array.length, DataType.INT); byte b1 = array[offset]; byte b2 = array[offset + 1]; @@ -188,7 +187,7 @@ public final class Field { * @return the address */ - public InsteonAddress getAddress(byte @Nullable [] array) throws FieldException { + public InsteonAddress getAddress(byte[] array) throws FieldException { check(array.length, DataType.ADDRESS); InsteonAddress adr = new InsteonAddress(); adr.loadBytes(array, offset); diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Msg.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Msg.java index 4e8f834f8..9185af7f8 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Msg.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/Msg.java @@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class Msg { private static final Logger logger = LoggerFactory.getLogger(Msg.class); @@ -51,7 +50,7 @@ public class Msg { TO_MODEM("TO_MODEM"), FROM_MODEM("FROM_MODEM"); - private static HashMap map = new HashMap<>(); + private static Map map = new HashMap<>(); private String directionString; @@ -69,7 +68,12 @@ public class Msg { } public static Direction getDirectionFromString(String dir) { - return map.get(dir); + Direction direction = map.get(dir); + if (direction != null) { + return direction; + } else { + throw new IllegalArgumentException("Unable to find direction for " + dir); + } } } @@ -81,7 +85,7 @@ public class Msg { private static final Map REPLY_MAP = new HashMap<>(); private int headerLength = -1; - private byte @Nullable [] data = null; + private byte[] data; private MsgDefinition definition = new MsgDefinition(); private Direction direction = Direction.TO_MODEM; private long quietTime = 0; @@ -97,7 +101,8 @@ public class Msg { public Msg(int headerLength, byte[] data, int dataLength, Direction dir) { this.headerLength = headerLength; this.direction = dir; - initialize(data, 0, dataLength); + this.data = new byte[dataLength]; + System.arraycopy(data, 0, this.data, 0, dataLength); } /** @@ -119,7 +124,7 @@ public class Msg { try { InputStream stream = FrameworkUtil.getBundle(Msg.class).getResource("/msg_definitions.xml").openStream(); if (stream != null) { - HashMap msgs = XMLMessageReader.readMessageDefinitions(stream); + Map msgs = XMLMessageReader.readMessageDefinitions(stream); MSG_MAP.putAll(msgs); } else { logger.warn("could not get message definition resource!"); @@ -171,15 +176,15 @@ public class Msg { } public byte getCommandNumber() { - return ((data == null || data.length < 2) ? -1 : data[1]); + return data.length < 2 ? -1 : data[1]; } public boolean isPureNack() { - return (data.length == 2 && data[1] == 0x15); + return data.length == 2 && data[1] == 0x15; } public boolean isExtended() { - if (data == null || getLength() < 2) { + if (getLength() < 2) { return false; } if (!definition.containsField("messageFlags")) { @@ -272,23 +277,6 @@ public class Msg { return hops; } - /** - * Will initialize the message with a byte[], an offset, and a length - * - * @param newData the src byte array - * @param offset the offset in the src byte array - * @param len the length to copy from the src byte array - */ - private void initialize(byte[] newData, int offset, int len) { - byte[] data = new byte[len]; - if (offset >= 0 && offset < newData.length) { - System.arraycopy(newData, offset, data, 0, len); - } else { - logger.warn("intialize(): Offset out of bounds!"); - } - this.data = data; - } - /** * Will put a byte at the specified key * @@ -346,9 +334,7 @@ public class Msg { } byte[] section = new byte[numBytes]; byte[] data = this.data; - if (data != null) { - System.arraycopy(data, offset, section, 0, numBytes); - } + System.arraycopy(data, offset, section, 0, numBytes); return section; } @@ -377,10 +363,7 @@ public class Msg { } public String toHexString() { - if (data != null) { - return Utils.getHexString(data); - } - return super.toString(); + return Utils.getHexString(data); } /** @@ -473,19 +456,15 @@ public class Msg { @Override public String toString() { String s = (direction == Direction.TO_MODEM) ? "OUT:" : "IN:"; - if (data == null) { - return toHexString(); - } // need to first sort the fields by offset - Comparator<@Nullable Field> cmp = new Comparator<@Nullable Field>() { + Comparator cmp = new Comparator() { @Override - public int compare(@Nullable Field f1, @Nullable Field f2) { + public int compare(Field f1, Field f2) { return f1.getOffset() - f2.getOffset(); } }; - TreeSet<@Nullable Field> fields = new TreeSet<>(cmp); - for (@Nullable - Field f : definition.getFields().values()) { + TreeSet fields = new TreeSet<>(cmp); + for (Field f : definition.getFields().values()) { fields.add(f); } for (Field f : fields) { @@ -517,7 +496,7 @@ public class Msg { * @return message, or null if the Msg cannot be created */ public static @Nullable Msg createMessage(byte[] buf, int msgLen, boolean isExtended) { - if (buf == null || buf.length < 2) { + if (buf.length < 2) { return null; } Msg template = REPLY_MAP.get(cmdToKey(buf[1], isExtended)); diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgDefinition.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgDefinition.java index 7fdcd66ae..34fd7a1d5 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgDefinition.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgDefinition.java @@ -27,7 +27,6 @@ import org.eclipse.jdt.annotation.Nullable; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class MsgDefinition { private Map fields = new HashMap<>(); @@ -39,7 +38,7 @@ public class MsgDefinition { * * @param m the definition to copy */ - MsgDefinition(@Nullable MsgDefinition m) { + MsgDefinition(MsgDefinition m) { fields = new HashMap<>(m.fields); } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/XMLMessageReader.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/XMLMessageReader.java index c23a18cc5..6ec2b4ffe 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/XMLMessageReader.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/XMLMessageReader.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Map; import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; @@ -23,7 +24,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.insteon.internal.utils.Pair; import org.openhab.binding.insteon.internal.utils.Utils.DataTypeParser; import org.openhab.binding.insteon.internal.utils.Utils.ParsingException; @@ -40,7 +40,6 @@ import org.xml.sax.SAXException; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class XMLMessageReader { /** * Reads the message definitions from an xml file @@ -51,9 +50,9 @@ public class XMLMessageReader { * @throws ParsingException something wrong with the file format * @throws FieldException something wrong with the field definition */ - public static HashMap readMessageDefinitions(InputStream input) + public static Map readMessageDefinitions(InputStream input) throws IOException, ParsingException, FieldException { - HashMap messageMap = new HashMap<>(); + Map messageMap = new HashMap<>(); try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); @@ -133,12 +132,9 @@ public class XMLMessageReader { for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { - @Nullable Pair definition = readField((Element) node, offset); - if (definition != null) { - offset += definition.getKey().getType().getSize(); - fields.put(definition.getKey(), definition.getValue()); - } + offset += definition.getKey().getType().getSize(); + fields.put(definition.getKey(), definition.getValue()); } } if (headerLen != offset) { @@ -165,8 +161,13 @@ public class XMLMessageReader { Msg msg = new Msg(headerLength, new byte[length], length, dir); for (Entry e : values.entrySet()) { Field f = e.getKey(); - f.set(msg.getData(), e.getValue()); - if (f.getName() != null && !f.getName().equals("")) { + byte[] data = msg.getData(); + if (data != null) { + f.set(data, e.getValue()); + } else { + throw new FieldException("data is null"); + } + if (!f.getName().equals("")) { msg.addField(f); } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/utils/Utils.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/utils/Utils.java index bcc0e3e7e..ba29cd4ec 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/utils/Utils.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/utils/Utils.java @@ -24,14 +24,13 @@ import org.openhab.binding.insteon.internal.message.DataType; * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class Utils { public static String getHexString(int b) { String result = String.format("%02X", b & 0xFF); return result; } - public static String getHexString(byte @Nullable [] b) { + public static String getHexString(byte[] b) { return getHexString(b, b.length); } @@ -70,9 +69,8 @@ public class Utils { return String.format("0x%02X", b); } - @NonNullByDefault public static class DataTypeParser { - public static Object parseDataType(@Nullable DataType type, String val) { + public static Object parseDataType(DataType type, String val) { switch (type) { case BYTE: return parseByte(val); @@ -123,7 +121,6 @@ public class Utils { /** * Exception to indicate various xml parsing errors. */ - @NonNullByDefault public static class ParsingException extends Exception { private static final long serialVersionUID = 3997461423241843949L; diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml b/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml index 26535c0fc..d6347127f 100644 --- a/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml +++ b/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml @@ -622,7 +622,7 @@ DefaultDispatcher NumberMsgHandler + low_byte="userData10" high_byte="userData9" factor="0.1" scale="celsius">NumberMsgHandler NumberMsgHandler @@ -634,7 +634,7 @@ DefaultDispatcher NumberMsgHandler + low_byte="userData10" high_byte="userData9" offset="32" factor="0.18" scale="fahrenheit">NumberMsgHandler NumberMsgHandler