mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[ism8] Add UoM support (#14206)
* Add UoM support Signed-off-by: lsiepel <leosiepel@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
c153944f6f
commit
921ed3b8b3
@ -34,15 +34,9 @@ The ISM8 does currently support 4 different devices at the same moment of time (
|
||||
Once you have an overview of your heating system set you can start to create the channels accordingly.
|
||||
Each channel should be created in the following way:
|
||||
|
||||
| Type | Name | Description | Configuration |
|
||||
|--------|---------|----------------------------|-----------------|
|
||||
| Number | DpId004 | "Kesseltemperatur" | id, type, write |
|
||||
|
||||
Type:
|
||||
|
||||
- Switch use for boolean values
|
||||
- Number use for any number
|
||||
- Other types may work as well.
|
||||
| Type | Name | Description | Configuration |
|
||||
|--------------------|---------|--------------------|---------------|
|
||||
| Number:Temperature | DpId004 | "Kesseltemperatur" | |
|
||||
|
||||
Name:
|
||||
|
||||
@ -65,11 +59,18 @@ Note:
|
||||
Not all available types of the ISM8 interface are fully supported, but this can be extended.
|
||||
For the moment the following data types are implemented:
|
||||
|
||||
- DPT-Bool: `1.001`, `1.002`, `1.003`, `1.009`
|
||||
- DPT-Scaling: `5.001`
|
||||
- DPT-Value: `9.001`, `9.002`, `9.006`
|
||||
- DPT-FlowRate: `13.002`
|
||||
- DPT-Mode: `20.102`, `20.103`, `20.105`
|
||||
| Channel type | Datapoint type | Item type | R/W | KNX-type's |
|
||||
|----------------|--------------------------------|---------------------------|-----|----------------------------|
|
||||
| switch-rw | Digital DataPoint | Switch | R/W | 1.001, 1.002, 1.003, 1.009 |
|
||||
| switch-r | Digital Readonly DataPoint | Switch | R | 1.001, 1.002, 1.003, 1.009 |
|
||||
| percentage-rw | Percentage DataPoint | Number:Dimensionless | R/W | 5.001 |
|
||||
| percentage-r | Percentage Readonly DataPoint | Number:Dimensionless | R | 5.001 |
|
||||
| temperature-rw | Temperature DataPoint | Number:Temperature | R/W | 9.001,9.002 |
|
||||
| temperature-r | Temperature Readonly DataPoint | Number:Temperature | R | 9.002,9.002 |
|
||||
| pressure-r | Pressure Readonly DataPoint | Number:Pressure | R | 9.006 |
|
||||
| flowrate-r | Flowrate Readonly DataPoint | Number:VolumetricFlowRate | R | 13.002 |
|
||||
| mode-rw | Mode DataPoint | Number:Dimensionless | R/W | 20.102, 20.103, 20.105 |
|
||||
| mode-r | Mode Readonly DataPoint | Number:Dimensionless | R | 20.102, 20.103, 20.105 |
|
||||
|
||||
## Full Example
|
||||
|
||||
@ -78,29 +79,29 @@ For the moment the following data types are implemented:
|
||||
```java
|
||||
Thing ism8:device:heater "Wolf Heizung" [portNumber=12004]
|
||||
{
|
||||
Type switch-readonly : DpId001 "Störung Heizgerät" [id=1, type="1.001"]
|
||||
Type number-readonly : DpId002 "Betriebsart" [id=2, type="20.105"]
|
||||
Type number-readonly : DpId003 "Brennerleistung" [id=3, type="5.001"]
|
||||
Type number-readonly : DpId004 "Kesseltemperatur" [id=4, type="9.001"]
|
||||
Type number-readonly : DpId006 "Rücklauftemperatur" [id=6, type="9.001"]
|
||||
Type number-readonly : DpId007 "Warmwassertemperatur" [id=7, type="9.001"]
|
||||
Type number-readonly : DpId008 "Außentemperatur" [id=8, type="9.001"]
|
||||
Type switch-readonly : DpId009 "Status Flamme" [id=9, type="1.001"]
|
||||
Type number-readonly : DpId013 "Anlagendruck" [id=13, type="9.006"]
|
||||
Type number-readonly : DpId053 "Störung Systemmodul" [id=53, type="1.001"]
|
||||
Type number-readonly : DpId054 "Außentemperatur Systemmodul" [id=54, type="9.001"]
|
||||
Type number : DpId056 "Sollwert Warmwasser" [id=56, type="9.001"]
|
||||
Type number : DpId057 "Betriebsart Heizkreis" [id=57, type="20.102"]
|
||||
Type number : DpId058 "Betriebsart Warmwasser" [id=58, type="20.103"]
|
||||
Type number : DpId065 "Sollwertverschiebung" [id=65, type="9.002"]
|
||||
Type number-readonly : DpId148 "CML Störung" [id=148, type="1.001"]
|
||||
Type number : DpId149 "CWL Betriebsart" [id=149, type="20.102"]
|
||||
Type number-readonly : DpId163 "CWL Lüftungsstufe" [id=163, type="5.001"]
|
||||
Type number-readonly : DpId164 "CWL Ablufttemperatur" [id=164, type="9.001"]
|
||||
Type number-readonly : DpId165 "CWL Zulufttemperatur" [id=165, type="9.001"]
|
||||
Type number-readonly : DpId166 "CWL Luftdurchsatz Zuluft" [id=166, type="13.002"]
|
||||
Type number-readonly : DpId167 "CWL Luftdurchsatz Abluft" [id=167, type="13.002"]
|
||||
Type number-readonly : DpId192 "CML Filterwarnung" [id=192, type="1.001"]
|
||||
Type switch-r : DpId001 "Störung Heizgerät" [id=1, type="1.001"]
|
||||
Type number-r : DpId002 "Betriebsart" [id=2, type="20.105"]
|
||||
Type percentage-r : DpId003 "Brennerleistung" [id=3, type="5.001"]
|
||||
Type temperature-r : DpId004 "Kesseltemperatur" [id=4, type="9.001"]
|
||||
Type temperature-r : DpId006 "Rücklauftemperatur" [id=6, type="9.001"]
|
||||
Type temperature-r : DpId007 "Warmwassertemperatur" [id=7, type="9.001"]
|
||||
Type temperature-r : DpId008 "Außentemperatur" [id=8, type="9.001"]
|
||||
Type switch-r : DpId009 "Status Flamme" [id=9, type="1.001"]
|
||||
Type temperature-r : DpId013 "Anlagendruck" [id=13, type="9.006"]
|
||||
Type switch-r : DpId053 "Störung Systemmodul" [id=53, type="1.001"]
|
||||
Type temperature-r : DpId054 "Außentemperatur Systemmodul" [id=54, type="9.001"]
|
||||
Type temperature-rw : DpId056 "Sollwert Warmwasser" [id=56, type="9.001"]
|
||||
Type mode-rw : DpId057 "Betriebsart Heizkreis" [id=57, type="20.102"]
|
||||
Type mode-rw : DpId058 "Betriebsart Warmwasser" [id=58, type="20.103"]
|
||||
Type temperature-rw : DpId065 "Sollwertverschiebung" [id=65, type="9.002"]
|
||||
Type switch-rw : DpId148 "CML Störung" [id=148, type="1.001"]
|
||||
Type mode-rw : DpId149 "CWL Betriebsart" [id=149, type="20.102"]
|
||||
Type percentage-r : DpId163 "CWL Lüftungsstufe" [id=163, type="5.001"]
|
||||
Type temperature-r : DpId164 "CWL Ablufttemperatur" [id=164, type="9.001"]
|
||||
Type temperature-r : DpId165 "CWL Zulufttemperatur" [id=165, type="9.001"]
|
||||
Type flowrate-r : DpId166 "CWL Luftdurchsatz Zuluft" [id=166, type="13.002"]
|
||||
Type flowrate-r : DpId167 "CWL Luftdurchsatz Abluft" [id=167, type="13.002"]
|
||||
Type switch-r : DpId192 "CML Filterwarnung" [id=192, type="1.001"]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -24,7 +24,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
@NonNullByDefault
|
||||
public class Ism8BindingConstants {
|
||||
// Binding ID
|
||||
private static final String BINDING_ID = "ism8";
|
||||
public static final String BINDING_ID = "ism8";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
|
||||
@ -41,4 +41,8 @@ public class Ism8BindingConstants {
|
||||
*
|
||||
*/
|
||||
public static final String PORT_NUMBER = "portNumber";
|
||||
|
||||
// Channel Configuration parameters
|
||||
public static final String CHANNEL_CONFIG_ID = "id";
|
||||
public static final String CHANNEL_CONFIG_TYPE = "type";
|
||||
}
|
||||
|
@ -12,21 +12,25 @@
|
||||
*/
|
||||
package org.openhab.binding.ism8.internal;
|
||||
|
||||
import static org.openhab.binding.ism8.internal.Ism8BindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ism8.internal.util.Ism8DomainMap;
|
||||
import org.openhab.binding.ism8.server.DataPointChangedEvent;
|
||||
import org.openhab.binding.ism8.server.IDataPoint;
|
||||
import org.openhab.binding.ism8.server.IDataPointChangeListener;
|
||||
import org.openhab.binding.ism8.server.Server;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -48,33 +52,42 @@ public class Ism8Handler extends BaseThingHandler implements IDataPointChangeLis
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
this.logger.debug("Ism8: Handle command = {} {}", channelUID.getId(), command);
|
||||
Channel channel = getThing().getChannel(channelUID);
|
||||
Server svr = this.server;
|
||||
if (channel != null && svr != null) {
|
||||
if (channel.getConfiguration().containsKey("id")) {
|
||||
IDataPoint dataPoint = null;
|
||||
try {
|
||||
int id = Integer.parseInt(channel.getConfiguration().get("id").toString());
|
||||
this.logger.debug("Channel '{}' writting into ID '{}'", channel.getUID().getId(), id);
|
||||
this.updateState(channelUID, new QuantityType<>(command.toString()));
|
||||
dataPoint = svr.getDataPoint(id);
|
||||
} catch (NumberFormatException e) {
|
||||
this.logger.debug("Updating State of ISM DataPoint '{}' failed. '{}'", channel.getConfiguration(),
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
if (dataPoint != null) {
|
||||
try {
|
||||
svr.sendData(dataPoint.createWriteData(command));
|
||||
} catch (IOException e) {
|
||||
this.logger.debug("Writting to ISM DataPoint '{}' failed. '{}'", dataPoint.getId(),
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
public void initialize() {
|
||||
this.config = getConfigAs(Ism8Configuration.class);
|
||||
Ism8Configuration cfg = this.config;
|
||||
final String uid = this.getThing().getUID().getAsString();
|
||||
Server svr = new Server(cfg.getPortNumber(), uid);
|
||||
this.server = svr;
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
Configuration channelConfig = channel.getConfiguration();
|
||||
if (registerDataPointToServer(channelConfig, channel.getLabel())) {
|
||||
logger.debug("Ism8: Channel={} registered datapoint", channelConfig.toString());
|
||||
} else {
|
||||
logger.warn("Ism8: Channel={} failed to register datapoint", channelConfig.toString());
|
||||
}
|
||||
}
|
||||
|
||||
this.updateStatus(ThingStatus.UNKNOWN);
|
||||
svr.addDataPointChangeListener(this);
|
||||
scheduler.execute(svr::start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("Ism8: Handle command = {} {}", channelUID.getId(), command);
|
||||
Channel channel = getThing().getChannel(channelUID);
|
||||
if (channel == null) {
|
||||
return;
|
||||
}
|
||||
IDataPoint dataPoint = getDataPoint(channel);
|
||||
if (dataPoint == null) {
|
||||
return;
|
||||
}
|
||||
if (command == RefreshType.REFRESH) {
|
||||
updateChannel(dataPoint);
|
||||
} else {
|
||||
setDataPoint(dataPoint, command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,46 +98,13 @@ public class Ism8Handler extends BaseThingHandler implements IDataPointChangeLis
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.config = getConfigAs(Ism8Configuration.class);
|
||||
Ism8Configuration cfg = this.config;
|
||||
final String uid = this.getThing().getUID().getAsString();
|
||||
Server svr = new Server(cfg.getPortNumber(), uid);
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
if (channel.getConfiguration().containsKey("id") && channel.getConfiguration().containsKey("type")) {
|
||||
try {
|
||||
int id = Integer.parseInt(channel.getConfiguration().get("id").toString());
|
||||
String type = channel.getConfiguration().get("type").toString();
|
||||
String description = channel.getLabel();
|
||||
if (type != null && description != null) {
|
||||
svr.addDataPoint(id, type, description);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
this.logger.warn(
|
||||
"Ism8 initialize: ID couldn't be converted correctly. Check the configuration of channel {}. Cfg={}",
|
||||
channel.getLabel(), channel.getConfiguration());
|
||||
}
|
||||
} else {
|
||||
this.logger.debug("Ism8: ID or type missing - Channel={} Cfg={}", channel.getLabel(),
|
||||
channel.getConfiguration());
|
||||
}
|
||||
this.logger.debug("Ism8: Channel={}", channel.getConfiguration().toString());
|
||||
}
|
||||
|
||||
this.updateStatus(ThingStatus.UNKNOWN);
|
||||
svr.addDataPointChangeListener(this);
|
||||
scheduler.execute(svr::start);
|
||||
this.server = svr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataPointChanged(@Nullable DataPointChangedEvent e) {
|
||||
if (e != null) {
|
||||
IDataPoint dataPoint = e.getDataPoint();
|
||||
if (dataPoint != null) {
|
||||
this.logger.debug("Ism8: dataPointChanged {}", dataPoint.toString());
|
||||
this.updateDataPoint(dataPoint);
|
||||
logger.debug("Ism8: dataPointChanged {}", dataPoint.toString());
|
||||
this.updateChannel(dataPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,25 +114,89 @@ public class Ism8Handler extends BaseThingHandler implements IDataPointChangeLis
|
||||
this.updateStatus(status);
|
||||
}
|
||||
|
||||
private void updateDataPoint(IDataPoint dataPoint) {
|
||||
this.updateStatus(ThingStatus.ONLINE);
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
if (channel.getConfiguration().containsKey("id")) {
|
||||
try {
|
||||
int id = Integer.parseInt(channel.getConfiguration().get("id").toString());
|
||||
if (id == dataPoint.getId()) {
|
||||
this.logger.debug("Ism8 updateDataPoint ID:{} {}", dataPoint.getId(), dataPoint.getValueText());
|
||||
Object val = dataPoint.getValueObject();
|
||||
if (val != null) {
|
||||
updateState(channel.getUID(), new QuantityType<>(val.toString()));
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
this.logger.warn(
|
||||
"Ism8 updateDataPoint: ID couldn't be converted correctly. Check the configuration of channel {}. {}",
|
||||
channel.getLabel(), e.getMessage());
|
||||
private boolean registerDataPointToServer(Configuration config, @Nullable String description) {
|
||||
Server svr = this.server;
|
||||
if (config.containsKey(CHANNEL_CONFIG_ID) && config.containsKey(CHANNEL_CONFIG_TYPE)) {
|
||||
try {
|
||||
int id = Integer.parseInt(config.get(CHANNEL_CONFIG_ID).toString());
|
||||
String type = config.get(CHANNEL_CONFIG_TYPE).toString();
|
||||
if (svr != null && type != null && description != null) {
|
||||
svr.addDataPoint(id, type, description);
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Ism8: ID couldn't be converted correctly. Check the configuration of channel {}. Cfg={}",
|
||||
description, config);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Ism8: ID or type missing - Channel={} Cfg={}", description, config);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setDataPoint(IDataPoint dataPoint, Command command) {
|
||||
Server svr = this.server;
|
||||
if (svr != null) {
|
||||
try {
|
||||
svr.sendData(Ism8DomainMap.toISM8WriteData(dataPoint, command));
|
||||
} catch (IOException e) {
|
||||
logger.debug("Writting to Ism8 DataPoint '{}' failed. '{}'", dataPoint.getId(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable IDataPoint getDataPoint(Channel channel) {
|
||||
IDataPoint dataPoint = null;
|
||||
Configuration config = channel.getConfiguration();
|
||||
Server svr = this.server;
|
||||
if (svr == null) {
|
||||
return dataPoint;
|
||||
}
|
||||
if (config.containsKey(CHANNEL_CONFIG_ID) && config.containsKey(CHANNEL_CONFIG_TYPE)) {
|
||||
try {
|
||||
int id = Integer.parseInt(config.get(CHANNEL_CONFIG_ID).toString());
|
||||
dataPoint = svr.getDataPoint(id);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.debug("Retrieving Ism8 DataPoint '{}' failed. '{}'", channel.getConfiguration(), e.getMessage());
|
||||
}
|
||||
} else {
|
||||
logger.debug("Ism8: ID or type missing - Channel={} Cfg={}", channel.getLabel(),
|
||||
channel.getConfiguration());
|
||||
}
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
private boolean updateChannel(Channel channel, IDataPoint dataPoint) {
|
||||
try {
|
||||
int id = Integer.parseInt(channel.getConfiguration().get(CHANNEL_CONFIG_ID).toString());
|
||||
if (id == dataPoint.getId()) {
|
||||
if (dataPoint.getValueObject() != null) {
|
||||
logger.debug("Ism8: updating channel {} with datapoint: {}", channel.getUID().getAsString(),
|
||||
dataPoint.getId());
|
||||
updateState(channel.getUID(), Ism8DomainMap.toOpenHABState(dataPoint));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
logger.debug("Ism8 channel: {} and DataPoint do not have a matching Id: {} vs {}", channel.getUID(), id,
|
||||
dataPoint.getId());
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn(
|
||||
"Ism8 updateChannel: ID couldn't be converted correctly. Check the configuration of channel {}. {}",
|
||||
channel.getLabel(), e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateChannel(IDataPoint dataPoint) {
|
||||
this.updateStatus(ThingStatus.ONLINE);
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
if (channel.getConfiguration().containsKey(CHANNEL_CONFIG_ID)) {
|
||||
if (updateChannel(channel, dataPoint)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.debug("Ism8: no channel was found for DataPoint id: {}", dataPoint.getId());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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.ism8.internal.util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Pressure;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.ism8.server.IDataPoint;
|
||||
import org.openhab.core.library.dimension.VolumetricFlowRate;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Ism8DomainMap} class holds static methods for domain mapping
|
||||
*
|
||||
* @author Leo Siepel - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public final class Ism8DomainMap {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Ism8DomainMap.class);
|
||||
|
||||
public static State toOpenHABState(IDataPoint dataPoint) {
|
||||
Object value = dataPoint.getValueObject();
|
||||
if (value == null) {
|
||||
return UnDefType.NULL;
|
||||
}
|
||||
|
||||
Unit<?> unit = dataPoint.getUnit();
|
||||
if (SIUnits.CELSIUS.equals(unit)) {
|
||||
return new QuantityType<Temperature>((Double) value, SIUnits.CELSIUS);
|
||||
} else if (Units.KELVIN.equals(unit)) {
|
||||
return new QuantityType<Temperature>((Double) value, Units.KELVIN);
|
||||
} else if (Units.CUBICMETRE_PER_HOUR.equals(unit)) {
|
||||
return new QuantityType<VolumetricFlowRate>((Double) value, Units.CUBICMETRE_PER_HOUR);
|
||||
} else if (Units.BAR.equals(unit)) {
|
||||
return new QuantityType<Pressure>((Double) value, Units.BAR);
|
||||
} else if (Units.PERCENT.equals(unit)) {
|
||||
return new QuantityType<Dimensionless>((Double) value, Units.PERCENT);
|
||||
} else if (Units.ONE.equals(unit)) {
|
||||
return new QuantityType<Dimensionless>((Double) value, Units.ONE);
|
||||
} else if (value instanceof Boolean) {
|
||||
return OnOffType.from((boolean) value);
|
||||
} else if (value instanceof Byte) {
|
||||
return new QuantityType<Dimensionless>((byte) value, Units.ONE);
|
||||
}
|
||||
|
||||
LOGGER.debug("Failed to map DataPoint id: {} val: {}, to UoM state. Performing fallback.", dataPoint.getId(),
|
||||
dataPoint.getValueText());
|
||||
|
||||
return new QuantityType<>(value.toString());
|
||||
}
|
||||
|
||||
public static byte[] toISM8WriteData(IDataPoint dataPoint, Command command) {
|
||||
if (command instanceof QuantityType) {
|
||||
Unit<?> expectedUnit = dataPoint.getUnit();
|
||||
if (expectedUnit != null) {
|
||||
QuantityType<?> state = Objects.requireNonNull(((QuantityType<?>) command).toUnit(expectedUnit));
|
||||
return dataPoint.createWriteData(state.doubleValue());
|
||||
}
|
||||
return dataPoint.createWriteData(command);
|
||||
} else if (command instanceof OnOffType) {
|
||||
return dataPoint.createWriteData(command);
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ package org.openhab.binding.ism8.server;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@ -32,7 +34,8 @@ public abstract class DataPointBase<@Nullable T> implements IDataPoint {
|
||||
private final String knxDataType;
|
||||
private final String description;
|
||||
private T value;
|
||||
private String unit = "";
|
||||
@Nullable
|
||||
private Unit<?> unit;
|
||||
|
||||
protected DataPointBase(int id, String knxDataType, String description) {
|
||||
this.id = id;
|
||||
@ -81,7 +84,7 @@ public abstract class DataPointBase<@Nullable T> implements IDataPoint {
|
||||
public abstract String getValueText();
|
||||
|
||||
@Override
|
||||
public String getUnit() {
|
||||
public @Nullable Unit<?> getUnit() {
|
||||
return this.unit;
|
||||
}
|
||||
|
||||
@ -89,7 +92,7 @@ public abstract class DataPointBase<@Nullable T> implements IDataPoint {
|
||||
* Sets the unit of the data-point.
|
||||
*
|
||||
*/
|
||||
public void setUnit(String value) {
|
||||
public void setUnit(@Nullable Unit<?> value) {
|
||||
this.unit = value;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class DataPointBool extends DataPointBase<@Nullable Boolean> {
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getValueObject() {
|
||||
return this.getValue() ? "1" : "0";
|
||||
return this.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,7 +55,7 @@ public class DataPointBool extends DataPointBase<@Nullable Boolean> {
|
||||
@Override
|
||||
protected byte[] convertWriteValue(Object value) {
|
||||
String valueText = value.toString().toLowerCase();
|
||||
if ("true".equalsIgnoreCase(valueText) || "1".equalsIgnoreCase(valueText)) {
|
||||
if ("true".equalsIgnoreCase(valueText) || "1".equalsIgnoreCase(valueText) || "ON".equalsIgnoreCase(valueText)) {
|
||||
this.setValue(true);
|
||||
return new byte[] { 0x01 };
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -34,11 +35,11 @@ public class DataPointLongValue extends DataPointBase<@Nullable Double> {
|
||||
super(id, knxDataType, description);
|
||||
|
||||
if ("13.002".equals(knxDataType)) {
|
||||
this.setUnit("m³/h");
|
||||
this.setUnit(Units.CUBICMETRE_PER_HOUR);
|
||||
this.factor = 0.0001f;
|
||||
this.outputFormat = "%.1f";
|
||||
} else {
|
||||
this.setUnit("");
|
||||
this.setUnit(Units.ONE);
|
||||
this.factor = 1.0f;
|
||||
this.outputFormat = "%.1f";
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ package org.openhab.binding.ism8.server;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -29,7 +30,7 @@ public class DataPointScaling extends DataPointBase<@Nullable Double> {
|
||||
|
||||
public DataPointScaling(int id, String knxDataType, String description) {
|
||||
super(id, knxDataType, description);
|
||||
this.setUnit("%");
|
||||
this.setUnit(Units.PERCENT);
|
||||
this.outputFormat = "%.1f";
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -34,15 +36,15 @@ public class DataPointValue extends DataPointBase<@Nullable Double> {
|
||||
super(id, knxDataType, description);
|
||||
this.factor = 0.0f;
|
||||
if ("9.001".equals(knxDataType)) {
|
||||
this.setUnit("°C");
|
||||
this.setUnit(SIUnits.CELSIUS);
|
||||
this.factor = 0.01f;
|
||||
this.outputFormat = "%.1f";
|
||||
} else if ("9.002".equals(knxDataType)) {
|
||||
this.setUnit("°K");
|
||||
this.setUnit(Units.KELVIN);
|
||||
this.factor = 0.01f;
|
||||
this.outputFormat = "%.1f";
|
||||
} else if ("9.006".equals(knxDataType)) {
|
||||
this.setUnit("Bar");
|
||||
this.setUnit(Units.BAR);
|
||||
this.factor = 0.0000001f;
|
||||
this.outputFormat = "%.2f";
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.ism8.server;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
@ -28,7 +30,8 @@ public interface IDataPoint {
|
||||
* Gets the unit of the data-point.
|
||||
*
|
||||
*/
|
||||
String getUnit();
|
||||
@Nullable
|
||||
Unit<?> getUnit();
|
||||
|
||||
/**
|
||||
* Gets the type of the data-point.
|
||||
|
@ -157,6 +157,7 @@ public class Server extends Thread {
|
||||
ServerSocket serverSock = this.serverSocket;
|
||||
if (serverSock != null) {
|
||||
serverSock.close();
|
||||
this.serverSocket = null;
|
||||
}
|
||||
|
||||
Socket clientSocket = this.client;
|
||||
@ -166,6 +167,8 @@ public class Server extends Thread {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error stopping Communication. {}", e.getMessage());
|
||||
this.serverSocket = null;
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="device" extensible="switch, switch-readonly, number, number-readonly">
|
||||
<thing-type id="device"
|
||||
extensible="switch-r, switch-rw, percentage-r, percentage-rw, temperature-r, temperature-rw, pressure-r, flowrate-r, mode-rw, mode-r">
|
||||
<label>ISM8 Device</label>
|
||||
<description>ISM8 Interface</description>
|
||||
|
||||
@ -17,7 +18,7 @@
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="switch">
|
||||
<channel-type id="switch-rw">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Digital DataPoint</label>
|
||||
<config-description>
|
||||
@ -38,7 +39,7 @@
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="switch-readonly">
|
||||
<channel-type id="switch-r">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Digital Readonly DataPoint</label>
|
||||
<state readOnly="true"/>
|
||||
@ -60,9 +61,9 @@
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="number-readonly">
|
||||
<item-type>Number</item-type>
|
||||
<label>Value Readonly DataPoint</label>
|
||||
<channel-type id="percentage-r">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Percentage Readonly DataPoint</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
@ -74,21 +75,33 @@
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="5.001">DPT_Scaling</option>
|
||||
<option value="9.001">DPT_Value_Temp</option>
|
||||
<option value="9.002">DPT_Value_Tempd</option>
|
||||
<option value="9.006">DPT_Value_Pres</option>
|
||||
<option value="13.002">DPT_FlowRate</option>
|
||||
<option value="20.102">DPT_HVACMode</option>
|
||||
<option value="20.103">DPT_DHWMode</option>
|
||||
<option value="20.105">DPT_HVACContrMode</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="number">
|
||||
<item-type>Number</item-type>
|
||||
<label>Value DataPoint</label>
|
||||
<channel-type id="percentage-rw">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Percentage DataPoint</label>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
<description>Put the number of the DataPoint ID to be mapped from the heating sytem.</description>
|
||||
</parameter>
|
||||
<parameter name="type" type="text" required="true">
|
||||
<label>Type</label>
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="5.001">DPT_Scaling</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="temperature-r">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature Readonly DataPoint</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
@ -99,6 +112,102 @@
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="9.001">DPT_Value_Temp</option>
|
||||
<option value="9.002">DPT_Value_Tempd</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="temperature-rw">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature DataPoint</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
<description>Put the number of the DataPoint ID to be mapped from the heating sytem.</description>
|
||||
</parameter>
|
||||
<parameter name="type" type="text" required="true">
|
||||
<label>Type</label>
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="9.001">DPT_Value_Temp</option>
|
||||
<option value="9.002">DPT_Value_Tempd</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pressure-r">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Pressure Readonly DataPoint</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
<description>Put the number of the DataPoint ID to be mapped from the heating sytem.</description>
|
||||
</parameter>
|
||||
<parameter name="type" type="text" required="true">
|
||||
<label>Type</label>
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="9.006">DPT_Value_Pres</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="flowrate-r">
|
||||
<item-type>Number:VolumetricFlowRate</item-type>
|
||||
<label>Flowrate Readonly DataPoint</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
<description>Put the number of the DataPoint ID to be mapped from the heating sytem.</description>
|
||||
</parameter>
|
||||
<parameter name="type" type="text" required="true">
|
||||
<label>Type</label>
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="13.002">DPT_FlowRate</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="mode-r">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Mode Readonly DataPoint</label>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
<description>Put the number of the DataPoint ID to be mapped from the heating sytem.</description>
|
||||
</parameter>
|
||||
<parameter name="type" type="text" required="true">
|
||||
<label>Type</label>
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="20.102">DPT_HVACMode</option>
|
||||
<option value="20.103">DPT_DHWMode</option>
|
||||
<option value="20.105">DPT_HVACContrMode</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="mode-rw">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Mode DataPoint</label>
|
||||
<config-description>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>DP ID</label>
|
||||
<description>Put the number of the DataPoint ID to be mapped from the heating sytem.</description>
|
||||
</parameter>
|
||||
<parameter name="type" type="text" required="true">
|
||||
<label>Type</label>
|
||||
<description>Put the KNX-type of the DataPoint (e.g. DPT_Value_Temp / 9.001)</description>
|
||||
<options>
|
||||
<option value="20.102">DPT_HVACMode</option>
|
||||
<option value="20.103">DPT_DHWMode</option>
|
||||
<option value="20.105">DPT_HVACContrMode</option>
|
||||
|
@ -0,0 +1,136 @@
|
||||
/**
|
||||
* 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.ism8.internal;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.openhab.binding.ism8.internal.Ism8BindingConstants.*;
|
||||
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.openhab.binding.ism8.server.DataPointBool;
|
||||
import org.openhab.binding.ism8.server.DataPointByteValue;
|
||||
import org.openhab.binding.ism8.server.DataPointChangedEvent;
|
||||
import org.openhab.binding.ism8.server.DataPointValue;
|
||||
import org.openhab.binding.ism8.server.IDataPoint;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leo Siepel - Initial contribution
|
||||
*
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@NonNullByDefault
|
||||
public class Ism8HandlerTest {
|
||||
|
||||
private @Mock @NonNullByDefault({}) ThingHandlerCallback thingHandlerCallback;
|
||||
private @NonNullByDefault({}) Thing ism8Thing;
|
||||
private @NonNullByDefault({}) Ism8Handler thingHandler;
|
||||
private ThingUID thingUID = new ThingUID(BINDING_ID, "ism8server");
|
||||
private ChannelUID channel1001 = new ChannelUID(thingUID, "switch1");
|
||||
private ChannelUID channel9001 = new ChannelUID(thingUID, "tempC");
|
||||
private ChannelUID channel9002 = new ChannelUID(thingUID, "tempD");
|
||||
private ChannelUID channel20001 = new ChannelUID(thingUID, "mode1");
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
Configuration config = new Configuration();
|
||||
|
||||
ism8Thing = ThingBuilder.create(THING_TYPE_DEVICE, thingUID).withConfiguration(config)
|
||||
.withChannel(ChannelBuilder.create(channel9002, "Number:Temperature")
|
||||
.withConfiguration(createChannelConfig("5", "9.002")).build())
|
||||
.withChannel(ChannelBuilder.create(channel9001, "Number:Temperature")
|
||||
.withConfiguration(createChannelConfig("4", "9.001")).build())
|
||||
.withChannel(ChannelBuilder.create(channel1001, "Switch")
|
||||
.withConfiguration(createChannelConfig("9", "1.001")).build())
|
||||
.withChannel(ChannelBuilder.create(channel20001, "Switch")
|
||||
.withConfiguration(createChannelConfig("2", "20.001")).build())
|
||||
.build();
|
||||
|
||||
thingHandler = new Ism8Handler(ism8Thing);
|
||||
thingHandler.initialize();
|
||||
}
|
||||
|
||||
private Configuration createChannelConfig(String id, String type) {
|
||||
Configuration config = new Configuration();
|
||||
config.put(CHANNEL_CONFIG_ID, id);
|
||||
config.put(CHANNEL_CONFIG_TYPE, type);
|
||||
return config;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void process1001MessageAndUpdateChannel() {
|
||||
// arrange
|
||||
IDataPoint dataPoint = new DataPointBool(9, "1.001", "Datapoint_1.001");
|
||||
dataPoint.processData(HexUtils.hexToBytes("0009030100"));
|
||||
DataPointChangedEvent event = new DataPointChangedEvent(new Object(), dataPoint);
|
||||
thingHandler.setCallback(thingHandlerCallback);
|
||||
|
||||
// act
|
||||
thingHandler.dataPointChanged(event);
|
||||
|
||||
// assert
|
||||
Mockito.verify(thingHandlerCallback).stateUpdated(eq(channel1001), eq(OnOffType.from(false)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void process9001MessageAndUpdateChannel() {
|
||||
// arrange
|
||||
IDataPoint dataPoint = new DataPointValue(4, "9.001", "Datapoint_9.001");
|
||||
dataPoint.processData(HexUtils.hexToBytes("000403020FE9"));
|
||||
DataPointChangedEvent event = new DataPointChangedEvent(new Object(), dataPoint);
|
||||
thingHandler.setCallback(thingHandlerCallback);
|
||||
|
||||
// act
|
||||
thingHandler.dataPointChanged(event);
|
||||
|
||||
// assert
|
||||
Mockito.verify(thingHandlerCallback).stateUpdated(eq(channel9001),
|
||||
eq(new QuantityType<Temperature>(40.49999909475446, SIUnits.CELSIUS)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void process20001MessageAndUpdateChannel() {
|
||||
// arrange
|
||||
IDataPoint dataPoint = new DataPointByteValue(2, "20.102", "Datapoint_20.102");
|
||||
dataPoint.processData(HexUtils.hexToBytes("0002030101"));
|
||||
DataPointChangedEvent event = new DataPointChangedEvent(new Object(), dataPoint);
|
||||
thingHandler.setCallback(thingHandlerCallback);
|
||||
|
||||
// act
|
||||
thingHandler.dataPointChanged(event);
|
||||
|
||||
// assert
|
||||
Mockito.verify(thingHandlerCallback).stateUpdated(eq(channel20001),
|
||||
eq(new QuantityType<Dimensionless>(1, Units.ONE)));
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 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.ism8.internal.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.openhab.binding.ism8.server.DataPointBool;
|
||||
import org.openhab.binding.ism8.server.DataPointByteValue;
|
||||
import org.openhab.binding.ism8.server.DataPointScaling;
|
||||
import org.openhab.binding.ism8.server.DataPointValue;
|
||||
import org.openhab.binding.ism8.server.IDataPoint;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leo Siepel - Initial contribution
|
||||
*
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@NonNullByDefault
|
||||
public class Ism8DomainMapTest {
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDataPointValueToMessageSameUnit() {
|
||||
// arrange
|
||||
Command command = new QuantityType<>(40.5, SIUnits.CELSIUS);
|
||||
IDataPoint dataPoint = new DataPointValue(4, "9.001", "Datapoint_9.001");
|
||||
|
||||
// act
|
||||
byte[] result = Ism8DomainMap.toISM8WriteData(dataPoint, command);
|
||||
|
||||
// assert
|
||||
assertEquals(String.format("%.1f", 40.5), dataPoint.getValueText());
|
||||
assertEquals("0620F080001604000000F0C100040001000400020FE9", HexUtils.bytesToHex(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDataPointValueToMessagOtherUnit() {
|
||||
// arrange
|
||||
Command command = new QuantityType<>(104.9, ImperialUnits.FAHRENHEIT);
|
||||
IDataPoint dataPoint = new DataPointValue(4, "9.001", "Datapoint_9.001");
|
||||
|
||||
// act
|
||||
byte[] result = Ism8DomainMap.toISM8WriteData(dataPoint, command);
|
||||
|
||||
// assert
|
||||
assertEquals(String.format("%.1f", 40.5), dataPoint.getValueText());
|
||||
assertEquals("0620F080001604000000F0C100040001000400020FE9", HexUtils.bytesToHex(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDataPointBoolToMessage() {
|
||||
// arrange
|
||||
Command command = OnOffType.from(true);
|
||||
IDataPoint dataPoint = new DataPointBool(9, "1.001", "Datapoint_1.001");
|
||||
|
||||
// act
|
||||
byte[] result = Ism8DomainMap.toISM8WriteData(dataPoint, command);
|
||||
|
||||
// assert
|
||||
assertEquals("True", dataPoint.getValueText());
|
||||
assertEquals("0620F080001504000000F0C1000900010009000101", HexUtils.bytesToHex(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDataPointScalingToMessage() {
|
||||
// arrange
|
||||
Command command = new QuantityType<Dimensionless>(13, Units.PERCENT);
|
||||
IDataPoint dataPoint = new DataPointScaling(3, "5.001", "Datapoint_5.001");
|
||||
|
||||
// act
|
||||
byte[] result = Ism8DomainMap.toISM8WriteData(dataPoint, command);
|
||||
|
||||
// assert
|
||||
assertEquals(String.format("%.1f", 13.0), dataPoint.getValueText());
|
||||
assertEquals("0620F080001504000000F0C1000300010003000121", HexUtils.bytesToHex(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDataPointValueToOHState() {
|
||||
// arrange
|
||||
IDataPoint dataPoint = new DataPointValue(4, "9.001", "Datapoint_9.001");
|
||||
dataPoint.processData(HexUtils.hexToBytes("000403020FE9"));
|
||||
|
||||
// act
|
||||
State result = Ism8DomainMap.toOpenHABState(dataPoint);
|
||||
|
||||
// assert
|
||||
assertEquals(new QuantityType<Temperature>(40.49999909475446, SIUnits.CELSIUS), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDataPointLongToOHState() {
|
||||
// arrange
|
||||
IDataPoint dataPoint = new DataPointByteValue(2, "20.102", "Datapoint_20.102");
|
||||
dataPoint.processData(HexUtils.hexToBytes("0002030101"));
|
||||
|
||||
// act
|
||||
State result = Ism8DomainMap.toOpenHABState(dataPoint);
|
||||
|
||||
// assert
|
||||
assertEquals(new QuantityType<Dimensionless>(1, Units.ONE), result);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user