class MemoCache(Cache): """Manages cached values for a single st.memo-ized function.""" def __init__( self, key: str, persist: Optional[str], max_entries: float, ttl: float, display_name: str, ): self.key = key self.display_name = display_name self.persist = persist self._mem_cache = TTLCache(maxsize=max_entries, ttl=ttl, timer=_TTLCACHE_TIMER) self._mem_cache_lock = threading.Lock() @property def max_entries(self) -> float: return cast(float, self._mem_cache.maxsize) @property def ttl(self) -> float: return cast(float, self._mem_cache.ttl) def get_stats(self) -> List[CacheStat]: stats: List[CacheStat] = [] with self._mem_cache_lock: for item_key, item_value in self._mem_cache.items(): stats.append( CacheStat( category_name="st_memo", cache_name=self.display_name, byte_length=len(item_value), ) ) return stats def read_value(self, key: str) -> Any: """Read a value from the cache. Raise `CacheKeyNotFoundError` if the value doesn't exist, and `CacheError` if the value exists but can't be unpickled. """ try: pickled_value = self._read_from_mem_cache(key) except CacheKeyNotFoundError as e: if self.persist == "disk": pickled_value = self._read_from_disk_cache(key) self._write_to_mem_cache(key, pickled_value) else: raise e try: return pickle.loads(pickled_value) except pickle.UnpicklingError as exc: raise CacheError(f"Failed to unpickle {key}") from exc def write_value(self, key: str, value: Any) -> None: """Write a value to the cache. It must be pickleable.""" try: pickled_value = pickle.dumps(value) except pickle.PicklingError as exc: raise CacheError(f"Failed to pickle {key}") from exc self._write_to_mem_cache(key, pickled_value) if self.persist == "disk": self._write_to_disk_cache(key, pickled_value) def _read_from_mem_cache(self, key: str) -> bytes: with self._mem_cache_lock: if key in self._mem_cache: entry = bytes(self._mem_cache[key]) _LOGGER.debug("Memory cache HIT: %s", key) return entry else: _LOGGER.debug("Memory cache MISS: %s", key) raise CacheKeyNotFoundError("Key not found in mem cache") def _read_from_disk_cache(self, key: str) -> bytes: path = self._get_file_path(key) try: with streamlit_read(path, binary=True) as input: value = input.read() _LOGGER.debug("Disk cache HIT: %s", key) return bytes(value) except FileNotFoundError: raise CacheKeyNotFoundError("Key not found in disk cache") except BaseException as e: _LOGGER.error(e) raise CacheError("Unable to read from cache") from e def _write_to_mem_cache(self, key: str, pickled_value: bytes) -> None: with self._mem_cache_lock: self._mem_cache[key] = pickled_value def _write_to_disk_cache(self, key: str, pickled_value: bytes) -> None: path = self._get_file_path(key) try: with streamlit_write(path, binary=True) as output: output.write(pickled_value) except util.Error as e: _LOGGER.debug(e) # Clean up file so we don't leave zero byte files. try: os.remove(path) except (FileNotFoundError, IOError, OSError): pass raise CacheError("Unable to write to cache") from e def _get_file_path(self, value_key: str): """Return the path of the disk cache file for the given value.""" return get_streamlit_file_path(_CACHE_DIR_NAME, f"{self.key}-{value_key}.memo")
class Processor: def __init__(self): self.socket = WebSocket("0.0.0.0", 5678, MaxTokensAtOnce, TokensTTL, self) self.socket.start() self.database = database.Database() self.externalAPI = ExternalAPI(None, None, None, None).metrics self.userThreads = {} self.clientTokens = TTLCache(maxsize=MaxTokensAtOnce, ttl=TokensTTL) self.medicTokens = TTLCache(maxsize=MaxTokensAtOnce, ttl=TokensTTL) self.userMetrics = {} allUsers = self.database.getAllUsers() for user in allUsers: metrics = { } #{GPS: [metric], HealthStatus: [metric, metric], Sleep:[metric]} userDevices = self.database.getAllDevices(user) for device in userDevices: deviceType = device["type"].strip().replace(" ", "_") userDevice = eval(deviceType + "(device[\"authentication_fields\"],\"" + user + "\",\"" + str(device.get("id", "")) + "\", [" + str(device.get("latitude", str(None))) + "," + str(device.get("longitude", str(None))) + "])") for metric in userDevice.metrics: if metric.metricType not in metrics: metrics[metric.metricType] = [] metrics[metric.metricType].append(metric) for metric in GPS(None, user, None, None).metrics + self.externalAPI: if metric.metricType not in metrics: metrics[metric.metricType] = [] metrics[metric.metricType].append(metric) self.userMetrics[user] = metrics #print(metrics) #passing only the GPS, HealthStatus and Sleep to the Thread self.userThreads[user] = AggregatorThread( self, { k: v for k, v in metrics.items() if k in ["GPS", "HealthStatus", "Sleep"] }, user) self.userThreads[user].start() #urls["https://api.fitbit.com/1/user/-/activities/heart/date/today/1d.json"]=[{"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkRLMlgiLCJzdWIiOiI3Q05RV1oiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyc29jIHJhY3QgcnNldCBybG9jIHJ3ZWkgcmhyIHJudXQgcnBybyByc2xlIiwiZXhwIjoxNTUzODAxNjA5LCJpYXQiOjE1NTM3NzI4MDl9.6_hSXgYG36430e-ZaRfcEYSzDezGJeaMF5R2PiSr4bk"}, 1] #urls["http://api.foobot.io/v2/device/240D676D40002482/datapoint/10/last/0/"]=[{"Accept":"application/json;charset=UTF-8","X-API-KEY-TOKEN":"eyJhbGciOiJIUzI1NiJ9.eyJncmFudGVlIjoiam9hby5wQHVhLnB0IiwiaWF0IjoxNTUyMDY2Njc5LCJ2YWxpZGl0eSI6LTEsImp0aSI6IjRiNmY2NzhiLWJjNTYtNDYxNi1hYmMyLTRiNjlkMTNkMjUzOSIsInBlcm1pc3Npb25zIjpbInVzZXI6cmVhZCIsImRldmljZTpyZWFkIl0sInF1b3RhIjoyMDAsInJhdGVMaW1pdCI6NX0.aeLLsrhh1-DVXSwl-Z_qDx1Xbr9oIid1IKsOyGQxwqQ"},1] def signup(self, jsonData): try: self.database.register(jsonData) if jsonData["type"] == "client": user = jsonData["username"] if user not in self.userMetrics: self.userMetrics[user] = {} for metric in GPS({}, user, None, None).metrics + self.externalAPI: if metric.metricType not in self.userMetrics[user]: self.userMetrics[user][metric.metricType] = [] self.userMetrics[user][metric.metricType].append( metric) self.userThreads[user] = AggregatorThread( self, { k: v for k, v in self.userMetrics[user].items() if k in ["GPS", "HealthStatus", "Sleep"] }, user) self.userThreads[user].start() return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def logout(self, token): client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 elif client: del self.clientTokens[token] elif medic: del self.medicTokens[token] return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 def _generateToken(self, tokenMap, username): """ Generates a new token for a user and stores it :param tokenMap: self.clientTokens or self.medicTokens :type tokenMap: dict :param username: of the user loggedin :type username: str :return: the new token :rtype: str """ min_char = 30 max_char = 40 allchar = string.ascii_letters + string.digits for t, n in tokenMap.items(): if n == username: return t token = "".join( choice(allchar) for x in range(randint(min_char, max_char))) while token in tokenMap: token = "".join( choice(allchar) for x in range(randint(min_char, max_char))) tokenMap[token] = username return token def signin(self, jsonData): userType = self.database.verifyUser(jsonData) if userType == 0: # invalid login return json.dumps({ "status": 1, "msg": "Incorrect username or password." }).encode("UTF-8"), 406 elif userType == 1: # valid login and user is a client token = self._generateToken(self.clientTokens, jsonData["username"]) elif userType == 2: # valid login and user is a medic token = self._generateToken(self.medicTokens, jsonData["username"]) return json.dumps({ "status": 0, "msg": "Successful operation.", "data": { "token": token } }).encode("UTF-8"), 200 def getAllDevices(self, token): if self.medicTokens.get(token): return json.dumps({ "status": 1, "msg": "Medic users don't have devices associated." }).encode("UTF-8"), 406 user = self.clientTokens.get(token, None) if not user: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: devices = self.database.getAllDevices(user) for device in devices: auth_fields = device.pop("authentication_fields") for field_name, field_value in auth_fields.items(): device[field_name] = field_value except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 return json.dumps({ "status": 0, "msg": "Successful operation.", "data": devices }).encode("UTF-8"), 200 def updateDevice(self, token, deviceConf): if self.medicTokens.get(token): return json.dumps({ "status": 3, "msg": "Medic users don't have devices associated." }).encode("UTF-8"), 403 user = self.clientTokens.get(token, None) if not user: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: userDevices = { submetric.dataSource for metric in self.userMetrics[user] for submetric in self.userMetrics[user][metric] } for device in userDevices: if device.id == str(deviceConf["id"]): latitude = deviceConf[ "latitude"] if "latitude" in deviceConf else device._location[ 0] longitude = deviceConf[ "longitude"] if "longitude" in deviceConf else device._location[ 1] device.update(deviceConf["authentication_fields"], [latitude, longitude]) if user in self.userThreads: self.userThreads[user].end() self.userThreads[user] = AggregatorThread( self, { k: v for k, v in self.userMetrics[user].items() if k in ["GPS", "HealthStatus", "Sleep"] }, user) self.userThreads[user].start() break self.database.updateDevice(user, deviceConf) return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def deleteDevice(self, token, data): if self.medicTokens.get(token): return json.dumps({ "status": 3, "msg": "Medic users don't have devices associated." }).encode("UTF-8"), 403 user = self.clientTokens.get(token, None) if not user: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: deviceId = data["id"] for metric in self.userMetrics[user]: for submetric in self.userMetrics[user][metric]: if submetric.dataSource.id == deviceId: self.userMetrics[user][metric].remove(submetric) self.database.deleteDevice(user, deviceId) if user in self.userThreads: self.userThreads[user].end() self.userThreads[user] = AggregatorThread( self, { k: v for k, v in self.userMetrics[user].items() if k in ["GPS", "HealthStatus", "Sleep"] }, user) self.userThreads[user].start() return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def addDevice(self, token, jsonData): if self.medicTokens.get(token): return json.dumps({ "status": 3, "msg": "Medic users don't have devices associated." }).encode("UTF-8"), 403 user = self.clientTokens.get(token, None) if not user: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: id = str(self.database.addDevice(user, jsonData)) print(id) if id not in [ submetric.dataSource.id for metric in self.userMetrics[user] for submetric in self.userMetrics[user][metric] ]: deviceType = jsonData["type"].strip().replace(" ", "_") device = eval(deviceType + "(jsonData[\"authentication_fields\"],\"" + user + "\",\"" + str(id) + "\", [" + jsonData.get("latitude", str(None)) + "," + jsonData.get("longitude", str(None)) + "])") for metric in device.metrics: if metric.metricType not in self.userMetrics[user]: self.userMetrics[user][metric.metricType] = [] self.userMetrics[user][metric.metricType].append(metric) print(self.userMetrics) if user in self.userThreads: self.userThreads[user].end() self.userThreads[user] = AggregatorThread( self, { k: v for k, v in self.userMetrics[user].items() if k in ["GPS", "HealthStatus", "Sleep"] }, user) self.userThreads[user].start() return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def getData(self, token, endpoint, start, end, interval, patient): client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: if client: values = self.database.getData(endpoint, client, start, end, interval) elif medic: if endpoint == "Path": return json.dumps({ "status": 4, "msg": "Only accecible to patitents." }).encode("UTF-8"), 401 if not patient: return json.dumps({ "status": 2, "msg": "Missing argument \"patient\"" }).encode("UTF-8"), 400 values = self.database.getDataByMedic(medic, endpoint, patient, start, end, interval) return json.dumps({ "status": 0, "msg": "Successful operation.", "data": values }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def download(self, userCount): """ Gets all data from a number of users, received If the number received is less than the number of existing users than the users are chosen randomly Else all the users are sent :param userCount: number os users to retrieve :type userCount: int :return: of all users, with all metrics and its data in each one :rtype: list """ users = self.database.getAllUsers() if userCount < len(users): users = choices(users, k=userCount) allData = [] for user in users: userData = {} for metric in [ "Environment", "Event", "HealthStatus", "Path", "PersonalStatus", "Sleep" ]: userData[metric] = self.database.getData( metric, user, 0, None, None) allData.append(userData) return json.dumps({ "status": 0, "msg": "Successful operation.", "data": allData }).encode("UTF-8") def updateProfile(self, token, data): client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 elif client: user = client elif medic: user = medic argsErrors = ArgumentValidator.signupAndUpdateProfile( True if client else False, True, data) if len(argsErrors) > 0: return json.dumps({ "status": 2, "msg": "Argument errors : " + ", ".join(argsErrors) }).encode("UTF-8"), 400 try: self.database.updateProfile("client" if client else "medic", user, data) return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def getProfile(self, token, data): client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) patient = None if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 elif client: user = client elif medic: user = medic patient = data.get("patient") try: if patient: profile = self.database.getPatientProfile(medic, patient) else: profile = self.database.getProfile(user) return json.dumps({ "status": 0, "msg": "Successful operation.", "data": profile }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def deleteProfile(self, token): client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 elif client: user = client elif medic: user = medic try: self.database.deleteProfile(user) return json.dumps({ "status": 0, "msg": "Successful operation." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def getSupportedDevices(self): try: values = self.database.getSupportedDevices() return json.dumps({ "status": 0, "msg": "Successful operation.", "data": values }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def uploadPermission(self, token, jsonData): """ Use by both medic and client grants/requests for a permission. calls 'grantPermission' and 'requestPermission' on database.py args: username - str - of the user the he wants to grant or request permission data - {username:str, health_number: int, duration: int} """ client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 argsErrors = ArgumentValidator.uploadPermissions( "medic" if medic else "client", jsonData) if len(argsErrors) > 0: return json.dumps({ "status": 2, "msg": "Argument errors : " + ", ".join(argsErrors) }).encode("UTF-8"), 400 try: target = jsonData["username"] targetToken = None for (k1, v1), (k2, v2) in zip(self.medicTokens.items(), self.clientTokens.items()): if v1 == target or v2 == target: targetToken = (k1 if v1 == target else k2) if client: source, destination = self.database.grantPermission( client, jsonData) elif medic: source, destination = self.database.requestPermission( medic, jsonData) permissionThread([source], targetToken, self.socket).start() return json.dumps({ "status": 0, "msg": "Successful operation.", "data": destination }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def getAllPermissions(self, token): """ Use by both medic and client gets all current permissions. calls 'allPermissionsData' on database.py """ client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: data = self.database.allPermissionsData( client if client else medic) return json.dumps({ "status": 0, "msg": "Successful operation.", "data": data }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def acceptPermission(self, token, medic): """ Used only by the client, accepts a pending permission args: token - str - token representing the user medic - str - of the medic that he wants to reject request for permission """ if self.medicTokens.get(token): return json.dumps({ "status": 1, "msg": "Only accessible to patients" }).encode("UTF-8"), 406 client = self.clientTokens.get(token) if not client: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: self.database.acceptPermission(client, medic) return json.dumps({ "status": 0, "msg": "Successful operation. Permission accepted with success." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def rejectPermission(self, token, medic): """ Used only by the client, rejects a pending permission args: token - str - token representing the user medic - str - of the medic that he wants to reject request for permission """ if self.medicTokens.get(token): return json.dumps({ "status": 1, "msg": "Only accessible to patients" }).encode("UTF-8"), 406 client = self.clientTokens.get(token) if not client: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: self.database.rejectPermission(client, medic) return json.dumps({ "status": 0, "msg": "Successful operation. Permission rejected with success." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def removePendingPermission(self, token, client): """ Used only by the medic, removes a pending permission (requests not responded by the client) args token - str - token representing the user client - str - of the client that he wants to remove the active permission """ if self.clientTokens.get(token): return json.dumps({ "status": 1, "msg": "Only accessible to medics" }).encode("UTF-8"), 406 medic = self.medicTokens.get(token) if not medic: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: self.database.deleteRequestPermission(medic, client) return json.dumps({ "status": 0, "msg": "Successful operation. Permission removed with success." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def removeAcceptedPermission(self, token, medic): """ Used only by the client, removes an accepted permission args token - str - token representing the user username - str - of the medic that he wants to remove an accepted permission """ if self.medicTokens.get(token): return json.dumps({ "status": 1, "msg": "Only accessible to patients" }).encode("UTF-8"), 406 client = self.clientTokens.get(token) if not client: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 try: self.database.removeAcceptedPermission(client, medic) return json.dumps({ "status": 0, "msg": "Successful operation. Permission removed with success." }).encode("UTF-8"), 200 except LogicException as e: return json.dumps({ "status": 1, "msg": str(e) }).encode("UTF-8"), 406 except DatabaseException as e: return json.dumps({ "status": -1, "msg": str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "Server internal error. " + str(e) }).encode("UTF-8"), 500 def process(self, responses, user): normalData = {} for resp in responses: metric = resp[0] if metric not in normalData: normalData[metric] = {} normalData[metric] = dict(normalData[metric], **resp[1]) if "GPS" in normalData: envMetrics = [ submetric for metric in self.userMetrics[user] for submetric in self.userMetrics[user][metric] if submetric.metricType == "Environment" ] if normalData["GPS"]["latitude"] != None and normalData["GPS"][ "longitude"] != None: if float(normalData["GPS"]["latitude"]) > -90 and float( normalData["GPS"]["latitude"]) < 90 and float( normalData["GPS"]["longitude"]) > -180 and float( normalData["GPS"]["longitude"]) < 180: for metric in [ metric for metric in envMetrics if metric.metricLocation == "inside" ]: distance = round( vincenty([ float(normalData["GPS"]["latitude"]), float(normalData["GPS"]["longitude"]) ], metric.dataSource.location).m) if distance <= RADIUS: try: jsonData = metric.getData() data = metric.normalizeData(jsonData) normalData["Environment"] = dict( normalData["Environment"], **data) except Exception as e: logging.error( "<" + user + ">Exception caught while refetching the data: " + str(e)) try: tokens = metric.dataSource.refreshToken() self.updateDevice( metric.dataSource.user, { "id": metric.dataSource.id, "token": tokens["token"], "refresh_token": tokens["refresh_token"] }) resp = metric.normalizeData( metric.getData()) normalData["Environment"] = dict( normalData["Environment"], **data) except Exception as e: logging.error( "<" + user + ">Tried to refresh tokens and couldn't, caught error: " + str(e)) if normalData["Environment"] == {}: for metric in [ metric for metric in envMetrics if metric.metricLocation == "outside" ]: try: jsonData = metric.getData() data = metric.normalizeData(jsonData) normalData["Environment"] = dict( normalData["Environment"], **data) except Exception as e: logging.error( "<" + user + ">Exception caught while refetching the data: " + str(e)) try: tokens = metric.dataSource.refreshToken() self.updateDevice( metric.dataSource.user, { "id": metric.dataSource.id, "token": tokens["token"], "refresh_token": tokens["refresh_token"] }) resp = metric.normalizeData( metric.getData()) normalData["Environment"] = dict( normalData["Environment"], **data) except Exception as e: logging.error( "<" + user + ">Tried to refresh tokens and couldn't, caught error: " + str(e)) #print(normalData["GPS"]) normalData["Environment"]["latitude"] = normalData["GPS"][ "latitude"] normalData["Environment"]["longitude"] = normalData["GPS"][ "longitude"] else: logging.error("Couldn't process GPS: " + str(normalData["GPS"])) del normalData["GPS"] try: coords = self.userMetrics[user]["GPS"][0].normalizeData( self.userMetrics[user]["GPS"][0].getData()) responses.append(("Path", {"path": coords})) for metric in normalData: if metric != "Environment": normalData[metric]["latitude"] = coords["latitude"] normalData[metric]["longitude"] = coords["longitude"] except Exception as e: logging.error("<" + user + ">Error while fetching GPS Coordinates. " + str(e)) for metric in normalData: if time not in normalData[metric]: normalData[metric]["time"] = int(time.time()) print(normalData) try: self._save(normalData, user) except Exception as e: logging.error("<" + user + ">Error while saving data. " + str(e)) def registerMood(self, token, data): if self.medicTokens.get(token): return json.dumps({ "status": 1, "msg": "Only accessible to patients" }).encode("UTF-8"), 406 user = self.clientTokens.get(token) if not user: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 moods = data["moods"] concatMoods = moods[0] allMoods = {"events": [], "metrics": [], "data": {}} for m in moods: allMoods["events"].append(m) allMoods["metrics"].append("PersonalStatus") concatMoods += "," + m try: self.process([("PersonalStatus", { "moods": concatMoods[:-1] }), ("Event", { "events": json.dumps(allMoods) })], user) return json.dumps({ "status": 0, "msg": "Successful operation. Mood(s) registered with success." }).encode("UTF-8"), 200 except DatabaseException as e: return json.dumps({ "status": -1, "msg": "While saving data. " + str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "While saving data.Server internal error. " + str(e) }).encode("UTF-8"), 500 def deleteMood(self, token, data): if self.medicTokens.get(token): return json.dumps({ "status": 1, "msg": "Only accessible to patients" }).encode("UTF-8"), 406 user = self.clientTokens.get(token) if not user: return json.dumps({ "status": 4, "msg": "Invalid Token." }).encode("UTF-8"), 401 time = data["time"] deleteMetrics = ["Event", "PersonalStatus"] try: for metric in deleteMetrics: self.database.delete(metric, time, user) return json.dumps({ "status": 0, "msg": "Successful operation. Mood(s) deleted with success." }).encode("UTF-8"), 200 except DatabaseException as e: return json.dumps({ "status": -1, "msg": "While saving data. " + str(e) }).encode("UTF-8"), 500 except Exception as e: return json.dumps({ "status": -1, "msg": "While saving data. Server internal error. " + str(e) }).encode("UTF-8"), 500 def _save(self, data, user): try: for key in data: self.database.insert(key, data[key], user) except Exception as e: raise e def end(self): for k in self.userThreads: self.userThreads[k].end() return "" def checkPermissions(self, token): client = self.clientTokens.get(token, None) medic = self.medicTokens.get(token, None) if not client and not medic: logging.error("Invalid Token in check permissions of " + client if client else medic) return try: data = self.database.getPendingPermissions( client if client else medic) permissionThread(data, token, self.socket).start() except DatabaseException as e: logging.error("Database error in check permissions of " + client if client else medic + " -> " + str(e)) return except Exception as e: print(e) logging.error("Server error in check permissions of " + client if client else medic + " -> " + str(e)) return