Entrixy v2 — architecture finale

Validé le 13 avril 2026. Document de travail pour la réalisation.

Sommaire
  1. Confidentialité : le serveur ne sait rien
  2. Quatre types d’objets : appel, URL, appareil (WS), contrôleur BLE
  3. Le webhook (URL) en détail
  4. L’appareil (ESP32 / ESP8266, WebSocket) en détail
  5. Le contrôleur BLE (ESP32) en détail
  6. Déclencheurs : GPS et Wi-Fi
  7. Trois niveaux de confirmation
  8. Propriétaire contre invité — le partage des réglages
  9. L’interface de l’application
  10. Limites de l'offre
  11. Icônes d’objets pour les invités
  12. Prévision de charge
  13. Structure de la base de données
  14. Plan de réalisation

1. Confidentialité : le serveur ne sait rien (par défaut)

La promesse que nous faisons : Nous ne connaissons ni les numéros de nos utilisateurs ni leurs coordonnées

Toutes les données sensibles sont conservées uniquement sur le téléphone. Le propriétaire peut, s’il le souhaite, en faire transiter une partie par le serveur — avec un avertissement explicite.

DonnéesPar défautEn option via le serveur
Coordonnées (lat, lon)Uniquement sur le téléphonePeut être partagé avec les invités (avec avertissement)
Empreinte Wi-Fi (BSSID[])Uniquement sur le téléphoneJamais transmise
URL et secret du webhookUniquement sur le téléphonePeut être stocké sur le serveur (avec avertissement)
Rayon, temps, niveau de confirmationVia le serveur
Une empreinte Wi-Fi vaut des coordonnées. À partir d’un ensemble de BSSID, des services vous localisent à 20–50 m près. L’image Wi-Fi ne transite jamais par le serveur, en aucun cas.

2. Quatre types d’objets

À l’ajout d’un objet, le propriétaire choisit le type de liaison. La fenêtre de réglages de ce type s’ouvre ensuite.

IconNomComment ça marcheFeedbackExample
📞CallUn appel depuis le téléphone du propriétaireAucun (l’appel est parti ou non)Une barrière, un interphone
🌐URL (webhook)Une requête HTTP vers l’adresse de l’appareil, depuis le téléphone ou depuis le serveur EntrixyOui — une réponse JSON avec un statutUne serrure connectée avec API, Tasmota, Shelly Cloud
📟Contrôleur internet (WS)Une commande par WebSocket vers un contrôleur connectéOui — une réponse par le WebSocketESP32 / ESP8266 maison, Shelly Plus 1, NodeMCU
📶Contrôleur BLEUn canal Bluetooth direct entre téléphone et contrôleur, sans internetOui — une réponse par BLE (notify)Un contrôleur sur piles à un portail sans Wi-Fi

Le configurateur de micrologiciel pour les deux derniers types : /controller/ (BLE et Internet, dans le navigateur).

Pour l’utilisateur, tous les types se ressemblent : une carte, un bouton Appeler, un statut. Seul le mécanisme d’acheminement diffère.

3. Le webhook (URL) en détail

Deux modes d’envoi

La fenêtre de réglages du webhook propose un sélecteur, avec les avantages et inconvénients écrits à l’écran :

◉ Depuis le téléphone du propriétaire (par défaut)
La requête part de votre téléphone. L’adresse et le secret de l’appareil restent chez vous — le serveur Entrixy ne les apprend jamais.
Avantage : confidentialité maximale
Inconvénient : votre téléphone doit être en ligne
○ Depuis le serveur Entrixy
C’est notre serveur qui envoie la requête. Cela fonctionne même si votre téléphone est hors ligne.
Avantage : fonctionne sans le téléphone du propriétaire
Inconvénient : l’adresse de l’appareil est stockée sur le serveur

Où vivent les données

ModeOù sont l’URL et le secretLe serveur connaît-il l’URL ?
Depuis le téléphonePrefs sur le téléphone du propriétaireNo
Depuis le serveurLa table numbers dans la base de donnéesYes

Protocole de la requête

Sécurité : une signature HMAC. L’appareil et Entrixy partagent un webhook_secret.

POST https://device-url.com/open
Content-Type: application/json

{
  "action": "open",
  "object_id": 42,
  "timestamp": 1713020000,
  "nonce": "a1b2c3",
  "signature": "hmac-sha256(secret, timestamp + nonce + action)"
}

L’appareil vérifie que la signature est valide, que l’horodatage a moins de 30 secondes et que le nonce n’est pas répété. Si tout va bien, il agit et répond :

{"status": "ok", "message": "Door opened"}
or
{"status": "error", "message": "Lock jammed"}

Le statut est affiché à l’utilisateur dans l’application.

Flux de données (mode téléphone)

The guest presses Call
  → the server receives the request
  → sends it to the owner over the WebSocket: {type: "do_webhook", ...}
  → the owner's phone makes the HTTP call to the device
  → receives the JSON response
  → sends it to the server: {type: "webhook_result", status, message}
  → the server passes it to the guest
  → both see the status in the log

Logging

Dans les deux modes, le journal sur le téléphone du propriétaire et de l’invité consigne qui, quand, quel objet et avec quel statut.

4. L’appareil (ESP32 / ESP8266, WebSocket) en détail

Comment ça marche

Le contrôleur — ESP32, ESP32-S3, ESP32-C3 et ESP8266 sont pris en charge — n’a pas d’IP publique. Il maintient une connexion WebSocket sortante vers le serveur Entrixy, exactement comme le téléphone du propriétaire.

Le micrologiciel et le configurateur vivent à /esp/socket/. Sources : ESP32, ESP8266.

Le protocole WebSocket de l’appareil

// Device → server: connect
{"type": "device_hello", "device_key": "xyz789", "device_secret": "..."}

// Server → device: OK
{"type": "device_ok"}

// Server → device: command
{"type": "device_command", "action": "open", "command_id": "abc123"}

// Device → server: result
{"type": "device_response", "command_id": "abc123", "status": "ok", "message": "Opened"}

Le serveur relaie le statut aux clients — propriétaire et invité — par leurs connexions WebSocket.

Enregistrer un appareil

  1. Dans l’application, le propriétaire choisit Ajouter un objet → type Appareil
  2. Cela génère device_key + device_secret
  3. Un QR code avec les paramètres du micrologiciel s’affiche
  4. L’utilisateur flashe l’ESP32 ou l’ESP8266 (voir le configurator) et l’appareil se connecte à wss://entrixy.com/ws

Indication

La carte de l’objet montre l’état de connexion de l’appareil, en ligne ou hors ligne, comme les invités voient l’état du propriétaire.

4a. Le contrôleur BLE (ESP32) en détail

Comment ça marche

Un contrôleur sur ESP32, S3, C3, C6 ou H2 n’a besoin ni de Wi-Fi ni de serveur pour déclencher. Il dort profondément, se réveille une fois par seconde pendant environ 200 ms et émet une annonce BLE avec un compteur signé. Quand un téléphone détenant une clé valide approche, Android — ou l’application si elle est au premier plan — capte l’annonce, se connecte en GATT, envoie une commande fire avec un nonce à usage unique, et le contrôleur ferme le relais le temps d’une brève impulsion. Pour les motorisations bistables et les serrures, un mode sépare ouvrir et fermer avec suivi de position, où ouvert/fermé voyage sous forme d’octet chiffré dans l’annonce.

Le serveur Entrixy ne participe pas à ce canal. Il n’est nécessaire qu’à la création d’une clé invité : le propriétaire signe un GuestToken et le transmet à l’invité par le canal chiffré de bout en bout. Ensuite l’invité travaille hors ligne.

Le protocole BLE en bref

La spécification complète du protocole, la disposition des bits et les vecteurs de test se trouvent à entrixy.com/ble. Le modèle de menaces figure dans un document séparé.

Quand le BLE l’emporte sur le WebSocket

Quand le WebSocket l’emporte sur le BLE

On peut équiper la même motorisation en BLE et en WebSocket — ils apparaissent comme deux objets distincts dans l’application. Le BLE pour ouvrir de près sans internet, le WebSocket pour les moments où vous êtes loin.

Enregistrer un appareil

  1. Dans l’application, le propriétaire choisit Ajouter un objet → type Contrôleur BLE
  2. L’application scanne les ondes à la recherche d’appareils en mode appairage (nommés entrixy-pair)
  3. Le choix d’un appareil lance un échange ECDH via GATT ; le secret partagé est enregistré dans les Prefs du téléphone et dans la NVS du contrôleur
  4. Ni QR code ni appui sur un bouton — un appareil neuf passe de lui-même en mode appairage une fois le programme chargé

Le micrologiciel et le configurateur vivent à /esp/ble/. Source : /esp32-example/.

Indication

Sur la carte de l’objet : gris signifie invisible dans les ondes, trop loin ou éteint ; orange, visible mais l’automatisme n’a pas déclenché ; vert, déclenché ou en train de déclencher ; gris à contour vert, déclenché récemment et l’on peut toucher pour rouvrir.

Database

CREATE TABLE devices (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  host_id INT UNSIGNED NOT NULL,
  device_key VARCHAR(64) NOT NULL UNIQUE,
  secret_hash VARCHAR(64) NOT NULL,
  label VARCHAR(128) DEFAULT '',
  last_seen DATETIME NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

In server.php un troisième rôle WebSocket s’ajoute : device (aux côtés de host et guest).

5. Déclencheurs : GPS et Wi-Fi

Le GPS et le Wi-Fi fonctionnent indépendamment. Si les deux sont configurés, c’est la condition remplie en premier qui déclenche. La pause commune entre deux déclenchements est de 20 secondes.

GPS — tel qu’aujourd’hui

Wi-Fi — deux modes

Mode 1 : l’image Wi-Fi (empreinte)

Mode 2 : connecté à un réseau

Consommation d’énergie

Stockage (Prefs, ne quitte jamais le téléphone)

wifi_trigger_<actionKey> = {
  "mode": "fingerprint" | "connect",
  "bssids": ["AA:BB:CC:DD:EE:FF", ...],
  "min_match": 5,
  "connect_bssid": "AA:BB:CC:DD:EE:FF",
  "connect_ssid": "TP-Link_5G",
  "enabled": true
}

6. Trois niveaux de confirmation

Le propriétaire décide si une confirmation est requise. La façon de confirmer l’identité relève du client, parmi ce que propose l’appareil.

LevelCe que voit l’utilisateurExample
AutomaticRien — l’objet s’ouvre tout seulBarrières, portails
ConfirmUne notification dans le volet : Ouvrir [objet] ? → une pressionUn garage, un portillon, une protection contre les faux déclenchements
Confirmer l’identitéBiométrie, code PIN du téléphone ou code PIN de l’applicationUne porte d’entrée

Confirmer n’est pas une étape gaspillée. La notification apparaît d’elle-même dans le volet au bon moment. Pas besoin de chercher l’application, de déverrouiller, de trouver l’objet. Une pression et la porte est ouverte.

Priorité des méthodes de confirmation d’identité

  1. Biométrie, si un capteur existe → BiometricPrompt
  2. Le code PIN ou le mot de passe du téléphone, à défaut de biométrie → KeyguardManager
  3. Le code PIN propre à l’application, sur un appareil sans verrouillage → notre propre boîte de dialogue

La fenêtre horaire — un facteur supplémentaire

Le propriétaire définit Heures autorisées : 07:00–23:00 . Hors de cette fenêtre, la condition est ignorée en silence. Un intervalle de nuit fonctionne aussi (22:00–06:00).

Trois facteurs de protection indépendants

  1. WHERE — GPS, une empreinte Wi-Fi ou une connexion
  2. WHO — automatique, confirmation ou biométrie
  3. WHEN — la fenêtre horaire
Une porte d’entrée : empreinte Wi-Fi plus confirmation d’identité plus 07:00–23:00 — plus solide que la plupart des serrures connectées .

7. Propriétaire contre invité — le partage des réglages

SettingPropriétaire (le sien)Propriétaire → invitésInvité
Type d’objetChoosesTransmetReceives
CoordinatesLes fixeEn option (avec avertissement)Les fixe ou les reçoit
Rayon GPSLe fixeTransmetReceives
Empreinte Wi-FiScansNeverScanne lui-même
Correspondances Wi-Fi minimalesLe fixeTransmetReceives
Fenêtre horaireLe fixeTransmetReceives
ConfirmationLe fixeTransmetReceives
GPS activé/désactivéyesyes
Wi-Fi activé/désactivéyesyes

8. L’interface de l’application

Ajouter un objet (SettingsScreen)

La première étape est le choix du type de liaison :

┌────────────────────────────┐
│  Connection type           │
│                            │
│  📞  Call                  │
│  Opening with a phone      │
│  call                      │
│                            │
│  🌐  URL                   │
│  Sending a command to      │
│  a device address          │
│                            │
│  📟  Device                │
│  Connected through Entrixy │
│  (ESP32, Arduino)          │
└────────────────────────────┘

Après le choix, la fenêtre de réglages de ce type s’ouvre.

La carte d’objet dépliée (ActionCard)

┌──────────────────────────────────────────┐
│  Corner barrier             📶 3/5  312m │
│  Mine • ●                                │
├──────────────────────────────────────────┤
│  [Edit]  [Icon]                          │
│  ─────────────────────────               │
│  [📍 Geo]   [📶 Wi-Fi]                   │
└──────────────────────────────────────────┘

La fenêtre 📍 Géo

La fenêtre 📶 Wi-Fi

◉ Par l’image Wi-Fi

○ Par la connexion à un réseau

En dessous : la fenêtre horaire et la confirmation, communes avec Géo

La fenêtre du webhook (🌐 URL)

◉ Depuis le téléphone (par défaut)
L’URL n’est conservée que sur votre téléphone. Le serveur Entrixy ne l’apprend jamais.
Avantage : confidentialité maximale
Inconvénient : votre téléphone doit être en ligne
○ Depuis le serveur Entrixy
C’est le serveur qui envoie la requête. Cela fonctionne sans votre téléphone.
Avantage : fonctionne toujours
Inconvénient : l’adresse de l’appareil est stockée sur le serveur

Indication sur la carte repliée

TriggerIndicator
GPS"312 m"
Empreinte Wi-Fi📶 barres (0–4 selon les correspondances)
Connexion Wi-Fi📶 vert ou gris
Webhook/Device● vert (en ligne) ou gris (hors ligne)

9. Limites de l’offre

Offres internes. Elles ne sont pas montrées à l’utilisateur, mais les limites s’appliquent.

Offre par défautLimit
Objets (numbers)10
Invités (user_keys)10

En cas de dépassement, un message doux : Le nombre d’objets est limité. Contactez le support pour l’augmenter.

CREATE TABLE plans (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(64) NOT NULL,
  max_numbers INT NOT NULL DEFAULT 10,
  max_keys INT NOT NULL DEFAULT 10
);
INSERT INTO plans (name) VALUES ('default');

ALTER TABLE hosts ADD COLUMN plan_id INT UNSIGNED DEFAULT 1;

10. Base de données — l’ensemble des modifications

-- Plans
CREATE TABLE plans (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(64) NOT NULL,
  max_numbers INT NOT NULL DEFAULT 10,
  max_keys INT NOT NULL DEFAULT 10
);
INSERT INTO plans (name) VALUES ('default');

ALTER TABLE hosts ADD COLUMN plan_id INT UNSIGNED DEFAULT 1;

-- Object type and settings
ALTER TABLE numbers
  ADD COLUMN type ENUM('call','webhook','device') DEFAULT 'call',
  ADD COLUMN radius INT DEFAULT 80,
  ADD COLUMN time_from TIME NULL,
  ADD COLUMN time_to TIME NULL,
  ADD COLUMN security_level ENUM('auto','confirm','identity') DEFAULT 'auto',
  ADD COLUMN geo_available TINYINT(1) DEFAULT 1,
  ADD COLUMN wifi_available TINYINT(1) DEFAULT 1,
  ADD COLUMN wifi_min_match INT DEFAULT 5,
  ADD COLUMN share_lat DOUBLE NULL,
  ADD COLUMN share_lon DOUBLE NULL,
  ADD COLUMN webhook_url VARCHAR(512) NULL,
  ADD COLUMN webhook_secret VARCHAR(64) NULL,
  ADD COLUMN webhook_mode ENUM('phone','server') DEFAULT 'phone',
  ADD COLUMN device_id INT UNSIGNED NULL;

-- Devices (ESP32)
CREATE TABLE devices (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  host_id INT UNSIGNED NOT NULL,
  device_key VARCHAR(64) NOT NULL UNIQUE,
  secret_hash VARCHAR(64) NOT NULL,
  label VARCHAR(128) DEFAULT '',
  last_seen DATETIME NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

share_lat / share_lon — renseignés seulement si le propriétaire a activé Partager les coordonnées avec les invités .

webhook_url / webhook_secret — renseignés uniquement en mode serveur. En mode téléphone, ils vivent dans les Prefs.

11. Icônes d’objets pour les invités

Le propriétaire attribue une icône personnalisée à un objet et l’invité doit la voir. Mais l’icône n’est pas stockée sur le serveur — le serveur joue les facteurs : il livre et oublie.

Préparation du côté du propriétaire

À sa définition, l’icône est aussitôt réduite à 64×64 PNG (environ 3–5 Ko) et conservée localement dans les Prefs ou dans un fichier.

Comment elle voyage

1. The guest connects
   → guest_ok carries has_avatar: true for objects that have an icon

2. The guest client checks: has_avatar=true but no icon locally?
   → Yes → it asks the server

3. The server has no icon
   → it asks the owner over the WebSocket: {type: "avatar_request", number_id: 42}

4. The owner's phone
   → reads the local file
   → sends: {type: "avatar_data", number_id: 42, data: "base64..."}

5. The server passes it to the guest
   → {type: "avatar_data", number_id: 42, data: "base64..."}

6. The guest stores it locally and never asks again

7. The server stored nothing — the data merely passed through

Cas limites

SituationBehaviour
Le propriétaire est hors ligneL’invité voit l’icône par défaut jusqu’à ce que le propriétaire revienne en ligne.
50 invités demandent en même temps50 × 5 Ko = 250 Ko par le WebSocket — négligeable.
Le propriétaire change l’icônehas_avatar_hash change et les invités la redemandent
Le propriétaire supprime l’icônehas_avatar : false et les invités affichent l’icône par défaut
La confidentialité est préservée. L’icône d’une barrière n’est pas une donnée sensible, et pourtant elle ne se dépose pas sur le serveur : elle transite par le WebSocket et n’est jamais écrite sur disque.

12. Prévision de charge

Un propriétaire actif génère

Un invité actif

Scaling

SubscribersEn ligne simultanément (~15 %)Connexions WebSocketServer
1 000~150~150Easy
10 000~1 500~1 500Easy
50 000~7 500~7 500un worker à la limite
100 000~15 000~15 0002–3 workers

Workerman sur un seul worker : 5 000–10 000 connexions simultanées, d’environ 20 Ko chacune.

Webhook et appareil

Le goulet d’étranglement

est MySQL, pas les WebSockets. Mais 250 000 insertions par jour — 50 000 abonnés × 5 appels — ne sont rien pour MySQL sur SSD.

Conclusion: до 50 000 абонентов текущий сервер справится без изменений. После — увеличиваем worker->et ajouter des index.

13. Plan de réalisation

  1. Database — offres, les nouvelles colonnes dans numbers et hosts, la table devices
  2. Limites côté serveur — contrôles dans number_add et key_create
  3. Type d’objet — choix du type à l’ajout, avec des dialogues différents
  4. API — host_sync et guest_ok avec les nouveaux champs de profil
  5. Webhook — le protocole HMAC, deux modes d’envoi, le statut de la réponse
  6. WS de l’appareil — device_hello, device_command et device_response dans server.php
  7. Le déclencheur Wi-Fi — empreinte et connexion
  8. Fenêtre horaire — time_from/time_to
  9. Confirmation — trois niveaux : automatique, confirmer, confirmer l’identité
  10. Icons — livraison en transit par le WebSocket, compressée en 64×64
  11. UI — les boutons Géo et Wi-Fi, les dialogues, les indicateurs, le sélecteur de type
  12. Partage des coordonnées — une option avec avertissement
  13. Compiler et publier
PWA: Le déclencheur Wi-Fi n’est pas disponible — les navigateurs n’ont pas d’API Wi-Fi. Le webhook et l’appareil fonctionnent via la PWA : bouton → serveur → appareil. La fenêtre horaire et la confirmation n’existent que dans l’application native.
Rétrocompatibilité : il n’y a presque pas d’anciens clients. Nous faisons au plus commode et forçons la mise à jour via version_check si nécessaire.

Entrixy — architecture finale v2, validée le 13 avril 2026