Added power, voltage and current to MQTT parsing

This commit is contained in:
Ziver Koc 2024-12-28 20:55:37 +01:00
parent f68ec9a8e9
commit 17026db07e
11 changed files with 484 additions and 42 deletions

View file

@ -0,0 +1,41 @@
package se.hal.struct.devicedata;
import se.hal.intf.HalSensorData;
public class CurrentSensorData extends HalSensorData {
private double current;
public CurrentSensorData() { }
public CurrentSensorData(double current, long timestamp) {
this.current = current;
super.setTimestamp(timestamp);
}
@Override
public String toString(){
if (current < 0.1)
return current / 100 + " mA";
return current + " A";
}
// ----------------------------------------
// Storage methods
// ----------------------------------------
/**
* @return number representing Volts measured
*/
@Override
public double getData() {
return current;
}
@Override
public void setData(double current){
this.current = current;
}
}

View file

@ -0,0 +1,39 @@
package se.hal.struct.devicedata;
import se.hal.intf.HalSensorData;
public class VoltageSensorData extends HalSensorData {
private double voltage;
public VoltageSensorData() { }
public VoltageSensorData(double voltage, long timestamp) {
this.voltage = voltage;
super.setTimestamp(timestamp);
}
@Override
public String toString(){
return voltage+" V";
}
// ----------------------------------------
// Storage methods
// ----------------------------------------
/**
* @return number representing Volts measured
*/
@Override
public double getData() {
return voltage;
}
@Override
public void setData(double voltage){
this.voltage = voltage;
}
}

View file

@ -1,9 +1,6 @@
package se.hal.plugin.mqtt.detector;
import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttHumidityDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttParticularMatterDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttTemperatureDeviceConfig;
import se.hal.plugin.mqtt.device.*;
import zutil.ObjectUtil;
import zutil.parser.DataNode;
import zutil.parser.json.JSONParser;
@ -47,6 +44,12 @@ public class GenericMqttDetector implements HalMqttDetector {
case "pm25":
config = new HalMqttParticularMatterDeviceConfig(topic);
break;
case "voltage":
config = new HalMqttVoltageDeviceConfig(topic);
break;
case "current":
config = new HalMqttCurrentDeviceConfig(topic);
break;
}
if (config != null) {
@ -71,6 +74,14 @@ public class GenericMqttDetector implements HalMqttDetector {
HalMqttDeviceConfig config = new HalMqttParticularMatterDeviceConfig(topic, "$.pm25");
detectedDeviceConfigs.add(config);
}
if (jsonPayload.get("voltage") != null) {
HalMqttVoltageDeviceConfig sensor = new HalMqttVoltageDeviceConfig(topic, "$.voltage");
detectedDeviceConfigs.add(sensor);
}
if (jsonPayload.get("current") != null) {
HalMqttCurrentDeviceConfig event = new HalMqttCurrentDeviceConfig(topic, "$.current");
detectedDeviceConfigs.add(event);
}
}
return detectedDeviceConfigs;

View file

@ -3,8 +3,7 @@ package se.hal.plugin.mqtt.detector;
import se.hal.intf.HalDeviceConfig;
import se.hal.intf.HalDeviceData;
import se.hal.intf.HalDeviceReportListener;
import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttOnOffEventConfig;
import se.hal.plugin.mqtt.device.*;
import zutil.ObjectUtil;
import zutil.parser.DataNode;
import zutil.parser.json.JSONParser;
@ -37,6 +36,11 @@ public class Zigbee2mqttDetector implements HalMqttDetector {
detectedDeviceConfigs.add(event);
}
if (json.getString("power") != null) {
HalMqttPowerConsumptionDeviceConfig event = new HalMqttPowerConsumptionDeviceConfig(topic, "$.power");
detectedDeviceConfigs.add(event);
}
return detectedDeviceConfigs;
}
}

View file

@ -0,0 +1,105 @@
/*
* 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.HalDeviceData;
import se.hal.struct.devicedata.CurrentSensorData;
import se.hal.struct.devicedata.VoltageSensorData;
import zutil.ObjectUtil;
import zutil.converter.Converter;
import zutil.parser.DataNode;
import zutil.parser.DataNodePath;
import zutil.parser.json.JSONParser;
import java.nio.charset.StandardCharsets;
public class HalMqttCurrentDeviceConfig extends HalMqttSensorConfig {
public HalMqttCurrentDeviceConfig() {}
public HalMqttCurrentDeviceConfig(String topic) {
super(topic);
}
public HalMqttCurrentDeviceConfig(String topic, String jsonPath) {
super(topic, jsonPath);
}
// --------------------------
// Hal Methods
// --------------------------
@Override
public Class<? extends HalDeviceData> getDeviceDataClass() {
return CurrentSensorData.class;
}
@Override
public CurrentSensorData getDeviceData(byte[] data) {
if(ObjectUtil.isEmpty(data)) {
return null;
}
if (!ObjectUtil.isEmpty(getJsonPath())) {
String dataStr = new String(data, StandardCharsets.UTF_8);
DataNode json = JSONParser.read(dataStr);
DataNode deviceDataValue = DataNodePath.search(getJsonPath(), json);
if (deviceDataValue != null) {
return new CurrentSensorData(deviceDataValue.getDouble(), System.currentTimeMillis());
} else {
return null;
}
}
return new CurrentSensorData(Converter.toInt(data), System.currentTimeMillis());
}
@Override
public AggregationMethod getAggregationMethod() {
return AggregationMethod.AVERAGE;
}
}

View file

@ -9,6 +9,7 @@ import zutil.parser.json.JSONParser;
import zutil.ui.conf.Configurator;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class HalMqttOnOffEventConfig extends HalMqttEventConfig {

View file

@ -0,0 +1,105 @@
/*
* 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.HalDeviceData;
import se.hal.struct.devicedata.HumiditySensorData;
import se.hal.struct.devicedata.PowerConsumptionSensorData;
import zutil.ObjectUtil;
import zutil.converter.Converter;
import zutil.parser.DataNode;
import zutil.parser.DataNodePath;
import zutil.parser.json.JSONParser;
import java.nio.charset.StandardCharsets;
public class HalMqttPowerConsumptionDeviceConfig extends HalMqttSensorConfig {
public HalMqttPowerConsumptionDeviceConfig() {}
public HalMqttPowerConsumptionDeviceConfig(String topic) {
super(topic);
}
public HalMqttPowerConsumptionDeviceConfig(String topic, String jsonPath) {
super(topic, jsonPath);
}
// --------------------------
// Hal Methods
// --------------------------
@Override
public Class<? extends HalDeviceData> getDeviceDataClass() {
return PowerConsumptionSensorData.class;
}
@Override
public PowerConsumptionSensorData getDeviceData(byte[] data) {
if(ObjectUtil.isEmpty(data)) {
return null;
}
if (!ObjectUtil.isEmpty(getJsonPath())) {
String dataStr = new String(data, StandardCharsets.UTF_8);
DataNode json = JSONParser.read(dataStr);
DataNode deviceDataValue = DataNodePath.search(getJsonPath(), json);
if (deviceDataValue != null) {
return new PowerConsumptionSensorData(deviceDataValue.getDouble(), System.currentTimeMillis());
} else {
return null;
}
}
return new PowerConsumptionSensorData(Converter.toInt(data), System.currentTimeMillis());
}
@Override
public AggregationMethod getAggregationMethod() {
return AggregationMethod.AVERAGE;
}
}

View file

@ -0,0 +1,105 @@
/*
* 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.HalDeviceData;
import se.hal.struct.devicedata.PowerConsumptionSensorData;
import se.hal.struct.devicedata.VoltageSensorData;
import zutil.ObjectUtil;
import zutil.converter.Converter;
import zutil.parser.DataNode;
import zutil.parser.DataNodePath;
import zutil.parser.json.JSONParser;
import java.nio.charset.StandardCharsets;
public class HalMqttVoltageDeviceConfig extends HalMqttSensorConfig {
public HalMqttVoltageDeviceConfig() {}
public HalMqttVoltageDeviceConfig(String topic) {
super(topic);
}
public HalMqttVoltageDeviceConfig(String topic, String jsonPath) {
super(topic, jsonPath);
}
// --------------------------
// Hal Methods
// --------------------------
@Override
public Class<? extends HalDeviceData> getDeviceDataClass() {
return VoltageSensorData.class;
}
@Override
public VoltageSensorData getDeviceData(byte[] data) {
if(ObjectUtil.isEmpty(data)) {
return null;
}
if (!ObjectUtil.isEmpty(getJsonPath())) {
String dataStr = new String(data, StandardCharsets.UTF_8);
DataNode json = JSONParser.read(dataStr);
DataNode deviceDataValue = DataNodePath.search(getJsonPath(), json);
if (deviceDataValue != null) {
return new VoltageSensorData(deviceDataValue.getDouble(), System.currentTimeMillis());
} else {
return null;
}
}
return new VoltageSensorData(Converter.toInt(data), System.currentTimeMillis());
}
@Override
public AggregationMethod getAggregationMethod() {
return AggregationMethod.AVERAGE;
}
}

View file

@ -8,9 +8,12 @@
{"se.hal.plugin.mqtt.detector.HalMqttDetector": "se.hal.plugin.mqtt.detector.TasmotaMqttDetector"},
{"se.hal.plugin.mqtt.detector.HalMqttDetector": "se.hal.plugin.mqtt.detector.Zigbee2mqttDetector"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttCurrentDeviceConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttHumidityDeviceConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttParticularMatterDeviceConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttPowerConsumptionDeviceConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttTemperatureDeviceConfig"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttVoltageDeviceConfig"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.mqtt.device.HalMqttOnOffEventConfig"},

View file

@ -1,10 +1,7 @@
package se.hal.plugin.mqtt.detector;
import org.junit.Test;
import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttHumidityDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttParticularMatterDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttTemperatureDeviceConfig;
import se.hal.plugin.mqtt.device.*;
import se.hal.struct.devicedata.HumiditySensorData;
import se.hal.struct.devicedata.ParticulateMatterSensorData;
import se.hal.struct.devicedata.TemperatureSensorData;
@ -90,4 +87,45 @@ public class GenericMqttDetectorTest {
devices.get(0));
}
@Test
public void parseVoltage() {
GenericMqttDetector detector = new GenericMqttDetector();
List<HalMqttDeviceConfig> devices = detector.parseTopic(
"zigbee2mqtt/Kitchen air quality/voltage",
Converter.toBytes(1));
assertEquals(1, devices.size());
assertEquals(
new HalMqttVoltageDeviceConfig("zigbee2mqtt/Kitchen air quality/voltage"),
devices.get(0));
devices = detector.parseTopic(
"zigbee2mqtt/Kitchen air quality",
"{\"voltage\": 1}".getBytes(StandardCharsets.UTF_8));
assertEquals(1, devices.size());
assertEquals(
new HalMqttVoltageDeviceConfig("zigbee2mqtt/Kitchen air quality", "$.voltage"),
devices.get(0));
}
@Test
public void parseCurrent() {
GenericMqttDetector detector = new GenericMqttDetector();
List<HalMqttDeviceConfig> devices = detector.parseTopic(
"zigbee2mqtt/Kitchen air quality/current",
Converter.toBytes(1));
assertEquals(1, devices.size());
assertEquals(
new HalMqttCurrentDeviceConfig("zigbee2mqtt/Kitchen air quality/current"),
devices.get(0));
devices = detector.parseTopic(
"zigbee2mqtt/Kitchen air quality",
"{\"current\": 1}".getBytes(StandardCharsets.UTF_8));
assertEquals(1, devices.size());
assertEquals(
new HalMqttCurrentDeviceConfig("zigbee2mqtt/Kitchen air quality", "$.current"),
devices.get(0));
}
}

View file

@ -4,7 +4,9 @@ import org.junit.Test;
import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttOnOffEventConfig;
import se.hal.plugin.mqtt.device.HalMqttParticularMatterDeviceConfig;
import se.hal.plugin.mqtt.device.HalMqttPowerConsumptionDeviceConfig;
import se.hal.test.MockHalDeviceReportListener;
import zutil.converter.Converter;
import java.nio.charset.StandardCharsets;
import java.util.List;
@ -24,45 +26,33 @@ public class Zigbee2mqttDetectorTest {
devices = detector.parseTopic("invalid/topic", new byte[]{});
assertEquals(0, devices.size());
devices = detector.parseTopic("zigbee2mqtt/Kitchen Plant Light", "{\"power\":10.48,\"state\":\"ON\"}".getBytes(StandardCharsets.UTF_8));
HalMqttOnOffEventConfig actualOnOff = new HalMqttOnOffEventConfig("zigbee2mqtt/Kitchen Plant Light", "$.state");
actualOnOff.setWriteTopicName("zigbee2mqtt/Kitchen Plant Light/set");
}
@Test
public void parseState() {
Zigbee2mqttDetector detector = new Zigbee2mqttDetector();
List<HalMqttDeviceConfig> devices = devices = detector.parseTopic(
"zigbee2mqtt/Kitchen Plant Light",
"{\"invalid_power\":10.48,\"state\":\"ON\"}".getBytes(StandardCharsets.UTF_8));
assertEquals(1, devices.size());
HalMqttOnOffEventConfig actualOnOff = new HalMqttOnOffEventConfig("zigbee2mqtt/Kitchen Plant Light", "$.state");
actualOnOff.setWriteTopicName("zigbee2mqtt/Kitchen Plant Light/set/state");
assertEquals(actualOnOff, devices.get(0));
}
/*
@Test
public void parseTemperature() {
Zigbee2mqttDetector detector = new Zigbee2mqttDetector();
assertEquals(
Collections.emptyList(),
detector.parseTopic(
"zigbee2mqtt/Kitchen air quality",
"{\"temperature\":26}".getBytes(StandardCharsets.UTF_8)));
}
@Test
public void parseHumidity() {
public void parsePower() {
Zigbee2mqttDetector detector = new Zigbee2mqttDetector();
List<HalMqttDeviceConfig> devices = detector.parseTopic(
"zigbee2mqtt/Kitchen air quality",
"{\"power\": 1}".getBytes(StandardCharsets.UTF_8));
assertEquals(1, devices.size());
assertEquals(
Collections.emptyList(),
detector.parseTopic(
"zigbee2mqtt/Kitchen air quality",
"{\"humidity\":51}".getBytes(StandardCharsets.UTF_8)));
new HalMqttPowerConsumptionDeviceConfig("zigbee2mqtt/Kitchen air quality", "$.power"),
devices.get(0));
}
@Test
public void parseParticularMatter() {
Zigbee2mqttDetector detector = new Zigbee2mqttDetector();
assertEquals(
Collections.list(new HalMqttParticularMatterDeviceConfig()),
detector.parseTopic(
"zigbee2mqtt/Kitchen air quality",
"{\"pm25\":1}".getBytes(StandardCharsets.UTF_8)));
}
*/
}