From 5e3ccec21d0ec9841f4946773b697c6e6c953135 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 16 Jun 2015 11:03:37 -0400 Subject: [PATCH 01/60] Changed based on code review --- blur_location2city.r2py | 269 ++++++++++++++++++++++++---------------- 1 file changed, 162 insertions(+), 107 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index 30a8bd2..fd940de 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -1,144 +1,198 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the coordinates, received +from the location sensors of an Android device, to the geographic center of +approximately the nearest city. + +The blurring is done using a DB lookup method. The DB contains a list of +cities, and their geodata (lat, lon, country code, state code), divided +by their coordinates. The DB is is available at: +http://sensibilityclearinghouse.poly.edu/data/quad/ + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2city.r2py user-program.r2py +""" + + + httpretrieve = dy_import_module("httpretrieve.r2py") math = dy_import_module("math.r2py") -librepyfile = dy_import_module("librepyfile.r2py") -statefilename = "states.txt" # Database of states -countryfilename = "countries.txt" # Database of countries -# Downloads the required file from the server def get_file_from_server(filename): + """ + Downloads the required file from the DB server, if it has not already + been downloaded. - if filename not in listfiles(): # In case it already exists - if filename not in [statefilename, countryfilename]: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename httpretrieve.httpretrieve_save_file(url, filename) -# Returns a dictionary containing information about the point closest to -# a given lat/lng pair, from the database. -# {"city": closest_city, "statecode": closest_state_code, "countrycode": -# closest_country_code, "coordinates": closest_point} -def find_closest_point(lat, lng): - - # Find the database file with coordinates closest to the given lat/lng pair - filename = get_filename(lat, lng) - # Get the list of coordinates from that file - listofpoints = load_lat_lng_from_file(filename) - min_dist = 9999 - point1 = (lat, lng) +def find_closest_city(lat, lon): + """ + Searches the DB and returns a dict containing the geodata of the city + that is approximately closest to a given lat/lon pair in the format: + { + "city_name": city name (string), + "state_code": 2-digit code representing the state to which the city + belongs (string), + "country_code": 2-letter ISO-3166 code representing the country to + which the city belongs (string), + "coordinates": tuple containing the lat/lon pair representing the + geographic center of the city (float, float) + } + + Note: We're looking for the closest lat/lon pair within the same + quadrant as the given lat/lon pair. There might be closer ones in + other quadrants. Thus, the "closest city" is only an approximation. + + """ + # Determine which file to download from the DB. + filename = get_database_filename(lat, lon) + + # Load all the cities and their geodata from the file. + city_dict = load_city_geodata(filename) + + # Set the minimum squared difference between two pairs of coordinates + # to an arbitrarily large number. + # XXX Should "large" be defined? + min_diff = 9999 + + for city_name, city_geodata in city_dict.items(): + city_lat, city_lon = city_geodata["coordinates"] + diff = find_squared_difference((lat, lon), (city_lat, city_lon)) + if diff < min_diff: + min_diff = diff + closest_city_coordinates = city_geodata["coordinates"] + closest_city_name = city_name + closest_city_state_code = city_geodata["state_code"] + closest_city_country_code = city_geodata["country_code"] + + closest_city_geodata = {"city_name": closest_city_name, + "coordinates": closest_city_coordinates, + "state_code": closest_city_state_code, + "country_code": closest_city_country_code + } + + return closest_city_geodata + + + +def get_database_filename(lat, lon): + """ + Returns the filename in the DB with coordinates in the same quadrant + as the given lat/lon pair. + + """ + # Get ceiling as x/y index. + x = int(math.math_ceil(lat)) + y = int(math.math_ceil(lon)) + filename = str(x) + '_' + str(y) + '.txt' + return filename - for city in listofpoints.keys(): - data = listofpoints[city] - point2 = (data[0], data[1]) - dist = find_distance(point1, point2) - if dist < min_dist: - min_dist = dist - closest_point = point2 - closest_city = city - closest_state_code = data[3] - closest_country_code = data[2] - closest = {"city": closest_city, "statecode": closest_state_code, "countrycode": closest_country_code, "coordinates": closest_point} - return closest +def load_city_geodata(filename): + """ + Returns a dict containing all the cities in the given file, + along with their corresponding geodata in the format: + { + city1: {"coordinates": (lat, lon), "country_code": country_code, + "state_code": state_code}, + city2: {"coordinates": (lat, lon), "country_code": country_code, + "state_code": state_code}, + ... + } + """ + get_file_from_server(filename) + city_dict = {} + city_geodata_fileobj = openfile(filename, False) + city_geodata_file = city_geodata_fileobj.reat(None, 0).split("\n") -# Returns the filename in the database with coordinates closest to the given lat/lng pair -def get_filename(lat, lng): + for line in city_geodata_file: + # Ignore the empty line at the end of the file + if line == "": + continue + city_geodata_record = line.split("\t") + city_name = city_geodata_record[0] + lat = float(city_geodata_record[1]) + lon = float(city_geodata_record[2]) + city_dict[city_name] = {"coordinates": (lat, lon), + "country_code": city_geodata_record[3], + "state_code": city_geodata_record[4] + } + city_geodata_fileobj.close() + return city_dict - # get ceiling as x/y index - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lng)) - filename = str(x) + '_' + str(y) + '.txt' - return filename -# Returns a dictionary containing all the cities in the given file, along with -# their corresponding data -# {city1: [lat, lng, country_code, state_code], city2: [lat, lng, country_code, -# state_code], ...} -def load_lat_lng_from_file(filename): +def find_squared_difference(p1, p2): + """ + Returns the squared difference between two pairs of coordinates (p1 + and p2). - get_file_from_server(filename) - listofpoints = {} - fileobj = librepyfile.open(filename, "r") - - while True: - try: - line = fileobj.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - city_name = line[0] - lat = line[1] - lng = line[2] - country_code = line[3] - state_code = line[4] - listofpoints[city_name] = [lat, lng, country_code, state_code] - fileobj.close() - return listofpoints - - -# Returns the distance between two lat/lng points -def find_distance(p1, p2): - - (lat1, lng1) = p1 - (lat2, lng2) = p2 - lat2 = float(lat2) - lng2 = float(lng2) - lat_diff = (lat1-lat2) * (lat1-lat2) - lng_diff = (lng1-lng2) * (lng1-lng2) - # return squared distance - return lat_diff + lng_diff - - -# To replace get_location() -def get_city_location(): + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff - try: - location_data = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - latitude = location_data["latitude"] - longitude = location_data["longitude"] - closest = find_closest_point(latitude, longitude) +def get_city_location(): + """ + Security layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the nearest city. - location_data["latitude"] = closest["coordinates"][0] - location_data["longitude"] = closest["coordinates"][1] + """ + location_data = get_location() - return location_data + closest_city = find_closest_city(location_data["latitude"], + location_data["longitude"]) + location_data["latitude"], location_data["longitude"] = \ + closest["coordinates"] -# To replace get_lastknown_location() -def get_city_lastknown_location(): + return location_data - try: - location_data = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - # Get the location from the the provider - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - latitude = location["latitude"] - longitude = location["longitude"] - closest = find_closest_point(latitude, longitude) - location_data[provider]["latitude"] = closest["coordinates"][0] - location_data[provider]["longitude"] = closest["coordinates"][1] +def get_city_lastknown_location(): + """ + Security layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the nearest city. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + closest_city = find_closest_city(provider_location_data["latitude"], + provider_location_data["longitude"]) + + location_data[location_provider]["latitude"], \ + location_data[provider]["longitude"] = closest["coordinates"] return location_data + +# Makes a security layer out of what otherwise would be just a plain +# library you could `dy_import` CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -156,4 +210,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { "target": get_city_lastknown_location, } + secure_dispatch_module() \ No newline at end of file From bfa6f061465e162e74516e5331e0fa65a03528c8 Mon Sep 17 00:00:00 2001 From: aditup Date: Thu, 18 Jun 2015 21:06:09 -0400 Subject: [PATCH 02/60] Fixed errors --- blur_location2city.r2py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index fd940de..b72a0ce 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -28,7 +28,7 @@ def get_file_from_server(filename): """ if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename httpretrieve.httpretrieve_save_file(url, filename) @@ -113,7 +113,7 @@ def load_city_geodata(filename): get_file_from_server(filename) city_dict = {} city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.reat(None, 0).split("\n") + city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") for line in city_geodata_file: # Ignore the empty line at the end of the file @@ -159,7 +159,7 @@ def get_city_location(): location_data["longitude"]) location_data["latitude"], location_data["longitude"] = \ - closest["coordinates"] + closest_city["coordinates"] return location_data @@ -185,7 +185,7 @@ def get_city_lastknown_location(): provider_location_data["longitude"]) location_data[location_provider]["latitude"], \ - location_data[provider]["longitude"] = closest["coordinates"] + location_data[location_provider]["longitude"] = closest_city["coordinates"] return location_data From 4bc06ba220d42f8e78889d5f6ca18e241220e5ce Mon Sep 17 00:00:00 2001 From: aditup Date: Fri, 19 Jun 2015 00:41:44 -0400 Subject: [PATCH 03/60] Added check_airplane_mode --- getsensor.r2py | 26 ++++++++++++++++++++++++++ sensor_layer.r2py | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/getsensor.r2py b/getsensor.r2py index c285cea..f584c29 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -239,3 +239,29 @@ def do_wifi_scan(): # we do not need to stop scan (it stops itself after scan is done) # convert unicode format to ASCII return unicode_scrubber.scrub(wifi_data) + + +def check_airplane_mode(): + """ + + Return if Airplane mode is enabled on this device (True/False). + + + None + + + None. + + + None. + + + Lookup if Airplane mode is enabled on the device. + + + A boolean vaiable indicating if Airplane mode is enabled on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) \ No newline at end of file diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 98f6846..4570a50 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -52,5 +52,14 @@ CHILD_CONTEXT_DEF["do_wifi_scan"] = { "target": getsensor.do_wifi_scan, } + +CHILD_CONTEXT_DEF["check_airplane_mode"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.check_airplane_mode, +} + secure_dispatch_module() From 277d6a6dc35f949bc7e8074fa4c518fd274c6add Mon Sep 17 00:00:00 2001 From: aditup Date: Fri, 19 Jun 2015 00:55:31 -0400 Subject: [PATCH 04/60] Added check_ringer_silent_mode --- getsensor.r2py | 27 ++++++++++++++++++++++++++- sensor_layer.r2py | 10 +++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index f584c29..a82515a 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -264,4 +264,29 @@ def check_airplane_mode(): """ # True or False - return sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) \ No newline at end of file + return sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) + +def check_ringer_silent_mode(): + """ + + Return if Silent mode is enabled on this device (True/False). + + + None + + + None. + + + None. + + + Lookup if Silent mode is enabled on the device. + + + A boolean vaiable indicating if Silent mode is enabled on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'checkRingerSilentMode', []) \ No newline at end of file diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 4570a50..e80d6eb 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -61,5 +61,13 @@ CHILD_CONTEXT_DEF["check_airplane_mode"] = { "target": getsensor.check_airplane_mode, } -secure_dispatch_module() +CHILD_CONTEXT_DEF["check_ringer_silent_mode"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.check_ringer_silent_mode, +} + +secure_dispatch_module() From 826a50c72c3f440ce2a303c2083e3e18a21158ae Mon Sep 17 00:00:00 2001 From: aditup Date: Fri, 19 Jun 2015 03:13:41 -0400 Subject: [PATCH 05/60] Edited docstrings, Added modules Added check_screen_on, get_max_media_volume --- getsensor.r2py | 110 +++++++++++++++++++++++++++++++++++++++------- sensor_layer.r2py | 18 ++++++++ 2 files changed, 112 insertions(+), 16 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index a82515a..26c8786 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -36,7 +36,7 @@ def get_location(): using unicode_scrubber. - None + None. LocationNotFoundException (descends from RepyException) when no location @@ -90,7 +90,7 @@ def get_lastknown_location(): using unicode_scrubber. - None + None. LocationNotFoundException (descends from RepyException) when the returned @@ -143,7 +143,7 @@ def is_wifi_enabled(): Return if WiFi is enabled on this device (True/False). - None + None. None. @@ -155,8 +155,8 @@ def is_wifi_enabled(): Lookup if WiFi is enabled on the device. - A boolean vaiable indicating if WiFi is enabled on the device. - + A boolean variable indicating if WiFi is enabled on the device. + """ # True or False @@ -170,7 +170,7 @@ def get_wifi_connection_info(): sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []). - None + None. None. @@ -209,7 +209,7 @@ def do_wifi_scan(): sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []). - None + None. None. @@ -244,10 +244,10 @@ def do_wifi_scan(): def check_airplane_mode(): """ - Return if Airplane mode is enabled on this device (True/False). + Checks whether the Airplane mode setting has been turned on. - None + None. None. @@ -259,20 +259,20 @@ def check_airplane_mode(): Lookup if Airplane mode is enabled on the device. - A boolean vaiable indicating if Airplane mode is enabled on the device. - + A boolean variable indicating if Airplane mode is enabled on the device. + """ # True or False return sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) - + def check_ringer_silent_mode(): """ - Return if Silent mode is enabled on this device (True/False). + Checks the ringer silent mode setting on the device (True/False). - None + None. None. @@ -284,9 +284,87 @@ def check_ringer_silent_mode(): Lookup if Silent mode is enabled on the device. - A boolean vaiable indicating if Silent mode is enabled on the device. + A boolean variable indicating if Silent mode is enabled on the device. """ # True or False - return sensorlib.request_data(sensor_socket, 'checkRingerSilentMode', []) \ No newline at end of file + return sensorlib.request_data(sensor_socket, 'checkRingerSilentMode', []) + + +def check_screen_on(): + """ + + Checks if the screen is currently on or off (True/False). + + + None. + + + None. + + + None. + + + Lookup if screen is currently on on the device. + + + A boolean variable indicating if screen is currently on on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'checkScreenOn', []) + + +def get_max_media_volume(): + """ + + Returns the current maximum media volume on the device. + + + None. + + + None. + + + None. + + + Lookup the current maximum media volume on the device. + + + A integer variable indicating the maximum media volume on the device. + Calls sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []). + + """ + + sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []) + + +def get_max_media_volume(): + """ + + Returns the current maximum media volume on the device. + + + None. + + + None. + + + None. + + + Lookup the current maximum media volume on the device. + + + A integer variable indicating the maximum media volume on the device. + Calls sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []). + + """ + + sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []) \ No newline at end of file diff --git a/sensor_layer.r2py b/sensor_layer.r2py index e80d6eb..f9b77fc 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -70,4 +70,22 @@ CHILD_CONTEXT_DEF["check_ringer_silent_mode"] = { "target": getsensor.check_ringer_silent_mode, } + +CHILD_CONTEXT_DEF["check_screen_on"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.check_screen_on, +} + + +CHILD_CONTEXT_DEF["get_max_media_volume"] = { + "type": "func", + "args": None, + "return": (int,type(None)), + "exceptions": "any", + "target": getsensor.get_max_media_volume, +} + secure_dispatch_module() From 22ff1c74917647b48200f054016f312f78afa1f4 Mon Sep 17 00:00:00 2001 From: aditup Date: Fri, 19 Jun 2015 03:21:50 -0400 Subject: [PATCH 06/60] Removed duplicated get_max_media_volume func --- getsensor.r2py | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 26c8786..be93101 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -321,7 +321,8 @@ def check_screen_on(): def get_max_media_volume(): """ - Returns the current maximum media volume on the device. + Returns the current maximum media volume on the device. Calls + sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []). None. @@ -337,33 +338,6 @@ def get_max_media_volume(): A integer variable indicating the maximum media volume on the device. - Calls sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []). - - """ - - sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []) - - -def get_max_media_volume(): - """ - - Returns the current maximum media volume on the device. - - - None. - - - None. - - - None. - - - Lookup the current maximum media volume on the device. - - - A integer variable indicating the maximum media volume on the device. - Calls sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []). """ From c2f47872a9f427d0c3b616d4bf70b62d118af292 Mon Sep 17 00:00:00 2001 From: aditup Date: Fri, 19 Jun 2015 03:26:50 -0400 Subject: [PATCH 07/60] Changed spacing, indentation --- getsensor.r2py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index be93101..c507576 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -266,6 +266,7 @@ def check_airplane_mode(): # True or False return sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) + def check_ringer_silent_mode(): """ @@ -285,7 +286,7 @@ def check_ringer_silent_mode(): A boolean variable indicating if Silent mode is enabled on the device. - + """ # True or False @@ -341,4 +342,4 @@ def get_max_media_volume(): """ - sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []) \ No newline at end of file + sensorlib.request_data(sensor_socket, 'getMaxMediaVolume', []) From d0015cedcb1528903e1b75745bbc38e8970bf009 Mon Sep 17 00:00:00 2001 From: aditup Date: Sun, 21 Jun 2015 19:32:31 -0400 Subject: [PATCH 08/60] fixed errors - cellular interface --- getsensor.r2py 2 | 607 ++++++++++++++++++++++++++++++++++++++++++++ sensor_layer.r2py 2 | 130 ++++++++++ 2 files changed, 737 insertions(+) create mode 100644 getsensor.r2py 2 create mode 100644 sensor_layer.r2py 2 diff --git a/getsensor.r2py 2 b/getsensor.r2py 2 new file mode 100644 index 0000000..8fa8c58 --- /dev/null +++ b/getsensor.r2py 2 @@ -0,0 +1,607 @@ +""" +getsensor.r2py + +Yanyan Zhuang, UBC, Canada + +Change log: + +v 0.0.1, 20150429 1630 YZ + Using sensor lib code to get all _original_ data from a phone + Note that we need to convert Unicode strings to ASCII because + namespace in Repy does not allow Unicode. + +""" + +# a small lib that makes `str`s from Unicode strings +# this is needed because namespace in Repy does not allow Unicode +unicode_scrubber = dy_import_module("unicode_scrubber.r2py") + +sensorlib = dy_import_module("sensorlib.r2py") +port = sensorlib.get_connectionport() +sensor_socket = sensorlib.getconnection(port) + +class BatteryNotFoundException(RepyException): + """This exception gets raised when no battery is found on the device. + """ + pass + + +class LocationNotFoundException(RepyException): + """This exception gets raised when location sensor returns no results. + """ + pass + + +class SIMNotFoundException(RepyException): + """This exception gets raised when no SIM card is found on the device. + In this case, no cellular information can be found. + """ + pass + +################################################## +############## location interface ############### +################################################## + +def get_location(): + """ + + Get original location data from GPS or network or passive. Calls + sensorlib.request_data(sensor_socket, 'readLocation', []). The location + information is returned as a dict, which is converted to ASCII + using unicode_scrubber. + + + None + + + LocationNotFoundException (descends from RepyException) when no location + information is found. + + + When LocationNotFoundException is raised, the user of this method needs + to try several times. If this still fails, then should try + get_lastknown_location(). + + + GPS or network location lookup. + + + location as a dict, such as {u'network': {u'bearing': 0, u'altitude': 0, + u'time': x, u'longitude': x, u'provider': u'network', u'latitude': x, + u'speed': 0, u'accuracy': x}}. + + """ + + # start the locating process + sensorlib.request_data(sensor_socket, 'startLocating', []) + + # try to read current location + # note: readLocation call can timeout, or not responsive + location_data = sensorlib.request_data(sensor_socket, 'readLocation', []) + + # stop the locating process + sensorlib.request_data(sensor_socket, 'stopLocating', []) + + if not location_data: + raise LocationNotFoundException + assert len(location_data.keys()) == 1 # should return at only one provider + + # take the first key (because only one provider) + provider = location_data.keys()[0] + location = location_data[provider] + + # convert unicode format (u'longitude') to ASCII (longitude) + # because Repy does not allow Unicode + location = unicode_scrubber.scrub(location) + return location + + +def get_lastknown_location(): + """ + + Get original _last-known_ location data from GPS/network/passive. Calls + sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []). The + location information is returned as a dict, which is converted to ASCII + using unicode_scrubber. + + + None + + + LocationNotFoundException (descends from RepyException) when the returned + location information is {'passive': None, 'network': None, 'gps': None}. + + + None. + + + Lookup cached location information on the device. + + + location as a dict with three keys: passive, network, and gps. Each key + value is a dict in the same format as the value returned by get_location(). + For example, {u'passive': {u'bearing': 0, u'altitude': 0, u'time': x, + u'longitude': x, u'provider': u'network', u'latitude': s, u'speed': 0, + u'accuracy': x}, u'network': {u'bearing': 0, u'altitude': 0, u'time': x, + u'longitude': x, u'provider': u'network', u'latitude': x, u'speed': 0, + u'accuracy': x}, u'gps': None} + + """ + + # start the locating process + sensorlib.request_data(sensor_socket, 'startLocating', []) + + # try to read the cached location + location_data = sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []) + + # stop the locating process + sensorlib.request_data(sensor_socket, 'stopLocating', []) + assert len(location_data.keys()) >= 1 # should return at least one provider + + # check if location_data is {'passive': None, 'network': None, 'gps': None} + for i in range(len(location_data.keys())): + provider = location_data.keys()[i] + location = location_data[provider] + if location != None: + break + else: + raise LocationNotFoundException + + # convert unicode format (u'longitude') to ASCII (longitude) + location = unicode_scrubber.scrub(location_data) + return location + + + +################################################## +############## WiFi interface ################### +################################################## + +def is_wifi_enabled(): + """ + + Return if WiFi is enabled on this device (True/False). + + + None + + + None. + + + None. + + + Lookup if WiFi is enabled on the device. + + + A boolean vaiable indicating if WiFi is enabled on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'checkWifiState', []) + + +def get_wifi_connection_info(): + """ + + Return information about the WiFi network currently connected to. Calls + sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []). + + + None + + + None. + + + None. + + + Lookup WiFi connection information on the device. + + + wifi_conn as a dict, and is returned as a dict of this format: + { + "ssid": network SSID (string), + "bssid": network BSSID, i.e. MAC address (string), + "rssi": received signal strength in dBm (negative int), + "supplicant_state": current WPA association state (string), + "link_speed": link speed in MBps (int), + "mac_address": this device's WiFi interface MAC (string), + XXX "ip_address": this device's IP address (XXX int, byte quadruples reversed!), + XXX "network_id": XXX (int), + "hidden_ssid": True if the SSID is not broadcast (bool) + } + """ + + wifi_conn = sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []) + + # convert unicode format to ASCII + return unicode_scrubber.scrub(wifi_conn) + + +def do_wifi_scan(): + """ + + Return WiFi connection info on this device. Calls + sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []). + + + None + + + None. + + + None. + + + Scan the WiFi network from the device. + + + WiFi scan results wifi_data as a HUGE dict of this format, + with one dict for each network found: + { + "ssid": network SSID (string), + "bssid": network BSSID, i.e. MAC address (string), + "frequency": frequency in MHz (int), + "level": received signal strength in dBm (negative int), + "capabilities": security features supported by the network (string) + } + + """ + + sensorlib.request_data(sensor_socket, 'wifiStartScan', []) + wifi_data = sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []) + + # we do not need to stop scan (it stops itself after scan is done) + # convert unicode format to ASCII + return unicode_scrubber.scrub(wifi_data) + + +################################################## +############## battery interface ################ +################################################## + +def get_battery_info(): + """ + + Get battery data from a devices. Calls sensorlib.request_data(sensor_socket, + 'readBatteryData', []). The battery information is returned as a dict. + + + None + + + BatteryNotFoundException (descends from RepyException) when no battery + is found on the device. + + + When BatteryNotFoundException is raised, the user of this method cannot + get any battery information. + + + Battery information lookup. + + + Battery info as a dict, such as {u'status': 3, u'temperature': 257, u'level': + 99, u'battery_present': True, u'plugged': 2, u'health': 2, u'voltage': + 4186, u'technology': u'Li-ion'}. + Return values for status: 1 - unknown; 2 - charging; 3 - discharging; + 4 - not charging; 5 - full. + Return values for temperature: in tenths of a degree Centigrade. E.g., + 257 is 25.7 celcius. + Return values for level: in percent. + Return values for plugged: -1 - unknown; 0 - unplugged; 1 - power + source is an AC charger; 2 - power source is a USB port. + Return values for health: 1 - unknown; 2 - good; 3 - overheat; 4 - dead; + 5 - over voltage; 6 - unspecified failure. + Return values for voltage: in millivolts. + + """ + + # start battery information lookup + sensorlib.request_data(sensor_socket, 'batteryStartMonitoring', []) + + # if no battery is present, then no battery information can be obtained + if sensorlib.request_data(sensor_socket, 'batteryCheckPresent', []) == False: + sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) + raise BatteryNotFoundException + + battery_info = sensorlib.request_data(sensor_socket, 'readBatteryData', []) + sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) + + return battery_info + + + +################################################## +############## bluetooth interface ############## +################################################## + +def get_bluetooth_info(): + """ + + Get bluetooth data from a devices. Calls sensorlib.request_data(sensor_socket, + 'checkBluetoothState'/'bluetoothGetScanMode'/'bluetoothGetLocalName', []). + The bluetooth information is returned as a dict. + + + None + + + None. + + + When bluetooth is not enabled, the user of this method cannot get any + bluetooth information. + + + Bluetooth information lookup. + + + Bluetooth info as a dict, such as {'state': True, 'scan_mode': 3, + 'local_name': 'GT1000'}. + Return values for scan_mode: -1 - when Bluetooth is disabled; + 0 - if non discoverable and non connectable; 1 - connectable + non discoverable; 3 - connectable and discoverable. + + """ + + state = sensorlib.request_data(sensor_socket, 'checkBluetoothState', []) + scan_mode = sensorlib.request_data(sensor_socket, 'bluetoothGetScanMode', []) + local_name = sensorlib.request_data(sensor_socket, 'bluetoothGetLocalName', []) + + bluetooth_info = {'state': state, 'scan_mode': scan_mode, 'local_name': local_name} + return bluetooth_info + + + +################################################## +############## cellular interface ############### +################################################## + +def is_roaming(): + """ + + Return if a phone is roaming (True/False). Calls sensorlib.request_data( + sensor_socket, 'checkNetworkRoaming', []). + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no cellular information can be obtained. + + + Lookup if phone is roaming. + + + A boolean vaiable indicating if the phone is roaming. + """ + + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + return sensorlib.request_data(sensor_socket, 'checkNetworkRoaming', []) + + + +def get_cellular_provider_info(): + """ + + Get cellular provider info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getNetworkOperator'/'getNetworkOperatorName', []). The + cellular network information, current cellular operator code (MNC+MCC), + and operator name, is returned as a dict. + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no cellular provider info can be obtained. + + + Cellular network provider information lookup. + + + Cellular provider info as a dict, such as {‘network_operator’: 310260, + ‘network_operator_name’: ‘T-Mobile’}. + + """ + + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + network_operator = sensorlib.request_data(sensor_socket, + 'getNetworkOperator', []) + network_operator_name = sensorlib.request_data(sensor_socket, + 'getNetworkOperatorName', []) + + cellular_network_info = {'network_operator': network_operator, + 'network_operator_name': network_operator_name} + return cellular_network_info + + + +def get_cell_info(): + """ + + Get cellular network info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getCellLocation'/'getNeighboringCellInfo'/'getNetworkType', + []). The cellular network information, current cellular cell ID, + neighboring cells, is returned as a dict. + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no cellular information can be obtained. + + + Cellular network information lookup. + + + Cellular info as a dict, such as {‘cellID’: {‘lac’: 32115, ‘cid’: 26742}, + ‘neighboring_cell’: [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, + {‘rssi’: 5, ‘cid’: 40153}]}. + + """ + + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + # get details about cell ID, e.g., {‘lac’: 32115, ‘cid’: 26742} + # cid = Cell ID, lac = location area code + cellID = sensorlib.request_data(sensor_socket, + 'getCellLocation', []) + + # get information about neighboring cells in a list, e.g., + # [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, + # {‘rssi’: 5, ‘cid’: 40153}] + neighboring_cell = sensorlib.request_data(sensor_socket, + 'getNeighboringCellInfo', []) + + cellular_info = {'cellID': cellID, 'neighboring_cell': neighboring_cell} + return cellular_info + + +def get_SIM_info(): + """ + + Get SIM card info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getSimState'/'getSimOperator'/'getSimOperatorName' + /'getSimCountryIso', []). The SIM card information, current SIM + card state, SIM card operator, SIM card operator name, SIM card + country code, is returned as a dict. + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no information can be obtained. + + + SIM card information lookup. + + + SIM card info as a dict, such as {‘SIM_operator’: 310260, + ‘SIM_operator_name’: ‘’, ‘SIM_country_code’: ‘us’, ‘SIM_state’: + ‘ready’}. + + """ + + SIM_state = sensorlib.request_data(sensor_socket, 'getSimState', []) + + if SIM_state == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + SIM_operator = sensorlib.request_data(sensor_socket, + 'getSimOperator', []) + SIM_operator_name = sensorlib.request_data(sensor_socket, + 'getSimOperatorName', []) + SIM_country_code = sensorlib.request_data(sensor_socket, + 'getSimCountryIso', []) + + SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, + 'SIM_operator_name': SIM_operator_name, + 'SIM_country_code': SIM_country_code} + return SIM_info + + +def get_phone_info(): + """ + + Get phone info from a devices. Calls sensorlib.request_data( + sensor_socket, 'readPhoneState'/'getPhoneType'/'getNetworkType', + []). The phone information, current phone state, phone type, + network type, is returned as a dict. + + + None + + + None. + + + None. + + + Phone information lookup. + + + Phone info as a dict, such as {‘phone_state’: {‘incomingNumber’: + ‘’, ‘state’: ‘idle’}, ‘phone_type’: ‘gsm’, ‘network_type’: 'edge'}. + When no SIM card is available, the phone info dict would be, e.g., + {‘phone_state’: {}, ‘phone_type’: ‘gsm’, ‘network_type’: 'unknown'}. + + """ + sensorlib.request_data(sensor_socket, 'startTrackingPhoneState', []) + + phone_state = sensorlib.request_data(sensor_socket, + 'readPhoneState', []) + phone_type = sensorlib.request_data(sensor_socket, + 'getPhoneType', []) + network_type = sensorlib.request_data(sensor_socket, + 'getNetworkType', []) + + sensorlib.request_data(sensor_socket, 'stopTrackingPhoneState', []) + + phone_info = {'phone_state': phone_state, 'phone_type': phone_type, + 'network_type': network_type} + return phone_info + + +def get_cellular_signal_strengths(): + """ + + Get the current signal strengths, in dictionary of gsm_signal_strength. + Calls sensorlib.request_data(sensor_socket, 'readSignalStrengths', []). + + + None + + + None. + + + None. + + + Current signal strengths lookup. + + + Signal strengths info as a dict, such as {"gsm_signal_strength": + 8, "evdo_ecio": -1, "gsm_bit_error_rate": -1, "cdma_ecio": -1, + "cdma_dbm": -1, "evdo_dbm": -1}. + """ + + sensorlib.request_data(sensor_socket, 'startTrackingSignalStrengths', []) + cellular_signal_strengths = sensorlib.request_data(sensor_socket, + 'readSignalStrengths', []) + sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) + + return cellular_signal_strengths + diff --git a/sensor_layer.r2py 2 b/sensor_layer.r2py 2 new file mode 100644 index 0000000..9879f9a --- /dev/null +++ b/sensor_layer.r2py 2 @@ -0,0 +1,130 @@ +"""A 'security layer'-like thing that adds getsenor.r2py's calls to the +child namespace so that they appear to belong to the API. + +Usage: +start dylink.r2py encasementlib.r2py sensor_layer.r2py [any blur layers] \ + user-program.r2py +""" + +getsensor = dy_import_module("getsensor.r2py") + +CHILD_CONTEXT_DEF["get_location"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_location, +} + + +CHILD_CONTEXT_DEF["get_lastknown_location"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_lastknown_location, +} + + +CHILD_CONTEXT_DEF["is_wifi_enabled"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.is_wifi_enabled, +} + + +CHILD_CONTEXT_DEF["get_wifi_connection_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_wifi_connection_info, +} + + +CHILD_CONTEXT_DEF["do_wifi_scan"] = { + "type": "func", + "args": None, + "return": list, + "exceptions": "any", + "target": getsensor.do_wifi_scan, +} + + +CHILD_CONTEXT_DEF["get_battery_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_battery_info, +} + + +CHILD_CONTEXT_DEF["get_bluetooth_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_bluetooth_info, +} + + +CHILD_CONTEXT_DEF["is_roaming"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.is_roaming, +} + + + +CHILD_CONTEXT_DEF["get_cellular_provider_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_cellular_provider_info, +} + + +CHILD_CONTEXT_DEF["get_cell_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_cell_info, +} + + +CHILD_CONTEXT_DEF["get_SIM_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_SIM_info, +} + + +CHILD_CONTEXT_DEF["get_phone_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_phone_info, +} + + +CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_cellular_signal_strengths, +} + + +secure_dispatch_module() + From e14bda3662cb4cfe634a300003743998b0001a56 Mon Sep 17 00:00:00 2001 From: aditup Date: Wed, 24 Jun 2015 16:22:18 -0400 Subject: [PATCH 09/60] changes based on test results for sensor interface --- getsensor.r2py | 12 ++++++------ sensor_layer.r2py | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 3e874c3..fb04ac1 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -821,7 +821,7 @@ def stop_sensing(): def get_sensors(): - """ + """ Get the most recently recorded sensor data (accelerometer, magnetic and orientation), in dictionary of sensors. Calls @@ -847,9 +847,9 @@ def get_sensors(): "accuracy":3}. """ - sensors = sensorlib.request_data(sensor_socket, 'readSensors', [1, 1]) + sensors = sensorlib.request_data(sensor_socket, 'readSensors', []) return unicode_scrubber.scrub(sensors) - + def get_sensors_accuracy(): """ @@ -962,7 +962,7 @@ def get_magnetic_field(): def get_orientation(): - """ + """ Get the most recently received orientation value. Calls sensorlib.request_data(sensor_socket, 'sensorsReadOrientation', @@ -985,6 +985,6 @@ def get_orientation(): [-0.17154279351234436, 0.080450139939785, -0.03844258934259415]. """ - return sensorlib.request_data(sensor_socket, - 'sensorsReadOrientation', []) + return sensorlib.request_data(sensor_socket, + 'sensorsReadOrientation', []) diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 7b5cf05..6c499b8 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -164,19 +164,19 @@ CHILD_CONTEXT_DEF["get_ringer_volume"] = { CHILD_CONTEXT_DEF["start_sensing"] = { "type": "func", - "args": int, int, - "return": dict, + "args": (int, int), + "return": None, "exceptions": "any", - "target": getsensor. start_sensing, + "target": getsensor.start_sensing, } CHILD_CONTEXT_DEF["stop_sensing"] = { "type": "func", - "args": (int, int) - "return": dict, + "args": None, + "return": None, "exceptions": "any", - "target": getsensor. stop_sensing, + "target": getsensor.stop_sensing, } @@ -192,7 +192,7 @@ CHILD_CONTEXT_DEF["get_sensors"] = { CHILD_CONTEXT_DEF["get_sensors_accuracy"] = { "type": "func", "args": None, - "return": dict, + "return": int, "exceptions": "any", "target": getsensor.get_sensors_accuracy, } @@ -211,7 +211,7 @@ CHILD_CONTEXT_DEF["get_light"] = { CHILD_CONTEXT_DEF["get_acceleration"] = { "type": "func", "args": None, - "return": dict, + "return": list, "exceptions": "any", "target": getsensor.get_acceleration, } @@ -221,7 +221,7 @@ CHILD_CONTEXT_DEF["get_acceleration"] = { CHILD_CONTEXT_DEF["get_magnetic_field"] = { "type": "func", "args": None, - "return": dict, + "return": list, "exceptions": "any", "target": getsensor.get_magnetic_field, } @@ -230,7 +230,7 @@ CHILD_CONTEXT_DEF["get_magnetic_field"] = { CHILD_CONTEXT_DEF["get_orientation"] = { "type": "func", "args": None, - "return": dict, + "return": list, "exceptions": "any", "target": getsensor.get_orientation, } From 3d3c777dddfe6f32924e8b221fb950b06276c86f Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 30 Jun 2015 11:46:16 -0400 Subject: [PATCH 10/60] added comments and docstrings --- blur_location2city.r2py | 163 ++++++++++-------- blur_location2state.r2py | 363 +++++++++++++++++++++++---------------- 2 files changed, 303 insertions(+), 223 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index b72a0ce..5014e49 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -1,13 +1,17 @@ """ A security layer for the functions get_location() and get_lastknown_location() -defined in getsensor.r2py. This program blurs the coordinates, received -from the location sensors of an Android device, to the geographic center of -approximately the nearest city. - -The blurring is done using a DB lookup method. The DB contains a list of -cities, and their geodata (lat, lon, country code, state code), divided -by their coordinates. The DB is is available at: -http://sensibilityclearinghouse.poly.edu/data/quad/ +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of approximately the nearest city. + +The blurring is done using a database lookup method. The database, +located at http://sensibilityclearinghouse.poly.edu/data/quad/, contains +a list of cities and their geodata (latitude, longitude, country code, +state code), divided by their latitude/longitude coordinates into cells. +Each cell is a separate file in the database, whose name is derived as +"ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan has +its center at coordinates 40.78343, -73.96625, so it will be mapped to +the file with name "41_-73.txt". Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -21,10 +25,47 @@ math = dy_import_module("math.r2py") +def load_city_geodata(filename): + """ + Loads all the cities and their geodata from the given file into a + dictionary. The dictionary that is returned has the format: + { + city1: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + city2: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + ... + } + + """ + get_file_from_server(filename) + city_dict = {} + city_geodata_fileobj = openfile(filename, False) + city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + + for line in city_geodata_file: + # Ignore the empty line at the end of the file + if line == "": + continue + city_geodata_record = line.split("\t") + city_name = city_geodata_record[0] + lat = float(city_geodata_record[1]) + lon = float(city_geodata_record[2]) + city_dict[city_name] = { + "latitude": lat, + "longitude": lon, + "country_code": city_geodata_record[3], + "state_code": city_geodata_record[4] + } + city_geodata_fileobj.close() + return city_dict + + + def get_file_from_server(filename): """ - Downloads the required file from the DB server, if it has not already - been downloaded. + Downloads the required file from the database server, if it has not + already been downloaded. """ if filename not in listfiles(): @@ -35,46 +76,50 @@ def get_file_from_server(filename): def find_closest_city(lat, lon): """ - Searches the DB and returns a dict containing the geodata of the city - that is approximately closest to a given lat/lon pair in the format: + Finds the city closest to the given latitude/longitude pair from the + dictionary of cities returned by the load_city_geodata() function, + and returns that city's geodata in the format: { "city_name": city name (string), "state_code": 2-digit code representing the state to which the city belongs (string), "country_code": 2-letter ISO-3166 code representing the country to which the city belongs (string), - "coordinates": tuple containing the lat/lon pair representing the - geographic center of the city (float, float) + "latitude": latitude of the geographic center of the city (float) + "longitude": longitude of the geographic center of the city (float) } - - Note: We're looking for the closest lat/lon pair within the same - quadrant as the given lat/lon pair. There might be closer ones in - other quadrants. Thus, the "closest city" is only an approximation. + + Note: We're looking for the closest city within the same cell as the + given latitude/longitude pair. There might be a closer city in the + surrounding cells. """ - # Determine which file to download from the DB. + # Determine which file to download from the database. filename = get_database_filename(lat, lon) # Load all the cities and their geodata from the file. city_dict = load_city_geodata(filename) # Set the minimum squared difference between two pairs of coordinates - # to an arbitrarily large number. - # XXX Should "large" be defined? + # to a number larger than any possible minimum distance to a close + # city in the current latitude/longitude quadrilateral. min_diff = 9999 for city_name, city_geodata in city_dict.items(): - city_lat, city_lon = city_geodata["coordinates"] - diff = find_squared_difference((lat, lon), (city_lat, city_lon)) + diff = find_squared_difference((lat, lon), (city_geodata["latitude"], + city_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_city_coordinates = city_geodata["coordinates"] + closest_city_latitude = city_geodata["latitude"] + closest_city_longitude = city_geodata["longitude"] closest_city_name = city_name closest_city_state_code = city_geodata["state_code"] closest_city_country_code = city_geodata["country_code"] - closest_city_geodata = {"city_name": closest_city_name, - "coordinates": closest_city_coordinates, + closest_city_geodata = { + "city_name": closest_city_name, + "latitude": closest_city_latitude, + "longitude": closest_city_longitude, "state_code": closest_city_state_code, "country_code": closest_city_country_code } @@ -85,8 +130,8 @@ def find_closest_city(lat, lon): def get_database_filename(lat, lon): """ - Returns the filename in the DB with coordinates in the same quadrant - as the given lat/lon pair. + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. """ # Get ceiling as x/y index. @@ -97,45 +142,11 @@ def get_database_filename(lat, lon): -def load_city_geodata(filename): - """ - Returns a dict containing all the cities in the given file, - along with their corresponding geodata in the format: - { - city1: {"coordinates": (lat, lon), "country_code": country_code, - "state_code": state_code}, - city2: {"coordinates": (lat, lon), "country_code": country_code, - "state_code": state_code}, - ... - } - - """ - get_file_from_server(filename) - city_dict = {} - city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") - - for line in city_geodata_file: - # Ignore the empty line at the end of the file - if line == "": - continue - city_geodata_record = line.split("\t") - city_name = city_geodata_record[0] - lat = float(city_geodata_record[1]) - lon = float(city_geodata_record[2]) - city_dict[city_name] = {"coordinates": (lat, lon), - "country_code": city_geodata_record[3], - "state_code": city_geodata_record[4] - } - city_geodata_fileobj.close() - return city_dict - - - def find_squared_difference(p1, p2): """ - Returns the squared difference between two pairs of coordinates (p1 - and p2). + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). """ lat1, lon1 = p1 @@ -148,7 +159,7 @@ def find_squared_difference(p1, p2): def get_city_location(): """ - Security layer for the get_location() function. It replaces the exact + Blurring layer for the get_location() function. It replaces the exact coordinates of the Android device with the coordinates for the geographic center of the nearest city. @@ -158,8 +169,8 @@ def get_city_location(): closest_city = find_closest_city(location_data["latitude"], location_data["longitude"]) - location_data["latitude"], location_data["longitude"] = \ - closest_city["coordinates"] + location_data["latitude"] = closest_city["latitude"] + location_data["longitude"] = closest_city["longitude"] return location_data @@ -167,7 +178,7 @@ def get_city_location(): def get_city_lastknown_location(): """ - Security layer for the get_lastknown_location() function. It replaces + Blurring layer for the get_lastknown_location() function. It replaces the last-known coordinates of the Android device with the coordinates for the geographic center of the nearest city. @@ -180,19 +191,18 @@ def get_city_lastknown_location(): # location. if provider_location_data is None: continue - + closest_city = find_closest_city(provider_location_data["latitude"], provider_location_data["longitude"]) - - location_data[location_provider]["latitude"], \ - location_data[location_provider]["longitude"] = closest_city["coordinates"] + + location_data[location_provider]["latitude"] = closest_city["latitude"] + location_data[location_provider]["longitude"] = closest_city["longitude"] return location_data -# Makes a security layer out of what otherwise would be just a plain -# library you could `dy_import` +# Mapping our blurring function get_city_location to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -202,6 +212,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function get_city_lastknown_location to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -211,4 +223,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } +# Dispatch secure_dispatch_module() \ No newline at end of file diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 652db41..3108372 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -1,191 +1,254 @@ -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") -librepyfile = dy_import_module("librepyfile.r2py") +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of approximately the nearest state. + +The blurring is done using a database lookup method. First, we find the +city closest to the original latitude/longitude coordinates from the +cities' database and extract the geodata associated with it. This +database, located at http://sensibilityclearinghouse.poly.edu/data/quad/, +contains a list of cities and their geodata (latitude, longitude, +country code, state code), divided by their coordinates into cells. +Each cell is a separate file in the database, whose name is derived +as "ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan +has its center at coordinates 40.78343, -73.96625, so it will be mapped +to the file with name "41_-73.txt". + +Next, we use the state code and country code from the city's geodata to +look up the coordinates of the geographic center of the state to which +the city belongs. This look up uses the states' database, states.txt, +located at http://sensibilityclearinghouse.poly.edu/data/. states.txt +is a database of the top level administrative divisions within each +country (for example, states/provinces). It has the following fields: +code, state name, latitude, longitude. The code field has the format +"country_code.state_code", where country_code is the ISO-3166 2-letter +country code of the country to which the admin division belongs and +state_code is the 2-digit state code representing the admin division. + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2state.r2py user-program.r2py +""" -statefilename = "states.txt" # Database of states -countryfilename = "countries.txt" # Database of countries -# Downloads the required file from the server -def get_file_from_server(filename): +httpretrieve = dy_import_module("httpretrieve.r2py") +math = dy_import_module("math.r2py") + +statefilename = "states.txt" - if filename not in listfiles(): # In case it already exists - if filename not in [statefilename, countryfilename]: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - httpretrieve.httpretrieve_save_file(url, filename) -# Returns a dictionary containing information about the point closest to -# a given lat/lng pair, from the database. -# {"city": closest_city, "statecode": closest_state_code, "countrycode": -# closest_country_code, "coordinates": closest_point} -def find_closest_point(lat, lng): +def load_city_geodata(filename): + """ + Loads all the cities and their geodata from the given file into a + dictionary. The dictionary that is returned has the format: + { + city1: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + city2: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + ... + } - # Find the database file with coordinates closest to the given lat/lng pair - filename = get_filename(lat, lng) - # Get the list of coordinates from that file - listofpoints = load_lat_lng_from_file(filename) + """ + get_file_from_server(filename) + city_dict = {} + city_geodata_fileobj = openfile(filename, False) + city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + + for line in city_geodata_file: + # Ignore the empty line at the end of the file + if line == "": + continue + city_geodata_record = line.split("\t") + city_name = city_geodata_record[0] + lat = float(city_geodata_record[1]) + lon = float(city_geodata_record[2]) + city_dict[city_name] = { + "latitude": lat, + "longitude": lon, + "country_code": city_geodata_record[3], + "state_code": city_geodata_record[4] + } + city_geodata_fileobj.close() + return city_dict - min_dist = 9999 - point1 = (lat, lng) - for city in listofpoints.keys(): - data = listofpoints[city] - point2 = (data[0], data[1]) - dist = find_distance(point1, point2) - if dist < min_dist: - min_dist = dist - closest_point = point2 - closest_city = city - closest_state_code = data[3] - closest_country_code = data[2] - closest = {"city": closest_city, "statecode": closest_state_code, "countrycode": closest_country_code, "coordinates": closest_point} +def get_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. - return closest + """ + if filename not in listfiles(): + if filename == statefilename: + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + else: + url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename + httpretrieve.httpretrieve_save_file(url, filename) -# Returns the filename in the database with coordinates closest to the given -# lat/lng pair -def get_filename(lat, lng): - # get ceiling as x/y index +def find_closest_city(lat, lon): + """ + Finds the city closest to the given latitude/longitude pair from the + dictionary of cities returned by the load_city_geodata() function, + and returns that city's geodata in the format: + { + "city_name": city name (string), + "state_code": 2-digit code representing the state to which the city + belongs (string), + "country_code": 2-letter ISO-3166 code representing the country to + which the city belongs (string), + "latitude": latitude of the geographic center of the city (float) + "longitude": longitude of the geographic center of the city (float) + } + + Note: We're looking for the closest city within the same cell as the + given latitude/longitude pair. There might be a closer city in the + surrounding cells. + + """ + # Determine which file to download from the database. + filename = get_database_filename(lat, lon) + + # Load all the cities and their geodata from the file. + city_dict = load_city_geodata(filename) + + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # city in the current latitude/longitude quadrilateral. + min_diff = 9999 + + for city_name, city_geodata in city_dict.items(): + diff = find_squared_difference((lat, lon), (city_geodata["latitude"], + city_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_city_latitude = city_geodata["latitude"] + closest_city_longitude = city_geodata["longitude"] + closest_city_name = city_name + closest_city_state_code = city_geodata["state_code"] + closest_city_country_code = city_geodata["country_code"] + + closest_city_geodata = { + "city_name": closest_city_name, + "latitude": closest_city_latitude, + "longitude": closest_city_longitude, + "state_code": closest_city_state_code, + "country_code": closest_city_country_code + } + + return closest_city_geodata + + + +def get_database_filename(lat, lon): + """ + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. + + """ + # Get ceiling as x/y index. x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lng)) + y = int(math.math_ceil(lon)) filename = str(x) + '_' + str(y) + '.txt' return filename -# Returns a dictionary containing all the cities in the given file, along with -# their corresponding data -# {city1: [lat, lng, country_code, state_code], city2: [lat, lng, country_code, -# state_code], ...} -def load_lat_lng_from_file(filename): - get_file_from_server(filename) - listofpoints = {} - fileobj = librepyfile.open(filename, "r") +def find_squared_difference(p1, p2): + """ + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). + + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff + + - while True: - try: - line = fileobj.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - city_name = line[0] - lat = line[1] - lng = line[2] - country_code = line[3] - state_code = line[4] - listofpoints[city_name] = [lat, lng, country_code, state_code] - fileobj.close() - return listofpoints - - -# Returns the distance between two lat/lng points -def find_distance(p1, p2): - - (lat1, lng1) = p1 - (lat2, lng2) = p2 - lat2 = float(lat2) - lng2 = float(lng2) - lat_diff = (lat1-lat2) * (lat1-lat2) - lng_diff = (lng1-lng2) * (lng1-lng2) - # return squared distance - return lat_diff + lng_diff - - -# To replace get_location() def get_state_location(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the nearest state. - try: - location_data = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception + """ + location_data = get_location() - latitude = location_data["latitude"] - longitude = location_data["longitude"] + closest_city = find_closest_city(location_data["latitude"], + location_data["longitude"]) - closest = find_closest_point(latitude, longitude) - country_code = closest["countrycode"] - state_code = closest["statecode"] - code = country_code + "." + str(state_code) + code = closest_city["country_code"] + "." + str(closest_city["state_code"]) - # Download the States database + # Download the states.txt database get_file_from_server(statefilename) - statefile = librepyfile.open(statefilename, "r") + state_fileobj = openfile(statefilename, False) + state_file = state_fileobj.readat(None, 0).split("\n") # Look for the state corresponding to the code - while True: - try: - line = statefile.next().strip() - except StopIteration: + for line in state_file: + state_record = line.split("\t") + if code == state_record[0]: + location_data["latitude"] = state_record[2] + location_data["longitude"] = state_record[3] break - else: - line = line.split("\t") - if code == line[0]: - slat = line[2] - slng = line[3] - break - statefile.close() - - location_data["latitude"] = slat - location_data["longitude"] = slng + state_fileobj.close() return location_data -# To replace get_lastknown_location() -def get_state_lastknown_location(): - try: - location_data = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - - # Get the location from the the provider - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - latitude = location["latitude"] - longitude = location["longitude"] - - closest = find_closest_point(latitude, longitude) - - country_code = closest["countrycode"] - state_code = closest["statecode"] - code = country_code + "." + str(state_code) - - # Download the States database - get_file_from_server(statefilename) - - statefile = librepyfile.open(statefilename, "r") - - # Look for the state corresponding to the code - while True: - try: - line = statefile.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - if code == line[0]: - slat = line[2] - slng = line[3] - break - statefile.close() - - location_data[provider]["latitude"] = slat - location_data[provider]["longitude"] = slng +def get_state_lastknown_location(): + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the nearest state. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + closest_city = find_closest_city(provider_location_data["latitude"], + provider_location_data["longitude"]) + + code = closest_city["country_code"] + "." + str(closest_city["state_code"]) + + # Download the states.txt database + get_file_from_server(statefilename) + + state_fileobj = openfile(statefilename, False) + state_file = state_fileobj.readat(None, 0).split("\n") + + # Look for the state corresponding to the code + for line in state_file: + state_record = line.split("\t") + if code == state_record[0]: + provider_location_data["latitude"] = state_record[2] + provider_location_data["longitude"] = state_record[3] + break + state_fileobj.close() return location_data + +# Mapping our blurring function get_state_location to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -195,6 +258,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function get_state_lastknown_location to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -203,4 +268,6 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { "target": get_state_lastknown_location, } + +# Dispatch secure_dispatch_module() \ No newline at end of file From 90cfeb1dc83e76462470b74c6767fb294f3e6e8f Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 04:56:02 -0400 Subject: [PATCH 11/60] reduced file downloads --- blur_location2state.r2py | 131 +++++++++++++-------------------------- sensor_layer.r2py | 2 +- 2 files changed, 44 insertions(+), 89 deletions(-) diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 3108372..8997349 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -36,44 +36,37 @@ Usage: httpretrieve = dy_import_module("httpretrieve.r2py") math = dy_import_module("math.r2py") -statefilename = "states.txt" - -def load_city_geodata(filename): +def load_states_geodata(filename): """ - Loads all the cities and their geodata from the given file into a + Loads all the states and their geodata from the given file into a dictionary. The dictionary that is returned has the format: { - city1: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, - city2: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, + state1: {"latitude": latitude, "longitude": longitude}, + state2: {"latitude": latitude, "longitude": longitude}, ... } """ get_file_from_server(filename) - city_dict = {} - city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + states_dict = {} + states_geodata_fileobj = openfile(filename.lower(), False) + states_geodata_file = states_geodata_fileobj.readat(None, 0).split("\n") + states_geodata_fileobj.close() - for line in city_geodata_file: - # Ignore the empty line at the end of the file + for line in states_geodata_file: + # Ignore the empty line at the end of the file. if line == "": continue - city_geodata_record = line.split("\t") - city_name = city_geodata_record[0] - lat = float(city_geodata_record[1]) - lon = float(city_geodata_record[2]) - city_dict[city_name] = { - "latitude": lat, - "longitude": lon, - "country_code": city_geodata_record[3], - "state_code": city_geodata_record[4] + state_geodata_record = line.split("\t") + state_name = state_geodata_record[1] + states_dict[state_name] = { + "latitude": float(state_geodata_record[2]), + "longitude": float(state_geodata_record[3]), } - city_geodata_fileobj.close() - return city_dict + + return states_dict @@ -84,15 +77,12 @@ def get_file_from_server(filename): """ if filename not in listfiles(): - if filename == statefilename: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - httpretrieve.httpretrieve_save_file(url, filename) + url = "http://sensibilityclearinghouse.poly.edu/data/states/" + filename + httpretrieve.httpretrieve_save_file(url, filename.lower()) -def find_closest_city(lat, lon): +def find_closest_state(lat, lon): """ Finds the city closest to the given latitude/longitude pair from the dictionary of cities returned by the load_city_geodata() function, @@ -115,34 +105,28 @@ def find_closest_city(lat, lon): # Determine which file to download from the database. filename = get_database_filename(lat, lon) - # Load all the cities and their geodata from the file. - city_dict = load_city_geodata(filename) + # Load all the states and their geodata from the file. + states_dict = load_states_geodata(filename) # Set the minimum squared difference between two pairs of coordinates # to a number larger than any possible minimum distance to a close - # city in the current latitude/longitude quadrilateral. + # state in the current country. min_diff = 9999 - for city_name, city_geodata in city_dict.items(): - diff = find_squared_difference((lat, lon), (city_geodata["latitude"], - city_geodata["longitude"])) + for state_name, state_geodata in states_dict.items(): + diff = find_squared_difference((lat, lon), (state_geodata["latitude"], + state_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_city_latitude = city_geodata["latitude"] - closest_city_longitude = city_geodata["longitude"] - closest_city_name = city_name - closest_city_state_code = city_geodata["state_code"] - closest_city_country_code = city_geodata["country_code"] - - closest_city_geodata = { - "city_name": closest_city_name, - "latitude": closest_city_latitude, - "longitude": closest_city_longitude, - "state_code": closest_city_state_code, - "country_code": closest_city_country_code + closest_state_name = state_name + + closest_state_geodata = { + "state_name": closest_state_name, + "latitude": states_dict[closest_state_name]["latitude"], + "longitude": states_dict[closest_state_name]["longitude"], } - return closest_city_geodata + return closest_state_geodata @@ -152,10 +136,9 @@ def get_database_filename(lat, lon): latitude/longitude pair belongs. """ - # Get ceiling as x/y index. - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + '.txt' + # Get the first address in the list of addresses + address = get_geolocation(lat, lon, 1)[0] + filename = address["country_code"] + ".txt" return filename @@ -184,25 +167,11 @@ def get_state_location(): """ location_data = get_location() - closest_city = find_closest_city(location_data["latitude"], + closest_state = find_closest_state(location_data["latitude"], location_data["longitude"]) - code = closest_city["country_code"] + "." + str(closest_city["state_code"]) - - # Download the states.txt database - get_file_from_server(statefilename) - - state_fileobj = openfile(statefilename, False) - state_file = state_fileobj.readat(None, 0).split("\n") - - # Look for the state corresponding to the code - for line in state_file: - state_record = line.split("\t") - if code == state_record[0]: - location_data["latitude"] = state_record[2] - location_data["longitude"] = state_record[3] - break - state_fileobj.close() + location_data["latitude"] = closest_state["latitude"] + location_data["longitude"] = closest_state["longitude"] return location_data @@ -224,25 +193,11 @@ def get_state_lastknown_location(): if provider_location_data is None: continue - closest_city = find_closest_city(provider_location_data["latitude"], + closest_state = find_closest_state(provider_location_data["latitude"], provider_location_data["longitude"]) - - code = closest_city["country_code"] + "." + str(closest_city["state_code"]) - - # Download the states.txt database - get_file_from_server(statefilename) - - state_fileobj = openfile(statefilename, False) - state_file = state_fileobj.readat(None, 0).split("\n") - - # Look for the state corresponding to the code - for line in state_file: - state_record = line.split("\t") - if code == state_record[0]: - provider_location_data["latitude"] = state_record[2] - provider_location_data["longitude"] = state_record[3] - break - state_fileobj.close() + + location_data[location_provider]["latitude"] = closest_state["latitude"] + location_data[location_provider]["longitude"] = closest_state["longitude"] return location_data diff --git a/sensor_layer.r2py b/sensor_layer.r2py index a096edc..c9218c1 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -28,7 +28,7 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { CHILD_CONTEXT_DEF["get_geolocation"] = { "type": "func", - "args": (double, double, int), + "args": (float, float, int), "return": list, "exceptions": "any", "target": getsensor.get_geolocation, From 7a4601193540473e4352f4fa9b363c389bdce102 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 05:01:53 -0400 Subject: [PATCH 12/60] changes based on comments --- blur_location2city.r2py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index 5014e49..d4b9fa1 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -42,22 +42,21 @@ def load_city_geodata(filename): city_dict = {} city_geodata_fileobj = openfile(filename, False) city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + city_geodata_fileobj.close() for line in city_geodata_file: - # Ignore the empty line at the end of the file + # Ignore the empty line at the end of the file. if line == "": continue city_geodata_record = line.split("\t") city_name = city_geodata_record[0] - lat = float(city_geodata_record[1]) - lon = float(city_geodata_record[2]) city_dict[city_name] = { - "latitude": lat, - "longitude": lon, + "latitude": float(city_geodata_record[1]), + "longitude": float(city_geodata_record[2]), "country_code": city_geodata_record[3], "state_code": city_geodata_record[4] } - city_geodata_fileobj.close() + return city_dict @@ -110,18 +109,14 @@ def find_closest_city(lat, lon): city_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_city_latitude = city_geodata["latitude"] - closest_city_longitude = city_geodata["longitude"] closest_city_name = city_name - closest_city_state_code = city_geodata["state_code"] - closest_city_country_code = city_geodata["country_code"] closest_city_geodata = { "city_name": closest_city_name, - "latitude": closest_city_latitude, - "longitude": closest_city_longitude, - "state_code": closest_city_state_code, - "country_code": closest_city_country_code + "latitude": city_dict[closest_city_name]["latitude"], + "longitude": city_dict[closest_city_name]["longitude"], + "state_code": city_dict[closest_city_name]["state_code"], + "country_code": city_dict[closest_city_name]["country_code"] } return closest_city_geodata @@ -137,7 +132,7 @@ def get_database_filename(lat, lon): # Get ceiling as x/y index. x = int(math.math_ceil(lat)) y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + '.txt' + filename = str(x) + '_' + str(y) + ".txt" return filename @@ -185,7 +180,7 @@ def get_city_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider + # Get the location from every provider. for location_provider, provider_location_data in location_data.items(): # Skip blurring this provider's data if it doesn't contain a previous # location. @@ -223,5 +218,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } -# Dispatch +# Dispatch. secure_dispatch_module() \ No newline at end of file From e26f3102cf395be073be9065f1f2e935f6968c50 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 06:23:52 -0400 Subject: [PATCH 13/60] blur to zipped --- blur_location2zipcode.r2py | 213 +++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 blur_location2zipcode.r2py diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py new file mode 100644 index 0000000..a3ca6e1 --- /dev/null +++ b/blur_location2zipcode.r2py @@ -0,0 +1,213 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of approximately the nearest ZIP code. + +The blurring is done using a database lookup method. The database, +located at http://sensibilityclearinghouse.poly.edu/data/zip/, contains +a list of ZIP codes and their geodata (country, area, state, latitude, +longitude), divided by their latitude/longitude coordinates into cells. +Each cell is a separate file in the database, whose name is derived as +"ceiling(latitude)_ceiling(longitude).txt". For example, if a location +has coordinates 40.78343, -73.96625, it will be mapped to the file with +name "41_-73.txt". + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2zipcode.r2py user-program.r2py +""" + + + +httpretrieve = dy_import_module("httpretrieve.r2py") +math = dy_import_module("math.r2py") + + + +def load_zipcodes_geodata(filename): + """ + Loads all the ZIP codes and their latitude/longitude coordinates from + the given file into a dictionary. The dictionary that is returned + has the format: + { + zipcode1: {"latitude": latitude, "longitude": longitude}, + zipcode2: {"latitude": latitude, "longitude": longitude}, + ... + } + + """ + get_file_from_server(filename) + zipcodes_dict = {} + zipcodes_geodata_fileobj = openfile(filename, False) + zipcodes_geodata_file = zipcodes_geodata_fileobj.readat(None, 0).split("\n") + zipcodes_geodata_fileobj.close() + + for line in zipcodes_geodata_file: + # Ignore the empty line at the end of the file. + if line == "": + continue + zipcode_geodata_record = line.split("\t") + zipcode = zipcode_geodata_record[1] + zipcodes_dict[int(zipcode)] = { + "latitude": float(zipcode_geodata_record[4]), + "longitude": float(zipcode_geodata_record[5]), + } + + return zipcodes_dict + + + +def get_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/zip/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def find_closest_zipcode(lat, lon): + """ + Finds the ZIP code closest to the given latitude/longitude pair from the + dictionary of ZIP codes returned by the load_zipcodes_geodata() function, + and returns that ZIP code's coordinates in the format: + { + "zipcode": ZIP code (int), + "latitude": latitude of the center of the ZIP code area (float) + "longitude": longitude of the center of the ZIP code area (float) + } + + Note: We're looking for the closest ZIP code within the same cell as + the given latitude/longitude pair. There might be a closer ZIP code + area in the surrounding cells. + + """ + # Determine which file to download from the database. + filename = get_database_filename(lat, lon) + + # Load all the ZIP codes and their geodata from the file. + zipcodes_dict = load_zipcodes_geodata(filename) + + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # ZIP code area in the current latitude/longitude quadilateral. + min_diff = 9999 + + for zipcode, zipcode_geodata in zipcodes_dict.items(): + diff = find_squared_difference((lat, lon), (zipcode_geodata["latitude"], + zipcode_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_zipcode = zipcode + + closest_zipcode_geodata = { + "zipcode": closest_zipcode, + "latitude": zipcodes_dict[closest_zipcode]["latitude"], + "longitude": zipcodes_dict[closest_zipcode]["longitude"], + } + + return closest_zipcode_geodata + + + +def get_database_filename(lat, lon): + """ + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. + + """ + # Get ceiling as x/y index. + x = int(math.math_ceil(lat)) + y = int(math.math_ceil(lon)) + filename = str(x) + '_' + str(y) + ".txt" + return filename + + + +def find_squared_difference(p1, p2): + """ + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). + + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff + + + +def get_zipcode_location(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the nearest ZIP code area. + + """ + location_data = get_location() + + closest_zipcode = find_closest_zipcode(location_data["latitude"], + location_data["longitude"]) + + location_data["latitude"] = closest_zipcode["latitude"] + location_data["longitude"] = closest_zipcode["longitude"] + + return location_data + + + +def get_zipcode_lastknown_location(): + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the nearest ZIP code area. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], + provider_location_data["longitude"]) + + location_data[location_provider]["latitude"] = closest_zipcode["latitude"] + location_data[location_provider]["longitude"] = closest_zipcode["longitude"] + + return location_data + + + +# Mapping our blurring function get_zipcode_location to get_location. +CHILD_CONTEXT_DEF["get_location"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": get_zipcode_location, +} + + +# Mapping our blurring function get_zipcode_lastknown_location to +# get_lastknown_location. +CHILD_CONTEXT_DEF["get_lastknown_location"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": get_zipcode_lastknown_location, +} + + +# Dispatch +secure_dispatch_module() \ No newline at end of file From 18bf4d8114e94c2a64b2159de29344b22184012f Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 23:39:11 -0400 Subject: [PATCH 14/60] improve blurring accuracy --- blur_location2state.r2py | 98 +++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 8997349..9cca592 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -2,18 +2,16 @@ A security layer for the functions get_location() and get_lastknown_location() defined in getsensor.r2py. This program blurs the latitude/longitude coordinates, received from the location sensors of an Android device, -to the geographic center of approximately the nearest state. - -The blurring is done using a database lookup method. First, we find the -city closest to the original latitude/longitude coordinates from the -cities' database and extract the geodata associated with it. This -database, located at http://sensibilityclearinghouse.poly.edu/data/quad/, -contains a list of cities and their geodata (latitude, longitude, -country code, state code), divided by their coordinates into cells. -Each cell is a separate file in the database, whose name is derived -as "ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan -has its center at coordinates 40.78343, -73.96625, so it will be mapped -to the file with name "41_-73.txt". +to the geographic center of approximately the nearest state (admin division). + +The blurring is done using a database lookup method. First, we use the +get_geolocation() call to get the current address. The country code in +the address returned is then used to look up the list of states for +that country from the database. This database, located at +http://sensibilityclearinghouse.poly.edu/data/states/, is a list of all +states/admin divisions and their corresponding geodata (state code, +latitude, longitude) divided by country, where each file is named with +the 2-letter country code (e.g., "US.txt"). Next, we use the state code and country code from the city's geodata to look up the coordinates of the geographic center of the state to which @@ -38,7 +36,7 @@ math = dy_import_module("math.r2py") -def load_states_geodata(filename): +def load_state_geodata(filename, address): """ Loads all the states and their geodata from the given file into a dictionary. The dictionary that is returned has the format: @@ -49,12 +47,29 @@ def load_states_geodata(filename): } """ - get_file_from_server(filename) states_dict = {} states_geodata_fileobj = openfile(filename.lower(), False) states_geodata_file = states_geodata_fileobj.readat(None, 0).split("\n") states_geodata_fileobj.close() + # Check if we can match the state name in the given address to the + # name in the database. If there is a match, return a dict with that + # state and its geodata. + if "admin_area" in address: + for line in states_geodata_file: + # Ignore the empty line at the end of the file. + if line == "": + continue + state_geodata_record = line.split("\t") + if address["admin_area"] == state_geodata_record[1]: + states_dict[address["admin_area"]] = { + "latitude": float(state_geodata_record[2]), + "longitude": float(state_geodata_record[3]), + } + return states_dict + + # If no match, return a dict of all states and their geodata to + # find the closest state. for line in states_geodata_file: # Ignore the empty line at the end of the file. if line == "": @@ -102,23 +117,37 @@ def find_closest_state(lat, lon): surrounding cells. """ - # Determine which file to download from the database. - filename = get_database_filename(lat, lon) - # Load all the states and their geodata from the file. - states_dict = load_states_geodata(filename) + # Get the address for the given coordinates. + address = get_geolocation(lat, lon, 1)[0] + + # Use the country code to get the filename of the list of states + # for that country. + filename = address["country_code"] + ".txt" + + # Download the file from the server. + get_file_from_server(filename) + + # Load the state(s) and corresponding geodata from the file. + states_dict = load_state_geodata(filename, address) + + # Check if there is only one state in the dictionary. + if len(states_dict) == 1: + closest_state_name = states_dict.keys()[0] - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # state in the current country. - min_diff = 9999 + # Else find closest state. + else: + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # state in the current country. + min_diff = 9999 - for state_name, state_geodata in states_dict.items(): - diff = find_squared_difference((lat, lon), (state_geodata["latitude"], - state_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_state_name = state_name + for state_name, state_geodata in states_dict.items(): + diff = find_squared_difference((lat, lon), (state_geodata["latitude"], + state_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_state_name = state_name closest_state_geodata = { "state_name": closest_state_name, @@ -130,19 +159,6 @@ def find_closest_state(lat, lon): -def get_database_filename(lat, lon): - """ - Returns the filename of the cell in the database to which the given - latitude/longitude pair belongs. - - """ - # Get the first address in the list of addresses - address = get_geolocation(lat, lon, 1)[0] - filename = address["country_code"] + ".txt" - return filename - - - def find_squared_difference(p1, p2): """ Returns the squared difference between the two given pairs of From c0d51c9dc7b549bc7256e42a5aeabb614475dfb5 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 23:56:06 -0400 Subject: [PATCH 15/60] update to match database changes --- blur_location2zipcode.r2py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index a3ca6e1..372b38f 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -50,8 +50,8 @@ def load_zipcodes_geodata(filename): zipcode_geodata_record = line.split("\t") zipcode = zipcode_geodata_record[1] zipcodes_dict[int(zipcode)] = { - "latitude": float(zipcode_geodata_record[4]), - "longitude": float(zipcode_geodata_record[5]), + "latitude": float(zipcode_geodata_record[2]), + "longitude": float(zipcode_geodata_record[3]), } return zipcodes_dict @@ -171,7 +171,7 @@ def get_zipcode_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider + # Get the location from every provider. for location_provider, provider_location_data in location_data.items(): # Skip blurring this provider's data if it doesn't contain a previous # location. @@ -209,5 +209,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } -# Dispatch +# Dispatch. secure_dispatch_module() \ No newline at end of file From c5da8c7f5744309aaf083ea8b517207586073d70 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 23:59:12 -0400 Subject: [PATCH 16/60] update to match database changes --- blur_location2zipcode.r2py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index 372b38f..1f4f5b3 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -6,7 +6,7 @@ to the geographic center of approximately the nearest ZIP code. The blurring is done using a database lookup method. The database, located at http://sensibilityclearinghouse.poly.edu/data/zip/, contains -a list of ZIP codes and their geodata (country, area, state, latitude, +a list of ZIP codes and their geodata (2-letter country code, latitude, longitude), divided by their latitude/longitude coordinates into cells. Each cell is a separate file in the database, whose name is derived as "ceiling(latitude)_ceiling(longitude).txt". For example, if a location From 4ab87c98aa42a6b40a7a65a537c0451e59cc1a82 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 14 Jul 2015 19:07:48 +0530 Subject: [PATCH 17/60] changes to match city and state blur layers reduced number of files to download and the number of operations to perform --- blur_location2country.r2py | 284 ++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 161 deletions(-) diff --git a/blur_location2country.r2py b/blur_location2country.r2py index 1e8081f..9c90b58 100644 --- a/blur_location2country.r2py +++ b/blur_location2country.r2py @@ -1,185 +1,143 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of the country to which it belongs. + +The blurring is done using a database lookup method. First, we use the +get_geolocation() call to get the current address. The country code +("country_code") in the address returned is then used to find a match +in the database "countries.txt", which is a list of all countries and +their geodata (country code, latitude, longitude). The country code is +the ISO-3166 2-letter code assigned to the country and the latitude and +longitude coordinates represent the geographical center of the country. +This database file is located at: +http://sensibilityclearinghouse.poly.edu/data/ + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2country.r2py user-program.r2py +""" + + + httpretrieve = dy_import_module("httpretrieve.r2py") math = dy_import_module("math.r2py") -librepyfile = dy_import_module("librepyfile.r2py") -statefilename = "states.txt" # Database of states -countryfilename = "countries.txt" # Database of countries -# Downloads the required file from the server def get_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + httpretrieve.httpretrieve_save_file(url, filename.lower()) + + + +def load_country_geodata(address): + """ + Finds the country in the database which has the same country code as + that in the given address and returns a dictionary with that country's + name, latitude and longitude. + + Below is an example of a line from the database of countries - + "countries.txt" (country code, name, latitude and longitude): + US United States 39.76 -98.5 + + The dictionary returned has the format: + { + "country_name": state name (string), + "latitude": latitude of the geographic center of the country (float) + "longitude": longitude of the geographic center of the country (float) + } + + """ + # Download the database of countries. + get_file_from_server("countries.txt") + + # Open the database of countries and read all data. + countries_geodata_fileobj = openfile("countries.txt", False) + countries_geodata_file = countries_geodata_fileobj.readat(None, 0).split("\n") + countries_geodata_fileobj.close() + + # Compare the country code from the address with the country code for + # each country in the database to find a match. + for line in countries_geodata_file: + # Ignore the empty line at the end of the file. + if line == "": + continue + country_geodata_record = line.split("\t") + # If there is a match, return the country name and its coordinates. + if address["country_code"] == country_geodata_record[0]: + country_geodata = { + "country_name": country_geodata_record[1], + "latitude": float(country_geodata_record[2]), + "longitude": float(country_geodata_record[3]) + } + return country_geodata + + # XXX will there ever not be a match? - if filename not in listfiles(): # In case it already exists - if filename not in [statefilename, countryfilename]: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - httpretrieve.httpretrieve_save_file(url, filename) - - -# Returns a dictionary containing information about the point closest to -# a given lat/lng pair, from the database. -# {"city": closest_city, "statecode": closest_state_code, "countrycode": -# closest_country_code, "coordinates": closest_point} -def find_closest_point(lat, lng): - - # Find the database file with coordinates closest to the given lat/lng pair - filename = get_filename(lat, lng) - # Get the list of coordinates from that file - listofpoints = load_lat_lng_from_file(filename) - - min_dist = 9999 - point1 = (lat, lng) - - for city in listofpoints.keys(): - data = listofpoints[city] - point2 = (data[0], data[1]) - dist = find_distance(point1, point2) - if dist < min_dist: - min_dist = dist - closest_point = point2 - closest_city = city - closest_state_code = data[3] - closest_country_code = data[2] - - closest = {"city": closest_city, "statecode": closest_state_code, "countrycode": closest_country_code, "coordinates": closest_point} - - return closest - - -# Returns the filename in the database with coordinates closest to the given -# lat/lng pair -def get_filename(lat, lng): - - # get ceiling as x/y index - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lng)) - filename = str(x) + '_' + str(y) + '.txt' - return filename - - -# Returns a dictionary containing all the cities in the given file, along with -# their corresponding data -# {city1: [lat, lng, country_code, state_code], city2: [lat, lng, country_code, -# state_code], ...} -def load_lat_lng_from_file(filename): - - get_file_from_server(filename) - listofpoints = {} - fileobj = librepyfile.open(filename, "r") - - while True: - try: - line = fileobj.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - city_name = line[0] - lat = line[1] - lng = line[2] - country_code = line[3] - state_code = line[4] - listofpoints[city_name] = [lat, lng, country_code, state_code] - fileobj.close() - return listofpoints - - -# Returns the distance between two lat/lng points -def find_distance(p1, p2): - - (lat1, lng1) = p1 - (lat2, lng2) = p2 - lat2 = float(lat2) - lng2 = float(lng2) - lat_diff = (lat1-lat2) * (lat1-lat2) - lng_diff = (lng1-lng2) * (lng1-lng2) - # return squared distance - return lat_diff + lng_diff - - -# To replace get_location() -def get_country_location(): - - try: - location_data = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - latitude = location_data["latitude"] - longitude = location_data["longitude"] - closest = find_closest_point(latitude, longitude) - country_code = closest["countrycode"] +def get_country_location(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the country to which they belong. - # Download the Countries database - get_file_from_server(countryfilename) + """ + location_data = get_location() - countryfile = librepyfile.open(countryfilename, "r") + # Get the first address from the list of addresses returned by + # get_geolocation(). + address = get_geolocation(location_data["latitude"], + location_data["longitude"], 1)[0] - # Look for the country corresponding to the country code - while True: - try: - line = countryfile.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - if country_code == line[0]: - clat = line[2] - clng = line[3] - break - countryfile.close() + country_geodata = load_country_geodata(address) - location_data["latitude"] = clat - location_data["longitude"] = clng + location_data["latitude"] = country_geodata["latitude"] + location_data["longitude"] = country_geodata["longitude"] return location_data + + def get_country_lastknown_location(): - # to replace get_lastknown_location() - try: - location_data = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - - # Get the location from the the provider - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - latitude = location["latitude"] - longitude = location["longitude"] - - closest = find_closest_point(latitude, longitude) - - country_code = closest["countrycode"] - - # Download the Countries database - get_file_from_server(countryfilename) - - countryfile = librepyfile.open(countryfilename, "r") - - # Look for the country corresponding to the country code - while True: - try: - line = countryfile.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - if country_code == line[0]: - clat = line[2] - clng = line[3] - break - countryfile.close() - - location_data[provider]["latitude"] = clat - location_data[provider]["longitude"] = clng + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the country to which they belong. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + # Get the first address from the list of addresses returned by + # get_geolocation(). + address = get_geolocation(provider_location_data["latitude"], + provider_location_data["longitude"], 1)[0] + + country_geodata = load_country_geodata(address) + + location_data[location_provider]["latitude"] = country_geodata["latitude"] + location_data[location_provider]["longitude"] = country_geodata["longitude"] return location_data + +# Mapping our blurring function get_country_location to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -189,6 +147,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function get_country_lastknown_location to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -197,4 +157,6 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { "target": get_country_lastknown_location, } + +# Dispatch. secure_dispatch_module() \ No newline at end of file From da905866d3c95f413553a7b3725c49ed3822e111 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 14 Jul 2015 19:11:32 +0530 Subject: [PATCH 18/60] refactored common parts into blur_helper --- blur_helper.r2py | 98 +++++++++++++++++++++++++++++ blur_location2city.r2py | 70 ++------------------- blur_location2state.r2py | 126 +++++++++++-------------------------- blur_location2zipcode.r2py | 68 ++------------------ 4 files changed, 142 insertions(+), 220 deletions(-) create mode 100644 blur_helper.r2py diff --git a/blur_helper.r2py b/blur_helper.r2py new file mode 100644 index 0000000..086f81f --- /dev/null +++ b/blur_helper.r2py @@ -0,0 +1,98 @@ +""" +This is a helper program that contains some of the common functions +shared between the blurring layers blur_location2city, blur_location2zipcode, +and blur_location2state. + +""" + + + +httpretrieve = dy_import_module("httpretrieve.r2py") +math = dy_import_module("math.r2py") + + + +def get_file_from_server(filename, blur_level): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The blur_level argument is an integer which indicates the blurring + level (blurring to ZIP code, city or state): + 0 - zipcode + 1 - city + 2 - state + + """ + if filename not in listfiles(): + if blur_level == 0: + folder = "zip/" + elif blur_level == 1: + folder = "quad/" + elif blur_level == 2: + folder = "states/" + url = "http://sensibilityclearinghouse.poly.edu/data/" + folder + \ + filename + httpretrieve.httpretrieve_save_file(url, filename.lower()) + + + +def get_database_filename(lat, lon): + """ + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. + + """ + # Get ceiling as x/y index. + x = int(math.math_ceil(lat)) + y = int(math.math_ceil(lon)) + filename = str(x) + '_' + str(y) + ".txt" + return filename + + + +def find_squared_difference(p1, p2): + """ + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). + + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff + + + +def find_closest_blur_level(lat, lon, blur_level_dict): + """ + + """ + # Check if there is only one entry in the dictionary. + if len(blur_level_dict) == 1: + closest_blur_level = blur_level_dict.keys()[0] + + # Else find closest blur level area (ZIP code area, city or state). + else: + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # blur level area (ZIP code area, city or state) in the current + # latitude/longitude quadilateral. + min_diff = 9999 + + for blur_level, blur_level_geodata in blur_level_dict.items(): + diff = find_squared_difference((lat, lon), (blur_level_geodata["latitude"], + blur_level_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_blur_level = blur_level + + closest_blur_level_geodata = { + "name": closest_blur_level, + "latitude": blur_level_dict[closest_blur_level]["latitude"], + "longitude": blur_level_dict[closest_blur_level]["longitude"], + } + + return closest_blur_level_geodata \ No newline at end of file diff --git a/blur_location2city.r2py b/blur_location2city.r2py index d4b9fa1..0f0e34c 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -20,8 +20,7 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") +blur_helper = dy_import_module("blur_helper.r2py") @@ -38,7 +37,7 @@ def load_city_geodata(filename): } """ - get_file_from_server(filename) + blur_helper.get_file_from_server(filename, 1) city_dict = {} city_geodata_fileobj = openfile(filename, False) city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") @@ -61,18 +60,6 @@ def load_city_geodata(filename): -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - httpretrieve.httpretrieve_save_file(url, filename) - - - def find_closest_city(lat, lon): """ Finds the city closest to the given latitude/longitude pair from the @@ -94,61 +81,12 @@ def find_closest_city(lat, lon): """ # Determine which file to download from the database. - filename = get_database_filename(lat, lon) + filename = blur_helper.get_database_filename(lat, lon) # Load all the cities and their geodata from the file. city_dict = load_city_geodata(filename) - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # city in the current latitude/longitude quadrilateral. - min_diff = 9999 - - for city_name, city_geodata in city_dict.items(): - diff = find_squared_difference((lat, lon), (city_geodata["latitude"], - city_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_city_name = city_name - - closest_city_geodata = { - "city_name": closest_city_name, - "latitude": city_dict[closest_city_name]["latitude"], - "longitude": city_dict[closest_city_name]["longitude"], - "state_code": city_dict[closest_city_name]["state_code"], - "country_code": city_dict[closest_city_name]["country_code"] - } - - return closest_city_geodata - - - -def get_database_filename(lat, lon): - """ - Returns the filename of the cell in the database to which the given - latitude/longitude pair belongs. - - """ - # Get ceiling as x/y index. - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + ".txt" - return filename - - - -def find_squared_difference(p1, p2): - """ - Returns the squared difference between the two given pairs of - coordinates (p1 and p2, where p1 and p2 are tuples of the form - (latitude, longitude)). - - """ - lat1, lon1 = p1 - lat2, lon2 = p2 - lat_diff = (lat1-lat2) ** 2 - lon_diff = (lon1-lon2) ** 2 - return lat_diff + lon_diff + return blur_helper.find_closest_blur_level(lat, lon, city_dict) diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 9cca592..f78c5e1 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -5,24 +5,20 @@ coordinates, received from the location sensors of an Android device, to the geographic center of approximately the nearest state (admin division). The blurring is done using a database lookup method. First, we use the -get_geolocation() call to get the current address. The country code in -the address returned is then used to look up the list of states for -that country from the database. This database, located at -http://sensibilityclearinghouse.poly.edu/data/states/, is a list of all -states/admin divisions and their corresponding geodata (state code, -latitude, longitude) divided by country, where each file is named with -the 2-letter country code (e.g., "US.txt"). - -Next, we use the state code and country code from the city's geodata to -look up the coordinates of the geographic center of the state to which -the city belongs. This look up uses the states' database, states.txt, -located at http://sensibilityclearinghouse.poly.edu/data/. states.txt -is a database of the top level administrative divisions within each -country (for example, states/provinces). It has the following fields: -code, state name, latitude, longitude. The code field has the format -"country_code.state_code", where country_code is the ISO-3166 2-letter -country code of the country to which the admin division belongs and -state_code is the 2-digit state code representing the admin division. +get_geolocation() call to get the current address. The country code +("country_code") in the address returned is then used to look up the +list of states for that country from the database. This database, +located at http://sensibilityclearinghouse.poly.edu/data/states/, is a +list of all states/admin divisions and their corresponding geodata +(state code, latitude, longitude) divided by country, where each file +is named with the 2-letter country code (e.g., "US.txt"). + +Next, we use the state name ("admin_area") from the returned address to +check for a match with the list of states. If there is a match, the +coordinates associated with that state are returned. If there is no +match, we look for the state that has coordinates closest to the +those received from the location sensors of the Android device +and return its latitude and longitude. Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -31,15 +27,21 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") +blur_helper = dy_import_module("blur_helper.r2py") def load_state_geodata(filename, address): """ - Loads all the states and their geodata from the given file into a - dictionary. The dictionary that is returned has the format: + Loads the state(s) and the corresponding latitude and longitude from + the given file into a dictionary. + + Below is an example of a line from the given file (state code, state + name, latitude, longitude): + US.NY New York 43.00035 -75.4999 + + The dictionary that is returned has + the format: { state1: {"latitude": latitude, "longitude": longitude}, state2: {"latitude": latitude, "longitude": longitude}, @@ -85,39 +87,22 @@ def load_state_geodata(filename, address): -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/states/" + filename - httpretrieve.httpretrieve_save_file(url, filename.lower()) - - - def find_closest_state(lat, lon): """ - Finds the city closest to the given latitude/longitude pair from the - dictionary of cities returned by the load_city_geodata() function, - and returns that city's geodata in the format: + Finds the state closest to the given latitude/longitude pair from the + dictionary of states returned by the load_state_geodata() function, + and returns its name, latitude and longitude in a dictionary. If the + load_state_geodata() function returns only one state, then that + state's name along with its latitude and longitude is returned in the + dictionary. + The dictionary returned has the format: { - "city_name": city name (string), - "state_code": 2-digit code representing the state to which the city - belongs (string), - "country_code": 2-letter ISO-3166 code representing the country to - which the city belongs (string), - "latitude": latitude of the geographic center of the city (float) - "longitude": longitude of the geographic center of the city (float) + "state_name": state name (string), + "latitude": latitude of the geographic center of the state (float) + "longitude": longitude of the geographic center of the state (float) } - Note: We're looking for the closest city within the same cell as the - given latitude/longitude pair. There might be a closer city in the - surrounding cells. - """ - # Get the address for the given coordinates. address = get_geolocation(lat, lon, 1)[0] @@ -126,51 +111,12 @@ def find_closest_state(lat, lon): filename = address["country_code"] + ".txt" # Download the file from the server. - get_file_from_server(filename) + blur_helper.get_file_from_server(filename, 2) # Load the state(s) and corresponding geodata from the file. states_dict = load_state_geodata(filename, address) - # Check if there is only one state in the dictionary. - if len(states_dict) == 1: - closest_state_name = states_dict.keys()[0] - - # Else find closest state. - else: - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # state in the current country. - min_diff = 9999 - - for state_name, state_geodata in states_dict.items(): - diff = find_squared_difference((lat, lon), (state_geodata["latitude"], - state_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_state_name = state_name - - closest_state_geodata = { - "state_name": closest_state_name, - "latitude": states_dict[closest_state_name]["latitude"], - "longitude": states_dict[closest_state_name]["longitude"], - } - - return closest_state_geodata - - - -def find_squared_difference(p1, p2): - """ - Returns the squared difference between the two given pairs of - coordinates (p1 and p2, where p1 and p2 are tuples of the form - (latitude, longitude)). - - """ - lat1, lon1 = p1 - lat2, lon2 = p2 - lat_diff = (lat1-lat2) ** 2 - lon_diff = (lon1-lon2) ** 2 - return lat_diff + lon_diff + return blur_helper.find_closest_blur_level(lat, lon, states_dict) diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index 1f4f5b3..f83565d 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -20,8 +20,7 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") +blur_helper = dy_import_module("blur_helper.r2py") @@ -37,7 +36,7 @@ def load_zipcodes_geodata(filename): } """ - get_file_from_server(filename) + blur_helper.get_file_from_server(filename, 0) zipcodes_dict = {} zipcodes_geodata_fileobj = openfile(filename, False) zipcodes_geodata_file = zipcodes_geodata_fileobj.readat(None, 0).split("\n") @@ -58,18 +57,6 @@ def load_zipcodes_geodata(filename): -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/zip/" + filename - httpretrieve.httpretrieve_save_file(url, filename) - - - def find_closest_zipcode(lat, lon): """ Finds the ZIP code closest to the given latitude/longitude pair from the @@ -87,59 +74,12 @@ def find_closest_zipcode(lat, lon): """ # Determine which file to download from the database. - filename = get_database_filename(lat, lon) + filename = blur_helper.get_database_filename(lat, lon) # Load all the ZIP codes and their geodata from the file. zipcodes_dict = load_zipcodes_geodata(filename) - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # ZIP code area in the current latitude/longitude quadilateral. - min_diff = 9999 - - for zipcode, zipcode_geodata in zipcodes_dict.items(): - diff = find_squared_difference((lat, lon), (zipcode_geodata["latitude"], - zipcode_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_zipcode = zipcode - - closest_zipcode_geodata = { - "zipcode": closest_zipcode, - "latitude": zipcodes_dict[closest_zipcode]["latitude"], - "longitude": zipcodes_dict[closest_zipcode]["longitude"], - } - - return closest_zipcode_geodata - - - -def get_database_filename(lat, lon): - """ - Returns the filename of the cell in the database to which the given - latitude/longitude pair belongs. - - """ - # Get ceiling as x/y index. - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + ".txt" - return filename - - - -def find_squared_difference(p1, p2): - """ - Returns the squared difference between the two given pairs of - coordinates (p1 and p2, where p1 and p2 are tuples of the form - (latitude, longitude)). - - """ - lat1, lon1 = p1 - lat2, lon2 = p2 - lat_diff = (lat1-lat2) ** 2 - lon_diff = (lon1-lon2) ** 2 - return lat_diff + lon_diff + return blur_helper.find_closest_blur_level(lat, lon, zipcodes_dict) From cd41777209e6db06c903d089c04c43f53a3c39cd Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 21 Jul 2015 14:04:36 +0530 Subject: [PATCH 19/60] changed name to location_blur_helper --- blur_helper.r2py => location_blur_helper.r2py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename blur_helper.r2py => location_blur_helper.r2py (100%) diff --git a/blur_helper.r2py b/location_blur_helper.r2py similarity index 100% rename from blur_helper.r2py rename to location_blur_helper.r2py From d755d5a812c1ba98894ae2b23bab07a2570d699b Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 21 Jul 2015 14:09:48 +0530 Subject: [PATCH 20/60] changes based on comments Refactored out more common code and made changes to some functions. Changed docstrings to reflect these changes. --- blur_location2city.r2py | 80 +++++++++++---------- blur_location2country.r2py | 144 +++++++++++++++++++++---------------- blur_location2state.r2py | 108 +++++++++++++++------------- blur_location2zipcode.r2py | 74 +++++++++++-------- location_blur_helper.r2py | 128 +++++++++++++++++++++++++-------- 5 files changed, 327 insertions(+), 207 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index 0f0e34c..a51063c 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -6,12 +6,11 @@ to the geographic center of approximately the nearest city. The blurring is done using a database lookup method. The database, located at http://sensibilityclearinghouse.poly.edu/data/quad/, contains -a list of cities and their geodata (latitude, longitude, country code, -state code), divided by their latitude/longitude coordinates into cells. -Each cell is a separate file in the database, whose name is derived as -"ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan has -its center at coordinates 40.78343, -73.96625, so it will be mapped to -the file with name "41_-73.txt". +a list of cities and their geodata, divided by their latitude/longitude +coordinates into cells. Each cell is a separate file in the database, +whose name is derived as "ceiling(latitude)_ceiling(longitude).txt". +For example, if a location has coordinates (40.78343, -73.96625), it +will be mapped to the file with name "41_-73.txt". Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -20,30 +19,39 @@ Usage: -blur_helper = dy_import_module("blur_helper.r2py") +location_blur_helper = dy_import_module("location_blur_helper.r2py") -def load_city_geodata(filename): +def load_city_geodata(lat, lon): """ - Loads all the cities and their geodata from the given file into a - dictionary. The dictionary that is returned has the format: + Loads all cities and corresponding geodata from the given file + into a dictionary. + + Below is an example of a line from the file + http://sensibilityclearinghouse.poly.edu/data/quad/41_-73.txt, + with fields - city name, latitude, longitude, country code, state + code: + Manhattan 40.78343 -73.96625 US NY + + The dictionary that is returned has the format: { - city1: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, - city2: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, + city1: {"latitude": latitude, "longitude": longitude}, + city2: {"latitude": latitude, "longitude": longitude}, ... } """ - blur_helper.get_file_from_server(filename, 1) + # Determine which file to download from the database. + filename = location_blur_helper.get_database_filename(lat, lon) + # Download the file from the city database. + location_blur_helper.get_city_file_from_server(filename) + # Obtain the list of cities and their geodata from the file. + cities_geodata = location_blur_helper.read_data_from_file(filename) + city_dict = {} - city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") - city_geodata_fileobj.close() - for line in city_geodata_file: + for line in cities_geodata: # Ignore the empty line at the end of the file. if line == "": continue @@ -51,9 +59,7 @@ def load_city_geodata(filename): city_name = city_geodata_record[0] city_dict[city_name] = { "latitude": float(city_geodata_record[1]), - "longitude": float(city_geodata_record[2]), - "country_code": city_geodata_record[3], - "state_code": city_geodata_record[4] + "longitude": float(city_geodata_record[2]) } return city_dict @@ -67,12 +73,8 @@ def find_closest_city(lat, lon): and returns that city's geodata in the format: { "city_name": city name (string), - "state_code": 2-digit code representing the state to which the city - belongs (string), - "country_code": 2-letter ISO-3166 code representing the country to - which the city belongs (string), - "latitude": latitude of the geographic center of the city (float) - "longitude": longitude of the geographic center of the city (float) + "latitude": latitude of the center of the city (float) + "longitude": longitude of the center of the city (float) } Note: We're looking for the closest city within the same cell as the @@ -80,13 +82,10 @@ def find_closest_city(lat, lon): surrounding cells. """ - # Determine which file to download from the database. - filename = blur_helper.get_database_filename(lat, lon) - - # Load all the cities and their geodata from the file. - city_dict = load_city_geodata(filename) + # Load all cities and corresponding geodata from the file. + city_dict = load_city_geodata(lat, lon) - return blur_helper.find_closest_blur_level(lat, lon, city_dict) + return location_blur_helper.find_closest_location(lat, lon, city_dict) @@ -118,9 +117,9 @@ def get_city_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider. + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue @@ -128,6 +127,15 @@ def get_city_lastknown_location(): closest_city = find_closest_city(provider_location_data["latitude"], provider_location_data["longitude"]) + break + + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + location_data[location_provider]["latitude"] = closest_city["latitude"] location_data[location_provider]["longitude"] = closest_city["longitude"] diff --git a/blur_location2country.r2py b/blur_location2country.r2py index 9c90b58..8f4dbc5 100644 --- a/blur_location2country.r2py +++ b/blur_location2country.r2py @@ -5,14 +5,11 @@ coordinates, received from the location sensors of an Android device, to the geographic center of the country to which it belongs. The blurring is done using a database lookup method. First, we use the -get_geolocation() call to get the current address. The country code -("country_code") in the address returned is then used to find a match -in the database "countries.txt", which is a list of all countries and -their geodata (country code, latitude, longitude). The country code is -the ISO-3166 2-letter code assigned to the country and the latitude and -longitude coordinates represent the geographical center of the country. +get_geolocation() call to get the current address. The country code in +the address returned is then used to find a match in the database +"countries.txt", which is a list of all countries and their geodata. This database file is located at: -http://sensibilityclearinghouse.poly.edu/data/ +http://sensibilityclearinghouse.poly.edu/data/countries.txt Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -21,66 +18,92 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") - - - -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - httpretrieve.httpretrieve_save_file(url, filename.lower()) +location_blur_helper = dy_import_module("location_blur_helper.r2py") +country_filename = "countries.txt" def load_country_geodata(address): """ - Finds the country in the database which has the same country code as - that in the given address and returns a dictionary with that country's - name, latitude and longitude. + Loads the country (or countries) and corresponding geodata from the + given file into a dictionary. - Below is an example of a line from the database of countries - - "countries.txt" (country code, name, latitude and longitude): + Below is an example of a line from the file "countries.txt" with + fields - country code, country name, latitude and longitude: US United States 39.76 -98.5 The dictionary returned has the format: { - "country_name": state name (string), - "latitude": latitude of the geographic center of the country (float) - "longitude": longitude of the geographic center of the country (float) + country1: {"latitude": latitude, "longitude": longitude}, + country2: {"latitude": latitude, "longitude": longitude}, + ... } """ - # Download the database of countries. - get_file_from_server("countries.txt") + # Download the file from the country database. + location_blur_helper.get_country_file_from_server(country_filename) + # Obtain the list of countries and their geodata from the file. + countries_geodata = location_blur_helper.read_data_from_file(country_filename) - # Open the database of countries and read all data. - countries_geodata_fileobj = openfile("countries.txt", False) - countries_geodata_file = countries_geodata_fileobj.readat(None, 0).split("\n") - countries_geodata_fileobj.close() + country_dict = {} - # Compare the country code from the address with the country code for - # each country in the database to find a match. - for line in countries_geodata_file: + # Check if we can match the country code in the given address to that + # in the database. If there is a match, return a dict with that + # country and its geodata. + for line in countries_geodata: # Ignore the empty line at the end of the file. if line == "": continue country_geodata_record = line.split("\t") - # If there is a match, return the country name and its coordinates. if address["country_code"] == country_geodata_record[0]: - country_geodata = { - "country_name": country_geodata_record[1], + country_name = country_geodata_record[1] + country_dict[country_name] = { "latitude": float(country_geodata_record[2]), "longitude": float(country_geodata_record[3]) } - return country_geodata + return country_dict + + # If no match, return a dict of all countries and their geodata to + # find the closest country. + for line in countries_geodata: + # Ignore the empty line at the end of the file. + if line == "": + continue + country_geodata_record = line.split("\t") + country_name = country_geodata_record[1] + country_dict[country_name] = { + "latitude": float(country_geodata_record[2]), + "longitude": float(country_geodata_record[3]), + } + + return country_dict - # XXX will there ever not be a match? + +def find_closest_country(lat, lon): + """ + Finds the country closest to the given latitude/longitude pair from the + dictionary of countries returned by the load_country_geodata() function, + and returns that country's geodata in the format: + { + "country_name": country name (string), + "latitude": latitude of the center of the country (float) + "longitude": longitude of the center of the country (float) + } + + Note: If the load_country_geodata() function returns only one country, + which happens when the country code from the get_geolocation() call + was successfully matched with one of the countries' code in the database, + then only that country's geodata is returned in the dictionary. + + """ + # Get the address for the given coordinates. Since get_geolocation() + # can possibly return more than one address, we take the first one. + address = get_geolocation(lat, lon, 1)[0] + + # Load the state(s) and corresponding geodata from the file. + countries_dict = load_country_geodata(address) + + return location_blur_helper.find_closest_location(lat, lon, countries_dict) @@ -93,15 +116,11 @@ def get_country_location(): """ location_data = get_location() - # Get the first address from the list of addresses returned by - # get_geolocation(). - address = get_geolocation(location_data["latitude"], - location_data["longitude"], 1)[0] - - country_geodata = load_country_geodata(address) + closest_country = find_closest_country(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = country_geodata["latitude"] - location_data["longitude"] = country_geodata["longitude"] + location_data["latitude"] = closest_country["latitude"] + location_data["longitude"] = closest_country["longitude"] return location_data @@ -116,22 +135,27 @@ def get_country_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider. + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue - # Get the first address from the list of addresses returned by - # get_geolocation(). - address = get_geolocation(provider_location_data["latitude"], - provider_location_data["longitude"], 1)[0] + closest_country = find_closest_country(provider_location_data["latitude"], + provider_location_data["longitude"]) + + break - country_geodata = load_country_geodata(address) + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = country_geodata["latitude"] - location_data[location_provider]["longitude"] = country_geodata["longitude"] + location_data[location_provider]["latitude"] = closest_country["latitude"] + location_data[location_provider]["longitude"] = closest_country["longitude"] return location_data diff --git a/blur_location2state.r2py b/blur_location2state.r2py index f78c5e1..e853160 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -2,23 +2,21 @@ A security layer for the functions get_location() and get_lastknown_location() defined in getsensor.r2py. This program blurs the latitude/longitude coordinates, received from the location sensors of an Android device, -to the geographic center of approximately the nearest state (admin division). +to the geographic center of approximately the nearest state (admin area). The blurring is done using a database lookup method. First, we use the -get_geolocation() call to get the current address. The country code -("country_code") in the address returned is then used to look up the -list of states for that country from the database. This database, -located at http://sensibilityclearinghouse.poly.edu/data/states/, is a -list of all states/admin divisions and their corresponding geodata -(state code, latitude, longitude) divided by country, where each file -is named with the 2-letter country code (e.g., "US.txt"). - -Next, we use the state name ("admin_area") from the returned address to -check for a match with the list of states. If there is a match, the -coordinates associated with that state are returned. If there is no -match, we look for the state that has coordinates closest to the -those received from the location sensors of the Android device -and return its latitude and longitude. +get_geolocation() call to get the current address. The country code in +the address returned is then used to look up the list of states for +that country from the database. This database, located at +http://sensibilityclearinghouse.poly.edu/data/states/, is a list of +all states and their corresponding geodata divided by country, where +each file is named with the 2-letter country code (e.g., "US.txt"). + +Next, we use the state name from the returned address to check for a +match with the list of states. If there is a match, the coordinates +associated with that state are returned. If there is no match, we look +for the state that has coordinates closest to the those received from +the location sensors and return its latitude and longitude. Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -27,21 +25,21 @@ Usage: -blur_helper = dy_import_module("blur_helper.r2py") +location_blur_helper = dy_import_module("location_blur_helper.r2py") -def load_state_geodata(filename, address): +def load_state_geodata(address): """ - Loads the state(s) and the corresponding latitude and longitude from - the given file into a dictionary. + Loads the state(s) and corresponding geodata from the given file + into a dictionary. - Below is an example of a line from the given file (state code, state - name, latitude, longitude): + Below is an example of a line from the file + http://sensibilityclearinghouse.poly.edu/data/states/US.txt, + with fields - state code, state name, latitude, longitude: US.NY New York 43.00035 -75.4999 - The dictionary that is returned has - the format: + The dictionary that is returned has the format: { state1: {"latitude": latitude, "longitude": longitude}, state2: {"latitude": latitude, "longitude": longitude}, @@ -49,22 +47,28 @@ def load_state_geodata(filename, address): } """ + # Use the country code to get the filename of the list of states + # for that country. + filename = address["country_code"] + ".txt" + # Download the file from the state database. + location_blur_helper.get_state_file_from_server(filename) + # Obtain the list of states and their geodata from the file. + states_geodata = location_blur_helper.read_data_from_file(filename) + states_dict = {} - states_geodata_fileobj = openfile(filename.lower(), False) - states_geodata_file = states_geodata_fileobj.readat(None, 0).split("\n") - states_geodata_fileobj.close() # Check if we can match the state name in the given address to the # name in the database. If there is a match, return a dict with that - # state and its geodata. + # state and its geodata (state names are unique in each file). if "admin_area" in address: - for line in states_geodata_file: + for line in states_geodata: # Ignore the empty line at the end of the file. if line == "": continue state_geodata_record = line.split("\t") if address["admin_area"] == state_geodata_record[1]: - states_dict[address["admin_area"]] = { + state_name = state_geodata_record[1] + states_dict[state_name] = { "latitude": float(state_geodata_record[2]), "longitude": float(state_geodata_record[3]), } @@ -72,7 +76,7 @@ def load_state_geodata(filename, address): # If no match, return a dict of all states and their geodata to # find the closest state. - for line in states_geodata_file: + for line in states_geodata: # Ignore the empty line at the end of the file. if line == "": continue @@ -91,32 +95,27 @@ def find_closest_state(lat, lon): """ Finds the state closest to the given latitude/longitude pair from the dictionary of states returned by the load_state_geodata() function, - and returns its name, latitude and longitude in a dictionary. If the - load_state_geodata() function returns only one state, then that - state's name along with its latitude and longitude is returned in the - dictionary. - The dictionary returned has the format: + and returns that state's geodata in the format: { "state_name": state name (string), - "latitude": latitude of the geographic center of the state (float) - "longitude": longitude of the geographic center of the state (float) + "latitude": latitude of the center of the state (float) + "longitude": longitude of the center of the state (float) } + Note: If the load_state_geodata() function returns only one state, + which happens when the state name from the get_geolocation() call + was successfully matched with one of the states in the database, + then only that state's geodata is returned in the dictionary. + """ - # Get the address for the given coordinates. + # Get the address for the given coordinates. Since get_geolocation() + # can possibly return more than one address, we take the first one. address = get_geolocation(lat, lon, 1)[0] - # Use the country code to get the filename of the list of states - # for that country. - filename = address["country_code"] + ".txt" - - # Download the file from the server. - blur_helper.get_file_from_server(filename, 2) - # Load the state(s) and corresponding geodata from the file. - states_dict = load_state_geodata(filename, address) + states_dict = load_state_geodata(address) - return blur_helper.find_closest_blur_level(lat, lon, states_dict) + return location_blur_helper.find_closest_location(lat, lon, states_dict) @@ -148,16 +147,25 @@ def get_state_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue closest_state = find_closest_state(provider_location_data["latitude"], provider_location_data["longitude"]) - + + break + + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + location_data[location_provider]["latitude"] = closest_state["latitude"] location_data[location_provider]["longitude"] = closest_state["longitude"] diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index f83565d..62c3b13 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -2,16 +2,15 @@ A security layer for the functions get_location() and get_lastknown_location() defined in getsensor.r2py. This program blurs the latitude/longitude coordinates, received from the location sensors of an Android device, -to the geographic center of approximately the nearest ZIP code. +to the geographic center of approximately the nearest ZIP code area. The blurring is done using a database lookup method. The database, located at http://sensibilityclearinghouse.poly.edu/data/zip/, contains -a list of ZIP codes and their geodata (2-letter country code, latitude, -longitude), divided by their latitude/longitude coordinates into cells. -Each cell is a separate file in the database, whose name is derived as -"ceiling(latitude)_ceiling(longitude).txt". For example, if a location -has coordinates 40.78343, -73.96625, it will be mapped to the file with -name "41_-73.txt". +a list of ZIP codes and their geodata, divided by their latitude/longitude +coordinates into cells. Each cell is a separate file in the database, +whose name is derived as "ceiling(latitude)_ceiling(longitude).txt". +For example, if a location has coordinates (40.78343, -73.96625), it +will be mapped to the file with name "41_-73.txt". Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -20,15 +19,21 @@ Usage: -blur_helper = dy_import_module("blur_helper.r2py") +location_blur_helper = dy_import_module("location_blur_helper.r2py") -def load_zipcodes_geodata(filename): +def load_zipcode_geodata(lat, lon): """ - Loads all the ZIP codes and their latitude/longitude coordinates from - the given file into a dictionary. The dictionary that is returned - has the format: + Loads all ZIP codes and corresponding geodata from the given file + into a dictionary. + + Below is an example of a line from the file + http://sensibilityclearinghouse.poly.edu/data/zip/41_-73.txt + with fields - country code, ZIP code, latitude, longitude: + US 10012 40.7255 -73.9983 + + The dictionary that is returned has the format: { zipcode1: {"latitude": latitude, "longitude": longitude}, zipcode2: {"latitude": latitude, "longitude": longitude}, @@ -36,19 +41,22 @@ def load_zipcodes_geodata(filename): } """ - blur_helper.get_file_from_server(filename, 0) + # Determine which file to download from the database. + filename = location_blur_helper.get_database_filename(lat, lon) + # Download the file from the ZIP code database. + location_blur_helper.get_zipcode_file_from_server(filename) + # Obtain the list of ZIP codes and their geodata from the file. + zipcodes_geodata = location_blur_helper.read_data_from_file(filename) + zipcodes_dict = {} - zipcodes_geodata_fileobj = openfile(filename, False) - zipcodes_geodata_file = zipcodes_geodata_fileobj.readat(None, 0).split("\n") - zipcodes_geodata_fileobj.close() - for line in zipcodes_geodata_file: + for line in zipcodes_geodata: # Ignore the empty line at the end of the file. if line == "": continue zipcode_geodata_record = line.split("\t") zipcode = zipcode_geodata_record[1] - zipcodes_dict[int(zipcode)] = { + zipcodes_dict[zipcode] = { "latitude": float(zipcode_geodata_record[2]), "longitude": float(zipcode_geodata_record[3]), } @@ -60,10 +68,10 @@ def load_zipcodes_geodata(filename): def find_closest_zipcode(lat, lon): """ Finds the ZIP code closest to the given latitude/longitude pair from the - dictionary of ZIP codes returned by the load_zipcodes_geodata() function, - and returns that ZIP code's coordinates in the format: + dictionary of ZIP codes returned by the load_zipcode_geodata() function, + and returns that ZIP code's geodata in the format: { - "zipcode": ZIP code (int), + "zipcode": ZIP code (string), "latitude": latitude of the center of the ZIP code area (float) "longitude": longitude of the center of the ZIP code area (float) } @@ -73,13 +81,10 @@ def find_closest_zipcode(lat, lon): area in the surrounding cells. """ - # Determine which file to download from the database. - filename = blur_helper.get_database_filename(lat, lon) - - # Load all the ZIP codes and their geodata from the file. - zipcodes_dict = load_zipcodes_geodata(filename) + # Load all ZIP codes and corresponding geodata from the file. + zipcodes_dict = load_zipcode_geodata(lat, lon) - return blur_helper.find_closest_blur_level(lat, lon, zipcodes_dict) + return location_blur_helper.find_closest_location(lat, lon, zipcodes_dict) @@ -111,16 +116,25 @@ def get_zipcode_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider. + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], provider_location_data["longitude"]) - + + break + + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + location_data[location_provider]["latitude"] = closest_zipcode["latitude"] location_data[location_provider]["longitude"] = closest_zipcode["longitude"] diff --git a/location_blur_helper.r2py b/location_blur_helper.r2py index 086f81f..615a473 100644 --- a/location_blur_helper.r2py +++ b/location_blur_helper.r2py @@ -1,7 +1,7 @@ """ This is a helper program that contains some of the common functions shared between the blurring layers blur_location2city, blur_location2zipcode, -and blur_location2state. +blur_location2state and blur_location2country. """ @@ -12,31 +12,66 @@ math = dy_import_module("math.r2py") -def get_file_from_server(filename, blur_level): +def get_zipcode_file_from_server(filename): """ Downloads the required file from the database server, if it has not already been downloaded. - The blur_level argument is an integer which indicates the blurring - level (blurring to ZIP code, city or state): - 0 - zipcode - 1 - city - 2 - state + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/zip/ """ if filename not in listfiles(): - if blur_level == 0: - folder = "zip/" - elif blur_level == 1: - folder = "quad/" - elif blur_level == 2: - folder = "states/" - url = "http://sensibilityclearinghouse.poly.edu/data/" + folder + \ - filename + url = "http://sensibilityclearinghouse.poly.edu/data/zip/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def get_city_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/quad/ + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def get_state_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/states/ + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/states/" + filename httpretrieve.httpretrieve_save_file(url, filename.lower()) +def get_country_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/countries.txt + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + def get_database_filename(lat, lon): """ Returns the filename of the cell in the database to which the given @@ -66,33 +101,64 @@ def find_squared_difference(p1, p2): -def find_closest_blur_level(lat, lon, blur_level_dict): +def read_data_from_file(filename): + """ + Reads all data from the given file and returns a list of the lines + in that file. + """ + fileobj = openfile(filename.lower(), False) + file_data = fileobj.readat(None, 0).split("\n") + fileobj.close() + return file_data + + +def find_closest_location(lat, lon, location_dict): + """ + Returns a dictionary with the name and coordinates of the center of + the closest location to the given latitude and longitude coordinates. + This location, depending on the level of blurring, could be the + closest city, state, ZIP code area or country. + + The argument "location_dict" contains a list of all nearby + locations (either cities, states, ZIP code areas or countries) and + their geodata (latitude and longitude). + + The dictionary returned has the format: + { + "name": name of the closest location (string), + "latitude": latitude of the center of the above location (float), + "longitude": longitude of the center of the above location (float) + } """ - # Check if there is only one entry in the dictionary. - if len(blur_level_dict) == 1: - closest_blur_level = blur_level_dict.keys()[0] + # Check if there is only one entry in the dictionary, (e.g., in a state + # file like this http://sensibilityclearinghouse.poly.edu/data/states/US.txt + # there's only one entry that matches the state name) + if len(location_dict) == 1: + closest_location = location_dict.keys()[0] - # Else find closest blur level area (ZIP code area, city or state). + # Else find closest location. else: # Set the minimum squared difference between two pairs of coordinates # to a number larger than any possible minimum distance to a close - # blur level area (ZIP code area, city or state) in the current - # latitude/longitude quadilateral. + # location in the current latitude/longitude quadilateral (in case + # of blurring to city/ZIP code area), in the current country (in + # case of blurring to state), or in the entire world (in case of + # blurring to country). min_diff = 9999 - for blur_level, blur_level_geodata in blur_level_dict.items(): - diff = find_squared_difference((lat, lon), (blur_level_geodata["latitude"], - blur_level_geodata["longitude"])) + for current_location, location_geodata in location_dict.items(): + diff = find_squared_difference((lat, lon), (location_geodata["latitude"], + location_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_blur_level = blur_level + closest_location = current_location - closest_blur_level_geodata = { - "name": closest_blur_level, - "latitude": blur_level_dict[closest_blur_level]["latitude"], - "longitude": blur_level_dict[closest_blur_level]["longitude"], + closest_location_geodata = { + "name": closest_location, + "latitude": location_dict[closest_location]["latitude"], + "longitude": location_dict[closest_location]["longitude"] } - return closest_blur_level_geodata \ No newline at end of file + return closest_location_geodata \ No newline at end of file From d75e0722d83c199e54b69b2add22cf3761052daf Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 21 Jul 2015 21:34:18 +0530 Subject: [PATCH 21/60] handle get_location() returning None --- blur_location2city.r2py | 44 ++++++++++++++++++++------------------ blur_location2country.r2py | 44 ++++++++++++++++++++------------------ blur_location2state.r2py | 44 ++++++++++++++++++++------------------ blur_location2zipcode.r2py | 44 ++++++++++++++++++++------------------ 4 files changed, 92 insertions(+), 84 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index a51063c..7f823e3 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -98,11 +98,12 @@ def get_city_location(): """ location_data = get_location() - closest_city = find_closest_city(location_data["latitude"], - location_data["longitude"]) + if location_data is not None: + closest_city = find_closest_city(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_city["latitude"] - location_data["longitude"] = closest_city["longitude"] + location_data["latitude"] = closest_city["latitude"] + location_data["longitude"] = closest_city["longitude"] return location_data @@ -117,27 +118,28 @@ def get_city_lastknown_location(): """ location_data = get_lastknown_location() - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + if location_data is not None: + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_city = find_closest_city(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_city = find_closest_city(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_city["latitude"] - location_data[location_provider]["longitude"] = closest_city["longitude"] + location_data[location_provider]["latitude"] = closest_city["latitude"] + location_data[location_provider]["longitude"] = closest_city["longitude"] return location_data diff --git a/blur_location2country.r2py b/blur_location2country.r2py index 8f4dbc5..4c8a7a1 100644 --- a/blur_location2country.r2py +++ b/blur_location2country.r2py @@ -116,11 +116,12 @@ def get_country_location(): """ location_data = get_location() - closest_country = find_closest_country(location_data["latitude"], - location_data["longitude"]) + if location_data is not None: + closest_country = find_closest_country(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_country["latitude"] - location_data["longitude"] = closest_country["longitude"] + location_data["latitude"] = closest_country["latitude"] + location_data["longitude"] = closest_country["longitude"] return location_data @@ -135,27 +136,28 @@ def get_country_lastknown_location(): """ location_data = get_lastknown_location() - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + if location_data is not None: + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_country = find_closest_country(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_country = find_closest_country(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_country["latitude"] - location_data[location_provider]["longitude"] = closest_country["longitude"] + location_data[location_provider]["latitude"] = closest_country["latitude"] + location_data[location_provider]["longitude"] = closest_country["longitude"] return location_data diff --git a/blur_location2state.r2py b/blur_location2state.r2py index e853160..c4790a5 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -128,11 +128,12 @@ def get_state_location(): """ location_data = get_location() - closest_state = find_closest_state(location_data["latitude"], - location_data["longitude"]) + if location_data is not None: + closest_state = find_closest_state(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_state["latitude"] - location_data["longitude"] = closest_state["longitude"] + location_data["latitude"] = closest_state["latitude"] + location_data["longitude"] = closest_state["longitude"] return location_data @@ -147,27 +148,28 @@ def get_state_lastknown_location(): """ location_data = get_lastknown_location() - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + if location_data is not None: + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_state = find_closest_state(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_state = find_closest_state(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_state["latitude"] - location_data[location_provider]["longitude"] = closest_state["longitude"] + location_data[location_provider]["latitude"] = closest_state["latitude"] + location_data[location_provider]["longitude"] = closest_state["longitude"] return location_data diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index 62c3b13..9243eeb 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -97,11 +97,12 @@ def get_zipcode_location(): """ location_data = get_location() - closest_zipcode = find_closest_zipcode(location_data["latitude"], - location_data["longitude"]) + if location_data is not None: + closest_zipcode = find_closest_zipcode(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_zipcode["latitude"] - location_data["longitude"] = closest_zipcode["longitude"] + location_data["latitude"] = closest_zipcode["latitude"] + location_data["longitude"] = closest_zipcode["longitude"] return location_data @@ -116,27 +117,28 @@ def get_zipcode_lastknown_location(): """ location_data = get_lastknown_location() - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + if location_data is not None: + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_zipcode["latitude"] - location_data[location_provider]["longitude"] = closest_zipcode["longitude"] + location_data[location_provider]["latitude"] = closest_zipcode["latitude"] + location_data[location_provider]["longitude"] = closest_zipcode["longitude"] return location_data From edf2a2f46f44f5f23e34c19dba15a7fea1dee050 Mon Sep 17 00:00:00 2001 From: aditup Date: Sat, 25 Jul 2015 17:31:30 +0530 Subject: [PATCH 22/60] removed try..except block, added docstrings --- blur_location_round.r2py | 66 ++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/blur_location_round.r2py b/blur_location_round.r2py index 3eb8c5a..2fca787 100644 --- a/blur_location_round.r2py +++ b/blur_location_round.r2py @@ -1,36 +1,59 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +by rounding them off to one decimal place. + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location_round.r2py user-program.r2py +""" + + + def blur_location_round(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates rounded off to + a single decimal place. - try: - location = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception + """ + location_data = get_location() - # Blur the coordinates by rounding - location["latitude"] = round(float(location["latitude"]), 1) - location["longitude"] = round(float(location["longitude"]), 1) + if location_data is not None: + location_data["latitude"] = round(float(location_data["latitude"]), 1) + location_data["longitude"] = round(float(location_data["longitude"]), 1) - return location + return location_data def blur_lastknown_location_round(): + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + rounded off to a single decimal place. + + """ + location_data = get_lastknown_location() + + if location_data is not None: + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - try: - location = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception + location_data[location_provider]["latitude"] = \ + round(float(provider_location_data["latitude"]), 1) + location_data[location_provider]["longitude"] = \ + round(float(provider_location_data["longitude"]), 1) - # Blur the coordinates by rounding - for i in range(len(location.keys())): - provider = location.keys()[i] - location_item = location[provider] - if location_item != None: - location[provider]["latitude"] = round(float(location_item["latitude"]), 1) - location[provider]["longitude"] = round(float(location_item["longitude"]), 1) + return location_data - return location +# Mapping our blurring function blur_location_round to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -40,6 +63,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function blur_lastknown_location_round to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -49,4 +74,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } +# Dispatch. secure_dispatch_module() \ No newline at end of file From b834885fa26ec10283174d2a4166a40d22713bd9 Mon Sep 17 00:00:00 2001 From: aditup Date: Sat, 25 Jul 2015 17:34:33 +0530 Subject: [PATCH 23/60] changed "quadrilateral" to "cell" in comment --- location_blur_helper.r2py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/location_blur_helper.r2py b/location_blur_helper.r2py index 615a473..8206c72 100644 --- a/location_blur_helper.r2py +++ b/location_blur_helper.r2py @@ -142,8 +142,8 @@ def find_closest_location(lat, lon, location_dict): else: # Set the minimum squared difference between two pairs of coordinates # to a number larger than any possible minimum distance to a close - # location in the current latitude/longitude quadilateral (in case - # of blurring to city/ZIP code area), in the current country (in + # location in the current latitude/longitude cell (in case of + # blurring to city/ZIP code area), in the current country (in # case of blurring to state), or in the entire world (in case of # blurring to country). min_diff = 9999 From bc083794025add4b095943ef95027cacb75c5695 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 28 Jul 2015 12:56:21 +0530 Subject: [PATCH 24/60] Merge branch 'SensibilityTestbed/master' Conflicts: getsensor.r2py --- getsensor.r2py | 794 ++++++++++++++++++++++++++-------------------- sensor_layer.r2py | 110 ++++--- 2 files changed, 523 insertions(+), 381 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 45037ea..5c2dd9b 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -38,331 +38,325 @@ class SIMNotFoundException(RepyException): """ pass + ################################################## -############## location interface ############### +############## battery interface ################ ################################################## -def get_location(): +def get_battery_info(): """ - Get original location data from GPS or network or passive. Calls - sensorlib.request_data(sensor_socket, 'readLocation', []). The location - information is returned as a dict, which is converted to ASCII - using unicode_scrubber. + Get battery data from a devices. Calls sensorlib.request_data(sensor_socket, + 'readBatteryData', []). The battery information is returned as a dict. None - LocationNotFoundException (descends from RepyException) when no location - information is found. + BatteryNotFoundException (descends from RepyException) when no battery + is found on the device. - When LocationNotFoundException is raised, the user of this method needs - to try several times. If this still fails, then should try - get_lastknown_location(). + When BatteryNotFoundException is raised, the user of this method cannot + get any battery information. - GPS or network location lookup. + Battery information lookup. - location as a dict, such as {'bearing': 0, 'altitude': 0, - 'time': x, 'longitude': x, 'provider': 'network', 'latitude': x, - 'speed': 0, 'accuracy': x}. - + Battery info as a dict, such as {'status': 3, 'temperature': 257, 'level': + 99, 'battery_present': True, 'plugged': 2, 'health': 2, 'voltage': + 4186, 'technology': 'Li-ion'}. + Return values for status: 1 - unknown; 2 - charging; 3 - discharging; + 4 - not charging; 5 - full. + Return values for temperature: in tenths of a degree Centigrade. E.g., + 257 is 25.7 celcius. + Return values for level: in percent. + Return values for plugged: -1 - unknown; 0 - unplugged; 1 - power + source is an AC charger; 2 - power source is a USB port. + Return values for health: 1 - unknown; 2 - good; 3 - overheat; 4 - dead; + 5 - over voltage; 6 - unspecified failure. + Return values for voltage: in millivolts. + """ - # start the locating process - sensorlib.request_data(sensor_socket, 'startLocating', []) + # start battery information lookup + sensorlib.request_data(sensor_socket, 'batteryStartMonitoring', []) - # try to read current location - # note: readLocation call can timeout, or not responsive - location_data = sensorlib.request_data(sensor_socket, 'readLocation', []) + # if no battery is present, then no battery information can be obtained + if sensorlib.request_data(sensor_socket, 'batteryCheckPresent', []) == False: + sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) + raise BatteryNotFoundException - # stop the locating process - sensorlib.request_data(sensor_socket, 'stopLocating', []) + battery_info = sensorlib.request_data(sensor_socket, 'readBatteryData', []) + sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) - if not location_data: - raise LocationNotFoundException - assert len(location_data.keys()) == 1 # should return at only one provider + return unicode_scrubber.scrub(battery_info) - # take the first key (because only one provider) - provider = location_data.keys()[0] - location = location_data[provider] - # convert unicode format (u'longitude') to ASCII (longitude) - # because Repy does not allow Unicode - location = unicode_scrubber.scrub(location) - return location +################################################## +############## bluetooth interface ############## +################################################## -def get_lastknown_location(): +def get_bluetooth_info(): """ - Get original _last-known_ location data from GPS/network/passive. Calls - sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []). The - location information is returned as a dict, which is converted to ASCII - using unicode_scrubber. + Get bluetooth data from a devices. Calls sensorlib.request_data(sensor_socket, + 'checkBluetoothState'/'bluetoothGetScanMode'/'bluetoothGetLocalName', []). + The bluetooth information is returned as a dict. - None + None - LocationNotFoundException (descends from RepyException) when the returned - location information is {'passive': None, 'network': None, 'gps': None}. + None. - None. + When bluetooth is not enabled, the user of this method cannot get any + bluetooth information. - Lookup cached location information on the device. + Bluetooth information lookup. - location as a dict with three keys: passive, network, and gps. Each key - value is a dict in the same format as the value returned by get_location(). - For example, {'passive': {'bearing': 0, 'altitude': 0, 'time': x, - 'longitude': x, 'provider': 'network', 'latitude': s, 'speed': 0, - 'accuracy': x}, 'network': {'bearing': 0, 'altitude': 0, 'time': x, - 'longitude': x, 'provider': 'network', 'latitude': x, 'speed': 0, - 'accuracy': x}, 'gps': None} - + Bluetooth info as a dict, such as {'state': True, 'scan_mode': 3, + 'local_name': 'GT-P1000'}. + Return values for scan_mode: -1 - when Bluetooth is disabled; + 0 - if non discoverable and non connectable; 1 - connectable + non discoverable; 3 - connectable and discoverable. + """ - # start the locating process - sensorlib.request_data(sensor_socket, 'startLocating', []) - - # try to read the cached location - location_data = sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []) + state = sensorlib.request_data(sensor_socket, 'checkBluetoothState', []) + scan_mode = sensorlib.request_data(sensor_socket, 'bluetoothGetScanMode', []) + local_name = sensorlib.request_data(sensor_socket, 'bluetoothGetLocalName', []) - # stop the locating process - sensorlib.request_data(sensor_socket, 'stopLocating', []) - assert len(location_data.keys()) >= 1 # should return at least one provider + bluetooth_info = {'state': state, 'scan_mode': scan_mode, 'local_name': local_name} + return unicode_scrubber.scrub(bluetooth_info) - # check if location_data is {'passive': None, 'network': None, 'gps': None} - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - break - else: - raise LocationNotFoundException - # convert unicode format (u'longitude') to ASCII (longitude) - location = unicode_scrubber.scrub(location_data) - return location +################################################## +############## cellular interface ############### +################################################## -def get_geolocation(latitude, longitude, max_results): +def is_roaming(): """ - Obtain a list of addresses for the given latitude and longitude. Calls - sensorlib.request_data(sensor_socket, 'geocode', [latitude, longitude, - max_results]). The addresses information is returned as a dict, which - is converted to ASCII using unicode_scrubber. + Return if a phone is roaming (True/False). Calls sensorlib.request_data( + sensor_socket, 'checkNetworkRoaming', []). - latitude (float): latitude of a location; - longitude (float): longitude of a location; - max_results (Integer): maximum number of results (normally =1). + None - None. + SIMNotFoundException. - None. + When no SIM card is found, no cellular information can be obtained. - Geolocation lookup. + Lookup if phone is roaming. - Geolocation (address) as a list, such as [{'thoroughfare': 'Some - Street', 'locality': u'Some Town', 'sub_admin_area': 'Some Borough', - 'admin_area': 'Some City', 'feature_name': 'House Numbers', - 'country_code': 'GB', 'country_name': 'United Kingdom', - 'postal_code': 'ST1 1'}] . - + A boolean vaiable indicating if the phone is roaming. """ - address = sensorlib.request_data(sensor_socket, 'geocode', - [latitude, longitude, max_results]) - return unicode_scrubber.scrub(address) + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException - + return sensorlib.request_data(sensor_socket, 'checkNetworkRoaming', []) -################################################## -############## WiFi interface ################### -################################################## -def is_wifi_enabled(): + +def get_cellular_provider_info(): """ - Return if WiFi is enabled on this device (True/False). + Get cellular provider info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getNetworkOperator'/'getNetworkOperatorName', []). The + cellular network information, current cellular operator code (MNC+MCC), + and operator name, is returned as a dict. - None + None - None. + SIMNotFoundException. - None. + When no SIM card is found, no cellular provider info can be obtained. - Lookup if WiFi is enabled on the device. + Cellular network provider information lookup. - A boolean vaiable indicating if WiFi is enabled on the device. - + Cellular provider info as a dict, such as {‘network_operator’: 310260, + ‘network_operator_name’: ‘T-Mobile’}. + """ - # True or False - return sensorlib.request_data(sensor_socket, 'checkWifiState', []) + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + network_operator = sensorlib.request_data(sensor_socket, + 'getNetworkOperator', []) + network_operator_name = sensorlib.request_data(sensor_socket, + 'getNetworkOperatorName', []) + + cellular_network_info = {'network_operator': network_operator, + 'network_operator_name': network_operator_name} + return unicode_scrubber.scrub(cellular_network_info) -def get_wifi_connection_info(): + +def get_cell_info(): """ - Return information about the WiFi network currently connected to. Calls - sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []). + Get cellular network info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getCellLocation'/'getNeighboringCellInfo'/'getNetworkType', + []). The cellular network information, current cellular cell ID, + neighboring cells, is returned as a dict. - None + None - None. + SIMNotFoundException. - None. + When no SIM card is found, no cellular information can be obtained. - Lookup WiFi connection information on the device. + Cellular network information lookup. - wifi_conn as a dict, and is returned as a dict of this format: - { - "ssid": network SSID (string), - "bssid": network BSSID, i.e. MAC address (string), - "rssi": received signal strength in dBm (negative int), - "supplicant_state": current WPA association state (string), - "link_speed": link speed in MBps (int), - "mac_address": this device's WiFi interface MAC (string), - XXX "ip_address": this device's IP address (XXX int, byte quadruples reversed!), - XXX "network_id": XXX (int), - "hidden_ssid": True if the SSID is not broadcast (bool) - } + Cellular info as a dict, such as {‘cellID’: {‘lac’: 32115, ‘cid’: 26742}, + ‘neighboring_cell’: [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, + {‘rssi’: 5, ‘cid’: 40153}]}. + """ - wifi_conn = sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []) + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException - # convert unicode format to ASCII - return unicode_scrubber.scrub(wifi_conn) + # get details about cell ID, e.g., {‘lac’: 32115, ‘cid’: 26742} + # cid = Cell ID, lac = location area code + cellID = sensorlib.request_data(sensor_socket, + 'getCellLocation', []) + # get information about neighboring cells in a list, e.g., + # [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, + # {‘rssi’: 5, ‘cid’: 40153}] + neighboring_cell = sensorlib.request_data(sensor_socket, + 'getNeighboringCellInfo', []) -def do_wifi_scan(): + cellular_info = {'cellID': cellID, 'neighboring_cell': neighboring_cell} + return unicode_scrubber.scrub(cellular_info) + + +def get_SIM_info(): """ - Return WiFi connection info on this device. Calls - sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []). + Get SIM card info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getSimState'/'getSimOperator'/'getSimOperatorName' + /'getSimCountryIso', []). The SIM card information, current SIM + card state, SIM card operator, SIM card operator name, SIM card + country code, is returned as a dict. - None + None - None. + SIMNotFoundException. - None. + When no SIM card is found, no information can be obtained. - Scan the WiFi network from the device. + SIM card information lookup. - WiFi scan results wifi_data as a HUGE dict of this format, - with one dict for each network found: - { - "ssid": network SSID (string), - "bssid": network BSSID, i.e. MAC address (string), - "frequency": frequency in MHz (int), - "level": received signal strength in dBm (negative int), - "capabilities": security features supported by the network (string) - } - + SIM card info as a dict, such as {‘SIM_operator’: 310260, + ‘SIM_operator_name’: ‘’, ‘SIM_country_code’: ‘us’, ‘SIM_state’: + ‘ready’}. + """ - sensorlib.request_data(sensor_socket, 'wifiStartScan', []) - wifi_data = sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []) + SIM_state = sensorlib.request_data(sensor_socket, 'getSimState', []) - # we do not need to stop scan (it stops itself after scan is done) - # convert unicode format to ASCII - return unicode_scrubber.scrub(wifi_data) + if SIM_state == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + SIM_operator = sensorlib.request_data(sensor_socket, + 'getSimOperator', []) + SIM_operator_name = sensorlib.request_data(sensor_socket, + 'getSimOperatorName', []) + SIM_country_code = sensorlib.request_data(sensor_socket, + 'getSimCountryIso', []) -################################################## -############## battery interface ################ -################################################## + SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, + 'SIM_operator_name': SIM_operator_name, + 'SIM_country_code': SIM_country_code} + return unicode_scrubber.scrub(SIM_info) -def get_battery_info(): + +def get_phone_info(): """ - Get battery data from a devices. Calls sensorlib.request_data(sensor_socket, - 'readBatteryData', []). The battery information is returned as a dict. + Get phone info from a devices. Calls sensorlib.request_data( + sensor_socket, 'readPhoneState'/'getPhoneType'/'getNetworkType', + []). The phone information, current phone state, phone type, + network type, is returned as a dict. None - BatteryNotFoundException (descends from RepyException) when no battery - is found on the device. + None. - When BatteryNotFoundException is raised, the user of this method cannot - get any battery information. + None. - Battery information lookup. + Phone information lookup. - Battery info as a dict, such as {'status': 3, 'temperature': 257, 'level': - 99, 'battery_present': True, 'plugged': 2, 'health': 2, 'voltage': - 4186, 'technology': 'Li-ion'}. - Return values for status: 1 - unknown; 2 - charging; 3 - discharging; - 4 - not charging; 5 - full. - Return values for temperature: in tenths of a degree Centigrade. E.g., - 257 is 25.7 celcius. - Return values for level: in percent. - Return values for plugged: -1 - unknown; 0 - unplugged; 1 - power - source is an AC charger; 2 - power source is a USB port. - Return values for health: 1 - unknown; 2 - good; 3 - overheat; 4 - dead; - 5 - over voltage; 6 - unspecified failure. - Return values for voltage: in millivolts. + Phone info as a dict, such as {‘phone_state’: {‘incomingNumber’: + ‘’, ‘state’: ‘idle’}, ‘phone_type’: ‘gsm’, ‘network_type’: 'edge'}. + When no SIM card is available, the phone info dict would be, e.g., + {‘phone_state’: {}, ‘phone_type’: ‘gsm’, ‘network_type’: 'unknown'}. """ + sensorlib.request_data(sensor_socket, 'startTrackingPhoneState', []) - # start battery information lookup - sensorlib.request_data(sensor_socket, 'batteryStartMonitoring', []) - - # if no battery is present, then no battery information can be obtained - if sensorlib.request_data(sensor_socket, 'batteryCheckPresent', []) == False: - sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) - raise BatteryNotFoundException - - battery_info = sensorlib.request_data(sensor_socket, 'readBatteryData', []) - sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) - - return unicode_scrubber.scrub(battery_info) - + phone_state = sensorlib.request_data(sensor_socket, + 'readPhoneState', []) + phone_type = sensorlib.request_data(sensor_socket, + 'getPhoneType', []) + network_type = sensorlib.request_data(sensor_socket, + 'getNetworkType', []) + sensorlib.request_data(sensor_socket, 'stopTrackingPhoneState', []) + + phone_info = {'phone_state': phone_state, 'phone_type': phone_type, + 'network_type': network_type} + return unicode_scrubber.scrub(phone_info) -################################################## -############## bluetooth interface ############## -################################################## -def get_bluetooth_info(): +def get_cellular_signal_strengths(): """ - Get bluetooth data from a devices. Calls sensorlib.request_data(sensor_socket, - 'checkBluetoothState'/'bluetoothGetScanMode'/'bluetoothGetLocalName', []). - The bluetooth information is returned as a dict. + Get the current signal strengths, in dictionary of gsm_signal_strength. + Calls sensorlib.request_data(sensor_socket, 'readSignalStrengths', []). None @@ -371,275 +365,280 @@ def get_bluetooth_info(): None. - When bluetooth is not enabled, the user of this method cannot get any - bluetooth information. + None. - Bluetooth information lookup. + Current signal strengths lookup. - Bluetooth info as a dict, such as {'state': True, 'scan_mode': 3, - 'local_name': 'GT-P1000'}. - Return values for scan_mode: -1 - when Bluetooth is disabled; - 0 - if non discoverable and non connectable; 1 - connectable - non discoverable; 3 - connectable and discoverable. - + Signal strengths info as a dict, such as {"gsm_signal_strength": + 8, "evdo_ecio": -1, "gsm_bit_error_rate": -1, "cdma_ecio": -1, + "cdma_dbm": -1, "evdo_dbm": -1}. """ - state = sensorlib.request_data(sensor_socket, 'checkBluetoothState', []) - scan_mode = sensorlib.request_data(sensor_socket, 'bluetoothGetScanMode', []) - local_name = sensorlib.request_data(sensor_socket, 'bluetoothGetLocalName', []) - - bluetooth_info = {'state': state, 'scan_mode': scan_mode, 'local_name': local_name} - return unicode_scrubber.scrub(bluetooth_info) + sensorlib.request_data(sensor_socket, 'startTrackingSignalStrengths', []) + cellular_signal_strengths = sensorlib.request_data(sensor_socket, + 'readSignalStrengths', []) + sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) + return unicode_scrubber.scrub(cellular_signal_strengths) ################################################## -############## cellular interface ############### +############## location interface ############### ################################################## -def is_roaming(): +def get_location(): """ - Return if a phone is roaming (True/False). Calls sensorlib.request_data( - sensor_socket, 'checkNetworkRoaming', []). + Get original location data from GPS or network or passive. Calls + sensorlib.request_data(sensor_socket, 'readLocation', []). The location + information is returned as a dict, which is converted to ASCII + using unicode_scrubber. None - SIMNotFoundException. + LocationNotFoundException (descends from RepyException) when no location + information is found. - When no SIM card is found, no cellular information can be obtained. + When LocationNotFoundException is raised, the user of this method needs + to try several times. If this still fails, then should try + get_lastknown_location(). - Lookup if phone is roaming. + GPS or network location lookup. - A boolean vaiable indicating if the phone is roaming. + location as a dict, such as {'bearing': 0, 'altitude': 0, + 'time': x, 'longitude': x, 'provider': 'network', 'latitude': x, + 'speed': 0, 'accuracy': x}. + """ - if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': - # when no SIM card is found on the device, cellular information is - # not meaningful - raise SIMNotFoundException + # start the locating process + sensorlib.request_data(sensor_socket, 'startLocating', []) - return sensorlib.request_data(sensor_socket, 'checkNetworkRoaming', []) + # try to read current location + # note: readLocation call can timeout, or not responsive + location_data = sensorlib.request_data(sensor_socket, 'readLocation', []) + # stop the locating process + sensorlib.request_data(sensor_socket, 'stopLocating', []) + if not location_data: + raise LocationNotFoundException + assert len(location_data.keys()) == 1 # should return at only one provider -def get_cellular_provider_info(): + # take the first key (because only one provider) + provider = location_data.keys()[0] + location = location_data[provider] + + # convert unicode format (u'longitude') to ASCII (longitude) + # because Repy does not allow Unicode + location = unicode_scrubber.scrub(location) + return location + + +def get_lastknown_location(): """ - Get cellular provider info from a devices. Calls sensorlib.request_data( - sensor_socket, 'getNetworkOperator'/'getNetworkOperatorName', []). The - cellular network information, current cellular operator code (MNC+MCC), - and operator name, is returned as a dict. + Get original _last-known_ location data from GPS/network/passive. Calls + sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []). The + location information is returned as a dict, which is converted to ASCII + using unicode_scrubber. - None + None - SIMNotFoundException. + LocationNotFoundException (descends from RepyException) when the returned + location information is {'passive': None, 'network': None, 'gps': None}. - When no SIM card is found, no cellular provider info can be obtained. + None. - Cellular network provider information lookup. + Lookup cached location information on the device. - Cellular provider info as a dict, such as {‘network_operator’: 310260, - ‘network_operator_name’: ‘T-Mobile’}. - + location as a dict with three keys: passive, network, and gps. Each key + value is a dict in the same format as the value returned by get_location(). + For example, {'passive': {'bearing': 0, 'altitude': 0, 'time': x, + 'longitude': x, 'provider': 'network', 'latitude': s, 'speed': 0, + 'accuracy': x}, 'network': {'bearing': 0, 'altitude': 0, 'time': x, + 'longitude': x, 'provider': 'network', 'latitude': x, 'speed': 0, + 'accuracy': x}, 'gps': None} + """ - if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': - # when no SIM card is found on the device, cellular information is - # not meaningful - raise SIMNotFoundException + # start the locating process + sensorlib.request_data(sensor_socket, 'startLocating', []) - network_operator = sensorlib.request_data(sensor_socket, - 'getNetworkOperator', []) - network_operator_name = sensorlib.request_data(sensor_socket, - 'getNetworkOperatorName', []) + # try to read the cached location + location_data = sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []) - cellular_network_info = {'network_operator': network_operator, - 'network_operator_name': network_operator_name} - return unicode_scrubber.scrub(cellular_network_info) + # stop the locating process + sensorlib.request_data(sensor_socket, 'stopLocating', []) + assert len(location_data.keys()) >= 1 # should return at least one provider + + # check if location_data is {'passive': None, 'network': None, 'gps': None} + for i in range(len(location_data.keys())): + provider = location_data.keys()[i] + location = location_data[provider] + if location != None: + break + else: + raise LocationNotFoundException + # convert unicode format (u'longitude') to ASCII (longitude) + location = unicode_scrubber.scrub(location_data) + return location -def get_cell_info(): +def get_geolocation(latitude, longitude, max_results): """ - Get cellular network info from a devices. Calls sensorlib.request_data( - sensor_socket, 'getCellLocation'/'getNeighboringCellInfo'/'getNetworkType', - []). The cellular network information, current cellular cell ID, - neighboring cells, is returned as a dict. + Obtain a list of addresses for the given latitude and longitude. Calls + sensorlib.request_data(sensor_socket, 'geocode', [latitude, longitude, + max_results]). The addresses information is returned as a dict, which + is converted to ASCII using unicode_scrubber. - None + latitude (float): latitude of a location; + longitude (float): longitude of a location; + max_results (Integer): maximum number of results (normally =1). - SIMNotFoundException. + None. - When no SIM card is found, no cellular information can be obtained. + None. - Cellular network information lookup. + Geolocation lookup. - Cellular info as a dict, such as {‘cellID’: {‘lac’: 32115, ‘cid’: 26742}, - ‘neighboring_cell’: [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, - {‘rssi’: 5, ‘cid’: 40153}]}. - + Geolocation (address) as a list, such as [{'thoroughfare': 'Some + Street', 'locality': u'Some Town', 'sub_admin_area': 'Some Borough', + 'admin_area': 'Some City', 'feature_name': 'House Numbers', + 'country_code': 'GB', 'country_name': 'United Kingdom', + 'postal_code': 'ST1 1'}] . + """ - if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': - # when no SIM card is found on the device, cellular information is - # not meaningful - raise SIMNotFoundException - - # get details about cell ID, e.g., {‘lac’: 32115, ‘cid’: 26742} - # cid = Cell ID, lac = location area code - cellID = sensorlib.request_data(sensor_socket, - 'getCellLocation', []) + address = sensorlib.request_data(sensor_socket, 'geocode', + [latitude, longitude, max_results]) + return unicode_scrubber.scrub(address) - # get information about neighboring cells in a list, e.g., - # [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, - # {‘rssi’: 5, ‘cid’: 40153}] - neighboring_cell = sensorlib.request_data(sensor_socket, - 'getNeighboringCellInfo', []) + - cellular_info = {'cellID': cellID, 'neighboring_cell': neighboring_cell} - return unicode_scrubber.scrub(cellular_info) +################################################## +############### media interface ################# +################################################## -def get_SIM_info(): +def microphone_record(filename, duration): """ - Get SIM card info from a devices. Calls sensorlib.request_data( - sensor_socket, 'getSimState'/'getSimOperator'/'getSimOperatorName' - /'getSimCountryIso', []). The SIM card information, current SIM - card state, SIM card operator, SIM card operator name, SIM card - country code, is returned as a dict. + Records audio from the microphone and saves it as filename. Calls sensorlib. + request_data(sensor_socket, 'recorderStartMicrophone', [filename]). - None + filename (string): the audio file name that will be saved as (e.g., record.mp4); + duration (Integer): the duration to record the audio. - SIMNotFoundException. + None. - When no SIM card is found, no information can be obtained. + None. - SIM card information lookup. + Record audio and save as a file on the device. - SIM card info as a dict, such as {‘SIM_operator’: 310260, - ‘SIM_operator_name’: ‘’, ‘SIM_country_code’: ‘us’, ‘SIM_state’: - ‘ready’}. - + None. """ - SIM_state = sensorlib.request_data(sensor_socket, 'getSimState', []) + filepath = '/mnt/sdcard/Android/data/com.sensibility_testbed/files/sl4a/seattle/seattle_repy/v1/' + targetpath = filepath + filename - if SIM_state == 'absent': - # when no SIM card is found on the device, cellular information is - # not meaningful - raise SIMNotFoundException + sensorlib.request_data(sensor_socket, 'recorderStartMicrophone', [targetpath]) + sleep(duration) + + sensorlib.request_data(sensor_socket, 'recorderStop', []) - SIM_operator = sensorlib.request_data(sensor_socket, - 'getSimOperator', []) - SIM_operator_name = sensorlib.request_data(sensor_socket, - 'getSimOperatorName', []) - SIM_country_code = sensorlib.request_data(sensor_socket, - 'getSimCountryIso', []) - SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, - 'SIM_operator_name': SIM_operator_name, - 'SIM_country_code': SIM_country_code} - return unicode_scrubber.scrub(SIM_info) -def get_phone_info(): +def is_media_playing(): """ - Get phone info from a devices. Calls sensorlib.request_data( - sensor_socket, 'readPhoneState'/'getPhoneType'/'getNetworkType', - []). The phone information, current phone state, phone type, - network type, is returned as a dict. + Return if media file is playing. (True/False). Calls sensorlib. + request_data(sensor_socket, 'mediaIsPlaying', []) - None + None. - None. + None. - None. + None. - Phone information lookup. + Lookup if media file is playing. - Phone info as a dict, such as {‘phone_state’: {‘incomingNumber’: - ‘’, ‘state’: ‘idle’}, ‘phone_type’: ‘gsm’, ‘network_type’: 'edge'}. - When no SIM card is available, the phone info dict would be, e.g., - {‘phone_state’: {}, ‘phone_type’: ‘gsm’, ‘network_type’: 'unknown'}. - + A boolean vaiable indicating if a media file is playing on the device. + """ - sensorlib.request_data(sensor_socket, 'startTrackingPhoneState', []) - phone_state = sensorlib.request_data(sensor_socket, - 'readPhoneState', []) - phone_type = sensorlib.request_data(sensor_socket, - 'getPhoneType', []) - network_type = sensorlib.request_data(sensor_socket, - 'getNetworkType', []) + # True or False + return sensorlib.request_data(sensor_socket, 'mediaIsPlaying', []) - sensorlib.request_data(sensor_socket, 'stopTrackingPhoneState', []) - - phone_info = {'phone_state': phone_state, 'phone_type': phone_type, - 'network_type': network_type} - return unicode_scrubber.scrub(phone_info) -def get_cellular_signal_strengths(): +def get_media_play_info(): """ - Get the current signal strengths, in dictionary of gsm_signal_strength. - Calls sensorlib.request_data(sensor_socket, 'readSignalStrengths', []). + Return information on current media. Calls sensorlib.request_data( + sensor_socket, 'mediaPlayInfo', []) - None + None. - None. + None. - None. + None. - Current signal strengths lookup. + Lookup media play information. - Signal strengths info as a dict, such as {"gsm_signal_strength": - 8, "evdo_ecio": -1, "gsm_bit_error_rate": -1, "cdma_ecio": -1, - "cdma_dbm": -1, "evdo_dbm": -1}. + media_play_info as a dict. + + If no media file is loaded, the result is {'loaded': False, 'tag': 'default'}. + + If there is a media file being played, the result is {'url': filepath, + 'looping': False, 'tag': 'default', 'loaded': True, 'duration': 17100, + 'position': 100, 'isplaying': True}. + + If the media file is finished playing, the result is {'url': filepath, + 'looping': False, 'tag': 'default', 'loaded': True, 'duration': 17100, + 'position': 17020, 'isplaying': False} + """ - sensorlib.request_data(sensor_socket, 'startTrackingSignalStrengths', []) - cellular_signal_strengths = sensorlib.request_data(sensor_socket, - 'readSignalStrengths', []) - sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) + # True or False + media_play_info = sensorlib.request_data(sensor_socket, 'mediaPlayInfo', []) + return unicode_scrubber.scrub(media_play_info) - return unicode_scrubber.scrub(cellular_signal_strengths) ################################################## @@ -1023,4 +1022,115 @@ def get_orientation(): return sensorlib.request_data(sensor_socket, 'sensorsReadOrientation', []) +<<<<<<< HEAD +======= + + + +################################################## +############## WiFi interface ################### +################################################## + +def is_wifi_enabled(): + """ + + Return if WiFi is enabled on this device (True/False). + + + None + + + None. + + + None. + + + Lookup if WiFi is enabled on the device. + + + A boolean vaiable indicating if WiFi is enabled on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'checkWifiState', []) + + +def get_wifi_connection_info(): + """ + + Return information about the WiFi network currently connected to. Calls + sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []). + + + None + + + None. +>>>>>>> SensibilityTestbed/master + + None. + + + Lookup WiFi connection information on the device. + + + wifi_conn as a dict, and is returned as a dict of this format: + { + "ssid": network SSID (string), + "bssid": network BSSID, i.e. MAC address (string), + "rssi": received signal strength in dBm (negative int), + "supplicant_state": current WPA association state (string), + "link_speed": link speed in MBps (int), + "mac_address": this device's WiFi interface MAC (string), + XXX "ip_address": this device's IP address (XXX int, byte quadruples reversed!), + XXX "network_id": XXX (int), + "hidden_ssid": True if the SSID is not broadcast (bool) + } + """ + + wifi_conn = sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []) + + # convert unicode format to ASCII + return unicode_scrubber.scrub(wifi_conn) + + +def do_wifi_scan(): + """ + + Return WiFi connection info on this device. Calls + sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []). + + + None + + + None. + + + None. + + + Scan the WiFi network from the device. + + + WiFi scan results wifi_data as a HUGE dict of this format, + with one dict for each network found: + { + "ssid": network SSID (string), + "bssid": network BSSID, i.e. MAC address (string), + "frequency": frequency in MHz (int), + "level": received signal strength in dBm (negative int), + "capabilities": security features supported by the network (string) + } + + """ + + sensorlib.request_data(sensor_socket, 'wifiStartScan', []) + wifi_data = sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []) + + # we do not need to stop scan (it stops itself after scan is done) + # convert unicode format to ASCII + return unicode_scrubber.scrub(wifi_data) diff --git a/sensor_layer.r2py b/sensor_layer.r2py index c9218c1..2b18970 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -8,130 +8,135 @@ start dylink.r2py encasementlib.r2py sensor_layer.r2py [any blur layers] \ getsensor = dy_import_module("getsensor.r2py") -CHILD_CONTEXT_DEF["get_location"] = { + +CHILD_CONTEXT_DEF["get_battery_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_location, + "target": getsensor.get_battery_info, } -CHILD_CONTEXT_DEF["get_lastknown_location"] = { +CHILD_CONTEXT_DEF["get_bluetooth_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_lastknown_location, + "target": getsensor.get_bluetooth_info, } -CHILD_CONTEXT_DEF["get_geolocation"] = { +CHILD_CONTEXT_DEF["is_roaming"] = { "type": "func", - "args": (float, float, int), - "return": list, + "args": None, + "return": bool, "exceptions": "any", - "target": getsensor.get_geolocation, + "target": getsensor.is_roaming, } -CHILD_CONTEXT_DEF["is_wifi_enabled"] = { + +CHILD_CONTEXT_DEF["get_cellular_provider_info"] = { "type": "func", "args": None, - "return": bool, + "return": dict, "exceptions": "any", - "target": getsensor.is_wifi_enabled, + "target": getsensor.get_cellular_provider_info, } -CHILD_CONTEXT_DEF["get_wifi_connection_info"] = { +CHILD_CONTEXT_DEF["get_cell_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_wifi_connection_info, + "target": getsensor.get_cell_info, } -CHILD_CONTEXT_DEF["do_wifi_scan"] = { +CHILD_CONTEXT_DEF["get_SIM_info"] = { "type": "func", "args": None, - "return": list, + "return": dict, "exceptions": "any", - "target": getsensor.do_wifi_scan, + "target": getsensor.get_SIM_info, } -CHILD_CONTEXT_DEF["get_battery_info"] = { +CHILD_CONTEXT_DEF["get_phone_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_battery_info, + "target": getsensor.get_phone_info, } -CHILD_CONTEXT_DEF["get_bluetooth_info"] = { +CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_bluetooth_info, + "target": getsensor.get_cellular_signal_strengths, } -CHILD_CONTEXT_DEF["is_roaming"] = { + +CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, - "return": bool, + "return": dict, "exceptions": "any", - "target": getsensor.is_roaming, + "target": getsensor.get_location, } - -CHILD_CONTEXT_DEF["get_cellular_provider_info"] = { +CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_cellular_provider_info, + "target": getsensor.get_lastknown_location, } -CHILD_CONTEXT_DEF["get_cell_info"] = { +CHILD_CONTEXT_DEF["get_geolocation"] = { "type": "func", - "args": None, - "return": dict, + "args": (float, float, int), + "return": list, "exceptions": "any", - "target": getsensor.get_cell_info, + "target": getsensor.get_geolocation, } -CHILD_CONTEXT_DEF["get_SIM_info"] = { + +CHILD_CONTEXT_DEF["microphone_record"] = { "type": "func", - "args": None, - "return": dict, + "args": (string, int), + "return": None, "exceptions": "any", - "target": getsensor.get_SIM_info, + "target": getsensor.microphone_record, } -CHILD_CONTEXT_DEF["get_phone_info"] = { + +CHILD_CONTEXT_DEF["is_media_playing"] = { "type": "func", "args": None, - "return": dict, + "return": bool, "exceptions": "any", - "target": getsensor.get_phone_info, + "target": getsensor.is_media_playing, } -CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { + +CHILD_CONTEXT_DEF["get_media_play_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_cellular_signal_strengths, + "target": getsensor.get_media_play_info, } @@ -245,5 +250,32 @@ CHILD_CONTEXT_DEF["get_orientation"] = { } + +CHILD_CONTEXT_DEF["is_wifi_enabled"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.is_wifi_enabled, +} + + +CHILD_CONTEXT_DEF["get_wifi_connection_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_wifi_connection_info, +} + + +CHILD_CONTEXT_DEF["do_wifi_scan"] = { + "type": "func", + "args": None, + "return": list, + "exceptions": "any", + "target": getsensor.do_wifi_scan, +} + secure_dispatch_module() From bcb082871c23c78e623f1dfa05b960cf08cb7d78 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 28 Jul 2015 13:17:46 +0530 Subject: [PATCH 25/60] deleted errors due to previous commit --- getsensor.r2py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index dcef31b..2eb6891 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -1022,11 +1022,6 @@ def get_orientation(): return sensorlib.request_data(sensor_socket, 'sensorsReadOrientation', []) -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> SensibilityTestbed/master @@ -1071,10 +1066,6 @@ def get_wifi_connection_info(): None. -<<<<<<< HEAD ->>>>>>> SensibilityTestbed/master -======= ->>>>>>> SensibilityTestbed/master None. From 59aba8581ffacb1010d76e07c02632bc15eb2adb Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 28 Jul 2015 14:40:05 +0530 Subject: [PATCH 26/60] changes based on media interface test --- getsensor.r2py | 2 +- sensor_layer.r2py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 2eb6891..d4df0a1 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -567,7 +567,7 @@ def microphone_record(filename, duration): targetpath = filepath + filename sensorlib.request_data(sensor_socket, 'recorderStartMicrophone', [targetpath]) - sleep(duration) + sleep(duration+1) sensorlib.request_data(sensor_socket, 'recorderStop', []) diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 2b18970..dd027b8 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -113,7 +113,7 @@ CHILD_CONTEXT_DEF["get_geolocation"] = { CHILD_CONTEXT_DEF["microphone_record"] = { "type": "func", - "args": (string, int), + "args": (str, int), "return": None, "exceptions": "any", "target": getsensor.microphone_record, From bad339a8ab9bfd3b3a5df9cb650511bead5412b2 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 17 Aug 2015 19:38:55 -0400 Subject: [PATCH 27/60] removed exception checking --- blur_location2country.r2py | 44 ++++++++++++++++++-------------------- blur_location2state.r2py | 44 ++++++++++++++++++-------------------- blur_location2zipcode.r2py | 44 ++++++++++++++++++-------------------- blur_location_round.r2py | 26 +++++++++++----------- 4 files changed, 75 insertions(+), 83 deletions(-) diff --git a/blur_location2country.r2py b/blur_location2country.r2py index 4c8a7a1..8f4dbc5 100644 --- a/blur_location2country.r2py +++ b/blur_location2country.r2py @@ -116,12 +116,11 @@ def get_country_location(): """ location_data = get_location() - if location_data is not None: - closest_country = find_closest_country(location_data["latitude"], - location_data["longitude"]) + closest_country = find_closest_country(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_country["latitude"] - location_data["longitude"] = closest_country["longitude"] + location_data["latitude"] = closest_country["latitude"] + location_data["longitude"] = closest_country["longitude"] return location_data @@ -136,28 +135,27 @@ def get_country_lastknown_location(): """ location_data = get_lastknown_location() - if location_data is not None: - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_country = find_closest_country(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_country = find_closest_country(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_country["latitude"] - location_data[location_provider]["longitude"] = closest_country["longitude"] + location_data[location_provider]["latitude"] = closest_country["latitude"] + location_data[location_provider]["longitude"] = closest_country["longitude"] return location_data diff --git a/blur_location2state.r2py b/blur_location2state.r2py index c4790a5..e853160 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -128,12 +128,11 @@ def get_state_location(): """ location_data = get_location() - if location_data is not None: - closest_state = find_closest_state(location_data["latitude"], - location_data["longitude"]) + closest_state = find_closest_state(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_state["latitude"] - location_data["longitude"] = closest_state["longitude"] + location_data["latitude"] = closest_state["latitude"] + location_data["longitude"] = closest_state["longitude"] return location_data @@ -148,28 +147,27 @@ def get_state_lastknown_location(): """ location_data = get_lastknown_location() - if location_data is not None: - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_state = find_closest_state(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_state = find_closest_state(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_state["latitude"] - location_data[location_provider]["longitude"] = closest_state["longitude"] + location_data[location_provider]["latitude"] = closest_state["latitude"] + location_data[location_provider]["longitude"] = closest_state["longitude"] return location_data diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index 9243eeb..62c3b13 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -97,12 +97,11 @@ def get_zipcode_location(): """ location_data = get_location() - if location_data is not None: - closest_zipcode = find_closest_zipcode(location_data["latitude"], - location_data["longitude"]) + closest_zipcode = find_closest_zipcode(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = closest_zipcode["latitude"] - location_data["longitude"] = closest_zipcode["longitude"] + location_data["latitude"] = closest_zipcode["latitude"] + location_data["longitude"] = closest_zipcode["longitude"] return location_data @@ -117,28 +116,27 @@ def get_zipcode_lastknown_location(): """ location_data = get_lastknown_location() - if location_data is not None: - # Blur the coordinates of the first non-empty location data. - for location_provider, provider_location_data in location_data.items(): - # Skip this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Blur the coordinates of the first non-empty location data. + for location_provider, provider_location_data in location_data.items(): + # Skip this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], - provider_location_data["longitude"]) + closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], + provider_location_data["longitude"]) - break + break - # Copy the blurred coordinates into all providers' location data. - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = closest_zipcode["latitude"] - location_data[location_provider]["longitude"] = closest_zipcode["longitude"] + location_data[location_provider]["latitude"] = closest_zipcode["latitude"] + location_data[location_provider]["longitude"] = closest_zipcode["longitude"] return location_data diff --git a/blur_location_round.r2py b/blur_location_round.r2py index 2fca787..53282c5 100644 --- a/blur_location_round.r2py +++ b/blur_location_round.r2py @@ -20,9 +20,8 @@ def blur_location_round(): """ location_data = get_location() - if location_data is not None: - location_data["latitude"] = round(float(location_data["latitude"]), 1) - location_data["longitude"] = round(float(location_data["longitude"]), 1) + location_data["latitude"] = round(float(location_data["latitude"]), 1) + location_data["longitude"] = round(float(location_data["longitude"]), 1) return location_data @@ -37,17 +36,16 @@ def blur_lastknown_location_round(): """ location_data = get_lastknown_location() - if location_data is not None: - for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous - # location. - if provider_location_data is None: - continue - - location_data[location_provider]["latitude"] = \ - round(float(provider_location_data["latitude"]), 1) - location_data[location_provider]["longitude"] = \ - round(float(provider_location_data["longitude"]), 1) + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + location_data[location_provider]["latitude"] = \ + round(float(provider_location_data["latitude"]), 1) + location_data[location_provider]["longitude"] = \ + round(float(provider_location_data["longitude"]), 1) return location_data From 788efdb3f5cead123e5ca45b797ac0b5f8397b6d Mon Sep 17 00:00:00 2001 From: aditup Date: Thu, 20 Aug 2015 12:53:29 -0400 Subject: [PATCH 28/60] Removed +1 in sleep() --- getsensor.r2py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getsensor.r2py b/getsensor.r2py index 18f4341..9c48e62 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -567,7 +567,7 @@ def microphone_record(filename, duration): targetpath = filepath + filename sensorlib.request_data(sensor_socket, 'recorderStartMicrophone', [targetpath]) - sleep(duration+1) + sleep(duration) sensorlib.request_data(sensor_socket, 'recorderStop', []) From ac1a6fe83fec860f64dfe3a78416ed22b313ca12 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 16 Jun 2015 11:03:37 -0400 Subject: [PATCH 29/60] change based on code review --- blur_location2city.r2py | 269 ++++++++++++++++++++++++---------------- 1 file changed, 162 insertions(+), 107 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index 30a8bd2..fd940de 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -1,144 +1,198 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the coordinates, received +from the location sensors of an Android device, to the geographic center of +approximately the nearest city. + +The blurring is done using a DB lookup method. The DB contains a list of +cities, and their geodata (lat, lon, country code, state code), divided +by their coordinates. The DB is is available at: +http://sensibilityclearinghouse.poly.edu/data/quad/ + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2city.r2py user-program.r2py +""" + + + httpretrieve = dy_import_module("httpretrieve.r2py") math = dy_import_module("math.r2py") -librepyfile = dy_import_module("librepyfile.r2py") -statefilename = "states.txt" # Database of states -countryfilename = "countries.txt" # Database of countries -# Downloads the required file from the server def get_file_from_server(filename): + """ + Downloads the required file from the DB server, if it has not already + been downloaded. - if filename not in listfiles(): # In case it already exists - if filename not in [statefilename, countryfilename]: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename httpretrieve.httpretrieve_save_file(url, filename) -# Returns a dictionary containing information about the point closest to -# a given lat/lng pair, from the database. -# {"city": closest_city, "statecode": closest_state_code, "countrycode": -# closest_country_code, "coordinates": closest_point} -def find_closest_point(lat, lng): - - # Find the database file with coordinates closest to the given lat/lng pair - filename = get_filename(lat, lng) - # Get the list of coordinates from that file - listofpoints = load_lat_lng_from_file(filename) - min_dist = 9999 - point1 = (lat, lng) +def find_closest_city(lat, lon): + """ + Searches the DB and returns a dict containing the geodata of the city + that is approximately closest to a given lat/lon pair in the format: + { + "city_name": city name (string), + "state_code": 2-digit code representing the state to which the city + belongs (string), + "country_code": 2-letter ISO-3166 code representing the country to + which the city belongs (string), + "coordinates": tuple containing the lat/lon pair representing the + geographic center of the city (float, float) + } + + Note: We're looking for the closest lat/lon pair within the same + quadrant as the given lat/lon pair. There might be closer ones in + other quadrants. Thus, the "closest city" is only an approximation. + + """ + # Determine which file to download from the DB. + filename = get_database_filename(lat, lon) + + # Load all the cities and their geodata from the file. + city_dict = load_city_geodata(filename) + + # Set the minimum squared difference between two pairs of coordinates + # to an arbitrarily large number. + # XXX Should "large" be defined? + min_diff = 9999 + + for city_name, city_geodata in city_dict.items(): + city_lat, city_lon = city_geodata["coordinates"] + diff = find_squared_difference((lat, lon), (city_lat, city_lon)) + if diff < min_diff: + min_diff = diff + closest_city_coordinates = city_geodata["coordinates"] + closest_city_name = city_name + closest_city_state_code = city_geodata["state_code"] + closest_city_country_code = city_geodata["country_code"] + + closest_city_geodata = {"city_name": closest_city_name, + "coordinates": closest_city_coordinates, + "state_code": closest_city_state_code, + "country_code": closest_city_country_code + } + + return closest_city_geodata + + + +def get_database_filename(lat, lon): + """ + Returns the filename in the DB with coordinates in the same quadrant + as the given lat/lon pair. + + """ + # Get ceiling as x/y index. + x = int(math.math_ceil(lat)) + y = int(math.math_ceil(lon)) + filename = str(x) + '_' + str(y) + '.txt' + return filename - for city in listofpoints.keys(): - data = listofpoints[city] - point2 = (data[0], data[1]) - dist = find_distance(point1, point2) - if dist < min_dist: - min_dist = dist - closest_point = point2 - closest_city = city - closest_state_code = data[3] - closest_country_code = data[2] - closest = {"city": closest_city, "statecode": closest_state_code, "countrycode": closest_country_code, "coordinates": closest_point} - return closest +def load_city_geodata(filename): + """ + Returns a dict containing all the cities in the given file, + along with their corresponding geodata in the format: + { + city1: {"coordinates": (lat, lon), "country_code": country_code, + "state_code": state_code}, + city2: {"coordinates": (lat, lon), "country_code": country_code, + "state_code": state_code}, + ... + } + """ + get_file_from_server(filename) + city_dict = {} + city_geodata_fileobj = openfile(filename, False) + city_geodata_file = city_geodata_fileobj.reat(None, 0).split("\n") -# Returns the filename in the database with coordinates closest to the given lat/lng pair -def get_filename(lat, lng): + for line in city_geodata_file: + # Ignore the empty line at the end of the file + if line == "": + continue + city_geodata_record = line.split("\t") + city_name = city_geodata_record[0] + lat = float(city_geodata_record[1]) + lon = float(city_geodata_record[2]) + city_dict[city_name] = {"coordinates": (lat, lon), + "country_code": city_geodata_record[3], + "state_code": city_geodata_record[4] + } + city_geodata_fileobj.close() + return city_dict - # get ceiling as x/y index - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lng)) - filename = str(x) + '_' + str(y) + '.txt' - return filename -# Returns a dictionary containing all the cities in the given file, along with -# their corresponding data -# {city1: [lat, lng, country_code, state_code], city2: [lat, lng, country_code, -# state_code], ...} -def load_lat_lng_from_file(filename): +def find_squared_difference(p1, p2): + """ + Returns the squared difference between two pairs of coordinates (p1 + and p2). - get_file_from_server(filename) - listofpoints = {} - fileobj = librepyfile.open(filename, "r") - - while True: - try: - line = fileobj.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - city_name = line[0] - lat = line[1] - lng = line[2] - country_code = line[3] - state_code = line[4] - listofpoints[city_name] = [lat, lng, country_code, state_code] - fileobj.close() - return listofpoints - - -# Returns the distance between two lat/lng points -def find_distance(p1, p2): - - (lat1, lng1) = p1 - (lat2, lng2) = p2 - lat2 = float(lat2) - lng2 = float(lng2) - lat_diff = (lat1-lat2) * (lat1-lat2) - lng_diff = (lng1-lng2) * (lng1-lng2) - # return squared distance - return lat_diff + lng_diff - - -# To replace get_location() -def get_city_location(): + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff - try: - location_data = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - latitude = location_data["latitude"] - longitude = location_data["longitude"] - closest = find_closest_point(latitude, longitude) +def get_city_location(): + """ + Security layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the nearest city. - location_data["latitude"] = closest["coordinates"][0] - location_data["longitude"] = closest["coordinates"][1] + """ + location_data = get_location() - return location_data + closest_city = find_closest_city(location_data["latitude"], + location_data["longitude"]) + location_data["latitude"], location_data["longitude"] = \ + closest["coordinates"] -# To replace get_lastknown_location() -def get_city_lastknown_location(): + return location_data - try: - location_data = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - # Get the location from the the provider - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - latitude = location["latitude"] - longitude = location["longitude"] - closest = find_closest_point(latitude, longitude) - location_data[provider]["latitude"] = closest["coordinates"][0] - location_data[provider]["longitude"] = closest["coordinates"][1] +def get_city_lastknown_location(): + """ + Security layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the nearest city. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + closest_city = find_closest_city(provider_location_data["latitude"], + provider_location_data["longitude"]) + + location_data[location_provider]["latitude"], \ + location_data[provider]["longitude"] = closest["coordinates"] return location_data + +# Makes a security layer out of what otherwise would be just a plain +# library you could `dy_import` CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -156,4 +210,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { "target": get_city_lastknown_location, } + secure_dispatch_module() \ No newline at end of file From faf8f4f742d40ec7f9f0a13f0cd086d493a9189b Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Fri, 19 Jun 2015 15:46:20 -0700 Subject: [PATCH 30/60] add battery calls --- getsensor.r2py | 57 +++++++++++++++++++++++++++++++++++++++++++++++ sensor_layer.r2py | 10 +++++++++ 2 files changed, 67 insertions(+) diff --git a/getsensor.r2py b/getsensor.r2py index c285cea..f417123 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -20,6 +20,11 @@ sensorlib = dy_import_module("sensorlib.r2py") port = sensorlib.get_connectionport() sensor_socket = sensorlib.getconnection(port) +class BatteryNotFoundException(RepyException): + """This exception gets raised when location sensor returns no results. + """ + pass + class LocationNotFoundException(RepyException): """This exception gets raised when location sensor returns no results. @@ -239,3 +244,55 @@ def do_wifi_scan(): # we do not need to stop scan (it stops itself after scan is done) # convert unicode format to ASCII return unicode_scrubber.scrub(wifi_data) + + +def get_battery_info(): + """ + + Get battery data from a devices. Calls sensorlib.request_data(sensor_socket, + 'readBatteryData', []). The battery information is returned as a dict. + + + None + + + BatteryNotFoundException (descends from RepyException) when no battery + is found on the device. + + + When BatteryNotFoundException is raised, the user of this method cannot + get any battery information. + + + Battery information lookup. + + + location as a dict, such as {u'status': 3, u'temperature': 257, u'level': + 99, u'battery_present': True, u'plugged': 2, u'health': 2, u'voltage': + 4186, u'technology': u'Li-ion'}. + Return values for status: 1 - unknown; 2 - charging; 3 - discharging; + 4 - not charging; 5 - full. + Return values for temperature: in tenths of a degree Centigrade. E.g., + 257 is 25.7 celcius. + Return values for level: in percent. + Return values for plugged: -1 - unknown; 0 - unplugged; 1 - power + source is an AC charger; 2 - power source is a USB port. + Return values for health: 1 - unknown; 2 - good; 3 - overheat; 4 - dead; + 5 - over voltage; 6 - unspecified failure. + Return values for voltage: in millivolts. + + """ + + # start battery information lookup + sensorlib.request_data(sensor_socket, 'batteryStartMonitoring', []) + + # if no battery is present, then no battery information can be obtained + if sensorlib.request_data(sensor_socket, 'batteryCheckPresent', []) == False: + sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) + raise BatteryNotFoundException + + battery_info = sensorlib.request_data(sensor_socket, 'readBatteryData', []) + sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) + + return battery_info + diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 98f6846..daea434 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -52,5 +52,15 @@ CHILD_CONTEXT_DEF["do_wifi_scan"] = { "target": getsensor.do_wifi_scan, } + +CHILD_CONTEXT_DEF["get_battery_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_battery_info, +} + + secure_dispatch_module() From ec5052f1df04447970e452b1e67a9ac670e73121 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Fri, 19 Jun 2015 20:58:32 -0700 Subject: [PATCH 31/60] fix a typo --- getsensor.r2py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getsensor.r2py b/getsensor.r2py index f417123..3890321 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -267,7 +267,7 @@ def get_battery_info(): Battery information lookup. - location as a dict, such as {u'status': 3, u'temperature': 257, u'level': + Battery info as a dict, such as {u'status': 3, u'temperature': 257, u'level': 99, u'battery_present': True, u'plugged': 2, u'health': 2, u'voltage': 4186, u'technology': u'Li-ion'}. Return values for status: 1 - unknown; 2 - charging; 3 - discharging; From 00c6c1bc2011ca9accf6eb89af54e0cac5bb2bc0 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Sat, 20 Jun 2015 12:26:37 -0700 Subject: [PATCH 32/60] add bluetooth call --- getsensor.r2py | 36 ++++++++++++++++++++++++++++++++++++ sensor_layer.r2py | 9 +++++++++ 2 files changed, 45 insertions(+) diff --git a/getsensor.r2py b/getsensor.r2py index 3890321..6d03733 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -296,3 +296,39 @@ def get_battery_info(): return battery_info + +def get_bluetooth_info(): + """ + + Get bluetooth data from a devices. Calls sensorlib.request_data(sensor_socket, + 'checkBluetoothState'/'bluetoothGetScanMode'/'bluetoothGetLocalName', []). + The bluetooth information is returned as a dict. + + + None + + + None. + + + When bluetooth is not enabled, the user of this method cannot get any + bluetooth information. + + + Bluetooth information lookup. + + + Bluetooth info as a dict, such as {'state': True, 'scan_mode': 3, + 'local_name': 'GT1000'}. + Return values for scan_mode: -1 - when Bluetooth is disabled; + 0 - if non discoverable and non connectable; 1 - connectable + non discoverable; 3 - connectable and discoverable. + + """ + + state = sensorlib.request_data(sensor_socket, 'checkBluetoothState', []) + scan_mode = sensorlib.request_data(sensor_socket, 'bluetoothGetScanMode', []) + local_name = sensorlib.request_data(sensor_socket, 'bluetoothGetLocalName', []) + + bluetooth_info = {'state': state, 'scan_mode': scan_mode, 'local_name': local_name} + return bluetooth_info diff --git a/sensor_layer.r2py b/sensor_layer.r2py index daea434..9f56a64 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -62,5 +62,14 @@ CHILD_CONTEXT_DEF["get_battery_info"] = { } +CHILD_CONTEXT_DEF["get_bluetooth_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_bluetooth_info, +} + + secure_dispatch_module() From 0bb86b76daacab0ba9fef8a401be8c48977a2459 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Sun, 21 Jun 2015 14:07:25 -0700 Subject: [PATCH 33/60] add cellular call --- getsensor.r2py | 275 +++++++++++++++++++++++++++++++++++++++++++++- sensor_layer.r2py | 55 ++++++++++ 2 files changed, 329 insertions(+), 1 deletion(-) diff --git a/getsensor.r2py b/getsensor.r2py index 6d03733..fb9c1fc 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -21,7 +21,7 @@ port = sensorlib.get_connectionport() sensor_socket = sensorlib.getconnection(port) class BatteryNotFoundException(RepyException): - """This exception gets raised when location sensor returns no results. + """This exception gets raised when no battery is found on the device. """ pass @@ -32,6 +32,16 @@ class LocationNotFoundException(RepyException): pass +class SIMNotFoundException(RepyException): + """This exception gets raised when no SIM card is found on the device. + In this case, no cellular information can be found. + """ + pass + +################################################## +############## location interface ############### +################################################## + def get_location(): """ @@ -142,6 +152,11 @@ def get_lastknown_location(): return location + +################################################## +############## WiFi interface ################### +################################################## + def is_wifi_enabled(): """ @@ -246,6 +261,10 @@ def do_wifi_scan(): return unicode_scrubber.scrub(wifi_data) +################################################## +############## battery interface ################ +################################################## + def get_battery_info(): """ @@ -297,6 +316,11 @@ def get_battery_info(): return battery_info + +################################################## +############## bluetooth interface ############## +################################################## + def get_bluetooth_info(): """ @@ -332,3 +356,252 @@ def get_bluetooth_info(): bluetooth_info = {'state': state, 'scan_mode': scan_mode, 'local_name': local_name} return bluetooth_info + + + +################################################## +############## cellular interface ############### +################################################## + +def is_roaming(): + """ + + Return if a phone is roaming (True/False). Calls sensorlib.request_data( + sensor_socket, 'checkNetworkRoaming', []). + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no cellular information can be obtained. + + + Lookup if phone is roaming. + + + A boolean vaiable indicating if the phone is roaming. + """ + + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + return sensorlib.request_data(sensor_socket, 'checkNetworkRoaming', []) + + + +def get_cellular_provider_info(): + """ + + Get cellular provider info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getNetworkOperator'/'getNetworkOperatorName', []). The + cellular network information, current cellular operator code (MNC+MCC), + and operator name, is returned as a dict. + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no cellular provider info can be obtained. + + + Cellular network provider information lookup. + + + Cellular provider info as a dict, such as {‘network_operator’: 310260, + ‘network_operator_name’: ‘T-Mobile’}. + + """ + + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + network_operator = sensorlib.request_data(sensor_socket, + 'getNetworkOperator', []) + network_operator_name = sensorlib.request_data(sensor_socket, + 'getNetworkOperatorName', []) + + cellular_network_info = {'network_operator': network_operator, + 'network_operator_name': network_operator_name} + return cellular_network_info + + + +def get_cell_info(): + """ + + Get cellular network info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getCellLocation'/'getNeighboringCellInfo'/'getNetworkType', + []). The cellular network information, current cellular cell ID, + neighboring cells, is returned as a dict. + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no cellular information can be obtained. + + + Cellular network information lookup. + + + Cellular info as a dict, such as {‘cellID’: {‘lac’: 32115, ‘cid’: 26742}, + ‘neighboring_cell’: [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, + {‘rssi’: 5, ‘cid’: 40153}]}. + + """ + + if sensorlib.request_data(sensor_socket, 'getSimState', []) == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + # get details about cell ID, e.g., {‘lac’: 32115, ‘cid’: 26742} + # cid = Cell ID, lac = location area code + cellID = sensorlib.request_data(sensor_socket, + 'getCellLocation', []) + + # get information about neighboring cells in a list, e.g., + # [{‘rssi’: 11, ‘cid’: 26741}, {‘rssi’: 9, ‘cid’: 40151}, + # {‘rssi’: 5, ‘cid’: 40153}] + neighboring_cell = sensorlib.request_data(sensor_socket, + 'getNeighboringCellInfo', []) + + cellular_info = {'cellID': cellID, 'neighboring_cell': neighboring_cell} + return cellula_info + + +def get_SIM_info(): + """ + + Get SIM card info from a devices. Calls sensorlib.request_data( + sensor_socket, 'getSimState'/'getSimOperator'/'getSimOperatorName' + /'getSimCountryIso', []). The SIM card information, current SIM + card state, SIM card operator, SIM card operator name, SIM card + country code, is returned as a dict. + + + None + + + SIMNotFoundException. + + + When no SIM card is found, no information can be obtained. + + + SIM card information lookup. + + + SIM card info as a dict, such as {‘SIM_operator’: 310260, + ‘SIM_operator_name’: ‘’, ‘SIM_country_code’: ‘us’, ‘SIM_state’: + ‘ready’}. + + """ + + SIM_state = sensorlib.request_data(sensor_socket, 'getSimState', []) + + if SIM_state == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + SIM_operator = sensorlib.request_data(sensor_socket, + 'getSimOperator', []) + SIM_operator_name = sensorlib.request_data(sensor_socket, + 'getSimOperatorName', []) + SIM_country_code = sensorlib.request_data(sensor_socket, + 'getSimCountryIso', []) + + SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, + 'SIM_operator_name': SIM_operator_name, + 'SIM_country_code': SIM_country_code} + return SIM_info + + +def get_phone_info(): + """ + + Get phone info from a devices. Calls sensorlib.request_data( + sensor_socket, 'readPhoneState'/'getPhoneType'/'getNetworkType', + []). The phone information, current phone state, phone type, + network type, is returned as a dict. + + + None + + + None. + + + None. + + + Phone information lookup. + + + Phone info as a dict, such as {‘phone_state’: {‘incomingNumber’: + ‘’, ‘state’: ‘idle’}, ‘phone_type’: ‘gsm’, ‘network_type’: 'edge'}. + When no SIM card is available, the phone info dict would be, e.g., + {‘phone_state’: {}, ‘phone_type’: ‘gsm’, ‘network_type’: 'unknown'}. + + """ + sensorlib.request_data(sensor_socket, 'startTrackingPhoneState', []) + + phone_state = sensorlib.request_data(sensor_socket, + 'readPhoneState', []) + phone_type = sensorlib.request_data(sensor_socket, + 'getPhoneType', []) + network_type = sensorlib.request_data(sensor_socket, + 'getNetworkType', []) + + sensorlib.request_data(sensor_socket, 'stopTrackingPhoneState', []) + + phone_info = {'phone_state': phone_state, 'phone_type': phone_type, + 'network_type': network_type} + return phone_info + + +def get_cellular_signal_strengths{} + """ + + Get the current signal strengths, in dictionary of gsm_signal_strength. + Calls sensorlib.request_data(sensor_socket, 'readSignalStrengths', []). + + + None + + + None. + + + None. + + + Current signal strengths lookup. + + + Signal strengths info as a dict, such as {"gsm_signal_strength": + 8, "evdo_ecio": -1, "gsm_bit_error_rate": -1, "cdma_ecio": -1, + "cdma_dbm": -1, "evdo_dbm": -1}. + """ + + sensorlib.request_data(sensor_socket, 'startTrackingSignalStrengths', []) + cellular_signal_strengths = sensorlib.request_data(sensor_socket, + 'readSignalStrengths', []) + sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) + + return cellular_signal_strengths + diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 9f56a64..6360424 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -71,5 +71,60 @@ CHILD_CONTEXT_DEF["get_bluetooth_info"] = { } +CHILD_CONTEXT_DEF["is_roaming"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.is_roaming, +} + + + +CHILD_CONTEXT_DEF["get_cellular_provider_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_cellular_provider_info, +} + + +CHILD_CONTEXT_DEF["get_cell_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_cell_info, +} + + +CHILD_CONTEXT_DEF["get_SIM_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_SIM_info, +} + + +CHILD_CONTEXT_DEF["get_phone_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_phone_info, +} + + +CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_cellular_signal_strengths, +} + + secure_dispatch_module() From c8c484af9f130f164b36c787b41a532119fe9459 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Mon, 22 Jun 2015 00:00:10 -0700 Subject: [PATCH 34/60] fix typos --- getsensor.r2py | 4 ++-- sensor_layer.r2py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index fb9c1fc..e1859f0 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -480,7 +480,7 @@ def get_cell_info(): 'getNeighboringCellInfo', []) cellular_info = {'cellID': cellID, 'neighboring_cell': neighboring_cell} - return cellula_info + return cellular_info def get_SIM_info(): @@ -574,7 +574,7 @@ def get_phone_info(): return phone_info -def get_cellular_signal_strengths{} +def get_cellular_signal_strengths() """ Get the current signal strengths, in dictionary of gsm_signal_strength. diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 6360424..9879f9a 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -74,7 +74,7 @@ CHILD_CONTEXT_DEF["get_bluetooth_info"] = { CHILD_CONTEXT_DEF["is_roaming"] = { "type": "func", "args": None, - "return": dict, + "return": bool, "exceptions": "any", "target": getsensor.is_roaming, } From 217a61cc321286b1921121dc798a9f0b1b36a482 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 23 Jun 2015 09:32:38 -0700 Subject: [PATCH 35/60] add settings interface --- getsensor.r2py | 149 +++++++++++++++++++++++++++++++++++++++++++++- sensor_layer.r2py | 36 +++++++++++ 2 files changed, 182 insertions(+), 3 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index e1859f0..249f2e2 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -431,7 +431,7 @@ def get_cellular_provider_info(): 'getNetworkOperatorName', []) cellular_network_info = {'network_operator': network_operator, - 'network_operator_name': network_operator_name} + 'network_operator_name': unicode_scrubber.scrub(network_operator_name)} return cellular_network_info @@ -526,7 +526,7 @@ def get_SIM_info(): 'getSimCountryIso', []) SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, - 'SIM_operator_name': SIM_operator_name, + 'SIM_operator_name': unicode_scrubber.scrub(SIM_operator_name), 'SIM_country_code': SIM_country_code} return SIM_info @@ -574,7 +574,7 @@ def get_phone_info(): return phone_info -def get_cellular_signal_strengths() +def get_cellular_signal_strengths(): """ Get the current signal strengths, in dictionary of gsm_signal_strength. @@ -605,3 +605,146 @@ def get_cellular_signal_strengths() return cellular_signal_strengths + +################################################## +############## settings interface ############### +################################################## + +def get_mode_settings(): + """ + + Get the current settings about mode (airplane mode, ringer silent mode, + vibrate mode), in dictionary of mode_settings. Calls sensorlib. + request_data(sensor_socket, 'checkAirplaneMode'/'checkRingerSilentMode'/ + 'getVibrateMode', []). + + + None + + + None. + + + None. + + + Current mode settings lookup. + + + Signal strengths info as a dict, such as {"airplane_mode": False, + "ringer_silent_mode": True, "vibrate_mode": True}. + """ + + airplane_mode = sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) + ringer_silent_mode = sensorlib.request_data(sensor_socket, + 'checkRingerSilentMode', []) + vibrate_mode = sensorlib.request_data(sensor_socket, 'getVibrateMode', []) + + mode_settings = {'airplane_mode': airplane_mode, 'ringer_silent_mode': + ringer_silent_mode, 'vibrate_mode': vibrate_mode} + return mode_settings + + +def get_screen_settings(): + """ + + Get the current settings about screen (screen on/off, screen brightness, + screen timeout), in dictionary of screen_settings. Calls sensorlib. + request_data(sensor_socket, 'checkScreenOn'/'getScreenBrightness'/ + 'getScreenTimeout', []). + + + None + + + None. + + + None. + + + Current screen settings lookup. + + + Signal strengths info as a dict, such as {"screen_on": True, + "screen_brightness": 200, "screen_timeout": 60}. + """ + + screen_on = sensorlib.request_data(sensor_socket, 'checkScreenOn', []) + screen_brightness = sensorlib.request_data(sensor_socket, + 'getScreenBrightness', []) + screen_timeout = sensorlib.request_data(sensor_socket, + 'getScreenTimeout', []) + + screen_settings = {'screen_on': screen_on, 'screen_brightness': + screen_brightness, 'screen_timeout': screen_timeout} + return screen_settings + + + +def get_media_volume(): + """ + + Get the current settings about media volume (current media volume, + maximum media volume), in dictionary of media_volume. Calls sensorlib. + request_data(sensor_socket, 'getMediaVolume'/'getMaxMediaVolume', []). + + + None + + + None. + + + None. + + + Current media volume settings lookup. + + + Signal strengths info as a dict, such as {"media_volume": xx, + "max_media_volume": xxx}. + """ + + media_volume = sensorlib.request_data(sensor_socket, 'getMediaVolume', []) + max_media_volume = sensorlib.request_data(sensor_socket, + 'getMaxMediaVolume', []) + + media_volume = {'media_volume': media_volume, 'max_media_volume': + max_media_volume} + return media_volume + + + +def get_ringer_volume(): + """ + + Get the current settings about ringer volume (current ringer volume, + maximum ringer volume), in dictionary of ringer_volume. Calls sensorlib. + request_data(sensor_socket, 'getRingerVolume'/'getMaxRingerVolume', []). + + + None + + + None. + + + None. + + + Current ringer volume settings lookup. + + + Signal strengths info as a dict, such as {"ringer_volume": xx, + "max_ringer_volume": xxx}. + """ + + ringer_volume = sensorlib.request_data(sensor_socket, 'getRingerVolume', []) + max_ringer_volume = sensorlib.request_data(sensor_socket, + 'getMaxRingerVolume', []) + + ringer_volume = {'ringer_volume': ringer_volume, 'max_ringer_volume': + max_ringer_volume} + return ringer_volume + diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 9879f9a..8b61951 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -126,5 +126,41 @@ CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { } +CHILD_CONTEXT_DEF["get_mode_settings"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_mode_settings, +} + + +CHILD_CONTEXT_DEF["get_screen_settings"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_screen_settings, +} + + +CHILD_CONTEXT_DEF["get_media_volume"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_media_volume, +} + + +CHILD_CONTEXT_DEF["get_ringer_volume"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_ringer_volume, +} + + secure_dispatch_module() From 4a7f3fd7732ebacd2911e50d83d90c09ed7d20d4 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 23 Jun 2015 15:28:44 -0700 Subject: [PATCH 36/60] scrub unicode --- getsensor.r2py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 249f2e2..04febb5 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -286,9 +286,9 @@ def get_battery_info(): Battery information lookup. - Battery info as a dict, such as {u'status': 3, u'temperature': 257, u'level': - 99, u'battery_present': True, u'plugged': 2, u'health': 2, u'voltage': - 4186, u'technology': u'Li-ion'}. + Battery info as a dict, such as {'status': 3, 'temperature': 257, 'level': + 99, 'battery_present': True, 'plugged': 2, 'health': 2, 'voltage': + 4186, 'technology': 'Li-ion'}. Return values for status: 1 - unknown; 2 - charging; 3 - discharging; 4 - not charging; 5 - full. Return values for temperature: in tenths of a degree Centigrade. E.g., @@ -313,7 +313,7 @@ def get_battery_info(): battery_info = sensorlib.request_data(sensor_socket, 'readBatteryData', []) sensorlib.request_data(sensor_socket, 'batteryStopMonitoring', []) - return battery_info + return unicode_scrubber.scrub(battery_info) @@ -343,7 +343,7 @@ def get_bluetooth_info(): Bluetooth info as a dict, such as {'state': True, 'scan_mode': 3, - 'local_name': 'GT1000'}. + 'local_name': 'GT-P1000'}. Return values for scan_mode: -1 - when Bluetooth is disabled; 0 - if non discoverable and non connectable; 1 - connectable non discoverable; 3 - connectable and discoverable. @@ -355,7 +355,7 @@ def get_bluetooth_info(): local_name = sensorlib.request_data(sensor_socket, 'bluetoothGetLocalName', []) bluetooth_info = {'state': state, 'scan_mode': scan_mode, 'local_name': local_name} - return bluetooth_info + return unicode_scrubber.scrub(bluetooth_info) @@ -431,8 +431,8 @@ def get_cellular_provider_info(): 'getNetworkOperatorName', []) cellular_network_info = {'network_operator': network_operator, - 'network_operator_name': unicode_scrubber.scrub(network_operator_name)} - return cellular_network_info + 'network_operator_name': network_operator_name} + return unicode_scrubber.scrub(cellular_network_info) @@ -480,7 +480,7 @@ def get_cell_info(): 'getNeighboringCellInfo', []) cellular_info = {'cellID': cellID, 'neighboring_cell': neighboring_cell} - return cellular_info + return unicode_scrubber.scrub(cellular_info) def get_SIM_info(): @@ -526,9 +526,9 @@ def get_SIM_info(): 'getSimCountryIso', []) SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, - 'SIM_operator_name': unicode_scrubber.scrub(SIM_operator_name), + 'SIM_operator_name': SIM_operator_name, 'SIM_country_code': SIM_country_code} - return SIM_info + return unicode_scrubber.scrub(SIM_info) def get_phone_info(): @@ -571,7 +571,7 @@ def get_phone_info(): phone_info = {'phone_state': phone_state, 'phone_type': phone_type, 'network_type': network_type} - return phone_info + return unicode_scrubber.scrub(phone_info) def get_cellular_signal_strengths(): @@ -603,7 +603,7 @@ def get_cellular_signal_strengths(): 'readSignalStrengths', []) sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) - return cellular_signal_strengths + return unicode_scrubber.scrub(cellular_signal_strengths) ################################################## @@ -645,6 +645,7 @@ def get_mode_settings(): return mode_settings + def get_screen_settings(): """ From eb22c940adcc57c63b1bcf3adbae3b48dd04df96 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Wed, 24 Jun 2015 09:24:02 -0700 Subject: [PATCH 37/60] add sensor calls --- getsensor.r2py | 230 ++++++++++++++++++++++++++++++++++++++++++++++ sensor_layer.r2py | 74 +++++++++++++++ 2 files changed, 304 insertions(+) diff --git a/getsensor.r2py b/getsensor.r2py index 04febb5..194e665 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -749,3 +749,233 @@ def get_ringer_volume(): max_ringer_volume} return ringer_volume + + +################################################## +############## sensors interface ################ +################################################## + +def start_sensing(sensor_number, delay_time): + """ + + Starts recording sensor data to be available for polling. + Calls sensorlib.request_data(sensor_socket, 'startSensingTimed', + []). + + + sensor_number (Integer): 1 = All, 2 = Accelerometer, + 3 = Magnetometer and 4 = Light + delay_time (Integer): Minimum time between readings in ms. + + + None. + + + None. + + + Starts recording sensor data. + + + None. + """ + + sensorlib.request_data(sensor_socket, 'startSensingTimed', + [sensor_number, delay_time]) + + + +def stop_sensing(): + """ + + Stops recording sensor data to be available for polling. Calls + sensorlib.request_data(sensor_socket, 'stopSensing', []). + + + None. + + + None. + + + None. + + + Stops recording sensor data. + + + None. + """ + + sensorlib.request_data(sensor_socket, 'stopSensing', []) + + + +def get_sensors(): + """ + + Get the most recently recorded sensor data (accelerometer, + magnetic and orientation), in dictionary of sensors. Calls + sensorlib.request_data(sensor_socket, 'readSensors', []). + + + None + + + None. + + + None. + + + Current sensors (accelerometer, magnetic and orientation) lookup. + + + Sensors as a dict, such as {"time": 1.386305361412E9, "roll": + -0.034543427079916, "zforce": 9.959879, "yforce": -0.842759, + "yMag": 164.9375, "xMag": -3.1875, "azimuth": 0.005331491399556398, + "xforce": 0.3439138, "zMag": -67.75, "pitch": 0.08443046659231186, + "accuracy":3}. + """ + + sensors = sensorlib.request_data(sensor_socket, 'readSensors', [1, 1]) + return unicode_scrubber.scrub(sensors) + + +def get_sensors_accuracy(): + """ + + Get the most recently received accuracy value. Calls + sensorlib.request_data(sensor_socket, 'sensorsGetAccuracy', []). + + + None. + + + None. + + + None. + + + Look up sensor accuracy. + + + Returns the most recently received accuracy value, e.g., 3 (highest accuracy). + """ + + return sensorlib.request_data(sensor_socket, 'sensorsGetAccuracy', []) + + + +def get_light(): + """ + + Get the most recently received light value. Calls + sensorlib.request_data(sensor_socket, 'sensorsGetLight', []). + + + None. + + + None. + + + None. + + + Look up light value. + + + TODO: what's the return value looks like? + """ + + return sensorlib.request_data(sensor_socket, 'sensorsGetLight', []) + + + +def get_acceleration(): + """ + + Get the most recently received accelerometer value. Calls + sensorlib.request_data(sensor_socket, 'sensorsReadAccelerometer', + []). + + + None. + + + None. + + + None. + + + Look up accelerometer value. + + + A list of floats [(acceleration on the) X axis, Y axis, Z axis], + e.g., [0.3830723, -0.8036005, 10.036493]. + """ + + return sensorlib.request_data(sensor_socket, + 'sensorsReadAccelerometer', []) + + + +def get_magnetic_field(): + """ + + Get the most recently received magnetic field value. Calls + sensorlib.request_data(sensor_socket, 'sensorsReadMagnetometer', + []). + + + None. + + + None. + + + None. + + + Look up magnetic field value. + + + A list of floats [(magnetic field value for) X axis, Y axis, Z + axis], e.g., [29.5, 206.875, -119.625]. + """ + + return sensorlib.request_data(sensor_socket, + 'sensorsReadMagnetometer', []) + + + +def get_orientation(): + """ + + Get the most recently received orientation value. Calls + sensorlib.request_data(sensor_socket, 'sensorsReadOrientation', + []). + + + None. + + + None. + + + None. + + + Look up orientation value. + + + A list of doubles [azimuth, pitch, roll], e.g., + [-0.17154279351234436, 0.080450139939785, -0.03844258934259415]. + """ + + return sensorlib.request_data(sensor_socket, + 'sensorsReadOrientation', []) + diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 8b61951..7b5cf05 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -162,5 +162,79 @@ CHILD_CONTEXT_DEF["get_ringer_volume"] = { } +CHILD_CONTEXT_DEF["start_sensing"] = { + "type": "func", + "args": int, int, + "return": dict, + "exceptions": "any", + "target": getsensor. start_sensing, +} + + +CHILD_CONTEXT_DEF["stop_sensing"] = { + "type": "func", + "args": (int, int) + "return": dict, + "exceptions": "any", + "target": getsensor. stop_sensing, +} + + +CHILD_CONTEXT_DEF["get_sensors"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_sensors, +} + + +CHILD_CONTEXT_DEF["get_sensors_accuracy"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_sensors_accuracy, +} + + + +CHILD_CONTEXT_DEF["get_light"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_light, +} + + +CHILD_CONTEXT_DEF["get_acceleration"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_acceleration, +} + + + +CHILD_CONTEXT_DEF["get_magnetic_field"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_magnetic_field, +} + + +CHILD_CONTEXT_DEF["get_orientation"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_orientation, +} + + secure_dispatch_module() From 8f3ea85fd83f9be73c2fb90d80ee58435cdae8c0 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Wed, 24 Jun 2015 10:18:04 -0700 Subject: [PATCH 38/60] adjust vibration mode --- getsensor.r2py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 194e665..3e874c3 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -632,13 +632,22 @@ def get_mode_settings(): Signal strengths info as a dict, such as {"airplane_mode": False, - "ringer_silent_mode": True, "vibrate_mode": True}. + "ringer_silent_mode": True, "vibrate_mode": {'ringer_vibrate': True, + 'notification_vibrate': False}}. """ airplane_mode = sensorlib.request_data(sensor_socket, 'checkAirplaneMode', []) ringer_silent_mode = sensorlib.request_data(sensor_socket, 'checkRingerSilentMode', []) - vibrate_mode = sensorlib.request_data(sensor_socket, 'getVibrateMode', []) + + # call to SL4A getVibrateMode: if the argument is true then query + # Ringer setting, else query Notification setting + ringer_vibrate = sensorlib.request_data(sensor_socket, + 'getVibrateMode', [True]) + notification_vibrate = sensorlib.request_data(sensor_socket, + 'getVibrateMode', [False]) + vibrate_mode = {'ringer_vibrate': ringer_vibrate, + 'notification_vibrate': notification_vibrate} mode_settings = {'airplane_mode': airplane_mode, 'ringer_silent_mode': ringer_silent_mode, 'vibrate_mode': vibrate_mode} From 3c405cc9a6f5b823785a02e874199ec3b699f86d Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Thu, 25 Jun 2015 09:42:43 -0700 Subject: [PATCH 39/60] fix typos --- getsensor.r2py | 6 +++--- sensor_layer.r2py | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 3e874c3..ce2b3f5 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -821,7 +821,7 @@ def stop_sensing(): def get_sensors(): - """ + """ Get the most recently recorded sensor data (accelerometer, magnetic and orientation), in dictionary of sensors. Calls @@ -847,7 +847,7 @@ def get_sensors(): "accuracy":3}. """ - sensors = sensorlib.request_data(sensor_socket, 'readSensors', [1, 1]) + sensors = sensorlib.request_data(sensor_socket, 'readSensors', []) return unicode_scrubber.scrub(sensors) @@ -962,7 +962,7 @@ def get_magnetic_field(): def get_orientation(): - """ + """ Get the most recently received orientation value. Calls sensorlib.request_data(sensor_socket, 'sensorsReadOrientation', diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 7b5cf05..6c499b8 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -164,19 +164,19 @@ CHILD_CONTEXT_DEF["get_ringer_volume"] = { CHILD_CONTEXT_DEF["start_sensing"] = { "type": "func", - "args": int, int, - "return": dict, + "args": (int, int), + "return": None, "exceptions": "any", - "target": getsensor. start_sensing, + "target": getsensor.start_sensing, } CHILD_CONTEXT_DEF["stop_sensing"] = { "type": "func", - "args": (int, int) - "return": dict, + "args": None, + "return": None, "exceptions": "any", - "target": getsensor. stop_sensing, + "target": getsensor.stop_sensing, } @@ -192,7 +192,7 @@ CHILD_CONTEXT_DEF["get_sensors"] = { CHILD_CONTEXT_DEF["get_sensors_accuracy"] = { "type": "func", "args": None, - "return": dict, + "return": int, "exceptions": "any", "target": getsensor.get_sensors_accuracy, } @@ -211,7 +211,7 @@ CHILD_CONTEXT_DEF["get_light"] = { CHILD_CONTEXT_DEF["get_acceleration"] = { "type": "func", "args": None, - "return": dict, + "return": list, "exceptions": "any", "target": getsensor.get_acceleration, } @@ -221,7 +221,7 @@ CHILD_CONTEXT_DEF["get_acceleration"] = { CHILD_CONTEXT_DEF["get_magnetic_field"] = { "type": "func", "args": None, - "return": dict, + "return": list, "exceptions": "any", "target": getsensor.get_magnetic_field, } @@ -230,7 +230,7 @@ CHILD_CONTEXT_DEF["get_magnetic_field"] = { CHILD_CONTEXT_DEF["get_orientation"] = { "type": "func", "args": None, - "return": dict, + "return": list, "exceptions": "any", "target": getsensor.get_orientation, } From 561b7510a3888c4097036a335218068474f77c15 Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 30 Jun 2015 11:46:16 -0400 Subject: [PATCH 40/60] add comments and docstrings --- blur_location2city.r2py | 165 ++++++++++-------- blur_location2state.r2py | 363 +++++++++++++++++++++++---------------- 2 files changed, 304 insertions(+), 224 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index fd940de..5014e49 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -1,13 +1,17 @@ """ A security layer for the functions get_location() and get_lastknown_location() -defined in getsensor.r2py. This program blurs the coordinates, received -from the location sensors of an Android device, to the geographic center of -approximately the nearest city. - -The blurring is done using a DB lookup method. The DB contains a list of -cities, and their geodata (lat, lon, country code, state code), divided -by their coordinates. The DB is is available at: -http://sensibilityclearinghouse.poly.edu/data/quad/ +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of approximately the nearest city. + +The blurring is done using a database lookup method. The database, +located at http://sensibilityclearinghouse.poly.edu/data/quad/, contains +a list of cities and their geodata (latitude, longitude, country code, +state code), divided by their latitude/longitude coordinates into cells. +Each cell is a separate file in the database, whose name is derived as +"ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan has +its center at coordinates 40.78343, -73.96625, so it will be mapped to +the file with name "41_-73.txt". Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -21,60 +25,101 @@ math = dy_import_module("math.r2py") +def load_city_geodata(filename): + """ + Loads all the cities and their geodata from the given file into a + dictionary. The dictionary that is returned has the format: + { + city1: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + city2: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + ... + } + + """ + get_file_from_server(filename) + city_dict = {} + city_geodata_fileobj = openfile(filename, False) + city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + + for line in city_geodata_file: + # Ignore the empty line at the end of the file + if line == "": + continue + city_geodata_record = line.split("\t") + city_name = city_geodata_record[0] + lat = float(city_geodata_record[1]) + lon = float(city_geodata_record[2]) + city_dict[city_name] = { + "latitude": lat, + "longitude": lon, + "country_code": city_geodata_record[3], + "state_code": city_geodata_record[4] + } + city_geodata_fileobj.close() + return city_dict + + + def get_file_from_server(filename): """ - Downloads the required file from the DB server, if it has not already - been downloaded. + Downloads the required file from the database server, if it has not + already been downloaded. """ if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename httpretrieve.httpretrieve_save_file(url, filename) def find_closest_city(lat, lon): """ - Searches the DB and returns a dict containing the geodata of the city - that is approximately closest to a given lat/lon pair in the format: + Finds the city closest to the given latitude/longitude pair from the + dictionary of cities returned by the load_city_geodata() function, + and returns that city's geodata in the format: { "city_name": city name (string), "state_code": 2-digit code representing the state to which the city belongs (string), "country_code": 2-letter ISO-3166 code representing the country to which the city belongs (string), - "coordinates": tuple containing the lat/lon pair representing the - geographic center of the city (float, float) + "latitude": latitude of the geographic center of the city (float) + "longitude": longitude of the geographic center of the city (float) } - - Note: We're looking for the closest lat/lon pair within the same - quadrant as the given lat/lon pair. There might be closer ones in - other quadrants. Thus, the "closest city" is only an approximation. + + Note: We're looking for the closest city within the same cell as the + given latitude/longitude pair. There might be a closer city in the + surrounding cells. """ - # Determine which file to download from the DB. + # Determine which file to download from the database. filename = get_database_filename(lat, lon) # Load all the cities and their geodata from the file. city_dict = load_city_geodata(filename) # Set the minimum squared difference between two pairs of coordinates - # to an arbitrarily large number. - # XXX Should "large" be defined? + # to a number larger than any possible minimum distance to a close + # city in the current latitude/longitude quadrilateral. min_diff = 9999 for city_name, city_geodata in city_dict.items(): - city_lat, city_lon = city_geodata["coordinates"] - diff = find_squared_difference((lat, lon), (city_lat, city_lon)) + diff = find_squared_difference((lat, lon), (city_geodata["latitude"], + city_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_city_coordinates = city_geodata["coordinates"] + closest_city_latitude = city_geodata["latitude"] + closest_city_longitude = city_geodata["longitude"] closest_city_name = city_name closest_city_state_code = city_geodata["state_code"] closest_city_country_code = city_geodata["country_code"] - closest_city_geodata = {"city_name": closest_city_name, - "coordinates": closest_city_coordinates, + closest_city_geodata = { + "city_name": closest_city_name, + "latitude": closest_city_latitude, + "longitude": closest_city_longitude, "state_code": closest_city_state_code, "country_code": closest_city_country_code } @@ -85,8 +130,8 @@ def find_closest_city(lat, lon): def get_database_filename(lat, lon): """ - Returns the filename in the DB with coordinates in the same quadrant - as the given lat/lon pair. + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. """ # Get ceiling as x/y index. @@ -97,45 +142,11 @@ def get_database_filename(lat, lon): -def load_city_geodata(filename): - """ - Returns a dict containing all the cities in the given file, - along with their corresponding geodata in the format: - { - city1: {"coordinates": (lat, lon), "country_code": country_code, - "state_code": state_code}, - city2: {"coordinates": (lat, lon), "country_code": country_code, - "state_code": state_code}, - ... - } - - """ - get_file_from_server(filename) - city_dict = {} - city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.reat(None, 0).split("\n") - - for line in city_geodata_file: - # Ignore the empty line at the end of the file - if line == "": - continue - city_geodata_record = line.split("\t") - city_name = city_geodata_record[0] - lat = float(city_geodata_record[1]) - lon = float(city_geodata_record[2]) - city_dict[city_name] = {"coordinates": (lat, lon), - "country_code": city_geodata_record[3], - "state_code": city_geodata_record[4] - } - city_geodata_fileobj.close() - return city_dict - - - def find_squared_difference(p1, p2): """ - Returns the squared difference between two pairs of coordinates (p1 - and p2). + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). """ lat1, lon1 = p1 @@ -148,7 +159,7 @@ def find_squared_difference(p1, p2): def get_city_location(): """ - Security layer for the get_location() function. It replaces the exact + Blurring layer for the get_location() function. It replaces the exact coordinates of the Android device with the coordinates for the geographic center of the nearest city. @@ -158,8 +169,8 @@ def get_city_location(): closest_city = find_closest_city(location_data["latitude"], location_data["longitude"]) - location_data["latitude"], location_data["longitude"] = \ - closest["coordinates"] + location_data["latitude"] = closest_city["latitude"] + location_data["longitude"] = closest_city["longitude"] return location_data @@ -167,7 +178,7 @@ def get_city_location(): def get_city_lastknown_location(): """ - Security layer for the get_lastknown_location() function. It replaces + Blurring layer for the get_lastknown_location() function. It replaces the last-known coordinates of the Android device with the coordinates for the geographic center of the nearest city. @@ -180,19 +191,18 @@ def get_city_lastknown_location(): # location. if provider_location_data is None: continue - + closest_city = find_closest_city(provider_location_data["latitude"], provider_location_data["longitude"]) - - location_data[location_provider]["latitude"], \ - location_data[provider]["longitude"] = closest["coordinates"] + + location_data[location_provider]["latitude"] = closest_city["latitude"] + location_data[location_provider]["longitude"] = closest_city["longitude"] return location_data -# Makes a security layer out of what otherwise would be just a plain -# library you could `dy_import` +# Mapping our blurring function get_city_location to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -202,6 +212,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function get_city_lastknown_location to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -211,4 +223,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } +# Dispatch secure_dispatch_module() \ No newline at end of file diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 652db41..3108372 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -1,191 +1,254 @@ -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") -librepyfile = dy_import_module("librepyfile.r2py") +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of approximately the nearest state. + +The blurring is done using a database lookup method. First, we find the +city closest to the original latitude/longitude coordinates from the +cities' database and extract the geodata associated with it. This +database, located at http://sensibilityclearinghouse.poly.edu/data/quad/, +contains a list of cities and their geodata (latitude, longitude, +country code, state code), divided by their coordinates into cells. +Each cell is a separate file in the database, whose name is derived +as "ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan +has its center at coordinates 40.78343, -73.96625, so it will be mapped +to the file with name "41_-73.txt". + +Next, we use the state code and country code from the city's geodata to +look up the coordinates of the geographic center of the state to which +the city belongs. This look up uses the states' database, states.txt, +located at http://sensibilityclearinghouse.poly.edu/data/. states.txt +is a database of the top level administrative divisions within each +country (for example, states/provinces). It has the following fields: +code, state name, latitude, longitude. The code field has the format +"country_code.state_code", where country_code is the ISO-3166 2-letter +country code of the country to which the admin division belongs and +state_code is the 2-digit state code representing the admin division. + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2state.r2py user-program.r2py +""" -statefilename = "states.txt" # Database of states -countryfilename = "countries.txt" # Database of countries -# Downloads the required file from the server -def get_file_from_server(filename): +httpretrieve = dy_import_module("httpretrieve.r2py") +math = dy_import_module("math.r2py") + +statefilename = "states.txt" - if filename not in listfiles(): # In case it already exists - if filename not in [statefilename, countryfilename]: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - httpretrieve.httpretrieve_save_file(url, filename) -# Returns a dictionary containing information about the point closest to -# a given lat/lng pair, from the database. -# {"city": closest_city, "statecode": closest_state_code, "countrycode": -# closest_country_code, "coordinates": closest_point} -def find_closest_point(lat, lng): +def load_city_geodata(filename): + """ + Loads all the cities and their geodata from the given file into a + dictionary. The dictionary that is returned has the format: + { + city1: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + city2: {"latitude": latitude, "longitude": longitude, "country_code": + country_code, "state_code": state_code}, + ... + } - # Find the database file with coordinates closest to the given lat/lng pair - filename = get_filename(lat, lng) - # Get the list of coordinates from that file - listofpoints = load_lat_lng_from_file(filename) + """ + get_file_from_server(filename) + city_dict = {} + city_geodata_fileobj = openfile(filename, False) + city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + + for line in city_geodata_file: + # Ignore the empty line at the end of the file + if line == "": + continue + city_geodata_record = line.split("\t") + city_name = city_geodata_record[0] + lat = float(city_geodata_record[1]) + lon = float(city_geodata_record[2]) + city_dict[city_name] = { + "latitude": lat, + "longitude": lon, + "country_code": city_geodata_record[3], + "state_code": city_geodata_record[4] + } + city_geodata_fileobj.close() + return city_dict - min_dist = 9999 - point1 = (lat, lng) - for city in listofpoints.keys(): - data = listofpoints[city] - point2 = (data[0], data[1]) - dist = find_distance(point1, point2) - if dist < min_dist: - min_dist = dist - closest_point = point2 - closest_city = city - closest_state_code = data[3] - closest_country_code = data[2] - closest = {"city": closest_city, "statecode": closest_state_code, "countrycode": closest_country_code, "coordinates": closest_point} +def get_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. - return closest + """ + if filename not in listfiles(): + if filename == statefilename: + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + else: + url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename + httpretrieve.httpretrieve_save_file(url, filename) -# Returns the filename in the database with coordinates closest to the given -# lat/lng pair -def get_filename(lat, lng): - # get ceiling as x/y index +def find_closest_city(lat, lon): + """ + Finds the city closest to the given latitude/longitude pair from the + dictionary of cities returned by the load_city_geodata() function, + and returns that city's geodata in the format: + { + "city_name": city name (string), + "state_code": 2-digit code representing the state to which the city + belongs (string), + "country_code": 2-letter ISO-3166 code representing the country to + which the city belongs (string), + "latitude": latitude of the geographic center of the city (float) + "longitude": longitude of the geographic center of the city (float) + } + + Note: We're looking for the closest city within the same cell as the + given latitude/longitude pair. There might be a closer city in the + surrounding cells. + + """ + # Determine which file to download from the database. + filename = get_database_filename(lat, lon) + + # Load all the cities and their geodata from the file. + city_dict = load_city_geodata(filename) + + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # city in the current latitude/longitude quadrilateral. + min_diff = 9999 + + for city_name, city_geodata in city_dict.items(): + diff = find_squared_difference((lat, lon), (city_geodata["latitude"], + city_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_city_latitude = city_geodata["latitude"] + closest_city_longitude = city_geodata["longitude"] + closest_city_name = city_name + closest_city_state_code = city_geodata["state_code"] + closest_city_country_code = city_geodata["country_code"] + + closest_city_geodata = { + "city_name": closest_city_name, + "latitude": closest_city_latitude, + "longitude": closest_city_longitude, + "state_code": closest_city_state_code, + "country_code": closest_city_country_code + } + + return closest_city_geodata + + + +def get_database_filename(lat, lon): + """ + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. + + """ + # Get ceiling as x/y index. x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lng)) + y = int(math.math_ceil(lon)) filename = str(x) + '_' + str(y) + '.txt' return filename -# Returns a dictionary containing all the cities in the given file, along with -# their corresponding data -# {city1: [lat, lng, country_code, state_code], city2: [lat, lng, country_code, -# state_code], ...} -def load_lat_lng_from_file(filename): - get_file_from_server(filename) - listofpoints = {} - fileobj = librepyfile.open(filename, "r") +def find_squared_difference(p1, p2): + """ + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). + + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff + + - while True: - try: - line = fileobj.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - city_name = line[0] - lat = line[1] - lng = line[2] - country_code = line[3] - state_code = line[4] - listofpoints[city_name] = [lat, lng, country_code, state_code] - fileobj.close() - return listofpoints - - -# Returns the distance between two lat/lng points -def find_distance(p1, p2): - - (lat1, lng1) = p1 - (lat2, lng2) = p2 - lat2 = float(lat2) - lng2 = float(lng2) - lat_diff = (lat1-lat2) * (lat1-lat2) - lng_diff = (lng1-lng2) * (lng1-lng2) - # return squared distance - return lat_diff + lng_diff - - -# To replace get_location() def get_state_location(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the nearest state. - try: - location_data = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception + """ + location_data = get_location() - latitude = location_data["latitude"] - longitude = location_data["longitude"] + closest_city = find_closest_city(location_data["latitude"], + location_data["longitude"]) - closest = find_closest_point(latitude, longitude) - country_code = closest["countrycode"] - state_code = closest["statecode"] - code = country_code + "." + str(state_code) + code = closest_city["country_code"] + "." + str(closest_city["state_code"]) - # Download the States database + # Download the states.txt database get_file_from_server(statefilename) - statefile = librepyfile.open(statefilename, "r") + state_fileobj = openfile(statefilename, False) + state_file = state_fileobj.readat(None, 0).split("\n") # Look for the state corresponding to the code - while True: - try: - line = statefile.next().strip() - except StopIteration: + for line in state_file: + state_record = line.split("\t") + if code == state_record[0]: + location_data["latitude"] = state_record[2] + location_data["longitude"] = state_record[3] break - else: - line = line.split("\t") - if code == line[0]: - slat = line[2] - slng = line[3] - break - statefile.close() - - location_data["latitude"] = slat - location_data["longitude"] = slng + state_fileobj.close() return location_data -# To replace get_lastknown_location() -def get_state_lastknown_location(): - try: - location_data = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - - # Get the location from the the provider - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - latitude = location["latitude"] - longitude = location["longitude"] - - closest = find_closest_point(latitude, longitude) - - country_code = closest["countrycode"] - state_code = closest["statecode"] - code = country_code + "." + str(state_code) - - # Download the States database - get_file_from_server(statefilename) - - statefile = librepyfile.open(statefilename, "r") - - # Look for the state corresponding to the code - while True: - try: - line = statefile.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - if code == line[0]: - slat = line[2] - slng = line[3] - break - statefile.close() - - location_data[provider]["latitude"] = slat - location_data[provider]["longitude"] = slng +def get_state_lastknown_location(): + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the nearest state. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + closest_city = find_closest_city(provider_location_data["latitude"], + provider_location_data["longitude"]) + + code = closest_city["country_code"] + "." + str(closest_city["state_code"]) + + # Download the states.txt database + get_file_from_server(statefilename) + + state_fileobj = openfile(statefilename, False) + state_file = state_fileobj.readat(None, 0).split("\n") + + # Look for the state corresponding to the code + for line in state_file: + state_record = line.split("\t") + if code == state_record[0]: + provider_location_data["latitude"] = state_record[2] + provider_location_data["longitude"] = state_record[3] + break + state_fileobj.close() return location_data + +# Mapping our blurring function get_state_location to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -195,6 +258,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function get_state_lastknown_location to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -203,4 +268,6 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { "target": get_state_lastknown_location, } + +# Dispatch secure_dispatch_module() \ No newline at end of file From f53043875cb1d193061e16fb5e69bca8f9e4762e Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 30 Jun 2015 14:27:03 -0700 Subject: [PATCH 41/60] add encasementlib --- encasementlib.r2py | 242 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 encasementlib.r2py diff --git a/encasementlib.r2py b/encasementlib.r2py new file mode 100644 index 0000000..87fee9f --- /dev/null +++ b/encasementlib.r2py @@ -0,0 +1,242 @@ +""" +Author: Armon Dadgar +Description: + This module is designed to help construct security layers. + + Its main mechanism is secure_dispatch_module() which takes a context + definition and executes the next layer within a secure context. +""" + +# Copy our clean context for importing +CLEAN_CONTEXT = _context.copy() +CLEAN_CONTEXT["_context"] = CLEAN_CONTEXT +CLEAN_CONTEXT["mycontext"] = {} + +# These are the calls that are initially copied to form +# INIT_DEFINITION +# +COPIED_API = ["gethostbyname", "getmyip", "sendmessage", "listenformessage", + "openconnection", "listenforconnection", "openfile", "listfiles", + "removefile", "exitall", "createlock", "getruntime", "randombytes", + "createthread", "sleep", "log", "getthreadname", "createvirtualnamespace", + "getresources", "getlasterror", "json_parse", ] + +# This is the definition of the first security layer +# Copy all of the functions named by COPIED_API +INIT_DEFINITION = {} + +# This is the maximum number of bytes we will try to read in for a file. +# Anything larger and we abort +MAX_FILE_SIZE = 100000 + +# Constants +TYPE = "type" +ANY = "any" +TARGET = "target" + + +#### Helper functions #### + +# Helper macro to build INIT_DEFINITION +def _build_INIT_DEFINITION(): + for API in COPIED_API: + INIT_DEFINITION[API] = {TYPE:ANY, + TARGET:_context[API]} + + # Expose wrap_references + INIT_DEFINITION["wrap_references"] = { + "type":"func", + "args":(dict,), + "return":dict, + "exceptions":RepyArgumentError, + "target":wrap_references + } + +# Imports the wrapper module +def _import_wrapper(): + # The code for the module + virt = _layer_code("wrapper.r2py") + + # Evaluate the module in a copy of the clean context + eval_context = CLEAN_CONTEXT.copy() + virt.evaluate(eval_context) + + # Export the wrap_references function + _context["wrap_references"] = eval_context["wrap_references"] + + +# Gets the code object for a layer +def _layer_code(layer): + + # Try to get a file handle to the module + try: + fileh = openfile(layer, False) + except FileNotFoundError: + raise FileNotFoundError, "Cannot load security layer '"+layer+"'. File not found." + except ResourceExhaustedError: + raise FileNotFoundError, "Cannot load security layer '"+layer+"'. No file resources." + + # Read in the code + code = fileh.readat(MAX_FILE_SIZE, 0) + fileh.close() + if len(code) == MAX_FILE_SIZE: + log("Failed to read all of security layer '"+layer+"'! File size exceeds 100K bytes!") + + # Create a new virtual namespace + try: + virt = createvirtualnamespace(code,layer) + except CodeUnsafeError, e: + raise CodeUnsafeError, "Compiling security layer '"+layer+"' failed! Got exception: '" + str(e) + "'" + + # Return the new namespace + return virt + + +# Generate the context for a layer +def _layer_context(caller_context, context_def): + """ + + Generates the context for the next layer. + + + caller_context: The context of the caller. + context_def: The definition of the context + + + RepyArgumentError if the definition is invalid. + + + A SafeDict execution context. + """ + # Wrap all the references in a SafeDict + wrapped_context = SafeDict(wrap_references(context_def)) + + # Provide a reference to itself + wrapped_context["_context"] = wrapped_context + + # Provide a clean mycontext dictionary + wrapped_context["mycontext"] = {} + + # Try to copy in callargs and callfunc + if "callfunc" in caller_context and type(caller_context["callfunc"]) is str: + wrapped_context["callfunc"] = caller_context["callfunc"] + + if "callargs" in caller_context and type(caller_context["callargs"]) is list: + # Offset the list by 1 + offset_args = caller_context["callargs"][1:] + + # If they are all strings, copy over + for elem in offset_args: + if type(elem) is not str: + break + else: + wrapped_context["callargs"] = offset_args + + # Generate a new CHILD_CONTEXT_DEF + new_def = _layer_generic_def(wrapped_context, context_def) + wrapped_context["CHILD_CONTEXT_DEF"] = new_def + + # Generate a layer-specific secure_dispatch_module + dispatch_func = _layer_instance_dispatch(wrapped_context, new_def) + wrapped_context["secure_dispatch_module"] = dispatch_func + + # Return the context + return wrapped_context + + +# Takes the definition used to generate a context +# and generates a generic definition can can be used +# to just copy the existing references +def _layer_generic_def(built_context, context_def): + # Create a new definition dict + new_def = {} + + # Just map the reference to any, this will result + # in a simple copy of the reference + for key in context_def: + new_def[key] = {TYPE:ANY, + TARGET:built_context[key]} + + # Return the new definition + return new_def + + +# Returns a new function which calls secure_dispatch +# using the specified caller, and a default context +# definition dictionary. +def _layer_instance_dispatch(caller, default_definition): + + def _secure_dispatch_closure(context_def=None): + # Check if we should use the default definition + if context_def is None: + context_def = default_definition + + # Call secure dispatch + secure_dispatch(caller, context_def) + + # Return this new closure + return _secure_dispatch_closure + + +#### Support for dispatch #### + +# Securely dispatches the next security layer +def secure_dispatch(caller_context, context_def): + """ + + Wraps the references provided by a security layer and + dispatches the next security layer. + + + caller_context: + The context of the caller. + + context_def: + The definition of the context for the next layer + + + As with the module being evaluated. An exception will be raised + if the module to be evaluated cannot be initialized in a VirtualNamespace + due to safety or syntax problems, or if the module does not exist. + + If the definition of the context is invalid, a RepyArgumentError will + be raised. + + + Execution will switch to the next module. + + + True if a recursive evaluation was performed, false otherwise. + """ + # Check that there is a next module + if not "callargs" in caller_context or len(caller_context["callargs"]) == 0: + return False + + # Get the next layer to run + next_layer = caller_context["callargs"][0] + + # Get the code for the layer + virt = _layer_code(next_layer) + + # Get the evaluation context for the layer + eval_context = _layer_context(caller_context, context_def) + + # Evaluate the new security layer + virt.evaluate(eval_context) + + # Return success + return True + + +#### Dispatch the next module #### + +# Import the wrapper module +_import_wrapper() + +# Build INIT_DEFINITION +_build_INIT_DEFINITION() + +# Dispatch now +secure_dispatch(_context, INIT_DEFINITION) + + From 0d64f45d278607025969c61950f5ddb8c861d1c7 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 30 Jun 2015 16:29:22 -0700 Subject: [PATCH 42/60] update readme --- README.md | 72 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2e5cc37..512a722 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,68 @@ -sensorlib +This is a sensor library for the Sensibility Testbed https://sensibilitytestbed.com/ ========= -To use the sensor code: +To use the sensors on the Sensibility Testbed is straight forward. You will need the following files: dylink.r2py, encasementlib.r2py, getsensor.r2py, sensor_layer.r2py, sensorlib.r2py, unicode_scrubber.r2py, wrapper.r2py, and your test file. -1. import necessary library: +1. Write your sensor code. - dy_import_module_symbols("sensorlib") - -2. get a connection to communicate with sensors - - port = get_connectionport() - - sensor_socket = getconnection(port) + Using location as an example. Since location depends on external services (GPS, WiFi or cellular networks), we highly recommend that you include some error handling in your code, such as + +`MAX_TIME = 5 +starttime = getruntime() -3. use the above socket to get sensor values: +while(getruntime() - starttime < MAX_TIME): + try: + location = get_location() + if location: + break + except Exception: + sleep(0.02)` + + The call `get_location()` returns real-time location data from the device. However, when this call cannot get any location data from those external services (`location == None`), we can try to get the previously cached location on the device: + +`if not location: + try: + location = get_lastknown_location() + except Exception: # Not able to use LocationNotFoundException here + log("can't locate using get_lastknown_location().. exit!\n") + exitall()` - request_data(sensor_socket, 'startSensingTimed', [1, 30]) - - request_data(sensor_socket, 'stopSensing', []) + The coordinates of the device can then be extracted from the data returned: + +`latitude = location["latitude"] +longitude = location["longitude"]` + + Location sensor is more complex to handle than other sensors. A less complex one is the accelerometer. Using accelerometer as another (less complex) example, we first need to start sensing on your phone by calling + + `start_sensing(sensor_number, delay_time)` + + Such that your phone will start recording sensor data. sensor_number is any of the following integer: 1 = All, 2 = Accelerometer, 3 = Magnetometer and 4 = Light; delay_time: minimum time between readings in ms, also in integer. Then call + + `get_acceleration()` + + This will return the most recently received accelerometer value in a list, e.g., [0.3830723, -0.8036005, 10.036493] as the acceleration on the X, Y, and Z axis. To stop recording sensor data, call + + `stop_sensing()` + + Save your sensor code as accelerometer.r2py. -4. upload your code +2. upload your code to a remote phone. albert@%1 !> upload dylink.repy albert@%1 !> upload sensorlib.repy - albert@%1 !> upload sensortest.r2py + albert@%1 !> upload encasementlib.r2py + + ...... albert@%1 !> show files - Files on '131.130.125.5:1224:v1': 'dylink.repy sensorlib.repy sensortest.r2py' + Files on '131.130.125.5:1224:v1': 'accelerometer.r2py dylink.r2py encasementlib.r2py getsensor.r2py sensor_layer.r2py sensorlib.r2py unicode_scrubber.r2py wrapper.r2py' - albert@%1 !> +3. run your code -5. run your code - - albert@%1 !> startv2 dylink.repy sensortest.r2py + albert@%1 !> start dylink.r2py encasementlib.r2py sensor_layer.r2py [any blur layers] accelerometer.r2py - albert@%1 !> startv2 dylink.repy sensortest.r2py BatteryFacade batteryGetLevel +4. How to write your blur layers? + From fd6fd5af3bc8461b9f6308927f8fb78b4ce33aba Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 30 Jun 2015 16:43:37 -0700 Subject: [PATCH 43/60] update readme with git marup --- README.md | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 512a722..5783f0c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This is a sensor library for the Sensibility Testbed https://sensibilitytestbed.com/ +Sensor library for the Sensibility Testbed https://sensibilitytestbed.com/ ========= To use the sensors on the Sensibility Testbed is straight forward. You will need the following files: dylink.r2py, encasementlib.r2py, getsensor.r2py, sensor_layer.r2py, sensorlib.r2py, unicode_scrubber.r2py, wrapper.r2py, and your test file. @@ -7,7 +7,8 @@ To use the sensors on the Sensibility Testbed is straight forward. You will need Using location as an example. Since location depends on external services (GPS, WiFi or cellular networks), we highly recommend that you include some error handling in your code, such as -`MAX_TIME = 5 +```python +MAX_TIME = 5 starttime = getruntime() while(getruntime() - starttime < MAX_TIME): @@ -16,38 +17,50 @@ while(getruntime() - starttime < MAX_TIME): if location: break except Exception: - sleep(0.02)` + sleep(0.02) +``` The call `get_location()` returns real-time location data from the device. However, when this call cannot get any location data from those external services (`location == None`), we can try to get the previously cached location on the device: -`if not location: +```python +if not location: try: location = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here + except Exception: log("can't locate using get_lastknown_location().. exit!\n") - exitall()` + exitall() +``` The coordinates of the device can then be extracted from the data returned: -`latitude = location["latitude"] -longitude = location["longitude"]` +```python +latitude = location["latitude"] +longitude = location["longitude"] +``` Location sensor is more complex to handle than other sensors. A less complex one is the accelerometer. Using accelerometer as another (less complex) example, we first need to start sensing on your phone by calling - `start_sensing(sensor_number, delay_time)` +```python +start_sensing(sensor_number, delay_time) +``` Such that your phone will start recording sensor data. sensor_number is any of the following integer: 1 = All, 2 = Accelerometer, 3 = Magnetometer and 4 = Light; delay_time: minimum time between readings in ms, also in integer. Then call - `get_acceleration()` +```python +get_acceleration() +``` This will return the most recently received accelerometer value in a list, e.g., [0.3830723, -0.8036005, 10.036493] as the acceleration on the X, Y, and Z axis. To stop recording sensor data, call - `stop_sensing()` +```python +stop_sensing() +``` Save your sensor code as accelerometer.r2py. 2. upload your code to a remote phone. +``` albert@%1 !> upload dylink.repy albert@%1 !> upload sensorlib.repy @@ -57,12 +70,15 @@ longitude = location["longitude"]` ...... albert@%1 !> show files +``` Files on '131.130.125.5:1224:v1': 'accelerometer.r2py dylink.r2py encasementlib.r2py getsensor.r2py sensor_layer.r2py sensorlib.r2py unicode_scrubber.r2py wrapper.r2py' 3. run your code - albert@%1 !> start dylink.r2py encasementlib.r2py sensor_layer.r2py [any blur layers] accelerometer.r2py +``` +albert@%1 !> start dylink.r2py encasementlib.r2py sensor_layer.r2py [any blur layers] accelerometer.r2py +``` 4. How to write your blur layers? From 7aaaf39e2220d438cc015062790c743dc509fede Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Wed, 1 Jul 2015 07:37:03 -0700 Subject: [PATCH 44/60] remove dup code --- encasementlib.r2py | 242 --------------------------------------------- 1 file changed, 242 deletions(-) delete mode 100644 encasementlib.r2py diff --git a/encasementlib.r2py b/encasementlib.r2py deleted file mode 100644 index 87fee9f..0000000 --- a/encasementlib.r2py +++ /dev/null @@ -1,242 +0,0 @@ -""" -Author: Armon Dadgar -Description: - This module is designed to help construct security layers. - - Its main mechanism is secure_dispatch_module() which takes a context - definition and executes the next layer within a secure context. -""" - -# Copy our clean context for importing -CLEAN_CONTEXT = _context.copy() -CLEAN_CONTEXT["_context"] = CLEAN_CONTEXT -CLEAN_CONTEXT["mycontext"] = {} - -# These are the calls that are initially copied to form -# INIT_DEFINITION -# -COPIED_API = ["gethostbyname", "getmyip", "sendmessage", "listenformessage", - "openconnection", "listenforconnection", "openfile", "listfiles", - "removefile", "exitall", "createlock", "getruntime", "randombytes", - "createthread", "sleep", "log", "getthreadname", "createvirtualnamespace", - "getresources", "getlasterror", "json_parse", ] - -# This is the definition of the first security layer -# Copy all of the functions named by COPIED_API -INIT_DEFINITION = {} - -# This is the maximum number of bytes we will try to read in for a file. -# Anything larger and we abort -MAX_FILE_SIZE = 100000 - -# Constants -TYPE = "type" -ANY = "any" -TARGET = "target" - - -#### Helper functions #### - -# Helper macro to build INIT_DEFINITION -def _build_INIT_DEFINITION(): - for API in COPIED_API: - INIT_DEFINITION[API] = {TYPE:ANY, - TARGET:_context[API]} - - # Expose wrap_references - INIT_DEFINITION["wrap_references"] = { - "type":"func", - "args":(dict,), - "return":dict, - "exceptions":RepyArgumentError, - "target":wrap_references - } - -# Imports the wrapper module -def _import_wrapper(): - # The code for the module - virt = _layer_code("wrapper.r2py") - - # Evaluate the module in a copy of the clean context - eval_context = CLEAN_CONTEXT.copy() - virt.evaluate(eval_context) - - # Export the wrap_references function - _context["wrap_references"] = eval_context["wrap_references"] - - -# Gets the code object for a layer -def _layer_code(layer): - - # Try to get a file handle to the module - try: - fileh = openfile(layer, False) - except FileNotFoundError: - raise FileNotFoundError, "Cannot load security layer '"+layer+"'. File not found." - except ResourceExhaustedError: - raise FileNotFoundError, "Cannot load security layer '"+layer+"'. No file resources." - - # Read in the code - code = fileh.readat(MAX_FILE_SIZE, 0) - fileh.close() - if len(code) == MAX_FILE_SIZE: - log("Failed to read all of security layer '"+layer+"'! File size exceeds 100K bytes!") - - # Create a new virtual namespace - try: - virt = createvirtualnamespace(code,layer) - except CodeUnsafeError, e: - raise CodeUnsafeError, "Compiling security layer '"+layer+"' failed! Got exception: '" + str(e) + "'" - - # Return the new namespace - return virt - - -# Generate the context for a layer -def _layer_context(caller_context, context_def): - """ - - Generates the context for the next layer. - - - caller_context: The context of the caller. - context_def: The definition of the context - - - RepyArgumentError if the definition is invalid. - - - A SafeDict execution context. - """ - # Wrap all the references in a SafeDict - wrapped_context = SafeDict(wrap_references(context_def)) - - # Provide a reference to itself - wrapped_context["_context"] = wrapped_context - - # Provide a clean mycontext dictionary - wrapped_context["mycontext"] = {} - - # Try to copy in callargs and callfunc - if "callfunc" in caller_context and type(caller_context["callfunc"]) is str: - wrapped_context["callfunc"] = caller_context["callfunc"] - - if "callargs" in caller_context and type(caller_context["callargs"]) is list: - # Offset the list by 1 - offset_args = caller_context["callargs"][1:] - - # If they are all strings, copy over - for elem in offset_args: - if type(elem) is not str: - break - else: - wrapped_context["callargs"] = offset_args - - # Generate a new CHILD_CONTEXT_DEF - new_def = _layer_generic_def(wrapped_context, context_def) - wrapped_context["CHILD_CONTEXT_DEF"] = new_def - - # Generate a layer-specific secure_dispatch_module - dispatch_func = _layer_instance_dispatch(wrapped_context, new_def) - wrapped_context["secure_dispatch_module"] = dispatch_func - - # Return the context - return wrapped_context - - -# Takes the definition used to generate a context -# and generates a generic definition can can be used -# to just copy the existing references -def _layer_generic_def(built_context, context_def): - # Create a new definition dict - new_def = {} - - # Just map the reference to any, this will result - # in a simple copy of the reference - for key in context_def: - new_def[key] = {TYPE:ANY, - TARGET:built_context[key]} - - # Return the new definition - return new_def - - -# Returns a new function which calls secure_dispatch -# using the specified caller, and a default context -# definition dictionary. -def _layer_instance_dispatch(caller, default_definition): - - def _secure_dispatch_closure(context_def=None): - # Check if we should use the default definition - if context_def is None: - context_def = default_definition - - # Call secure dispatch - secure_dispatch(caller, context_def) - - # Return this new closure - return _secure_dispatch_closure - - -#### Support for dispatch #### - -# Securely dispatches the next security layer -def secure_dispatch(caller_context, context_def): - """ - - Wraps the references provided by a security layer and - dispatches the next security layer. - - - caller_context: - The context of the caller. - - context_def: - The definition of the context for the next layer - - - As with the module being evaluated. An exception will be raised - if the module to be evaluated cannot be initialized in a VirtualNamespace - due to safety or syntax problems, or if the module does not exist. - - If the definition of the context is invalid, a RepyArgumentError will - be raised. - - - Execution will switch to the next module. - - - True if a recursive evaluation was performed, false otherwise. - """ - # Check that there is a next module - if not "callargs" in caller_context or len(caller_context["callargs"]) == 0: - return False - - # Get the next layer to run - next_layer = caller_context["callargs"][0] - - # Get the code for the layer - virt = _layer_code(next_layer) - - # Get the evaluation context for the layer - eval_context = _layer_context(caller_context, context_def) - - # Evaluate the new security layer - virt.evaluate(eval_context) - - # Return success - return True - - -#### Dispatch the next module #### - -# Import the wrapper module -_import_wrapper() - -# Build INIT_DEFINITION -_build_INIT_DEFINITION() - -# Dispatch now -secure_dispatch(_context, INIT_DEFINITION) - - From 384c094c8c7e7f11f39cb4cc997d2525c176b6fb Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Thu, 2 Jul 2015 13:47:01 -0700 Subject: [PATCH 45/60] add geocode call --- getsensor.r2py | 52 +++++++++++++++++++++++++++++++++++++++-------- sensor_layer.r2py | 9 ++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index ce2b3f5..eeb35bd 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -66,9 +66,9 @@ def get_location(): GPS or network location lookup. - location as a dict, such as {u'network': {u'bearing': 0, u'altitude': 0, - u'time': x, u'longitude': x, u'provider': u'network', u'latitude': x, - u'speed': 0, u'accuracy': x}}. + location as a dict, such as {'bearing': 0, 'altitude': 0, + 'time': x, 'longitude': x, 'provider': 'network', 'latitude': x, + 'speed': 0, 'accuracy': x}. """ @@ -120,11 +120,11 @@ def get_lastknown_location(): location as a dict with three keys: passive, network, and gps. Each key value is a dict in the same format as the value returned by get_location(). - For example, {u'passive': {u'bearing': 0, u'altitude': 0, u'time': x, - u'longitude': x, u'provider': u'network', u'latitude': s, u'speed': 0, - u'accuracy': x}, u'network': {u'bearing': 0, u'altitude': 0, u'time': x, - u'longitude': x, u'provider': u'network', u'latitude': x, u'speed': 0, - u'accuracy': x}, u'gps': None} + For example, {'passive': {'bearing': 0, 'altitude': 0, 'time': x, + 'longitude': x, 'provider': 'network', 'latitude': s, 'speed': 0, + 'accuracy': x}, 'network': {'bearing': 0, 'altitude': 0, 'time': x, + 'longitude': x, 'provider': 'network', 'latitude': x, 'speed': 0, + 'accuracy': x}, 'gps': None} """ @@ -152,6 +152,42 @@ def get_lastknown_location(): return location +def get_geolocation(latitude, longitude, max_results): + """ + + Obtain a list of addresses for the given latitude and longitude. Calls + sensorlib.request_data(sensor_socket, 'geocode', [latitude, longitude, + max_results]). The addresses information is returned as a dict, which + is converted to ASCII using unicode_scrubber. + + + latitude (double): latitude of a location; + longitude (double): longitude of a location; + max_results (Integer): maximum number of results (normally =1). + + + None. + + + None. + + + Geolocation lookup. + + + Geolocation (address) as a list, such as [{'thoroughfare': 'Some + Street', 'locality': u'Some Town', 'sub_admin_area': 'Some Borough', + 'admin_area': 'Some City', 'feature_name': 'House Numbers', + 'country_code': 'GB', 'country_name': 'United Kingdom', + 'postal_code': 'ST1 1'}] . + + """ + + address = sensorlib.request_data(sensor_socket, 'geocode', + [latitude, longitude, max_results]) + return unicode_scrubber.scrub(address) + + ################################################## ############## WiFi interface ################### diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 6c499b8..a096edc 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -26,6 +26,15 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } +CHILD_CONTEXT_DEF["get_geolocation"] = { + "type": "func", + "args": (double, double, int), + "return": list, + "exceptions": "any", + "target": getsensor.get_geolocation, +} + + CHILD_CONTEXT_DEF["is_wifi_enabled"] = { "type": "func", "args": None, From 599c5595fdb4dc5b01d85b7a2245b5d4b73e657d Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 04:56:02 -0400 Subject: [PATCH 46/60] change method to find closest state (reduce file downloads) --- blur_location2city.r2py | 29 ++++----- blur_location2state.r2py | 131 +++++++++++++-------------------------- sensor_layer.r2py | 2 +- 3 files changed, 56 insertions(+), 106 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index 5014e49..d4b9fa1 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -42,22 +42,21 @@ def load_city_geodata(filename): city_dict = {} city_geodata_fileobj = openfile(filename, False) city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + city_geodata_fileobj.close() for line in city_geodata_file: - # Ignore the empty line at the end of the file + # Ignore the empty line at the end of the file. if line == "": continue city_geodata_record = line.split("\t") city_name = city_geodata_record[0] - lat = float(city_geodata_record[1]) - lon = float(city_geodata_record[2]) city_dict[city_name] = { - "latitude": lat, - "longitude": lon, + "latitude": float(city_geodata_record[1]), + "longitude": float(city_geodata_record[2]), "country_code": city_geodata_record[3], "state_code": city_geodata_record[4] } - city_geodata_fileobj.close() + return city_dict @@ -110,18 +109,14 @@ def find_closest_city(lat, lon): city_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_city_latitude = city_geodata["latitude"] - closest_city_longitude = city_geodata["longitude"] closest_city_name = city_name - closest_city_state_code = city_geodata["state_code"] - closest_city_country_code = city_geodata["country_code"] closest_city_geodata = { "city_name": closest_city_name, - "latitude": closest_city_latitude, - "longitude": closest_city_longitude, - "state_code": closest_city_state_code, - "country_code": closest_city_country_code + "latitude": city_dict[closest_city_name]["latitude"], + "longitude": city_dict[closest_city_name]["longitude"], + "state_code": city_dict[closest_city_name]["state_code"], + "country_code": city_dict[closest_city_name]["country_code"] } return closest_city_geodata @@ -137,7 +132,7 @@ def get_database_filename(lat, lon): # Get ceiling as x/y index. x = int(math.math_ceil(lat)) y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + '.txt' + filename = str(x) + '_' + str(y) + ".txt" return filename @@ -185,7 +180,7 @@ def get_city_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider + # Get the location from every provider. for location_provider, provider_location_data in location_data.items(): # Skip blurring this provider's data if it doesn't contain a previous # location. @@ -223,5 +218,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } -# Dispatch +# Dispatch. secure_dispatch_module() \ No newline at end of file diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 3108372..8997349 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -36,44 +36,37 @@ Usage: httpretrieve = dy_import_module("httpretrieve.r2py") math = dy_import_module("math.r2py") -statefilename = "states.txt" - -def load_city_geodata(filename): +def load_states_geodata(filename): """ - Loads all the cities and their geodata from the given file into a + Loads all the states and their geodata from the given file into a dictionary. The dictionary that is returned has the format: { - city1: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, - city2: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, + state1: {"latitude": latitude, "longitude": longitude}, + state2: {"latitude": latitude, "longitude": longitude}, ... } """ get_file_from_server(filename) - city_dict = {} - city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") + states_dict = {} + states_geodata_fileobj = openfile(filename.lower(), False) + states_geodata_file = states_geodata_fileobj.readat(None, 0).split("\n") + states_geodata_fileobj.close() - for line in city_geodata_file: - # Ignore the empty line at the end of the file + for line in states_geodata_file: + # Ignore the empty line at the end of the file. if line == "": continue - city_geodata_record = line.split("\t") - city_name = city_geodata_record[0] - lat = float(city_geodata_record[1]) - lon = float(city_geodata_record[2]) - city_dict[city_name] = { - "latitude": lat, - "longitude": lon, - "country_code": city_geodata_record[3], - "state_code": city_geodata_record[4] + state_geodata_record = line.split("\t") + state_name = state_geodata_record[1] + states_dict[state_name] = { + "latitude": float(state_geodata_record[2]), + "longitude": float(state_geodata_record[3]), } - city_geodata_fileobj.close() - return city_dict + + return states_dict @@ -84,15 +77,12 @@ def get_file_from_server(filename): """ if filename not in listfiles(): - if filename == statefilename: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - httpretrieve.httpretrieve_save_file(url, filename) + url = "http://sensibilityclearinghouse.poly.edu/data/states/" + filename + httpretrieve.httpretrieve_save_file(url, filename.lower()) -def find_closest_city(lat, lon): +def find_closest_state(lat, lon): """ Finds the city closest to the given latitude/longitude pair from the dictionary of cities returned by the load_city_geodata() function, @@ -115,34 +105,28 @@ def find_closest_city(lat, lon): # Determine which file to download from the database. filename = get_database_filename(lat, lon) - # Load all the cities and their geodata from the file. - city_dict = load_city_geodata(filename) + # Load all the states and their geodata from the file. + states_dict = load_states_geodata(filename) # Set the minimum squared difference between two pairs of coordinates # to a number larger than any possible minimum distance to a close - # city in the current latitude/longitude quadrilateral. + # state in the current country. min_diff = 9999 - for city_name, city_geodata in city_dict.items(): - diff = find_squared_difference((lat, lon), (city_geodata["latitude"], - city_geodata["longitude"])) + for state_name, state_geodata in states_dict.items(): + diff = find_squared_difference((lat, lon), (state_geodata["latitude"], + state_geodata["longitude"])) if diff < min_diff: min_diff = diff - closest_city_latitude = city_geodata["latitude"] - closest_city_longitude = city_geodata["longitude"] - closest_city_name = city_name - closest_city_state_code = city_geodata["state_code"] - closest_city_country_code = city_geodata["country_code"] - - closest_city_geodata = { - "city_name": closest_city_name, - "latitude": closest_city_latitude, - "longitude": closest_city_longitude, - "state_code": closest_city_state_code, - "country_code": closest_city_country_code + closest_state_name = state_name + + closest_state_geodata = { + "state_name": closest_state_name, + "latitude": states_dict[closest_state_name]["latitude"], + "longitude": states_dict[closest_state_name]["longitude"], } - return closest_city_geodata + return closest_state_geodata @@ -152,10 +136,9 @@ def get_database_filename(lat, lon): latitude/longitude pair belongs. """ - # Get ceiling as x/y index. - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + '.txt' + # Get the first address in the list of addresses + address = get_geolocation(lat, lon, 1)[0] + filename = address["country_code"] + ".txt" return filename @@ -184,25 +167,11 @@ def get_state_location(): """ location_data = get_location() - closest_city = find_closest_city(location_data["latitude"], + closest_state = find_closest_state(location_data["latitude"], location_data["longitude"]) - code = closest_city["country_code"] + "." + str(closest_city["state_code"]) - - # Download the states.txt database - get_file_from_server(statefilename) - - state_fileobj = openfile(statefilename, False) - state_file = state_fileobj.readat(None, 0).split("\n") - - # Look for the state corresponding to the code - for line in state_file: - state_record = line.split("\t") - if code == state_record[0]: - location_data["latitude"] = state_record[2] - location_data["longitude"] = state_record[3] - break - state_fileobj.close() + location_data["latitude"] = closest_state["latitude"] + location_data["longitude"] = closest_state["longitude"] return location_data @@ -224,25 +193,11 @@ def get_state_lastknown_location(): if provider_location_data is None: continue - closest_city = find_closest_city(provider_location_data["latitude"], + closest_state = find_closest_state(provider_location_data["latitude"], provider_location_data["longitude"]) - - code = closest_city["country_code"] + "." + str(closest_city["state_code"]) - - # Download the states.txt database - get_file_from_server(statefilename) - - state_fileobj = openfile(statefilename, False) - state_file = state_fileobj.readat(None, 0).split("\n") - - # Look for the state corresponding to the code - for line in state_file: - state_record = line.split("\t") - if code == state_record[0]: - provider_location_data["latitude"] = state_record[2] - provider_location_data["longitude"] = state_record[3] - break - state_fileobj.close() + + location_data[location_provider]["latitude"] = closest_state["latitude"] + location_data[location_provider]["longitude"] = closest_state["longitude"] return location_data diff --git a/sensor_layer.r2py b/sensor_layer.r2py index a096edc..c9218c1 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -28,7 +28,7 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { CHILD_CONTEXT_DEF["get_geolocation"] = { "type": "func", - "args": (double, double, int), + "args": (float, float, int), "return": list, "exceptions": "any", "target": getsensor.get_geolocation, From 1b1e462e3785008ad4e2265814cfae1139e3da92 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 06:23:52 -0400 Subject: [PATCH 47/60] blur to zipcode area --- blur_location2zipcode.r2py | 213 +++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 blur_location2zipcode.r2py diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py new file mode 100644 index 0000000..a3ca6e1 --- /dev/null +++ b/blur_location2zipcode.r2py @@ -0,0 +1,213 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of approximately the nearest ZIP code. + +The blurring is done using a database lookup method. The database, +located at http://sensibilityclearinghouse.poly.edu/data/zip/, contains +a list of ZIP codes and their geodata (country, area, state, latitude, +longitude), divided by their latitude/longitude coordinates into cells. +Each cell is a separate file in the database, whose name is derived as +"ceiling(latitude)_ceiling(longitude).txt". For example, if a location +has coordinates 40.78343, -73.96625, it will be mapped to the file with +name "41_-73.txt". + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2zipcode.r2py user-program.r2py +""" + + + +httpretrieve = dy_import_module("httpretrieve.r2py") +math = dy_import_module("math.r2py") + + + +def load_zipcodes_geodata(filename): + """ + Loads all the ZIP codes and their latitude/longitude coordinates from + the given file into a dictionary. The dictionary that is returned + has the format: + { + zipcode1: {"latitude": latitude, "longitude": longitude}, + zipcode2: {"latitude": latitude, "longitude": longitude}, + ... + } + + """ + get_file_from_server(filename) + zipcodes_dict = {} + zipcodes_geodata_fileobj = openfile(filename, False) + zipcodes_geodata_file = zipcodes_geodata_fileobj.readat(None, 0).split("\n") + zipcodes_geodata_fileobj.close() + + for line in zipcodes_geodata_file: + # Ignore the empty line at the end of the file. + if line == "": + continue + zipcode_geodata_record = line.split("\t") + zipcode = zipcode_geodata_record[1] + zipcodes_dict[int(zipcode)] = { + "latitude": float(zipcode_geodata_record[4]), + "longitude": float(zipcode_geodata_record[5]), + } + + return zipcodes_dict + + + +def get_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/zip/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def find_closest_zipcode(lat, lon): + """ + Finds the ZIP code closest to the given latitude/longitude pair from the + dictionary of ZIP codes returned by the load_zipcodes_geodata() function, + and returns that ZIP code's coordinates in the format: + { + "zipcode": ZIP code (int), + "latitude": latitude of the center of the ZIP code area (float) + "longitude": longitude of the center of the ZIP code area (float) + } + + Note: We're looking for the closest ZIP code within the same cell as + the given latitude/longitude pair. There might be a closer ZIP code + area in the surrounding cells. + + """ + # Determine which file to download from the database. + filename = get_database_filename(lat, lon) + + # Load all the ZIP codes and their geodata from the file. + zipcodes_dict = load_zipcodes_geodata(filename) + + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # ZIP code area in the current latitude/longitude quadilateral. + min_diff = 9999 + + for zipcode, zipcode_geodata in zipcodes_dict.items(): + diff = find_squared_difference((lat, lon), (zipcode_geodata["latitude"], + zipcode_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_zipcode = zipcode + + closest_zipcode_geodata = { + "zipcode": closest_zipcode, + "latitude": zipcodes_dict[closest_zipcode]["latitude"], + "longitude": zipcodes_dict[closest_zipcode]["longitude"], + } + + return closest_zipcode_geodata + + + +def get_database_filename(lat, lon): + """ + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. + + """ + # Get ceiling as x/y index. + x = int(math.math_ceil(lat)) + y = int(math.math_ceil(lon)) + filename = str(x) + '_' + str(y) + ".txt" + return filename + + + +def find_squared_difference(p1, p2): + """ + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). + + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff + + + +def get_zipcode_location(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the nearest ZIP code area. + + """ + location_data = get_location() + + closest_zipcode = find_closest_zipcode(location_data["latitude"], + location_data["longitude"]) + + location_data["latitude"] = closest_zipcode["latitude"] + location_data["longitude"] = closest_zipcode["longitude"] + + return location_data + + + +def get_zipcode_lastknown_location(): + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the nearest ZIP code area. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], + provider_location_data["longitude"]) + + location_data[location_provider]["latitude"] = closest_zipcode["latitude"] + location_data[location_provider]["longitude"] = closest_zipcode["longitude"] + + return location_data + + + +# Mapping our blurring function get_zipcode_location to get_location. +CHILD_CONTEXT_DEF["get_location"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": get_zipcode_location, +} + + +# Mapping our blurring function get_zipcode_lastknown_location to +# get_lastknown_location. +CHILD_CONTEXT_DEF["get_lastknown_location"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": get_zipcode_lastknown_location, +} + + +# Dispatch +secure_dispatch_module() \ No newline at end of file From b4dd0a3ed127beecab44e30246a934d7c5052899 Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 6 Jul 2015 23:39:11 -0400 Subject: [PATCH 48/60] add function to lookup by state name (improve accuracy) --- blur_location2state.r2py | 98 ++++++++++++++++++++++---------------- blur_location2zipcode.r2py | 10 ++-- 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 8997349..9cca592 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -2,18 +2,16 @@ A security layer for the functions get_location() and get_lastknown_location() defined in getsensor.r2py. This program blurs the latitude/longitude coordinates, received from the location sensors of an Android device, -to the geographic center of approximately the nearest state. - -The blurring is done using a database lookup method. First, we find the -city closest to the original latitude/longitude coordinates from the -cities' database and extract the geodata associated with it. This -database, located at http://sensibilityclearinghouse.poly.edu/data/quad/, -contains a list of cities and their geodata (latitude, longitude, -country code, state code), divided by their coordinates into cells. -Each cell is a separate file in the database, whose name is derived -as "ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan -has its center at coordinates 40.78343, -73.96625, so it will be mapped -to the file with name "41_-73.txt". +to the geographic center of approximately the nearest state (admin division). + +The blurring is done using a database lookup method. First, we use the +get_geolocation() call to get the current address. The country code in +the address returned is then used to look up the list of states for +that country from the database. This database, located at +http://sensibilityclearinghouse.poly.edu/data/states/, is a list of all +states/admin divisions and their corresponding geodata (state code, +latitude, longitude) divided by country, where each file is named with +the 2-letter country code (e.g., "US.txt"). Next, we use the state code and country code from the city's geodata to look up the coordinates of the geographic center of the state to which @@ -38,7 +36,7 @@ math = dy_import_module("math.r2py") -def load_states_geodata(filename): +def load_state_geodata(filename, address): """ Loads all the states and their geodata from the given file into a dictionary. The dictionary that is returned has the format: @@ -49,12 +47,29 @@ def load_states_geodata(filename): } """ - get_file_from_server(filename) states_dict = {} states_geodata_fileobj = openfile(filename.lower(), False) states_geodata_file = states_geodata_fileobj.readat(None, 0).split("\n") states_geodata_fileobj.close() + # Check if we can match the state name in the given address to the + # name in the database. If there is a match, return a dict with that + # state and its geodata. + if "admin_area" in address: + for line in states_geodata_file: + # Ignore the empty line at the end of the file. + if line == "": + continue + state_geodata_record = line.split("\t") + if address["admin_area"] == state_geodata_record[1]: + states_dict[address["admin_area"]] = { + "latitude": float(state_geodata_record[2]), + "longitude": float(state_geodata_record[3]), + } + return states_dict + + # If no match, return a dict of all states and their geodata to + # find the closest state. for line in states_geodata_file: # Ignore the empty line at the end of the file. if line == "": @@ -102,23 +117,37 @@ def find_closest_state(lat, lon): surrounding cells. """ - # Determine which file to download from the database. - filename = get_database_filename(lat, lon) - # Load all the states and their geodata from the file. - states_dict = load_states_geodata(filename) + # Get the address for the given coordinates. + address = get_geolocation(lat, lon, 1)[0] + + # Use the country code to get the filename of the list of states + # for that country. + filename = address["country_code"] + ".txt" + + # Download the file from the server. + get_file_from_server(filename) + + # Load the state(s) and corresponding geodata from the file. + states_dict = load_state_geodata(filename, address) + + # Check if there is only one state in the dictionary. + if len(states_dict) == 1: + closest_state_name = states_dict.keys()[0] - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # state in the current country. - min_diff = 9999 + # Else find closest state. + else: + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # state in the current country. + min_diff = 9999 - for state_name, state_geodata in states_dict.items(): - diff = find_squared_difference((lat, lon), (state_geodata["latitude"], - state_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_state_name = state_name + for state_name, state_geodata in states_dict.items(): + diff = find_squared_difference((lat, lon), (state_geodata["latitude"], + state_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_state_name = state_name closest_state_geodata = { "state_name": closest_state_name, @@ -130,19 +159,6 @@ def find_closest_state(lat, lon): -def get_database_filename(lat, lon): - """ - Returns the filename of the cell in the database to which the given - latitude/longitude pair belongs. - - """ - # Get the first address in the list of addresses - address = get_geolocation(lat, lon, 1)[0] - filename = address["country_code"] + ".txt" - return filename - - - def find_squared_difference(p1, p2): """ Returns the squared difference between the two given pairs of diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index a3ca6e1..1f4f5b3 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -6,7 +6,7 @@ to the geographic center of approximately the nearest ZIP code. The blurring is done using a database lookup method. The database, located at http://sensibilityclearinghouse.poly.edu/data/zip/, contains -a list of ZIP codes and their geodata (country, area, state, latitude, +a list of ZIP codes and their geodata (2-letter country code, latitude, longitude), divided by their latitude/longitude coordinates into cells. Each cell is a separate file in the database, whose name is derived as "ceiling(latitude)_ceiling(longitude).txt". For example, if a location @@ -50,8 +50,8 @@ def load_zipcodes_geodata(filename): zipcode_geodata_record = line.split("\t") zipcode = zipcode_geodata_record[1] zipcodes_dict[int(zipcode)] = { - "latitude": float(zipcode_geodata_record[4]), - "longitude": float(zipcode_geodata_record[5]), + "latitude": float(zipcode_geodata_record[2]), + "longitude": float(zipcode_geodata_record[3]), } return zipcodes_dict @@ -171,7 +171,7 @@ def get_zipcode_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider + # Get the location from every provider. for location_provider, provider_location_data in location_data.items(): # Skip blurring this provider's data if it doesn't contain a previous # location. @@ -209,5 +209,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } -# Dispatch +# Dispatch. secure_dispatch_module() \ No newline at end of file From c01e680227974f6ee9a64b37b7a620feafe03d9b Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 7 Jul 2015 13:23:12 -0700 Subject: [PATCH 49/60] change double to float in geocode --- getsensor.r2py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index eeb35bd..35be51c 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -161,8 +161,8 @@ def get_geolocation(latitude, longitude, max_results): is converted to ASCII using unicode_scrubber. - latitude (double): latitude of a location; - longitude (double): longitude of a location; + latitude (float): latitude of a location; + longitude (float): longitude of a location; max_results (Integer): maximum number of results (normally =1). From 64ed85c960cb7283818e4d5b825350598a04ad6f Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 14 Jul 2015 19:07:48 +0530 Subject: [PATCH 50/60] change to match city and state blur layers reduced number of files to download and the number of operations to perform --- blur_location2country.r2py | 284 ++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 161 deletions(-) diff --git a/blur_location2country.r2py b/blur_location2country.r2py index 1e8081f..9c90b58 100644 --- a/blur_location2country.r2py +++ b/blur_location2country.r2py @@ -1,185 +1,143 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +to the geographic center of the country to which it belongs. + +The blurring is done using a database lookup method. First, we use the +get_geolocation() call to get the current address. The country code +("country_code") in the address returned is then used to find a match +in the database "countries.txt", which is a list of all countries and +their geodata (country code, latitude, longitude). The country code is +the ISO-3166 2-letter code assigned to the country and the latitude and +longitude coordinates represent the geographical center of the country. +This database file is located at: +http://sensibilityclearinghouse.poly.edu/data/ + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location2country.r2py user-program.r2py +""" + + + httpretrieve = dy_import_module("httpretrieve.r2py") math = dy_import_module("math.r2py") -librepyfile = dy_import_module("librepyfile.r2py") -statefilename = "states.txt" # Database of states -countryfilename = "countries.txt" # Database of countries -# Downloads the required file from the server def get_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + httpretrieve.httpretrieve_save_file(url, filename.lower()) + + + +def load_country_geodata(address): + """ + Finds the country in the database which has the same country code as + that in the given address and returns a dictionary with that country's + name, latitude and longitude. + + Below is an example of a line from the database of countries - + "countries.txt" (country code, name, latitude and longitude): + US United States 39.76 -98.5 + + The dictionary returned has the format: + { + "country_name": state name (string), + "latitude": latitude of the geographic center of the country (float) + "longitude": longitude of the geographic center of the country (float) + } + + """ + # Download the database of countries. + get_file_from_server("countries.txt") + + # Open the database of countries and read all data. + countries_geodata_fileobj = openfile("countries.txt", False) + countries_geodata_file = countries_geodata_fileobj.readat(None, 0).split("\n") + countries_geodata_fileobj.close() + + # Compare the country code from the address with the country code for + # each country in the database to find a match. + for line in countries_geodata_file: + # Ignore the empty line at the end of the file. + if line == "": + continue + country_geodata_record = line.split("\t") + # If there is a match, return the country name and its coordinates. + if address["country_code"] == country_geodata_record[0]: + country_geodata = { + "country_name": country_geodata_record[1], + "latitude": float(country_geodata_record[2]), + "longitude": float(country_geodata_record[3]) + } + return country_geodata + + # XXX will there ever not be a match? - if filename not in listfiles(): # In case it already exists - if filename not in [statefilename, countryfilename]: - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - else: - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - httpretrieve.httpretrieve_save_file(url, filename) - - -# Returns a dictionary containing information about the point closest to -# a given lat/lng pair, from the database. -# {"city": closest_city, "statecode": closest_state_code, "countrycode": -# closest_country_code, "coordinates": closest_point} -def find_closest_point(lat, lng): - - # Find the database file with coordinates closest to the given lat/lng pair - filename = get_filename(lat, lng) - # Get the list of coordinates from that file - listofpoints = load_lat_lng_from_file(filename) - - min_dist = 9999 - point1 = (lat, lng) - - for city in listofpoints.keys(): - data = listofpoints[city] - point2 = (data[0], data[1]) - dist = find_distance(point1, point2) - if dist < min_dist: - min_dist = dist - closest_point = point2 - closest_city = city - closest_state_code = data[3] - closest_country_code = data[2] - - closest = {"city": closest_city, "statecode": closest_state_code, "countrycode": closest_country_code, "coordinates": closest_point} - - return closest - - -# Returns the filename in the database with coordinates closest to the given -# lat/lng pair -def get_filename(lat, lng): - - # get ceiling as x/y index - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lng)) - filename = str(x) + '_' + str(y) + '.txt' - return filename - - -# Returns a dictionary containing all the cities in the given file, along with -# their corresponding data -# {city1: [lat, lng, country_code, state_code], city2: [lat, lng, country_code, -# state_code], ...} -def load_lat_lng_from_file(filename): - - get_file_from_server(filename) - listofpoints = {} - fileobj = librepyfile.open(filename, "r") - - while True: - try: - line = fileobj.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - city_name = line[0] - lat = line[1] - lng = line[2] - country_code = line[3] - state_code = line[4] - listofpoints[city_name] = [lat, lng, country_code, state_code] - fileobj.close() - return listofpoints - - -# Returns the distance between two lat/lng points -def find_distance(p1, p2): - - (lat1, lng1) = p1 - (lat2, lng2) = p2 - lat2 = float(lat2) - lng2 = float(lng2) - lat_diff = (lat1-lat2) * (lat1-lat2) - lng_diff = (lng1-lng2) * (lng1-lng2) - # return squared distance - return lat_diff + lng_diff - - -# To replace get_location() -def get_country_location(): - - try: - location_data = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - latitude = location_data["latitude"] - longitude = location_data["longitude"] - closest = find_closest_point(latitude, longitude) - country_code = closest["countrycode"] +def get_country_location(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates for the + geographic center of the country to which they belong. - # Download the Countries database - get_file_from_server(countryfilename) + """ + location_data = get_location() - countryfile = librepyfile.open(countryfilename, "r") + # Get the first address from the list of addresses returned by + # get_geolocation(). + address = get_geolocation(location_data["latitude"], + location_data["longitude"], 1)[0] - # Look for the country corresponding to the country code - while True: - try: - line = countryfile.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - if country_code == line[0]: - clat = line[2] - clng = line[3] - break - countryfile.close() + country_geodata = load_country_geodata(address) - location_data["latitude"] = clat - location_data["longitude"] = clng + location_data["latitude"] = country_geodata["latitude"] + location_data["longitude"] = country_geodata["longitude"] return location_data + + def get_country_lastknown_location(): - # to replace get_lastknown_location() - try: - location_data = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception - - # Get the location from the the provider - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - latitude = location["latitude"] - longitude = location["longitude"] - - closest = find_closest_point(latitude, longitude) - - country_code = closest["countrycode"] - - # Download the Countries database - get_file_from_server(countryfilename) - - countryfile = librepyfile.open(countryfilename, "r") - - # Look for the country corresponding to the country code - while True: - try: - line = countryfile.next().strip() - except StopIteration: - break - else: - line = line.split("\t") - if country_code == line[0]: - clat = line[2] - clng = line[3] - break - countryfile.close() - - location_data[provider]["latitude"] = clat - location_data[provider]["longitude"] = clng + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + for the geographic center of the country to which they belong. + + """ + location_data = get_lastknown_location() + + # Get the location from every provider. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + + # Get the first address from the list of addresses returned by + # get_geolocation(). + address = get_geolocation(provider_location_data["latitude"], + provider_location_data["longitude"], 1)[0] + + country_geodata = load_country_geodata(address) + + location_data[location_provider]["latitude"] = country_geodata["latitude"] + location_data[location_provider]["longitude"] = country_geodata["longitude"] return location_data + +# Mapping our blurring function get_country_location to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -189,6 +147,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function get_country_lastknown_location to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -197,4 +157,6 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { "target": get_country_lastknown_location, } + +# Dispatch. secure_dispatch_module() \ No newline at end of file From 3124a4edc1f072f0dbebffa1d3a9ef8e8f79bedd Mon Sep 17 00:00:00 2001 From: aditup Date: Tue, 14 Jul 2015 19:11:32 +0530 Subject: [PATCH 51/60] refactor common parts into location_blur_helper --- blur_location2city.r2py | 142 ++++++++++--------------------- blur_location2country.r2py | 144 ++++++++++++++++++------------- blur_location2state.r2py | 170 ++++++++++++++----------------------- blur_location2zipcode.r2py | 134 ++++++++++------------------- location_blur_helper.r2py | 164 +++++++++++++++++++++++++++++++++++ 5 files changed, 398 insertions(+), 356 deletions(-) create mode 100644 location_blur_helper.r2py diff --git a/blur_location2city.r2py b/blur_location2city.r2py index d4b9fa1..a51063c 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -6,12 +6,11 @@ to the geographic center of approximately the nearest city. The blurring is done using a database lookup method. The database, located at http://sensibilityclearinghouse.poly.edu/data/quad/, contains -a list of cities and their geodata (latitude, longitude, country code, -state code), divided by their latitude/longitude coordinates into cells. -Each cell is a separate file in the database, whose name is derived as -"ceiling(latitude)_ceiling(longitude).txt". For example, Manhattan has -its center at coordinates 40.78343, -73.96625, so it will be mapped to -the file with name "41_-73.txt". +a list of cities and their geodata, divided by their latitude/longitude +coordinates into cells. Each cell is a separate file in the database, +whose name is derived as "ceiling(latitude)_ceiling(longitude).txt". +For example, if a location has coordinates (40.78343, -73.96625), it +will be mapped to the file with name "41_-73.txt". Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -20,31 +19,39 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") +location_blur_helper = dy_import_module("location_blur_helper.r2py") -def load_city_geodata(filename): +def load_city_geodata(lat, lon): """ - Loads all the cities and their geodata from the given file into a - dictionary. The dictionary that is returned has the format: + Loads all cities and corresponding geodata from the given file + into a dictionary. + + Below is an example of a line from the file + http://sensibilityclearinghouse.poly.edu/data/quad/41_-73.txt, + with fields - city name, latitude, longitude, country code, state + code: + Manhattan 40.78343 -73.96625 US NY + + The dictionary that is returned has the format: { - city1: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, - city2: {"latitude": latitude, "longitude": longitude, "country_code": - country_code, "state_code": state_code}, + city1: {"latitude": latitude, "longitude": longitude}, + city2: {"latitude": latitude, "longitude": longitude}, ... } """ - get_file_from_server(filename) + # Determine which file to download from the database. + filename = location_blur_helper.get_database_filename(lat, lon) + # Download the file from the city database. + location_blur_helper.get_city_file_from_server(filename) + # Obtain the list of cities and their geodata from the file. + cities_geodata = location_blur_helper.read_data_from_file(filename) + city_dict = {} - city_geodata_fileobj = openfile(filename, False) - city_geodata_file = city_geodata_fileobj.readat(None, 0).split("\n") - city_geodata_fileobj.close() - for line in city_geodata_file: + for line in cities_geodata: # Ignore the empty line at the end of the file. if line == "": continue @@ -52,27 +59,13 @@ def load_city_geodata(filename): city_name = city_geodata_record[0] city_dict[city_name] = { "latitude": float(city_geodata_record[1]), - "longitude": float(city_geodata_record[2]), - "country_code": city_geodata_record[3], - "state_code": city_geodata_record[4] + "longitude": float(city_geodata_record[2]) } return city_dict -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename - httpretrieve.httpretrieve_save_file(url, filename) - - - def find_closest_city(lat, lon): """ Finds the city closest to the given latitude/longitude pair from the @@ -80,12 +73,8 @@ def find_closest_city(lat, lon): and returns that city's geodata in the format: { "city_name": city name (string), - "state_code": 2-digit code representing the state to which the city - belongs (string), - "country_code": 2-letter ISO-3166 code representing the country to - which the city belongs (string), - "latitude": latitude of the geographic center of the city (float) - "longitude": longitude of the geographic center of the city (float) + "latitude": latitude of the center of the city (float) + "longitude": longitude of the center of the city (float) } Note: We're looking for the closest city within the same cell as the @@ -93,62 +82,10 @@ def find_closest_city(lat, lon): surrounding cells. """ - # Determine which file to download from the database. - filename = get_database_filename(lat, lon) - - # Load all the cities and their geodata from the file. - city_dict = load_city_geodata(filename) - - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # city in the current latitude/longitude quadrilateral. - min_diff = 9999 - - for city_name, city_geodata in city_dict.items(): - diff = find_squared_difference((lat, lon), (city_geodata["latitude"], - city_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_city_name = city_name + # Load all cities and corresponding geodata from the file. + city_dict = load_city_geodata(lat, lon) - closest_city_geodata = { - "city_name": closest_city_name, - "latitude": city_dict[closest_city_name]["latitude"], - "longitude": city_dict[closest_city_name]["longitude"], - "state_code": city_dict[closest_city_name]["state_code"], - "country_code": city_dict[closest_city_name]["country_code"] - } - - return closest_city_geodata - - - -def get_database_filename(lat, lon): - """ - Returns the filename of the cell in the database to which the given - latitude/longitude pair belongs. - - """ - # Get ceiling as x/y index. - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + ".txt" - return filename - - - -def find_squared_difference(p1, p2): - """ - Returns the squared difference between the two given pairs of - coordinates (p1 and p2, where p1 and p2 are tuples of the form - (latitude, longitude)). - - """ - lat1, lon1 = p1 - lat2, lon2 = p2 - lat_diff = (lat1-lat2) ** 2 - lon_diff = (lon1-lon2) ** 2 - return lat_diff + lon_diff + return location_blur_helper.find_closest_location(lat, lon, city_dict) @@ -180,9 +117,9 @@ def get_city_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider. + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue @@ -190,6 +127,15 @@ def get_city_lastknown_location(): closest_city = find_closest_city(provider_location_data["latitude"], provider_location_data["longitude"]) + break + + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + location_data[location_provider]["latitude"] = closest_city["latitude"] location_data[location_provider]["longitude"] = closest_city["longitude"] diff --git a/blur_location2country.r2py b/blur_location2country.r2py index 9c90b58..8f4dbc5 100644 --- a/blur_location2country.r2py +++ b/blur_location2country.r2py @@ -5,14 +5,11 @@ coordinates, received from the location sensors of an Android device, to the geographic center of the country to which it belongs. The blurring is done using a database lookup method. First, we use the -get_geolocation() call to get the current address. The country code -("country_code") in the address returned is then used to find a match -in the database "countries.txt", which is a list of all countries and -their geodata (country code, latitude, longitude). The country code is -the ISO-3166 2-letter code assigned to the country and the latitude and -longitude coordinates represent the geographical center of the country. +get_geolocation() call to get the current address. The country code in +the address returned is then used to find a match in the database +"countries.txt", which is a list of all countries and their geodata. This database file is located at: -http://sensibilityclearinghouse.poly.edu/data/ +http://sensibilityclearinghouse.poly.edu/data/countries.txt Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -21,66 +18,92 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") - - - -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/" + filename - httpretrieve.httpretrieve_save_file(url, filename.lower()) +location_blur_helper = dy_import_module("location_blur_helper.r2py") +country_filename = "countries.txt" def load_country_geodata(address): """ - Finds the country in the database which has the same country code as - that in the given address and returns a dictionary with that country's - name, latitude and longitude. + Loads the country (or countries) and corresponding geodata from the + given file into a dictionary. - Below is an example of a line from the database of countries - - "countries.txt" (country code, name, latitude and longitude): + Below is an example of a line from the file "countries.txt" with + fields - country code, country name, latitude and longitude: US United States 39.76 -98.5 The dictionary returned has the format: { - "country_name": state name (string), - "latitude": latitude of the geographic center of the country (float) - "longitude": longitude of the geographic center of the country (float) + country1: {"latitude": latitude, "longitude": longitude}, + country2: {"latitude": latitude, "longitude": longitude}, + ... } """ - # Download the database of countries. - get_file_from_server("countries.txt") + # Download the file from the country database. + location_blur_helper.get_country_file_from_server(country_filename) + # Obtain the list of countries and their geodata from the file. + countries_geodata = location_blur_helper.read_data_from_file(country_filename) - # Open the database of countries and read all data. - countries_geodata_fileobj = openfile("countries.txt", False) - countries_geodata_file = countries_geodata_fileobj.readat(None, 0).split("\n") - countries_geodata_fileobj.close() + country_dict = {} - # Compare the country code from the address with the country code for - # each country in the database to find a match. - for line in countries_geodata_file: + # Check if we can match the country code in the given address to that + # in the database. If there is a match, return a dict with that + # country and its geodata. + for line in countries_geodata: # Ignore the empty line at the end of the file. if line == "": continue country_geodata_record = line.split("\t") - # If there is a match, return the country name and its coordinates. if address["country_code"] == country_geodata_record[0]: - country_geodata = { - "country_name": country_geodata_record[1], + country_name = country_geodata_record[1] + country_dict[country_name] = { "latitude": float(country_geodata_record[2]), "longitude": float(country_geodata_record[3]) } - return country_geodata + return country_dict + + # If no match, return a dict of all countries and their geodata to + # find the closest country. + for line in countries_geodata: + # Ignore the empty line at the end of the file. + if line == "": + continue + country_geodata_record = line.split("\t") + country_name = country_geodata_record[1] + country_dict[country_name] = { + "latitude": float(country_geodata_record[2]), + "longitude": float(country_geodata_record[3]), + } + + return country_dict - # XXX will there ever not be a match? + +def find_closest_country(lat, lon): + """ + Finds the country closest to the given latitude/longitude pair from the + dictionary of countries returned by the load_country_geodata() function, + and returns that country's geodata in the format: + { + "country_name": country name (string), + "latitude": latitude of the center of the country (float) + "longitude": longitude of the center of the country (float) + } + + Note: If the load_country_geodata() function returns only one country, + which happens when the country code from the get_geolocation() call + was successfully matched with one of the countries' code in the database, + then only that country's geodata is returned in the dictionary. + + """ + # Get the address for the given coordinates. Since get_geolocation() + # can possibly return more than one address, we take the first one. + address = get_geolocation(lat, lon, 1)[0] + + # Load the state(s) and corresponding geodata from the file. + countries_dict = load_country_geodata(address) + + return location_blur_helper.find_closest_location(lat, lon, countries_dict) @@ -93,15 +116,11 @@ def get_country_location(): """ location_data = get_location() - # Get the first address from the list of addresses returned by - # get_geolocation(). - address = get_geolocation(location_data["latitude"], - location_data["longitude"], 1)[0] - - country_geodata = load_country_geodata(address) + closest_country = find_closest_country(location_data["latitude"], + location_data["longitude"]) - location_data["latitude"] = country_geodata["latitude"] - location_data["longitude"] = country_geodata["longitude"] + location_data["latitude"] = closest_country["latitude"] + location_data["longitude"] = closest_country["longitude"] return location_data @@ -116,22 +135,27 @@ def get_country_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider. + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue - # Get the first address from the list of addresses returned by - # get_geolocation(). - address = get_geolocation(provider_location_data["latitude"], - provider_location_data["longitude"], 1)[0] + closest_country = find_closest_country(provider_location_data["latitude"], + provider_location_data["longitude"]) + + break - country_geodata = load_country_geodata(address) + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - location_data[location_provider]["latitude"] = country_geodata["latitude"] - location_data[location_provider]["longitude"] = country_geodata["longitude"] + location_data[location_provider]["latitude"] = closest_country["latitude"] + location_data[location_provider]["longitude"] = closest_country["longitude"] return location_data diff --git a/blur_location2state.r2py b/blur_location2state.r2py index 9cca592..e853160 100644 --- a/blur_location2state.r2py +++ b/blur_location2state.r2py @@ -2,27 +2,21 @@ A security layer for the functions get_location() and get_lastknown_location() defined in getsensor.r2py. This program blurs the latitude/longitude coordinates, received from the location sensors of an Android device, -to the geographic center of approximately the nearest state (admin division). +to the geographic center of approximately the nearest state (admin area). The blurring is done using a database lookup method. First, we use the get_geolocation() call to get the current address. The country code in -the address returned is then used to look up the list of states for -that country from the database. This database, located at -http://sensibilityclearinghouse.poly.edu/data/states/, is a list of all -states/admin divisions and their corresponding geodata (state code, -latitude, longitude) divided by country, where each file is named with -the 2-letter country code (e.g., "US.txt"). - -Next, we use the state code and country code from the city's geodata to -look up the coordinates of the geographic center of the state to which -the city belongs. This look up uses the states' database, states.txt, -located at http://sensibilityclearinghouse.poly.edu/data/. states.txt -is a database of the top level administrative divisions within each -country (for example, states/provinces). It has the following fields: -code, state name, latitude, longitude. The code field has the format -"country_code.state_code", where country_code is the ISO-3166 2-letter -country code of the country to which the admin division belongs and -state_code is the 2-digit state code representing the admin division. +the address returned is then used to look up the list of states for +that country from the database. This database, located at +http://sensibilityclearinghouse.poly.edu/data/states/, is a list of +all states and their corresponding geodata divided by country, where +each file is named with the 2-letter country code (e.g., "US.txt"). + +Next, we use the state name from the returned address to check for a +match with the list of states. If there is a match, the coordinates +associated with that state are returned. If there is no match, we look +for the state that has coordinates closest to the those received from +the location sensors and return its latitude and longitude. Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -31,15 +25,21 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") +location_blur_helper = dy_import_module("location_blur_helper.r2py") -def load_state_geodata(filename, address): +def load_state_geodata(address): """ - Loads all the states and their geodata from the given file into a - dictionary. The dictionary that is returned has the format: + Loads the state(s) and corresponding geodata from the given file + into a dictionary. + + Below is an example of a line from the file + http://sensibilityclearinghouse.poly.edu/data/states/US.txt, + with fields - state code, state name, latitude, longitude: + US.NY New York 43.00035 -75.4999 + + The dictionary that is returned has the format: { state1: {"latitude": latitude, "longitude": longitude}, state2: {"latitude": latitude, "longitude": longitude}, @@ -47,22 +47,28 @@ def load_state_geodata(filename, address): } """ + # Use the country code to get the filename of the list of states + # for that country. + filename = address["country_code"] + ".txt" + # Download the file from the state database. + location_blur_helper.get_state_file_from_server(filename) + # Obtain the list of states and their geodata from the file. + states_geodata = location_blur_helper.read_data_from_file(filename) + states_dict = {} - states_geodata_fileobj = openfile(filename.lower(), False) - states_geodata_file = states_geodata_fileobj.readat(None, 0).split("\n") - states_geodata_fileobj.close() # Check if we can match the state name in the given address to the # name in the database. If there is a match, return a dict with that - # state and its geodata. + # state and its geodata (state names are unique in each file). if "admin_area" in address: - for line in states_geodata_file: + for line in states_geodata: # Ignore the empty line at the end of the file. if line == "": continue state_geodata_record = line.split("\t") if address["admin_area"] == state_geodata_record[1]: - states_dict[address["admin_area"]] = { + state_name = state_geodata_record[1] + states_dict[state_name] = { "latitude": float(state_geodata_record[2]), "longitude": float(state_geodata_record[3]), } @@ -70,7 +76,7 @@ def load_state_geodata(filename, address): # If no match, return a dict of all states and their geodata to # find the closest state. - for line in states_geodata_file: + for line in states_geodata: # Ignore the empty line at the end of the file. if line == "": continue @@ -85,92 +91,31 @@ def load_state_geodata(filename, address): -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/states/" + filename - httpretrieve.httpretrieve_save_file(url, filename.lower()) - - - def find_closest_state(lat, lon): """ - Finds the city closest to the given latitude/longitude pair from the - dictionary of cities returned by the load_city_geodata() function, - and returns that city's geodata in the format: + Finds the state closest to the given latitude/longitude pair from the + dictionary of states returned by the load_state_geodata() function, + and returns that state's geodata in the format: { - "city_name": city name (string), - "state_code": 2-digit code representing the state to which the city - belongs (string), - "country_code": 2-letter ISO-3166 code representing the country to - which the city belongs (string), - "latitude": latitude of the geographic center of the city (float) - "longitude": longitude of the geographic center of the city (float) + "state_name": state name (string), + "latitude": latitude of the center of the state (float) + "longitude": longitude of the center of the state (float) } - Note: We're looking for the closest city within the same cell as the - given latitude/longitude pair. There might be a closer city in the - surrounding cells. + Note: If the load_state_geodata() function returns only one state, + which happens when the state name from the get_geolocation() call + was successfully matched with one of the states in the database, + then only that state's geodata is returned in the dictionary. """ - - # Get the address for the given coordinates. + # Get the address for the given coordinates. Since get_geolocation() + # can possibly return more than one address, we take the first one. address = get_geolocation(lat, lon, 1)[0] - # Use the country code to get the filename of the list of states - # for that country. - filename = address["country_code"] + ".txt" - - # Download the file from the server. - get_file_from_server(filename) - # Load the state(s) and corresponding geodata from the file. - states_dict = load_state_geodata(filename, address) - - # Check if there is only one state in the dictionary. - if len(states_dict) == 1: - closest_state_name = states_dict.keys()[0] - - # Else find closest state. - else: - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # state in the current country. - min_diff = 9999 + states_dict = load_state_geodata(address) - for state_name, state_geodata in states_dict.items(): - diff = find_squared_difference((lat, lon), (state_geodata["latitude"], - state_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_state_name = state_name - - closest_state_geodata = { - "state_name": closest_state_name, - "latitude": states_dict[closest_state_name]["latitude"], - "longitude": states_dict[closest_state_name]["longitude"], - } - - return closest_state_geodata - - - -def find_squared_difference(p1, p2): - """ - Returns the squared difference between the two given pairs of - coordinates (p1 and p2, where p1 and p2 are tuples of the form - (latitude, longitude)). - - """ - lat1, lon1 = p1 - lat2, lon2 = p2 - lat_diff = (lat1-lat2) ** 2 - lon_diff = (lon1-lon2) ** 2 - return lat_diff + lon_diff + return location_blur_helper.find_closest_location(lat, lon, states_dict) @@ -202,16 +147,25 @@ def get_state_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue closest_state = find_closest_state(provider_location_data["latitude"], provider_location_data["longitude"]) - + + break + + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + location_data[location_provider]["latitude"] = closest_state["latitude"] location_data[location_provider]["longitude"] = closest_state["longitude"] diff --git a/blur_location2zipcode.r2py b/blur_location2zipcode.r2py index 1f4f5b3..62c3b13 100644 --- a/blur_location2zipcode.r2py +++ b/blur_location2zipcode.r2py @@ -2,16 +2,15 @@ A security layer for the functions get_location() and get_lastknown_location() defined in getsensor.r2py. This program blurs the latitude/longitude coordinates, received from the location sensors of an Android device, -to the geographic center of approximately the nearest ZIP code. +to the geographic center of approximately the nearest ZIP code area. The blurring is done using a database lookup method. The database, located at http://sensibilityclearinghouse.poly.edu/data/zip/, contains -a list of ZIP codes and their geodata (2-letter country code, latitude, -longitude), divided by their latitude/longitude coordinates into cells. -Each cell is a separate file in the database, whose name is derived as -"ceiling(latitude)_ceiling(longitude).txt". For example, if a location -has coordinates 40.78343, -73.96625, it will be mapped to the file with -name "41_-73.txt". +a list of ZIP codes and their geodata, divided by their latitude/longitude +coordinates into cells. Each cell is a separate file in the database, +whose name is derived as "ceiling(latitude)_ceiling(longitude).txt". +For example, if a location has coordinates (40.78343, -73.96625), it +will be mapped to the file with name "41_-73.txt". Usage: start dylink.r2py encasementlib.r2py sensor_layer.r2py \ @@ -20,16 +19,21 @@ Usage: -httpretrieve = dy_import_module("httpretrieve.r2py") -math = dy_import_module("math.r2py") +location_blur_helper = dy_import_module("location_blur_helper.r2py") -def load_zipcodes_geodata(filename): +def load_zipcode_geodata(lat, lon): """ - Loads all the ZIP codes and their latitude/longitude coordinates from - the given file into a dictionary. The dictionary that is returned - has the format: + Loads all ZIP codes and corresponding geodata from the given file + into a dictionary. + + Below is an example of a line from the file + http://sensibilityclearinghouse.poly.edu/data/zip/41_-73.txt + with fields - country code, ZIP code, latitude, longitude: + US 10012 40.7255 -73.9983 + + The dictionary that is returned has the format: { zipcode1: {"latitude": latitude, "longitude": longitude}, zipcode2: {"latitude": latitude, "longitude": longitude}, @@ -37,19 +41,22 @@ def load_zipcodes_geodata(filename): } """ - get_file_from_server(filename) + # Determine which file to download from the database. + filename = location_blur_helper.get_database_filename(lat, lon) + # Download the file from the ZIP code database. + location_blur_helper.get_zipcode_file_from_server(filename) + # Obtain the list of ZIP codes and their geodata from the file. + zipcodes_geodata = location_blur_helper.read_data_from_file(filename) + zipcodes_dict = {} - zipcodes_geodata_fileobj = openfile(filename, False) - zipcodes_geodata_file = zipcodes_geodata_fileobj.readat(None, 0).split("\n") - zipcodes_geodata_fileobj.close() - for line in zipcodes_geodata_file: + for line in zipcodes_geodata: # Ignore the empty line at the end of the file. if line == "": continue zipcode_geodata_record = line.split("\t") zipcode = zipcode_geodata_record[1] - zipcodes_dict[int(zipcode)] = { + zipcodes_dict[zipcode] = { "latitude": float(zipcode_geodata_record[2]), "longitude": float(zipcode_geodata_record[3]), } @@ -58,25 +65,13 @@ def load_zipcodes_geodata(filename): -def get_file_from_server(filename): - """ - Downloads the required file from the database server, if it has not - already been downloaded. - - """ - if filename not in listfiles(): - url = "http://sensibilityclearinghouse.poly.edu/data/zip/" + filename - httpretrieve.httpretrieve_save_file(url, filename) - - - def find_closest_zipcode(lat, lon): """ Finds the ZIP code closest to the given latitude/longitude pair from the - dictionary of ZIP codes returned by the load_zipcodes_geodata() function, - and returns that ZIP code's coordinates in the format: + dictionary of ZIP codes returned by the load_zipcode_geodata() function, + and returns that ZIP code's geodata in the format: { - "zipcode": ZIP code (int), + "zipcode": ZIP code (string), "latitude": latitude of the center of the ZIP code area (float) "longitude": longitude of the center of the ZIP code area (float) } @@ -86,60 +81,10 @@ def find_closest_zipcode(lat, lon): area in the surrounding cells. """ - # Determine which file to download from the database. - filename = get_database_filename(lat, lon) - - # Load all the ZIP codes and their geodata from the file. - zipcodes_dict = load_zipcodes_geodata(filename) - - # Set the minimum squared difference between two pairs of coordinates - # to a number larger than any possible minimum distance to a close - # ZIP code area in the current latitude/longitude quadilateral. - min_diff = 9999 - - for zipcode, zipcode_geodata in zipcodes_dict.items(): - diff = find_squared_difference((lat, lon), (zipcode_geodata["latitude"], - zipcode_geodata["longitude"])) - if diff < min_diff: - min_diff = diff - closest_zipcode = zipcode - - closest_zipcode_geodata = { - "zipcode": closest_zipcode, - "latitude": zipcodes_dict[closest_zipcode]["latitude"], - "longitude": zipcodes_dict[closest_zipcode]["longitude"], - } - - return closest_zipcode_geodata - - - -def get_database_filename(lat, lon): - """ - Returns the filename of the cell in the database to which the given - latitude/longitude pair belongs. - - """ - # Get ceiling as x/y index. - x = int(math.math_ceil(lat)) - y = int(math.math_ceil(lon)) - filename = str(x) + '_' + str(y) + ".txt" - return filename - + # Load all ZIP codes and corresponding geodata from the file. + zipcodes_dict = load_zipcode_geodata(lat, lon) - -def find_squared_difference(p1, p2): - """ - Returns the squared difference between the two given pairs of - coordinates (p1 and p2, where p1 and p2 are tuples of the form - (latitude, longitude)). - - """ - lat1, lon1 = p1 - lat2, lon2 = p2 - lat_diff = (lat1-lat2) ** 2 - lon_diff = (lon1-lon2) ** 2 - return lat_diff + lon_diff + return location_blur_helper.find_closest_location(lat, lon, zipcodes_dict) @@ -171,16 +116,25 @@ def get_zipcode_lastknown_location(): """ location_data = get_lastknown_location() - # Get the location from every provider. + # Blur the coordinates of the first non-empty location data. for location_provider, provider_location_data in location_data.items(): - # Skip blurring this provider's data if it doesn't contain a previous + # Skip this provider's data if it doesn't contain a previous # location. if provider_location_data is None: continue closest_zipcode = find_closest_zipcode(provider_location_data["latitude"], provider_location_data["longitude"]) - + + break + + # Copy the blurred coordinates into all providers' location data. + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue + location_data[location_provider]["latitude"] = closest_zipcode["latitude"] location_data[location_provider]["longitude"] = closest_zipcode["longitude"] diff --git a/location_blur_helper.r2py b/location_blur_helper.r2py new file mode 100644 index 0000000..8206c72 --- /dev/null +++ b/location_blur_helper.r2py @@ -0,0 +1,164 @@ +""" +This is a helper program that contains some of the common functions +shared between the blurring layers blur_location2city, blur_location2zipcode, +blur_location2state and blur_location2country. + +""" + + + +httpretrieve = dy_import_module("httpretrieve.r2py") +math = dy_import_module("math.r2py") + + + +def get_zipcode_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/zip/ + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/zip/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def get_city_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/quad/ + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/quad/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def get_state_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/states/ + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/states/" + filename + httpretrieve.httpretrieve_save_file(url, filename.lower()) + + + +def get_country_file_from_server(filename): + """ + Downloads the required file from the database server, if it has not + already been downloaded. + + The database is located at: + http://sensibilityclearinghouse.poly.edu/data/countries.txt + + """ + if filename not in listfiles(): + url = "http://sensibilityclearinghouse.poly.edu/data/" + filename + httpretrieve.httpretrieve_save_file(url, filename) + + + +def get_database_filename(lat, lon): + """ + Returns the filename of the cell in the database to which the given + latitude/longitude pair belongs. + + """ + # Get ceiling as x/y index. + x = int(math.math_ceil(lat)) + y = int(math.math_ceil(lon)) + filename = str(x) + '_' + str(y) + ".txt" + return filename + + + +def find_squared_difference(p1, p2): + """ + Returns the squared difference between the two given pairs of + coordinates (p1 and p2, where p1 and p2 are tuples of the form + (latitude, longitude)). + + """ + lat1, lon1 = p1 + lat2, lon2 = p2 + lat_diff = (lat1-lat2) ** 2 + lon_diff = (lon1-lon2) ** 2 + return lat_diff + lon_diff + + + +def read_data_from_file(filename): + """ + Reads all data from the given file and returns a list of the lines + in that file. + + """ + fileobj = openfile(filename.lower(), False) + file_data = fileobj.readat(None, 0).split("\n") + fileobj.close() + return file_data + + + +def find_closest_location(lat, lon, location_dict): + """ + Returns a dictionary with the name and coordinates of the center of + the closest location to the given latitude and longitude coordinates. + This location, depending on the level of blurring, could be the + closest city, state, ZIP code area or country. + + The argument "location_dict" contains a list of all nearby + locations (either cities, states, ZIP code areas or countries) and + their geodata (latitude and longitude). + + The dictionary returned has the format: + { + "name": name of the closest location (string), + "latitude": latitude of the center of the above location (float), + "longitude": longitude of the center of the above location (float) + } + """ + # Check if there is only one entry in the dictionary, (e.g., in a state + # file like this http://sensibilityclearinghouse.poly.edu/data/states/US.txt + # there's only one entry that matches the state name) + if len(location_dict) == 1: + closest_location = location_dict.keys()[0] + + # Else find closest location. + else: + # Set the minimum squared difference between two pairs of coordinates + # to a number larger than any possible minimum distance to a close + # location in the current latitude/longitude cell (in case of + # blurring to city/ZIP code area), in the current country (in + # case of blurring to state), or in the entire world (in case of + # blurring to country). + min_diff = 9999 + + for current_location, location_geodata in location_dict.items(): + diff = find_squared_difference((lat, lon), (location_geodata["latitude"], + location_geodata["longitude"])) + if diff < min_diff: + min_diff = diff + closest_location = current_location + + closest_location_geodata = { + "name": closest_location, + "latitude": location_dict[closest_location]["latitude"], + "longitude": location_dict[closest_location]["longitude"] + } + + return closest_location_geodata \ No newline at end of file From be9b9fae85d457c8f2fc2d642f527c307d707532 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Sat, 25 Jul 2015 14:56:46 -0700 Subject: [PATCH 52/60] order sensors alphebatically --- getsensor.r2py | 644 +++++++++++++++++++++++++------------------------ 1 file changed, 323 insertions(+), 321 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 35be51c..33c0811 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -38,264 +38,6 @@ class SIMNotFoundException(RepyException): """ pass -################################################## -############## location interface ############### -################################################## - -def get_location(): - """ - - Get original location data from GPS or network or passive. Calls - sensorlib.request_data(sensor_socket, 'readLocation', []). The location - information is returned as a dict, which is converted to ASCII - using unicode_scrubber. - - - None - - - LocationNotFoundException (descends from RepyException) when no location - information is found. - - - When LocationNotFoundException is raised, the user of this method needs - to try several times. If this still fails, then should try - get_lastknown_location(). - - - GPS or network location lookup. - - - location as a dict, such as {'bearing': 0, 'altitude': 0, - 'time': x, 'longitude': x, 'provider': 'network', 'latitude': x, - 'speed': 0, 'accuracy': x}. - - """ - - # start the locating process - sensorlib.request_data(sensor_socket, 'startLocating', []) - - # try to read current location - # note: readLocation call can timeout, or not responsive - location_data = sensorlib.request_data(sensor_socket, 'readLocation', []) - - # stop the locating process - sensorlib.request_data(sensor_socket, 'stopLocating', []) - - if not location_data: - raise LocationNotFoundException - assert len(location_data.keys()) == 1 # should return at only one provider - - # take the first key (because only one provider) - provider = location_data.keys()[0] - location = location_data[provider] - - # convert unicode format (u'longitude') to ASCII (longitude) - # because Repy does not allow Unicode - location = unicode_scrubber.scrub(location) - return location - - -def get_lastknown_location(): - """ - - Get original _last-known_ location data from GPS/network/passive. Calls - sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []). The - location information is returned as a dict, which is converted to ASCII - using unicode_scrubber. - - - None - - - LocationNotFoundException (descends from RepyException) when the returned - location information is {'passive': None, 'network': None, 'gps': None}. - - - None. - - - Lookup cached location information on the device. - - - location as a dict with three keys: passive, network, and gps. Each key - value is a dict in the same format as the value returned by get_location(). - For example, {'passive': {'bearing': 0, 'altitude': 0, 'time': x, - 'longitude': x, 'provider': 'network', 'latitude': s, 'speed': 0, - 'accuracy': x}, 'network': {'bearing': 0, 'altitude': 0, 'time': x, - 'longitude': x, 'provider': 'network', 'latitude': x, 'speed': 0, - 'accuracy': x}, 'gps': None} - - """ - - # start the locating process - sensorlib.request_data(sensor_socket, 'startLocating', []) - - # try to read the cached location - location_data = sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []) - - # stop the locating process - sensorlib.request_data(sensor_socket, 'stopLocating', []) - assert len(location_data.keys()) >= 1 # should return at least one provider - - # check if location_data is {'passive': None, 'network': None, 'gps': None} - for i in range(len(location_data.keys())): - provider = location_data.keys()[i] - location = location_data[provider] - if location != None: - break - else: - raise LocationNotFoundException - - # convert unicode format (u'longitude') to ASCII (longitude) - location = unicode_scrubber.scrub(location_data) - return location - - -def get_geolocation(latitude, longitude, max_results): - """ - - Obtain a list of addresses for the given latitude and longitude. Calls - sensorlib.request_data(sensor_socket, 'geocode', [latitude, longitude, - max_results]). The addresses information is returned as a dict, which - is converted to ASCII using unicode_scrubber. - - - latitude (float): latitude of a location; - longitude (float): longitude of a location; - max_results (Integer): maximum number of results (normally =1). - - - None. - - - None. - - - Geolocation lookup. - - - Geolocation (address) as a list, such as [{'thoroughfare': 'Some - Street', 'locality': u'Some Town', 'sub_admin_area': 'Some Borough', - 'admin_area': 'Some City', 'feature_name': 'House Numbers', - 'country_code': 'GB', 'country_name': 'United Kingdom', - 'postal_code': 'ST1 1'}] . - - """ - - address = sensorlib.request_data(sensor_socket, 'geocode', - [latitude, longitude, max_results]) - return unicode_scrubber.scrub(address) - - - -################################################## -############## WiFi interface ################### -################################################## - -def is_wifi_enabled(): - """ - - Return if WiFi is enabled on this device (True/False). - - - None - - - None. - - - None. - - - Lookup if WiFi is enabled on the device. - - - A boolean vaiable indicating if WiFi is enabled on the device. - - """ - - # True or False - return sensorlib.request_data(sensor_socket, 'checkWifiState', []) - - -def get_wifi_connection_info(): - """ - - Return information about the WiFi network currently connected to. Calls - sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []). - - - None - - - None. - - - None. - - - Lookup WiFi connection information on the device. - - - wifi_conn as a dict, and is returned as a dict of this format: - { - "ssid": network SSID (string), - "bssid": network BSSID, i.e. MAC address (string), - "rssi": received signal strength in dBm (negative int), - "supplicant_state": current WPA association state (string), - "link_speed": link speed in MBps (int), - "mac_address": this device's WiFi interface MAC (string), - XXX "ip_address": this device's IP address (XXX int, byte quadruples reversed!), - XXX "network_id": XXX (int), - "hidden_ssid": True if the SSID is not broadcast (bool) - } - """ - - wifi_conn = sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []) - - # convert unicode format to ASCII - return unicode_scrubber.scrub(wifi_conn) - - -def do_wifi_scan(): - """ - - Return WiFi connection info on this device. Calls - sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []). - - - None - - - None. - - - None. - - - Scan the WiFi network from the device. - - - WiFi scan results wifi_data as a HUGE dict of this format, - with one dict for each network found: - { - "ssid": network SSID (string), - "bssid": network BSSID, i.e. MAC address (string), - "frequency": frequency in MHz (int), - "level": received signal strength in dBm (negative int), - "capabilities": security features supported by the network (string) - } - - """ - - sensorlib.request_data(sensor_socket, 'wifiStartScan', []) - wifi_data = sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []) - - # we do not need to stop scan (it stops itself after scan is done) - # convert unicode format to ASCII - return unicode_scrubber.scrub(wifi_data) - ################################################## ############## battery interface ################ @@ -538,86 +280,236 @@ def get_SIM_info(): When no SIM card is found, no information can be obtained. - SIM card information lookup. + SIM card information lookup. + + + SIM card info as a dict, such as {‘SIM_operator’: 310260, + ‘SIM_operator_name’: ‘’, ‘SIM_country_code’: ‘us’, ‘SIM_state’: + ‘ready’}. + + """ + + SIM_state = sensorlib.request_data(sensor_socket, 'getSimState', []) + + if SIM_state == 'absent': + # when no SIM card is found on the device, cellular information is + # not meaningful + raise SIMNotFoundException + + SIM_operator = sensorlib.request_data(sensor_socket, + 'getSimOperator', []) + SIM_operator_name = sensorlib.request_data(sensor_socket, + 'getSimOperatorName', []) + SIM_country_code = sensorlib.request_data(sensor_socket, + 'getSimCountryIso', []) + + SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, + 'SIM_operator_name': SIM_operator_name, + 'SIM_country_code': SIM_country_code} + return unicode_scrubber.scrub(SIM_info) + + +def get_phone_info(): + """ + + Get phone info from a devices. Calls sensorlib.request_data( + sensor_socket, 'readPhoneState'/'getPhoneType'/'getNetworkType', + []). The phone information, current phone state, phone type, + network type, is returned as a dict. + + + None + + + None. + + + None. + + + Phone information lookup. + + + Phone info as a dict, such as {‘phone_state’: {‘incomingNumber’: + ‘’, ‘state’: ‘idle’}, ‘phone_type’: ‘gsm’, ‘network_type’: 'edge'}. + When no SIM card is available, the phone info dict would be, e.g., + {‘phone_state’: {}, ‘phone_type’: ‘gsm’, ‘network_type’: 'unknown'}. + + """ + sensorlib.request_data(sensor_socket, 'startTrackingPhoneState', []) + + phone_state = sensorlib.request_data(sensor_socket, + 'readPhoneState', []) + phone_type = sensorlib.request_data(sensor_socket, + 'getPhoneType', []) + network_type = sensorlib.request_data(sensor_socket, + 'getNetworkType', []) + + sensorlib.request_data(sensor_socket, 'stopTrackingPhoneState', []) + + phone_info = {'phone_state': phone_state, 'phone_type': phone_type, + 'network_type': network_type} + return unicode_scrubber.scrub(phone_info) + + +def get_cellular_signal_strengths(): + """ + + Get the current signal strengths, in dictionary of gsm_signal_strength. + Calls sensorlib.request_data(sensor_socket, 'readSignalStrengths', []). + + + None + + + None. + + + None. + + + Current signal strengths lookup. + + + Signal strengths info as a dict, such as {"gsm_signal_strength": + 8, "evdo_ecio": -1, "gsm_bit_error_rate": -1, "cdma_ecio": -1, + "cdma_dbm": -1, "evdo_dbm": -1}. + """ + + sensorlib.request_data(sensor_socket, 'startTrackingSignalStrengths', []) + cellular_signal_strengths = sensorlib.request_data(sensor_socket, + 'readSignalStrengths', []) + sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) + + return unicode_scrubber.scrub(cellular_signal_strengths) + + +################################################## +############## location interface ############### +################################################## + +def get_location(): + """ + + Get original location data from GPS or network or passive. Calls + sensorlib.request_data(sensor_socket, 'readLocation', []). The location + information is returned as a dict, which is converted to ASCII + using unicode_scrubber. + + + None + + + LocationNotFoundException (descends from RepyException) when no location + information is found. + + + When LocationNotFoundException is raised, the user of this method needs + to try several times. If this still fails, then should try + get_lastknown_location(). + + + GPS or network location lookup. - SIM card info as a dict, such as {‘SIM_operator’: 310260, - ‘SIM_operator_name’: ‘’, ‘SIM_country_code’: ‘us’, ‘SIM_state’: - ‘ready’}. - + location as a dict, such as {'bearing': 0, 'altitude': 0, + 'time': x, 'longitude': x, 'provider': 'network', 'latitude': x, + 'speed': 0, 'accuracy': x}. + """ - SIM_state = sensorlib.request_data(sensor_socket, 'getSimState', []) - - if SIM_state == 'absent': - # when no SIM card is found on the device, cellular information is - # not meaningful - raise SIMNotFoundException + # start the locating process + sensorlib.request_data(sensor_socket, 'startLocating', []) - SIM_operator = sensorlib.request_data(sensor_socket, - 'getSimOperator', []) - SIM_operator_name = sensorlib.request_data(sensor_socket, - 'getSimOperatorName', []) - SIM_country_code = sensorlib.request_data(sensor_socket, - 'getSimCountryIso', []) + # try to read current location + # note: readLocation call can timeout, or not responsive + location_data = sensorlib.request_data(sensor_socket, 'readLocation', []) - SIM_info = {'SIM_state': SIM_state, 'SIM_operator': SIM_operator, - 'SIM_operator_name': SIM_operator_name, - 'SIM_country_code': SIM_country_code} - return unicode_scrubber.scrub(SIM_info) + # stop the locating process + sensorlib.request_data(sensor_socket, 'stopLocating', []) + if not location_data: + raise LocationNotFoundException + assert len(location_data.keys()) == 1 # should return at only one provider -def get_phone_info(): + # take the first key (because only one provider) + provider = location_data.keys()[0] + location = location_data[provider] + + # convert unicode format (u'longitude') to ASCII (longitude) + # because Repy does not allow Unicode + location = unicode_scrubber.scrub(location) + return location + + +def get_lastknown_location(): """ - Get phone info from a devices. Calls sensorlib.request_data( - sensor_socket, 'readPhoneState'/'getPhoneType'/'getNetworkType', - []). The phone information, current phone state, phone type, - network type, is returned as a dict. + Get original _last-known_ location data from GPS/network/passive. Calls + sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []). The + location information is returned as a dict, which is converted to ASCII + using unicode_scrubber. - None + None - None. + LocationNotFoundException (descends from RepyException) when the returned + location information is {'passive': None, 'network': None, 'gps': None}. - None. + None. - Phone information lookup. + Lookup cached location information on the device. - Phone info as a dict, such as {‘phone_state’: {‘incomingNumber’: - ‘’, ‘state’: ‘idle’}, ‘phone_type’: ‘gsm’, ‘network_type’: 'edge'}. - When no SIM card is available, the phone info dict would be, e.g., - {‘phone_state’: {}, ‘phone_type’: ‘gsm’, ‘network_type’: 'unknown'}. - + location as a dict with three keys: passive, network, and gps. Each key + value is a dict in the same format as the value returned by get_location(). + For example, {'passive': {'bearing': 0, 'altitude': 0, 'time': x, + 'longitude': x, 'provider': 'network', 'latitude': s, 'speed': 0, + 'accuracy': x}, 'network': {'bearing': 0, 'altitude': 0, 'time': x, + 'longitude': x, 'provider': 'network', 'latitude': x, 'speed': 0, + 'accuracy': x}, 'gps': None} + """ - sensorlib.request_data(sensor_socket, 'startTrackingPhoneState', []) - phone_state = sensorlib.request_data(sensor_socket, - 'readPhoneState', []) - phone_type = sensorlib.request_data(sensor_socket, - 'getPhoneType', []) - network_type = sensorlib.request_data(sensor_socket, - 'getNetworkType', []) + # start the locating process + sensorlib.request_data(sensor_socket, 'startLocating', []) - sensorlib.request_data(sensor_socket, 'stopTrackingPhoneState', []) - - phone_info = {'phone_state': phone_state, 'phone_type': phone_type, - 'network_type': network_type} - return unicode_scrubber.scrub(phone_info) + # try to read the cached location + location_data = sensorlib.request_data(sensor_socket, 'getLastKnownLocation', []) + # stop the locating process + sensorlib.request_data(sensor_socket, 'stopLocating', []) + assert len(location_data.keys()) >= 1 # should return at least one provider -def get_cellular_signal_strengths(): + # check if location_data is {'passive': None, 'network': None, 'gps': None} + for i in range(len(location_data.keys())): + provider = location_data.keys()[i] + location = location_data[provider] + if location != None: + break + else: + raise LocationNotFoundException + + # convert unicode format (u'longitude') to ASCII (longitude) + location = unicode_scrubber.scrub(location_data) + return location + + +def get_geolocation(latitude, longitude, max_results): """ - Get the current signal strengths, in dictionary of gsm_signal_strength. - Calls sensorlib.request_data(sensor_socket, 'readSignalStrengths', []). + Obtain a list of addresses for the given latitude and longitude. Calls + sensorlib.request_data(sensor_socket, 'geocode', [latitude, longitude, + max_results]). The addresses information is returned as a dict, which + is converted to ASCII using unicode_scrubber. - None + latitude (float): latitude of a location; + longitude (float): longitude of a location; + max_results (Integer): maximum number of results (normally =1). None. @@ -626,20 +518,22 @@ def get_cellular_signal_strengths(): None. - Current signal strengths lookup. + Geolocation lookup. - Signal strengths info as a dict, such as {"gsm_signal_strength": - 8, "evdo_ecio": -1, "gsm_bit_error_rate": -1, "cdma_ecio": -1, - "cdma_dbm": -1, "evdo_dbm": -1}. + Geolocation (address) as a list, such as [{'thoroughfare': 'Some + Street', 'locality': u'Some Town', 'sub_admin_area': 'Some Borough', + 'admin_area': 'Some City', 'feature_name': 'House Numbers', + 'country_code': 'GB', 'country_name': 'United Kingdom', + 'postal_code': 'ST1 1'}] . + """ - sensorlib.request_data(sensor_socket, 'startTrackingSignalStrengths', []) - cellular_signal_strengths = sensorlib.request_data(sensor_socket, - 'readSignalStrengths', []) - sensorlib.request_data(sensor_socket, 'stopTrackingSignalStrengths', []) + address = sensorlib.request_data(sensor_socket, 'geocode', + [latitude, longitude, max_results]) + return unicode_scrubber.scrub(address) - return unicode_scrubber.scrub(cellular_signal_strengths) + ################################################## @@ -885,7 +779,7 @@ def get_sensors(): sensors = sensorlib.request_data(sensor_socket, 'readSensors', []) return unicode_scrubber.scrub(sensors) - + def get_sensors_accuracy(): """ @@ -1021,6 +915,114 @@ def get_orientation(): [-0.17154279351234436, 0.080450139939785, -0.03844258934259415]. """ - return sensorlib.request_data(sensor_socket, - 'sensorsReadOrientation', []) + return sensorlib.request_data(sensor_socket, + 'sensorsReadOrientation', []) + + + +################################################## +############## WiFi interface ################### +################################################## + +def is_wifi_enabled(): + """ + + Return if WiFi is enabled on this device (True/False). + + + None + + + None. + + + None. + + + Lookup if WiFi is enabled on the device. + + + A boolean vaiable indicating if WiFi is enabled on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'checkWifiState', []) + + +def get_wifi_connection_info(): + """ + + Return information about the WiFi network currently connected to. Calls + sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []). + + + None + + + None. + + None. + + + Lookup WiFi connection information on the device. + + + wifi_conn as a dict, and is returned as a dict of this format: + { + "ssid": network SSID (string), + "bssid": network BSSID, i.e. MAC address (string), + "rssi": received signal strength in dBm (negative int), + "supplicant_state": current WPA association state (string), + "link_speed": link speed in MBps (int), + "mac_address": this device's WiFi interface MAC (string), + XXX "ip_address": this device's IP address (XXX int, byte quadruples reversed!), + XXX "network_id": XXX (int), + "hidden_ssid": True if the SSID is not broadcast (bool) + } + """ + + wifi_conn = sensorlib.request_data(sensor_socket, 'wifiGetConnectionInfo', []) + + # convert unicode format to ASCII + return unicode_scrubber.scrub(wifi_conn) + + +def do_wifi_scan(): + """ + + Return WiFi connection info on this device. Calls + sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []). + + + None + + + None. + + + None. + + + Scan the WiFi network from the device. + + + WiFi scan results wifi_data as a HUGE dict of this format, + with one dict for each network found: + { + "ssid": network SSID (string), + "bssid": network BSSID, i.e. MAC address (string), + "frequency": frequency in MHz (int), + "level": received signal strength in dBm (negative int), + "capabilities": security features supported by the network (string) + } + + """ + + sensorlib.request_data(sensor_socket, 'wifiStartScan', []) + wifi_data = sensorlib.request_data(sensor_socket, 'wifiGetScanResults', []) + + # we do not need to stop scan (it stops itself after scan is done) + # convert unicode format to ASCII + return unicode_scrubber.scrub(wifi_data) From 8d79ea5e1fae923d71ee35c5c275b947d15d97c9 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Sun, 26 Jul 2015 18:11:55 -0700 Subject: [PATCH 53/60] add media calls --- getsensor.r2py | 105 +++++++++++++++++++++++++++++++++++++++++++ sensor_layer.r2py | 110 ++++++++++++++++++++++++++++++---------------- 2 files changed, 176 insertions(+), 39 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 33c0811..2eb6891 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -535,6 +535,111 @@ def get_geolocation(latitude, longitude, max_results): +################################################## +############### media interface ################# +################################################## + + +def microphone_record(filename, duration): + """ + + Records audio from the microphone and saves it as filename. Calls sensorlib. + request_data(sensor_socket, 'recorderStartMicrophone', [filename]). + + + filename (string): the audio file name that will be saved as (e.g., record.mp4); + duration (Integer): the duration to record the audio. + + + None. + + + None. + + + Record audio and save as a file on the device. + + + None. + """ + + filepath = '/mnt/sdcard/Android/data/com.sensibility_testbed/files/sl4a/seattle/seattle_repy/v1/' + targetpath = filepath + filename + + sensorlib.request_data(sensor_socket, 'recorderStartMicrophone', [targetpath]) + sleep(duration) + + sensorlib.request_data(sensor_socket, 'recorderStop', []) + + + + +def is_media_playing(): + """ + + Return if media file is playing. (True/False). Calls sensorlib. + request_data(sensor_socket, 'mediaIsPlaying', []) + + + None. + + + None. + + + None. + + + Lookup if media file is playing. + + + A boolean vaiable indicating if a media file is playing on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'mediaIsPlaying', []) + + + +def get_media_play_info(): + """ + + Return information on current media. Calls sensorlib.request_data( + sensor_socket, 'mediaPlayInfo', []) + + + None. + + + None. + + + None. + + + Lookup media play information. + + + media_play_info as a dict. + + If no media file is loaded, the result is {'loaded': False, 'tag': 'default'}. + + If there is a media file being played, the result is {'url': filepath, + 'looping': False, 'tag': 'default', 'loaded': True, 'duration': 17100, + 'position': 100, 'isplaying': True}. + + If the media file is finished playing, the result is {'url': filepath, + 'looping': False, 'tag': 'default', 'loaded': True, 'duration': 17100, + 'position': 17020, 'isplaying': False} + + """ + + # True or False + media_play_info = sensorlib.request_data(sensor_socket, 'mediaPlayInfo', []) + return unicode_scrubber.scrub(media_play_info) + + ################################################## ############## settings interface ############### diff --git a/sensor_layer.r2py b/sensor_layer.r2py index c9218c1..2b18970 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -8,130 +8,135 @@ start dylink.r2py encasementlib.r2py sensor_layer.r2py [any blur layers] \ getsensor = dy_import_module("getsensor.r2py") -CHILD_CONTEXT_DEF["get_location"] = { + +CHILD_CONTEXT_DEF["get_battery_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_location, + "target": getsensor.get_battery_info, } -CHILD_CONTEXT_DEF["get_lastknown_location"] = { +CHILD_CONTEXT_DEF["get_bluetooth_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_lastknown_location, + "target": getsensor.get_bluetooth_info, } -CHILD_CONTEXT_DEF["get_geolocation"] = { +CHILD_CONTEXT_DEF["is_roaming"] = { "type": "func", - "args": (float, float, int), - "return": list, + "args": None, + "return": bool, "exceptions": "any", - "target": getsensor.get_geolocation, + "target": getsensor.is_roaming, } -CHILD_CONTEXT_DEF["is_wifi_enabled"] = { + +CHILD_CONTEXT_DEF["get_cellular_provider_info"] = { "type": "func", "args": None, - "return": bool, + "return": dict, "exceptions": "any", - "target": getsensor.is_wifi_enabled, + "target": getsensor.get_cellular_provider_info, } -CHILD_CONTEXT_DEF["get_wifi_connection_info"] = { +CHILD_CONTEXT_DEF["get_cell_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_wifi_connection_info, + "target": getsensor.get_cell_info, } -CHILD_CONTEXT_DEF["do_wifi_scan"] = { +CHILD_CONTEXT_DEF["get_SIM_info"] = { "type": "func", "args": None, - "return": list, + "return": dict, "exceptions": "any", - "target": getsensor.do_wifi_scan, + "target": getsensor.get_SIM_info, } -CHILD_CONTEXT_DEF["get_battery_info"] = { +CHILD_CONTEXT_DEF["get_phone_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_battery_info, + "target": getsensor.get_phone_info, } -CHILD_CONTEXT_DEF["get_bluetooth_info"] = { +CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_bluetooth_info, + "target": getsensor.get_cellular_signal_strengths, } -CHILD_CONTEXT_DEF["is_roaming"] = { + +CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, - "return": bool, + "return": dict, "exceptions": "any", - "target": getsensor.is_roaming, + "target": getsensor.get_location, } - -CHILD_CONTEXT_DEF["get_cellular_provider_info"] = { +CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_cellular_provider_info, + "target": getsensor.get_lastknown_location, } -CHILD_CONTEXT_DEF["get_cell_info"] = { +CHILD_CONTEXT_DEF["get_geolocation"] = { "type": "func", - "args": None, - "return": dict, + "args": (float, float, int), + "return": list, "exceptions": "any", - "target": getsensor.get_cell_info, + "target": getsensor.get_geolocation, } -CHILD_CONTEXT_DEF["get_SIM_info"] = { + +CHILD_CONTEXT_DEF["microphone_record"] = { "type": "func", - "args": None, - "return": dict, + "args": (string, int), + "return": None, "exceptions": "any", - "target": getsensor.get_SIM_info, + "target": getsensor.microphone_record, } -CHILD_CONTEXT_DEF["get_phone_info"] = { + +CHILD_CONTEXT_DEF["is_media_playing"] = { "type": "func", "args": None, - "return": dict, + "return": bool, "exceptions": "any", - "target": getsensor.get_phone_info, + "target": getsensor.is_media_playing, } -CHILD_CONTEXT_DEF["get_cellular_signal_strengths"] = { + +CHILD_CONTEXT_DEF["get_media_play_info"] = { "type": "func", "args": None, "return": dict, "exceptions": "any", - "target": getsensor.get_cellular_signal_strengths, + "target": getsensor.get_media_play_info, } @@ -245,5 +250,32 @@ CHILD_CONTEXT_DEF["get_orientation"] = { } + +CHILD_CONTEXT_DEF["is_wifi_enabled"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.is_wifi_enabled, +} + + +CHILD_CONTEXT_DEF["get_wifi_connection_info"] = { + "type": "func", + "args": None, + "return": dict, + "exceptions": "any", + "target": getsensor.get_wifi_connection_info, +} + + +CHILD_CONTEXT_DEF["do_wifi_scan"] = { + "type": "func", + "args": None, + "return": list, + "exceptions": "any", + "target": getsensor.do_wifi_scan, +} + secure_dispatch_module() From fafacd550d7d7f913782afae28bd4283a2fef3e0 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 28 Jul 2015 06:39:17 -0700 Subject: [PATCH 54/60] fix arg type --- sensor_layer.r2py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sensor_layer.r2py b/sensor_layer.r2py index 2b18970..dd027b8 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -113,7 +113,7 @@ CHILD_CONTEXT_DEF["get_geolocation"] = { CHILD_CONTEXT_DEF["microphone_record"] = { "type": "func", - "args": (string, int), + "args": (str, int), "return": None, "exceptions": "any", "target": getsensor.microphone_record, From f26effb99e3be000a763cba6f8fb890252b99d7c Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Thu, 30 Jul 2015 18:57:00 -0700 Subject: [PATCH 55/60] add TTS interface --- getsensor.r2py | 61 ++++++++++++++++++++++++++++++++++++++++++++++- sensor_layer.r2py | 17 +++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/getsensor.r2py b/getsensor.r2py index 2eb6891..18f7489 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -1024,6 +1024,64 @@ def get_orientation(): 'sensorsReadOrientation', []) +################################################## +########### text to speech interface ############ +################################################## + + +def is_tts_speaking(): + """ + + Return if text to speech (tts) is currently in progress (True/False). Calls + sensorlib.request_data(sensor_socket, 'ttsIsSpeaking', []). + + + None + + + None. + + + None. + + + Lookup if tts is currently in progress. + + + A boolean vaiable indicating if tts is currently in progress on the device. + + """ + + # True or False + return sensorlib.request_data(sensor_socket, 'ttsIsSpeaking', []) + + + +def tts_speak(message): + """ + + Speaks the provided message via text to speech (tts). Calls + sensorlib.request_data(sensor_socket, 'ttsSpeak', [message]). + + + message (string): the message to speak. + + + None. + + + None. + + + Text to speech speaks the provided message. + + + None. + + """ + + sensorlib.request_data(sensor_socket, 'ttsSpeak', [message]) + ################################################## ############## WiFi interface ################### @@ -1032,7 +1090,8 @@ def get_orientation(): def is_wifi_enabled(): """ - Return if WiFi is enabled on this device (True/False). + Return if WiFi is enabled on this device (True/False). Calls + sensorlib.request_data(sensor_socket, 'checkWifiState', []). None diff --git a/sensor_layer.r2py b/sensor_layer.r2py index dd027b8..fa00080 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -250,6 +250,23 @@ CHILD_CONTEXT_DEF["get_orientation"] = { } +CHILD_CONTEXT_DEF["is_tts_speaking"] = { + "type": "func", + "args": None, + "return": bool, + "exceptions": "any", + "target": getsensor.is_tts_speaking, +} + + +CHILD_CONTEXT_DEF["tts_speak"] = { + "type": "func", + "args": str, + "return": None, + "exceptions": "any", + "target": getsensor.tts_speak, +} + CHILD_CONTEXT_DEF["is_wifi_enabled"] = { "type": "func", From 6fdae97e0ed8759412ba5da581f72bf36e7b6a3a Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Fri, 31 Jul 2015 15:28:54 -0700 Subject: [PATCH 56/60] add error handling in reading sensor --- getsensor.r2py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 18f7489..5465832 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -949,7 +949,7 @@ def get_acceleration(): None. - None. + ValueError. None. @@ -962,9 +962,14 @@ def get_acceleration(): e.g., [0.3830723, -0.8036005, 10.036493]. """ - return sensorlib.request_data(sensor_socket, + try: + data = sensorlib.request_data(sensor_socket, 'sensorsReadAccelerometer', []) + except ValueError: + log(data) + raise ValueError + return data def get_magnetic_field(): From 601e553fec97332394551921e5caa2335dfc9ce1 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Sat, 1 Aug 2015 17:44:53 -0700 Subject: [PATCH 57/60] refactor blur to city --- blur_location2city.r2py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/blur_location2city.r2py b/blur_location2city.r2py index a51063c..85c1a9e 100644 --- a/blur_location2city.r2py +++ b/blur_location2city.r2py @@ -99,7 +99,7 @@ def get_city_location(): location_data = get_location() closest_city = find_closest_city(location_data["latitude"], - location_data["longitude"]) + location_data["longitude"]) location_data["latitude"] = closest_city["latitude"] location_data["longitude"] = closest_city["longitude"] @@ -113,7 +113,6 @@ def get_city_lastknown_location(): Blurring layer for the get_lastknown_location() function. It replaces the last-known coordinates of the Android device with the coordinates for the geographic center of the nearest city. - """ location_data = get_lastknown_location() @@ -125,7 +124,7 @@ def get_city_lastknown_location(): continue closest_city = find_closest_city(provider_location_data["latitude"], - provider_location_data["longitude"]) + provider_location_data["longitude"]) break From 5e0db35c9528c3e4c6d51e84d3676c283eec4544 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Thu, 6 Aug 2015 19:06:54 -0700 Subject: [PATCH 58/60] fix single arg list type --- sensor_layer.r2py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sensor_layer.r2py b/sensor_layer.r2py index fa00080..41dfc9a 100644 --- a/sensor_layer.r2py +++ b/sensor_layer.r2py @@ -261,7 +261,7 @@ CHILD_CONTEXT_DEF["is_tts_speaking"] = { CHILD_CONTEXT_DEF["tts_speak"] = { "type": "func", - "args": str, + "args": (str,), "return": None, "exceptions": "any", "target": getsensor.tts_speak, From cd4085cef7e68bf923b48def947aa383c32ef489 Mon Sep 17 00:00:00 2001 From: yyzhuang Date: Tue, 11 Aug 2015 09:22:10 -0700 Subject: [PATCH 59/60] raise exp instead of log --- getsensor.r2py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/getsensor.r2py b/getsensor.r2py index 5465832..9c48e62 100644 --- a/getsensor.r2py +++ b/getsensor.r2py @@ -965,9 +965,8 @@ def get_acceleration(): try: data = sensorlib.request_data(sensor_socket, 'sensorsReadAccelerometer', []) - except ValueError: - log(data) - raise ValueError + except ValueError, e: + raise ValueError(str( e ) + " Data was '" + str(data) + "'") return data From b26f62ade53b11abfeae02cc031fa7ddda0f3f0b Mon Sep 17 00:00:00 2001 From: aditup Date: Mon, 17 Aug 2015 19:38:55 -0400 Subject: [PATCH 60/60] remove exception checking --- blur_location_round.r2py | 64 +++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/blur_location_round.r2py b/blur_location_round.r2py index 3eb8c5a..53282c5 100644 --- a/blur_location_round.r2py +++ b/blur_location_round.r2py @@ -1,36 +1,57 @@ +""" +A security layer for the functions get_location() and get_lastknown_location() +defined in getsensor.r2py. This program blurs the latitude/longitude +coordinates, received from the location sensors of an Android device, +by rounding them off to one decimal place. + +Usage: + start dylink.r2py encasementlib.r2py sensor_layer.r2py \ + blur_location_round.r2py user-program.r2py +""" + + + def blur_location_round(): + """ + Blurring layer for the get_location() function. It replaces the exact + coordinates of the Android device with the coordinates rounded off to + a single decimal place. - try: - location = get_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception + """ + location_data = get_location() - # Blur the coordinates by rounding - location["latitude"] = round(float(location["latitude"]), 1) - location["longitude"] = round(float(location["longitude"]), 1) + location_data["latitude"] = round(float(location_data["latitude"]), 1) + location_data["longitude"] = round(float(location_data["longitude"]), 1) - return location + return location_data def blur_lastknown_location_round(): + """ + Blurring layer for the get_lastknown_location() function. It replaces + the last-known coordinates of the Android device with the coordinates + rounded off to a single decimal place. + + """ + location_data = get_lastknown_location() + + for location_provider, provider_location_data in location_data.items(): + # Skip blurring this provider's data if it doesn't contain a previous + # location. + if provider_location_data is None: + continue - try: - location = get_lastknown_location() - except Exception: # Not able to use LocationNotFoundException here - raise Exception + location_data[location_provider]["latitude"] = \ + round(float(provider_location_data["latitude"]), 1) + location_data[location_provider]["longitude"] = \ + round(float(provider_location_data["longitude"]), 1) - # Blur the coordinates by rounding - for i in range(len(location.keys())): - provider = location.keys()[i] - location_item = location[provider] - if location_item != None: - location[provider]["latitude"] = round(float(location_item["latitude"]), 1) - location[provider]["longitude"] = round(float(location_item["longitude"]), 1) + return location_data - return location +# Mapping our blurring function blur_location_round to get_location. CHILD_CONTEXT_DEF["get_location"] = { "type": "func", "args": None, @@ -40,6 +61,8 @@ CHILD_CONTEXT_DEF["get_location"] = { } +# Mapping our blurring function blur_lastknown_location_round to +# get_lastknown_location. CHILD_CONTEXT_DEF["get_lastknown_location"] = { "type": "func", "args": None, @@ -49,4 +72,5 @@ CHILD_CONTEXT_DEF["get_lastknown_location"] = { } +# Dispatch. secure_dispatch_module() \ No newline at end of file