Skip to content

energie_gestes

energie_gestes

Ce que le mode gestes COÛTE, et comment il cesse de le coûter (§83).

Spatial Mesh, gestes — 25 août 2026. Le §78 dit qu'une caméra ne guette pas en permanence, et quatre chemins d'extinction le tiennent déjà. Le §83 dit autre chose : même armée, la caméra ne doit pas coûter le même prix selon qu'on s'en sert ou non.

Jusqu'ici la cadence était figée à douze images par seconde, du premier instant au désarmement. Armer le mode et aller lire un document, c'était douze captures, douze encodages JPEG et douze appels à Vision par seconde, pendant dix minutes, pour filmer une chaise.

Quatre états, et un seul chiffre en sort — la cadence que l'interface doit appliquer. C'est le SERVEUR qui décide, parce qu'il est le seul à savoir si une main a été vue ; l'interface obéit et ne devine rien.

Ce que ce module refuse de faire : baisser la cadence pendant qu'une main est suivie. Le geste se mesure en IMAGES (« ≤ 10 images pour un attraper », figé par un test), donc une cadence qui tombe au milieu d'un geste allonge ce geste en secondes sans que personne l'ait demandé. On économise entre les gestes, jamais pendant.

Functions:

etat_energie

etat_energie(
    *,
    armee: bool,
    depuis_derniere_main_s: Optional[float],
    sur_batterie: bool = False,
    batterie_pct: Optional[int] = None,
) -> Energie

L'état d'énergie, à partir de ce qui est CONSTATÉ.

depuis_derniere_main_s vaut None tant qu'aucune main n'a jamais été vue : une session qu'on vient d'armer n'est pas « active », elle attend.

Source code in src/diapason/desktop/energie_gestes.py
def etat_energie(
    *,
    armee: bool,
    depuis_derniere_main_s: Optional[float],
    sur_batterie: bool = False,
    batterie_pct: Optional[int] = None,
) -> Energie:
    """L'état d'énergie, à partir de ce qui est CONSTATÉ.

    ``depuis_derniere_main_s`` vaut None tant qu'aucune main n'a jamais été
    vue : une session qu'on vient d'armer n'est pas « active », elle attend.
    """
    if not armee:
        return Energie.ETEINT

    # UNE MAIN SUIVIE PRIME SUR TOUT, batterie faible comprise.
    #
    # L'en-tête de ce module déclare : « Ce que ce module refuse de faire :
    # baisser la cadence pendant qu'une main est suivie. » La batterie était
    # pourtant consultée EN PREMIER, donc à 18 % un geste en cours tombait de
    # douze à deux images par seconde — et le geste casse, puisqu'il se
    # mesure en IMAGES (« ≤ 10 images pour un attraper », figé par un test) et
    # non en secondes. Le module faisait le contraire de ce qu'il annonçait
    # (constaté le 26 août 2026).
    #
    # Ce que cela coûte est borné : un geste dure quelques secondes, pas la
    # session. Ce que l'inverse coûtait ne l'était pas — un geste qui échoue
    # se recommence, à pleine cadence, autant de fois qu'il échoue.
    suivie = (
        depuis_derniere_main_s is not None
        and depuis_derniere_main_s <= SANS_MAIN_AVANT_VEILLE_S
    )
    if suivie:
        return Energie.ACTIF

    if sur_batterie and batterie_pct is not None and batterie_pct <= BATTERIE_BASSE_PCT:
        return Energie.ECONOMIE
    return Energie.PRET

cadence

cadence(etat: Energie, *, pointeur: bool = False) -> int

Les images par seconde que l'interface doit appliquer.

Source code in src/diapason/desktop/energie_gestes.py
def cadence(etat: Energie, *, pointeur: bool = False) -> int:
    """Les images par seconde que l'interface doit appliquer."""
    if pointeur and etat is Energie.ACTIF:
        return CADENCE_POINTEUR
    return {
        Energie.ETEINT: 0,
        Energie.PRET: CADENCE_PRETE,
        Energie.ACTIF: CADENCE_ACTIVE,
        Energie.ECONOMIE: CADENCE_ECONOMIE,
    }[etat]

batterie

batterie(
    *, maintenant: Optional[float] = None
) -> Optional[tuple[int, bool]]

(pourcentage, sur batterie) — en cache, ou None si illisible.

Source code in src/diapason/desktop/energie_gestes.py
def batterie(*, maintenant: Optional[float] = None) -> Optional[tuple[int, bool]]:
    """(pourcentage, sur batterie) — en cache, ou None si illisible."""
    global _batterie_vue
    maintenant = time.monotonic() if maintenant is None else maintenant
    if (
        _batterie_vue is not None
        and maintenant - _batterie_vue[0] < _RELECTURE_BATTERIE_S
    ):
        return _batterie_vue[1]
    try:
        from diapason.heartbeat.tick import lire_batterie

        mesure = lire_batterie()
    except Exception:  # noqa: BLE001 - une machine sans batterie n'est pas en panne
        mesure = None
    _batterie_vue = (maintenant, mesure)
    return mesure

oublier_la_batterie

oublier_la_batterie() -> None

Vider le cache — pour les tests, et pour un réveil de veille.

Source code in src/diapason/desktop/energie_gestes.py
def oublier_la_batterie() -> None:
    """Vider le cache — pour les tests, et pour un réveil de veille."""
    global _batterie_vue
    _batterie_vue = None