mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[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 <markus7017@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
b7aaf621f5
commit
a7eb60c15d
@ -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)
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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<ShellySettingsRoller> rollers;
|
||||
public @Nullable ArrayList<ShellySettingsRgbwLight> lights;
|
||||
public @Nullable ArrayList<ShellySettingsEMeter> emeters;
|
||||
@SerializedName("emeter_n")
|
||||
public ShellyEMNCurrentSettings neutralCurrent;
|
||||
public @Nullable ArrayList<ShellyThermnostat> thermostats; // TRV
|
||||
|
||||
@SerializedName("ext_switch_enable")
|
||||
@ -745,6 +764,9 @@ public class Shelly1ApiJsonDTO {
|
||||
public ArrayList<ShellySettingsMeter> meters;
|
||||
|
||||
public ArrayList<ShellySettingsEMeter> emeters;
|
||||
@SerializedName("emeter_n")
|
||||
public ShellyEMNCurrentStatus neutralCurrent;
|
||||
|
||||
public Double totalCurrent;
|
||||
public Double totalPower;
|
||||
public Double totalReturned;
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<String, Channel> createEMNCurrentChannels(final Thing thing, ShellyEMNCurrentSettings settings,
|
||||
ShellyEMNCurrentStatus status) {
|
||||
String group = CHANNEL_GROUP_NMETER;
|
||||
Map<String, Channel> 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<String, Channel> createSensorChannels(final Thing thing, final ShellyDeviceProfile profile,
|
||||
final ShellyStatusSensor sdata) {
|
||||
Map<String, Channel> newChannels = new LinkedHashMap<>();
|
||||
|
@ -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
|
||||
|
@ -77,6 +77,7 @@
|
||||
<channel-group id="meter3" typeId="meter">
|
||||
<label>@text/channel-group-type.shelly.meter3.label</label>
|
||||
</channel-group>
|
||||
<channel-group id="nmeter" typeId="nmeter"/>
|
||||
<channel-group id="relay" typeId="relayChannel"/>
|
||||
<channel-group id="device" typeId="deviceStatus"/>
|
||||
</channel-groups>
|
||||
@ -328,6 +329,11 @@
|
||||
<description>@text/channel-group-type.shelly.meter.description</description>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="nmeter">
|
||||
<label>@text/channel-group-type.shelly.nmeter.label</label>
|
||||
<description>@text/channel-group-type.shelly.nmeter.description</description>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="externalSensors">
|
||||
<label>@text/channel-group-type.shelly.externalSensors.label</label>
|
||||
<description>@text/channel-group-type.shelly.externalSensors.description</description>
|
||||
@ -604,6 +610,51 @@
|
||||
<description>@text/channel-type.shelly.meterResetTotals.description</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ncurrent">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>@text/channel-type.shelly.ncurrent.label</label>
|
||||
<description>@text/channel-type.shelly.ncurrent.description</description>
|
||||
<category>Energy</category>
|
||||
<tags>
|
||||
<tag>Measurement</tag>
|
||||
<tag>Energy</tag>
|
||||
</tags>
|
||||
<state readOnly="true" pattern="%.3f %unit%">
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ixsum">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>@text/channel-type.shelly.ixsum.label</label>
|
||||
<description>@text/channel-type.shelly.ixsum.description</description>
|
||||
<category>Energy</category>
|
||||
<tags>
|
||||
<tag>Measurement</tag>
|
||||
<tag>Energy</tag>
|
||||
</tags>
|
||||
<state readOnly="true" pattern="%.3f %unit%">
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nmTreshhold">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>@text/channel-type.shelly.nmTreshhold.label</label>
|
||||
<description>@text/channel-type.shelly.nmTreshhold.description</description>
|
||||
<category>Energy</category>
|
||||
<tags>
|
||||
<tag>Measurement</tag>
|
||||
<tag>Energy</tag>
|
||||
</tags>
|
||||
<state readOnly="true" pattern="%.3f %unit%">
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nmismatch">
|
||||
<item-type>Switch</item-type>
|
||||
<label>@text/channel-type.shelly.nmismatch.label</label>
|
||||
<description>@text/channel-type.shelly.nmismatch.description</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="timestamp">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>@text/channel-type.shelly.timestamp.label</label>
|
||||
|
Loading…
Reference in New Issue
Block a user