From b986da5fef7bc218f902eaef10b2c0e4e78b55ae Mon Sep 17 00:00:00 2001 From: "Kasper D. Fischer" Date: Fri, 21 Mar 2025 17:43:41 +0100 Subject: [PATCH 1/4] [minor] fixed some typos and missing import --- README.md | 34 +++++++++++++++++----------------- survBot.py | 18 +++++++++--------- utils.py | 3 ++- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 48bbc3c..3eb633f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ version: 0.2 survBot is a small program used to track station quality channels of DSEBRA stations via PowBox output over SOH channels - by analysing contents of a Seiscomp3 datapath. + by analyzing contents of a Seiscomp data archive. ## Requirements @@ -60,33 +60,33 @@ The directory `/path/to/conf-dir` should contain the `parameters.yaml` file, and The e-mail server settings can be configured in the `parameters.yaml` file. The following settings are available: -- `mailserver`: the address of the mail server -- `auth_type`: the authentication type for the mail server (`None`, `SSL`, `TLS`) -- `port`: the port of the mail server -- `user`: the username for the mail server (if required) -- `password`: the password for the mail server (if required) +* `mailserver`: the address of the mail server +* `auth_type`: the authentication type for the mail server (`None`, `SSL`, `TLS`) +* `port`: the port of the mail server +* `user`: the username for the mail server (if required) +* `password`: the password for the mail server (if required) -The `user` and `password` fields are optional, and can be left empty if the mail server does not require authentication. The `auth_type` field can be set to `None` if no authentication is required, `SSL` if the mail server requires SSL authentication, or `TLS` if the mail server requires TLS authentication. If the `user` or `password` fileds are set to `Docker` ore `ENV` the program will try to read the values from the docker secrets `mail_user` and `mail_password` or environment variables `MAIL_USER` and `MAIL_PASSWORD` respectively. Docker secrets are only available in Docker Swarm mode, i.e. if the program is run as a service. +The `user` and `password` fields are optional, and can be left empty if the mail server does not require authentication. The `auth_type` field can be set to `None` if no authentication is required, `SSL` if the mail server requires SSL authentication, or `TLS` if the mail server requires TLS authentication. If the `user` or `password` fields are set to `Docker` ore `ENV` the program will try to read the values from the docker secrets `mail_user` and `mail_password` or environment variables `MAIL_USER` and `MAIL_PASSWORD` respectively. Docker secrets are only available in Docker Swarm mode, i.e. if the program is run as a service. ## Version Changes ### 0.2 -- surveillance of mass, clock and gaps -- individual mailing lists for different stations -- html mail with recent status information -- updated web page design -- restructured parameter file -- recognize if PBox is disconnected +* surveillance of mass, clock and gaps +* individual mailing lists for different stations +* html mail with recent status information +* updated web page design +* restructured parameter file +* recognize if PBox is disconnected ### 0.2-docker -- added Dockerfile for easy deployment -- added more settings for connection to a mail server +* added Dockerfile for easy deployment +* added more settings for connection to a mail server ## Staff -Original author: M.Paffrath (marcel.paffrath@rub.de) -Contributions by: Kasper D. Fischer (kasper.fischer@rub.de) +Original author: M.Paffrath () +Contributions: Kasper D. Fischer () Jan 2025 diff --git a/survBot.py b/survBot.py index 2d5fef5..bd4fe70 100755 --- a/survBot.py +++ b/survBot.py @@ -234,7 +234,7 @@ class SurveillanceBot(object): self.gaps = self.dataStream.get_gaps(min_gap=self.parameters['THRESHOLDS'].get('min_gap')) self.dataStream.merge() - # organise data in dictionary with key for each station + # organize data in dictionary with key for each station for trace in self.dataStream: nwst_id = get_nwst_id(trace) if not nwst_id in self.data.keys(): @@ -351,7 +351,7 @@ class SurveillanceBot(object): first_exec = False def console_print(self, itemlist, str_len=21, sep='|', seplen=3): - assert len(sep) <= seplen, f'Make sure seperator has less than {seplen} characters' + assert len(sep) <= seplen, f'Make sure separator has less than {seplen} characters' sl = sep.ljust(seplen) sr = sep.rjust(seplen) string = sl @@ -1299,7 +1299,7 @@ class StationQC(object): # Warn in case of voltage under OK-level (1V) if len(under) > 0: - # try calculate number of occurences from gaps between indices + # try calculate number of occurrences from gaps between indices n_occurrences = len(np.where(np.diff(under) > 1)[0]) + 1 voltage_dict[-1] = under self.status_other(detailed_message=f'Trace {trace.get_id()}: ' @@ -1395,15 +1395,15 @@ class StatusOK(Status): class StatusWarn(Status): - def __init__(self, message='WARN', count=1, last_occurence=None, detailed_messages=None, show_count=False): - super(StatusWarn, self).__init__(message=message, count=count, last_occurrence=last_occurence, + def __init__(self, message='WARN', count=1, last_occurrence=None, detailed_messages=None, show_count=False): + super(StatusWarn, self).__init__(message=message, count=count, last_occurrence=last_occurrence, detailed_messages=detailed_messages, show_count=show_count) self.set_warn() class StatusError(Status): - def __init__(self, message='FAIL', count=1, last_occurence=None, detailed_messages=None, show_count=False): - super(StatusError, self).__init__(message=message, count=count, last_occurrence=last_occurence, + def __init__(self, message='FAIL', count=1, last_occurrence=None, detailed_messages=None, show_count=False): + super(StatusError, self).__init__(message=message, count=count, last_occurrence=last_occurrence, detailed_messages=detailed_messages, show_count=show_count) self.set_error() self.default_message = message @@ -1420,8 +1420,8 @@ class StatusError(Status): class StatusOther(Status): - def __init__(self, messages=None, count=1, last_occurence=None, detailed_messages=None): - super(StatusOther, self).__init__(count=count, last_occurrence=last_occurence, + def __init__(self, messages=None, count=1, last_occurrence=None, detailed_messages=None): + super(StatusOther, self).__init__(count=count, last_occurrence=last_occurrence, detailed_messages=detailed_messages) if messages is None: messages = [] diff --git a/utils.py b/utils.py index f8364ab..65fe69e 100644 --- a/utils.py +++ b/utils.py @@ -6,6 +6,7 @@ import logging import matplotlib import numpy as np import smtplib +import os from obspy import Stream @@ -174,7 +175,7 @@ def transform_trace(data, transf): elif operator_str == '/': data = data / val else: - raise IOError(f'Unknown arithmethic operator string: {operator_str}') + raise IOError(f'Unknown arithmetic operator string: {operator_str}') return data From 16fbbde3d9c0e3938d5d40e58406ca88902af0ad Mon Sep 17 00:00:00 2001 From: "Kasper D. Fischer" Date: Fri, 21 Mar 2025 17:48:49 +0100 Subject: [PATCH 2/4] [bugfix] fixed call of function connect_to_mail_server --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 65fe69e..3ad80f8 100644 --- a/utils.py +++ b/utils.py @@ -302,7 +302,7 @@ def get_credential(source, param): # return source if no credential was found return source -def connect_to_mail_server(self, mail_params): +def connect_to_mail_server(mail_params): """ Connect to mail server and return server object. """ From fcba73fcc57c1a2de9180d36fd3250dcb2be0bc5 Mon Sep 17 00:00:00 2001 From: "Kasper D. Fischer" Date: Fri, 21 Mar 2025 22:42:23 +0100 Subject: [PATCH 3/4] [bugfix] fix bug in connect_to_mail_server function --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 3ad80f8..057bc74 100644 --- a/utils.py +++ b/utils.py @@ -326,5 +326,5 @@ def connect_to_mail_server(mail_params): else: logging.error('Unknown authentication type. Mails can not be sent') return - s.login(mail_params.get('user'), mail_params.get('password')) + s.login(user, password) return s From 8ac501e8dca0d004f252cf54256e79aef3becf44 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 25 Mar 2025 11:39:17 +0100 Subject: [PATCH 4/4] [update] add parameter to disable PowBox usage for selected stations also to parameters.yaml, updated style sheets for html --- parameters.yaml | 4 +++- stylesheets/desktop.css | 1 - stylesheets/mobile.css | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parameters.yaml b/parameters.yaml index 519fbaa..4b41238 100644 --- a/parameters.yaml +++ b/parameters.yaml @@ -3,7 +3,7 @@ datapath: "/data/SDS/" # SC3 Datapath networks: ["1Y", "HA", "MK"] # select networks, list or str stations: "*" # select stations, list or str locations: "*" # select locations, list or str -stations_blacklist: ["TEST", "EREA", "DOMV", "LFKM", "GR19", "LAKA"] # exclude these stations +stations_blacklist: ["TEST", "EREA", "DOMV", "LFKM", "GR19", "LAKA", "ATHR", "HAVD"] # exclude these stations networks_blacklist: [] # exclude these networks interval: 60 # Perform checks every x seconds n_track: 360 # wait n_track * intervals before performing an action (i.e. send mail/end highlight status) @@ -117,6 +117,8 @@ data_channels: ["HHZ", "HHN", "HHE"] # ---------------------------------------- OPTIONAL PARAMETERS --------------------------------------------------------- +# deactivate powbox surveillance for stations (e.g. for solar powered), key: station, value: status message (abbr.) +no_pbox_stations: {'GR33': 'SOL'} # add links to html table with specified key as column and value as relative link, interpretable string parameters: # nw (e.g. 1Y), st (e.g. GR01A), nwst_id (e.g. 1Y.GR01A) diff --git a/stylesheets/desktop.css b/stylesheets/desktop.css index f25fc28..ba59cfd 100644 --- a/stylesheets/desktop.css +++ b/stylesheets/desktop.css @@ -1,6 +1,5 @@ body { background-color: #ffffff; - place-items: center; text-align: center; padding-bottom: 30px; font-family: "Helvetica", "sans-serif"; diff --git a/stylesheets/mobile.css b/stylesheets/mobile.css index 10701b6..aeeb416 100644 --- a/stylesheets/mobile.css +++ b/stylesheets/mobile.css @@ -1,6 +1,5 @@ body { background-color: #ffffff; - place-items: center; text-align: center; padding-bottom: 30px; font-family: "Helvetica", "sans-serif"; @@ -20,7 +19,7 @@ th { background-color: #999; color: #fff; border-radius: 3px; - padding: 10px, 2px; + padding: 10px 2px; position: sticky; top: 0; }