mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-02-04 03:14:07 +01:00
[smartmeter] Fix Undelivered IOException (#17133)
Signed-off-by: Leo Siepel <leosiepel@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
caea49ffc9
commit
c48c77d82b
@ -12,19 +12,25 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.smartmeter;
|
package org.openhab.binding.smartmeter;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SmartMeterConfiguration} is the class used to match the
|
* The {@link SmartMeterConfiguration} is the class used to match the
|
||||||
* thing configuration.
|
* thing configuration.
|
||||||
*
|
*
|
||||||
* @author Matthias Steigenberger - Initial contribution
|
* @author Matthias Steigenberger - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class SmartMeterConfiguration {
|
public class SmartMeterConfiguration {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String port;
|
public String port;
|
||||||
public Integer refresh;
|
public Integer refresh = 10;
|
||||||
public Integer baudrateChangeDelay;
|
public Integer baudrateChangeDelay = 0;
|
||||||
|
@Nullable
|
||||||
public String initMessage;
|
public String initMessage;
|
||||||
public String baudrate;
|
public String baudrate = "AUTO";
|
||||||
public String mode;
|
public String mode = "SML";
|
||||||
public String conformity;
|
public String conformity = "NONE";
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.smartmeter.internal;
|
package org.openhab.binding.smartmeter.internal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import io.reactivex.Flowable;
|
import io.reactivex.Flowable;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
|
import io.reactivex.exceptions.UndeliverableException;
|
||||||
import io.reactivex.plugins.RxJavaPlugins;
|
import io.reactivex.plugins.RxJavaPlugins;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
@ -83,7 +85,18 @@ public abstract class MeterDevice<T> {
|
|||||||
this.connector = createConnector(serialPortManagerSupplier, serialPort, baudrate, baudrateChangeDelay,
|
this.connector = createConnector(serialPortManagerSupplier, serialPort, baudrate, baudrateChangeDelay,
|
||||||
protocolMode);
|
protocolMode);
|
||||||
RxJavaPlugins.setErrorHandler(error -> {
|
RxJavaPlugins.setErrorHandler(error -> {
|
||||||
logger.error("Fatal error occured", error);
|
if (error == null) {
|
||||||
|
logger.warn("Fatal but unknown error occurred");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (error instanceof UndeliverableException) {
|
||||||
|
error = error.getCause();
|
||||||
|
}
|
||||||
|
if (error instanceof IOException) {
|
||||||
|
logger.warn("Connection related issue occurred: {}", error.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.warn("Fatal error occurred", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import java.util.function.Supplier;
|
|||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.smartmeter.internal.helper.ProtocolMode;
|
import org.openhab.binding.smartmeter.internal.helper.ProtocolMode;
|
||||||
import org.openhab.binding.smartmeter.internal.iec62056.Iec62056_21MeterReader;
|
import org.openhab.binding.smartmeter.internal.iec62056.MeterReader;
|
||||||
import org.openhab.binding.smartmeter.internal.sml.SmlMeterReader;
|
import org.openhab.binding.smartmeter.internal.sml.SmlMeterReader;
|
||||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ public class MeterDeviceFactory {
|
|||||||
switch (protocolMode) {
|
switch (protocolMode) {
|
||||||
case D:
|
case D:
|
||||||
case ABC:
|
case ABC:
|
||||||
return new Iec62056_21MeterReader(serialPortManagerSupplier, deviceId, serialPort, initMessage,
|
return new MeterReader(serialPortManagerSupplier, deviceId, serialPort, initMessage, baudrate,
|
||||||
baudrate, baudrateChangeDelay, protocolMode);
|
baudrateChangeDelay, protocolMode);
|
||||||
case SML:
|
case SML:
|
||||||
return SmlMeterReader.createInstance(serialPortManagerSupplier, deviceId, serialPort, initMessage,
|
return SmlMeterReader.createInstance(serialPortManagerSupplier, deviceId, serialPort, initMessage,
|
||||||
baudrate, baudrateChangeDelay);
|
baudrate, baudrateChangeDelay);
|
||||||
|
@ -66,11 +66,15 @@ public class MeterValue<Q extends Quantity<Q>> {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
final String status = this.status;
|
||||||
|
final Unit<? extends Q> unit = this.unit;
|
||||||
|
final String value = this.value;
|
||||||
|
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((obis == null) ? 0 : obis.hashCode());
|
result = prime * result + obis.hashCode();
|
||||||
result = prime * result + ((status == null) ? 0 : status.hashCode());
|
result = prime * result + (status == null ? 0 : status.hashCode());
|
||||||
result = prime * result + ((unit == null) ? 0 : unit.hashCode());
|
result = prime * result + (unit == null ? 0 : unit.hashCode());
|
||||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
result = prime * result + value.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +94,7 @@ public class MeterValue<Q extends Quantity<Q>> {
|
|||||||
if (!obis.equals(other.obis)) {
|
if (!obis.equals(other.obis)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
String status = this.status;
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
if (other.status != null) {
|
if (other.status != null) {
|
||||||
return false;
|
return false;
|
||||||
@ -97,6 +102,7 @@ public class MeterValue<Q extends Quantity<Q>> {
|
|||||||
} else if (!status.equals(other.status)) {
|
} else if (!status.equals(other.status)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Unit<? extends Q> unit = this.unit;
|
||||||
if (unit == null) {
|
if (unit == null) {
|
||||||
if (other.unit != null) {
|
if (other.unit != null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -82,6 +82,10 @@ public class ObisCode {
|
|||||||
* @return the obis as string.
|
* @return the obis as string.
|
||||||
*/
|
*/
|
||||||
public String asDecimalString() {
|
public String asDecimalString() {
|
||||||
|
Byte a = this.a;
|
||||||
|
Byte b = this.b;
|
||||||
|
Byte c = this.c;
|
||||||
|
Byte f = this.f;
|
||||||
try (Formatter format = new Formatter()) {
|
try (Formatter format = new Formatter()) {
|
||||||
format.format(SmartMeterBindingConstants.OBIS_FORMAT, a != null ? a & 0xFF : 0, b != null ? b & 0xFF : 0,
|
format.format(SmartMeterBindingConstants.OBIS_FORMAT, a != null ? a & 0xFF : 0, b != null ? b & 0xFF : 0,
|
||||||
c & 0xFF, d & 0xFF, e & 0xFF, f != null ? f & 0xFF : 0);
|
c & 0xFF, d & 0xFF, e & 0xFF, f != null ? f & 0xFF : 0);
|
||||||
@ -118,10 +122,15 @@ public class ObisCode {
|
|||||||
return asDecimalString();
|
return asDecimalString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(@Nullable Byte a, @Nullable Byte b, Byte c, Byte d, Byte e, @Nullable Byte f) {
|
public boolean matches(@Nullable Byte otherA, @Nullable Byte otherB, Byte otherC, Byte d, Byte e,
|
||||||
return (this.a == null || a == null || this.a.equals(a)) && (this.b == null || b == null || this.b.equals(b))
|
@Nullable Byte otherF) {
|
||||||
&& this.c.equals(c) && this.d.equals(d) && this.e.equals(e)
|
Byte a = this.a;
|
||||||
&& (this.f == null || f == null || this.f.equals(f));
|
Byte b = this.b;
|
||||||
|
Byte c = this.c;
|
||||||
|
Byte f = this.f;
|
||||||
|
return (a == null || otherA == null || a.equals(otherA)) && (b == null || otherB == null || b.equals(otherB))
|
||||||
|
&& c.equals(otherC) && this.d.equals(d) && this.e.equals(e)
|
||||||
|
&& (f == null || otherF == null || f.equals(otherF));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(Byte c, Byte d, Byte e) {
|
public boolean matches(Byte c, Byte d, Byte e) {
|
||||||
|
@ -21,7 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import javax.measure.Quantity;
|
import javax.measure.Quantity;
|
||||||
import javax.measure.Unit;
|
import javax.measure.Unit;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNull;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.smartmeter.SmartMeterBindingConstants;
|
import org.openhab.binding.smartmeter.SmartMeterBindingConstants;
|
||||||
import org.openhab.core.library.CoreItemFactory;
|
import org.openhab.core.library.CoreItemFactory;
|
||||||
@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @author Matthias Steigenberger - Initial contribution
|
* @author Matthias Steigenberger - Initial contribution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
@Component(service = { ChannelTypeProvider.class, SmartMeterChannelTypeProvider.class })
|
@Component(service = { ChannelTypeProvider.class, SmartMeterChannelTypeProvider.class })
|
||||||
public class SmartMeterChannelTypeProvider implements ChannelTypeProvider, MeterValueListener {
|
public class SmartMeterChannelTypeProvider implements ChannelTypeProvider, MeterValueListener {
|
||||||
|
|
||||||
@ -68,14 +69,14 @@ public class SmartMeterChannelTypeProvider implements ChannelTypeProvider, Meter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q extends @NonNull Quantity<Q>> void valueChanged(MeterValue<Q> value) {
|
public <Q extends Quantity<Q>> void valueChanged(MeterValue<Q> value) {
|
||||||
if (!obisChannelMap.containsKey(value.getObisCode())) {
|
if (!obisChannelMap.containsKey(value.getObisCode())) {
|
||||||
logger.debug("Creating ChannelType for OBIS {}", value.getObisCode());
|
logger.debug("Creating ChannelType for OBIS {}", value.getObisCode());
|
||||||
obisChannelMap.put(value.getObisCode(), getChannelType(value.getUnit(), value.getObisCode()));
|
obisChannelMap.put(value.getObisCode(), getChannelType(value.getUnit(), value.getObisCode()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChannelType getChannelType(Unit<?> unit, String obis) {
|
private ChannelType getChannelType(@Nullable Unit<?> unit, String obis) {
|
||||||
String obisChannelId = SmartMeterBindingConstants.getObisChannelId(obis);
|
String obisChannelId = SmartMeterBindingConstants.getObisChannelId(obis);
|
||||||
StateChannelTypeBuilder stateDescriptionBuilder;
|
StateChannelTypeBuilder stateDescriptionBuilder;
|
||||||
if (unit != null) {
|
if (unit != null) {
|
||||||
@ -96,7 +97,7 @@ public class SmartMeterChannelTypeProvider implements ChannelTypeProvider, Meter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q extends @NonNull Quantity<Q>> void valueRemoved(MeterValue<Q> value) {
|
public <Q extends Quantity<Q>> void valueRemoved(MeterValue<Q> value) {
|
||||||
obisChannelMap.remove(value.getObisCode());
|
obisChannelMap.remove(value.getObisCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ public class SmartMeterChannelTypeProvider implements ChannelTypeProvider, Meter
|
|||||||
* @param obis The obis code.
|
* @param obis The obis code.
|
||||||
* @return The {@link ChannelTypeUID} or null.
|
* @return The {@link ChannelTypeUID} or null.
|
||||||
*/
|
*/
|
||||||
public ChannelTypeUID getChannelTypeIdForObis(String obis) {
|
public @Nullable ChannelTypeUID getChannelTypeIdForObis(String obis) {
|
||||||
ChannelType channeltype = obisChannelMap.get(obis);
|
ChannelType channeltype = obisChannelMap.get(obis);
|
||||||
return channeltype != null ? channeltype.getUID() : null;
|
return channeltype != null ? channeltype.getUID() : null;
|
||||||
}
|
}
|
||||||
|
@ -68,14 +68,13 @@ import io.reactivex.disposables.Disposable;
|
|||||||
public class SmartMeterHandler extends BaseThingHandler {
|
public class SmartMeterHandler extends BaseThingHandler {
|
||||||
|
|
||||||
private static final long DEFAULT_TIMEOUT = 30000;
|
private static final long DEFAULT_TIMEOUT = 30000;
|
||||||
private static final int DEFAULT_REFRESH_PERIOD = 30;
|
|
||||||
private Logger logger = LoggerFactory.getLogger(SmartMeterHandler.class);
|
private Logger logger = LoggerFactory.getLogger(SmartMeterHandler.class);
|
||||||
private MeterDevice<?> smlDevice;
|
private MeterDevice<?> smlDevice;
|
||||||
private Disposable valueReader;
|
private Disposable valueReader;
|
||||||
private Conformity conformity;
|
private Conformity conformity;
|
||||||
private MeterValueListener valueChangeListener;
|
private MeterValueListener valueChangeListener;
|
||||||
private SmartMeterChannelTypeProvider channelTypeProvider;
|
private SmartMeterChannelTypeProvider channelTypeProvider;
|
||||||
private @NonNull Supplier<SerialPortManager> serialPortManagerSupplier;
|
private Supplier<SerialPortManager> serialPortManagerSupplier;
|
||||||
|
|
||||||
public SmartMeterHandler(Thing thing, SmartMeterChannelTypeProvider channelProvider,
|
public SmartMeterHandler(Thing thing, SmartMeterChannelTypeProvider channelProvider,
|
||||||
Supplier<SerialPortManager> serialPortManagerSupplier) {
|
Supplier<SerialPortManager> serialPortManagerSupplier) {
|
||||||
@ -99,11 +98,10 @@ public class SmartMeterHandler extends BaseThingHandler {
|
|||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
"Parameter 'port' is mandatory and must be configured");
|
"Parameter 'port' is mandatory and must be configured");
|
||||||
} else {
|
} else {
|
||||||
byte[] pullSequence = config.initMessage == null ? null
|
String initMessage = config.initMessage;
|
||||||
: HexUtils.hexToBytes(config.initMessage.replaceAll("\\s+", ""));
|
byte[] pullSequence = initMessage == null ? null : HexUtils.hexToBytes(initMessage.replaceAll("\\s+", ""));
|
||||||
int baudrate = config.baudrate == null ? Baudrate.AUTO.getBaudrate()
|
int baudrate = Baudrate.fromString(config.baudrate).getBaudrate();
|
||||||
: Baudrate.fromString(config.baudrate).getBaudrate();
|
this.conformity = Conformity.valueOf(config.conformity);
|
||||||
this.conformity = config.conformity == null ? Conformity.NONE : Conformity.valueOf(config.conformity);
|
|
||||||
this.smlDevice = MeterDeviceFactory.getDevice(serialPortManagerSupplier, config.mode,
|
this.smlDevice = MeterDeviceFactory.getDevice(serialPortManagerSupplier, config.mode,
|
||||||
this.thing.getUID().getAsString(), port, pullSequence, baudrate, config.baudrateChangeDelay);
|
this.thing.getUID().getAsString(), port, pullSequence, baudrate, config.baudrateChangeDelay);
|
||||||
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.HANDLER_CONFIGURATION_PENDING,
|
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.HANDLER_CONFIGURATION_PENDING,
|
||||||
@ -158,53 +156,58 @@ public class SmartMeterHandler extends BaseThingHandler {
|
|||||||
|
|
||||||
String obisChannelString = SmartMeterBindingConstants.getObisChannelId(obis);
|
String obisChannelString = SmartMeterBindingConstants.getObisChannelId(obis);
|
||||||
Channel channel = thing.getChannel(obisChannelString);
|
Channel channel = thing.getChannel(obisChannelString);
|
||||||
|
|
||||||
ChannelTypeUID channelTypeId = channelTypeProvider.getChannelTypeIdForObis(obis);
|
ChannelTypeUID channelTypeId = channelTypeProvider.getChannelTypeIdForObis(obis);
|
||||||
|
if (channelTypeId == null) {
|
||||||
|
logger.warn("No ChannelTypeId found for OBIS {}", obis);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ChannelType channelType = channelTypeProvider.getChannelType(channelTypeId, null);
|
ChannelType channelType = channelTypeProvider.getChannelType(channelTypeId, null);
|
||||||
if (channelType != null) {
|
if (channelType == null) {
|
||||||
String itemType = channelType.getItemType();
|
|
||||||
|
|
||||||
State state = getStateForObisValue(value, channel);
|
|
||||||
if (channel == null) {
|
|
||||||
logger.debug("Adding channel: {} with item type: {}", obisChannelString, itemType);
|
|
||||||
|
|
||||||
// channel has not been created yet
|
|
||||||
ChannelBuilder channelBuilder = ChannelBuilder
|
|
||||||
.create(new ChannelUID(thing.getUID(), obisChannelString), itemType)
|
|
||||||
.withType(channelTypeId);
|
|
||||||
|
|
||||||
Configuration configuration = new Configuration();
|
|
||||||
configuration.put(SmartMeterBindingConstants.CONFIGURATION_CONVERSION, 1);
|
|
||||||
channelBuilder.withConfiguration(configuration);
|
|
||||||
channelBuilder.withLabel(obis);
|
|
||||||
Map<String, String> channelProps = new HashMap<>();
|
|
||||||
channelProps.put(SmartMeterBindingConstants.CHANNEL_PROPERTY_OBIS, obis);
|
|
||||||
channelBuilder.withProperties(channelProps);
|
|
||||||
channelBuilder.withDescription(
|
|
||||||
MessageFormat.format("Value for OBIS code: {0} with Unit: {1}", obis, value.getUnit()));
|
|
||||||
channel = channelBuilder.build();
|
|
||||||
ChannelUID channelId = channel.getUID();
|
|
||||||
|
|
||||||
// add all valid channels to the thing builder
|
|
||||||
List<Channel> channels = new ArrayList<>(getThing().getChannels());
|
|
||||||
if (channels.stream().filter((element) -> element.getUID().equals(channelId)).count() == 0) {
|
|
||||||
channels.add(channel);
|
|
||||||
thingBuilder.withChannels(channels);
|
|
||||||
updateThing(thingBuilder.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!channel.getProperties().containsKey(SmartMeterBindingConstants.CHANNEL_PROPERTY_OBIS)) {
|
|
||||||
addObisPropertyToChannel(obis, channel);
|
|
||||||
}
|
|
||||||
if (state != null) {
|
|
||||||
updateState(channel.getUID(), state);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE);
|
|
||||||
} else {
|
|
||||||
logger.warn("No ChannelType found for OBIS {}", obis);
|
logger.warn("No ChannelType found for OBIS {}", obis);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
String itemType = channelType.getItemType();
|
||||||
|
|
||||||
|
State state = getStateForObisValue(value, channel);
|
||||||
|
if (channel == null) {
|
||||||
|
logger.debug("Adding channel: {} with item type: {}", obisChannelString, itemType);
|
||||||
|
|
||||||
|
// channel has not been created yet
|
||||||
|
ChannelBuilder channelBuilder = ChannelBuilder
|
||||||
|
.create(new ChannelUID(thing.getUID(), obisChannelString), itemType)
|
||||||
|
.withType(channelTypeId);
|
||||||
|
|
||||||
|
Configuration configuration = new Configuration();
|
||||||
|
configuration.put(SmartMeterBindingConstants.CONFIGURATION_CONVERSION, 1);
|
||||||
|
channelBuilder.withConfiguration(configuration);
|
||||||
|
channelBuilder.withLabel(obis);
|
||||||
|
Map<String, String> channelProps = new HashMap<>();
|
||||||
|
channelProps.put(SmartMeterBindingConstants.CHANNEL_PROPERTY_OBIS, obis);
|
||||||
|
channelBuilder.withProperties(channelProps);
|
||||||
|
channelBuilder.withDescription(
|
||||||
|
MessageFormat.format("Value for OBIS code: {0} with Unit: {1}", obis, value.getUnit()));
|
||||||
|
channel = channelBuilder.build();
|
||||||
|
ChannelUID channelId = channel.getUID();
|
||||||
|
|
||||||
|
// add all valid channels to the thing builder
|
||||||
|
List<Channel> channels = new ArrayList<>(getThing().getChannels());
|
||||||
|
if (channels.stream().filter((element) -> element.getUID().equals(channelId)).count() == 0) {
|
||||||
|
channels.add(channel);
|
||||||
|
thingBuilder.withChannels(channels);
|
||||||
|
updateThing(thingBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channel.getProperties().containsKey(SmartMeterBindingConstants.CHANNEL_PROPERTY_OBIS)) {
|
||||||
|
addObisPropertyToChannel(obis, channel);
|
||||||
|
}
|
||||||
|
if (state != null) {
|
||||||
|
updateState(channel.getUID(), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addObisPropertyToChannel(String obis, Channel channel) {
|
private void addObisPropertyToChannel(String obis, Channel channel) {
|
||||||
@ -238,8 +241,7 @@ public class SmartMeterHandler extends BaseThingHandler {
|
|||||||
this.smlDevice.addValueChangeListener(valueChangeListener);
|
this.smlDevice.addValueChangeListener(valueChangeListener);
|
||||||
|
|
||||||
SmartMeterConfiguration config = getConfigAs(SmartMeterConfiguration.class);
|
SmartMeterConfiguration config = getConfigAs(SmartMeterConfiguration.class);
|
||||||
int delay = config.refresh != null ? config.refresh : DEFAULT_REFRESH_PERIOD;
|
valueReader = this.smlDevice.readValues(DEFAULT_TIMEOUT, this.scheduler, Duration.ofSeconds(config.refresh));
|
||||||
valueReader = this.smlDevice.readValues(DEFAULT_TIMEOUT, this.scheduler, Duration.ofSeconds(delay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOBISChannel(ChannelUID channelId) {
|
private void updateOBISChannel(ChannelUID channelId) {
|
||||||
|
@ -28,7 +28,6 @@ import org.openhab.core.library.unit.Units;
|
|||||||
import org.openhab.core.thing.Channel;
|
import org.openhab.core.thing.Channel;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +88,8 @@ public enum Conformity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Failed to check negate status for obis {}", obis, e);
|
LoggerFactory.getLogger(Conformity.class)
|
||||||
|
.warn("Failed to check negate status for obis {}", obis, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,8 +99,6 @@ public enum Conformity {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Conformity.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the overwritten negation setting for the channel.
|
* Applies the overwritten negation setting for the channel.
|
||||||
*
|
*
|
||||||
|
@ -17,7 +17,6 @@ import java.util.function.Function;
|
|||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.smartmeter.internal.MeterValue;
|
import org.openhab.binding.smartmeter.internal.MeterValue;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +27,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class NegateHandler {
|
public class NegateHandler {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(NegateHandler.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether negation should be applied for the given <code>negateProperty</code> and the {@link MeterValue}
|
* Gets whether negation should be applied for the given <code>negateProperty</code> and the {@link MeterValue}
|
||||||
@ -71,7 +69,8 @@ public class NegateHandler {
|
|||||||
try {
|
try {
|
||||||
longValue = (long) Double.parseDouble(value);
|
longValue = (long) Double.parseDouble(value);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
LOGGER.warn("Failed to parse value: {} when determining isNegateSet, assuming false", value);
|
LoggerFactory.getLogger(NegateHandler.class)
|
||||||
|
.warn("Failed to parse value: {} when determining isNegateSet, assuming false", value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (longValue & (1L << negatePosition)) != 0;
|
return (longValue & (1L << negatePosition)) != 0;
|
||||||
|
@ -16,7 +16,6 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
import javax.measure.Quantity;
|
import javax.measure.Quantity;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNull;
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.smartmeter.connectors.IMeterReaderConnector;
|
import org.openhab.binding.smartmeter.connectors.IMeterReaderConnector;
|
||||||
@ -34,11 +33,10 @@ import org.openmuc.j62056.DataSet;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class Iec62056_21MeterReader extends MeterDevice<DataMessage> {
|
public class MeterReader extends MeterDevice<DataMessage> {
|
||||||
|
|
||||||
public Iec62056_21MeterReader(Supplier<SerialPortManager> serialPortManagerSupplier, String deviceId,
|
public MeterReader(Supplier<SerialPortManager> serialPortManagerSupplier, String deviceId, String serialPort,
|
||||||
String serialPort, byte @Nullable [] initMessage, int baudrate, int baudrateChangeDelay,
|
byte @Nullable [] initMessage, int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
|
||||||
ProtocolMode protocolMode) {
|
|
||||||
super(serialPortManagerSupplier, deviceId, serialPort, initMessage, baudrate, baudrateChangeDelay,
|
super(serialPortManagerSupplier, deviceId, serialPort, initMessage, baudrate, baudrateChangeDelay,
|
||||||
protocolMode);
|
protocolMode);
|
||||||
}
|
}
|
||||||
@ -46,17 +44,15 @@ public class Iec62056_21MeterReader extends MeterDevice<DataMessage> {
|
|||||||
@Override
|
@Override
|
||||||
protected IMeterReaderConnector<DataMessage> createConnector(Supplier<SerialPortManager> serialPortManagerSupplier,
|
protected IMeterReaderConnector<DataMessage> createConnector(Supplier<SerialPortManager> serialPortManagerSupplier,
|
||||||
String serialPort, int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
|
String serialPort, int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
|
||||||
return new Iec62056_21SerialConnector(serialPortManagerSupplier, serialPort, baudrate, baudrateChangeDelay,
|
return new SerialConnector(serialPortManagerSupplier, serialPort, baudrate, baudrateChangeDelay, protocolMode);
|
||||||
protocolMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <Q extends @NonNull Quantity<Q>> void populateValueCache(DataMessage smlFile) {
|
protected <Q extends Quantity<Q>> void populateValueCache(DataMessage smlFile) {
|
||||||
for (DataSet dataSet : smlFile.getDataSets()) {
|
for (DataSet dataSet : smlFile.getDataSets()) {
|
||||||
String address = dataSet.getAddress();
|
String address = dataSet.getAddress();
|
||||||
if (address != null && !address.isEmpty()) {
|
if (address != null && !address.isEmpty()) {
|
||||||
addObisCache(new MeterValue<Q>(address, dataSet.getValue(),
|
addObisCache(new MeterValue<Q>(address, dataSet.getValue(), UnitConversion.getUnit(dataSet.getUnit())));
|
||||||
Iec62056_21UnitConversion.getUnit(dataSet.getUnit())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,17 +40,17 @@ import io.reactivex.FlowableEmitter;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class Iec62056_21SerialConnector extends ConnectorBase<DataMessage> {
|
public class SerialConnector extends ConnectorBase<DataMessage> {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(Iec62056_21SerialConnector.class);
|
private final Logger logger = LoggerFactory.getLogger(SerialConnector.class);
|
||||||
private int baudrate;
|
private int baudrate;
|
||||||
private int baudrateChangeDelay;
|
private int baudrateChangeDelay;
|
||||||
private ProtocolMode protocolMode;
|
private ProtocolMode protocolMode;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Iec21Port iec21Port;
|
private Iec21Port iec21Port;
|
||||||
|
|
||||||
public Iec62056_21SerialConnector(Supplier<SerialPortManager> serialPortManagerSupplier, String portName,
|
public SerialConnector(Supplier<SerialPortManager> serialPortManagerSupplier, String portName, int baudrate,
|
||||||
int baudrate, int baudrateChangeDelay, ProtocolMode protocolMode) {
|
int baudrateChangeDelay, ProtocolMode protocolMode) {
|
||||||
super(portName);
|
super(portName);
|
||||||
this.baudrate = baudrate;
|
this.baudrate = baudrate;
|
||||||
this.baudrateChangeDelay = baudrateChangeDelay;
|
this.baudrateChangeDelay = baudrateChangeDelay;
|
||||||
@ -78,6 +78,7 @@ public class Iec62056_21SerialConnector extends ConnectorBase<DataMessage> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataMessage readNext(byte @Nullable [] initMessage) throws IOException {
|
protected DataMessage readNext(byte @Nullable [] initMessage) throws IOException {
|
||||||
|
Iec21Port iec21Port = this.iec21Port;
|
||||||
if (iec21Port != null) {
|
if (iec21Port != null) {
|
||||||
DataMessage dataMessage = iec21Port.read();
|
DataMessage dataMessage = iec21Port.read();
|
||||||
logger.debug("Datamessage read: {}", dataMessage);
|
logger.debug("Datamessage read: {}", dataMessage);
|
||||||
@ -94,6 +95,7 @@ public class Iec62056_21SerialConnector extends ConnectorBase<DataMessage> {
|
|||||||
super.emitValues(initMessage, emitter);
|
super.emitValues(initMessage, emitter);
|
||||||
break;
|
break;
|
||||||
case D:
|
case D:
|
||||||
|
Iec21Port iec21Port = this.iec21Port;
|
||||||
if (iec21Port != null) {
|
if (iec21Port != null) {
|
||||||
iec21Port.listen(new ModeDListener() {
|
iec21Port.listen(new ModeDListener() {
|
||||||
|
|
||||||
@ -108,6 +110,7 @@ public class Iec62056_21SerialConnector extends ConnectorBase<DataMessage> {
|
|||||||
logger.warn("Exception while listening for mode D data message", e);
|
logger.warn("Exception while listening for mode D data message", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.iec21Port = iec21Port;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SML:
|
case SML:
|
||||||
@ -128,6 +131,7 @@ public class Iec62056_21SerialConnector extends ConnectorBase<DataMessage> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeConnection() {
|
public void closeConnection() {
|
||||||
|
Iec21Port iec21Port = this.iec21Port;
|
||||||
if (iec21Port != null) {
|
if (iec21Port != null) {
|
||||||
iec21Port.close();
|
iec21Port.close();
|
||||||
}
|
}
|
@ -18,7 +18,6 @@ import javax.measure.Unit;
|
|||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.types.util.UnitUtils;
|
import org.openhab.core.types.util.UnitUtils;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,9 +27,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class Iec62056_21UnitConversion {
|
public class UnitConversion {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Iec62056_21UnitConversion.class);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static @Nullable <Q extends Quantity<Q>> Unit<Q> getUnit(String unit) {
|
public static @Nullable <Q extends Quantity<Q>> Unit<Q> getUnit(String unit) {
|
||||||
@ -38,7 +35,7 @@ public class Iec62056_21UnitConversion {
|
|||||||
try {
|
try {
|
||||||
return (Unit<Q>) UnitUtils.parseUnit(" " + unit);
|
return (Unit<Q>) UnitUtils.parseUnit(" " + unit);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Failed to parse unit {}: {}", unit, e.getMessage());
|
LoggerFactory.getLogger(UnitConversion.class).warn("Failed to parse unit {}: {}", unit, e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -105,48 +105,48 @@ public class SmlFileDebugOutput {
|
|||||||
|
|
||||||
private static void parseGetListResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseGetListResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got GetListResponse");
|
consumer.accept("Got GetListResponse");
|
||||||
SmlGetListRes sml_listRes = (SmlGetListRes) smlMessage.getMessageBody().getChoice();
|
SmlGetListRes smlListRes = (SmlGetListRes) smlMessage.getMessageBody().getChoice();
|
||||||
|
|
||||||
// consumer.accept(sml_listRes.toString());
|
// consumer.accept(sml_listRes.toString());
|
||||||
|
|
||||||
consumer.accept(sml_listRes.toStringIndent(" "));
|
consumer.accept(smlListRes.toStringIndent(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseAttentionResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseAttentionResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got AttentionResponse");
|
consumer.accept("Got AttentionResponse");
|
||||||
SmlAttentionRes sml_attentionRes = (SmlAttentionRes) smlMessage.getMessageBody().getChoice();
|
SmlAttentionRes smlAttentionRes = (SmlAttentionRes) smlMessage.getMessageBody().getChoice();
|
||||||
consumer.accept(sml_attentionRes.toString());
|
consumer.accept(smlAttentionRes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseGetProcParameterResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseGetProcParameterResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got GetProcParameterResponse");
|
consumer.accept("Got GetProcParameterResponse");
|
||||||
SmlGetProcParameterRes sml_getProcParameterRes = (SmlGetProcParameterRes) smlMessage.getMessageBody()
|
SmlGetProcParameterRes smlGetProcParameterRes = (SmlGetProcParameterRes) smlMessage.getMessageBody()
|
||||||
.getChoice();
|
.getChoice();
|
||||||
consumer.accept(sml_getProcParameterRes.toString());
|
consumer.accept(smlGetProcParameterRes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseGetProfileListResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseGetProfileListResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got GetProfileListResponse");
|
consumer.accept("Got GetProfileListResponse");
|
||||||
SmlGetProfileListRes sml_getProfileListRes = (SmlGetProfileListRes) smlMessage.getMessageBody().getChoice();
|
SmlGetProfileListRes smlGetProfileListRes = (SmlGetProfileListRes) smlMessage.getMessageBody().getChoice();
|
||||||
consumer.accept(sml_getProfileListRes.toString());
|
consumer.accept(smlGetProfileListRes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseOpenResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseOpenResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got OpenResponse");
|
consumer.accept("Got OpenResponse");
|
||||||
SmlPublicOpenRes sml_PublicOpenRes = (SmlPublicOpenRes) smlMessage.getMessageBody().getChoice();
|
SmlPublicOpenRes smlPublicOpenRes = (SmlPublicOpenRes) smlMessage.getMessageBody().getChoice();
|
||||||
consumer.accept(sml_PublicOpenRes.toString());
|
consumer.accept(smlPublicOpenRes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseCloseResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseCloseResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got CloseResponse");
|
consumer.accept("Got CloseResponse");
|
||||||
SmlPublicCloseRes sml_PublicCloseRes = (SmlPublicCloseRes) smlMessage.getMessageBody().getChoice();
|
SmlPublicCloseRes smlPublicCloseRes = (SmlPublicCloseRes) smlMessage.getMessageBody().getChoice();
|
||||||
consumer.accept(sml_PublicCloseRes.toString());
|
consumer.accept(smlPublicCloseRes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseGetProfilePackResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
private static void parseGetProfilePackResponse(SmlMessage smlMessage, Consumer<String> consumer) {
|
||||||
consumer.accept("Got GetProfilePackResponse");
|
consumer.accept("Got GetProfilePackResponse");
|
||||||
SmlGetProfilePackRes sml_getProfilePackRes = (SmlGetProfilePackRes) smlMessage.getMessageBody().getChoice();
|
SmlGetProfilePackRes smlGetProfilePackRes = (SmlGetProfilePackRes) smlMessage.getMessageBody().getChoice();
|
||||||
consumer.accept(sml_getProfilePackRes.toString());
|
consumer.accept(smlGetProfilePackRes.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================= Requests =================================
|
// ========================= Requests =================================
|
||||||
|
@ -81,6 +81,7 @@ public final class SmlSerialConnector extends ConnectorBase<SmlFile> {
|
|||||||
protected SmlFile readNext(byte @Nullable [] initMessage) throws IOException {
|
protected SmlFile readNext(byte @Nullable [] initMessage) throws IOException {
|
||||||
if (initMessage != null) {
|
if (initMessage != null) {
|
||||||
logger.debug("Writing init message: {}", HexUtils.bytesToHex(initMessage, " "));
|
logger.debug("Writing init message: {}", HexUtils.bytesToHex(initMessage, " "));
|
||||||
|
DataOutputStream os = this.os;
|
||||||
if (os != null) {
|
if (os != null) {
|
||||||
os.write(initMessage);
|
os.write(initMessage);
|
||||||
os.flush();
|
os.flush();
|
||||||
@ -89,6 +90,7 @@ public final class SmlSerialConnector extends ConnectorBase<SmlFile> {
|
|||||||
|
|
||||||
// read out the whole buffer. We are only interested in the most recent SML file.
|
// read out the whole buffer. We are only interested in the most recent SML file.
|
||||||
Stack<SmlFile> smlFiles = new Stack<>();
|
Stack<SmlFile> smlFiles = new Stack<>();
|
||||||
|
DataInputStream is = this.is;
|
||||||
do {
|
do {
|
||||||
logger.trace("Reading {}. SML message", smlFiles.size() + 1);
|
logger.trace("Reading {}. SML message", smlFiles.size() + 1);
|
||||||
smlFiles.push(TRANSPORT.getSMLFile(is));
|
smlFiles.push(TRANSPORT.getSMLFile(is));
|
||||||
@ -137,12 +139,10 @@ public final class SmlSerialConnector extends ConnectorBase<SmlFile> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void closeConnection() {
|
public void closeConnection() {
|
||||||
try {
|
try {
|
||||||
|
DataInputStream is = this.is;
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
is.close();
|
is.close();
|
||||||
is = null;
|
is = null;
|
||||||
@ -151,6 +151,7 @@ public final class SmlSerialConnector extends ConnectorBase<SmlFile> {
|
|||||||
logger.error("Failed to close serial input stream", e);
|
logger.error("Failed to close serial input stream", e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
DataOutputStream os = this.os;
|
||||||
if (os != null) {
|
if (os != null) {
|
||||||
os.close();
|
os.close();
|
||||||
os = null;
|
os = null;
|
||||||
|
@ -15,6 +15,8 @@ package org.openhab.binding.smartmeter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.smartmeter.connectors.ConnectorBase;
|
import org.openhab.binding.smartmeter.connectors.ConnectorBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +24,7 @@ import org.openhab.binding.smartmeter.connectors.ConnectorBase;
|
|||||||
* @author Matthias Steigenberger - Initial contribution
|
* @author Matthias Steigenberger - Initial contribution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class MockMeterReaderConnector extends ConnectorBase<Object> {
|
public class MockMeterReaderConnector extends ConnectorBase<Object> {
|
||||||
|
|
||||||
private boolean applyRetry;
|
private boolean applyRetry;
|
||||||
@ -42,12 +45,12 @@ public class MockMeterReaderConnector extends ConnectorBase<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object readNext(byte[] initMessage) throws IOException {
|
protected Object readNext(byte @Nullable [] initMessage) throws IOException {
|
||||||
try {
|
try {
|
||||||
return readNextSupplier.get();
|
return readNextSupplier.get();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
if (e.getCause() instanceof IOException) {
|
if (e.getCause() instanceof IOException cause) {
|
||||||
throw (IOException) e.getCause();
|
throw cause;
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
import javax.measure.Quantity;
|
import javax.measure.Quantity;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNull;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
@ -44,6 +44,7 @@ import io.reactivex.plugins.RxJavaPlugins;
|
|||||||
* @author Matthias Steigenberger - Initial contribution
|
* @author Matthias Steigenberger - Initial contribution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class TestMeterReading {
|
public class TestMeterReading {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -118,6 +119,7 @@ public class TestMeterReading {
|
|||||||
throw new RuntimeException(new IOException("fucked up"));
|
throw new RuntimeException(new IOException("fucked up"));
|
||||||
}));
|
}));
|
||||||
MeterDevice<Object> meter = getMeterDevice(connector);
|
MeterDevice<Object> meter = getMeterDevice(connector);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
Consumer<Throwable> errorHandler = mock(Consumer.class);
|
Consumer<Throwable> errorHandler = mock(Consumer.class);
|
||||||
RxJavaPlugins.setErrorHandler(errorHandler);
|
RxJavaPlugins.setErrorHandler(errorHandler);
|
||||||
MeterValueListener changeListener = Mockito.mock(MeterValueListener.class);
|
MeterValueListener changeListener = Mockito.mock(MeterValueListener.class);
|
||||||
@ -139,14 +141,15 @@ public class TestMeterReading {
|
|||||||
return new MeterDevice<>(() -> mock(SerialPortManager.class), "id", "port", null, 9600, 0, ProtocolMode.SML) {
|
return new MeterDevice<>(() -> mock(SerialPortManager.class), "id", "port", null, 9600, 0, ProtocolMode.SML) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NonNull IMeterReaderConnector<Object> createConnector(
|
protected IMeterReaderConnector<Object> createConnector(
|
||||||
@NonNull Supplier<@NonNull SerialPortManager> serialPortManagerSupplier, @NonNull String serialPort,
|
Supplier<SerialPortManager> serialPortManagerSupplier, String serialPort, int baudrate,
|
||||||
int baudrate, int baudrateChangeDelay, @NonNull ProtocolMode protocolMode) {
|
int baudrateChangeDelay, ProtocolMode protocolMode) {
|
||||||
return connector;
|
return connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@Override
|
@Override
|
||||||
protected <Q extends @NonNull Quantity<Q>> void populateValueCache(Object smlFile) {
|
protected <Q extends Quantity<Q>> void populateValueCache(Object smlFile) {
|
||||||
addObisCache(new MeterValue("123", "333", null));
|
addObisCache(new MeterValue("123", "333", null));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,7 @@ package org.openhab.binding.smartmeter;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.openhab.binding.smartmeter.internal.MeterValue;
|
import org.openhab.binding.smartmeter.internal.MeterValue;
|
||||||
import org.openhab.binding.smartmeter.internal.conformity.negate.NegateBitModel;
|
import org.openhab.binding.smartmeter.internal.conformity.negate.NegateBitModel;
|
||||||
@ -25,6 +26,7 @@ import org.openhab.binding.smartmeter.internal.conformity.negate.NegateHandler;
|
|||||||
* @author Matthias Steigenberger - Initial contribution
|
* @author Matthias Steigenberger - Initial contribution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class TestNegateBit {
|
public class TestNegateBit {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user