diff --git a/plugins/hal-zigbee/resource/resource/hal-zigbee-default.db b/plugins/hal-zigbee/resource/resource/hal-zigbee-default.db new file mode 100644 index 00000000..883a1fc1 Binary files /dev/null and b/plugins/hal-zigbee/resource/resource/hal-zigbee-default.db differ diff --git a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeHalDataStore.java b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeHalDataStore.java new file mode 100644 index 00000000..f55d54e6 --- /dev/null +++ b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeHalDataStore.java @@ -0,0 +1,151 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 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.zigbee; + +import com.zsmartsystems.zigbee.IeeeAddress; +import com.zsmartsystems.zigbee.database.ZigBeeNetworkDataStore; +import com.zsmartsystems.zigbee.database.ZigBeeNodeDao; +import zutil.db.DBConnection; +import zutil.db.bean.DBBean; +import zutil.db.bean.DBBeanSQLResultHandler; +import zutil.db.handler.ListSQLResult; +import zutil.io.StringInputStream; +import zutil.log.LogUtil; +import zutil.parser.json.JSONObjectInputStream; +import zutil.parser.json.JSONObjectOutputStream; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; + + +public class ZigBeeHalDataStore implements ZigBeeNetworkDataStore { + private static final Logger logger = LogUtil.getLogger(); + + private DBConnection db; + + + public ZigBeeHalDataStore(DBConnection db) { + this.db = db; + } + + + @Override + public Set readNetworkNodes() { + Set ieeeAddresses = new HashSet<>(); + + try { + PreparedStatement stmt = db.getPreparedStatement( "SELECT address FROM zigbee_node" ); + List strAddresses = DBConnection.exec(stmt, new ListSQLResult()); + + for (String address : strAddresses) { + ieeeAddresses.add(new IeeeAddress(address)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return ieeeAddresses; + } + + @Override + public ZigBeeNodeDao readNode(IeeeAddress address) { + try { + ZigbeeNodeDSO dso = ZigbeeNodeDSO.load(db, address.toString()); + if (dso != null) + return dso.getConfig(); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void writeNode(ZigBeeNodeDao node) { + try { + logger.fine("[Node: " + node.getIeeeAddress() + "]: Storing Zigbee Node in DB: " + + "NetAddr: " + node.getNetworkAddress() + ", " + + "binding: " + node.getBindingTable() + ", " + + "description: " + node.getNodeDescriptor() + ", " + + "endpoints: " + node.getEndpoints() + ", " + + "Power: " + node.getPowerDescriptor() + ); + + ZigbeeNodeDSO dso = ZigbeeNodeDSO.load(db, node.getIeeeAddress().toString()); + if (dso == null) { + dso = new ZigbeeNodeDSO(); + dso.address = node.getIeeeAddress().toString(); + } + + dso.setConfig(node); + dso.save(db); + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void removeNode(IeeeAddress address) { + try { + logger.fine("[Node: " + address + "]: Removing Node from DB."); + + ZigbeeNodeDSO dso = ZigbeeNodeDSO.load(db, address.toString()); + if (dso != null) + dso.delete(db); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * A private data storage object connected to the DB schema. + */ + private static class ZigbeeNodeDSO extends DBBean { + protected String address; + protected String config; + + + public static ZigbeeNodeDSO load(DBConnection db, String address) throws SQLException{ + PreparedStatement stmt = db.getPreparedStatement( "SELECT * FROM zigbee_node WHERE ? == zigbee_node.address" ); + stmt.setString(1, address); + return DBConnection.exec(stmt, DBBeanSQLResultHandler.create(ZigbeeNodeDSO.class, db)); + } + + + protected void setConfig(ZigBeeNodeDao node) { + config = JSONObjectOutputStream.toString(node); + } + + protected ZigBeeNodeDao getConfig() { + JSONObjectInputStream in = new JSONObjectInputStream(new StringInputStream(config)); + in.registerRootClass(ZigBeeNodeDao.class); + return (ZigBeeNodeDao) in.readObject(); + } + } +} diff --git a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeDataStore.java b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeMemoryDataStore.java similarity index 82% rename from plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeDataStore.java rename to plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeMemoryDataStore.java index bfdd5215..3837bcf1 100644 --- a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeDataStore.java +++ b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigBeeMemoryDataStore.java @@ -34,14 +34,13 @@ import java.util.Set; import java.util.logging.Logger; -public class ZigBeeDataStore implements ZigBeeNetworkDataStore { +public class ZigBeeMemoryDataStore implements ZigBeeNetworkDataStore { private static final Logger logger = LogUtil.getLogger(); - private static ZigBeeDataStore instance; private HashMap devices = new HashMap<>(); - private ZigBeeDataStore() {} + private ZigBeeMemoryDataStore() {} @Override @@ -58,9 +57,9 @@ public class ZigBeeDataStore implements ZigBeeNetworkDataStore { public void writeNode(ZigBeeNodeDao node) { logger.fine("[Node: " + node.getIeeeAddress() + "]: Storing Zigbee Node in DB: " + "NetAddr: " + node.getNetworkAddress() + ", " + - "binding: " + node.getBindingTable() + ", " + - "description: " + node.getNodeDescriptor() + ", " + - "endpoints: " + node.getEndpoints() + ", " + + "Binding: " + node.getBindingTable() + ", " + + "Description: " + node.getNodeDescriptor() + ", " + + "Endpoints: " + node.getEndpoints() + ", " + "Power: " + node.getPowerDescriptor() ); @@ -73,11 +72,4 @@ public class ZigBeeDataStore implements ZigBeeNetworkDataStore { devices.remove(address); } - - - public static ZigBeeDataStore getInstance() { - if (instance == null) - instance = new ZigBeeDataStore(); - return instance; - } } diff --git a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/HalZigbeeController.java b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigbeeController.java similarity index 98% rename from plugins/hal-zigbee/src/se/hal/plugin/zigbee/HalZigbeeController.java rename to plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigbeeController.java index 3a9abcc4..3dfb36dc 100644 --- a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/HalZigbeeController.java +++ b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/ZigbeeController.java @@ -36,7 +36,7 @@ import java.util.logging.Logger; /** * Controller that will connect to a Zigbee USB coordinator. */ -public class HalZigbeeController implements HalSensorController, +public class ZigbeeController implements HalSensorController, HalEventController, HalAutostartController, HalScannableController, @@ -61,7 +61,7 @@ public class HalZigbeeController implements HalSensorController, private List registeredDevices = new ArrayList<>(); - public HalZigbeeController() {} + public ZigbeeController() {} // ------------------------------------------ // Lifecycle Methods @@ -86,7 +86,7 @@ public class HalZigbeeController implements HalSensorController, ZigBeeTransportTransmit dongle = getDongle(dongleName, serialPort, transportOptions); networkManager = new ZigBeeNetworkManager(dongle); - networkManager.setNetworkDataStore(ZigBeeDataStore.getInstance()); + networkManager.setNetworkDataStore(new ZigBeeHalDataStore(HalContext.getDB())); networkManager.setSerializer(DefaultSerializer.class, DefaultDeserializer.class); networkManager.addAnnounceListener(this); networkManager.addNetworkNodeListener(this); diff --git a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/device/ZigbeeHalDeviceConfig.java b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/device/ZigbeeHalDeviceConfig.java index 90718b35..7ceda7a9 100644 --- a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/device/ZigbeeHalDeviceConfig.java +++ b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/device/ZigbeeHalDeviceConfig.java @@ -5,25 +5,25 @@ import com.zsmartsystems.zigbee.zcl.ZclAttribute; import se.hal.intf.HalAbstractController; import se.hal.intf.HalDeviceConfig; import se.hal.intf.HalDeviceData; -import se.hal.plugin.zigbee.HalZigbeeController; +import se.hal.plugin.zigbee.ZigbeeController; +import zutil.ui.conf.Configurator; + +import java.util.Objects; /** * A generic class that is extended by all Endpoint config classes. */ public abstract class ZigbeeHalDeviceConfig implements HalDeviceConfig { + @Configurator.Configurable(value = "Node IeeeAddress") private String zigbeeNodeAddressStr; - private transient IeeeAddress zigbeeNodeAddress; public void setZigbeeNodeAddress(IeeeAddress zigbeeNodeAddress) { - this.zigbeeNodeAddress = zigbeeNodeAddress; this.zigbeeNodeAddressStr = zigbeeNodeAddress.toString(); } public IeeeAddress getZigbeeNodeAddress() { - if (zigbeeNodeAddress == null && zigbeeNodeAddressStr != null) - zigbeeNodeAddress = new IeeeAddress(zigbeeNodeAddressStr); - return zigbeeNodeAddress; + return new IeeeAddress(zigbeeNodeAddressStr); } // -------------------------- @@ -47,17 +47,16 @@ public abstract class ZigbeeHalDeviceConfig implements HalDeviceConfig { @Override public Class getDeviceControllerClass() { - return HalZigbeeController.class; + return ZigbeeController.class; } @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof ZigbeeHalDeviceConfig)) return false; ZigbeeHalDeviceConfig that = (ZigbeeHalDeviceConfig) o; - return zigbeeNodeAddress.equals(that.zigbeeNodeAddress) && - getZigbeeClusterId() == that.getZigbeeClusterId(); + return Objects.equals(zigbeeNodeAddressStr, that.zigbeeNodeAddressStr); } diff --git a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/page/ZigbeeNodeOverviewPage.java b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/page/ZigbeeNodeOverviewPage.java index 6c0875ac..16494dcf 100644 --- a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/page/ZigbeeNodeOverviewPage.java +++ b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/page/ZigbeeNodeOverviewPage.java @@ -5,7 +5,7 @@ import se.hal.HalContext; import se.hal.intf.HalAbstractController; import se.hal.intf.HalAbstractControllerManager; import se.hal.intf.HalWebPage; -import se.hal.plugin.zigbee.HalZigbeeController; +import se.hal.plugin.zigbee.ZigbeeController; import zutil.io.file.FileUtil; import zutil.parser.Templator; @@ -29,8 +29,8 @@ public class ZigbeeNodeOverviewPage extends HalWebPage { Set nodes = null; for (HalAbstractController controller : HalAbstractControllerManager.getControllers()) { - if (controller instanceof HalZigbeeController) { - nodes = ((HalZigbeeController) controller).getNodes(); + if (controller instanceof ZigbeeController) { + nodes = ((ZigbeeController) controller).getNodes(); break; } } diff --git a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/plugin.json b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/plugin.json index 778f79b0..2bf4d6f1 100644 --- a/plugins/hal-zigbee/src/se/hal/plugin/zigbee/plugin.json +++ b/plugins/hal-zigbee/src/se/hal/plugin/zigbee/plugin.json @@ -3,7 +3,12 @@ "name": "Hal-Zigbee", "description": "A Zigbee plugin for directly connecting to a CC2531 device over serial port.", "interfaces": [ - {"se.hal.intf.HalAutostartController": "se.hal.plugin.zigbee.HalZigbeeController"}, + {"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOnOffConfig"}, + {"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeHumidityConfig"}, + {"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeePressureConfig"}, + {"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeTemperatureConfig"}, + + {"se.hal.intf.HalAutostartController": "se.hal.plugin.zigbee.ZigbeeController"}, {"se.hal.intf.HalWebPage": "se.hal.plugin.zigbee.page.ZigbeeNodeOverviewPage"} ] diff --git a/plugins/hal-zigbee/test/se/hal/plugin/zigbee/HalZigbeeControllerTest.java b/plugins/hal-zigbee/test/se/hal/plugin/zigbee/HalZigbeeControllerTest.java index cfe15b2d..eb0036e5 100644 --- a/plugins/hal-zigbee/test/se/hal/plugin/zigbee/HalZigbeeControllerTest.java +++ b/plugins/hal-zigbee/test/se/hal/plugin/zigbee/HalZigbeeControllerTest.java @@ -47,8 +47,8 @@ public class HalZigbeeControllerTest { LogUtil.setGlobalFormatter(new CompactLogFormatter()); LogUtil.setGlobalLevel(Level.ALL); - HalZigbeeController controller = new HalZigbeeController(); - controller.initialize("COM5", HalZigbeeController.ZIGBEE_DONGLE_CC2531); + ZigbeeController controller = new ZigbeeController(); + controller.initialize("COM5", ZigbeeController.ZIGBEE_DONGLE_CC2531); controller.addListener(new HalDeviceReportListener() { @Override public void reportReceived(HalDeviceConfig deviceConfig, HalDeviceData deviceData) {