Tizen 2.1 base
[platform/upstream/hplip.git] / base / wifi.py
1 # -*- coding: utf-8 -*-
2 #
3 # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # Author: Don Welch
20 #
21
22 # StdLib
23 import time
24 import cStringIO
25 import xml.parsers.expat
26
27 # Local
28 from base.g import *
29 from base import device, utils
30
31 MAX_NETWORKS = 100
32 MAX_RETRIES = 20
33 NS = "http://www.hp.com/schemas/imaging/cnc/dcsl/2006/05/WifiConfig"
34 PREAMBLE = """<?xml version="1.0" encoding="utf-8"?>
35 <WiFiConfig xmlns="%s">
36 """ % NS
37
38 def _readWriteWifiConfig(dev, request):
39     if not request:
40         log.error("Invalid request")
41         return 'executionfailed', {}
42
43     log.debug("Sending request on wifi config channel...")
44     log.log_data(request)
45     #log.xml(request)
46
47     bytes_written = dev.writeWifiConfig(request)
48     log.debug("Wrote %d bytes." % bytes_written)
49
50     data = cStringIO.StringIO()
51     log.debug("Reading response on wifi config channel...")
52     bytesread = dev.readWifiConfig(device.MAX_BUFFER, stream=data, timeout=30)
53     i = 0
54     # if response data is > 8192 bytes, make sure we have read it all...
55     while True:
56         i += 1
57         bytesread = dev.readWifiConfig(device.MAX_BUFFER, stream=data, timeout=1)
58         if not bytesread or i > MAX_RETRIES:
59             break
60
61     data = data.getvalue()
62
63     #log.xml(repr(data))
64
65     # Convert any char references
66     data = utils.unescape(data)
67
68     #log.xml(repr(data))
69     data = unicode(data, 'utf-8')
70
71     #log.xml(repr(data))
72
73     # C4380 returns invalid XML for DeviceCapabilitiesResponse
74     # Eliminate any invalid characters
75     data = data.replace(u"Devicecapabilities", u"DeviceCapabilities").replace('\x00', '')
76
77     log.log_data(data)
78     log.debug("Read %d bytes." % len(data))
79
80     if not data:
81         log.error("No data")
82         return 'executionfailed', {}
83
84     #log.xml(data)
85
86     try:
87         params = utils.XMLToDictParser().parseXML(data)
88     except xml.parsers.expat.ExpatError, e:
89         log.error("XML parser failed: %s" % e)
90         match = re.search(r"""line\s*(\d+).*?column\s*(\d+)""", str(e), re.I)
91         if match is not None:
92             log.error(data[int(match.group(2)):])
93         return 'executionfailed', {}
94
95     #log.pprint(params)
96
97     errorreturn = 'executionfailed'
98     for p in params:
99         if p.lower().endswith('errorreturn'):
100             errorreturn = params[p].lower()
101             break
102
103     params['errorreturn'] = errorreturn
104
105     return errorreturn, params
106
107 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
108
109
110 def getDeviceCapabilities(dev):
111     ret = {}
112     request = PREAMBLE + """<GetDeviceCapabilitiesRequest>
113 </GetDeviceCapabilitiesRequest>
114 </WiFiConfig>"""
115
116     errorreturn, params = _readWriteWifiConfig(dev, request)
117     if not params:
118         return {}
119
120     ret['errorreturn'] = errorreturn
121     if errorreturn != 'ok':
122         log.error("GetDeviceCapabilities returned an error: %s" % errorreturn)
123         return ret
124
125     param_keys = ['wificonfig-getdevicecapabilitiesresponse-devicecapabilities-numberofsupportedwifiaccessories',
126                   'wificonfig-getdevicecapabilitiesresponse-interfaceversion-minorreleasenumber',
127                   'wificonfig-getdevicecapabilitiesresponse-interfaceversion-majorreleasenumber',
128                  ]
129
130     for p in param_keys:
131         try:
132             ret[p.split('-')[-1]] = params[p]
133         except KeyError:
134             log.debug("Missing response key: %s" % p)
135             continue
136
137     return ret
138
139 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
140
141
142 def getAdaptorList(dev):
143     ret = {}
144     request = PREAMBLE + """<GetAdaptorListRequest>
145 </GetAdaptorListRequest>
146 </WiFiConfig>"""
147
148     errorreturn, params = _readWriteWifiConfig(dev, request)
149     if not params:
150         return {'adaptorlistlength': 0}
151
152     ret['errorreturn'] = errorreturn
153     if errorreturn != 'ok':
154         log.error("GetAdaptorList returned an error: %s" % errorreturn)
155         return ret
156
157     try:
158         adaptor_list_length = int(params['wificonfig-getadaptorlistresponse-adaptorlistlength'])
159     except (ValueError, KeyError):
160         adaptor_list_length = 0
161
162     ret['adaptorlistlength'] = adaptor_list_length
163
164     if adaptor_list_length == 0:
165         log.error("GetAdaptorList returned 0 adaptors")
166
167     elif adaptor_list_length == 1:
168         try:
169             ret['adaptorid-0'] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorid']
170             ret['adaptorname-0'] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorname']
171             ret['adaptorpresence-0'] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorpresence']
172             ret['adaptorstate-0'] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorstate']
173             ret['adaptortype-0'] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptortype']
174         except KeyError, e:
175             log.debug("Missing response key: %s" % e)
176     else:
177         for a in xrange(adaptor_list_length):
178             try:
179                 ret['adaptorid-%d' % a] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorid-%d' % a]
180                 ret['adaptorname-%d' % a] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorname-%d' % a]
181                 ret['adaptorpresence-%d' % a] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorpresence-%d' % a]
182                 ret['adaptorstate-%d' % a] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptorstate-%d' % a]
183                 ret['adaptortype-%d' % a] = params['wificonfig-getadaptorlistresponse-adaptorlist-adaptorinfo-adaptortype-%d' % a]
184             except KeyError, e:
185                 log.debug("Missing response key: %s" % e)
186
187     return ret
188
189 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
190
191 def getWifiAdaptorID(dev):
192     # ret: adaptor_id, name, state, presence
193     ret = getAdaptorList(dev)
194
195     try:
196         num_adaptors = ret['adaptorlistlength']
197     except KeyError:
198         num_adaptors = 0
199
200     for n in xrange(num_adaptors):
201         try:
202             name = ret['adaptortype-%d' % n]
203         except KeyError:
204             name = ''
205
206         if name.lower() in ('wifiembedded', 'wifiaccessory'):
207             params = ['adaptorid', 'adaptorname', 'adaptorstate', 'adaptorpresence']
208
209             r = []
210             for p in params:
211                 try:
212                     x = ret[''.join([p, '-', str(n)])]
213                 except KeyError:
214                     if p == 'adaptorid':
215                         x = -1
216                     else:
217                         x = 'Unknown'
218
219                 r.append(x)
220
221             return r
222
223     return -1, 'Unknown', 'Unknown', 'Unknown'
224
225 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
226
227
228 def setAdaptorPower(dev, adapterName, adaptor_id=0, power_state='PowerOn'):
229     ret = {}
230     request = PREAMBLE + """<SetAdaptorPowerRequest>
231 <AdaptorID>%s</AdaptorID>
232 <PowerState>%s</PowerState>
233 </SetAdaptorPowerRequest>
234 </WiFiConfig>""" % (adaptor_id, power_state.encode('utf-8'))
235
236     errorreturn, params = _readWriteWifiConfig(dev, request)
237     if not params:
238         return {}
239
240     ret['errorreturn'] = errorreturn
241     if errorreturn != 'ok':
242         log.error("SetAdaptorPower returned an error: %s" % errorreturn)
243         return ret
244
245     return ret
246
247 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
248
249
250 def performScan(dev, adapterName, ssid=None):
251     ret, i, scan_state = {}, 0, "NewScan"
252
253     while True:
254         if ssid is None: # Undirected
255             request = PREAMBLE + """<UndirectedScanRequest>
256 <ScanState>%s</ScanState>
257 </UndirectedScanRequest>
258 </WiFiConfig>""" % scan_state
259
260             typ = 'UndirectedScan'
261             rsp = 'undirectedscanresponse'
262
263         else: # Directed
264             request = PREAMBLE + """<DirectedScanRequest>
265 <SSID>%s</SSID>
266 <ScanState>%s</ScanState>
267 </DirectedScanRequest>
268 </WiFiConfig>""" % (ssid.encode('utf-8'), scan_state)
269
270             typ = 'Directed'
271             rsp = 'directedscanresponse'
272
273         errorreturn, params = _readWriteWifiConfig(dev, request)
274         if not params:
275             return {'numberofscanentries': 0}
276
277         ret['errorreturn'] = errorreturn
278         if errorreturn != 'ok':
279             log.error("%s returned an error: %s" % (typ, errorreturn))
280             return ret
281
282         try:
283             number_of_scan_entries = int(params['wificonfig-%s-numberofscanentries' % rsp])
284         except (ValueError, KeyError):
285             number_of_scan_entries = 0
286
287         ret['numberofscanentries'] = number_of_scan_entries
288
289         if number_of_scan_entries == 0:
290             if scan_state.lower() == 'scancomplete':
291                 log.debug("%s returned 0 entries. Scan complete." % typ)
292             else:
293                 log.debug("%s returned 0 entries. Resuming scan..." % typ)
294
295         elif number_of_scan_entries == 1:
296             try:
297                 ssid = params['wificonfig-%s-scanlist-scanentry-ssid' % rsp]
298                 if not ssid:
299                     ret['ssid-0'] = u'(unknown)'
300                 else:
301                     ret['ssid-0'] = ssid
302                 ret['bssid-0'] = params['wificonfig-%s-scanlist-scanentry-bssid' % rsp]
303                 ret['channel-0'] = params['wificonfig-%s-scanlist-scanentry-channel' % rsp]
304                 ret['communicationmode-0'] = params['wificonfig-%s-scanlist-scanentry-communicationmode' % rsp]
305                 ret['dbm-0'] = params['wificonfig-%s-scanlist-scanentry-dbm' % rsp]
306                 ret['encryptiontype-0'] = params['wificonfig-%s-scanlist-scanentry-encryptiontype' % rsp]
307                 ret['rank-0'] = params['wificonfig-%s-scanlist-scanentry-rank' % rsp]
308                 ret['signalstrength-0'] = params['wificonfig-%s-scanlist-scanentry-signalstrength' % rsp]
309             except KeyError, e:
310                 log.debug("Missing response key: %s" % e)
311
312         else:
313             for a in xrange(number_of_scan_entries):
314                 j = a+i
315                 try:
316                     ssid = params['wificonfig-%s-scanlist-scanentry-ssid-%d' % (rsp, j)]
317                     if not ssid:
318                         ret['ssid-%d' % j] = u'(unknown)'
319                     else:
320                         ret['ssid-%d' % j] = ssid
321                     ret['bssid-%d' % j] = params['wificonfig-%s-scanlist-scanentry-bssid-%d' % (rsp, j)]
322                     ret['channel-%d' % j] = params['wificonfig-%s-scanlist-scanentry-channel-%d' % (rsp, j)]
323                     ret['communicationmode-%d' % j] = params['wificonfig-%s-scanlist-scanentry-communicationmode-%d' % (rsp, j)]
324                     ret['dbm-%d' % j] = params['wificonfig-%s-scanlist-scanentry-dbm-%d' % (rsp, j)]
325                     ret['encryptiontype-%d' % j] = params['wificonfig-%s-scanlist-scanentry-encryptiontype-%d' % (rsp, j)]
326                     ret['rank-%d' % j] = params['wificonfig-%s-scanlist-scanentry-rank-%d' % (rsp, j)]
327                     ret['signalstrength-%d' % j] = params['wificonfig-%s-scanlist-scanentry-signalstrength-%d' % (rsp, j)]
328                 except KeyError, e:
329                     log.debug("Missing response key: %s" % e)
330
331         try:
332             scan_state = ret['scanstate'] = params['wificonfig-%s-scanstate' % rsp] # MoreEntriesAvailable, ScanComplete
333             ret['signalstrengthmax'] = params['wificonfig-%s-scansettings-signalstrengthmax' % rsp]
334             ret['signalstrengthmin'] = params['wificonfig-%s-scansettings-signalstrengthmin' % rsp]
335         except KeyError, e:
336             log.debug("Missing response key: %s" % e)
337
338         if scan_state.lower() == 'scancomplete':
339             break
340
341         scan_state = "ResumeScan"
342         i += number_of_scan_entries
343
344         if i > MAX_NETWORKS:
345             break
346
347         time.sleep(2)
348
349     return ret
350
351 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
352
353
354 def associate(dev, adapterName,ssid, communication_mode, encryption_type, key):
355     ret = {}
356     request = PREAMBLE + """<AssociateRequest>
357 <SSID>%s</SSID>
358 <CommunicationMode>%s</CommunicationMode>
359 <EncryptionType>%s</EncryptionType>
360 <EncryptedParameters>%s</EncryptedParameters>
361 <Key>%s</Key>
362 </AssociateRequest>
363 </WiFiConfig>""" % (ssid.encode('utf-8'), communication_mode.encode('utf-8'),
364                     encryption_type.encode('utf-8'), u"False".encode('utf-8'),
365                     key.encode('utf-8'))
366
367     errorreturn, params = _readWriteWifiConfig(dev, request)
368     if not params:
369         return {}
370
371     ret['errorreturn'] = errorreturn
372     if errorreturn != 'ok':
373         log.error("Associate returned an error: %s" % errorreturn)
374         return ret
375
376     return ret
377
378 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
379
380
381 def getVSACodes(dev,adapterName):
382     ret = []
383     request = PREAMBLE + """<GetVSACodesRequest>
384 </GetVSACodesRequest>
385 </WiFiConfig>"""
386
387     errorreturn, params = _readWriteWifiConfig(dev, request)
388     if not params:
389         return []
390
391     if errorreturn != 'ok':
392         log.error("GetVSACodes returned an error: %s" % errorreturn)
393         return ret
394
395     try:
396         rule = params['wificonfig-getvsacodesresponse-vsacodelist-vsacode-rulenumber']
397         severity = params['wificonfig-getvsacodesresponse-vsacodelist-vsacode-severity']
398     except KeyError:
399         n = 0
400         while True:
401             try:
402                 rule = params['wificonfig-getvsacodesresponse-vsacodelist-vsacode-rulenumber-%d' % n]
403             except KeyError:
404                 break
405
406             severity = params['wificonfig-getvsacodesresponse-vsacodelist-vsacode-severity-%d' % n]
407
408             ret.append((rule, severity))
409             n += 1
410     else:
411         ret.append((rule, severity))
412
413     return ret
414
415 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
416
417 def __getIPConfiguration(dev, adaptor_id=0):
418     ret = {}
419     request = PREAMBLE + """<GetIPConfigurationRequest>
420 <AdaptorID>%d</AdaptorID>
421 </GetIPConfigurationRequest>
422 </WiFiConfig>""" % adaptor_id
423
424     errorreturn, params = _readWriteWifiConfig(dev, request)
425     if not params:
426         return {}
427
428     ret['errorreturn'] = errorreturn
429     if errorreturn != 'ok':
430         log.error("GetIPConfiguration returned an error: %s" % errorreturn)
431         return ret
432
433     param_keys = ['wificonfig-getipconfigurationresponse-ipconfiguration-addressmode',
434                   'wificonfig-getipconfigurationresponse-ipconfiguration-alternatednsaddress',
435                   'wificonfig-getipconfigurationresponse-ipconfiguration-gatewayaddress',
436                   'wificonfig-getipconfigurationresponse-ipconfiguration-ipaddress',
437                   'wificonfig-getipconfigurationresponse-ipconfiguration-primarydnsaddress',
438                   'wificonfig-getipconfigurationresponse-ipconfiguration-subnetmask',
439                   'wificonfig-getipconfigurationresponse-networkconfiguration-hostname',
440                   ]
441
442     for p in param_keys:
443         try:
444             ret[p.split('-')[-1]] = params[p]
445         except KeyError:
446             log.debug("Missing response key: %s" % p)
447             continue
448
449     return ret
450
451
452 def getIPConfiguration(dev, adapterName, adaptor_id=0):
453     ip, hostname, addressmode, subnetmask, gateway, pridns, sec_dns = \
454         '0.0.0.0', 'Unknown', 'Unknown', '0.0.0.0', '0.0.0.0', '0.0.0.0', '0.0.0.0'
455     ret = __getIPConfiguration(dev, adaptor_id)
456
457     if ret and ret['errorreturn'].lower() == 'ok':
458         try:
459             ip = ret['ipaddress']
460             hostname = ret['hostname']
461             addressmode = ret['addressmode']
462             subnetmask = ret['subnetmask']
463             gateway = ret['gatewayaddress']
464             pridns = ret['primarydnsaddress']
465             sec_dns = ret['alternatednsaddress']
466         except KeyError, e:
467             log.debug("Missing response key: %s" % str(e))
468
469     return ip, hostname, addressmode, subnetmask, gateway, pridns, sec_dns
470
471 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
472
473 def __getSignalStrength(dev, adaptor_id=0):
474     ret = {}
475     request = PREAMBLE + """<GetSignalStrengthRequest>
476 <AdaptorID>%d</AdaptorID>
477 </GetSignalStrengthRequest>
478 </WiFiConfig>""" % adaptor_id
479
480     errorreturn, params = _readWriteWifiConfig(dev, request)
481     if not params:
482         return {}
483
484     ret['errorreturn'] = errorreturn
485     if errorreturn != 'ok':
486         log.error("GetSignalStrength returned an error: %s" % errorreturn)
487         return ret
488
489     param_keys = ['wificonfig-getsignalstrengthresponse-signalstrength-dbm',
490                   'wificonfig-getsignalstrengthresponse-signalstrength-signalstrengthmax',
491                   'wificonfig-getsignalstrengthresponse-signalstrength-signalstrengthmin',
492                   'wificonfig-getsignalstrengthresponse-signalstrength-signalstrengthvalue',
493                   ]
494
495     for p in param_keys:
496         try:
497             ret[p.split('-')[-1]] = params[p]
498         except KeyError:
499             log.debug("Missing response key: %s" % p)
500             continue
501
502     return ret
503
504
505 def getSignalStrength(dev, adapterName, ssid, adaptor_id=0):
506     ss_max, ss_min, ss_val, ss_dbm = 5, 0, 0, -200
507     ret = __getSignalStrength(dev, adaptor_id)
508
509     if ret and ret['errorreturn'].lower() == 'ok':
510         try:
511             ss_max = ret['signalstrengthmax']
512             ss_min = ret['signalstrengthmin']
513             ss_val = ret['signalstrengthvalue']
514             ss_dbm = ret['dbm']
515         except KeyError, e:
516             log.debug("Missing response key: %s" % str(e))
517
518     return ss_max, ss_min, ss_val, ss_dbm
519
520
521 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
522
523 def __getCryptoSuite(dev):
524     ret = {}
525     request = PREAMBLE + """<GetCryptoSuiteRequest>
526 </GetCryptoSuiteRequest>
527 </WiFiConfig>"""
528
529     errorreturn, params = _readWriteWifiConfig(dev, request)
530     if not params:
531         return {}
532
533     ret['errorreturn'] = errorreturn
534     if errorreturn != 'ok':
535         log.error("GetSignalStrength returned an error: %s" % errorreturn)
536         return ret
537
538     #log.pprint(params)
539
540     param_keys = ['wificonfig-getcryptosuiteresponse-cryposuite-crypoalgorithm',
541                   'wificonfig-getcryptosuiteresponse-cryposuite-crypomode',
542                   'wificonfig-getcryptosuiteresponse-cryposuite-secretid',]
543
544     for p in param_keys:
545         try:
546             ret[p.split('-')[-1]] = params[p]
547         except KeyError:
548             log.debug("Missing response key: %s" % p)
549             continue
550
551     return ret
552
553
554 def getCryptoSuite(dev, adapterName):
555     alg, mode, secretid = '', '', ''
556     ret = __getCryptoSuite(dev)
557
558     if ret and ret['errorreturn'].lower() == 'ok':
559         try:
560             alg = ret['crypoalgorithm']
561             mode = ret['crypomode']
562             secretid = ret['secretid']
563         except KeyError, e:
564             log.debug("Missing response key: %s" % str(e))
565
566     return  alg, mode, secretid
567
568 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
569
570 def getHostname(dev):
571     ret = ''
572     request = PREAMBLE + """<GetHostnameRequest>
573 </GetHostnameRequest>
574 </WiFiConfig>"""
575
576     errorreturn, params = _readWriteWifiConfig(dev, request)
577     if not params:
578         return ret
579
580     if errorreturn != 'ok':
581        # log.error("GetHostname returned an error: %s" % errorreturn)
582         return ret
583
584     try:
585         ret = params['wificonfig-gethostnameresponse-hostname']
586     except KeyError:
587         log.debug("Missing response key: hostname")
588
589     return ret
590
591 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
592
593
594 def getLocation(bssid, ss):
595     log.debug("Getting location for wifi AP: %s" % bssid)
596     request = """<?xml version='1.0'?>
597 <LocationRQ xmlns='http://skyhookwireless.com/wps/2005' version='2.6' street-address-lookup='full'>
598 <authentication version='2.0'>
599 <simple>
600 <username>beta</username>
601 <realm>js.loki.com</realm>
602 </simple>
603 </authentication>
604 <access-point>
605 <mac>%s</mac>
606 <signal-strength>%d</signal-strength>
607 </access-point>
608 </LocationRQ>""" % (bssid.encode("utf-8"), ss)
609
610     import httplib, socket
611     ret = {}
612     request_len = len(request)
613
614     log.log_data(request)
615
616     try:
617         conn = httplib.HTTPSConnection("api.skyhookwireless.com")
618         conn.putrequest("POST", "/wps2/location")
619         conn.putheader("Content-type", "text/xml")
620         conn.putheader("Content-Length", str(request_len))
621         conn.endheaders()
622         conn.send(request)
623     except (socket.gaierror, socket.error):
624         log.debug("Host connection error")
625         return {}
626
627     response = conn.getresponse()
628     if response.status != 200:
629         log.debug("Connection to location server failed")
630         return {}
631
632     xml = response.read()
633     log.log_data(xml)
634
635     try:
636         params = utils.XMLToDictParser().parseXML(xml)
637     except xml.parsers.expat.ExpatError:
638         return {}
639
640     if 'locationrs-error' in params:
641         log.debug("Location server returned failure")
642         return {}
643
644     ret['latitude'] = params.get('locationrs-location-latitude', 0)
645     ret['longitude'] = params.get('locationrs-location-longitude', 0)
646     street_number = params.get('locationrs-location-street-address-street-number', '')
647     street_name = params.get('locationrs-location-street-address-address-line', '')
648     city = params.get('locationrs-location-street-address-city', '')
649     country = params.get('locationrs-location-street-address-country-code', '')
650
651     address = "%s %s, %s, %s" % (street_number, street_name, city, country)
652     ret['address'] = address.strip()
653
654     return ret
655