File name
Commit message
Commit date
import sched
import psycopg2
from flask_restx import Resource, Api, Namespace, fields
from flask import request
from flask import Flask, render_template, request, jsonify, Response
from statsmodels.tsa.statespace.sarimax import SARIMAX
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
import pickle
import time
Action = Namespace(
name="Action",
description="노드 분석을 위해 사용하는 api.",
)
db_config = {
'dbname': 'welding',
'user': 'postgres',
'password': 'ts4430!@',
'host': 'localhost', # e.g., 'localhost'
'port': '5432', # e.g., '5432'
}
key_columns = ["temperature", "relative_humidity", "absolute_humidity"]
def buck_equation(temperature): # temp in Celsius
saturation_vapor_pressure = 0.61121 * np.exp((18.678 - temperature / 234.5) * (temperature / (257.14 + temperature)))
return saturation_vapor_pressure * 1000 # KPa -> Pa
def absolute_humidity(relative_humidity, temperature):
relative_humidity = np.array(relative_humidity)
temperature = np.array(temperature)
saturation_vapor_pressure = buck_equation(temperature)
# 461.5/Kg Kelvin is specific gas constant
return saturation_vapor_pressure * relative_humidity * 0.01 /(461.5 * (temperature + 273.15)) # g/m^3
# @sched.scheduler
# def weather_update
@Action.route('/forecast')
class forecast(Resource):
@Action.doc(responses={200: 'Success'})
@Action.doc(responses={500: 'Register Failed'})
def post(self):
if request.method == 'GET':
df = pd.read_csv("data/weather/weather_data_forecast.csv")
humidity = df['forecast'].value[6:] / 6
if humidity > 90:
return {
'report': "warn"
}, 200
elif humidity <= 90 and humidity > 80:
return {
'report': "caution"
}, 200
else:
return {
'report': "safe"
}, 200
@Action.route('/train_sarima', methods=['POST'])
class TrainSARIMA(Resource):
@Action.doc(responses={200: 'Success'})
@Action.doc(responses={500: 'Register Failed'})
def post(self):
query = "SELECT * FROM weather_data ORDER BY time DESC LIMIT 600"
try:
view_past = int(request.form.get('past_data_for_prediction',72))
future_hours = int(request.form.get('future_hours', 24))
save_name = request.form.get('save_name', 'prediction')
with psycopg2.connect(**db_config) as conn:
df = pd.read_sql_query(query, conn)
df_sarima = df.iloc[:view_past]
df_sarima = df_sarima.iloc[::-1].reset_index(drop=True)
df = df.iloc[::-1].reset_index(drop=True)
return_index = [df_sarima['time'].iloc[-1] + timedelta(hours=i) for i in range(1, future_hours + 1)]
forecast_return = pd.DataFrame(None, columns=["time", "temperature", "relative_humidity", "absolute_humidity"])
forecast_return['time'] = return_index
seasonal_order = {
f"{key_columns[0]}": (0, 1, 1, 24),
f"{key_columns[1]}": (0, 1, 1, 24),
f"{key_columns[2]}": (0, 1, 1, 24),
}
t1 = time.time()
for col_key in key_columns:
model = SARIMAX(df_sarima[col_key], order=(1, 0, 2), seasonal_order=seasonal_order[col_key])
model_fit = model.fit(disp=False)
forecast_values = model_fit.forecast(steps=future_hours)
forecast_return[col_key] = forecast_values.values
# with open(f'predictions/sarima_model_{save_name}_{col_key}.pkl', 'wb') as pkl_file:
# pickle.dump(model_fit, pkl_file)
t2 = -(t1 - time.time())
print(f"{t2} seconds per {future_hours*3}\n"
f"that is {future_hours*3 / t2} per seconds")
return Response((pd.concat((df, forecast_return)).reset_index(drop=True)).to_json(orient='columns'), mimetype='application/json')
except Exception as e:
return jsonify({"error": str(e)}), 500
def forecast_from_saved_model(df, trained_weight="predictions" , future_hours=24):
# Load the saved model
forecast_df = None
for key_col in key_columns:
with open(trained_weight, 'rb') as pkl_file:
loaded_model = pickle.load(pkl_file)
print("files loaded")
t1 = time.time()
# Forecast the next 'future_hours' using the loaded model
forecast_values = loaded_model.forecast(steps=future_hours)
forecast_index = [df['time'].iloc[-1] + timedelta(hours=i) for i in range(1, future_hours + 1)]
forecast_df = pd.DataFrame({
'time': forecast_index,
'forecast': forecast_values
})
# forecast_df.to_csv(f"{file.split('.')[0]}_forecast.csv", index=False)
t2 = -(t1 - time.time())
# print(forecast_df)
print(f"{t2} seconds per {future_hours}\n"
f"that is {future_hours/t2} per seconds")
return forecast_df
@Action.route('/fetch_sensor')
class FetchSensorData(Resource):
@Action.doc(responses={200: 'Success', 500: 'Failed'})
def get(self):
conn_params = db_config # Define or fetch your connection parameters here
query = "SELECT * FROM weather_data ORDER BY time DESC LIMIT 600"
try:
with psycopg2.connect(**conn_params) as conn:
df = pd.read_sql_query(query, conn)
# predictions
# Convert Timestamp columns to string
for column in df.columns:
if df[column].dtype == "datetime64[ns]":
df[column] = df[column].astype(str)
return df.to_dict(orient='list'), 200
except Exception as e:
return {"message": str(e)}, 500