Cómo funciona una fuente
- Una fuente, una tarjeta. Una fuente indica la tarjeta que alimenta. Una tarjeta tiene como máximo una fuente, y una organización admite hasta 200 en todos sus proyectos.
- Se ejecuta según una programación. Una fuente de calendario se sincroniza cada 5 minutos, y cada fuente puede ajustarse entre 1 minuto y 24 horas. Una fuente se ejecuta a los pocos segundos de crearse o cambiarse, y
source refreshla sincroniza al instante. - Una sincronización fallida nunca modifica la tarjeta. La tarjeta conserva su último documento válido y el estado de la fuente indica qué falló. Los fallos se reintentan solos, con una espera mayor tras cada uno.
- Solo se escriben los cambios. Cuando una sincronización encuentra lo que la tarjeta ya contiene, no se escribe nada y las pantallas no se activan.
- Las sincronizaciones son gratuitas. Los documentos cuentan para el almacenamiento de datos de tarjetas como cualquier otra escritura.
- Las credenciales se guardan cifradas. Una dirección que da acceso se almacena cifrada, se devuelve solo con su esquema y su host, y nunca aparece en un registro, un error ni el registro de eventos del proyecto.
- Conserva los últimos datos buenos durante el periodo que elijas. Cuando una fuente no puede actualizarse, su tarjeta conserva los últimos datos buenos durante el periodo de caducidad de la fuente (
--stale-after, de 1 minuto a 7 días; una fuente de reservas de recinto los conserva 30 minutos); después los datos caducan en todas las pantallas, también las que están sin conexión, y las páginas que dependen de ellos pasan a las páginas siguientes. Sin periodo, los últimos datos buenos permanecen hasta que la fuente vuelve a actualizarse. Consulta Cuando una fuente no puede actualizarse.
Empezar con una opción predefinida
Una opción predefinida es una fuente ya preparada para un servicio que la gente suele poner en una pantalla. Elija una, rellene unos pocos campos, añada la credencial que emite el servicio, y screenRIG crea la fuente y adapta la respuesta a la tarjeta. Las opciones predefinidas son fuentes json, que todos los planes incluyen.
| Opción predefinida | Tarjeta | Qué necesita |
|---|---|---|
slack-channel | workplace-posts, message-wall | El ID del canal y el token de bot (xoxb-…) de una aplicación interna de Slack en su espacio de trabajo: en api.slack.com/apps añada los ámbitos channels:history y groups:history, instale la aplicación y luego añádala al canal |
bonusly | kudos | Un token de acceso de Bonusly con recognition:read, que un administrador Global o Tech crea en Company, Integrations, API & Tokens |
facebook-page | social-wall | El ID de la página, el nombre que se mostrará y un token de acceso de página con pages_read_engagement y pages_show_list del Explorador de la API Graph |
instagram-business | social-wall | El ID de la cuenta de Instagram, el nombre que se mostrará y el token de acceso de la página de Facebook vinculada, con instagram_basic, pages_show_list y pages_read_engagement |
google-reviews | reviews | El ID del lugar y una clave de API de Google Cloud con la API Places (New) habilitada |
google-travel-times | travel-times | Una dirección de partida, de uno a ocho destinos, en coche o en transporte público, y una clave de API de Google Cloud con la API Routes habilitada |
greenhouse-jobs | now-hiring | El token del tablero de boards.greenhouse.io/TOKEN. Sin credencial: el tablero es público |
lever-jobs | now-hiring | El nombre del sitio de jobs.lever.co/NAME y la región. Sin credencial |
ashby-jobs | now-hiring | El nombre del tablero de jobs.ashbyhq.com/NAME. Sin credencial |
github-actions | build-board | El propietario, el repositorio y la rama, y un token de acceso personal de granularidad fina con acceso de solo lectura a las Actions de ese repositorio, de github.com/settings/personal-access-tokens |
El panel, su agente y la API listan las opciones predefinidas, con la ayuda y el ejemplo de cada campo y los pasos para obtener cada credencial: GET /api/source-presets las devuelve todas y GET /api/source-presets/NAME una (el grupo Fuentes de datos de la referencia de la API). Cree una fuente a partir de una opción predefinida con preset, settings y secrets en lugar de kind y config. Guarde la credencial en el archivo de la solicitud, no en la línea de comandos, y sustituya BOT_TOKEN por el token:
{
"name": "Announcements",
"preset": "slack-channel",
"target": {"card_id": "crd_CARD"},
"settings": {"channel": "C0123456789", "channel_label": "#announcements"},
"secrets": {"token": "BOT_TOKEN"}
}curl -sS https://api.screenrig.ai/api/sources/test \
-H "Authorization: Bearer $SCREENRIG_TOKEN" -H "Content-Type: application/json" -d @source.jsonPOST /api/sources/test imprime el documento que mostraría la tarjeta, si la tarjeta lo acepta y lo que observó, y no escribe nada. POST /api/sources guarda el mismo archivo, y PATCH /api/sources/ID con nuevos settings vuelve a crear la fuente a partir de la opción predefinida.
- Su cuenta, sus condiciones. Una opción predefinida lee su propia cuenta con una credencial que usted crea, bajo las condiciones del servicio, y la tarjeta muestra lo que esas condiciones exigen: las reseñas de Google aparecen con la marca de Google y el nombre de cada autor.
- Horario y caducidad. Cada opción predefinida fija su propio intervalo y su propio periodo de caducidad, por ejemplo un minuto y 15 minutos para Slack, o 6 horas y 24 horas para las reseñas de Google. Una fuente puede elegir otro intervalo, nunca uno más corto que el mínimo de su opción predefinida. Cuando una sincronización falla, la tarjeta conserva sus últimos datos hasta que pasa el periodo de caducidad y luego queda en blanco.
- Facturación en el servicio. Cada actualización de las reseñas de Google es una solicitud Place Details en su proyecto de Google Cloud, y cada actualización de los tiempos de trayecto de Google es un elemento de ruta por cada destino: cuatro destinos cada 15 minutos son unos 11 500 elementos al mes.
- Slack necesita una aplicación interna. No la distribuya: Slack limita a una solicitud por minuto una aplicación distribuida fuera de su Marketplace. La aplicación solo lee los canales a los que se añadió, y la tarjeta muestra los mensajes propios de las personas, no las incorporaciones, las publicaciones de bots ni los avisos del canal.
Crear una fuente
Cree primero la tarjeta, luego haga una vista previa y después guarde.
screenrig card create --type events --file events.json
screenrig source test --kind ics --card crd_CARD \
--set 'calendars=[{"key":"lobby"}]' --set time_zone=America/Vancouver \
--secret calendar_url.lobby=@lobby.url
screenrig source create --kind ics --card crd_CARD --name "Lobby calendar" \
--set 'calendars=[{"key":"lobby"}]' --set time_zone=America/Vancouver \
--secret calendar_url.lobby=@lobby.url
screenrig source show src_SOURCEsource test obtiene la dirección, la adapta a la tarjeta y comprueba el resultado con la tarjeta, sin guardar ni escribir nada. Muestra el documento, si la tarjeta lo acepta y lo que ha observado por el camino. Indique la dirección en un archivo (@FILE) o por la entrada estándar (-) para que no quede en el historial de su shell.
| Comando | Qué hace |
|---|---|
source list, source show ID | Las fuentes del proyecto, con su estado, ajustes y secretos enmascarados |
source create | Guarda una fuente y la ejecuta en unos segundos |
source update ID | Cambia el nombre, la tarjeta, los ajustes (--set KEY=VALUE o --settings JSON), los secretos (--secret, --unset-secret), la programación (--refresh 10m) o --enable y --disable |
source test | Hace una vista previa de una fuente, guardada o no, sin escribir nada |
source refresh ID | Sincroniza al instante y muestra el resultado |
source delete ID | Elimina la fuente; la tarjeta conserva su último documento |
--settings recibe toda la configuración de la fuente como JSON, @FILE o -. La opción --config de la CLI indica su archivo de credenciales y no tiene nada que ver con las fuentes.
Cuando una fuente no puede actualizarse
Una fuente escribe cada documento con un plazo: su periodo de caducidad después de la escritura, que se renueva mientras la fuente sigue actualizándose. Mientras la fuente funciona, el plazo se va desplazando. Cuando falla, la tarjeta sigue mostrando los últimos datos buenos hasta el plazo, y entonces los datos caducan en todas las pantallas, también las que están sin conexión.
- Define el periodo con
--stale-after 30mensource createosource update, de 1 minuto a 7 días y como mínimo el doble del intervalo de actualización.--stale-after noneconserva los últimos datos buenos hasta la próxima actualización. Una fuente de reservas de recinto (momentus) los conserva 30 minutos salvo que indiques otra cosa; los demás tipos los conservan hasta la próxima actualización. - Recurrir a tu propio contenido. Una página cuya condición
visibility.datanombra el documento (para una sala,momentus-room-{screen.field.room}) se muestra mientras los datos están y cede el paso a la página siguiente cuando caducan. Deja después una página normal, con tu propia marca, como respaldo. - Consultarlo.
source showmuestrastale_after,data_expires_aty, cuando los datos han caducado mientras la fuente sigue fallando,stale: true. La página Fuentes de datos del panel muestra lo mismo: una fuente con fallos aparece como Con fallos, y una cuyos datos han caducado como Caducada. - Recibir avisos. Una notificación sobre las condiciones
source_failed(falló una actualización) ysource_stale(los datos caducaron) envía un correo o publica en Slack, Teams, PagerDuty o Telegram, como para una pantalla:screenrig notifications create --email owner --conditions source_failed,source_stale --hold 5. Un aviso nombra la fuente y enlaza su página, se cierra cuando una actualización funciona, y--tagnunca coincide con una fuente.
Estado y errores
Cada fuente muestra su estado: cuándo se ejecutó por última vez, cuándo tuvo éxito y cuándo cambió la tarjeta por última vez, cuándo se ejecutará de nuevo, cuántas sincronizaciones seguidas han fallado y el último error.
| Estado | Significado |
|---|---|
pending | La fuente aún no se ha ejecutado |
ok | La última obtención se completó y la tarjeta aceptó el documento |
error | La última sincronización falló; la tarjeta conserva su último documento válido |
disabled | La programación está detenida |
ok no juzga si los datos de origen son correctos o actuales, ni si una pantalla muestra la tarjeta.
| Código de error | Qué ocurrió |
|---|---|
unreachable | screenRIG no pudo acceder a la dirección. Use una dirección http(s) pública en el puerto 80 o 443 |
timeout | La dirección no respondió en 20 segundos |
too_large | La respuesta supera los 5 MB |
http_status | La dirección respondió con un error HTTP. Un 404 significa que la dirección ya no es correcta |
auth_failed | La dirección rechazó las credenciales; el siguiente intento espera una hora |
not_shared | Una hoja de Google no está compartida: Google respondió con una página de inicio de sesión, un 401 o un 403. Compártala con Cualquier persona que tenga el enlace, o publíquela en la web |
parse_failed | La respuesta no es un calendario. Una página de inicio de sesión se lee como una página web, no como un calendario: use la dirección ICS del calendario |
rate_limited | El servicio está limitando las solicitudes; la siguiente sincronización espera |
mapping_failed | El mapeo no pudo leer la respuesta en el lugar que nombra el mensaje, por ejemplo un rows_path que no encuentra ninguna matriz |
card_data_invalid | La tarjeta rechazó el documento en la ruta que indica el mensaje |
target_missing | Se eliminó la tarjeta. Apunte la fuente a otra tarjeta |
payment_required | El almacenamiento del proyecto está lleno, así que no se escribió el documento |
config_invalid | Un ajuste o un secreto almacenado ya no se puede usar. Introdúzcalo de nuevo |
internal | La sincronización falló dentro de screenRIG y se reintenta |
Crear o cambiar una fuente puede responder source_target_taken (la tarjeta ya tiene una fuente), source_target_unsupported (el tipo no puede rellenar esa tarjeta; la respuesta indica las tarjetas posibles), source_secret_required (falta un secreto, o se introdujo para otra dirección y debe introducirse de nuevo), source_limit_reached y source_busy (hay una sincronización en curso; reintente tras el intervalo). source test responde source_test_failed con el motivo cuando no se puede leer la dirección.
Calendarios
Una fuente de calendario lee direcciones iCalendar (ICS): la dirección secreta que Google Calendar, Outlook, iCloud y Nextcloud dan para un calendario, y cualquier enlace webcal://. Rellena una tarjeta events con una agenda de todos los calendarios, o una tarjeta study-rooms con una sala por calendario.
| Configuración | Significado |
|---|---|
calendars | De 1 a 60 calendarios, cada uno con {key, name, floor, capacity}. La clave admite letras minúsculas, dígitos, - y _; el nombre, la planta y la capacidad describen una sala |
days | Cuántos días mostrar a partir de hoy, de 1 a 31 (7 por defecto) |
time_zone | Una zona horaria IANA como America/Vancouver, que se usa para el límite del día y para las horas que un feed deja sin zona |
private_title | El título que se muestra para los eventos privados (por defecto Private) |
include, exclude | Palabras clave que conservan u ocultan eventos según el título: vea Conservar u ocultar eventos por palabra clave |
Cada calendario tiene un secreto, calendar_url.KEY, que contiene su dirección.
- Los eventos recurrentes (reglas diarias, semanales, mensuales y anuales, excepciones, repeticiones movidas y canceladas) y las zonas horarias se expanden en el servidor, de modo que un evento conserva su hora con el cambio de horario y una tarjeta nunca repite las reglas del calendario. Se reconocen los nombres de zona horaria de Windows que usa Outlook.
- Los eventos privados (
CLASS:PRIVATEoCONFIDENTIAL) muestran solo sus horarios, con el título privado y sin organizador ni lugar. La regla cubre los marcados como privados y no juzga lo que revelan los demás eventos. - El tiempo libre (eventos marcados como transparentes o libres) se conserva en una agenda y se omite en un panel de salas, donde solo cuenta el tiempo ocupado. Los eventos cancelados se descartan y los provisionales cuentan como ocupados.
- Los eventos de todo el día se muestran como fechas; un evento sin final no muestra final.
- Advertencias. Cuando un feed no indica zona horaria, usa una que screenRIG no reconoce, o contiene más de 500 repeticiones de un evento o más de 5000 eventos, la sincronización se completa y el estado muestra una advertencia.
- Varios calendarios se sincronizan juntos: si uno falla, falla toda la sincronización y el error nombra el calendario, de modo que un panel nunca muestra un conjunto parcial.
Conservar u ocultar eventos por palabra clave
Las fuentes ics, microsoft365, google_calendar y momentus aceptan dos ajustes opcionales, include y exclude, cada uno una lista de 1 a 20 palabras clave de 1 a 100 caracteres. Un evento se conserva cuando su título contiene al menos una palabra clave de include (si include está definido) y ninguna de las de exclude. Una palabra clave coincide dentro de un título sin distinguir mayúsculas ni acentos, así que café y CAFE coinciden entre sí.
- Solo el título. La ubicación, el organizador y la descripción nunca se comparan. Un evento sin título se compara como
Untitled event. - Los eventos privados se comparan por su propio título y siguen mostrando el título privado. El título privado en sí nunca se compara, así que
exclude: ["private"]no elimina nada. - Todo lo que escribe la fuente lee los calendarios filtrados: la tarjeta y cada documento de sala por clave. Un filtro elimina solo eventos, nunca un calendario ni una sala, y los eventos libres cuentan como los demás.
- El estado cuenta lo que se dejó fuera como
filtered, incluido el 0. Cuando la ventana contiene eventos y las palabras clave no dejan ninguno, la sincronización se completa con una advertencia que pide revisarlas, y la tarjeta muestra una lista vacía.source testmuestra lo mismo.
screenrig source create --kind ics --card crd_EVENTS --name "Public events" \
--set 'calendars=[{"key":"main"}]' --set 'include=["open house","tour"]' --set 'exclude=["cancelled"]' \
--secret calendar_url.main=@calendar.urlHojas, CSV y JSON
Una fuente sheets, csv o json lee una tabla o un documento JSON y crea con ello los datos de una tarjeta mediante un mapeo, de modo que sirve para cualquier tarjeta: un menú a partir de una lista de precios, un panel de indicadores a partir de una hoja de métricas, una tabla a partir de una hoja de clasificación. El mapeo es una plantilla JSON en los ajustes de la fuente. Las reglas propias de la tarjeta deciden si se acepta lo que genera el mapeo, y source test muestra el documento y si la tarjeta lo acepta, así que edita el mapeo hasta que lo haga. Estas fuentes se sincronizan cada 5 minutos, y cada minuto como mínimo.
screenrig source test --kind sheets --card crd_MENU --settings @menu-sheet.json
screenrig source create --kind sheets --card crd_MENU --name "Cafe menu" --settings @menu-sheet.json
screenrig source create --kind json --card crd_KPI --name "Daily numbers" \
--settings @kpi-api.json --secret token=@api.token| Configuración | Tipos | Significado |
|---|---|---|
url | todo | El enlace de la hoja, o la dirección del archivo CSV o del documento JSON: una dirección http(s) pública en el puerto 80 o 443 |
mapping | todo | La plantilla que genera los datos de la tarjeta. Obligatorio |
key_template | todo | Clave opcional con marcadores {screen.field.NAME}; la transformación devuelve un arreglo documents de {fields,document} |
sheet | sheets | El nombre de una pestaña, para leer una pestaña distinta de la que nombra el enlace |
header_row | sheets, csv | true (predeterminado) cuando la primera fila contiene los nombres de las columnas; false cuando todas las filas son datos, con los nombres Column 1, Column 2 |
key_column | sheets, csv | La columna cuyas celdas nombran las filas, para que el mapeo pueda buscar una fila por su nombre |
delimiter | csv | ,, ; o tab. De forma predeterminada, el que más usa la primera línea |
auth | csv, json | none (predeterminado), bearer, header, basic, oauth2 o token_request: vea Solicitudes, inicio de sesión y páginas |
header_name | csv, json | Con auth header, el encabezado que lleva el token, por ejemplo X-API-Key |
rows_path | json | Dónde está la matriz de filas en la respuesta, por ejemplo data.items |
key_field | json | El miembro de cada fila que la nombra. Establézcalo junto con rows_path |
Compartir una hoja de Google
Una fuente sheets lee la hoja mediante la exportación CSV de Google. No necesita iniciar sesión ni acceder a su cuenta de Google, y la hoja debe poder leerla cualquiera que tenga su enlace.
- En Google Sheets elija Compartir, establezca el Acceso general en Cualquier persona que tenga el enlace y el rol en Lector. Para publicar en su lugar, elija Archivo, Compartir, Publicar en la Web.
- Copie el enlace de la barra de direcciones del navegador en
url. Un enlace a una pestaña conserva esa pestaña. Para leer otra pestaña por su nombre, establezcasheet; un enlace publicado no admitesheet. - Haga una vista previa con
source test. La fila de encabezado de la hoja se convierte en las claves de columna que lee el mapeo.
Una hoja que no está compartida responde con una página de inicio de sesión, un 401 o un 403. El estado es entonces not_shared, y el mensaje nombra el ajuste que hay que cambiar: Compartir, Acceso general, Cualquier persona que tenga el enlace, Lector, o Archivo, Compartir, Publicar en la Web. Pida al propietario de la hoja que la comparta. not_shared solo juzga esas tres respuestas. No compara las columnas con su mapeo.
Direcciones con token
Un archivo CSV o un documento JSON en una dirección pública no necesita token. Para uno protegido, establezca auth en bearer (screenRIG envía Authorization: Bearer TOKEN) o en header con header_name (envía HEADER_NAME: TOKEN), y entregue el token como el secreto token:
screenrig source create --kind csv --card crd_TABLE --name "Standings" \
--settings @standings.json --secret token=@api.tokenEl token se almacena cifrado y solo se muestra como una pista: sus últimos cuatro caracteres si tiene 12 o más, y en caso contrario …. Se envía únicamente al origen de la propia dirección: el esquema, el host y el puerto. Una redirección a otro sitio no se sigue con el token, y apuntar la fuente a otro origen sin volver a introducir el token se rechaza con source_secret_required. Cambiar solo la ruta o la consulta conserva el token. Para basic, OAuth 2 y las solicitudes de token, y para una solicitud con cuerpo, encabezados o páginas, vea Solicitudes, inicio de sesión y páginas. header_name no puede ser Host, Cookie, Content-Length, Connection, Transfer-Encoding, Upgrade ni un encabezado Proxy-, ni un encabezado que screenRIG establece por sí mismo.
Solicitudes, inicio de sesión y páginas
Una fuente csv o json envía un GET a su url. Estos ajustes envían un cuerpo o encabezados adicionales, inician sesión, leen más de una página y ponen la fecha de hoy en una solicitud. Cada solicitud tiene 20 segundos y una ejecución completa tiene 60.
| Configuración | Significado |
|---|---|
method | GET (predeterminado) o POST. Un body o un graphql lo convierte en POST |
body | Un objeto o matriz JSON, o texto enviado tal cual. Como máximo 16 KiB una vez rellenados sus marcadores |
body_format | json (predeterminado) o form. Un cuerpo de formulario es un objeto de campos de texto, número y booleanos, o un texto como a=1&b={{today}}; los valores se codifican para URL |
graphql | {query, variables}, enviado como un POST JSON. Una respuesta con errores y sin datos es parse_failed; los errores junto a datos son una advertencia |
headers | Hasta 8 encabezados adicionales cuyos valores no son secretos. Authorization se rechaza, y también cualquier encabezado que header_name rechace: use auth o un secreto de encabezado |
time_zone | Una zona IANA para los marcadores de fecha. Sin ella se leen en UTC y el estado muestra una advertencia |
pagination | Lee más de una página, como se describe abajo |
format | Solo el tipo json: auto (predeterminado), json, csv o xml |
Un secreto llamado header.NAME se envía como el encabezado NAME, así que una API con dos encabezados de credenciales usa header.X-Client-Id y header.X-Api-Key. Un secreto llamado query.NAME se añade a la dirección como NAME=value. Cada tipo admite hasta 8, ambos se almacenan sellados y nunca se muestran, y la vista previa muestra un secreto de consulta como NAME=***.
| Autenticación | Ajustes y secretos |
|---|---|
none | El valor predeterminado |
bearer | El secreto token, enviado como Authorization: Bearer |
header | header_name y el secreto token |
basic | username (sin dos puntos) y el secreto password, enviados como Authorization: Basic |
oauth2 | Credenciales de cliente: token_url, client_id, scope y audience opcionales, token_auth (body, el predeterminado, o basic) y el secreto client_secret. screenRIG pide un token a token_url y lo envía como Authorization: Bearer |
token_request | Un inicio de sesión que devuelve un token: token_url, token_body (un objeto cuyas cadenas pueden leer los secretos almacenados como {{secrets.NAME}}), token_body_format (json o form), token_path (dónde está el token en la respuesta, como token.accessToken) y, opcionalmente, token_expires_path, token_ttl (de 60 a 86 400 segundos, 3600 por defecto) y header_name (el encabezado que lleva el token tal cual; sin él, Authorization: Bearer) |
screenRIG guarda un token en memoria, nunca en almacenamiento, y lo renueva un minuto antes de que caduque. Cuando la dirección rechaza un token con un 401, pide uno nuevo una vez. Un rechazo en la dirección del token (HTTP 400, 401 o 403) es auth_failed, y nada de lo que dice la dirección del token se cita.
{
"url": "https://api.example.com/v2/orders/summary",
"method": "POST",
"body": {"from": "{{today-7d}}", "to": "{{today}}"},
"time_zone": "America/Vancouver",
"auth": "oauth2",
"token_url": "https://login.example.com/oauth/token",
"client_id": "screen-signs",
"scope": "orders.read",
"mapping": {"body": "{{body.total}} orders this week"}
}screenrig source create --kind json --card crd_BOARD --name "Orders" \
--settings @orders.json --secret client_secret=@client.secretLos marcadores de fecha rellenan la dirección, el cuerpo y headers: {{now}} (2026-11-01T17:30:00Z), {{today}} (2026-11-01) y {{unix}} (segundos), cada uno con un desfase opcional como {{now-90m}}, {{now+7d}} o {{today-1d}} (unidades m, h y d; {{today}} solo admite días). Se leen en time_zone, o en UTC. Cada ejecución los rellena con el reloj, así que la ejecución de mañana pide la fecha de mañana.
Páginas. pagination es {type, max_pages}, con max_pages de 1 a 20 (5 por defecto). Una fuente json define rows_path para que las filas de las páginas se unan en una sola matriz, y una fuente csv une las filas de la tabla.
| Tipo | Cómo se encuentra la página siguiente |
|---|---|
link_header | La dirección rel="next" del encabezado Link |
next_url | path, el lugar de la respuesta que contiene la dirección siguiente (solo json) |
cursor | param y path: el cursor va en la dirección como param, o en el cuerpo con "in": "body", y la lectura termina cuando el cursor falta o está vacío (solo json) |
page | param, start (1 por defecto) y size_param con size: el número de página va en la dirección o, con "in": "body", en el cuerpo, y la lectura termina en una página sin filas o con menos de size |
La dirección siguiente debe permanecer en el origen de la propia fuente, así que un secreto nunca sale de él. Una página repetida, o más páginas que max_pages, termina la lectura con una advertencia, y todas las páginas juntas pesan como máximo 5 MB.
XML y RSS. Una respuesta que empieza por <, o format xml, se lee como XML. body contiene el elemento raíz: los atributos son @name, el texto de un elemento que tiene hijos es #text, los elementos repetidos son listas y los nombres conservan su prefijo (item["media:thumbnail"]["@url"]). Un feed RSS o Atom también recibe body.items, cada entrada con title, link, published, summary (texto sin formato, hasta 1000 caracteres) y image, cuando la entrada los tiene. Un DOCTYPE nunca se sigue y no se obtiene nada de él.
source test muestra en request la primera solicitud tal como salió: los marcadores rellenados, los secretos de consulta como NAME=***, los nombres de los encabezados distintos de Accept y Content-Type sin sus valores, el primer KiB del cuerpo y el número de páginas leídas.
Qué lee una fuente
- CSV y hojas. CSV común: se leen la marca de orden de bytes, los campos entre comillas, las comillas dobles, los saltos de línea dentro de comillas y los finales de línea CRLF. Las celdas se recortan y las filas sin contenido se descartan. Un encabezado se convierte en una clave en minúsculas, sin acentos y con cada serie de otros caracteres convertida en un solo
_, de modo queSold outpasa a sersold_out; un encabezado vacío se convierte encolumn_3(su posición) y uno repetido en_2,_3. Un archivo que no es texto UTF-8, como un archivo de hoja de cálculo, esparse_failed: guárdelo como CSV en UTF-8. - JSON. Los números conservan sus dígitos. Con
rows_pathla fuente busca allí la matriz de filas; una ruta que no encuentra ninguna matriz esmapping_failedenrows_path, y una matriz vacía es una tabla sin filas. - Límites. Una tabla se lee hasta 10 000 filas y 200 columnas. Más allá, la sincronización tiene éxito y el estado muestra una advertencia que cuenta las filas o columnas omitidas.
- Una página web en la dirección, en lugar de los datos, es
parse_failed.
El mapeo
El mapeo es una plantilla JSON. Una cadena con marcadores como {{item.price}} es texto, y una cadena que es exactamente un solo marcador conserva el tipo del valor. Una ruta que no contiene nada queda vacía en un texto y omite un valor suelto, de modo que la tarjeta nombra entonces lo que le falta. Desde dónde puede empezar una ruta depende del tipo:
| Tipo | Punto de partida | Contiene |
|---|---|---|
sheets, csv | rows | Cada fila de datos, un objeto por clave de columna |
sheets, csv | columns | [{key, name}] en el orden de la hoja |
sheets, csv | by_key | Con key_column: las filas según el texto recortado de la celda de esa columna |
json | body | Toda la respuesta |
json | by_key | Con rows_path y key_field: las filas según el texto, número o booleano recortado de ese miembro |
Prefiera by_key a una posición como rows[2]: una fila encontrada por su clave sigue encontrándose cuando alguien ordena la hoja o inserta una fila encima. Escriba una clave con espacios así: by_key["Net sales"].value. Si dos filas comparten una clave, gana la primera y el estado muestra una advertencia que cuenta las repeticiones. Ninguna advertencia cita una celda.
Las celdas son texto, así que conviértalas: {"$number": "{{item.price}}"} lee 1,234.50, $4.50, 3,50 € y 12% (añada "$decimal": "," para una coma decimal), y {"$bool": "{{item.sold_out}}"} lee true, yes, y, 1 y x. $each recorre una lista con item y index disponibles, $group con $by agrupa las filas en el orden de primera aparición con group.key y group.items disponibles, y $text con $max recorta el texto. La plantilla se comprueba al guardar la fuente.
Un menú a partir de una hoja con las columnas Section, Item, Price y Sold out agrupa las filas por sección:
{
"url": "https://docs.google.com/spreadsheets/d/SHEET_ID/edit#gid=0",
"mapping": {
"sections": {
"$group": "{{rows}}", "$by": "{{item.section}}",
"$template": {
"name": "{{group.key}}",
"items": {
"$each": "{{group.items}}",
"$template": {
"name": "{{item.item}}",
"price": { "$number": "{{item.price}}" },
"soldOut": { "$bool": "{{item.sold_out}}" }
}
}
}
}
}
}Un panel de indicadores a partir de una hoja con las columnas Metric, Value, Unit y Change busca cada métrica por su nombre, así que ordenar la hoja no mueve nada:
{
"url": "https://docs.google.com/spreadsheets/d/SHEET_ID/edit#gid=0",
"key_column": "Metric",
"mapping": {
"tiles": [
{ "label": "Revenue", "value": { "$number": "{{by_key.Revenue.value}}" },
"unit": "{{by_key.Revenue.unit}}", "delta": { "$number": "{{by_key.Revenue.change}}" } },
{ "label": "Orders", "value": { "$number": "{{by_key.Orders.value}}" },
"delta": { "$number": "{{by_key.Orders.change}}" } }
]
}
}Una tarjeta de tabla muestra todas las filas:
{
"mapping": {
"rows": {
"$each": "{{rows}}", "$limit": 50,
"$template": {
"team": "{{item.team}}",
"points": { "$number": "{{item.points}}" },
"played": { "$number": "{{item.played}}" }
}
}
}
}Para ver qué lee una fuente, pruebe con el mapeo {"columns": "{{columns}}", "rows": "{{rows}}"}. La tarjeta rechaza ese documento, y la vista previa lo muestra igualmente, con cada clave y cada fila.
ok en una de estas fuentes significa que la dirección respondió y la tarjeta aceptó el documento generado por el mapeo. No indica que la hoja o la respuesta contenga las filas que espera su mapeo: una columna que desaparece deja fuera su miembro, y la tarjeta rechaza un documento al que le falta uno obligatorio.
Valores calculados
Un mapeo también puede calcular verdadero o falso y números en el servidor, así que una condición de página que solo comprueba igualdad, como visibility.data con equals: true, puede seguir un número. Los mapeos de webhooks de tarjeta y de activadores de superposición tienen las mismas funciones.
| Función | Devuelve | Escritura |
|---|---|---|
$gt, $gte, $lt, $lte | Verdadero o falso, leyendo ambos valores como números | {"$lt": ["{{body.stock}}", 5]} |
$between | Verdadero cuando el valor está dentro de ambos límites, inclusive | {"$between": ["{{body.temp}}", 18, 24]} |
$eq, $ne | Números por valor (5, "5" y "5.00" coinciden), todo lo demás como texto exacto, con mayúsculas y minúsculas | {"$eq": ["{{body.status}}", "open"]} |
$contains | Un texto contiene otro texto, sin distinguir mayúsculas, o una lista contiene un valor | {"$contains": ["{{body.title}}", "closed"]} |
$in | El valor es uno de una lista | {"$in": ["{{body.tier}}", ["gold", "silver"]]} |
$and, $or, $not | Combinan condiciones | {"$and": [{"$gt": ["{{body.a}}", 1]}, {"$not": {"$eq": ["{{body.s}}", "x"]}}]} |
$sum, $avg, $min, $max | Un número a partir de una lista | {"$sum": "{{rows}}", "$of": "{{item.amount}}"} |
$count | Cuántos elementos hay, o cuántos cumplen $where | {"$count": "{{body.queue}}", "$where": {"$gt": ["{{item.wait}}", 5]}} |
- Una comparación que no puede hacerse es falsa, con una advertencia que nombra el lugar y nunca el valor, así que un valor ausente, vacío o no numérico nunca activa una página.
$booles el único lector que toma un valor ausente como falso. - Listas.
$oflee un marcador de cada elemento, conitemyindexdisponibles, y$whereconserva los elementos para los que se cumple una condición. Un elemento vacío o que no es un número se omite, y una advertencia los cuenta. Si no hay nada que sumar,$sumy$countvalen 0, y$avg,$miny$maxomiten su miembro. - Números. Una coma decimal (
3,50,1.234,50) necesita"$decimal": ",".$avgredondea a 2 decimales, y"$round"fija de 0 a 6.$sum,$miny$maxson exactos.
Un indicador de poco stock a partir de una respuesta JSON. Una página cuyo visibility.data nombra el documento con path /low_stock y equals true se muestra solo mientras hay poco stock:
{
"sku": "{{body.sku}}",
"stock": {"$number": "{{body.stock}}"},
"low_stock": {"$lt": ["{{body.stock}}", 5]}
}A partir de una hoja, cualquier producto por debajo de su propio nivel de reposición:
{"low_stock": {"$gt": [{"$count": "{{rows}}", "$where": {"$lt": ["{{item.stock}}", "{{item.reorder_at}}"]}}, 0]}}Documentos por clave
Las fuentes JSON, CSV y Sheets aceptan key_template, por ejemplo room-{screen.field.room}. Transforma el feed en un arreglo documents de objetos {"fields":{"room":"A101"},"document":{"body":"Room A101"}}. Un webhook de tarjeta usa --key-template con la misma salida, o recibe el objeto contenedor directamente sin transformación.
{
"key_template": "room-{screen.field.room}",
"mapping": {
"documents": {
"$each": "{{rows}}",
"$template": {
"fields": {"room": "{{item.room}}"},
"document": {"body": "{{item.title}}"}
}
}
}
}Coloca la instancia crd_ correspondiente con data: "room-{screen.field.room}"; cada pantalla lee solo la clave formada con su propio campo room. Todas las salidas usan el esquema de tarjeta de la instancia. Usa instancias, transformaciones y prefijos separados para distintos tipos de tarjeta que lean el mismo feed.
Previsualiza con source test. Los documentos no válidos, los campos ausentes y las claves duplicadas rechazan el lote antes de escribir. Un fallo de almacenamiento puede dejar una parte escrita: reintenta el mismo cuerpo del webhook con el mismo Idempotency-Key, o actualiza la fuente. Las claves omitidas conservan sus datos y su vencimiento anteriores; los webhooks no establecen vencimiento. Borra la plantilla de un webhook con --clear-key-template.
Consejos para archivos y hojas
- OneDrive y SharePoint. Un enlace para compartir abre una página de vista previa, que una fuente lee como una página web (
parse_failed). Añada?download=1al enlace de un archivo CSV, o&download=1si ya tiene un?, para que el enlace devuelva el archivo mismo. El enlace debe funcionar sin iniciar sesión. - Busque filas por nombre. Establezca
key_columnen la columna que da nombre a cada fila, por su encabezado sin distinguir mayúsculas, y lea una fila comoby_key.NAME.column: ordenar la hoja o insertar una fila no cambia nada. Un nombre que no coincide con ninguna columna damapping_failedenkey_column, y una clave repetida conserva la primera fila con una advertencia que cuenta las repeticiones.
Salas de reuniones
Una fuente de salas lee calendarios de salas de reuniones y alimenta una tarjeta room, el cartel de puerta de una sala, o una tarjeta room-board, todas las salas de un edificio. También puede alimentar una agenda events o una tarjeta study-rooms, y una dirección de calendario (ICS) alimenta las mismas tarjetas.
Las tarjetas calculan en la pantalla, cada segundo, si una sala está libre, en uso o qué viene después, a partir de las reservas que tienen: un cartel sigue siendo correcto aunque su pantalla esté sin conexión. Una fuente de salas solo lee: una tarjeta muestra reservas y no admite entradas, así que desde una pantalla no se reserva, termina ni registra nada.
| Configuración | Significado |
|---|---|
rooms | De 1 a 60 salas, cada una con una key (letras minúsculas, dígitos, - y _), la dirección de la sala (email en Microsoft 365, calendar_id en Google) y, opcionalmente, name, floor y capacity. Una tarjeta room admite exactamente una sala |
days | Cuántos días mostrar a partir de hoy, de 1 a 31 (7 por defecto) |
time_zone | Una zona IANA como America/Los_Angeles, que se usa para el límite del día y para los eventos de todo el día. Sin ella, el día empieza a medianoche UTC y el estado muestra una advertencia |
private_title | El título que se muestra para los eventos privados (por defecto Private) |
Buzones de sala de Microsoft 365
El tipo microsoft365 lee los buzones de sala de Exchange Online con tu propia aplicación de Microsoft Entra, de modo que la aplicación, su secreto y lo que puede leer siguen siendo tuyos. Dos ajustes más: tenant, el ID del directorio o un dominio verificado como contoso.com (common, organizations y consumers se rechazan), y client_id, el ID de aplicación (cliente) de la aplicación. El secreto client_secret es el valor del secreto de cliente de la aplicación.
- En el centro de administración de Microsoft Entra, registra una aplicación de un solo inquilino sin URI de redirección, agrega un secreto de cliente (copia su valor, no su ID de secreto), agrega el permiso de aplicación de Microsoft Graph
Calendars.Ready concede el consentimiento del administrador. - Limita la aplicación a los buzones de sala.
Calendars.Readllega a todos los buzones de la organización hasta que una directiva de acceso de aplicaciones lo restringe. Pon las salas en un grupo de seguridad habilitado para correo y ejecuta los dos primeros comandos de abajo en Exchange Online PowerShell;Test-ApplicationAccessPolicyrespondeGrantedpara una sala del grupo. El RBAC de Exchange para aplicaciones limita una aplicación del mismo modo. - Los buzones de sala sustituyen el asunto de una reunión por el nombre del organizador, salvo que se indique otra cosa. Para mostrar los títulos de las reuniones, ejecuta el tercer comando para cada sala.
- Haz una vista previa y luego guarda.
source testinicia sesión, lee cada sala e informa de las salas y reservas leídas, un recuento por sala y, si la aplicación también tienePlace.Read.All, cuántas salas lista la organización.
# Exchange Online PowerShell
New-ApplicationAccessPolicy -AppId CLIENT_ID -PolicyScopeGroupId rooms@example.com -AccessRight RestrictAccess -Description "screenRIG room signs"
Test-ApplicationAccessPolicy -AppId CLIENT_ID -Identity boardroom@example.com
Set-CalendarProcessing -Identity boardroom@example.com -DeleteSubject $false -AddOrganizerToSubject $false
# screenRIG (source create takes the same options, plus --name)
screenrig source test --kind microsoft365 --card crd_ROOM \
--set tenant=contoso.com --set client_id=CLIENT_ID --set time_zone=America/Los_Angeles \
--set 'rooms=[{"key":"boardroom","email":"boardroom@example.com","name":"Boardroom","floor":"Level 4","capacity":12}]' \
--secret client_secret=@secret.txt- Correspondencia. Las reuniones privadas y confidenciales muestran el título privado y ningún organizador. Las reuniones marcadas como libres o trabajando en otro lugar, y las que la sala rechazó, son tiempo libre; las provisionales cuentan como ocupadas; las canceladas se descartan. Los eventos de todo el día son fechas en la zona horaria de la sala.
- Frecuencia. Una fuente de salas se sincroniza cada 2 minutos. El inicio de sesión dura alrededor de una hora y se reutiliza.
- Errores. Se citan el código y el texto de error de Microsoft, por ejemplo
AADSTS7000215para un secreto de cliente incorrecto, y una sala que la aplicación no puede leer hace fallar la sincronización y se nombra. - Una conexión en su lugar. Establezca
connection_iden una conexión de Microsoft del proyecto, en cualquiera de los dos modos, en lugar detenant,client_idyclient_secret. La fuente no guarda entonces ningún secreto e inicia sesión como lo hace la conexión.
Calendarios de recursos de Google Workspace
El tipo google_calendar lee calendarios de recursos y de salas con tu propia cuenta de servicio de Google. El secreto service_account_key es el archivo de clave tal como lo emite Google, y su pista es la dirección de la cuenta. El ajuste opcional subject nombra al usuario en cuyo nombre actúa la cuenta con la delegación en todo el dominio.
- En Google Cloud, habilita la API de Google Calendar, crea una cuenta de servicio y descarga una clave JSON para ella.
- Dale a la cuenta acceso a las salas. O bien comparte cada calendario de sala con la dirección de la cuenta y el permiso Ver todos los detalles del evento, o activa la delegación en todo el dominio para la cuenta en la consola de administración con el ámbito
https://www.googleapis.com/auth/calendar.events.readonlyy establecesubjecten un usuario que pueda ver las salas. - El
calendar_idde una sala es el ID de calendario del recurso en la consola de administración, en Edificios y recursos; termina en@resource.calendar.google.com. Haz una vista previa consource testy luego guarda.
screenrig source test --kind google_calendar --card crd_ROOM \
--set time_zone=America/Los_Angeles \
--set 'rooms=[{"key":"boardroom","calendar_id":"CALENDAR_ID","name":"Boardroom"}]' \
--secret service_account_key=@key.json- Correspondencia. Los eventos privados y confidenciales muestran el título privado y ningún organizador. Los eventos marcados como transparentes, y los que la sala rechazó, son tiempo libre; los cancelados se descartan. Los eventos de todo el día conservan sus fechas.
- Errores. Se cita el texto de error de Google. Un calendario que la cuenta no puede ver se nombra en el error, con la forma de compartirlo.
- Una conexión en su lugar. Establezca
connection_iden una conexión de Google del proyecto en lugar deservice_account_key. Con la aplicación de screenRIG, la fuente lee los calendarios que puede ver la cuenta que la aprobó, así que esa cuenta debe ver cada calendario de sala que la fuente lista, ysubjectno está permitido.
Límites y privacidad
- Una tarjeta
roomguarda las 200 reservas más próximas y una tarjetaroom-boardguarda 60 por sala. Si hay más, el estado muestra una advertencia con cuántas se dejaron fuera. - El documento de la tarjeta contiene solo lo que la tarjeta muestra, porque cada pantalla que muestra una tarjeta conserva su documento. Una tarjeta
roomrecibe los organizadores solo conshowOrganizeractivado. Una tarjetaroom-boardnunca recibe organizadores y recibe el título privado en lugar de cada título de reunión, salvo queshowTitlesesté activado. Un cambio en cualquiera de los dos ajustes llega a la tarjeta en la siguiente sincronización. Una reunión privada lleva el título privado en ambos casos. - Los mensajes de estos tipos citan el texto de error que respondió Microsoft o Google, y nunca un secreto.
El sistema de reservas de un recinto
El tipo momentus lee las funciones (cada uso de una sala, con sus fechas y horas) y los espacios de una instalación de Momentus Enterprise, el sistema que antes se vendía como Ungerboeck y EBMS, con un usuario de API que tu administrador crea en Momentus (Main Menu, Api Users). Rellena una tarjeta events para un directorio de eventos, una tarjeta room-board para un vestíbulo o un pasillo, o una tarjeta room para una sala, y con un documento por sala, cada pantalla muestra las reservas de su propia sala. Una sala que cambia poco antes de un evento se muestra dentro del intervalo de actualización, un minuto por defecto.
| Configuración | Significado |
|---|---|
base_url | La dirección https de tu servidor web de Momentus, por ejemplo https://momentus.example.com/prod; la API se lee desde {base_url}/api/v1/... |
organization | El código de organización de Momentus del que se leen los datos |
api_user | El id del usuario de API |
time_zone | La zona IANA del recinto. Momentus guarda fechas y horas locales, así que defínela; sin ella las horas se leen como UTC y el estado muestra una advertencia |
days | Cuántos días leer desde hoy, de 1 a 31 (7 por defecto) |
rooms | Lista opcional de {key, space, name?, floor?, capacity?, area?}; space es el código de espacio de Momentus. Sin ella, cada espacio que Momentus lista es una sala (clave: el código en minúsculas) |
space_filter, function_filter | Expresiones de búsqueda de Momentus opcionales que limitan los espacios o las funciones leídos |
exclude_status_codes | Códigos de estado de función que se excluyen, como los cancelados. Los códigos de estado son propios de tu recinto, así que no hay valor por defecto |
include, exclude | Palabras clave que conservan u ocultan funciones según el título que muestra la fuente, como en los calendarios |
Dos secretos: api_key, uno de los GUID de clave del usuario de API, y api_secret, su GUID secreto. Ambos se guardan cifrados, no se vuelven a mostrar y se introducen de nuevo si la fuente apunta a otro servidor, organización o usuario de API.
screenrig source test --kind momentus --card crd_EVENTS \
--set base_url=https://momentus.example.com/prod --set organization=10 \
--set api_user=venue-api --set time_zone=America/Los_Angeles \
--set 'exclude_status_codes=["XX"]' \
--secret api_key=@key.guid --secret api_secret=@secret.guid
screenrig source create --kind momentus --card crd_EVENTS --name "Venue events" \
--settings @momentus.json --secret api_key=@key.guid --secret api_secret=@secret.guidsource test lee Momentus, da forma al documento y lo comprueba con la tarjeta, y muestra las salas y los eventos que leyó (functions, functions_other_spaces, events_KEY). No se guarda ni se escribe nada.
- En qué se convierte una función. El
Spacede la función elige la sala, suDescriptiones el título (title_fieldpuede nombrar una de sus descripciones alternativas) y el nombre de la sala es la ubicación. Una función sin hora de inicio es un evento de todo el día. Una función de varias fechas con horas muestra esas horas en cada fecha; la que termina antes de empezar se prolonga durante la noche. - Títulos privados. Un
room-boardmuestra el título privado salvo queshow_titlesesté activado, como en los demás tipos de sala. - Errores. El texto propio de Momentus nunca se cita, porque el servidor es tuyo:
auth_failedsignifica que el usuario de API, la clave o el secreto es incorrecto o no puede leer funciones y espacios,config_invalidque un filtro no es una búsqueda válida de Momentus, yparse_failedquebase_urlllegó a una página web y no a la API.
Un cartel para cada sala
Define room_key_prefix (por ejemplo momentus-room-) y la fuente también escribe un documento room por cada sala bajo ese prefijo seguido de la clave de la sala. Asigna a la pantalla de cada sala su sala y coloca una tarjeta room cuya clave data sea el prefijo seguido del campo propio de la pantalla:
screenrig screen update scr_BALLROOM --field room=ballroom-aUse el tipo de catálogo en línea room en esta primitiva de la lista de reproducción:
{"id":"door","primitive":"card","card":"room","layout":"full","content_fit":"fill","params":{"room":"{screen.field.room}"},"data":"momentus-room-{screen.field.room}"}Las primitivas crd_ usan params y major de la propia instancia; omite esos campos. Su data opcional selecciona una clave de documento o una plantilla de clave por pantalla. --card crd_ID de la fuente sigue indicando su destino de sincronización. Para la página, establece visibility.data.key en momentus-room-{screen.field.room} y añade después una página alternativa sin condiciones.
El backend rellena el campo en el manifiesto de cada pantalla, así que una sola lista de reproducción muestra a cada pantalla su propia sala, y una pantalla sin campo de sala no muestra nada para esa tarjeta. area_key_prefix hace lo mismo para una pantalla de pasillo: el area de cada sala la agrupa, y una room-board de las salas de esa área se escribe bajo el prefijo seguido de la clave del área (area_card puede ser events). screen_field y area_field nombran los campos de pantalla que lee la comprobación de abajo (room y area por defecto).
Comprobar la asignación
screenrig source rooms src_ID (y la sección Asignación de salas de la página de la fuente en el panel) lista las salas que ofrece la fuente y que ninguna pantalla muestra, y las pantallas cuya sala falta o nombra una sala que Momentus no tiene:
screenrig source rooms src_VENUEUna pantalla aparece en el informe cuando tiene un valor para el campo, o cuando su propia lista de reproducción coloca una tarjeta que lee la clave. Cada una es mapped, missing (la lista lee el campo y la pantalla no tiene ninguno) o unknown (el valor no nombra ninguna sala; el informe indica la sala que probablemente quiso decir, por ejemplo las mismas letras en otra capitalización). Corrige una pantalla con screenrig screen update scr_ID --field room=ROOM_KEY. El informe lee las salas de la última actualización correcta de la fuente y no consulta nada; una fuente que lista sus rooms las conoce antes de su primera actualización.
Seguridad
Una dirección que da acceso es una credencial. screenRIG la almacena cifrada, devuelve solo su esquema y su host, y la usa únicamente para ejecutar la sincronización. Las fuentes leen direcciones http(s) públicas en el puerto 80 o 443 y siguen como máximo tres redirecciones; una dirección que no se resuelve a un host público, una conexión rechazada y un fallo de negociación se leen igual, por lo que una fuente no sirve para explorar una red. Ningún mensaje cita una dirección ni la respuesta recibida. Las fuentes solo leen: nunca escriben en un calendario.