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.

278 lines
7.7 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()
return [
{
"station_id": row[0],
"datetime": row[1],
"value": row[2],
"forecast": row[3]
}
for row in 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):
"""Возращает значения в станции на заданный временной интервал для всех показателей.
Использовать дату и время вида 2020-12-31T17:00
"""
# Wide form
cur.execute(
"""SELECT
datetime,
GROUP_CONCAT(CASE WHEN "parameter" == 1 THEN value END) as co,
GROUP_CONCAT(CASE WHEN "parameter" == 2 THEN value END) as no2,
GROUP_CONCAT(CASE WHEN "parameter" == 3 THEN value END) as no,
GROUP_CONCAT(CASE WHEN "parameter" == 4 THEN value END) as pm10,
GROUP_CONCAT(CASE WHEN "parameter" == 5 THEN value END) as pm25,
forecast
FROM
stations_all_params
WHERE
station_id = :station_id
AND datetime >= strftime('%s', :start_datetime)
AND datetime < strftime('%s', :end_datetime)
GROUP BY datetime
""",
{
"station_id": station_id,
"start_datetime": start_datetime,
"end_datetime": end_datetime
}
)
one_station_values = cur.fetchall()
return [
{
"station_id": station_id,
"datetime": row[0],
"co": row[1],
"no2": row[2],
"no": row[3],
"pm10": row[4],
"pm25": row[5],
"forecast": row[6]
}
for row in one_station_values
]
@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()
return [
{
"grid_id": row[0],
"datetime": row[1],
"value": row[2],
"forecast": row[3]
}
for row in 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])