no hardcode

This commit is contained in:
Mateusz Gruszczyński
2026-02-05 11:01:23 +01:00
parent 0910b4ddb4
commit 9e6d280b05
2 changed files with 57 additions and 40 deletions

68
app.py
View File

@@ -105,24 +105,15 @@ def get_timeseries(phase_id):
if start_param and end_param:
time_filter = f"time >= '{start_param}' AND time <= '{end_param}'"
interval = "1m"
interval = config.DEFAULT_INTERVAL
else:
clean_range = range_param.replace(" ", "")
time_filter = f"time > now() - {clean_range}"
mapping = {
"1h": "10s",
"6h": "30s",
"24h": "2m",
"7d": "10m",
"30d": "30m",
"60d": "1h",
"120d": "2h",
"180d": "4h",
"365d": "6h"
}
interval = mapping.get(range_param, "1m")
if range_param in config.TIME_RANGES:
interval = config.TIME_RANGES[range_param]['interval']
else:
interval = config.DEFAULT_INTERVALk
query = f'''
SELECT mean("value") AS voltage
@@ -152,13 +143,17 @@ def get_events():
end_p = request.args.get('end')
now_utc = datetime.now(timezone.utc)
# Blokada dla zakresów powyżej 61 dni
# Blokada dla zakresów powyżej MAX_EVENT_RANGE_DAYS
if not (start_p and end_p) and "d" in range_p:
try:
days = int(''.join(filter(str.isdigit, range_p)))
if days > 61:
return jsonify({"error": "range_too_large", "message": "Zbyt duży zakres. Zaznacz obszar na wykresie lub wybierz własny zakres."})
except: pass
if days > config.MAX_EVENT_RANGE_DAYS:
return jsonify({
"error": "range_too_large",
"message": f"Zbyt duży zakres. Maksymalnie {config.MAX_EVENT_RANGE_DAYS} dni. Zaznacz obszar na wykresie lub wybierz własny zakres."
})
except:
pass
if start_p and end_p:
dt_view_start = datetime.fromisoformat(start_p.replace('Z', '+00:00'))
@@ -182,7 +177,7 @@ def get_events():
FROM "{config.MEASUREMENT}"
WHERE "entity_id" = '{p_cfg["entity_id"]}'
AND {time_filter}
GROUP BY time(1m) fill(0)
GROUP BY time({config.EVENT_DETECTION_INTERVAL}) fill(0)
'''
result = client.query(query)
points = list(result.get_points())
@@ -197,22 +192,34 @@ def get_events():
v_now = float(val)
ev_type = None
if v_now < 100: ev_type = "zanik"
elif 100 <= v_now < 207: ev_type = "niskie"
elif v_now > 253: ev_type = "wysokie"
# Używamy progów z config.VOLTAGE_THRESHOLDS
if v_now < config.VOLTAGE_THRESHOLDS['outage']:
ev_type = "zanik"
elif config.VOLTAGE_THRESHOLDS['outage'] <= v_now < config.VOLTAGE_THRESHOLDS['min_safe']:
ev_type = "niskie"
elif v_now > config.VOLTAGE_THRESHOLDS['max_safe']:
ev_type = "wysokie"
# else: ev_type = None (wartość w zakresie bezpiecznym 207-253V)
if ev_type:
start_str = points[i]['time']
dt_s = datetime.fromisoformat(start_str.replace('Z', '+00:00'))
j = i
while j + 1 < len(points):
v_next_val = points[j+1].get('volts')
next_type = None
if v_next_val is not None:
v_next = float(v_next_val)
if v_next < 100: next_type = "zanik"
elif 100 <= v_next < 207: next_type = "niskie"
elif v_next > 253: next_type = "wysokie"
# Używamy progów z config.VOLTAGE_THRESHOLDS
if v_next < config.VOLTAGE_THRESHOLDS['outage']:
next_type = "zanik"
elif config.VOLTAGE_THRESHOLDS['outage'] <= v_next < config.VOLTAGE_THRESHOLDS['min_safe']:
next_type = "niskie"
elif v_next > config.VOLTAGE_THRESHOLDS['max_safe']:
next_type = "wysokie"
# else: next_type = None (wartość w zakresie bezpiecznym)
if next_type == ev_type:
j += 1
@@ -224,7 +231,8 @@ def get_events():
duration = (dt_e - dt_s).total_seconds() / 60 + 1
if duration >= 5.1:
# Używamy progu minimalnego czasu trwania z config
if duration >= config.MIN_EVENT_DURATION_MINUTES:
if dt_e >= dt_view_start and dt_s <= dt_view_end:
all_events.append({
"start": start_str,
@@ -235,6 +243,7 @@ def get_events():
})
i = j
i += 1
return jsonify(sorted(all_events, key=lambda x: x['start'], reverse=True))
except Exception as e:
app.logger.error(f"Event Logic Error: {e}")
@@ -242,13 +251,12 @@ def get_events():
finally:
client.close()
@app.route('/api/outages/<int:phase_id>')
@app.route('/api/outages/<phase_id>')
def api_outages(phase_id):
client = get_influx_client()
t_range = request.args.get('range', '24h')
entity_id = config.PHASES[phase_id]['entity_id']
query = f'SELECT "value" FROM "{config.MEASUREMENT}" WHERE "entity_id" = \'{entity_id}\' AND "value" < 10 AND time > now() - {t_range}'
query = f'SELECT "value" FROM "{config.MEASUREMENT}" WHERE "entity_id" = \'{entity_id}\' AND "value" < {config.VOLTAGE_THRESHOLDS["outage_detection"]} AND time > now() - {t_range}'
try:
result = client.query(query)
return jsonify(list(result.get_points()))
@@ -274,4 +282,4 @@ if __name__ == '__main__':
print("="*50 + "\n")
eventlet.spawn(background_voltage_update)
socketio.run(app, host='0.0.0.0', port=config.FLASK_CONFIG['port'])
socketio.run(app, host='0.0.0.0', port=config.FLASK_CONFIG['port'])

View File

@@ -35,25 +35,34 @@ PHASES = {
# Zakresy czasu
TIME_RANGES = {
'1h': {'filter': '1h', 'interval': '10s', 'label': '1h'},
'6h': {'filter': '6h', 'interval': '1m', 'label': '6h'},
'24h': {'filter': '24h', 'interval': '5m', 'label': '24h'},
'7d': {'filter': '7d', 'interval': '30m', 'label': '7d'},
'30d': {'filter': '30d', 'interval': '2h', 'label': '30d'},
'60d': {'filter': '60d', 'interval': '4h', 'label': '60d'},
'120d': {'filter': '120d', 'interval': '8h', 'label': '120d'},
'180d': {'filter': '180d', 'interval': '12h', 'label': '6m'},
'365d': {'filter': '365d', 'interval': '1d', 'label': '1r'}
'6h': {'filter': '6h', 'interval': '30s', 'label': '6h'},
'24h': {'filter': '24h', 'interval': '2m', 'label': '24h'},
'7d': {'filter': '7d', 'interval': '10m', 'label': '7d'},
'30d': {'filter': '30d', 'interval': '30m', 'label': '30d'},
'60d': {'filter': '60d', 'interval': '1h', 'label': '60d'},
'120d': {'filter': '120d', 'interval': '2h', 'label': '120d'},
'180d': {'filter': '180d', 'interval': '4h', 'label': '6m'},
'365d': {'filter': '365d', 'interval': '6h', 'label': '1r'}
}
DEFAULT_TIME_RANGE = '6h'
MEASUREMENT = 'V'
# ZAKRES BEZPIECZNY: 207V - 253V
# PROGI NAPIĘCIA
VOLTAGE_THRESHOLDS = {
'min_safe': 207,
'max_safe': 253
'outage': 100, # < 100V = zanik
'min_safe': 207, # Dolny próg bezpieczny
'max_safe': 253, # Górny próg bezpieczny
'outage_detection': 10 # Próg dla api_outages
}
# PARAMETRY WYKRYWANIA EVENTÓW
MAX_EVENT_RANGE_DAYS = 61
MIN_EVENT_DURATION_MINUTES = 5.1
EVENT_DETECTION_INTERVAL = '1m'
DEFAULT_INTERVAL = '1m'
# Skalowanie
GAUGE_CONFIG = {'min': 190, 'max': 270}
CHART_CONFIG = {'y_min': 190, 'y_max': 270, 'update_interval': 2000}