Class: UPnPControlPoint
- Inherits:
-
Object
- Object
- UPnPControlPoint
- Defined in:
- lib/upnp_control_point.rb
Instance Attribute Summary collapse
-
#device_listener ⇒ Object
Returns the value of attribute device_listener.
-
#event_listener ⇒ Object
Returns the value of attribute event_listener.
-
#subscriptions ⇒ Object
Returns the value of attribute subscriptions.
Instance Method Summary collapse
- #build_device(ssdp_header) ⇒ Object
- #get_ip_address ⇒ Object
-
#initialize(host = '0.0.0.0', port = 0) ⇒ UPnPControlPoint
constructor
A new instance of UPnPControlPoint.
- #invoke_action(device, service, action_name, params) ⇒ Object
- #on_event_notify(sid, body) ⇒ Object
- #on_ssdp_header(ssdp_header) ⇒ Object
- #on_timer ⇒ Object
- #send_msearch(st, mx = 3) ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
- #subscribe(device, service) ⇒ Object
- #timer_loop ⇒ Object
- #unsubscribe(subscription) ⇒ Object
Constructor Details
#initialize(host = '0.0.0.0', port = 0) ⇒ UPnPControlPoint
Returns a new instance of UPnPControlPoint.
49 50 51 52 53 54 55 56 57 58 |
# File 'lib/upnp_control_point.rb', line 49 def initialize(host = '0.0.0.0', port = 0) @finishing = false @ssdp_listener = SSDP::SsdpListener.new @ssdp_listener.handler = self @http_server = WEBrick::HTTPServer.new :BindAddress => host, :Port => port @http_server.mount '/', EventNotifyServlet, self @devices = {} @subscriptions = {} @interval_timer = 10 end |
Instance Attribute Details
#device_listener ⇒ Object
Returns the value of attribute device_listener.
60 61 62 |
# File 'lib/upnp_control_point.rb', line 60 def device_listener @device_listener end |
#event_listener ⇒ Object
Returns the value of attribute event_listener.
60 61 62 |
# File 'lib/upnp_control_point.rb', line 60 def event_listener @event_listener end |
#subscriptions ⇒ Object
Returns the value of attribute subscriptions.
60 61 62 |
# File 'lib/upnp_control_point.rb', line 60 def subscriptions @subscriptions end |
Instance Method Details
#build_device(ssdp_header) ⇒ Object
106 107 108 109 |
# File 'lib/upnp_control_point.rb', line 106 def build_device(ssdp_header) uri = URI(ssdp_header.location) xml = Net::HTTP.get(uri) end |
#get_ip_address ⇒ Object
112 113 114 |
# File 'lib/upnp_control_point.rb', line 112 def get_ip_address Socket::getaddrinfo(Socket.gethostname, 'echo', Socket::AF_INET)[0][3] end |
#invoke_action(device, service, action_name, params) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/upnp_control_point.rb', line 152 def invoke_action(device, service, action_name, params) url = URI::join(device.base_url, service['controlURL']) soap_req = UPnPSoapRequest.new service.service_type, action_name soap_req.merge! params header = { 'SOAPACTION' => "#{service.service_type}##{action_name}", 'Content-Type' => 'text/xml; charset="utf-8' } http = Net::HTTP.new(url.host, url.port) req = Net::HTTP::Post.new(url.request_uri, header) req.body = soap_req.to_xml res = http.request(req) UPnPSoapResponse.read res.body end |
#on_event_notify(sid, body) ⇒ Object
63 64 65 66 67 68 |
# File 'lib/upnp_control_point.rb', line 63 def on_event_notify(sid, body) props = UPnPEventProperty.read(body) if @event_listener @event_listener.on_event_notify sid, props end end |
#on_ssdp_header(ssdp_header) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/upnp_control_point.rb', line 71 def on_ssdp_header(ssdp_header) if ssdp_header.notify_alive? or ssdp_header.http_response? usn = Usn.read(ssdp_header.usn) if not @devices.key? usn.udn xml = self.build_device ssdp_header if xml.to_s.empty? return end device = UPnPDevice.read xml device.base_url = ssdp_header.location @devices[usn.udn] = device if @device_listener @device_listener.on_device_added device end end elsif ssdp_header.notify_byebye? usn = Usn.read(ssdp_header['usn']) device = @devices[usn.udn] if device if @device_listener @device_listener.on_device_removed device end @devices.delete usn.udn end end end |
#on_timer ⇒ Object
168 169 170 |
# File 'lib/upnp_control_point.rb', line 168 def on_timer @devices.reject! {|key, value| value.expired? } end |
#send_msearch(st, mx = 3) ⇒ Object
99 100 101 102 103 |
# File 'lib/upnp_control_point.rb', line 99 def send_msearch(st, mx = 3) $logger.debug("send msearch / #{st}") SSDP.send_msearch st, mx, lambda { |ssdp_header| on_ssdp_header ssdp_header} end |
#start ⇒ Object
183 184 185 186 187 188 |
# File 'lib/upnp_control_point.rb', line 183 def start @finishing = false @ssdp_listener_thread = Thread.new { @ssdp_listener.run } @http_server_thread = Thread.new { @http_server.start } @timer_thread = Thread.new { timer_loop } end |
#stop ⇒ Object
191 192 193 194 195 196 |
# File 'lib/upnp_control_point.rb', line 191 def stop @finishing = true @http_server.shutdown @http_server_thread.join @timer_thread.join end |
#subscribe(device, service) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/upnp_control_point.rb', line 117 def subscribe(device, service) host = self.get_ip_address port = @http_server.config[:Port] headers = { 'NT' => 'upnp:event', 'CALLBACK' => "<http://#{host}:#{port}/event>", 'TIMEOUT' => 'Second-1800' } url = URI::join(device.base_url, service['eventSubURL']) Net::HTTP.start(url.host, url.port) { |http| req = SubscribeRequest.new url, initheader = headers res = http.request req sid = res['sid'] timeout = res['timeout'].split('-')[-1] subscription = UPnPEventSubscription.new device, service, sid, timeout @subscriptions[sid] = subscription return subscription } end |
#timer_loop ⇒ Object
172 173 174 175 176 177 178 179 180 181 |
# File 'lib/upnp_control_point.rb', line 172 def timer_loop start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) while not @finishing dur = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - start if dur >= @interval_timer on_timer start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) end end end |
#unsubscribe(subscription) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/upnp_control_point.rb', line 138 def unsubscribe(subscription) headers = { 'SID' => subscription.sid, } url = URI::join(subscription.device.base_url, subscription.service.scpdurl) Net::HTTP.start(url.host, url.port) { |http| req = UnsubscribeRequest.new url, initheader = headers res = http.request req $logger.debug("response : #{res.code}'") } @subscriptions.delete(subscription.sid) end |