Bonjour à tous !
Beaucoup de choses ont bougé ces dernières semaines côté intégrations externes : nouvelle version du SDK JavaScript (@gladysassistant/integration-sdk v0.16.0), nouveaux champs dans le manifest, nouvelles règles de validation dans le store… Ce post rassemble tout ce que vous devez faire pour mettre votre intégration à jour, et ce que vous pouvez faire en plus si vous le souhaitez.
Bonne nouvelle : il n’y a pas de changement cassant obligatoire. Une intégration publiée aujourd’hui reste indexée. Mais quelques points méritent une vérification, et les nouveautés valent le détour ![]()
La checklist rapide
- Passer le SDK en
^0.16.0(Node.js ≥ 20) - Vérifier vos
poll_frequency: en millisecondes, et uniquement parmi les valeurs autorisées - Utiliser
publishChangedStatessi vous publiez beaucoup d’états (limite de 300 états/minute) - Ajouter
categories(et éventuellementkeywords/countries) au manifest - Vérifier que
gladys_versioncouvre bien tous les champs que vous déclarez - Avoir
docs/en.mdetdocs/fr.md(300 caractères minimum chacun) - Vérifier la cover : JPEG ou PNG, 800×534 px exactement, 150 Ko maximum
- Lancer le validateur local :
npx github:GladysAssistant/integration-store - Publier : incrémenter
version+docker_image, en poussant l’image avant le manifest
Le détail de chaque point est ci-dessous.
1. Mettre à jour le SDK
npm install @gladysassistant/integration-sdk@^0.16.0
Le SDK demande Node.js ≥ 20. Pensez à vérifier l’image de base de votre Dockerfile.
Ce qui a changé depuis la v0.11 :
| Version | Nouveautés principales |
|---|---|
| 0.12 | Synchro avec Gladys 4.86 : capteurs réseau électrique / gaz, caméras PTZ, wakeOnLan(), champ de config account_link |
| 0.13 | Six nouveaux phénomènes météo dans le format pivot, sirènes, recharge de batterie, format des résultats de scan |
| 0.14 | Déclencheurs et actions de scènes, widgets de tableau de bord, getHouses(), capteurs carbone du réseau et fumée |
| 0.15 | DEVICE_POLL_FREQUENCIES, Gladys factice pour vos tests, parseMdnsTxt(), publishChangedStates(), type calendar, contrats d’énergie, formulaires dans les boutons de widgets, sélecteur de maison, publishEnergyConsumption() |
| 0.16 | Lecteurs de musique, types ai et tts, should_poll devient facultatif |
Le changelog complet est sur GitHub.
2. Les points à vérifier dans votre code
poll_frequency : en millisecondes, et seulement certaines valeurs
C’est le piège le plus fréquent. poll_frequency est exprimé en millisecondes, et seules ces valeurs sont acceptées : 1 s, 2 s, 10 s, 15 s, 30 s ou 1 min. Toute autre valeur (300 pensé en secondes, 300000 pour 5 minutes…) fait échouer publishDiscoveredDevices avec une erreur 400.
Utilisez les constantes exportées par le SDK :
import { DEVICE_POLL_FREQUENCIES } from '@gladysassistant/integration-sdk';
await gladys.publishDiscoveredDevices([
{
name: 'Station météo',
external_id: ids.device,
should_poll: true,
poll_frequency: DEVICE_POLL_FREQUENCIES.EVERY_MINUTES, // 60000 ms
features: [/* … */],
},
]);
Quelques précisions :
- Une minute, c’est le rythme le plus lent. Pour aller plus lentement (API cloud avec quota, réglage utilisateur en minutes), gardez
EVERY_MINUTESet ignorez les polls inutiles dansonPoll, ou utilisez votre propre timer. - Depuis Gladys 5.3,
poll_frequencysuffit : le core activeshould_polltout seul. Si votregladys_versionaccepte des versions plus anciennes, gardezshould_poll: true. Si vous mettezshould_poll, ce doit être un booléen. - Ces deux champs sont lus à la création de l’appareil : les modifier ensuite ne met pas à jour un appareil déjà créé.
Limite de 300 états par minute : publishChangedStates
L’API hôte limite POST /state à 300 états par minute et par intégration. Si vous interrogez beaucoup d’appareils, ne publiez que ce qui a changé :
// remplace publishStates : seules les valeurs modifiées partent vers Gladys
await gladys.publishChangedStates(states);
// et on renvoie quand même une valeur inchangée toutes les 30 minutes
await gladys.publishChangedStates(states, { heartbeat: 30 * 60 * 1000 });
Le SDK découpe les lots de plus de 100 états, renvoie ce que Gladys a refusé et oublie les valeurs d’un appareil quand l’utilisateur le crée, le modifie ou le supprime.
Utilisez les constantes, pas des chaînes en dur
DEVICE_FEATURE_CATEGORIES, DEVICE_FEATURE_TYPES et DEVICE_FEATURE_UNITS sont une copie conforme de server/utils/constants.js dans Gladys, et elles sont tenues à jour à chaque version. Si vous avez recopié des chaînes à la main, c’est le bon moment pour passer aux constantes : vous évitez les fautes de frappe et vous avez l’autocomplétion.
Intégrations météo : night est déprécié
La condition night reste acceptée mais elle est dépréciée. Une nuit pluvieuse s’écrit weather: 'rain', is_day: false. Pensez aussi aux nouvelles conditions du format pivot et au champ type des alertes (WEATHER_ALERT_TYPES).
Déclencheurs et actions de scènes : les clés sont définitives
Si vous déclarez des scene_triggers / scene_actions, une clé publiée ne doit jamais être renommée. Et ajouter un champ required sans default à une action existante casse les scènes qui l’utilisent.
3. Mettre à jour le manifest
La règle d’or : gladys_version doit couvrir ce que vous déclarez
Les anciennes versions de Gladys refusent les champs qu’elles ne connaissent pas. Le store vérifie donc que le minimum de votre gladys_version couvre chaque champ déclaré, sinon l’intégration est rejetée. Comme ça, l’utilisateur voit simplement « nécessite Gladys ≥ X » dans le catalogue, au lieu d’une installation qui échoue sans explication.
| Vous déclarez… | gladys_version minimum |
|---|---|
categories |
>=4.86.0 |
type: "provider", widgets, scene_triggers, scene_actions |
>=5.1.0 |
type: "calendar", account_schema, energy_contracts, un champ avec source: "houses" |
>=5.2.0 |
type: "ai", type: "tts", music, keywords, countries |
>=5.3.0 |
Dans l’autre sens, ne montez pas gladys_version sans raison : votre intégration serait masquée pour les utilisateurs qui n’ont pas encore mis à jour Gladys.
categories : votre place dans le catalogue
Entre 1 et 3 catégories parmi : climate, lighting, energy, security, multimedia, appliances, environment, protocols, network, notifications, assistants, services, transport, vehicles, servers, leisure.
Les quatre dernières (transport, vehicles, servers, leisure) viennent d’être ajoutées. Sans categories, votre intégration reste visible dans « Toutes » et dans la recherche, mais n’apparaît dans aucune rubrique. Pour les intégrations déjà publiées, le store applique en attendant un mapping de secours (data/category-fallback.json). Déclarer vous-même vos catégories est le meilleur moyen d’être bien placé. Une catégorie inconnue est simplement ignorée, avec un avertissement.
keywords et countries (Gladys ≥ 5.3)
{
"gladys_version": ">=5.3.0",
"categories": ["energy"],
"keywords": ["linky", "enedis", "téléinfo"],
"countries": ["FR"]
}
keywords: 1 à 10 termes de 2 à 30 caractères, jamais affichés, utilisés uniquement par la recherche (marques, modèles, synonymes, villes ou réseaux desservis…).countries: 1 à 20 codes pays ISO en majuscules. Ne le mettez pas si votre intégration fonctionne partout (c’est le comportement par défaut). Si vous le déclarez, les instances situées dans un autre pays ne verront plus l’intégration dans les rubriques du catalogue (elle reste trouvable via la recherche). Pensez-y pour une intégration régionale : service météo national, réseau de transport, fournisseur d’énergie, FAI…
N’oubliez pas : déclarer keywords ou countries impose gladys_version ≥ 5.3.0.
4. Documentation et cover
- Documentation obligatoire :
docs/en.mdetdocs/fr.mdà la racine du dépôt, 300 caractères minimum chacun, en suivant les sections du template (Présentation / Prérequis / Configuration / Dépannage). S’il en manque une, l’intégration est rejetée. Les fichiers sont hébergés par le store et affichés dans les écrans d’installation et de configuration de Gladys. - Nouveau :
docs/de.mdetdocs/es.mdsont facultatifs. S’ils sont présents (300 caractères minimum), ils sont affichés aux utilisateurs allemands et espagnols. - Cover : JPEG ou PNG, exactement 800×534 px, 150 Ko maximum, URL
httpsdirecte (sans redirection). Le plus simple : une URLraw.githubusercontent.comvers un fichier de votre dépôt. Une cover invalide ne bloque pas l’indexation, mais vous aurez une image par défaut dans le catalogue.
5. Valider en local avant de publier
Plus besoin d’attendre l’indexation horaire pour découvrir un rejet ! À la racine de votre dépôt :
npx github:GladysAssistant/integration-store
Le validateur fait exactement les mêmes vérifications que le robot du store (schéma, règles gladys_version, catégories, documentation, existence des images Docker, cover) et affiche tous les problèmes d’un coup. Code de sortie 0 = l’intégration serait indexée, 1 = elle serait rejetée.
Dans la CI de vos pull requests
Dans une PR qui incrémente la version, l’image Docker n’est généralement pas encore publiée : ajoutez --skip-image-check pour sauter seulement cette vérification.
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npx github:GladysAssistant/integration-store --skip-image-check
Relancez-le sans l’option une fois les images publiées, par exemple en dernière étape de votre workflow de release.
6. Publier la nouvelle version
- Incrémentez
version(semver strict) etdocker_image(avec un tag explicite) dans le manifest. - Publiez l’image Docker avant que le manifest qui la référence n’arrive sur la branche par défaut : le store vérifie que l’image existe et qu’elle est téléchargeable sans authentification. Si l’image manque, l’intégration est retirée du catalogue jusqu’à la prochaine indexation.
- Poussez. À la prochaine indexation (toutes les heures), Gladys affichera « mise à jour disponible » à vos utilisateurs.
Votre intégration n’apparaît pas ? Regardez le fichier public rejected.json du store : chaque rejet y est listé avec sa raison (error = non indexée, warning = indexée avec une dégradation, par exemple la cover par défaut).
7. Testez votre intégration avec le Gladys factice
Le SDK fournit maintenant un Gladys en mémoire pour vos tests unitaires : c’est un vrai GladysIntegration, branché sur un faux Gladys au lieu du réseau.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createFakeGladys } from '@gladysassistant/integration-sdk/testing';
import { registerHandlers } from '../src/app.js';
test('publie la température au poll', async () => {
const gladys = createFakeGladys({ config: { api_key: 'key' } });
registerHandlers(gladys);
await gladys.connect();
const [device] = gladys.fake.discoveredDevices;
assert.deepEqual(await gladys.fake.poll(device), { success: true });
assert.equal(gladys.fake.lastState(`${device.external_id}:temperature`), 21.5);
});
Il applique les mêmes vérifications que l’API hôte (préfixe des external_id, catégories/types/unités connus, poll_frequency…) et répond avec les mêmes erreurs 400. Vous voyez donc les erreurs dans vos tests plutôt que chez vos utilisateurs.
8. Pour aller plus loin (facultatif)
Si vous voulez enrichir votre intégration, voici tout ce qui est maintenant possible :
| Fonctionnalité | Manifest | SDK | Gladys |
|---|---|---|---|
| Widgets de tableau de bord | widgets |
onWidgetGet, onWidgetAction, requestWidgetRefresh |
≥ 5.1 |
| Déclencheurs / actions de scènes | scene_triggers, scene_actions |
publishSceneEvent, onSceneAction |
≥ 5.1 |
| Intégration « capacités seules » | type: "provider" |
— | ≥ 5.1 |
| Fournisseur de calendrier | type: "calendar", account_schema |
publishCalendars, publishCalendarEvents… |
≥ 5.2 |
| Contrats et calendriers d’énergie | energy_contracts |
publishEnergyCalendar, onEnergyPrice… |
≥ 5.2 |
| Consommation datée (relevés reçus après coup) | — | publishEnergyConsumption |
≥ 5.2 |
| Choix d’une maison dans un formulaire | source: "houses" |
— | ≥ 5.2 |
| Fournisseur d’IA (compatible OpenAI) | type: "ai" |
onAiChat |
≥ 5.3 |
| Synthèse vocale | type: "tts" |
onTtsSynthesize |
≥ 5.3 |
| Lecteurs de musique (navigation, recherche, file d’attente) | music |
publishNowPlaying, onMusicBrowse, onMusicPlay… |
≥ 5.3 |
| Wake-on-LAN | network_wake: true |
wakeOnLan |
≥ 4.86 |
| Connexion à un compte sans redirection (QR code…) | champ account_link |
onOAuthAuthorizeUrl |
≥ 4.86 |
Tout est documenté dans le README du SDK, et toutes les règles du manifest sont dans le README du store.
Si vous bloquez sur une migration ou si une règle de validation vous paraît bizarre, répondez dans ce sujet ou ouvrez une issue sur integration-sdk-js / integration-store.
Merci à tous ceux qui développent des intégrations, le catalogue grandit très vite ! ![]()