Ticket #142: urlbase.patch
| File urlbase.patch, 12.6 kB (added by Lawrence, 4 years ago) |
|---|
-
device.py
old new 5 5 # Copyright 2006, Frank Scholz <coherence@beebits.net> 6 6 7 7 import urllib2 8 from urlparse import urlparse,urljoin 8 9 import time 9 10 10 11 from twisted.internet import defer … … 79 80 def get_id(self): 80 81 return self.udn 81 82 83 def get_root_id(self): 84 if self.parent: 85 return self.parent.get_id() 86 return self.get_id() 87 82 88 def get_uuid(self): 83 89 return self.udn[5:] 84 90 91 def get_root_uuid(self): 92 if self.parent: 93 return self.parent.get_root_uuid() 94 return self.get_uuid() 95 85 96 def get_services(self): 86 97 return self.services 87 98 … … 139 150 140 151 def parse_device(self, d): 141 152 self.device_type = unicode(d.findtext('./{%s}deviceType' % ns)) 153 self.model_name = unicode(d.findtext('./{%s}modelName' % ns)) 142 154 self.friendly_name = unicode(d.findtext('./{%s}friendlyName' % ns)) 143 155 self.udn = d.findtext('.//{%s}UDN' % ns) 144 156 145 157 icon_list = d.find('./{%s}iconList' % ns) 146 158 if icon_list is not None: 147 159 import urllib2 148 url_base = "%s://%s" % urllib2.urlparse.urlparse(self.get_location())[:2]160 # url_base = "%s://%s" % urllib2.urlparse.urlparse(self.get_location())[:2] 149 161 for icon in icon_list.findall('./{%s}icon' % ns): 150 162 try: 151 163 i = {} … … 154 166 i['height'] = icon.find('./{%s}height' % ns).text 155 167 i['depth'] = icon.find('./{%s}depth' % ns).text 156 168 i['url'] = icon.find('./{%s}url' % ns).text 157 if i['url'].startswith('/'): 158 i['url'] = ''.join((url_base,i['url'])) 169 i['url'] = urljoin(get_url_base(), i['url']) 170 # if i['url'].startswith('/'): 171 # i['url'] = ''.join((url_base,i['url'])) 159 172 self.icons.append(i) 160 173 self.debug("adding icon %r for %r" % (i,self.friendly_name)) 161 174 except: … … 183 196 if len(controlUrl) == 0: 184 197 self.warning("service has no uri for controling") 185 198 continue 186 self.add_service(Service(serviceType, serviceId, self.get_ location(),199 self.add_service(Service(serviceType, serviceId, self.get_url_base(), 187 200 controlUrl, 188 201 eventSubUrl, presentationUrl, scpdUrl, self)) 189 202 … … 199 212 def get_location(self): 200 213 return self.parent.get_location() 201 214 215 def get_url_base(self): 216 return self.parent.get_url_base() 217 202 218 def get_usn(self): 203 219 return self.parent.get_usn() 204 220 … … 231 247 def get_location(self): 232 248 return self.location 233 249 250 def get_url_base(self): 251 return self.url_base 252 234 253 def get_host(self): 235 254 return self.host 236 255 … … 279 298 data, headers = x 280 299 tree = utils.parse_xml(data, 'utf-8').getroot() 281 300 301 # This is the base for all relative URLs 302 self.url_base = tree.findtext('./{%s}URLBase' % ns) 303 if self.url_base is None or len(self.url_base) == 0: 304 # not given in description so use location 305 306 # TODO should we parse out only protocol and host or use as is 307 # I think the url_base could contain part of a path as well. 308 parsed = urlparse(self.location) 309 # ensure has trailing slash 310 self.url_base = "%s://%s/" % (parsed[0], parsed[1]) 311 self.debug("url_base %r" % self.url_base) 312 282 313 d = tree.find('.//{%s}device' % ns) 283 314 if d is not None: 284 315 self.parse_device(d) # root device -
event.py
old new 243 243 log_category = "event_protocol" 244 244 log.info(log_category, "event.subscribe, action: %r", action) 245 245 246 _,host_port,path,_,_ = urlsplit(service.get_base_url()) 246 # _,host_port,path,_,_ = urlsplit(service.get_base_url()) 247 # have service keep complete event URL 248 _,host_port,path,_,_ = urlsplit(service.get_event_sub_url()) 247 249 if host_port.find(':') != -1: 248 250 host,port = tuple(host_port.split(':')) 249 251 port = int(port) … … 253 255 254 256 def send_request(p, action): 255 257 log.info(log_category, "event.subscribe.send_request %r, action: %r %r", 256 p, action, service.get_event_sub_url())258 p, action, path) 257 259 if action == 'subscribe': 258 260 timeout = service.timeout 259 261 if timeout == 0: 260 262 timeout = 1800 261 request = ["SUBSCRIBE %s HTTP/1.1" % service.get_event_sub_url(),263 request = ["SUBSCRIBE %s HTTP/1.1" % path, 262 264 "HOST: %s:%d" % (host, port), 263 265 "TIMEOUT: Second-%d" % timeout, 264 266 ] 265 267 service.event_connection = p 266 268 else: 267 request = ["UNSUBSCRIBE %s HTTP/1.1" % service.get_event_sub_url(),269 request = ["UNSUBSCRIBE %s HTTP/1.1" % path, 268 270 "HOST: %s:%d" % (host, port), 269 271 ] 270 272 … … 293 295 #return d 294 296 295 297 def got_error(failure, action): 296 log.info(log_category, "error on %s request with %s" % (action,service.get_base_url()))298 log.info(log_category, "error on %s request with %s", action,service.get_event_sub_url()) 297 299 log.debug(log_category, failure) 298 300 299 301 def teardown_connection(c, d): -
service.py
old new 7 7 import os 8 8 9 9 import time 10 import urllib2 10 from urlparse import urlparse,urljoin 11 11 from coherence.upnp.core import action 12 12 from coherence.upnp.core import event 13 13 from coherence.upnp.core import variable … … 41 41 class Service(log.Loggable): 42 42 logCategory = 'service_client' 43 43 44 def __init__(self, service_type, service_id, location, control_url,44 def __init__(self, service_type, service_id, url_base, control_url, 45 45 event_sub_url, presentation_url, scpd_url, device): 46 if not control_url.startswith('/'): 47 control_url = "/%s" % control_url 48 if not event_sub_url.startswith('/'): 49 event_sub_url = "/%s" % event_sub_url 50 if presentation_url and not presentation_url.startswith('/'): 51 presentation_url = "/%s" % presentation_url 52 if not scpd_url.startswith('/'): 53 scpd_url = "/%s" % scpd_url 54 46 55 47 self.service_type = service_type 56 48 self.detection_completed = False 57 self.id = service_id 58 self.control_url = control_url 59 self.event_sub_url = event_sub_url 60 self.presentation_url = presentation_url 61 self.scpd_url = scpd_url 49 self.id = service_id 50 51 self.control_url = urljoin(url_base, control_url) 52 self.event_sub_url = urljoin(url_base, event_sub_url) 53 self.presentation_url = urljoin(url_base, presentation_url) 54 self.scpd_url = urljoin(url_base, scpd_url) 55 62 56 self.device = device 63 57 self._actions = {} 64 58 self._variables = { 0: {}} … … 71 65 72 66 self.client = None 73 67 74 parsed = urllib2.urlparse.urlparse(location)75 self.url_base = "%s://%s" % (parsed[0], parsed[1])76 77 68 self.parse_actions() 78 self.info("%s %s %s initialized" % (self.device.friendly_name,self.service_type,self.id)) 69 self.info("%s %s %s initialized" % (self.device.friendly_name,self.service_type,self.id)) 70 self.debug("control_url %s", self.control_url) 71 self.debug("event_sub_url %s", self.event_sub_url) 72 self.debug("presentation_url %s", self.presentation_url) 73 self.debug("scpd_url %s", self.scpd_url) 79 74 80 75 def __repr__(self): 81 76 return "Service %s %s" % (self.service_type,self.id) … … 151 146 return self._actions 152 147 153 148 def get_action( self, name): 154 return self.get_actions()[name] 149 if self._actions.has_key(name): 150 return self._actions[name] 151 return None # not implemented 155 152 156 153 def get_state_variables(self, instance): 157 return self._variables.get(in stance)154 return self._variables.get(int(instance)) 158 155 159 156 def get_state_variable(self, name, instance=0): 160 157 instance = int(instance) 161 158 return self._variables.get(instance).get(name) 162 159 163 160 def get_control_url(self): 164 return self. url_base + self.control_url161 return self.control_url 165 162 166 163 def get_event_sub_url(self): 167 #return self.url_base + self.event_sub_url 168 return self.event_sub_url 164 return self.event_sub_url 169 165 170 166 def get_presentation_url(self): 171 return self. url_base + self.presentation_url167 return self.presentation_url 172 168 173 169 def get_scpd_url(self): 174 return self. url_base + self.scpd_url170 return self.scpd_url 175 171 176 def get_base_url(self):177 return self.url_base172 # def get_base_url(self): 173 # return self.url_base 178 174 179 175 def subscribe(self): 180 176 self.debug("subscribe %s", self.id) … … 215 211 def process_event(self,event): 216 212 self.info("process event %r" % self) 217 213 for var_name, var_value in event.items(): 218 if var_name == 'LastChange': 219 self.info("we have a LastChange event ")220 self.get_state_variable(var_name, 0).update(var_value) 221 tree = utils.parse_xml(var_value, 'utf-8').getroot() 214 if var_name == 'LastChange': 215 self.info("we have a LastChange event %s", var_value) 216 self.get_state_variable(var_name, 0).update(var_value) 217 tree = utils.parse_xml(var_value, 'utf-8').getroot() 222 218 namespace_uri, tag = tree.tag[1:].split( "}", 1) 223 219 for instance in tree.findall('{%s}InstanceID' % namespace_uri): 224 220 instance_id = instance.attrib['val'] … … 226 222 for var in instance.getchildren(): 227 223 self.info("var %r" % var) 228 224 namespace_uri, tag = var.tag[1:].split("}", 1) 229 self.info("%r %r %r" % (namespace_uri, tag,var.attrib['val'])) 230 self.get_state_variable(tag, instance_id).update(var.attrib['val']) 225 if len(var.attrib) > 1: 226 self.info("Extended StateVariable %s - %s", var.tag, var.attrib) 227 228 if var.attrib.has_key('channel') and var.attrib['channel'] != 'Master': 229 # TODO handle attributes that them selves have multiple instances 230 self.info("Skiiping update to %s its not for master channel %s", var.tag, var.attrib) 231 pass 232 else: 233 if not self.get_state_variables(instance_id) : 234 # TODO Create instance ? 235 self.error("%r update failed (not self.get_state_variables(instance_id)) %r", self, instance_id) 236 elif not self.get_state_variables(instance_id).has_key(tag): 237 # TODO Create instance StateVariable? 238 # SONOS stuff, it returns attributes that are not listed in the state decsription. The soap reply propogates the changes as state updates. 239 self.error("%r update failed (not self.get_state_variables(instance_id).has_key(tag)) %r", self, tag) 240 else: 241 val = None 242 if var.attrib.has_key('val'): 243 val = var.attrib['val'] 244 #self.debug("%r update %r %r %r", self,namespace_uri, tag, var.attrib['val']) 245 self.get_state_variable(tag, instance_id).update(val) 231 246 self.info("updated var %r" % var) 232 247 else: 233 248 self.get_state_variable(var_name, 0).update(var_value) … … 369 384 self._pending_notifications = {} 370 385 371 386 def get_action(self, action_name): 372 return self._actions[action_name] 387 if self._actions.has_key(name): 388 return self._actions[name] 389 return None # not implemented 373 390 374 391 def get_actions(self): 375 392 return self._actions
