diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba0430d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ \ No newline at end of file diff --git a/pytryfi/__init__.py b/pytryfi/__init__.py index 0a3eb7a..ad8da95 100644 --- a/pytryfi/__init__.py +++ b/pytryfi/__init__.py @@ -92,9 +92,8 @@ def updatePets(self): try: petListJSON = query.getPetList(self._session) updatedPets = [] - h = 0 for house in petListJSON: - for pet in petListJSON[h]['household']['pets']: + for pet in house['household']['pets']: p = FiPet(pet['id']) p.setPetDetailsJSON(pet) #get the current location and set it @@ -108,7 +107,6 @@ def updatePets(self): p.setRestStats(pRestStatsJSON['dailyStat'],pRestStatsJSON['weeklyStat'],pRestStatsJSON['monthlyStat']) LOGGER.debug(f"Adding Pet: {p._name} with Device: {p._device._deviceId}") updatedPets.append(p) - h = h + 1 self._pets = updatedPets except Exception as e: capture_exception(e) @@ -143,15 +141,14 @@ def updateBases(self): try: updatedBases = [] baseListJSON = query.getBaseList(self._session) - h = 0 for house in baseListJSON: - for base in baseListJSON[h]['household']['bases']: + for base in house['household']['bases']: b = FiBase(base['baseId']) b.setBaseDetailsJSON(base) updatedBases.append(b) - h = h + 1 self._bases = updatedBases except Exception as e: + LOGGER.error("Error fetching bases", exc_info=e) capture_exception(e) # return the pet object based on petId @@ -228,7 +225,4 @@ def login(self): LOGGER.debug(f"Successfully logged in. UserId: {self._userId}") except requests.RequestException as e: LOGGER.error(f"Cannot login, error: ({e})") - capture_exception(e) - raise requests.RequestException(e) - except Exception as e: - capture_exception(e) + raise e diff --git a/pytryfi/common/query.py b/pytryfi/common/query.py index f9d845f..1fe8034 100644 --- a/pytryfi/common/query.py +++ b/pytryfi/common/query.py @@ -1,172 +1,113 @@ from pytryfi.const import * from pytryfi.exceptions import * import json -import requests import logging -from sentry_sdk import capture_exception +import requests +from typing import Literal LOGGER = logging.getLogger(__name__) def getUserDetail(sessionId): - try: - qString = QUERY_CURRENT_USER + FRAGMENT_USER_DETAILS - response = query(sessionId, qString) - LOGGER.debug(f"getUserDetails: {response}") - return response['data']['currentUser'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_CURRENT_USER + FRAGMENT_USER_DETAILS + response = query(sessionId, qString) + LOGGER.debug(f"getUserDetails: {response}") + return response['data']['currentUser'] def getPetList(sessionId): - try: - qString = QUERY_CURRENT_USER_FULL_DETAIL + FRAGMENT_USER_DETAILS \ - + FRAGMENT_USER_FULL_DETAILS + FRAGMENT_PET_PROFILE + FRAGEMENT_BASE_PET_PROFILE \ - + FRAGMENT_BASE_DETAILS + FRAGMENT_POSITION_COORDINATES + FRAGMENT_BREED_DETAILS \ - + FRAGMENT_PHOTO_DETAILS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_LED_DETAILS + FRAGMENT_OPERATIONAL_DETAILS \ - + FRAGMENT_CONNECTION_STATE_DETAILS - response = query(sessionId, qString) - LOGGER.debug(f"getPetList: {response}") - return response['data']['currentUser']['userHouseholds'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_CURRENT_USER_FULL_DETAIL + FRAGMENT_USER_DETAILS \ + + FRAGMENT_USER_FULL_DETAILS + FRAGMENT_PET_PROFILE + FRAGEMENT_BASE_PET_PROFILE \ + + FRAGMENT_BASE_DETAILS + FRAGMENT_POSITION_COORDINATES + FRAGMENT_BREED_DETAILS \ + + FRAGMENT_PHOTO_DETAILS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_LED_DETAILS + FRAGMENT_OPERATIONAL_DETAILS \ + + FRAGMENT_CONNECTION_STATE_DETAILS + response = query(sessionId, qString) + LOGGER.debug(f"getPetList: {response}") + return response['data']['currentUser']['userHouseholds'] def getBaseList(sessionId): - try: - qString = QUERY_CURRENT_USER_FULL_DETAIL + FRAGMENT_USER_DETAILS \ - + FRAGMENT_USER_FULL_DETAILS + FRAGMENT_PET_PROFILE + FRAGEMENT_BASE_PET_PROFILE \ - + FRAGMENT_BASE_DETAILS + FRAGMENT_POSITION_COORDINATES + FRAGMENT_BREED_DETAILS \ - + FRAGMENT_PHOTO_DETAILS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_LED_DETAILS + FRAGMENT_OPERATIONAL_DETAILS \ - + FRAGMENT_CONNECTION_STATE_DETAILS - response = query(sessionId, qString) - LOGGER.debug(f"getBaseList: {response}") - return response['data']['currentUser']['userHouseholds'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_CURRENT_USER_FULL_DETAIL + FRAGMENT_USER_DETAILS \ + + FRAGMENT_USER_FULL_DETAILS + FRAGMENT_PET_PROFILE + FRAGEMENT_BASE_PET_PROFILE \ + + FRAGMENT_BASE_DETAILS + FRAGMENT_POSITION_COORDINATES + FRAGMENT_BREED_DETAILS \ + + FRAGMENT_PHOTO_DETAILS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_LED_DETAILS + FRAGMENT_OPERATIONAL_DETAILS \ + + FRAGMENT_CONNECTION_STATE_DETAILS + response = query(sessionId, qString) + LOGGER.debug(f"getBaseList: {response}") + return response['data']['currentUser']['userHouseholds'] def getCurrentPetLocation(sessionId, petId): - try: - qString = QUERY_PET_CURRENT_LOCATION.replace(VAR_PET_ID, petId) + FRAGMENT_ONGOING_ACTIVITY_DETAILS \ - + FRAGMENT_UNCERTAINTY_DETAILS + FRAGMENT_CIRCLE_DETAILS + FRAGMENT_LOCATION_POINT \ - + FRAGMENT_PLACE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_POSITION_COORDINATES - response = query(sessionId, qString) - LOGGER.debug(f"getCurrentPetLocation: {response}") - return response['data']['pet']['ongoingActivity'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_PET_CURRENT_LOCATION.replace(VAR_PET_ID, petId) + FRAGMENT_ONGOING_ACTIVITY_DETAILS \ + + FRAGMENT_UNCERTAINTY_DETAILS + FRAGMENT_CIRCLE_DETAILS + FRAGMENT_LOCATION_POINT \ + + FRAGMENT_PLACE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_POSITION_COORDINATES + response = query(sessionId, qString) + LOGGER.debug(f"getCurrentPetLocation: {response}") + return response['data']['pet']['ongoingActivity'] def getCurrentPetStats(sessionId, petId): - try: - qString = QUERY_PET_ACTIVITY.replace(VAR_PET_ID, petId) + FRAGMENT_ACTIVITY_SUMMARY_DETAILS - response = query(sessionId, qString) - LOGGER.debug(f"getCurrentPetStats: {response}") - return response['data']['pet'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_PET_ACTIVITY.replace(VAR_PET_ID, petId) + FRAGMENT_ACTIVITY_SUMMARY_DETAILS + response = query(sessionId, qString) + LOGGER.debug(f"getCurrentPetStats: {response}") + return response['data']['pet'] def getCurrentPetRestStats(sessionId, petId): - try: - qString = QUERY_PET_REST.replace(VAR_PET_ID, petId) + FRAGMENT_REST_SUMMARY_DETAILS - response = query(sessionId, qString) - LOGGER.debug(f"getCurrentPetStats: {response}") - return response['data']['pet'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_PET_REST.replace(VAR_PET_ID, petId) + FRAGMENT_REST_SUMMARY_DETAILS + response = query(sessionId, qString) + LOGGER.debug(f"getCurrentPetStats: {response}") + return response['data']['pet'] def getDevicedetails(sessionId, petId): - try: - qString = QUERY_PET_DEVICE_DETAILS.replace(VAR_PET_ID, petId) + FRAGMENT_PET_PROFILE + FRAGEMENT_BASE_PET_PROFILE + FRAGMENT_DEVICE_DETAILS + FRAGMENT_LED_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_BREED_DETAILS + FRAGMENT_PHOTO_DETAILS - response = query(sessionId, qString) - LOGGER.debug(f"getDevicedetails: {response}") - return response['data']['pet'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = QUERY_PET_DEVICE_DETAILS.replace(VAR_PET_ID, petId) + FRAGMENT_PET_PROFILE + FRAGEMENT_BASE_PET_PROFILE + FRAGMENT_DEVICE_DETAILS + FRAGMENT_LED_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_BREED_DETAILS + FRAGMENT_PHOTO_DETAILS + response = query(sessionId, qString) + LOGGER.debug(f"getDevicedetails: {response}") + return response['data']['pet'] def setLedColor(sessionId, deviceId, ledColorCode): - try: - qString = MUTATION_SET_LED_COLOR + FRAGMENT_DEVICE_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_LED_DETAILS - qVariables = '{"moduleId":"'+deviceId+'","ledColorCode":'+str(ledColorCode)+'}' - response = mutation(sessionId, qString, qVariables) - LOGGER.debug(f"setLedColor: {response}") - return response['data'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = MUTATION_SET_LED_COLOR + FRAGMENT_DEVICE_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_LED_DETAILS + qVariables = '{"moduleId":"'+deviceId+'","ledColorCode":'+str(ledColorCode)+'}' + response = mutation(sessionId, qString, qVariables) + LOGGER.debug(f"setLedColor: {response}") + return response['data'] def turnOnOffLed(sessionId, moduleId, ledEnabled): - try: - qString = MUTATION_DEVICE_OPS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_LED_DETAILS - qVariables = '{"input": {"moduleId":"'+moduleId+'","ledEnabled":'+str(ledEnabled).lower()+'}}' - response = mutation(sessionId, qString, qVariables) - LOGGER.debug(f"turnOnOffLed: {response}") - return response['data'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + qString = MUTATION_DEVICE_OPS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_LED_DETAILS + qVariables = '{"input": {"moduleId":"'+moduleId+'","ledEnabled":'+str(ledEnabled).lower()+'}}' + response = mutation(sessionId, qString, qVariables) + LOGGER.debug(f"turnOnOffLed: {response}") + return response['data'] def setLostDogMode(sessionId, moduleId, action): - try: - if action: - mode = PET_MODE_LOST - else: - mode = PET_MODE_NORMAL - qString = MUTATION_DEVICE_OPS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_LED_DETAILS - qVariables = '{"input": {"moduleId":"'+moduleId+'","mode":"'+mode+'"}}' - response = mutation(sessionId, qString, qVariables) - LOGGER.debug(f"setLostDogMode: {response}") - return response['data'] - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + if action: + mode = PET_MODE_LOST + else: + mode = PET_MODE_NORMAL + qString = MUTATION_DEVICE_OPS + FRAGMENT_DEVICE_DETAILS + FRAGMENT_OPERATIONAL_DETAILS + FRAGMENT_CONNECTION_STATE_DETAILS + FRAGMENT_USER_DETAILS + FRAGMENT_LED_DETAILS + qVariables = '{"input": {"moduleId":"'+moduleId+'","mode":"'+mode+'"}}' + response = mutation(sessionId, qString, qVariables) + LOGGER.debug(f"setLostDogMode: {response}") + return response['data'] def getGraphqlURL(): - try: - return API_HOST_URL_BASE + API_GRAPHQL - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + return API_HOST_URL_BASE + API_GRAPHQL def mutation(sessionId, qString, qVariables): - try: - jsonObject = None - url = getGraphqlURL() - - params = {"query": qString, "variables": json.loads(qVariables)} - jsonObject = execute(url, sessionId, params=params, method='POST').json() - return jsonObject - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) + jsonObject = None + url = getGraphqlURL() + + params = {"query": qString, "variables": json.loads(qVariables)} + jsonObject = execute(url, sessionId, params=params, method='POST').json() + return jsonObject -def query(sessionId, qString): - try: - jsonObject = None - url = getGraphqlURL() - params={'query': qString} - jsonObject = execute(url, sessionId, params=params).json() - return jsonObject - except Exception as e: - LOGGER.error("Error performing query: " + e) - capture_exception(e) +def query(sessionId : requests.Session, qString): + jsonObject = None + url = getGraphqlURL() + params={'query': qString} + jsonObject = execute(url, sessionId, params=params).json() + return jsonObject -def execute(url, sessionId, method='GET', params=None, cookies=None): +def execute(url : str, sessionId : requests.Session, method: Literal['GET', 'POST'] = 'GET', params=None, cookies=None): response = None - try: - if method == 'GET': - response = sessionId.get(url, params=params) - elif method == 'POST': - response = sessionId.post(url, json=params) - else: - raise TryFiError(f"Method Passed was invalid: {method}") - except requests.RequestException as e: - capture_exception(e) - raise requests.RequestException(e) - except Exception as e: - capture_exception(e) + if method == 'GET': + response = sessionId.get(url, params=params) + elif method == 'POST': + response = sessionId.post(url, json=params) + else: + raise TryFiError(f"Method Passed was invalid: {method}. Only GET and POST are supported") return response - \ No newline at end of file diff --git a/pytryfi/const.py b/pytryfi/const.py index e3f3184..b4cd40c 100644 --- a/pytryfi/const.py +++ b/pytryfi/const.py @@ -1,6 +1,6 @@ SENTRY_URL = "https://c7618923f758480ca2af05a21123f855@o580516.ingest.sentry.io/5735605" -PYTRYFI_VERSION = "0.0.21" +PYTRYFI_VERSION = "0.0.22" API_HOST_URL_BASE = "https://api.tryfi.com" API_GRAPHQL = "/graphql" diff --git a/pytryfi/fiPet.py b/pytryfi/fiPet.py index b0009f3..2e7c4a7 100644 --- a/pytryfi/fiPet.py +++ b/pytryfi/fiPet.py @@ -1,9 +1,9 @@ +import datetime import logging -from pytryfi.fiDevice import FiDevice from pytryfi.common import query -from pytryfi.exceptions import * from pytryfi.const import PET_ACTIVITY_ONGOINGWALK -import datetime +from pytryfi.exceptions import * +from pytryfi.fiDevice import FiDevice from sentry_sdk import capture_exception LOGGER = logging.getLogger(__name__) @@ -12,17 +12,9 @@ class FiPet(object): def __init__(self, petId): self._petId = petId - def setPetDetailsJSON(self, petJSON): - try: - self._name = petJSON['name'] - except: - LOGGER.warning(f"Unknown Pet Name") - self._name = "Unknown Pet Name" - try: - self._homeCityState = petJSON['homeCityState'] - except: - LOGGER.warning(f"Unknown City") - self._homeCityState = "FakeCity" + def setPetDetailsJSON(self, petJSON: dict): + self._name = petJSON.get('name') + self._homeCityState = petJSON.get('homeCityState') try: self._yearOfBirth = int(petJSON['yearOfBirth']) except: @@ -37,23 +29,14 @@ def setPetDetailsJSON(self, petJSON): self._dayOfBirth = int(petJSON['dayOfBirth']) except: LOGGER.warning(f"Unknown day of birth") - self._dayOfBirth = 1 - try: - self._gender = petJSON['gender'] - except: - LOGGER.warning(f"Unknown Gender") - self._gender = "Male" - try: - #weight is in kg - self._weight = float(petJSON['weight']) - except: - LOGGER.warning(f"Unknown Weight") - self._weight = float(1.00) + self._dayOfBirth = None + self._gender = petJSON.get('gender') + self._weight = float(petJSON['weight']) if 'weight' in petJSON else None try: self._breed = petJSON['breed']['name'] except: LOGGER.warning(f"Unknown Breed of Dog") - self._breed = "Dog" + self._breed = None #track last updated self._lastUpdated = datetime.datetime.now() try: @@ -62,11 +45,9 @@ def setPetDetailsJSON(self, petJSON): #capture_exception(e) LOGGER.warning(f"Cannot find photo of your pet. Defaulting to empty string.") self._photoLink = "" - try: - self._device = FiDevice(petJSON['device']['id']) - self._device.setDeviceDetailsJSON(petJSON['device']) - except Exception as e: - capture_exception(e) + self._device = FiDevice(petJSON['device']['id']) + self._device.setDeviceDetailsJSON(petJSON['device']) + self._connectedTo = self.setConnectedTo(petJSON['device']['lastConnectionState']) def __str__(self): return f"Last Updated - {self.lastUpdated} - Pet ID: {self.petId} Name: {self.name} Is Lost: {self.isLost} From: {self.homeCityState} ActivityType: {self.activityType} Located: {self.currLatitude},{self.currLongitude} Last Updated: {self.currStartTime}\n \ @@ -80,21 +61,20 @@ def setCurrentLocation(self, activityJSON): try: if activityType == PET_ACTIVITY_ONGOINGWALK: positionSize = len(activityJSON['positions']) - self._currLongitude = float(activityJSON['positions'][positionSize-1]['position']['longitude']) - self._currLatitude = float(activityJSON['positions'][positionSize-1]['position']['latitude']) - self._currStartTime = datetime.datetime.fromisoformat(activityJSON['start'].replace('Z', '+00:00')) + currentPosition = activityJSON['positions'][positionSize-1]['position'] + self._currLongitude = float(currentPosition['longitude']) + self._currLatitude = float(currentPosition['latitude']) else: self._currLongitude = float(activityJSON['position']['longitude']) self._currLatitude = float(activityJSON['position']['latitude']) - self._currStartTime = datetime.datetime.fromisoformat(activityJSON['start'].replace('Z', '+00:00')) - try: + self._currStartTime = datetime.datetime.fromisoformat(activityJSON['start'].replace('Z', '+00:00')) + + if 'place' in activityJSON: self._currPlaceName = activityJSON['place']['name'] self._currPlaceAddress = activityJSON['place']['address'] - except Exception as e: - #capture_exception(e) - LOGGER.warning("Could not set place, defaulting to Unknown") - self._currPlaceName = "UNKNOWN" - self._currPlaceAddress = "UNKNOWN" + else: + self._currPlaceName = None + self._currPlaceAddress = None self._lastUpdated = datetime.datetime.now() except TryFiError as e: capture_exception(e) @@ -103,39 +83,31 @@ def setCurrentLocation(self, activityJSON): except Exception as e: capture_exception(e) + def setConnectedTo(self, connectedToJSON): + connectedToString = "" + typename = connectedToJSON['__typename'] + if typename == 'ConnectedToUser': + connectedToString = connectedToJSON['user']['firstName'] + " " + connectedToJSON['user']['lastName'] + elif typename == 'ConnectedToCellular': + connectedToString = "Cellular Signal Strength - " + str(connectedToJSON['signalStrengthPercent']) + elif typename == 'ConnectedToBase': + connectedToString = "Base ID - " + connectedToJSON['chargingBase']['id'] + else: + connectedToString = None + return connectedToString + # set the Pet's current steps, goals and distance details for daily, weekly and monthly def setStats(self, activityJSONDaily, activityJSONWeekly, activityJSONMonthly): - try: #distance is in metres - self._dailyGoal = int(activityJSONDaily['stepGoal']) - self._dailySteps = int(activityJSONDaily['totalSteps']) - self._dailyTotalDistance = float(activityJSONDaily['totalDistance']) - except TryFiError as e: - LOGGER.error(f"Unable to set values Daily Stats for Pet {self.name}.\nException: {e}\nwhile parsing {activityJSONDaily}") - capture_exception(e) - raise TryFiError("Unable to set Pet Daily Stats") - except Exception as e: - capture_exception(e) - try: - self._weeklyGoal = int(activityJSONWeekly['stepGoal']) - self._weeklySteps = int(activityJSONWeekly['totalSteps']) - self._weeklyTotalDistance = float(activityJSONWeekly['totalDistance']) - except TryFiError as e: - LOGGER.error(f"Unable to set values Weekly Stats for Pet {self.name}.\nException: {e}\nwhile parsing {activityJSONWeekly}") - capture_exception(e) - raise TryFiError("Unable to set Pet Weekly Stats") - except Exception as e: - capture_exception(e) - try: - self._monthlyGoal = int(activityJSONMonthly['stepGoal']) - self._monthlySteps = int(activityJSONMonthly['totalSteps']) - self._monthlyTotalDistance = float(activityJSONMonthly['totalDistance']) - except TryFiError as e: - LOGGER.error(f"Unable to set values Monthly Stats for Pet {self.name}.\nException: {e}\nwhile parsing {activityJSONMonthly}") - capture_exception(e) - raise TryFiError("Unable to set Pet Monthly Stats") - except Exception as e: - capture_exception(e) + self._dailyGoal = int(activityJSONDaily['stepGoal']) + self._dailySteps = int(activityJSONDaily['totalSteps']) + self._dailyTotalDistance = float(activityJSONDaily['totalDistance']) + self._weeklyGoal = int(activityJSONWeekly['stepGoal']) + self._weeklySteps = int(activityJSONWeekly['totalSteps']) + self._weeklyTotalDistance = float(activityJSONWeekly['totalDistance']) + self._monthlyGoal = int(activityJSONMonthly['stepGoal']) + self._monthlySteps = int(activityJSONMonthly['totalSteps']) + self._monthlyTotalDistance = float(activityJSONMonthly['totalDistance']) self._lastUpdated = datetime.datetime.now() @@ -279,7 +251,6 @@ def setLostDogMode(self, sessionId, action): capture_exception(e) return True except Exception as e: - LOGGER.error(f"Could not complete Lost Dog Mode request:\n{e}") LOGGER.error(f"Could not complete turn on/off light where ledEnable is {action}.\nException: {e}") capture_exception(e) return False @@ -392,6 +363,10 @@ def activityType(self): def areaName(self): return self._areaName + @property + def connectedTo(self): + return self._connectedTo + def getCurrPlaceName(self): return self.currPlaceName