From: Markus Michels Date: Sat, 17 Feb 2024 14:36:20 +0000 (+0100) Subject: [shelly] New channel group ncurrent for 3EM (#16336) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=4ca013d99bb055ab6a30835c78c4d9bceeff83ec;p=openhab-addons.git [shelly] New channel group ncurrent for 3EM (#16336) * Add channels for emeter_n (neutral current-based measurements) - polled status and CoAP update (ncurrent only, no other values) Signed-off-by: Markus Michels --- diff --git a/bundles/org.openhab.binding.shelly/README.md b/bundles/org.openhab.binding.shelly/README.md index 89b34d8e41..389e8ed818 100644 --- a/bundles/org.openhab.binding.shelly/README.md +++ b/bundles/org.openhab.binding.shelly/README.md @@ -492,7 +492,7 @@ In this case the is no real measurement based on power consumption, but the Shel | | input | Switch | yes | ON: Input/Button is powered, see General Notes on Channels | | | button | Trigger | yes | Event trigger, see section Button Events | | meter | currentWatts | Number | yes | Current power consumption in Watts | -| | lastPower1 | Number | yes | Energy consumption for a round minute, 1 minute ago | +| | lastPower1 | Number | yes | The average power for the previous minute | | | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) | | | | | | | | | lastUpdate | DateTime | yes | Timestamp of the last measurement | @@ -573,6 +573,15 @@ The Thing id is derived from the service name, so that's the reason why the Thin | | powerFactor | Number | yes | Power Factor in percent | | | resetTotals | Switch | yes | ON: Resets total values for the power meter | | | lastUpdate | DateTime | yes | Timestamp of the last measurement | +| nmeter | ncurrent | Number | yes | Current current based on N clamp (requires calibration) | +| | ixsum | Number | yes | Measured current over all phases | +| | nmismatch | Switch | yes | ON: abs(ncurrent-ixsum) is greater than nmTreshhold | +| | nmTreshhold | Number | yes | Treshhod (delta) before nMismatch goes ON | + +_Note: +You should calibrate the device if you want to use "neutral current" measurements. +Check the Shelly documentation for details._ + ### Shelly 2 - relay mode (thing-type: shelly2-relay) diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java index ba0fd6b0ee..1dcf6dd99c 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java @@ -178,6 +178,11 @@ public class ShellyBindingConstants { public static final String CHANNEL_EMETER_CURRENT = "current"; public static final String CHANNEL_EMETER_PFACTOR = "powerFactor"; public static final String CHANNEL_EMETER_RESETTOTAL = "resetTotals"; + public static final String CHANNEL_GROUP_NMETER = "nmeter"; + public static final String CHANNEL_NMETER_CURRENT = "ncurrent"; + public static final String CHANNEL_NMETER_IXSUM = "ixsum"; + public static final String CHANNEL_NMETER_MISMATCH = "nmismatch"; + public static final String CHANNEL_NMETER_MTRESHHOLD = "nmTreshhold"; public static final String CHANNEL_GROUP_SENSOR = "sensors"; public static final String CHANNEL_SENSOR_TEMP = "temperature"; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java index ec99dda4b7..ffb2e35667 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java @@ -553,6 +553,23 @@ public class Shelly1ApiJsonDTO { public Double current; // 3EM } + public static class ShellyEMNCurrentSettings { + // "emeter_n":{ "range_extender":1, "mismatch_threshold":0.00} + @SerializedName("range_extender") + public Integer rangeExtender; + @SerializedName("mismatch_threshold") + public Double mismatchThreshold; + } + + public static class ShellyEMNCurrentStatus { + // "emeter_n":{"current":2.28,"ixsum":2.29,"mismatch":false,"is_valid":true} + public Double current; + public Double ixsum; + public Boolean mismatch; + @SerializedName("is_valid") + public Boolean isValid; + } + public static class ShellySettingsUpdate { public String status; @SerializedName("has_update") @@ -621,6 +638,8 @@ public class Shelly1ApiJsonDTO { public @Nullable ArrayList rollers; public @Nullable ArrayList lights; public @Nullable ArrayList emeters; + @SerializedName("emeter_n") + public ShellyEMNCurrentSettings neutralCurrent; public @Nullable ArrayList thermostats; // TRV @SerializedName("ext_switch_enable") @@ -745,6 +764,9 @@ public class Shelly1ApiJsonDTO { public ArrayList meters; public ArrayList emeters; + @SerializedName("emeter_n") + public ShellyEMNCurrentStatus neutralCurrent; + public Double totalCurrent; public Double totalPower; public Double totalReturned; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java index fc29530369..8dce4010b3 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion2.java @@ -142,9 +142,6 @@ public class Shelly1CoIoTVersion2 extends Shelly1CoIoTProtocol implements Shelly processed = true; switch (sen.id) { - case "6": // 3EM: neutralCurrent - break; - case "3106": // L, luminosity, lux, U32, -1 case "3110": // S, luminosityLevel, dark/twilight/bright, "unknown"=unknown case "3111": // B, battery, 0-100%, unknown -1 @@ -307,7 +304,7 @@ public class Shelly1CoIoTVersion2 extends Shelly1CoIoTProtocol implements Shelly case "4209": // emeter_1: A, current, 0/120A, -1 case "4309": // emeter_2: A, current, 0/120A, -1 updateChannel(updates, rGroup, CHANNEL_EMETER_CURRENT, - toQuantityType(getDouble(s.value), DIGITS_VOLT, Units.AMPERE)); + toQuantityType(getDouble(s.value), DIGITS_AMPERE, Units.AMPERE)); break; case "4110": // emeter_0: S, powerFactor, 0/1, -1 @@ -316,6 +313,11 @@ public class Shelly1CoIoTVersion2 extends Shelly1CoIoTProtocol implements Shelly updateChannel(updates, rGroup, CHANNEL_EMETER_PFACTOR, getDecimal(s.value)); break; + case "6": // 3EM: emeter_n: nCurrent + updateChannel(updates, CHANNEL_GROUP_NMETER, CHANNEL_NMETER_CURRENT, + toQuantityType(value, DIGITS_AMPERE, Units.AMPERE)); + break; + case "5101": // {"I":5101,"T":"S","D":"brightness","R":"0/100","L":1}, case "5102": // {"I":5102,"T":"S","D":"gain","R":"0/100","L":1}, case "5103": // {"I":5103,"T":"S","D":"colorTemp","U":"K","R":"3000/6500","L":1}, diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java index 9ab5e29c39..d3fe61dc63 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoapHandler.java @@ -362,6 +362,7 @@ public class Shelly1CoapHandler implements Shelly1CoapListener { if (!valid) { logger.debug("{}: WARNING: Incompatible device description detected for CoIoT version {}!", thingName, coiot.getVersion()); + return; } coiot.completeMissingSensorDefinition(sensorMap); // fix incomplete format @@ -386,8 +387,8 @@ public class Shelly1CoapHandler implements Shelly1CoapListener { // This happens on firmware up/downgrades (version 1.8 brings CoIoT v2 with 4 digit IDs) int vers = coiot.getVersion(); if (((vers == COIOT_VERSION_1) && (sen.id.length() > 3)) - || ((vers >= COIOT_VERSION_2) && (sen.id.length() < 4))) { - logger.debug("{}: Invalid format for sensor defition detected, id={}", thingName, sen.id); + || ((vers >= COIOT_VERSION_2) && (sen.id.length() < 4) && !sen.id.equals("6"))) { + logger.debug("{}: Invalid format for sensor definition detected, id={}", thingName, sen.id); return false; } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java index fe6e70a5cd..1d5a0cc133 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java @@ -264,6 +264,25 @@ public class ShellyComponents { m++; } } else { + if (status.neutralCurrent != null) { + if (!thingHandler.areChannelsCreated()) { + thingHandler.updateChannelDefinitions(ShellyChannelDefinitions.createEMNCurrentChannels( + thingHandler.getThing(), profile.settings.neutralCurrent, status.neutralCurrent)); + } + if (getBool(status.neutralCurrent.isValid)) { + String ngroup = CHANNEL_GROUP_NMETER; + updated |= thingHandler.updateChannel(ngroup, CHANNEL_NMETER_CURRENT, toQuantityType( + getDouble(status.neutralCurrent.current), DIGITS_AMPERE, Units.AMPERE)); + updated |= thingHandler.updateChannel(ngroup, CHANNEL_NMETER_IXSUM, toQuantityType( + getDouble(status.neutralCurrent.ixsum), DIGITS_AMPERE, Units.AMPERE)); + updated |= thingHandler.updateChannel(ngroup, CHANNEL_NMETER_MTRESHHOLD, + toQuantityType(getDouble(profile.settings.neutralCurrent.mismatchThreshold), + DIGITS_AMPERE, Units.AMPERE)); + updated |= thingHandler.updateChannel(ngroup, CHANNEL_NMETER_MISMATCH, + getOnOff(status.neutralCurrent.mismatch)); + } + } + for (ShellySettingsEMeter emeter : status.emeters) { if (getBool(emeter.isValid)) { String groupName = profile.getMeterGroup(m); diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java index 3c7d1af24b..5ad1b45682 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java @@ -31,6 +31,8 @@ import javax.measure.Unit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyEMNCurrentSettings; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyEMNCurrentStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyInputState; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; @@ -94,6 +96,7 @@ public class ShellyChannelDefinitions { private static final String CHGR_LIGHTCH = CHANNEL_GROUP_LIGHT_CHANNEL; private static final String CHGR_STATUS = CHANNEL_GROUP_STATUS; private static final String CHGR_METER = CHANNEL_GROUP_METER; + private static final String CHGR_EMN = CHANNEL_GROUP_NMETER; private static final String CHGR_SENSOR = CHANNEL_GROUP_SENSOR; private static final String CHGR_CONTROL = CHANNEL_GROUP_CONTROL; private static final String CHGR_BAT = CHANNEL_GROUP_BATTERY; @@ -203,6 +206,12 @@ public class ShellyChannelDefinitions { .add(new ShellyChannel(m, CHGR_METER, CHANNEL_EMETER_PFACTOR, "meterPowerFactor", ITEMT_NUMBER)) .add(new ShellyChannel(m, CHGR_METER, CHANNEL_EMETER_RESETTOTAL, "meterResetTotals", ITEMT_SWITCH)) + // 3EM: neutral current (emeter_n) + .add(new ShellyChannel(m, CHGR_EMN, CHANNEL_NMETER_CURRENT, "ncurrent", ITEMT_AMP)) + .add(new ShellyChannel(m, CHGR_EMN, CHANNEL_NMETER_IXSUM, "ixsum", ITEMT_AMP)) + .add(new ShellyChannel(m, CHGR_EMN, CHANNEL_NMETER_MTRESHHOLD, "nmTreshhold", ITEMT_AMP)) + .add(new ShellyChannel(m, CHGR_EMN, CHANNEL_NMETER_MISMATCH, "nmismatch", ITEMT_SWITCH)) + // Sensors .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_TEMP, "sensorTemp", ITEMT_TEMP)) .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_HUM, "sensorHumidity", ITEMT_PERCENT)) @@ -264,13 +273,13 @@ public class ShellyChannelDefinitions { String group = substringBefore(channelName, "#"); String channel = substringAfter(channelName, "#"); - if (group.contains(CHANNEL_GROUP_METER)) { + if (group.startsWith(CHANNEL_GROUP_METER)) { group = CHANNEL_GROUP_METER; // map meter1..n to meter - } else if (group.contains(CHANNEL_GROUP_RELAY_CONTROL)) { + } else if (group.startsWith(CHANNEL_GROUP_RELAY_CONTROL)) { group = CHANNEL_GROUP_RELAY_CONTROL; // map meter1..n to meter - } else if (group.contains(CHANNEL_GROUP_LIGHT_CHANNEL)) { + } else if (group.startsWith(CHANNEL_GROUP_LIGHT_CHANNEL)) { group = CHANNEL_GROUP_LIGHT_CHANNEL; - } else if (group.contains(CHANNEL_GROUP_STATUS)) { + } else if (group.startsWith(CHANNEL_GROUP_STATUS)) { group = CHANNEL_GROUP_STATUS; // map status1..n to meter } @@ -491,6 +500,17 @@ public class ShellyChannelDefinitions { return newChannels; } + public static Map createEMNCurrentChannels(final Thing thing, ShellyEMNCurrentSettings settings, + ShellyEMNCurrentStatus status) { + String group = CHANNEL_GROUP_NMETER; + Map newChannels = new LinkedHashMap<>(); + addChannel(thing, newChannels, status.current != null, group, CHANNEL_NMETER_CURRENT); + addChannel(thing, newChannels, status.ixsum != null, group, CHANNEL_NMETER_IXSUM); + addChannel(thing, newChannels, status.mismatch != null, group, CHANNEL_NMETER_MISMATCH); + addChannel(thing, newChannels, settings.mismatchThreshold != null, group, CHANNEL_NMETER_MTRESHHOLD); + return newChannels; + } + public static Map createSensorChannels(final Thing thing, final ShellyDeviceProfile profile, final ShellyStatusSensor sdata) { Map newChannels = new LinkedHashMap<>(); diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties index 987c3e5089..2e90f78618 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties @@ -222,6 +222,8 @@ channel-group-type.shelly.meter2.label = Power Meter 2 channel-group-type.shelly.meter3.label = Power Meter 3 channel-group-type.shelly.meter4.label = Power Meter 4 channel-group-type.shelly.meter.description = Power consumption for the relay +channel-group-type.shelly.nmeter.label = Neutral Current +channel-group-type.shelly.nmeter.description = Based measurements based on the N clamp (has to be calibrated) channel-group-type.shelly.externalSensors.label = External Sensors channel-group-type.shelly.externalSensors.description = Temperatures from external sensors connected to the optional Addon @@ -310,6 +312,14 @@ channel-type.shelly.meterCurrent.label = Current channel-type.shelly.meterCurrent.description = Current in A channel-type.shelly.meterPowerFactor.label = Power Factor channel-type.shelly.meterPowerFactor.description = Power Factor in percent for photovoltaic +channel-type.shelly.ncurrent.label = Neutral Current +channel-type.shelly.ncurrent.description = Measured neutral current +channel-type.shelly.ixsum.label = Accumulated Current +channel-type.shelly.ixsum.description = Sum of measured current on all phases +channel-type.shelly.nmismatch.label = N-Current Mismatch +channel-type.shelly.nmismatch.description = ON: Sum of all signed currents of the 4 wires is greater than the configured N Current Treshhold +channel-type.shelly.nmTreshhold.label = Mismatch Treshhold +channel-type.shelly.nmTreshhold.description = Mismatch becomes ON when treshhold is exceeded channel-type.shelly.timestamp.label = Last Update channel-type.shelly.timestamp.description = Timestamp of last measurement channel-type.shelly.ledStatusDisable.label = Disable Status LED diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml index 0a252956ac..5e0fb73711 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml @@ -77,6 +77,7 @@ + @@ -328,6 +329,11 @@ @text/channel-group-type.shelly.meter.description + + + @text/channel-group-type.shelly.nmeter.description + + @text/channel-group-type.shelly.externalSensors.description @@ -604,6 +610,51 @@ @text/channel-type.shelly.meterResetTotals.description + + Number:ElectricCurrent + + @text/channel-type.shelly.ncurrent.description + Energy + + Measurement + Energy + + + + + + + Number:ElectricCurrent + + @text/channel-type.shelly.ixsum.description + Energy + + Measurement + Energy + + + + + + + Number:ElectricCurrent + + @text/channel-type.shelly.nmTreshhold.description + Energy + + Measurement + Energy + + + + + + + Switch + + @text/channel-type.shelly.nmismatch.description + + DateTime