Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[jeelink] Add support for emt7110 energy meter #16725

Merged
merged 6 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ private JeeLinkBindingConstants() {
public static final ThingTypeUID LACROSSE_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "lacrosse");
public static final ThingTypeUID EC3000_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "ec3k");
public static final ThingTypeUID PCA301_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "pca301");
public static final ThingTypeUID EMT7110_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "emt7110");
public static final ThingTypeUID TX22_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "tx22");
public static final ThingTypeUID REVOLT_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "revolt");
public static final ThingTypeUID LGW_SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, "lgw");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.stream.Stream;

import org.openhab.binding.jeelink.internal.ec3k.Ec3kSensorDefinition;
import org.openhab.binding.jeelink.internal.emt7110.Emt7110SensorDefinition;
import org.openhab.binding.jeelink.internal.lacrosse.LaCrosseSensorDefinition;
import org.openhab.binding.jeelink.internal.lacrosse.LgwSensorDefinition;
import org.openhab.binding.jeelink.internal.lacrosse.Tx22SensorDefinition;
Expand All @@ -36,9 +37,9 @@
public abstract class SensorDefinition<R extends Reading> {
public static final String ALL_TYPE = "All";

private static final Set<SensorDefinition<?>> SENSOR_DEFS = Stream
.of(new LaCrosseSensorDefinition(), new Ec3kSensorDefinition(), new Pca301SensorDefinition(),
new Tx22SensorDefinition(), new RevoltSensorDefinition(), new LgwSensorDefinition())
private static final Set<SensorDefinition<?>> SENSOR_DEFS = Stream.of(new LaCrosseSensorDefinition(),
new Ec3kSensorDefinition(), new Pca301SensorDefinition(), new Emt7110SensorDefinition(),
new Tx22SensorDefinition(), new RevoltSensorDefinition(), new LgwSensorDefinition())
.collect(Collectors.toSet());
private static final Set<JeeLinkReadingConverter<?>> CONVERTERS = SENSOR_DEFS.stream()
.map(SensorDefinition::createConverter).collect(Collectors.toSet());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.jeelink.internal.config;

/**
* Configuration for a EMT7110SensorHandler.
*
* @author Timo Schober - Initial contribution
*/
public class EMT7110SensorConfig extends JeeLinkSensorConfig {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.jeelink.internal.emt7110;

import org.openhab.binding.jeelink.internal.Reading;

/**
* Handler for a EMT7110 energy Sensor thing.
*
* @author Timo Schober - Initial contribution
*/
public class Emt7110Reading implements Reading {
private final String sensorId;
private final float voltage;
private final float current;
private final float power;
private final float aPower;
private final boolean on;

public Emt7110Reading(String sensorId, float voltage, float current, float power, float aPower, boolean deviceOn) {
this.sensorId = sensorId;
this.voltage = voltage;
this.current = current;
this.power = power;
this.aPower = aPower;
this.on = deviceOn;
}

@Override
public String getSensorId() {
return sensorId;
}

public int getChannel() {
return 0;
}

public float getVoltage() {
return voltage;
}

public float getCurrent() {
return current;
}

public boolean isOn() {
return on;
}

public float getPower() {
return power;
}

public float getaPower() {
return aPower;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.jeelink.internal.emt7110;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openhab.binding.jeelink.internal.JeeLinkReadingConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Handler for a EMT7110 energy Sensor thing.
*
* @author Timo Schober - Initial contribution
*/
public class Emt7110ReadingConverter implements JeeLinkReadingConverter<Emt7110Reading> {
private static final Pattern READING_P = Pattern.compile(
"OK EMT7110\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)");

private final Logger logger = LoggerFactory.getLogger(Emt7110ReadingConverter.class);
tischober marked this conversation as resolved.
Show resolved Hide resolved

@Override
public Emt7110Reading createReading(String inputLine) {
// parse lines only if we have registered listeners
if (inputLine != null) {
Matcher matcher = READING_P.matcher(inputLine);
if (matcher.matches()) {
String id = matcher.group(1) + matcher.group(2);
float voltage = (Integer.parseInt(matcher.group(3)) * 256 + Integer.parseInt(matcher.group(4))) / 10f;
float current = (Integer.parseInt(matcher.group(5)) * 256 + Integer.parseInt(matcher.group(6)));
float power = (Integer.parseInt(matcher.group(7)) * 256 + Integer.parseInt(matcher.group(8)));
float aPower = (Integer.parseInt(matcher.group(9)) * 256 + Integer.parseInt(matcher.group(10))) / 100f;

return new Emt7110Reading(id, voltage, current, power, aPower, true);
}
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.jeelink.internal.emt7110;

import org.openhab.binding.jeelink.internal.JeeLinkBindingConstants;
import org.openhab.binding.jeelink.internal.JeeLinkReadingConverter;
import org.openhab.binding.jeelink.internal.JeeLinkSensorHandler;
import org.openhab.binding.jeelink.internal.SensorDefinition;
import org.openhab.core.thing.Thing;

/**
* Handler for a EMT7110 energy Sensor thing.
*
* @author Timo Schober - Initial contribution
*/
public class Emt7110SensorDefinition extends SensorDefinition<Emt7110Reading> {

public Emt7110SensorDefinition() {
super(JeeLinkBindingConstants.EMT7110_SENSOR_THING_TYPE, "EMT7110 power monitoring wireless socket", "EMT");
}

@Override
public JeeLinkReadingConverter<Emt7110Reading> createConverter() {
return new Emt7110ReadingConverter();
}

@Override
public Class<Emt7110Reading> getReadingClass() {
return Emt7110Reading.class;
}

@Override
public JeeLinkSensorHandler<Emt7110Reading> createHandler(Thing thing) {
return new Emt7110SensorHandler(thing, type);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.jeelink.internal.emt7110;

import static org.openhab.binding.jeelink.internal.JeeLinkBindingConstants.*;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;

import org.openhab.binding.jeelink.internal.JeeLinkHandler;
tischober marked this conversation as resolved.
Show resolved Hide resolved
import org.openhab.binding.jeelink.internal.JeeLinkSensorHandler;
import org.openhab.binding.jeelink.internal.ReadingPublisher;
import org.openhab.core.library.types.OnOffType;
tischober marked this conversation as resolved.
Show resolved Hide resolved
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Handler for an EMT7110 sensor thing.
*
* @author Timo Schober - Initial contribution
*/
public class Emt7110SensorHandler extends JeeLinkSensorHandler<Emt7110Reading> {
private final Logger logger = LoggerFactory.getLogger(Emt7110SensorHandler.class);
private OnOffType state;
private JeeLinkHandler bridge;
private final AtomicInteger channel = new AtomicInteger(-1);

private ScheduledFuture<?> retry;
tischober marked this conversation as resolved.
Show resolved Hide resolved

public Emt7110SensorHandler(Thing thing, String sensorType) {
super(thing, sensorType);
}

@Override
public Class<Emt7110Reading> getReadingClass() {
return Emt7110Reading.class;
}

@Override
public void initialize() {
super.initialize();

bridge = (JeeLinkHandler) getBridge().getHandler();

tischober marked this conversation as resolved.
Show resolved Hide resolved
logger.debug("initilized handler for thing {} ({})}", getThing().getLabel(), getThing().getUID().getId());
}

@Override
public void dispose() {
super.dispose();
cancelRetry();
tischober marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public synchronized void handleCommand(ChannelUID channelUid, Command command) {
logger.debug("received command for thing {} ({}): {}", getThing().getLabel(), getThing().getUID().getId(),
command);
}

@Override
public ReadingPublisher<Emt7110Reading> createPublisher() {
return new ReadingPublisher<>() {
@Override
public void publish(Emt7110Reading reading) {
if (reading != null) {
updateState(CURRENT_POWER_CHANNEL, new QuantityType<>(reading.getPower(), Units.WATT));
updateState(CONSUMPTION_CHANNEL, new QuantityType<>(reading.getaPower(), Units.KILOWATT_HOUR));
updateState(ELECTRIC_POTENTIAL_CHANNEL, new QuantityType<>(reading.getVoltage(), Units.VOLT));
updateState(ELECTRIC_CURRENT_CHANNEL,
new QuantityType<>(reading.getCurrent() / 1000, Units.AMPERE));
}
}

@Override
public void dispose() {
}
};
}

private void cancelRetry() {
ScheduledFuture<?> retry = this.retry;
if (retry != null) {
retry.cancel(true);
retry = null;
}
}
tischober marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ thing-type.ec3k.label = ec3k
thing-type.ec3k.description = Thing for an EnergyCount 3000 Power Monitor connected to a JeeLink USB Receiver.
thing-type.pca301.label = PCA301
thing-type.pca301.description = Thing for a PCA301 power monitoring wireless socket connected to a JeeLink USB Receiver.
thing-type.emt7110.label = EMT7110
thing-type.emt7110.description = Thing for a EMT7110 power monitoring wireless socket connected to a JeeLink USB Receiver.

thing-type.tx22.label = TX22 Sensor
thing-type.tx22.description = Thing for a TX22 Sensor connected to a JeeLink USB Receiver.
thing-type.revolt.label = Revolt Power Monitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,38 @@
</config-description>
</thing-type>

<!-- EMT7110 power monitoring wireless socket Thing Type -->
<thing-type id="emt7110">
<supported-bridge-type-refs>
<bridge-type-ref id="jeelinkTcp"/>
<bridge-type-ref id="jeelinkUsb"/>
<bridge-type-ref id="lgwTcp"/>
<bridge-type-ref id="lgwUsb"/>
</supported-bridge-type-refs>

<label>@text/thing-type.emt7110.label</label>
<description>@text/thing-type.emt7110.description</description>

<channels>
<channel id="currentPower" typeId="current-power"/>
<channel id="consumptionTotal" typeId="consumption-total"/>
<channel id="electricPotential" typeId="electric-potential"/>
<channel id="electricCurrent" typeId="electric-current"/>
</channels>

<config-description>
<parameter name="sensorId" type="text" required="true">
<label>@text/parameter.sensorid.label</label>
<description>@text/parameter.sensorid.description</description>
</parameter>
<parameter name="sensorTimeout" type="integer" required="false" min="5" max="3600" unit="s" step="5">
<label>@text/parameter.sensortimeout.label</label>
<description>@text/parameter.sensortimeout.description</description>
<default>600</default>
</parameter>
</config-description>
</thing-type>

<!-- Revolt Energy Meter Thing Type -->
<thing-type id="revolt">
<supported-bridge-type-refs>
Expand Down