building apis
updating weather info on the fly and updates regularly, as well as the predictions, and also api that gives warning accordingly
@da011f0d1caf009cb6d7a8207e9868f787c61e2f
+++ action.py
... | ... | @@ -0,0 +1,34 @@ |
1 | +import sched | |
2 | + | |
3 | +from flask_restx import Resource, Api, Namespace, fields | |
4 | +from flask import request | |
5 | +from flask import Flask, render_template, request | |
6 | +import pandas as pd | |
7 | + | |
8 | +Action = Namespace( | |
9 | + name="Action", | |
10 | + description="노드 분석을 위해 사용하는 api.", | |
11 | +) | |
12 | +# @sched.scheduler | |
13 | +# def weather_update | |
14 | + | |
15 | [email protected]('/forecast') | |
16 | +class forecast(Resource): | |
17 | + @Action.doc(responses={200: 'Success'}) | |
18 | + @Action.doc(responses={500: 'Register Failed'}) | |
19 | + def post(self): | |
20 | + if request.method == 'GET': | |
21 | + df = pd.read_csv("data/weather/weather_data_forecast.csv") | |
22 | + humidity = df['forecast'].value[6:] / 6 | |
23 | + if humidity > 90: | |
24 | + return { | |
25 | + 'report': "warn" | |
26 | + }, 200 | |
27 | + elif humidity <= 90 and humidity > 80: | |
28 | + return { | |
29 | + 'report': "caution" | |
30 | + }, 200 | |
31 | + else: | |
32 | + return { | |
33 | + 'report': "safe" | |
34 | + }, 200(파일 끝에 줄바꿈 문자 없음) |
--- app.py
+++ app.py
... | ... | @@ -2,6 +2,10 @@ |
2 | 2 |
from flask_restx import Api |
3 | 3 |
from auth import Auth |
4 | 4 |
from action import Action |
5 |
+from apscheduler.schedulers.background import BackgroundScheduler |
|
6 |
+from apscheduler.triggers.interval import IntervalTrigger |
|
7 |
+from tools.weather_agency_api.weather_api import update_weather_info_to_today |
|
8 |
+from tools.algo.SARIMA import sarima |
|
5 | 9 |
|
6 | 10 |
app = Flask(__name__) |
7 | 11 |
|
... | ... | @@ -14,11 +18,41 @@ |
14 | 18 |
contact="[email protected]", |
15 | 19 |
license="MIT") |
16 | 20 |
|
21 |
+ |
|
22 |
+scheduler = BackgroundScheduler() |
|
23 |
+scheduler.start() |
|
24 |
+ |
|
25 |
+# Schedule task_function to be called every 6 hours |
|
26 |
+scheduler.add_job( |
|
27 |
+ func=update_weather_info_to_today, |
|
28 |
+ trigger=IntervalTrigger(hours=6), |
|
29 |
+ args=("data/weather/weather_data.csv",), |
|
30 |
+ # comma to make it a tuple, so that python won't confuse this as a list of char |
|
31 |
+ id='weather_data_update', |
|
32 |
+ name='update weather time every 6 hours', |
|
33 |
+ replace_existing=True |
|
34 |
+) |
|
35 |
+scheduler.add_job( |
|
36 |
+ func=sarima, |
|
37 |
+ trigger=IntervalTrigger(hours=6), |
|
38 |
+ args=("data/weather/weather_data.csv",), |
|
39 |
+ # comma to make it a tuple, so that python won't confuse this as a list of char |
|
40 |
+ id='weather_data_update', |
|
41 |
+ name='update weather time every 6 hours', |
|
42 |
+ replace_existing=True |
|
43 |
+) |
|
44 |
+ |
|
45 |
+api.add_namespace(Action, '/action') |
|
46 |
+update_weather_info_to_today("data/weather/weather_data.csv") |
|
47 |
+sarima("data/weather/weather_data.csv") |
|
48 |
+ |
|
17 | 49 |
api.add_namespace(Auth, '/auth') |
18 | 50 |
print("Api Add Auth") |
19 | 51 |
|
20 |
-api.add_namespace(Action, '/action') |
|
21 | 52 |
|
22 | 53 |
if __name__ == "__main__": |
23 |
- app.run(debug=False, host='0.0.0.0', port=8080) |
|
54 |
+ try: |
|
55 |
+ app.run(debug=False, host='0.0.0.0', port=8080) |
|
56 |
+ except: |
|
57 |
+ scheduler.shutdown() |
|
24 | 58 |
print("Flask Start")(파일 끝에 줄바꿈 문자 없음) |
+++ auth.py
... | ... | @@ -0,0 +1,114 @@ |
1 | +import hashlib | |
2 | +from flask import request,jsonify,render_template,redirect,url_for | |
3 | +from flask_restx import Resource, Api, Namespace, fields | |
4 | +from database.database import DB | |
5 | +import datetime | |
6 | +import jwt | |
7 | + | |
8 | + | |
9 | + | |
10 | + | |
11 | + | |
12 | +users = {} | |
13 | + | |
14 | +Auth = Namespace( | |
15 | + name="Auth", | |
16 | + description="사용자 인증을 위한 API", | |
17 | +) | |
18 | + | |
19 | + | |
20 | +user_fields = Auth.model('User', { # Model 객체 생성 | |
21 | + 'id': fields.String(description='a User Name', required=True, example="id") | |
22 | +}) | |
23 | + | |
24 | + | |
25 | +user_fields_auth = Auth.inherit('User Auth', user_fields, { | |
26 | + 'password': fields.String(description='Password', required=True) | |
27 | + | |
28 | +}) | |
29 | + | |
30 | +user_fields_register = Auth.inherit('User reigster', user_fields, { | |
31 | + 'password': fields.String(description='Password', required=True),'email': fields.String(description='email', required=True),'user_sex': fields.String(description='sex', required=True),'phone': fields.String(description='phone', required=True) | |
32 | + | |
33 | +}) | |
34 | + | |
35 | + | |
36 | + | |
37 | [email protected]('/id') | |
38 | +class AuthCheck(Resource): | |
39 | + @Auth.doc(responses={200: 'Success'}) | |
40 | + @Auth.doc(responses={500: 'Register Failed'}) | |
41 | + def post(self): | |
42 | + db=DB() | |
43 | + id = request.json['id'] | |
44 | + value=db.db_check_id(id) | |
45 | + if value != None: | |
46 | + return { | |
47 | + "message": "중복 아이디가 있습니다" | |
48 | + }, 500 | |
49 | + else: | |
50 | + return { | |
51 | + 'message': '사용가능한 아이디입니다' # str으로 반환하여 return | |
52 | + }, 200 | |
53 | + | |
54 | + | |
55 | + | |
56 | + | |
57 | [email protected]('/register') | |
58 | +class AuthRegister(Resource): | |
59 | + @Auth.expect(user_fields_register) | |
60 | + @Auth.doc(responses={200: 'Success'}) | |
61 | + @Auth.doc(responses={500: 'Register Failed'}) | |
62 | + def post(self): | |
63 | + db=DB() | |
64 | + id = request.json['id'] | |
65 | + password = request.json['password'] | |
66 | + user_email = request.json['email'] | |
67 | + sex = request.json['user_sex'] | |
68 | + phone = request.json['phone'] | |
69 | + pw_has = hashlib.sha256(password.encode('utf-8')).hexdigest() | |
70 | + value=db.db_login(id,password) | |
71 | + if value != None: | |
72 | + return { | |
73 | + "message": "Register Failed" | |
74 | + }, 500 | |
75 | + else: | |
76 | + db.db_add_id(id,pw_has,user_email,sex,phone) | |
77 | + return { | |
78 | + 'Authorization': id # str으로 반환하여 return | |
79 | + }, 200 | |
80 | + | |
81 | [email protected]('/login') | |
82 | +class AuthLogin(Resource): | |
83 | + @Auth.expect(user_fields_auth) | |
84 | + @Auth.doc(responses={200: 'Success'}) | |
85 | + @Auth.doc(responses={404: 'User Not Found'}) | |
86 | + @Auth.doc(responses={500: 'Auth Failed'}) | |
87 | + def post(self): | |
88 | + db=DB() | |
89 | + id = request.json['id'] | |
90 | + password = request.json['password'] | |
91 | + pw_hash = hashlib.sha256(password.encode('utf-8')).hexdigest() | |
92 | + result = db.db_login(id,pw_hash) | |
93 | + if result is not None: | |
94 | + payload = { | |
95 | + 'id' : id, | |
96 | + 'exp' : datetime.datetime.utcnow() + datetime.timedelta(seconds=70) | |
97 | + } | |
98 | + token = jwt.encode(payload, "secret", algorithm='HS256') | |
99 | + return jsonify({'result': 'success', 'token': token}) | |
100 | + else: | |
101 | + return jsonify({'result': 'fail', 'msg': '아이디/비밀번호가 일치하지 않습니다.'}) | |
102 | + | |
103 | + | |
104 | [email protected]('/secession') | |
105 | +class AuthSecession(Resource): | |
106 | + def post(self): | |
107 | + db=DB() | |
108 | + id = request.json['token'] | |
109 | + payload = jwt.decode(id, "secret", algorithms=['HS256']) | |
110 | + db.db_delete_id(payload['id']) | |
111 | + return {'secession':'success'} | |
112 | + | |
113 | + | |
114 | + |
+++ data/weather/weather_data.csv
This file is too big to display. |
+++ database/database.py
This diff is skipped because there are too many other diffs. |
--- tools/algo/ARIMA.py
+++ tools/algo/SARIMA.py
This diff is skipped because there are too many other diffs. |
+++ tools/weather_agency_api/check_missing.py
This diff is skipped because there are too many other diffs. |
+++ tools/weather_agency_api/duplicate_check.py
This diff is skipped because there are too many other diffs. |
--- tools/weather_agency_api/weather_api.py
+++ tools/weather_agency_api/weather_api.py
This diff is skipped because there are too many other diffs. |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?