* @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<InsteonAddress, InsteonDevice> devices = new ConcurrentHashMap<>();
- private ConcurrentHashMap<String, InsteonChannelConfiguration> bindingConfigs = new ConcurrentHashMap<>();
+ private Map<InsteonAddress, InsteonDevice> devices = new ConcurrentHashMap<>();
+ private Map<String, InsteonChannelConfiguration> bindingConfigs = new ConcurrentHashMap<>();
private PortListener portListener = new PortListener();
private int devicePollIntervalMilliseconds = 300000;
private int deadDeviceTimeout = -1;
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();
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);
}
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()) {
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(", ");
}
handler.updateState(channelUID, state);
}
- public InsteonDevice makeNewDevice(InsteonAddress addr, String productKey, Map<String, Object> deviceConfigMap) {
- DeviceType dt = DeviceTypeLoader.instance().getDeviceType(productKey);
+ public @Nullable InsteonDevice makeNewDevice(InsteonAddress addr, String productKey,
+ Map<String, Object> 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);
private String getLinkInfo(Map<InsteonAddress, ModemDBEntry> dbes, InsteonAddress a, boolean prefix) {
ModemDBEntry dbe = dbes.get(a);
+ if (dbe == null) {
+ return "";
+ }
List<Byte> controls = dbe.getControls();
List<Byte> 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();
* 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) {
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());
}
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.");
}
}
- if (monitoring == false) {
+ if (!monitoring) {
getInsteonBinding().getDriver().addMsgListener(this);
this.console = console;
}
private void stopMonitoring(Console console, String addr) {
- if (monitoring == false) {
+ if (!monitoring) {
console.println("Not mointoring any devices.");
return;
}
}
}
- if (monitorAllDevices == false && monitoredAddresses.isEmpty()) {
+ if (!monitorAllDevices && monitoredAddresses.isEmpty()) {
getInsteonBinding().getDriver().removeListener(this);
this.console = null;
monitoring = false;
}
}
- @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();
}
}
* @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<String, String> parameters = new HashMap<>();
/**
protected int getMaxLightLevel(InsteonChannelConfiguration conf, int defaultLevel) {
Map<String, String> 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);
}
}
return iv;
}
- @NonNullByDefault
public static class WarnCommandHandler extends CommandHandler {
WarnCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class NoOpCommandHandler extends CommandHandler {
NoOpCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class LightOnOffCommandHandler extends CommandHandler {
LightOnOffCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class FastOnOffCommandHandler extends CommandHandler {
FastOnOffCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class RampOnOffCommandHandler extends RampCommandHandler {
RampOnOffCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class ManualChangeCommandHandler extends CommandHandler {
ManualChangeCommandHandler(DeviceFeature f) {
super(f);
/**
* Sends ALLLink broadcast commands to group
*/
- @NonNullByDefault
public static class GroupBroadcastCommandHandler extends CommandHandler {
GroupBroadcastCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class LEDOnOffCommandHandler extends CommandHandler {
LEDOnOffCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class X10OnOffCommandHandler extends CommandHandler {
X10OnOffCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class X10PercentCommandHandler extends CommandHandler {
X10PercentCommandHandler(DeviceFeature f) {
super(f);
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);
}
}
- @NonNullByDefault
public static class IOLincOnOffCommandHandler extends CommandHandler {
IOLincOnOffCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class IncreaseDecreaseCommandHandler extends CommandHandler {
IncreaseDecreaseCommandHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class PercentHandler extends CommandHandler {
PercentHandler(DeviceFeature f) {
super(f);
}
}
- @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 };
}
}
- @NonNullByDefault
public static class RampPercentHandler extends RampCommandHandler {
RampPercentHandler(DeviceFeature f) {
}
}
- @NonNullByDefault
public static class PowerMeterCommandHandler extends CommandHandler {
PowerMeterCommandHandler(DeviceFeature f) {
super(f);
* First used for setting thermostat parameters.
*/
- @NonNullByDefault
public static class NumberCommandHandler extends CommandHandler {
NumberCommandHandler(DeviceFeature f) {
super(f);
/**
* Handler to set the thermostat system mode
*/
- @NonNullByDefault
public static class ThermostatSystemModeCommandHandler extends NumberCommandHandler {
ThermostatSystemModeCommandHandler(DeviceFeature f) {
super(f);
/**
* Handler to set the thermostat fan mode
*/
- @NonNullByDefault
public static class ThermostatFanModeCommandHandler extends NumberCommandHandler {
ThermostatFanModeCommandHandler(DeviceFeature f) {
super(f);
/**
* Handler to set the fanlinc fan mode
*/
- @NonNullByDefault
public static class FanLincFanCommandHandler extends NumberCommandHandler {
FanLincFanCommandHandler(DeviceFeature f) {
super(f);
Class<?> c = Class.forName(cname);
@SuppressWarnings("unchecked")
Class<? extends T> dc = (Class<? extends T>) c;
+ @Nullable
T ch = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f);
ch.setParameters(params);
return ch;
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class DeviceFeature {
public static enum QueryStatus {
NEVER_QUERIED,
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;
return directAckTimeout;
}
- public @Nullable MessageHandler getDefaultMsgHandler() {
+ public MessageHandler getDefaultMsgHandler() {
return defaultMsgHandler;
}
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;
}
* @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);
}
/**
public void handleCommand(InsteonChannelConfiguration c, Command cmd) {
Class<? extends Command> 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());
+ }
}
/**
* @return the poll message
*/
public @Nullable Msg makePollMsg() {
+ PollHandler pollHandler = this.pollHandler;
if (pollHandler == null) {
return null;
}
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);
}
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);
+ }
}
}
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
import java.util.Map.Entry;
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<String, String> features = new HashMap<>();
- private HashMap<String, FeatureGroup> featureGroups = new HashMap<>();
+ private Map<String, String> features = new HashMap<>();
+ private Map<String, FeatureGroup> featureGroups = new HashMap<>();
/**
* Constructor
*
* @return all features that this device type supports
*/
- public HashMap<String, String> getFeatures() {
+ public Map<String, String> getFeatures() {
return features;
}
*
* @return all feature groups of this device type
*/
- public HashMap<String, FeatureGroup> getFeatureGroups() {
+ public Map<String, FeatureGroup> getFeatureGroups() {
return featureGroups;
}
*
* @author Bernd Pfrommer - Initial contribution
*/
- @NonNullByDefault
public static class FeatureGroup {
private String name;
private String type;
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;
* @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<String, DeviceType> deviceTypes = new HashMap<>();
- private @Nullable static DeviceTypeLoader deviceTypeLoader = null;
+ private Map<String, DeviceType> deviceTypes = new HashMap<>();
+ private static DeviceTypeLoader deviceTypeLoader = new DeviceTypeLoader();
private DeviceTypeLoader() {
} // private so nobody can call it
*
* @return currently known device types
*/
- public HashMap<String, DeviceType> getDeviceTypes() {
+ public Map<String, DeviceType> getDeviceTypes() {
return (deviceTypes);
}
*/
@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;
}
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;
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class FeatureTemplate {
private String name;
private String timeout;
private @Nullable HandlerEntry pollHandler = null;
private @Nullable HandlerEntry defaultMsgHandler = null;
private @Nullable HandlerEntry defaultCmdHandler = null;
- private HashMap<Integer, HandlerEntry> messageHandlers = new HashMap<>();
- private HashMap<Class<? extends Command>, HandlerEntry> commandHandlers = new HashMap<>();
+ private Map<Integer, HandlerEntry> messageHandlers = new HashMap<>();
+ private Map<Class<? extends Command>, HandlerEntry> commandHandlers = new HashMap<>();
public FeatureTemplate(String name, boolean isStatus, String timeout) {
this.name = name;
*
* @return a Hashmap from Integer to String representing the command codes and the associated message handlers
*/
- public HashMap<Integer, HandlerEntry> getMessageHandlers() {
+ public Map<Integer, HandlerEntry> getMessageHandlers() {
return messageHandlers;
}
* @see #getMessageHandlers()
* @return a HashMap from Command Classes to CommandHandler names
*/
- public HashMap<Class<? extends Command>, HandlerEntry> getCommandHandlers() {
+ public Map<Class<? extends Command>, HandlerEntry> getCommandHandlers() {
return commandHandlers;
}
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<Integer, HandlerEntry> mH : messageHandlers.entrySet()) {
f.addMessageHandler(mH.getKey(),
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class InsteonDevice {
private final Logger logger = LoggerFactory.getLogger(InsteonDevice.class);
}
public boolean hasProductKey(String key) {
+ String productKey = this.productKey;
return productKey != null && productKey.equals(key);
}
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;
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.
}
}
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;
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<String, String> fe : dt.getFeatures().entrySet()) {
DeviceFeature f = DeviceFeature.makeDeviceFeature(fe.getValue());
if (f == null) {
* @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;
*
* @author Bernd Pfrommer - Initial contribution
*/
- @NonNullByDefault
public static class QEntry implements Comparable<QEntry> {
private DeviceFeature feature;
private Msg msg;
* @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);
//
//
- @NonNullByDefault
public static class DefaultDispatcher extends MessageDispatcher {
DefaultDispatcher(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class DefaultGroupDispatcher extends MessageDispatcher {
DefaultGroupDispatcher(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class PollGroupDispatcher extends MessageDispatcher {
PollGroupDispatcher(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class SimpleDispatcher extends MessageDispatcher {
SimpleDispatcher(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class X10Dispatcher extends MessageDispatcher {
X10Dispatcher(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class PassThroughDispatcher extends MessageDispatcher {
PassThroughDispatcher(DeviceFeature f) {
super(f);
/**
* Drop all incoming messages silently
*/
- @NonNullByDefault
public static class NoOpDispatcher extends MessageDispatcher {
NoOpDispatcher(DeviceFeature f) {
super(f);
Class<?> c = Class.forName(cname);
@SuppressWarnings("unchecked")
Class<? extends T> dc = (Class<? extends T>) c;
+ @Nullable
T ch = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f);
ch.setParameters(params);
return ch;
* @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);
* @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;
}
/**
//
//
- @NonNullByDefault
public static class DefaultMsgHandler extends MessageHandler {
DefaultMsgHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class NoOpMsgHandler extends MessageHandler {
NoOpMsgHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class LightOnDimmerHandler extends MessageHandler {
LightOnDimmerHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class LightOffDimmerHandler extends MessageHandler {
LightOffDimmerHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class LightOnSwitchHandler extends MessageHandler {
LightOnSwitchHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class LightOffSwitchHandler extends MessageHandler {
LightOffSwitchHandler(DeviceFeature p) {
super(p);
* 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;
* else if command2 == 0x00 then the light has been turned off
*/
- @NonNullByDefault
public static class SwitchRequestReplyHandler extends MessageHandler {
SwitchRequestReplyHandler(DeviceFeature p) {
super(p);
* 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);
}
}
- @NonNullByDefault
public static class DimmerStopManualChangeHandler extends MessageHandler {
DimmerStopManualChangeHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class StartManualChangeHandler extends MessageHandler {
StartManualChangeHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class StopManualChangeHandler extends MessageHandler {
StopManualChangeHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class InfoRequestReplyHandler extends MessageHandler {
InfoRequestReplyHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class MotionSensorDataReplyHandler extends MessageHandler {
MotionSensorDataReplyHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class MotionSensor2AlternateHeartbeatHandler extends MessageHandler {
MotionSensor2AlternateHeartbeatHandler(DeviceFeature p) {
super(p);
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;
}
}
- @NonNullByDefault
public static class HiddenDoorSensorDataReplyHandler extends MessageHandler {
HiddenDoorSensorDataReplyHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class PowerMeterUpdateHandler extends MessageHandler {
PowerMeterUpdateHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class PowerMeterResetHandler extends MessageHandler {
PowerMeterResetHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class LastTimeHandler extends MessageHandler {
LastTimeHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class ContactRequestReplyHandler extends MessageHandler {
ContactRequestReplyHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class ClosedContactHandler extends MessageHandler {
ClosedContactHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class OpenedContactHandler extends MessageHandler {
OpenedContactHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class OpenedOrClosedContactHandler extends MessageHandler {
OpenedOrClosedContactHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class ClosedSleepingContactHandler extends MessageHandler {
ClosedSleepingContactHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class OpenedSleepingContactHandler extends MessageHandler {
OpenedSleepingContactHandler(DeviceFeature p) {
super(p);
* 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);
/**
* Flexible handler to extract numerical data from messages.
*/
- @NonNullByDefault
public static class NumberMsgHandler extends MessageHandler {
NumberMsgHandler(DeviceFeature p) {
super(p);
}
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;
}
} 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);
* 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);
/**
* Handle reply to system mode change command
*/
- @NonNullByDefault
public static class ThermostatSystemModeReplyHandler extends NumberMsgHandler {
ThermostatSystemModeReplyHandler(DeviceFeature p) {
super(p);
/**
* Handle reply to fan mode change command
*/
- @NonNullByDefault
public static class ThermostatFanModeReplyHandler extends NumberMsgHandler {
ThermostatFanModeReplyHandler(DeviceFeature p) {
super(p);
/**
* Handle reply to fanlinc fan speed change command
*/
- @NonNullByDefault
public static class FanLincFanReplyHandler extends NumberMsgHandler {
FanLincFanReplyHandler(DeviceFeature p) {
super(p);
* 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);
}
}
- @NonNullByDefault
public static class X10OffHandler extends MessageHandler {
X10OffHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class X10BrightHandler extends MessageHandler {
X10BrightHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class X10DimHandler extends MessageHandler {
X10DimHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class X10OpenHandler extends MessageHandler {
X10OpenHandler(DeviceFeature p) {
super(p);
}
}
- @NonNullByDefault
public static class X10ClosedHandler extends MessageHandler {
X10ClosedHandler(DeviceFeature p) {
super(p);
Class<?> c = Class.forName(cname);
@SuppressWarnings("unchecked")
Class<? extends T> dc = (Class<? extends T>) c;
+ @Nullable
T mh = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f);
mh.setParameters(params);
return mh;
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class ModemDBBuilder implements MsgListener {
private static final int MESSAGE_TIMEOUT = 30000;
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 = "";
* @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;
* most query messages. Provide the suitable parameters in
* the device features file.
*/
- @NonNullByDefault
public static class FlexPollHandler extends PollHandler {
FlexPollHandler(DeviceFeature f) {
super(f);
}
}
- @NonNullByDefault
public static class NoPollHandler extends PollHandler {
NoPollHandler(DeviceFeature f) {
super(f);
* @return the handler which was created
*/
@Nullable
- public static <T extends PollHandler> T makeHandler(@Nullable HandlerEntry ph, DeviceFeature f) {
+ public static <T extends PollHandler> T makeHandler(HandlerEntry ph, DeviceFeature f) {
String cname = PollHandler.class.getName() + "$" + ph.getName();
try {
Class<?> c = Class.forName(cname);
@SuppressWarnings("unchecked")
Class<? extends T> dc = (Class<? extends T>) c;
+ @Nullable
T phc = dc.getDeclaredConstructor(DeviceFeature.class).newInstance(f);
phc.setParameters(ph.getParams());
return phc;
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;
* @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<RequestQueue> requestQueues = new PriorityQueue<>();
+ private Queue<RequestQueue> requestQueues = new PriorityQueue<>();
private Map<InsteonDevice, RequestQueue> 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();
+ }
}
/**
*/
private void stopThread() {
logger.debug("stopping thread");
+ Thread queueThread = this.queueThread;
if (queueThread != null) {
synchronized (requestQueues) {
keepRunning = false;
} 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() {
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();
}
}
- @NonNullByDefault
public static class RequestQueue implements Comparable<RequestQueue> {
private InsteonDevice device;
private long expirationTime;
}
}
- @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;
}
}
}
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.
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class X10 {
/**
* Enumerates the X10 command codes.
* @return coded house byte
*/
public static int houseStringToCode(String s) {
- Integer i = findKey(houseCodeToString, s);
- return (i == null) ? 0xf : i;
+ for (Entry<Integer, String> entry : houseCodeToString.entrySet()) {
+ if (s.equals(entry.getValue())) {
+ return entry.getKey();
+ }
+ }
+ return 0xf;
}
/**
*/
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<Integer, Integer> entry : unitCodeToInt.entrySet()) {
+ if (i == entry.getValue()) {
+ return entry.getKey();
+ }
+ }
} catch (NumberFormatException e) {
}
return 0xf;
}
- private static @Nullable <T, E> T findKey(Map<T, E> map, E value) {
- for (Entry<T, E> entry : map.entrySet()) {
- if (value.equals(entry.getValue())) {
- return entry.getKey();
- }
- }
- return null;
- }
-
/**
* Map between 4-bit X10 code and the house code.
*/
* @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;
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();
}
* @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");
+ }
}
/**
return new TcpIOStream(hp.host, hp.port);
}
- @NonNullByDefault
private static class HostPort {
public String host = "localhost";
public int port = -1;
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class Poller {
private static final long MIN_MSEC_BETWEEN_POLLS = 2000L;
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();
}
}
pollQueue.notify();
}
try {
+ Thread pollThread = this.pollThread;
if (pollThread != null) {
pollThread.join();
- pollThread = null;
+ this.pollThread = null;
}
keepRunning = true;
} catch (InterruptedException e) {
return expTime;
}
- @NonNullByDefault
private class PollQueueReader implements Runnable {
@Override
public void run() {
* @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());
+ }
}
}
* @author Bernd Pfrommer - Initial contribution
*
*/
- @NonNullByDefault
private static class PQEntry implements Comparable<PQEntry> {
private InsteonDevice dev;
private long expirationTime;
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;
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class Port {
private final Logger logger = LoggerFactory.getLogger(Port.class);
public void clearModemDB() {
logger.debug("clearing modem db!");
Map<InsteonAddress, ModemDBEntry> dbes = getDriver().lockModemDBEntries();
- for (InsteonAddress addr : dbes.keySet()) {
- if (!dbes.get(addr).isModem()) {
- dbes.remove(addr);
+ for (Entry<InsteonAddress, ModemDBEntry> entry : dbes.entrySet()) {
+ if (!entry.getValue().isModem()) {
+ dbes.remove(entry.getKey());
}
}
getDriver().unlockModemDBEntries();
}
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();
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
*/
ioStream.stop();
ioStream.close();
+ Thread readThread = this.readThread;
if (readThread != null) {
readThread.interrupt();
}
+ Thread writeThread = this.writeThread;
if (writeThread != null) {
writeThread.interrupt();
}
} 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);
}
*
* @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
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();
}
}
}
- /**
- * 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<Byte> 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
*
* @author Bernd Pfrommer - Initial contribution
*/
- @NonNullByDefault
class IOStreamWriter implements Runnable {
private static final int WAIT_TIME = 200; // milliseconds
/**
* 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());
}
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);
}
}
+ 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");
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;
* @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;
}
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);
}
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) {
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;
}
}
}
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;
*
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class TcpIOStream extends IOStream {
private final Logger logger = LoggerFactory.getLogger(TcpIOStream.class);
}
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);
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;
}
}
}
*
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class HubIOStream extends IOStream implements Runnable {
private final Logger logger = LoggerFactory.getLogger(HubIOStream.class);
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;
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;
}
}
}
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;
}
* @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
* @author Daniel Pfrommer - Initial contribution
*
*/
- @NonNullByDefault
public class HubOutputStream extends OutputStream {
private ByteArrayOutputStream out = new ByteArrayOutputStream();
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;
* @author Rob Nielsen - Initial contribution
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class InsteonDeviceHandler extends BaseThingHandler {
private static final Set<String> ALL_CHANNEL_IDS = Collections.unmodifiableSet(Stream.of(
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
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);
}
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<Channel> channels = new ArrayList<>();
ChannelTypeUID channelTypeUID = new ChannelTypeUID(
InsteonBindingConstants.BINDING_ID,
InsteonBindingConstants.SWITCH);
- Channel channel = getCallback()
+ Channel channel = callback
.createChannelBuilder(channelUID, channelTypeUID).withLabel(id)
.build();
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);
@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();
}
Map<String, String> params = new HashMap<>();
Channel channel = getThing().getChannel(channelUID.getId());
+ if (channel == null) {
+ logger.warn("channel is null");
+ return;
+ }
Map<String, Object> channelProperties = channel.getConfiguration().getProperties();
for (String key : channelProperties.keySet()) {
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)) {
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();
}
}
* @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;
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.
// 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);
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);
});
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();
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.");
}
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) {
public void addMissingDevices(List<String> missing) {
scheduler.execute(() -> {
- insteonDeviceDiscoveryService.addInsteonDevices(missing, getThing().getUID());
+ InsteonDeviceDiscoveryService insteonDeviceDiscoveryService = this.insteonDeviceDiscoveryService;
+ if (insteonDeviceDiscoveryService != null) {
+ insteonDeviceDiscoveryService.addInsteonDevices(missing, getThing().getUID());
+ }
});
}
}
public void displayLocalDatabase(Console console) {
- Map<String, String> databaseInfo = insteonBinding.getDatabaseInfo();
- console.println("local database contains " + databaseInfo.size() + " entries");
- display(console, databaseInfo);
+ InsteonBinding insteonBinding = this.insteonBinding;
+ if (insteonBinding != null) {
+ Map<String, String> databaseInfo = insteonBinding.getDatabaseInfo();
+ console.println("local database contains " + databaseInfo.size() + " entries");
+ display(console, databaseInfo);
+ }
}
public void initialized(ThingUID uid, String msg) {
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.
ADDRESS("address", 3),
INVALID("INVALID", -1);
- private static HashMap<String, DataType> typeMap = new HashMap<>();
+ private static Map<String, DataType> 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);
* @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);
+ }
}
}
* @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;
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;
return getName() + " Type: " + getType() + " Offset " + getOffset();
}
- public String toString(byte @Nullable [] array) {
+ public String toString(byte[] array) {
String s = name + ":";
try {
switch (type) {
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);
* @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;
}
* @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);
* @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);
}
* @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];
}
* @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];
* @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);
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class Msg {
private static final Logger logger = LoggerFactory.getLogger(Msg.class);
TO_MODEM("TO_MODEM"),
FROM_MODEM("FROM_MODEM");
- private static HashMap<String, Direction> map = new HashMap<>();
+ private static Map<String, Direction> map = new HashMap<>();
private String directionString;
}
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);
+ }
}
}
private static final Map<Integer, Msg> 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;
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);
}
/**
try {
InputStream stream = FrameworkUtil.getBundle(Msg.class).getResource("/msg_definitions.xml").openStream();
if (stream != null) {
- HashMap<String, Msg> msgs = XMLMessageReader.readMessageDefinitions(stream);
+ Map<String, Msg> msgs = XMLMessageReader.readMessageDefinitions(stream);
MSG_MAP.putAll(msgs);
} else {
logger.warn("could not get message definition resource!");
}
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")) {
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
*
}
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;
}
}
public String toHexString() {
- if (data != null) {
- return Utils.getHexString(data);
- }
- return super.toString();
+ return Utils.getHexString(data);
}
/**
@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<Field> cmp = new Comparator<Field>() {
@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<Field> fields = new TreeSet<>(cmp);
+ for (Field f : definition.getFields().values()) {
fields.add(f);
}
for (Field f : fields) {
* @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));
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class MsgDefinition {
private Map<String, Field> fields = new HashMap<>();
*
* @param m the definition to copy
*/
- MsgDefinition(@Nullable MsgDefinition m) {
+ MsgDefinition(MsgDefinition m) {
fields = new HashMap<>(m.fields);
}
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;
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;
* @author Rob Nielsen - Port to openHAB 2 insteon binding
*/
@NonNullByDefault
-@SuppressWarnings("null")
public class XMLMessageReader {
/**
* Reads the message definitions from an xml file
* @throws ParsingException something wrong with the file format
* @throws FieldException something wrong with the field definition
*/
- public static HashMap<String, Msg> readMessageDefinitions(InputStream input)
+ public static Map<String, Msg> readMessageDefinitions(InputStream input)
throws IOException, ParsingException, FieldException {
- HashMap<String, Msg> messageMap = new HashMap<>();
+ Map<String, Msg> messageMap = new HashMap<>();
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
- @Nullable
Pair<Field, Object> 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) {
Msg msg = new Msg(headerLength, new byte[length], length, dir);
for (Entry<Field, Object> 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);
}
}
* @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);
}
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);
/**
* Exception to indicate various xml parsing errors.
*/
- @NonNullByDefault
public static class ParsingException extends Exception {
private static final long serialVersionUID = 3997461423241843949L;
<message-dispatcher>DefaultDispatcher</message-dispatcher>
<!-- handles direct extended message after query -->
<message-handler cmd="0x2e" ext="1" match_cmd1="0x2e" match_cmd2="0x02" match_d1="0x01"
- low_byte="userData10" high_byte="userData9" factor="0.1">NumberMsgHandler</message-handler>
+ low_byte="userData10" high_byte="userData9" factor="0.1" scale="celsius">NumberMsgHandler</message-handler>
<!-- handles out-of band status messages -->
<message-handler cmd="0x6e" ext="0" match_cmd1="0x6e" low_byte="command2" offset="-17.7777778"
factor="0.2777778" scale="celsius">NumberMsgHandler</message-handler>
<message-dispatcher>DefaultDispatcher</message-dispatcher>
<!-- handles direct extended message after query -->
<message-handler cmd="0x2e" ext="1" match_cmd1="0x2e" match_cmd2="0x02" match_d1="0x01"
- low_byte="userData10" high_byte="userData9" offset="32" factor="0.18">NumberMsgHandler</message-handler>
+ low_byte="userData10" high_byte="userData9" offset="32" factor="0.18" scale="fahrenheit">NumberMsgHandler</message-handler>
<!-- handles out-of band status messages -->
<message-handler cmd="0x6e" ext="0" match_cmd1="0x6e" low_byte="command2" offset="0" factor="0.5"
scale="fahrenheit">NumberMsgHandler</message-handler>