loco.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import os
  2. import time
  3. import random
  4. import logging
  5. from urllib import urlopen, urlencode
  6. import thread
  7. from collections import defaultdict
  8. log = logging.getLogger()
  9. INTERVALL = 3
  10. MAX_INTERVALL = 100
  11. #~ LWS_ADDRESS = 'http://loco.visual-library.de'
  12. LWS_ADDRESS = 'http://127.0.0.1:20080'
  13. INTERESTING_SSIDS = set(['']) # ALL
  14. # for virtual device to replay measurements
  15. ID2MAC = {'107': '00:22:15:21:b0:c2',
  16. '108': '00:22:15:24:25:97',
  17. '109p2': '00:22:15:26:ad:c2',
  18. '114': '00:22:15:26:ac:ee',
  19. '104': '00:0f:a3:11:17:9a',
  20. '106': '00:22:15:22:51:18',
  21. '110p2': '00:22:15:26:ac:eb',
  22. 'edueg031': '00:17:df:a8:1b:41',
  23. 'eduegdemo': '00:17:df:a8:19:91',
  24. 'eduegcorr1': '00:17:df:a8:19:e1',
  25. 'eduegcorr2': '00:17:df:a7:e8:0d',
  26. 'eduog1108': '00:17:df:a8:03:21',
  27. 'eduog1server': '00:17:df:a7:e8:e1',
  28. 'eduog2206': '00:17:df:a8:a4:f1',
  29. 'eduog2kitchen': '00:17:df:a7:e9:31',
  30. 'eduog2corr': '00:17:df:a7:ea:f1',
  31. 'gaia': '00:23:69:b9:af:45',
  32. 'iris': '00:23:69:c2:67:1f',
  33. 'hyperion': '00:23:69:b9:aa:29',
  34. 'freya': '00:23:69:b9:a9:8d',
  35. '171': '00:12:17:cb:f8:26',
  36. '172': '00:0f:66:90:45:12',}
  37. def android(droid):
  38. ''' uses android API for wifi signals'''
  39. def _inner():
  40. scandata = {}
  41. try:
  42. startscan_result = droid.wifiStartScan().result
  43. res = droid.wifiGetScanResults().result
  44. except Exception:
  45. log.exception('error during accessing wifi api')
  46. return scandata
  47. for scanres in res:
  48. if not any(e in scanres['ssid'].lower() for e in INTERESTING_SSIDS):
  49. continue
  50. scandata[scanres['bssid']] = {'rssi': scanres['level'], 'ts': time.time(), 'ssid': scanres['ssid']}
  51. return scandata
  52. return _inner
  53. def pcap():
  54. ''' uses PCAP API for wifi signals'''
  55. from scapy.all import sniff
  56. from ieee_802_11_radio import Packet
  57. listPackets = sniff(iface='wlan1', timeout=0.11)
  58. def _inner():
  59. scandata = {}
  60. for channelN in [1,4,7,10,13,2,5,8,11,3,6,9,12]:
  61. os.system("iwconfig "+ 'wlan1' +" channel "+ str(channelN))
  62. for packet in listPackets:
  63. packetDecode = Packet(str(packet), packet)
  64. if packetDecode.prsntDbmSignal and packetDecode.prsntManagement:
  65. mac = packetDecode.AdrTranmitter
  66. ssid = packetDecode.SSID
  67. channel = packetDecode.Channel
  68. if not any(e in ssid.lower() for e in INTERESTING_SSIDS):
  69. continue
  70. if channel != channelN:
  71. continue
  72. rssi = packetDecode.DbmSignal
  73. #~ print mac, ssid, channel, rssi
  74. scandata[mac] = {'rssi': rssi, 'ts': time.time(), 'ssid': ssid}
  75. return scandata
  76. return _inner
  77. def virtual(datafile, pushfactor=1, buffer=1, filter=None):
  78. ''' virtual device, pumps data from measurement file'''
  79. state = {'i': 0, 'forward': True, 'lastts': 0}
  80. lines = open(datafile).read().strip().split('\n')
  81. def _inner():
  82. scandata = defaultdict(list)
  83. for j in range(buffer):
  84. i = state['i']
  85. s = lines[i]
  86. if state['forward']:
  87. if i < len(lines) - 1:
  88. i += 1
  89. else:
  90. state['forward'] = not state['forward']
  91. else:
  92. if i > 0:
  93. i -= 1
  94. else:
  95. state['forward'] = not state['forward']
  96. state['i'] = i
  97. data = [e.split(':') for e in s.split()]
  98. delay = 0
  99. pos = None
  100. for name, value in data:
  101. if name == 'ts':
  102. delay = abs(float(value) - state['lastts'])
  103. state['lastts'] = float(value)
  104. elif name == 'pos':
  105. pos = [float(e) for e in value.split(',')]
  106. else:
  107. if filter is not None:
  108. if not any(e in name for e in filter):
  109. continue
  110. # its an rssi value
  111. ssid = name # this is not really correct but we dont have a ssid stored
  112. rssi = value
  113. mac = ID2MAC.get(name, name)
  114. d = {'rssi': float(rssi), 'ts': time.time(), 'ssid': ssid}
  115. if pos is not None:
  116. d['pos'] = pos
  117. scandata[mac].append(d)
  118. time.sleep(delay / pushfactor)
  119. return scandata
  120. return _inner
  121. def communicate(url, post_params):
  122. t = time.time()
  123. log.info('transmitting...')
  124. try:
  125. #~ print url, urlencode(post_params)
  126. #~ print post_params
  127. return urlopen(url, data=urlencode(post_params)).read()
  128. except Exception:
  129. log.exception('error during communication')
  130. finally:
  131. log.info('... in %.3f sec' % (time.time() - t))
  132. def main(stationname, maxiter, iterlength, datafunc):
  133. url = '%s/%s/%s' % (LWS_ADDRESS, 'initDevice', stationname)
  134. log.info('fetching device cfg from %s' % url)
  135. cfg = urlopen(url).read()
  136. log.info('got: %s' % cfg)
  137. threaded, iterlength = cfg.split()
  138. threaded = threaded == 'true'
  139. iterlength = float(iterlength)
  140. log.info('threaded: %s, iterlength: %s' % (threaded, iterlength))
  141. def buildRecord(v):
  142. res = {'bssid': bssid,
  143. 'rssi': v['rssi'],
  144. 'ts': v['ts'],
  145. 'ssid': v['ssid'],
  146. }
  147. if 'pos' in v:
  148. res['pos'] = v['pos']
  149. return res
  150. url = '%s/%s' % (LWS_ADDRESS, 'newData')
  151. for i in range(maxiter):
  152. log.info('scan %s of %s' % (i+1, maxiter))
  153. scandata = datafunc()
  154. # convert to list of dicts
  155. _scandata = []
  156. for bssid, values in sorted(scandata.items()):
  157. if isinstance(values, list): # multiple values for this macaddr=bssid
  158. for _values in values:
  159. #~ log.debug('%s/%s: %.1f' % (_values['ssid'], bssid, _values['rssi']))
  160. _scandata.append(buildRecord(_values))
  161. else:
  162. #~ log.debug('%s/%s: %.1f' % (values['ssid'], bssid, values['rssi']))
  163. _scandata.append(buildRecord(values))
  164. post_params = [('name', stationname), ('data', str(_scandata))]
  165. if threaded:
  166. thread.start_new_thread(communicate, (url, post_params))
  167. else:
  168. communicate(url, post_params)
  169. time.sleep(iterlength)
  170. if __name__ == '__main__':
  171. logging.basicConfig(level=logging.DEBUG)
  172. #~ main('messbook', 20, 3, pcap())
  173. #~ main('iconia', 20000, 0, virtual(r'D:\loco-dev\dirk\tests\data\synthetic\measurements_0.txt', 1, 1, filter={'107', '108'}))
  174. main('iconia', 20000, 0, virtual(r'D:\loco-dev\dirk\tmp\tracked_path_synthetic\sigma_8.0\og1_long_rooms\measurements_00.txt',
  175. pushfactor=15, buffer=1, filter=None))
  176. #~ main('iconia', 20000, 0, virtual(r'D:\loco-dev\dirk\tmp\tracked_path_synthetic\sigma_8.0\og1_long_rooms\measurements_00.txt',
  177. #~ pushfactor=15, buffer=1, filter=None))