easy_upnp 0.3.2 → 0.4.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 +4 -4
- data/lib/easy_upnp/argument_validator.rb +125 -0
- data/lib/easy_upnp/device_control_point.rb +62 -2
- data/lib/easy_upnp/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14a33377666a3b363416fdc8080e4bf411f2574d
|
4
|
+
data.tar.gz: b6c87a73312c8c4002b9d4d1206518f2f43c199a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcd63c1ca7bd1060112f5da3e12b8b05f8b8ab34053e3f57e93eb4c67e0015ce1d33d54505d7374c19c0e7c2d893cd95e129f8f5bce9fbaabe29de0659777d2d
|
7
|
+
data.tar.gz: ef39cf1f54bbb336e53df619f62f9a181f7f5050baec03e83e7495cddf809052d45af2caf1fb958493c5fbc87b792f9bad1fa8b9b28c0d503002a3e17887fadd
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module EasyUpnp
|
2
|
+
class ArgumentValidator
|
3
|
+
class Builder
|
4
|
+
def initialize(&block)
|
5
|
+
@validators = {}
|
6
|
+
block.call(self) if block
|
7
|
+
end
|
8
|
+
|
9
|
+
def in_range(min, max, step = 1)
|
10
|
+
add_validator(RangeValidator.new((min..max).step(step)))
|
11
|
+
end
|
12
|
+
|
13
|
+
def allowed_values(*values)
|
14
|
+
add_validator(AllowedValueValidator.new(*values))
|
15
|
+
end
|
16
|
+
|
17
|
+
def type(type)
|
18
|
+
add_validator(TypeValidator.new(type))
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_validator(validator)
|
22
|
+
@validators[validator.class] = validator
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
ArgumentValidator.new(@validators)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class RangeValidator
|
31
|
+
attr_reader :range
|
32
|
+
|
33
|
+
def initialize(range)
|
34
|
+
@range = range
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate(value)
|
38
|
+
if !@range.include?(value)
|
39
|
+
raise ArgumentError, "#{value} is not in allowed range of values: #{@range.inspect}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class AllowedValueValidator
|
45
|
+
attr_reader :allowed_values
|
46
|
+
|
47
|
+
def initialize(*allowed_values)
|
48
|
+
@allowed_values = allowed_values
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate(value)
|
52
|
+
if !@allowed_values.include?(value)
|
53
|
+
raise ArgumentError, "#{value} is not in list of allowed values: #{@allowed_values.inspect}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class TypeValidator
|
59
|
+
# Valid UPnP types for each ruby class
|
60
|
+
RUBY_TYPE_TO_UPNP_TYPE = {
|
61
|
+
Float: %w{r4 r8 number fixed.14.4 float},
|
62
|
+
Integer: %w{ui1 ui2 ui4 i1 i2 i4 int},
|
63
|
+
String: %w{char string bin.base64 bin.hex uri uuid},
|
64
|
+
TrueClass: %w{bool boolean},
|
65
|
+
FalseClass: %w{bool boolean},
|
66
|
+
DateTime: %w{date dateTime dateTime.tz time time.tz},
|
67
|
+
Time: %w{date dateTime dateTime.tz time time.tz},
|
68
|
+
Date: %w{date dateTime time}
|
69
|
+
}
|
70
|
+
|
71
|
+
# Inversion of RUBY_TYPE_TO_UPNP_TYPE.
|
72
|
+
UPNP_TYPE_VALID_CLASSES = Hash[
|
73
|
+
RUBY_TYPE_TO_UPNP_TYPE.map { |k,v|
|
74
|
+
k = Kernel.const_get(k)
|
75
|
+
v.map { |x| [x, k] }
|
76
|
+
}.reduce({}) { |a,i|
|
77
|
+
Hash[i].each { |x,y| a[x] ||= []; a[x] << y }
|
78
|
+
a
|
79
|
+
}
|
80
|
+
]
|
81
|
+
|
82
|
+
attr_reader :valid_classes
|
83
|
+
|
84
|
+
def initialize(type)
|
85
|
+
@valid_classes = UPNP_TYPE_VALID_CLASSES[type]
|
86
|
+
raise ArgumentError, "Unrecognized UPnP type: #{type}" if @valid_classes.nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate(value)
|
90
|
+
if !@valid_classes.any? { |x| value.is_a?(x) }
|
91
|
+
raise ArgumentError, "#{value} is the wrong type. Should be one of: #{@valid_classes.inspect}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def initialize(validators)
|
97
|
+
@validators = validators
|
98
|
+
end
|
99
|
+
|
100
|
+
def validate(value)
|
101
|
+
@validators.each { |_, v| v.validate(value) }
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
def required_class
|
106
|
+
return nil unless @validators[TypeValidator]
|
107
|
+
c = @validators[TypeValidator].valid_classes
|
108
|
+
c.size == 1 ? c.first : c
|
109
|
+
end
|
110
|
+
|
111
|
+
def allowed_values
|
112
|
+
return nil unless @validators[AllowedValueValidator]
|
113
|
+
@validators[AllowedValueValidator].allowed_values
|
114
|
+
end
|
115
|
+
|
116
|
+
def valid_range
|
117
|
+
return nil unless @validators[RangeValidator]
|
118
|
+
@validators[RangeValidator].range
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.build(&block)
|
122
|
+
Builder.new(&block).build
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -3,6 +3,7 @@ require 'open-uri'
|
|
3
3
|
require 'nori'
|
4
4
|
|
5
5
|
require_relative 'logger'
|
6
|
+
require_relative 'argument_validator'
|
6
7
|
|
7
8
|
module EasyUpnp
|
8
9
|
class DeviceControlPoint
|
@@ -10,7 +11,8 @@ module EasyUpnp
|
|
10
11
|
|
11
12
|
class Options
|
12
13
|
DEFAULTS = {
|
13
|
-
advanced_typecasting: true
|
14
|
+
advanced_typecasting: true,
|
15
|
+
validate_arguments: false
|
14
16
|
}
|
15
17
|
|
16
18
|
attr_reader :options
|
@@ -57,11 +59,29 @@ module EasyUpnp
|
|
57
59
|
definition_xml.remove_namespaces!
|
58
60
|
|
59
61
|
service_methods = []
|
62
|
+
service_methods_args = {}
|
60
63
|
definition_xml.xpath('//actionList/action').map do |action|
|
61
|
-
service_methods.push
|
64
|
+
service_methods.push(define_action(action))
|
65
|
+
|
66
|
+
name = action.xpath('name').text
|
67
|
+
args = {}
|
68
|
+
action.xpath('argumentList/argument').map do |arg|
|
69
|
+
arg_name = arg.xpath('name').text
|
70
|
+
arg_ref = arg.xpath('relatedStateVariable').text
|
71
|
+
args[arg_name.to_sym] = arg_ref.to_sym
|
72
|
+
end
|
73
|
+
service_methods_args[name.to_sym] = args
|
74
|
+
end
|
75
|
+
|
76
|
+
arg_validators = {}
|
77
|
+
definition_xml.xpath('//serviceStateTable/stateVariable').map do |var|
|
78
|
+
name = var.xpath('name').text
|
79
|
+
arg_validators[name.to_sym] = extract_validators(var)
|
62
80
|
end
|
63
81
|
|
64
82
|
@service_methods = service_methods
|
83
|
+
@service_methods_args = service_methods_args
|
84
|
+
@arg_validators = arg_validators
|
65
85
|
end
|
66
86
|
|
67
87
|
def to_params
|
@@ -111,8 +131,38 @@ module EasyUpnp
|
|
111
131
|
end
|
112
132
|
end
|
113
133
|
|
134
|
+
def arg_validator(method, arg)
|
135
|
+
method_args = @service_methods_args[method.to_sym]
|
136
|
+
raise ArgumentError, "Unknown method: #{method}" if method_args.nil?
|
137
|
+
|
138
|
+
arg_ref = method_args[arg.to_sym]
|
139
|
+
raise ArgumentValidator, "Unknown argument: #{arg}" if arg_ref.nil?
|
140
|
+
|
141
|
+
@arg_validators[arg_ref]
|
142
|
+
end
|
143
|
+
|
114
144
|
private
|
115
145
|
|
146
|
+
def extract_validators(var)
|
147
|
+
ArgumentValidator.build do |v|
|
148
|
+
v.type(var.xpath('dataType').text)
|
149
|
+
|
150
|
+
if (range = var.xpath('allowedValueRange')).any?
|
151
|
+
min = range.xpath('minimum').text
|
152
|
+
max = range.xpath('maximum').text
|
153
|
+
step = range.xpath('step')
|
154
|
+
step = step.any? ? step.text : 1
|
155
|
+
|
156
|
+
v.in_range(min.to_i, max.to_i, step.to_i)
|
157
|
+
end
|
158
|
+
|
159
|
+
if (list = var.xpath('allowedValueList')).any?
|
160
|
+
allowed_values = list.xpath('allowedValue').map { |x| x.text }
|
161
|
+
v.allowed_values(*allowed_values)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
116
166
|
def define_action(action)
|
117
167
|
action = Nori.new.parse(action.to_xml)['action']
|
118
168
|
action_name = action['name']
|
@@ -138,6 +188,16 @@ module EasyUpnp
|
|
138
188
|
" Supported args: #{input_args}"
|
139
189
|
end
|
140
190
|
|
191
|
+
if @options.validate_arguments
|
192
|
+
args_hash.each { |k,v|
|
193
|
+
begin
|
194
|
+
arg_validator(action['name'], k).validate(v)
|
195
|
+
rescue ArgumentError => e
|
196
|
+
raise ArgumentError, "Invalid value for argument #{k}: #{e}"
|
197
|
+
end
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
141
201
|
attrs = {
|
142
202
|
soap_action: "#{@urn}##{action_name}",
|
143
203
|
attributes: {
|
data/lib/easy_upnp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: easy_upnp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Mullins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- Rakefile
|
95
95
|
- bin/upnp-list
|
96
96
|
- easy_upnp.gemspec
|
97
|
+
- lib/easy_upnp/argument_validator.rb
|
97
98
|
- lib/easy_upnp/device_control_point.rb
|
98
99
|
- lib/easy_upnp/logger.rb
|
99
100
|
- lib/easy_upnp/ssdp_searcher.rb
|