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.



42
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
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 42

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
  )

  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



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

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



100
101
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
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 100

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



153
154
155
156
157
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 153

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)


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

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



138
139
140
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 138

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

#on_event(callback, &block) ⇒ Object

Raises:

  • (ArgumentError)


159
160
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
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 159

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)


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

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

  method
end

#service_methodsObject



149
150
151
# File 'lib/easy_upnp/control_point/device_control_point.rb', line 149

def service_methods
  @service_methods.keys
end

#to_paramsObject



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

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