152 lines
4.2 KiB
Python
Executable File
152 lines
4.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import base64
|
|
import json
|
|
import sys
|
|
import urllib.error
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
|
|
BASE_URL = "http://127.0.0.1:3000"
|
|
DASHBOARD_UID = "ucepsa-edge-oee-machine"
|
|
|
|
|
|
def read_env(path=".env"):
|
|
env = {}
|
|
p = Path(path)
|
|
if not p.exists():
|
|
return env
|
|
for raw in p.read_text().splitlines():
|
|
line = raw.strip()
|
|
if not line or line.startswith("#") or "=" not in line:
|
|
continue
|
|
key, value = line.split("=", 1)
|
|
env[key.strip()] = value.strip().strip('"').strip("'")
|
|
return env
|
|
|
|
|
|
env = read_env()
|
|
user = env.get("GRAFANA_ADMIN_USER", "admin")
|
|
password = env.get("GRAFANA_ADMIN_PASSWORD")
|
|
|
|
if not password:
|
|
print("ERROR: no encuentro GRAFANA_ADMIN_PASSWORD en .env", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
token = base64.b64encode(f"{user}:{password}".encode()).decode()
|
|
|
|
|
|
def api(method, path, payload=None):
|
|
data = None
|
|
headers = {
|
|
"Authorization": f"Basic {token}",
|
|
"Content-Type": "application/json",
|
|
"Accept": "application/json",
|
|
}
|
|
|
|
if payload is not None:
|
|
data = json.dumps(payload).encode("utf-8")
|
|
|
|
req = urllib.request.Request(
|
|
BASE_URL + path,
|
|
data=data,
|
|
headers=headers,
|
|
method=method,
|
|
)
|
|
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=30) as resp:
|
|
body = resp.read().decode("utf-8")
|
|
return json.loads(body) if body else {}
|
|
except urllib.error.HTTPError as e:
|
|
print("HTTP ERROR:", e.code, e.read().decode("utf-8"), file=sys.stderr)
|
|
raise
|
|
|
|
|
|
def all_panels(panels):
|
|
out = []
|
|
for p in panels or []:
|
|
out.append(p)
|
|
out.extend(all_panels(p.get("panels", [])))
|
|
return out
|
|
|
|
|
|
doc = api("GET", f"/api/dashboards/uid/{DASHBOARD_UID}")
|
|
dashboard = doc["dashboard"]
|
|
meta = doc.get("meta", {})
|
|
|
|
changed = 0
|
|
|
|
for panel in all_panels(dashboard.get("panels", [])):
|
|
title = panel.get("title", "")
|
|
|
|
if title == "Nº paros":
|
|
panel["title"] = "Nº paros en rango"
|
|
changed += 1
|
|
|
|
elif title == "Minutos paro":
|
|
panel["title"] = "Minutos paro en rango"
|
|
changed += 1
|
|
|
|
elif title == "Coste paros":
|
|
panel["title"] = "Coste paros en rango"
|
|
changed += 1
|
|
|
|
elif title == "Duración media":
|
|
panel["title"] = "Duración media en rango"
|
|
changed += 1
|
|
|
|
elif title == "Pareto causas de paro":
|
|
panel["title"] = "Pareto causas clasificadas"
|
|
for target in panel.get("targets", []):
|
|
target["rawSql"] = """
|
|
SELECT
|
|
cause_name AS "Causa",
|
|
ROUND(SUM(duration_min)::numeric, 2) AS "Minutos",
|
|
COUNT(*) AS "Nº paros",
|
|
ROUND(SUM(cost_eur)::numeric, 2) AS "Coste €"
|
|
FROM mv_reports_ucepsa_demo.machine_stops_grafana
|
|
WHERE machine_id = '$machine_id'
|
|
AND classification_status = 'CLASSIFIED'
|
|
GROUP BY cause_name
|
|
ORDER BY SUM(duration_min) DESC
|
|
LIMIT 10
|
|
"""
|
|
target["format"] = "table"
|
|
changed += 1
|
|
|
|
elif title == "Paros pendientes de clasificación":
|
|
# Dejamos este panel sin filtro temporal: es backlog operativo.
|
|
for target in panel.get("targets", []):
|
|
target["rawSql"] = """
|
|
SELECT
|
|
id AS "ID",
|
|
started_at AS "Inicio",
|
|
ROUND(duration_min::numeric, 2) AS "Min",
|
|
cost_eur AS "Coste €",
|
|
status AS "Estado",
|
|
classification_status AS "Clasificación",
|
|
cause_name AS "Causa",
|
|
operator_note AS "Nota operario"
|
|
FROM mv_reports_ucepsa_demo.machine_stops_grafana
|
|
WHERE machine_id = '$machine_id'
|
|
AND classification_status = 'PENDING'
|
|
ORDER BY started_at DESC
|
|
"""
|
|
changed += 1
|
|
|
|
payload = {
|
|
"dashboard": dashboard,
|
|
"overwrite": True,
|
|
"message": "Fix stop report pareto and clarify time-scoped panels",
|
|
}
|
|
|
|
if meta.get("folderUid"):
|
|
payload["folderUid"] = meta["folderUid"]
|
|
|
|
result = api("POST", "/api/dashboards/db", payload)
|
|
|
|
print(f"Paneles modificados: {changed}")
|
|
print("Dashboard actualizado:")
|
|
print(BASE_URL + result.get("url", f"/d/{DASHBOARD_UID}"))
|