mirror of
https://gitcode.com/gh_mirrors/on/onvif.git
synced 2026-05-14 03:02:30 +00:00
some findbug edits and google style applied
This commit is contained in:
@@ -2,54 +2,78 @@ package de.onvif.beans;
|
||||
|
||||
public class DeviceInfo {
|
||||
|
||||
private String manufacturer;
|
||||
private String model;
|
||||
private String firmwareVersion;
|
||||
private String serialNumber;
|
||||
private String hardwareId;
|
||||
|
||||
public DeviceInfo(String manufacturer, String model, String firmwareVersion, String serialNumber,
|
||||
String hardwareId) {
|
||||
super();
|
||||
this.manufacturer = manufacturer;
|
||||
this.model = model;
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
this.serialNumber = serialNumber;
|
||||
this.hardwareId = hardwareId;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceInfo [manufacturer=" + manufacturer + ", model=" + model + ", firmwareVersion=" + firmwareVersion
|
||||
+ ", serialNumber=" + serialNumber + ", hardwareId=" + hardwareId + "]";
|
||||
}
|
||||
public String getManufacturer() {
|
||||
return manufacturer;
|
||||
}
|
||||
public void setManufacturer(String manufacturer) {
|
||||
this.manufacturer = manufacturer;
|
||||
}
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
public String getFirmwareVersion() {
|
||||
return firmwareVersion;
|
||||
}
|
||||
public void setFirmwareVersion(String firmwareVersion) {
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
}
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
public void setSerialNumber(String serialNumber) {
|
||||
this.serialNumber = serialNumber;
|
||||
}
|
||||
public String getHardwareId() {
|
||||
return hardwareId;
|
||||
}
|
||||
public void setHardwareId(String hardwareId) {
|
||||
this.hardwareId = hardwareId;
|
||||
}
|
||||
private String manufacturer;
|
||||
private String model;
|
||||
private String firmwareVersion;
|
||||
private String serialNumber;
|
||||
private String hardwareId;
|
||||
|
||||
public DeviceInfo(
|
||||
String manufacturer,
|
||||
String model,
|
||||
String firmwareVersion,
|
||||
String serialNumber,
|
||||
String hardwareId) {
|
||||
super();
|
||||
this.manufacturer = manufacturer;
|
||||
this.model = model;
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
this.serialNumber = serialNumber;
|
||||
this.hardwareId = hardwareId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceInfo [manufacturer="
|
||||
+ manufacturer
|
||||
+ ", model="
|
||||
+ model
|
||||
+ ", firmwareVersion="
|
||||
+ firmwareVersion
|
||||
+ ", serialNumber="
|
||||
+ serialNumber
|
||||
+ ", hardwareId="
|
||||
+ hardwareId
|
||||
+ "]";
|
||||
}
|
||||
|
||||
public String getManufacturer() {
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
public void setManufacturer(String manufacturer) {
|
||||
this.manufacturer = manufacturer;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getFirmwareVersion() {
|
||||
return firmwareVersion;
|
||||
}
|
||||
|
||||
public void setFirmwareVersion(String firmwareVersion) {
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public void setSerialNumber(String serialNumber) {
|
||||
this.serialNumber = serialNumber;
|
||||
}
|
||||
|
||||
public String getHardwareId() {
|
||||
return hardwareId;
|
||||
}
|
||||
|
||||
public void setHardwareId(String hardwareId) {
|
||||
this.hardwareId = hardwareId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,41 @@
|
||||
package de.onvif.discovery;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.soap.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InterfaceAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.soap.MimeHeaders;
|
||||
import javax.xml.soap.SOAPBody;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Device discovery class to list local accessible devices probed per UDP probe messages.
|
||||
@@ -20,193 +46,207 @@ import java.util.concurrent.*;
|
||||
*/
|
||||
@SuppressWarnings({"unused", "UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"})
|
||||
public class DeviceDiscovery {
|
||||
public static String WS_DISCOVERY_SOAP_VERSION = "SOAP 1.2 Protocol";
|
||||
public static String WS_DISCOVERY_CONTENT_TYPE = "application/soap+xml";
|
||||
public static int WS_DISCOVERY_TIMEOUT = 4000;
|
||||
public static int WS_DISCOVERY_PORT = 3702;
|
||||
public static String WS_DISCOVERY_ADDRESS_IPv4 = "239.255.255.250";
|
||||
public static final String WS_DISCOVERY_SOAP_VERSION = "SOAP 1.2 Protocol";
|
||||
public static final String WS_DISCOVERY_CONTENT_TYPE = "application/soap+xml";
|
||||
public static final int WS_DISCOVERY_TIMEOUT = 4000;
|
||||
public static final int WS_DISCOVERY_PORT = 3702;
|
||||
public static final String WS_DISCOVERY_ADDRESS_IPv4 = "239.255.255.250";
|
||||
|
||||
/**
|
||||
* IPv6 not supported yet. set enableIPv6 to true for testing if you need IP6 discovery.
|
||||
*/
|
||||
public static boolean enableIPv6 = false;
|
||||
public static String WS_DISCOVERY_ADDRESS_IPv6 = "[FF02::C]";
|
||||
public static String WS_DISCOVERY_PROBE_MESSAGE = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:tns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\"><soap:Header><wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action><wsa:MessageID>urn:uuid:c032cfdd-c3ca-49dc-820e-ee6696ad63e2</wsa:MessageID><wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To></soap:Header><soap:Body><tns:Probe/></soap:Body></soap:Envelope>";
|
||||
private static final Random random = new SecureRandom();
|
||||
/** IPv6 not supported yet. set enableIPv6 to true for testing if you need IP6 discovery. */
|
||||
public static final boolean enableIPv6 = false;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
for (URL url : discoverWsDevicesAsUrls()) {
|
||||
System.out.println("Device discovered: " + url.toString());
|
||||
}
|
||||
}
|
||||
public static final String WS_DISCOVERY_ADDRESS_IPv6 = "[FF02::C]";
|
||||
public static final String WS_DISCOVERY_PROBE_MESSAGE =
|
||||
"<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:tns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\"><soap:Header><wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action><wsa:MessageID>urn:uuid:c032cfdd-c3ca-49dc-820e-ee6696ad63e2</wsa:MessageID><wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To></soap:Header><soap:Body><tns:Probe/></soap:Body></soap:Envelope>";
|
||||
private static final Random random = new SecureRandom();
|
||||
|
||||
/**
|
||||
* Discover WS device on the local network and returns Urls
|
||||
*
|
||||
* @return list of unique device urls
|
||||
*/
|
||||
public static Collection<URL> discoverWsDevicesAsUrls() {
|
||||
return discoverWsDevicesAsUrls("", "");
|
||||
}
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
for (URL url : discoverWsDevicesAsUrls()) {
|
||||
System.out.println("Device discovered: " + url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover WS device on the local network with specified filter
|
||||
*
|
||||
* @param regexpProtocol url protocol matching regexp like "^http$", might be empty ""
|
||||
* @param regexpPath url path matching regexp like "onvif", might be empty ""
|
||||
* @return list of unique device urls filtered
|
||||
*/
|
||||
public static Collection<URL> discoverWsDevicesAsUrls(String regexpProtocol, String regexpPath) {
|
||||
final Collection<URL> urls = new TreeSet<>(new Comparator<URL>() {
|
||||
public int compare(URL o1, URL o2) {
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
});
|
||||
for (String key : discoverWsDevices()) {
|
||||
try {
|
||||
final URL url = new URL(key);
|
||||
boolean ok = true;
|
||||
if (regexpProtocol.length() > 0 && !url.getProtocol().matches(regexpProtocol))
|
||||
ok = false;
|
||||
if (regexpPath.length() > 0 && !url.getPath().matches(regexpPath))
|
||||
ok = false;
|
||||
// ignore ip6 hosts
|
||||
if (ok && !enableIPv6 && url.getHost().startsWith("["))
|
||||
ok = false;
|
||||
if (ok) urls.add(url);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
/**
|
||||
* Discover WS device on the local network and returns Urls
|
||||
*
|
||||
* @return list of unique device urls
|
||||
*/
|
||||
public static Collection<URL> discoverWsDevicesAsUrls() {
|
||||
return discoverWsDevicesAsUrls("", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover WS device on the local network
|
||||
*
|
||||
* @return list of unique devices access strings which might be URLs in most cases
|
||||
*/
|
||||
public static Collection<String> discoverWsDevices() {
|
||||
final Collection<String> addresses = new ConcurrentSkipListSet<>();
|
||||
final CountDownLatch serverStarted = new CountDownLatch(1);
|
||||
final CountDownLatch serverFinished = new CountDownLatch(1);
|
||||
final Collection<InetAddress> addressList = new ArrayList<>();
|
||||
try {
|
||||
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
if (interfaces != null) {
|
||||
while (interfaces.hasMoreElements()) {
|
||||
NetworkInterface anInterface = interfaces.nextElement();
|
||||
if (!anInterface.isLoopback()) {
|
||||
final List<InterfaceAddress> interfaceAddresses = anInterface.getInterfaceAddresses();
|
||||
for (InterfaceAddress address : interfaceAddresses) {
|
||||
Class clz = address.getAddress().getClass();
|
||||
/**
|
||||
* Discover WS device on the local network with specified filter
|
||||
*
|
||||
* @param regexpProtocol url protocol matching regexp like "^http$", might be empty ""
|
||||
* @param regexpPath url path matching regexp like "onvif", might be empty ""
|
||||
* @return list of unique device urls filtered
|
||||
*/
|
||||
public static Collection<URL> discoverWsDevicesAsUrls(String regexpProtocol, String regexpPath) {
|
||||
final Collection<URL> urls =
|
||||
new TreeSet<>(
|
||||
new Comparator<URL>() {
|
||||
public int compare(URL o1, URL o2) {
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
});
|
||||
for (String key : discoverWsDevices()) {
|
||||
try {
|
||||
final URL url = new URL(key);
|
||||
boolean ok = true;
|
||||
if (regexpProtocol.length() > 0 && !url.getProtocol().matches(regexpProtocol)) ok = false;
|
||||
if (regexpPath.length() > 0 && !url.getPath().matches(regexpPath)) ok = false;
|
||||
// ignore ip6 hosts
|
||||
if (ok && !enableIPv6 && url.getHost().startsWith("[")) ok = false;
|
||||
if (ok) urls.add(url);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
if (!enableIPv6 && address.getAddress() instanceof Inet6Address)
|
||||
continue;
|
||||
addressList.add(address.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/**
|
||||
* Discover WS device on the local network
|
||||
*
|
||||
* @return list of unique devices access strings which might be URLs in most cases
|
||||
*/
|
||||
public static Collection<String> discoverWsDevices() {
|
||||
final Collection<String> addresses = new ConcurrentSkipListSet<>();
|
||||
final CountDownLatch serverStarted = new CountDownLatch(1);
|
||||
final CountDownLatch serverFinished = new CountDownLatch(1);
|
||||
final Collection<InetAddress> addressList = new ArrayList<>();
|
||||
try {
|
||||
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
if (interfaces != null) {
|
||||
while (interfaces.hasMoreElements()) {
|
||||
NetworkInterface anInterface = interfaces.nextElement();
|
||||
if (!anInterface.isLoopback()) {
|
||||
final List<InterfaceAddress> interfaceAddresses = anInterface.getInterfaceAddresses();
|
||||
for (InterfaceAddress address : interfaceAddresses) {
|
||||
Class clz = address.getAddress().getClass();
|
||||
|
||||
if (!enableIPv6 && address.getAddress() instanceof Inet6Address) continue;
|
||||
addressList.add(address.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
for (final InetAddress address : addressList) {
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
final String probe = WS_DISCOVERY_PROBE_MESSAGE.replaceAll("<wsa:MessageID>urn:uuid:.*</wsa:MessageID>", "<wsa:MessageID>urn:uuid:" + uuid + "</wsa:MessageID>");
|
||||
final int port = random.nextInt(20000) + 40000;
|
||||
@SuppressWarnings("SocketOpenedButNotSafelyClosed") final DatagramSocket server = new DatagramSocket(port, address);
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
final DatagramPacket packet = new DatagramPacket(new byte[4096], 4096);
|
||||
server.setSoTimeout(WS_DISCOVERY_TIMEOUT);
|
||||
long timerStarted = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - timerStarted < (WS_DISCOVERY_TIMEOUT)) {
|
||||
serverStarted.countDown();
|
||||
server.receive(packet);
|
||||
final Collection<String> collection = parseSoapResponseForUrls(Arrays.copyOf(packet.getData(), packet.getLength()));
|
||||
for (String key : collection) {
|
||||
addresses.add(key);
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException ignored) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
serverFinished.countDown();
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
try {
|
||||
serverStarted.await(1000, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (address instanceof Inet4Address) {
|
||||
server.send(new DatagramPacket(probe.getBytes(), probe.length(), InetAddress.getByName(WS_DISCOVERY_ADDRESS_IPv4), WS_DISCOVERY_PORT));
|
||||
} else {
|
||||
if (address instanceof Inet6Address) {
|
||||
if (enableIPv6)
|
||||
server.send(new DatagramPacket(probe.getBytes(), probe.length(), InetAddress.getByName(WS_DISCOVERY_ADDRESS_IPv6), WS_DISCOVERY_PORT));
|
||||
} else
|
||||
{
|
||||
assert(false); // unknown network type.. ignore or warn developer
|
||||
}
|
||||
}
|
||||
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
for (final InetAddress address : addressList) {
|
||||
Runnable runnable =
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
final String probe =
|
||||
WS_DISCOVERY_PROBE_MESSAGE.replaceAll(
|
||||
"<wsa:MessageID>urn:uuid:.*</wsa:MessageID>",
|
||||
"<wsa:MessageID>urn:uuid:" + uuid + "</wsa:MessageID>");
|
||||
final int port = random.nextInt(20000) + 40000;
|
||||
@SuppressWarnings("SocketOpenedButNotSafelyClosed")
|
||||
final DatagramSocket server = new DatagramSocket(port, address);
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
final DatagramPacket packet = new DatagramPacket(new byte[4096], 4096);
|
||||
server.setSoTimeout(WS_DISCOVERY_TIMEOUT);
|
||||
long timerStarted = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - timerStarted < (WS_DISCOVERY_TIMEOUT)) {
|
||||
serverStarted.countDown();
|
||||
server.receive(packet);
|
||||
final Collection<String> collection =
|
||||
parseSoapResponseForUrls(
|
||||
Arrays.copyOf(packet.getData(), packet.getLength()));
|
||||
for (String key : collection) {
|
||||
addresses.add(key);
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException ignored) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
serverFinished.countDown();
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
try {
|
||||
serverStarted.await(1000, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (address instanceof Inet4Address) {
|
||||
server.send(
|
||||
new DatagramPacket(
|
||||
probe.getBytes(StandardCharsets.UTF_8),
|
||||
probe.length(),
|
||||
InetAddress.getByName(WS_DISCOVERY_ADDRESS_IPv4),
|
||||
WS_DISCOVERY_PORT));
|
||||
} else {
|
||||
if (address instanceof Inet6Address) {
|
||||
if (enableIPv6)
|
||||
server.send(
|
||||
new DatagramPacket(
|
||||
probe.getBytes(StandardCharsets.UTF_8),
|
||||
probe.length(),
|
||||
InetAddress.getByName(WS_DISCOVERY_ADDRESS_IPv6),
|
||||
WS_DISCOVERY_PORT));
|
||||
} else {
|
||||
assert (false); // unknown network type.. ignore or warn developer
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
serverFinished.await((WS_DISCOVERY_TIMEOUT), TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
executorService.submit(runnable);
|
||||
}
|
||||
try {
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(WS_DISCOVERY_TIMEOUT + 2000, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
serverFinished.await((WS_DISCOVERY_TIMEOUT), TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
executorService.submit(runnable);
|
||||
}
|
||||
try {
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(WS_DISCOVERY_TIMEOUT + 2000, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private static Collection<Node> getNodeMatching(Node body, String regexp) {
|
||||
final Collection<Node> nodes = new ArrayList<>();
|
||||
if (body.getNodeName().matches(regexp)) nodes.add(body);
|
||||
if (body.getChildNodes().getLength() == 0) return nodes;
|
||||
NodeList returnList = body.getChildNodes();
|
||||
for (int k = 0; k < returnList.getLength(); k++) {
|
||||
final Node node = returnList.item(k);
|
||||
nodes.addAll(getNodeMatching(node, regexp));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
private static Collection<Node> getNodeMatching(Node body, String regexp) {
|
||||
final Collection<Node> nodes = new ArrayList<>();
|
||||
if (body.getNodeName().matches(regexp)) nodes.add(body);
|
||||
if (body.getChildNodes().getLength() == 0) return nodes;
|
||||
NodeList returnList = body.getChildNodes();
|
||||
for (int k = 0; k < returnList.getLength(); k++) {
|
||||
final Node node = returnList.item(k);
|
||||
nodes.addAll(getNodeMatching(node, regexp));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static Collection<String> parseSoapResponseForUrls(byte[] data) throws SOAPException, IOException {
|
||||
//System.out.println(new String(data));
|
||||
final Collection<String> urls = new ArrayList<>();
|
||||
MessageFactory factory = MessageFactory.newInstance(WS_DISCOVERY_SOAP_VERSION);
|
||||
final MimeHeaders headers = new MimeHeaders();
|
||||
headers.addHeader("Content-type", WS_DISCOVERY_CONTENT_TYPE);
|
||||
SOAPMessage message = factory.createMessage(headers, new ByteArrayInputStream(data));
|
||||
SOAPBody body = message.getSOAPBody();
|
||||
for (Node node : getNodeMatching(body, ".*:XAddrs")) {
|
||||
if (node.getTextContent().length() > 0) {
|
||||
urls.addAll(Arrays.asList(node.getTextContent().split(" ")));
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
private static Collection<String> parseSoapResponseForUrls(byte[] data)
|
||||
throws SOAPException, IOException {
|
||||
// System.out.println(new String(data));
|
||||
final Collection<String> urls = new ArrayList<>();
|
||||
MessageFactory factory = MessageFactory.newInstance(WS_DISCOVERY_SOAP_VERSION);
|
||||
final MimeHeaders headers = new MimeHeaders();
|
||||
headers.addHeader("Content-type", WS_DISCOVERY_CONTENT_TYPE);
|
||||
SOAPMessage message = factory.createMessage(headers, new ByteArrayInputStream(data));
|
||||
SOAPBody body = message.getSOAPBody();
|
||||
for (Node node : getNodeMatching(body, ".*:XAddrs")) {
|
||||
if (node.getTextContent().length() > 0) {
|
||||
urls.addAll(Arrays.asList(node.getTextContent().split(" ")));
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,13 @@ package de.onvif.discovery;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* @author th
|
||||
* @date 2015-06-18
|
||||
*/
|
||||
public class OnvifDiscovery {
|
||||
|
||||
public static Collection<URL> discoverOnvifURLs() {
|
||||
return DeviceDiscovery.discoverWsDevicesAsUrls("^http$", ".*onvif.*");
|
||||
}
|
||||
|
||||
public static Collection<URL> discoverOnvifURLs() {
|
||||
return DeviceDiscovery.discoverWsDevicesAsUrls("^http$", ".*onvif.*");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
package de.onvif.soap;
|
||||
|
||||
import de.onvif.beans.DeviceInfo;
|
||||
import java.net.ConnectException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import javax.xml.ws.Holder;
|
||||
import org.apache.cxf.binding.soap.Soap12;
|
||||
import org.apache.cxf.binding.soap.SoapBindingConfiguration;
|
||||
import org.apache.cxf.endpoint.Client;
|
||||
@@ -16,7 +27,15 @@ import org.onvif.ver10.events.wsdl.EventPortType;
|
||||
import org.onvif.ver10.events.wsdl.EventService;
|
||||
import org.onvif.ver10.media.wsdl.Media;
|
||||
import org.onvif.ver10.media.wsdl.MediaService;
|
||||
import org.onvif.ver10.schema.*;
|
||||
import org.onvif.ver10.schema.Capabilities;
|
||||
import org.onvif.ver10.schema.CapabilityCategory;
|
||||
import org.onvif.ver10.schema.DateTime;
|
||||
import org.onvif.ver10.schema.MediaUri;
|
||||
import org.onvif.ver10.schema.SetDateTimeType;
|
||||
import org.onvif.ver10.schema.StreamSetup;
|
||||
import org.onvif.ver10.schema.StreamType;
|
||||
import org.onvif.ver10.schema.Transport;
|
||||
import org.onvif.ver10.schema.TransportProtocol;
|
||||
import org.onvif.ver20.imaging.wsdl.ImagingPort;
|
||||
import org.onvif.ver20.imaging.wsdl.ImagingService;
|
||||
import org.onvif.ver20.ptz.wsdl.PTZ;
|
||||
@@ -24,271 +43,283 @@ import org.onvif.ver20.ptz.wsdl.PtzService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.ws.BindingProvider;
|
||||
import javax.xml.ws.Holder;
|
||||
import java.net.ConnectException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Robin Dick
|
||||
* @author Modified by Brad Lowe
|
||||
*/
|
||||
public class OnvifDevice {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OnvifDevice.class);
|
||||
private static final String DEVICE_SERVICE = "/onvif/device_service";
|
||||
private static final Logger logger = LoggerFactory.getLogger(OnvifDevice.class);
|
||||
private static final String DEVICE_SERVICE = "/onvif/device_service";
|
||||
|
||||
final private URL url; // Example http://host:port, https://host, http://host, http://ip_address
|
||||
private final URL url; // Example http://host:port, https://host, http://host, http://ip_address
|
||||
|
||||
private Device device;
|
||||
private Media media;
|
||||
private PTZ ptz;
|
||||
private ImagingPort imaging;
|
||||
private EventPortType events;
|
||||
public static boolean verbose = false; // enable/disable logging of SOAP messages
|
||||
final SimpleSecurityHandler securityHandler;
|
||||
private Device device;
|
||||
private Media media;
|
||||
private PTZ ptz;
|
||||
private ImagingPort imaging;
|
||||
private EventPortType events;
|
||||
|
||||
/*
|
||||
* @param url is http://host or http://host:port or https://host or https://host:port
|
||||
* @param user Username you need to login, or "" for none
|
||||
* @param password User's password to login, or "" for none
|
||||
*/
|
||||
public OnvifDevice(URL url, String user, String password) throws ConnectException, SOAPException, MalformedURLException {
|
||||
this.url = url;
|
||||
String f = url.getFile();
|
||||
if (!f.isEmpty()) throw new MalformedURLException("Expected empty file in URL, not:" + f);
|
||||
securityHandler = !user.isEmpty() && !password.isEmpty() ? new SimpleSecurityHandler(user, password) : null;
|
||||
init();
|
||||
}
|
||||
private static boolean verbose = false; // enable/disable logging of SOAP messages
|
||||
final SimpleSecurityHandler securityHandler;
|
||||
|
||||
/*
|
||||
* @param url is http://host or http://host:port or https://host or https://host:port
|
||||
* @param user Username you need to login, or "" for none
|
||||
* @param password User's password to login, or "" for none
|
||||
*/
|
||||
public OnvifDevice(URL url, String user, String password)
|
||||
throws ConnectException, SOAPException, MalformedURLException {
|
||||
this.url = url;
|
||||
String f = url.getFile();
|
||||
if (!f.isEmpty()) throw new MalformedURLException("Expected empty file in URL, not:" + f);
|
||||
securityHandler =
|
||||
!user.isEmpty() && !password.isEmpty() ? new SimpleSecurityHandler(user, password) : null;
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an Onvif device, e.g. a Network Video Transmitter (NVT) with
|
||||
* logindata.
|
||||
*
|
||||
* @param deviceIp The IP address or host name of your device, you can also add a port
|
||||
* @param user Username you need to login
|
||||
* @param password User's password to login
|
||||
* @throws ConnectException Exception gets thrown, if device isn't accessible or invalid
|
||||
* and doesn't answer to SOAP messages
|
||||
* @throws SOAPException
|
||||
*/
|
||||
public OnvifDevice(String deviceIp, String user, String password) throws ConnectException, SOAPException, MalformedURLException {
|
||||
this(deviceIp.startsWith("http")? new URL(deviceIp):new URL("http://" + deviceIp), user, password);
|
||||
}
|
||||
/**
|
||||
* Initializes an Onvif device, e.g. a Network Video Transmitter (NVT) with logindata.
|
||||
*
|
||||
* @param deviceIp The IP address or host name of your device, you can also add a port
|
||||
* @param user Username you need to login
|
||||
* @param password User's password to login
|
||||
* @throws ConnectException Exception gets thrown, if device isn't accessible or invalid and
|
||||
* doesn't answer to SOAP messages
|
||||
* @throws SOAPException
|
||||
*/
|
||||
public OnvifDevice(String deviceIp, String user, String password)
|
||||
throws ConnectException, SOAPException, MalformedURLException {
|
||||
this(
|
||||
deviceIp.startsWith("http") ? new URL(deviceIp) : new URL("http://" + deviceIp),
|
||||
user,
|
||||
password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an Onvif device, e.g. a Network Video Transmitter (NVT) with
|
||||
* logindata.
|
||||
*
|
||||
* @param hostIp The IP address of your device, you can also add a port but
|
||||
* noch protocol (e.g. http://)
|
||||
* @throws ConnectException Exception gets thrown, if device isn't accessible or invalid
|
||||
* and doesn't answer to SOAP messages
|
||||
* @throws SOAPException
|
||||
*/
|
||||
public OnvifDevice(String hostIp) throws ConnectException, SOAPException, MalformedURLException {
|
||||
this(hostIp, null, null);
|
||||
}
|
||||
/**
|
||||
* Initializes an Onvif device, e.g. a Network Video Transmitter (NVT) with logindata.
|
||||
*
|
||||
* @param hostIp The IP address of your device, you can also add a port but noch protocol (e.g.
|
||||
* http://)
|
||||
* @throws ConnectException Exception gets thrown, if device isn't accessible or invalid and
|
||||
* doesn't answer to SOAP messages
|
||||
* @throws SOAPException
|
||||
*/
|
||||
public OnvifDevice(String hostIp) throws ConnectException, SOAPException, MalformedURLException {
|
||||
this(hostIp, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initalizes the addresses used for SOAP messages and to get the internal IP, if given IP is a
|
||||
* proxy.
|
||||
*
|
||||
* @throws ConnectException Get thrown if device doesn't give answers to GetCapabilities()
|
||||
* @throws SOAPException
|
||||
*/
|
||||
protected void init() throws ConnectException, SOAPException {
|
||||
|
||||
/**
|
||||
* Initalizes the addresses used for SOAP messages and to get the internal
|
||||
* IP, if given IP is a proxy.
|
||||
*
|
||||
* @throws ConnectException Get thrown if device doesn't give answers to
|
||||
* GetCapabilities()
|
||||
* @throws SOAPException
|
||||
*/
|
||||
protected void init() throws ConnectException, SOAPException {
|
||||
DeviceService deviceService = new DeviceService(null, DeviceService.SERVICE);
|
||||
|
||||
DeviceService deviceService = new DeviceService(null, DeviceService.SERVICE);
|
||||
BindingProvider deviceServicePort = (BindingProvider) deviceService.getDevicePort();
|
||||
this.device =
|
||||
getServiceProxy(deviceServicePort, url.toString() + DEVICE_SERVICE).create(Device.class);
|
||||
|
||||
BindingProvider deviceServicePort = (BindingProvider) deviceService.getDevicePort();
|
||||
this.device = getServiceProxy(deviceServicePort, url.toString() + DEVICE_SERVICE).create(Device.class);
|
||||
// resetSystemDateAndTime(); // don't modify the camera in a constructor.. :)
|
||||
|
||||
// resetSystemDateAndTime(); // don't modify the camera in a constructor.. :)
|
||||
Capabilities capabilities = this.device.getCapabilities(Arrays.asList(CapabilityCategory.ALL));
|
||||
if (capabilities == null) {
|
||||
throw new ConnectException("Capabilities not reachable.");
|
||||
}
|
||||
|
||||
Capabilities capabilities = this.device.getCapabilities(Arrays.asList(CapabilityCategory.ALL));
|
||||
if (capabilities == null) {
|
||||
throw new ConnectException("Capabilities not reachable.");
|
||||
}
|
||||
if (capabilities.getMedia() != null && capabilities.getMedia().getXAddr() != null) {
|
||||
this.media = new MediaService().getMediaPort();
|
||||
this.media =
|
||||
getServiceProxy((BindingProvider) media, capabilities.getMedia().getXAddr())
|
||||
.create(Media.class);
|
||||
}
|
||||
|
||||
if (capabilities.getMedia() != null && capabilities.getMedia().getXAddr() != null) {
|
||||
this.media = new MediaService().getMediaPort();
|
||||
this.media = getServiceProxy((BindingProvider) media, capabilities.getMedia().getXAddr()).create(Media.class);
|
||||
}
|
||||
if (capabilities.getPTZ() != null && capabilities.getPTZ().getXAddr() != null) {
|
||||
this.ptz = new PtzService().getPtzPort();
|
||||
this.ptz =
|
||||
getServiceProxy((BindingProvider) ptz, capabilities.getPTZ().getXAddr())
|
||||
.create(PTZ.class);
|
||||
}
|
||||
|
||||
if (capabilities.getPTZ() != null && capabilities.getPTZ().getXAddr() != null) {
|
||||
this.ptz = new PtzService().getPtzPort();
|
||||
this.ptz = getServiceProxy((BindingProvider) ptz, capabilities.getPTZ().getXAddr()).create(PTZ.class);
|
||||
}
|
||||
if (capabilities.getImaging() != null && capabilities.getImaging().getXAddr() != null) {
|
||||
this.imaging = new ImagingService().getImagingPort();
|
||||
this.imaging =
|
||||
getServiceProxy((BindingProvider) imaging, capabilities.getImaging().getXAddr())
|
||||
.create(ImagingPort.class);
|
||||
}
|
||||
|
||||
if (capabilities.getImaging() != null && capabilities.getImaging().getXAddr() != null) {
|
||||
this.imaging = new ImagingService().getImagingPort();
|
||||
this.imaging = getServiceProxy((BindingProvider) imaging, capabilities.getImaging().getXAddr()).create(ImagingPort.class);
|
||||
}
|
||||
if (capabilities.getEvents() != null && capabilities.getEvents().getXAddr() != null) {
|
||||
this.events = new EventService().getEventPort();
|
||||
this.events =
|
||||
getServiceProxy((BindingProvider) events, capabilities.getEvents().getXAddr())
|
||||
.create(EventPortType.class);
|
||||
}
|
||||
}
|
||||
|
||||
if (capabilities.getEvents() != null && capabilities.getEvents().getXAddr() != null) {
|
||||
this.events = new EventService().getEventPort();
|
||||
this.events = getServiceProxy((BindingProvider) events, capabilities.getEvents().getXAddr()).create(EventPortType.class);
|
||||
}
|
||||
}
|
||||
public JaxWsProxyFactoryBean getServiceProxy(BindingProvider servicePort, String serviceAddr) {
|
||||
|
||||
JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
|
||||
proxyFactory.getHandlers();
|
||||
|
||||
public JaxWsProxyFactoryBean getServiceProxy(BindingProvider servicePort, String serviceAddr) {
|
||||
if (serviceAddr != null) proxyFactory.setAddress(serviceAddr);
|
||||
proxyFactory.setServiceClass(servicePort.getClass());
|
||||
|
||||
JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
|
||||
proxyFactory.getHandlers();
|
||||
SoapBindingConfiguration config = new SoapBindingConfiguration();
|
||||
|
||||
if (serviceAddr != null)
|
||||
proxyFactory.setAddress(serviceAddr);
|
||||
proxyFactory.setServiceClass(servicePort.getClass());
|
||||
config.setVersion(Soap12.getInstance());
|
||||
proxyFactory.setBindingConfig(config);
|
||||
Client deviceClient = ClientProxy.getClient(servicePort);
|
||||
|
||||
SoapBindingConfiguration config = new SoapBindingConfiguration();
|
||||
if (verbose) {
|
||||
// these logging interceptors are depreciated, but should be fine for debugging/development
|
||||
// use.
|
||||
proxyFactory.getOutInterceptors().add(new LoggingOutInterceptor());
|
||||
proxyFactory.getInInterceptors().add(new LoggingInInterceptor());
|
||||
}
|
||||
|
||||
config.setVersion(Soap12.getInstance());
|
||||
proxyFactory.setBindingConfig(config);
|
||||
Client deviceClient = ClientProxy.getClient(servicePort);
|
||||
HTTPConduit http = (HTTPConduit) deviceClient.getConduit();
|
||||
if (securityHandler != null) proxyFactory.getHandlers().add(securityHandler);
|
||||
HTTPClientPolicy httpClientPolicy = http.getClient();
|
||||
httpClientPolicy.setConnectionTimeout(36000);
|
||||
httpClientPolicy.setReceiveTimeout(32000);
|
||||
httpClientPolicy.setAllowChunking(false);
|
||||
|
||||
if (verbose) {
|
||||
// these logging interceptors are depreciated, but should be fine for debugging/development use.
|
||||
proxyFactory.getOutInterceptors().add(new LoggingOutInterceptor());
|
||||
proxyFactory.getInInterceptors().add(new LoggingInInterceptor());
|
||||
}
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
HTTPConduit http = (HTTPConduit) deviceClient.getConduit();
|
||||
if (securityHandler != null)
|
||||
proxyFactory.getHandlers().add(securityHandler);
|
||||
HTTPClientPolicy httpClientPolicy = http.getClient();
|
||||
httpClientPolicy.setConnectionTimeout(36000);
|
||||
httpClientPolicy.setReceiveTimeout(32000);
|
||||
httpClientPolicy.setAllowChunking(false);
|
||||
public void resetSystemDateAndTime() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Date currentDate = new Date();
|
||||
boolean daylightSavings = calendar.getTimeZone().inDaylightTime(currentDate);
|
||||
org.onvif.ver10.schema.TimeZone timeZone = new org.onvif.ver10.schema.TimeZone();
|
||||
timeZone.setTZ(displayTimeZone(calendar.getTimeZone()));
|
||||
org.onvif.ver10.schema.Time time = new org.onvif.ver10.schema.Time();
|
||||
time.setHour(calendar.get(Calendar.HOUR_OF_DAY));
|
||||
time.setMinute(calendar.get(Calendar.MINUTE));
|
||||
time.setSecond(calendar.get(Calendar.SECOND));
|
||||
org.onvif.ver10.schema.Date date = new org.onvif.ver10.schema.Date();
|
||||
date.setYear(calendar.get(Calendar.YEAR));
|
||||
date.setMonth(calendar.get(Calendar.MONTH) + 1);
|
||||
date.setDay(calendar.get(Calendar.DAY_OF_MONTH));
|
||||
org.onvif.ver10.schema.DateTime utcDateTime = new org.onvif.ver10.schema.DateTime();
|
||||
utcDateTime.setDate(date);
|
||||
utcDateTime.setTime(time);
|
||||
device.setSystemDateAndTime(SetDateTimeType.MANUAL, daylightSavings, timeZone, utcDateTime);
|
||||
}
|
||||
|
||||
return proxyFactory;
|
||||
}
|
||||
private static String displayTimeZone(TimeZone tz) {
|
||||
|
||||
long hours = TimeUnit.MILLISECONDS.toHours(tz.getRawOffset());
|
||||
long minutes =
|
||||
TimeUnit.MILLISECONDS.toMinutes(tz.getRawOffset()) - TimeUnit.HOURS.toMinutes(hours);
|
||||
// avoid -4:-30 issue
|
||||
minutes = Math.abs(minutes);
|
||||
|
||||
public void resetSystemDateAndTime() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Date currentDate = new Date();
|
||||
boolean daylightSavings = calendar.getTimeZone().inDaylightTime(currentDate);
|
||||
org.onvif.ver10.schema.TimeZone timeZone = new org.onvif.ver10.schema.TimeZone();
|
||||
timeZone.setTZ(displayTimeZone(calendar.getTimeZone()));
|
||||
org.onvif.ver10.schema.Time time = new org.onvif.ver10.schema.Time();
|
||||
time.setHour(calendar.get(Calendar.HOUR_OF_DAY));
|
||||
time.setMinute(calendar.get(Calendar.MINUTE));
|
||||
time.setSecond(calendar.get(Calendar.SECOND));
|
||||
org.onvif.ver10.schema.Date date = new org.onvif.ver10.schema.Date();
|
||||
date.setYear(calendar.get(Calendar.YEAR));
|
||||
date.setMonth(calendar.get(Calendar.MONTH) + 1);
|
||||
date.setDay(calendar.get(Calendar.DAY_OF_MONTH));
|
||||
org.onvif.ver10.schema.DateTime utcDateTime = new org.onvif.ver10.schema.DateTime();
|
||||
utcDateTime.setDate(date);
|
||||
utcDateTime.setTime(time);
|
||||
device.setSystemDateAndTime(SetDateTimeType.MANUAL, daylightSavings, timeZone, utcDateTime);
|
||||
}
|
||||
String result = "";
|
||||
if (hours > 0) {
|
||||
result = String.format("GMT+%02d:%02d", hours, minutes);
|
||||
} else {
|
||||
result = String.format("GMT%02d:%02d", hours, minutes);
|
||||
}
|
||||
|
||||
private static String displayTimeZone(TimeZone tz) {
|
||||
return result;
|
||||
}
|
||||
|
||||
long hours = TimeUnit.MILLISECONDS.toHours(tz.getRawOffset());
|
||||
long minutes = TimeUnit.MILLISECONDS.toMinutes(tz.getRawOffset()) - TimeUnit.HOURS.toMinutes(hours);
|
||||
// avoid -4:-30 issue
|
||||
minutes = Math.abs(minutes);
|
||||
/** Is used for basic devices and requests of given Onvif Device */
|
||||
public Device getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
String result = "";
|
||||
if (hours > 0) {
|
||||
result = String.format("GMT+%02d:%02d", hours, minutes);
|
||||
} else {
|
||||
result = String.format("GMT%02d:%02d", hours, minutes);
|
||||
}
|
||||
public PTZ getPtz() {
|
||||
return ptz;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
public Media getMedia() {
|
||||
return media;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is used for basic devices and requests of given Onvif Device
|
||||
*/
|
||||
public Device getDevice() {
|
||||
return device;
|
||||
}
|
||||
public ImagingPort getImaging() {
|
||||
return imaging;
|
||||
}
|
||||
|
||||
public PTZ getPtz() {
|
||||
return ptz;
|
||||
}
|
||||
public EventPortType getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
public Media getMedia() {
|
||||
return media;
|
||||
}
|
||||
public DateTime getDate() {
|
||||
return device.getSystemDateAndTime().getLocalDateTime();
|
||||
}
|
||||
|
||||
public ImagingPort getImaging() {
|
||||
return imaging;
|
||||
}
|
||||
public DeviceInfo getDeviceInfo() {
|
||||
Holder<String> manufacturer = new Holder<>();
|
||||
Holder<String> model = new Holder<>();
|
||||
Holder<String> firmwareVersion = new Holder<>();
|
||||
Holder<String> serialNumber = new Holder<>();
|
||||
Holder<String> hardwareId = new Holder<>();
|
||||
device.getDeviceInformation(manufacturer, model, firmwareVersion, serialNumber, hardwareId);
|
||||
return new DeviceInfo(
|
||||
manufacturer.value,
|
||||
model.value,
|
||||
firmwareVersion.value,
|
||||
serialNumber.value,
|
||||
hardwareId.value);
|
||||
}
|
||||
|
||||
public EventPortType getEvents() {
|
||||
return events;
|
||||
}
|
||||
public String getHostname() {
|
||||
return device.getHostname().getName();
|
||||
}
|
||||
|
||||
public DateTime getDate() {
|
||||
return device.getSystemDateAndTime().getLocalDateTime();
|
||||
}
|
||||
public String reboot() throws ConnectException, SOAPException {
|
||||
return device.systemReboot();
|
||||
}
|
||||
|
||||
public DeviceInfo getDeviceInfo() {
|
||||
Holder<String> manufacturer = new Holder<>();
|
||||
Holder<String> model = new Holder<>();
|
||||
Holder<String> firmwareVersion = new Holder<>();
|
||||
Holder<String> serialNumber = new Holder<>();
|
||||
Holder<String> hardwareId = new Holder<>();
|
||||
device.getDeviceInformation(manufacturer, model, firmwareVersion, serialNumber, hardwareId);
|
||||
return new DeviceInfo(manufacturer.value, model.value, firmwareVersion.value, serialNumber.value,
|
||||
hardwareId.value);
|
||||
}
|
||||
// returns http://host[:port]/path_for_snapshot
|
||||
public String getSnapshotUri(String profileToken) {
|
||||
MediaUri sceenshotUri = media.getSnapshotUri(profileToken);
|
||||
if (sceenshotUri != null) {
|
||||
return sceenshotUri.getUri();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return device.getHostname().getName();
|
||||
}
|
||||
public String getSnapshotUri() {
|
||||
return getSnapshotUri(0);
|
||||
}
|
||||
|
||||
public String reboot() throws ConnectException, SOAPException {
|
||||
return device.systemReboot();
|
||||
}
|
||||
public String getRTSPUri() {
|
||||
return getRTSPUri(0);
|
||||
}
|
||||
|
||||
// returns http://host[:port]/path_for_snapshot
|
||||
public String getSnapshotUri(String profileToken) {
|
||||
MediaUri sceenshotUri = media.getSnapshotUri(profileToken);
|
||||
if (sceenshotUri!=null)
|
||||
{
|
||||
try {
|
||||
URL u = new URL(sceenshotUri.getUri());
|
||||
// if using port forwarding, this URL may be incorrect..
|
||||
// Here we can normalize the URL to use the
|
||||
String up = url.toString() + u.getFile();
|
||||
return up;
|
||||
}catch(MalformedURLException m)
|
||||
{
|
||||
// This should never happen.
|
||||
logger.error(sceenshotUri.getUri(), m);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// Get snapshot uri for profile with index
|
||||
public String getSnapshotUri(int index) {
|
||||
if (media.getProfiles().size() >= index)
|
||||
return getSnapshotUri(media.getProfiles().get(index).getToken());
|
||||
return "";
|
||||
}
|
||||
|
||||
// returns rtsp://host[:port]/path_for_rtsp
|
||||
public String getRTSPURL(String profileToken) {
|
||||
StreamSetup streamSetup = new StreamSetup();
|
||||
Transport t = new Transport();
|
||||
t.setProtocol(TransportProtocol.RTSP);
|
||||
streamSetup.setTransport(t);
|
||||
streamSetup.setStream(StreamType.RTP_UNICAST);
|
||||
MediaUri rtsp = media.getStreamUri(streamSetup, profileToken);
|
||||
public String getRTSPUri(int index) {
|
||||
return getRTSPUri(media.getProfiles().get(index).getToken());
|
||||
}
|
||||
|
||||
return rtsp!=null ? rtsp.getUri():"";
|
||||
}
|
||||
// returns rtsp://host[:port]/path_for_rtsp
|
||||
public String getRTSPUri(String profileToken) {
|
||||
StreamSetup streamSetup = new StreamSetup();
|
||||
Transport t = new Transport();
|
||||
t.setProtocol(TransportProtocol.RTSP);
|
||||
streamSetup.setTransport(t);
|
||||
streamSetup.setStream(StreamType.RTP_UNICAST);
|
||||
MediaUri rtsp = media.getStreamUri(streamSetup, profileToken);
|
||||
return rtsp != null ? rtsp.getUri() : "";
|
||||
}
|
||||
|
||||
public static boolean isVerbose() {
|
||||
return verbose;
|
||||
}
|
||||
|
||||
public static void setVerbose(boolean verbose) {
|
||||
OnvifDevice.verbose = verbose;
|
||||
}
|
||||
}
|
||||
|
||||
282
onvif-java/src/main/java/de/onvif/soap/SSLUtilities.java
Normal file
282
onvif-java/src/main/java/de/onvif/soap/SSLUtilities.java
Normal file
@@ -0,0 +1,282 @@
|
||||
package de.onvif.soap;
|
||||
|
||||
/** @author schrepfler */
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* This class provide various static methods that relax X509 certificate and hostname verification
|
||||
* while using the SSL over the HTTP protocol.
|
||||
*
|
||||
* @author Francis Labrie
|
||||
*/
|
||||
public final class SSLUtilities {
|
||||
|
||||
/**
|
||||
* Hostname verifier for the Sun's deprecated API.
|
||||
*
|
||||
* @deprecated see {@link #_hostnameVerifier}.
|
||||
*/
|
||||
private static HostnameVerifier __hostnameVerifier;
|
||||
/**
|
||||
* Thrust managers for the Sun's deprecated API.
|
||||
*
|
||||
* @deprecated see {@link #_trustManagers}.
|
||||
*/
|
||||
private static TrustManager[] __trustManagers;
|
||||
/** Hostname verifier. */
|
||||
private static HostnameVerifier _hostnameVerifier;
|
||||
/** Thrust managers. */
|
||||
private static TrustManager[] _trustManagers;
|
||||
|
||||
/**
|
||||
* Set the default Hostname Verifier to an instance of a fake class that trust all hostnames. This
|
||||
* method uses the old deprecated API from the com.sun.ssl package.
|
||||
*
|
||||
* @deprecated see {@link #_trustAllHostnames()}.
|
||||
*/
|
||||
private static void __trustAllHostnames() {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
if (__hostnameVerifier == null) {
|
||||
__hostnameVerifier = new _FakeHostnameVerifier();
|
||||
} // if
|
||||
// Install the all-trusting host name verifier
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(__hostnameVerifier);
|
||||
} // __trustAllHttpsCertificates
|
||||
|
||||
/**
|
||||
* Set the default X509 Trust Manager to an instance of a fake class that trust all certificates,
|
||||
* even the self-signed ones. This method uses the old deprecated API from the com.sun.ssl
|
||||
* package.
|
||||
*
|
||||
* @deprecated see {@link #_trustAllHttpsCertificates()}.
|
||||
*/
|
||||
private static void __trustAllHttpsCertificates() {
|
||||
SSLContext context;
|
||||
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
if (__trustManagers == null) {
|
||||
__trustManagers = new TrustManager[] {new _FakeX509TrustManager()};
|
||||
} // if
|
||||
// Install the all-trusting trust manager
|
||||
try {
|
||||
context = SSLContext.getInstance("SSL");
|
||||
context.init(null, __trustManagers, new SecureRandom());
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new IllegalStateException(gse.getMessage());
|
||||
} // catch
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
|
||||
} // __trustAllHttpsCertificates
|
||||
|
||||
/**
|
||||
* Return true if the protocol handler property java. protocol.handler.pkgs is set to the Sun's
|
||||
* com.sun.net.ssl. internal.www.protocol deprecated one, false otherwise.
|
||||
*
|
||||
* @return true if the protocol handler property is set to the Sun's deprecated one, false
|
||||
* otherwise.
|
||||
*/
|
||||
private static boolean isDeprecatedSSLProtocol() {
|
||||
return ("com.sun.net.ssl.internal.www.protocol"
|
||||
.equals(System.getProperty("java.protocol.handler.pkgs")));
|
||||
} // isDeprecatedSSLProtocol
|
||||
|
||||
/** Set the default Hostname Verifier to an instance of a fake class that trust all hostnames. */
|
||||
private static void _trustAllHostnames() {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
if (_hostnameVerifier == null) {
|
||||
_hostnameVerifier = new FakeHostnameVerifier();
|
||||
} // if
|
||||
// Install the all-trusting host name verifier:
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier);
|
||||
} // _trustAllHttpsCertificates
|
||||
|
||||
/**
|
||||
* Set the default X509 Trust Manager to an instance of a fake class that trust all certificates,
|
||||
* even the self-signed ones.
|
||||
*/
|
||||
private static void _trustAllHttpsCertificates() {
|
||||
SSLContext context;
|
||||
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
if (_trustManagers == null) {
|
||||
_trustManagers = new TrustManager[] {new FakeX509TrustManager()};
|
||||
} // if
|
||||
// Install the all-trusting trust manager:
|
||||
try {
|
||||
context = SSLContext.getInstance("SSL");
|
||||
context.init(null, _trustManagers, new SecureRandom());
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new IllegalStateException(gse.getMessage());
|
||||
} // catch
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
|
||||
} // _trustAllHttpsCertificates
|
||||
|
||||
/** Set the default Hostname Verifier to an instance of a fake class that trust all hostnames. */
|
||||
public static void trustAllHostnames() {
|
||||
// Is the deprecated protocol setted?
|
||||
if (isDeprecatedSSLProtocol()) {
|
||||
__trustAllHostnames();
|
||||
} else {
|
||||
_trustAllHostnames();
|
||||
} // else
|
||||
} // trustAllHostnames
|
||||
|
||||
/**
|
||||
* Set the default X509 Trust Manager to an instance of a fake class that trust all certificates,
|
||||
* even the self-signed ones.
|
||||
*/
|
||||
public static void trustAllHttpsCertificates() {
|
||||
// Is the deprecated protocol setted?
|
||||
if (isDeprecatedSSLProtocol()) {
|
||||
__trustAllHttpsCertificates();
|
||||
} else {
|
||||
_trustAllHttpsCertificates();
|
||||
} // else
|
||||
} // trustAllHttpsCertificates
|
||||
|
||||
/**
|
||||
* This class implements a fake hostname verificator, trusting any host name. This class uses the
|
||||
* old deprecated API from the com.sun. ssl package.
|
||||
*
|
||||
* @author Francis Labrie
|
||||
* @deprecated see {@link SSLUtilities.FakeHostnameVerifier}.
|
||||
*/
|
||||
public static class _FakeHostnameVerifier implements HostnameVerifier {
|
||||
|
||||
/**
|
||||
* Always return true, indicating that the host name is an acceptable match with the server's
|
||||
* authentication scheme.
|
||||
*
|
||||
* @param hostname the host name.
|
||||
* @param session the SSL session used on the connection to host.
|
||||
* @return the true boolean value indicating the host name is trusted.
|
||||
*/
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return (true);
|
||||
}
|
||||
} // _FakeHostnameVerifier
|
||||
|
||||
/**
|
||||
* This class allow any X509 certificates to be used to authenticate the remote side of a secure
|
||||
* socket, including self-signed certificates. This class uses the old deprecated API from the
|
||||
* com.sun.ssl package.
|
||||
*
|
||||
* @author Francis Labrie
|
||||
* @deprecated see {@link SSLUtilities.FakeX509TrustManager}.
|
||||
*/
|
||||
public static class _FakeX509TrustManager implements X509TrustManager {
|
||||
|
||||
/** Empty array of certificate authority certificates. */
|
||||
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
|
||||
|
||||
/**
|
||||
* Always return true, trusting for client SSL chain peer certificate chain.
|
||||
*
|
||||
* @param chain the peer certificate chain.
|
||||
* @return the true boolean value indicating the chain is trusted.
|
||||
*/
|
||||
public boolean isClientTrusted(X509Certificate[] chain) {
|
||||
return (true);
|
||||
} // checkClientTrusted
|
||||
|
||||
/**
|
||||
* Always return true, trusting for server SSL chain peer certificate chain.
|
||||
*
|
||||
* @param chain the peer certificate chain.
|
||||
* @return the true boolean value indicating the chain is trusted.
|
||||
*/
|
||||
public boolean isServerTrusted(X509Certificate[] chain) {
|
||||
return (true);
|
||||
} // checkServerTrusted
|
||||
|
||||
/**
|
||||
* Return an empty array of certificate authority certificates which are trusted for
|
||||
* authenticating peers.
|
||||
*
|
||||
* @return a empty array of issuer certificates.
|
||||
*/
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return (_AcceptedIssuers);
|
||||
} // getAcceptedIssuers
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
|
||||
throws CertificateException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
|
||||
throws CertificateException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
} // _FakeX509TrustManager
|
||||
|
||||
/**
|
||||
* This class implements a fake hostname verificator, trusting any host name.
|
||||
*
|
||||
* @author Francis Labrie
|
||||
*/
|
||||
public static class FakeHostnameVerifier implements HostnameVerifier {
|
||||
|
||||
/**
|
||||
* Always return true, indicating that the host name is an acceptable match with the server's
|
||||
* authentication scheme.
|
||||
*
|
||||
* @param hostname the host name.
|
||||
* @param session the SSL session used on the connection to host.
|
||||
* @return the true boolean value indicating the host name is trusted.
|
||||
*/
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return (true);
|
||||
} // verify
|
||||
} // FakeHostnameVerifier
|
||||
|
||||
/**
|
||||
* This class allow any X509 certificates to be used to authenticate the remote side of a secure
|
||||
* socket, including self-signed certificates.
|
||||
*
|
||||
* @author Francis Labrie
|
||||
*/
|
||||
public static class FakeX509TrustManager implements X509TrustManager {
|
||||
|
||||
/** Empty array of certificate authority certificates. */
|
||||
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
|
||||
|
||||
/**
|
||||
* Always trust for client SSL chain peer certificate chain with any authType authentication
|
||||
* types.
|
||||
*
|
||||
* @param chain the peer certificate chain.
|
||||
* @param authType the authentication type based on the client certificate.
|
||||
*/
|
||||
public void checkClientTrusted(
|
||||
X509Certificate[] chain, String authType) {} // checkClientTrusted
|
||||
|
||||
/**
|
||||
* Always trust for server SSL chain peer certificate chain with any authType exchange algorithm
|
||||
* types.
|
||||
*
|
||||
* @param chain the peer certificate chain.
|
||||
* @param authType the key exchange algorithm used.
|
||||
*/
|
||||
public void checkServerTrusted(
|
||||
X509Certificate[] chain, String authType) {} // checkServerTrusted
|
||||
|
||||
/**
|
||||
* Return an empty array of certificate authority certificates which are trusted for
|
||||
* authenticating peers.
|
||||
*
|
||||
* @return a empty array of issuer certificates.
|
||||
*/
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return (_AcceptedIssuers);
|
||||
} // getAcceptedIssuers
|
||||
} // FakeX509TrustManager
|
||||
} // SSLUtilities
|
||||
@@ -1,129 +1,154 @@
|
||||
package de.onvif.soap;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.MessageDigestAlgorithms;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.BASE64_ENCODING;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.CREATED_LN;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.NONCE_LN;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.PASSWORD_DIGEST;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.PASSWORD_LN;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.PASSWORD_TYPE_ATTR;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.USERNAME_LN;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.USERNAME_TOKEN_LN;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.WSSE_LN;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.WSSE_NS;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.WSSE_PREFIX;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.WSU_NS;
|
||||
import static org.apache.wss4j.common.WSS4JConstants.WSU_PREFIX;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.soap.*;
|
||||
import javax.xml.soap.SOAPElement;
|
||||
import javax.xml.soap.SOAPEnvelope;
|
||||
import javax.xml.soap.SOAPHeader;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
import javax.xml.soap.SOAPPart;
|
||||
import javax.xml.ws.handler.MessageContext;
|
||||
import javax.xml.ws.handler.soap.SOAPHandler;
|
||||
import javax.xml.ws.handler.soap.SOAPMessageContext;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static org.apache.wss4j.common.WSS4JConstants.*;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.MessageDigestAlgorithms;
|
||||
/*
|
||||
Utility class to add user/password onvif credentials to SOAP communications
|
||||
*/
|
||||
public class SimpleSecurityHandler implements SOAPHandler<SOAPMessageContext> {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
private String nonce;
|
||||
private String utcTime;
|
||||
|
||||
public SimpleSecurityHandler(String username,String password){
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.nonce = "" + new Random().nextInt();
|
||||
}
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final String nonce;
|
||||
private String utcTime;
|
||||
private static Random rnd = new SecureRandom();
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(final SOAPMessageContext msgCtx) {
|
||||
// System.out.println("SimpleSecurityHandler");
|
||||
public SimpleSecurityHandler(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.nonce = "" + rnd.nextInt();
|
||||
}
|
||||
|
||||
// Indicator telling us which direction this message is going in
|
||||
final Boolean outInd = (Boolean) msgCtx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
|
||||
@Override
|
||||
public boolean handleMessage(final SOAPMessageContext msgCtx) {
|
||||
// System.out.println("SimpleSecurityHandler");
|
||||
|
||||
// Handler must only add security headers to outbound messages
|
||||
if (outInd.booleanValue()) {
|
||||
try {
|
||||
// Create the xml
|
||||
SOAPMessage soapMessage = msgCtx.getMessage();
|
||||
SOAPEnvelope envelope = soapMessage.getSOAPPart().getEnvelope();
|
||||
SOAPHeader header = envelope.getHeader();
|
||||
if (header == null)
|
||||
header = envelope.addHeader();
|
||||
// Indicator telling us which direction this message is going in
|
||||
final Boolean outInd = (Boolean) msgCtx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
|
||||
|
||||
SOAPPart sp = soapMessage.getSOAPPart();
|
||||
SOAPEnvelope se = sp.getEnvelope();
|
||||
se.addNamespaceDeclaration(WSSE_PREFIX, WSSE_NS);
|
||||
se.addNamespaceDeclaration(WSU_PREFIX, WSU_NS);
|
||||
// Handler must only add security headers to outbound messages
|
||||
if (outInd.booleanValue()) {
|
||||
try {
|
||||
// Create the xml
|
||||
SOAPMessage soapMessage = msgCtx.getMessage();
|
||||
SOAPEnvelope envelope = soapMessage.getSOAPPart().getEnvelope();
|
||||
SOAPHeader header = envelope.getHeader();
|
||||
if (header == null) header = envelope.addHeader();
|
||||
|
||||
SOAPElement securityElem = header.addChildElement(WSSE_LN, WSSE_PREFIX);
|
||||
// securityElem.setAttribute("SOAP-ENV:mustUnderstand", "1");
|
||||
SOAPPart sp = soapMessage.getSOAPPart();
|
||||
SOAPEnvelope se = sp.getEnvelope();
|
||||
se.addNamespaceDeclaration(WSSE_PREFIX, WSSE_NS);
|
||||
se.addNamespaceDeclaration(WSU_PREFIX, WSU_NS);
|
||||
|
||||
SOAPElement usernameTokenElem = securityElem.addChildElement(USERNAME_TOKEN_LN, WSSE_PREFIX);
|
||||
SOAPElement securityElem = header.addChildElement(WSSE_LN, WSSE_PREFIX);
|
||||
// securityElem.setAttribute("SOAP-ENV:mustUnderstand", "1");
|
||||
|
||||
SOAPElement usernameElem = usernameTokenElem.addChildElement(USERNAME_LN, WSSE_PREFIX);
|
||||
usernameElem.setTextContent(username);
|
||||
SOAPElement usernameTokenElem =
|
||||
securityElem.addChildElement(USERNAME_TOKEN_LN, WSSE_PREFIX);
|
||||
|
||||
SOAPElement passwordElem = usernameTokenElem.addChildElement(PASSWORD_LN, WSSE_PREFIX);
|
||||
passwordElem.setAttribute(PASSWORD_TYPE_ATTR, PASSWORD_DIGEST);
|
||||
passwordElem.setTextContent(encryptPassword(password));
|
||||
SOAPElement usernameElem = usernameTokenElem.addChildElement(USERNAME_LN, WSSE_PREFIX);
|
||||
usernameElem.setTextContent(username);
|
||||
|
||||
SOAPElement nonceElem = usernameTokenElem.addChildElement(NONCE_LN, WSSE_PREFIX);
|
||||
nonceElem.setAttribute("EncodingType", BASE64_ENCODING);
|
||||
nonceElem.setTextContent(Base64.encodeBase64String(nonce.getBytes()));
|
||||
SOAPElement passwordElem = usernameTokenElem.addChildElement(PASSWORD_LN, WSSE_PREFIX);
|
||||
passwordElem.setAttribute(PASSWORD_TYPE_ATTR, PASSWORD_DIGEST);
|
||||
passwordElem.setTextContent(encryptPassword(password));
|
||||
|
||||
SOAPElement createdElem = usernameTokenElem.addChildElement(CREATED_LN, WSU_PREFIX);
|
||||
createdElem.setTextContent(getLastUTCTime());
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
SOAPElement nonceElem = usernameTokenElem.addChildElement(NONCE_LN, WSSE_PREFIX);
|
||||
nonceElem.setAttribute("EncodingType", BASE64_ENCODING);
|
||||
nonceElem.setTextContent(Base64.encodeBase64String(nonce.getBytes()));
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getLastUTCTime() {
|
||||
return utcTime;
|
||||
}
|
||||
public String getUTCTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-d'T'HH:mm:ss'Z'");
|
||||
sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
|
||||
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||
String utcTime = sdf.format(cal.getTime());
|
||||
this.utcTime = utcTime;
|
||||
return utcTime;
|
||||
}
|
||||
public String encryptPassword(String password) {
|
||||
String timestamp = getUTCTime();
|
||||
String beforeEncryption = nonce + timestamp + password;
|
||||
byte[] encryptedRaw;
|
||||
try {
|
||||
encryptedRaw = sha1(beforeEncryption);
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
String encoded = Base64.encodeBase64String(encryptedRaw);
|
||||
return encoded;
|
||||
}
|
||||
// Other required methods on interface need no guts
|
||||
private static byte[] sha1(String s) throws NoSuchAlgorithmException {
|
||||
MessageDigest SHA1 = MessageDigest.getInstance(MessageDigestAlgorithms.SHA_1);
|
||||
SHA1.reset();
|
||||
SHA1.update(s.getBytes());
|
||||
return SHA1.digest();
|
||||
}
|
||||
@Override
|
||||
public boolean handleFault(SOAPMessageContext context) {
|
||||
// TODO Auto-generated method stub
|
||||
SOAPElement createdElem = usernameTokenElem.addChildElement(CREATED_LN, WSU_PREFIX);
|
||||
createdElem.setTextContent(getLastUTCTime());
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(MessageContext context) {
|
||||
// TODO Auto-generated method stub
|
||||
public String getLastUTCTime() {
|
||||
return utcTime;
|
||||
}
|
||||
|
||||
public String getUTCTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-d'T'HH:mm:ss'Z'");
|
||||
sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
|
||||
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||
String utcTime = sdf.format(cal.getTime());
|
||||
this.utcTime = utcTime;
|
||||
return utcTime;
|
||||
}
|
||||
|
||||
public String encryptPassword(String password) {
|
||||
String timestamp = getUTCTime();
|
||||
String beforeEncryption = nonce + timestamp + password;
|
||||
byte[] encryptedRaw;
|
||||
try {
|
||||
encryptedRaw = sha1(beforeEncryption);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
String encoded = Base64.encodeBase64String(encryptedRaw);
|
||||
return encoded;
|
||||
}
|
||||
// Other required methods on interface need no guts
|
||||
private static byte[] sha1(String s) throws NoSuchAlgorithmException {
|
||||
MessageDigest SHA1 = MessageDigest.getInstance(MessageDigestAlgorithms.SHA_1);
|
||||
SHA1.reset();
|
||||
SHA1.update(s.getBytes());
|
||||
return SHA1.digest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<QName> getHeaders() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public boolean handleFault(SOAPMessageContext context) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(MessageContext context) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<QName> getHeaders() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,59 +6,63 @@ import org.onvif.ver10.schema.PTZVector;
|
||||
|
||||
public class OnvifUtils {
|
||||
|
||||
public static String format(PTZVector vector)
|
||||
{
|
||||
String out = "";
|
||||
if (vector!=null)
|
||||
{
|
||||
out += "["+vector.getPanTilt().getX()+","+vector.getPanTilt().getY();
|
||||
if (vector.getZoom()!=null) out += ","+vector.getZoom().getX();
|
||||
out += "]";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
public static String format(PTZPreset preset)
|
||||
{
|
||||
String out = "";
|
||||
if (preset!=null)
|
||||
{
|
||||
out += preset.getToken()+"/"+preset.getName()+":"+format(preset.getPTZPosition());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
public static String format(PTZStatus status)
|
||||
{
|
||||
String out = "";
|
||||
if (status!=null)
|
||||
{
|
||||
out += "moveStatus="+format(status.getMoveStatus())+" position="+format(status.getPosition())+" time="+status.getUtcTime();
|
||||
public static String format(PTZVector vector) {
|
||||
String out = "";
|
||||
if (vector != null) {
|
||||
out += "[" + vector.getPanTilt().getX() + "," + vector.getPanTilt().getY();
|
||||
if (vector.getZoom() != null) out += "," + vector.getZoom().getX();
|
||||
out += "]";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
return out;
|
||||
public static String format(PTZPreset preset) {
|
||||
String out = "";
|
||||
if (preset != null) {
|
||||
out += preset.getToken() + "/" + preset.getName() + ":" + format(preset.getPTZPosition());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
public static String format(Object o)
|
||||
{
|
||||
String out = "";
|
||||
if (o!=null)
|
||||
{
|
||||
out = o.toString();
|
||||
for (;;)
|
||||
{
|
||||
int ch = out.indexOf("org.onvif.ver");
|
||||
if (ch==-1) break;
|
||||
int end = out.indexOf("[", ch);
|
||||
if (end==-1) { assert(false); break; }//
|
||||
int at = out.indexOf("@", ch);
|
||||
if (at==-1||at>end) { assert(false); break;}
|
||||
public static String format(PTZStatus status) {
|
||||
String out = "";
|
||||
if (status != null) {
|
||||
out +=
|
||||
"moveStatus="
|
||||
+ format(status.getMoveStatus())
|
||||
+ " position="
|
||||
+ format(status.getPosition())
|
||||
+ " time="
|
||||
+ status.getUtcTime();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
out = out.substring(0, ch)+out.substring(end);
|
||||
}
|
||||
public static String format(Object o) {
|
||||
String out = "";
|
||||
if (o != null) {
|
||||
out = o.toString();
|
||||
for (; ; ) {
|
||||
int ch = out.indexOf("org.onvif.ver");
|
||||
if (ch == -1) break;
|
||||
int end = out.indexOf("[", ch);
|
||||
if (end == -1) {
|
||||
assert (false);
|
||||
break;
|
||||
} //
|
||||
int at = out.indexOf("@", ch);
|
||||
if (at == -1 || at > end) {
|
||||
assert (false);
|
||||
break;
|
||||
}
|
||||
|
||||
out = out.replaceAll("<null>",""); // speed=<null>,foo=bar to just speed=,foo=bar
|
||||
out = out.substring(0, ch) + out.substring(end);
|
||||
}
|
||||
|
||||
// out += preset.getToken()+"/"+preset.getName()+":"+format(preset.getPTZPosition());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
out = out.replaceAll("<null>", ""); // speed=<null>,foo=bar to just speed=,foo=bar
|
||||
|
||||
// out += preset.getToken()+"/"+preset.getName()+":"+format(preset.getPTZPosition());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package de.onvif.utils;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class URLComparator implements Comparator<URL> {
|
||||
public int compare(URL o1, URL o2) {
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,79 +1,65 @@
|
||||
package org.onvif.client;
|
||||
|
||||
|
||||
import de.onvif.discovery.OnvifDiscovery;
|
||||
import org.apache.cxf.common.logging.LogUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
/* Class calls OnvifDiscovery and for each device URL found, calls TestDevice */
|
||||
import org.apache.cxf.common.logging.LogUtils;
|
||||
|
||||
/**
|
||||
* Class calls OnvifDiscovery and for each device URL found, calls TestDevice
|
||||
* This assumes all onvif devices on your network use the same username and password.
|
||||
* @author Brad Lowe
|
||||
*/
|
||||
public class DiscoverAndTest {
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(TestDevice.class);
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(TestDevice.class);
|
||||
|
||||
public static String discoverAndTest(String user, String password)
|
||||
{
|
||||
String out ="";
|
||||
String sep = "\n";
|
||||
public static String discoverAndTest(String user, String password) {
|
||||
String sep = "\n";
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
Collection<URL> urls = OnvifDiscovery.discoverOnvifURLs();
|
||||
for (URL u : urls) {
|
||||
out += ("Discovered URL:"+u.toString())+sep;
|
||||
}
|
||||
ArrayList<String> results = new ArrayList<>();
|
||||
Collection<URL> urls = OnvifDiscovery.discoverOnvifURLs();
|
||||
for (URL u : urls) {
|
||||
out.append("Discovered URL:" + u.toString() + sep);
|
||||
}
|
||||
ArrayList<String> results = new ArrayList<>();
|
||||
|
||||
int good = 0, bad = 0;
|
||||
int good = 0, bad = 0;
|
||||
|
||||
for (URL u : urls) {
|
||||
for (URL u : urls) {
|
||||
|
||||
try {
|
||||
String result = TestDevice.testCamera(u, user, password);
|
||||
LOG.info(u + "->" + result);
|
||||
good++;
|
||||
results.add(u.toString() + ":" + result);
|
||||
} catch (Throwable e) {
|
||||
bad++;
|
||||
LOG.severe("error:" + u + " " + e.toString());
|
||||
try {
|
||||
String result = TestDevice.testCamera(u, user, password);
|
||||
LOG.info(u + "->" + result);
|
||||
good++;
|
||||
results.add(u.toString() + ":" + result);
|
||||
} catch (Throwable e) {
|
||||
bad++;
|
||||
LOG.severe("error:" + u + " " + e.toString());
|
||||
// This is a bit of a hack. When a camera is password protected (it should be!)
|
||||
// and the password is not provided or wrong, a "Unable to Send Message" exception
|
||||
// is thrown. This is not clear-- buried in the stack track is the real cause.
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
e.printStackTrace(pw);
|
||||
String trace = sw.getBuffer().toString();
|
||||
if (trace.contains("Unauthorized")) results.add(u + ":Unauthorized:");
|
||||
else results.add(u + ":" + trace);
|
||||
}
|
||||
}
|
||||
out.append("RESULTS: " + sep);
|
||||
for (String s : results) out.append(s + sep);
|
||||
out.append("cameras found:" + urls.size() + " good=" + good + ", bad=" + bad + sep);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
e.printStackTrace(pw);
|
||||
String trace = sw.getBuffer().toString();
|
||||
if (trace.contains("Unauthorized"))
|
||||
results.add(u + ":Unauthorized:");
|
||||
else
|
||||
results.add(u + ":" + trace);
|
||||
}
|
||||
}
|
||||
out += "RESULTS: "+sep;
|
||||
for (String s : results)
|
||||
out += s+sep;
|
||||
out +=("cameras found:" + urls.size() + " good=" + good + ", bad=" + bad)+sep;
|
||||
return out;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
OnvifCredentials creds = GetTestDevice.getOnvifCredentials(args);
|
||||
|
||||
String user=null,pass;
|
||||
if (args.length==3) {
|
||||
user = args[1];
|
||||
pass = args[2];
|
||||
} else
|
||||
{
|
||||
user=System.getProperty("ONVIF_USER");
|
||||
pass=System.getProperty("ONVIF_PASSWORD");;
|
||||
if (user==null) user="";
|
||||
if (pass==null) pass="";
|
||||
}
|
||||
|
||||
if (creds.getPassword().isEmpty()) LOG.info("Warning: No password for discover and test...");
|
||||
|
||||
LOG.info(discoverAndTest(creds.getUser(),creds.getPassword()));
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
// get user and password.. we will ignore device host
|
||||
OnvifCredentials creds = GetTestDevice.getOnvifCredentials(args);
|
||||
if (creds.getPassword().isEmpty()) LOG.info("Warning: No password for discover and test...");
|
||||
LOG.info(discoverAndTest(creds.getUser(), creds.getPassword()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,17 +45,20 @@ public class GetTestDevice {
|
||||
return new OnvifCredentials("","","","");
|
||||
}
|
||||
|
||||
private static OnvifCredentials getFromArgs(String[] args) {
|
||||
if (args==null||args.length<2) return null;
|
||||
// arguments to any test app can be host user password profilename
|
||||
// if no arguments passed, returns null.
|
||||
// All arguments optional.
|
||||
public static OnvifCredentials getFromArgs(String[] args) {
|
||||
if (args==null||args.length==0) return null;
|
||||
String host="",user="",password="",profile="";
|
||||
if (args.length > 0) host = args[0];
|
||||
host = args[0];
|
||||
if (args.length > 1) user = args[1];
|
||||
if (args.length > 2) password = args[2];
|
||||
if (args.length > 3) profile = args[3];
|
||||
return new OnvifCredentials(host,user,password,profile);
|
||||
}
|
||||
|
||||
private static OnvifCredentials getFromProperties() {
|
||||
public static OnvifCredentials getFromProperties() {
|
||||
String test = null;
|
||||
if (test == null) test = System.getProperty(PROPERTY_NAME);
|
||||
if (test == null) test = System.getenv(PROPERTY_NAME);
|
||||
@@ -69,7 +72,7 @@ public class GetTestDevice {
|
||||
private static OnvifCredentials getFromStandardInput() throws IOException {
|
||||
|
||||
System.out.println("Getting camera credentials from standard input");
|
||||
InputStreamReader inputStream = new InputStreamReader(System.in);
|
||||
InputStreamReader inputStream = new InputStreamReader(System.in, "utf-8");
|
||||
BufferedReader keyboardInput = new BufferedReader(inputStream);
|
||||
System.out.println("Please enter camera IP (with port if not 80):");
|
||||
String cameraAddress = keyboardInput.readLine();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.onvif.client;
|
||||
|
||||
public class OnvifCredentials {
|
||||
private String host; // 92.168.xx.yy
|
||||
private String host; // 92.168.xx.yy, or http://host[:port]
|
||||
private String user; // admin
|
||||
private String password; // secret
|
||||
private String profile; // "MediaProfile000" If empty, will use first profile.
|
||||
private String profile; // "MediaProfile000" If empty, will use first profile.
|
||||
|
||||
public OnvifCredentials(String host, String user, String password, String profile) {
|
||||
this.host = host;
|
||||
|
||||
@@ -27,6 +27,7 @@ public class ReadCommandsFromStdInput {
|
||||
user = keyboardInput.readLine();
|
||||
System.out.println("Please enter camera password:");
|
||||
password = keyboardInput.readLine();
|
||||
if (cameraAddress==null||user==null||password==null) throw new IOException("No input");
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
return;
|
||||
@@ -48,7 +49,7 @@ public class ReadCommandsFromStdInput {
|
||||
System.out.println();
|
||||
System.out.println("Enter a command (type \"info\" to get commands):");
|
||||
input = keyboardInput.readLine();
|
||||
|
||||
if (input==null) break;
|
||||
switch (input) {
|
||||
case "url": {
|
||||
List<Profile> profiles = cam.getMedia().getProfiles();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.onvif.client;
|
||||
|
||||
import de.onvif.soap.OnvifDevice;
|
||||
import de.onvif.utils.OnvifUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.onvif.ver10.media.wsdl.Media;
|
||||
import org.onvif.ver10.schema.*;
|
||||
@@ -27,72 +28,41 @@ public class SimpleTest {
|
||||
|
||||
|
||||
final Map<String, OnvifDevice> onvifCameras = new HashMap<>();
|
||||
final Map<String, String> onvifCamerasTokens = new HashMap<>();
|
||||
final Map<String, OnvifCredentials> credentialsMap = new HashMap<>();
|
||||
final String propFileRelativePath = "src/test/resources/onvif.properties";
|
||||
final Properties config = new Properties();
|
||||
final File f = new File(propFileRelativePath);
|
||||
if (!f.exists()) throw new Exception("fnf: " + f.getAbsolutePath());
|
||||
|
||||
config.load(new FileInputStream(f));
|
||||
String firstCamId = null;
|
||||
for (Entry<Object, Object> entry : config.entrySet()) {
|
||||
String deviceName = (String) entry.getKey();
|
||||
String[] confStr = ((String) entry.getValue()).split(",");
|
||||
String deviceIp = confStr[0];
|
||||
String user = confStr[1];
|
||||
String password = confStr[2];
|
||||
// profileToken = "MediaProfile000"/"MediaProfile001";
|
||||
String profileToken = confStr[3];
|
||||
try {
|
||||
System.out.println("Connect to camera, please wait ...");
|
||||
OnvifDevice cam = new OnvifDevice(deviceIp, user, password);
|
||||
System.out.printf("Connected to device %s (%s)\n", cam.getDeviceInfo(), deviceName);
|
||||
onvifCameras.put(deviceName, cam);
|
||||
onvifCamerasTokens.put(deviceName, profileToken);
|
||||
if (firstCamId == null)
|
||||
firstCamId = deviceName;
|
||||
} catch (ConnectException | SOAPException e1) {
|
||||
e1.printStackTrace();
|
||||
System.err.println("No connection to device with ip " + deviceIp + ", please try again.");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
if (firstCamId == null) {
|
||||
System.out.println("No ONVIF devices found");
|
||||
return;
|
||||
}
|
||||
// take the first OnvifDevice
|
||||
OnvifDevice firstCam = onvifCameras.get(firstCamId);
|
||||
String profileToken = onvifCamerasTokens.get(firstCamId);
|
||||
Media media = firstCam.getMedia();
|
||||
|
||||
StreamSetup streamSetup = new StreamSetup();
|
||||
for (Object k:config.keySet())
|
||||
{
|
||||
String line = config.get(k.toString()).toString();
|
||||
OnvifCredentials credentials = GetTestDevice.parse(line);
|
||||
if (credentials!=null)
|
||||
{
|
||||
try {
|
||||
System.out.println("Connect to camera, please wait ...");
|
||||
OnvifDevice cam = new OnvifDevice(credentials.getHost(), credentials.getUser(), credentials.getPassword());
|
||||
System.out.printf("Connected to device %s (%s)%n", cam.getDeviceInfo(), k.toString());
|
||||
System.out.println(TestDevice.inspect(cam));
|
||||
|
||||
Transport t = new Transport();
|
||||
String snapshotUri = cam.getSnapshotUri();
|
||||
if (!snapshotUri.isEmpty()) {
|
||||
File tempFile = File.createTempFile("tmp", ".jpg");
|
||||
|
||||
t.setProtocol(TransportProtocol.RTSP);
|
||||
streamSetup.setTransport(t);
|
||||
streamSetup.setStream(StreamType.RTP_UNICAST);
|
||||
// Note: This will likely fail if the camera/device is password protected.
|
||||
// embedding the user:password@ into the URL will not work with FileUtils.copyURLToFile
|
||||
FileUtils.copyURLToFile(new URL(snapshotUri), tempFile);
|
||||
System.out.println("snapshot: " + tempFile.getAbsolutePath() + " length:" + tempFile.length());
|
||||
}
|
||||
|
||||
|
||||
MediaUri rtsp = media.getStreamUri(streamSetup, profileToken);
|
||||
System.out.println("rtspURL: " + rtsp + ": " + rtsp.getUri());
|
||||
|
||||
|
||||
Profile profile = media.getProfile(profileToken);
|
||||
|
||||
|
||||
// Example 1 - take a snapshot (the file gets deleted once the app ends..)
|
||||
MediaUri sceenshotUri = media.getSnapshotUri(profileToken);
|
||||
File tempFile = File.createTempFile("tmp", ".jpg");
|
||||
FileUtils.copyURLToFile(new URL(sceenshotUri.getUri()), tempFile);
|
||||
System.out.println("snapshot: " + tempFile.getAbsolutePath() + " length:" + tempFile.length());
|
||||
|
||||
PTZ ptz = firstCam.getPtz();
|
||||
if (ptz != null) {
|
||||
List<PTZPreset> presets = ptz.getPresets(profileToken);
|
||||
if (presets != null && !presets.isEmpty()) {
|
||||
System.out.println("Found " + presets.size() + " presets");
|
||||
}catch(Throwable th)
|
||||
{
|
||||
System.err.println("Error on device: "+k);
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import de.onvif.soap.OnvifDevice;
|
||||
import de.onvif.utils.OnvifUtils;
|
||||
import org.apache.cxf.common.logging.LogUtils;
|
||||
import org.onvif.ver10.device.wsdl.DeviceServiceCapabilities;
|
||||
import org.onvif.ver10.device.wsdl.SystemCapabilities;
|
||||
import org.onvif.ver10.events.wsdl.EventPortType;
|
||||
import org.onvif.ver10.events.wsdl.GetEventProperties;
|
||||
import org.onvif.ver10.events.wsdl.GetEventPropertiesResponse;
|
||||
@@ -15,6 +14,8 @@ import org.onvif.ver20.imaging.wsdl.ImagingPort;
|
||||
import org.onvif.ver20.ptz.wsdl.Capabilities;
|
||||
import org.onvif.ver20.ptz.wsdl.PTZ;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.soap.SOAPException;
|
||||
import java.io.IOException;
|
||||
@@ -23,7 +24,9 @@ import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* @author Brad Lowe
|
||||
*/
|
||||
public class TestDevice {
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(TestDevice.class);
|
||||
|
||||
@@ -40,19 +43,19 @@ public class TestDevice {
|
||||
public static String inspect(OnvifDevice device) {
|
||||
String out = "";
|
||||
DeviceInfo info = device.getDeviceInfo();
|
||||
out += "DeviceInfo:" + info + sep;
|
||||
out += "DeviceInfo:" +sep + "\t" + info + sep;
|
||||
DeviceServiceCapabilities caps = device.getDevice().getServiceCapabilities();
|
||||
out += "\tgetServiceCapabilities: " + OnvifUtils.format(caps) + sep;
|
||||
out += "\tgetServiceCapabilities.getSystem: " + OnvifUtils.format(caps.getSystem()) + sep;
|
||||
|
||||
|
||||
Media media = device.getMedia();
|
||||
|
||||
media.getVideoSources();
|
||||
|
||||
|
||||
List<Profile> profiles = media.getProfiles();
|
||||
out += "Media Profiles: " + profiles.size() + sep;
|
||||
|
||||
for (Profile profile : profiles) {
|
||||
String profileToken = profile.getToken();
|
||||
String rtsp = device.getRTSPURL(profileToken);
|
||||
String rtsp = device.getRTSPUri(profileToken);
|
||||
out += "\tProfile: " + profile.getName() + " token=" + profile.getToken() + sep;
|
||||
out += "\t\trtsp: " + rtsp + sep;
|
||||
out += "\t\tsnapshot: " + device.getSnapshotUri(profileToken) + sep;
|
||||
@@ -63,15 +66,12 @@ public class TestDevice {
|
||||
out += "VideoSources: " + videoSources.size() + sep;
|
||||
for (VideoSource v : videoSources)
|
||||
out += "\t" + OnvifUtils.format(v) + sep;
|
||||
|
||||
List<AudioSource> audioSources = media.getAudioSources();
|
||||
out += "AudioSources: " + audioSources.size() + sep;
|
||||
for (AudioSource a : audioSources)
|
||||
out += "\t" + OnvifUtils.format(a) + sep;
|
||||
|
||||
out += "hostName=" + device.getHostname() + sep;
|
||||
DeviceServiceCapabilities caps = device.getDevice().getServiceCapabilities();
|
||||
out += "getServiceCapabilities=" + OnvifUtils.format(caps) + sep;
|
||||
out += "getServiceCapabilities.getSystem=" + OnvifUtils.format(caps.getSystem()) + sep;
|
||||
|
||||
ImagingPort imaging = device.getImaging();
|
||||
if (imaging != null && videoSources.size() > 0) {
|
||||
@@ -102,13 +102,21 @@ public class TestDevice {
|
||||
|
||||
GetEventProperties getEventProperties = new GetEventProperties();
|
||||
GetEventPropertiesResponse getEventPropertiesResp = events.getEventProperties(getEventProperties);
|
||||
getEventPropertiesResp.getMessageContentFilterDialect().forEach(x -> System.out.println(x));
|
||||
getEventPropertiesResp.getTopicExpressionDialect().forEach(x -> System.out.println(x));
|
||||
out += "\tMessageContentFilterDialects:" + sep;
|
||||
for (String f : getEventPropertiesResp.getMessageContentFilterDialect())
|
||||
out += ("\t\t" + f + sep);
|
||||
out += "\tTopicExpressionDialects:" + sep;
|
||||
for (String f : getEventPropertiesResp.getTopicExpressionDialect())
|
||||
out += ("\t\t" + f + sep);
|
||||
|
||||
out += "\tTopics:" + sep;
|
||||
StringBuffer tree = new StringBuffer();
|
||||
for (Object object : getEventPropertiesResp.getTopicSet().getAny()) {
|
||||
Element e = (Element) object;
|
||||
WsNotificationTest.printTree(e, e.getNodeName());
|
||||
printTree(e, e.getNodeName(), tree);
|
||||
// WsNotificationTest.printTree(e, e.getNodeName());
|
||||
}
|
||||
|
||||
out += tree;
|
||||
|
||||
}
|
||||
|
||||
@@ -116,7 +124,7 @@ public class TestDevice {
|
||||
PTZ ptz = device.getPtz();
|
||||
if (ptz != null) {
|
||||
|
||||
out += "PTZ:" + sep;
|
||||
out += "PTZ:" + sep;
|
||||
String profileToken = profiles.get(0).getToken();
|
||||
|
||||
Capabilities ptz_caps = ptz.getServiceCapabilities();
|
||||
@@ -126,7 +134,7 @@ public class TestDevice {
|
||||
// out += "ptz.getConfiguration=" + ptz.getConfiguration(profileToken) + sep;
|
||||
List<PTZPreset> presets = ptz.getPresets(profileToken);
|
||||
if (presets != null && !presets.isEmpty()) {
|
||||
out += "\tPresets:" + presets.size() +sep;
|
||||
out += "\tPresets:" + presets.size() + sep;
|
||||
for (PTZPreset p : presets)
|
||||
out += "\t\t" + OnvifUtils.format(p) + sep;
|
||||
}
|
||||
@@ -136,6 +144,20 @@ public class TestDevice {
|
||||
return out;
|
||||
}
|
||||
|
||||
public static void printTree(Node node, String name, StringBuffer buffer) {
|
||||
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nodes = node.getChildNodes();
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Node n = nodes.item(i);
|
||||
printTree(n, name + " - " + n.getNodeName(), buffer);
|
||||
}
|
||||
} else {
|
||||
buffer.append("\t\t"+ name + " - " + node.getNodeName() + "\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String testCamera(URL url, String user, String password) throws SOAPException, IOException {
|
||||
OnvifDevice device = new OnvifDevice(url, user, password);
|
||||
return inspect(device);
|
||||
@@ -146,8 +168,9 @@ public class TestDevice {
|
||||
try {
|
||||
OnvifCredentials creds = GetTestDevice.getOnvifCredentials(args);
|
||||
String out = testCamera(creds);
|
||||
LOG.info("\n"+out+"\n");
|
||||
LOG.info("\n" + out + "\n");
|
||||
} catch (Throwable th) {
|
||||
LOG.warning("Error "+th);
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ public class WsNotificationTest {
|
||||
|
||||
List<Profile> profiles = cam.getMedia().getProfiles();
|
||||
for (Profile p : profiles) {
|
||||
System.out.printf("Profile: [token=%s,name=%s,snapshotUri=%s]\n", p.getToken(), p.getName(),
|
||||
System.out.printf("Profile: [token=%s,name=%s,snapshotUri=%s]%n", p.getToken(), p.getName(),
|
||||
cam.getMedia().getSnapshotUri(p.getToken()).getUri());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user