class GoogleMapsScanner: """Representation of an Google Maps location sharing account.""" def __init__(self, hass, config: ConfigType, see) -> None: """Initialize the scanner.""" from locationsharinglib import Service from locationsharinglib.locationsharinglibexceptions import InvalidUser self.see = see self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] self.max_gps_accuracy = config[CONF_MAX_GPS_ACCURACY] try: self.service = Service(self.username, self.password, hass.config.path(CREDENTIALS_FILE)) self._update_info() track_time_interval( hass, self._update_info, MIN_TIME_BETWEEN_SCANS) self.success_init = True except InvalidUser: _LOGGER.error("You have specified invalid login credentials") self.success_init = False def _update_info(self, now=None): for person in self.service.get_all_people(): try: dev_id = 'google_maps_{0}'.format(slugify(person.id)) except TypeError: _LOGGER.warning("No location(s) shared with this account") return if self.max_gps_accuracy is not None and \ person.accuracy > self.max_gps_accuracy: _LOGGER.info("Ignoring %s update because expected GPS " "accuracy %s is not met: %s", person.nickname, self.max_gps_accuracy, person.accuracy) continue attrs = { ATTR_ADDRESS: person.address, ATTR_FULL_NAME: person.full_name, ATTR_ID: person.id, ATTR_LAST_SEEN: dt_util.as_utc(person.datetime), ATTR_NICKNAME: person.nickname, ATTR_BATTERY_CHARGING: person.charging, ATTR_BATTERY_LEVEL: person.battery_level } self.see( dev_id=dev_id, gps=(person.latitude, person.longitude), picture=person.picture_url, source_type=SOURCE_TYPE_GPS, gps_accuracy=person.accuracy, attributes=attrs, )
class GoogleMapsScanner: """Representation of an Google Maps location sharing account.""" def __init__(self, hass, config: ConfigType, see) -> None: """Initialize the scanner.""" from locationsharinglib import Service from locationsharinglib.locationsharinglibexceptions import InvalidUser self.see = see self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] self.max_gps_accuracy = config[CONF_MAX_GPS_ACCURACY] try: self.service = Service(self.username, self.password, hass.config.path(CREDENTIALS_FILE)) self._update_info() track_time_interval(hass, self._update_info, MIN_TIME_BETWEEN_SCANS) self.success_init = True except InvalidUser: _LOGGER.error("You have specified invalid login credentials") self.success_init = False def _update_info(self, now=None): for person in self.service.get_all_people(): try: dev_id = 'google_maps_{0}'.format(slugify(person.id)) except TypeError: _LOGGER.warning("No location(s) shared with this account") return if self.max_gps_accuracy is not None and \ person.accuracy > self.max_gps_accuracy: _LOGGER.info( "Ignoring %s update because expected GPS " "accuracy %s is not met: %s", person.nickname, self.max_gps_accuracy, person.accuracy) continue attrs = { ATTR_ADDRESS: person.address, ATTR_FULL_NAME: person.full_name, ATTR_ID: person.id, ATTR_LAST_SEEN: person.datetime, ATTR_NICKNAME: person.nickname, } self.see( dev_id=dev_id, gps=(person.latitude, person.longitude), picture=person.picture_url, source_type=SOURCE_TYPE_GPS, gps_accuracy=person.accuracy, attributes=attrs, )
def get_people_latlons(): service = Service(cookies_file='cookies.txt', authenticating_account=os.getenv('GOOGLE_ACCOUNT_EMAIL')) people = {} for person in service.get_all_people(): people[person.nickname] = { 'lat': person.latitude, 'lon': person.longitude } print(person.nickname, person.latitude, person.longitude) return people
def get_location(): cookies_file = 'location_sharing.cookies' google_email = '*****@*****.**' service = Service(cookies_file=cookies_file, authenticating_account=google_email) person = list(service.get_all_people())[0] for location in settings.locations: dist = geodesic((person.latitude,person.longitude),location[1]).miles if dist <= location[2]: return location[0]
class GoogleMapsScanner(object): """Representation of an Google Maps location sharing account.""" def __init__(self, hass, config: ConfigType, see) -> None: """Initialize the scanner.""" from locationsharinglib import Service from locationsharinglib.locationsharinglibexceptions import InvalidUser self.see = see self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] try: self.service = Service(self.username, self.password, hass.config.path(CREDENTIALS_FILE)) self._update_info() track_time_interval( hass, self._update_info, MIN_TIME_BETWEEN_SCANS) self.success_init = True except InvalidUser: _LOGGER.error('You have specified invalid login credentials') self.success_init = False def _update_info(self, now=None): for person in self.service.get_all_people(): dev_id = 'google_maps_{0}'.format(slugify(person.id)) attrs = { 'id': person.id, 'nickname': person.nickname, 'full_name': person.full_name, 'last_seen': person.datetime, 'address': person.address } self.see( dev_id=dev_id, gps=(person.latitude, person.longitude), picture=person.picture_url, source_type=SOURCE_TYPE_GPS, attributes=attrs )
class GoogleMapsScanner(object): """Representation of an Google Maps location sharing account.""" def __init__(self, hass, config: ConfigType, see) -> None: """Initialize the scanner.""" from locationsharinglib import Service from locationsharinglib.locationsharinglibexceptions import InvalidUser self.see = see self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] try: self.service = Service(self.username, self.password, hass.config.path(CREDENTIALS_FILE)) self._update_info() track_time_interval(hass, self._update_info, MIN_TIME_BETWEEN_SCANS) self.success_init = True except InvalidUser: _LOGGER.error('You have specified invalid login credentials') self.success_init = False def _update_info(self, now=None): for person in self.service.get_all_people(): dev_id = 'google_maps_{0}'.format(slugify(person.id)) attrs = { 'id': person.id, 'nickname': person.nickname, 'full_name': person.full_name, 'last_seen': person.datetime, 'address': person.address } self.see(dev_id=dev_id, gps=(person.latitude, person.longitude), picture=person.picture_url, source_type=SOURCE_TYPE_GPS, gps_accuracy=person.accuracy, attributes=attrs)
class GoogleMapsScanner: """Representation of an Google Maps location sharing account.""" def __init__(self, opp, config: ConfigType, see) -> None: """Initialize the scanner.""" self.see = see self.username = config[CONF_USERNAME] self.max_gps_accuracy = config[CONF_MAX_GPS_ACCURACY] self.scan_interval = config.get(CONF_SCAN_INTERVAL) or timedelta(seconds=60) self._prev_seen = {} credfile = "{}.{}".format( opp.config.path(CREDENTIALS_FILE), slugify(self.username) ) try: self.service = Service(credfile, self.username) self._update_info() track_time_interval(opp, self._update_info, self.scan_interval) self.success_init = True except InvalidCookies: _LOGGER.error( "The cookie file provided does not provide a valid session. Please create another one and try again." ) self.success_init = False def _update_info(self, now=None): for person in self.service.get_all_people(): try: dev_id = "google_maps_{0}".format(slugify(person.id)) except TypeError: _LOGGER.warning("No location(s) shared with this account") return if ( self.max_gps_accuracy is not None and person.accuracy > self.max_gps_accuracy ): _LOGGER.info( "Ignoring %s update because expected GPS " "accuracy %s is not met: %s", person.nickname, self.max_gps_accuracy, person.accuracy, ) continue last_seen = dt_util.as_utc(person.datetime) if last_seen < self._prev_seen.get(dev_id, last_seen): _LOGGER.warning( "Ignoring %s update because timestamp " "is older than last timestamp", person.nickname, ) _LOGGER.debug("%s < %s", last_seen, self._prev_seen[dev_id]) continue self._prev_seen[dev_id] = last_seen attrs = { ATTR_ADDRESS: person.address, ATTR_FULL_NAME: person.full_name, ATTR_ID: person.id, ATTR_LAST_SEEN: last_seen, ATTR_NICKNAME: person.nickname, ATTR_BATTERY_CHARGING: person.charging, ATTR_BATTERY_LEVEL: person.battery_level, } self.see( dev_id=dev_id, gps=(person.latitude, person.longitude), picture=person.picture_url, source_type=SOURCE_TYPE_GPS, gps_accuracy=person.accuracy, attributes=attrs, )
class GoogleMapsScanner: """Representation of an Google Maps location sharing account.""" def __init__(self, hass, config: ConfigType, see) -> None: """Initialize the scanner.""" self.see = see self.username = config[CONF_USERNAME] self.max_gps_accuracy = config[CONF_MAX_GPS_ACCURACY] self.scan_interval = config.get(CONF_SCAN_INTERVAL) or timedelta(seconds=60) credfile = "{}.{}".format( hass.config.path(CREDENTIALS_FILE), slugify(self.username) ) try: self.service = Service(credfile, self.username) self._update_info() track_time_interval(hass, self._update_info, self.scan_interval) self.success_init = True except InvalidCookies: _LOGGER.error( "You have specified invalid login credentials. " "Please make sure you have saved your credentials" " in the following file: %s", credfile, ) self.success_init = False def _update_info(self, now=None): for person in self.service.get_all_people(): try: dev_id = "google_maps_{0}".format(slugify(person.id)) except TypeError: _LOGGER.warning("No location(s) shared with this account") return if ( self.max_gps_accuracy is not None and person.accuracy > self.max_gps_accuracy ): _LOGGER.info( "Ignoring %s update because expected GPS " "accuracy %s is not met: %s", person.nickname, self.max_gps_accuracy, person.accuracy, ) continue attrs = { ATTR_ADDRESS: person.address, ATTR_FULL_NAME: person.full_name, ATTR_ID: person.id, ATTR_LAST_SEEN: dt_util.as_utc(person.datetime), ATTR_NICKNAME: person.nickname, ATTR_BATTERY_CHARGING: person.charging, ATTR_BATTERY_LEVEL: person.battery_level, } self.see( dev_id=dev_id, gps=(person.latitude, person.longitude), picture=person.picture_url, source_type=SOURCE_TYPE_GPS, gps_accuracy=person.accuracy, attributes=attrs, )
class FrontEnd: def __init__(self, username, cookie): try: self.service = Service(cookie, username) except InvalidCookies: print("Invalid cookie.") raise InvalidCookies print("Authenticated.\n") print(list(self.service.get_all_people())) self.now = None self.you = None self.people = [] # dictionary of people by id self.person_d = {} self.person_n = {} self.load() self.auto_update() def load(self): if not os.path.isfile(FNAME): return for line in open(FNAME, 'r'): parts = line.split(",") if len(parts) != 3: continue pid, lat, lon = parts home = (float(lat), float(lon)) self.person_d[pid] = home print("Loaded.") def auto_update(self): self.update() # update every N seconds (on a thread) self.t = Timer(POLLING_DURATION, self.auto_update) self.t.start() def update(self): self.now = datetime.datetime.now() if PRINT_UPDATES: print("Updating... (%s)\n> " % self.now.strftime("%H:%M:%S")) you = self.service.get_authenticated_person() if self.person_d.get(you.id) is None: self.you = You(you) else: # both 'homes' and people stored in the person dictionary if type(self.person_d[you.id]) == tuple: self.you = You(you, home=self.person_d[you.id]) else: self.you = self.person_d[you.id] self.you.update(you) self.person_d[you.id] = self.you self.people = [] for p in self.service.get_shared_people(): new_p = None if p.id in self.person_d.keys(): # both 'homes' and people stored in the person dictionary if type(self.person_d[p.id]) == tuple: new_p = Person(p, you=self.you, home=self.person_d[p.id]) else: new_p = self.person_d[p.id] new_p.update(p, self.you) else: new_p = Person(p, you=self.you) self.person_d[p.id] = new_p self.people.append(new_p) self.person_n[new_p.nickname.lower()] = new_p # sort by furthest distance self.people.sort(key=lambda p: p.distance) def print_all(self): self.you.print() print("") for i, p in enumerate(self.people): print("%2d. " % (i + 1), end="") p.print() print("(Refreshed at %s.)" % self.now.strftime('%Y-%m-%d %H:%M:%S')) def who_find(self): if len(self.people): return "I've got no-one to find." res = "I can find " lst = [str(p.nickname) for p in self.people] if len(lst) == 1: res += lst[0] + "." else: res += ", ".join(lst[:-1]) + " and " + lst[-1] + "." def who_home(self): people_at_home = [] for i, p in enumerate(self.people): if p.at_home: people_at_home.append(p) if len(people_at_home) == 0: if self.you.at_home: return "You are at home by yourself." else: return "No-one is home." else: res = "" if self.you.at_home: res += "You are at home with " lst = [str(p.nickname) for p in people_at_home] if len(lst) == 1: res += lst[0] + "." else: res += ", ".join(lst[:-1]) + " and " + lst[-1] + "." return res def who_out(self): people_out = [] for i, p in enumerate(self.people): if not p.at_home: people_out.append(p) if len(people_out) == 0: if self.you.at_home: return "Everyone is home." else: return "Everyone but you is home." else: res = "" if not self.you.at_home: res += "You, " lst = [str(p.nickname) for p in people_out] if len(lst) == 1: res += lst[0] else: res += ", ".join(lst[:-1]) + " and " + lst[-1] return res + " are out." def set_home(self, name): if name == 'me': self.you.set_home() self.save() return "Set your home to where you are." else: p = self.person_n.get(name.lower()) if p is None: return "Could not find {}.".format(name) else: p.set_home() self.save() return "Set home of {}.".format(p.nickname) def save(self): f = open(FNAME, "w") for p in self.person_d.values(): x = p.serialise() if x is not None: f.write(x) def whereis(self, name): if name == 'me': return self.you.get_info_str() else: p = self.person_n.get(name.lower()) if p is None: return "Could not find where \"{}\" is.".format(name) else: return p.get_info_str()
import re from locationsharinglib import Service service = Service("*****@*****.**", "3BUnwejC4BwDkTjP", cookies_file=".google_maps_location_sharing.cookies") for person in service.get_all_people(): print(person)
home_longitude = os.environ['HOME_LONGITUDE'] print("Pulling locations for", email) client = mqtt.Client() client.connect(mqtt_server, 1883, 60) client.loop_start() print("Connected to", mqtt_server) service = Service(email, password) home = (float(home_latitude), float(home_longitude)) while True: people = service.get_all_people() print("Found " + str(len(people)) + " people.") for person in people: # ignore locations that are not at least accurate within 1000 meters if person._accuracy > 1000: continue mqtt_topic = 'google/location/' + person.full_name.lower().replace( " ", "_") mqtt_data = { "latitude": person.latitude, "longitude": person.longitude, "datetime": int(person.datetime.timestamp()), "gps_accuracy": person._accuracy } # if home is within the accuracy radius, assume home