[tr064] fix certificate problems and add call list channel (#9149)
* improvements - use insecure client and remove TrustManager - add call list channel * address review comments Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>
This commit is contained in:
parent
66421c6939
commit
936a4dc8d8
@ -49,7 +49,7 @@ This is an optional parameter and multiple values are allowed.
|
|||||||
|
|
||||||
Most devices support call lists.
|
Most devices support call lists.
|
||||||
The binding can analyze these call lists and provide channels for the number of missed calls, inbound calls, outbound calls and rejected (blocked) calls.
|
The binding can analyze these call lists and provide channels for the number of missed calls, inbound calls, outbound calls and rejected (blocked) calls.
|
||||||
The days for which this analysis takes place can be controlled with the `missedCallDays`, `rejectedCallDays`, `inboundCallDays` and `outboundCallDays`
|
The days for which this analysis takes place can be controlled with the `missedCallDays`, `rejectedCallDays`, `inboundCallDays`, `outboundCallDays` and `callListDays`.
|
||||||
This is an optional parameter and multiple values are allowed.
|
This is an optional parameter and multiple values are allowed.
|
||||||
|
|
||||||
Since FritzOS! 7.20 WAN access of local devices can be controlled by their IPs.
|
Since FritzOS! 7.20 WAN access of local devices can be controlled by their IPs.
|
||||||
@ -75,7 +75,8 @@ This is an optional parameter and multiple values are allowed.
|
|||||||
| channel | item-type | advanced | description |
|
| channel | item-type | advanced | description |
|
||||||
|----------------------------|---------------------------|:--------:|----------------------------------------------------------------|
|
|----------------------------|---------------------------|:--------:|----------------------------------------------------------------|
|
||||||
| `callDeflectionEnable` | `Switch` | | Enable/Disable the call deflection setup with the given index. |
|
| `callDeflectionEnable` | `Switch` | | Enable/Disable the call deflection setup with the given index. |
|
||||||
| `deviceLog` | `String` | x | A string containing the last log messages. |
|
| `callList` | `String` | x | A string containing the call list as JSON (see below) |
|
||||||
|
| `deviceLog` | `String` | x | A string containing the last log messages |
|
||||||
| `dslCRCErrors` | `Number:Dimensionless` | x | DSL CRC Errors |
|
| `dslCRCErrors` | `Number:Dimensionless` | x | DSL CRC Errors |
|
||||||
| `dslDownstreamNoiseMargin` | `Number:Dimensionless` | x | DSL Downstream Noise Margin |
|
| `dslDownstreamNoiseMargin` | `Number:Dimensionless` | x | DSL Downstream Noise Margin |
|
||||||
| `dslDownstreamNoiseMargin` | `Number:Dimensionless` | x | DSL Downstream Attenuation |
|
| `dslDownstreamNoiseMargin` | `Number:Dimensionless` | x | DSL Downstream Attenuation |
|
||||||
@ -107,6 +108,12 @@ This is an optional parameter and multiple values are allowed.
|
|||||||
| `wifi5GHzEnable` | `Switch` | | Enable/Disable the 5.0 GHz WiFi device. |
|
| `wifi5GHzEnable` | `Switch` | | Enable/Disable the 5.0 GHz WiFi device. |
|
||||||
| `wifiGuestEnable` | `Switch` | | Enable/Disable the guest WiFi. |
|
| `wifiGuestEnable` | `Switch` | | Enable/Disable the guest WiFi. |
|
||||||
|
|
||||||
|
### Channel `callList`
|
||||||
|
|
||||||
|
Call lists are provided for one or more days (as configured) as JSON.
|
||||||
|
The JSON consists of an array of individual calls with the fields `date`, `type`, `localNumber`, `remoteNumber`, `duration`.
|
||||||
|
The call-types are the same as provided by the FritzBox, i.e. `1` (inbound), `2` (missed), `3` (outbound), `10` (rejected).
|
||||||
|
|
||||||
## `PHONEBOOK` Profile
|
## `PHONEBOOK` Profile
|
||||||
|
|
||||||
The binding provides a profile for using the FritzBox phonebooks for resolving numbers to names.
|
The binding provides a profile for using the FritzBox phonebooks for resolving numbers to names.
|
||||||
@ -117,3 +124,4 @@ If only a specific phonebook from the device should be used, this can be specifi
|
|||||||
The default is to use all available phonebooks from the specified thing.
|
The default is to use all available phonebooks from the specified thing.
|
||||||
In case the format of the number in the phonebook and the format of the number from the channel are different (e.g. regarding country prefixes), the `matchCount` parameter can be used.
|
In case the format of the number in the phonebook and the format of the number from the channel are different (e.g. regarding country prefixes), the `matchCount` parameter can be used.
|
||||||
The configured `matchCount` is counted from the right end and denotes the number of matching characters needed to consider this number as matching.
|
The configured `matchCount` is counted from the right end and denotes the number of matching characters needed to consider this number as matching.
|
||||||
|
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.tr064.internal;
|
|
||||||
|
|
||||||
import javax.net.ssl.X509ExtendedTrustManager;
|
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
|
||||||
import org.openhab.core.io.net.http.TlsTrustManagerProvider;
|
|
||||||
import org.openhab.core.io.net.http.TrustAllTrustManager;
|
|
||||||
import org.osgi.service.component.annotations.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a TrustManager to allow secure connections to any FRITZ!Box
|
|
||||||
*
|
|
||||||
* @author Christoph Weitkamp - Initial Contribution
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@NonNullByDefault
|
|
||||||
public class AVMFritzTlsTrustManagerProvider implements TlsTrustManagerProvider {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHostName() {
|
|
||||||
return "fritz.box";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public X509ExtendedTrustManager getTrustManager() {
|
|
||||||
return TrustAllTrustManager.getInstance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -21,8 +21,8 @@ import java.util.stream.Stream;
|
|||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.openhab.binding.tr064.internal.phonebook.PhonebookProfileFactory;
|
import org.openhab.binding.tr064.internal.phonebook.PhonebookProfileFactory;
|
||||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
@ -31,7 +31,10 @@ import org.openhab.core.thing.binding.ThingHandler;
|
|||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
import org.osgi.service.component.annotations.Activate;
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Deactivate;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link Tr064HandlerFactory} is responsible for creating things and thing
|
* The {@link Tr064HandlerFactory} is responsible for creating things and thing
|
||||||
@ -46,6 +49,7 @@ public class Tr064HandlerFactory extends BaseThingHandlerFactory {
|
|||||||
.of(Tr064RootHandler.SUPPORTED_THING_TYPES, Tr064SubHandler.SUPPORTED_THING_TYPES).flatMap(Set::stream)
|
.of(Tr064RootHandler.SUPPORTED_THING_TYPES, Tr064SubHandler.SUPPORTED_THING_TYPES).flatMap(Set::stream)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(Tr064HandlerFactory.class);
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
private final PhonebookProfileFactory phonebookProfileFactory;
|
private final PhonebookProfileFactory phonebookProfileFactory;
|
||||||
|
|
||||||
@ -56,12 +60,29 @@ public class Tr064HandlerFactory extends BaseThingHandlerFactory {
|
|||||||
private final Tr064ChannelTypeProvider channelTypeProvider;
|
private final Tr064ChannelTypeProvider channelTypeProvider;
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public Tr064HandlerFactory(@Reference HttpClientFactory httpClientFactory,
|
public Tr064HandlerFactory(@Reference Tr064ChannelTypeProvider channelTypeProvider,
|
||||||
@Reference Tr064ChannelTypeProvider channelTypeProvider,
|
|
||||||
@Reference PhonebookProfileFactory phonebookProfileFactory) {
|
@Reference PhonebookProfileFactory phonebookProfileFactory) {
|
||||||
httpClient = httpClientFactory.getCommonHttpClient();
|
|
||||||
this.channelTypeProvider = channelTypeProvider;
|
this.channelTypeProvider = channelTypeProvider;
|
||||||
this.phonebookProfileFactory = phonebookProfileFactory;
|
this.phonebookProfileFactory = phonebookProfileFactory;
|
||||||
|
// use an insecure client (i.e. without verifying the certificate)
|
||||||
|
this.httpClient = new HttpClient(new SslContextFactory(true));
|
||||||
|
try {
|
||||||
|
this.httpClient.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// catching exception is necessary due to the signature of HttpClient.start()
|
||||||
|
logger.warn("Failed to start http client: {}", e.getMessage());
|
||||||
|
throw new IllegalStateException("Could not create HttpClient instance.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deactivate
|
||||||
|
public void deactivate() {
|
||||||
|
try {
|
||||||
|
httpClient.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// catching exception is necessary due to the signature of HttpClient.stop()
|
||||||
|
logger.warn("Failed to stop http client: {}", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -40,6 +40,8 @@ import org.openhab.binding.tr064.internal.dto.scpd.service.SCPDActionType;
|
|||||||
import org.openhab.binding.tr064.internal.phonebook.Phonebook;
|
import org.openhab.binding.tr064.internal.phonebook.Phonebook;
|
||||||
import org.openhab.binding.tr064.internal.phonebook.PhonebookProvider;
|
import org.openhab.binding.tr064.internal.phonebook.PhonebookProvider;
|
||||||
import org.openhab.binding.tr064.internal.phonebook.Tr064PhonebookImpl;
|
import org.openhab.binding.tr064.internal.phonebook.Tr064PhonebookImpl;
|
||||||
|
import org.openhab.binding.tr064.internal.soap.SOAPConnector;
|
||||||
|
import org.openhab.binding.tr064.internal.soap.SOAPValueConverter;
|
||||||
import org.openhab.binding.tr064.internal.util.SCPDUtil;
|
import org.openhab.binding.tr064.internal.util.SCPDUtil;
|
||||||
import org.openhab.binding.tr064.internal.util.Util;
|
import org.openhab.binding.tr064.internal.util.Util;
|
||||||
import org.openhab.core.cache.ExpiringCacheMap;
|
import org.openhab.core.cache.ExpiringCacheMap;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||||||
import org.openhab.binding.tr064.internal.config.Tr064ChannelConfig;
|
import org.openhab.binding.tr064.internal.config.Tr064ChannelConfig;
|
||||||
import org.openhab.binding.tr064.internal.config.Tr064SubConfiguration;
|
import org.openhab.binding.tr064.internal.config.Tr064SubConfiguration;
|
||||||
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDDeviceType;
|
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDDeviceType;
|
||||||
|
import org.openhab.binding.tr064.internal.soap.SOAPConnector;
|
||||||
import org.openhab.binding.tr064.internal.util.SCPDUtil;
|
import org.openhab.binding.tr064.internal.util.SCPDUtil;
|
||||||
import org.openhab.binding.tr064.internal.util.Util;
|
import org.openhab.binding.tr064.internal.util.Util;
|
||||||
import org.openhab.core.cache.ExpiringCacheMap;
|
import org.openhab.core.cache.ExpiringCacheMap;
|
||||||
|
|||||||
@ -35,6 +35,7 @@ public class Tr064RootConfiguration extends Tr064BaseThingConfiguration {
|
|||||||
public List<String> rejectedCallDays = Collections.emptyList();
|
public List<String> rejectedCallDays = Collections.emptyList();
|
||||||
public List<String> inboundCallDays = Collections.emptyList();
|
public List<String> inboundCallDays = Collections.emptyList();
|
||||||
public List<String> outboundCallDays = Collections.emptyList();
|
public List<String> outboundCallDays = Collections.emptyList();
|
||||||
|
public List<String> callListDays = Collections.emptyList();
|
||||||
public int phonebookInterval = 0;
|
public int phonebookInterval = 0;
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
|
|||||||
@ -31,8 +31,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
|||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.openhab.binding.tr064.internal.dto.phonebook.NumberType;
|
import org.openhab.binding.tr064.internal.dto.additions.NumberType;
|
||||||
import org.openhab.binding.tr064.internal.dto.phonebook.PhonebooksType;
|
import org.openhab.binding.tr064.internal.dto.additions.PhonebooksType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|||||||
@ -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.tr064.internal.soap;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.tr064.internal.dto.additions.Call;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link CallListEntry} is used for post processing the retrieved call
|
||||||
|
* lists
|
||||||
|
*
|
||||||
|
* @author Jan N. Klug - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class CallListEntry {
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT_PARSER = new SimpleDateFormat("dd.MM.yy hh:mm");
|
||||||
|
public @Nullable String localNumber;
|
||||||
|
public @Nullable String remoteNumber;
|
||||||
|
public @Nullable Date date;
|
||||||
|
public @Nullable Integer type;
|
||||||
|
public @Nullable Integer duration;
|
||||||
|
|
||||||
|
public CallListEntry(Call call) {
|
||||||
|
try {
|
||||||
|
date = DATE_FORMAT_PARSER.parse(call.getDate());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
// ignore parsing error
|
||||||
|
date = null;
|
||||||
|
}
|
||||||
|
String[] durationParts = call.getDuration().split(":");
|
||||||
|
duration = Integer.parseInt(durationParts[0]) * 60 + Integer.parseInt(durationParts[1]);
|
||||||
|
type = Integer.parseInt(call.getType());
|
||||||
|
if (CallListType.OUTBOUND_COUNT.typeString().equals(call.getType())) {
|
||||||
|
localNumber = call.getCallerNumber();
|
||||||
|
remoteNumber = call.getCalled();
|
||||||
|
} else {
|
||||||
|
localNumber = call.getCalledNumber();
|
||||||
|
remoteNumber = call.getCaller();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.tr064.internal.soap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link CallListType} is used for post processing the retrieved call list
|
||||||
|
*
|
||||||
|
* @author Jan N. Klug - Initial contribution
|
||||||
|
*/
|
||||||
|
public enum CallListType {
|
||||||
|
MISSED_COUNT("2"),
|
||||||
|
INBOUND_COUNT("1"),
|
||||||
|
REJECTED_COUNT("10"),
|
||||||
|
OUTBOUND_COUNT("3"),
|
||||||
|
JSON_LIST("");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
CallListType(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String typeString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.tr064.internal;
|
package org.openhab.binding.tr064.internal.soap;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
@ -25,6 +25,10 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
|||||||
public class PostProcessingException extends Exception {
|
public class PostProcessingException extends Exception {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public PostProcessingException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
public PostProcessingException(String message, Throwable t) {
|
public PostProcessingException(String message, Throwable t) {
|
||||||
super(message, t);
|
super(message, t);
|
||||||
}
|
}
|
||||||
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.tr064.internal;
|
package org.openhab.binding.tr064.internal.soap;
|
||||||
|
|
||||||
import static org.openhab.binding.tr064.internal.util.Util.getSOAPElement;
|
import static org.openhab.binding.tr064.internal.util.Util.getSOAPElement;
|
||||||
|
|
||||||
@ -34,6 +34,7 @@ import org.eclipse.jetty.client.api.Request;
|
|||||||
import org.eclipse.jetty.client.util.BytesContentProvider;
|
import org.eclipse.jetty.client.util.BytesContentProvider;
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.openhab.binding.tr064.internal.Tr064CommunicationException;
|
||||||
import org.openhab.binding.tr064.internal.config.Tr064ChannelConfig;
|
import org.openhab.binding.tr064.internal.config.Tr064ChannelConfig;
|
||||||
import org.openhab.binding.tr064.internal.dto.config.ActionType;
|
import org.openhab.binding.tr064.internal.dto.config.ActionType;
|
||||||
import org.openhab.binding.tr064.internal.dto.config.ChannelTypeDescription;
|
import org.openhab.binding.tr064.internal.dto.config.ChannelTypeDescription;
|
||||||
@ -10,17 +10,19 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.tr064.internal;
|
package org.openhab.binding.tr064.internal.soap;
|
||||||
|
|
||||||
import static org.openhab.binding.tr064.internal.util.Util.getSOAPElement;
|
import static org.openhab.binding.tr064.internal.util.Util.getSOAPElement;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.xml.soap.SOAPMessage;
|
import javax.xml.soap.SOAPMessage;
|
||||||
|
|
||||||
@ -29,15 +31,22 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
import org.openhab.binding.tr064.internal.config.Tr064ChannelConfig;
|
import org.openhab.binding.tr064.internal.config.Tr064ChannelConfig;
|
||||||
|
import org.openhab.binding.tr064.internal.dto.additions.Call;
|
||||||
|
import org.openhab.binding.tr064.internal.dto.additions.Root;
|
||||||
|
import org.openhab.binding.tr064.internal.util.Util;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
import org.openhab.core.library.types.QuantityType;
|
||||||
import org.openhab.core.library.types.StringType;
|
import org.openhab.core.library.types.StringType;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
import org.openhab.core.types.UnDefType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SOAPValueConverter} converts SOAP values and openHAB states
|
* The {@link SOAPValueConverter} converts SOAP values and openHAB states
|
||||||
*
|
*
|
||||||
@ -189,7 +198,7 @@ public class SOAPValueConverter {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private State processMissedCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
private State processMissedCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
||||||
return processCallList(state, channelConfig.getParameter(), "2");
|
return processCallList(state, channelConfig.getParameter(), CallListType.MISSED_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,7 +211,7 @@ public class SOAPValueConverter {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private State processInboundCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
private State processInboundCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
||||||
return processCallList(state, channelConfig.getParameter(), "1");
|
return processCallList(state, channelConfig.getParameter(), CallListType.INBOUND_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -215,7 +224,7 @@ public class SOAPValueConverter {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private State processRejectedCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
private State processRejectedCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
||||||
return processCallList(state, channelConfig.getParameter(), "3");
|
return processCallList(state, channelConfig.getParameter(), CallListType.REJECTED_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -228,7 +237,20 @@ public class SOAPValueConverter {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private State processOutboundCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
private State processOutboundCalls(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
||||||
return processCallList(state, channelConfig.getParameter(), "4");
|
return processCallList(state, channelConfig.getParameter(), CallListType.OUTBOUND_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post processor for JSON call list
|
||||||
|
*
|
||||||
|
* @param state the call list URL
|
||||||
|
* @param channelConfig channel config of the call list channel (contains day number)
|
||||||
|
* @return caller list in JSON format
|
||||||
|
* @throws PostProcessingException if call list could not be retrieved
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private State processCallListJSON(State state, Tr064ChannelConfig channelConfig) throws PostProcessingException {
|
||||||
|
return processCallList(state, channelConfig.getParameter(), CallListType.JSON_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,20 +258,30 @@ public class SOAPValueConverter {
|
|||||||
*
|
*
|
||||||
* @param state the call list URL
|
* @param state the call list URL
|
||||||
* @param days number of days to get
|
* @param days number of days to get
|
||||||
* @param type type of call (1=missed 2=inbound 3=rejected 4=outbund)
|
* @param type type of call (2=missed 1=inbound 4=rejected 3=outbund)
|
||||||
* @return the quantity of calls of the given type within the given number of days
|
* @return the quantity of calls of the given type within the given number of days
|
||||||
* @throws PostProcessingException if the call list could not be retrieved
|
* @throws PostProcessingException if the call list could not be retrieved
|
||||||
*/
|
*/
|
||||||
private State processCallList(State state, @Nullable String days, String type) throws PostProcessingException {
|
private State processCallList(State state, @Nullable String days, CallListType type)
|
||||||
try {
|
throws PostProcessingException {
|
||||||
ContentResponse response = httpClient.newRequest(state.toString() + "&days=" + days)
|
Root callListRoot = Util.getAndUnmarshalXML(httpClient, state.toString() + "&days=" + days, Root.class);
|
||||||
.timeout(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS).send();
|
if (callListRoot == null) {
|
||||||
String responseContent = response.getContentAsString();
|
throw new PostProcessingException("Failed to get call list from URL " + state.toString());
|
||||||
int callCount = responseContent.split("<Type>" + type + "</Type>").length - 1;
|
|
||||||
|
|
||||||
return new DecimalType(callCount);
|
|
||||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
|
||||||
throw new PostProcessingException("Failed to get call list from URL " + state.toString(), e);
|
|
||||||
}
|
}
|
||||||
|
List<Call> calls = callListRoot.getCall();
|
||||||
|
switch (type) {
|
||||||
|
case INBOUND_COUNT:
|
||||||
|
case MISSED_COUNT:
|
||||||
|
case OUTBOUND_COUNT:
|
||||||
|
case REJECTED_COUNT:
|
||||||
|
long callCount = calls.stream().filter(call -> type.typeString().equals(call.getType())).count();
|
||||||
|
return new DecimalType(callCount);
|
||||||
|
case JSON_LIST:
|
||||||
|
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssX").serializeNulls().create();
|
||||||
|
List<CallListEntry> callListEntries = calls.stream().map(CallListEntry::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return new StringType(gson.toJson(callListEntries));
|
||||||
|
}
|
||||||
|
return UnDefType.UNDEF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,36 +12,21 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.tr064.internal.util;
|
package org.openhab.binding.tr064.internal.util;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import javax.xml.transform.stream.StreamSource;
|
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
|
||||||
import org.openhab.binding.tr064.internal.SCPDException;
|
import org.openhab.binding.tr064.internal.SCPDException;
|
||||||
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDDeviceType;
|
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDDeviceType;
|
||||||
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDRootType;
|
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDRootType;
|
||||||
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDServiceType;
|
import org.openhab.binding.tr064.internal.dto.scpd.root.SCPDServiceType;
|
||||||
import org.openhab.binding.tr064.internal.dto.scpd.service.SCPDScpdType;
|
import org.openhab.binding.tr064.internal.dto.scpd.service.SCPDScpdType;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SCPDUtil} is responsible for handling commands, which are
|
* The {@link SCPDUtil} is responsible for handling commands, which are
|
||||||
@ -51,18 +36,12 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SCPDUtil {
|
public class SCPDUtil {
|
||||||
private final Logger logger = LoggerFactory.getLogger(SCPDUtil.class);
|
|
||||||
|
|
||||||
private final HttpClient httpClient;
|
|
||||||
|
|
||||||
private SCPDRootType scpdRoot;
|
private SCPDRootType scpdRoot;
|
||||||
private final List<SCPDDeviceType> scpdDevicesList = new ArrayList<>();
|
private final List<SCPDDeviceType> scpdDevicesList = new ArrayList<>();
|
||||||
private final Map<String, SCPDScpdType> serviceMap = new HashMap<>();
|
private final Map<String, SCPDScpdType> serviceMap = new HashMap<>();
|
||||||
|
|
||||||
public SCPDUtil(HttpClient httpClient, String endpoint) throws SCPDException {
|
public SCPDUtil(HttpClient httpClient, String endpoint) throws SCPDException {
|
||||||
this.httpClient = httpClient;
|
SCPDRootType scpdRoot = Util.getAndUnmarshalXML(httpClient, endpoint + "/tr64desc.xml", SCPDRootType.class);
|
||||||
|
|
||||||
SCPDRootType scpdRoot = getAndUnmarshalSCPD(endpoint + "/tr64desc.xml", SCPDRootType.class);
|
|
||||||
if (scpdRoot == null) {
|
if (scpdRoot == null) {
|
||||||
throw new SCPDException("could not get SCPD root");
|
throw new SCPDException("could not get SCPD root");
|
||||||
}
|
}
|
||||||
@ -71,8 +50,8 @@ public class SCPDUtil {
|
|||||||
scpdDevicesList.addAll(flatDeviceList(scpdRoot.getDevice()).collect(Collectors.toList()));
|
scpdDevicesList.addAll(flatDeviceList(scpdRoot.getDevice()).collect(Collectors.toList()));
|
||||||
for (SCPDDeviceType device : scpdDevicesList) {
|
for (SCPDDeviceType device : scpdDevicesList) {
|
||||||
for (SCPDServiceType service : device.getServiceList()) {
|
for (SCPDServiceType service : device.getServiceList()) {
|
||||||
SCPDScpdType scpd = serviceMap.computeIfAbsent(service.getServiceId(),
|
SCPDScpdType scpd = serviceMap.computeIfAbsent(service.getServiceId(), serviceId -> Util
|
||||||
serviceId -> getAndUnmarshalSCPD(endpoint + service.getSCPDURL(), SCPDScpdType.class));
|
.getAndUnmarshalXML(httpClient, endpoint + service.getSCPDURL(), SCPDScpdType.class));
|
||||||
if (scpd == null) {
|
if (scpd == null) {
|
||||||
throw new SCPDException("could not get SCPD service");
|
throw new SCPDException("could not get SCPD service");
|
||||||
}
|
}
|
||||||
@ -80,30 +59,6 @@ public class SCPDUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* generic unmarshaller
|
|
||||||
*
|
|
||||||
* @param uri the uri of the XML file
|
|
||||||
* @param clazz the class describing the XML file
|
|
||||||
* @return unmarshalling result
|
|
||||||
*/
|
|
||||||
private <T> @Nullable T getAndUnmarshalSCPD(String uri, Class<T> clazz) {
|
|
||||||
try {
|
|
||||||
ContentResponse contentResponse = httpClient.newRequest(uri).timeout(2, TimeUnit.SECONDS)
|
|
||||||
.method(HttpMethod.GET).send();
|
|
||||||
InputStream xml = new ByteArrayInputStream(contentResponse.getContent());
|
|
||||||
|
|
||||||
JAXBContext context = JAXBContext.newInstance(clazz);
|
|
||||||
Unmarshaller um = context.createUnmarshaller();
|
|
||||||
return um.unmarshal(new StreamSource(xml), clazz).getValue();
|
|
||||||
} catch (ExecutionException | InterruptedException | TimeoutException e) {
|
|
||||||
logger.debug("HTTP Failed to GET uri '{}': {}", uri, e.getMessage());
|
|
||||||
} catch (JAXBException e) {
|
|
||||||
logger.debug("Unmarshalling failed: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* recursively flatten the device tree to a stream
|
* recursively flatten the device tree to a stream
|
||||||
*
|
*
|
||||||
|
|||||||
@ -14,9 +14,13 @@ package org.openhab.binding.tr064.internal.util;
|
|||||||
|
|
||||||
import static org.openhab.binding.tr064.internal.Tr064BindingConstants.*;
|
import static org.openhab.binding.tr064.internal.Tr064BindingConstants.*;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@ -29,6 +33,10 @@ import javax.xml.soap.SOAPMessage;
|
|||||||
import javax.xml.transform.stream.StreamSource;
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.openhab.binding.tr064.internal.ChannelConfigException;
|
import org.openhab.binding.tr064.internal.ChannelConfigException;
|
||||||
import org.openhab.binding.tr064.internal.Tr064RootHandler;
|
import org.openhab.binding.tr064.internal.Tr064RootHandler;
|
||||||
import org.openhab.binding.tr064.internal.config.Tr064BaseThingConfiguration;
|
import org.openhab.binding.tr064.internal.config.Tr064BaseThingConfiguration;
|
||||||
@ -75,7 +83,7 @@ public class Util {
|
|||||||
return root.getValue().getChannel();
|
return root.getValue().getChannel();
|
||||||
} catch (JAXBException e) {
|
} catch (JAXBException e) {
|
||||||
LOGGER.warn("Failed to read channel definitions", e);
|
LOGGER.warn("Failed to read channel definitions", e);
|
||||||
return Collections.emptyList();
|
return List.of();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +282,7 @@ public class Util {
|
|||||||
}
|
}
|
||||||
return parameters;
|
return parameters;
|
||||||
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
|
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
|
||||||
throw new ChannelConfigException("Could not get required parameter '" + channelId
|
throw new ChannelConfigException("Could not get required parameter for channel '" + channelId
|
||||||
+ "' from thing config (missing, empty or invalid)");
|
+ "' from thing config (missing, empty or invalid)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,4 +298,32 @@ public class Util {
|
|||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generic unmarshaller
|
||||||
|
*
|
||||||
|
* @param uri the uri of the XML file
|
||||||
|
* @param clazz the class describing the XML file
|
||||||
|
* @return unmarshalling result
|
||||||
|
*/
|
||||||
|
public static <T> @Nullable T getAndUnmarshalXML(HttpClient httpClient, String uri, Class<T> clazz) {
|
||||||
|
try {
|
||||||
|
ContentResponse contentResponse = httpClient.newRequest(uri).timeout(2, TimeUnit.SECONDS)
|
||||||
|
.method(HttpMethod.GET).send();
|
||||||
|
byte[] response = contentResponse.getContent();
|
||||||
|
if (LOGGER.isTraceEnabled()) {
|
||||||
|
LOGGER.trace("XML = {}", new String(response));
|
||||||
|
}
|
||||||
|
InputStream xml = new ByteArrayInputStream(response);
|
||||||
|
|
||||||
|
JAXBContext context = JAXBContext.newInstance(clazz);
|
||||||
|
Unmarshaller um = context.createUnmarshaller();
|
||||||
|
return um.unmarshal(new StreamSource(xml), clazz).getValue();
|
||||||
|
} catch (ExecutionException | InterruptedException | TimeoutException e) {
|
||||||
|
LOGGER.debug("HTTP Failed to GET uri '{}': {}", uri, e.getMessage());
|
||||||
|
} catch (JAXBException e) {
|
||||||
|
LOGGER.debug("Unmarshalling failed: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,6 +82,11 @@
|
|||||||
<description>List of days for which outbound calls should be calculated.</description>
|
<description>List of days for which outbound calls should be calculated.</description>
|
||||||
<advanced>true</advanced>
|
<advanced>true</advanced>
|
||||||
</parameter>
|
</parameter>
|
||||||
|
<parameter name="callListDays" type="text" multiple="true">
|
||||||
|
<label>Call List Days</label>
|
||||||
|
<description>List of days for which JSON call list should be generated.</description>
|
||||||
|
<advanced>true</advanced>
|
||||||
|
</parameter>
|
||||||
<parameter name="wanBlockIPs" type="text" multiple="true">
|
<parameter name="wanBlockIPs" type="text" multiple="true">
|
||||||
<label>WAN Block IPs</label>
|
<label>WAN Block IPs</label>
|
||||||
<description>List of IPs that can be blocked for WAN access.</description>
|
<description>List of IPs that can be blocked for WAN access.</description>
|
||||||
|
|||||||
@ -106,6 +106,14 @@
|
|||||||
<parameter name="CallDays" thingParameter="outboundCallDays" pattern="[0-9]+" internalOnly="true"/>
|
<parameter name="CallDays" thingParameter="outboundCallDays" pattern="[0-9]+" internalOnly="true"/>
|
||||||
</getAction>
|
</getAction>
|
||||||
</channel>
|
</channel>
|
||||||
|
<channel name="callList" label="Call List" description="Call list in JSON format for the given number of days.">
|
||||||
|
<item type="String"/>
|
||||||
|
<service deviceType="urn:dslforum-org:device:InternetGatewayDevice:1"
|
||||||
|
serviceId="urn:X_AVM-DE_OnTel-com:serviceId:X_AVM-DE_OnTel1"/>
|
||||||
|
<getAction name="GetCallList" argument="NewCallListURL" postProcessor="processCallListJSON">
|
||||||
|
<parameter name="CallDays" thingParameter="callListDays" pattern="[0-9]+" internalOnly="true"/>
|
||||||
|
</getAction>
|
||||||
|
</channel>
|
||||||
|
|
||||||
<!-- LAN Device -->
|
<!-- LAN Device -->
|
||||||
<channel name="wifi24GHzEnable" label="WiFi 2.4 GHz" description="Enable/Disable the 2.4 GHz WiFi device.">
|
<channel name="wifi24GHzEnable" label="WiFi 2.4 GHz" description="Enable/Disable the 2.4 GHz WiFi device.">
|
||||||
|
|||||||
@ -51,4 +51,47 @@
|
|||||||
<xs:element type="phonebookType" name="phonebook"/>
|
<xs:element type="phonebookType" name="phonebook"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
<xs:element name="root">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element ref="timestamp"/>
|
||||||
|
<xs:element maxOccurs="unbounded" ref="Call"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="timestamp" type="xs:integer"/>
|
||||||
|
<xs:element name="Call">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element ref="Id"/>
|
||||||
|
<xs:element ref="Type"/>
|
||||||
|
<xs:element ref="Called"/>
|
||||||
|
<xs:element ref="Caller"/>
|
||||||
|
<xs:element ref="CalledNumber"/>
|
||||||
|
<xs:element ref="CallerNumber"/>
|
||||||
|
<xs:element ref="Name"/>
|
||||||
|
<xs:element ref="Numbertype"/>
|
||||||
|
<xs:element ref="Device"/>
|
||||||
|
<xs:element ref="Port"/>
|
||||||
|
<xs:element ref="Date"/>
|
||||||
|
<xs:element ref="Duration"/>
|
||||||
|
<xs:element ref="Count"/>
|
||||||
|
<xs:element ref="Path"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Id" type="xs:integer"/>
|
||||||
|
<xs:element name="Type" type="xs:string"/>
|
||||||
|
<xs:element name="Called" type="xs:string"/>
|
||||||
|
<xs:element name="Caller" type="xs:string"/>
|
||||||
|
<xs:element name="CalledNumber" type="xs:string"/>
|
||||||
|
<xs:element name="CallerNumber" type="xs:string"/>
|
||||||
|
<xs:element name="Name" type="xs:string" />
|
||||||
|
<xs:element name="Numbertype" type="xs:string"/>
|
||||||
|
<xs:element name="Device" type="xs:string"/>
|
||||||
|
<xs:element name="Port" type="xs:string"/>
|
||||||
|
<xs:element name="Date" type="xs:string"/>
|
||||||
|
<xs:element name="Duration" type="xs:string"/>
|
||||||
|
<xs:element name="Count" type="xs:string"/>
|
||||||
|
<xs:element name="Path" type = "xs:string"/>
|
||||||
</xs:schema>
|
</xs:schema>
|
||||||
@ -4,9 +4,10 @@
|
|||||||
<xjc:serializable uid="1"/>
|
<xjc:serializable uid="1"/>
|
||||||
</jaxb:globalBindings>
|
</jaxb:globalBindings>
|
||||||
|
|
||||||
<jaxb:bindings schemaLocation="phonebook.xsd">
|
<!-- additions (without namespace): phonebook, calllist -->
|
||||||
|
<jaxb:bindings schemaLocation="additions.xsd">
|
||||||
<jaxb:schemaBindings>
|
<jaxb:schemaBindings>
|
||||||
<jaxb:package name="org.openhab.binding.tr064.internal.dto.phonebook"/>
|
<jaxb:package name="org.openhab.binding.tr064.internal.dto.additions"/>
|
||||||
</jaxb:schemaBindings>
|
</jaxb:schemaBindings>
|
||||||
</jaxb:bindings>
|
</jaxb:bindings>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user