added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
12
bundles/org.openhab.binding.ihc/src/main/feature/feature.xml
Normal file
12
bundles/org.openhab.binding.ihc/src/main/feature/feature.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.ihc-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-ihc" description="IHC / ELKO Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle dependency="true">mvn:org.apache.httpcomponents/httpcore-osgi/4.4.10</bundle>
|
||||
<bundle dependency="true">mvn:org.apache.httpcomponents/httpclient-osgi/4.5.8</bundle>
|
||||
<bundle dependency="true">mvn:commons-logging/commons-logging/1.2</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.ihc/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class to handle button press durations
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ButtonPressDurationDetector {
|
||||
private final Logger logger = LoggerFactory.getLogger(ButtonPressDurationDetector.class);
|
||||
|
||||
private boolean shortPress;
|
||||
private boolean longPress;
|
||||
private Duration duration;
|
||||
private long longPressTime;
|
||||
private long longPressMaxTime;
|
||||
|
||||
public boolean isShortPress() {
|
||||
return shortPress;
|
||||
}
|
||||
|
||||
public boolean isLongPress() {
|
||||
return longPress;
|
||||
}
|
||||
|
||||
public ButtonPressDurationDetector(Duration duration, long longPressTime, long longPressMaxTime) {
|
||||
this.duration = duration;
|
||||
this.longPressTime = longPressTime;
|
||||
this.longPressMaxTime = longPressMaxTime;
|
||||
|
||||
calculate();
|
||||
}
|
||||
|
||||
private void calculate() {
|
||||
if (duration.toMillis() < 0) {
|
||||
logger.debug("Button press duration < 0ms");
|
||||
} else if (isBetween(duration.toMillis(), 0, longPressTime)) {
|
||||
logger.debug("Button press duration > {}ms and < {}ms", 0, longPressTime);
|
||||
shortPress = true;
|
||||
} else if (isBetween(duration.toMillis(), longPressTime, longPressMaxTime)) {
|
||||
logger.debug("Button press duration > {}ms and < {}ms", longPressTime, longPressMaxTime);
|
||||
longPress = true;
|
||||
} else {
|
||||
logger.debug("Button press duration > {}ms, ignore it", longPressMaxTime);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBetween(long value, long minValue, long maxValueInclusive) {
|
||||
return (value > minValue && value <= maxValueInclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[ duration=%sms, shortPress=%b, longPress=%b ]", duration.toMillis(), shortPress,
|
||||
longPress);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import static org.openhab.binding.ihc.internal.IhcBindingConstants.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.ihc.internal.config.ChannelParams;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
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.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Generic methods related to openHAB channels.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ChannelUtils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelUtils.class);
|
||||
|
||||
public static Set<Integer> getAllChannelsResourceIds(Thing thing) {
|
||||
Set<Integer> resourceIds = new HashSet<>();
|
||||
|
||||
thing.getChannels().forEach(c -> {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(c);
|
||||
if (params.getResourceId() != null && params.getResourceId() != 0) {
|
||||
resourceIds.add(params.getResourceId());
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
LOGGER.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
return resourceIds;
|
||||
}
|
||||
|
||||
public static Set<Integer> getAllTriggerChannelsResourceIds(Thing thing) {
|
||||
Set<Integer> resourceIds = new HashSet<>();
|
||||
|
||||
thing.getChannels().forEach(c -> {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(c);
|
||||
if (params.getChannelTypeId() != null) {
|
||||
switch (params.getChannelTypeId()) {
|
||||
case CHANNEL_TYPE_PUSH_BUTTON_TRIGGER:
|
||||
if (params.getResourceId() != null && params.getResourceId() != 0) {
|
||||
resourceIds.add(params.getResourceId());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
LOGGER.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
return resourceIds;
|
||||
}
|
||||
|
||||
public static void addChannelsFromProjectFile(Thing thing, Document projectFile, List<Channel> thingChannels) {
|
||||
if (projectFile != null) {
|
||||
try {
|
||||
NodeList nodes = projectFile.getElementsByTagName("product_dataline");
|
||||
if (nodes != null) {
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element node = (Element) nodes.item(i);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("dataline_input"), "Switch",
|
||||
"input", CHANNEL_TYPE_SWITCH, thingChannels);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("dataline_output"), "Switch",
|
||||
"output", CHANNEL_TYPE_SWITCH, thingChannels);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("resource_temperature"), "Number",
|
||||
"temperature", CHANNEL_TYPE_NUMBER, thingChannels);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("resource_humidity_level"),
|
||||
"Number", "humidity", CHANNEL_TYPE_NUMBER, thingChannels);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.warn("Error occured when adding channels, reason: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
NodeList nodes = projectFile.getElementsByTagName("product_airlink");
|
||||
if (nodes != null) {
|
||||
addRFDeviceChannels(thing, nodes, thingChannels);
|
||||
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element node = (Element) nodes.item(i);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_input"), "Switch", "input",
|
||||
CHANNEL_TYPE_SWITCH, thingChannels);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_output"), "Switch",
|
||||
"output", CHANNEL_TYPE_SWITCH, thingChannels);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_relay"), "Switch",
|
||||
"output", CHANNEL_TYPE_SWITCH, thingChannels);
|
||||
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_dimming"), "Dimmer",
|
||||
"output", CHANNEL_TYPE_SWITCH, thingChannels);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.warn("Error occured when adding channels, reason: {}", e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Project file data doesn't exist, can't automatically create channels!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void addControllerChannels(Thing thing, List<Channel> thingChannels) {
|
||||
if (thing != null && thingChannels != null) {
|
||||
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), CHANNEL_CONTROLLER_STATE), "String")
|
||||
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_CONTROLLER_STATE)).build();
|
||||
addOrUpdateChannel(channel, thingChannels);
|
||||
|
||||
channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), CHANNEL_CONTROLLER_UPTIME), "Number")
|
||||
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_CONTROLLER_UPTIME)).build();
|
||||
addOrUpdateChannel(channel, thingChannels);
|
||||
|
||||
channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), CHANNEL_CONTROLLER_TIME), "DateTime")
|
||||
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_CONTROLLER_TIME)).build();
|
||||
addOrUpdateChannel(channel, thingChannels);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addRFDeviceChannels(Thing thing, NodeList nodes, List<Channel> thingChannels) {
|
||||
if (thing != null && nodes != null && thingChannels != null) {
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element element = (Element) nodes.item(i);
|
||||
Long serialNumber = Long.parseLong(element.getAttribute("serialnumber").replace("_0x", ""), 16);
|
||||
if (serialNumber != 0) {
|
||||
String name = element.getAttribute("name");
|
||||
String position = element.getAttribute("position");
|
||||
|
||||
String serialNumberHex = Long.toHexString(serialNumber);
|
||||
Configuration configuration = new Configuration();
|
||||
configuration.put("serialNumber", serialNumber);
|
||||
|
||||
// low battery
|
||||
String channelId = String.format("%s-lowBattery", serialNumberHex);
|
||||
String label = createDescription(position, name, serialNumberHex, "Low Battery");
|
||||
|
||||
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channelId), "Switch")
|
||||
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_RF_LOW_BATTERY))
|
||||
.withConfiguration(configuration).withLabel(label).build();
|
||||
addOrUpdateChannel(channel, thingChannels);
|
||||
|
||||
// signal level
|
||||
channelId = String.format("%s-signalStrength", serialNumberHex);
|
||||
label = createDescription(position, name, serialNumberHex, "Signal Strength");
|
||||
|
||||
channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channelId), "String")
|
||||
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_RF_SIGNAL_STRENGTH))
|
||||
.withConfiguration(configuration).withLabel(label).build();
|
||||
addOrUpdateChannel(channel, thingChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addChannelsFromProjectFile(Thing thing, NodeList nodes, String acceptedItemType, String group,
|
||||
String channelType, List<Channel> thingChannels) {
|
||||
if (thing != null && nodes != null && thingChannels != null) {
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element element = (Element) nodes.item(i);
|
||||
Element parent = (Element) element.getParentNode();
|
||||
|
||||
if ("settings".equals(parent.getNodeName())) {
|
||||
// get settings element parent
|
||||
parent = (Element) parent.getParentNode();
|
||||
}
|
||||
|
||||
Element parentParent = (Element) parent.getParentNode();
|
||||
|
||||
String parentName = parent.getAttribute("name");
|
||||
String parentPosition = parent.getAttribute("position");
|
||||
String parentParentName = parentParent.getAttribute("name");
|
||||
|
||||
String resourceName = element.getAttribute("name");
|
||||
int resourceId = Integer.parseInt(element.getAttribute("id").replace("_0x", ""), 16);
|
||||
|
||||
String description = createDescription(parentParentName, parentPosition, parentName, resourceName);
|
||||
ChannelUID channelUID = new ChannelUID(thing.getUID(), group + resourceId);
|
||||
ChannelTypeUID type = new ChannelTypeUID(BINDING_ID, channelType);
|
||||
Configuration configuration = new Configuration();
|
||||
configuration.put(PARAM_RESOURCE_ID, new Integer(resourceId));
|
||||
|
||||
Channel channel = ChannelBuilder.create(channelUID, acceptedItemType).withConfiguration(configuration)
|
||||
.withLabel(description).withType(type).build();
|
||||
addOrUpdateChannel(channel, thingChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String createDescription(String name1, String name2, String name3, String name4) {
|
||||
String description = "";
|
||||
if (StringUtils.isNotEmpty(name1)) {
|
||||
description = name1;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(name2)) {
|
||||
description += String.format(" - %s", name2);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(name3)) {
|
||||
description += String.format(" - %s", name3);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(name4)) {
|
||||
description += String.format(" - %s", name4);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
private static void addOrUpdateChannel(Channel newChannel, List<Channel> thingChannels) {
|
||||
removeChannelByUID(thingChannels, newChannel.getUID());
|
||||
thingChannels.add(newChannel);
|
||||
}
|
||||
|
||||
private static void removeChannelByUID(List<Channel> thingChannels, ChannelUID channelUIDtoRemove) {
|
||||
Predicate<Channel> channelPredicate = c -> c.getUID().getId().equals(channelUIDtoRemove.getId());
|
||||
thingChannels.removeIf(channelPredicate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
|
||||
|
||||
/**
|
||||
* Class for holding enumerations from IHC / ELKO project file.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class EnumDictionary {
|
||||
|
||||
private Map<Integer, List<IhcEnumValue>> enumDictionary = new HashMap<>();
|
||||
|
||||
public EnumDictionary(Map<Integer, List<IhcEnumValue>> enums) {
|
||||
this.enumDictionary = enums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all possible enumerated values for corresponding enum type.
|
||||
*
|
||||
* @param typeDefinititonId Enum type definition identifier.
|
||||
* @return list of enum values.
|
||||
*/
|
||||
public List<IhcEnumValue> getEnumValues(int typeDefinititonId) {
|
||||
return enumDictionary.get(typeDefinititonId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link IhcBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IhcBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "ihc";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_CONTROLLER = new ThingTypeUID(BINDING_ID, "controller");
|
||||
|
||||
public static final String PROPERTY_MANUFACTURER = "controllerManufacturer";
|
||||
public static final String PROPERTY_SERIALNUMBER = "controllerSerialNumber";
|
||||
public static final String PROPERTY_SW_VERSION = "controllerSwVersion";
|
||||
public static final String PROPERTY_FW_VERSION = "controllerHwVersion";
|
||||
public static final String PROPERTY_APP_WITHOUT_VIEWER = "controllerIsWithoutViewer";
|
||||
public static final String PROPERTY_SW_DATE = "controllerSwDate";
|
||||
public static final String PROPERTY_PRODUCTION_DATE = "controllerProductionDate";
|
||||
public static final String PROPERTY_PROJECT_DATE = "projectDate";
|
||||
public static final String PROPERTY_PROJECT_NUMBER = "projectNumber";
|
||||
public static final String PROPERTY_DATALINE_VERSION = "controllerDatalineVersion";
|
||||
public static final String PROPERTY_RF_MODULE_VERSION = "controllerRfModSwVersion";
|
||||
public static final String PROPERTY_RF_MODULE_SERIALNUMBER = "controllerRfModSerialNumber";
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_CONTROLLER_STATE = "controllerState";
|
||||
public static final String CHANNEL_CONTROLLER_UPTIME = "controllerUptime";
|
||||
public static final String CHANNEL_CONTROLLER_TIME = "controllerTime";
|
||||
|
||||
// List of all Channel type ids
|
||||
public static final String CHANNEL_TYPE_CONTROLLER_STATE = "controller-state";
|
||||
public static final String CHANNEL_TYPE_CONTROLLER_SW_VER = "controller-sw-version";
|
||||
public static final String CHANNEL_TYPE_CONTROLLER_HW_VER = "controller-hw-version";
|
||||
public static final String CHANNEL_TYPE_CONTROLLER_UPTIME = "controller-uptime";
|
||||
public static final String CHANNEL_TYPE_CONTROLLER_TIME = "controller-time";
|
||||
|
||||
public static final String CHANNEL_TYPE_NUMBER = "number";
|
||||
public static final String CHANNEL_TYPE_SWITCH = "switch";
|
||||
public static final String CHANNEL_TYPE_CONTACT = "contact";
|
||||
public static final String CHANNEL_TYPE_DIMMER = "dimmer";
|
||||
public static final String CHANNEL_TYPE_DATETIME = "datetime";
|
||||
public static final String CHANNEL_TYPE_STRING = "string";
|
||||
public static final String CHANNEL_TYPE_ROLLERSHUTTER = "rollershutter";
|
||||
public static final String CHANNEL_TYPE_RF_SIGNAL_STRENGTH = "rf-device-signal-strength";
|
||||
public static final String CHANNEL_TYPE_RF_LOW_BATTERY = "rf-device-low-battery";
|
||||
public static final String CHANNEL_TYPE_PUSH_BUTTON_TRIGGER = "push-button-trigger";
|
||||
|
||||
// List of all channel parameters
|
||||
public static final String PARAM_RESOURCE_ID = "resourceId";
|
||||
public static final String PARAM_DIRECTION = "direction";
|
||||
public static final String PARAM_CMD_TO_REACT = "commandToReact";
|
||||
public static final String PARAM_SERIAL_NUMBER = "serialNumber";
|
||||
public static final String PARAM_PULSE_WIDTH = "pulseWidth";
|
||||
public static final String PARAM_LONG_PRESS_TIME = "longPressTime";
|
||||
public static final String PARAM_INVERTED = "inverted";
|
||||
public static final String PARAM_ON_LEVEL = "onLevel";
|
||||
|
||||
public static final String DIRECTION_READ_WRITE = "ReadWrite";
|
||||
public static final String DIRECTION_WRITE_ONLY = "WriteOnly";
|
||||
public static final String DIRECTION_READ_ONLY = "ReadOnly";
|
||||
|
||||
public static final String EVENT_PRESSED = "PRESSED";
|
||||
public static final String EVENT_RELEASED = "RELEASED";
|
||||
public static final String EVENT_SHORT_PRESS = "SHORT_PRESS";
|
||||
public static final String EVENT_LONG_PRESS = "LONG_PRESS";
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import static org.openhab.binding.ihc.internal.IhcBindingConstants.THING_CONTROLLER;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ihc.internal.handler.IhcHandler;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* The {@link IhcHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.ihc")
|
||||
@NonNullByDefault
|
||||
public class IhcHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(THING_CONTROLLER).collect(Collectors.toSet()));
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(THING_CONTROLLER)) {
|
||||
return new IhcHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
/**
|
||||
* Class to convert IHC RF signal level value to openHAB signal level.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class SignalLevelConverter {
|
||||
|
||||
int signalLevel;
|
||||
|
||||
public SignalLevelConverter(int signalLevel) {
|
||||
this.signalLevel = signalLevel;
|
||||
}
|
||||
|
||||
public int getSystemWideSignalLevel() {
|
||||
return convertSignalLevelToSystemWideLevel(signalLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert internal signal level (0-18) to system wide signal level (0-4).
|
||||
*
|
||||
* @param signalLevel Internal signal level
|
||||
* @return Signal level in system wide level
|
||||
*/
|
||||
private int convertSignalLevelToSystemWideLevel(int signalLevel) {
|
||||
int newLevel;
|
||||
|
||||
/*
|
||||
* IHC signal levels are always between 0-18.
|
||||
*
|
||||
* Use switch case to make level adaption easier in future if needed.
|
||||
*/
|
||||
|
||||
switch (signalLevel) {
|
||||
case 0:
|
||||
case 1:
|
||||
newLevel = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
newLevel = 1;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
newLevel = 2;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
newLevel = 3;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
default:
|
||||
newLevel = 4;
|
||||
}
|
||||
|
||||
return newLevel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.config;
|
||||
|
||||
import static org.openhab.binding.ihc.internal.IhcBindingConstants.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
|
||||
/**
|
||||
* Class for holding channel parameterization.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ChannelParams {
|
||||
|
||||
private String channelTypeId;
|
||||
private Integer resourceId;
|
||||
private String direction;
|
||||
private String commandToReact;
|
||||
private Integer pulseWidth;
|
||||
private Boolean inverted;
|
||||
private Long serialNumber;
|
||||
private Integer longPressTime;
|
||||
private Integer onLevel;
|
||||
|
||||
public ChannelParams(@NonNull Channel channel) throws ConversionException {
|
||||
ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID != null) {
|
||||
channelTypeId = channelTypeUID.getId();
|
||||
}
|
||||
|
||||
Map<String, Object> map = channel.getConfiguration().getProperties();
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
switch (entry.getKey()) {
|
||||
case PARAM_RESOURCE_ID:
|
||||
resourceId = getChannelParameterAsInteger(entry.getValue());
|
||||
break;
|
||||
case PARAM_DIRECTION:
|
||||
direction = getChannelParameterAsString(entry.getValue());
|
||||
break;
|
||||
case PARAM_CMD_TO_REACT:
|
||||
commandToReact = getChannelParameterAsString(entry.getValue());
|
||||
break;
|
||||
case PARAM_SERIAL_NUMBER:
|
||||
serialNumber = getChannelParameterAsLong(entry.getValue());
|
||||
break;
|
||||
case PARAM_PULSE_WIDTH:
|
||||
pulseWidth = getChannelParameterAsInteger(entry.getValue());
|
||||
break;
|
||||
case PARAM_LONG_PRESS_TIME:
|
||||
longPressTime = getChannelParameterAsInteger(entry.getValue());
|
||||
break;
|
||||
case PARAM_INVERTED:
|
||||
inverted = getChannelParameterAsBoolean(entry.getValue());
|
||||
break;
|
||||
case PARAM_ON_LEVEL:
|
||||
onLevel = getChannelParameterAsInteger(entry.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getChannelTypeId() {
|
||||
return channelTypeId;
|
||||
}
|
||||
|
||||
public Integer getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public String getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public boolean isDirectionBoth() {
|
||||
return direction != null && DIRECTION_READ_WRITE.equals(direction);
|
||||
}
|
||||
|
||||
public boolean isDirectionReadOnly() {
|
||||
return direction != null && DIRECTION_READ_ONLY.equals(direction);
|
||||
}
|
||||
|
||||
public boolean isDirectionWriteOnly() {
|
||||
return direction != null && DIRECTION_WRITE_ONLY.equals(direction);
|
||||
}
|
||||
|
||||
public String getCommandToReact() {
|
||||
return commandToReact;
|
||||
}
|
||||
|
||||
public Integer getPulseWidth() {
|
||||
return pulseWidth;
|
||||
}
|
||||
|
||||
public Boolean getInverted() {
|
||||
return inverted;
|
||||
}
|
||||
|
||||
public boolean isInverted() {
|
||||
if (inverted != null) {
|
||||
return inverted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Long getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public Integer getLongPressTime() {
|
||||
return longPressTime;
|
||||
}
|
||||
|
||||
public Integer getOnLevel() {
|
||||
return onLevel;
|
||||
}
|
||||
|
||||
private static Boolean getChannelParameterAsBoolean(Object value) throws ConversionException {
|
||||
return convert(value, (v) -> (Boolean) v);
|
||||
}
|
||||
|
||||
private Integer getChannelParameterAsInteger(Object value) throws ConversionException {
|
||||
return convert(value, (v) -> ((BigDecimal) v).intValue());
|
||||
}
|
||||
|
||||
private Long getChannelParameterAsLong(Object value) throws ConversionException {
|
||||
return convert(value, (v) -> ((BigDecimal) v).longValue());
|
||||
}
|
||||
|
||||
private String getChannelParameterAsString(Object value) throws ConversionException {
|
||||
return convert(value, (v) -> (String) v);
|
||||
}
|
||||
|
||||
private static <T> T convert(Object value, Function<Object, T> f) throws ConversionException {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return f.apply(value);
|
||||
} catch (ClassCastException e) {
|
||||
throw new ConversionException(String.format("Failed to convert, reason %s.", e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[ channelTypeId=%s, resourceId=%d, direction=%s, commandToReact=%s, pulseWidth=%d, inverted=%b, serialNumber=%d, longPressTime=%d, onLevel=%d ]",
|
||||
channelTypeId, resourceId, direction, commandToReact, pulseWidth, inverted, serialNumber, longPressTime,
|
||||
onLevel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for {@link IhcBinding} binding.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcConfiguration {
|
||||
public String hostname;
|
||||
public String username;
|
||||
public String password;
|
||||
public int timeout;
|
||||
public boolean loadProjectFile;
|
||||
public boolean createChannelsAutomatically;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + "hostname=" + hostname + ", username=" + username + ", password=******" + ", timeout=" + timeout
|
||||
+ ", loadProjectFile=" + loadProjectFile + ", createChannelsAutomatically="
|
||||
+ createChannelsAutomatically + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
|
||||
/**
|
||||
* IHC / ELKO <-> openHAB data type converter interface.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public interface Converter<R, T> {
|
||||
T convertFromResourceValue(@NonNull R from, @NonNull ConverterAdditionalInfo convertData)
|
||||
throws ConversionException;
|
||||
|
||||
R convertFromOHType(@NonNull T from, @NonNull R value, @NonNull ConverterAdditionalInfo convertData)
|
||||
throws ConversionException;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* Class to hold additional information which is needed for data conversion.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ConverterAdditionalInfo {
|
||||
private List<IhcEnumValue> enumValues;
|
||||
private Boolean inverted;
|
||||
private Map<Command, Object> commandLevels;
|
||||
|
||||
public ConverterAdditionalInfo(List<IhcEnumValue> enumValues, Boolean inverted,
|
||||
Map<Command, Object> commandLevels) {
|
||||
this.enumValues = enumValues;
|
||||
this.inverted = inverted;
|
||||
this.commandLevels = commandLevels;
|
||||
}
|
||||
|
||||
public List<IhcEnumValue> getEnumValues() {
|
||||
return enumValues;
|
||||
}
|
||||
|
||||
public Boolean getInverted() {
|
||||
return inverted;
|
||||
}
|
||||
|
||||
public Map<Command, Object> getCommandLevels() {
|
||||
return commandLevels;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* IHC / ELKO <-> openHAB data type converter factory.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public enum ConverterFactory {
|
||||
INSTANCE;
|
||||
|
||||
private static final String ITEM_TYPE_NUMBER = "Number";
|
||||
private static final String ITEM_TYPE_SWITCH = "Switch";
|
||||
private static final String ITEM_TYPE_CONTACT = "Contact";
|
||||
private static final String ITEM_TYPE_DIMMER = "Dimmer";
|
||||
private static final String ITEM_TYPE_DATETIME = "DateTime";
|
||||
private static final String ITEM_TYPE_STRING = "String";
|
||||
private static final String ITEM_TYPE_ROLLERSHUTTER = "Rollershutter";
|
||||
|
||||
private class Key {
|
||||
Class<? extends WSResourceValue> ihcType;
|
||||
Class<? extends Type> openhabType;
|
||||
|
||||
Key(Class<? extends WSResourceValue> ihcType, Class<? extends Type> openhabType) {
|
||||
this.ihcType = ihcType;
|
||||
this.openhabType = openhabType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ihcType.getClass().hashCode() + openhabType.getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Key)) {
|
||||
return false;
|
||||
}
|
||||
Key key = (Key) o;
|
||||
|
||||
return key.ihcType.equals(ihcType) && key.openhabType.equals(openhabType);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Key, Converter<? extends WSResourceValue, ? extends Type>> converters;
|
||||
|
||||
private ConverterFactory() {
|
||||
converters = new HashMap<>();
|
||||
|
||||
converters.put(new Key(WSDateValue.class, DateTimeType.class), new DateTimeTypeWSDateValueConverter());
|
||||
converters.put(new Key(WSTimeValue.class, DateTimeType.class), new DateTimeTypeWSTimeValueConverter());
|
||||
converters.put(new Key(WSBooleanValue.class, DecimalType.class), new DecimalTypeWSBooleanValueConverter());
|
||||
converters.put(new Key(WSEnumValue.class, DecimalType.class), new DecimalTypeWSEnumValueConverter());
|
||||
converters.put(new Key(WSFloatingPointValue.class, DecimalType.class),
|
||||
new DecimalTypeWSFloatingPointValueConverter());
|
||||
converters.put(new Key(WSIntegerValue.class, DecimalType.class), new DecimalTypeWSIntegerValueConverter());
|
||||
converters.put(new Key(WSTimerValue.class, DecimalType.class), new DecimalTypeWSTimerValueConverter());
|
||||
converters.put(new Key(WSWeekdayValue.class, DecimalType.class), new DecimalTypeWSWeekdayValueConverter());
|
||||
converters.put(new Key(WSBooleanValue.class, OnOffType.class), new OnOffTypeWSBooleanValueConverter());
|
||||
converters.put(new Key(WSIntegerValue.class, OnOffType.class), new OnOffTypeWSIntegerValueConverter());
|
||||
converters.put(new Key(WSBooleanValue.class, OpenClosedType.class),
|
||||
new OpenClosedTypeWSBooleanValueConverter());
|
||||
converters.put(new Key(WSIntegerValue.class, OpenClosedType.class),
|
||||
new OpenClosedTypeWSIntegerValueConverter());
|
||||
converters.put(new Key(WSIntegerValue.class, PercentType.class), new PercentTypeWSIntegerValueConverter());
|
||||
converters.put(new Key(WSEnumValue.class, StringType.class), new StringTypeWSEnumValueConverter());
|
||||
converters.put(new Key(WSBooleanValue.class, UpDownType.class), new UpDownTypeWSBooleanValueConverter());
|
||||
converters.put(new Key(WSIntegerValue.class, UpDownType.class), new UpDownTypeWSIntegerValueConverter());
|
||||
}
|
||||
|
||||
public static ConverterFactory getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Converter<WSResourceValue, Type> getConverter(Class<? extends WSResourceValue> resourceValueType,
|
||||
Class<? extends Type> type) {
|
||||
return (Converter<WSResourceValue, Type>) converters.get(new Key(resourceValueType, type));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Converter<WSResourceValue, Type> getConverter(Class<? extends WSResourceValue> resourceValueType,
|
||||
String itemType) {
|
||||
Class<? extends Type> type = null;
|
||||
switch (itemType) {
|
||||
case ITEM_TYPE_SWITCH:
|
||||
type = OnOffType.class;
|
||||
break;
|
||||
case ITEM_TYPE_ROLLERSHUTTER:
|
||||
case ITEM_TYPE_DIMMER:
|
||||
type = PercentType.class;
|
||||
break;
|
||||
case ITEM_TYPE_CONTACT:
|
||||
type = OpenClosedType.class;
|
||||
break;
|
||||
case ITEM_TYPE_STRING:
|
||||
type = StringType.class;
|
||||
break;
|
||||
case ITEM_TYPE_NUMBER:
|
||||
type = DecimalType.class;
|
||||
break;
|
||||
case ITEM_TYPE_DATETIME:
|
||||
type = DateTimeType.class;
|
||||
break;
|
||||
}
|
||||
return (Converter<WSResourceValue, Type>) converters.get(new Key(resourceValueType, type));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
|
||||
/**
|
||||
* DateTimeType <-> WSDateValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DateTimeTypeWSDateValueConverter implements Converter<WSDateValue, DateTimeType> {
|
||||
|
||||
@Override
|
||||
public DateTimeType convertFromResourceValue(@NonNull WSDateValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
Calendar cal = dateTimeToCalendar(from, null);
|
||||
return new DateTimeType(ZonedDateTime.ofInstant(cal.toInstant(), TimeZone.getDefault().toZoneId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSDateValue convertFromOHType(@NonNull DateTimeType from, @NonNull WSDateValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
Calendar cal = GregorianCalendar.from(from.getZonedDateTime());
|
||||
short year = (short) cal.get(Calendar.YEAR);
|
||||
byte month = (byte) (cal.get(Calendar.MONTH) + 1);
|
||||
byte day = (byte) cal.get(Calendar.DAY_OF_MONTH);
|
||||
return new WSDateValue(value.resourceID, year, month, day);
|
||||
}
|
||||
|
||||
private Calendar dateTimeToCalendar(WSDateValue date, WSTimeValue time) {
|
||||
Calendar cal = new GregorianCalendar(2000, 01, 01);
|
||||
if (date != null) {
|
||||
short year = date.year;
|
||||
short month = date.month;
|
||||
short day = date.day;
|
||||
cal.set(year, month - 1, day, 0, 0, 0);
|
||||
}
|
||||
if (time != null) {
|
||||
int hour = time.hours;
|
||||
int minute = time.minutes;
|
||||
int second = time.seconds;
|
||||
cal.set(2000, 0, 1, hour, minute, second);
|
||||
}
|
||||
return cal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
|
||||
/**
|
||||
* DateTimeType <-> WSTimeValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DateTimeTypeWSTimeValueConverter implements Converter<WSTimeValue, DateTimeType> {
|
||||
|
||||
@Override
|
||||
public DateTimeType convertFromResourceValue(@NonNull WSTimeValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
Calendar cal = dateTimeToCalendar(null, from);
|
||||
return new DateTimeType(ZonedDateTime.ofInstant(cal.toInstant(), TimeZone.getDefault().toZoneId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSTimeValue convertFromOHType(@NonNull DateTimeType from, @NonNull WSTimeValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
Calendar cal = GregorianCalendar.from(from.getZonedDateTime());
|
||||
return new WSTimeValue(value.resourceID, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE),
|
||||
cal.get(Calendar.SECOND));
|
||||
}
|
||||
|
||||
private Calendar dateTimeToCalendar(WSDateValue date, WSTimeValue time) {
|
||||
Calendar cal = new GregorianCalendar(2000, 01, 01);
|
||||
if (date != null) {
|
||||
short year = date.year;
|
||||
short month = date.month;
|
||||
short day = date.day;
|
||||
|
||||
cal.set(year, month - 1, day, 0, 0, 0);
|
||||
}
|
||||
if (time != null) {
|
||||
int hour = time.hours;
|
||||
int minute = time.minutes;
|
||||
int second = time.seconds;
|
||||
cal.set(2000, 0, 1, hour, minute, second);
|
||||
}
|
||||
return cal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* DecimalType <-> WSBooleanValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSBooleanValueConverter implements Converter<WSBooleanValue, DecimalType> {
|
||||
|
||||
@Override
|
||||
public DecimalType convertFromResourceValue(@NonNull WSBooleanValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new DecimalType(from.value ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSBooleanValue convertFromOHType(@NonNull DecimalType from, @NonNull WSBooleanValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSBooleanValue(value.resourceID, from.intValue() > 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* DecimalType <-> WSEnumValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSEnumValueConverter implements Converter<WSEnumValue, DecimalType> {
|
||||
|
||||
@Override
|
||||
public DecimalType convertFromResourceValue(@NonNull WSEnumValue from, @NonNull ConverterAdditionalInfo convertData)
|
||||
throws ConversionException {
|
||||
return new DecimalType(from.enumValueID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSEnumValue convertFromOHType(@NonNull DecimalType from, @NonNull WSEnumValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSEnumValue(value.resourceID, value.definitionTypeID, from.intValue(), value.enumName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* DecimalType <-> WSFloatingPointValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSFloatingPointValueConverter implements Converter<WSFloatingPointValue, DecimalType> {
|
||||
|
||||
@Override
|
||||
public DecimalType convertFromResourceValue(@NonNull WSFloatingPointValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
BigDecimal bd = new BigDecimal(from.value).setScale(2, RoundingMode.HALF_EVEN);
|
||||
return new DecimalType(bd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSFloatingPointValue convertFromOHType(@NonNull DecimalType from, @NonNull WSFloatingPointValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
if (from.doubleValue() >= value.minimumValue && from.doubleValue() <= value.maximumValue) {
|
||||
return new WSFloatingPointValue(value.resourceID, from.doubleValue(), value.minimumValue,
|
||||
value.maximumValue);
|
||||
} else {
|
||||
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
|
||||
+ value.maximumValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* DecimalType <-> WSIntegerValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSIntegerValueConverter implements Converter<WSIntegerValue, DecimalType> {
|
||||
|
||||
@Override
|
||||
public DecimalType convertFromResourceValue(@NonNull WSIntegerValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new DecimalType(from.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSIntegerValue convertFromOHType(@NonNull DecimalType from, @NonNull WSIntegerValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
if (from.intValue() >= value.minimumValue && from.intValue() <= value.maximumValue) {
|
||||
return new WSIntegerValue(value.resourceID, from.intValue(), value.minimumValue, value.maximumValue);
|
||||
} else {
|
||||
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
|
||||
+ value.maximumValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* DecimalType <-> WSTimerValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSTimerValueConverter implements Converter<WSTimerValue, DecimalType> {
|
||||
|
||||
@Override
|
||||
public DecimalType convertFromResourceValue(@NonNull WSTimerValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new DecimalType(from.milliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSTimerValue convertFromOHType(@NonNull DecimalType from, @NonNull WSTimerValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSTimerValue(value.resourceID, from.longValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
||||
/**
|
||||
* DecimalType <-> WSWeekdayValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSWeekdayValueConverter implements Converter<WSWeekdayValue, DecimalType> {
|
||||
|
||||
@Override
|
||||
public DecimalType convertFromResourceValue(@NonNull WSWeekdayValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new DecimalType(from.weekdayNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSWeekdayValue convertFromOHType(@NonNull DecimalType from, @NonNull WSWeekdayValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSWeekdayValue(value.resourceID, from.intValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
||||
/**
|
||||
* OnOffType <-> WSBooleanValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OnOffTypeWSBooleanValueConverter implements Converter<WSBooleanValue, OnOffType> {
|
||||
|
||||
@Override
|
||||
public OnOffType convertFromResourceValue(@NonNull WSBooleanValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return from.value ^ convertData.getInverted() ? OnOffType.ON : OnOffType.OFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSBooleanValue convertFromOHType(@NonNull OnOffType from, @NonNull WSBooleanValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSBooleanValue(value.resourceID, from == OnOffType.ON ^ convertData.getInverted());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* OnOffType <-> WSIntegerValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OnOffTypeWSIntegerValueConverter implements Converter<WSIntegerValue, OnOffType> {
|
||||
|
||||
@Override
|
||||
public OnOffType convertFromResourceValue(@NonNull WSIntegerValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return from.value > 0 ^ convertData.getInverted() ? OnOffType.ON : OnOffType.OFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSIntegerValue convertFromOHType(@NonNull OnOffType from, @NonNull WSIntegerValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
int onLevel = Math.min(value.maximumValue, getCommandLevel(value, convertData, OnOffType.ON));
|
||||
int newVal = from == OnOffType.ON ? onLevel : value.minimumValue;
|
||||
|
||||
if (convertData.getInverted()) {
|
||||
newVal = newVal == value.maximumValue ? value.minimumValue : value.maximumValue;
|
||||
}
|
||||
if (newVal >= value.minimumValue && newVal <= value.maximumValue) {
|
||||
return new WSIntegerValue(value.resourceID, newVal, value.minimumValue, value.maximumValue);
|
||||
} else {
|
||||
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
|
||||
+ value.maximumValue + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private int getCommandLevel(@NonNull WSIntegerValue value, @NonNull ConverterAdditionalInfo convertData,
|
||||
Command command) throws ConversionException {
|
||||
try {
|
||||
if (convertData.getCommandLevels() != null) {
|
||||
return (int) convertData.getCommandLevels().get(command);
|
||||
}
|
||||
return value.maximumValue;
|
||||
} catch (RuntimeException e) {
|
||||
throw new ConversionException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
|
||||
/**
|
||||
* OpenClosedType <-> WSBooleanValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OpenClosedTypeWSBooleanValueConverter implements Converter<WSBooleanValue, OpenClosedType> {
|
||||
|
||||
@Override
|
||||
public OpenClosedType convertFromResourceValue(@NonNull WSBooleanValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return from.value ^ convertData.getInverted() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSBooleanValue convertFromOHType(@NonNull OpenClosedType from, @NonNull WSBooleanValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSBooleanValue(value.resourceID, from == OpenClosedType.OPEN ^ convertData.getInverted());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
|
||||
/**
|
||||
* OpenClosedType <-> WSIntegerValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OpenClosedTypeWSIntegerValueConverter implements Converter<WSIntegerValue, OpenClosedType> {
|
||||
|
||||
@Override
|
||||
public OpenClosedType convertFromResourceValue(@NonNull WSIntegerValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return from.value > 0 ^ convertData.getInverted() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSIntegerValue convertFromOHType(@NonNull OpenClosedType from, @NonNull WSIntegerValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
int newVal = from == OpenClosedType.OPEN ? value.maximumValue : value.minimumValue;
|
||||
|
||||
if (convertData.getInverted()) {
|
||||
newVal = newVal == value.maximumValue ? value.minimumValue : value.maximumValue;
|
||||
}
|
||||
if (newVal >= value.minimumValue && newVal <= value.maximumValue) {
|
||||
return new WSIntegerValue(value.resourceID, newVal, value.minimumValue, value.maximumValue);
|
||||
} else {
|
||||
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
|
||||
+ value.maximumValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
|
||||
/**
|
||||
* PercentType <-> WSIntegerValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class PercentTypeWSIntegerValueConverter implements Converter<WSIntegerValue, PercentType> {
|
||||
|
||||
@Override
|
||||
public PercentType convertFromResourceValue(@NonNull WSIntegerValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new PercentType(from.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSIntegerValue convertFromOHType(@NonNull PercentType from, @NonNull WSIntegerValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
if (from.intValue() >= value.minimumValue && from.intValue() <= value.maximumValue) {
|
||||
return new WSIntegerValue(value.resourceID, from.intValue(), value.minimumValue, value.maximumValue);
|
||||
} else {
|
||||
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
|
||||
+ value.maximumValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
||||
/**
|
||||
* StringType <-> WSEnumValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class StringTypeWSEnumValueConverter implements Converter<WSEnumValue, StringType> {
|
||||
|
||||
@Override
|
||||
public StringType convertFromResourceValue(@NonNull WSEnumValue from, @NonNull ConverterAdditionalInfo convertData)
|
||||
throws ConversionException {
|
||||
return new StringType(from.enumName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSEnumValue convertFromOHType(@NonNull StringType from, @NonNull WSEnumValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
if (convertData.getEnumValues() != null) {
|
||||
for (IhcEnumValue item : convertData.getEnumValues()) {
|
||||
if (item.getName().equals(from.toString())) {
|
||||
return new WSEnumValue(value.resourceID, value.definitionTypeID, item.getId(), item.getName());
|
||||
}
|
||||
}
|
||||
throw new ConversionException("Can't find enum value for string " + value.toString());
|
||||
} else {
|
||||
throw new ConversionException("Enum list is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
|
||||
/**
|
||||
* UpDownType <-> WSBooleanValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class UpDownTypeWSBooleanValueConverter implements Converter<WSBooleanValue, UpDownType> {
|
||||
|
||||
@Override
|
||||
public UpDownType convertFromResourceValue(@NonNull WSBooleanValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return from.value ^ convertData.getInverted() ? UpDownType.UP : UpDownType.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSBooleanValue convertFromOHType(@NonNull UpDownType from, @NonNull WSBooleanValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return new WSBooleanValue(value.resourceID, from == UpDownType.UP ^ convertData.getInverted());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
|
||||
/**
|
||||
* UpDownType <-> WSIntegerValue converter.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class UpDownTypeWSIntegerValueConverter implements Converter<WSIntegerValue, UpDownType> {
|
||||
|
||||
@Override
|
||||
public UpDownType convertFromResourceValue(@NonNull WSIntegerValue from,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
return from.value > 0 ^ convertData.getInverted() ? UpDownType.UP : UpDownType.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WSIntegerValue convertFromOHType(@NonNull UpDownType from, @NonNull WSIntegerValue value,
|
||||
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
|
||||
int newVal = from == UpDownType.UP ? value.maximumValue : value.minimumValue;
|
||||
|
||||
if (convertData.getInverted()) {
|
||||
newVal = newVal == value.maximumValue ? value.minimumValue : value.maximumValue;
|
||||
}
|
||||
if (newVal >= value.minimumValue && newVal <= value.maximumValue) {
|
||||
return new WSIntegerValue(value.resourceID, newVal, value.minimumValue, value.maximumValue);
|
||||
} else {
|
||||
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
|
||||
+ value.maximumValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,979 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.handler;
|
||||
|
||||
import static org.openhab.binding.ihc.internal.IhcBindingConstants.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ButtonPressDurationDetector;
|
||||
import org.openhab.binding.ihc.internal.ChannelUtils;
|
||||
import org.openhab.binding.ihc.internal.EnumDictionary;
|
||||
import org.openhab.binding.ihc.internal.SignalLevelConverter;
|
||||
import org.openhab.binding.ihc.internal.config.ChannelParams;
|
||||
import org.openhab.binding.ihc.internal.config.IhcConfiguration;
|
||||
import org.openhab.binding.ihc.internal.converters.Converter;
|
||||
import org.openhab.binding.ihc.internal.converters.ConverterAdditionalInfo;
|
||||
import org.openhab.binding.ihc.internal.converters.ConverterFactory;
|
||||
import org.openhab.binding.ihc.internal.ws.IhcClient;
|
||||
import org.openhab.binding.ihc.internal.ws.IhcClient.ConnectionState;
|
||||
import org.openhab.binding.ihc.internal.ws.IhcEventListener;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSTimeManagerSettings;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.projectfile.ProjectFileUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
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.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.Type;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* The {@link IhcHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcHandler extends BaseThingHandler implements IhcEventListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(IhcHandler.class);
|
||||
|
||||
/** Maximum pulse width in milliseconds. */
|
||||
private static final int MAX_PULSE_WIDTH_IN_MS = 4000;
|
||||
|
||||
/** Maximum long press time in milliseconds. */
|
||||
private static final int MAX_LONG_PRESS_IN_MS = 5000;
|
||||
|
||||
/** Name of the local IHC / ELKO project file */
|
||||
private static final String LOCAL_IHC_PROJECT_FILE_NAME_TEMPLATE = "ihc-project-file-%s.xml";
|
||||
|
||||
/** Holds runtime notification reorder timeout in milliseconds */
|
||||
private static final int NOTIFICATIONS_REORDER_WAIT_TIME = 1000;
|
||||
|
||||
/** IHC / ELKO LS Controller client */
|
||||
private IhcClient ihc;
|
||||
|
||||
/**
|
||||
* Reminder to slow down resource value notification ordering from
|
||||
* controller.
|
||||
*/
|
||||
private ScheduledFuture<?> notificationsRequestReminder;
|
||||
|
||||
/** Holds local IHC / ELKO project file */
|
||||
private Document projectFile;
|
||||
|
||||
/**
|
||||
* Store current state of the controller, use to recognize when controller
|
||||
* state is changed
|
||||
*/
|
||||
private String controllerState = "";
|
||||
|
||||
private IhcConfiguration conf;
|
||||
private final Set<Integer> linkedResourceIds = Collections.synchronizedSet(new HashSet<>());
|
||||
private Map<Integer, LocalDateTime> lastUpdate = new HashMap<>();
|
||||
private EnumDictionary enumDictionary;
|
||||
|
||||
private boolean connecting = false;
|
||||
private boolean reconnectRequest = false;
|
||||
private boolean valueNotificationRequest = false;
|
||||
|
||||
private ScheduledFuture<?> controlJob;
|
||||
private ScheduledFuture<?> pollingJobRf;
|
||||
|
||||
private Map<String, ScheduledFuture<?>> longPressFutures = new HashMap<>();
|
||||
|
||||
public IhcHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
protected boolean isValueNotificationRequestActivated() {
|
||||
synchronized (this) {
|
||||
return valueNotificationRequest;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setValueNotificationRequest(boolean valueNotificationRequest) {
|
||||
synchronized (this) {
|
||||
this.valueNotificationRequest = valueNotificationRequest;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isReconnectRequestActivated() {
|
||||
synchronized (this) {
|
||||
return reconnectRequest;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setReconnectRequest(boolean reconnect) {
|
||||
synchronized (this) {
|
||||
this.reconnectRequest = reconnect;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isConnecting() {
|
||||
synchronized (this) {
|
||||
return connecting;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setConnectingState(boolean value) {
|
||||
synchronized (this) {
|
||||
this.connecting = value;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFilePathInUserDataFolder(String fileName) {
|
||||
String progArg = System.getProperty("smarthome.userdata");
|
||||
if (progArg != null) {
|
||||
return progArg + File.separator + fileName;
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
conf = getConfigAs(IhcConfiguration.class);
|
||||
logger.debug("Using configuration: {}", conf);
|
||||
|
||||
linkedResourceIds.clear();
|
||||
linkedResourceIds.addAll(getAllLinkedChannelsResourceIds());
|
||||
logger.debug("Linked resources {}: {}", linkedResourceIds.size(), linkedResourceIds);
|
||||
|
||||
if (controlJob == null || controlJob.isCancelled()) {
|
||||
logger.debug("Start control task, interval={}sec", 1);
|
||||
controlJob = scheduler.scheduleWithFixedDelay(this::reconnectCheck, 0, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Stopping thing");
|
||||
if (controlJob != null && !controlJob.isCancelled()) {
|
||||
controlJob.cancel(true);
|
||||
controlJob = null;
|
||||
}
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("Received channel: {}, command: {}", channelUID, command);
|
||||
|
||||
if (ihc == null) {
|
||||
logger.warn("Connection is not initialized, abort resource value update for channel '{}'!", channelUID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ihc.getConnectionState() != ConnectionState.CONNECTED) {
|
||||
logger.warn("Connection to controller is not open, abort resource value update for channel '{}'!",
|
||||
channelUID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_CONTROLLER_STATE:
|
||||
if (command.equals(RefreshType.REFRESH)) {
|
||||
updateControllerStateChannel();
|
||||
}
|
||||
break;
|
||||
|
||||
case CHANNEL_CONTROLLER_UPTIME:
|
||||
if (command.equals(RefreshType.REFRESH)) {
|
||||
updateControllerInformationChannels();
|
||||
}
|
||||
break;
|
||||
|
||||
case CHANNEL_CONTROLLER_TIME:
|
||||
if (command.equals(RefreshType.REFRESH)) {
|
||||
updateControllerTimeChannels();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (command.equals(RefreshType.REFRESH)) {
|
||||
refreshChannel(channelUID);
|
||||
} else {
|
||||
updateResourceChannel(channelUID, command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshChannel(ChannelUID channelUID) {
|
||||
logger.debug("REFRESH channel {}", channelUID);
|
||||
Channel channel = thing.getChannel(channelUID.getId());
|
||||
if (channel != null) {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
logger.debug("Channel params: {}", params);
|
||||
if (params.isDirectionWriteOnly()) {
|
||||
logger.warn("Write only channel, skip refresh command to {}", channelUID);
|
||||
return;
|
||||
}
|
||||
WSResourceValue value = ihc.resourceQuery(params.getResourceId());
|
||||
resourceValueUpdateReceived(value);
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Can't update channel '{}' value, reason: {}", channelUID, e.getMessage(), e);
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateControllerStateChannel() {
|
||||
try {
|
||||
String state = ihc.getControllerState().getState();
|
||||
String value;
|
||||
|
||||
switch (state) {
|
||||
case IhcClient.CONTROLLER_STATE_INITIALIZE:
|
||||
value = "Initialize";
|
||||
break;
|
||||
case IhcClient.CONTROLLER_STATE_READY:
|
||||
value = "Ready";
|
||||
break;
|
||||
default:
|
||||
value = "Unknown state: " + state;
|
||||
}
|
||||
|
||||
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_STATE), new StringType(value));
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Controller state information fetch failed, reason: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateControllerProperties() {
|
||||
try {
|
||||
WSSystemInfo systemInfo = ihc.getSystemInfo();
|
||||
logger.debug("Controller information: {}", systemInfo);
|
||||
WSProjectInfo projectInfo = ihc.getProjectInfo();
|
||||
logger.debug("Project information: {}", projectInfo);
|
||||
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(PROPERTY_MANUFACTURER, systemInfo.getBrand());
|
||||
properties.put(PROPERTY_SERIALNUMBER, systemInfo.getSerialNumber());
|
||||
properties.put(PROPERTY_SW_VERSION, systemInfo.getVersion());
|
||||
properties.put(PROPERTY_FW_VERSION, systemInfo.getHwRevision());
|
||||
properties.put(PROPERTY_APP_WITHOUT_VIEWER, Boolean.toString(systemInfo.getApplicationIsWithoutViewer()));
|
||||
properties.put(PROPERTY_SW_DATE,
|
||||
systemInfo.getSwDate().withZoneSameInstant(ZoneId.systemDefault()).toString());
|
||||
properties.put(PROPERTY_PRODUCTION_DATE, systemInfo.getProductionDate());
|
||||
if (!systemInfo.getDatalineVersion().isEmpty()) {
|
||||
properties.put(PROPERTY_DATALINE_VERSION, systemInfo.getDatalineVersion());
|
||||
}
|
||||
if (!systemInfo.getRfModuleSerialNumber().isEmpty()) {
|
||||
properties.put(PROPERTY_RF_MODULE_SERIALNUMBER, systemInfo.getRfModuleSerialNumber());
|
||||
}
|
||||
if (!systemInfo.getRfModuleSoftwareVersion().isEmpty()) {
|
||||
properties.put(PROPERTY_RF_MODULE_VERSION, systemInfo.getRfModuleSoftwareVersion());
|
||||
}
|
||||
properties.put(PROPERTY_PROJECT_DATE,
|
||||
projectInfo.getLastmodified().getAsLocalDateTime().atZone(ZoneId.systemDefault()).toString());
|
||||
properties.put(PROPERTY_PROJECT_NUMBER, projectInfo.getProjectNumber());
|
||||
updateProperties(properties);
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Controller information fetch failed, reason: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateControllerInformationChannels() {
|
||||
try {
|
||||
WSSystemInfo systemInfo = ihc.getSystemInfo();
|
||||
logger.debug("Controller information: {}", systemInfo);
|
||||
|
||||
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_UPTIME),
|
||||
new DecimalType((double) systemInfo.getUptime() / 1000));
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Controller uptime information fetch failed, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateControllerTimeChannels() {
|
||||
try {
|
||||
WSTimeManagerSettings timeSettings = ihc.getTimeSettings();
|
||||
logger.debug("Controller time settings: {}", timeSettings);
|
||||
|
||||
ZonedDateTime time = timeSettings.getTimeAndDateInUTC().getAsZonedDateTime(ZoneId.of("Z"))
|
||||
.withZoneSameInstant(ZoneId.systemDefault());
|
||||
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_TIME), new DateTimeType(time));
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Controller uptime information fetch failed, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateResourceChannel(ChannelUID channelUID, Command command) {
|
||||
Channel channel = thing.getChannel(channelUID.getId());
|
||||
if (channel != null) {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
logger.debug("Channel params: {}", params);
|
||||
if (params.isDirectionReadOnly()) {
|
||||
logger.debug("Read only channel, skip the update to {}", channelUID);
|
||||
return;
|
||||
}
|
||||
updateChannel(channelUID, params, command);
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Can't update channel '{}' value, cause {}", channelUID, e.getMessage());
|
||||
} catch (ConversionException e) {
|
||||
logger.debug("Conversion error for channel {}, reason: {}", channelUID, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChannel(ChannelUID channelUID, ChannelParams params, Command command)
|
||||
throws IhcExecption, ConversionException {
|
||||
if (params.getCommandToReact() != null) {
|
||||
if (command.toString().equals(params.getCommandToReact())) {
|
||||
logger.debug("Command '{}' equal to channel reaction parameter '{}', execute it", command,
|
||||
params.getCommandToReact());
|
||||
} else {
|
||||
logger.debug("Command '{}' doesn't equal to reaction trigger parameter '{}', skip it", command,
|
||||
params.getCommandToReact());
|
||||
return;
|
||||
}
|
||||
}
|
||||
WSResourceValue value = ihc.getResourceValueInformation(params.getResourceId());
|
||||
if (value != null) {
|
||||
if (params.getPulseWidth() != null) {
|
||||
sendPulseCommand(channelUID, params, value, Math.min(params.getPulseWidth(), MAX_PULSE_WIDTH_IN_MS));
|
||||
} else {
|
||||
sendNormalCommand(channelUID, params, command, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendNormalCommand(ChannelUID channelUID, ChannelParams params, Command command, WSResourceValue value)
|
||||
throws IhcExecption, ConversionException {
|
||||
logger.debug("Send command '{}' to resource '{}'", command, value.resourceID);
|
||||
ConverterAdditionalInfo converterAdditionalInfo = new ConverterAdditionalInfo(getEnumValues(value),
|
||||
params.isInverted(), getCommandLevels(params));
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(value.getClass(),
|
||||
command.getClass());
|
||||
if (converter != null) {
|
||||
WSResourceValue val = converter.convertFromOHType(command, value, converterAdditionalInfo);
|
||||
logger.debug("Update resource value (inverted output={}): {}", params.isInverted(), val);
|
||||
if (!updateResource(val)) {
|
||||
logger.warn("Channel {} update to resource '{}' failed.", channelUID, val);
|
||||
}
|
||||
} else {
|
||||
logger.debug("No converter implemented for {} <-> {}", value.getClass(), command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private List<IhcEnumValue> getEnumValues(WSResourceValue value) {
|
||||
if (value instanceof WSEnumValue) {
|
||||
return enumDictionary.getEnumValues(((WSEnumValue) value).definitionTypeID);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendPulseCommand(ChannelUID channelUID, ChannelParams params, WSResourceValue value,
|
||||
Integer pulseWidth) throws IhcExecption, ConversionException {
|
||||
logger.debug("Send {}ms pulse to resource: {}", pulseWidth, value.resourceID);
|
||||
logger.debug("Channel params: {}", params);
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(value.getClass(),
|
||||
OnOffType.class);
|
||||
|
||||
if (converter != null) {
|
||||
ConverterAdditionalInfo converterAdditionalInfo = new ConverterAdditionalInfo(null, params.isInverted(),
|
||||
getCommandLevels(params));
|
||||
|
||||
WSResourceValue valOn = converter.convertFromOHType(OnOffType.ON, value, converterAdditionalInfo);
|
||||
WSResourceValue valOff = converter.convertFromOHType(OnOffType.OFF, value, converterAdditionalInfo);
|
||||
|
||||
// set resource to ON
|
||||
logger.debug("Update resource value (inverted output={}): {}", params.isInverted(), valOn);
|
||||
if (updateResource(valOn)) {
|
||||
logger.debug("Sleeping: {}ms", pulseWidth);
|
||||
scheduler.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// set resource back to OFF
|
||||
logger.debug("Update resource value (inverted output={}): {}", params.isInverted(), valOff);
|
||||
try {
|
||||
if (!updateResource(valOff)) {
|
||||
logger.warn("Channel {} update to resource '{}' failed.", channelUID, valOff);
|
||||
}
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Can't update channel '{}' value, cause {}", channelUID, e.getMessage());
|
||||
}
|
||||
}
|
||||
}, pulseWidth, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
logger.warn("Channel {} update failed.", channelUID);
|
||||
}
|
||||
} else {
|
||||
logger.debug("No converter implemented for {} <-> {}", value.getClass(), OnOffType.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update resource value to IHC controller.
|
||||
*/
|
||||
private boolean updateResource(WSResourceValue value) throws IhcExecption {
|
||||
boolean result = false;
|
||||
try {
|
||||
result = ihc.resourceUpdate(value);
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Value could not be updated - retrying one time: {}.", e.getMessage(), e);
|
||||
result = ihc.resourceUpdate(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
logger.debug("channelLinked: {}", channelUID);
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_CONTROLLER_STATE:
|
||||
updateControllerStateChannel();
|
||||
break;
|
||||
|
||||
case CHANNEL_CONTROLLER_UPTIME:
|
||||
updateControllerInformationChannels();
|
||||
break;
|
||||
|
||||
case CHANNEL_CONTROLLER_TIME:
|
||||
updateControllerTimeChannels();
|
||||
break;
|
||||
|
||||
default:
|
||||
Channel channel = thing.getChannel(channelUID.getId());
|
||||
if (channel != null) {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
if (params.getResourceId() != null) {
|
||||
if (!linkedResourceIds.contains(params.getResourceId())) {
|
||||
logger.debug("New channel '{}' found, resource id '{}'", channelUID.getAsString(),
|
||||
params.getResourceId());
|
||||
linkedResourceIds.add(params.getResourceId());
|
||||
updateNotificationsRequestReminder();
|
||||
}
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelUnlinked(ChannelUID channelUID) {
|
||||
logger.debug("channelUnlinked: {}", channelUID);
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_CONTROLLER_STATE:
|
||||
case CHANNEL_CONTROLLER_UPTIME:
|
||||
case CHANNEL_CONTROLLER_TIME:
|
||||
break;
|
||||
|
||||
default:
|
||||
Channel channel = thing.getChannel(channelUID.getId());
|
||||
if (channel != null) {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
if (params.getResourceId() != null) {
|
||||
linkedResourceIds.removeIf(c -> c.equals(params.getResourceId()));
|
||||
updateNotificationsRequestReminder();
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize IHC client and open connection to IHC / ELKO LS controller.
|
||||
*
|
||||
*/
|
||||
private void connect() throws IhcExecption {
|
||||
try {
|
||||
setConnectingState(true);
|
||||
logger.debug("Connecting to IHC / ELKO LS controller [hostname='{}', username='{}'].", conf.hostname,
|
||||
conf.username);
|
||||
ihc = new IhcClient(conf.hostname, conf.username, conf.password, conf.timeout);
|
||||
ihc.openConnection();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"Initializing communication to the IHC / ELKO controller");
|
||||
loadProject();
|
||||
createChannels();
|
||||
updateControllerProperties();
|
||||
updateControllerStateChannel();
|
||||
updateControllerInformationChannels();
|
||||
updateControllerTimeChannels();
|
||||
ihc.addEventListener(this);
|
||||
ihc.startControllerEventListeners();
|
||||
updateNotificationsRequestReminder();
|
||||
startRFPolling();
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} finally {
|
||||
setConnectingState(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadProject() throws IhcExecption {
|
||||
if (conf.loadProjectFile) {
|
||||
String fileName = String.format(LOCAL_IHC_PROJECT_FILE_NAME_TEMPLATE, thing.getUID().getId());
|
||||
String filePath = getFilePathInUserDataFolder(fileName);
|
||||
boolean loadProject = false;
|
||||
|
||||
if (projectFile == null) {
|
||||
// try first load project file from local cache file.
|
||||
try {
|
||||
projectFile = ProjectFileUtils.readFromFile(filePath);
|
||||
} catch (IhcExecption e) {
|
||||
logger.debug("Error occured when read project file from file '{}', reason {}", filePath,
|
||||
e.getMessage(), e);
|
||||
loadProject = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ProjectFileUtils.projectEqualsToControllerProject(projectFile, ihc.getProjectInfo())) {
|
||||
logger.debug(
|
||||
"Local project file is not same as in the controller, reload project file from controller!");
|
||||
loadProject = true;
|
||||
}
|
||||
|
||||
if (loadProject) {
|
||||
logger.debug("Loading IHC /ELKO LS project file from controller...");
|
||||
byte[] data = ihc.getProjectFileFromController();
|
||||
logger.debug("Saving project file to local file '{}'", filePath);
|
||||
try {
|
||||
ProjectFileUtils.saveToFile(filePath, data);
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Error occured when trying to write data to file '{}', reason {}", filePath,
|
||||
e.getMessage(), e);
|
||||
}
|
||||
projectFile = ProjectFileUtils.converteBytesToDocument(data);
|
||||
}
|
||||
}
|
||||
|
||||
enumDictionary = new EnumDictionary(ProjectFileUtils.parseEnums(projectFile));
|
||||
}
|
||||
|
||||
private void createChannels() {
|
||||
if (conf.loadProjectFile && conf.createChannelsAutomatically) {
|
||||
logger.debug("Creating channels");
|
||||
List<Channel> thingChannels = new ArrayList<>();
|
||||
thingChannels.addAll(getThing().getChannels());
|
||||
ChannelUtils.addControllerChannels(getThing(), thingChannels);
|
||||
ChannelUtils.addChannelsFromProjectFile(getThing(), projectFile, thingChannels);
|
||||
printChannels(thingChannels);
|
||||
updateThing(editThing().withChannels(thingChannels).build());
|
||||
} else {
|
||||
logger.debug("Automatic channel creation disabled");
|
||||
}
|
||||
}
|
||||
|
||||
private void printChannels(List<Channel> thingChannels) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
thingChannels.forEach(channel -> {
|
||||
if (channel != null) {
|
||||
String resourceId;
|
||||
try {
|
||||
Object id = channel.getConfiguration().get(PARAM_RESOURCE_ID);
|
||||
resourceId = id != null ? "0x" + Integer.toHexString(((BigDecimal) id).intValue()) : "";
|
||||
} catch (IllegalArgumentException e) {
|
||||
resourceId = "";
|
||||
}
|
||||
|
||||
String channelType = channel.getAcceptedItemType() != null ? channel.getAcceptedItemType() : "";
|
||||
String channelLabel = channel.getLabel() != null ? channel.getLabel() : "";
|
||||
|
||||
logger.debug("Channel: {}", String.format("%-55s | %-10s | %-10s | %s", channel.getUID(),
|
||||
resourceId, channelType, channelLabel));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void startRFPolling() {
|
||||
if (pollingJobRf == null || pollingJobRf.isCancelled()) {
|
||||
logger.debug("Start RF device refresh task, interval={}sec", 60);
|
||||
pollingJobRf = scheduler.scheduleWithFixedDelay(this::updateRfDeviceStates, 10, 60, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect connection to IHC / ELKO LS controller.
|
||||
*
|
||||
*/
|
||||
private void disconnect() {
|
||||
cancelAllLongPressTasks();
|
||||
if (pollingJobRf != null && !pollingJobRf.isCancelled()) {
|
||||
pollingJobRf.cancel(true);
|
||||
pollingJobRf = null;
|
||||
}
|
||||
if (ihc != null) {
|
||||
try {
|
||||
ihc.removeEventListener(this);
|
||||
ihc.closeConnection();
|
||||
ihc = null;
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Couldn't close connection to IHC controller", e);
|
||||
}
|
||||
}
|
||||
clearLastUpdateTimeCache();
|
||||
}
|
||||
|
||||
private void clearLastUpdateTimeCache() {
|
||||
lastUpdate.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorOccured(IhcExecption e) {
|
||||
logger.warn("Error occurred on communication to IHC controller: {}", e.getMessage(), e);
|
||||
logger.debug("Reconnection request");
|
||||
setReconnectRequest(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void statusUpdateReceived(WSControllerState newState) {
|
||||
logger.debug("Controller state: {}", newState.getState());
|
||||
|
||||
if (!controllerState.equals(newState.getState())) {
|
||||
logger.debug("Controller state change detected ({} -> {})", controllerState, newState.getState());
|
||||
|
||||
switch (newState.getState()) {
|
||||
case IhcClient.CONTROLLER_STATE_INITIALIZE:
|
||||
logger.info("Controller state changed to initializing state, waiting for ready state");
|
||||
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_STATE),
|
||||
new StringType("initialize"));
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
|
||||
"Controller is in initializing state");
|
||||
break;
|
||||
case IhcClient.CONTROLLER_STATE_READY:
|
||||
logger.info("Controller state changed to ready state");
|
||||
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_STATE), new StringType("ready"));
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if (controllerState.equals(IhcClient.CONTROLLER_STATE_INITIALIZE)
|
||||
&& newState.getState().equals(IhcClient.CONTROLLER_STATE_READY)) {
|
||||
logger.debug("Reconnection request");
|
||||
projectFile = null;
|
||||
setReconnectRequest(true);
|
||||
}
|
||||
}
|
||||
|
||||
controllerState = newState.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceValueUpdateReceived(WSResourceValue value) {
|
||||
logger.debug("resourceValueUpdateReceived: {}", value);
|
||||
|
||||
thing.getChannels().forEach(channel -> {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
if (params.getResourceId() != null && params.getResourceId().intValue() == value.resourceID) {
|
||||
updateChannelState(channel, params, value);
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
} catch (RuntimeException e) {
|
||||
logger.warn("Unknown error occured, reason: {}.", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
checkPotentialButtonPresses(value);
|
||||
}
|
||||
|
||||
private void updateChannelState(Channel channel, ChannelParams params, WSResourceValue value) {
|
||||
if (params.isDirectionWriteOnly()) {
|
||||
logger.debug("Write only channel, skip update to {}", channel.getUID());
|
||||
} else {
|
||||
if (params.getChannelTypeId() != null) {
|
||||
switch (params.getChannelTypeId()) {
|
||||
case CHANNEL_TYPE_PUSH_BUTTON_TRIGGER:
|
||||
break;
|
||||
|
||||
default:
|
||||
try {
|
||||
logger.debug("Update channel '{}' state, channel params: {}", channel.getUID(), params);
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance()
|
||||
.getConverter(value.getClass(), channel.getAcceptedItemType());
|
||||
if (converter != null) {
|
||||
State state = (State) converter.convertFromResourceValue(value,
|
||||
new ConverterAdditionalInfo(null, params.isInverted(),
|
||||
getCommandLevels(params)));
|
||||
updateState(channel.getUID(), state);
|
||||
} else {
|
||||
logger.debug("No converter implemented for {} <-> {}", value.getClass(),
|
||||
channel.getAcceptedItemType());
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
logger.debug("Can't convert resource value '{}' to item type {}, reason: {}.", value,
|
||||
channel.getAcceptedItemType(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPotentialButtonPresses(WSResourceValue value) {
|
||||
if (value instanceof WSBooleanValue) {
|
||||
if (((WSBooleanValue) value).value) {
|
||||
// potential button press
|
||||
lastUpdate.put(value.resourceID, LocalDateTime.now());
|
||||
updateTriggers(value.resourceID, Duration.ZERO);
|
||||
} else {
|
||||
// potential button release
|
||||
LocalDateTime lastUpdateTime = lastUpdate.get(value.resourceID);
|
||||
if (lastUpdateTime != null) {
|
||||
Duration duration = Duration.between(lastUpdateTime, LocalDateTime.now());
|
||||
logger.debug("Time between uddates: {}", duration);
|
||||
updateTriggers(value.resourceID, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTriggers(int resourceId, Duration duration) {
|
||||
thing.getChannels().forEach(channel -> {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
if (params.getResourceId() != null && params.getResourceId().intValue() == resourceId) {
|
||||
if (params.getChannelTypeId() != null) {
|
||||
switch (params.getChannelTypeId()) {
|
||||
case CHANNEL_TYPE_PUSH_BUTTON_TRIGGER:
|
||||
logger.debug("Update trigger channel '{}', channel params: {}",
|
||||
channel.getUID().getId(), params);
|
||||
if (duration.toMillis() == 0) {
|
||||
triggerChannel(channel.getUID().getId(), EVENT_PRESSED);
|
||||
createLongPressTask(channel.getUID().getId(), params.getLongPressTime());
|
||||
} else {
|
||||
cancelLongPressTask(channel.getUID().getId());
|
||||
triggerChannel(channel.getUID().getId(), EVENT_RELEASED);
|
||||
triggerChannel(channel.getUID().getId(), String.valueOf(duration.toMillis()));
|
||||
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration,
|
||||
params.getLongPressTime(), MAX_LONG_PRESS_IN_MS);
|
||||
logger.debug("resourceId={}, ButtonPressDurationDetector={}", resourceId, button);
|
||||
if (button.isShortPress()) {
|
||||
triggerChannel(channel.getUID().getId(), EVENT_SHORT_PRESS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createLongPressTask(String channelId, long longPressTimeInMs) {
|
||||
if (longPressFutures.containsKey(channelId)) {
|
||||
cancelLongPressTask(channelId);
|
||||
}
|
||||
logger.debug("Create long press task for channel '{}'", channelId);
|
||||
longPressFutures.put(channelId, scheduler.schedule(() -> triggerChannel(channelId, EVENT_LONG_PRESS),
|
||||
longPressTimeInMs, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
private void cancelLongPressTask(String channelId) {
|
||||
if (longPressFutures.containsKey(channelId)) {
|
||||
logger.debug("Cancel long press task for channel '{}'", channelId);
|
||||
longPressFutures.get(channelId).cancel(false);
|
||||
longPressFutures.remove(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelAllLongPressTasks() {
|
||||
longPressFutures.entrySet().parallelStream().forEach(e -> e.getValue().cancel(true));
|
||||
longPressFutures.clear();
|
||||
}
|
||||
|
||||
private void updateRfDeviceStates() {
|
||||
if (ihc != null) {
|
||||
if (ihc.getConnectionState() != ConnectionState.CONNECTED) {
|
||||
logger.debug("Controller is connecting, abort subscribe");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Update RF device data");
|
||||
try {
|
||||
List<WSRFDevice> devs = ihc.getDetectedRFDevices();
|
||||
logger.debug("RF data: {}", devs);
|
||||
|
||||
devs.forEach(dev -> {
|
||||
thing.getChannels().forEach(channel -> {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(channel);
|
||||
if (params.getSerialNumber() != null
|
||||
&& params.getSerialNumber().longValue() == dev.getSerialNumber()) {
|
||||
String channelId = channel.getUID().getId();
|
||||
if (params.getChannelTypeId() != null) {
|
||||
switch (params.getChannelTypeId()) {
|
||||
case CHANNEL_TYPE_RF_LOW_BATTERY:
|
||||
updateState(channelId,
|
||||
dev.getBatteryLevel() == 1 ? OnOffType.OFF : OnOffType.ON);
|
||||
break;
|
||||
case CHANNEL_TYPE_RF_SIGNAL_STRENGTH:
|
||||
int signalLevel = new SignalLevelConverter(dev.getSignalStrength())
|
||||
.getSystemWideSignalLevel();
|
||||
updateState(channelId, new StringType(String.valueOf(signalLevel)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (IhcExecption e) {
|
||||
logger.debug("Error occured when fetching RF device information, reason: : {} ", e.getMessage(), e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reconnectCheck() {
|
||||
if (ihc == null || isReconnectRequestActivated()) {
|
||||
try {
|
||||
if (ihc != null) {
|
||||
disconnect();
|
||||
}
|
||||
connect();
|
||||
setReconnectRequest(false);
|
||||
} catch (IhcExecption e) {
|
||||
logger.debug("Can't open connection to controller {}", e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
setReconnectRequest(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isValueNotificationRequestActivated() && !isConnecting()) {
|
||||
try {
|
||||
enableResourceValueNotifications();
|
||||
} catch (IhcExecption e) {
|
||||
logger.warn("Can't enable resource value notifications from controller. ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Integer> getAllLinkedChannelsResourceIds() {
|
||||
Set<Integer> resourceIds = Collections.synchronizedSet(new HashSet<>());
|
||||
resourceIds.addAll(this.getThing().getChannels().stream().filter(c -> isLinked(c.getUID())).map(c -> {
|
||||
try {
|
||||
ChannelParams params = new ChannelParams(c);
|
||||
logger.debug("Linked channel '{}' found, resource id '{}'", c.getUID().getAsString(),
|
||||
params.getResourceId());
|
||||
return params.getResourceId();
|
||||
} catch (ConversionException e) {
|
||||
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}).filter(c -> c != null && c != 0).collect(Collectors.toSet()));
|
||||
return resourceIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order resource value notifications from IHC controller.
|
||||
*/
|
||||
private void enableResourceValueNotifications() throws IhcExecption {
|
||||
logger.debug("Subscribe resource runtime value notifications");
|
||||
|
||||
if (ihc != null) {
|
||||
if (ihc.getConnectionState() != ConnectionState.CONNECTED) {
|
||||
logger.debug("Controller is connecting, abort subscribe");
|
||||
return;
|
||||
}
|
||||
setValueNotificationRequest(false);
|
||||
Set<Integer> resourceIds = ChannelUtils.getAllTriggerChannelsResourceIds(getThing());
|
||||
logger.debug("Enable runtime notfications for {} trigger(s)", resourceIds.size());
|
||||
logger.debug("Enable runtime notfications for {} channel(s)", linkedResourceIds.size());
|
||||
resourceIds.addAll(linkedResourceIds);
|
||||
resourceIds.addAll(getAllLinkedChannelsResourceIds());
|
||||
logger.debug("Enable runtime notfications for {} resources: {}", resourceIds.size(), resourceIds);
|
||||
if (!resourceIds.isEmpty()) {
|
||||
try {
|
||||
ihc.enableRuntimeValueNotifications(resourceIds);
|
||||
} catch (IhcExecption e) {
|
||||
logger.debug("Reconnection request");
|
||||
setReconnectRequest(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn("Controller is not initialized!");
|
||||
logger.debug("Reconnection request");
|
||||
setReconnectRequest(true);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void updateNotificationsRequestReminder() {
|
||||
if (notificationsRequestReminder != null) {
|
||||
notificationsRequestReminder.cancel(false);
|
||||
}
|
||||
|
||||
logger.debug("Rechedule resource runtime value notifications order by {}ms", NOTIFICATIONS_REORDER_WAIT_TIME);
|
||||
notificationsRequestReminder = scheduler.schedule(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.debug("Delayed resource value notifications request is now enabled");
|
||||
setValueNotificationRequest(true);
|
||||
}
|
||||
}, NOTIFICATIONS_REORDER_WAIT_TIME, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private Map<Command, Object> getCommandLevels(ChannelParams params) {
|
||||
if (params.getOnLevel() != null) {
|
||||
Map<Command, Object> commandLevels = new HashMap<>();
|
||||
commandLevels.put(OnOffType.ON, params.getOnLevel());
|
||||
return Collections.unmodifiableMap(commandLevels);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.profiles;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.thing.profiles.Profile;
|
||||
import org.openhab.core.thing.profiles.ProfileCallback;
|
||||
import org.openhab.core.thing.profiles.ProfileContext;
|
||||
import org.openhab.core.thing.profiles.ProfileFactory;
|
||||
import org.openhab.core.thing.profiles.ProfileType;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeProvider;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* A factory for IHC / ELKO profiles.
|
||||
*
|
||||
* @author Pauli Anttila - initial contribution.
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = { ProfileFactory.class, ProfileTypeProvider.class })
|
||||
public class IhcProfileFactory implements ProfileFactory, ProfileTypeProvider {
|
||||
|
||||
private static final Set<ProfileType> SUPPORTED_PROFILE_TYPES = Stream.of(IhcProfiles.PUSHBUTTON_COMMAND_TYPE)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
private static final Set<ProfileTypeUID> SUPPORTED_PROFILE_TYPE_UIDS = Stream.of(IhcProfiles.PUSHBUTTON_COMMAND)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback, ProfileContext context) {
|
||||
if (IhcProfiles.PUSHBUTTON_COMMAND.equals(profileTypeUID)) {
|
||||
return new PushButtonToCommandProfile(callback, context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ProfileType> getProfileTypes(@Nullable Locale locale) {
|
||||
return SUPPORTED_PROFILE_TYPES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ProfileTypeUID> getSupportedProfileTypeUIDs() {
|
||||
return SUPPORTED_PROFILE_TYPE_UIDS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.profiles;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.CoreItemFactory;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeBuilder;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||
import org.openhab.core.thing.profiles.TriggerProfileType;
|
||||
|
||||
/**
|
||||
* IHC / ELKO profile constants.
|
||||
*
|
||||
* @author Pauli Anttila - initial contribution.
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface IhcProfiles {
|
||||
|
||||
ProfileTypeUID PUSHBUTTON_COMMAND = new ProfileTypeUID("ihc", "pushbutton-to-command");
|
||||
|
||||
TriggerProfileType PUSHBUTTON_COMMAND_TYPE = ProfileTypeBuilder
|
||||
.newTrigger(PUSHBUTTON_COMMAND, "Push Button To Command")
|
||||
.withSupportedItemTypes(CoreItemFactory.DIMMER, CoreItemFactory.ROLLERSHUTTER, CoreItemFactory.CONTACT,
|
||||
CoreItemFactory.SWITCH, CoreItemFactory.PLAYER)
|
||||
.build();
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.profiles;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.ihc.internal.IhcBindingConstants;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.NextPreviousType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PlayPauseType;
|
||||
import org.openhab.core.library.types.RewindFastforwardType;
|
||||
import org.openhab.core.library.types.StopMoveType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
import org.openhab.core.thing.profiles.ProfileCallback;
|
||||
import org.openhab.core.thing.profiles.ProfileContext;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||
import org.openhab.core.thing.profiles.TriggerProfile;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PushButtonToCommandProfile} transforms push button channel events to commands.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PushButtonToCommandProfile implements TriggerProfile {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PushButtonToCommandProfile.class);
|
||||
|
||||
private static final String PARAM_SHORT_PRESS_COMMAND = "short-press-command";
|
||||
private static final String PARAM_LONG_PRESS_COMMAND = "long-press-command";
|
||||
private static final String PARAM_LONG_PRESS_TIME = "long-press-time";
|
||||
private static final String PARAM_REPEAT_TIME = "repeat-time";
|
||||
private static final String PARAM_TIMEOUT_TIME = "timeout";
|
||||
|
||||
private static final Command DEF_SHORT_PRESS_COMMAND = OnOffType.ON;
|
||||
private static final Command DEF_LONG_PRESS_COMMAND = IncreaseDecreaseType.INCREASE;
|
||||
private static final long DEF_LONG_PRESS_TIME = 1000;
|
||||
private static final long DEF_REPEAT_TIME = 200;
|
||||
private static final long DEF_TIMEOUT_TIME = 10000;
|
||||
|
||||
private final ProfileCallback callback;
|
||||
|
||||
private final ProfileContext context;
|
||||
|
||||
@Nullable
|
||||
private Command shortPressCommand;
|
||||
|
||||
@Nullable
|
||||
private Command longPressCommand;
|
||||
|
||||
@Nullable
|
||||
private ScheduledFuture<?> dimmFuture;
|
||||
@Nullable
|
||||
private ScheduledFuture<?> timeoutFuture;
|
||||
|
||||
@Nullable
|
||||
private State previousState;
|
||||
|
||||
private long pressedTime = 0;
|
||||
|
||||
private long longPressTime;
|
||||
private long repeatTime;
|
||||
private long timeout;
|
||||
|
||||
PushButtonToCommandProfile(ProfileCallback callback, ProfileContext context) {
|
||||
this.callback = callback;
|
||||
this.context = context;
|
||||
|
||||
shortPressCommand = getParamAsCommand(PARAM_SHORT_PRESS_COMMAND, DEF_SHORT_PRESS_COMMAND);
|
||||
longPressCommand = getParamAsCommand(PARAM_LONG_PRESS_COMMAND, DEF_LONG_PRESS_COMMAND);
|
||||
longPressTime = getParamAsLong(PARAM_LONG_PRESS_TIME, DEF_LONG_PRESS_TIME);
|
||||
repeatTime = getParamAsLong(PARAM_REPEAT_TIME, DEF_REPEAT_TIME);
|
||||
timeout = getParamAsLong(PARAM_TIMEOUT_TIME, DEF_TIMEOUT_TIME);
|
||||
}
|
||||
|
||||
private long getParamAsLong(String param, long defValue) {
|
||||
long retval;
|
||||
Object paramValue = context.getConfiguration().get(param);
|
||||
logger.debug("Configuring profile with {} parameter '{}'", param, paramValue);
|
||||
if (paramValue instanceof BigDecimal) {
|
||||
retval = ((BigDecimal) paramValue).longValue();
|
||||
} else {
|
||||
logger.debug("Parameter '{}' is not of type BigDecimal, using default value '{}'", param, defValue);
|
||||
retval = defValue;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private @Nullable Command getParamAsCommand(String param, Command defValue) {
|
||||
Command retval;
|
||||
Object paramValue = context.getConfiguration().get(param);
|
||||
logger.debug("Configuring profile with {} parameter '{}'", param, paramValue);
|
||||
|
||||
if (paramValue instanceof String) {
|
||||
try {
|
||||
retval = convertStringToCommand(String.valueOf(paramValue));
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.warn("Parameter '{}' is not a valid command type, using default value '{}'", param, defValue);
|
||||
retval = defValue;
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.debug("Parameter '{}' is not of type String, using default value '{}'", param, defValue);
|
||||
retval = defValue;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
private @Nullable Command convertStringToCommand(String str) throws IllegalArgumentException {
|
||||
Command retval = null;
|
||||
switch (str) {
|
||||
case "ON":
|
||||
retval = OnOffType.ON;
|
||||
break;
|
||||
case "OFF":
|
||||
retval = OnOffType.OFF;
|
||||
break;
|
||||
case "STOP":
|
||||
retval = StopMoveType.STOP;
|
||||
break;
|
||||
case "MOVE":
|
||||
retval = StopMoveType.MOVE;
|
||||
break;
|
||||
case "PLAY":
|
||||
retval = PlayPauseType.PLAY;
|
||||
break;
|
||||
case "PAUSE":
|
||||
retval = PlayPauseType.PAUSE;
|
||||
break;
|
||||
case "NEXT":
|
||||
retval = NextPreviousType.NEXT;
|
||||
break;
|
||||
case "PREVIOUS":
|
||||
retval = NextPreviousType.PREVIOUS;
|
||||
break;
|
||||
case "FASTFORWARD":
|
||||
retval = RewindFastforwardType.FASTFORWARD;
|
||||
break;
|
||||
case "REWIND":
|
||||
retval = RewindFastforwardType.REWIND;
|
||||
break;
|
||||
case "INCREASE":
|
||||
retval = IncreaseDecreaseType.INCREASE;
|
||||
break;
|
||||
case "DECREASE":
|
||||
retval = IncreaseDecreaseType.DECREASE;
|
||||
break;
|
||||
case "UP":
|
||||
retval = UpDownType.UP;
|
||||
break;
|
||||
case "DOWN":
|
||||
retval = UpDownType.DOWN;
|
||||
break;
|
||||
case "TOGGLE":
|
||||
break; // return null
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal argument '" + str + "'");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileTypeUID getProfileTypeUID() {
|
||||
return IhcProfiles.PUSHBUTTON_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateUpdateFromItem(State state) {
|
||||
previousState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTriggerFromHandler(String event) {
|
||||
if (IhcBindingConstants.EVENT_PRESSED.equals(event)) {
|
||||
buttonPressed(toggleCommandIfNeeded(longPressCommand));
|
||||
} else if (IhcBindingConstants.EVENT_RELEASED.equals(event)) {
|
||||
buttonReleased(toggleCommandIfNeeded(shortPressCommand));
|
||||
}
|
||||
}
|
||||
|
||||
private Command toggleCommandIfNeeded(@Nullable Command command) {
|
||||
if (command == null) {
|
||||
logger.debug("Toggling command: previous state is '{}'", previousState);
|
||||
return OnOffType.ON.equals(previousState) ? OnOffType.OFF : OnOffType.ON;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
private synchronized void buttonPressed(Command commandToSend) {
|
||||
cancelTimeoutFuture();
|
||||
cancelDimmFuture();
|
||||
|
||||
if (repeatTime > 0) {
|
||||
// run repeatedly
|
||||
dimmFuture = context.getExecutorService().scheduleWithFixedDelay(() -> callback.sendCommand(commandToSend),
|
||||
longPressTime + 50, repeatTime, TimeUnit.MILLISECONDS);
|
||||
timeoutFuture = context.getExecutorService().schedule(() -> this.cancelDimmFuture(), timeout,
|
||||
TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
// run only ones
|
||||
dimmFuture = context.getExecutorService().schedule(() -> callback.sendCommand(commandToSend),
|
||||
longPressTime + 50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
pressedTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private synchronized void buttonReleased(Command commandToSend) {
|
||||
cancelTimeoutFuture();
|
||||
cancelDimmFuture();
|
||||
|
||||
if (System.currentTimeMillis() - pressedTime <= longPressTime) {
|
||||
callback.sendCommand(commandToSend);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void cancelDimmFuture() {
|
||||
if (dimmFuture != null) {
|
||||
dimmFuture.cancel(false);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void cancelTimeoutFuture() {
|
||||
if (timeoutFuture != null) {
|
||||
timeoutFuture.cancel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,566 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSLoginResult;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSTimeManagerSettings;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.binding.ihc.internal.ws.services.IhcAirlinkManagementService;
|
||||
import org.openhab.binding.ihc.internal.ws.services.IhcAuthenticationService;
|
||||
import org.openhab.binding.ihc.internal.ws.services.IhcConfigurationService;
|
||||
import org.openhab.binding.ihc.internal.ws.services.IhcControllerService;
|
||||
import org.openhab.binding.ihc.internal.ws.services.IhcResourceInteractionService;
|
||||
import org.openhab.binding.ihc.internal.ws.services.IhcTimeService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* IhcClient provides interface to communicate IHC / ELKO LS Controller.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcClient {
|
||||
|
||||
/** Current state of the connection */
|
||||
public enum ConnectionState {
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED
|
||||
}
|
||||
|
||||
public static final String CONTROLLER_STATE_READY = "text.ctrl.state.ready";
|
||||
public static final String CONTROLLER_STATE_INITIALIZE = "text.ctrl.state.initialize";
|
||||
|
||||
private static final int NOTIFICATION_WAIT_TIMEOUT_IN_SEC = 5;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(IhcClient.class);
|
||||
|
||||
private ConnectionState connState = ConnectionState.DISCONNECTED;
|
||||
|
||||
private IhcConnectionPool ihcConnectionPool;
|
||||
|
||||
/** Controller services */
|
||||
private IhcAuthenticationService authenticationService;
|
||||
private IhcResourceInteractionService resourceInteractionService;
|
||||
private IhcControllerService controllerService;
|
||||
private IhcConfigurationService configurationService;
|
||||
private IhcAirlinkManagementService airlinkManagementService;
|
||||
private IhcTimeService timeService;
|
||||
|
||||
/** Thread to handle resource value notifications from the controller */
|
||||
private IhcResourceValueNotificationListener resourceValueNotificationListener;
|
||||
|
||||
/** Thread to handle controller's state change notifications */
|
||||
private IhcControllerStateListener controllerStateListener;
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
private String host;
|
||||
|
||||
/** Timeout in milliseconds */
|
||||
private int timeout;
|
||||
|
||||
private Map<Integer, WSResourceValue> resourceValues = new HashMap<>();
|
||||
private List<IhcEventListener> eventListeners = new ArrayList<>();
|
||||
|
||||
public IhcClient(String host, String username, String password) {
|
||||
this(host, username, password, 5000);
|
||||
}
|
||||
|
||||
public IhcClient(String host, String username, String password, int timeout) {
|
||||
this.host = host;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public synchronized ConnectionState getConnectionState() {
|
||||
return connState;
|
||||
}
|
||||
|
||||
private synchronized void setConnectionState(ConnectionState newState) {
|
||||
connState = newState;
|
||||
}
|
||||
|
||||
public void addEventListener(IhcEventListener listener) {
|
||||
eventListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeEventListener(IhcEventListener listener) {
|
||||
eventListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open connection and authenticate session to IHC / ELKO LS controller.
|
||||
*
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public void closeConnection() throws IhcExecption {
|
||||
logger.debug("Closing connection");
|
||||
|
||||
// interrupt
|
||||
|
||||
if (resourceValueNotificationListener != null) {
|
||||
resourceValueNotificationListener.setInterrupted(true);
|
||||
}
|
||||
if (controllerStateListener != null) {
|
||||
controllerStateListener.setInterrupted(true);
|
||||
}
|
||||
|
||||
// wait to stop
|
||||
|
||||
if (resourceValueNotificationListener != null) {
|
||||
logger.debug("Waiting resource value notification listener to stop");
|
||||
try {
|
||||
resourceValueNotificationListener.join(NOTIFICATION_WAIT_TIMEOUT_IN_SEC * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerStateListener != null) {
|
||||
logger.debug("Waiting controller state listener to stop");
|
||||
try {
|
||||
controllerStateListener.join(NOTIFICATION_WAIT_TIMEOUT_IN_SEC * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
logger.debug("Connection closed");
|
||||
setConnectionState(ConnectionState.DISCONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open connection and authenticate session to IHC / ELKO LS controller.
|
||||
*
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public void openConnection() throws IhcExecption {
|
||||
logger.debug("Opening connection");
|
||||
|
||||
setConnectionState(ConnectionState.CONNECTING);
|
||||
ihcConnectionPool = new IhcConnectionPool();
|
||||
authenticationService = new IhcAuthenticationService(host, timeout, ihcConnectionPool);
|
||||
WSLoginResult loginResult = authenticationService.authenticate(username, password, "treeview");
|
||||
|
||||
if (!loginResult.isLoginWasSuccessful()) {
|
||||
// Login failed
|
||||
|
||||
setConnectionState(ConnectionState.DISCONNECTED);
|
||||
|
||||
if (loginResult.isLoginFailedDueToAccountInvalid()) {
|
||||
throw new IhcExecption("login failed because of invalid account");
|
||||
}
|
||||
|
||||
if (loginResult.isLoginFailedDueToConnectionRestrictions()) {
|
||||
throw new IhcExecption("login failed because of connection restrictions");
|
||||
}
|
||||
|
||||
if (loginResult.isLoginFailedDueToInsufficientUserRights()) {
|
||||
throw new IhcExecption("login failed because of insufficient user rights");
|
||||
}
|
||||
|
||||
throw new IhcExecption("login failed because of unknown reason");
|
||||
}
|
||||
|
||||
logger.debug("Connection successfully opened");
|
||||
|
||||
resourceInteractionService = new IhcResourceInteractionService(host, timeout, ihcConnectionPool);
|
||||
controllerService = new IhcControllerService(host, timeout, ihcConnectionPool);
|
||||
configurationService = new IhcConfigurationService(host, timeout, ihcConnectionPool);
|
||||
airlinkManagementService = new IhcAirlinkManagementService(host, timeout, ihcConnectionPool);
|
||||
timeService = new IhcTimeService(host, timeout, ihcConnectionPool);
|
||||
setConnectionState(ConnectionState.CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start event listener to get notifications from IHC / ELKO LS controller.
|
||||
*
|
||||
* @throws IhcExecption
|
||||
*
|
||||
*/
|
||||
public void startControllerEventListeners() throws IhcExecption {
|
||||
if (getConnectionState() == ConnectionState.CONNECTED) {
|
||||
logger.debug("Start IHC / ELKO listeners");
|
||||
resourceValueNotificationListener = new IhcResourceValueNotificationListener();
|
||||
resourceValueNotificationListener.start();
|
||||
controllerStateListener = new IhcControllerStateListener();
|
||||
controllerStateListener.start();
|
||||
} else {
|
||||
throw new IhcExecption("Connection to controller not open");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query project information from the controller.
|
||||
*
|
||||
* @return project information.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSProjectInfo getProjectInfo() throws IhcExecption {
|
||||
return controllerService.getProjectInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query system information from the controller.
|
||||
*
|
||||
* @return system information.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSSystemInfo getSystemInfo() throws IhcExecption {
|
||||
return configurationService.getSystemInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query time settings from the controller.
|
||||
*
|
||||
* @return time settings.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSTimeManagerSettings getTimeSettings() throws IhcExecption {
|
||||
return timeService.getTimeSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query detected RF devices from the controller.
|
||||
*
|
||||
* @return List of RF devices.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized List<WSRFDevice> getDetectedRFDevices() throws IhcExecption {
|
||||
return airlinkManagementService.getDetectedDeviceList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query controller current state.
|
||||
*
|
||||
* @return controller's current state.
|
||||
*/
|
||||
public WSControllerState getControllerState() throws IhcExecption {
|
||||
return controllerService.getControllerState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query project number of segments.
|
||||
*
|
||||
* @return number of segments.
|
||||
*/
|
||||
public int getProjectNumberOfSegments() throws IhcExecption {
|
||||
return controllerService.getProjectNumberOfSegments();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query project segmentation size.
|
||||
*
|
||||
* @return segmentation size in bytes.
|
||||
*/
|
||||
public int getProjectSegmentationSize() throws IhcExecption {
|
||||
return controllerService.getProjectSegmentationSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query project segments data.
|
||||
*
|
||||
* @return segments data.
|
||||
*/
|
||||
public WSFile getProjectSegment(int index, int major, int minor) throws IhcExecption {
|
||||
return controllerService.getProjectSegment(index, major, minor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch project file from controller.
|
||||
*
|
||||
* @return project file.
|
||||
*/
|
||||
public byte[] getProjectFileFromController() throws IhcExecption {
|
||||
try {
|
||||
WSProjectInfo projectInfo = getProjectInfo();
|
||||
int numberOfSegments = getProjectNumberOfSegments();
|
||||
int segmentationSize = getProjectSegmentationSize();
|
||||
|
||||
logger.debug("Number of segments: {}", numberOfSegments);
|
||||
logger.debug("Segmentation size: {}", segmentationSize);
|
||||
|
||||
try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
|
||||
for (int i = 0; i < numberOfSegments; i++) {
|
||||
logger.debug("Downloading segment {}", i);
|
||||
|
||||
WSFile data = getProjectSegment(i, projectInfo.getProjectMajorRevision(),
|
||||
projectInfo.getProjectMinorRevision());
|
||||
byteStream.write(data.getData());
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("File size before base64 encoding: {} bytes", byteStream.size());
|
||||
}
|
||||
byte[] decodedBytes = Base64.getDecoder().decode(byteStream.toString());
|
||||
logger.debug("File size after base64 encoding: {} bytes", decodedBytes.length);
|
||||
try (GZIPInputStream gzis = new GZIPInputStream(new ByteArrayInputStream(decodedBytes))) {
|
||||
try (InputStreamReader in = new InputStreamReader(gzis, "ISO-8859-1")) {
|
||||
return IOUtils.toByteArray(in, "ISO-8859-1");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
throw new IhcExecption(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait controller state change notification.
|
||||
*
|
||||
* @param previousState Previous controller state.
|
||||
* @param timeoutInSecondscHow many seconds to wait notifications.
|
||||
* @return current controller state.
|
||||
*/
|
||||
private WSControllerState waitStateChangeNotifications(WSControllerState previousState, int timeoutInSeconds)
|
||||
throws IhcExecption {
|
||||
return controllerService.waitStateChangeNotifications(previousState, timeoutInSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable resources runtime value notifications.
|
||||
*
|
||||
* @param resourceIdList List of resource Identifiers.
|
||||
* @return True is connection successfully opened.
|
||||
*/
|
||||
public synchronized void enableRuntimeValueNotifications(Set<Integer> resourceIdList) throws IhcExecption {
|
||||
resourceInteractionService.enableRuntimeValueNotifications(resourceIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait runtime value notifications.
|
||||
*
|
||||
* Runtime value notification should firstly be activated by
|
||||
* enableRuntimeValueNotifications function.
|
||||
*
|
||||
* @param timeoutInSeconds How many seconds to wait notifications.
|
||||
* @return List of received runtime value notifications.
|
||||
* @throws SocketTimeoutException
|
||||
*/
|
||||
private List<WSResourceValue> waitResourceValueNotifications(int timeoutInSeconds) throws IhcExecption {
|
||||
List<WSResourceValue> list = resourceInteractionService.waitResourceValueNotifications(timeoutInSeconds);
|
||||
|
||||
for (WSResourceValue val : list) {
|
||||
resourceValues.put(val.resourceID, val);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query resource value from controller.
|
||||
*
|
||||
*
|
||||
* @param resoureId Resource Identifier.
|
||||
* @return Resource value.
|
||||
*/
|
||||
public WSResourceValue resourceQuery(int resoureId) throws IhcExecption {
|
||||
return resourceInteractionService.resourceQuery(resoureId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource value information.
|
||||
*
|
||||
* Function return resource value from internal memory, if data is not
|
||||
* available information is read from the controller.
|
||||
*
|
||||
* Resource value's value field (e.g. floatingPointValue) could be old
|
||||
* information.
|
||||
*
|
||||
* @param resoureId Resource Identifier.
|
||||
* @return Resource value.
|
||||
*/
|
||||
public WSResourceValue getResourceValueInformation(int resourceId) throws IhcExecption {
|
||||
if (resourceId != 0) {
|
||||
WSResourceValue data = resourceValues.get(resourceId);
|
||||
if (data == null) {
|
||||
// data is not available, read it from the controller
|
||||
data = resourceInteractionService.resourceQuery(resourceId);
|
||||
}
|
||||
return data;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update resource value to controller.
|
||||
*
|
||||
*
|
||||
* @param value Resource value.
|
||||
* @return True if value is successfully updated.
|
||||
*/
|
||||
public boolean resourceUpdate(WSResourceValue value) throws IhcExecption {
|
||||
return resourceInteractionService.resourceUpdate(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The IhcReader runs as a separate thread.
|
||||
*
|
||||
* Thread listen resource value notifications from IHC / ELKO LS controller.
|
||||
*/
|
||||
private class IhcResourceValueNotificationListener extends Thread {
|
||||
private volatile boolean interrupted = false;
|
||||
|
||||
public void setInterrupted(boolean interrupted) {
|
||||
this.interrupted = interrupted;
|
||||
this.interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.debug("IHC resource value listener started");
|
||||
|
||||
// as long as no interrupt is requested, continue running
|
||||
while (!interrupted) {
|
||||
waitResourceNotifications();
|
||||
}
|
||||
logger.debug("IHC resource value listener stopped");
|
||||
}
|
||||
|
||||
private void waitResourceNotifications() {
|
||||
try {
|
||||
logger.trace("Wait new resource value notifications from controller");
|
||||
List<WSResourceValue> resourceValueList = waitResourceValueNotifications(
|
||||
NOTIFICATION_WAIT_TIMEOUT_IN_SEC);
|
||||
logger.debug("{} new notifications received from controller", resourceValueList.size());
|
||||
for (WSResourceValue value : resourceValueList) {
|
||||
sendResourceValueUpdateEvent(value);
|
||||
}
|
||||
} catch (IhcExecption e) {
|
||||
if (!interrupted) {
|
||||
logger.warn("New notifications wait failed...", e);
|
||||
sendErrorEvent(e);
|
||||
mysleep(1000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mysleep(long milli) {
|
||||
try {
|
||||
sleep(milli);
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The IhcReader runs as a separate thread.
|
||||
*
|
||||
* Thread listen controller state change notifications from IHC / ELKO LS
|
||||
* controller.
|
||||
*
|
||||
*/
|
||||
private class IhcControllerStateListener extends Thread {
|
||||
private volatile boolean interrupted = false;
|
||||
|
||||
public void setInterrupted(boolean interrupted) {
|
||||
this.interrupted = interrupted;
|
||||
this.interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.debug("IHC controller state listener started");
|
||||
WSControllerState previousState = null;
|
||||
|
||||
// as long as no interrupt is requested, continue running
|
||||
while (!interrupted) {
|
||||
try {
|
||||
if (previousState == null) {
|
||||
// initialize previous state
|
||||
previousState = controllerService.getControllerState();
|
||||
logger.debug("Controller initial state {}", previousState.getState());
|
||||
}
|
||||
logger.trace("Wait new state change notification from controller");
|
||||
WSControllerState currentState = waitStateChangeNotifications(previousState,
|
||||
NOTIFICATION_WAIT_TIMEOUT_IN_SEC);
|
||||
logger.trace("Controller state {}", currentState.getState());
|
||||
|
||||
if (!previousState.getState().equals(currentState.getState())) {
|
||||
logger.debug("Controller state change detected ({} -> {})", previousState.getState(),
|
||||
currentState.getState());
|
||||
sendControllerStateUpdateEvent(currentState);
|
||||
previousState.setState(currentState.getState());
|
||||
}
|
||||
} catch (IhcExecption e) {
|
||||
if (!interrupted) {
|
||||
logger.error("New controller state change notification wait failed...", e);
|
||||
sendErrorEvent(e);
|
||||
mysleep(1000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.debug("IHC controller state listener stopped");
|
||||
}
|
||||
|
||||
private void mysleep(long milli) {
|
||||
try {
|
||||
sleep(milli);
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendErrorEvent(IhcExecption err) {
|
||||
eventListeners.forEach(listener -> {
|
||||
try {
|
||||
listener.errorOccured(err);
|
||||
} catch (RuntimeException e) {
|
||||
logger.debug("Event listener invoking error.", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendControllerStateUpdateEvent(WSControllerState state) {
|
||||
eventListeners.forEach(listener -> {
|
||||
try {
|
||||
listener.statusUpdateReceived(state);
|
||||
} catch (RuntimeException e) {
|
||||
logger.debug("Event listener invoking error.", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendResourceValueUpdateEvent(WSResourceValue value) {
|
||||
eventListeners.forEach(listener -> {
|
||||
try {
|
||||
listener.resourceValueUpdateReceived(value);
|
||||
} catch (RuntimeException e) {
|
||||
logger.debug("Event listener invoking error.", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
|
||||
/**
|
||||
* This interface defines interface to receive updates from IHC controller.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public interface IhcEventListener {
|
||||
|
||||
/**
|
||||
* Event for receive status update from IHC controller.
|
||||
*
|
||||
* @param status Received status update from controller.
|
||||
*/
|
||||
void statusUpdateReceived(WSControllerState status);
|
||||
|
||||
/**
|
||||
* Event for receive resource value updates from IHC controller.
|
||||
*
|
||||
* @param value Received value update from controller.
|
||||
*/
|
||||
void resourceValueUpdateReceived(WSResourceValue value);
|
||||
|
||||
/**
|
||||
* Event for fatal error on communication to IHC controller.
|
||||
*
|
||||
* @param e IhcException occurred.
|
||||
*/
|
||||
void errorOccured(IhcExecption e);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSControllerState complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
|
||||
public class WSControllerState {
|
||||
private String state;
|
||||
|
||||
public WSControllerState() {
|
||||
}
|
||||
|
||||
public WSControllerState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state value for this WSControllerState.
|
||||
*
|
||||
* @return state
|
||||
*/
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state value for this WSControllerState.
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public WSControllerState parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
if (data.contains("getState1")) {
|
||||
state = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getState1/ns1:state");
|
||||
} else if (data.contains("waitForControllerStateChange3")) {
|
||||
state = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:waitForControllerStateChange3/ns1:state");
|
||||
} else {
|
||||
throw new IhcExecption("Encoding error, unsupported data");
|
||||
}
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
/**
|
||||
* Class for WSDate complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSDate {
|
||||
private int hours;
|
||||
private int minutes;
|
||||
private int seconds;
|
||||
private int year;
|
||||
private int day;
|
||||
private int monthWithJanuaryAsOne;
|
||||
|
||||
public WSDate() {
|
||||
}
|
||||
|
||||
public WSDate(int hours, int minutes, int seconds, int year, int day, int monthWithJanuaryAsOne) {
|
||||
this.hours = hours;
|
||||
this.minutes = minutes;
|
||||
this.seconds = seconds;
|
||||
this.year = year;
|
||||
this.day = day;
|
||||
this.monthWithJanuaryAsOne = monthWithJanuaryAsOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hours value for this WSDate.
|
||||
*
|
||||
* @return hours
|
||||
*/
|
||||
public int getHours() {
|
||||
return hours;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hours value for this WSDate.
|
||||
*
|
||||
* @param hours
|
||||
*/
|
||||
public void setHours(int hours) {
|
||||
this.hours = hours;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minutes value for this WSDate.
|
||||
*
|
||||
* @return minutes
|
||||
*/
|
||||
public int getMinutes() {
|
||||
return minutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minutes value for this WSDate.
|
||||
*
|
||||
* @param minutes
|
||||
*/
|
||||
public void setMinutes(int minutes) {
|
||||
this.minutes = minutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the seconds value for this WSDate.
|
||||
*
|
||||
* @return seconds
|
||||
*/
|
||||
public int getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the seconds value for this WSDate.
|
||||
*
|
||||
* @param seconds
|
||||
*/
|
||||
public void setSeconds(int seconds) {
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the year value for this WSDate.
|
||||
*
|
||||
* @return year
|
||||
*/
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the year value for this WSDate.
|
||||
*
|
||||
* @param year
|
||||
*/
|
||||
public void setYear(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the day value for this WSDate.
|
||||
*
|
||||
* @return day
|
||||
*/
|
||||
public int getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the day value for this WSDate.
|
||||
*
|
||||
* @param day
|
||||
*/
|
||||
public void setDay(int day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the monthWithJanuaryAsOne value for this WSDate.
|
||||
*
|
||||
* @return monthWithJanuaryAsOne
|
||||
*/
|
||||
public int getMonthWithJanuaryAsOne() {
|
||||
return monthWithJanuaryAsOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the monthWithJanuaryAsOne value for this WSDate.
|
||||
*
|
||||
* @param monthWithJanuaryAsOne
|
||||
*/
|
||||
public void setMonthWithJanuaryAsOne(int monthWithJanuaryAsOne) {
|
||||
this.monthWithJanuaryAsOne = monthWithJanuaryAsOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets WSDate as LocalDateTime.
|
||||
*
|
||||
* @return LocalDateTime
|
||||
*/
|
||||
public LocalDateTime getAsLocalDateTime() {
|
||||
return LocalDateTime.of(year, monthWithJanuaryAsOne, day, hours, minutes, seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets WSDate as ZonedDateTime.
|
||||
*
|
||||
* @return LocalDateTime
|
||||
*/
|
||||
public ZonedDateTime getAsZonedDateTime(ZoneId zoneId) {
|
||||
return ZonedDateTime.of(getAsLocalDateTime(), zoneId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSFile complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSFile {
|
||||
private byte[] data;
|
||||
private String filename;
|
||||
|
||||
public WSFile() {
|
||||
}
|
||||
|
||||
public WSFile(byte[] data, String filename) {
|
||||
this.data = data;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data value for this WSFile.
|
||||
*
|
||||
* @return data
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data value for this WSFile.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filename value for this WSFile.
|
||||
*
|
||||
* @return filename
|
||||
*/
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filename value for this WSFile.
|
||||
*
|
||||
* @param filename
|
||||
*/
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public WSFile parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
filename = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectSegment4/ns1:filename");
|
||||
this.data = XPathUtils
|
||||
.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectSegment4/ns1:data")
|
||||
.getBytes();
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSLoginResult complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSLoginResult {
|
||||
|
||||
protected WSUser loggedInUser;
|
||||
protected boolean loginWasSuccessful;
|
||||
protected boolean loginFailedDueToConnectionRestrictions;
|
||||
protected boolean loginFailedDueToInsufficientUserRights;
|
||||
protected boolean loginFailedDueToAccountInvalid;
|
||||
|
||||
public WSLoginResult() {
|
||||
}
|
||||
|
||||
public WSLoginResult(WSUser loggedInUser, boolean loginWasSuccessful,
|
||||
boolean loginFailedDueToConnectionRestrictions, boolean loginFailedDueToInsufficientUserRights,
|
||||
boolean loginFailedDueToAccountInvalid) {
|
||||
this.loggedInUser = loggedInUser;
|
||||
this.loginWasSuccessful = loginWasSuccessful;
|
||||
this.loginFailedDueToConnectionRestrictions = loginFailedDueToConnectionRestrictions;
|
||||
this.loginFailedDueToInsufficientUserRights = loginFailedDueToInsufficientUserRights;
|
||||
this.loginFailedDueToAccountInvalid = loginFailedDueToAccountInvalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the loggedInUser property.
|
||||
*
|
||||
* @return possible object is {@link WSUser }
|
||||
*
|
||||
*/
|
||||
public WSUser getLoggedInUser() {
|
||||
return loggedInUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the loggedInUser property.
|
||||
*
|
||||
* @param value allowed object is {@link WSUser }
|
||||
*
|
||||
*/
|
||||
public void setLoggedInUser(WSUser value) {
|
||||
this.loggedInUser = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the loginWasSuccessful property.
|
||||
*
|
||||
*/
|
||||
public boolean isLoginWasSuccessful() {
|
||||
return loginWasSuccessful;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the loginWasSuccessful property.
|
||||
*
|
||||
*/
|
||||
public void setLoginWasSuccessful(boolean value) {
|
||||
this.loginWasSuccessful = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the loginFailedDueToConnectionRestrictions property.
|
||||
*
|
||||
*/
|
||||
public boolean isLoginFailedDueToConnectionRestrictions() {
|
||||
return loginFailedDueToConnectionRestrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the loginFailedDueToConnectionRestrictions property.
|
||||
*
|
||||
*/
|
||||
public void setLoginFailedDueToConnectionRestrictions(boolean value) {
|
||||
this.loginFailedDueToConnectionRestrictions = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the loginFailedDueToInsufficientUserRights property.
|
||||
*
|
||||
*/
|
||||
public boolean isLoginFailedDueToInsufficientUserRights() {
|
||||
return loginFailedDueToInsufficientUserRights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the loginFailedDueToInsufficientUserRights property.
|
||||
*
|
||||
*/
|
||||
public void setLoginFailedDueToInsufficientUserRights(boolean value) {
|
||||
this.loginFailedDueToInsufficientUserRights = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the loginFailedDueToAccountInvalid property.
|
||||
*
|
||||
*/
|
||||
public boolean isLoginFailedDueToAccountInvalid() {
|
||||
return loginFailedDueToAccountInvalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the loginFailedDueToAccountInvalid property.
|
||||
*
|
||||
*/
|
||||
public void setLoginFailedDueToAccountInvalid(boolean value) {
|
||||
this.loginFailedDueToAccountInvalid = value;
|
||||
}
|
||||
|
||||
public WSLoginResult parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
loginWasSuccessful = XPathUtils.parseValueToBoolean(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginWasSuccessful");
|
||||
|
||||
loginFailedDueToConnectionRestrictions = XPathUtils.parseValueToBoolean(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginFailedDueToConnectionRestrictions");
|
||||
|
||||
loginFailedDueToInsufficientUserRights = XPathUtils.parseValueToBoolean(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginFailedDueToInsufficientUserRights");
|
||||
|
||||
loginFailedDueToAccountInvalid = XPathUtils.parseValueToBoolean(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginFailedDueToAccountInvalid");
|
||||
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSNumberOfSegments complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSNumberOfSegments {
|
||||
|
||||
private int segments;
|
||||
|
||||
public WSNumberOfSegments() {
|
||||
}
|
||||
|
||||
public WSNumberOfSegments(int segments) {
|
||||
this.segments = segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of segments.
|
||||
*
|
||||
* @return segmentation size
|
||||
*/
|
||||
public int getNumberOfSegments() {
|
||||
return segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of segmentations.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public void setNumberOfSegments(int segments) {
|
||||
this.segments = segments;
|
||||
}
|
||||
|
||||
public WSNumberOfSegments parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
String value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectNumberOfSegments1");
|
||||
setNumberOfSegments(Integer.parseInt(value));
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException | NumberFormatException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSProjectInfo complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSProjectInfo {
|
||||
|
||||
private int visualMinorVersion;
|
||||
private int visualMajorVersion;
|
||||
private int projectMajorRevision;
|
||||
private int projectMinorRevision;
|
||||
private WSDate lastmodified;
|
||||
private String projectNumber;
|
||||
private String customerName;
|
||||
private String installerName;
|
||||
|
||||
public WSProjectInfo() {
|
||||
}
|
||||
|
||||
public WSProjectInfo(int visualMinorVersion, int visualMajorVersion, int projectMajorRevision,
|
||||
int projectMinorRevision, WSDate lastmodified, String projectNumber, String customerName,
|
||||
String installerName) {
|
||||
this.visualMinorVersion = visualMinorVersion;
|
||||
this.visualMajorVersion = visualMajorVersion;
|
||||
this.projectMajorRevision = projectMajorRevision;
|
||||
this.projectMinorRevision = projectMinorRevision;
|
||||
this.lastmodified = lastmodified;
|
||||
this.projectNumber = projectNumber;
|
||||
this.customerName = customerName;
|
||||
this.installerName = installerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visualMinorVersion value for this WSProjectInfo.
|
||||
*
|
||||
* @return visualMinorVersion
|
||||
*/
|
||||
public int getVisualMinorVersion() {
|
||||
return visualMinorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visualMinorVersion value for this WSProjectInfo.
|
||||
*
|
||||
* @param visualMinorVersion
|
||||
*/
|
||||
public void setVisualMinorVersion(int visualMinorVersion) {
|
||||
this.visualMinorVersion = visualMinorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visualMajorVersion value for this WSProjectInfo.
|
||||
*
|
||||
* @return visualMajorVersion
|
||||
*/
|
||||
public int getVisualMajorVersion() {
|
||||
return visualMajorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visualMajorVersion value for this WSProjectInfo.
|
||||
*
|
||||
* @param visualMajorVersion
|
||||
*/
|
||||
public void setVisualMajorVersion(int visualMajorVersion) {
|
||||
this.visualMajorVersion = visualMajorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the projectMajorRevision value for this WSProjectInfo.
|
||||
*
|
||||
* @return projectMajorRevision
|
||||
*/
|
||||
public int getProjectMajorRevision() {
|
||||
return projectMajorRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the projectMajorRevision value for this WSProjectInfo.
|
||||
*
|
||||
* @param projectMajorRevision
|
||||
*/
|
||||
public void setProjectMajorRevision(int projectMajorRevision) {
|
||||
this.projectMajorRevision = projectMajorRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the projectMinorRevision value for this WSProjectInfo.
|
||||
*
|
||||
* @return projectMinorRevision
|
||||
*/
|
||||
public int getProjectMinorRevision() {
|
||||
return projectMinorRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the projectMinorRevision value for this WSProjectInfo.
|
||||
*
|
||||
* @param projectMinorRevision
|
||||
*/
|
||||
public void setProjectMinorRevision(int projectMinorRevision) {
|
||||
this.projectMinorRevision = projectMinorRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lastmodified value for this WSProjectInfo.
|
||||
*
|
||||
* @return lastmodified
|
||||
*/
|
||||
public WSDate getLastmodified() {
|
||||
return lastmodified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lastmodified value for this WSProjectInfo.
|
||||
*
|
||||
* @param lastmodified
|
||||
*/
|
||||
public void setLastmodified(WSDate lastmodified) {
|
||||
this.lastmodified = lastmodified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the projectNumber value for this WSProjectInfo.
|
||||
*
|
||||
* @return projectNumber
|
||||
*/
|
||||
public java.lang.String getProjectNumber() {
|
||||
return projectNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the projectNumber value for this WSProjectInfo.
|
||||
*
|
||||
* @param projectNumber
|
||||
*/
|
||||
public void setProjectNumber(String projectNumber) {
|
||||
this.projectNumber = projectNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the customerName value for this WSProjectInfo.
|
||||
*
|
||||
* @return customerName
|
||||
*/
|
||||
public java.lang.String getCustomerName() {
|
||||
return customerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the customerName value for this WSProjectInfo.
|
||||
*
|
||||
* @param customerName
|
||||
*/
|
||||
public void setCustomerName(String customerName) {
|
||||
this.customerName = customerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the installerName value for this WSProjectInfo.
|
||||
*
|
||||
* @return installerName
|
||||
*/
|
||||
public java.lang.String getInstallerName() {
|
||||
return installerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the installerName value for this WSProjectInfo.
|
||||
*
|
||||
* @param installerName
|
||||
*/
|
||||
public void setInstallerName(String installerName) {
|
||||
this.installerName = installerName;
|
||||
}
|
||||
|
||||
public WSProjectInfo parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
String value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:visualMinorVersion");
|
||||
setVisualMinorVersion(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:visualMajorVersion");
|
||||
setVisualMajorVersion(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:projectMajorRevision");
|
||||
setProjectMajorRevision(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:projectMinorRevision");
|
||||
setProjectMinorRevision(Integer.parseInt(value));
|
||||
|
||||
WSDate lastmodified = new WSDate();
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:day");
|
||||
lastmodified.setDay(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:monthWithJanuaryAsOne");
|
||||
lastmodified.setMonthWithJanuaryAsOne(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:hours");
|
||||
lastmodified.setHours(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:minutes");
|
||||
lastmodified.setMinutes(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:seconds");
|
||||
lastmodified.setSeconds(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:year");
|
||||
lastmodified.setYear(Integer.parseInt(value));
|
||||
|
||||
setLastmodified(lastmodified);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:projectNumber");
|
||||
setProjectNumber(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:customerName");
|
||||
setCustomerName(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:installerName");
|
||||
setInstallerName(value);
|
||||
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException | NumberFormatException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[ visualMinorVersion=%d, visualMajorVersion=%d, projectMajorRevision=%d, projectMinorRevision=%d, lastmodified=%s, projectNumber=%s, customerName=%s, installerName=%s ]",
|
||||
visualMinorVersion, visualMajorVersion, projectMajorRevision, projectMinorRevision,
|
||||
lastmodified.getAsLocalDateTime(), projectNumber, customerName, installerName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
/**
|
||||
* Class for WSRFDevice complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSRFDevice {
|
||||
|
||||
private int batteryLevel;
|
||||
private int deviceType;
|
||||
private long serialNumber;
|
||||
private int signalStrength;
|
||||
private int version;
|
||||
private boolean detected;
|
||||
|
||||
public WSRFDevice() {
|
||||
}
|
||||
|
||||
public WSRFDevice(int batteryLevel, int deviceType, long serialNumber, int signalStrength, int version,
|
||||
boolean detected) {
|
||||
this.batteryLevel = batteryLevel;
|
||||
this.deviceType = deviceType;
|
||||
this.serialNumber = serialNumber;
|
||||
this.signalStrength = signalStrength;
|
||||
this.version = version;
|
||||
this.detected = detected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the battery level value for this WSRFDevice.
|
||||
*
|
||||
* @return Battery Level
|
||||
*/
|
||||
public int getBatteryLevel() {
|
||||
return batteryLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the battery level value for this WSRFDevice.
|
||||
*
|
||||
* @param batteryLevel battery level
|
||||
*/
|
||||
public void setBatteryLevel(int batteryLevel) {
|
||||
this.batteryLevel = batteryLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the device type value for this WSRFDevice.
|
||||
*
|
||||
* @return device type
|
||||
*/
|
||||
public int getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the device type value for this WSRFDevice.
|
||||
*
|
||||
* @param device type
|
||||
*/
|
||||
public void setDeviceType(int deviceType) {
|
||||
this.deviceType = deviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the serial number value for this WSRFDevice.
|
||||
*
|
||||
* @return Serial number
|
||||
*/
|
||||
public long getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serial number value for this WSRFDevice.
|
||||
*
|
||||
* @param Serial number
|
||||
*/
|
||||
public void setSerialNumber(long serialNumber) {
|
||||
this.serialNumber = serialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the signal strength value for this WSRFDevice.
|
||||
*
|
||||
* @return Signal strength
|
||||
*/
|
||||
public int getSignalStrength() {
|
||||
return signalStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the signal strength value for this WSRFDevice.
|
||||
*
|
||||
* @param signalStrength Signal strength
|
||||
*/
|
||||
public void setSignalStrength(int signalStrength) {
|
||||
this.signalStrength = signalStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version value for this WSRFDevice.
|
||||
*
|
||||
* @return version
|
||||
*/
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version value for this WSRFDevice.
|
||||
*
|
||||
* @param version
|
||||
*/
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the detected value for this WSRFDevice.
|
||||
*
|
||||
* @return Detected
|
||||
*/
|
||||
public boolean getDetected() {
|
||||
return detected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the detected value for this WSRFDevice.
|
||||
*
|
||||
* @param detected
|
||||
*/
|
||||
public void setdetected(boolean detected) {
|
||||
this.detected = detected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[ batteryLevel=%d, deviceType=%d, serialNumber=%d, signalStrength=%d, version=%d, detected=%b ]",
|
||||
batteryLevel, deviceType, serialNumber, signalStrength, version, detected);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSSegmentationSize complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSSegmentationSize {
|
||||
|
||||
private int size;
|
||||
|
||||
public WSSegmentationSize() {
|
||||
}
|
||||
|
||||
public WSSegmentationSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the segmentation size value.
|
||||
*
|
||||
* @return segmentation size
|
||||
*/
|
||||
public int getSegmentationSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the segmentation size value.
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public void setSegmentationSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public WSSegmentationSize parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
String value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectSegmentationSize1");
|
||||
setSegmentationSize(Integer.parseInt(value));
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException | NumberFormatException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSProjectInfo complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSSystemInfo {
|
||||
|
||||
private long uptime;
|
||||
private ZonedDateTime realtimeclock;
|
||||
private String serialNumber;
|
||||
private String brand;
|
||||
private String version;
|
||||
private String hwRevision;
|
||||
private ZonedDateTime swDate;
|
||||
private boolean applicationIsWithoutViewer;
|
||||
private String productionDate;
|
||||
private String datalineVersion;
|
||||
private String rfModuleSoftwareVersion;
|
||||
private String rfModuleSerialNumber;
|
||||
|
||||
public WSSystemInfo() {
|
||||
}
|
||||
|
||||
public WSSystemInfo(long uptime, ZonedDateTime realtimeclock, String serialNumber, String brand, String version,
|
||||
String hwRevision, ZonedDateTime swDate, boolean applicationIsWithoutViewer, String productionDate,
|
||||
String datalineVersion, String rfModuleSoftwareVersion, String rfModuleSerialNumber) {
|
||||
this.uptime = uptime;
|
||||
this.realtimeclock = realtimeclock;
|
||||
this.serialNumber = serialNumber;
|
||||
this.brand = brand;
|
||||
this.version = version;
|
||||
this.hwRevision = hwRevision;
|
||||
this.swDate = swDate;
|
||||
this.applicationIsWithoutViewer = applicationIsWithoutViewer;
|
||||
this.productionDate = productionDate;
|
||||
this.datalineVersion = datalineVersion;
|
||||
this.rfModuleSoftwareVersion = rfModuleSoftwareVersion;
|
||||
this.rfModuleSerialNumber = rfModuleSerialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the uptime value for this WSSystemInfo.
|
||||
*
|
||||
* @return uptime in milliseconds
|
||||
*/
|
||||
public long getUptime() {
|
||||
return uptime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the uptime value for this WSSystemInfo.
|
||||
*
|
||||
* @param uptime uptime in milliseconds
|
||||
*/
|
||||
public void setUptime(long uptime) {
|
||||
this.uptime = uptime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RealTimeClock value for this WSSystemInfo.
|
||||
*
|
||||
* @return Real Time Clock
|
||||
*/
|
||||
public ZonedDateTime getRealTimeClock() {
|
||||
return realtimeclock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RealTimeClock value for this WSSystemInfo.
|
||||
*
|
||||
* @param RealTimeClock
|
||||
*/
|
||||
public void setRealTimeClock(ZonedDateTime realtimeclock) {
|
||||
this.realtimeclock = realtimeclock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SerialNumber value for this WSSystemInfo.
|
||||
*
|
||||
* @return SerialNumber
|
||||
*/
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SerialNumber value for this WSSystemInfo.
|
||||
*
|
||||
* @param SerialNumber
|
||||
*/
|
||||
public void setSerialNumber(String serialNumber) {
|
||||
this.serialNumber = serialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the brand value for this WSSystemInfo.
|
||||
*
|
||||
* @return brand
|
||||
*/
|
||||
public String getBrand() {
|
||||
return brand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the brand value for this WSSystemInfo.
|
||||
*
|
||||
* @param brand
|
||||
*/
|
||||
public void setBrand(String brand) {
|
||||
this.brand = brand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version value for this WSSystemInfo.
|
||||
*
|
||||
* @return version
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version value for this WSSystemInfo.
|
||||
*
|
||||
* @param version
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hwRevision value for this WSSystemInfo.
|
||||
*
|
||||
* @return hwRevision
|
||||
*/
|
||||
public String getHwRevision() {
|
||||
return hwRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hwRevision value for this WSSystemInfo.
|
||||
*
|
||||
* @param hwRevision
|
||||
*/
|
||||
public void setHwRevision(String hwRevision) {
|
||||
this.hwRevision = hwRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the swDate value for this WSSystemInfo.
|
||||
*
|
||||
* @return swDate
|
||||
*/
|
||||
public ZonedDateTime getSwDate() {
|
||||
return swDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the swDate value for this WSSystemInfo.
|
||||
*
|
||||
* @param swDate
|
||||
*/
|
||||
public void setSwDate(ZonedDateTime swDate) {
|
||||
this.swDate = swDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the applicationIsWithoutViewer value for this WSSystemInfo.
|
||||
*
|
||||
* @return applicationIsWithoutViewer
|
||||
*/
|
||||
public boolean getApplicationIsWithoutViewer() {
|
||||
return applicationIsWithoutViewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the applicationIsWithoutViewer value for this WSSystemInfo.
|
||||
*
|
||||
* @param applicationIsWithoutViewer
|
||||
*/
|
||||
public void setApplicationIsWithoutViewer(boolean applicationIsWithoutViewer) {
|
||||
this.applicationIsWithoutViewer = applicationIsWithoutViewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the productionDate value for this WSSystemInfo.
|
||||
*
|
||||
* @return productionDate
|
||||
*/
|
||||
public String getProductionDate() {
|
||||
return productionDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the productionDate value for this WSSystemInfo.
|
||||
*
|
||||
* @param productionDate
|
||||
*/
|
||||
public void setProductionDate(String productionDate) {
|
||||
this.productionDate = productionDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the datalineVersion value for this WSSystemInfo.
|
||||
*
|
||||
* @return datalineVersion
|
||||
*/
|
||||
public String getDatalineVersion() {
|
||||
return datalineVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the datalineVersion value for this WSSystemInfo.
|
||||
*
|
||||
* @param datalineVersion
|
||||
*/
|
||||
public void setDatalineVersion(String datalineVersion) {
|
||||
this.datalineVersion = datalineVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rfModuleSoftwareVersion value for this WSSystemInfo.
|
||||
*
|
||||
* @return rfModuleSoftwareVersion
|
||||
*/
|
||||
public String getRfModuleSoftwareVersion() {
|
||||
return rfModuleSoftwareVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rfModuleSoftwareVersion value for this WSSystemInfo.
|
||||
*
|
||||
* @param rfModuleSoftwareVersion
|
||||
*/
|
||||
public void setRfModuleSoftwareVersion(String rfModuleSoftwareVersion) {
|
||||
this.rfModuleSoftwareVersion = rfModuleSoftwareVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rfModuleSerialNumber value for this WSSystemInfo.
|
||||
*
|
||||
* @return rfModuleSerialNumber
|
||||
*/
|
||||
public String getRfModuleSerialNumber() {
|
||||
return rfModuleSerialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rfModuleSerialNumber value for this WSSystemInfo.
|
||||
*
|
||||
* @param rfModuleSerialNumber
|
||||
*/
|
||||
public void setRfModuleSerialNumber(String rfModuleSerialNumber) {
|
||||
this.rfModuleSerialNumber = rfModuleSerialNumber;
|
||||
}
|
||||
|
||||
public WSSystemInfo parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
String value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:uptime");
|
||||
setUptime(Long.parseLong(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:serialNumber");
|
||||
setSerialNumber(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:realtimeclock");
|
||||
setRealTimeClock(ZonedDateTime.parse(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:brand");
|
||||
setBrand(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:version");
|
||||
setVersion(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:hwRevision");
|
||||
setHwRevision(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:swDate");
|
||||
setSwDate(ZonedDateTime.parse(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:applicationIsWithoutViewer");
|
||||
setApplicationIsWithoutViewer(Boolean.parseBoolean(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:productionDate");
|
||||
setProductionDate(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:datalineVersion");
|
||||
setDatalineVersion(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:rfModuleSoftwareVersion");
|
||||
setRfModuleSoftwareVersion(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:rfModuleSerialNumber");
|
||||
setRfModuleSerialNumber(value);
|
||||
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException | NumberFormatException | DateTimeParseException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[ uptime=%d, realtimeclock=%s, serialNumber=%s, brand=%s, version=%s, hwRevision=%s, swDate=%s, applicationIsWithoutViewer=%b, productionDate=%s, datalineVersion=%s, rfModuleSoftwareVersion=%s, rfModuleSerialNumber=%s ]",
|
||||
uptime, realtimeclock, serialNumber, brand, version, hwRevision, swDate, applicationIsWithoutViewer,
|
||||
productionDate, datalineVersion, rfModuleSoftwareVersion, rfModuleSerialNumber);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Class for WSTimeManagerSettings complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSTimeManagerSettings {
|
||||
|
||||
private boolean synchroniseTimeAgainstServer;
|
||||
private boolean useDST;
|
||||
private int gmtOffsetInHours;
|
||||
private String serverName;
|
||||
private int syncIntervalInHours;
|
||||
private WSDate timeAndDateInUTC;
|
||||
|
||||
public WSTimeManagerSettings() {
|
||||
}
|
||||
|
||||
public WSTimeManagerSettings(boolean synchroniseTimeAgainstServer, boolean useDST, int gmtOffsetInHours,
|
||||
String serverName, int syncIntervalInHours, WSDate timeAndDateInUTC) {
|
||||
this.synchroniseTimeAgainstServer = synchroniseTimeAgainstServer;
|
||||
this.useDST = useDST;
|
||||
this.gmtOffsetInHours = gmtOffsetInHours;
|
||||
this.serverName = serverName;
|
||||
this.syncIntervalInHours = syncIntervalInHours;
|
||||
this.timeAndDateInUTC = timeAndDateInUTC;
|
||||
}
|
||||
|
||||
public boolean getSynchroniseTimeAgainstServer() {
|
||||
return synchroniseTimeAgainstServer;
|
||||
}
|
||||
|
||||
public void setSynchroniseTimeAgainstServer(boolean synchroniseTimeAgainstServer) {
|
||||
this.synchroniseTimeAgainstServer = synchroniseTimeAgainstServer;
|
||||
}
|
||||
|
||||
public boolean getUseDST() {
|
||||
return useDST;
|
||||
}
|
||||
|
||||
public void setUseDST(boolean useDST) {
|
||||
this.useDST = useDST;
|
||||
}
|
||||
|
||||
public int getGmtOffsetInHours() {
|
||||
return gmtOffsetInHours;
|
||||
}
|
||||
|
||||
public void setGmtOffsetInHours(int gmtOffsetInHours) {
|
||||
this.gmtOffsetInHours = gmtOffsetInHours;
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
public void setServerName(String serverName) {
|
||||
this.serverName = serverName;
|
||||
}
|
||||
|
||||
public int getSyncIntervalInHours() {
|
||||
return syncIntervalInHours;
|
||||
}
|
||||
|
||||
public void setSyncIntervalInHours(int syncIntervalInHours) {
|
||||
this.syncIntervalInHours = syncIntervalInHours;
|
||||
}
|
||||
|
||||
public WSDate getTimeAndDateInUTC() {
|
||||
return timeAndDateInUTC;
|
||||
}
|
||||
|
||||
public void setTimeAndDateInUTC(WSDate timeAndDateInUTC) {
|
||||
this.timeAndDateInUTC = timeAndDateInUTC;
|
||||
}
|
||||
|
||||
public WSTimeManagerSettings parseXMLData(String data) throws IhcExecption {
|
||||
try {
|
||||
String value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:synchroniseTimeAgainstServer");
|
||||
setSynchroniseTimeAgainstServer(Boolean.parseBoolean(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:useDST");
|
||||
setUseDST(Boolean.parseBoolean(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:gmtOffsetInHours");
|
||||
setGmtOffsetInHours(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:serverName");
|
||||
setServerName(value);
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:syncIntervalInHours");
|
||||
setSyncIntervalInHours(Integer.parseInt(value));
|
||||
|
||||
WSDate timeAndDateInUTC = new WSDate();
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:day");
|
||||
timeAndDateInUTC.setDay(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:monthWithJanuaryAsOne");
|
||||
timeAndDateInUTC.setMonthWithJanuaryAsOne(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:hours");
|
||||
timeAndDateInUTC.setHours(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:minutes");
|
||||
timeAndDateInUTC.setMinutes(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:seconds");
|
||||
timeAndDateInUTC.setSeconds(Integer.parseInt(value));
|
||||
|
||||
value = XPathUtils.parseXMLValue(data,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:year");
|
||||
timeAndDateInUTC.setYear(Integer.parseInt(value));
|
||||
|
||||
setTimeAndDateInUTC(timeAndDateInUTC);
|
||||
|
||||
return this;
|
||||
} catch (IOException | XPathExpressionException | NumberFormatException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[ synchroniseTimeAgainstServer=%b, useDST=%b, gmtOffsetInHours=%d, serverName=%s, syncIntervalInHours=%d, timeAndDateInUTC=%s ]",
|
||||
synchroniseTimeAgainstServer, useDST, gmtOffsetInHours, serverName, syncIntervalInHours,
|
||||
timeAndDateInUTC.getAsLocalDateTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
/**
|
||||
* Class for WSUser complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSUser {
|
||||
|
||||
protected WSDate createdDate;
|
||||
protected WSDate loginDate;
|
||||
protected String username;
|
||||
protected String password;
|
||||
protected String email;
|
||||
protected String firstname;
|
||||
protected String lastname;
|
||||
protected String phone;
|
||||
protected WSUserGroup group;
|
||||
protected String project;
|
||||
|
||||
public WSUser() {
|
||||
}
|
||||
|
||||
public WSUser(WSDate createdDate, WSDate loginDate, String username, String password, String email,
|
||||
String firstname, String lastname, String phone, WSUserGroup group, String project) {
|
||||
this.createdDate = createdDate;
|
||||
this.loginDate = loginDate;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.email = email;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.phone = phone;
|
||||
this.group = group;
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the createdDate property.
|
||||
*
|
||||
* @return possible object is {@link WSDate }
|
||||
*
|
||||
*/
|
||||
public WSDate getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the createdDate property.
|
||||
*
|
||||
* @param value allowed object is {@link WSDate }
|
||||
*
|
||||
*/
|
||||
public void setCreatedDate(WSDate value) {
|
||||
this.createdDate = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the loginDate property.
|
||||
*
|
||||
* @return possible object is {@link WSDate }
|
||||
*
|
||||
*/
|
||||
public WSDate getLoginDate() {
|
||||
return loginDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the loginDate property.
|
||||
*
|
||||
* @param value allowed object is {@link WSDate }
|
||||
*
|
||||
*/
|
||||
public void setLoginDate(WSDate value) {
|
||||
this.loginDate = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the username property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the username property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setUsername(String value) {
|
||||
this.username = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the password property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the password property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setPassword(String value) {
|
||||
this.password = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the email property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the email property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setEmail(String value) {
|
||||
this.email = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the firstname property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the firstname property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setFirstname(String value) {
|
||||
this.firstname = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the lastname property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the lastname property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setLastname(String value) {
|
||||
this.lastname = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the phone property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the phone property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setPhone(String value) {
|
||||
this.phone = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the group property.
|
||||
*
|
||||
* @return possible object is {@link WSUserGroup }
|
||||
*
|
||||
*/
|
||||
public WSUserGroup getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the group property.
|
||||
*
|
||||
* @param value allowed object is {@link WSUserGroup }
|
||||
*
|
||||
*/
|
||||
public void setGroup(WSUserGroup value) {
|
||||
this.group = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the project property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the project property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setProject(String value) {
|
||||
this.project = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
/**
|
||||
* Class for WSUserGroup complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSUserGroup {
|
||||
|
||||
protected String type;
|
||||
|
||||
public WSUserGroup() {
|
||||
}
|
||||
|
||||
public WSUserGroup(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the type property.
|
||||
*
|
||||
* @return possible object is {@link String }
|
||||
*
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the type property.
|
||||
*
|
||||
* @param value allowed object is {@link String }
|
||||
*
|
||||
*/
|
||||
public void setType(String value) {
|
||||
this.type = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.datatypes;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/**
|
||||
* Class for XPath utils.
|
||||
*
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class XPathUtils {
|
||||
private static NamespaceContext ihcNamespaceContext = new NamespaceContext() {
|
||||
@Override
|
||||
public String getNamespaceURI(String prefix) {
|
||||
if (prefix == null) {
|
||||
throw new IllegalArgumentException("Prefix argument can't be null");
|
||||
} else if ("SOAP-ENV".equals(prefix)) {
|
||||
return "http://schemas.xmlsoap.org/soap/envelope/";
|
||||
} else if ("ns1".equals(prefix)) {
|
||||
return "utcs";
|
||||
}
|
||||
return "utcs.values";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix(String uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Iterator getPrefixes(String uri) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
public static String parseXMLValue(String xml, String xpathExpression)
|
||||
throws IOException, XPathExpressionException {
|
||||
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8.name()))) {
|
||||
XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
InputSource inputSource = new InputSource(is);
|
||||
|
||||
xpath.setNamespaceContext(ihcNamespaceContext);
|
||||
return (String) xpath.evaluate(xpathExpression, inputSource, XPathConstants.STRING);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean parseValueToBoolean(String xml, String xpathExpression)
|
||||
throws IOException, XPathExpressionException {
|
||||
return Boolean.parseBoolean(parseXMLValue(xml, xpathExpression));
|
||||
}
|
||||
|
||||
public static String createIgnoreNameSpaceSyntaxExpr(String name) {
|
||||
return "*[local-name() = '" + name + "']";
|
||||
}
|
||||
|
||||
public static String getSpeficValueFromNode(Node n, String xpathExpr) throws XPathExpressionException {
|
||||
XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
xpath.setNamespaceContext(ihcNamespaceContext);
|
||||
XPathExpression pathExpr = xpath.compile(xpathExpr);
|
||||
return (String) pathExpr.evaluate(n, XPathConstants.STRING);
|
||||
}
|
||||
|
||||
public static NodeList parseList(String xml, String xpathExpression) throws XPathExpressionException, IOException {
|
||||
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8.name()))) {
|
||||
XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
InputSource inputSource = new InputSource(is);
|
||||
xpath.setNamespaceContext(ihcNamespaceContext);
|
||||
return (NodeList) xpath.evaluate(xpathExpression, inputSource, XPathConstants.NODESET);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getValueFromNode(Node n, String value) throws XPathExpressionException {
|
||||
return getSpeficValueFromNode(n, XPathUtils.createIgnoreNameSpaceSyntaxExpr(value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.exeptions;
|
||||
|
||||
/**
|
||||
* Exception for conversion errors.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ConversionException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
public ConversionException() {
|
||||
}
|
||||
|
||||
public ConversionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ConversionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ConversionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.exeptions;
|
||||
|
||||
/**
|
||||
* Exception for handling communication errors to controller.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcExecption extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -8048415193494625295L;
|
||||
|
||||
public IhcExecption() {
|
||||
}
|
||||
|
||||
public IhcExecption(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public IhcExecption(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public IhcExecption(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.http;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.http.client.CookieStore;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.BasicCookieStore;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Custom HTTP connection pool, which install all-trusting trust manager.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcConnectionPool {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(IhcConnectionPool.class);
|
||||
|
||||
/**
|
||||
* Controller TLS certificate is self signed, which means that certificate
|
||||
* need to be manually added to java key store as a trusted certificate.
|
||||
* This is special SSL context which will be configured to trust all
|
||||
* certificates and manual work is not required.
|
||||
*/
|
||||
private SSLContext sslContext;
|
||||
|
||||
/** Holds and share cookie information (session id) from authentication procedure */
|
||||
private CookieStore cookieStore;
|
||||
|
||||
private HttpClientBuilder httpClientBuilder;
|
||||
private HttpClientContext localContext;
|
||||
|
||||
public IhcConnectionPool() {
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
// Create a local instance of cookie store
|
||||
cookieStore = new BasicCookieStore();
|
||||
|
||||
// Create local HTTP context
|
||||
localContext = HttpClientContext.create();
|
||||
|
||||
// Bind custom cookie store to the local context
|
||||
localContext.setCookieStore(cookieStore);
|
||||
|
||||
httpClientBuilder = HttpClientBuilder.create();
|
||||
|
||||
// Setup a Trust Strategy that allows all certificates.
|
||||
|
||||
logger.debug("Initialize SSL context");
|
||||
|
||||
// Create a trust manager that does not validate certificate chains, but accept all.
|
||||
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) {
|
||||
logger.trace("Trusting server cert: {}", certs[0].getIssuerDN());
|
||||
}
|
||||
} };
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
|
||||
try {
|
||||
// Controller supports only SSLv3 and TLSv1
|
||||
sslContext = SSLContext.getInstance("TLSv1");
|
||||
sslContext.init(null, trustAllCerts, new SecureRandom());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
logger.warn("Exception", e);
|
||||
} catch (KeyManagementException e) {
|
||||
logger.warn("Exception", e);
|
||||
}
|
||||
|
||||
// Controller accepts only HTTPS connections and because normally IP address are used on home network rather
|
||||
// than DNS names, create custom host name verifier.
|
||||
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
|
||||
|
||||
@Override
|
||||
public boolean verify(String arg0, SSLSession arg1) {
|
||||
logger.trace("HostnameVerifier: arg0 = {}, arg1 = {}", arg0, arg1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Create an SSL Socket Factory, to use our weakened "trust strategy"
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
|
||||
new String[] { "TLSv1" }, null, hostnameVerifier);
|
||||
|
||||
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
|
||||
.register("https", sslSocketFactory).build();
|
||||
|
||||
// Create connection-manager using our Registry. Allows multi-threaded use
|
||||
PoolingHttpClientConnectionManager connMngr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
|
||||
|
||||
// Increase max connection counts
|
||||
connMngr.setMaxTotal(20);
|
||||
connMngr.setDefaultMaxPerRoute(6);
|
||||
|
||||
httpClientBuilder.setConnectionManager(connMngr);
|
||||
}
|
||||
|
||||
public HttpClient getHttpClient() {
|
||||
return httpClientBuilder.build();
|
||||
}
|
||||
|
||||
public HttpClientContext getHttpContext() {
|
||||
return localContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NoHttpResponseException;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Simple HTTP Client for IHC / ELKO LS Controller connection purposes.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public abstract class IhcHttpsClient {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(IhcHttpsClient.class);
|
||||
|
||||
private IhcConnectionPool ihcConnectionPool;
|
||||
private HttpClient client;
|
||||
private HttpPost postReq;
|
||||
private AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
public IhcHttpsClient(IhcConnectionPool ihcConnectionPool) {
|
||||
this.ihcConnectionPool = ihcConnectionPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init HTTP connection.
|
||||
*
|
||||
* @param url Url to connect.
|
||||
*/
|
||||
private void initConnection(String url) throws IhcExecption {
|
||||
if (client == null) {
|
||||
client = ihcConnectionPool.getHttpClient();
|
||||
}
|
||||
postReq = new HttpPost(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send HTTP request and wait response from the server.
|
||||
*
|
||||
*/
|
||||
public String sendQuery(String url, Map<String, String> requestProperties, String query, int timeout)
|
||||
throws IhcExecption {
|
||||
initConnection(url);
|
||||
setRequestProperty(requestProperties);
|
||||
try {
|
||||
return sendQ(query, timeout);
|
||||
} catch (NoHttpResponseException | SocketTimeoutException e) {
|
||||
try {
|
||||
logger.debug("No response received, resend query");
|
||||
return sendQ(query, timeout);
|
||||
} catch (IOException ee) {
|
||||
throw new IhcExecption(ee);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IhcExecption(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String sendQ(String query, int timeout)
|
||||
throws ClientProtocolException, IOException, NoHttpResponseException {
|
||||
postReq.setEntity(new StringEntity(query, StandardCharsets.UTF_8.name()));
|
||||
postReq.addHeader("content-type", "text/xml");
|
||||
|
||||
int requestId = 0;
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
requestId = counter.getAndIncrement();
|
||||
logger.trace("Send query (url={}, connectionPool={}, clientId={} requestId={}, timeout={}, headers={}): {}",
|
||||
postReq.getURI(), ihcConnectionPool.hashCode(), client.hashCode(), requestId, timeout,
|
||||
postReq.getAllHeaders(), query);
|
||||
}
|
||||
|
||||
final RequestConfig params = RequestConfig.custom().setConnectTimeout(timeout)
|
||||
.setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();
|
||||
postReq.setConfig(params);
|
||||
|
||||
// Execute POST
|
||||
LocalDateTime start = LocalDateTime.now();
|
||||
try {
|
||||
HttpResponse response = client.execute(postReq, ihcConnectionPool.getHttpContext());
|
||||
String resp = EntityUtils.toString(response.getEntity());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Received response (connectionPool={}, clientId={} requestId={}, in {}, headers={}): {}",
|
||||
ihcConnectionPool.hashCode(), client.hashCode(), requestId,
|
||||
Duration.between(start, LocalDateTime.now()), response.getAllHeaders(), resp);
|
||||
}
|
||||
return resp;
|
||||
} catch (Exception e) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Exception occured (connectionPool={}, clientId={} requestId={}, in {}): {}",
|
||||
ihcConnectionPool.hashCode(), client.hashCode(), requestId,
|
||||
Duration.between(start, LocalDateTime.now()), e.getMessage());
|
||||
}
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set request properties.
|
||||
*
|
||||
*/
|
||||
private void setRequestProperty(Map<String, String> requestProperties) {
|
||||
if (postReq != null && requestProperties != null) {
|
||||
requestProperties.forEach((k, v) -> postReq.setHeader(k, v));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.projectfile;
|
||||
|
||||
/**
|
||||
* Class to store IHC / ELKO LS controller's enum value information.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcEnumValue {
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
public IhcEnumValue(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[ id=%d, name='%s' ]", id, name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.projectfile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Generic methods related to IHC / ELKO project file handling.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ProjectFileUtils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ProjectFileUtils.class);
|
||||
|
||||
/**
|
||||
* Read IHC project file from local file.
|
||||
*
|
||||
* @param filePath File to read.
|
||||
* @return XML document.
|
||||
* @throws IhcExecption when file read fails.
|
||||
*/
|
||||
public static Document readFromFile(String filePath) throws IhcExecption {
|
||||
File fXmlFile = new File(filePath);
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.parse(fXmlFile);
|
||||
return doc;
|
||||
} catch (IOException | ParserConfigurationException | SAXException e) {
|
||||
throw new IhcExecption(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save IHC project file to local file.
|
||||
*
|
||||
* @param filePath File path.
|
||||
* @param data Data to write
|
||||
* @throws IhcExecption when file write fails.
|
||||
*/
|
||||
public static void saveToFile(String filePath, byte[] data) throws IhcExecption {
|
||||
try {
|
||||
FileUtils.writeByteArrayToFile(new File(filePath), data);
|
||||
} catch (IOException e) {
|
||||
throw new IhcExecption(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert bytes to XML document.
|
||||
*
|
||||
* @return XML document or null if conversion fails.
|
||||
*/
|
||||
public static Document converteBytesToDocument(byte[] data) {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
try {
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
return builder.parse(new ByteArrayInputStream(data));
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
LOGGER.warn("Error occured when trying to convert data to XML, reason {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare XML document header information to project info.
|
||||
*
|
||||
* @return true if information is equal and false if not.
|
||||
*/
|
||||
public static boolean projectEqualsToControllerProject(Document projectfile, WSProjectInfo projectInfo) {
|
||||
if (projectInfo != null) {
|
||||
try {
|
||||
NodeList nodes = projectfile.getElementsByTagName("modified");
|
||||
if (nodes.getLength() == 1) {
|
||||
Element node = (Element) nodes.item(0);
|
||||
int year = Integer.parseInt(node.getAttribute("year"));
|
||||
int month = Integer.parseInt(node.getAttribute("month"));
|
||||
int day = Integer.parseInt(node.getAttribute("day"));
|
||||
int hour = Integer.parseInt(node.getAttribute("hour"));
|
||||
int minute = Integer.parseInt(node.getAttribute("minute"));
|
||||
|
||||
LOGGER.debug("Project file from file, date: {}.{}.{} {}:{}", year, month, day, hour, minute);
|
||||
LOGGER.debug("Project file in controller, date: {}.{}.{} {}:{}",
|
||||
projectInfo.getLastmodified().getYear(),
|
||||
projectInfo.getLastmodified().getMonthWithJanuaryAsOne(),
|
||||
projectInfo.getLastmodified().getDay(), projectInfo.getLastmodified().getHours(),
|
||||
projectInfo.getLastmodified().getMinutes());
|
||||
|
||||
if (projectInfo.getLastmodified().getYear() == year
|
||||
&& projectInfo.getLastmodified().getMonthWithJanuaryAsOne() == month
|
||||
&& projectInfo.getLastmodified().getDay() == day
|
||||
&& projectInfo.getLastmodified().getHours() == hour
|
||||
&& projectInfo.getLastmodified().getMinutes() == minute) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.debug("Error occured during project file date comparasion, reason {}.", e.getMessage(), e);
|
||||
// There is no documentation available for XML content. This is part of inessential feature, so do
|
||||
// nothing, but return false
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all enum values from IHC project file.
|
||||
*
|
||||
* @param doc IHC project file in XML format.
|
||||
* @return enum dictionary.
|
||||
*/
|
||||
public static Map<Integer, List<IhcEnumValue>> parseEnums(Document doc) {
|
||||
Map<Integer, List<IhcEnumValue>> enumDictionary = new HashMap<>();
|
||||
if (doc != null) {
|
||||
NodeList nodes = doc.getElementsByTagName("enum_definition");
|
||||
|
||||
// iterate enum definitions from project
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element element = (Element) nodes.item(i);
|
||||
|
||||
int typedefId = Integer.parseInt(element.getAttribute("id").replace("_0x", ""), 16);
|
||||
String enumName = element.getAttribute("name");
|
||||
|
||||
List<IhcEnumValue> enumValues = new ArrayList<>();
|
||||
|
||||
NodeList name = element.getElementsByTagName("enum_value");
|
||||
|
||||
for (int j = 0; j < name.getLength(); j++) {
|
||||
Element val = (Element) name.item(j);
|
||||
int id = Integer.parseInt(val.getAttribute("id").replace("_0x", ""), 16);
|
||||
String n = val.getAttribute("name");
|
||||
IhcEnumValue enumVal = new IhcEnumValue(id, n);
|
||||
enumValues.add(enumVal);
|
||||
}
|
||||
|
||||
LOGGER.debug("Enum values found: typedefId={}, name={}: {}", typedefId, enumName, enumValues);
|
||||
enumDictionary.put(typedefId, enumValues);
|
||||
}
|
||||
}
|
||||
return enumDictionary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSBooleanValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSBooleanValue extends WSResourceValue {
|
||||
|
||||
public final boolean value;
|
||||
|
||||
public WSBooleanValue(int resourceID, boolean value) {
|
||||
super(resourceID);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, value=%b]", super.resourceID, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSDateValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSDateValue extends WSResourceValue {
|
||||
|
||||
public final short year;
|
||||
public final byte month;
|
||||
public final byte day;
|
||||
|
||||
public WSDateValue(int resourceID, short year, byte month, byte day) {
|
||||
super(resourceID);
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, year=%d, month=%d, day=%d]", super.resourceID, year, month, day);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSEnumValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSEnumValue extends WSResourceValue {
|
||||
|
||||
public final int definitionTypeID;
|
||||
public final int enumValueID;
|
||||
public final String enumName;
|
||||
|
||||
public WSEnumValue(int resourceID, int definitionTypeID, int enumValueID, String enumName) {
|
||||
super(resourceID);
|
||||
this.definitionTypeID = definitionTypeID;
|
||||
this.enumValueID = enumValueID;
|
||||
this.enumName = enumName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, definitionTypeID=%d, enumValueID=%d, enumName=%s]", super.resourceID,
|
||||
definitionTypeID, enumValueID, enumName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSFloatingPointValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSFloatingPointValue extends WSResourceValue {
|
||||
|
||||
public final double maximumValue;
|
||||
public final double minimumValue;
|
||||
public final double value;
|
||||
|
||||
public WSFloatingPointValue(int resourceID, double value, double minimumValue, double maximumValue) {
|
||||
super(resourceID);
|
||||
this.value = value;
|
||||
this.minimumValue = minimumValue;
|
||||
this.maximumValue = maximumValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, value=%.2f, min=%.2f, max=%.2f]", super.resourceID, value, minimumValue,
|
||||
maximumValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSIntegerValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSIntegerValue extends WSResourceValue {
|
||||
|
||||
public final int value;
|
||||
public final int maximumValue;
|
||||
public final int minimumValue;
|
||||
|
||||
public WSIntegerValue(int resourceID, int value, int minimumValue, int maximumValue) {
|
||||
super(resourceID);
|
||||
this.value = value;
|
||||
this.minimumValue = minimumValue;
|
||||
this.maximumValue = maximumValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, value=%d, min=%d, max=%d]", super.resourceID, value, minimumValue,
|
||||
maximumValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSPhoneNumberValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSPhoneNumberValue extends WSResourceValue {
|
||||
|
||||
public final String number;
|
||||
|
||||
public WSPhoneNumberValue(int resourceID, String number) {
|
||||
super(resourceID);
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, number=%s]", super.resourceID, number);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSResourceValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSResourceValue {
|
||||
|
||||
public final int resourceID;
|
||||
|
||||
public WSResourceValue(int resourceID) {
|
||||
this.resourceID = resourceID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d]", resourceID);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSSceneDimmerValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSSceneDimmerValue extends WSResourceValue {
|
||||
|
||||
public final int delayTime;
|
||||
public final int dimmerPercentage;
|
||||
public final int rampTime;
|
||||
|
||||
public WSSceneDimmerValue(int resourceID, int delayTime, int dimmerPercentage, int rampTime) {
|
||||
super(resourceID);
|
||||
this.delayTime = delayTime;
|
||||
this.dimmerPercentage = dimmerPercentage;
|
||||
this.rampTime = rampTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, delayTime=%d, dimmerPercentage=%d, rampTime=%d]", super.resourceID,
|
||||
delayTime, dimmerPercentage, rampTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSSceneRelayValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSSceneRelayValue extends WSResourceValue {
|
||||
|
||||
public final int delayTime;
|
||||
public final boolean relayValue;
|
||||
|
||||
public WSSceneRelayValue(int resourceID, int delayTime, boolean relayValue) {
|
||||
super(resourceID);
|
||||
this.delayTime = delayTime;
|
||||
this.relayValue = relayValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, value=%b, delayTime=%d]", super.resourceID, relayValue, delayTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSSceneShutterSimpleValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSSceneShutterSimpleValue extends WSResourceValue {
|
||||
|
||||
public final int delayTime;
|
||||
public final boolean shutterPositionIsUp;
|
||||
|
||||
public WSSceneShutterSimpleValue(int resourceID, int delayTime, boolean shutterPositionIsUp) {
|
||||
super(resourceID);
|
||||
this.delayTime = delayTime;
|
||||
this.shutterPositionIsUp = shutterPositionIsUp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, shutterPositionIsUp=%b, delayTime=%d]", super.resourceID,
|
||||
shutterPositionIsUp, delayTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSTimeValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSTimeValue extends WSResourceValue {
|
||||
|
||||
public final int hours;
|
||||
public final int minutes;
|
||||
public final int seconds;
|
||||
|
||||
public WSTimeValue(int resourceID, int hours, int minutes, int seconds) {
|
||||
super(resourceID);
|
||||
this.hours = hours;
|
||||
this.minutes = minutes;
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, hours=%d, minutes=%d, seconds=%d]", super.resourceID, hours, minutes,
|
||||
seconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSTimerValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSTimerValue extends WSResourceValue {
|
||||
|
||||
public final long milliseconds;
|
||||
|
||||
public WSTimerValue(int resourceID, long milliseconds) {
|
||||
super(resourceID);
|
||||
this.milliseconds = milliseconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, milliseconds=%b]", super.resourceID, milliseconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.resourcevalues;
|
||||
|
||||
/**
|
||||
* Class for WSWeekdayValue complex type.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class WSWeekdayValue extends WSResourceValue {
|
||||
|
||||
public final int weekdayNumber;
|
||||
|
||||
public WSWeekdayValue(int resourceID, int weekdayNumber) {
|
||||
super(resourceID);
|
||||
this.weekdayNumber = weekdayNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[resourceId=%d, weekdayNumber=%d]", super.resourceID, weekdayNumber);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.XPathUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Class to handle IHC / ELKO LS Controller's airlink management service.
|
||||
*
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcAirlinkManagementService extends IhcBaseService {
|
||||
|
||||
public IhcAirlinkManagementService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
|
||||
super(ihcConnectionPool, timeout, host, "AirlinkManagementService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query system information from the controller.
|
||||
*
|
||||
* @return system information.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized List<WSRFDevice> getDetectedDeviceList() throws IhcExecption {
|
||||
String response = sendSoapQuery("getDetectedDeviceList", EMPTY_QUERY);
|
||||
|
||||
List<WSRFDevice> resourceValueList = new ArrayList<>();
|
||||
|
||||
try {
|
||||
NodeList nodeList = XPathUtils.parseList(response,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getDetectedDeviceList1/ns1:arrayItem");
|
||||
|
||||
if (nodeList != null) {
|
||||
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
Node node = nodeList.item(i);
|
||||
if (node != null) {
|
||||
WSRFDevice dev = parseResourceValue(node);
|
||||
if (dev != null) {
|
||||
resourceValueList.add(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IhcExecption("Illegal resource value notification response received");
|
||||
}
|
||||
return resourceValueList;
|
||||
} catch (IOException | XPathExpressionException | NumberFormatException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
|
||||
private WSRFDevice parseResourceValue(Node n) throws XPathExpressionException, NumberFormatException {
|
||||
try {
|
||||
int batteryLevel = Integer.parseInt(XPathUtils.getValueFromNode(n, "batteryLevel"));
|
||||
int deviceType = Integer.parseInt(XPathUtils.getValueFromNode(n, "deviceType"));
|
||||
long serialNumber = Long.parseLong(XPathUtils.getValueFromNode(n, "serialNumber"));
|
||||
int signalStrength = Integer.parseInt(XPathUtils.getValueFromNode(n, "signalStrength"));
|
||||
int version = Integer.parseInt(XPathUtils.getValueFromNode(n, "version"));
|
||||
boolean detected = Boolean.valueOf(XPathUtils.getValueFromNode(n, "detected"));
|
||||
return new WSRFDevice(batteryLevel, deviceType, serialNumber, signalStrength, version, detected);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSLoginResult;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class to handle IHC / ELKO LS Controller's authentication service.
|
||||
*
|
||||
* Communication to controller need to be authenticated. On successful
|
||||
* authentication Controller returns session id which need to be used further
|
||||
* communication.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcAuthenticationService extends IhcBaseService {
|
||||
private final Logger logger = LoggerFactory.getLogger(IhcAuthenticationService.class);
|
||||
|
||||
public IhcAuthenticationService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
|
||||
super(ihcConnectionPool, timeout, host, "AuthenticationService");
|
||||
}
|
||||
|
||||
public WSLoginResult authenticate(String username, String password, String application) throws IhcExecption {
|
||||
logger.debug("Authenticate");
|
||||
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
|
||||
+ " <soapenv:Body>\n"
|
||||
+ " <authenticate1 xmlns=\"utcs\">\n"
|
||||
+ " <password>%s</password>\n"
|
||||
+ " <username>%s</username>\n"
|
||||
+ " <application>%s</application>\n"
|
||||
+ " </authenticate1>\n"
|
||||
+ " </soapenv:Body>\n"
|
||||
+ "</soapenv:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, password, username, application);
|
||||
String response = sendSoapQuery(null, query);
|
||||
return new WSLoginResult().parseXMLData(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcHttpsClient;
|
||||
|
||||
/**
|
||||
* Base class for all IHC / ELKO services.
|
||||
*
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public abstract class IhcBaseService extends IhcHttpsClient {
|
||||
|
||||
// @formatter:off
|
||||
protected static final String EMPTY_QUERY =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soapenv:Body>\n"
|
||||
+ " </soapenv:Body>\n"
|
||||
+ "</soapenv:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
private String url;
|
||||
private int timeout;
|
||||
|
||||
public IhcBaseService(IhcConnectionPool ihcConnectionPool, int timeout, String host, String service) {
|
||||
super(ihcConnectionPool);
|
||||
this.timeout = timeout;
|
||||
this.url = createUrl(host, service);
|
||||
}
|
||||
|
||||
private String createUrl(String host, String service) {
|
||||
return "https://" + host + "/ws/" + service;
|
||||
}
|
||||
|
||||
protected String sendSoapQuery(String soapAction, String query) throws IhcExecption {
|
||||
return sendSoapQuery(soapAction, query, timeout);
|
||||
}
|
||||
|
||||
protected String sendSoapQuery(String soapAction, String query, int timeout) throws IhcExecption {
|
||||
Map<String, String> reqProperties = null;
|
||||
if (soapAction != null) {
|
||||
reqProperties = new HashMap<>();
|
||||
reqProperties.put("SOAPAction", soapAction);
|
||||
}
|
||||
return sendQuery(url, reqProperties, query, timeout);
|
||||
}
|
||||
|
||||
protected int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Class to handle IHC / ELKO LS Controller's configuration service.
|
||||
*
|
||||
* Controller service is used to fetch system information from the controller.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcConfigurationService extends IhcBaseService {
|
||||
|
||||
public IhcConfigurationService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
|
||||
super(ihcConnectionPool, timeout, host, "ConfigurationService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query system information from the controller.
|
||||
*
|
||||
* @return system information.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSSystemInfo getSystemInfo() throws IhcExecption {
|
||||
String response = sendSoapQuery("getSystemInfo", EMPTY_QUERY);
|
||||
return new WSSystemInfo().parseXMLData(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSNumberOfSegments;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSSegmentationSize;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Class to handle IHC / ELKO LS Controller's controller service.
|
||||
*
|
||||
* Controller service is used to fetch information from the controller.
|
||||
* E.g. Project file or controller status.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcControllerService extends IhcBaseService {
|
||||
|
||||
public IhcControllerService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
|
||||
super(ihcConnectionPool, timeout, host, "ControllerService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query project information from the controller.
|
||||
*
|
||||
* @return project information.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSProjectInfo getProjectInfo() throws IhcExecption {
|
||||
String response = sendSoapQuery("getProjectInfo", EMPTY_QUERY);
|
||||
return new WSProjectInfo().parseXMLData(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query number of segments project contains.
|
||||
*
|
||||
* @return number of segments.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized int getProjectNumberOfSegments() throws IhcExecption {
|
||||
String response = sendSoapQuery("getIHCProjectNumberOfSegments", EMPTY_QUERY);
|
||||
return new WSNumberOfSegments().parseXMLData(response).getNumberOfSegments();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query segmentation size.
|
||||
*
|
||||
* @return segmentation size in bytes.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized int getProjectSegmentationSize() throws IhcExecption {
|
||||
String response = sendSoapQuery("getIHCProjectSegmentationSize", EMPTY_QUERY);
|
||||
return new WSSegmentationSize().parseXMLData(response).getSegmentationSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query project segment data.
|
||||
*
|
||||
* @param index segments index.
|
||||
* @param major project major revision number.
|
||||
* @param minor project minor revision number.
|
||||
* @return segments data.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSFile getProjectSegment(int index, int major, int minor) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <ns1:getIHCProjectSegment1 xmlns:ns1=\"utcs\" xsi:type=\"xsd:int\">%s</ns1:getIHCProjectSegment1>\n"
|
||||
+ " <ns2:getIHCProjectSegment2 xmlns:ns2=\"utcs\" xsi:type=\"xsd:int\">%s</ns2:getIHCProjectSegment2>\n"
|
||||
+ " <ns3:getIHCProjectSegment3 xmlns:ns3=\"utcs\" xsi:type=\"xsd:int\">%s</ns3:getIHCProjectSegment3>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, index, major, minor);
|
||||
String response = sendSoapQuery("getIHCProjectSegment", query);
|
||||
return new WSFile().parseXMLData(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query controller current state.
|
||||
*
|
||||
* @return controller's current state.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSControllerState getControllerState() throws IhcExecption {
|
||||
String response = sendSoapQuery("getState", EMPTY_QUERY);
|
||||
return new WSControllerState().parseXMLData(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait controller state change notification.
|
||||
*
|
||||
* @param previousState Previous controller state.
|
||||
* @param timeoutInSeconds How many seconds to wait notifications.
|
||||
* @return current controller state.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSControllerState waitStateChangeNotifications(WSControllerState previousState,
|
||||
int timeoutInSeconds) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soapenv:Body>\n"
|
||||
+ " <ns1:waitForControllerStateChange1 xmlns:ns1=\"utcs\" xsi:type=\"ns1:WSControllerState\">\n"
|
||||
+ " <ns1:state xsi:type=\"xsd:string\">%s</ns1:state>\n"
|
||||
+ " </ns1:waitForControllerStateChange1>\n"
|
||||
+ " <ns2:waitForControllerStateChange2 xmlns:ns2=\"utcs\" xsi:type=\"xsd:int\">%s</ns2:waitForControllerStateChange2>\n"
|
||||
+ " </soapenv:Body>\n"
|
||||
+ "</soapenv:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, previousState.getState(), timeoutInSeconds);
|
||||
String response = sendSoapQuery("waitForControllerStateChange", query, getTimeout() + timeoutInSeconds * 1000);
|
||||
return new WSControllerState().parseXMLData(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,470 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.XPathUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Class to handle IHC / ELKO LS Controller's resource interaction service.
|
||||
*
|
||||
* Service is used to fetch or update resource values from/to controller.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcResourceInteractionService extends IhcBaseService {
|
||||
|
||||
public IhcResourceInteractionService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
|
||||
super(ihcConnectionPool, timeout, host, "ResourceInteractionService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query resource value from controller.
|
||||
*
|
||||
* @param resoureId Resource Identifier.
|
||||
* @return Resource value.
|
||||
*/
|
||||
public WSResourceValue resourceQuery(int resoureId) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soapenv:Body>\n"
|
||||
+ " <ns1:getRuntimeValue1 xmlns:ns1=\"utcs\">%s</ns1:getRuntimeValue1>\n"
|
||||
+ " </soapenv:Body>\n"
|
||||
+ "</soapenv:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, String.valueOf(resoureId));
|
||||
String response = sendSoapQuery(null, query);
|
||||
NodeList nodeList;
|
||||
try {
|
||||
nodeList = XPathUtils.parseList(response, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getRuntimeValue2");
|
||||
|
||||
if (nodeList != null && nodeList.getLength() == 1) {
|
||||
WSResourceValue val = parseResourceValue(nodeList.item(0));
|
||||
|
||||
if (val != null && val.resourceID == resoureId) {
|
||||
return val;
|
||||
} else {
|
||||
throw new IhcExecption("No resource id found");
|
||||
}
|
||||
} else {
|
||||
throw new IhcExecption("No resource value found");
|
||||
}
|
||||
} catch (XPathExpressionException | NumberFormatException | IOException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
|
||||
private WSResourceValue parseResourceValue(Node n) throws XPathExpressionException, NumberFormatException {
|
||||
// parse resource id
|
||||
String resourceId = XPathUtils.getSpeficValueFromNode(n, "ns1:resourceID");
|
||||
|
||||
if (StringUtils.isNotBlank(resourceId)) {
|
||||
int id = Integer.parseInt(resourceId);
|
||||
|
||||
// Parse floating point value
|
||||
String floatingPointValue = getValue(n, "floatingPointValue");
|
||||
if (StringUtils.isNotBlank(floatingPointValue)) {
|
||||
String min = getValue(n, "minimumValue");
|
||||
String max = getValue(n, "maximumValue");
|
||||
return new WSFloatingPointValue(id, Double.valueOf(floatingPointValue), Double.valueOf(min),
|
||||
Double.valueOf(max));
|
||||
}
|
||||
|
||||
// Parse boolean value
|
||||
String value = getValue(n, "value");
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
return new WSBooleanValue(id, Boolean.valueOf(value));
|
||||
}
|
||||
|
||||
// Parse integer value
|
||||
String integer = getValue(n, "integer");
|
||||
if (StringUtils.isNotBlank(integer)) {
|
||||
String min = getValue(n, "minimumValue");
|
||||
String max = getValue(n, "maximumValue");
|
||||
return new WSIntegerValue(id, Integer.valueOf(integer), Integer.valueOf(min), Integer.valueOf(max));
|
||||
}
|
||||
|
||||
// Parse timer value
|
||||
String milliseconds = getValue(n, "milliseconds");
|
||||
if (StringUtils.isNotBlank(milliseconds)) {
|
||||
return new WSTimerValue(id, Integer.valueOf(milliseconds));
|
||||
}
|
||||
|
||||
// Parse time value
|
||||
String hours = getValue(n, "hours");
|
||||
if (StringUtils.isNotBlank(hours)) {
|
||||
String minutes = getValue(n, "minutes");
|
||||
String seconds = getValue(n, "seconds");
|
||||
return new WSTimeValue(id, Integer.valueOf(hours), Integer.valueOf(minutes), Integer.valueOf(seconds));
|
||||
}
|
||||
|
||||
// Parse date value
|
||||
String year = getValue(n, "year");
|
||||
if (StringUtils.isNotBlank(year)) {
|
||||
String month = getValue(n, "month");
|
||||
String day = getValue(n, "day");
|
||||
return new WSDateValue(id, Short.valueOf(year), Byte.valueOf(month), Byte.valueOf(day));
|
||||
}
|
||||
|
||||
// Parse enum value
|
||||
String definitionTypeID = getValue(n, "definitionTypeID");
|
||||
if (StringUtils.isNotBlank(definitionTypeID)) {
|
||||
String enumValueID = getValue(n, "enumValueID");
|
||||
String enumName = getValue(n, "enumName");
|
||||
return new WSEnumValue(id, Integer.valueOf(definitionTypeID), Integer.valueOf(enumValueID), enumName);
|
||||
}
|
||||
|
||||
// Parse week day value
|
||||
value = getValue(n, "weekdayNumber");
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
return new WSWeekdayValue(id, Integer.valueOf(value));
|
||||
}
|
||||
|
||||
// Unknown value type
|
||||
throw new IllegalArgumentException("Unsupported value type");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getValue(Node n, String value) throws XPathExpressionException {
|
||||
return XPathUtils.getSpeficValueFromNode(n, "ns1:value/" + XPathUtils.createIgnoreNameSpaceSyntaxExpr(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update resource value to controller.
|
||||
*
|
||||
*
|
||||
* @param value Resource value.
|
||||
* @return True if value is successfully updated.
|
||||
*/
|
||||
public boolean resourceUpdate(WSResourceValue value) throws IhcExecption {
|
||||
boolean retval = false;
|
||||
|
||||
if (value instanceof WSFloatingPointValue) {
|
||||
retval = resourceUpdate((WSFloatingPointValue) value);
|
||||
} else if (value instanceof WSBooleanValue) {
|
||||
retval = resourceUpdate((WSBooleanValue) value);
|
||||
} else if (value instanceof WSIntegerValue) {
|
||||
retval = resourceUpdate((WSIntegerValue) value);
|
||||
} else if (value instanceof WSTimerValue) {
|
||||
retval = resourceUpdate((WSTimerValue) value);
|
||||
} else if (value instanceof WSWeekdayValue) {
|
||||
retval = resourceUpdate((WSWeekdayValue) value);
|
||||
} else if (value instanceof WSEnumValue) {
|
||||
retval = resourceUpdate((WSEnumValue) value);
|
||||
} else if (value instanceof WSTimeValue) {
|
||||
retval = resourceUpdate((WSTimeValue) value);
|
||||
} else if (value instanceof WSDateValue) {
|
||||
retval = resourceUpdate((WSDateValue) value);
|
||||
} else {
|
||||
throw new IhcExecption("Unsupported value type " + value.getClass().toString());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSBooleanValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSBooleanValue\">\n"
|
||||
+ " <q1:value>%s</q1:value>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.value ? "true" : "false", value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSFloatingPointValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSFloatingPointValue\">\n"
|
||||
+ " <q1:maximumValue>%s</q1:maximumValue>\n"
|
||||
+ " <q1:minimumValue>%s</q1:minimumValue>\n"
|
||||
+ " <q1:floatingPointValue>%s</q1:floatingPointValue>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.maximumValue, value.minimumValue, value.value, value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSIntegerValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSIntegerValue\">\n"
|
||||
+ " <q1:maximumValue>%s</q1:maximumValue>\n"
|
||||
+ " <q1:minimumValue>%s</q1:minimumValue>\n"
|
||||
+ " <q1:integer>%s</q1:integer>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.maximumValue, value.minimumValue, value.value, value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSTimerValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSTimerValue\">\n"
|
||||
+ " <q1:milliseconds>%s</q1:milliseconds>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.milliseconds, value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSWeekdayValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSWeekdayValue\">\n"
|
||||
+ " <q1:weekdayNumber>%s</q1:weekdayNumber>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.weekdayNumber, value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSEnumValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSEnumValue\">\n"
|
||||
+ " <q1:definitionTypeID>%s</q1:definitionTypeID>\n"
|
||||
+ " <q1:enumValueID>%s</q1:enumValueID>\n"
|
||||
+ " <q1:enumName>%s</q1:enumName>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.definitionTypeID, value.enumValueID, value.enumName,
|
||||
value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSTimeValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSTimeValue\">\n"
|
||||
+ " <q1:hours>%s</q1:hours>\n"
|
||||
+ " <q1:minutes>%s</q1:minutes>\n"
|
||||
+ " <q1:seconds>%s</q1:seconds>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.hours, value.minutes, value.seconds, value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
public boolean resourceUpdate(WSDateValue value) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <setResourceValue1 xmlns=\"utcs\">\n"
|
||||
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSDateValue\">\n"
|
||||
+ " <q1:month>%s</q1:month>\n"
|
||||
+ " <q1:year>%s</q1:year>\n"
|
||||
+ " <q1:day>%s</q1:day>\n"
|
||||
+ " </value>\n"
|
||||
+ " <resourceID>%s</resourceID>\n"
|
||||
+ " <isValueRuntime>true</isValueRuntime>\n"
|
||||
+ " </setResourceValue1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, value.month, value.year, value.day, value.resourceID);
|
||||
return doResourceUpdate(query);
|
||||
}
|
||||
|
||||
private boolean doResourceUpdate(String query) throws IhcExecption {
|
||||
String response = sendSoapQuery(null, query);
|
||||
try {
|
||||
return Boolean.parseBoolean(
|
||||
XPathUtils.parseXMLValue(response, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:setResourceValue2"));
|
||||
} catch (IOException | XPathExpressionException e) {
|
||||
throw new IhcExecption(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable resources runtime value notifications.
|
||||
*
|
||||
* @param resourceIdList List of resource Identifiers.
|
||||
* @return True is connection successfully opened.
|
||||
*/
|
||||
public void enableRuntimeValueNotifications(Set<Integer> resourceIdList) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQueryPrefix =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
|
||||
+ " <soap:Body>\n"
|
||||
+ " <enableRuntimeValueNotifications1 xmlns=\"utcs\">\n";
|
||||
|
||||
final String soapQuerySuffix =
|
||||
" </enableRuntimeValueNotifications1>\n"
|
||||
+ " </soap:Body>\n"
|
||||
+ "</soap:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = soapQueryPrefix;
|
||||
for (int i : resourceIdList) {
|
||||
query += " <xsd:arrayItem>" + i + "</xsd:arrayItem>\n";
|
||||
}
|
||||
query += soapQuerySuffix;
|
||||
sendSoapQuery(null, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait runtime value notifications.
|
||||
*
|
||||
* Runtime value notification should firstly be activated by
|
||||
* enableRuntimeValueNotifications function.
|
||||
*
|
||||
* @param timeoutInSeconds How many seconds to wait notifications.
|
||||
* @return List of received runtime value notifications.
|
||||
* @throws SocketTimeoutException
|
||||
* @throws IhcTimeoutExecption
|
||||
*/
|
||||
public List<WSResourceValue> waitResourceValueNotifications(int timeoutInSeconds) throws IhcExecption {
|
||||
// @formatter:off
|
||||
final String soapQuery =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:utcs=\"utcs\">\n"
|
||||
+ " <soapenv:Body>\n"
|
||||
+ " <utcs:waitForResourceValueChanges1>%s</utcs:waitForResourceValueChanges1>\n"
|
||||
+ " </soapenv:Body>\n"
|
||||
+ "</soapenv:Envelope>";
|
||||
// @formatter:on
|
||||
|
||||
String query = String.format(soapQuery, timeoutInSeconds);
|
||||
String response = sendSoapQuery(null, query, getTimeout() + timeoutInSeconds * 1000);
|
||||
List<WSResourceValue> resourceValueList = new ArrayList<>();
|
||||
|
||||
try {
|
||||
NodeList nodeList = XPathUtils.parseList(response,
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:waitForResourceValueChanges2/ns1:arrayItem");
|
||||
|
||||
if (nodeList != null) {
|
||||
if (nodeList.getLength() == 1) {
|
||||
String resourceId = XPathUtils.getSpeficValueFromNode(nodeList.item(0), "ns1:resourceID");
|
||||
if (resourceId == null || resourceId.isEmpty()) {
|
||||
// IHC controller indicates timeout, return empty list
|
||||
return resourceValueList;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
WSResourceValue newVal = parseResourceValue(nodeList.item(i));
|
||||
if (newVal != null) {
|
||||
resourceValueList.add(newVal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IhcExecption("Illegal resource value notification response received");
|
||||
}
|
||||
return resourceValueList;
|
||||
} catch (XPathExpressionException | NumberFormatException | IOException e) {
|
||||
throw new IhcExecption("Error occured during XML data parsing", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSTimeManagerSettings;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Class to handle IHC / ELKO LS Controller's time service.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcTimeService extends IhcBaseService {
|
||||
|
||||
public IhcTimeService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
|
||||
super(ihcConnectionPool, timeout, host, "TimeManagerService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query time settings from the controller.
|
||||
*
|
||||
* @return time settings.
|
||||
* @throws IhcExecption
|
||||
*/
|
||||
public synchronized WSTimeManagerSettings getTimeSettings() throws IhcExecption {
|
||||
String response = sendSoapQuery("getSettings", EMPTY_QUERY);
|
||||
return new WSTimeManagerSettings().parseXMLData(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="ihc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>IHC / ELKO Binding</name>
|
||||
<description>Binding to communicate IHC / ELKO controller</description>
|
||||
<author>Pauli Anttila</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="ihc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
<channel-type id="controller-state" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Controller State</label>
|
||||
<description>Displays IHC / ELKO controller state</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="controller-uptime" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Controller Uptime</label>
|
||||
<description>Displays IHC / ELKO controller uptime in seconds</description>
|
||||
<state readOnly="true" pattern="%.3f sec"></state>
|
||||
</channel-type>
|
||||
<channel-type id="controller-time" advanced="true">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Controller Date and Time</label>
|
||||
<description>Displays IHC / ELKO controller date and time</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="switch">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Generic Switch</label>
|
||||
<description>Generic switch channel</description>
|
||||
<state readOnly="false"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="direction" type="text" required="false">
|
||||
<label>Channel Direction</label>
|
||||
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
|
||||
<default>ReadWrite</default>
|
||||
<options>
|
||||
<option value="ReadWrite">Read Write</option>
|
||||
<option value="WriteOnly">Write only</option>
|
||||
<option value="ReadOnly">Read only</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="commandToReact" type="text" required="false">
|
||||
<label>Command to React</label>
|
||||
<description>Command to react. If not defined, channel react to all commands.</description>
|
||||
</parameter>
|
||||
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
|
||||
<label>Pulse Width</label>
|
||||
<description>Pulse width in milliseconds. If defined, binding send pulse rather than command value to IHC
|
||||
controller.</description>
|
||||
</parameter>
|
||||
<parameter name="inverted" type="boolean" required="false">
|
||||
<label>Inverted Signal</label>
|
||||
<description>openHAB state is inverted compared to IHC output/input signal</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="contact">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Generic Contact</label>
|
||||
<description>Generic contact channel</description>
|
||||
<state readOnly="true"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="inverted" type="boolean" required="false">
|
||||
<label>Inverted Signal</label>
|
||||
<description>openHAB state is inverted compared to IHC output/input signal</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="number">
|
||||
<item-type>Number</item-type>
|
||||
<label>Generic Number</label>
|
||||
<description>Generic number channel</description>
|
||||
<state readOnly="false"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="direction" type="text" required="false">
|
||||
<label>Channel Direction</label>
|
||||
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
|
||||
<default>ReadWrite</default>
|
||||
<options>
|
||||
<option value="ReadWrite">Read Write</option>
|
||||
<option value="WriteOnly">Write only</option>
|
||||
<option value="ReadOnly">Read only</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="commandToReact" type="text" required="false">
|
||||
<label>Command to React</label>
|
||||
<description>Command to react. If not defined, channel react to all commands.</description>
|
||||
</parameter>
|
||||
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
|
||||
<label>Pulse Width</label>
|
||||
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="dimmer">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Generic Dimmer</label>
|
||||
<description>Generic dimmer channel</description>
|
||||
<state readOnly="false"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="direction" type="text" required="false">
|
||||
<label>Channel Direction</label>
|
||||
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
|
||||
<default>ReadWrite</default>
|
||||
<options>
|
||||
<option value="ReadWrite">Read Write</option>
|
||||
<option value="WriteOnly">Write only</option>
|
||||
<option value="ReadOnly">Read only</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="commandToReact" type="text" required="false">
|
||||
<label>Command to React</label>
|
||||
<description>Command to react. If not defined, channel react to all commands.</description>
|
||||
</parameter>
|
||||
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
|
||||
<label>Pulse Width</label>
|
||||
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
|
||||
</parameter>
|
||||
<parameter name="onLevel" type="integer" required="false" min="0" max="100" step="1">
|
||||
<label>ON Command Level</label>
|
||||
<description>If defined, binding use this level when ON command is received rather than resource maximum value.
|
||||
Level is anyhow limited to resource maximum value.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="datetime">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Generic Datetime</label>
|
||||
<description>Generic datetime channel</description>
|
||||
<state readOnly="false"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="direction" type="text" required="false">
|
||||
<label>Channel Direction</label>
|
||||
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
|
||||
<default>ReadWrite</default>
|
||||
<options>
|
||||
<option value="ReadWrite">Read Write</option>
|
||||
<option value="WriteOnly">Write only</option>
|
||||
<option value="ReadOnly">Read only</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="commandToReact" type="text" required="false">
|
||||
<label>Command to React</label>
|
||||
<description>Command to react. If not defined, channel react to all commands.</description>
|
||||
</parameter>
|
||||
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
|
||||
<label>Pulse Width</label>
|
||||
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="string">
|
||||
<item-type>String</item-type>
|
||||
<label>Generic String</label>
|
||||
<description>Generic string channel</description>
|
||||
<state readOnly="false"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="direction" type="text" required="false">
|
||||
<label>Channel Direction</label>
|
||||
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
|
||||
<default>ReadWrite</default>
|
||||
<options>
|
||||
<option value="ReadWrite">Read Write</option>
|
||||
<option value="WriteOnly">Write only</option>
|
||||
<option value="ReadOnly">Read only</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="commandToReact" type="text" required="false">
|
||||
<label>Command to React</label>
|
||||
<description>Command to react. If not defined, channel react to all commands.</description>
|
||||
</parameter>
|
||||
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
|
||||
<label>Pulse Width</label>
|
||||
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="rollershutter">
|
||||
<item-type>RollerShutter</item-type>
|
||||
<label>Generic Roller Shutter</label>
|
||||
<description>Generic roller shutter channel</description>
|
||||
<state readOnly="false"></state>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="direction" type="text" required="false">
|
||||
<label>Channel Direction</label>
|
||||
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
|
||||
<default>ReadWrite</default>
|
||||
<options>
|
||||
<option value="ReadWrite">Read Write</option>
|
||||
<option value="WriteOnly">Write only</option>
|
||||
<option value="ReadOnly">Read only</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="commandToReact" type="text" required="false">
|
||||
<label>Command to React</label>
|
||||
<description>Command to react. If not defined, channel react to all commands.</description>
|
||||
</parameter>
|
||||
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
|
||||
<label>Pulse Width</label>
|
||||
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="rf-device-low-battery">
|
||||
<item-type>Switch</item-type>
|
||||
<label>RF Device Low Battery Warning</label>
|
||||
<description>RF device low battery warning.</description>
|
||||
<category>Battery</category>
|
||||
<state readOnly="true"></state>
|
||||
<config-description>
|
||||
<parameter name="serialNumber" type="integer" required="true">
|
||||
<label>RF Device Serial Number</label>
|
||||
<description>Serial Number of RF device in decimal format.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
<channel-type id="rf-device-signal-strength">
|
||||
<item-type>String</item-type>
|
||||
<label>RF Device Signal Strength</label>
|
||||
<description>RF device signal strength.</description>
|
||||
<category>QualityOfService</category>
|
||||
<state readOnly="true" min="0" max="4">
|
||||
<options>
|
||||
<option value="0">No signal</option>
|
||||
<option value="1">Weak</option>
|
||||
<option value="2">Average</option>
|
||||
<option value="3">Good</option>
|
||||
<option value="4">Excellent</option>
|
||||
</options>
|
||||
</state>
|
||||
<config-description>
|
||||
<parameter name="serialNumber" type="integer" required="true">
|
||||
<label>RF Device Serial Number</label>
|
||||
<description>Serial number of RF device in decimal format.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="push-button-trigger">
|
||||
<kind>trigger</kind>
|
||||
<label>Push Button Trigger Channel</label>
|
||||
<event>
|
||||
<options>
|
||||
<option value="PRESSED">Pressed</option>
|
||||
<option value="RELEASED">Released</option>
|
||||
<option value="SHORT_PRESS">Short press</option>
|
||||
<option value="LONG_PRESS">Long press</option>
|
||||
</options>
|
||||
</event>
|
||||
<config-description>
|
||||
<parameter name="resourceId" type="integer" required="true">
|
||||
<label>Resource Id</label>
|
||||
<description></description>
|
||||
</parameter>
|
||||
<parameter name="longPressTime" type="integer" required="true" step="1000" min="0" max="5000" unit="ms">
|
||||
<label>Long Press Time</label>
|
||||
<description>Long press time in milliseconds.</description>
|
||||
<default>1000</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="ihc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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="controller"
|
||||
extensible="switch, contact, number, dimmmer, datetime, string, rollershutter, pulse-output, rf-device-battery-level, rf-device-signal-strength, push-button-trigger">
|
||||
|
||||
<label>IHC / ELKO Controller</label>
|
||||
<description></description>
|
||||
|
||||
<channels>
|
||||
<channel typeId="controller-state" id="controllerState"/>
|
||||
<channel typeId="controller-uptime" id="controllerUptime"/>
|
||||
<channel typeId="controller-time" id="controllerTime"/>
|
||||
</channels>
|
||||
|
||||
<properties>
|
||||
<property name="controllerManufacturer"/>
|
||||
<property name="controllerSerialNumber"/>
|
||||
<property name="controllerSwVersion"/>
|
||||
<property name="controllerHwVersion"/>
|
||||
<property name="controllerIsWithoutViewer"/>
|
||||
<property name="controllerSwDate"/>
|
||||
<property name="controllerProductionDate"/>
|
||||
<property name="projectDate"/>
|
||||
<property name="projectNumber"/>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="hostname" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>Network Address</label>
|
||||
<description>Network/IP address of the IHC / ELKO controller without https prefix, but can contain TCP port if
|
||||
default port is not used</description>
|
||||
</parameter>
|
||||
<parameter name="username" type="text" required="true">
|
||||
<label>User Name</label>
|
||||
<description>User name to login to the IHC / ELKO controller.</description>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true">
|
||||
<context>password</context>
|
||||
<label>Password</label>
|
||||
<description>Password to login to the IHC / ELKO controller.</description>
|
||||
</parameter>
|
||||
<parameter name="timeout" type="integer" required="false" step="1000" unit="ms">
|
||||
<label>Timeout</label>
|
||||
<description>Timeout to communicate to IHC / ELKO controller.</description>
|
||||
<default>5000</default>
|
||||
</parameter>
|
||||
<parameter name="loadProjectFile" type="boolean" required="false">
|
||||
<label>Load Project File</label>
|
||||
<description>Load project file from controller.</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="createChannelsAutomatically" type="boolean" required="false">
|
||||
<label>Create Channels Automatically</label>
|
||||
<description>Create channels automatically from project file. Project file loading parameter should be enabled as
|
||||
well.</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ButtonPressDurationDetectorTest {
|
||||
|
||||
@Test
|
||||
public void testShortPress() {
|
||||
Duration duration = Duration.ofMillis(450);
|
||||
long longPressTime = 1000;
|
||||
long longPressMaxTime = 2000;
|
||||
|
||||
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
|
||||
|
||||
assertTrue(button.isShortPress());
|
||||
assertFalse(button.isLongPress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongPress() {
|
||||
Duration duration = Duration.ofMillis(1003);
|
||||
long longPressTime = 1000;
|
||||
long longPressMaxTime = 2000;
|
||||
|
||||
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
|
||||
|
||||
assertFalse(button.isShortPress());
|
||||
assertTrue(button.isLongPress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtraLongPress() {
|
||||
Duration duration = Duration.ofMillis(2423);
|
||||
long longPressTime = 1000;
|
||||
long longPressMaxTime = 2000;
|
||||
|
||||
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
|
||||
|
||||
assertFalse(button.isShortPress());
|
||||
assertFalse(button.isLongPress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTooLongPress() {
|
||||
Duration duration = Duration.ofMillis(5001);
|
||||
long longPressTime = 1000;
|
||||
long longPressMaxTime = 2000;
|
||||
|
||||
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
|
||||
|
||||
assertFalse(button.isShortPress());
|
||||
assertFalse(button.isLongPress());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class SignalLevelConverterTest {
|
||||
|
||||
@Test
|
||||
public void checkSignalLevelConverter() {
|
||||
// IHC signal levels are between 0-18.
|
||||
|
||||
assertEquals(0, new SignalLevelConverter(0).getSystemWideSignalLevel());
|
||||
assertEquals(0, new SignalLevelConverter(1).getSystemWideSignalLevel());
|
||||
assertEquals(1, new SignalLevelConverter(2).getSystemWideSignalLevel());
|
||||
assertEquals(1, new SignalLevelConverter(3).getSystemWideSignalLevel());
|
||||
assertEquals(1, new SignalLevelConverter(4).getSystemWideSignalLevel());
|
||||
assertEquals(2, new SignalLevelConverter(5).getSystemWideSignalLevel());
|
||||
assertEquals(2, new SignalLevelConverter(6).getSystemWideSignalLevel());
|
||||
assertEquals(2, new SignalLevelConverter(7).getSystemWideSignalLevel());
|
||||
assertEquals(2, new SignalLevelConverter(8).getSystemWideSignalLevel());
|
||||
assertEquals(3, new SignalLevelConverter(9).getSystemWideSignalLevel());
|
||||
assertEquals(3, new SignalLevelConverter(10).getSystemWideSignalLevel());
|
||||
assertEquals(3, new SignalLevelConverter(11).getSystemWideSignalLevel());
|
||||
assertEquals(3, new SignalLevelConverter(12).getSystemWideSignalLevel());
|
||||
assertEquals(3, new SignalLevelConverter(13).getSystemWideSignalLevel());
|
||||
assertEquals(4, new SignalLevelConverter(14).getSystemWideSignalLevel());
|
||||
assertEquals(4, new SignalLevelConverter(15).getSystemWideSignalLevel());
|
||||
assertEquals(4, new SignalLevelConverter(16).getSystemWideSignalLevel());
|
||||
assertEquals(4, new SignalLevelConverter(17).getSystemWideSignalLevel());
|
||||
assertEquals(4, new SignalLevelConverter(18).getSystemWideSignalLevel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DateTimeTypeWSDateValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
final DateTimeType dateTimeType = new DateTimeType("2000-12-30T00:00:00");
|
||||
WSDateValue val = new WSDateValue(12345, (short) 1999, (byte) 1, (byte) 1);
|
||||
|
||||
val = convertFromOHType(val, dateTimeType, null);
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(2000, val.year);
|
||||
assertEquals(12, val.month);
|
||||
assertEquals(30, val.day);
|
||||
|
||||
DateTimeType type = convertFromResourceValue(val, null);
|
||||
assertEquals(dateTimeType.format("yyyy-MM-dd"), type.format("yyyy-MM-dd"));
|
||||
}
|
||||
|
||||
private WSDateValue convertFromOHType(WSDateValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DateTimeType.class);
|
||||
return (WSDateValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DateTimeType convertFromResourceValue(WSDateValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DateTimeType.class);
|
||||
return (DateTimeType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DateTimeTypeWSTimeValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
final DateTimeType dateTimeType = new DateTimeType("2000-12-30T13:59:30");
|
||||
WSTimeValue val = new WSTimeValue(12345, 0, 0, 0);
|
||||
|
||||
val = convertFromOHType(val, dateTimeType, null);
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(13, val.hours);
|
||||
assertEquals(59, val.minutes);
|
||||
assertEquals(30, val.seconds);
|
||||
|
||||
DateTimeType type = convertFromResourceValue(val, null);
|
||||
assertEquals(dateTimeType.format("HH:mm:ss"), type.format("HH:mm:ss"));
|
||||
}
|
||||
|
||||
private WSTimeValue convertFromOHType(WSTimeValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DateTimeType.class);
|
||||
return (WSTimeValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DateTimeType convertFromResourceValue(WSTimeValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DateTimeType.class);
|
||||
return (DateTimeType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSBooleanValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOn() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
|
||||
val = convertFromOHType(val, new DecimalType(1), new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(new DecimalType(1), type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOff() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, new DecimalType(0), new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(new DecimalType(0), type);
|
||||
}
|
||||
|
||||
private WSBooleanValue convertFromOHType(WSBooleanValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (WSBooleanValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DecimalType convertFromResourceValue(WSBooleanValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSEnumValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
WSEnumValue val = new WSEnumValue(12345, 100, 0, "testB");
|
||||
|
||||
val = convertFromOHType(val, new DecimalType(2), new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(100, val.definitionTypeID);
|
||||
assertEquals(2, val.enumValueID);
|
||||
assertEquals("testB", val.enumName);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(new DecimalType(2), type);
|
||||
}
|
||||
|
||||
private WSEnumValue convertFromOHType(WSEnumValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (WSEnumValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DecimalType convertFromResourceValue(WSEnumValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSFloatingPointValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
WSFloatingPointValue val = new WSFloatingPointValue(12345, 0, -100, 100);
|
||||
|
||||
val = convertFromOHType(val, new DecimalType(2.54), new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.minimumValue, 0.001);
|
||||
assertEquals(100, val.maximumValue, 0.001);
|
||||
assertEquals(2.54, val.value, 0.001);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(new DecimalType(2.54), type);
|
||||
}
|
||||
|
||||
@Test(expected = ConversionException.class)
|
||||
public void testMinExceed() throws ConversionException {
|
||||
WSFloatingPointValue val = new WSFloatingPointValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, new DecimalType(-101.5), new ConverterAdditionalInfo(null, false, null));
|
||||
}
|
||||
|
||||
@Test(expected = ConversionException.class)
|
||||
public void testMaxExceed() throws ConversionException {
|
||||
WSFloatingPointValue val = new WSFloatingPointValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, new DecimalType(101.5), new ConverterAdditionalInfo(null, false, null));
|
||||
}
|
||||
|
||||
private WSFloatingPointValue convertFromOHType(WSFloatingPointValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (WSFloatingPointValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DecimalType convertFromResourceValue(WSFloatingPointValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSIntegerValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
val = convertFromOHType(val, new DecimalType(2), new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(2, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(new DecimalType(2), type);
|
||||
}
|
||||
|
||||
@Test(expected = ConversionException.class)
|
||||
public void testMinExceed() throws ConversionException {
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, new DecimalType(-101.5), new ConverterAdditionalInfo(null, false, null));
|
||||
}
|
||||
|
||||
@Test(expected = ConversionException.class)
|
||||
public void testMaxExceed() throws ConversionException {
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, new DecimalType(101.5), new ConverterAdditionalInfo(null, false, null));
|
||||
}
|
||||
|
||||
private WSIntegerValue convertFromOHType(WSIntegerValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (WSIntegerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DecimalType convertFromResourceValue(WSIntegerValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSTimerValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
WSTimerValue val = new WSTimerValue(12345, 0);
|
||||
|
||||
val = convertFromOHType(val, new DecimalType(123456), new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(123456, val.milliseconds);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(new DecimalType(123456), type);
|
||||
}
|
||||
|
||||
private WSTimerValue convertFromOHType(WSTimerValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (WSTimerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DecimalType convertFromResourceValue(WSTimerValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class DecimalTypeWSWeekdayValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testConversion() throws ConversionException {
|
||||
WSWeekdayValue val = new WSWeekdayValue(12345, 0);
|
||||
|
||||
val = convertFromOHType(val, new DecimalType(6), new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(6, val.weekdayNumber);
|
||||
|
||||
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(new DecimalType(6), type);
|
||||
}
|
||||
|
||||
private WSWeekdayValue convertFromOHType(WSWeekdayValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (WSWeekdayValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private DecimalType convertFromResourceValue(WSWeekdayValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
DecimalType.class);
|
||||
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OnOffTypeWSBooleanValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOn() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
|
||||
val = convertFromOHType(val, OnOffType.ON, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.ON, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOff() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, OnOffType.OFF, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.OFF, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, OnOffType.ON, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.ON, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOffInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
val = convertFromOHType(val, OnOffType.OFF, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.OFF, type);
|
||||
}
|
||||
|
||||
private WSBooleanValue convertFromOHType(WSBooleanValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OnOffType.class);
|
||||
return (WSBooleanValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private OnOffType convertFromResourceValue(WSBooleanValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OnOffType.class);
|
||||
return (OnOffType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OnOffTypeWSIntegerValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOn() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
val = convertFromOHType(val, OnOffType.ON, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.ON, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnLevelled() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
final int onLevel = 70;
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
Map<Command, Object> commandLevels = new HashMap<>();
|
||||
commandLevels.put(OnOffType.ON, onLevel);
|
||||
|
||||
val = convertFromOHType(val, OnOffType.ON,
|
||||
new ConverterAdditionalInfo(null, inverted, Collections.unmodifiableMap(commandLevels)));
|
||||
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(onLevel, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.ON, type);
|
||||
}
|
||||
|
||||
@Test(expected = ConversionException.class)
|
||||
public void testOnLevelledError() throws ConversionException {
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
Map<Command, Object> commandLevels = new HashMap<>();
|
||||
commandLevels.put(OnOffType.ON, "70");
|
||||
|
||||
val = convertFromOHType(val, OnOffType.ON,
|
||||
new ConverterAdditionalInfo(null, false, Collections.unmodifiableMap(commandLevels)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOff() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, OnOffType.OFF, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.OFF, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, OnOffType.ON, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.ON, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOffInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, OnOffType.OFF, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OnOffType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OnOffType.OFF, type);
|
||||
}
|
||||
|
||||
private WSIntegerValue convertFromOHType(WSIntegerValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OnOffType.class);
|
||||
return (WSIntegerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private OnOffType convertFromResourceValue(WSIntegerValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OnOffType.class);
|
||||
return (OnOffType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OpenClosedTypeWSBooleanValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOpen() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
|
||||
val = convertFromOHType(val, OpenClosedType.OPEN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.OPEN, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosed() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, OpenClosedType.CLOSED, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.CLOSED, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, OpenClosedType.OPEN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.OPEN, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosedInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
val = convertFromOHType(val, OpenClosedType.CLOSED, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.CLOSED, type);
|
||||
}
|
||||
|
||||
private WSBooleanValue convertFromOHType(WSBooleanValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OpenClosedType.class);
|
||||
return (WSBooleanValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private OpenClosedType convertFromResourceValue(WSBooleanValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OpenClosedType.class);
|
||||
return (OpenClosedType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class OpenClosedTypeWSIntegerValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOpen() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
val = convertFromOHType(val, OpenClosedType.OPEN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.OPEN, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosed() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, OpenClosedType.CLOSED, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.CLOSED, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, OpenClosedType.OPEN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.OPEN, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosedInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, OpenClosedType.CLOSED, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(100, val.value);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
|
||||
OpenClosedType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(OpenClosedType.CLOSED, type);
|
||||
}
|
||||
|
||||
private WSIntegerValue convertFromOHType(WSIntegerValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OpenClosedType.class);
|
||||
return (WSIntegerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private OpenClosedType convertFromResourceValue(WSIntegerValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
OpenClosedType.class);
|
||||
return (OpenClosedType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class PercentTypeWSIntegerValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void test() throws ConversionException {
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
val = convertFromOHType(val, new PercentType(2), new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
assertEquals(2, val.value);
|
||||
|
||||
PercentType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
|
||||
assertEquals(new PercentType(2), type);
|
||||
}
|
||||
|
||||
private WSIntegerValue convertFromOHType(WSIntegerValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
PercentType.class);
|
||||
return (WSIntegerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private PercentType convertFromResourceValue(WSIntegerValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
PercentType.class);
|
||||
return (PercentType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class StringTypeWSEnumValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void test() throws ConversionException {
|
||||
ArrayList<IhcEnumValue> enumValues = new ArrayList<>();
|
||||
enumValues.add(new IhcEnumValue(101, "testA"));
|
||||
enumValues.add(new IhcEnumValue(102, "testB"));
|
||||
enumValues.add(new IhcEnumValue(103, "testC"));
|
||||
enumValues.add(new IhcEnumValue(104, "testD"));
|
||||
|
||||
WSEnumValue val = new WSEnumValue(12345, 5555, 0, "");
|
||||
|
||||
val = convertFromOHType(val, new StringType("testC"), new ConverterAdditionalInfo(enumValues, false, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(5555, val.definitionTypeID);
|
||||
assertEquals(103, val.enumValueID);
|
||||
assertEquals("testC", val.enumName);
|
||||
|
||||
StringType type = convertFromResourceValue(val, new ConverterAdditionalInfo(enumValues, false, null));
|
||||
assertEquals(new StringType("testC"), type);
|
||||
}
|
||||
|
||||
private WSEnumValue convertFromOHType(WSEnumValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
StringType.class);
|
||||
return (WSEnumValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private StringType convertFromResourceValue(WSEnumValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
|
||||
throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
StringType.class);
|
||||
return (StringType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class UpDownTypeWSBooleanValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOpen() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
|
||||
val = convertFromOHType(val, UpDownType.UP, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.UP, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosed() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, UpDownType.DOWN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.DOWN, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, true);
|
||||
val = convertFromOHType(val, UpDownType.UP, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(false, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.UP, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosedInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSBooleanValue val = new WSBooleanValue(12345, false);
|
||||
val = convertFromOHType(val, UpDownType.DOWN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(true, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.DOWN, type);
|
||||
}
|
||||
|
||||
private WSBooleanValue convertFromOHType(WSBooleanValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
UpDownType.class);
|
||||
return (WSBooleanValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private UpDownType convertFromResourceValue(WSBooleanValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
UpDownType.class);
|
||||
return (UpDownType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.converters;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
|
||||
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
import org.openhab.core.types.Type;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class UpDownTypeWSIntegerValueConverterTest {
|
||||
|
||||
@Test
|
||||
public void testOpen() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
|
||||
val = convertFromOHType(val, UpDownType.UP, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
assertEquals(100, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.UP, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosed() throws ConversionException {
|
||||
final boolean inverted = false;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, UpDownType.DOWN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
assertEquals(-100, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.DOWN, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, UpDownType.UP, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
assertEquals(-100, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.UP, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosedInverted() throws ConversionException {
|
||||
final boolean inverted = true;
|
||||
|
||||
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
|
||||
val = convertFromOHType(val, UpDownType.DOWN, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(12345, val.resourceID);
|
||||
assertEquals(-100, val.minimumValue);
|
||||
assertEquals(100, val.maximumValue);
|
||||
assertEquals(100, val.value);
|
||||
|
||||
UpDownType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
|
||||
assertEquals(UpDownType.DOWN, type);
|
||||
}
|
||||
|
||||
private WSIntegerValue convertFromOHType(WSIntegerValue IHCvalue, Type OHval,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
UpDownType.class);
|
||||
return (WSIntegerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
|
||||
private UpDownType convertFromResourceValue(WSIntegerValue IHCvalue,
|
||||
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
|
||||
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
|
||||
UpDownType.class);
|
||||
return (UpDownType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcClientTest {
|
||||
|
||||
private IhcClient ihcClient;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IhcExecption, SocketTimeoutException {
|
||||
ihcClient = spy(new IhcClient("test1", "test2", "test3"));
|
||||
WSProjectInfo projectInfo = new WSProjectInfo();
|
||||
projectInfo.setProjectMajorRevision(111);
|
||||
projectInfo.setProjectMinorRevision(222);
|
||||
|
||||
doReturn(projectInfo).when(ihcClient).getProjectInfo();
|
||||
doReturn(2).when(ihcClient).getProjectNumberOfSegments();
|
||||
doReturn(100).when(ihcClient).getProjectSegmentationSize();
|
||||
|
||||
final String segment0 = ResourceFileUtils.getFileContent("Segment0.base64");
|
||||
final String segment1 = ResourceFileUtils.getFileContent("Segment1.base64");
|
||||
|
||||
WSFile file0 = new WSFile(segment0.getBytes(), "");
|
||||
doReturn(file0).when(ihcClient).getProjectSegment(ArgumentMatchers.eq(0), ArgumentMatchers.eq(111),
|
||||
ArgumentMatchers.eq(222));
|
||||
WSFile file1 = new WSFile(segment1.getBytes(), "");
|
||||
doReturn(file1).when(ihcClient).getProjectSegment(ArgumentMatchers.eq(1), ArgumentMatchers.eq(111),
|
||||
ArgumentMatchers.eq(222));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadProjectFileFromControllerTest() throws IhcExecption, UnsupportedEncodingException {
|
||||
final String expectedFileContent = ResourceFileUtils.getFileContent("ProjectFileContent.txt");
|
||||
|
||||
final byte[] result = ihcClient.getProjectFileFromController();
|
||||
assertEquals(expectedFileContent, new String(result, "UTF-8"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Util class to load file content from resource files.
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class ResourceFileUtils {
|
||||
public static String getFileContent(String resourceFile) {
|
||||
try (InputStream inputStream = ResourceFileUtils.class.getClassLoader().getResourceAsStream(resourceFile);
|
||||
Reader inputStreamReader = new InputStreamReader(inputStream);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
return bufferedReader.lines().collect(Collectors.joining("\n"));
|
||||
} catch (IOException e) {
|
||||
fail("IOException reading xml file '" + resourceFile + "': " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.ResourceFileUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcAirlinkManagementServiceTest {
|
||||
|
||||
private IhcAirlinkManagementService ihcAirlinkManagementService;
|
||||
private final String host = "1.1.1.1";
|
||||
private final String url = "https://1.1.1.1/ws/AirlinkManagementService";
|
||||
private Map<String, String> requestProps = new HashMap<>();
|
||||
private String query;
|
||||
private final int timeout = 100;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IhcExecption, SocketTimeoutException {
|
||||
ihcAirlinkManagementService = spy(new IhcAirlinkManagementService(host, timeout, new IhcConnectionPool()));
|
||||
|
||||
query = ResourceFileUtils.getFileContent("EmptyQuery.xml");
|
||||
|
||||
requestProps.clear();
|
||||
requestProps.put("SOAPAction", "getDetectedDeviceList");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws IhcExecption {
|
||||
final String response = ResourceFileUtils.getFileContent("GetDetectedDeviceListResponse.xml");
|
||||
doReturn(response).when(ihcAirlinkManagementService).sendQuery(eq(url), eq(requestProps), eq(query),
|
||||
eq(timeout));
|
||||
|
||||
final List<WSRFDevice> result = ihcAirlinkManagementService.getDetectedDeviceList();
|
||||
|
||||
assertEquals(1, result.size());
|
||||
|
||||
assertEquals(1, result.get(0).getBatteryLevel());
|
||||
assertEquals(true, result.get(0).getDetected());
|
||||
assertEquals(2049, result.get(0).getDeviceType());
|
||||
assertEquals(123456789, result.get(0).getSerialNumber());
|
||||
assertEquals(10, result.get(0).getSignalStrength());
|
||||
assertEquals(1, result.get(0).getVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyList() throws IhcExecption {
|
||||
final String response = ResourceFileUtils.getFileContent("GetEmptyDetectedDeviceListResponse.xml");
|
||||
doReturn(response).when(ihcAirlinkManagementService).sendQuery(eq(url), eq(requestProps), eq(query),
|
||||
eq(timeout));
|
||||
|
||||
final List<WSRFDevice> result = ihcAirlinkManagementService.getDetectedDeviceList();
|
||||
|
||||
assertEquals(0, result.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.ResourceFileUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSLoginResult;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcAuthenticationServiceTest {
|
||||
|
||||
private IhcAuthenticationService ihcAuthenticationService;
|
||||
private final String host = "1.1.1.1";
|
||||
private final String url = "https://1.1.1.1/ws/AuthenticationService";
|
||||
private final int timeout = 100;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IhcExecption, SocketTimeoutException {
|
||||
ihcAuthenticationService = spy(new IhcAuthenticationService(host, timeout, new IhcConnectionPool()));
|
||||
|
||||
final String querySuccesfulLogin = ResourceFileUtils.getFileContent("SuccesfulLoginQuery.xml");
|
||||
final String responseSuccesfulLogin = ResourceFileUtils.getFileContent("SuccesfulLoginResponse.xml");
|
||||
|
||||
doReturn(responseSuccesfulLogin).when(ihcAuthenticationService).sendQuery(eq(url), any(),
|
||||
eq(querySuccesfulLogin), eq(timeout));
|
||||
|
||||
final String queryLoginFailed = ResourceFileUtils.getFileContent("LoginFailedQuery.xml");
|
||||
final String responseLoginFailed = ResourceFileUtils.getFileContent("LoginFailedResponse.xml");
|
||||
|
||||
doReturn(responseLoginFailed).when(ihcAuthenticationService).sendQuery(eq(url), any(), eq(queryLoginFailed),
|
||||
eq(timeout));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccesfulLogin() throws IhcExecption {
|
||||
final WSLoginResult result = ihcAuthenticationService.authenticate("user", "pass", "treeview");
|
||||
assertEquals(true, result.isLoginWasSuccessful());
|
||||
assertEquals(false, result.isLoginFailedDueToAccountInvalid());
|
||||
assertEquals(false, result.isLoginFailedDueToConnectionRestrictions());
|
||||
assertEquals(false, result.isLoginFailedDueToInsufficientUserRights());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailedLogin() throws IhcExecption {
|
||||
final WSLoginResult result = ihcAuthenticationService.authenticate("user", "wrong", "treeview");
|
||||
assertEquals(false, result.isLoginWasSuccessful());
|
||||
assertEquals(true, result.isLoginFailedDueToAccountInvalid());
|
||||
assertEquals(false, result.isLoginFailedDueToConnectionRestrictions());
|
||||
assertEquals(false, result.isLoginFailedDueToInsufficientUserRights());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.ResourceFileUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcConfigurationServiceTest {
|
||||
|
||||
private IhcConfigurationService ihcConfigurationService;
|
||||
private final String host = "1.1.1.1";
|
||||
private final String url = "https://1.1.1.1/ws/ConfigurationService";
|
||||
final String query = ResourceFileUtils.getFileContent("EmptyQuery.xml");
|
||||
private Map<String, String> requestProps = new HashMap<>();
|
||||
private final int timeout = 100;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IhcExecption, SocketTimeoutException {
|
||||
ihcConfigurationService = spy(new IhcConfigurationService(host, timeout, new IhcConnectionPool()));
|
||||
requestProps.clear();
|
||||
requestProps.put("SOAPAction", "getSystemInfo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testv2() throws IhcExecption {
|
||||
final String response = ResourceFileUtils.getFileContent("GetSystemInfoResponse.xml");
|
||||
|
||||
doReturn(response).when(ihcConfigurationService).sendQuery(eq(url), eq(requestProps), eq(query), eq(timeout));
|
||||
|
||||
final WSSystemInfo result = ihcConfigurationService.getSystemInfo();
|
||||
|
||||
assertEquals(false, result.getApplicationIsWithoutViewer());
|
||||
assertEquals("ELKOFI", result.getBrand());
|
||||
assertEquals("6.2", result.getHwRevision());
|
||||
assertEquals(LocalDateTime.parse("2018-06-28T17:02:29", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")),
|
||||
result.getRealTimeClock().toLocalDateTime());
|
||||
assertEquals("1234567890", result.getSerialNumber());
|
||||
assertEquals(LocalDateTime.parse("2011-03-04T09:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")),
|
||||
result.getSwDate().toLocalDateTime());
|
||||
assertEquals(3980146956L, result.getUptime());
|
||||
assertEquals("2.7.144", result.getVersion());
|
||||
assertEquals("2011-04-28T09:00:00Z", result.getProductionDate());
|
||||
assertEquals("", result.getDatalineVersion());
|
||||
assertEquals("", result.getRfModuleSoftwareVersion());
|
||||
assertEquals("", result.getRfModuleSerialNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testv3() throws IhcExecption {
|
||||
final String response = ResourceFileUtils.getFileContent("GetSystemInfoResponse2.xml");
|
||||
doReturn(response).when(ihcConfigurationService).sendQuery(eq(url), eq(requestProps), eq(query), eq(timeout));
|
||||
|
||||
final WSSystemInfo result = ihcConfigurationService.getSystemInfo();
|
||||
|
||||
assertEquals(false, result.getApplicationIsWithoutViewer());
|
||||
assertEquals("LK", result.getBrand());
|
||||
assertEquals("7.1", result.getHwRevision());
|
||||
assertEquals(
|
||||
LocalDateTime.parse("2018-12-15T13:15:00Z", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")),
|
||||
result.getRealTimeClock().toLocalDateTime());
|
||||
assertEquals("CN1734000000", result.getSerialNumber());
|
||||
assertEquals(
|
||||
LocalDateTime.parse("2018-07-23T10:00:00Z", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")),
|
||||
result.getSwDate().toLocalDateTime());
|
||||
assertEquals(164057634L, result.getUptime());
|
||||
assertEquals("3.3.9", result.getVersion());
|
||||
assertEquals("2017/34", result.getProductionDate());
|
||||
assertEquals("IOB.B.03.02.01", result.getDatalineVersion());
|
||||
assertEquals("3.06.c", result.getRfModuleSoftwareVersion());
|
||||
assertEquals("640C10140000", result.getRfModuleSerialNumber());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.ihc.internal.ws.services;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.ihc.internal.ws.IhcClient;
|
||||
import org.openhab.binding.ihc.internal.ws.ResourceFileUtils;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
|
||||
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
|
||||
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
|
||||
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
|
||||
|
||||
/**
|
||||
* Test for IHC / ELKO binding
|
||||
*
|
||||
* @author Pauli Anttila - Initial contribution
|
||||
*/
|
||||
public class IhcControllerServiceTest {
|
||||
|
||||
private IhcControllerService ihcControllerService;
|
||||
private final String host = "1.1.1.1";
|
||||
private final String url = "https://1.1.1.1/ws/ControllerService";
|
||||
private Map<String, String> requestProps = new HashMap<>();
|
||||
private String query;
|
||||
private final int timeout = 100;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IhcExecption, SocketTimeoutException {
|
||||
ihcControllerService = spy(new IhcControllerService(host, timeout, new IhcConnectionPool()));
|
||||
|
||||
query = ResourceFileUtils.getFileContent("EmptyQuery.xml");
|
||||
requestProps.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectInfoTest() throws IhcExecption {
|
||||
requestProps.put("SOAPAction", "getProjectInfo");
|
||||
final String projectInfoResponse = ResourceFileUtils.getFileContent("GetProjectInfoResponse.xml");
|
||||
|
||||
doReturn(projectInfoResponse).when(ihcControllerService).sendQuery(eq(url), eq(requestProps), eq(query),
|
||||
eq(timeout));
|
||||
|
||||
final WSProjectInfo result = ihcControllerService.getProjectInfo();
|
||||
|
||||
assertEquals("Pertti 'Speedy' Keinonen", result.getCustomerName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectNumberOfSegmentsTest() throws IhcExecption {
|
||||
final String projectNumberOfSegmentsResponse = ResourceFileUtils
|
||||
.getFileContent("GetProjectNumberOfSegmentsResponse.xml");
|
||||
|
||||
requestProps.put("SOAPAction", "getIHCProjectNumberOfSegments");
|
||||
doReturn(projectNumberOfSegmentsResponse).when(ihcControllerService).sendQuery(eq(url), eq(requestProps),
|
||||
eq(query), eq(timeout));
|
||||
|
||||
final int result = ihcControllerService.getProjectNumberOfSegments();
|
||||
|
||||
assertEquals(28, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectSegmentationSizeTest() throws IhcExecption {
|
||||
final String projectSegmentationSizeResponse = ResourceFileUtils
|
||||
.getFileContent("GetProjectSegmentationSizeResponse.xml");
|
||||
|
||||
requestProps.put("SOAPAction", "getIHCProjectSegmentationSize");
|
||||
|
||||
doReturn(projectSegmentationSizeResponse).when(ihcControllerService).sendQuery(eq(url), eq(requestProps),
|
||||
eq(query), anyInt());
|
||||
|
||||
final int result = ihcControllerService.getProjectSegmentationSize();
|
||||
|
||||
assertEquals(7500, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controllerStateTest() throws IhcExecption {
|
||||
final String controllerStateResponse = ResourceFileUtils.getFileContent("ControllerStateResponse.xml");
|
||||
|
||||
requestProps.put("SOAPAction", "getState");
|
||||
doReturn(controllerStateResponse).when(ihcControllerService).sendQuery(eq(url), eq(requestProps), eq(query),
|
||||
anyInt());
|
||||
|
||||
final WSControllerState result = ihcControllerService.getControllerState();
|
||||
|
||||
assertEquals(IhcClient.CONTROLLER_STATE_READY, result.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void waitForControllerStateChangeQueryTest() throws IhcExecption {
|
||||
final String waitForControllerStateChangeQuery = ResourceFileUtils
|
||||
.getFileContent("WaitForControllerStateChangeQuery.xml");
|
||||
final String waitForControllerStateChangeResponse = ResourceFileUtils
|
||||
.getFileContent("WaitForControllerStateChangeResponse.xml");
|
||||
|
||||
requestProps.put("SOAPAction", "waitForControllerStateChange");
|
||||
doReturn(waitForControllerStateChangeResponse).when(ihcControllerService).sendQuery(eq(url), eq(requestProps),
|
||||
eq(waitForControllerStateChangeQuery), anyInt());
|
||||
|
||||
WSControllerState previousState = new WSControllerState();
|
||||
previousState.setState(IhcClient.CONTROLLER_STATE_INITIALIZE);
|
||||
final WSControllerState result = ihcControllerService.waitStateChangeNotifications(previousState, 5);
|
||||
|
||||
assertEquals(IhcClient.CONTROLLER_STATE_READY, result.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectSegmentQueryTest() throws IhcExecption {
|
||||
final String projectSegmentQuery = ResourceFileUtils.getFileContent("GetProjectSegmentQuery.xml");
|
||||
final String projectSegmentResponse = ResourceFileUtils.getFileContent("GetProjectSegmentResponse.xml");
|
||||
|
||||
requestProps.put("SOAPAction", "getIHCProjectSegment");
|
||||
doReturn(projectSegmentResponse).when(ihcControllerService).sendQuery(eq(url), eq(requestProps),
|
||||
eq(projectSegmentQuery), anyInt());
|
||||
|
||||
final byte[] expectedResult = "LvVF4VWSi0WqRKps7lGH6U....OBCl1gwKGbvYM1SDh".getBytes();
|
||||
final WSFile result = ihcControllerService.getProjectSegment(1, 1001, 2002);
|
||||
|
||||
assertTrue("Result bytes doesn't match to expected bytes", Arrays.equals(expectedResult, result.getData()));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user