121 lines
3.8 KiB
Python
121 lines
3.8 KiB
Python
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
VALID_ICONS = {
|
|
"detector-smoke",
|
|
"detector-heat",
|
|
"module-input",
|
|
"siren",
|
|
"panel-nfs320",
|
|
}
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(description="Gera bundle versionavel de planta baixa para o Grafana")
|
|
parser.add_argument("spec", help="Arquivo JSON com o mapa da planta")
|
|
parser.add_argument(
|
|
"--output",
|
|
help="Arquivo de saida. Default: mesmo nome com sufixo .bundle.json",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def validate_item(item: dict, seen_ids: set[str]) -> dict:
|
|
item_id = str(item.get("id", "")).strip()
|
|
if not item_id:
|
|
raise ValueError("Cada item precisa de id.")
|
|
if item_id in seen_ids:
|
|
raise ValueError(f"Item duplicado: {item_id}")
|
|
seen_ids.add(item_id)
|
|
|
|
icon = str(item.get("icon", "")).strip()
|
|
if icon not in VALID_ICONS:
|
|
raise ValueError(f"Icone invalido para item {item_id}: {icon}")
|
|
|
|
label = str(item.get("label", "")).strip()
|
|
item_key = str(item.get("item_key", "")).strip()
|
|
if not label:
|
|
raise ValueError(f"Label obrigatorio para item {item_id}.")
|
|
if not item_key:
|
|
raise ValueError(f"item_key obrigatorio para item {item_id}.")
|
|
|
|
for field in ("x", "y", "width", "height"):
|
|
value = item.get(field)
|
|
if not isinstance(value, int) or value < 0:
|
|
raise ValueError(f"Campo {field} invalido para item {item_id}.")
|
|
|
|
rotation = item.get("rotation", 0)
|
|
if not isinstance(rotation, int):
|
|
raise ValueError(f"rotation invalido para item {item_id}.")
|
|
|
|
return {
|
|
"id": item_id,
|
|
"label": label,
|
|
"item_key": item_key,
|
|
"icon": icon,
|
|
"x": item["x"],
|
|
"y": item["y"],
|
|
"width": item["width"],
|
|
"height": item["height"],
|
|
"rotation": rotation,
|
|
}
|
|
|
|
|
|
def build_bundle(spec: dict) -> dict:
|
|
title = str(spec.get("title", "")).strip()
|
|
dashboard_uid = str(spec.get("grafana_dashboard_uid", "")).strip()
|
|
background_image_url = str(spec.get("background_image_url", "")).strip()
|
|
vfire_base_url = str(spec.get("vfire_base_url", "")).rstrip("/")
|
|
zabbix_host = str(spec.get("zabbix_host", "")).strip()
|
|
|
|
if not title:
|
|
raise ValueError("title obrigatorio.")
|
|
if not dashboard_uid:
|
|
raise ValueError("grafana_dashboard_uid obrigatorio.")
|
|
if not background_image_url:
|
|
raise ValueError("background_image_url obrigatorio.")
|
|
if not vfire_base_url:
|
|
raise ValueError("vfire_base_url obrigatorio.")
|
|
if not zabbix_host:
|
|
raise ValueError("zabbix_host obrigatorio.")
|
|
|
|
raw_items = spec.get("items")
|
|
if not isinstance(raw_items, list) or not raw_items:
|
|
raise ValueError("items deve conter ao menos um elemento.")
|
|
|
|
seen_ids: set[str] = set()
|
|
items = [validate_item(item, seen_ids) for item in raw_items]
|
|
for item in items:
|
|
item["icon_url"] = f"{vfire_base_url}/static/grafana-icons/{item['icon']}.svg"
|
|
item["zabbix_ref"] = {
|
|
"host": zabbix_host,
|
|
"item_key": item["item_key"],
|
|
}
|
|
|
|
return {
|
|
"title": title,
|
|
"grafana_dashboard_uid": dashboard_uid,
|
|
"background_image_url": background_image_url,
|
|
"vfire_base_url": vfire_base_url,
|
|
"zabbix_host": zabbix_host,
|
|
"items": items,
|
|
}
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
spec_path = Path(args.spec)
|
|
output_path = Path(args.output) if args.output else spec_path.with_suffix(".bundle.json")
|
|
|
|
spec = json.loads(spec_path.read_text(encoding="utf-8"))
|
|
bundle = build_bundle(spec)
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(json.dumps(bundle, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
print(output_path)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|