mirror of https://github.com/gtitov/mosecohak
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
8.2 KiB
280 lines
8.2 KiB
from fastapi import FastAPI
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.middleware.cors import CORSMiddleware # CORS
|
|
from fastapi.middleware.gzip import GZipMiddleware # gZip
|
|
|
|
from enum import Enum
|
|
|
|
import sqlite3
|
|
from datetime import datetime
|
|
|
|
class ParameterName(str, Enum):
|
|
co = "co"
|
|
no2 = "no2"
|
|
no = "no"
|
|
pm10 = "pm10"
|
|
pm25 = "pm25"
|
|
|
|
app = FastAPI()
|
|
|
|
app.add_middleware(GZipMiddleware, minimum_size=1000) # gZip
|
|
|
|
origins = [ # CORS
|
|
"*",
|
|
]
|
|
|
|
app.add_middleware( # CORS
|
|
CORSMiddleware,
|
|
allow_origins=origins,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
DB_LOCATION = "./db.sqlite"
|
|
|
|
con = sqlite3.connect(DB_LOCATION)
|
|
con.row_factory
|
|
cur = con.cursor()
|
|
|
|
|
|
@app.get("/")
|
|
async def root():
|
|
return "Hello World!"
|
|
|
|
@app.get("/parameters")
|
|
async def get_parameters():
|
|
"""Возращает доступные показатели
|
|
"""
|
|
|
|
cur.execute(
|
|
"""SELECT
|
|
parameter_id,
|
|
parameter_name
|
|
FROM parameters
|
|
"""
|
|
)
|
|
|
|
parameters = cur.fetchall()
|
|
|
|
return [
|
|
{
|
|
"parameter_id": row[0],
|
|
"parameter_name": row[1]
|
|
}
|
|
for row in parameters
|
|
]
|
|
|
|
|
|
@app.get("/stations")
|
|
async def get_stations():
|
|
"""Возращает названия и координаты станций
|
|
"""
|
|
|
|
cur.execute(
|
|
"""SELECT
|
|
station_id,
|
|
st_name,
|
|
lat,
|
|
lon
|
|
FROM stations
|
|
"""
|
|
)
|
|
|
|
stations = cur.fetchall()
|
|
|
|
return [
|
|
{
|
|
"station_id": row[0],
|
|
"st_name": row[1],
|
|
"lat": row[2],
|
|
"lon": row[3]
|
|
}
|
|
for row in stations
|
|
]
|
|
|
|
|
|
@app.get("/stations/{parameter}/{start_datetime}/{end_datetime}")
|
|
async def get_stations_parameter_values(parameter: ParameterName, start_datetime: datetime, end_datetime: datetime):
|
|
"""Возращает значения в станциях на заданный временной интервал для выбранного показателя. Для каждого показателя приводиться список значений на каждый час
|
|
в заданном интервале, включая `start_datetime` и не включая `end_datetime`.
|
|
|
|
Использовать дату и время вида 2020-12-31T17:00
|
|
"""
|
|
|
|
cur.execute(
|
|
"""SELECT
|
|
station_id,
|
|
datetime,
|
|
value,
|
|
forecast
|
|
FROM stations_all_params
|
|
JOIN parameters ON stations_all_params.parameter = parameters.parameter_id
|
|
WHERE parameter_name = :parameter AND datetime >= strftime('%s', :start_datetime) AND datetime < strftime('%s', :end_datetime)
|
|
""",
|
|
{
|
|
"parameter": parameter,
|
|
"start_datetime": start_datetime,
|
|
"end_datetime": end_datetime
|
|
}
|
|
)
|
|
|
|
stations_values = cur.fetchall()
|
|
|
|
measured = [row for row in stations_values if not row[3]]
|
|
try:
|
|
measured_max_datetime = max([row[1] for row in measured])
|
|
except:
|
|
return []
|
|
forecast = [row for row in stations_values if row[1] > measured_max_datetime]
|
|
clear_stations_values = measured + forecast
|
|
|
|
return [
|
|
{
|
|
"station_id": row[0],
|
|
"datetime": row[1],
|
|
"value": row[2],
|
|
"forecast": row[3]
|
|
}
|
|
for row in clear_stations_values
|
|
]
|
|
|
|
|
|
@app.get("/station/{station_id}/{start_datetime}/{end_datetime}")
|
|
async def get_one_station_values(station_id: int, start_datetime: datetime, end_datetime: datetime):
|
|
"""Возращает значения в станции на заданный временной интервал для всех показателей. Для каждого показателя приводиться список значений на каждый час
|
|
в заданном интервале, включая `start_datetime` и не включая `end_datetime`.
|
|
|
|
Использовать дату и время вида 2020-12-31T17:00
|
|
"""
|
|
|
|
cur.execute(
|
|
"""SELECT
|
|
datetime,
|
|
parameter,
|
|
value
|
|
FROM stations_all_params
|
|
WHERE station_id = :station_id AND datetime >= strftime('%s', :start_datetime) AND datetime < strftime('%s', :end_datetime)
|
|
""",
|
|
{
|
|
"station_id": station_id,
|
|
"start_datetime": start_datetime,
|
|
"end_datetime": end_datetime
|
|
}
|
|
)
|
|
|
|
one_station_values = cur.fetchall()
|
|
|
|
return {
|
|
"station_id": station_id,
|
|
"datetime": set([row[0] for row in one_station_values]),
|
|
"co": [row[2] for row in one_station_values if row[1] == 1],
|
|
"no2": [row[2] for row in one_station_values if row[1] == 2],
|
|
"no": [row[2] for row in one_station_values if row[1] == 3],
|
|
"pm10": [row[2] for row in one_station_values if row[1] == 4],
|
|
"pm25": [row[2] for row in one_station_values if row[1] == 5]
|
|
}
|
|
|
|
@app.get("/stations/dates")
|
|
async def get_stations_dates():
|
|
"""Возращает минимальную и максимальную даты, которые есть в таблице сетки.
|
|
"""
|
|
|
|
cur.execute(
|
|
f"""SELECT
|
|
MIN(datetime), MAX(datetime)
|
|
FROM stations_all_params
|
|
"""
|
|
)
|
|
|
|
stations_dates = cur.fetchall()
|
|
return(stations_dates[0])
|
|
|
|
|
|
@app.get("/basenet")
|
|
async def get_basenet_geo():
|
|
"""Возращает центры ячеек и ближайшую станцию, соответствующую каждой ячейке
|
|
"""
|
|
|
|
cur.execute(
|
|
"""SELECT
|
|
grid_id,
|
|
lat,
|
|
lon,
|
|
station_id
|
|
FROM basenet
|
|
"""
|
|
)
|
|
|
|
basenet = cur.fetchall()
|
|
|
|
return [
|
|
{
|
|
"grid_id": row[0],
|
|
"lat": row[1],
|
|
"lon": row[2],
|
|
"station_id": row[3]
|
|
}
|
|
for row in basenet
|
|
]
|
|
|
|
|
|
@app.get("/net/{parameter}/{start_datetime}/{end_datetime}")
|
|
async def get_net_parameter_values(parameter: ParameterName, start_datetime: datetime, end_datetime: datetime):
|
|
"""Возращает значения ячеек на заданный временной интервал для выбранного показателя. Для каждого показателя приводиться список значений на каждый час
|
|
в заданном интервале, включая `start_datetime` и не включая `end_datetime`.
|
|
|
|
Использовать дату и время вида 2020-12-31T17:00 (пока есть данные только для 2020-12-31 и 2021-01-01)
|
|
"""
|
|
|
|
cur.execute(
|
|
"""SELECT
|
|
grid_id,
|
|
datetime,
|
|
param_value,
|
|
forecast
|
|
FROM net_all_params
|
|
JOIN parameters ON net_all_params.parameter = parameters.parameter_id
|
|
WHERE parameter_name = :parameter AND datetime >= strftime('%s', :start_datetime) AND datetime < strftime('%s', :end_datetime)
|
|
""",
|
|
{
|
|
"parameter": parameter,
|
|
"start_datetime": start_datetime,
|
|
"end_datetime": end_datetime
|
|
}
|
|
)
|
|
|
|
net_values = cur.fetchall()
|
|
|
|
measured = [row for row in net_values if not row[3]]
|
|
try:
|
|
measured_max_datetime = max([row[1] for row in measured])
|
|
except:
|
|
[]
|
|
forecast = [row for row in net_values if row[1] > measured_max_datetime]
|
|
clear_net_values = measured + forecast
|
|
|
|
return [
|
|
{
|
|
"grid_id": row[0],
|
|
"datetime": row[1],
|
|
"value": row[2],
|
|
"forecast": row[3]
|
|
}
|
|
for row in clear_net_values
|
|
]
|
|
|
|
@app.get("/net/dates")
|
|
async def get_net_dates():
|
|
"""Возращает минимальную и максимальную даты, которые есть в таблице сетки.
|
|
"""
|
|
|
|
cur.execute(
|
|
f"""SELECT
|
|
MIN(datetime), MAX(datetime)
|
|
FROM net_all_params
|
|
"""
|
|
)
|
|
|
|
net_dates = cur.fetchall()
|
|
return(net_dates[0]) |