diff --git a/build.gradle b/build.gradle index 035447c8..8324bd5e 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ subprojects { apply plugin: 'java-library' dependencies { - implementation 'se.koc:zutil:1.0.312' + implementation 'se.koc:zutil:1.0.313' //implementation 'se.koc:zutil:1.0.0-SNAPSHOT' testImplementation 'junit:junit:4.12' diff --git a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTraitFactory.java b/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTraitFactory.java index 5f1a9b8d..0528a326 100644 --- a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTraitFactory.java +++ b/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/DeviceTraitFactory.java @@ -58,6 +58,9 @@ public class DeviceTraitFactory { case "se.hal.struct.devicedata.OpenClosedEventData": return new DeviceTrait[]{new OpenCloseTrait()}; + case "se.hal.struct.devicedata.ParticulateMatterSensorData": + return new DeviceTrait[]{new SensorStateTrait()}; + case "se.hal.struct.devicedata.PowerConsumptionSensorData": case "se.hal.struct.devicedata.LightSensorData": return new DeviceTrait[]{new SensorStateTrait()}; diff --git a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/SensorStateTrait.java b/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/SensorStateTrait.java index 804bb3a8..e3b16fca 100644 --- a/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/SensorStateTrait.java +++ b/plugins/hal-assistant-google/src/se/hal/plugin/assistant/google/trait/SensorStateTrait.java @@ -27,14 +27,14 @@ package se.hal.plugin.assistant.google.trait; import se.hal.intf.HalDeviceConfig; import se.hal.intf.HalDeviceData; -import se.hal.struct.devicedata.OpenClosedEventData; +import se.hal.struct.devicedata.ParticulateMatterSensorData; import java.util.ArrayList; import java.util.HashMap; /** - * https://developers.google.com/assistant/smarthome/traits/openclose + * https://developers.home.google.com/cloud-to-cloud/traits/sensorstate */ public class SensorStateTrait extends DeviceTrait { @@ -48,10 +48,14 @@ public class SensorStateTrait extends DeviceTrait { HashMap response = new HashMap<>(); ArrayList sensorStatesSupported = new ArrayList<>(); - /*sensorStatesSupported.add(new HashMap() {{ - put("name", xxx); - put("maxThresholdCelsius", 60); - }});*/ + sensorStatesSupported.add(new HashMap() {{ + if (config.getDeviceDataClass() == ParticulateMatterSensorData.class) { + put("name", "PM2.5"); + put("numericCapabilities", new HashMap() {{ + put("rawValueUnit", "MICROGRAMS_PER_CUBIC_METER"); + }}); + } + }}); response.put("sensorStatesSupported", sensorStatesSupported); return response; @@ -62,11 +66,13 @@ public class SensorStateTrait extends DeviceTrait { HashMap response = new HashMap<>(); ArrayList currentSensorStateData = new ArrayList<>(); - /*currentSensorStateData.add(new HashMap() {{ - put("name", xxx); - put("currentSensorState", xxx); - put("rawValue", xxx); - }});*/ + currentSensorStateData.add(new HashMap() {{ + if (data instanceof ParticulateMatterSensorData) { + put("name", "PM2.5"); + //put("currentSensorState", xxx); + put("rawValue", data.getData()); + } + }}); response.put("currentSensorStateData", currentSensorStateData); return response; diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java index aa98a2ec..63a7414f 100644 --- a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java +++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/HalMqttController.java @@ -27,14 +27,18 @@ package se.hal.plugin.mqtt; import se.hal.daemon.HalMulticastDnsDaemon; import se.hal.intf.*; import se.hal.plugin.mqtt.device.HalMqttDeviceConfig; +import se.hal.plugin.mqtt.device.HalMqttUnknownDeviceConfig; import zutil.InetUtil; +import zutil.ObjectUtil; import zutil.log.LogUtil; import zutil.net.mqtt.MqttBroker; import zutil.net.mqtt.MqttSubscriptionListener; import java.io.IOException; import java.net.InetAddress; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -96,16 +100,18 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti @Override public void dataPublished(String topic, byte[] data) { + logger.finest("MQTT data published(topic: " + topic + "): " + new String(data, StandardCharsets.UTF_8)); + List devices = topics.get(topic); + if (ObjectUtil.isEmpty(devices)) + devices = Arrays.asList(new HalMqttUnknownDeviceConfig(topic)); - if (devices != null && data.length > 0) { - for (HalMqttDeviceConfig deviceConfig : devices) { - HalDeviceData deviceData = deviceConfig.getDeviceData(data); + for (HalMqttDeviceConfig deviceConfig : devices) { + HalDeviceData deviceData = deviceConfig.getDeviceData(data); - if (deviceListeners != null) { - for (HalDeviceReportListener deviceListener : deviceListeners) { - deviceListener.reportReceived(deviceConfig, deviceData); - } + if (deviceListeners != null) { + for (HalDeviceReportListener deviceListener : deviceListeners) { + deviceListener.reportReceived(deviceConfig, deviceData); } } } 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 index ca5c99cb..a422ad4d 100644 --- a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceConfig.java +++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttDeviceConfig.java @@ -50,11 +50,12 @@ package se.hal.plugin.mqtt.device; import se.hal.intf.HalDeviceData; import se.hal.intf.HalEventController; -import se.hal.intf.HalEventData; import se.hal.intf.HalSensorConfig; import se.hal.plugin.mqtt.HalMqttController; import zutil.ui.conf.Configurator; +import java.util.Objects; + public abstract class HalMqttDeviceConfig implements HalSensorConfig { @Configurator.Configurable(value = "MQTT Topic") private String topic; @@ -97,10 +98,21 @@ public abstract class HalMqttDeviceConfig implements HalSensorConfig { // -------------------------- @Override - public boolean equals(Object obj) { - if (obj instanceof HalMqttDeviceConfig) - return topic.equals(((HalMqttDeviceConfig) obj).topic) && jsonPath.equals(((HalMqttDeviceConfig) obj).jsonPath); - return false; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + HalMqttDeviceConfig that = (HalMqttDeviceConfig) o; + + if (!Objects.equals(topic, that.topic)) return false; + return Objects.equals(jsonPath, that.jsonPath); + } + + @Override + public int hashCode() { + int result = topic != null ? topic.hashCode() : 0; + result = 31 * result + (jsonPath != null ? jsonPath.hashCode() : 0); + return result; } @Override diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttParticularMatterDeviceConfig.java b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttParticularMatterDeviceConfig.java index 41917238..ae908ffb 100644 --- a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttParticularMatterDeviceConfig.java +++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttParticularMatterDeviceConfig.java @@ -51,7 +51,7 @@ package se.hal.plugin.mqtt.device; import se.hal.intf.HalDeviceData; import se.hal.intf.HalEventController; import se.hal.plugin.mqtt.HalMqttController; -import se.hal.struct.devicedata.TemperatureSensorData; +import se.hal.struct.devicedata.ParticulateMatterSensorData; import zutil.ObjectUtil; import zutil.converter.Converter; import zutil.parser.DataNode; @@ -73,7 +73,7 @@ public class HalMqttParticularMatterDeviceConfig extends HalMqttDeviceConfig { @Override public Class getDeviceDataClass() { - return TemperatureSensorData.class; + return ParticulateMatterSensorData.class; } @Override @@ -84,11 +84,11 @@ public class HalMqttParticularMatterDeviceConfig extends HalMqttDeviceConfig { DataNode deviceDataValue = DataNodePath.search(getJsonPath(), json); if (deviceDataValue != null) - return new TemperatureSensorData(deviceDataValue.getDouble(), System.currentTimeMillis()); + return new ParticulateMatterSensorData(deviceDataValue.getDouble(), System.currentTimeMillis()); else return null; } - return new TemperatureSensorData(Converter.toInt(data), System.currentTimeMillis()); + return new ParticulateMatterSensorData(Converter.toInt(data), System.currentTimeMillis()); } @Override diff --git a/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttUnknownDeviceConfig.java b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttUnknownDeviceConfig.java new file mode 100644 index 00000000..d6a197f6 --- /dev/null +++ b/plugins/hal-mqtt/src/se/hal/plugin/mqtt/device/HalMqttUnknownDeviceConfig.java @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 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.HalDeviceData; +import se.hal.intf.HalEventController; +import se.hal.plugin.mqtt.HalMqttController; + +/** + * Represents a unknown device data type + */ +public class HalMqttUnknownDeviceConfig extends HalMqttDeviceConfig { + + + public HalMqttUnknownDeviceConfig(String topic) { + setTopic(topic); + } + + // -------------------------- + // Hal Methods + // -------------------------- + + @Override + public Class getDeviceControllerClass() { + return HalMqttController.class; + } + + @Override + public Class getDeviceDataClass() { + return null; + } + + @Override + public HalDeviceData getDeviceData(byte[] data) { + return null; + } + + @Override + public AggregationMethod getAggregationMethod() { + return AggregationMethod.AVERAGE; + } +}