# -*- coding: utf-8 -*-
##############################################################################
# LICENSE
#
# This file is part of mss_dataserver.
#
# If you use mss_dataserver in any program or publication, please inform and
# acknowledge its authors.
#
# mss_dataserver is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# mss_dataserver is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with mss_dataserver. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2020 Stefan Mertl
##############################################################################
''' Pydantic data validation models.
The validation models are used to validate the data messages
sent and received using the websocket interface.
'''
import enum
import pydantic
from pydantic import (
confloat,
constr,
PositiveInt,
PositiveFloat,
validator
)
from typing import (
Dict,
List,
Optional,
Union,
)
[docs]class Event(pydantic.BaseModel):
''' The Event validation model.
'''
db_id: Union[None, PositiveInt]
public_id: constr(regex=r'^\w+_\w+_\d{4}-\d{2}-\d{2}T\d{6,12}')
start_time: constr(min_length=19, max_length=26)
end_time: constr(min_length=19, max_length=26)
length: confloat(ge=0)
max_pgv: PositiveFloat
num_detections: PositiveInt
triggered_stations: List[constr(regex=r'^\w{1,10}:\w{1,10}:\w{1,4}')]
description: Optional[constr(max_length=255)] = None
comment: Optional[constr(max_length=255)] = None
state: Optional[constr(max_length=20)] = None
[docs]class MsgClassEnum(str, enum.Enum):
''' The websocket message class enumeration.
'''
control = 'control'
data = 'data'
soh = 'soh'
request = 'request'
cancel = 'cancel'
[docs]class MsgControlIdEnum(str, enum.Enum):
''' The control message id enumeration.
'''
mode = 'mode'
[docs]class MsgRequestIdEnum(str, enum.Enum):
''' The request message id enumeration.
'''
event_supplement = 'event_supplement'
pgv_timeseries = 'pgv_timeseries'
[docs]class MsgCancelIdEnum(str, enum.Enum):
''' The cancel message id enumeration.
'''
pgv_timeseries = 'pgv_timeseries'
[docs]class MsgSohIdEnum(str, enum.Enum):
''' The SOH message id enumeration.
'''
connection = 'connection'
server_state = 'server_state'
[docs]class MsgDataIdEnum(str, enum.Enum):
''' The data message id enumeration.
'''
current_pgv = 'current_pgv'
pgv_timeseries = 'pgv_timeseries'
pgv_archive = 'pgv_timeseries_archive'
detection_result = 'detection_result'
event_data = 'event_data'
recent_events = 'recent_events'
event_archive = 'event_archive'
event_warning = 'event_warning'
keydata = 'keydata'
event_supplement = 'event_supplement'
station_metadata = 'station_metadata'
[docs]class WSMessage(pydantic.BaseModel):
''' The websocket message model.
'''
header: WSMessageHeader
payload: dict
[docs]class MsgControlModeDataModeEnum(str, enum.Enum):
''' The control:datamode enumeration.
'''
pgv = 'pgv'
keydata = 'keydata'
[docs]class MsgControlModePayload(pydantic.BaseModel):
''' The control:mode message model.
'''
data_mode: MsgControlModeDataModeEnum
[docs]class MsgRequestEventSupplementNameEnum(str, enum.Enum):
''' The request:event_supplement_name enumeration.
'''
pgvstation = 'pgvstation'
pgvvoronoi = 'pgvvoronoi'
simplices = 'simplices'
isoseismalfilledcontours = 'isoseismalfilledcontours'
[docs]class MsgRequestEventSupplementCategoryEnum(str, enum.Enum):
''' The request:event_supplement_category enumeration.
'''
eventpgv = 'eventpgv'
pgvsequence = 'pgvsequence'
detectionsequence = 'detectionsequence'
[docs]class MsgRequestEventSupplementPayload(pydantic.BaseModel):
''' The request:event_supplement message payload model.
'''
public_id: constr(regex=r'^\w+_\w+_\d{4}-\d{2}-\d{2}T\d{6,12}')
selection: List[Dict[str, str]]
[docs] @validator('selection')
def check_selection(cls, v, values):
''' Check if the dictionary contains valid category and name entries.
'''
for cur_supp_name in v:
keys = list(cur_supp_name.keys())
if sorted(keys) != ['category', 'name']:
raise ValueError('Wrong dictionary keys for the supplement name.')
return v
[docs]class MsgRequestPgvTimeseriesPayload(pydantic.BaseModel):
''' The request:pgv_timeseries message payload model.
'''
nsl_code: constr(regex=r'^\w{1,10}:\w{1,10}:\w{1,4}')
[docs]class MsgCancelPgvTimeseriesPayload(pydantic.BaseModel):
''' The cancel:pgv_timeseries message payload model.
'''
nsl_code: constr(regex=r'^\w{1,10}:\w{1,10}:\w{1,4}')