Інтеграція Web Serial API: зв'язок COM-порта з браузером

Принтер етикеток не друкує, Arduino не відповідає, промисловий датчик мовчить — усе через відсутність зв'язку браузера з COM-портом. **Web Serial API** вирішує цю проблему: браузер отримує прямий доступ до послідовного порту без встановлення драйверів або нативних застосунків. Ми забезпечуємо повну

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Інтеграція Web Serial API: зв'язок COM-порта з браузером
Складний
~2-3 дні

Наші компетенції:

Часті запитання

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1467
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1317
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1014
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1276
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1019
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1019

Принтер етикеток не друкує, Arduino не відповідає, промисловий датчик мовчить — усе через відсутність зв'язку браузера з COM-портом. Web Serial API вирішує цю проблему: браузер отримує прямий доступ до послідовного порту без встановлення драйверів або нативних застосунків. Ми забезпечуємо повну інтеграцію COM-порту з веб-застосунком. Впроваджуємо це рішення вже понад 5 років і реалізували більше 50 проєктів для промислових датчиків, медичних приладів та POS-терміналів. Економія на ліцензіях сягає 50%, витрати на підтримку знижуються на 40%.

Чому Web Serial API кращий за нативні застосунки?

Web Serial API в 10 разів спрощує розгортання: не потрібно встановлювати драйвери, оновлювати застосунок або налаштовувати середовище. Користувач просто відкриває сторінку в Chromium-браузері та працює. Порівняння з традиційними підходами:

Критерій Web Serial API Java-аплет Electron-застосунок
Встановлення Не потрібно Потрібна JRE Потрібна установка
Оновлення Автоматично (веб) Ручне Ручне
Безпека Same-origin, HTTPS Сумнівна Залежить від збірки
Підтримка пристроїв USB/Bluetooth/COM Тільки COM Через Native Messaging

Web Serial API — це сучасне безпечне рішення. Ми впроваджуємо його під ключ за 2–4 дні.

Підтримка та обмеження

API підтримується в Chrome 89+, Edge 89+, Opera 75+. Firefox і Safari не підтримують. Тому сторінка повинна або вимагати Chromium-браузер, або надавати Serial API fallback.

Перевірка підтримки:

if (!('serial' in navigator)) { throw new Error('Web Serial API не підтримується. Використовуйте Chrome 89+') } 

Дозвіл Origin: у продакшені обов'язково додати в заголовки Permissions-Policy: serial=*.

Як забезпечити роботу в непідтримуваних браузерах?

Якщо аудиторія використовує Firefox або Safari, передбачте fallback. Ми пропонуємо три підходи:

Fallback-метод Опис Складність
Ручне введення Користувач вводить дані вручну через форму Мінімальна
Завантаження файлу Дані експортуються з пристрою у файл, потім завантажуються Низька
WebSocket-агент На пристрої працює локальний агент, що передає дані через WebSocket Середня

Вибір залежить від типу даних та вимог до автоматизації. Наприклад, для сканера етикеток достатньо завантаження файлу, а для інтерактивного керування Arduino веб-застосунок потребуватиме WebSocket-агент.

Архітектура сервісу: як ізолювати роботу з портом

Всю роботу з портом ізолюємо в клас SerialService. UI-компонент не знає про потоки та буфери — він викликає методи сервісу та отримує дані через колбеки або EventEmitter.

type SerialDataHandler = (data: Uint8Array) => void type SerialErrorHandler = (error: Error) => void interface SerialConfig { baudRate: number dataBits?: 7 | 8 stopBits?: 1 | 2 parity?: 'none' | 'even' | 'odd' bufferSize?: number flowControl?: 'none' | 'hardware' } class SerialService extends EventTarget { private port: SerialPort | null = null private reader: ReadableStreamDefaultReader<Uint8Array> | null = null private writer: WritableStreamDefaultWriter<Uint8Array> | null = null private readLoopActive = false async requestPort(filters: SerialPortFilter[] = []): Promise<void> { this.port = await navigator.serial.requestPort({ filters }) } async connect(config: SerialConfig): Promise<void> { if (!this.port) throw new Error('Порт не вибрано') await this.port.open({ baudRate: config.baudRate, dataBits: config.dataBits ?? 8, stopBits: config.stopBits ?? 1, parity: config.parity ?? 'none', bufferSize: config.bufferSize ?? 4096, flowControl: config.flowControl ?? 'none', }) this.writer = this.port.writable!.getWriter() this.startReadLoop() } private async startReadLoop(): Promise<void> { if (!this.port?.readable) return this.readLoopActive = true while (this.port.readable && this.readLoopActive) { this.reader = this.port.readable.getReader() try { while (true) { const { value, done } = await this.reader.read() if (done) break if (value) { this.dispatchEvent( Object.assign(new Event('data'), { detail: value }) ) } } } catch (error) { if (this.readLoopActive) { this.dispatchEvent( Object.assign(new Event('error'), { detail: error }) ) } } finally { this.reader.releaseLock() } } } async write(data: Uint8Array | string): Promise<void> { if (!this.writer) throw new Error('Порт не відкрито') const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data await this.writer.write(bytes) } async disconnect(): Promise<void> { this.readLoopActive = false this.reader?.cancel() this.writer?.releaseLock() await this.port?.close() this.port = null this.reader = null this.writer = null } get isConnected(): boolean { return this.port !== null && this.port.readable !== null } } 

Детальніше про методи роботи з Serial API читайте в офіційній документації на MDN.

Як працювати з протоколами: адаптер для запит-відповідь

Більшість пристроїв використовують текстові або бінарні протоколи поверх UART. Приклад для пристрою з протоколом запит-відповідь через \r\n-роздільники:

class LineProtocolAdapter { private buffer = '' private pendingResolvers: Array<(line: string) => void> = [] constructor(private serial: SerialService) { serial.addEventListener('data', (e: Event) => { const event = e as Event & { detail: Uint8Array } this.buffer += new TextDecoder().decode(event.detail) this.flushLines() }) } private flushLines(): void { const lines = this.buffer.split('\r\n') this.buffer = lines.pop() ?? '' for (const line of lines) { if (line.trim()) { const resolver = this.pendingResolvers.shift() if (resolver) resolver(line.trim()) } } } async sendCommand(command: string, timeoutMs = 2000): Promise<string> { return new Promise((resolve, reject) => { const timer = setTimeout(() => { this.pendingResolvers = this.pendingResolvers.filter(r => r !== resolve) reject(new Error(`Timeout: немає відповіді на "${command}" за ${timeoutMs}ms`)) }, timeoutMs) this.pendingResolvers.push((line) => { clearTimeout(timer) resolve(line) }) this.serial.write(command + '\r\n').catch(reject) }) } } // Використання: const adapter = new LineProtocolAdapter(serialService) const version = await adapter.sendCommand('VERSION') const sensorData = await adapter.sendCommand('READ SENSOR 1') 

Для фільтрації пристроїв за USB Vendor/Product ID використовуйте navigator.serial.requestPort() з опцією filters. Після першого дозволу порт можна відновити без діалогу через navigator.serial.getPorts(). Це реалізує автопідключення USB. Для бінарних протоколів працюйте з Uint8Array безпосередньо.

Як реалізувати інтеграцію: покроковий план

  1. Аналіз протоколу пристрою. Вивчіть документацію: налаштування baud rate, parity, формат команд. Зберіть тестові дані.
  2. Налаштування порту. Відкрийте порт з потрібними параметрами через SerialPort.open(). Використовуйте клас SerialService з прикладу.
  3. Реалізація протокольного адаптера. Якщо протокол текстовий, напишіть LineProtocolAdapter; для бінарних — працюйте з Uint8Array безпосередньо.
  4. Інтеграція з UI. Оберніть сервіс у React Serial Service (хук useSerialService) або Vue-composable. Додайте обробку помилок та перепідключень.
  5. Тестування. Перевірте на реальному пристрої або емуляторі (socat/VSPE). Переконайтеся, що Serial API fallback працює.
Типові помилки при інтеграції
  • Забули видалити зайві символи з буфера — отримуєте сміття.
  • Не обробили відключення пристрою — порт зависає.
  • Використовуєте неправильний baud rate — дані не читаються.
  • Не реалізували таймаут для команд — застосунок зависає назавжди.

Що входить у роботу

Аналіз протоколу цільового пристрою, налаштування параметрів порту (baud rate, parity, flow control), реалізація класів SerialService та протокольного адаптера, React-хук або Vue-composable, обробка перепідключень, fallback для непідтримуваних браузерів, тестування на реальному обладнанні або емуляторі. Якщо пристрій використовує пропрієтарний бінарний протокол — додатковий час на реверс-інжиніринг або вивчення документації. Ми також гарантуємо підтримку розробленого рішення та безкоштовні консультації протягом місяця після впровадження.

Термін: 2–4 дні залежно від складності протоколу пристрою. Замовте впровадження — наші інженери адаптують рішення під ваше обладнання.