Saltar al contenido principal

Recorrido por las funciones

Tu primer dispositivo termina en la primera lectura. Este recorrido sigue adelante. Al final, un sitio funciona de extremo a extremo: un tipo de dispositivo y su perfil, dos dispositivos que envían lecturas, un panel, una regla que genera una alarma y envía un comando, la respuesta del dispositivo a ese comando y un usuario cliente que inicia sesión y ve solo su propio dispositivo.

Después repites el mismo recorrido como un segundo tenant, con otro cliente, cambiando un único archivo de parámetros. No se bifurca nada.

El recorrido es un conjunto de scripts de shell del repositorio, en examples/feature-tour. Llaman a la misma API GraphQL pública y al mismo dcctl que usarías tú, y cada paso de abajo indica también dónde lo hace la consola. DeviceChain no tiene una importación para un sitio completo: los scripts son llamadas ordinarias a la API que puedes leer y modificar.

Calcula unos 45 minutos una vez que haya una instancia en marcha.

Qué necesitas​

  • Una instancia en marcha y su consola. El paso 1 de Tu primer dispositivo levanta una en un clúster local de kind. No necesitas su tenant ni su dispositivo: el recorrido crea los suyos.

  • bash, curl, jq, openssl, docker y kubectl en tu PATH. En Windows usa Git Bash.

  • Una copia del repositorio, para obtener los scripts:

    git clone https://github.com/devicechain-io/devicechain
    cd devicechain/examples/feature-tour

Tres ajustes indican dónde está tu instancia. Cada uno tiene un valor por defecto que coincide con un dcctl install local normal seguido de dcctl bootstrap local tour --host localhost --no-tls, y cada uno puede sustituirse desde el entorno:

VariableValor por defectoDefínela cuando
DC_URLhttp://localhostLa consola se sirve en otro host o puerto.
INSTANCEtourTu instancia de dcctl tiene otro nombre. Da nombre al namespace dci-<instance>, del que los scripts leen la autoridad certificadora del broker y la contraseña del superusuario.
MQTT_HOSTdevicechain-control-planeTu clúster de kind no se llama devicechain. Es el nombre del contenedor del nodo del clúster, <cluster>-control-plane.

Si tu kubectl tiene más de un contexto, define también KUBE_CONTEXT.

export DC_URL=http://localhost INSTANCE=devicechain MQTT_HOST=devicechain-control-plane

Los dispositivos simulados son contenedores de la red de Docker kind, así que llegan al puerto de nodo MQTT del broker por el nombre del nodo. En un clúster que no sea kind, ejecuta device/coldroom.sh desde cualquier máquina que alcance el broker, o apunta tu propio cliente a él. Consulta Conexión de un dispositivo.

Ejecútalo​

./tour.sh sites/site-a.env all

Eso aprovisiona todo, arranca los dos dispositivos, espera a que la regla actúe y después comprueba cada afirmación de esta página, imprimiendo PASS o FAIL en cada una. Las comprobaciones terminan con tour tour-a: all checks passed. Las dos mitades pueden ejecutarse por separado:

./tour.sh sites/site-a.env up # provision, dashboards, customer user, start the devices
./tour.sh sites/site-a.env verify # wait for the loop, then check the operator's and the customer's views

Los scripts pueden ejecutarse de nuevo sin riesgo. Lo que ya existe se deja como está, y un panel cuya definición cambió se actualiza y se publica como una versión nueva.

Las contraseñas que generan los scripts (la del administrador del sitio, la del usuario cliente y las de los dispositivos) se escriben en .state/<tenant>/, que git ignora y que solo tú puedes leer. Nunca se imprimen.

Las secciones siguientes recorren lo que hizo cada script y muestran el mismo paso en la consola.

1. El tenant y su administrador​

01-provision.sh empieza en el nivel de instancia. Con la contraseña del superusuario tomada del Secret que creó dcctl bootstrap, crea el tenant (createTenant en la API de administración) y una identidad para el administrador del propio sitio, operator@coldchain-a.example, que es tenant-admin de ese tenant y de ningún otro.

Todo lo que sigue se ejecuta como ese administrador, que es con quien inicias sesión: la consola del superusuario es la consola de Admin de la instancia, sin páginas de tenant. En la consola, el mismo trabajo es Tenants → New tenant e Identities en la consola de Admin.

Para iniciar sesión en la consola del tenant, abre DC_URL, escribe operator@coldchain-a.example y usa la contraseña de .state/tour-a/operator-password.

2. Un tipo de dispositivo y su perfil​

Un tipo de dispositivo clasifica dispositivos, y su perfil es el contrato: qué mediciones envía un dispositivo, qué comandos acepta y qué reglas vigilan sus lecturas. El script crea el perfil cold-room con:

  • las mediciones temperature y humidity,
  • un comando, boost-cooling, y
  • una regla de detección, cold-room-too-warm: cuando temperature supera el límite del sitio, genera una alarma mayor y envía boost-cooling. La regla es rule.json, que es lo que guarda el formulario de reglas de la consola.

Después publica el perfil y crea el tipo de dispositivo cold-room sobre él. Publicar importa: las reglas solo llegan a las lecturas en vivo cuando el perfil está publicado, y la plataforma compila la regla en ese momento, de modo que una regla que no puede compilar se rechaza ahí y no falla en silencio más tarde. Un perfil que declara comandos acepta únicamente esos comandos.

En la consola: Devices → Device Profiles (reglas, métricas y comandos) y Devices → Device Types. Consulta Tipos y perfiles de dispositivo y Reglas de detección.

3. Dispositivos​

El script crea dos dispositivos del tipo, coldroom-a1 y coldroom-a2, y da a cada uno una credencial MQTT_BASIC. Un dispositivo presenta el nombre de usuario <tenant>:<credentialId> y su contraseña; la plataforma guarda solo un resumen (digest) de la contraseña.

En la consola: Devices → Devices y después la pestaña Credentials de un dispositivo. Consulta Dispositivos y Credenciales de dispositivo.

4. Un cliente y cuál es su dispositivo​

El script crea un tipo de cliente y el cliente acme, y asigna coldroom-a1 a él: una relación de tipo assigned del dispositivo al cliente. coldroom-a2 se deja sin asignar a propósito, en el mismo tenant. Eso permite que el último paso muestre al cliente viendo un dispositivo mientras el operador ve ambos.

En la consola: Organization → Customers y la pestaña Assignment del dispositivo. Consulta Activos, clientes y áreas y Gestión de asignaciones.

5. Lecturas​

./02-devices.sh sites/site-a.env up

arranca un contenedor por dispositivo. Cada uno son unas pocas líneas de shell alrededor de mosquitto_pub y mosquitto_sub. La cámara fría se calienta un grado cada cuatro segundos, publica temperature y humidity y mantiene abierta una suscripción para los comandos. No sabe nada de la regla, la alarma ni el panel: informa y obedece. La suscripción es también lo que muestra al dispositivo en línea.

En pocos segundos las lecturas están en la consola (la página del dispositivo, con los últimos valores) y por la API:

curl -s http://localhost/api/device-state/graphql -H "Authorization: Bearer $DC_TOKEN" -H 'Content-Type: application/json' \
-d '{"query":"{latestMeasurements(deviceToken:\"coldroom-a1\"){name value unit}}"}'

$DC_TOKEN es un token de acceso del tenant. El paso 3 de Tu primer dispositivo muestra las dos llamadas que lo obtienen.

6. Tu primer panel​

Un panel es una definición JSON de widgets enlazados a un slot, como «el dispositivo que se está viendo». Hay dos maneras de crear el primero, y el recorrido usa las dos.

En la consola, desde el tipo de dispositivo. Abre Devices → Device Types → Cold room, elige la pestaña Profile y elige Create dashboard. El panel lateral lee lo que declara el perfil y muestra una vista previa del tablero: un selector de dispositivo, una tarjeta por medición, un gráfico, una tabla de alarmas y un botón por cada comando que es seguro enviar desde un tablero. Dale un token, elige Create draft and open editor y el tablero se abre con datos en vivo. Es un borrador: los espectadores no ven nada hasta que lo publicas desde el panel History del editor. Consulta Crear un panel desde un tipo de dispositivo.

Desde un script. 03-dashboards.sh construye el mismo tipo de tablero a partir de dashboard.jq y lo crea con createDashboard, lo publica con publishDashboard, y lo hace dos veces:

  • tour-a-ops, para el operador, con un botón Send Boost cooling; y
  • tour-a-customer, sin el botón, que comparte con el cliente acme (shareDashboard). Un miembro limitado a un cliente ve un panel solo cuando está compartido con ese cliente y publicado.

Abre DC_URL/dashboards/tour-a-ops. Los dos tableros no difieren en nada salvo el botón, que es la razón de generarlos a partir de una sola definición.

7. La regla genera una alarma​

Espera medio minuto. Cuando una cámara pasa el límite, la regla se dispara: aparece una alarma en Monitor → Alarms (y en la tabla y el contador de alarmas del tablero), y se borra sola cuando la lectura baja de nuevo. Nada redacta el borrado: una regla se activa por flanco y su alarma dura mientras se cumple su condición. La lista de alarmas conserva una fila por cada clave de alarma en cada dispositivo, con su última activación.

La cámara vuelve a calentarse después de enfriarse, así que el ciclo se repite: una alarma y un comando por cada exceso. Consulta Alarmas y Procesamiento de eventos.

8. El comando y su resultado​

La misma activación envió el comando boost-cooling. El dispositivo lo recibió en su topic de comandos, enfrió y respondió, con el token del propio comando y el nonce de la entrega. La respuesta es lo que pasa el comando de SENT a SUCCESSFUL. Un dispositivo que obedece pero nunca responde deja el comando en SENT hasta que vence el tiempo de espera.

05-verify.sh también envía un comando propio, como lo harías tú:

mutation {
createCommand(request: {
token: "my-first-command",
deviceToken: "coldroom-a1",
name: "boost-cooling",
payload: "{\"targetC\":3}"
}) {
command { token status }
rejection { code reason }
}
}

Vuelve como QUEUED y, unos segundos después, como SUCCESSFUL:

query {
commandsByToken(tokens: ["my-first-command"]) { status outcome responsePayload }
}

Comprueba rejection además de los errores: un comando rechazado es una respuesta correcta que lleva un rejection. En la consola, la pestaña Commands de la página del dispositivo lista el historial, y el botón del tablero envía uno. Consulta Envío de un comando y Comandos.

9. La vista del cliente​

04-customer-user.sh invita a ops@acme.example como miembro del tenant con el rol integrado de solo lectura viewer y un ámbito de acceso de un cliente, acme, y después acepta la invitación con una contraseña generada. En la consola esto se hace en Access → Members → Invite member, que muestra un enlace de invitación de un solo uso que entregas tú mismo. El script lo acepta para que el recorrido pueda ejecutarse sin supervisión.

Inicia sesión como ops@acme.example (la contraseña está en .state/tour-a/customer-password). El usuario ve:

  • una barra lateral con Dashboards, Alarms y Devices, y nada más;
  • un dispositivo, coldroom-a1;
  • un panel, tour-a-customer, con lecturas en vivo y la alarma de su propia cámara;
  • ninguna señal de coldroom-a2, de sus lecturas, de sus alarmas ni del tablero del operador.

El indicador del tenant, arriba a la derecha, dice Acme Foods · viewer. 05-verify.sh comprueba cada uno de estos puntos como el usuario cliente, y también que enviar un comando se rechaza. Consulta Miembros, roles y usuarios cliente.

Qué imprimen las comprobaciones​

PASS the rule raised an alarm on coldroom-a1 and its command ended SUCCESSFUL
PASS createCommand boost-cooling was accepted (QUEUED), not rejected
PASS your own command reached SUCCESSFUL (the device answered; last status: SUCCESSFUL)
PASS the operator sees both devices (2)
PASS the operator sees alarms on both devices (2 devices with alarms)
PASS the customer sees exactly coldroom-a1 (saw: coldroom-a1)
PASS the customer sees alarms for coldroom-a1 only (saw: coldroom-a1)
PASS the customer reads no state of coldroom-a2 (0 measurements)
PASS the customer lists only the board shared with them (saw: tour-a-customer)
PASS the operator's board is invisible to the customer
PASS the read-only customer user cannot send a command (refused: FORBIDDEN)

Un usuario cliente que pide un dispositivo que no es suyo recibe una respuesta vacía, no un error, así que un script no puede distinguir «no es tuyo» de «no existe». Es lo previsto.

El mismo recorrido para un segundo sitio​

Un sitio es un archivo de parámetros. sites/site-a.env contiene todo lo que difiere entre sitios: el tenant, su administrador, el cliente, los tokens de los dos dispositivos y los números que usan la regla y las cámaras simuladas.

./tour.sh sites/site-b.env all

El sitio B es otro tenant, tour-b, con otro cliente (globex, cuyo usuario es ops@globex.example), otros dispositivos y un límite de alarma más bajo (6 grados en lugar de 8). Solo difiere el archivo. Para crear un sitio propio, copia un archivo de sitio, cambia los valores y ejecuta el mismo comando. Cada tenant tiene su propio administrador, usuario cliente, contraseña de dispositivo y paneles, y ninguno puede ver al otro.

Capítulos opcionales​

Son más breves, y cada uno lleva a la página que contiene el detalle. La columna Activado por defecto indica si una instalación estándar ya ejecuta la función o si primero hay que activar algo.

CapítuloQué añadeRequisitos previos¿Activado por defecto?Empieza aquí
Alta y autorregistroLos dispositivos se presentan con una clave de aprovisionamiento compartida y crean su propia credencial, en lugar de crearse antes.Un perfil de aprovisionamiento (Connect → Provisioning Profiles). Los dispositivos se registran por HTTPS a través del ingress de API de la instancia, así que necesitan una ruta hasta él.La capacidad forma parte de la instalación estándar. Nada se registra hasta que creas un perfil de aprovisionamiento.Autorregistro de dispositivos
Certificados de cliente X.509Los dispositivos se autentican ante el broker con un certificado, fijado a un dispositivo o confiado mediante una CA que registra dispositivos en su primera conexión.openssl y una CA de confianza (la guía crea una desechable). Solo MQTT; sin CRL ni OCSP. examples/x509-device del repositorio recorre todo el camino.Nada que activar. La confianza existe solo cuando añades un ancla de confianza o fijas un certificado.Conexión con un certificado
Autenticación de dos factoresUn código de una app de autenticación en los inicios de sesión con contraseña, para una cuenta o exigido a un tenant.La app de autenticación de cada persona; relojes correctos en todos los nodos.Integrada y no exigida: cada persona la activa en Account security, y un administrador del tenant puede exigirla.Autenticación de dos factores
Configuración del dispositivoUna configuración deseada, construida a partir de los atributos compartidos que declara el perfil, entregada al dispositivo con revisiones y un informe de aplicada o rechazada.Declara las claves en el perfil y publícalo. El dispositivo debe usar MQTT; los dispositivos que solo hablan HTTP no reciben este canal.Disponible en toda instalación. Un dispositivo no recibe nada hasta que el perfil declara claves.Conexión de un dispositivo
Actualizaciones remotas firmadasUn catálogo de artefactos, firmantes, asignaciones firmadas y despliegues, con cada intento seguido hasta que el dispositivo demuestra la versión nueva.Un almacén de objetos para el contenido de los artefactos (un volumen compartido o S3), un firmante registrado y un dispositivo MQTT que siga el protocolo de actualización. El dispositivo de referencia es examples/ota-device.En el perfil default. Los perfiles telemetry e ingest-only lo omiten, y una instancia sin almacén de objetos rechaza los artefactos con OBJECT_STORE_NOT_CONFIGURED.Actualizaciones remotas y Firma de actualizaciones
SQL y BISQL de solo lectura sobre la telemetría de tu propio tenant para Metabase, Grafana, Power BI o psql, mediante el esquema analytics.Un lector que tú declaras. Las credenciales de base de datos de la propia plataforma nunca se entregan a una herramienta de BI.El esquema analytics existe en toda instalación y no tiene lectores hasta que declaras uno.Acceso SQL y BI
Widgets personalizadosTu propio widget de React, dibujado en los paneles con el mismo enlace de datos que los integrados.Node y npm, y recompilar la consola o /dash incluyendo tu paquete. No hay instalador en tiempo de ejecución.No. Solo están los widgets integrados.Escritura de un widget personalizado y Adición de paquetes de widgets

Si algo no funcionó​

Qué vesNormalmente significa
error: ... cannot sign in de un scriptNo se ejecutó un paso anterior. Ejecuta primero ./01-provision.sh <site>; crea la identidad con la que inician sesión los scripts posteriores.
could not read the broker CAINSTANCE no es el nombre de tu instancia, o kubectl apunta a otro clúster. Define INSTANCE y KUBE_CONTEXT.
La comprobación espera y falla en la primera líneaLos dispositivos no están publicando. Ejecuta ./02-devices.sh <site> logs. publish refused significa que la credencial o el nombre del tenant son incorrectos; un error de conexión significa que MQTT_HOST no es el nombre del contenedor del nodo de tu clúster.
Un dispositivo está en línea pero no aparece ninguna alarmaEl perfil no se publicó, o el límite de la regla está por encima de donde la cámara deja de calentarse. Revisa TOUR_ALARM_ABOVE en el archivo del sitio.
El registro de un dispositivo dice command ... answered pero el comando sigue en SENTLa respuesta no se aceptó. Debe llevar el token y el dispatchNonce del propio comando.
El usuario cliente no ve ningún dispositivoEl dispositivo no está asignado al cliente, o no se definió el ámbito del miembro. ./04-customer-user.sh <site> imprime el ámbito que encontró.

Limpieza​

./tour.sh sites/site-a.env down
./tour.sh sites/site-b.env down

detiene los dispositivos simulados. Los tenants permanecen. Eliminar un tenant revoca el acceso de inmediato, pero su token se retiene al menos 12 horas antes de poder reutilizarse, y se rechaza eliminar un tenant que aún tiene miembros. Consulta Eliminación de un tenant. Para repetir el recorrido desde cero de inmediato, destruye la instancia con dcctl destroy local <instance> y arranca una nueva, o da nuevos tokens de tenant al archivo del sitio.

Siguientes pasos​