def search_cell_lac(session, data): radio = RADIO_TYPE.get(data['radio'], -1) lacs = [] for cell in data['cell']: cell = normalized_cell_dict(cell, default_radio=radio) if not cell: continue cell['cid'] = CELLID_LAC key = to_cellkey(cell) query = session.query(Cell.lat, Cell.lon, Cell.range).filter( *join_cellkey(Cell, key)).filter( Cell.lat.isnot(None)).filter( Cell.lon.isnot(None) ) result = query.first() if result is not None: lacs.append(Network(key, *result)) if not lacs: return # take the smallest LAC of any the user is inside lac = sorted(lacs, key=operator.attrgetter('range'))[0] return { 'lat': quantize(lac.lat), 'lon': quantize(lac.lon), 'accuracy': max(LAC_MIN_ACCURACY, lac.range), }
def search_cell(session, data): sql_null = None # avoid pep8 warning radio = RADIO_TYPE.get(data['radio'], -1) cells = [] for cell in data['cell']: if cell.get('radio'): radio = RADIO_TYPE.get(cell['radio'], -1) query = session.query(Cell.lat, Cell.lon).filter( Cell.radio == radio).filter(Cell.mcc == cell['mcc']).filter( Cell.mnc == cell['mnc']).filter( Cell.lac == cell['lac']).filter( Cell.cid == cell['cid']).filter( Cell.lat != sql_null).filter(Cell.lon != sql_null) result = query.first() if result is not None: cells.append(result) if not cells: return length = len(cells) avg_lat = sum([c[0] for c in cells]) / length avg_lon = sum([c[1] for c in cells]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 35000, }
def search_cell(session, data): radio = RADIO_TYPE.get(data['radio'], -1) cells = [] for cell in data['cell']: cell = normalized_cell_dict(cell, default_radio=radio) if not cell: continue key = to_cellkey(cell) query = session.query(Cell.lat, Cell.lon, Cell.range).filter( *join_cellkey(Cell, key)).filter( Cell.lat.isnot(None)).filter( Cell.lon.isnot(None) ) result = query.first() if result is not None: cells.append(Network(key, *result)) if not cells: return length = len(cells) avg_lat = sum([c.lat for c in cells]) / length avg_lon = sum([c.lon for c in cells]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': estimate_accuracy(avg_lat, avg_lon, cells, CELL_MIN_ACCURACY), }
def search_wifi(session, data): wifi_data = data['wifi'] wifi_keys = set([normalize_wifi_key(w['key']) for w in wifi_data]) if not any(wifi_keys): # no valid normalized keys return None if len(wifi_keys) < 2: # we didn't even get two keys, bail out return None sql_null = None # avoid pep8 warning query = session.query(Wifi.lat, Wifi.lon).filter( Wifi.key.in_(wifi_keys)).filter(Wifi.lat != sql_null).filter( Wifi.lon != sql_null) wifis = query.all() if len(wifis) < 2: # we got fewer than two actual matches return None length = len(wifis) avg_lat = sum([w[0] for w in wifis]) / length avg_lon = sum([w[1] for w in wifis]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 500, }
def search_cell(session, data): sql_null = None # avoid pep8 warning radio = RADIO_TYPE.get(data['radio'], -1) cells = [] for cell in data['cell']: if cell.get('radio'): radio = RADIO_TYPE.get(cell['radio'], -1) query = session.query(Cell.lat, Cell.lon).filter( Cell.radio == radio).filter( Cell.mcc == cell['mcc']).filter( Cell.mnc == cell['mnc']).filter( Cell.lac == cell['lac']).filter( Cell.cid == cell['cid']).filter( Cell.lat != sql_null).filter( Cell.lon != sql_null ) result = query.first() if result is not None: cells.append(result) if not cells: return length = len(cells) avg_lat = sum([c[0] for c in cells]) / length avg_lon = sum([c[1] for c in cells]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 35000, }
def search_wifi(session, data): wifi_data = data['wifi'] wifi_keys = set([normalize_wifi_key(w['key']) for w in wifi_data]) if not any(wifi_keys): # no valid normalized keys return None if len(wifi_keys) < 2: # we didn't even get two keys, bail out return None sql_null = None # avoid pep8 warning query = session.query(Wifi.lat, Wifi.lon).filter( Wifi.key.in_(wifi_keys)).filter( Wifi.lat != sql_null).filter( Wifi.lon != sql_null) wifis = query.all() if len(wifis) < 2: # we got fewer than two actual matches return None length = len(wifis) avg_lat = sum([w[0] for w in wifis]) / length avg_lon = sum([w[1] for w in wifis]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 500, }
def search_cell(session, data): radio = RADIO_TYPE.get(data['radio'], -1) cell = data['cell'][0] if cell.get('radio'): radio = RADIO_TYPE.get(cell['radio'], -1) mcc = cell['mcc'] mnc = cell['mnc'] lac = cell['lac'] cid = cell['cid'] query = session.query(Cell) query = query.filter(Cell.radio == radio) query = query.filter(Cell.mcc == mcc) query = query.filter(Cell.mnc == mnc) query = query.filter(Cell.cid == cid) if lac >= 0: query = query.filter(Cell.lac == lac) result = query.first() if result is None: return return { 'lat': quantize(result.lat), 'lon': quantize(result.lon), 'accuracy': 35000, }
def search_cell_lac(session, data): sql_null = None # avoid pep8 warning radio = RADIO_TYPE.get(data['radio'], -1) lacs = [] for cell in data['cell']: if cell['mcc'] < 1 or cell['mnc'] < 0 or \ cell['lac'] < 0 or cell['cid'] < 0: # Skip over invalid values continue if cell.get('radio'): radio = RADIO_TYPE.get(cell['radio'], -1) query = session.query(Cell).filter( Cell.radio == radio).filter( Cell.mcc == cell['mcc']).filter( Cell.mnc == cell['mnc']).filter( Cell.lac == cell['lac']).filter( Cell.cid == CELLID_LAC).filter( Cell.lat != sql_null).filter( Cell.lon != sql_null ) result = query.first() if result is not None: lacs.append(result) if not lacs: return None # take the smallest LAC of any the user is inside lac = sorted(lacs, key=operator.attrgetter('range'))[0] return { 'lat': quantize(lac.lat), 'lon': quantize(lac.lon), 'accuracy': lac.range, }
def search_wifi(session, data): wifi_data = data['wifi'] wifi_keys = set([normalize_wifi_key(w['key']) for w in wifi_data]) if not any(wifi_keys): # no valid normalized keys return None if len(wifi_keys) < 3: # we didn't even get three keys, bail out return None sql_null = None # avoid pep8 warning query = session.query(Wifi.lat, Wifi.lon).filter( Wifi.key.in_(wifi_keys)).filter( Wifi.lat != sql_null).filter( Wifi.lon != sql_null) wifis = query.all() if len(wifis) < 3: # we got fewer than three actual matches return None length = len(wifis) avg_lat = sum([w[0] for w in wifis]) / length avg_lon = sum([w[1] for w in wifis]) / length # check to make sure all wifi AP's are close by # we might later relax this to allow some outliers latitudes = [w[0] for w in wifis] longitudes = [w[1] for w in wifis] lat_diff = abs(max(latitudes) - min(latitudes)) lon_diff = abs(max(longitudes) - min(longitudes)) if lat_diff >= MAX_DIFF or lon_diff >= MAX_DIFF: return None return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 500, }
def search_cell(session, data): radio = RADIO_TYPE.get(data['radio'], -1) cells = [] for cell in data['cell']: if cell['mcc'] < 1 or cell['mnc'] < 0 or \ cell['lac'] < 0 or cell['cid'] < 0: # Skip over invalid values continue if cell.get('radio'): radio = RADIO_TYPE.get(cell['radio'], -1) query = session.query(Cell.lat, Cell.lon).filter( Cell.radio == radio).filter( Cell.mcc == cell['mcc']).filter( Cell.mnc == cell['mnc']).filter( Cell.lac == cell['lac']).filter( Cell.cid == cell['cid']).filter( Cell.lat.isnot(None)).filter( Cell.lon.isnot(None) ) result = query.first() if result is not None: cells.append(result) if not cells: return length = len(cells) avg_lat = sum([c[0] for c in cells]) / length avg_lon = sum([c[1] for c in cells]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 35000, }
def search_wifi(session, data): # Estimate signal strength at -100 dBm if none is provided, # which is worse than the 99th percentile of wifi dBms we # see in practice (-98). def signal_strength(w): if 'signal' in w: return int(w['signal']) else: return -100 wifi_signals = dict([(normalized_wifi_key(w['key']), signal_strength(w)) for w in data['wifi']]) wifi_keys = set(wifi_signals.keys()) if not any(wifi_keys): # No valid normalized keys. return None if len(wifi_keys) < MIN_WIFIS_IN_QUERY: # We didn't get enough keys. return None query = session.query(Wifi.key, Wifi.lat, Wifi.lon, Wifi.range).filter( Wifi.key.in_(wifi_keys)).filter( Wifi.lat.isnot(None)).filter( Wifi.lon.isnot(None)) wifis = query.all() if len(wifis) < MIN_WIFIS_IN_QUERY: # We didn't get enough matches. return None wifis = [Network(normalized_wifi_key(w[0]), w[1], w[2], w[3]) for w in wifis] # Sort networks by signal strengths in query. wifis.sort(lambda a, b: cmp(wifi_signals[b.key], wifi_signals[a.key])) clusters = [] # The first loop forms a set of clusters by distance, # preferring the cluster with the stronger signal strength # if there's a tie. for w in wifis: # Try to assign w to a cluster (but at most one). for c in clusters: for n in c: if distance(quantize(n.lat), quantize(n.lon), quantize(w.lat), quantize(w.lon)) <= MAX_WIFI_CLUSTER_KM: c.append(w) w = None break if w is None: break # If w didn't adhere to any cluster, make a new one. if w is not None: clusters.append([w]) # The second loop selects a cluster and estimates the position of that # cluster. The selected cluster is the one with the most points, larger # than MIN_WIFIS_IN_CLUSTER; its position is estimated taking up-to # MAX_WIFIS_IN_CLUSTER worth of points from the cluster, which is # pre-sorted in signal-strength order due to the way we built the # clusters. # # The reasoning here is that if we have >1 cluster at all, we probably # have some bad data -- likely an AP or set of APs associated with a # single antenna that moved -- since a user shouldn't be able to hear # multiple groups 500m apart. # # So we're trying to select a cluster that's most-likely good data, # which we assume to be the one with the most points in it. # # The reason we take a subset of those points when estimating location # is that we're doing a (non-weighted) centroid calculation, which is # itself unbalanced by distant elements. Even if we did a weighted # centroid here, using radio intensity as a proxy for distance has an # error that increases significantly with distance, so we'd have to # underweight pretty heavily. clusters = [c for c in clusters if len(c) > MIN_WIFIS_IN_CLUSTER] if len(clusters) == 0: return None clusters.sort(lambda a, b: cmp(len(b), len(a))) cluster = clusters[0] sample = cluster[:min(len(cluster), MAX_WIFIS_IN_CLUSTER)] length = len(sample) avg_lat = sum([n.lat for n in sample]) / length avg_lon = sum([n.lon for n in sample]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': estimate_accuracy(avg_lat, avg_lon, sample, WIFI_MIN_ACCURACY), }
def search_wifi(session, data): # estimate signal strength at -100 dBm if none is provided, # which is worse than the 99th percentile of wifi dBms we # see in practice (-98). def signal_strength(w): if 'signal' in w: return int(w['signal']) else: return -100 wifi_signals = dict([(normalize_wifi_key(w['key']), signal_strength(w)) for w in data['wifi']]) wifi_keys = set(wifi_signals.keys()) if not any(wifi_keys): # no valid normalized keys return None if len(wifi_keys) < 3: # we didn't even get three keys, bail out return None sql_null = None # avoid pep8 warning query = session.query(Wifi.key, Wifi.lat, Wifi.lon).filter( Wifi.key.in_(wifi_keys)).filter( Wifi.lat != sql_null).filter( Wifi.lon != sql_null) wifis = query.all() if len(wifis) < 3: # we got fewer than three actual matches return None wifis = [Network(normalize_wifi_key(w[0]), w[1], w[2]) for w in wifis] # sort networks by signal strengths in query wifis.sort(lambda a, b: cmp(wifi_signals[b.key], wifi_signals[a.key])) clusters = [] for w in wifis: # try to assign w to a cluster (but at most one) for c in clusters: for n in c: if distance(quantize(n.lat), quantize(n.lon), quantize(w.lat), quantize(w.lon)) <= MAX_DIST: c.append(w) w = None break if len(c) >= 3: # if we have a cluster with more than 3 # networks in it, return its centroid. length = len(c) avg_lat = sum([n.lat for n in c]) / length avg_lon = sum([n.lon for n in c]) / length return { 'lat': quantize(avg_lat), 'lon': quantize(avg_lon), 'accuracy': 500, } if w is None: break # if w didn't adhere to any cluster, make a new one if w is not None: clusters.append([w]) # if we didn't get any clusters with >3 networks, # the query is a bunch of outliers; give up and # let the next location method try. return None