[Helios] Remove support for obsolete firmware 2.7 including SOAP base… (#12721)

* Helios] Remove support for obsolete firmware 2.7 including SOAP based communication

Signed-off-by: Karel Goderis <karel.goderis@me.com>
This commit is contained in:
Karel Goderis
2022-05-29 16:25:43 +02:00
committed by GitHub
parent a0c3e7a88a
commit 020db307bb
18 changed files with 7 additions and 1191 deletions

View File

@@ -1,16 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.helios-${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>
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features
</repository>
<feature name="openhab-binding-helios" description="Helios Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle dependency="true">mvn:org.apache.ws.xmlschema/xmlschema-core/2.2.4</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/2.9.0</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.saaj-api-1.3/2.9.0</bundle>
<bundle dependency="true">mvn:org.apache.cxf/cxf-core/3.1.14</bundle>
<bundle dependency="true">mvn:org.apache.cxf.services.wsn/cxf-services-wsn-api/3.1.14</bundle>
<bundle dependency="true">mvn:org.apache.felix/org.apache.felix.framework/6.0.2</bundle>
<bundle dependency="true">mvn:org.apache.geronimo.specs/geronimo-ws-metadata_2.0_spec/1.1.3</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.helios/${project.version}</bundle>
</feature>
</features>

View File

@@ -27,7 +27,6 @@ public class HeliosBindingConstants {
public static final String BINDING_ID = "helios";
// List of all Thing Type UIDs
public static final ThingTypeUID HELIOS_VARIO_IP_2_7_TYPE = new ThingTypeUID(BINDING_ID, "ipvario27");
public static final ThingTypeUID HELIOS_VARIO_IP_2_21_TYPE = new ThingTypeUID(BINDING_ID, "ipvario221");
// List of all Channel ids

View File

@@ -12,7 +12,7 @@
*/
package org.openhab.binding.helios.internal;
import static org.openhab.binding.helios.internal.HeliosBindingConstants.*;
import static org.openhab.binding.helios.internal.HeliosBindingConstants.HELIOS_VARIO_IP_2_21_TYPE;
import java.util.Collections;
import java.util.Set;
@@ -20,7 +20,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openhab.binding.helios.internal.handler.HeliosHandler221;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
@@ -37,8 +36,7 @@ import org.osgi.service.component.annotations.Component;
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.helios")
public class HeliosHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
Stream.of(HELIOS_VARIO_IP_2_7_TYPE, HELIOS_VARIO_IP_2_21_TYPE).collect(Collectors.toSet()));
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(HELIOS_VARIO_IP_2_21_TYPE);
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
@@ -49,10 +47,6 @@ public class HeliosHandlerFactory extends BaseThingHandlerFactory {
protected ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(HELIOS_VARIO_IP_2_7_TYPE)) {
return new HeliosHandler27(thing);
}
if (thingTypeUID.equals(HELIOS_VARIO_IP_2_21_TYPE)) {
return new HeliosHandler221(thing);
}

View File

@@ -1,450 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.handler;
import static org.openhab.binding.helios.internal.HeliosBindingConstants.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMResult;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.BindingType;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.wsn.wsdl.WSNWSDLLocator;
import org.oasis_open.docs.wsn.b_2.FilterType;
import org.oasis_open.docs.wsn.b_2.Notify;
import org.oasis_open.docs.wsn.b_2.Renew;
import org.oasis_open.docs.wsn.b_2.RenewResponse;
import org.oasis_open.docs.wsn.b_2.Subscribe;
import org.oasis_open.docs.wsn.b_2.SubscribeResponse;
import org.oasis_open.docs.wsn.b_2.TopicExpressionType;
import org.oasis_open.docs.wsn.b_2.Unsubscribe;
import org.oasis_open.docs.wsn.bw_2.InvalidFilterFault;
import org.oasis_open.docs.wsn.bw_2.InvalidMessageContentExpressionFault;
import org.oasis_open.docs.wsn.bw_2.InvalidProducerPropertiesExpressionFault;
import org.oasis_open.docs.wsn.bw_2.InvalidTopicExpressionFault;
import org.oasis_open.docs.wsn.bw_2.NotificationConsumer;
import org.oasis_open.docs.wsn.bw_2.NotificationProducer;
import org.oasis_open.docs.wsn.bw_2.NotifyMessageNotSupportedFault;
import org.oasis_open.docs.wsn.bw_2.PausableSubscriptionManager;
import org.oasis_open.docs.wsn.bw_2.SubscribeCreationFailedFault;
import org.oasis_open.docs.wsn.bw_2.TopicExpressionDialectUnknownFault;
import org.oasis_open.docs.wsn.bw_2.TopicNotSupportedFault;
import org.oasis_open.docs.wsn.bw_2.UnableToDestroySubscriptionFault;
import org.oasis_open.docs.wsn.bw_2.UnacceptableInitialTerminationTimeFault;
import org.oasis_open.docs.wsn.bw_2.UnacceptableTerminationTimeFault;
import org.oasis_open.docs.wsn.bw_2.UnrecognizedPolicyRequestFault;
import org.oasis_open.docs.wsn.bw_2.UnsupportedPolicyRequestFault;
import org.oasis_open.docs.wsrf.rw_2.ResourceUnknownFault;
import org.openhab.binding.helios.internal.ws.soap.SOAPActionHandler;
import org.openhab.binding.helios.internal.ws.soap.SOAPCallStateChanged;
import org.openhab.binding.helios.internal.ws.soap.SOAPCardEntered;
import org.openhab.binding.helios.internal.ws.soap.SOAPCodeEntered;
import org.openhab.binding.helios.internal.ws.soap.SOAPDeviceState;
import org.openhab.binding.helios.internal.ws.soap.SOAPEvent;
import org.openhab.binding.helios.internal.ws.soap.SOAPKeyPressed;
import org.openhab.binding.helios.internal.ws.soap.SOAPObjectFactory;
import org.openhab.binding.helios.internal.ws.soap.SOAPSubscriptionActionHandler;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.StringType;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* The {@link HeliosHandler27} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Karel Goderis - Initial contribution
*/
@WebService(endpointInterface = "org.oasis_open.docs.wsn.bw_2.NotificationConsumer")
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class HeliosHandler27 extends BaseThingHandler implements NotificationConsumer {
// List of Configuration constants
public static final String IP_ADDRESS = "ipAddress";
public static final String OPENHAB_IP_ADDRESS = "openHABipAddress";
public static final String OPENHAB_PORT_NUMBER = "openHABportNumber";
private final Logger logger = LoggerFactory.getLogger(HeliosHandler27.class);
private static final String SUBSCRIPTION_PERIOD = "PT1H";
private JAXBContext context = null;
private Endpoint endpoint = null;
private NotificationProducer notificationProducer = null;
private PausableSubscriptionManager subscription = null;
private GregorianCalendar currentTime;
private GregorianCalendar terminationTime;
private W3CEndpointReference subscriptionReference;
private String subscriptionID;
private SOAPEvent previousEvent = null;
public static final String HELIOS_URI = "http://www.2n.cz/2013/event";
public static final String DIALECT_URI = "http://www.2n.cz/2013/TopicExpression/Multiple";
public static final String WSN_URI = "http://docs.oasis-open.org/wsn/b-2";
public static final QName TOPIC_EXPRESSION = new QName(WSN_URI, "TopicExpression");
public static final QName INITIAL_TERMINATION_TIME = new QName(WSN_URI, "InitialTerminationTime");
public static final QName MAXIMUM_NUMBER = new QName(HELIOS_URI, "MaximumNumber");
public static final QName SIMPLE_MESSAGES = new QName(HELIOS_URI, "SimpleMessages");
public static final QName START_TIME_STAMP = new QName(HELIOS_URI, "StartTimestamp");
public static final QName START_RECORD_ID = new QName(HELIOS_URI, "StartRecordId");
public HeliosHandler27(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (!(command instanceof RefreshType)) {
// 2N.cz has not yet released the automation part of the Helios IP HTTP/SOAP based API. Only the
// notification part has been documented, so for now there is nothing to do
// here
logger.debug("The Helios IP is a read-only device and can not handle commands");
}
}
public String getSubscriptionID() {
return subscriptionID;
}
@SuppressWarnings("rawtypes")
@Override
public void initialize() {
logger.debug("Initializing Helios IP handler.");
List<Handler> handlerChain = new ArrayList<>();
handlerChain.add(new SOAPActionHandler());
try {
context = JAXBContext.newInstance(SOAPObjectFactory.class, SOAPEvent.class, SOAPKeyPressed.class,
SOAPCallStateChanged.class, SOAPCodeEntered.class, SOAPCardEntered.class, SOAPDeviceState.class);
} catch (JAXBException e) {
logger.error("An exception occurred while setting up the JAXB Context factory: {}", e.getMessage(), e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
throw new RuntimeException();
}
try {
if (endpoint == null || (endpoint != null && !endpoint.isPublished())) {
String address = "http://" + (String) getConfig().get(OPENHAB_IP_ADDRESS) + ":"
+ ((BigDecimal) getConfig().get(OPENHAB_PORT_NUMBER)).toString() + "/notification"
+ System.currentTimeMillis();
logger.debug("Publishing the notification consumer webservice on '{}", address);
endpoint = Endpoint.publish(address, this);
((javax.xml.ws.soap.SOAPBinding) endpoint.getBinding()).setHandlerChain(handlerChain);
}
} catch (WebServiceException e1) {
logger.debug("An exception occurred while setting up the notification consumer webservice: {}",
e1.getMessage(), e1);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e1.getMessage());
return;
}
try {
String heliosAddress = "http://" + (String) getConfig().get(IP_ADDRESS) + "/notification";
Service notificationProducerService = Service.create(WSNWSDLLocator.getWSDLUrl(),
new QName("http://cxf.apache.org/wsn/jaxws", "NotificationProducerService"));
notificationProducer = notificationProducerService.getPort(
new W3CEndpointReferenceBuilder().address(heliosAddress).build(), NotificationProducer.class);
((BindingProvider) notificationProducer).getBinding().setHandlerChain(handlerChain);
} catch (WebServiceException e1) {
logger.debug("An exception occurred while setting up the notification webservice client: {}",
e1.getMessage(), e1);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e1.getMessage());
return;
}
try {
// set up the access to the subscription manager on the Helios IP
// Vario so that we can renew in the future
String heliosAddress = "http://" + (String) getConfig().get(IP_ADDRESS) + "/notification";
Service subscriptionService = Service.create(WSNWSDLLocator.getWSDLUrl(),
new QName("http://cxf.apache.org/wsn/jaxws", "PausableSubscriptionManagerService"));
subscription = subscriptionService.getPort(new W3CEndpointReferenceBuilder().address(heliosAddress).build(),
PausableSubscriptionManager.class);
handlerChain = new ArrayList<>();
handlerChain.add(new SOAPSubscriptionActionHandler(this));
((BindingProvider) subscription).getBinding().setHandlerChain(handlerChain);
} catch (WebServiceException e1) {
logger.debug("An exception occurred while setting up the subscription manager client: {}", e1.getMessage(),
e1);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e1.getMessage());
return;
}
try {
subscribe(endpoint.getEndpointReference(W3CEndpointReference.class));
} catch (WebServiceException | TopicNotSupportedFault | InvalidFilterFault | TopicExpressionDialectUnknownFault
| UnacceptableInitialTerminationTimeFault | SubscribeCreationFailedFault
| InvalidMessageContentExpressionFault | InvalidTopicExpressionFault | UnrecognizedPolicyRequestFault
| UnsupportedPolicyRequestFault | ResourceUnknownFault | NotifyMessageNotSupportedFault
| InvalidProducerPropertiesExpressionFault e) {
logger.debug("An exception occurred while subscribing to the notifications for thing '{}': {}",
getThing().getUID(), e.getMessage(), e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
return;
}
updateStatus(ThingStatus.ONLINE);
}
@Override
public void dispose() {
logger.debug("Disposing Helios IP handler.");
try {
unsubscribe();
if (endpoint != null) {
endpoint.stop();
}
endpoint = null;
terminationTime = null;
context = null;
notificationProducer = null;
subscription = null;
} catch (Exception e) {
logger.error("An exception occurred while disposing the Helios Thing Handler : {}", e.getMessage(), e);
}
}
@Override
public void notify(
@WebParam(partName = "Notify", name = "Notify", targetNamespace = "http://docs.oasis-open.org/wsn/b-2") Notify notify) {
for (Object object : notify.getAny()) {
try {
this.processNotification(context.createUnmarshaller().unmarshal((Element) object, SOAPEvent.class));
} catch (JAXBException e) {
logger.error("An exception occurred while processing a notification message : {}", e.getMessage(), e);
}
}
}
public void processNotification(JAXBElement<SOAPEvent> message) {
if (getThing().getStatus() == ThingStatus.ONLINE) {
SOAPEvent event = message.getValue();
// WS-Notification does not provide a mechanism to query existing
// subscriptions established before, so these keep lingering on the
// remote device. Therefore, when restarting the OH runtime, we
// might receive events more than one time, we need to filter these
// out
if (previousEvent == null || !previousEvent.equals(event)) {
previousEvent = event;
Object data = event.getData();
if (data instanceof SOAPKeyPressed) {
StringType valueType = new StringType(((SOAPKeyPressed) data).getKeyCode());
updateState(new ChannelUID(getThing().getUID(), KEY_PRESSED), valueType);
DateTimeType stampType = new DateTimeType(event.getTimestamp());
updateState(new ChannelUID(getThing().getUID(), KEY_PRESSED_STAMP), stampType);
}
if (data instanceof SOAPCallStateChanged) {
StringType valueType = new StringType(((SOAPCallStateChanged) data).getState());
updateState(new ChannelUID(getThing().getUID(), CALL_STATE), valueType);
valueType = new StringType(((SOAPCallStateChanged) data).getDirection());
updateState(new ChannelUID(getThing().getUID(), CALL_DIRECTION), valueType);
DateTimeType stampType = new DateTimeType(event.getTimestamp());
updateState(new ChannelUID(getThing().getUID(), CALL_STATE_STAMP), stampType);
}
if (data instanceof SOAPCardEntered) {
StringType valueType = new StringType(((SOAPCardEntered) data).getCard());
updateState(new ChannelUID(getThing().getUID(), CARD), valueType);
valueType = new StringType(((SOAPCardEntered) data).getValid());
updateState(new ChannelUID(getThing().getUID(), CARD_VALID), valueType);
DateTimeType stampType = new DateTimeType(event.getTimestamp());
updateState(new ChannelUID(getThing().getUID(), CARD_STAMP), stampType);
}
if (data instanceof SOAPCodeEntered) {
StringType valueType = new StringType(((SOAPCodeEntered) data).getCode());
updateState(new ChannelUID(getThing().getUID(), CODE), valueType);
valueType = new StringType(((SOAPCodeEntered) data).getValid());
updateState(new ChannelUID(getThing().getUID(), CODE_VALID), valueType);
DateTimeType stampType = new DateTimeType(event.getTimestamp());
updateState(new ChannelUID(getThing().getUID(), CODE_STAMP), stampType);
}
if (data instanceof SOAPDeviceState) {
StringType valueType = new StringType(((SOAPDeviceState) data).getState());
updateState(new ChannelUID(getThing().getUID(), DEVICE_STATE), valueType);
DateTimeType stampType = new DateTimeType(event.getTimestamp());
updateState(new ChannelUID(getThing().getUID(), DEVICE_STATE_STAMP), stampType);
}
} else {
logger.warn("Duplicate event received due to lingering subscriptions: '{}':'{}'", event.getEventName(),
event.getTimestamp());
}
}
}
public void renew(String newTerminationTime) throws ResourceUnknownFault, UnacceptableTerminationTimeFault {
if (subscription != null) {
Renew renew = new Renew();
renew.setTerminationTime(newTerminationTime);
RenewResponse response = subscription.renew(renew);
currentTime = response.getCurrentTime().toGregorianCalendar();
terminationTime = response.getTerminationTime().toGregorianCalendar();
SimpleDateFormat pFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
logger.debug("Renewed the subscription with ID '{}' for '{}' from {} until {}",
new Object[] { getSubscriptionID(), getThing().getUID(), pFormatter.format(currentTime.getTime()),
pFormatter.format(terminationTime.getTime()) });
}
}
public void unsubscribe() {
if (subscription != null) {
try {
subscription.unsubscribe(new Unsubscribe());
logger.debug("Unsubscribing the subscription with ID '{}' for '{}' ", getSubscriptionID(),
getThing().getUID());
} catch (UnableToDestroySubscriptionFault | ResourceUnknownFault e) {
logger.error("An exception occurred while unsubscribing from the subscription : {}", e.getMessage(), e);
}
}
}
public void subscribe(W3CEndpointReference epr)
throws TopicNotSupportedFault, InvalidFilterFault, TopicExpressionDialectUnknownFault,
UnacceptableInitialTerminationTimeFault, SubscribeCreationFailedFault, InvalidMessageContentExpressionFault,
InvalidTopicExpressionFault, UnrecognizedPolicyRequestFault, UnsupportedPolicyRequestFault,
ResourceUnknownFault, NotifyMessageNotSupportedFault, InvalidProducerPropertiesExpressionFault {
if (notificationProducer != null) {
Subscribe subscribeRequest = new Subscribe();
subscribeRequest.setConsumerReference(epr);
subscribeRequest.setFilter(new FilterType());
TopicExpressionType topicExp = new TopicExpressionType();
topicExp.getContent().add("");
topicExp.setDialect(DIALECT_URI);
subscribeRequest.getFilter().getAny()
.add(new JAXBElement<>(TOPIC_EXPRESSION, TopicExpressionType.class, topicExp));
subscribeRequest.setInitialTerminationTime(
new JAXBElement<>(INITIAL_TERMINATION_TIME, String.class, SUBSCRIPTION_PERIOD));
subscribeRequest.setSubscriptionPolicy(new Subscribe.SubscriptionPolicy());
subscribeRequest.getSubscriptionPolicy().getAny().add(new JAXBElement<>(MAXIMUM_NUMBER, Integer.class, 1));
subscribeRequest.getSubscriptionPolicy().getAny().add(new JAXBElement<>(SIMPLE_MESSAGES, Integer.class, 1));
GregorianCalendar now = new GregorianCalendar();
SimpleDateFormat pFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
subscribeRequest.getSubscriptionPolicy().getAny()
.add(new JAXBElement<>(START_TIME_STAMP, String.class, pFormatter.format(now.getTime())));
SubscribeResponse response = notificationProducer.subscribe(subscribeRequest);
if (response != null) {
currentTime = response.getCurrentTime().toGregorianCalendar();
terminationTime = response.getTerminationTime().toGregorianCalendar();
subscriptionReference = response.getSubscriptionReference();
Element element = DOMUtils.createDocument().createElement("elem");
subscriptionReference.writeTo(new DOMResult(element));
NodeList nl = element.getElementsByTagNameNS("http://www.2n.cz/2013/event", "SubscriptionId");
if (nl != null && nl.getLength() > 0) {
Element e = (Element) nl.item(0);
subscriptionID = DOMUtils.getContent(e).trim();
}
logger.debug("Established a subscription with ID '{}' for '{}' as from {} until {}",
new Object[] { subscriptionID, getThing().getUID(), pFormatter.format(currentTime.getTime()),
pFormatter.format(terminationTime.getTime()) });
java.util.Calendar triggerTime = terminationTime;
triggerTime.add(Calendar.MINUTE, -1);
logger.debug("Scheduling a renewal of the subscription with ID '{}' for '{}' to happen on {}",
new Object[] { subscriptionID, getThing().getUID(), pFormatter.format(triggerTime.getTime()) });
try {
scheduler.schedule(renewRunnable, triggerTime.getTimeInMillis() - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
} catch (RejectedExecutionException e) {
logger.error("An exception occurred while scheduling a renewal : '{}'", e.getMessage(), e);
}
}
}
}
protected Runnable renewRunnable = new Runnable() {
@Override
public void run() {
SimpleDateFormat pFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
boolean result = false;
try {
((HeliosHandler27) getThing().getHandler()).renew(SUBSCRIPTION_PERIOD);
result = true;
} catch (Exception e) {
logger.error("An exception occurred while renewing the subscription : {}", e.getMessage(), e);
((HeliosHandler27) getThing().getHandler()).dispose();
((HeliosHandler27) getThing().getHandler()).initialize();
return;
}
if (result) {
java.util.Calendar triggerTime = terminationTime;
triggerTime.add(Calendar.MINUTE, -1);
logger.debug("Scheduling a renewal of the subscription with ID '{}' for '{}' to happen on {}",
new Object[] { subscriptionID, getThing().getUID(), pFormatter.format(triggerTime.getTime()) });
try {
scheduler.schedule(renewRunnable, triggerTime.getTimeInMillis() - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
} catch (RejectedExecutionException e) {
logger.error("An exception occurred while scheduling a renewal : '{}'", e.getMessage(), e);
}
}
}
};
}

View File

@@ -1,56 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
* The {@link SOAPActionHandler} is a custom SOAP handler that modifies some SOAP
* headers in order to get the Helios comm. working
*
* @author Karel Goderis - Initial contribution
*/
public class SOAPActionHandler implements SOAPHandler<SOAPMessageContext> {
@Override
public boolean handleMessage(SOAPMessageContext context) {
// Nothing to do here
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
// Nothing to do here
return false;
}
@Override
public void close(MessageContext context) {
// Nothing to do here
}
@Override
public Set<QName> getHeaders() {
Set<QName> set = new HashSet<>();
// Make sure the '[{http://www.w3.org/2005/08/addressing}]Action' header
// is handled in case the device set the 'MustUnderstand' attribute to
// '1'
set.add(new QName("http://www.w3.org/2005/08/addressing", "Action"));
return set;
}
}

View File

@@ -1,52 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Data", namespace = HeliosHandler27.HELIOS_URI)
public class SOAPCallStateChanged extends SOAPDataField {
@XmlElement(name = "State", namespace = HeliosHandler27.HELIOS_URI)
protected String state;
@XmlElement(name = "Direction", namespace = HeliosHandler27.HELIOS_URI)
protected String direction;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
}

View File

@@ -1,52 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Data", namespace = HeliosHandler27.HELIOS_URI)
public class SOAPCardEntered extends SOAPDataField {
@XmlElement(name = "Card", namespace = HeliosHandler27.HELIOS_URI)
protected String card;
@XmlElement(name = "Valid", namespace = HeliosHandler27.HELIOS_URI)
protected String valid;
public String getCard() {
return card;
}
public void setCard(String card) {
this.card = card;
}
public String getValid() {
return valid;
}
public void setValid(String valid) {
this.valid = valid;
}
}

View File

@@ -1,52 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Data", namespace = HeliosHandler27.HELIOS_URI)
public class SOAPCodeEntered extends SOAPDataField {
@XmlElement(name = "Code", namespace = HeliosHandler27.HELIOS_URI)
protected String code;
@XmlElement(name = "Valid", namespace = HeliosHandler27.HELIOS_URI)
protected String valid;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getValid() {
return valid;
}
public void setValid(String valid) {
this.valid = valid;
}
}

View File

@@ -1,24 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlJavaTypeAdapter(SOAPDataFieldAdapter.class)
public abstract class SOAPDataField {
}

View File

@@ -1,87 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* The {@link SOAPDataFieldAdapter} is a helper class that is used to
* unmarshal some 'variable' SOAP messages
*
* @author Karel Goderis - Initial contribution
*/
public class SOAPDataFieldAdapter extends XmlAdapter<SOAPDataFieldAdapter.AdaptedHeliosDataField, SOAPDataField> {
public static class AdaptedHeliosDataField {
@XmlElement
public String State;
@XmlElement
public String Direction;
@XmlElement
public String Code;
@XmlElement
public String Valid;
@XmlElement
public String Key;
@XmlElement
public String Card;
}
@Override
public AdaptedHeliosDataField marshal(SOAPDataField arg0) throws Exception {
return null;
}
@Override
public SOAPDataField unmarshal(AdaptedHeliosDataField arg0) throws Exception {
if (null == arg0) {
return null;
}
if (null != arg0.Card && null != arg0.Valid) {
SOAPCardEntered heliosCardEntered = new SOAPCardEntered();
heliosCardEntered.setCard(arg0.Card);
heliosCardEntered.setValid(arg0.Valid);
return heliosCardEntered;
}
if (null != arg0.Code && null != arg0.Valid) {
SOAPCodeEntered heliosCodeEntered = new SOAPCodeEntered();
heliosCodeEntered.setCode(arg0.Code);
heliosCodeEntered.setValid(arg0.Valid);
return heliosCodeEntered;
}
if (null != arg0.Key) {
SOAPKeyPressed heliosKeyPressed = new SOAPKeyPressed();
heliosKeyPressed.setKeyCode(arg0.Key);
return heliosKeyPressed;
}
if (null != arg0.State && null != arg0.Direction) {
SOAPCallStateChanged heliosCallStateChanged = new SOAPCallStateChanged();
heliosCallStateChanged.setState(arg0.State);
heliosCallStateChanged.setDirection(arg0.Direction);
return heliosCallStateChanged;
}
if (null != arg0.State) {
SOAPDeviceState heliosDeviceState = new SOAPDeviceState();
heliosDeviceState.setState(arg0.State);
return heliosDeviceState;
}
return null;
}
}

View File

@@ -1,41 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Data", namespace = HeliosHandler27.HELIOS_URI)
public class SOAPDeviceState extends SOAPDataField {
@XmlElement(name = "State", namespace = HeliosHandler27.HELIOS_URI)
protected String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}

View File

@@ -1,108 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "HeliosEvent", namespace = HeliosHandler27.HELIOS_URI, propOrder = { "timestamp", "eventName", "data" })
@XmlRootElement(name = "Msg")
public class SOAPEvent {
@XmlElement(name = "Timestamp", namespace = HeliosHandler27.HELIOS_URI)
protected String timestamp;
@XmlElement(name = "EventName", namespace = HeliosHandler27.HELIOS_URI)
protected String eventName;
@XmlElement(name = "Data", namespace = HeliosHandler27.HELIOS_URI)
protected SOAPDataField data;
public SOAPDataField getData() {
return data;
}
public void setData(SOAPDataField data) {
this.data = data;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SOAPEvent)) {
return false;
}
if (obj == this) {
return true;
}
SOAPEvent event = (SOAPEvent) obj;
if (event.getEventName().equals(eventName) && event.getTimestamp().equals(timestamp)) {
Object eventData = event.getData();
if (data instanceof SOAPKeyPressed) {
return ((SOAPKeyPressed) data).getKeyCode().equals(((SOAPKeyPressed) eventData).getKeyCode());
}
if (data instanceof SOAPCallStateChanged) {
return ((SOAPCallStateChanged) data).getDirection()
.equals(((SOAPCallStateChanged) eventData).getDirection())
&& ((SOAPCallStateChanged) data).getState()
.equals(((SOAPCallStateChanged) eventData).getState());
}
if (data instanceof SOAPCardEntered) {
return ((SOAPCardEntered) data).getCard().equals(((SOAPCardEntered) eventData).getCard())
&& ((SOAPCardEntered) data).getValid().equals(((SOAPCardEntered) eventData).getValid());
}
if (data instanceof SOAPCodeEntered) {
return ((SOAPCodeEntered) data).getCode().equals(((SOAPCodeEntered) eventData).getCode())
&& ((SOAPCodeEntered) data).getValid().equals(((SOAPCodeEntered) eventData).getValid());
}
if (data instanceof SOAPDeviceState) {
return ((SOAPDeviceState) data).getState().equals(((SOAPDeviceState) eventData).getState());
}
}
return false;
}
}

View File

@@ -1,41 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* Helios SOAP Protocol Message
*
* @author Karel Goderis - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Data", namespace = HeliosHandler27.HELIOS_URI)
public class SOAPKeyPressed extends SOAPDataField {
@XmlElement(name = "Key", namespace = HeliosHandler27.HELIOS_URI)
protected String keyCode;
public String getKeyCode() {
return keyCode;
}
public void setKeyCode(String code) {
this.keyCode = code;
}
}

View File

@@ -1,57 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
/**
* The {@link SOAPObjectFactory} is a helper class that is used to generate JAXB
* Elements
*
* @author Karel Goderis - Initial contribution
*/
@XmlRegistry
public class SOAPObjectFactory {
private static final QName DATA_QNAME = new QName(HeliosHandler27.HELIOS_URI, "Data");
@XmlElementDecl(namespace = HeliosHandler27.HELIOS_URI, name = "CallStateChanged")
public JAXBElement<SOAPCallStateChanged> createHeliosCallStateChanged(SOAPCallStateChanged value) {
return new JAXBElement<>(DATA_QNAME, SOAPCallStateChanged.class, null, value);
}
@XmlElementDecl(namespace = HeliosHandler27.HELIOS_URI, name = "CodeEntered")
public JAXBElement<SOAPCodeEntered> createHeliosCodeEntered(SOAPCodeEntered value) {
return new JAXBElement<>(DATA_QNAME, SOAPCodeEntered.class, null, value);
}
@XmlElementDecl(namespace = HeliosHandler27.HELIOS_URI, name = "CardEntered")
public JAXBElement<SOAPCardEntered> createHeliosCardEntered(SOAPCardEntered value) {
return new JAXBElement<>(DATA_QNAME, SOAPCardEntered.class, null, value);
}
@XmlElementDecl(namespace = HeliosHandler27.HELIOS_URI, name = "DeviceState")
public JAXBElement<SOAPDeviceState> createHeliosDeviceState(SOAPDeviceState value) {
return new JAXBElement<>(DATA_QNAME, SOAPDeviceState.class, null, value);
}
@XmlElementDecl(namespace = HeliosHandler27.HELIOS_URI, name = "KeyPressed")
public JAXBElement<SOAPKeyPressed> createHeliosKeyPressedd(SOAPKeyPressed value) {
return new JAXBElement<>(DATA_QNAME, SOAPKeyPressed.class, null, value);
}
}

View File

@@ -1,73 +0,0 @@
/**
* Copyright (c) 2010-2022 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.helios.internal.ws.soap;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.openhab.binding.helios.internal.handler.HeliosHandler27;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link SOAPSubscriptionActionHandler} is a custom SOAP handler that modifies
* some SOAP headers in order to get the Helios comm. working
*
* @author Karel Goderis - Initial contribution
*/
public class SOAPSubscriptionActionHandler extends SOAPActionHandler {
private Logger logger = LoggerFactory.getLogger(SOAPSubscriptionActionHandler.class);
private HeliosHandler27 handler;
public SOAPSubscriptionActionHandler(HeliosHandler27 heliosHandler) {
this.handler = heliosHandler;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (isRequest) {
try {
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
if (soapHeader == null) {
soapHeader = soapEnv.addHeader();
}
QName qname = new QName("http://www.2n.cz/2013/event", "SubscriptionId");
SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(qname);
soapHeaderElement.addAttribute(
new QName("http://www.w3.org/2005/08/addressing", "IsReferenceParameter"), "true");
if (handler.getSubscriptionID() != null) {
soapHeaderElement.addTextNode(handler.getSubscriptionID());
}
soapMsg.saveChanges();
} catch (Exception e) {
logger.debug("An exception occurred while formatting a SOAP header : '{}'", e.getMessage());
}
}
return true;
}
}

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="helios"
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="ipvario27">
<label>Helios IP Vario</label>
<description>Helios IP Vario Door Station / Intercom with Firmware v2.7</description>
<channels>
<channel id="keypressed" typeId="keypressed"/>
<channel id="keypressedstamp" typeId="keypressedstamp"/>
<channel id="callstate" typeId="callstate"/>
<channel id="calldirection" typeId="calldirection"/>
<channel id="callstatestamp" typeId="callstatestamp"/>
<channel id="card" typeId="card"/>
<channel id="cardvalid" typeId="cardvalid"/>
<channel id="cardstamp" typeId="cardstamp"/>
<channel id="code" typeId="code"/>
<channel id="codevalid" typeId="codevalid"/>
<channel id="codestamp" typeId="codestamp"/>
<channel id="devicestate" typeId="devicestate"/>
<channel id="devicestatestamp" typeId="devicestatestamp"/>
</channels>
<config-description>
<parameter name="ipAddress" type="text" required="true">
<context>network-address</context>
<label>Network Address</label>
<description>Network address of the Helios IP device</description>
</parameter>
<parameter name="openHABipAddress" type="text" required="true">
<context>network-address</context>
<label>Network Address</label>
<description>Network address of the openHAB host</description>
</parameter>
<parameter name="openHABportNumber" type="integer" required="true">
<label>Port Number</label>
<description>TCP port number the notification web service will be registered on</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>