¡Hola a todos!
Han cambiado muchas cosas en las últimas semanas en cuanto a integraciones externas: nueva versión del SDK de JavaScript (@gladysassistant/integration-sdk v0.16.0), nuevos campos en el manifiesto, nuevas reglas de validación en la tienda… Esta publicación recoge todo lo que debe hacer para actualizar su integración, y lo que puede hacer además si lo desea.
Buena noticia: no hay cambios obligatorios que rompan la compatibilidad. Una integración publicada hoy sigue indexada. Pero algunos puntos merecen una verificación, y las novedades valen la pena ![]()
La lista de verificación rápida
- Actualizar el SDK a
^0.16.0(Node.js ≥ 20) - Verificar sus
poll_frequency: en milisegundos, y solo entre los valores permitidos - Usar
publishChangedStatessi publica muchos estados (límite de 300 estados/minuto) - Añadir
categories(y eventualmentekeywords/countries) al manifiesto - Verificar que
gladys_versioncubre bien todos los campos que declara - Tener
docs/en.mdydocs/fr.md(300 caracteres mínimo cada uno) - Verificar la portada: JPEG o PNG, 800×534 px exactamente, 150 Ko máximo
- Ejecutar el validador local:
npx github:GladysAssistant/integration-store - Publicar: incrementar
version+docker_image, empujando la imagen antes del manifiesto
El detalle de cada punto está abajo.
1. Actualizar el SDK
npm install @gladysassistant/integration-sdk@^0.16.0
El SDK requiere Node.js ≥ 20. Asegúrese de verificar la imagen base de su Dockerfile.
Lo que ha cambiado desde la v0.11:
| Versión | Principales novedades |
|---|---|
| 0.12 | Sincronización con Gladys 4.86: sensores de red eléctrica/gas, cámaras PTZ, wakeOnLan(), campo de configuración account_link |
| 0.13 | Seis nuevos fenómenos meteorológicos en el formato pivot, sirenas, carga de batería, formato de los resultados del escaneo |
| 0.14 | Disparadores y acciones de escenas, widgets de tablero, getHouses(), sensores de carbono de la red y humo |
| 0.15 | DEVICE_POLL_FREQUENCIES, Gladys falso para sus pruebas, parseMdnsTxt(), publishChangedStates(), tipo calendar, contratos de energía, formularios en los botones de widgets, selector de casa, publishEnergyConsumption() |
| 0.16 | Lectores de música, tipos ai y tts, should_poll se vuelve opcional |
El registro completo de cambios está en GitHub.
2. Los puntos a verificar en su código
poll_frequency: en milisegundos, y solo ciertos valores
Este es el error más frecuente. poll_frequency se expresa en milisegundos, y solo se aceptan estos valores: 1 s, 2 s, 10 s, 15 s, 30 s o 1 min. Cualquier otro valor (300 pensado en segundos, 300000 para 5 minutos…) hace que publishDiscoveredDevices falle con un error 400.
Use las constantes exportadas por el SDK:
import { DEVICE_POLL_FREQUENCIES } from '@gladysassistant/integration-sdk';
await gladys.publishDiscoveredDevices([
{
name: 'Estación meteorológica',
external_id: ids.device,
should_poll: true,
poll_frequency: DEVICE_POLL_FREQUENCIES.EVERY_MINUTES, // 60000 ms
features: [/* … */],
},
]);
Algunas precisiones:
- Un minuto es el ritmo más lento. Para ir más lento (API en la nube con cuota, ajuste del usuario en minutos), mantenga
EVERY_MINUTESe ignore las consultas innecesarias enonPoll, o use su propio temporizador. - Desde Gladys 5.3,
poll_frequencyes suficiente: el núcleo activashould_pollsolo. Si sugladys_versionacepta versiones más antiguas, mantengashould_poll: true. Si estableceshould_poll, debe ser un booleano. - Estos dos campos se leen al crear el dispositivo: modificarlos después no actualiza un dispositivo ya creado.
Límite de 300 estados por minuto: publishChangedStates
La API anfitriona limita POST /state a 300 estados por minuto y por integración. Si consulta muchos dispositivos, publique solo lo que ha cambiado:
// reemplaza publishStates: solo los valores modificados se envían a Gladys
await gladys.publishChangedStates(states);
// y se devuelve un valor sin cambios cada 30 minutos
await gladys.publishChangedStates(states, { heartbeat: 30 * 60 * 1000 });
El SDK divide los lotes de más de 100 estados, devuelve lo que Gladys ha rechazado y olvida los valores de un dispositivo cuando el usuario lo crea, lo modifica o lo elimina.
Use las constantes, no cadenas fijas
DEVICE_FEATURE_CATEGORIES, DEVICE_FEATURE_TYPES y DEVICE_FEATURE_UNITS son una copia exacta de server/utils/constants.js en Gladys, y se mantienen actualizadas en cada versión. Si ha copiado cadenas manualmente, este es el momento de pasar a las constantes: evita errores tipográficos y tiene autocompletado.
Integraciones meteorológicas: night está obsoleto
La condición night sigue siendo aceptada pero está obsoleta. Una noche lluviosa se escribe weather: 'rain', is_day: false. También piense en las nuevas condiciones del formato pivot y en el campo type de las alertas (WEATHER_ALERT_TYPES).
Disparadores y acciones de escenas: las claves son definitivas
Si declara scene_triggers / scene_actions, una clave publicada nunca debe ser renombrada. Y añadir un campo required sin default a una acción existente rompe las escenas que la usan.
3. Actualizar el manifiesto
La regla de oro: gladys_version debe cubrir lo que declara
Las versiones antiguas de Gladys rechazan los campos que no conocen. La tienda verifica que el mínimo de su gladys_version cubra cada campo declarado, de lo contrario la integración es rechazada. Así, el usuario ve simplemente «requiere Gladys ≥ X» en el catálogo, en lugar de una instalación que falla sin explicación.
| Usted declara… | gladys_version mínimo |
|---|---|
categories |
>=4.86.0 |
type: "provider", widgets, scene_triggers, scene_actions |
>=5.1.0 |
type: "calendar", account_schema, energy_contracts, un campo con source: "houses" |
>=5.2.0 |
type: "ai", type: "tts", music, keywords, countries |
>=5.3.0 |
En el otro sentido, no suba gladys_version sin razón: su integración sería ocultada para los usuarios que aún no han actualizado Gladys.
categories: su lugar en el catálogo
Entre 1 y 3 categorías entre: climate, lighting, energy, security, multimedia, appliances, environment, protocols, network, notifications, assistants, services, transport, vehicles, servers, leisure.
Las cuatro últimas (transport, vehicles, servers, leisure) acaban de ser añadidas. Sin categories, su integración sigue visible en « Todas » y en la búsqueda, pero no aparece en ninguna sección. Para las integraciones ya publicadas, la tienda aplica de momento un mapeo de respaldo (data/category-fallback.json). Declarar sus propias categorías es la mejor manera de estar bien posicionado. Una categoría desconocida es simplemente ignorada, con una advertencia.
keywords y countries (Gladys ≥ 5.3)
{
"gladys_version": ">=5.3.0",
"categories": ["energy"],
"keywords": ["linky", "enedis", "téléinfo"],
"countries": ["FR"]
}
keywords: 1 a 10 términos de 2 a 30 caracteres, nunca mostrados, usados únicamente por la búsqueda (marcas, modelos, sinónimos, ciudades o redes atendidas…).countries: 1 a 20 códigos de país ISO en mayúsculas. No lo ponga si su integración funciona en todas partes (ese es el comportamiento por defecto). Si lo declara, las instancias ubicadas en otro país ya no verán la integración en las secciones del catálogo (sigue siendo encontrada a través de la búsqueda). Piensa en esto para una integración regional: servicio meteorológico nacional, red de transporte, proveedor de energía, ISP…
No olvides: declarar keywords o countries obliga a gladys_version ≥ 5.3.0.
4. Documentación y portada
- Documentación obligatoria :
docs/en.mdydocs/fr.mden la raíz del repositorio, 300 caracteres mínimo cada uno, siguiendo las secciones de la plantilla (Presentación / Requisitos previos / Configuración / Solución de problemas). Si falta una, la integración es rechazada. Los archivos son alojados por la tienda y mostrados en las pantallas de instalación y configuración de Gladys. - Nuevo :
docs/de.mdydocs/es.mdson opcionales. Si están presentes (300 caracteres mínimo), se muestran a los usuarios alemanes y españoles. - Portada : JPEG o PNG, exactamente 800×534 px, 150 Ko máximo, URL
httpsdirecta (sin redirección). Lo más simple: una URLraw.githubusercontent.comhacia un archivo de tu repositorio. Una portada inválida no bloquea la indexación, pero tendrás una imagen por defecto en el catálogo.
5. Validar localmente antes de publicar
¡Ya no es necesario esperar la indexación horaria para descubrir un rechazo! En la raíz de tu repositorio:
npx github:GladysAssistant/integration-store
El validador hace exactamente las mismas comprobaciones que el robot de la tienda (esquema, reglas gladys_version, categorías, documentación, existencia de las imágenes Docker, portada) y muestra todos los problemas de una vez. Código de salida 0 = la integración sería indexada, 1 = sería rechazada.
En la CI de tus pull requests
En una PR que incrementa la versión, la imagen Docker generalmente no está publicada todavía: añade --skip-image-check para saltar solo esta comprobación.
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npx github:GladysAssistant/integration-store --skip-image-check
Vuelve a ejecutarlo sin la opción una vez que las imágenes estén publicadas, por ejemplo en el último paso de tu flujo de trabajo de lanzamiento.
6. Publicar la nueva versión
- Incrementa
version(semver estricto) ydocker_image(con un tag explícito) en el manifiesto. - Publica la imagen Docker antes de que el manifiesto que la referencia llegue a la rama por defecto: la tienda verifica que la imagen existe y que es descargable sin autenticación. Si falta la imagen, la integración es retirada del catálogo hasta la próxima indexación.
- Empuja. En la próxima indexación (cada hora), Gladys mostrará « actualización disponible » a tus usuarios.
¿Tu integración no aparece? Mira el archivo público rejected.json de la tienda: cada rechazo está listado con su razón (error = no indexada, warning = indexada con una degradación, por ejemplo la portada por defecto).
7. Prueba tu integración con el Gladys falso
El SDK ahora proporciona un Gladys en memoria para tus pruebas unitarias: es un verdadero GladysIntegration, conectado a un Gladys falso en lugar de la red.
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('publica la temperatura en el sondeo', 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);
});
Aplica las mismas comprobaciones que la API host (prefijo de los external_id, categorías/tipos/unidades conocidas, poll_frequency…) y responde con los mismos errores 400. Así que ves los errores en tus pruebas en lugar de en tus usuarios.
8. Para ir más allá (opcional)
Si quieres enriquecer tu integración, aquí está todo lo que ahora es posible:
| Funcionalidad | Manifiesto | SDK | Gladys |
|---|---|---|---|
| Widgets de panel de control | widgets |
onWidgetGet, onWidgetAction, requestWidgetRefresh |
≥ 5.1 |
| Disparadores / acciones de escenas | scene_triggers, scene_actions |
publishSceneEvent, onSceneAction |
≥ 5.1 |
| Integración « capacidades solas » | type: "provider" |
— | ≥ 5.1 |
| Proveedor de calendario | type: "calendar", account_schema |
publishCalendars, publishCalendarEvents… |
≥ 5.2 |
| Contratos y calendarios de energía | energy_contracts |
publishEnergyCalendar, onEnergyPrice… |
≥ 5.2 |
| Consumo datado (lecturas recibidas después) | — | publishEnergyConsumption |
≥ 5.2 |
| Elección de una casa en un formulario | source: "houses" |
— | ≥ 5.2 |
| Proveedor de IA (compatible OpenAI) | type: "ai" |
onAiChat |
≥ 5.3 |
| Síntesis de voz | type: "tts" |
onTtsSynthesize |
≥ 5.3 |
| Reproductores de música (navegación, búsqueda, cola) | music |
publishNowPlaying, onMusicBrowse, onMusicPlay… |
≥ 5.3 |
| Wake-on-LAN | network_wake: true |
wakeOnLan |
≥ 4.86 |
| Conexión a una cuenta sin redirección (código QR…) | campo account_link |
onOAuthAuthorizeUrl |
≥ 4.86 |
Todo está documentado en el README del SDK, y todas las reglas del manifiesto están en el README de la tienda.
Si te bloqueas en una migración o si una regla de validación te parece rara, responde en este tema o abre un issue en integration-sdk-js / integration-store.
¡Gracias a todos los que desarrollan integraciones, el catálogo está creciendo muy rápido! ![]()