goog.loadJs('web', () => { goog.require('Mixly.Serial'); goog.require('Mixly.Web'); goog.provide('Mixly.Web.HID'); const { Serial, Web } = Mixly; class WebHID extends Serial { static { this.type = 'hid'; this.getConfig = function () { return Serial.getConfig(); } this.getSelectedPortName = function () { return Serial.getSelectedPortName(); } this.getCurrentPortsName = function () { return Serial.getCurrentPortsName(); } this.refreshPorts = function () { Serial.refreshPorts();; } this.requestPort = async function () { const devices = await navigator.hid.requestDevice({ filters: [] }); if (!devices.length) { return; } for (let device of devices) { this.addPort(device); } this.refreshPorts(); } this.getPort = function (name) { return Serial.nameToPortRegistry.getItem(name); } this.addPort = function (device) { if (Serial.portToNameRegistry.hasKey(device)) { return; } let name = ''; for (let i = 1; i <= 20; i++) { name = `hid${i}`; if (Serial.nameToPortRegistry.hasKey(name)) { continue; } break; } Serial.portToNameRegistry.register(device, name); Serial.nameToPortRegistry.register(name, device); } this.removePort = function (device) { if (!Serial.portToNameRegistry.hasKey(device)) { return; } const name = Serial.portToNameRegistry.getItem(device); if (!name) { return; } Serial.portToNameRegistry.unregister(device); Serial.nameToPortRegistry.unregister(name); } this.addEventsListener = function () { navigator?.hid?.addEventListener('connect', (event) => { this.addPort(event.device); this.refreshPorts(); }); navigator?.hid?.addEventListener('disconnect', (event) => { event.device.onclose && event.device.onclose(); this.removePort(event.device); this.refreshPorts(); }); } this.init = function () { navigator?.hid?.getDevices().then((devices) => { for (let device of devices) { this.addPort(device); } }); this.addEventsListener(); } } #device_ = null; #keepReading_ = null; #reader_ = null; #writer_ = null; #stringTemp_ = ''; constructor(port) { super(port); } #addEventsListener_() { this.#device_.oninputreport = (event) => { const { data } = event; const length = Math.min(data.getUint8(0) + 1, data.byteLength); let buffer = []; for (let i = 1; i < length; i++) { buffer.push(data.getUint8(i)); } this.onBuffer(buffer); }; this.#device_.onclose = () => { if (!this.isOpened()) { return; } super.close(); this.#stringTemp_ = ''; this.onClose(1); } } async open(baud) { return new Promise((resolve, reject) => { const portsName = Serial.getCurrentPortsName(); const currentPortName = this.getPortName(); if (!portsName.includes(currentPortName)) { reject('无可用设备'); return; } if (this.isOpened()) { resolve(); return; } baud = baud ?? this.getBaudRate(); this.#device_ = WebHID.getPort(currentPortName); this.#device_.open() .then(() => { super.open(baud); super.setBaudRate(baud); this.onOpen(); this.#addEventsListener_(); resolve(); }) .catch(reject); }); } async close() { if (!this.isOpened()) { return; } super.close(); await this.#device_.close(); this.#stringTemp_ = ''; this.#device_.oninputreport = null; this.#device_.onclose = null; this.onClose(1); } async setBaudRate(baud) { return Promise.resolve(); } async sendString(str) { const buffer = this.encode(str); return this.sendBuffer(buffer); } async sendBuffer(buffer) { return new Promise((resolve, reject) => { if (buffer instanceof Uint8Array) { let temp = new Uint8Array(buffer.length + 1); temp[0] = buffer.length; temp.set(buffer, 1); buffer = temp; } else { buffer.unshift(buffer.length); buffer = new Uint8Array(buffer); } this.#device_.sendReport(0, buffer) .then(resolve) .catch(reject); }); } async setDTRAndRTS(dtr, rts) { return Promise.resolve(); } async setDTR(dtr) { return this.setDTRAndRTS(dtr, this.getRTS()); } async setRTS(rts) { return this.setDTRAndRTS(this.getDTR(), rts); } onBuffer(buffer) { super.onBuffer(buffer); for (let i = 0; i < buffer.length; i++) { super.onByte(buffer[i]); } const string = this.decodeBuffer(buffer); if (!string) { return; } for (let char of string) { super.onChar(char); if (['\r', '\n'].includes(char)) { super.onString(this.#stringTemp_); this.#stringTemp_ = ''; } else { this.#stringTemp_ += char; } } } } Web.HID = WebHID; });