DOCS/outputs/mnaha/seed/step8_devices.py
Thomas Fransolet d14f151517 Livrables de presentation, seed de demo MNAHA et wireframes
- outputs/platform, outputs/prospect : scripts de construction des decks
  commerciaux + captures sources et .pptx generes.
- outputs/mnaha : seed complet de l'instance de demo luxembourgeoise
  (scripts par etape, contenus, images generees), le deck en version
  marque blanche et en version brandee, le PDF de presentation.
- outputs/Wireframes : maquettes app mobile, app web et manager.
- interview clients : notes de l'entretien Fourneau St Michel.

state.json et les __pycache__ sont ignores : le premier porte les cles
d'API de l'instance seedee, les scripts le regenerent.
2026-09-11 15:47:57 +02:00

93 lines
3.4 KiB
Python

# -*- coding: utf-8 -*-
"""Étape 8 — parc de bornes.
Trois tablettes déclarées, avec leur état de connexion, leur batterie et leur
version : c'est ce que montre l'écran « Applications → Kiosk » du back-office.
Chaque appareil est ensuite rattaché au lien de configuration de son site, sans
quoi les cartes de l'écran restent « aucune tablette appairée ».
"""
import json
from datetime import datetime, timedelta, timezone
from pathlib import Path
from api import Api
STATE = Path(__file__).resolve().parent / "state.json"
DEVICES = [
{"site": "feschmaart", "name": "Fëschmaart — hall d'accueil",
"identifier": "MNAHA-FM-01", "wlan": "192.168.20.41", "eth": "10.0.20.41",
"battery": "94", "connection": "excellent", "version": "3.4.1",
"connected": True, "seen_minutes": 2},
{"site": "feschmaart", "name": "Fëschmaart — salles d'archéologie",
"identifier": "MNAHA-FM-02", "wlan": "192.168.20.42", "eth": "",
"battery": "61", "connection": "bon", "version": "3.4.1",
"connected": True, "seen_minutes": 7},
{"site": "draieechelen", "name": "Dräi Eechelen — billetterie",
"identifier": "MNAHA-DE-01", "wlan": "192.168.30.11", "eth": "10.0.30.11",
"battery": "18", "connection": "faible", "version": "3.3.8",
"connected": False, "seen_minutes": 1490},
]
def utc(dt):
return dt.strftime("%Y-%m-%dT%H:%M:%SZ")
def main():
api = Api()
state = json.loads(STATE.read_text(encoding="utf-8"))
instance_id = state["instanceId"]
now = datetime.now(timezone.utc)
existing = {d["identifier"]: d
for d in (api.get(f"/api/Device?instanceId={instance_id}") or [])}
created = {}
for spec in DEVICES:
seen = now - timedelta(minutes=spec["seen_minutes"])
body = {
"instanceId": instance_id,
"identifier": spec["identifier"],
"name": spec["name"],
"configurationId": state["configs"][spec["site"]],
"ipAddressWLAN": spec["wlan"],
"ipAddressETH": spec["eth"],
"connected": spec["connected"],
"batteryLevel": spec["battery"],
"lastBatteryLevel": utc(seen),
"connectionLevel": spec["connection"],
"lastConnectionLevel": utc(seen),
"appVersion": spec["version"],
"lastSeen": utc(seen),
}
if spec["identifier"] in existing:
body["id"] = existing[spec["identifier"]]["id"]
device = api.put("/api/Device", body)
print(f" ~ {spec['name']}")
else:
device = api.post("/api/Device", body)
print(f" + {spec['name']}")
created[spec["identifier"]] = device["id"] if device else \
existing[spec["identifier"]]["id"]
# Rattachement aux liens de configuration de l'application borne.
kiosk_id = state["apps"]["kiosk"]
links = api.get(f"/api/ApplicationInstance/{kiosk_id}/application-link") or []
by_config = {l["configurationId"]: l for l in links}
for spec in DEVICES:
link = by_config.get(state["configs"][spec["site"]])
if not link or link.get("deviceId"):
continue
link["deviceId"] = created[spec["identifier"]]
api.put("/api/ApplicationInstance/application-link", link)
print(f" lien borne {spec['site']} <- {spec['identifier']}")
print("\nétape 8 terminée")
if __name__ == "__main__":
main()