Volver al Centro de conocimiento
Plataforma

Permisos y ciclo de vida de puertos con Web Serial API

Solicita Web Serial mediante una acción, separa permiso y disponibilidad, limita streams, gestiona desconexiones y conserva una alternativa segura.

BotBrowser Team

Documentación

Quieres la documentación estructurada de Plataforma?

Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.

Web Serial permite solicitar un puerto elegido por la persona, pero el selector no es una conexión, un periférico confiable ni prueba de propiedad. BotBrowser puede probar las ramas de permiso y alternativa de la página en un contexto controlado; no fabrica un dispositivo serial, concede permiso del sistema fuera del navegador ni demuestra E/S física. El contrato es explícito: pedir tras una acción, abrir solo un puerto compatible, limitar cada trama, cancelar y cerrar streams al desconectar y mantener la tarea útil sin hardware serial.

Acción de usuario, permiso del selector Web Serial, estado SerialPort abierto, streams limitados, limpieza por desconexión y alternativa

TL;DR

  • navigator.serial.requestPort({ filters: [{ usbVendorId: 0x2341 }] }) necesita contexto seguro y activación transitoria del usuario.
  • Un SerialPort seleccionado es una capacidad del origen; no demuestra que esté abierto, conectado, sea seguro o use el protocolo correcto.
  • Llama port.open({ baudRate: 115200 }) con configuración revisada y valida tramas decodificadas antes de cambiar el estado.
  • Los eventos connect y disconnect muestran cambios visibles para el navegador; cancela readers, libera locks, cierra el puerto y conserva los borradores.
  • Guarda granted, unsupported, invalid-frame o disconnected, no números de serie, buffers crudos ni identidad inferida.

Contenido

Preguntar en el punto de uso

Web Serial está limitado a contextos seguros y requestPort() debe ejecutarse durante activación transitoria. Coloca la petición detrás de un control con nombre claro. Detectar navigator.serial solo indica que existe; no abre el selector ni concede acceso. Una política de iframe, configuración administrada, plataforma no compatible o regla del sistema puede impedirla.

async function connectSerial() {
  if (!window.isSecureContext || !navigator.serial) return showSerialState('unsupported');
  setSerialState('requesting');
  try {
    const port = await navigator.serial.requestPort({
      filters: [{ usbVendorId: 0x2341 }],
    });
    await openSelectedPort(port);
  } catch (error) {
    showSerialState(error.name === 'NotFoundError' ? 'cancelled' : 'denied');
  }
}

connectButton.addEventListener('click', connectSerial);

No abras el selector al cargar ni repitas tras cancelar. Conserva el borrador y ofrece otro intento después de una acción nueva. Acceso WebUSB: permisos, interfaces y privacidad separa concesión y preparación de sesión. Permisos WebHID y límites de privacidad del dispositivo aplica la misma frontera a los informes. Huella de permisos del navegador explica por qué un estado no concede acceso ni identifica a una persona.

Separar permiso y disponibilidad del puerto

requestPort() devuelve el SerialPort elegido por el navegador. No significa que siga conectado, que acepte la velocidad, que hable el protocolo previsto ni que una escritura llegue a un actuador. Trata selección, apertura, lectura, escritura y cierre como estados distintos.

Antes de open(), decide baudRate, dataBits, stopBits, parity y flowControl soportados. Mantén la tupla documentada y estrecha. Abrir con framing incorrecto puede producir bytes plausibles pero inválidos; la validación debe ocurrir después del decoder.

async function openSelectedPort(port) {
  try {
    await port.open({ baudRate: 115200, dataBits: 8, stopBits: 1, parity: 'none' });
    setSerialState('opened');
    await readSerialFrames(port);
  } catch (error) {
    showSerialState('unsupported');
    await closeSerialPort(port);
  }
}

navigator.serial.getPorts() puede devolver puertos concedidos antes al origen, pero no es inventario completo ni reemplaza un control de reconexión. Vuelve a comprobar el puerto y el protocolo; no elijas silenciosamente el primero porque un label coincida.

La especificación Web Serial define el modelo de puerto y streams. MDN Web Serial API documenta disponibilidad. Ninguna fuente convierte el puerto en identidad, ubicación, propiedad o prueba de funcionamiento físico.

Limitar streams legibles y escribibles

port.readable y port.writable son streams asíncronos. Trata los bytes como entrada no confiable. Usa decoder con tamaño máximo, delimitador o longitud, checksum cuando el protocolo lo defina y timeout para tramas incompletas. Rechaza antes de cambiar el estado.

const MAX_FRAME_BYTES = 128;

async function readSerialFrames(port) {
  const reader = port.readable.getReader();
  const decoder = new Uint8Array();
  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      if (value.byteLength > MAX_FRAME_BYTES) {
        showSerialState('invalid-frame');
        continue;
      }
      acceptBoundedFrame(value);
    }
  } finally {
    reader.releaseLock();
  }
}

El ejemplo mantiene visible el límite; un decoder real debe guardar parciales y limitar el buffer total. No registres cada byte ni envíes una trama arbitraria a un intérprete. Clasifica invalid-length, invalid-checksum o timeout sin retener contenido crudo.

Para escribir, adquiere port.writable.getWriter() solo durante la operación, valida la trama y libera el writer en finally. Un writer.write() resuelto solo prueba que el navegador aceptó bytes; no demuestra que un instrumento se movió o que otra aplicación los recibió. En una escritura incierta, conserva el formulario y exige reintento explícito.

Cancela el reader antes de cerrar el puerto. Si el stream está bloqueado, port.close() puede esperar o rechazar hasta liberar el lock. El dueño de cada tarea debe invalidar su token al navegar o desconectar y evitar que una lectura tardía pinte la alternativa como conectada.

Coordinar connect y disconnect

Escucha navigator.serial.addEventListener('connect', ...) y disconnect. connect significa que el navegador observó un puerto disponible, no que pueda abrir un selector silencioso ni que coincida con la tarea. disconnect confirma retirada observada, no su causa.

Al desconectar, marca la tarea terminal, cancela reader, libera writer, llama port.close() de forma tolerante, quita listeners, conserva datos y muestra reconexión. No reconectes ni reenvíes automáticamente: una orden pudo entregarse parcialmente.

Usa estados idle, requesting, selected, opening, opened, reading, invalid-frame, disconnected, cancelled y fallback. Cada estado necesita mensaje, siguiente acción y regla de retención. Al volver un puerto, exige acción nueva, repite configuración y handshake, y separa label elegido de usbVendorId, usbProductId, serialNumber o getInfo().

Minimizar metadatos y conservar una alternativa

Separa permiso del navegador, sesión serial, consentimiento del protocolo y subida remota. Leer un sensor localmente no autoriza enviar datos. Explica los campos que salen, pide una decisión separada y permite terminar localmente si se rechaza la sincronización.

Un registro necesita normalmente unsupported, denied, cancelled, opened, invalid-frame, disconnected o fallback, más fecha y entorno. Rara vez necesita SerialPort.getInfo(), identificadores USB, fabricante, buffers crudos o historial largo. Un diagnóstico debe ser breve, visible, controlado y eliminado.

Conserva entrada manual, importación, valor simulado o configuración estática. Mantén datos, foco, validación y recuperación sin puerto vivo. No hagas depender login, facturación, recuperación, instrucciones de seguridad ni contenido obligatorio de un dispositivo serial.

Clasificar resultados con una tabla

Etapa observadaQué estableceSiguiente acción segura
API ausente, contexto inseguro o políticaWeb Serial no puede iniciar aquíMantener tarea sin serial y explicar el límite
Selector cancelado o permiso denegadoNo hay concesión utilizableConservar borrador y esperar acción explícita
Puerto elegido pero open() rechazaNo se obtuvo sesión utilizableMostrar ajustes, cerrar y no ampliar acceso
Reader informa trama inválidaLa entrada falló el protocoloDescartar, registrar categoría y continuar
Evento disconnectEl navegador observó retiradaCancelar streams, cerrar, conservar y ofrecer reintento
Trama válida y limitadaSe aceptó un valorInformar solo ese valor; no inferir efecto físico

Cada fila debe terminar en estado comprensible. El selector no es conexión, un stream abierto no es protocolo confiable y una trama válida no prueba una acción física.

Capacidad y límite de BotBrowser

Los contextos controlados de BotBrowser pueden verificar el botón, la detección, el resultado del selector, la validación de tramas, la limpieza al desconectar y la alternativa sin serial. La documentación de funciones avanzadas describe capacidades revisables. Sigue siendo evidencia de página: BotBrowser no proporciona periférico serial, no concede permiso del sistema, no garantiza un puerto ni demuestra que bytes cambien hardware. BotBrowser valida estados visibles de navigator.serial y la alternativa en un contexto controlado; no valida una operación eléctrica de un periférico real.

{
  "api": "navigator.serial",
  "permission": "denied",
  "portState": "fallback",
  "framesAccepted": 0,
  "rawIdentifiersRetained": false,
  "physicalDevice": "not-asserted"
}

Repite el fixture al cambiar navegador, política, permiso, configuración, trama simulada o desconexión. Compara la primera divergencia visible sin prometer hardware universal.

Fuentes

Conclusión práctica

Usa una acción explícita, separa permiso de apertura y streams, valida cada trama y cancela readers antes de cerrar tras desconectar. Conserva la tarea sin hardware serial y registra la etapa del fallo, no metadatos del puerto. Repite el fixture tras cambios de navegador, política, driver, firmware o permiso; un resultado de página no promete comportamiento físico.

#Web Serial API#Permisos#Puertos Seriales#Privacidad#BotBrowser

Este artículo forma parte de la guía: Superficies de la plataforma web: mapa de revisión

Lleva BotBrowser de la investigación a producción

Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.