From 905e0de05e76efe9a32c394753d068ff0b5df368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:02:01 +0900 Subject: [PATCH 01/77] =?UTF-8?q?fix:=20=ED=86=A0=ED=81=B0=EC=9D=84=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20rou?= =?UTF-8?q?te2=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/fastapi/app/__init__.py b/backend/fastapi/app/__init__.py index f296513f..64f238c6 100644 --- a/backend/fastapi/app/__init__.py +++ b/backend/fastapi/app/__init__.py @@ -14,10 +14,10 @@ # 라우트 설정 def create_app(): - from . import routes - app.include_router(routes.router) + from . import routes2 + app.include_router(routes2.router) - routes.sched.start() + routes2.sched.start() return app From dd80e405edcb9d94b90723c8ebcd2615f0fc3076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:02:24 +0900 Subject: [PATCH 02/77] =?UTF-8?q?fix:=20=ED=8F=89=EA=B7=A0=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=86=8D=EB=8F=84=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index bb937dc0..b6e12561 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -202,4 +202,18 @@ class locpredict(BaseModel): class PredictLocationResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result : locpredict \ No newline at end of file + result : locpredict + +class AverageWalkingSpeedRequest(BaseModel): + dementiaKey : int = Field(examples=["123456"]) + +class AverageAndLastLoc(BaseModel): + averageSpeed : float = Field(examples=["2.0"]) + lastLatitude : float = Field(examples=["37.123456"]) + lastLongitude : float = Field(examples=["127.123456"]) + addressName : str = Field(examples=["서울특별시 강남구 니가 사는 그 집"]) + +class AverageWalkingSpeedResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: AverageAndLastLoc \ No newline at end of file From dca2d5545d0d9346a05fcf72c92374a745b0a43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:02:48 +0900 Subject: [PATCH 03/77] =?UTF-8?q?fix:=20fcm=20test=20code=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/fcm_notification.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/fcm_notification.py b/backend/fastapi/app/fcm_notification.py index 1180213d..ab56a918 100644 --- a/backend/fastapi/app/fcm_notification.py +++ b/backend/fastapi/app/fcm_notification.py @@ -5,9 +5,18 @@ -def send_push_notification(token, body, title): +def send_push_notification(token, body, title, data): - result = push_service.notify_single_device(registration_id=token, message_title=title, message_body=body) + #result = push_service.notify_single_device(registration_id=token, message_title=title, message_body=body) + + result = push_service.notify_single_device( + registration_id=token, + message_title=title, + message_body=body, + data_message={ + "이도영": data + } + ) return result From 3a41378e3a7f46c4a2bfc7186c5097060f1c69a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:03:19 +0900 Subject: [PATCH 04/77] =?UTF-8?q?fix:=20refresh=20token=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20primary=20key=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index 1bf91423..bfc9a9e7 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -78,5 +78,5 @@ class police_info(Base): class refresh_token_info(Base): __tablename__ = 'refresh_token_info' - key = Column(String) + key = Column(String, primary_key=True) refresh_token = Column(String) \ No newline at end of file From 3b77242b783829c54ead9fcad23f78a25888bbd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:03:39 +0900 Subject: [PATCH 05/77] =?UTF-8?q?fix:=20fcm=20test=20code=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/backend/fastapi/app/routes.py b/backend/fastapi/app/routes.py index df1ec7ff..34acf65b 100644 --- a/backend/fastapi/app/routes.py +++ b/backend/fastapi/app/routes.py @@ -15,7 +15,7 @@ from .config import Config from .schedularFunc import SchedulerFunc from .fcm_notification import send_push_notification -from .LocationPredict import ForecastLSTMClassification, Preprocessing +#from .LocationPredict import ForecastLSTMClassification, Preprocessing import asyncio import datetime @@ -868,15 +868,11 @@ async def predict_location(user_info : int = Depends(APIKeyHeader(name = "Author session.close() -@router.post("/test/fcm", responses = {200 : {"model" : CommonResponse, "description" : "FCM 전송 성공" }}, description="FCM 테스트") -async def send_fcm(title: str, body: str, token: str): +@router.post("/test/fcm", description="FCM 테스트") +async def send_fcm(title: str, body: str, token: str, data : str): - send_push_notification(token, body, title) - - return { - 'status': 'success', - 'message': 'FCM sent' - } + return send_push_notification(token, body, title, data) + '''#스케줄러 비활성화 From 76b6c12bbbeed7811f576cf853d47f081151b58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:04:17 +0900 Subject: [PATCH 06/77] =?UTF-8?q?feat:=20=EC=9D=B4=EB=8F=99=EC=83=81?= =?UTF-8?q?=ED=83=9C=20str=20->=20int=20=EB=B3=80=EA=B2=BD=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/user_status_convertor.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 backend/fastapi/app/user_status_convertor.py diff --git a/backend/fastapi/app/user_status_convertor.py b/backend/fastapi/app/user_status_convertor.py new file mode 100644 index 00000000..da05b64b --- /dev/null +++ b/backend/fastapi/app/user_status_convertor.py @@ -0,0 +1,11 @@ +def convertor(data): + + status = { + "정지": 1, + "도보": 2, + "차량": 3, + "지하철": 4 + }.get(data, None) + + return status + \ No newline at end of file From ae11ae3e765ef24d57bc99beda66b09add8115c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sat, 18 May 2024 20:06:19 +0900 Subject: [PATCH 07/77] =?UTF-8?q?fix:=20=ED=86=A0=ED=81=B0=EC=9D=84=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20rou?= =?UTF-8?q?te2=20=EC=83=9D=EC=84=B1(=EC=86=8C=EC=85=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=82=AC=EC=9A=A9=20=EC=A0=84=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EC=9A=A9=20=EC=98=88=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 842 +++++++++++++++++++++++++++++++++ 1 file changed, 842 insertions(+) create mode 100644 backend/fastapi/app/routes2.py diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py new file mode 100644 index 00000000..b7f744c8 --- /dev/null +++ b/backend/fastapi/app/routes2.py @@ -0,0 +1,842 @@ +from fastapi import APIRouter, HTTPException, status, Depends +from fastapi.security import OAuth2PasswordRequestForm, APIKeyHeader, OAuth2PasswordBearer + +from apscheduler.schedulers.background import BackgroundScheduler +from passlib.context import CryptContext +from haversine import haversine +from PyKakao import Local + +from . import models +from .random_generator import RandomNumberGenerator +from .update_user_status import UpdateUserStatus +from .database import Database +from .bodymodel import * +from .util import JWTService +from .config import Config +from .schedularFunc import SchedulerFunc +from .fcm_notification import send_push_notification +from .user_status_convertor import convertor +#from .LocationPredict import ForecastLSTMClassification, Preprocessing + +import asyncio +import datetime +import requests +import urllib.parse +import pandas as pd +import time + + +router = APIRouter() +db = Database() +session = next(db.get_session()) +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +jwt = JWTService() +schedFunc = SchedulerFunc() +sched = BackgroundScheduler(timezone="Asia/Seoul", daemon=True) +kakao = Local(service_key=Config.kakao_service_key) +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + + +@router.post("/test/fcm", description="FCM 테스트") +async def send_fcm(title: str, body: str, token: str, data : str): + + return send_push_notification(token, body, title, data) + +@router.post("/noks",status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveNokInfoResponse, "description" : "유저 등록 성공" },404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호자가 보호 대상자의 정보를 등록") +async def receive_nok_info(request: ReceiveNokInfoRequest): + + _key_from_dementia = request.keyFromDementia + + rng = RandomNumberGenerator() + + try: + existing_dementia = session.query(models.dementia_info).filter(models.dementia_info.dementia_key == _key_from_dementia).first() + if existing_dementia: + _nok_name = request.nokName + _nok_phonenumber = request.nokPhoneNumber + + duplication_check = session.query(models.nok_info).filter(models.nok_info.nok_name == _nok_name, models.nok_info.nok_phonenumber == _nok_phonenumber, models.nok_info.dementia_info_key == _key_from_dementia).first() + + if duplication_check: + _key = duplication_check.nok_key + + else: + unique_key = None + for _ in range(10): + unique_key = rng.generate_unique_random_number(100000, 999999) + + _key = str(unique_key) + + new_nok = models.nok_info(nok_key=_key, nok_name=_nok_name, nok_phonenumber=_nok_phonenumber, dementia_info_key=_key_from_dementia, update_rate=1) # update_rate는 기본값 1분으로 설정 + session.add(new_nok) + session.commit() + + result = { + 'dementiaInfoRecord' : { + 'dementiaKey' : existing_dementia.dementia_key, + 'dementiaName': existing_dementia.dementia_name, + 'dementiaPhoneNumber': existing_dementia.dementia_phonenumber + }, + 'nokKey': _key + } + + print(f"[INFO] NOK information received from {existing_dementia.dementia_name}({existing_dementia.dementia_key})") + + response = { + 'status': 'success', + 'message': 'NOK information received', + 'result': result + } + + return response + + else: # 보호 대상자 인증번호가 등록되어 있지 않은 경우 + + print(f"[ERROR] Dementia key({_key_from_dementia}) not found") + + raise HTTPException(status_code=404, detail="Dementia key not found") + + finally: + session.close() + +@router.post("/dementias", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveDementiaInfoResponse, "description" : "유저 등록 성공" }}, description="보호 대상자의 정보를 등록") +async def receive_dementia_info(request: ReceiveDementiaInfoRequest): + + rng = RandomNumberGenerator() + + try: + _dementia_name = request.name + _dementia_phonenumber = request.phoneNumber + + duplication_check = session.query(models.dementia_info).filter(models.dementia_info.dementia_name == _dementia_name, models.dementia_info.dementia_phonenumber == _dementia_phonenumber).first() + + if duplication_check: # 기존의 인증번호를 가져옴 + _key = duplication_check.dementia_key + else: # 새로운 인증번호 생성 + unique_key = None + for _ in range(10): + unique_key = rng.generate_unique_random_number(100000, 999999) + + _key = str(unique_key) + + #_key = pwd_context.hash(unique_key) + + new_dementia = models.dementia_info(dementia_key=_key, dementia_name=_dementia_name, dementia_phonenumber=_dementia_phonenumber, update_rate=1) # update_rate는 기본값 1분으로 설정 + session.add(new_dementia) + session.commit() + + result = { + 'dementiaKey': _key + } + + response = { + 'status': 'success', + 'message' : 'Dementia information received', + 'result': result + } + + print(f"[INFO] Dementia information received from {_dementia_name}({_key})") + + return response + + finally: + session.close() + +@router.post("/connection", responses = {200 : {"model" : ConnectionResponse, "description" : "연결 확인 성공" }, 400: {"model": ErrorResponse, "description": "연결 실패"}}, description="보호자와 보호 대상자의 연결 확인") +async def is_connected(request: ConnectionRequest): + + _dementia_key = request.dementiaKey + + session = next(db.get_session()) + try: + existing_nok = session.query(models.nok_info).filter_by(dementia_info_key = _dementia_key).first() + if existing_nok: + result = { + 'nokInfoRecord':{ + 'nokKey': existing_nok.nok_key, + 'nokName': existing_nok.nok_name, + 'nokPhoneNumber': existing_nok.nok_phonenumber + } + } + response = { + 'status': 'success', + 'message': 'Connection check', + 'result': result + } + + print(f"[INFO] Connection check from {existing_nok.nok_name}(from {existing_nok.dementia_info_key})") + + return response + + else: + print (f"[ERROR] Connection denied from Dementia key({_dementia_key})") + + raise HTTPException(status_code=400, detail="Connection denied") + + finally: + session.close() + +@router.post("/login", responses = {200 : {"model" : CommonResponse, "description" : "로그인 성공" }, 400: {"model": ErrorResponse, "description": "로그인 실패"}}, description="보호자와 보호 대상자의 로그인 | isDementia : 0(보호자), 1(보호 대상자)") +async def receive_user_login(request: loginRequest): + _key = request.key + _isdementia = request.isDementia + try: + if _isdementia == 0: # 보호자인 경우 + existing_nok = session.query(models.nok_info).filter_by(nok_key = _key).first() + + if existing_nok: + response = { + 'status': 'success', + 'message': 'User login success', + } + print(f"[INFO] User login from {existing_nok.nok_name}({existing_nok.nok_key})") + + else: + print(f"[ERROR] User login failed from NOK key({_key})") + + raise HTTPException(status_code=400, detail="User login failed") + + elif _isdementia == 1: # 보호 대상자인 경우 + existing_dementia = session.query(models.dementia_info).filter_by(dementia_key = _key).first() + + if existing_dementia: + response = { + 'status': 'success', + 'message': 'User login success', + } + print(f"[INFO] User login from {existing_dementia.dementia_name}({existing_dementia.dementia_key})") + + else: + print(f"[ERROR] User login failed from Dementia key({_key})") + + raise HTTPException(status_code=400, detail="User login failed") + + return response + + finally: + session.close() + +@router.post("/locations/dementias", responses = {200 : {"model" : TempResponse, "description" : "위치 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 위치 정보를 전송 | isRingstoneOn : 0(무음), 1(진동), 2(벨소리)") +async def receive_location_info(request: ReceiveLocationRequest): + + try: + _dementia_key = request.dementiaKey + + existing_dementia = session.query(models.dementia_info).filter_by(dementia_key = _dementia_key).first() + + if existing_dementia: + + user_status_updater = UpdateUserStatus() + + accel = request.accelerationSensor + gyro = request.gyroSensor + direction = request.directionSensor + + prediction = user_status_updater.predict(accel, gyro, direction) + + if prediction[0]==1: + status = "정지" + elif prediction[0]==2: + status = "도보" + elif prediction[0]==3: + status = "차량" + elif prediction[0]==4: + status = "지하철" + else: + pass + + new_location = models.location_info( + dementia_key = _dementia_key, + date = request.date, + time = request.time, + latitude = request.latitude, + longitude = request.longitude, + bearing = request.bearing, + user_status = status, + accelerationsensor_x = accel[0], + accelerationsensor_y = accel[1], + accelerationsensor_z = accel[2], + directionsensor_x = direction[0], + directionsensor_y = direction[1], + directionsensor_z = direction[2], + gyrosensor_x = gyro[0], + gyrosensor_y = gyro[1], + gyrosensor_z = gyro[2], + lightsensor = request.lightSensor[0], + battery = request.battery, + isInternetOn = request.isInternetOn, + isRingstoneOn = request.isRingstoneOn, + isGpsOn = request.isGpsOn, + current_speed = request.currentSpeed + ) + + session.add(new_location) + session.commit() + + print(f"[INFO] Location data received from {existing_dementia.dementia_name}({existing_dementia.dementia_key})") + + response = { + 'status': 'success', + 'message': 'Location data received', + 'result' : int(prediction[0]) + } + + else: + print(f"[ERROR] Dementia key({_dementia_key}) not found(receive location info)") + + raise HTTPException(status_code=404, detail="Dementia key not found") + + return response + + finally: + session.close() + +@router.get("/locations/noks", responses = {200 : {"model" : GetLocationResponse, "description" : "위치 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "위치 정보 없음"}}, description="보호자에게 보호 대상자의 위치 정보를 전송(쿼리 스트링) | userStatus : 1(정지), 2(도보), 3(차량), 4(지하철) | isRingstoneOn : 0(무음), 1(진동), 2(벨소리)") +async def send_live_location_info(dementiaKey : str): + + try: + + latest_location = session.query(models.location_info).filter_by(dementia_key = dementiaKey).order_by(models.location_info.num.desc()).first() + + + + if latest_location: + result = { + 'latitude': latest_location.latitude, + 'longitude': latest_location.longitude, + 'bearing': latest_location.bearing, + 'currentSpeed': latest_location.current_speed, + 'userStatus': latest_location.user_status, # 1: 정지, 2: 도보, 3: 차량, 4: 지하철 + 'battery': latest_location.battery, + 'isInternetOn': latest_location.isInternetOn, + 'isGpsOn': latest_location.isGpsOn, + 'isRingstoneOn': latest_location.isRingstoneOn # 0 : 무음, 1 : 진동, 2 : 벨소리 + } + response = { + 'status': 'success', + 'message': 'Live location data sent', + 'result': result + } + print(f"[INFO] Live location data sent to {latest_location.dementia_key}") + + else: + print(f"[ERROR] Location data not found for Dementia key({dementiaKey})") + + raise HTTPException(status_code=404, detail="Location data not found") + + return response + + finally: + session.close() + +@router.post("/users/modification/userInfo", responses = {200 : {"model" : CommonResponse, "description" : "유저 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "유저 키 조회 실패"}}, description="보호자와 보호대상자의 정보를 수정 | isDementia : 0(보호자), 1(보호대상자) | 변경하지 않는 값은 기존의 값을 그대로 수신할 것") +async def modify_user_info(request: ModifyUserInfoRequest): + + _is_dementia = request.isDementia + _key = request.key + _before_name = request.name + _before_phonenumber = request.phoneNumber + + try: + if _is_dementia == 0: #보호자 + existing_nok = session.query(models.nok_info).filter_by(nok_key = _key).first() + + if existing_nok: + # 수정된 정보를 제외한 나머지 정보들은 기존의 값을 그대로 수신받음 + + if not existing_nok.nok_name == _before_name: + existing_nok.nok_name = _before_name + + if not existing_nok.nok_phonenumber == _before_phonenumber: + existing_nok.nok_phonenumber = _before_phonenumber + + session.commit() + + print(f"[INFO] User information modified by {existing_nok.nok_name}({existing_nok.nok_key})") + + response = { + 'status': 'success', + 'message': 'User information modified' + } + else: + print(f"[ERROR] NOK key not found") + + raise HTTPException(status_code=404, detail="NOK key not found") + + elif _is_dementia == 1: #보호대상자 + existing_dementia = session.query(models.dementia_info).filter_by(dementia_key = _key).first() + + if existing_dementia: + # 수정된 정보를 제외한 나머지 정보들은 기존의 값을 그대로 수신받음 + + if not existing_dementia.dementia_name == _before_name: + existing_dementia.dementia_name = _before_name + + if not existing_dementia.dementia_phonenumber == _before_phonenumber: + existing_dementia.dementia_phonenumber = _before_phonenumber + + session.commit() + + print(f"[INFO] User information modified by {existing_dementia.dementia_name}({existing_dementia.dementia_key})") + + response = { + 'status': 'success', + 'message': 'User information modified' + } + + else: + print(f"[ERROR] Dementia key not found") + + raise HTTPException(status_code=404, detail="Dementia key not found") + + return response + + finally: + session.close() + +@router.post("/users/modification/updateRate", responses = {200 : {"model" : CommonResponse, "description" : "업데이트 주기 수정 성공" }, 404: {"model": ErrorResponse, "description": "유저 키 조회 실패"}}, description="보호자와 보호대상자의 업데이트 주기를 수정 | isDementia : 0(보호자), 1(보호대상자)") +async def modify_updatint_rate(request: ModifyUserUpdateRateRequest): + _is_dementia = request.isDementia + _key = request.key + _update_rate = request.updateRate + + #보호자와 보호대상자 모두 업데이트 + try: + if _is_dementia == 0: #보호자 + existing_nok = session.query(models.nok_info).filter_by(nok_key = _key).first() + + if existing_nok: + connected_dementia = session.query(models.dementia_info).filter_by(dementia_key = existing_nok.dementia_info_key).first() + existing_nok.update_rate = _update_rate + connected_dementia.update_rate = _update_rate + + print(f"[INFO] Update rate modified by {existing_nok.nok_name}, {connected_dementia.dementia_name}") + + response = { + 'status': 'success', + 'message': 'User update rate modified' + } + else: + print(f"[ERROR] NOK key not found(update rate)") + + raise HTTPException(status_code=404, detail="NOK key not found") + + elif _is_dementia == 1: + existing_dementia = session.query(models.dementia_info).filter_by(dementia_key = _key).first() + + if existing_dementia: + connected_nok = session.query(models.nok_info).filter_by(dementia_info_key = existing_dementia.dementia_key).first() + existing_dementia.update_rate = _update_rate + connected_nok.update_rate = _update_rate + + print(f"[INFO] Update rate modified by {existing_dementia.dementia_name}, {connected_nok.nok_name}") + + response = { + 'status': 'success', + 'message': 'User update rate modified' + } + else: + print(f"[ERROR] Dementia key not found(update rate)") + + raise HTTPException(status_code=404, detail="Dementia key not found") + + session.commit() + + return response + + finally: + session.close() + +@router.post("/dementias/averageWalkingSpeed", responses = {200 : {"model" : AverageWalkingSpeedResponse, "description" : "평균 걷기 속도 계산 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패 or 위치 정보 부족"}}, description="보호 대상자의 평균 걷기 속도를 계산 및 마지막 정보 전송") +async def caculate_dementia_average_walking_speed(requset: AverageWalkingSpeedRequest): # current_user : int = Depends(APIKeyHeader(name = "Authorization")) + + #_dementia_key = get_current_user(current_user)["key"] + + _dementia_key = requset.dementiaKey + + if _dementia_key is None: + print(f"[ERROR] Dementia key not found(calculate dementia average walking speed)") + + raise HTTPException(status_code=404, detail="Dementia key not found") + + try: + #최근 10개의 정보를 가져와 평균 속도 계산(임시) + location_info_list = session.query(models.location_info).filter_by(dementia_key = _dementia_key, user_status = "도보").order_by(models.location_info.num.desc()).limit(10).all() + + if location_info_list: + sum_speed = 0 + for location_info in location_info_list: + print(location_info.current_speed) + sum_speed += float(location_info.current_speed) + print(sum_speed) + + average_speed = round(sum_speed / len(location_info_list), 2) + + geo = kakao.geo_coord2address(location_info_list[0].longitude, location_info_list[0].latitude) + + if not geo['documents'][0]['road_address'] == None: + xy2addr = geo['documents'][0]['road_address']['address_name'] + " " + geo['documents'][0]['road_address']['building_name'] + + else: + xy2addr = geo['documents'][0]['address']['address_name'] + + response = { + 'status': 'success', + 'message': 'Dementia average walking speed calculated', + 'result': { + 'averageSpeed': average_speed, + 'lastLatitude': location_info_list[0].latitude, + 'lastLongitude': location_info_list[0].longitude, + 'addressName' : xy2addr + } + } + print(f"[INFO] Dementia average walking speed calculated for {location_info_list[0].dementia_key}") + + else: + print(f"[ERROR] Not enough location data for Dementia key({_dementia_key})") + + raise HTTPException(status_code=404, detail="Not enough location data") + + return response + + finally: + session.close() + +@router.get("/users/info", responses = {200 : {"model" : GetUserInfoResponse, "description" : "유저 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "유저 정보 없음"}}, description="보호자와 보호 대상자 정보 전달(쿼리 스트링)") +async def get_user_info(nokKey : str): + _nok_key = nokKey + + try: + nok_info_record = session.query(models.nok_info).filter_by(nok_key = _nok_key).first() + + + if nok_info_record: + dementia_info_record = session.query(models.dementia_info).filter_by(dementia_key = nok_info_record.dementia_info_key).first() + if not dementia_info_record: + print(f"[ERROR] Dementia information not found for nok key({_nok_key})") + + raise HTTPException(status_code=404, detail="Dementia information not found") + + result = { + 'dementiaInfoRecord': { + 'dementiaKey': dementia_info_record.dementia_key, + 'dementiaName': dementia_info_record.dementia_name, + 'dementiaPhoneNumber': dementia_info_record.dementia_phonenumber, + 'updateRate': dementia_info_record.update_rate + }, + 'nokInfoRecord': { + 'nokKey': nok_info_record.nok_key, + 'nokName': nok_info_record.nok_name, + 'nokPhoneNumber': nok_info_record.nok_phonenumber, + 'updateRate': nok_info_record.update_rate + } + } + + response = { + 'status': 'success', + 'message': 'User information sent', + 'result': result + } + + print(f"[INFO] User information sent to {dementia_info_record.dementia_name}({dementia_info_record.dementia_key})") + + else: + print(f"[ERROR] User information not found for nok key({_nok_key})") + + raise HTTPException(status_code=404, detail="User information not found") + + return response + + finally: + session.close() + +@router.get("/locations/meaningful", responses = {200 : {"model" : MeaningfulLocResponse, "description" : "의미장소 전송 성공" }, 404: {"model": ErrorResponse, "description": "의미 장소 없음"}}, description="보호 대상자의 의미 장소 정보 및 주변 경찰서 정보 전달(쿼리 스트링)") +async def send_meaningful_location_info(dementiaKey: str): + _key = dementiaKey + + try: + meaningful_location_list = session.query(models.meaningful_location_info).filter_by(dementia_key=_key).all() + + if meaningful_location_list: + meaningful_places_dict = {} + + + for location in meaningful_location_list: + address = location.address + day_of_week = location.day_of_the_week + time = location.time + + # 주소가 이미 존재하는지 확인하고, 없으면 새로운 딕셔너리 엔트리 생성 + if address not in meaningful_places_dict: + # 해당 주소의 경찰서 정보 가져오기(distance 순으로 정렬) + police_list = session.query(models.police_info).filter_by(key = location.key).order_by(models.police_info.distance).limit(3).all() + + #police_list의 num 속성 제거 + for police in police_list: + del police.num + del police.key + + meaningful_places_dict[address] = { + 'address': address, + 'timeInfo': [], + 'latitude': location.latitude, + 'longitude': location.longitude, + 'policeStationInfo' : police_list + } + + # 해당 주소의 시간 정보 리스트에 현재 시간 정보가 없으면 추가 + time_info_list = meaningful_places_dict[address]['timeInfo'] + if {'dayOfTheWeek': day_of_week, 'time': time} not in time_info_list: + time_info_list.append({'dayOfTheWeek': day_of_week, 'time': time}) + + # 결과를 리스트 형태로 변환 + meaningful_places = list(meaningful_places_dict.values()) + + result = { + 'meaningfulPlaces': meaningful_places + } + + response = { + 'status': 'success', + 'message': 'Meaningful location data sent', + 'result': result + } + + print(f"[INFO] Meaningful location data sent to {_key}") + + else: + print(f"[ERROR] Meaningful location data not found for {_key}") + raise HTTPException(status_code=404, detail="Meaningful location data not found") + + return response + + finally: + session.close() + +@router.get("/locations/history", responses = {200 : {"model" : LocHistoryResponse, "description" : "위치 이력 전송 성공" }, 404: {"model": ErrorResponse, "description": "위치 이력 없음"}}, description="보호 대상자의 위치 이력 정보 전달(쿼리 스트링) | distance는 현재 값과 다음 값과의 거리 | date : YYYY-MM-DD") +async def send_location_history(date: str, dementiaKey: str): + _key = dementiaKey + + try: + location_list = session.query(models.location_info).filter_by(dementia_key=_key, date=date).all() + + if not location_list: + print(f"[ERROR] Location history data not found for {_key}") + raise HTTPException(status_code=404, detail="Location history data not found") + + locHistory = [] + prev_location = None + + for index, location in enumerate(location_list): + current_location = (location.latitude, location.longitude) + distance = 0 + + if prev_location: + distance = round(haversine(current_location, prev_location, unit='m'), 2) + + if not locHistory or location.user_status != "정지" or locHistory[-1]['userStatus'] != "정지": + locHistory.append({ + 'latitude': location.latitude, + 'longitude': location.longitude, + 'time': location.time, + 'userStatus': location.user_status, + 'distance': distance + }) + else: + locHistory[-1]['time'] = locHistory[-1]['time'][:8] + '~' + location.time + + prev_location = current_location + + # If it's the last location, set distance to 0 + if index == len(location_list) - 1: + locHistory[-1]['distance'] = 0 + + result = { + 'locationHistory': locHistory, + } + + response = { + 'status': 'success', + 'message': 'Location history data sent', + 'result': result + } + + print(f"[INFO] Location history data sent to {_key}") + + finally: + session.close() + + return response + +@router.get("/locations/predict", responses = {200 : {"model" : PredictLocationResponse, "description" : "위치 예측 성공" }, 404: {"model": ErrorResponse, "description": "위치 정보 부족"}}, description="보호 대상자의 다음 위치 예측(쿼리 스트링) | 경찰서 정보는 아직임") +async def predict_location(dementiaKey: str): + _key = dementiaKey + + try: + loc_list = [] + location_list = session.query(models.location_info).filter_by(dementia_key=_key, date = "2024-05-16").all() + + + + for location in location_list: + status = convertor(location.user_status) + loc_list.append({ + 'date' : location.date, + 'time': location.time, + 'latitude': location.latitude, + 'longitude': location.longitude, + 'user_status' : status + }) + # dataframe으로 변환 + + loc_list_df = pd.DataFrame(loc_list, columns=['date', 'time', 'latitude', 'longitude', 'user_status']) + + '''meaningful_list = session.query(models.meaningful_location_info).filter_by(dementia_key = _key).all() + + mean_list = [] + + for location in meaningful_list: + mean_list.append({ + 'date' : location.date, + 'time': location.time, + 'latitude': location.latitude, + 'longitude': location.longitude, + 'address' : location.address, + 'key' : location.key + })''' + + #meaningful_df = pd.DataFrame(mean_list, columns=['date', 'time', 'latitude', 'longitude', 'address', 'key']) + pr = Preprocessing(loc_list_df) + df, meaningful_df= pr.run_analysis() + + test_idx = int(len(df) * 0.8) + df_train = df.iloc[:test_idx] + df_test = df.iloc[test_idx:] + + seq_len = 5 # 150개의 데이터를 feature로 사용 + steps = 5 # 향후 150개 뒤의 y를 예측 + single_output = False + metrics = ["accuracy"] # 모델 성능 지표 + lstm_params = { + "seq_len": seq_len, + "epochs": 100, # epochs 반복 횟수 + "patience": 30, # early stopping 조건 + "steps_per_epoch": 5, # 1 epochs 시 dataset을 5개로 분할하여 학습 + "learning_rate": 0.03, + "lstm_units": [64, 32], # Dense Layer: 2, Unit: (64, 32) + "activation": "softmax", + "dropout": 0, + "validation_split": 0.3, # 검증 데이터셋 30% + } + fl = ForecastLSTMClassification(class_num=len(df['y'].unique())) + model = fl.fit_lstm( + df=df_train, + steps=steps, + single_output=single_output, + verbose=True, + metrics=metrics, + **lstm_params, + ) + y_pred = fl.pred(df=df_test, + steps=steps, + num_classes=len(df['y'].unique()), + seq_len=seq_len, + single_output=single_output) + + print(y_pred) + print(meaningful_df.iloc[y_pred].iloc[-1]) + + pred_loc = meaningful_df.iloc[y_pred].iloc[-1] + + geo = kakao.geo_coord2address(pred_loc.longitude, pred_loc.latitude) + + if not geo['documents'][0]['road_address'] == None: + xy2addr = geo['documents'][0]['road_address']['address_name'] + " " + geo['documents'][0]['road_address']['building_name'] + + else: + xy2addr = geo['documents'][0]['address']['address_name'] + + police = kakao.search_keyword("경찰서", x = pred_loc.longitude, y = pred_loc.latitude, sort = 'distance')\ + + '''police_list = [] + if police['meta']['total_count'] == 0: + print(f"[INFO] No police station found near {xy2addr}") + else: + for pol in police['documents']: + if not pol['phone'] == '': + new_police = { + "policeName" : pol['place_name'], + "policeAddress" : pol['road_address_name'], + "policePhoneNumber" : pol['phone'], + "distance" : pol['distance'], + "latitude" : pol['y'], + "longitude" : pol['x'] + } + + police_list.append(new_police) + else: + pass''' + + pol_info = { + "policeName" : "이름", + "policeAddress" : "주소", + "policePhoneNumber" : "전번", + "distance" : "거리", + "latitude" : "위도", + "longitude" : "경도" + } + pred_loc = { + "latitude" : pred_loc.latitude, + "longitude" : pred_loc.longitude, + "address" : xy2addr + } + result = { + "predictLocation" : pred_loc, + "policeInfo" : pol_info + + } + response = { + "status" : "susccess", + "message" : "predict complete", + "result" : result + } + + return response + finally: + session.close() + +@router.get("/locations/predict/gura") +async def predict_location(dementiaKey : str): + + try: + # db 에서 의미장소 정보 가져오기 + meaningful_location_list = session.query(models.meaningful_location_info).filter_by(dementia_key = dementiaKey, address = '경기도 시흥시 산기대학로 237 한국공학대학교').limit(1).all() + police_info = session.query(models.police_info).filter_by(key = meaningful_location_list[0].key).order_by(models.police_info.distance).limit(3).all() + + for police in police_info: + del police.num + del police.key + + pred_loc = { + "latitude" : meaningful_location_list[0].latitude, + "longitude" : meaningful_location_list[0].longitude, + "address" : meaningful_location_list[0].address + } + + result = { + 'predictLocation' : pred_loc, + 'policeInfo' : police_info + } + + response = { + 'status': 'success', + 'message': 'Predict location data sent', + 'result': result + + } + + time.sleep(10) + + return response + finally: + session.close() \ No newline at end of file From 399eeb30d0148db1197836ae26aeb2b983e2a08c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 20 May 2024 15:26:57 +0900 Subject: [PATCH 08/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EB=93=B1=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index b6e12561..b4120af8 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -216,4 +216,13 @@ class AverageAndLastLoc(BaseModel): class AverageWalkingSpeedResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: AverageAndLastLoc \ No newline at end of file + result: AverageAndLastLoc + +class RegisterSafeAreaRequest(BaseModel): + dementiaKey : int = Field(examples=["123456"]) + groupName : str = Field(examples=["안심구역 그룹 1"]) + areaName : str = Field(examples=["집"]) + latitude : float = Field(examples=["37.123456"]) + longitude : float = Field(examples=["127.123456"]) + radius : int = Field(examples=["100"], description="미터 단위") + From c89ab2842b03e0ff38c0d84e815742d7a056b68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 20 May 2024 15:27:16 +0900 Subject: [PATCH 09/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD,=20=EC=95=88=EC=8B=AC=EA=B5=AC=EC=97=AD=20=EA=B7=B8?= =?UTF-8?q?=EB=A3=B9=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index bfc9a9e7..df43be91 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -69,7 +69,6 @@ class police_info(Base): key = Column(String) policeName = Column(String) policeAddress = Column(String) - roadAddress = Column(String) policePhoneNumber = Column(String) distance = Column(Integer) latitude = Column(Double) @@ -79,4 +78,21 @@ class refresh_token_info(Base): __tablename__ = 'refresh_token_info' key = Column(String, primary_key=True) - refresh_token = Column(String) \ No newline at end of file + refresh_token = Column(String) + +class safe_area_info(Base): + __tablename__ = 'safe_area_info' + + area_key = Column(String, primary_key=True) + group_key = Column(String) + area_name = Column(String) + dementia_key = Column(String) + latitude = Column(Double) + longitude = Column(Double) + radius = Column(Integer) + +class safe_area_group_info(Base): + __tablename__ = 'safe_area_group_info' + + group_key = Column(String, primary_key=True) + group_name = Column(String) \ No newline at end of file From 9f9d8d1ffd5d9c935edc0c800706671484e9c81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 20 May 2024 15:27:28 +0900 Subject: [PATCH 10/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EB=93=B1=EB=A1=9D=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 52 ++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index b7f744c8..268addbf 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -16,7 +16,7 @@ from .schedularFunc import SchedulerFunc from .fcm_notification import send_push_notification from .user_status_convertor import convertor -#from .LocationPredict import ForecastLSTMClassification, Preprocessing +from .LocationPredict import ForecastLSTMClassification, Preprocessing import asyncio import datetime @@ -835,8 +835,54 @@ async def predict_location(dementiaKey : str): } - time.sleep(10) + #time.sleep(10) return response finally: - session.close() \ No newline at end of file + session.close() + +@router.post("/safeArea/register", responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록") +async def register_safe_area(request: RegisterSafeAreaRequest): + try: + _dementia_key = request.dementiaKey + _area_name = request.areaName + _group_name = request.groupName + + _latitude = request.latitude + _longitude = request.longitude + _radius = request.radius + + existing_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name).first() + + if existing_group: + _group_key = existing_group.group_key + else: + rng = RandomNumberGenerator() + _group_key = rng.generate_unique_random_number(100000, 999999) + + new_group = models.safe_area_group_info(group_key = _group_key, group_name = _group_name) + session.add(new_group) + + _area_key = rng.generate_unique_random_number(100000, 999999) + + new_area = models.safe_area_info(area_key = _area_key, dementia_key = _dementia_key, area_name = _area_name, latitude = _latitude, longitude = _longitude, radius = _radius, group_key = _group_key) + + session.add(new_area) + + session.commit() + + print(f"[INFO] Safe area registered for {_dementia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area registered' + } + + return response + + finally: + session.close() + +@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') +def analyzing_location_data(): + asyncio.run(schedFunc.load_analyze_location_data(session)) \ No newline at end of file From f7382bc69e7b46ef489bd2a54f947993747697bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Tue, 21 May 2024 22:17:30 +0900 Subject: [PATCH 11/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A0=95=EB=B3=B4=20=EC=9D=91=EB=8B=B5=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index b4120af8..ed20c09d 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -226,3 +226,18 @@ class RegisterSafeAreaRequest(BaseModel): longitude : float = Field(examples=["127.123456"]) radius : int = Field(examples=["100"], description="미터 단위") +class safeAreaList(BaseModel): + areaName : str = Field(examples=["집"]) + latitude : float = Field(examples=["37.123456"]) + longitude : float = Field(examples=["127.123456"]) + radius : int = Field(examples=["100"], description="미터 단위") + +class safeAreaGroupInfo(BaseModel): + groupName : str = Field(examples=["안심구역 그룹 1"]) + safeAreaList : List[safeAreaList] + + +class GetSafeAreaResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: List[safeAreaGroupInfo] \ No newline at end of file From ad14fe57cd163f206e60e5e5d2f069c79f06a366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Tue, 21 May 2024 22:19:05 +0900 Subject: [PATCH 12/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A0=95=EB=B3=B4=20=EC=A0=84=EB=8B=AC=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 그룹별 안심구역 반환 --- backend/fastapi/app/routes2.py | 56 +++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 268addbf..920a0b85 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -5,6 +5,8 @@ from passlib.context import CryptContext from haversine import haversine from PyKakao import Local +from datetime import datetime, timedelta +from pytz import timezone from . import models from .random_generator import RandomNumberGenerator @@ -19,7 +21,6 @@ from .LocationPredict import ForecastLSTMClassification, Preprocessing import asyncio -import datetime import requests import urllib.parse import pandas as pd @@ -37,6 +38,7 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + @router.post("/test/fcm", description="FCM 테스트") async def send_fcm(title: str, body: str, token: str, data : str): @@ -543,7 +545,7 @@ async def get_user_info(nokKey : str): else: print(f"[ERROR] User information not found for nok key({_nok_key})") - raise HTTPException(status_code=404, detail="User information not found") + return ErrorResponse(status_code=404, message="User information not found") return response @@ -841,7 +843,7 @@ async def predict_location(dementiaKey : str): finally: session.close() -@router.post("/safeArea/register", responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록") +@router.post("/safeArea/register", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록") async def register_safe_area(request: RegisterSafeAreaRequest): try: _dementia_key = request.dementiaKey @@ -858,13 +860,13 @@ async def register_safe_area(request: RegisterSafeAreaRequest): _group_key = existing_group.group_key else: rng = RandomNumberGenerator() - _group_key = rng.generate_unique_random_number(100000, 999999) + for _ in range(10): + _group_key = rng.generate_unique_random_number(100000, 999999) new_group = models.safe_area_group_info(group_key = _group_key, group_name = _group_name) session.add(new_group) - _area_key = rng.generate_unique_random_number(100000, 999999) - + _area_key = int(_dementia_key) + datetime.timestamp(datetime.now(timezone('Asia/Seoul'))) + ord(_area_name[0]) new_area = models.safe_area_info(area_key = _area_key, dementia_key = _dementia_key, area_name = _area_name, latitude = _latitude, longitude = _longitude, radius = _radius, group_key = _group_key) session.add(new_area) @@ -883,6 +885,44 @@ async def register_safe_area(request: RegisterSafeAreaRequest): finally: session.close() -@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') +@router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링)") +async def get_safe_area_info(dementiaKey: str): + try: + _safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = dementiaKey).all() + + # 안심 구역 그룹 별로 분류 + safe_area_dict = {} + for safe_area in _safe_area_list: + if safe_area.group_key not in safe_area_dict: + safe_area_dict[safe_area.group_key] = { + 'groupName': session.query(models.safe_area_group_info).filter_by(group_key = safe_area.group_key).first().group_name, + 'safeAreas': [] + } + + safe_area_dict[safe_area.group_key]['safeAreas'].append({ + 'areaName': safe_area.area_name, + 'latitude': safe_area.latitude, + 'longitude': safe_area.longitude, + 'radius': safe_area.radius + }) + + result = { + 'safeAreaList': list(safe_area_dict.values()) + } + + response = { + 'status': 'success', + 'message': 'Safe area information sent', + 'result': result + } + + return response + + finally: + session.close() + + + +'''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') def analyzing_location_data(): - asyncio.run(schedFunc.load_analyze_location_data(session)) \ No newline at end of file + asyncio.run(schedFunc.load_analyze_location_data(session))''' \ No newline at end of file From 022864def1aad743ca6df2b3dedbf15064451d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 00:54:53 +0900 Subject: [PATCH 13/77] =?UTF-8?q?fix:=20=EC=9D=BC=EB=B0=98=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EB=AA=A8=EB=8D=B8=20=ED=86=A0=ED=81=B0=EA=B0=92=20?= =?UTF-8?q?=EC=9E=84=EC=8B=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index ed20c09d..8a5d6b4b 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -2,13 +2,17 @@ from typing import List, Dict # Define request and response models -class accessToken(BaseModel): +'''class accessToken(BaseModel): accessToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) class CommonResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result : accessToken + result : accessToken''' + +class CommonResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") class dementiaInfoRecord(BaseModel): dementiaKey : str = Field(examples=["123456"]) From bba3de8b9201bc6e54de3db4bdb428675dd53284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 00:55:29 +0900 Subject: [PATCH 14/77] =?UTF-8?q?fix:=20=EA=B7=B8=EB=A3=B9=EB=AA=85?= =?UTF-8?q?=EC=9D=B4=20=EC=97=86=EC=9D=84=20=EC=8B=9C=20notGrouped?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 920a0b85..3d29d473 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -848,11 +848,15 @@ async def register_safe_area(request: RegisterSafeAreaRequest): try: _dementia_key = request.dementiaKey _area_name = request.areaName - _group_name = request.groupName - _latitude = request.latitude _longitude = request.longitude _radius = request.radius + _group_name = request.groupName + + if _group_name == '': + _group_name = 'notGrouped' + else: + pass existing_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name).first() @@ -885,7 +889,7 @@ async def register_safe_area(request: RegisterSafeAreaRequest): finally: session.close() -@router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링)") +@router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링) | 그룹 미지정시 groupName은 큰따옴표로 빈 문자열로 전달할 것") async def get_safe_area_info(dementiaKey: str): try: _safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = dementiaKey).all() From e50464c98d5847a274db6c75a7b3199482c2c043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 19:40:54 +0900 Subject: [PATCH 15/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=9D=B4=EB=A6=84,=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 8a5d6b4b..63d801df 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -1,5 +1,5 @@ from pydantic import BaseModel, Field -from typing import List, Dict +from typing import List, Dict, Optional # Define request and response models '''class accessToken(BaseModel): @@ -244,4 +244,14 @@ class safeAreaGroupInfo(BaseModel): class GetSafeAreaResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: List[safeAreaGroupInfo] \ No newline at end of file + result: List[safeAreaGroupInfo] + +class ModifySafeAreaName(BaseModel): + dementiaKey : int = Field(examples=["123456"]) + beforeAreaName : str = Field(examples=["집1"]) + afterAreaName : Optional[str] = Field(examples=["집2"]) + +class ModifySafeAreaGroup(BaseModel): + dementiaKey : int = Field(examples=["123456"]) + beforeGroupName : str = Field(examples=["안심구역 그룹 1"]) + afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) \ No newline at end of file From eb6e264b5bff2dc5c1f77510857572f8abcf8a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 19:41:08 +0900 Subject: [PATCH 16/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 3d29d473..26d7c468 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -925,6 +925,34 @@ async def get_safe_area_info(dementiaKey: str): finally: session.close() +@router.post("/safeArea/modification/name", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 수정") +async def modify_name_safe_area_info(request: ModifySafeAreaName): + try: + _dementaia_key = request.dementiaKey + _before_name = request.beforeAreaName + _after_name = request.afterAreaName + + existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementaia_key, area_name = _before_name).first() + + if existing_area: + existing_area.area_name = _after_name + session.commit() + + print(f"[INFO] Safe area name modified for {_dementaia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area name modified' + } + + return response + + + finally: + session.close() + + + '''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') From 1a36db1bd66fd73decd1340156404cb3cb80bb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:01:59 +0900 Subject: [PATCH 17/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=88=98=EC=A0=95=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 63d801df..755b4874 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -253,5 +253,5 @@ class ModifySafeAreaName(BaseModel): class ModifySafeAreaGroup(BaseModel): dementiaKey : int = Field(examples=["123456"]) - beforeGroupName : str = Field(examples=["안심구역 그룹 1"]) - afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) \ No newline at end of file + areaName : str = Field(examples=["집"]) + groupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) \ No newline at end of file From 54a2dcf42f659e1655fdfa26941d1336e3fc2903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:02:11 +0900 Subject: [PATCH 18/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=88=98=EC=A0=95=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 26d7c468..b32a4202 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -951,7 +951,54 @@ async def modify_name_safe_area_info(request: ModifySafeAreaName): finally: session.close() +@router.post("/safeArea/modification/group", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 수정") +async def modify_group_safe_area_info(request: ModifySafeAreaGroup): + try: + _dementia_key = request.dementiaKey + _area_name = request.areaName + _group_name = request.groupName + + existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_name = _area_name).first() + + if existing_area: + before_group = session.query(models.safe_area_group_info).filter_by(group_key = existing_area.group_key).first() + after_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name).first() + + if after_group: + existing_area.group_key = after_group.group_key + else: + rng = RandomNumberGenerator() + for _ in range(10): + _group_key = rng.generate_unique_random_number(100000, 999999) + + new_group = models.safe_area_group_info(group_key = _group_key, group_name = _group_name) + session.add(new_group) + existing_area.group_key = _group_key + + if session.query(models.safe_area_info).filter_by(group_key = before_group.group_key).count() == 0: + session.delete(before_group) + + else: + pass + session.commit() + + print(f"[INFO] Safe area group modified for {_dementia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area group modified' + } + + return response + + else: + return ErrorResponse(status_code=404, message="Safe area information not found") + + + finally: + session.close() + From 34d54030d36d1d2f905576951945ab18899973c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:12:30 +0900 Subject: [PATCH 19/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=A1=B0=ED=9A=8C=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EB=AA=A8=EB=8D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 755b4874..5ad057ca 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -254,4 +254,9 @@ class ModifySafeAreaName(BaseModel): class ModifySafeAreaGroup(BaseModel): dementiaKey : int = Field(examples=["123456"]) areaName : str = Field(examples=["집"]) - groupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) \ No newline at end of file + groupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) + +class GetSafeAreaGroupResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: List[safeAreaList] \ No newline at end of file From 1e853a2b9c59c989fd17faf6672e6457ca35b99c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:12:49 +0900 Subject: [PATCH 20/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?dementia=5Fkey=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index df43be91..33543905 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -95,4 +95,5 @@ class safe_area_group_info(Base): __tablename__ = 'safe_area_group_info' group_key = Column(String, primary_key=True) - group_name = Column(String) \ No newline at end of file + group_name = Column(String) + dementia_key = Column(String) \ No newline at end of file From 673b1fbb47f44e47a9ba598080ff7d04e5e4bec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:13:03 +0900 Subject: [PATCH 21/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=A1=B0=ED=9A=8C=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index b32a4202..5e350545 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -924,7 +924,38 @@ async def get_safe_area_info(dementiaKey: str): finally: session.close() - + +@router.get("/safeArea/info/group", responses = {200 : {"model" : GetSafeAreaGroupResponse, "description" : "안전 지역 그룹 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 전달(쿼리 스트링)") +async def get_safe_area_group_info(dementiaKey: str, groupName: str): + try: + group_key = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey, group_name = groupName).first().group_key + + if group_key: + safe_area_list = session.query(models.safe_area_info).filter_by(group_key = group_key).all() + + safe_areas = [] + for safe_area in safe_area_list: + safe_areas.append({ + 'areaName': safe_area.area_name, + 'latitude': safe_area.latitude, + 'longitude': safe_area.longitude, + 'radius': safe_area.radius + }) + + result = { + 'safeAreas': safe_areas + } + + response = { + 'status': 'success', + 'message': 'Safe area group information sent', + 'result': result + } + + return response + finally: + session.close() + @router.post("/safeArea/modification/name", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 수정") async def modify_name_safe_area_info(request: ModifySafeAreaName): try: From 128dcd61032e448e89c2f984b19f09c1e149cf7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:25:49 +0900 Subject: [PATCH 22/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 안심구역 그룹 테이블에 dementia_key를 추가하여 로직 단축 --- backend/fastapi/app/routes2.py | 40 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 5e350545..9fefe383 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -892,26 +892,31 @@ async def register_safe_area(request: RegisterSafeAreaRequest): @router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링) | 그룹 미지정시 groupName은 큰따옴표로 빈 문자열로 전달할 것") async def get_safe_area_info(dementiaKey: str): try: - _safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = dementiaKey).all() - - # 안심 구역 그룹 별로 분류 - safe_area_dict = {} - for safe_area in _safe_area_list: - if safe_area.group_key not in safe_area_dict: - safe_area_dict[safe_area.group_key] = { - 'groupName': session.query(models.safe_area_group_info).filter_by(group_key = safe_area.group_key).first().group_name, - 'safeAreas': [] - } + group_list = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey).all() + + group_lists = [] + + # 그룹별로 저장 + for group in group_list: + safe_area_list = session.query(models.safe_area_info).filter_by(group_key = group.group_key).all() + + safe_areas = [] + for safe_area in safe_area_list: + safe_areas.append({ + 'areaName': safe_area.area_name, + 'latitude': safe_area.latitude, + 'longitude': safe_area.longitude, + 'radius': safe_area.radius + }) - safe_area_dict[safe_area.group_key]['safeAreas'].append({ - 'areaName': safe_area.area_name, - 'latitude': safe_area.latitude, - 'longitude': safe_area.longitude, - 'radius': safe_area.radius + group_lists.append({ + 'groupName': group.group_name, + 'safeAreas': safe_areas }) + result = { - 'safeAreaList': list(safe_area_dict.values()) + 'safeAreaList': group_lists } response = { @@ -919,7 +924,8 @@ async def get_safe_area_info(dementiaKey: str): 'message': 'Safe area information sent', 'result': result } - + + return response finally: From e42f6a727d16cacfa30b33dc0905c3e01629e56f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:27:35 +0900 Subject: [PATCH 23/77] =?UTF-8?q?fix:=20=EA=B7=B8=EB=A3=B9=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20dementia=5Fkey=EB=A5=BC=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 9fefe383..c267f30d 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -999,7 +999,7 @@ async def modify_group_safe_area_info(request: ModifySafeAreaGroup): if existing_area: before_group = session.query(models.safe_area_group_info).filter_by(group_key = existing_area.group_key).first() - after_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name).first() + after_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name, dementia_key = _dementia_key).first() if after_group: existing_area.group_key = after_group.group_key From e71521944251eea8e43804039373735c80ecc20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:36:01 +0900 Subject: [PATCH 24/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=EB=AA=85=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 5ad057ca..e8a853ef 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -259,4 +259,9 @@ class ModifySafeAreaGroup(BaseModel): class GetSafeAreaGroupResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: List[safeAreaList] \ No newline at end of file + result: List[safeAreaList] + +class ModifySafeAreaGroupName(BaseModel): + dementiaKey : int = Field(examples=["123456"]) + beforeGroupName : str = Field(examples=["안심구역 그룹 1"]) + afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) \ No newline at end of file From 25ddb2e3be88b2b7aa44f6064c852eb872b92e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:36:18 +0900 Subject: [PATCH 25/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=EB=AA=85=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index c267f30d..b2061a62 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -1035,9 +1035,34 @@ async def modify_group_safe_area_info(request: ModifySafeAreaGroup): finally: session.close() - +@router.post("/safeArea/modification/groupName", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 그룹 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 이름 수정") +async def modify_group_name_safe_area_info(request: ModifySafeAreaGroupName): + try: + _dementia_key = request.dementiaKey + _before_group_name = request.beforeGroupName + _after_group_name = request.afterGroupName + + existing_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = _before_group_name).first() + + if existing_group: + existing_group.group_name = _after_group_name + session.commit() + + print(f"[INFO] Safe area group name modified for {_dementia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area group name modified' + } + return response + + else: + return ErrorResponse(status_code=404, message="Safe area group information not found") + + finally: + session.close() '''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') def analyzing_location_data(): From 4a18916b585a53d5bd2e395eb0153b137e305541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:46:39 +0900 Subject: [PATCH 26/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=82=AD=EC=A0=9C=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index e8a853ef..eeaa09dd 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -264,4 +264,8 @@ class GetSafeAreaGroupResponse(BaseModel): class ModifySafeAreaGroupName(BaseModel): dementiaKey : int = Field(examples=["123456"]) beforeGroupName : str = Field(examples=["안심구역 그룹 1"]) - afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) \ No newline at end of file + afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) + +class DeleteSafeAreaRequest(BaseModel): + dementiaKey : int = Field(examples=["123456"]) + areaName : str = Field(examples=["집"]) \ No newline at end of file From 8b8252a722a1b2e185e1b2a6518b55bd7b0ab75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 20:46:53 +0900 Subject: [PATCH 27/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=82=AD=EC=A0=9C=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index b2061a62..d1c5126a 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -1064,6 +1064,34 @@ async def modify_group_name_safe_area_info(request: ModifySafeAreaGroupName): finally: session.close() +@router.delete("/safeArea/delete", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 삭제 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 삭제") +async def delete_safe_area(request: DeleteSafeAreaRequest): + try: + _dementia_key = request.dementiaKey + _area_name = request.areaName + + existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_name = _area_name).first() + + if existing_area: + session.delete(existing_area) + session.commit() + + print(f"[INFO] Safe area deleted for {_dementia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area deleted' + } + + return response + + else: + return ErrorResponse(status_code=404, message="Safe area information not found") + + finally: + session.close() + + '''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') def analyzing_location_data(): asyncio.run(schedFunc.load_analyze_location_data(session))''' \ No newline at end of file From 46cd643d0a4691a592f3a55089aebc7392d2d1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 21:58:42 +0900 Subject: [PATCH 28/77] =?UTF-8?q?fix:=20http=20handler=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/__init__.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/backend/fastapi/app/__init__.py b/backend/fastapi/app/__init__.py index 64f238c6..0b2cfefa 100644 --- a/backend/fastapi/app/__init__.py +++ b/backend/fastapi/app/__init__.py @@ -19,11 +19,4 @@ def create_app(): routes2.sched.start() - return app - -@app.exception_handler(HTTPException) -async def http_exception_handler(exc): - return JSONResponse( - status_code=exc.status_code, - content={"message": exc.detail} - ) \ No newline at end of file + return app \ No newline at end of file From 1400f0531a77cb95b349604acce81cfe2eda935a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 21:59:38 +0900 Subject: [PATCH 29/77] =?UTF-8?q?fix:=20dementiaKey=EA=B0=80=20int=20?= =?UTF-8?q?=ED=98=95=EC=9D=B4=20=EC=98=80=EB=8D=98=20=EA=B2=83=20str?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95,=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B4=80=EB=A0=A8=20=EB=AA=A8=EB=8D=B8=EC=97=90=20?= =?UTF-8?q?groupKey,=20areaKey=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index eeaa09dd..f00a4421 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -176,8 +176,7 @@ class LocHistoryResponse(BaseModel): result : LocHisRecord class ErrorResponse(BaseModel): - status: str = Field("error") - message: str = Field("에러 내용") + detail: str = Field("에러 내용") class TempResponse(BaseModel): status: str = Field("success") @@ -209,7 +208,7 @@ class PredictLocationResponse(BaseModel): result : locpredict class AverageWalkingSpeedRequest(BaseModel): - dementiaKey : int = Field(examples=["123456"]) + dementiaKey : str = Field(examples=["123456"]) class AverageAndLastLoc(BaseModel): averageSpeed : float = Field(examples=["2.0"]) @@ -223,7 +222,7 @@ class AverageWalkingSpeedResponse(BaseModel): result: AverageAndLastLoc class RegisterSafeAreaRequest(BaseModel): - dementiaKey : int = Field(examples=["123456"]) + dementiaKey : str = Field(examples=["123456"]) groupName : str = Field(examples=["안심구역 그룹 1"]) areaName : str = Field(examples=["집"]) latitude : float = Field(examples=["37.123456"]) @@ -232,12 +231,14 @@ class RegisterSafeAreaRequest(BaseModel): class safeAreaList(BaseModel): areaName : str = Field(examples=["집"]) + areaKey : str = Field(examples=["123456"]) latitude : float = Field(examples=["37.123456"]) longitude : float = Field(examples=["127.123456"]) radius : int = Field(examples=["100"], description="미터 단위") class safeAreaGroupInfo(BaseModel): groupName : str = Field(examples=["안심구역 그룹 1"]) + groupKey : str = Field(examples=["123456"]) safeAreaList : List[safeAreaList] @@ -247,14 +248,14 @@ class GetSafeAreaResponse(BaseModel): result: List[safeAreaGroupInfo] class ModifySafeAreaName(BaseModel): - dementiaKey : int = Field(examples=["123456"]) - beforeAreaName : str = Field(examples=["집1"]) + dementiaKey : str = Field(examples=["123456"]) + areaKey : str = Field(examples=["123456"]) afterAreaName : Optional[str] = Field(examples=["집2"]) class ModifySafeAreaGroup(BaseModel): - dementiaKey : int = Field(examples=["123456"]) - areaName : str = Field(examples=["집"]) - groupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) + dementiaKey : str = Field(examples=["123456"]) + areaKey : str = Field(examples=["123456"]) + groupKey : str = Field(examples=["123456"]) class GetSafeAreaGroupResponse(BaseModel): status: str = Field("success") @@ -262,10 +263,10 @@ class GetSafeAreaGroupResponse(BaseModel): result: List[safeAreaList] class ModifySafeAreaGroupName(BaseModel): - dementiaKey : int = Field(examples=["123456"]) - beforeGroupName : str = Field(examples=["안심구역 그룹 1"]) + dementiaKey : str = Field(examples=["123456"]) + groupKey : str = Field(examples=["123456"]) afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) class DeleteSafeAreaRequest(BaseModel): dementiaKey : int = Field(examples=["123456"]) - areaName : str = Field(examples=["집"]) \ No newline at end of file + areaKey : str = Field(examples=["123456"]) \ No newline at end of file From 4577e9e5ff8872533fb48fad87539274edbff0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 22 May 2024 22:00:12 +0900 Subject: [PATCH 30/77] =?UTF-8?q?fix:=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95,=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=EC=8B=9C=20?= =?UTF-8?q?key=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=98=EB=8A=94=20=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 87 ++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index d1c5126a..5a50fefb 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -1,5 +1,6 @@ -from fastapi import APIRouter, HTTPException, status, Depends +from fastapi import APIRouter, HTTPException, status, Depends, Request from fastapi.security import OAuth2PasswordRequestForm, APIKeyHeader, OAuth2PasswordBearer +from fastapi.responses import JSONResponse from apscheduler.schedulers.background import BackgroundScheduler from passlib.context import CryptContext @@ -19,6 +20,7 @@ from .fcm_notification import send_push_notification from .user_status_convertor import convertor from .LocationPredict import ForecastLSTMClassification, Preprocessing +from .exceptHandler import duplicate_error import asyncio import requests @@ -545,7 +547,7 @@ async def get_user_info(nokKey : str): else: print(f"[ERROR] User information not found for nok key({_nok_key})") - return ErrorResponse(status_code=404, message="User information not found") + raise HTTPException(status_code=404, detail="User information not found") return response @@ -678,7 +680,8 @@ async def predict_location(dementiaKey: str): loc_list = [] location_list = session.query(models.location_info).filter_by(dementia_key=_key, date = "2024-05-16").all() - + if not location_list: + raise HTTPException(status_code=404, detail="Location data not found") for location in location_list: status = convertor(location.user_status) @@ -853,6 +856,13 @@ async def register_safe_area(request: RegisterSafeAreaRequest): _radius = request.radius _group_name = request.groupName + if not session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_name = _area_name).first() == None: + print(f"[ERROR] Safe area already exists for {_dementia_key}") + + raise HTTPException(status_code=400, message="Safe area already exists") + else: + pass + if _group_name == '': _group_name = 'notGrouped' else: @@ -904,6 +914,7 @@ async def get_safe_area_info(dementiaKey: str): for safe_area in safe_area_list: safe_areas.append({ 'areaName': safe_area.area_name, + 'areaKey': safe_area.area_key, 'latitude': safe_area.latitude, 'longitude': safe_area.longitude, 'radius': safe_area.radius @@ -911,6 +922,7 @@ async def get_safe_area_info(dementiaKey: str): group_lists.append({ 'groupName': group.group_name, + 'groupKey': group.group_key, 'safeAreas': safe_areas }) @@ -932,9 +944,12 @@ async def get_safe_area_info(dementiaKey: str): session.close() @router.get("/safeArea/info/group", responses = {200 : {"model" : GetSafeAreaGroupResponse, "description" : "안전 지역 그룹 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 전달(쿼리 스트링)") -async def get_safe_area_group_info(dementiaKey: str, groupName: str): +async def get_safe_area_group_info(dementiaKey: str, groupKey: str): try: - group_key = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey, group_name = groupName).first().group_key + group_key = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey, group_key = groupKey).first().group_key + + if not group_key: + raise HTTPException(status_code=404, detail="Safe area group information not found") if group_key: safe_area_list = session.query(models.safe_area_info).filter_by(group_key = group_key).all() @@ -962,59 +977,58 @@ async def get_safe_area_group_info(dementiaKey: str, groupName: str): finally: session.close() -@router.post("/safeArea/modification/name", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 수정") +@router.post("/safeArea/modification/name", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 400 : {"model" : ErrorResponse, "description" : "안심 구역 이름 중복"},404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 수정") async def modify_name_safe_area_info(request: ModifySafeAreaName): try: _dementaia_key = request.dementiaKey - _before_name = request.beforeAreaName + _area_key = request.areaKey _after_name = request.afterAreaName - existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementaia_key, area_name = _before_name).first() + existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementaia_key, area_key = _area_key).first() if existing_area: - existing_area.area_name = _after_name - session.commit() + if not session.query(models.safe_area_info).filter_by(dementia_key = _dementaia_key, area_name = _after_name).first() == None: + print(f"[ERROR] Safe area already exists for {_dementaia_key}") - print(f"[INFO] Safe area name modified for {_dementaia_key}") + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Safe area already exists") + else: + existing_area.area_name = _after_name + session.commit() - response = { - 'status': 'success', - 'message': 'Safe area name modified' - } + print(f"[INFO] Safe area name modified for {_dementaia_key}") - return response - + response = { + 'status': 'success', + 'message': 'Safe area name modified' + } + + return response + else: + raise HTTPException(status_code=404, detail="Safe area information not found") finally: session.close() -@router.post("/safeArea/modification/group", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 수정") +@router.post("/safeArea/modification/group", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 수정 | areaKey : 옮기고자 하는 안심구역, groupKey : 옮길 그룹") async def modify_group_safe_area_info(request: ModifySafeAreaGroup): try: _dementia_key = request.dementiaKey - _area_name = request.areaName - _group_name = request.groupName + _area_key = request.areaKey + _group_key = request.groupKey - existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_name = _area_name).first() + existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_key = _area_key).first() if existing_area: before_group = session.query(models.safe_area_group_info).filter_by(group_key = existing_area.group_key).first() - after_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name, dementia_key = _dementia_key).first() + after_group = session.query(models.safe_area_group_info).filter_by(group_key = _group_key, dementia_key = _dementia_key).first() if after_group: existing_area.group_key = after_group.group_key else: - rng = RandomNumberGenerator() - for _ in range(10): - _group_key = rng.generate_unique_random_number(100000, 999999) - - new_group = models.safe_area_group_info(group_key = _group_key, group_name = _group_name) - session.add(new_group) - existing_area.group_key = _group_key + raise HTTPException(status_code=404, message="Safe area group information not found") if session.query(models.safe_area_info).filter_by(group_key = before_group.group_key).count() == 0: session.delete(before_group) - else: pass @@ -1040,10 +1054,10 @@ async def modify_group_safe_area_info(request: ModifySafeAreaGroup): async def modify_group_name_safe_area_info(request: ModifySafeAreaGroupName): try: _dementia_key = request.dementiaKey - _before_group_name = request.beforeGroupName + _group_key = request.groupKey _after_group_name = request.afterGroupName - existing_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = _before_group_name).first() + existing_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_key = _group_key).first() if existing_group: existing_group.group_name = _after_group_name @@ -1059,7 +1073,7 @@ async def modify_group_name_safe_area_info(request: ModifySafeAreaGroupName): return response else: - return ErrorResponse(status_code=404, message="Safe area group information not found") + raise HTTPException(status_code=404, message="Safe area group information not found") finally: session.close() @@ -1068,9 +1082,9 @@ async def modify_group_name_safe_area_info(request: ModifySafeAreaGroupName): async def delete_safe_area(request: DeleteSafeAreaRequest): try: _dementia_key = request.dementiaKey - _area_name = request.areaName + _area_key = request.areaKey - existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_name = _area_name).first() + existing_area = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_key = _area_key).first() if existing_area: session.delete(existing_area) @@ -1086,11 +1100,12 @@ async def delete_safe_area(request: DeleteSafeAreaRequest): return response else: - return ErrorResponse(status_code=404, message="Safe area information not found") + raise HTTPException(status_code=404, message="Safe area information not found") finally: session.close() +#@router.delete() '''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') def analyzing_location_data(): From 05520d3a197f19361ed488fc37034087658e794d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 11:51:30 +0900 Subject: [PATCH 31/77] =?UTF-8?q?fix:=20=EC=8B=A4=EC=A0=9C=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=EA=B3=BC=20=EB=8B=A4=EB=A5=B8=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index f00a4421..17106c00 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -239,7 +239,7 @@ class safeAreaList(BaseModel): class safeAreaGroupInfo(BaseModel): groupName : str = Field(examples=["안심구역 그룹 1"]) groupKey : str = Field(examples=["123456"]) - safeAreaList : List[safeAreaList] + safeAreas : List[safeAreaList] class GetSafeAreaResponse(BaseModel): @@ -257,10 +257,13 @@ class ModifySafeAreaGroup(BaseModel): areaKey : str = Field(examples=["123456"]) groupKey : str = Field(examples=["123456"]) +class safeAreaGruop(BaseModel): + safeAreas : List[safeAreaList] + class GetSafeAreaGroupResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: List[safeAreaList] + result: safeAreaGruop class ModifySafeAreaGroupName(BaseModel): dementiaKey : str = Field(examples=["123456"]) @@ -268,5 +271,9 @@ class ModifySafeAreaGroupName(BaseModel): afterGroupName : Optional[str] = Field(examples=["안심구역 그룹 2"]) class DeleteSafeAreaRequest(BaseModel): - dementiaKey : int = Field(examples=["123456"]) - areaKey : str = Field(examples=["123456"]) \ No newline at end of file + dementiaKey : str = Field(examples=["123456"]) + areaKey : str = Field(examples=["123456"]) + +class DeleteSafeAreaGroupRequest(BaseModel): + dementiaKey : str = Field(examples=["123456"]) + groupKey : str = Field(examples=["123456"]) \ No newline at end of file From 455a78f6f628b7525fed7fdaf35c7945cc11d092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 11:52:22 +0900 Subject: [PATCH 32/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=82=AD=EC=A0=9C=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 65 ++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 5a50fefb..906f66a0 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -20,7 +20,6 @@ from .fcm_notification import send_push_notification from .user_status_convertor import convertor from .LocationPredict import ForecastLSTMClassification, Preprocessing -from .exceptHandler import duplicate_error import asyncio import requests @@ -46,6 +45,8 @@ async def send_fcm(title: str, body: str, token: str, data : str): return send_push_notification(token, body, title, data) + +#유저 등록 @router.post("/noks",status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveNokInfoResponse, "description" : "유저 등록 성공" },404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호자가 보호 대상자의 정보를 등록") async def receive_nok_info(request: ReceiveNokInfoRequest): @@ -220,6 +221,8 @@ async def receive_user_login(request: loginRequest): finally: session.close() + +#위치 정보 전송 @router.post("/locations/dementias", responses = {200 : {"model" : TempResponse, "description" : "위치 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 위치 정보를 전송 | isRingstoneOn : 0(무음), 1(진동), 2(벨소리)") async def receive_location_info(request: ReceiveLocationRequest): @@ -333,6 +336,8 @@ async def send_live_location_info(dementiaKey : str): finally: session.close() + +# 유저 정보 수정 @router.post("/users/modification/userInfo", responses = {200 : {"model" : CommonResponse, "description" : "유저 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "유저 키 조회 실패"}}, description="보호자와 보호대상자의 정보를 수정 | isDementia : 0(보호자), 1(보호대상자) | 변경하지 않는 값은 기존의 값을 그대로 수신할 것") async def modify_user_info(request: ModifyUserInfoRequest): @@ -451,6 +456,8 @@ async def modify_updatint_rate(request: ModifyUserUpdateRateRequest): finally: session.close() + +#유저 정보 전달 @router.post("/dementias/averageWalkingSpeed", responses = {200 : {"model" : AverageWalkingSpeedResponse, "description" : "평균 걷기 속도 계산 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패 or 위치 정보 부족"}}, description="보호 대상자의 평균 걷기 속도를 계산 및 마지막 정보 전송") async def caculate_dementia_average_walking_speed(requset: AverageWalkingSpeedRequest): # current_user : int = Depends(APIKeyHeader(name = "Authorization")) @@ -554,6 +561,7 @@ async def get_user_info(nokKey : str): finally: session.close() +#의미장소, 위치 이력, 위치 예측 @router.get("/locations/meaningful", responses = {200 : {"model" : MeaningfulLocResponse, "description" : "의미장소 전송 성공" }, 404: {"model": ErrorResponse, "description": "의미 장소 없음"}}, description="보호 대상자의 의미 장소 정보 및 주변 경찰서 정보 전달(쿼리 스트링)") async def send_meaningful_location_info(dementiaKey: str): _key = dementiaKey @@ -846,7 +854,9 @@ async def predict_location(dementiaKey : str): finally: session.close() -@router.post("/safeArea/register", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록") + +#안심구역 +@router.post("/safeArea/register", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록 | groupName이 없으면 notGrouped로 저장됨") async def register_safe_area(request: RegisterSafeAreaRequest): try: _dementia_key = request.dementiaKey @@ -899,7 +909,7 @@ async def register_safe_area(request: RegisterSafeAreaRequest): finally: session.close() -@router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링) | 그룹 미지정시 groupName은 큰따옴표로 빈 문자열로 전달할 것") +@router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링)") async def get_safe_area_info(dementiaKey: str): try: group_list = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey).all() @@ -943,7 +953,7 @@ async def get_safe_area_info(dementiaKey: str): finally: session.close() -@router.get("/safeArea/info/group", responses = {200 : {"model" : GetSafeAreaGroupResponse, "description" : "안전 지역 그룹 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 전달(쿼리 스트링)") +@router.get("/safeArea/info/group", responses = {200 : {"model" : GetSafeAreaGroupResponse, "description" : "안전 지역 그룹 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 정보 없음"}}, description="보호 대상자의 특정 안전 지역 그룹 정보 전달(쿼리 스트링)") async def get_safe_area_group_info(dementiaKey: str, groupKey: str): try: group_key = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey, group_key = groupKey).first().group_key @@ -1009,7 +1019,7 @@ async def modify_name_safe_area_info(request: ModifySafeAreaName): finally: session.close() -@router.post("/safeArea/modification/group", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 정보 수정 | areaKey : 옮기고자 하는 안심구역, groupKey : 옮길 그룹") +@router.post("/safeArea/modification/group", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 이동 | areaKey : 옮기고자 하는 안심구역, groupKey : 옮길 그룹") async def modify_group_safe_area_info(request: ModifySafeAreaGroup): try: _dementia_key = request.dementiaKey @@ -1105,7 +1115,50 @@ async def delete_safe_area(request: DeleteSafeAreaRequest): finally: session.close() -#@router.delete() +@router.delete("/safeArea/delete/group", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 그룹 삭제 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 정보 없음"}}, description="보호 대상자의 안전 지역 그룹 삭제") +async def delete_safe_area_group(request: DeleteSafeAreaGroupRequest): + try: + _dementia_key = request.dementiaKey + _group_key = request.groupKey + + existing_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_key = _group_key).first() + + not_grouped = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = 'notGrouped').first() + + if not not_grouped: + rng = RandomNumberGenerator() + for _ in range(10): + _not_grouped_key = rng.generate_unique_random_number(100000, 999999) + + new_group = models.safe_area_group_info(group_key = _group_key, group_name = 'notGrouped', dementia_key = _dementia_key) + session.add(new_group) + else: + _not_grouped_key = not_grouped.group_key + + if existing_group: + safe_area_list = session.query(models.safe_area_info).filter_by(group_key = existing_group.group_key).all() + if safe_area_list: + for safe_area in safe_area_list: + safe_area.group_key = _not_grouped_key + else: + pass + + session.delete(existing_group) + session.commit() + + print(f"[INFO] Safe area group deleted for {_dementia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area group deleted' + } + + return response + else: + raise HTTPException(status_code=404, message="Safe area group information not found") + + finally: + session.close() '''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') def analyzing_location_data(): From b4dcc4f21ed2f7c5b863bde6addb4f0c5c84150c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 15:11:52 +0900 Subject: [PATCH 33/77] =?UTF-8?q?fix:=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=EC=97=90=20dementiaKey=20=EC=97=86=EB=8D=98=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EC=88=98=EC=A0=95,=20fcmRequest=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 17106c00..ce1b77bf 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -77,6 +77,7 @@ class loginRequest(BaseModel): isDementia : int = Field(examples=["1"], description="1 : 보호대상자, 0 : 보호자") class ReceiveLocationRequest(BaseModel): + dementiaKey : str = Field(examples=["123456"]) date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") time : str = Field(examples=["12:00:00"]) latitude : float = Field(examples=["37.123456"]) @@ -109,11 +110,15 @@ class GetLocationResponse(BaseModel): result: LastLoc class ModifyUserInfoRequest(BaseModel): + key: str = Field(examples=["123456"]) + isDementia : int = Field(examples=[1], description="1 : 보호대상자, 0 : 보호자") name : str = Field(examples=["김이름"]) phoneNumber : str = Field(examples=["010-1234-5678"]) class ModifyUserUpdateRateRequest(BaseModel): - updateRate : int = Field(examples=["15"], description="초 단위") + key: str = Field(examples=["123456"]) + isDementia : int = Field(examples=[1], description="1 : 보호대상자, 0 : 보호자") + updateRate : int = Field(examples=[1], description="분 단위") class AverageAndLastLoc(BaseModel): averageSpeed : float = Field(examples=["2.0"]) @@ -276,4 +281,9 @@ class DeleteSafeAreaRequest(BaseModel): class DeleteSafeAreaGroupRequest(BaseModel): dementiaKey : str = Field(examples=["123456"]) - groupKey : str = Field(examples=["123456"]) \ No newline at end of file + groupKey : str = Field(examples=["123456"]) + +class FCMRequest(BaseModel): + title : str = Field(examples=["어디U"]) + body : str = Field(examples=["안심 구역 진입"]) + data : Dict[str, str] = Field(examples=[{"safeAreaName" : "집", "time" : "12:00:00"}]) \ No newline at end of file From 1242a68766dca647fd592f3f27b0e16dd809e9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 15:12:13 +0900 Subject: [PATCH 34/77] =?UTF-8?q?fix:=20fcm=20notification=20data=20?= =?UTF-8?q?=EC=98=81=EC=97=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/fcm_notification.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/fastapi/app/fcm_notification.py b/backend/fastapi/app/fcm_notification.py index ab56a918..7171666c 100644 --- a/backend/fastapi/app/fcm_notification.py +++ b/backend/fastapi/app/fcm_notification.py @@ -5,7 +5,7 @@ -def send_push_notification(token, body, title, data): +def send_push_notification(token, title, body, data): #result = push_service.notify_single_device(registration_id=token, message_title=title, message_body=body) @@ -13,9 +13,7 @@ def send_push_notification(token, body, title, data): registration_id=token, message_title=title, message_body=body, - data_message={ - "이도영": data - } + data_message=data ) return result From 1256d595564a639ea20b245a4786fd35e2f45d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 15:12:46 +0900 Subject: [PATCH 35/77] =?UTF-8?q?fix:=20location=5Finfo=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=EC=97=90=20isInSafeArea,=20nearSafeArea=20?= =?UTF-8?q?=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index 33543905..856b420e 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -48,6 +48,8 @@ class location_info(Base): isRingstoneOn = Column(Integer) isGpsOn = Column(Boolean) current_speed = Column(String) + isInSafeArea = Column(Boolean) + nearSafeArea = Column(String) class meaningful_location_info(Base): __tablename__ = 'meaningful_location_info' From be092bb1314c482eec2b4987dbb3737fdd2b91b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 15:13:40 +0900 Subject: [PATCH 36/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A7=84=EC=9E=85=20=EC=9D=B4=ED=83=88=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20fcm=20=EB=B0=9C?= =?UTF-8?q?=EC=86=A1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 906f66a0..978563b9 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -17,9 +17,10 @@ from .util import JWTService from .config import Config from .schedularFunc import SchedulerFunc -from .fcm_notification import send_push_notification from .user_status_convertor import convertor from .LocationPredict import ForecastLSTMClassification, Preprocessing +from .validater import validateInSafeArea +from .fcm_notification import send_push_notification import asyncio import requests @@ -35,15 +36,19 @@ jwt = JWTService() schedFunc = SchedulerFunc() sched = BackgroundScheduler(timezone="Asia/Seoul", daemon=True) +val = validateInSafeArea() kakao = Local(service_key=Config.kakao_service_key) oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + @router.post("/test/fcm", description="FCM 테스트") -async def send_fcm(title: str, body: str, token: str, data : str): +async def send_fcm(request: FCMRequest): + + send_push_notification(Config.temp_fcm_token, request.title, request.body, request.data) - return send_push_notification(token, body, title, data) + return {"status": "success", "message": "FCM sent"} #유저 등록 @@ -230,6 +235,9 @@ async def receive_location_info(request: ReceiveLocationRequest): _dementia_key = request.dementiaKey existing_dementia = session.query(models.dementia_info).filter_by(dementia_key = _dementia_key).first() + safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key).all() + + current_location = (request.latitude, request.longitude) if existing_dementia: @@ -241,6 +249,8 @@ async def receive_location_info(request: ReceiveLocationRequest): prediction = user_status_updater.predict(accel, gyro, direction) + _near_safe_area, _isInSafeArea = val.isinsafearea(current_location, safe_area_list) + if prediction[0]==1: status = "정지" elif prediction[0]==2: @@ -274,7 +284,9 @@ async def receive_location_info(request: ReceiveLocationRequest): isInternetOn = request.isInternetOn, isRingstoneOn = request.isRingstoneOn, isGpsOn = request.isGpsOn, - current_speed = request.currentSpeed + current_speed = request.currentSpeed, + isInSafeArea = _isInSafeArea, + nearSafeArea = _near_safe_area.area_key ) session.add(new_location) @@ -299,15 +311,19 @@ async def receive_location_info(request: ReceiveLocationRequest): session.close() @router.get("/locations/noks", responses = {200 : {"model" : GetLocationResponse, "description" : "위치 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "위치 정보 없음"}}, description="보호자에게 보호 대상자의 위치 정보를 전송(쿼리 스트링) | userStatus : 1(정지), 2(도보), 3(차량), 4(지하철) | isRingstoneOn : 0(무음), 1(진동), 2(벨소리)") -async def send_live_location_info(dementiaKey : str): +def send_live_location_info(dementiaKey : str): try: - latest_location = session.query(models.location_info).filter_by(dementia_key = dementiaKey).order_by(models.location_info.num.desc()).first() - - + latest_location = session.query(models.location_info).filter_by(dementia_key = dementiaKey).order_by(models.location_info.num.desc()).limit(2).all() if latest_location: + for index, location in enumerate(latest_location): + if index == 0: + latest_location = location + elif index == 1: + before_location = location + result = { 'latitude': latest_location.latitude, 'longitude': latest_location.longitude, @@ -326,6 +342,10 @@ async def send_live_location_info(dementiaKey : str): } print(f"[INFO] Live location data sent to {latest_location.dementia_key}") + safeArea = session.query(models.safe_area_info).filter_by(area_key = latest_location.nearSafeArea).first() + + asyncio.run(val.pushNotification(latest_location, before_location, safeArea)) + else: print(f"[ERROR] Location data not found for Dementia key({dementiaKey})") From 77eeb78d9663f4995e71b8472ccd5823d13f704a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 23 May 2024 15:13:58 +0900 Subject: [PATCH 37/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A7=84=EC=9E=85=20=EC=9D=B4=ED=83=88=20=ED=8C=90?= =?UTF-8?q?=EB=B3=84=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/validater.py | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 backend/fastapi/app/validater.py diff --git a/backend/fastapi/app/validater.py b/backend/fastapi/app/validater.py new file mode 100644 index 00000000..041b05e6 --- /dev/null +++ b/backend/fastapi/app/validater.py @@ -0,0 +1,41 @@ +from haversine import haversine +from .config import Config +from .fcm_notification import send_push_notification + + +class validateInSafeArea: + def __init__(self): + pass + + async def isinsafearea(self, current_loc, safe_area_list): + distance_list = [] + for safe_area in safe_area_list: + safe_area_location = (safe_area.latitude, safe_area.longitude) + distance = haversine(current_loc, safe_area_location, unit='m') + distance_list.append(distance) + + min_distance = min(distance_list) + min_distance_index = distance_list.index(min_distance) + nearest_safe_area = safe_area_list[min_distance_index] + + if min_distance > nearest_safe_area.radius: + print(f"[INFO] Current location is not in safe area({nearest_safe_area.area_name})") + return nearest_safe_area, False + else: + return nearest_safe_area, True + + async def pushNotification(self, latest_location, before_location, safeArea): + if latest_location.isInSafeArea == 0 and before_location.isInSafeArea == 1: + data = { + "safeAreaName" : safeArea.area_name, + "time" : latest_location.time + } + send_push_notification(Config.temp_fcm_token, "어디U", "안심 구역 이탈", data) + elif latest_location.isInSafeArea == 1 and before_location.isInSafeArea == 0: + data = { + "safeAreaName" : safeArea.area_name, + "time" : latest_location.time + } + send_push_notification(Config.temp_fcm_token, "어디U", "안심 구역 진입", data) + + From 8aa2ccce4bcb995c32a3d48017c3ceed98bcd33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Fri, 24 May 2024 14:52:55 +0900 Subject: [PATCH 38/77] =?UTF-8?q?feat:=20=EC=A3=BC=EC=86=8C=20->=20?= =?UTF-8?q?=EC=A2=8C=ED=91=9C=20=EB=B3=80=ED=99=98=20=EC=9D=91=EB=8B=B5,?= =?UTF-8?q?=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index ce1b77bf..68cb0899 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -284,6 +284,20 @@ class DeleteSafeAreaGroupRequest(BaseModel): groupKey : str = Field(examples=["123456"]) class FCMRequest(BaseModel): + token : str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) title : str = Field(examples=["어디U"]) body : str = Field(examples=["안심 구역 진입"]) - data : Dict[str, str] = Field(examples=[{"safeAreaName" : "집", "time" : "12:00:00"}]) \ No newline at end of file + data : Dict[str, str] = Field(examples=[{"safeAreaName" : "집", "time" : "12:00:00"}]) + + +class AddressConversionRequest(BaseModel): + address : str = Field(examples=["서울특별시 강남구 니가 사는 그 집"]) + +class latilongi(BaseModel): + latitude : float = Field(examples=["37.123456"]) + longitude : float = Field(examples=["127.123456"]) + +class AddressConversionResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: Dict[str, float] = latilongi \ No newline at end of file From 00a6ca96fefc6e804a5d773b8cfcbdbf968e3512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Fri, 24 May 2024 14:53:17 +0900 Subject: [PATCH 39/77] =?UTF-8?q?fix:=20=ED=86=A0=ED=81=B0=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20fcm=5Ftoken?= =?UTF-8?q?=20=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index 856b420e..dbc6ebab 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -81,6 +81,7 @@ class refresh_token_info(Base): key = Column(String, primary_key=True) refresh_token = Column(String) + fcm_token = Column(String) class safe_area_info(Base): __tablename__ = 'safe_area_info' From b1933e40f601a2de059f4e7d763cf81e2b0a3487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Fri, 24 May 2024 14:53:55 +0900 Subject: [PATCH 40/77] =?UTF-8?q?feat:=20fcm=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=ED=91=B8=EC=8B=9C=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=A3=BC=EC=86=8C=20->=20=EC=A2=8C?= =?UTF-8?q?=ED=91=9C=20=EB=B3=80=ED=99=98=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 74 ++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 978563b9..9de5af25 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -46,7 +46,7 @@ @router.post("/test/fcm", description="FCM 테스트") async def send_fcm(request: FCMRequest): - send_push_notification(Config.temp_fcm_token, request.title, request.body, request.data) + send_push_notification(request.token, request.title, request.body, request.data) return {"status": "success", "message": "FCM sent"} @@ -343,9 +343,12 @@ def send_live_location_info(dementiaKey : str): print(f"[INFO] Live location data sent to {latest_location.dementia_key}") safeArea = session.query(models.safe_area_info).filter_by(area_key = latest_location.nearSafeArea).first() - - asyncio.run(val.pushNotification(latest_location, before_location, safeArea)) - + fcm_token = session.query(models.refresh_token_info).filter_by(key = latest_location.dementia_key).first().fcm_token + if fcm_token: + asyncio.run(val.pushNotification(fcm_token, latest_location, before_location, safeArea)) + else: + pass + else: print(f"[ERROR] Location data not found for Dementia key({dementiaKey})") @@ -1180,6 +1183,69 @@ async def delete_safe_area_group(request: DeleteSafeAreaGroupRequest): finally: session.close() + +#유틸 +@router.post("/address/conversion", responses = {200 : {"model" : AddressConversionResponse, "description" : "주소 변환 성공" }, 404: {"model": ErrorResponse, "description": "주소 변환 실패"}}, description="주소를 위경도로 변환") +async def address_conversion(request: AddressConversionRequest): + try: + _address = request.address + + xy = kakao.search_address(_address) + + latitude = xy['documents'][0]['y'] + longitude = xy['documents'][0]['x'] + + result = { + 'latitude': latitude, + 'longitude': longitude + } + + response = { + 'status': 'success', + 'message': 'Address conversion complete', + 'result': result + } + + return response + + except Exception as e: + print(f"[ERROR] Address conversion failed: {e}") + + raise HTTPException(status_code=404, detail="Address conversion failed") + + finally: + session.close() + + + + + + + +'''@router.post("/asdasd") +async def test(): + try: + loc_list = session.query(models.location_info).filter_by(isInSafeArea = None).all() + + #가장 가까운 안심구역을 찾고 isInSafeArea, nearSafeArea 업데이트 + for loc in loc_list: + current_location = (loc.latitude, loc.longitude) + safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = loc.dementia_key).all() + _near_safe_area, _isInSafeArea = val.isinsafearea(current_location, safe_area_list) + loc.isInSafeArea = _near_safe_area + loc.nearSafeArea = _isInSafeArea + + session.commit() + + + finally: + session.close()''' + + + + + + '''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') def analyzing_location_data(): asyncio.run(schedFunc.load_analyze_location_data(session))''' \ No newline at end of file From 353f83cde1bd5ce4a1cc852ddc037ffe63f0bede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Fri, 24 May 2024 14:54:19 +0900 Subject: [PATCH 41/77] =?UTF-8?q?fix:=20fcm=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=ED=91=B8=EC=8B=9C=20=ED=95=A8=EC=88=98=20=EB=B9=84=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/validater.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/fastapi/app/validater.py b/backend/fastapi/app/validater.py index 041b05e6..1294c633 100644 --- a/backend/fastapi/app/validater.py +++ b/backend/fastapi/app/validater.py @@ -7,7 +7,7 @@ class validateInSafeArea: def __init__(self): pass - async def isinsafearea(self, current_loc, safe_area_list): + def isinsafearea(self, current_loc, safe_area_list): distance_list = [] for safe_area in safe_area_list: safe_area_location = (safe_area.latitude, safe_area.longitude) @@ -24,7 +24,7 @@ async def isinsafearea(self, current_loc, safe_area_list): else: return nearest_safe_area, True - async def pushNotification(self, latest_location, before_location, safeArea): + async def pushNotification(self, fcm_token, latest_location, before_location, safeArea): if latest_location.isInSafeArea == 0 and before_location.isInSafeArea == 1: data = { "safeAreaName" : safeArea.area_name, @@ -36,6 +36,6 @@ async def pushNotification(self, latest_location, before_location, safeArea): "safeAreaName" : safeArea.area_name, "time" : latest_location.time } - send_push_notification(Config.temp_fcm_token, "어디U", "안심 구역 진입", data) + send_push_notification(fcm_token, "어디U", "안심 구역 진입", data) From 9ab19ef0419ae02a0004a374563fb33ec19e6c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Fri, 24 May 2024 15:14:14 +0900 Subject: [PATCH 42/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A7=84=EC=9E=85=20=EC=9D=B4=ED=83=88=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=ED=8A=B8=EB=A6=AC=EA=B1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 9de5af25..3bcf826c 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -229,15 +229,17 @@ async def receive_user_login(request: loginRequest): #위치 정보 전송 @router.post("/locations/dementias", responses = {200 : {"model" : TempResponse, "description" : "위치 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 위치 정보를 전송 | isRingstoneOn : 0(무음), 1(진동), 2(벨소리)") -async def receive_location_info(request: ReceiveLocationRequest): +def receive_location_info(request: ReceiveLocationRequest): try: _dementia_key = request.dementiaKey existing_dementia = session.query(models.dementia_info).filter_by(dementia_key = _dementia_key).first() safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key).all() + latest_loc = session.query(models.location_info).filter_by(dementia_key = _dementia_key).order_by(models.location_info.num.desc()).first() current_location = (request.latitude, request.longitude) + if existing_dementia: @@ -261,7 +263,7 @@ async def receive_location_info(request: ReceiveLocationRequest): status = "지하철" else: pass - + new_location = models.location_info( dementia_key = _dementia_key, date = request.date, @@ -292,6 +294,12 @@ async def receive_location_info(request: ReceiveLocationRequest): session.add(new_location) session.commit() + fcm_token = session.query(models.refresh_token_info).filter_by(key = _dementia_key).first().fcm_token + if fcm_token: + asyncio.run(val.pushNotification(fcm_token, new_location, latest_loc, _near_safe_area)) + else: + pass + print(f"[INFO] Location data received from {existing_dementia.dementia_name}({existing_dementia.dementia_key})") response = { @@ -315,14 +323,9 @@ def send_live_location_info(dementiaKey : str): try: - latest_location = session.query(models.location_info).filter_by(dementia_key = dementiaKey).order_by(models.location_info.num.desc()).limit(2).all() + latest_location = session.query(models.location_info).filter_by(dementia_key = dementiaKey).order_by(models.location_info.num.desc()).first() if latest_location: - for index, location in enumerate(latest_location): - if index == 0: - latest_location = location - elif index == 1: - before_location = location result = { 'latitude': latest_location.latitude, @@ -341,13 +344,6 @@ def send_live_location_info(dementiaKey : str): 'result': result } print(f"[INFO] Live location data sent to {latest_location.dementia_key}") - - safeArea = session.query(models.safe_area_info).filter_by(area_key = latest_location.nearSafeArea).first() - fcm_token = session.query(models.refresh_token_info).filter_by(key = latest_location.dementia_key).first().fcm_token - if fcm_token: - asyncio.run(val.pushNotification(fcm_token, latest_location, before_location, safeArea)) - else: - pass else: print(f"[ERROR] Location data not found for Dementia key({dementiaKey})") From ec717c2b9469210bccfaf01194c335468c5cf060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sun, 26 May 2024 00:01:06 +0900 Subject: [PATCH 43/77] =?UTF-8?q?fix:=20=EC=A3=BC=EC=86=8C=20->=20?= =?UTF-8?q?=EC=A2=8C=ED=91=9C=20=EB=B3=80=ED=99=98=20search=5Fkeyword=20ap?= =?UTF-8?q?i=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 3bcf826c..bc1e1411 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -1186,7 +1186,7 @@ async def address_conversion(request: AddressConversionRequest): try: _address = request.address - xy = kakao.search_address(_address) + xy = kakao.search_keyword(_address) latitude = xy['documents'][0]['y'] longitude = xy['documents'][0]['x'] From d6635bee0822bccd41818a01defa4bc917d2d92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Sun, 26 May 2024 20:25:28 +0900 Subject: [PATCH 44/77] =?UTF-8?q?fix:=20=EC=9C=84=EC=B9=98=20=EC=98=88?= =?UTF-8?q?=EC=B8=A1=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EA=B2=BD=EC=B0=B0?= =?UTF-8?q?=EC=84=9C=20=EC=A0=95=EB=B3=B4=20=EC=B6=94=EA=B0=80,=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=8D=B0=EC=9D=B4=ED=84=B0=202=EC=A3=BC?= =?UTF-8?q?=EC=B9=98=20=EC=82=AC=EC=9A=A9(=EC=9E=84=EC=8B=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 81 +++++++++++----------------------- 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index bc1e1411..3d719941 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -8,6 +8,7 @@ from PyKakao import Local from datetime import datetime, timedelta from pytz import timezone +from sqlalchemy import and_, func from . import models from .random_generator import RandomNumberGenerator @@ -699,13 +700,26 @@ async def send_location_history(date: str, dementiaKey: str): return response -@router.get("/locations/predict", responses = {200 : {"model" : PredictLocationResponse, "description" : "위치 예측 성공" }, 404: {"model": ErrorResponse, "description": "위치 정보 부족"}}, description="보호 대상자의 다음 위치 예측(쿼리 스트링) | 경찰서 정보는 아직임") +@router.get("/locations/predict", responses = {200 : {"model" : PredictLocationResponse, "description" : "위치 예측 성공" }, 404: {"model": ErrorResponse, "description": "위치 정보 부족"}}, description="보호 대상자의 다음 위치 예측(쿼리 스트링) | 2주치 위치 데이터 사용(임시)") async def predict_location(dementiaKey: str): _key = dementiaKey try: loc_list = [] - location_list = session.query(models.location_info).filter_by(dementia_key=_key, date = "2024-05-16").all() + today = datetime.today() + + # 2주 전 날짜 + two_weeks_ago = today - timedelta(weeks=2) + + # 쿼리문 수정 + # 쿼리문 수정 (MySQL에서 문자열을 날짜로 변환할 때) + location_list = session.query(models.location_info).filter( + and_( + models.location_info.dementia_key == _key, + func.STR_TO_DATE(models.location_info.date, '%Y-%m-%d') >= two_weeks_ago, + func.STR_TO_DATE(models.location_info.date, '%Y-%m-%d') <= today + ) + ).all() if not location_list: raise HTTPException(status_code=404, detail="Location data not found") @@ -722,22 +736,7 @@ async def predict_location(dementiaKey: str): # dataframe으로 변환 loc_list_df = pd.DataFrame(loc_list, columns=['date', 'time', 'latitude', 'longitude', 'user_status']) - - '''meaningful_list = session.query(models.meaningful_location_info).filter_by(dementia_key = _key).all() - - mean_list = [] - - for location in meaningful_list: - mean_list.append({ - 'date' : location.date, - 'time': location.time, - 'latitude': location.latitude, - 'longitude': location.longitude, - 'address' : location.address, - 'key' : location.key - })''' - #meaningful_df = pd.DataFrame(mean_list, columns=['date', 'time', 'latitude', 'longitude', 'address', 'key']) pr = Preprocessing(loc_list_df) df, meaningful_df= pr.run_analysis() @@ -790,7 +789,7 @@ async def predict_location(dementiaKey: str): police = kakao.search_keyword("경찰서", x = pred_loc.longitude, y = pred_loc.latitude, sort = 'distance')\ - '''police_list = [] + police_list = [] if police['meta']['total_count'] == 0: print(f"[INFO] No police station found near {xy2addr}") else: @@ -807,16 +806,8 @@ async def predict_location(dementiaKey: str): police_list.append(new_police) else: - pass''' + pass - pol_info = { - "policeName" : "이름", - "policeAddress" : "주소", - "policePhoneNumber" : "전번", - "distance" : "거리", - "latitude" : "위도", - "longitude" : "경도" - } pred_loc = { "latitude" : pred_loc.latitude, "longitude" : pred_loc.longitude, @@ -824,7 +815,7 @@ async def predict_location(dementiaKey: str): } result = { "predictLocation" : pred_loc, - "policeInfo" : pol_info + "policeInfo" : police_list[:3] } response = { @@ -1213,35 +1204,15 @@ async def address_conversion(request: AddressConversionRequest): session.close() + - -'''@router.post("/asdasd") -async def test(): - try: - loc_list = session.query(models.location_info).filter_by(isInSafeArea = None).all() - - #가장 가까운 안심구역을 찾고 isInSafeArea, nearSafeArea 업데이트 - for loc in loc_list: - current_location = (loc.latitude, loc.longitude) - safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = loc.dementia_key).all() - _near_safe_area, _isInSafeArea = val.isinsafearea(current_location, safe_area_list) - loc.isInSafeArea = _near_safe_area - loc.nearSafeArea = _isInSafeArea - - session.commit() - - - finally: - session.close()''' - - - - - - -'''@sched.scheduled_job('cron', hour=11, minute=57, id = 'analyze_location_data') +'''@sched.scheduled_job('cron', hour=0, minute=0, id = 'analyze_location_data') def analyzing_location_data(): - asyncio.run(schedFunc.load_analyze_location_data(session))''' \ No newline at end of file + asyncio.run(schedFunc.load_analyze_location_data(session)) + +@sched.scheduled_job('cron', hour=1, minute=0, id = 'geocoding') +def geocoding(): + asyncio.run(schedFunc.load_kakao_api(session))''' \ No newline at end of file From 302b337962ddbfb1077bcb6d089f89cd59b87728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 27 May 2024 10:38:42 +0900 Subject: [PATCH 45/77] =?UTF-8?q?fix:=20=EB=B3=B4=ED=98=B8=EC=9E=90,=20?= =?UTF-8?q?=EB=B3=B4=ED=98=B8=EB=8C=80=EC=83=81=EC=9E=90=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=EC=97=90=20fcmToken=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 68cb0899..3bf135cf 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -40,6 +40,7 @@ class ReceiveNokInfoRequest(BaseModel): keyFromDementia : int = Field(examples=["123456"]) nokName : str = Field(examples=["홍길동"]) nokPhoneNumber : str = Field(examples=["010-1234-5678"]) + fcmToken : str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) class ReceiveNokInfoResponse(BaseModel): status: str = Field("success") @@ -53,6 +54,7 @@ class dementiaResult(BaseModel): class ReceiveDementiaInfoRequest(BaseModel): name : str = Field(examples=["성춘향"]) phoneNumber : str = Field(examples=["010-1234-5678"]) + fcmToken : str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) class ReceiveDementiaInfoResponse(BaseModel): status: str = Field("success") From 73df265aaed9b4672306879ebe88d2fe769c2eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 27 May 2024 10:39:19 +0900 Subject: [PATCH 46/77] =?UTF-8?q?fix:=20=EB=B3=B4=ED=98=B8=EC=9E=90,=20?= =?UTF-8?q?=EB=B3=B4=ED=98=B8=20=EB=8C=80=EC=83=81=EC=9E=90=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20fcmToken=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 3d719941..4980862b 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -53,7 +53,7 @@ async def send_fcm(request: FCMRequest): #유저 등록 -@router.post("/noks",status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveNokInfoResponse, "description" : "유저 등록 성공" },404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호자가 보호 대상자의 정보를 등록") +@router.post("/noks",status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveNokInfoResponse, "description" : "유저 등록 성공" },404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호자가 보호 대상자의 정보를 등록 | fcmToken 없으면 그냥 빈칸으로 보낼 것") async def receive_nok_info(request: ReceiveNokInfoRequest): _key_from_dementia = request.keyFromDementia @@ -65,6 +65,12 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): if existing_dementia: _nok_name = request.nokName _nok_phonenumber = request.nokPhoneNumber + if request.fcmToken == '': + new_token = models.refresh_token_info(key = _key_from_dementia, fcm_token = request.fcmToken) + session.add(new_token) + session.commit() + else: + pass duplication_check = session.query(models.nok_info).filter(models.nok_info.nok_name == _nok_name, models.nok_info.nok_phonenumber == _nok_phonenumber, models.nok_info.dementia_info_key == _key_from_dementia).first() @@ -110,7 +116,7 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): finally: session.close() -@router.post("/dementias", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveDementiaInfoResponse, "description" : "유저 등록 성공" }}, description="보호 대상자의 정보를 등록") +@router.post("/dementias", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : ReceiveDementiaInfoResponse, "description" : "유저 등록 성공" }}, description="보호 대상자의 정보를 등록 | fcmToken 없으면 그냥 빈칸으로 보낼 것") async def receive_dementia_info(request: ReceiveDementiaInfoRequest): rng = RandomNumberGenerator() @@ -118,6 +124,12 @@ async def receive_dementia_info(request: ReceiveDementiaInfoRequest): try: _dementia_name = request.name _dementia_phonenumber = request.phoneNumber + if request.fcmToken == '': + new_token = models.refresh_token_info(key = _dementia_name, fcm_token = request.fcmToken) + session.add(new_token) + session.commit() + else: + pass duplication_check = session.query(models.dementia_info).filter(models.dementia_info.dementia_name == _dementia_name, models.dementia_info.dementia_phonenumber == _dementia_phonenumber).first() From 32cae13abee6f5ac0f21e82716f063c25397e635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Tue, 28 May 2024 16:39:54 +0900 Subject: [PATCH 47/77] =?UTF-8?q?fix:=20fcm=20token=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 4980862b..c32674e4 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -65,9 +65,15 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): if existing_dementia: _nok_name = request.nokName _nok_phonenumber = request.nokPhoneNumber - if request.fcmToken == '': - new_token = models.refresh_token_info(key = _key_from_dementia, fcm_token = request.fcmToken) - session.add(new_token) + if not request.fcmToken == '': + existing_token = session.query(models.refresh_token_info).filter_by(key = _key_from_dementia).first() + if existing_token: + existing_token.fcm_token = request.fcmToken + else: + + new_token = models.refresh_token_info(key = _key_from_dementia, fcm_token = request.fcmToken) + session.add(new_token) + session.commit() else: pass @@ -124,9 +130,13 @@ async def receive_dementia_info(request: ReceiveDementiaInfoRequest): try: _dementia_name = request.name _dementia_phonenumber = request.phoneNumber - if request.fcmToken == '': - new_token = models.refresh_token_info(key = _dementia_name, fcm_token = request.fcmToken) - session.add(new_token) + if not request.fcmToken == '': + existing_token = session.query(models.refresh_token_info).filter_by(key = _dementia_name).first() + if existing_token: + existing_token.fcm_token = request.fcmToken + else: + new_token = models.refresh_token_info(key = _dementia_name, fcm_token = request.fcmToken) + session.add(new_token) session.commit() else: pass @@ -1210,13 +1220,12 @@ async def address_conversion(request: AddressConversionRequest): except Exception as e: print(f"[ERROR] Address conversion failed: {e}") - raise HTTPException(status_code=404, detail="Address conversion failed") + raise HTTPException(status_code=404, detail=f"{e}") finally: session.close() - From e99c471b64077194f043e982c0bb8ea5ae4f2e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Tue, 28 May 2024 16:43:35 +0900 Subject: [PATCH 48/77] =?UTF-8?q?fix:=20fcmToken=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=EC=8B=9C=20key=EA=B0=80=20=EC=9D=B4=EB=A6=84=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=A0=80=EC=9E=A5=EB=90=98=EB=8D=98=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 48 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index c32674e4..d525c2ec 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -65,18 +65,7 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): if existing_dementia: _nok_name = request.nokName _nok_phonenumber = request.nokPhoneNumber - if not request.fcmToken == '': - existing_token = session.query(models.refresh_token_info).filter_by(key = _key_from_dementia).first() - if existing_token: - existing_token.fcm_token = request.fcmToken - else: - - new_token = models.refresh_token_info(key = _key_from_dementia, fcm_token = request.fcmToken) - session.add(new_token) - - session.commit() - else: - pass + duplication_check = session.query(models.nok_info).filter(models.nok_info.nok_name == _nok_name, models.nok_info.nok_phonenumber == _nok_phonenumber, models.nok_info.dementia_info_key == _key_from_dementia).first() @@ -94,6 +83,19 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): session.add(new_nok) session.commit() + if not request.fcmToken == '': + existing_token = session.query(models.refresh_token_info).filter_by(key = _key).first() + if existing_token: + existing_token.fcm_token = request.fcmToken + else: + + new_token = models.refresh_token_info(key = _key, fcm_token = request.fcmToken) + session.add(new_token) + + session.commit() + else: + pass + result = { 'dementiaInfoRecord' : { 'dementiaKey' : existing_dementia.dementia_key, @@ -130,16 +132,7 @@ async def receive_dementia_info(request: ReceiveDementiaInfoRequest): try: _dementia_name = request.name _dementia_phonenumber = request.phoneNumber - if not request.fcmToken == '': - existing_token = session.query(models.refresh_token_info).filter_by(key = _dementia_name).first() - if existing_token: - existing_token.fcm_token = request.fcmToken - else: - new_token = models.refresh_token_info(key = _dementia_name, fcm_token = request.fcmToken) - session.add(new_token) - session.commit() - else: - pass + duplication_check = session.query(models.dementia_info).filter(models.dementia_info.dementia_name == _dementia_name, models.dementia_info.dementia_phonenumber == _dementia_phonenumber).first() @@ -158,6 +151,17 @@ async def receive_dementia_info(request: ReceiveDementiaInfoRequest): session.add(new_dementia) session.commit() + if not request.fcmToken == '': + existing_token = session.query(models.refresh_token_info).filter_by(key = _key).first() + if existing_token: + existing_token.fcm_token = request.fcmToken + else: + new_token = models.refresh_token_info(key = _key, fcm_token = request.fcmToken) + session.add(new_token) + session.commit() + else: + pass + result = { 'dementiaKey': _key } From 6a6f52f4c9cc0f9c59f53b4e07795c276d51797a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 30 May 2024 14:00:04 +0900 Subject: [PATCH 49/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20radius=20m=20->=20km=20=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 3bf135cf..b40195a0 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -33,8 +33,8 @@ class UserRecord(BaseModel): class nokResult(BaseModel): dementiaInfoRecord: dementiaInfoRecord nokKey: str = Field(examples=["123456"]) - accessToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) - refreshToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) + #accessToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) + #refreshToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) class ReceiveNokInfoRequest(BaseModel): keyFromDementia : int = Field(examples=["123456"]) @@ -63,8 +63,8 @@ class ReceiveDementiaInfoResponse(BaseModel): class connectionResult(BaseModel): nokInfoRecord: nokInfoRecord - accessToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) - refreshToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) + #accessToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) + #refreshToken: str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) class ConnectionRequest(BaseModel): dementiaKey : int = Field(examples=["123456"]) @@ -234,14 +234,14 @@ class RegisterSafeAreaRequest(BaseModel): areaName : str = Field(examples=["집"]) latitude : float = Field(examples=["37.123456"]) longitude : float = Field(examples=["127.123456"]) - radius : int = Field(examples=["100"], description="미터 단위") + radius : float = Field(examples=["0.5"], description="킬로미터 단위") class safeAreaList(BaseModel): areaName : str = Field(examples=["집"]) areaKey : str = Field(examples=["123456"]) latitude : float = Field(examples=["37.123456"]) longitude : float = Field(examples=["127.123456"]) - radius : int = Field(examples=["100"], description="미터 단위") + radius : float = Field(examples=["0.5"], description="킬로미터 단위") class safeAreaGroupInfo(BaseModel): groupName : str = Field(examples=["안심구역 그룹 1"]) From f5244c2c60206f97cc6b26f20ba96e4a5565694e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 30 May 2024 14:00:34 +0900 Subject: [PATCH 50/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=EC=A0=95=EB=B3=B4=20=ED=85=8C=EC=9D=B4=EB=B8=94=20rad?= =?UTF-8?q?ius=20int=20->=20Double=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index dbc6ebab..491282e8 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -92,7 +92,7 @@ class safe_area_info(Base): dementia_key = Column(String) latitude = Column(Double) longitude = Column(Double) - radius = Column(Integer) + radius = Column(Double) class safe_area_group_info(Base): __tablename__ = 'safe_area_group_info' From 521dbff32d32905ce983bda0ac1876b2f6a0c6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 30 May 2024 14:01:03 +0900 Subject: [PATCH 51/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A7=84=EC=9E=85=20=EC=9D=B4=ED=83=88=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B0=98=EC=A7=80=EB=A6=84=20m=20->=20km=EB=A1=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 2 +- backend/fastapi/app/validater.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index d525c2ec..d5e90f3f 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -892,7 +892,7 @@ async def predict_location(dementiaKey : str): #안심구역 -@router.post("/safeArea/register", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록 | groupName이 없으면 notGrouped로 저장됨") +@router.post("/safeArea/register", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역을 등록 | 단위는 km | groupName이 없으면 notGrouped로 저장됨") async def register_safe_area(request: RegisterSafeAreaRequest): try: _dementia_key = request.dementiaKey diff --git a/backend/fastapi/app/validater.py b/backend/fastapi/app/validater.py index 1294c633..5750f234 100644 --- a/backend/fastapi/app/validater.py +++ b/backend/fastapi/app/validater.py @@ -11,7 +11,7 @@ def isinsafearea(self, current_loc, safe_area_list): distance_list = [] for safe_area in safe_area_list: safe_area_location = (safe_area.latitude, safe_area.longitude) - distance = haversine(current_loc, safe_area_location, unit='m') + distance = haversine(current_loc, safe_area_location, unit='km') distance_list.append(distance) min_distance = min(distance_list) From 9073405e7465e245dd02e88ba46ba779aa8406f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Fri, 31 May 2024 18:40:36 +0900 Subject: [PATCH 52/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EB=AF=B8=EB=B6=84=EB=A5=98=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?notGrouped=20->=20=EA=B8=B0=EB=B3=B8=20=EA=B7=B8=EB=A3=B9?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index d5e90f3f..78845d32 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -910,7 +910,7 @@ async def register_safe_area(request: RegisterSafeAreaRequest): pass if _group_name == '': - _group_name = 'notGrouped' + _group_name = '기본 그룹' else: pass @@ -1159,14 +1159,14 @@ async def delete_safe_area_group(request: DeleteSafeAreaGroupRequest): existing_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_key = _group_key).first() - not_grouped = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = 'notGrouped').first() + not_grouped = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = '기본 그룹').first() if not not_grouped: rng = RandomNumberGenerator() for _ in range(10): _not_grouped_key = rng.generate_unique_random_number(100000, 999999) - new_group = models.safe_area_group_info(group_key = _group_key, group_name = 'notGrouped', dementia_key = _dementia_key) + new_group = models.safe_area_group_info(group_key = _group_key, group_name = '기본 그룹', dementia_key = _dementia_key) session.add(new_group) else: _not_grouped_key = not_grouped.group_key From 3bc90570535017ecd24f35254a2a29ec655a009f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 3 Jun 2024 16:08:46 +0900 Subject: [PATCH 53/77] =?UTF-8?q?fix=20:=20=EC=9A=94=EA=B5=AC=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/fastapi/requirements.txt b/backend/fastapi/requirements.txt index ef5681e0..ba3b9a8c 100644 --- a/backend/fastapi/requirements.txt +++ b/backend/fastapi/requirements.txt @@ -18,3 +18,4 @@ bcrypt==4.1.2 haversine==2.8.1 pyfcm==1.5.4 folium==0.16.0 +openai==1.30.5 From cbb5027fe534c89753ca924aa9b4aa8a071e8f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 3 Jun 2024 16:09:04 +0900 Subject: [PATCH 54/77] =?UTF-8?q?feat=20:=20gpt=20test=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index b40195a0..d974db60 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -302,4 +302,8 @@ class latilongi(BaseModel): class AddressConversionResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: Dict[str, float] = latilongi \ No newline at end of file + result: Dict[str, float] = latilongi + +class GPTRequest(BaseModel): + dementiaKey : str = Field(examples=["123456"]) + date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") \ No newline at end of file From 343a9648e9f7d37435b58075982140a69fcf81fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 3 Jun 2024 16:09:29 +0900 Subject: [PATCH 55/77] =?UTF-8?q?feat=20:=20gpt=20api=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 78845d32..47ed7340 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -28,6 +28,7 @@ import urllib.parse import pandas as pd import time +from openai import OpenAI router = APIRouter() @@ -40,6 +41,9 @@ val = validateInSafeArea() kakao = Local(service_key=Config.kakao_service_key) oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") +client = OpenAI( + api_key=Config.GPT_API_KEY, +) @@ -1229,6 +1233,39 @@ async def address_conversion(request: AddressConversionRequest): finally: session.close() +#gpt test +@router.post("/gpt") +async def gpt_test(request: GPTRequest): + _key = request.dementiaKey + _date = request.date + + loc_list = session.query(models.location_info).filter_by(dementia_key = _key, date = _date).all() + + if not loc_list: + raise HTTPException(status_code=404, detail="Location data not found") + + route_descriptions = [f"({loc.latitude}, {loc.longitude})" for loc in loc_list] + route_prompt = "User's travel route: " + " -> ".join(route_descriptions) + + try: + response = client.chat.completions.create( + model="gpt-3.5-turbo", + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": route_prompt} + ] + ) + + return {"summary": response.choices[0].message['content'].strip()} + except Exception as e: + print(f"[ERROR] GPT-3 failed: {e}") + + raise HTTPException(status_code=404, detail=f"{e}") + + finally: + session.close() + + From 28623ea75a42238407e32209e8776e067242c9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 00:34:55 +0900 Subject: [PATCH 56/77] =?UTF-8?q?feat:=20=EA=B7=B8=EB=A3=B9=ED=82=A4=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=EC=9D=91=EB=8B=B5=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index d974db60..17eb36d4 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -306,4 +306,13 @@ class AddressConversionResponse(BaseModel): class GPTRequest(BaseModel): dementiaKey : str = Field(examples=["123456"]) - date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") \ No newline at end of file + date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") + +class safeAreaGroupInfo(BaseModel): + groupName : str = Field(examples=["안심구역 그룹 1"]) + groupKey : str = Field(examples=["123456"]) + +class GetSafeAreaGroupKeyResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: safeAreaGroupInfo \ No newline at end of file From 35ebb4a59d2826d37730198df9a432e368f68b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 00:35:06 +0900 Subject: [PATCH 57/77] =?UTF-8?q?feat:=20=EA=B7=B8=EB=A3=B9=20=ED=82=A4=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 47ed7340..7638f48e 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -988,6 +988,28 @@ async def get_safe_area_info(dementiaKey: str): } + return response + + finally: + session.close() + +@router.get("/safeArea/group/key", responses = {200 : {"model" : GetSafeAreaGroupKeyResponse, "description" : "안전 지역 그룹 키 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 키 없음"}}, description="보호 대상자의 안전 지역 그룹 키 전달(쿼리 스트링)") +async def get_safe_area_group_key(dementiaKey: str, groupName: str): + try: + group_key = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey, group_name = groupName).first().group_key + + if not group_key: + raise HTTPException(status_code=404, detail="Safe area group key not found") + + response = { + 'status': 'success', + 'message': 'Safe area group key sent', + 'result': { + 'groupName': groupName, # '기본 그룹' or '사용자 지정 그룹 + 'groupKey': group_key + } + } + return response finally: From fd17615ac8a134660b2c1b80e5f4c81f78cc3cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 00:57:56 +0900 Subject: [PATCH 58/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=83=9D=EC=84=B1=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 17eb36d4..e9356ce3 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -230,7 +230,7 @@ class AverageWalkingSpeedResponse(BaseModel): class RegisterSafeAreaRequest(BaseModel): dementiaKey : str = Field(examples=["123456"]) - groupName : str = Field(examples=["안심구역 그룹 1"]) + groupKey : str = Field(examples=["123456"]) areaName : str = Field(examples=["집"]) latitude : float = Field(examples=["37.123456"]) longitude : float = Field(examples=["127.123456"]) @@ -311,7 +311,7 @@ class GPTRequest(BaseModel): class safeAreaGroupInfo(BaseModel): groupName : str = Field(examples=["안심구역 그룹 1"]) groupKey : str = Field(examples=["123456"]) - + class GetSafeAreaGroupKeyResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") From 9cd07f670f517e12c4b2e4462068aa5b56231556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 00:58:20 +0900 Subject: [PATCH 59/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=83=9D=EC=84=B1=20=EA=B3=BC=20=EC=95=88=EC=8B=AC?= =?UTF-8?q?=EA=B5=AC=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?api=20=EB=B6=84=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 42 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 7638f48e..32bc4fe5 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -904,34 +904,40 @@ async def register_safe_area(request: RegisterSafeAreaRequest): _latitude = request.latitude _longitude = request.longitude _radius = request.radius - _group_name = request.groupName + _group_key = request.groupKey - if not session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, area_name = _area_name).first() == None: + if not session.query(models.safe_area_info).filter_by(dementia_key = _dementia_key, group_key = _group_key, area_name = _area_name).first() == None: print(f"[ERROR] Safe area already exists for {_dementia_key}") - raise HTTPException(status_code=400, message="Safe area already exists") + raise HTTPException(status_code=400, detail="Safe area already exists in group") else: pass - if _group_name == '': - _group_name = '기본 그룹' + if _group_key == '': + _default_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = '기본 그룹').first() + if _default_group: + _group_key = _default_group.group_key + else: + rng = RandomNumberGenerator() + for _ in range(10): + _group_key = rng.generate_unique_random_number(100000, 999999) + + new_group = models.safe_area_group_info(group_key = _group_key, group_name = '기본 그룹', dementia_key = _dementia_key) + session.add(new_group) else: pass - existing_group = session.query(models.safe_area_group_info).filter_by(group_name = _group_name).first() - - if existing_group: - _group_key = existing_group.group_key - else: - rng = RandomNumberGenerator() - for _ in range(10): - _group_key = rng.generate_unique_random_number(100000, 999999) - - new_group = models.safe_area_group_info(group_key = _group_key, group_name = _group_name) - session.add(new_group) - _area_key = int(_dementia_key) + datetime.timestamp(datetime.now(timezone('Asia/Seoul'))) + ord(_area_name[0]) - new_area = models.safe_area_info(area_key = _area_key, dementia_key = _dementia_key, area_name = _area_name, latitude = _latitude, longitude = _longitude, radius = _radius, group_key = _group_key) + + new_area = models.safe_area_info( + dementia_key = _dementia_key, + area_key = _area_key, + area_name = _area_name, + latitude = _latitude, + longitude = _longitude, + radius = _radius, + group_key = _group_key + ) session.add(new_area) From 416246cebfca6e82f4f504a64b3835d93971f625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 01:02:50 +0900 Subject: [PATCH 60/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=83=9D=EC=84=B1=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=AA=A8=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index e9356ce3..218a757a 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -236,6 +236,10 @@ class RegisterSafeAreaRequest(BaseModel): longitude : float = Field(examples=["127.123456"]) radius : float = Field(examples=["0.5"], description="킬로미터 단위") +class RegisterSafeAreaGroupRequest(BaseModel): + dementiaKey : str = Field(examples=["123456"]) + groupName : str = Field(examples=["안심구역 그룹 1"]) + class safeAreaList(BaseModel): areaName : str = Field(examples=["집"]) areaKey : str = Field(examples=["123456"]) From d38018e3932114804eb7b90abc0b828dd1c6a5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 01:03:06 +0900 Subject: [PATCH 61/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=EC=83=9D=EC=84=B1=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 32bc4fe5..1aca4211 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -955,6 +955,44 @@ async def register_safe_area(request: RegisterSafeAreaRequest): finally: session.close() +@router.post("/safeArea/register/group", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 그룹 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역 그룹을 등록") +async def register_safe_area_group(request: RegisterSafeAreaGroupRequest): + try: + _dementia_key = request.dementiaKey + _group_name = request.groupName + + existing_group = session.query(models.safe_area_group_info).filter_by(dementia_key = _dementia_key, group_name = _group_name).first() + + if existing_group: + print(f"[ERROR] Safe area group already exists for {_dementia_key}") + + raise HTTPException(status_code=400, detail="Safe area group already exists") + else: + rng = RandomNumberGenerator() + for _ in range(10): + _group_key = rng.generate_unique_random_number(100000, 999999) + + new_group = models.safe_area_group_info( + dementia_key = _dementia_key, + group_key = _group_key, + group_name = _group_name + ) + session.add(new_group) + session.commit() + + print(f"[INFO] Safe area group registered for {_dementia_key}") + + response = { + 'status': 'success', + 'message': 'Safe area group registered' + } + + return response + + finally: + session.close() + + @router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링)") async def get_safe_area_info(dementiaKey: str): try: From 794c2a08f59178834be145cd035ad83493c45103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 01:07:24 +0900 Subject: [PATCH 62/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A0=95=EB=B3=B4=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EA=B7=B8=EB=A3=B9=20=EB=AA=85=EA=B3=BC=20=ED=82=A4?= =?UTF-8?q?=EB=A7=8C=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 218a757a..be15dc45 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -250,13 +250,14 @@ class safeAreaList(BaseModel): class safeAreaGroupInfo(BaseModel): groupName : str = Field(examples=["안심구역 그룹 1"]) groupKey : str = Field(examples=["123456"]) - safeAreas : List[safeAreaList] +class groupList(BaseModel): + groupList : List[safeAreaGroupInfo] class GetSafeAreaResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: List[safeAreaGroupInfo] + result: groupList class ModifySafeAreaName(BaseModel): dementiaKey : str = Field(examples=["123456"]) From e3ea2a46bb4e141963c49b76972098205525eb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 01:09:37 +0900 Subject: [PATCH 63/77] =?UTF-8?q?fix:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EA=B7=B8=EB=A3=B9=20=ED=82=A4=EC=99=80=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EB=A7=8C=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 1aca4211..1adac29a 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -992,7 +992,6 @@ async def register_safe_area_group(request: RegisterSafeAreaGroupRequest): finally: session.close() - @router.get("/safeArea/info", responses = {200 : {"model" : GetSafeAreaResponse, "description" : "안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 전달(쿼리 스트링)") async def get_safe_area_info(dementiaKey: str): try: @@ -1002,27 +1001,15 @@ async def get_safe_area_info(dementiaKey: str): # 그룹별로 저장 for group in group_list: - safe_area_list = session.query(models.safe_area_info).filter_by(group_key = group.group_key).all() - - safe_areas = [] - for safe_area in safe_area_list: - safe_areas.append({ - 'areaName': safe_area.area_name, - 'areaKey': safe_area.area_key, - 'latitude': safe_area.latitude, - 'longitude': safe_area.longitude, - 'radius': safe_area.radius - }) group_lists.append({ 'groupName': group.group_name, - 'groupKey': group.group_key, - 'safeAreas': safe_areas + 'groupKey': group.group_key }) result = { - 'safeAreaList': group_lists + 'groupList': group_lists } response = { From dd658034b1ddf3076fb20a436b5af14d6416c1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 01:20:13 +0900 Subject: [PATCH 64/77] =?UTF-8?q?fix:=20=EA=B7=B8=EB=A3=B9=ED=82=A4=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=EC=9D=91=EB=8B=B5=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index be15dc45..6849cba1 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -311,13 +311,4 @@ class AddressConversionResponse(BaseModel): class GPTRequest(BaseModel): dementiaKey : str = Field(examples=["123456"]) - date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") - -class safeAreaGroupInfo(BaseModel): - groupName : str = Field(examples=["안심구역 그룹 1"]) - groupKey : str = Field(examples=["123456"]) - -class GetSafeAreaGroupKeyResponse(BaseModel): - status: str = Field("success") - message: str = Field("메~시~지~") - result: safeAreaGroupInfo \ No newline at end of file + date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") \ No newline at end of file From f37e25ab238a4c5f3f9beddbd6e0ccb5d867189e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 5 Jun 2024 01:20:36 +0900 Subject: [PATCH 65/77] =?UTF-8?q?fix:=20=EA=B7=B8=EB=A3=B9=20=ED=82=A4=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=ED=95=98=EC=9A=B0=ED=8A=B8=20=EB=A1=A4?= =?UTF-8?q?=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 1adac29a..efa305b4 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -1019,28 +1019,6 @@ async def get_safe_area_info(dementiaKey: str): } - return response - - finally: - session.close() - -@router.get("/safeArea/group/key", responses = {200 : {"model" : GetSafeAreaGroupKeyResponse, "description" : "안전 지역 그룹 키 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 그룹 키 없음"}}, description="보호 대상자의 안전 지역 그룹 키 전달(쿼리 스트링)") -async def get_safe_area_group_key(dementiaKey: str, groupName: str): - try: - group_key = session.query(models.safe_area_group_info).filter_by(dementia_key = dementiaKey, group_name = groupName).first().group_key - - if not group_key: - raise HTTPException(status_code=404, detail="Safe area group key not found") - - response = { - 'status': 'success', - 'message': 'Safe area group key sent', - 'result': { - 'groupName': groupName, # '기본 그룹' or '사용자 지정 그룹 - 'groupKey': group_key - } - } - return response finally: From f344ca2b89e8d567bb72c6df2aafd5923163a626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 10 Jun 2024 20:21:49 +0900 Subject: [PATCH 66/77] =?UTF-8?q?fix:=20=EA=B7=B8=EB=A3=B9=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=ED=82=A4=20=EB=A6=AC=ED=84=B4=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index efa305b4..861b0e2f 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -955,7 +955,7 @@ async def register_safe_area(request: RegisterSafeAreaRequest): finally: session.close() -@router.post("/safeArea/register/group", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : CommonResponse, "description" : "안전 지역 그룹 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역 그룹을 등록") +@router.post("/safeArea/register/group", status_code=status.HTTP_201_CREATED, responses = {201 : {"model" : RegisterSafeAreaGroupResponse, "description" : "안전 지역 그룹 등록 성공" }, 404: {"model": ErrorResponse, "description": "보호 대상자 키 조회 실패"}}, description="보호 대상자의 안전 지역 그룹을 등록") async def register_safe_area_group(request: RegisterSafeAreaGroupRequest): try: _dementia_key = request.dementiaKey @@ -982,9 +982,14 @@ async def register_safe_area_group(request: RegisterSafeAreaGroupRequest): print(f"[INFO] Safe area group registered for {_dementia_key}") + result = { + 'groupKey': _group_key + } + response = { 'status': 'success', - 'message': 'Safe area group registered' + 'message': 'Safe area group registered', + 'result' : result } return response From fe2d948697022ccc0a76668018b91244fc7268fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Mon, 10 Jun 2024 20:22:12 +0900 Subject: [PATCH 67/77] =?UTF-8?q?fix:=20=EA=B7=B8=EB=A3=B9=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 6849cba1..5f177cc0 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -311,4 +311,12 @@ class AddressConversionResponse(BaseModel): class GPTRequest(BaseModel): dementiaKey : str = Field(examples=["123456"]) - date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") \ No newline at end of file + date : str = Field(examples=["2024-03-19"], description="yyyy-mm-dd") + +class groupKey(BaseModel): + groupKey : str = Field(examples=["123456"]) + +class RegisterSafeAreaGroupResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: groupKey \ No newline at end of file From 172192bea15bff3a2267fcbc24b37888f72c235a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Tue, 18 Jun 2024 23:01:59 +0900 Subject: [PATCH 68/77] =?UTF-8?q?fix:=20=EC=9E=84=EC=8B=9C=EB=A1=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8D=98=20fcm=20token=EC=9D=84=20d?= =?UTF-8?q?b=EC=97=90=EC=84=9C=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/validater.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/fastapi/app/validater.py b/backend/fastapi/app/validater.py index 5750f234..ad05116d 100644 --- a/backend/fastapi/app/validater.py +++ b/backend/fastapi/app/validater.py @@ -30,7 +30,7 @@ async def pushNotification(self, fcm_token, latest_location, before_location, sa "safeAreaName" : safeArea.area_name, "time" : latest_location.time } - send_push_notification(Config.temp_fcm_token, "어디U", "안심 구역 이탈", data) + send_push_notification(fcm_token, "어디U", "안심 구역 이탈", data) elif latest_location.isInSafeArea == 1 and before_location.isInSafeArea == 0: data = { "safeAreaName" : safeArea.area_name, From 596e711f43ec9979b4b817aeddc3bd7bdbfb987b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 19 Jun 2024 15:03:25 +0900 Subject: [PATCH 69/77] =?UTF-8?q?fix:=20=EC=A7=84=EC=9E=85=20=EC=9D=B4?= =?UTF-8?q?=ED=83=88=20=EA=B0=90=EC=A7=80=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20/=20fcm=20title=20body=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/validater.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/fastapi/app/validater.py b/backend/fastapi/app/validater.py index ad05116d..aae7d632 100644 --- a/backend/fastapi/app/validater.py +++ b/backend/fastapi/app/validater.py @@ -11,14 +11,14 @@ def isinsafearea(self, current_loc, safe_area_list): distance_list = [] for safe_area in safe_area_list: safe_area_location = (safe_area.latitude, safe_area.longitude) - distance = haversine(current_loc, safe_area_location, unit='km') + distance = haversine(current_loc, safe_area_location, unit='m') distance_list.append(distance) min_distance = min(distance_list) min_distance_index = distance_list.index(min_distance) nearest_safe_area = safe_area_list[min_distance_index] - if min_distance > nearest_safe_area.radius: + if min_distance > nearest_safe_area.radius * 1000: print(f"[INFO] Current location is not in safe area({nearest_safe_area.area_name})") return nearest_safe_area, False else: @@ -30,12 +30,12 @@ async def pushNotification(self, fcm_token, latest_location, before_location, sa "safeAreaName" : safeArea.area_name, "time" : latest_location.time } - send_push_notification(fcm_token, "어디U", "안심 구역 이탈", data) + send_push_notification(fcm_token, "안심 구역 이탈", "",data) elif latest_location.isInSafeArea == 1 and before_location.isInSafeArea == 0: data = { "safeAreaName" : safeArea.area_name, "time" : latest_location.time } - send_push_notification(fcm_token, "어디U", "안심 구역 진입", data) + send_push_notification(fcm_token, "안심 구역 진입", "",data) From 0cba4d0fbd14d614ed93ffa284528c0f4b556c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 19 Jun 2024 18:33:00 +0900 Subject: [PATCH 70/77] =?UTF-8?q?fix:=20fcm=20push=20message=20=EB=94=94?= =?UTF-8?q?=EB=B2=84=EA=B9=85=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/fcm_notification.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/fastapi/app/fcm_notification.py b/backend/fastapi/app/fcm_notification.py index 7171666c..e9f8384d 100644 --- a/backend/fastapi/app/fcm_notification.py +++ b/backend/fastapi/app/fcm_notification.py @@ -4,10 +4,7 @@ push_service = FCMNotification(Config.fcm_server_key) - -def send_push_notification(token, title, body, data): - - #result = push_service.notify_single_device(registration_id=token, message_title=title, message_body=body) +async def send_push_notification(token, title, body, data): result = push_service.notify_single_device( registration_id=token, @@ -15,6 +12,7 @@ def send_push_notification(token, title, body, data): message_body=body, data_message=data ) + print("[INFO] push notification sent") return result From 560acad85484af2ab189043218a06b0e6819b41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 19 Jun 2024 18:33:22 +0900 Subject: [PATCH 71/77] =?UTF-8?q?fix:=20nok=5Finfo=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=EC=97=90=20fcm=5Ftoken=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/fastapi/app/models.py b/backend/fastapi/app/models.py index 491282e8..49a1ea85 100644 --- a/backend/fastapi/app/models.py +++ b/backend/fastapi/app/models.py @@ -12,6 +12,7 @@ class nok_info(Base): nok_phonenumber = Column(String) update_rate = Column(String) dementia_info_key = Column(String) + fcm_token = Column(String) class dementia_info(Base): __tablename__ = 'dementia_info' From edc34a57d3152bfa5fd88982572b6cce6531fa02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 19 Jun 2024 18:33:49 +0900 Subject: [PATCH 72/77] =?UTF-8?q?fix:=20=EB=B3=B4=ED=98=B8=EC=9E=90=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=EC=8B=9C=20fcm=5Ftoken=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 861b0e2f..5bc2dd5d 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -75,6 +75,11 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): if duplication_check: _key = duplication_check.nok_key + if not duplication_check.fcm_token == request.fcmToken: + duplication_check.fcm_token = request.fcmToken + session.commit() + else: + pass else: unique_key = None @@ -83,11 +88,11 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): _key = str(unique_key) - new_nok = models.nok_info(nok_key=_key, nok_name=_nok_name, nok_phonenumber=_nok_phonenumber, dementia_info_key=_key_from_dementia, update_rate=1) # update_rate는 기본값 1분으로 설정 + new_nok = models.nok_info(nok_key=_key, nok_name=_nok_name, nok_phonenumber=_nok_phonenumber, dementia_info_key=_key_from_dementia, update_rate=1, fcm_token = request.fcmToken) # update_rate는 기본값 1분으로 설정 session.add(new_nok) session.commit() - if not request.fcmToken == '': + '''if not request.fcmToken == '': existing_token = session.query(models.refresh_token_info).filter_by(key = _key).first() if existing_token: existing_token.fcm_token = request.fcmToken @@ -98,7 +103,7 @@ async def receive_nok_info(request: ReceiveNokInfoRequest): session.commit() else: - pass + pass''' result = { 'dementiaInfoRecord' : { @@ -155,7 +160,7 @@ async def receive_dementia_info(request: ReceiveDementiaInfoRequest): session.add(new_dementia) session.commit() - if not request.fcmToken == '': + '''if not request.fcmToken == '': existing_token = session.query(models.refresh_token_info).filter_by(key = _key).first() if existing_token: existing_token.fcm_token = request.fcmToken @@ -164,7 +169,7 @@ async def receive_dementia_info(request: ReceiveDementiaInfoRequest): session.add(new_token) session.commit() else: - pass + pass''' result = { 'dementiaKey': _key @@ -325,9 +330,14 @@ def receive_location_info(request: ReceiveLocationRequest): session.add(new_location) session.commit() - fcm_token = session.query(models.refresh_token_info).filter_by(key = _dementia_key).first().fcm_token - if fcm_token: - asyncio.run(val.pushNotification(fcm_token, new_location, latest_loc, _near_safe_area)) + nok_info = session.query(models.nok_info).filter_by(dementia_info_key = _dementia_key).all() + + if nok_info: + for nok in nok_info: + if nok.fcm_token == None: + pass + else: + asyncio.run(val.pushNotification(nok.fcm_token, new_location, latest_loc, _near_safe_area)) else: pass From 2be4c85418da33695b4eecde5ccae6eb289f774f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Wed, 19 Jun 2024 18:34:10 +0900 Subject: [PATCH 73/77] =?UTF-8?q?fix:=20fcm=20=EB=B9=84=EB=8F=99=EA=B8=B0?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/validater.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/fastapi/app/validater.py b/backend/fastapi/app/validater.py index aae7d632..371e8673 100644 --- a/backend/fastapi/app/validater.py +++ b/backend/fastapi/app/validater.py @@ -25,17 +25,16 @@ def isinsafearea(self, current_loc, safe_area_list): return nearest_safe_area, True async def pushNotification(self, fcm_token, latest_location, before_location, safeArea): + if latest_location.isInSafeArea == 0 and before_location.isInSafeArea == 1: data = { "safeAreaName" : safeArea.area_name, "time" : latest_location.time } - send_push_notification(fcm_token, "안심 구역 이탈", "",data) + await send_push_notification(fcm_token, "안심 구역 이탈", "", data) elif latest_location.isInSafeArea == 1 and before_location.isInSafeArea == 0: data = { "safeAreaName" : safeArea.area_name, "time" : latest_location.time } - send_push_notification(fcm_token, "안심 구역 진입", "",data) - - + await send_push_notification(fcm_token, "안심 구역 진입", "", data) \ No newline at end of file From c0549c83e96769ed9ed37c3fe90e943ce4d6fc0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 20 Jun 2024 23:50:18 +0900 Subject: [PATCH 74/77] =?UTF-8?q?fix:=20=EC=9A=94=EA=B5=AC=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/fastapi/requirements.txt b/backend/fastapi/requirements.txt index ba3b9a8c..23a75644 100644 --- a/backend/fastapi/requirements.txt +++ b/backend/fastapi/requirements.txt @@ -16,6 +16,6 @@ python-multipart==0.0.9 passlib==1.7.4 bcrypt==4.1.2 haversine==2.8.1 -pyfcm==1.5.4 +firebase-admin==6.5.0 folium==0.16.0 openai==1.30.5 From f6d839505a49c6b9a557669922ca1b37a5ad95a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 20 Jun 2024 23:50:41 +0900 Subject: [PATCH 75/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A0=84=EC=B2=B4=20=EC=A0=95=EB=B3=B4=20=EC=A0=84?= =?UTF-8?q?=EB=8B=AC=20=EC=9D=91=EB=8B=B5=20=EB=AA=A8=EB=8D=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/bodymodel.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/backend/fastapi/app/bodymodel.py b/backend/fastapi/app/bodymodel.py index 5f177cc0..ae841a68 100644 --- a/backend/fastapi/app/bodymodel.py +++ b/backend/fastapi/app/bodymodel.py @@ -54,7 +54,6 @@ class dementiaResult(BaseModel): class ReceiveDementiaInfoRequest(BaseModel): name : str = Field(examples=["성춘향"]) phoneNumber : str = Field(examples=["010-1234-5678"]) - fcmToken : str = Field(examples=["ksjdnfjkdasnfljsknafljansdfjlsakn"]) class ReceiveDementiaInfoResponse(BaseModel): status: str = Field("success") @@ -319,4 +318,15 @@ class groupKey(BaseModel): class RegisterSafeAreaGroupResponse(BaseModel): status: str = Field("success") message: str = Field("메~시~지~") - result: groupKey \ No newline at end of file + result: groupKey + +class safeArea(BaseModel): + areaName : str = Field(examples=["집"]) + latitude : float = Field(examples=["37.123456"]) + longitude : float = Field(examples=["127.123456"]) + radius : float = Field(examples=["0.5"], description="킬로미터 단위") + +class GetSafeAreaAllResponse(BaseModel): + status: str = Field("success") + message: str = Field("메~시~지~") + result: List[safeArea] \ No newline at end of file From 6c1bdc15f1d318243c55e2667f771409b392600e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 20 Jun 2024 23:51:02 +0900 Subject: [PATCH 76/77] =?UTF-8?q?fix:=20fcm=20HTTP=20->=20HTTP=20=20v1?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B2=84=EC=A0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/fcm_notification.py | 26 ++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/backend/fastapi/app/fcm_notification.py b/backend/fastapi/app/fcm_notification.py index e9f8384d..a5a072fb 100644 --- a/backend/fastapi/app/fcm_notification.py +++ b/backend/fastapi/app/fcm_notification.py @@ -1,18 +1,34 @@ -from pyfcm import FCMNotification +import firebase_admin +from firebase_admin import credentials +from firebase_admin import messaging + from .config import Config -push_service = FCMNotification(Config.fcm_server_key) +cred_path = Config.cred_path +cred = credentials.Certificate(cred_path) +firebase_admin.initialize_app(cred) + async def send_push_notification(token, title, body, data): - result = push_service.notify_single_device( + '''result = push_service.notify_single_device( registration_id=token, message_title=title, message_body=body, data_message=data + )''' + + message = messaging.Message( + notification=messaging.Notification( + title=title, + body=body + ), + data=data, + token=token ) - print("[INFO] push notification sent") - return result + response = messaging.send(message) + + print('Successfully sent message:', response) From e65c1d650785a60946aff37debe7ff35b573e900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=87=E1=85=A1=E1=86=A8=E1=84=89=E1=85=B3=E1=86=BC?= =?UTF-8?q?=E1=84=92=E1=85=A9?= Date: Thu, 20 Jun 2024 23:51:17 +0900 Subject: [PATCH 77/77] =?UTF-8?q?feat:=20=EC=95=88=EC=8B=AC=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=A0=84=EC=B2=B4=20=EB=B0=98=ED=99=98=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/fastapi/app/routes2.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/fastapi/app/routes2.py b/backend/fastapi/app/routes2.py index 5bc2dd5d..e13b19af 100644 --- a/backend/fastapi/app/routes2.py +++ b/backend/fastapi/app/routes2.py @@ -51,7 +51,7 @@ @router.post("/test/fcm", description="FCM 테스트") async def send_fcm(request: FCMRequest): - send_push_notification(request.token, request.title, request.body, request.data) + await send_push_notification(request.token, request.title, request.body, request.data) return {"status": "success", "message": "FCM sent"} @@ -1073,6 +1073,37 @@ async def get_safe_area_group_info(dementiaKey: str, groupKey: str): finally: session.close() +@router.get("/safeArea/info/all", responses = {200 : {"model" : GetSafeAreaAllResponse, "description" : "전체 안전 지역 정보 전송 성공" }, 404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 전체 안전 지역 정보 전달(쿼리 스트링)") +async def get_safe_area_all_info(dementiaKey: str): + try: + safe_area_list = session.query(models.safe_area_info).filter_by(dementia_key = dementiaKey).all() + + areas = [] + + for area in safe_area_list: + new_area = { + 'areaName' : area.area_name, + 'latitude' : area.latitude, + 'longitude' : area.longitude, + 'radius' : area.radius + } + areas.append(new_area) + + result = { + 'safeAreas': areas + } + + response = { + 'status': 'success', + 'message': 'Safe area information sent', + 'result': result + } + + return response + + finally: + session.close() + @router.post("/safeArea/modification/name", responses = {200 : {"model" : CommonResponse, "description" : "안전 지역 정보 수정 성공" }, 400 : {"model" : ErrorResponse, "description" : "안심 구역 이름 중복"},404: {"model": ErrorResponse, "description": "안전 지역 정보 없음"}}, description="보호 대상자의 안전 지역 정보 수정") async def modify_name_safe_area_info(request: ModifySafeAreaName): try: