ruby_onvif_client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/lib/ruby_onvif_client/action.rb +31 -0
- data/lib/ruby_onvif_client/client.rb +44 -0
- data/lib/ruby_onvif_client/device_discovery.rb +36 -0
- data/lib/ruby_onvif_client/device_management/get_capabilities.rb +118 -0
- data/lib/ruby_onvif_client/device_management/get_device_information.rb +30 -0
- data/lib/ruby_onvif_client/device_management/get_network_interfaces.rb +131 -0
- data/lib/ruby_onvif_client/device_management/get_network_protocols.rb +32 -0
- data/lib/ruby_onvif_client/device_management/get_system_date_and_time.rb +60 -0
- data/lib/ruby_onvif_client/device_management/get_users.rb +32 -0
- data/lib/ruby_onvif_client/device_management/set_network_interfaces.rb +83 -0
- data/lib/ruby_onvif_client/device_management/set_system_date_and_time.rb +48 -0
- data/lib/ruby_onvif_client/device_management/set_system_factory_default.rb +21 -0
- data/lib/ruby_onvif_client/device_management/system_reboot.rb +25 -0
- data/lib/ruby_onvif_client/device_management.rb +10 -0
- data/lib/ruby_onvif_client/media/get_audio_encoder_configuration.rb +48 -0
- data/lib/ruby_onvif_client/media/get_audio_encoder_configuration_options.rb +57 -0
- data/lib/ruby_onvif_client/media/get_audio_encoder_configurations.rb +49 -0
- data/lib/ruby_onvif_client/media/get_audio_source_configurations.rb +32 -0
- data/lib/ruby_onvif_client/media/get_stream_uri.rb +58 -0
- data/lib/ruby_onvif_client/media/get_video_encoder_configuration.rb +104 -0
- data/lib/ruby_onvif_client/media/get_video_encoder_configuration_options.rb +95 -0
- data/lib/ruby_onvif_client/media/get_video_source_configuration.rb +55 -0
- data/lib/ruby_onvif_client/media/get_video_source_configurations.rb +40 -0
- data/lib/ruby_onvif_client/media.rb +10 -0
- data/lib/ruby_onvif_client/message.rb +41 -0
- data/lib/ruby_onvif_client/path.rb +5 -0
- data/lib/ruby_onvif_client/service.rb +37 -0
- data/lib/ruby_onvif_client.rb +3 -0
- data/ruby-onvif-client.gemspec +20 -0
- metadata +143 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: a4ea5d47b7c0f188430173401d43c90c576fcc48
|
|
4
|
+
data.tar.gz: 070b68e1ef2e54093147fc3b32a220003ac85c4c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 49aa588d66590b7b98f28f0bd793619d89f144a5da078f7d132a27d7403c3b924f3ae74e5e49df71cc9e770cef943b66f8933e611f86c344c1010ff5a05cb0d1
|
|
7
|
+
data.tar.gz: 9ab55c46c26c1c379e607d42cc79cf48796e4475d4d71463c466dff3e5ad2e8de95864e1cf7f0b0a0f717d7ee1f457b5d50feb3d634ced117a35a583dadb43b5
|
data/Gemfile
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require_relative 'message'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
class Action
|
|
5
|
+
def initialize client
|
|
6
|
+
@client = client
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def send_message message
|
|
10
|
+
@client.send message.to_s do |success, result|
|
|
11
|
+
yield success, result
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def callback cb, *args
|
|
16
|
+
return if cb.class != Proc
|
|
17
|
+
cb.call *args
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def value xml_doc, xpath
|
|
21
|
+
node = xml_doc.at_xpath(xpath)
|
|
22
|
+
return node.content unless node.nil?
|
|
23
|
+
''
|
|
24
|
+
end
|
|
25
|
+
def attribute xml_doc, xpath
|
|
26
|
+
node = xml_doc[xpath]
|
|
27
|
+
return node unless node.nil?
|
|
28
|
+
''
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require "em-http"
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
require "nori"
|
|
4
|
+
|
|
5
|
+
module ONVIF
|
|
6
|
+
class Client
|
|
7
|
+
def initialize options
|
|
8
|
+
@options = {
|
|
9
|
+
connect_timeout: 5,
|
|
10
|
+
}.merge(options)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def send data
|
|
14
|
+
puts "send data to #{@options} ", data
|
|
15
|
+
http_options = {
|
|
16
|
+
connect_timeout: @options[:connect_timeout]
|
|
17
|
+
}
|
|
18
|
+
request_options = {
|
|
19
|
+
body: data,
|
|
20
|
+
}
|
|
21
|
+
http = EventMachine::HttpRequest.new(
|
|
22
|
+
@options[:address],
|
|
23
|
+
http_options
|
|
24
|
+
).post(request_options)
|
|
25
|
+
http.errback { yield false, {} }
|
|
26
|
+
http.callback do
|
|
27
|
+
puts "========================="
|
|
28
|
+
puts "receive message =>", http.response
|
|
29
|
+
puts "========================="
|
|
30
|
+
if http.response_header.status != 200
|
|
31
|
+
yield false, {header: http.response_header}
|
|
32
|
+
else
|
|
33
|
+
#nori = Nori.new(:strip_namespaces => true)
|
|
34
|
+
yield true, {
|
|
35
|
+
header: http.response_header,
|
|
36
|
+
#content: nori.parse(http.response)
|
|
37
|
+
content: http.response
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_relative 'path.rb'
|
|
2
|
+
require "uri"
|
|
3
|
+
require "ws_discovery"
|
|
4
|
+
|
|
5
|
+
module ONVIF
|
|
6
|
+
class DeviceDiscovery
|
|
7
|
+
def self.start options = {}
|
|
8
|
+
DeviceDiscovery.new.start(options) do |devices|
|
|
9
|
+
yield devices
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start options
|
|
14
|
+
@options = {
|
|
15
|
+
}.merge(options)
|
|
16
|
+
searcher = WSDiscovery.search(
|
|
17
|
+
env_namespaces: {
|
|
18
|
+
"xmlns:dn" => "http://www.onvif.org/ver10/network/wsdl"
|
|
19
|
+
},
|
|
20
|
+
types: "dn:NetworkVideoTransmitter"
|
|
21
|
+
)
|
|
22
|
+
searcher.discovery_responses.subscribe do |notification|
|
|
23
|
+
device = {
|
|
24
|
+
ep_address: notification[:probe_matches][:probe_match][:endpoint_reference][:address],
|
|
25
|
+
types: notification[:probe_matches][:probe_match][:types],
|
|
26
|
+
device_ip: URI(notification[:probe_matches][:probe_match][:x_addrs]).host,
|
|
27
|
+
device_service_address: notification[:probe_matches][:probe_match][:x_addrs],
|
|
28
|
+
scopes: notification[:probe_matches][:probe_match][:scopes].split(' '),
|
|
29
|
+
metadata_version: notification[:probe_matches][:probe_match][:metadata_version]
|
|
30
|
+
}
|
|
31
|
+
yield device
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class GetCapabilities < Action
|
|
6
|
+
# options 的结构 <!--0 or more-->
|
|
7
|
+
# [{
|
|
8
|
+
# Category: "All", //nil, 'All', 'Analytics', 'Device', 'Events', 'Imaging', 'Media', 'PTZ'
|
|
9
|
+
# <!--0 or more-->
|
|
10
|
+
# }]
|
|
11
|
+
def run options, cb
|
|
12
|
+
message = Message.new
|
|
13
|
+
message.body = ->(xml) do
|
|
14
|
+
xml.wsdl(:GetCapabilities) do
|
|
15
|
+
unless options.nil?
|
|
16
|
+
options.each do |option|
|
|
17
|
+
xml.wsdl :Category, option["Category"]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
send_message message do |success, result|
|
|
23
|
+
if success
|
|
24
|
+
xml_doc = Nokogiri::XML(result[:content])
|
|
25
|
+
xml_analytics = xml_doc.at_xpath('//tt:Analytics')
|
|
26
|
+
xml_device = xml_doc.at_xpath('//tt:Device')
|
|
27
|
+
xml_events = xml_doc.at_xpath('//tt:Events')
|
|
28
|
+
xml_imaging = xml_doc.at_xpath('//tt:Imaging')
|
|
29
|
+
xml_media = xml_doc.xpath('//tt:Media')
|
|
30
|
+
xml_ptz = xml_doc.xpath('//tt:PTZ')
|
|
31
|
+
success_result = {}
|
|
32
|
+
success_result["analytics"] = _get_analytics(xml_analytics) unless xml_analytics.nil?
|
|
33
|
+
success_result["device"] = _get_device(xml_device) unless xml_device.nil?
|
|
34
|
+
success_result["events"] = _get_events(xml_events) unless xml_events.nil?
|
|
35
|
+
success_result["imaging"] = _get_imaging(xml_imaging) unless xml_imaging.nil?
|
|
36
|
+
success_result["media"] = _get_media(xml_media) unless xml_media.nil?
|
|
37
|
+
success_result["ptz"] = _get_ptz(xml_ptz) unless xml_ptz.nil?
|
|
38
|
+
callback cb, success, success_result
|
|
39
|
+
else
|
|
40
|
+
callback cb, success, result
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def _get_analytics xml_analytics
|
|
46
|
+
{
|
|
47
|
+
x_addr: value(xml_analytics, '//tt:XAddr'),
|
|
48
|
+
rule_support: value(xml_analytics, '//tt:RuleSupport'),
|
|
49
|
+
ams: value(xml_analytics, '//tt:AnalyticsModuleSupport')
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def _get_device xml_device
|
|
54
|
+
network_keys = ["IPFilter", "ZeroConfiguration", "IPVersion6", "DynDNS", "Dot11Configuration",
|
|
55
|
+
"Dot1XConfigurations", "HostnameFromDHCP", "NTP", "DHCPv6"]
|
|
56
|
+
system_keys = ["DiscoveryResolve", "DiscoveryBye", "RemoteDiscovery", "SystemBackup", "SystemLogging",
|
|
57
|
+
"FirmwareUpgrade", "HttpFirmwareUpgrade", "HttpSystemBackup", "HttpSystemLogging", "HttpSupportInformation"]
|
|
58
|
+
security_keys = ["TLS1.0", "TLS1.1", "TLS1.2", "OnboardKeyGeneration", "AccessPolicyConfig",
|
|
59
|
+
"DefaultAccessPolicy", "Dot1X", "RemoteUserHandling", "X.509Token", "SAMLToken", "KerberosToken",
|
|
60
|
+
"UsernameToken", "HttpDigest", "RELToken", "SupportedEAPMethods"]
|
|
61
|
+
network = {}; system = {}; security = {}
|
|
62
|
+
network_keys.each do |key|
|
|
63
|
+
network[key.underscore] = value(xml_device, '//tt:' + key) unless value(xml_device, '//tt:' + key) == ''
|
|
64
|
+
end
|
|
65
|
+
system_keys.each do |key|
|
|
66
|
+
system[key.underscore] = value(xml_device, '//tt:' + key) unless value(xml_device, '//tt:' + key) == ''
|
|
67
|
+
end
|
|
68
|
+
security_keys.each do |key|
|
|
69
|
+
security[key.underscore] = value(xml_device, '//tt:' + key) unless value(xml_device, '//tt:' + key) == ''
|
|
70
|
+
end
|
|
71
|
+
return {
|
|
72
|
+
x_addr: value(xml_device, '//tt:XAddr'),
|
|
73
|
+
network: network,
|
|
74
|
+
system: system,
|
|
75
|
+
io: {
|
|
76
|
+
input_connectors: value(xml_device, '//tt:InputConnectors'),
|
|
77
|
+
relay_outputs: value(xml_device, '//tt:RelayOutputs'),
|
|
78
|
+
extension: ""
|
|
79
|
+
},
|
|
80
|
+
security: security
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def _get_events xml_events
|
|
85
|
+
{
|
|
86
|
+
x_addr: value(xml_events, '//tt:XAddr'),
|
|
87
|
+
wssubscription_policy_support: value(xml_events, '//tt:WSSubscriptionPolicySupport'),
|
|
88
|
+
wspull_point_support: value(xml_events, '//tt:WSPullPointSupport'),
|
|
89
|
+
wspsmis: value(xml_events, '//tt:WSPausableSubscriptionManagerInterfaceSupport')
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def _get_imaging xml_imaging
|
|
94
|
+
{
|
|
95
|
+
x_addr: value(xml_imaging, '//tt:XAddr')
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def _get_media xml_media
|
|
100
|
+
{
|
|
101
|
+
x_addr: value(xml_media, '//tt:XAddr'),
|
|
102
|
+
streaming_capabilities: {
|
|
103
|
+
rtp_multicast: value(xml_media, '//tt:RTPMulticast'),
|
|
104
|
+
rtp_tcp: value(xml_media, '//tt:RTPMulticast'),
|
|
105
|
+
rtp_rtsp_tcp: value(xml_media, '//tt:RTP_RTSP_TCP'),
|
|
106
|
+
extension: ""
|
|
107
|
+
},
|
|
108
|
+
extension: ""
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def _get_ptz xml_ptz
|
|
113
|
+
{x_addr: value(xml_ptz, '//tt:XAddr')}
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class GetDeviceInformation < Action
|
|
6
|
+
def run cb
|
|
7
|
+
message = Message.new
|
|
8
|
+
message.body = ->(xml) do
|
|
9
|
+
xml.wsdl(:GetDeviceInformation)
|
|
10
|
+
end
|
|
11
|
+
send_message message do |success, result|
|
|
12
|
+
if success
|
|
13
|
+
xml_doc = Nokogiri::XML(result[:content])
|
|
14
|
+
info = {
|
|
15
|
+
mf: value(xml_doc, '//tds:Manufacturer'),
|
|
16
|
+
model: value(xml_doc, '//tds:Model'),
|
|
17
|
+
firmware_version: value(xml_doc, '//tds:FirmwareVersion'),
|
|
18
|
+
serial_number: value(xml_doc, '//tds:SerialNumber'),
|
|
19
|
+
hardware_id: value(xml_doc, '//tds:HardwareId')
|
|
20
|
+
}
|
|
21
|
+
callback cb, success, info
|
|
22
|
+
else
|
|
23
|
+
callback cb, success, result
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class GetNetworkInterfaces < Action
|
|
6
|
+
def run cb
|
|
7
|
+
message = Message.new
|
|
8
|
+
message.body = ->(xml) do
|
|
9
|
+
xml.wsdl(:GetNetworkInterfaces)
|
|
10
|
+
end
|
|
11
|
+
send_message message do |success, result|
|
|
12
|
+
if success
|
|
13
|
+
xml_doc_main = Nokogiri::XML(result[:content])
|
|
14
|
+
interfaces = []
|
|
15
|
+
xml_doc_main.xpath('//tds:NetworkInterfaces').each do |xml_doc|
|
|
16
|
+
xml_info = xml_doc.at_xpath('tt:Info')
|
|
17
|
+
xml_link = xml_doc.at_xpath('tt:Link')
|
|
18
|
+
xml_ipv4 = xml_doc.at_xpath('tt:IPv4')
|
|
19
|
+
xml_ipv6 = xml_doc.at_xpath('tt:IPv6')
|
|
20
|
+
success_result = {
|
|
21
|
+
token: attribute(xml_doc, "token"),
|
|
22
|
+
enabled: value(xml_doc, "tt:Enabled")
|
|
23
|
+
}
|
|
24
|
+
success_result["info"] = _get_info(xml_info) unless xml_info.nil?
|
|
25
|
+
success_result["link"] = _get_link(xml_link) unless xml_link.nil?
|
|
26
|
+
success_result["ipv4"] = _get_ipv_four(xml_ipv4) unless xml_ipv4.nil?
|
|
27
|
+
success_result["ipv6"] = _get_ipv_six(xml_ipv6) unless xml_ipv6.nil?
|
|
28
|
+
interfaces << success_result
|
|
29
|
+
end
|
|
30
|
+
callback cb, success, interfaces
|
|
31
|
+
else
|
|
32
|
+
callback cb, success, result
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def _get_info xml_info
|
|
38
|
+
{
|
|
39
|
+
name: value(xml_info, 'tt:Name'),
|
|
40
|
+
hw_address: value(xml_info, 'tt:HwAddress'),
|
|
41
|
+
mtu: value(xml_info, 'tt:MTU')
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def _get_link xml_link
|
|
46
|
+
admin_xml_doc = xml_link.at_xpath('tt:AdminSettings')
|
|
47
|
+
oper_xml_doc = xml_link.at_xpath('tt:OperSettings')
|
|
48
|
+
link = {}
|
|
49
|
+
unless xml_doc.nil?
|
|
50
|
+
link["admin_settings"] = {
|
|
51
|
+
auto_negotiation: value(admin_xml_doc, "tt:AutoNegotiation"),
|
|
52
|
+
speed: value(admin_xml_doc, "tt:Speed"),
|
|
53
|
+
duplex: value(admin_xml_doc, "tt:Duplex")
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
unless oper_xml_doc.nil?
|
|
57
|
+
link["oper_settings"] = {
|
|
58
|
+
auto_negotiation: value(oper_xml_doc, "tt:AutoNegotiation"),
|
|
59
|
+
speed: value(oper_xml_doc, "tt:Speed"),
|
|
60
|
+
duplex: value(oper_xml_doc, "tt:Duplex")
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
link["interface_type"] = value(xml_link, "tt:InterfaceType") unless xml_link.at_xpath('tt:InterfaceType')
|
|
64
|
+
return link
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def _get_ipv_four xml_ipv_four
|
|
68
|
+
puts xml_ipv_four
|
|
69
|
+
ipv_four = {enabled: value(xml_ipv_four, 'tt:Enabled')}
|
|
70
|
+
manual = []; config = {}
|
|
71
|
+
link_local = xml_ipv_four.xpath('tt:Config/tt:LinkLocal')
|
|
72
|
+
form_dhcp = xml_ipv_four.xpath('tt:Config/tt:FromDHCP')
|
|
73
|
+
xml_ipv_four.xpath('tt:Config//tt:Manual').each do |node|
|
|
74
|
+
manual << {
|
|
75
|
+
address: value(node, "tt:Address"),
|
|
76
|
+
prefix_length: value(node, "tt:PrefixLength")
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
config["manual"] = manual
|
|
80
|
+
config["link_local"] = {
|
|
81
|
+
address: value(link_local, "tt:Address"),
|
|
82
|
+
prefix_length: value(link_local, "tt:PrefixLength")
|
|
83
|
+
}
|
|
84
|
+
config["form_dhcp"] = {
|
|
85
|
+
address: value(form_dhcp, "tt:Address"),
|
|
86
|
+
prefix_length: value(form_dhcp, "tt:PrefixLength")
|
|
87
|
+
}
|
|
88
|
+
config["dhcp"] = value(xml_ipv_four, "tt:Config//tt:DHCP")
|
|
89
|
+
ipv_four["config"] = config
|
|
90
|
+
return ipv_four
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def _get_ipv_six xml_ipv_six
|
|
94
|
+
ipv_six = {enabled: value(xml_ipv_six, 'tt:Enabled')}
|
|
95
|
+
config = {}; manual = []; link_local = []; form_dhcp = []; form_ra = []
|
|
96
|
+
xml_ipv_six.xpath('tt:Config/tt:Manual').each do |node|
|
|
97
|
+
manual << {
|
|
98
|
+
address: value(node, "tt:Address"),
|
|
99
|
+
prefix_length: value(node, "tt:PrefixLength")
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
xml_ipv_six.xpath('tt:Config/tt:LinkLocal').each do |node|
|
|
103
|
+
link_local << {
|
|
104
|
+
address: value(node, "tt:Address"),
|
|
105
|
+
prefix_length: value(node, "tt:PrefixLength")
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
xml_ipv_six.xpath('tt:Config/tt:FromDHCP').each do |node|
|
|
109
|
+
form_dhcp << {
|
|
110
|
+
address: value(node, "tt:Address"),
|
|
111
|
+
prefix_length: value(node, "tt:PrefixLength")
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
xml_ipv_six.xpath('tt:Config/tt:FromRA').each do |node|
|
|
115
|
+
form_ra << {
|
|
116
|
+
address: value(node, "tt:Address"),
|
|
117
|
+
prefix_length: value(node, "tt:PrefixLength")
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
config["manual"] = manual
|
|
121
|
+
config["link_local"] = link_local
|
|
122
|
+
config["form_dhcp"] = form_dhcp
|
|
123
|
+
config["form_ra"] = form_ra
|
|
124
|
+
config["ara"] = value(xml_ipv_six, "tt:AcceptRouterAdvert")
|
|
125
|
+
config["dhcp"] = value(xml_ipv_six, "tt:DHCP")
|
|
126
|
+
ipv_six["config"] = config
|
|
127
|
+
return ipv_six
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class GetNetworkProtocols < Action
|
|
6
|
+
def run cb
|
|
7
|
+
message = Message.new
|
|
8
|
+
message.body = ->(xml) do
|
|
9
|
+
xml.wsdl(:GetNetworkProtocols)
|
|
10
|
+
end
|
|
11
|
+
send_message message do |success, result|
|
|
12
|
+
if success
|
|
13
|
+
xml_doc = Nokogiri::XML(result[:content])
|
|
14
|
+
network = []
|
|
15
|
+
xml_doc.xpath('//tds:NetworkProtocols').each do |node|
|
|
16
|
+
network << {
|
|
17
|
+
name: value(node, 'tt:Name'),
|
|
18
|
+
enabled: value(node, 'tt:Enabled'),
|
|
19
|
+
port: value(node, 'tt:Port'),
|
|
20
|
+
extension: value(node, 'tt:Extension')
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
callback cb, success, network
|
|
25
|
+
else
|
|
26
|
+
callback cb, success, result
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class GetSystemDateAndTime < Action
|
|
6
|
+
def run cb
|
|
7
|
+
message = Message.new
|
|
8
|
+
message.body = ->(xml) do
|
|
9
|
+
xml.wsdl(:GetSystemDateAndTime)
|
|
10
|
+
end
|
|
11
|
+
send_message message do |success, result|
|
|
12
|
+
if success
|
|
13
|
+
xml_doc = Nokogiri::XML(result[:content])
|
|
14
|
+
xml_utc = xml_doc.xpath('//tt:UTCDateTime')
|
|
15
|
+
xml_local = xml_doc.xpath('//tt:LocalDateTime')
|
|
16
|
+
utc_data_time = {
|
|
17
|
+
time: {
|
|
18
|
+
hour: value(xml_utc, '//tt:Hour'),
|
|
19
|
+
minute: value(xml_utc, '//tt:Minute'),
|
|
20
|
+
second: value(xml_utc, '//tt:Second')
|
|
21
|
+
},
|
|
22
|
+
date: {
|
|
23
|
+
year: value(xml_utc, '//tt:Year'),
|
|
24
|
+
month: value(xml_utc, '//tt:Month'),
|
|
25
|
+
day: value(xml_utc, '//tt:Day')
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
local_date_time = {
|
|
29
|
+
time: {
|
|
30
|
+
hour: value(xml_local, '//tt:Hour'),
|
|
31
|
+
minute: value(xml_local, '//tt:Minute'),
|
|
32
|
+
second: value(xml_local, '//tt:Second')
|
|
33
|
+
},
|
|
34
|
+
date: {
|
|
35
|
+
year: value(xml_local, '//tt:Year'),
|
|
36
|
+
month: value(xml_local, '//tt:Month'),
|
|
37
|
+
day: value(xml_local, '//tt:Day')
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
date_time = {
|
|
41
|
+
date_time_type: value(xml_doc, '//tt:DateTimeType'),
|
|
42
|
+
daylight_savings: value(xml_doc, '//tt:DaylightSavings'),
|
|
43
|
+
time_zone: {
|
|
44
|
+
tz: value(xml_doc, '//tt:TZ'),
|
|
45
|
+
},
|
|
46
|
+
extension: value(xml_doc, '//tt:Extension')
|
|
47
|
+
}
|
|
48
|
+
xml_utc_time = xml_doc.at_xpath('//tt:UTCDateTime')
|
|
49
|
+
xml_local_time = xml_doc.at_xpath('//tt:LocalDateTime')
|
|
50
|
+
date_time["utc_date_time"] = utc_data_time unless xml_utc_time.nil?
|
|
51
|
+
date_time["local_date_time"] = local_date_time unl unless xml_local_time.nil?
|
|
52
|
+
callback cb, success, date_time
|
|
53
|
+
else
|
|
54
|
+
callback cb, success, result
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class GetUsers < Action
|
|
6
|
+
def run cb
|
|
7
|
+
message = Message.new
|
|
8
|
+
message.body = ->(xml) do
|
|
9
|
+
xml.wsdl(:GetUsers)
|
|
10
|
+
end
|
|
11
|
+
send_message message do |success, result|
|
|
12
|
+
if success
|
|
13
|
+
xml_doc = Nokogiri::XML(result[:content])
|
|
14
|
+
users = []
|
|
15
|
+
xml_doc.xpath('//tds:User').each do |node|
|
|
16
|
+
users << {
|
|
17
|
+
name: value(node, 'tt:Username'),
|
|
18
|
+
password: value(node, 'tt:Password'),
|
|
19
|
+
user_level: value(node, 'tt:UserLevel')
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
callback cb, success, users
|
|
24
|
+
else
|
|
25
|
+
callback cb, success, result
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class SetNetworkInterfaces < Action
|
|
6
|
+
# network_interface 的结构
|
|
7
|
+
# {
|
|
8
|
+
# interface_token: 'xxxxxx', // name [string]
|
|
9
|
+
# nwif:{ // #NetworkInterface
|
|
10
|
+
# enabled: true, //true, false [boolean]
|
|
11
|
+
# link: {
|
|
12
|
+
# auto_negotiation: true, //true, false [boolean]
|
|
13
|
+
# speed: 3, // [int]
|
|
14
|
+
# duplex: 'Full' //'Full', 'Half'
|
|
15
|
+
# }
|
|
16
|
+
# mtu: 2, // [int]
|
|
17
|
+
# ipv4: {
|
|
18
|
+
# enabled: true, //true, false [boolean]
|
|
19
|
+
# manual: [{
|
|
20
|
+
# address: "xxx.xxx.xxx.xxx", // [IPv4Address]
|
|
21
|
+
# prefix_length: 22 // [int]
|
|
22
|
+
# }],
|
|
23
|
+
# dhcp: true //true, false [boolean]
|
|
24
|
+
# },
|
|
25
|
+
# ipv6: {
|
|
26
|
+
# enabled: true, //true, false [boolean]
|
|
27
|
+
# ara: false//true, false #AcceptRouterAdvert [boolean]
|
|
28
|
+
# manual: [{
|
|
29
|
+
# address: "xxx.xxx.xxx.xxx", // [IPv4Address]
|
|
30
|
+
# prefix_length: 22 // [int]
|
|
31
|
+
# }],
|
|
32
|
+
# dhcp: true //true, false [boolean]
|
|
33
|
+
# }
|
|
34
|
+
# }
|
|
35
|
+
# }
|
|
36
|
+
def run network_interface, cb
|
|
37
|
+
message = Message.new namespaces: {:'xmlns:sch' => 'http://www.onvif.org/ver10/schema'}
|
|
38
|
+
message.body = ->(xml) do
|
|
39
|
+
xml.wsdl(:SetNetworkInterfaces) do
|
|
40
|
+
xml.wsdl :InterfaceToken, network_interface["interface_token"]
|
|
41
|
+
xml.wsdl :NetworkInterface do
|
|
42
|
+
xml.sch :Enabled, network_interface["nwif"]["enabled"]
|
|
43
|
+
xml.sch :Link do
|
|
44
|
+
xml.sch :AutoNegotiation, network_interface["nwif"]["link"]["auto_negotiation"]
|
|
45
|
+
xml.sch :Speed, network_interface["nwif"]["link"]["speed"]
|
|
46
|
+
xml.sch :Duplex, network_interface["nwif"]["link"]["duplex"]
|
|
47
|
+
end
|
|
48
|
+
xml.sch :MTU, network_interface["nwif"]["mtu"]
|
|
49
|
+
xml.sch :IPv4 do
|
|
50
|
+
xml.sch :Enabled, network_interface["nwif"]["ipv4"]["enabled"]
|
|
51
|
+
network_interface["nwif"]["ipv4"]["manual"].each do |manual|
|
|
52
|
+
xml.sch :Manual do
|
|
53
|
+
xml.sch :Address, manual["address"]
|
|
54
|
+
xml.sch :PrefixLength, manual["prefix_length"]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
xml.sch :DHCP, network_interface["nwif"]["ipv4"]["dhcp"]
|
|
58
|
+
end
|
|
59
|
+
xml.sch :IPv6 do
|
|
60
|
+
xml.sch :Enabled, network_interface["nwif"]["ipv6"]["enabled"]
|
|
61
|
+
xml.sch :AcceptRouterAdvert, network_interface["nwif"]["ipv6"]["ara"]
|
|
62
|
+
network_interface["nwif"]["ipv6"]["manual"].each do |manual|
|
|
63
|
+
xml.sch :Manual do
|
|
64
|
+
xml.sch :Address, manual["address"]
|
|
65
|
+
xml.sch :PrefixLength, manual["prefix_length"]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
xml.sch :DHCP, network_interface["nwif"]["ipv6"]["dhcp"]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
xml.wsdl :Extension do
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
send_message message do |success, result|
|
|
77
|
+
#????
|
|
78
|
+
callback cb, success, result
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require_relative '../action'
|
|
2
|
+
|
|
3
|
+
module ONVIF
|
|
4
|
+
module DeviceManagementAction
|
|
5
|
+
class SetSystemDateAndTime < Action
|
|
6
|
+
# system_date_time 的结构
|
|
7
|
+
# {
|
|
8
|
+
# type: 'Manual', // 'Manual', 'NTP'
|
|
9
|
+
# ds: false // DaylightSavings [booblean]
|
|
10
|
+
# time_zone_tz: 'xxxxx'// string TimeZone -> TZ [token]
|
|
11
|
+
# year: 2013 // int
|
|
12
|
+
# month: 6 // int 1 to 12
|
|
13
|
+
# day: 26 // int 1 to 31
|
|
14
|
+
# hour: 5 // int 0 to 23
|
|
15
|
+
# minute: 31 //int 0 to 59
|
|
16
|
+
# second: 44 //int 0 to 61 (typically 59)
|
|
17
|
+
# }
|
|
18
|
+
def run system_date_time, cb
|
|
19
|
+
message = Message.new namespaces: {:'xmlns:sch' => 'http://www.onvif.org/ver10/schema'}
|
|
20
|
+
message.body = ->(xml) do
|
|
21
|
+
xml.wsdl(:SetSystemDateAndTime) do
|
|
22
|
+
xml.wsdl :DateTimeType, system_date_time["type"]
|
|
23
|
+
xml.wsdl :DaylightSavings, system_date_time["ds"]
|
|
24
|
+
xml.wsdl(:TimeZone) do
|
|
25
|
+
xml.sch :TZ, system_date_time["time_zone_tz"]
|
|
26
|
+
end
|
|
27
|
+
xml.wsdl(:TimeZone) do
|
|
28
|
+
xml.sch :Time do
|
|
29
|
+
xml.sch :Hour, system_date_time["hour"]
|
|
30
|
+
xml.sch :Minute, system_date_time["minute"]
|
|
31
|
+
xml.sch :Second, system_date_time["second"]
|
|
32
|
+
end
|
|
33
|
+
xml.sch :Date do
|
|
34
|
+
xml.sch :Year, system_date_time["year"]
|
|
35
|
+
xml.sch :Month, system_date_time["month"]
|
|
36
|
+
xml.sch :Day, system_date_time["day"]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
send_message message do |success, result|
|
|
42
|
+
#????
|
|
43
|
+
callback cb, success, result
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|