diff --git a/Hal.iml b/Hal.iml
index 0a3e95e6..6da1b2e3 100755
--- a/Hal.iml
+++ b/Hal.iml
@@ -12,6 +12,7 @@
+
diff --git a/plugins/hal-mqtt/build.xml b/plugins/hal-mqtt/build.xml
new file mode 100644
index 00000000..8a3983b8
--- /dev/null
+++ b/plugins/hal-mqtt/build.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java
new file mode 100644
index 00000000..02dc831b
--- /dev/null
+++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java
@@ -0,0 +1,147 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Ziver Koc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package se.hal.plugin.mqtt;
+
+import se.hal.intf.*;
+import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
+import se.hal.plugin.mqtt.device.HalMqttDeviceData;
+import zutil.InetUtil;
+import zutil.log.LogUtil;
+import zutil.net.dns.MulticastDnsServer;
+import zutil.net.mqtt.MqttBroker;
+import zutil.net.mqtt.MqttSubscriptionListener;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class HalMqttController implements HalAutoScannableController, MqttSubscriptionListener, HalEventController {
+ private final Logger logger = LogUtil.getLogger();
+
+ private MulticastDnsServer mDns;
+ private MqttBroker mqttBroker;
+
+ private HashMap topics = new HashMap<>();
+ private HalEventReportListener eventListener;
+
+ // --------------------------
+ // Lifecycle methods
+ // --------------------------
+
+ @Override
+ public void initialize() {
+ try {
+ InetAddress serverIp = InetUtil.getLocalInet4Address().get(0);
+
+ mDns = new MulticastDnsServer();
+ mDns.addEntry("_mqtt.tcp", serverIp);
+ mDns.addEntry("hal.local", serverIp);
+
+ mqttBroker = new MqttBroker();
+
+ } catch (IOException e) {
+ logger.log(Level.SEVERE, "Unable to initialize MQTT plugin.", e);
+
+ close();
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mDns != null && mqttBroker != null;
+ }
+
+ @Override
+ public void close(){
+ if (mDns != null) {
+ mDns.close();
+ mDns = null;
+ }
+
+ if (mqttBroker != null) {
+ mqttBroker.close();
+ mqttBroker = null;
+ }
+ }
+
+ // --------------------------
+ // MQTT Methods
+ // --------------------------
+
+ @Override
+ public void dataPublished(String topic, byte[] data) {
+ HalMqttDeviceConfig eventConfig = topics.get(topic);
+
+ if (eventConfig != null && data.length > 0) {
+ HalMqttDeviceData eventData = new HalMqttDeviceData(data);
+
+ if (eventListener != null) {
+ eventListener.reportReceived(eventConfig, eventData);
+ }
+ }
+ }
+
+ // --------------------------
+ // Hal Methods
+ // --------------------------
+
+ @Override
+ public void register(HalEventConfig eventConfig) {
+ if(eventConfig instanceof HalMqttDeviceConfig) {
+ HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) eventConfig;
+ topics.put(mqttEvent.getTopic(), mqttEvent);
+ } else throw new IllegalArgumentException(
+ "Device config is not an instance of " + HalMqttDeviceConfig.class + ": " + eventConfig.getClass());
+ }
+
+ @Override
+ public void deregister(HalEventConfig eventConfig) {
+ if(eventConfig instanceof HalMqttDeviceConfig) {
+ HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) eventConfig;
+ topics.remove(mqttEvent.getTopic());
+ }
+ }
+
+ @Override
+ public void send(HalEventConfig eventConfig, HalEventData eventData) {
+ if(eventConfig instanceof HalMqttDeviceConfig) {
+ HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) eventConfig;
+ mqttBroker.publish(mqttEvent.getTopic(), Double.toString(eventData.getData()).getBytes());
+ } else throw new IllegalArgumentException(
+ "Device config is not an instance of " + HalMqttDeviceConfig.class + ": " + eventConfig.getClass());
+ }
+
+ @Override
+ public int size() {
+ return topics.size();
+ }
+
+ @Override
+ public void setListener(HalEventReportListener listener) {
+ eventListener = listener;
+ }
+}
diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceConfig.java b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceConfig.java
new file mode 100644
index 00000000..811ccb11
--- /dev/null
+++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceConfig.java
@@ -0,0 +1,82 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Ziver Koc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Ziver Koc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package se.hal.plugin.mqtt.device;
+
+import se.hal.intf.HalEventConfig;
+import se.hal.intf.HalEventController;
+import se.hal.intf.HalEventData;
+import se.hal.plugin.mqtt.HalMqttController;
+
+public class HalMqttDeviceConfig implements HalEventConfig {
+ private final String topic;
+
+
+ public HalMqttDeviceConfig(String topic) {
+ this.topic = topic;
+ }
+
+
+ public String getTopic() {
+ return topic;
+ }
+
+ // --------------------------
+ // Hal Methods
+ // --------------------------
+
+ @Override
+ public Class extends HalEventController> getEventControllerClass() {
+ return HalMqttController.class;
+ }
+
+ @Override
+ public Class extends HalEventData> getEventDataClass() {
+ return HalMqttDeviceData.class;
+ }
+}
diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceData.java b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceData.java
new file mode 100644
index 00000000..87ab2688
--- /dev/null
+++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceData.java
@@ -0,0 +1,59 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Ziver Koc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package se.hal.plugin.mqtt.device;
+
+import se.hal.intf.HalEventData;
+import zutil.StringUtil;
+import zutil.log.LogUtil;
+
+import java.util.logging.Logger;
+
+public class HalMqttDeviceData extends HalEventData {
+ private static final Logger logger = LogUtil.getLogger();
+
+ private double data;
+
+
+ public HalMqttDeviceData(byte[] byteData) {
+ String str = new String(byteData);
+
+ if (StringUtil.isDecimalNumber(str)) {
+ data = Double.parseDouble(str);
+ } else {
+ logger.warning("Received non numeric MQTT data.");
+ }
+ }
+
+
+ @Override
+ public double getData() {
+ return data;
+ }
+
+ @Override
+ public void setData(double data) {
+ this.data = data;
+ }
+}
diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/plugin.json b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/plugin.json
new file mode 100644
index 00000000..ef2f0051
--- /dev/null
+++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/plugin.json
@@ -0,0 +1,7 @@
+{
+ "version": 1.0,
+ "name": "Hal-MQTT",
+ "interfaces": [
+ {"se.hal.intf.HalAutoScannableController": "se.hal.plugin.mqtt.HalMqttController"}
+ ]
+}
\ No newline at end of file