Class: EasyUpnp::DeviceControlPoint

Inherits:
Object
  • Object
show all
Defined in:
lib/easy_upnp/control_point/device_control_point.rb

Defined Under Namespace

Classes: EventConfigOptions, Options

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(urn, service_endpoint, events_endpoint, definition, options, &block) ⇒ DeviceControlPoint

Returns a new instance of DeviceControlPoint.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 43

def initialize(urn, service_endpoint, events_endpoint, definition, options, &block)
  @urn = urn
  @service_endpoint = service_endpoint
  @definition = definition
  @options = Options.new(options, &block)

  @events_endpoint = events_endpoint
  @events_client = EasyUpnp::EventClient.new(events_endpoint)

  @client = ClientWrapper.new(
    service_endpoint,
    urn,
    @options.call_options,
    @options.advanced_typecasting,
    @options.log_enabled,
    @options.log_level,
    @options.cookies
  )

  definition_xml = Nokogiri::XML(definition)
  definition_xml.remove_namespaces!

  @validator_provider = EasyUpnp::ValidatorProvider.from_xml(definition_xml)

  @service_methods = {}
  definition_xml.xpath('//actionList/action').map do |action|
    method = EasyUpnp::ServiceMethod.from_xml(action)
    @service_methods[method.name] = method

    # Adds a method to the class
    define_service_method(method, @client, @validator_provider, @options)
  end

  @event_vars = definition_xml.
    xpath('//serviceStateTable/stateVariable[@sendEvents = "yes"]/name').
    map(&:text).
    map(&:to_sym)
end

Instance Attribute Details

#event_varsObject (readonly)

Returns the value of attribute event_vars.



15
16
17
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 15

def event_vars
  @event_vars
end

#events_endpointObject (readonly)

Returns the value of attribute events_endpoint.



15
16
17
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 15

def events_endpoint
  @events_endpoint
end

#service_endpointObject (readonly)

Returns the value of attribute service_endpoint.



15
16
17
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 15

def service_endpoint
  @service_endpoint
end

Class Method Details

.from_params(params) ⇒ Object



92
93
94
95
96
97
98
99
100
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 92

def self.from_params(params)
  DeviceControlPoint.new(
      params[:urn],
      params[:service_endpoint],
      params[:events_endpoint],
      params[:definition],
      params[:options]
  )
end

.from_service_definition(definition, options, &block) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 102

def self.from_service_definition(definition, options, &block)
  urn = definition[:st]
  root_uri = definition[:location]

  xml = Nokogiri::XML(open(root_uri))
  xml.remove_namespaces!

  service = xml.xpath("//device/serviceList/service[serviceType=\"#{urn}\"]").first

  if service.nil?
    raise RuntimeError, "Couldn't find service with urn: #{urn}"
  else
    service = Nokogiri::XML(service.to_xml)
    service_definition_uri = URI.join(root_uri, service.xpath('service/SCPDURL').text).to_s
    service_definition = open(service_definition_uri) { |f| f.read }

    endpoint_url = ->(xpath) do
      URI.join(root_uri, service.xpath(xpath).text).to_s
    end

    DeviceControlPoint.new(
        urn,
        endpoint_url.call('service/controlURL'),
        endpoint_url.call('service/eventSubURL'),
        service_definition,
        options,
        &block
    )
  end
end

Instance Method Details

#add_event_callback(url, &block) ⇒ Object



155
156
157
158
159
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 155

def add_event_callback(url, &block)
  manager = EasyUpnp::SubscriptionManager.new(@events_client, url, &block)
  manager.subscribe
  manager
end

#arg_validator(method_ref, arg_name) ⇒ Object

Raises:

  • (ArgumentError)


133
134
135
136
137
138
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 133

def arg_validator(method_ref, arg_name)
  arg_ref = service_method(method_ref).arg_reference(arg_name)
  raise ArgumentError, "Unknown argument: #{arg_name}" if arg_ref.nil?

  @validator_provider.validator(arg_ref)
end

#method_args(method_ref) ⇒ Object



140
141
142
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 140

def method_args(method_ref)
  service_method(method_ref).in_args
end

#on_event(callback, &block) ⇒ Object

Raises:

  • (ArgumentError)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 161

def on_event(callback, &block)
  raise ArgumentError, 'Must provide block' if callback.nil?

  options = EventConfigOptions.new(&block)

  listener = EasyUpnp::HttpListener.new do |c|
    options.configure_http_listener.call(c)

    # It'd be kinda weird if a user set this (since a callback is taken as
    # an argument to the `on_event` method), but it'd be even weirder if
    # we ignored it.
    user_callback = c.callback
    c.callback do |r|
      user_callback.call(r) if user_callback
      callback.call(r)
    end
  end

  # exposing the URL as a lambda allows the subscription manager to get a
  # new URL should the server stop and start again on a different port.
  url = ->() { listener.listen }

  manager = EasyUpnp::SubscriptionManager.new(@events_client, url) do |c|
    options.configure_subscription_manager.call(c)

    user_shutdown = c.on_shutdown
    c.on_shutdown = ->() do
      user_shutdown.call if user_shutdown
      listener.shutdown
    end
  end

  manager.subscribe
  manager
end

#service_method(method_ref) ⇒ Object

Raises:

  • (ArgumentError)


144
145
146
147
148
149
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 144

def service_method(method_ref)
  method = @service_methods[method_ref]
  raise ArgumentError, "Unknown method: #{method_ref}" if method.nil?

  method
end

#service_methodsObject



151
152
153
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 151

def service_methods
  @service_methods.keys
end

#to_paramsObject



82
83
84
85
86
87
88
89
90
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 82

def to_params
  {
    urn: @urn,
    service_endpoint: @service_endpoint,
    events_endpoint: @events_endpoint,
    definition: @definition,
    options: @options.options
  }
end