From 3eba9b9245d79a0817836d6cf35fe66044da090f Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 11 Nov 2016 16:42:20 -0600 Subject: [PATCH] Basic MQTT configuration implementation. Still needs username/pwd and MQTT screen helper. --- pom.xml | 11 +++- .../HABridge/BridgeSettingsDescriptor.java | 23 +++++++ .../com/bwssystems/HABridge/HABridge.java | 6 ++ .../java/com/bwssystems/HABridge/NamedIP.java | 15 +++++ .../java/com/bwssystems/mqtt/MQTTHandler.java | 61 +++++++++++++++++++ .../java/com/bwssystems/mqtt/MQTTHome.java | 56 +++++++++++++++++ src/main/resources/public/scripts/app.js | 16 +++++ src/main/resources/public/views/system.html | 29 +++++++++ 8 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/bwssystems/mqtt/MQTTHandler.java create mode 100644 src/main/java/com/bwssystems/mqtt/MQTTHome.java diff --git a/pom.xml b/pom.xml index e98fb16..6066ff5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 3.2.2a + 3.2.2b jar HA Bridge @@ -22,6 +22,10 @@ jitpack.io https://jitpack.io + + Eclipse Paho Repo + https://repo.eclipse.org/content/repositories/paho-releases/ + @@ -106,6 +110,11 @@ smack-core 4.0.7 + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.1.0 + diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index 20e4e5f..ce8a173 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -34,6 +34,8 @@ public class BridgeSettingsDescriptor { private boolean settingsChanged; private String myechourl; private String webaddress; + private IpList mqttaddress; + private boolean mqttconfigured; public BridgeSettingsDescriptor() { super(); @@ -44,6 +46,7 @@ public class BridgeSettingsDescriptor { this.harmonyconfigured = false; this.hueconfigured = false; this.halconfigured = false; + this.mqttconfigured = false; this.farenheit = true; this.whitelist = null; this.settingsChanged = false; @@ -224,6 +227,18 @@ public class BridgeSettingsDescriptor { public void setWebaddress(String webaddress) { this.webaddress = webaddress; } + public IpList getMqttaddress() { + return mqttaddress; + } + public void setMqttaddress(IpList mqttaddress) { + this.mqttaddress = mqttaddress; + } + public boolean isMqttconfigured() { + return mqttconfigured; + } + public void setMqttconfigured(boolean mqttconfigured) { + this.mqttconfigured = mqttconfigured; + } public Boolean isValidVera() { if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0) return false; @@ -269,4 +284,12 @@ public class BridgeSettingsDescriptor { return false; return true; } + public Boolean isValidMQTT() { + if(this.getMqttaddress() == null || this.getMqttaddress().getDevices().size() <= 0) + return false; + List devicesList = this.getMqttaddress().getDevices(); + if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + return false; + return true; + } } diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java index 1036d5e..2cc6a00 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -13,6 +13,7 @@ import com.bwssystems.NestBridge.NestHome; import com.bwssystems.hal.HalHome; import com.bwssystems.harmony.HarmonyHome; import com.bwssystems.hue.HueHome; +import com.bwssystems.mqtt.MQTTHome; import com.bwssystems.util.UDPDatagramSender; public class HABridge { @@ -39,6 +40,7 @@ public class HABridge { NestHome nestHome; HueHome hueHome; HalHome halHome; + MQTTHome mqttHome; HueMulator theHueMulator; UDPDatagramSender udpSender; UpnpSettingsResource theSettingResponder; @@ -72,6 +74,8 @@ public class HABridge { hueHome = new HueHome(bridgeSettings.getBridgeSettingsDescriptor()); //setup the hal configuration if available halHome = new HalHome(bridgeSettings.getBridgeSettingsDescriptor()); + //setup the mqtt handlers if available + mqttHome = new MQTTHome(bridgeSettings.getBridgeSettingsDescriptor()); // setup the class to handle the resource setup rest api theResources = new DeviceResource(bridgeSettings.getBridgeSettingsDescriptor(), harmonyHome, nestHome, hueHome, halHome); // setup the class to handle the upnp response rest api @@ -104,6 +108,8 @@ public class HABridge { nestHome = null; harmonyHome.shutdownHarmonyHubs(); harmonyHome = null; + mqttHome.shutdownMQTTClients(); + mqttHome = null; udpSender.closeResponseSocket(); } log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting...."); diff --git a/src/main/java/com/bwssystems/HABridge/NamedIP.java b/src/main/java/com/bwssystems/HABridge/NamedIP.java index 4a59f82..38a6d7f 100644 --- a/src/main/java/com/bwssystems/HABridge/NamedIP.java +++ b/src/main/java/com/bwssystems/HABridge/NamedIP.java @@ -4,6 +4,9 @@ public class NamedIP { private String name; private String ip; private String port; + private String username; + private String password; + public String getName() { return name; } @@ -22,4 +25,16 @@ public class NamedIP { public void setPort(String port) { this.port = port; } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } } diff --git a/src/main/java/com/bwssystems/mqtt/MQTTHandler.java b/src/main/java/com/bwssystems/mqtt/MQTTHandler.java new file mode 100644 index 0000000..01f9dde --- /dev/null +++ b/src/main/java/com/bwssystems/mqtt/MQTTHandler.java @@ -0,0 +1,61 @@ +package com.bwssystems.mqtt; + +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.eclipse.paho.client.mqttv3.MqttPersistenceException; +import org.eclipse.paho.client.mqttv3.MqttSecurityException; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.bwssystems.HABridge.NamedIP; + +public class MQTTHandler { + private static final Logger log = LoggerFactory.getLogger(MQTTHandler.class); + private NamedIP myConfig; + private MqttClient myClient; + private int qos = 1; + + public MQTTHandler(NamedIP aConfig) { + super(); + log.debug("Setting up handler for name: " + aConfig.getName()); + MemoryPersistence persistence = new MemoryPersistence(); + myConfig = aConfig; + try { + myClient = new MqttClient("tcp://" + myConfig.getIp(), myConfig.getName(), persistence); + } catch (MqttException e) { + log.error("Could not create MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage()); + } + MqttConnectOptions connOpts = new MqttConnectOptions(); + connOpts.setCleanSession(true); + try { + myClient.connect(connOpts); + } catch (MqttSecurityException e) { + log.error("Could not connect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage()); + } catch (MqttException e) { + log.error("Could not connect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage()); + } + } + + public void publishMessage(String topic, String content) { + MqttMessage message = new MqttMessage(content.getBytes()); + message.setQos(qos); + try { + myClient.publish(topic, message); + } catch (MqttPersistenceException e) { + log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage()); + } catch (MqttException e) { + log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage()); + } + } + + public void shutdown() { + try { + myClient.disconnect(); + } catch (MqttException e) { + log.warn("Could not disconnect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp()); + } + } +} diff --git a/src/main/java/com/bwssystems/mqtt/MQTTHome.java b/src/main/java/com/bwssystems/mqtt/MQTTHome.java new file mode 100644 index 0000000..a2794a2 --- /dev/null +++ b/src/main/java/com/bwssystems/mqtt/MQTTHome.java @@ -0,0 +1,56 @@ +package com.bwssystems.mqtt; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.bwssystems.HABridge.BridgeSettingsDescriptor; +import com.bwssystems.HABridge.NamedIP; + +public class MQTTHome { + private static final Logger log = LoggerFactory.getLogger(MQTTHome.class); + private Map handlers; + + public MQTTHome(BridgeSettingsDescriptor bridgeSettings) { + super(); + if(!bridgeSettings.isValidMQTT()) + return; + + handlers = new HashMap(); + Iterator theList = bridgeSettings.getMqttaddress().getDevices().iterator(); + while(theList.hasNext()) { + NamedIP aClientConfig = theList.next(); + MQTTHandler aHandler = new MQTTHandler(aClientConfig); + if(aHandler != null) + handlers.put(aClientConfig.getName(), aHandler); + } + } + + public void shutdownMQTTClients() { + log.debug("Shutting down MQTT handlers."); + if(!handlers.isEmpty()) { + Iterator keys = handlers.keySet().iterator(); + while(keys.hasNext()) { + String key = keys.next(); + handlers.get(key).shutdown(); + } + } + } + + public MQTTHandler getMQTTHandler(String aName) { + MQTTHandler aHandler; + if(aName == null || aName.equals("")) { + aHandler = null; + log.debug("Cannot get MQTT handler for name as it is empty."); + } + else { + aHandler = handlers.get(aName); + log.debug("Retrieved a MQTT hanlder for name: " + aName); + } + return aHandler; + } + +} diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index a5c3da1..51b97eb 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -680,6 +680,22 @@ app.controller('SystemController', function ($scope, $location, $http, $window, } } }; + $scope.addMQTTtoSettings = function (newmqttname, newmqttip) { + if($scope.bridge.settings.mqttaddress == null) { + $scope.bridge.settings.mqttaddress = { devices: [] }; + } + var newmqtt = {name: newmqttname, ip: newmqttip } + $scope.bridge.settings.mqttaddress.devices.push(newmqtt); + $scope.newmqttname = null; + $scope.newmqttip = null; + }; + $scope.removeMQTTtoSettings = function (mqttname, mqttip) { + for(var i = $scope.bridge.settings.mqttaddress.devices.length - 1; i >= 0; i--) { + if($scope.bridge.settings.mqttaddress.devices[i].name === mqttname && $scope.bridge.settings.mqttaddress.devices[i].ip === mqttip) { + $scope.bridge.settings.mqttaddress.devices.splice(i, 1); + } + } + }; $scope.bridgeReinit = function () { bridgeService.reinit(); }; diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index dbf10d6..9e62b11 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -236,6 +236,35 @@ type="password" ng-model="bridge.settings.haltoken" placeholder="thetoken"> + + MQTT Client IDs and IP Addresses + + + + + + + + + + + + + + + + + + +
Client IDIPManage
{{mqtt.name}}{{mqtt.ip}}
+ Nest Username