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.
304 lines
8.3 KiB
304 lines
8.3 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("/station/{station_id}/dates")
|
|
async def get_one_station_dates(station_id: int):
|
|
"""Возращает даты, для которых на данной станции есть данные.
|
|
"""
|
|
|
|
# Wide form
|
|
cur.execute(
|
|
"""SELECT
|
|
DISTINCT(date(datetime, 'unixepoch'))
|
|
FROM
|
|
stations_all_params
|
|
WHERE
|
|
station_id = :station_id
|
|
""",
|
|
{
|
|
"station_id": station_id
|
|
}
|
|
)
|
|
|
|
one_station_dates = cur.fetchall()
|
|
|
|
return [
|
|
row[0]
|
|
for row in one_station_dates
|
|
]
|
|
|
|
@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]) |