Automatiser l'activation d'équipements
L'activation est le mécanisme qui permet à un équipement de se déclarer lui-même sur la plateforme sans qu'un opérateur ait à pré-saisir ses informations équipement par équipement. Le firmware embarque une logique générique et un seul secret à pré-charger : la clé d'activation du site.
À partir de là, l'équipement récupère tout ce qu'il faut pour émettre ses données.
Récupérer la clé d'activation
La clé d'activation est unique par site et se récupère depuis la fiche du site dans le module Administration. C'est la seule information à pré-charger côté équipement (en usine, via une étiquette, ou poussée par un installateur sur le terrain).
Vue d'ensemble du cycle
Ce que renvoie l'API d'activation
À l'activation, l'équipement reçoit un bloc d'informations qu'il doit stocker en mémoire et ne pas redemander sauf perte avérée.
| Champ | Rôle |
|---|---|
uuid | Identifiant de l'équipement côté plateforme. Sert à appeler le GET de refresh quotidien. |
deviceDeveloperId | Identifiant de l'équipement permettant d'identifier l'équipement lors de l'envoi de données. |
apiKey | Clé d'authentification utilisée à chaque envoi de mesures. |
checksum | Couche de signature additionnelle (protocole Smartcore v3). |
restUrl | Endpoint HTTPS d'envoi des données. |
mqttUrl | Broker MQTT principal. |
mqttSecondaryUrl | Broker MQTT secondaire (fallback). |
Séquence d'activation
Ce diagramme synthétise le flux complet vu jusqu'ici : une activation initiale unique, puis le cycle stable de fonctionnement (émission de mesures + refresh quotidien).
L'étape 1 (le PUT) n'est rejouée qu'en cas d'évènement exceptionnel : perte des informations en mémoire, changement de nom côté produit, ou changement de clé d'activation. Le détail de ces cas est documenté ci-dessous.
Cas particuliers
Mise à jour de la configuration côté produit
Tous les champs ne se comportent pas pareil sur une nouvelle activation :
| Champ | Comportement |
|---|---|
name | Écrasé lors d'une nouvelle activation, inchangé si non-précisé. |
items | Écrasé lors d'une nouvelle activation, inchangé si non-précisé. |
serialNumber | Clé d'identité, permet d'identifier le produit. Un nouvel équipement est créé en cas modification. |
type | Verrouillé après création. Erreur 400 si modifié. |
manufacturer | Verrouillé après création. Erreur 400 si modifié. |
technicalName | Immuable après création. Une valeur différente ignorée. |
tags | Toujours ignorés lors d'une activation. |
En pratique, côté firmware, les seuls champs qu'il est utile de remettre dans une ré-activation sont le serialNumber (nécessaire pour identifier l'équipement), le type et le name si on veut le changer.
Changement de clé d'activation = nouvel équipement
Activer un équipement avec une clé d'activation différente (donc un autre site) ne déplace pas l'équipement : la plateforme crée un nouvel équipement sur le nouveau site, avec un nouvel uuid et de nouvelles credentials. L'ancien équipement reste sur le site d'origine et continue de fonctionner.
Les deux devices coexistent sans contrainte : c'est utile pour conserver une trace de l'historique côté site d'origine (debug, audit, vérification a posteriori). Si vous souhaitez nettoyer la flotte, l'ancien équipement peut être supprimé manuellement depuis l'IHM Admin du site d'origine.
Activation de gateway
Une gateway (concentrateur, automate, passerelle Modbus/LoRa…) qui agrège des équipements muets (donc incapables de s'auto-déclarer) est en charge de leur activation. Pattern en deux temps :
- La gateway s'active elle-même via, stocke son propre
uuid. - Pour chaque équipement enfant, elle rejoue une activation en renseignant le champ
gateway.uuid(= son propreuuid) dans le payload.
La gateway peut paralléliser les appels, mais doit gérer ses propres retries.
Utiliser les tags pour piloter le produit
Les tags sont des paires clé/valeur attachées à un équipement depuis l'IHM Administration. Comme ils sont renvoyés dans la réponse du GET, En plus de servir de méta données pour des calculs ou des moyens de classifier les équipements, ils constituent un canal léger pour pousser de la configuration depuis la plateforme vers le produit.
Exemples d'usages typiques :
| Tag | Effet attendu côté produit |
|---|---|
poll_interval = 60 | Le produit interroge son capteur toutes les 60 s au lieu de l'intervalle par défaut. |
mode = eco | Le produit réduit la fréquence d'émission pour économiser la batterie. |
alarm_threshold = 80 | Le produit déclenche une alarme locale au-delà du seuil défini. |
zone = atelier_3 | Catégorisation utilisée par le produit pour son affichage local. |
- Cadence : les tags ne sont à récupérer que sur une faible fréquence : ne les utilisez pas pour une configuration qui doit changer en temps réel.
- Sens unique : la modification des tags se fait exclusivement depuis l'IHM Administration. Les tags envoyés par le produit dans le payload du
PUTsont ignorés.
Robustesse côté firmware
L'API d'activation peut être temporairement injoignable (panne réseau, maintenance). Le firmware doit rester opérationnel et reprendre proprement quand le service revient.
Backoff exponentiel sur erreur
| Tentative | Délai avant le prochain essai |
|---|---|
| 1 → 2 | 5 minutes |
| 2 → 3 | 10 minutes |
| 3 → 4 | 20 minutes |
| 4+ | 1 heure |
Principe d'indépendance
L'équipement ne doit pas se bloquer si l'API d'activation est indisponible :
- S'il a déjà ses credentials en mémoire, il continue d'émettre ses données si les requêtes aboutissent. Le chemin d'ingestion est totalement indépendant de l'API d'activation.
- Une requête de lecture quotidienne qui échoue est sans gravité.
- Une réactivation qui échoue n'a d'impact bloquant que si les credentials sont aussi perdus. Sinon, l'équipement reprend son comportement nominal.
Référence de l'API
| Paramètre | Valeur |
|---|---|
| Host | https://activation.magicbuilder.io |
| Version | v1 |
| Swagger | https://activation.magicbuilder.io/swagger-api/ |
| Authentification | Header activationkey (UUID v4) sur toutes les routes |
PUT /api/v1/devices - Activer un équipement
Crée l'équipement s'il n'existe pas pour le couple activationkey // serialNumber, ou met à jour les champs mutables s'il existe déjà.
Headers
| Nom | Obligatoire | Description |
|---|---|---|
activationkey | ✅ | Clé d'activation du site |
Content-Type | ✅ | application/json |
Body
| Champ | Type |
|---|---|
serialNumber | string (≤ 30) |
type | string |
manufacturer | string |
name | string |
items | Item |
technicalName | string |
tags | { key: value } |
gateway | { uuid: string } |
Modèle d'un item
Représente une sous-catégorie d'un équipement. Voir Items pour le contexte.
| Champ | Type | Description |
|---|---|---|
itemType | string | Type d'item, défini dans le Référentiel (ex. Phase, Global). Combiné avec index, il identifie l'item dans l'équipement. |
index | string | Index de l'item au sein de son type (ex. "0", "1", "2"). Défaut : "0". |
name | string | Nom d'affichage de l'item. |
tags | {key:value} | Tags attaché à l'item. Couple clé/valeur attaché à l'item. Utilisé pour catégoriser, filtrer ou enrichir les données côté plateforme. |
L'item Global 0 est ajouté automatiquement s'il n'est pas présent dans la liste.
Réponses
| Code | Sens |
|---|---|
201 | Équipement créé |
200 | Équipement existant mis à jour, ou nouvelle activation sur un autre site |
400 | Payload invalide, changement de type/manufacturer refusé, ou gateway introuvable |
401 | Header activationkey manquant |
403 | Clé d'activation invalide ou site inaccessible |
500 | Erreur serveur |
Exemple
curl -X PUT 'https://activation.magicbuilder.io/api/v1/devices' \
-H 'accept: application/json' \
-H 'activationkey: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"serialNumber": "SN_789456123",
"type": "Generic",
"manufacturer": "Generic",
"name": "Compteur Atelier 1"
}'
Réponse :
{
"code": "201",
"message": "Device created",
"details": {
"uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"serialNumber": "SN_789456123",
"name": "Compteur Atelier 1",
"type": "Generic",
"manufacturer": "Generic",
"items": [{ "index": "0", "itemType": "Global", "name": "Global" }],
"tags": null,
"iotPlatform": {
"restUrl": "https://streams-api.magicbuilder.io",
"mqttUrl": "mqtts://streams-mqtt.magicbuilder.io",
"mqttSecondaryUrl": "mqtts://streams-mqtt.magicbuilder.io",
"deviceDeveloperId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"checksum": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"configurationKey": "GENERIC_CONNECTED_DEVICE_CONNECT_001"
}
}
GET /api/v1/devices/{uuid} - Récupérer les informations d'un équipement
Lecture seule. Renvoie l'état courant de l'équipement et les informations d'envoi de données.
Path parameters
| Nom | Description |
|---|---|
uuid | UUID de l'équipement. Champ details.uuid renvoyé par le PUT. |
Headers
| Nom | Description |
|---|---|
activationkey | Clé d'activation du site auquel appartient l'équipement |
Exemple
curl -X GET 'https://activation.magicbuilder.io/api/v1/devices/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
-H 'accept: application/json' \
-H 'activationkey: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Réponse :
{
"code": "200",
"message": "Device's details",
"details": {
"uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"serialNumber": "SN_789456123",
"name": "Compteur Atelier 1",
"type": "Generic",
"manufacturer": "Generic",
"items": [{ "index": "0", "itemType": "Global", "name": "Global" }],
"tags": [
{ "key": "poll_interval", "value": "60" },
{ "key": "mode", "value": "eco" },
{ "key": "zone", "value": "atelier_3" }
],
"iotPlatform": {
"restUrl": "https://streams-api.magicbuilder.io",
"mqttUrl": "mqtts://streams-mqtt.magicbuilder.io",
"mqttSecondaryUrl": "mqtts://streams-mqtt.magicbuilder.io",
"deviceDeveloperId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"checksum": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"configurationKey": "GENERIC_CONNECTED_DEVICE_CONNECT_001"
}
}
Codes d'erreur
En cas d'échec, la réponse contient un objet d'erreur avec statusCode, errorCode et un message et un errorUUID qui permettent d'analyser la source de l'erreur.
| Code | HTTP | Déclencheur |
|---|---|---|
ERR_ACT_ACTIVATIONKEY_001 | 400 | activationkey absente ou vide |
ERR_ACT_DEVICE_002 | 400 | Mise à jour des champs échoué - changement de type ou manufacturer sur un équipement existant, ou panne réseau |
ERR_ACT_DEVICE_003 | 400 | gateway.uuid fourni dans le payload mais aucune gateway correspondante |
ERR_ACT_DEVICE_005 | 403 | GET d'un équipement situé sur un autre site que celui de la clé d'activation fournie |
ERR_ACT_DEVICE_007 | 400 | Gateway trouvée mais sur un site différent de celui de l'équipement |
ERR_ACT_ACTIVATE_001 | 500 | Erreur serveur inattendue |
ERR_ACT_ACTIVATE_002 | 400 | Conflit serialNumber existant avec un type différent |
