From 58c5f9f53c15aed63bd03d89f2d88cc65476ae92 Mon Sep 17 00:00:00 2001 From: Luc Patiny Date: Sun, 12 Mar 2023 17:21:04 +0100 Subject: [PATCH] wip: improve interface of GRBL --- demo/grbl.html | 115 ++++++------ demo/grbl.init.js | 81 +++++---- dist/legoino-navigator-serial.js | 219 ++++++++++++++++++----- dist/legoino-navigator-serial.js.map | 2 +- dist/legoino-navigator-serial.min.js | 2 +- dist/legoino-navigator-serial.min.js.map | 2 +- scripts/arduino/convert.mjs | 2 - src/Action.js | 15 +- src/Device.js | 7 +- src/DevicesManager.js | 3 +- src/grbl/alarmsDescription.js | 11 ++ src/grbl/grbl.js | 19 +- src/grbl/optionsDescription.js | 23 +++ src/grbl/updateState.js | 177 ++++++++++++++++++ src/grbl/updateStatus.js | 64 ------- src/terminal/Terminal.js | 14 +- 16 files changed, 547 insertions(+), 209 deletions(-) create mode 100644 src/grbl/alarmsDescription.js create mode 100644 src/grbl/optionsDescription.js create mode 100644 src/grbl/updateState.js delete mode 100644 src/grbl/updateStatus.js diff --git a/demo/grbl.html b/demo/grbl.html index cef2e4c..72c878e 100644 --- a/demo/grbl.html +++ b/demo/grbl.html @@ -5,13 +5,10 @@ - +

- @@ -37,91 +34,101 @@

-
- -
+
-
-

- - - - -

- -

+

+ + -

-

- - - - -

+
-

Command

+

Manual control

X: - - - - + -

Y: - - - - + -

Z: - - - - + -

+
+
Status + +
+ + +
+
+
+

GCODE + +

+ + +
@@ -130,7 +137,7 @@

Command

id="terminal" style=" background-color: black; - font-family: 'Courier New', Courier, monospace; + font-family: Monaco, Courier, monospace; font-size: 14px; overflow: auto; height: 300px; @@ -139,20 +146,24 @@

Command

flex-direction: column-reverse; " > -
-

Status

-
-
+
-

Settings

+
Settings + +
-

Parameters

+
Parameters + +
+
diff --git a/demo/grbl.init.js b/demo/grbl.init.js index c10aa3c..d551eb1 100644 --- a/demo/grbl.init.js +++ b/demo/grbl.init.js @@ -1,18 +1,12 @@ -const status = { - message: '', - info: {}, - settings: {}, - parameters: {}, - error: {}, - version: '', -}; +const state = LegoinoSerial.GRBL.getEmptyState(); const terminal = new LegoinoSerial.Terminal({ onChange: (newEvents, allEvents) => { document.getElementById('terminal').innerHTML = terminal.toHtml(); }, - ignoreSend: [/\?/], - ignoreReceive: [/^(ok|<)/], + //ignoreSend: [/\?/], + // ignoreReceive: [/^(ok|<)/], + showSpecial: false, }); const devicesManager = new LegoinoSerial.DevicesManager(navigator.serial, { @@ -33,7 +27,7 @@ const devicesManager = new LegoinoSerial.DevicesManager(navigator.serial, { }, device: { interCommandDelay: 50, - timeout: 100, + timeout: 1000, }, }); @@ -48,9 +42,9 @@ async function doAll() { }, }); - // monitoring the status + // monitoring the state window.setInterval(async () => { - await sendCommand('?'); + await sendCommand('?', { disableTerminal: true }); }, 250); // checking if anything is coming just like that @@ -60,7 +54,6 @@ async function doAll() { timeout: 20, timeoutResolve: true, }); - console.log(result); }, 2000); } @@ -75,27 +68,51 @@ async function sendCommand(command, options = {}) { await devicesManager .sendCommand('9025-67', command, options) .then((result) => { - LegoinoSerial.GRBL.updateStatus(result, status); + LegoinoSerial.GRBL.updateState(result, state); }) .catch((e) => { - LegoinoSerial.GRBL.updateStatus(e, status); + LegoinoSerial.GRBL.updateState(e, state); }); updateScreen(); } +function sendGcode(text) { + for (let command of text.split(/\r?\n/).filter((line) => line)) { + const sentLine = state.gcode.sentLine++; + sendCommand(`N${sentLine} ${command}`); + } +} + function updateScreen() { - console.log(status.error); - document.getElementById('error').innerHTML = status.error.code - ? `${status.error.code}: ${status.error.description}` - : ''; - document.getElementById('status').innerHTML = ` -

${status.message}

-

X: ${status.info?.MPos?.[0]}

-

Y: ${status.info?.MPos?.[1]}

-

Z: ${status.info?.MPos?.[2]}

- FS: ${status.info.FS}
- Ov: ${status.info.Ov}
- WCO: ${status.info.Ov}
+ document.getElementById('messages').innerHTML = `
${state.messages + .map((message) => { + const style = message.kind.match(/(error|alarm)/i) + ? 'color: red; font-weight: bold' + : ''; + let line = `
${message.kind}: ${message.description}
`; + + return line; + }) + .join('\n')}
`; + + const pinStates = state.status.Pn.map((pinState, pinIndex) => { + const pinName = state.settings[`$P${pinIndex}`]?.description; + return `${String.fromCharCode(88 + pinIndex)}: ${pinState}`; + }).join('\n'); + + document.getElementById('state').innerHTML = ` +
${state.status.value}
+
X: ${state.status?.MPos?.[0]}
+
Y: ${state.status?.MPos?.[1]}
+
Z: ${state.status?.MPos?.[2]}
+ Pin states: ${pinStates}
+ Feed rate: ${state.status.FS?.[0]}
+ Spindle rate: ${state.status.FS?.[1]}
+ GCode line number: ${state.status.Ln?.[0]}
+ Override Values: ${state.status.Ov}
+ Work Coordinate Offset: ${state.status.WCO}
`; document.getElementById('settings').innerHTML = ` @@ -105,9 +122,9 @@ function updateScreen() { Value Description - ${Object.keys(status.settings) + ${Object.keys(state.settings) .sort((a, b) => Number(a.substring(1)) - Number(b.substring(1))) - .map((key) => status.settings[key]) + .map((key) => state.settings[key]) .map( (setting) => ` @@ -129,9 +146,9 @@ function updateScreen() { Value Description - ${Object.keys(status.parameters) + ${Object.keys(state.parameters) .sort() - .map((key) => status.parameters[key]) + .map((key) => state.parameters[key]) .map( (parameter) => ` diff --git a/dist/legoino-navigator-serial.js b/dist/legoino-navigator-serial.js index f1c40b6..994017e 100644 --- a/dist/legoino-navigator-serial.js +++ b/dist/legoino-navigator-serial.js @@ -104,8 +104,9 @@ this.device = device; this.currentTimeout = undefined; this.command = command; - this.timeout = options.timeout ?? 100; + this.timeout = options.timeout ?? 200; this.timeoutResolve = options.timeoutResolve ?? false; + this.disableTerminal = options.disableTerminal ?? false; this.kind = options.kind ?? 'writeRead'; this.answer = ''; this.partialAnswer = ''; @@ -138,12 +139,12 @@ if (this.timeoutResolve) { this.status = STATUS_RESOLVED; this.resolve(this.partialAnswer); - this.device.terminal?.receive(this.partialAnswer); + !this.disableTerminal && this.device.terminal?.receive(this.partialAnswer); this.logger?.info(`Timeout resolved after ${this.timeout}ms`); } else { this.status = STATUS_ERROR$1; this.reject(this.partialAnswer); - this.device.terminal?.receive(this.partialAnswer); + !this.disableTerminal && this.device.terminal?.receive(this.partialAnswer); this.logger?.error(`Timeout reject after ${this.timeout}ms`); } }, this.timeout); @@ -165,7 +166,7 @@ async writeText(command) { if (!command) return; const dataArrayBuffer = encoder.encode(`${command}\n`); - this.device.terminal?.send(command); + !this.disableTerminal && this.device.terminal?.send(command); return this.device.writer.write(dataArrayBuffer); } async readText() { @@ -178,9 +179,9 @@ } this.partialAnswer += decoder.decode(chunk.value); if (this.isEndCommandAnswer(this.command, this.partialAnswer)) break; - await delay$1(1); + await delay$1(5); } - this.device.terminal?.receive(this.partialAnswer); + !this.disableTerminal && this.device.terminal?.receive(this.partialAnswer); } } @@ -299,12 +300,14 @@ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const { timeout = this.timeout, - timeoutResolve = false + timeoutResolve = false, + disableTerminal = false } = options; const action = new Action(command, this, { ...this.commandOptions, timeout, timeoutResolve, + disableTerminal, logger: this.logger.child({ kind: 'Command', command @@ -487,7 +490,8 @@ * @param {string} command Command to send * @param {object} [options={}] options * @param {number} [options.timeout] Timeout in [ms] - * @param {number} [options.timeoutResolve=false] If `true` the promise will resolve even if the command timed out + * @param {boolean} [options.timeoutResolve=false] If `true` the promise will resolve even if the command timed out + * @param {boolean} [options.disableTerminal=false] */ async sendCommand(id, command) { let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; @@ -527,15 +531,16 @@ class Terminal { constructor() { let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.start = Date.now(); this.lineNumber = 0; this.eventNumber = 0; - this.limit = options.limit || 1000; + this.limit = options.limit ?? 1000; this.onChange = options.onChange; this.ignoreSend = options.ignoreSend ?? []; this.ignoreReceive = options.ignoreReceive ?? []; - this.showSpecial = options.showSpecial || true; - this.sendColor = options.sendColor || '#41c5d1'; - this.receiveColor = options.receiveColor || '#2ea600'; + this.showSpecial = options.showSpecial ?? true; + this.sendColor = options.sendColor ?? '#efcef2'; + this.receiveColor = options.receiveColor ?? '#bbeeb7'; this.events = []; } send(text) { @@ -561,6 +566,7 @@ this.lineNumber++; const event = { uuid: v4(), + time: Math.round(Date.now() - this.start), lineNumber: this.lineNumber, eventNumber: this.eventNumber, kind, @@ -580,7 +586,7 @@ let html = []; html.push('
'); for (let event of this.events) { - html.push(`
${htmlEscape(event.line)}
`); + html.push(`
${(event.time / 1000).toFixed(3)}: ${htmlEscape(event.line)}
`); } html.push('
'); return html.join('\n'); @@ -590,12 +596,24 @@ if (showSpecial) { text = text.replace(/\r/g, '').replace(/\n/g, '\n').replace(/\t/g, '\t'); } - return text.split(/\r?\n/); + return text.replace(/[\r\n]+$/, '').split(/\r?\n/); } function htmlEscape(str) { return str.replace(/&/g, '&').replace(/>/g, '>').replace(/ 1 && arguments[1] !== undefined ? arguments[1] : {}; + if (!input) return; const lines = input.split(/\r?\n/); for (let line of lines) { if (line.startsWith('<')) { - parseQuestionMark(line, status); + parseQuestionMark(line, state); } if (line.startsWith('[')) { - parseParameters(line, status); + parseSquareBracket(line, state); } if (line.startsWith('$')) { - parseSettings(line, status); + parseSettings(line, state); } if (line.startsWith('Grbl')) { - status.version = line.replace('Grbl ', ''); + state.version = line.replace('Grbl ', ''); } if (line.startsWith('error')) { - parseErrors(line, status); + parseErrors(line, state); + } + if (line.includes('ALARM')) { + parseAlarms(line, state); } } } - function parseErrors(line, status) { + + /** + * + * @param {string} line + * @param {State} [state={}] + * @returns + */ + function parseErrors(line, state) { const [, error] = line.split(':'); - status.error = { + appendMessage({ + kind: 'ERROR', code: error, description: errorsDescription[error] - }; + }, state); + } + + /** + * + * @param {string} line + * @param {State} [state={}] + * @returns + */ + function parseAlarms(line, state) { + const [, alarm] = line.split(':'); + appendMessage({ + kind: 'ALARM', + code: alarm, + description: alarmsDescription[alarm] + }, state); } - function parseSettings(line, status) { + + /** + * + * @param {string} line + * @param {State} [state] + * @return + */ + function parseSettings(line, state) { const [key, value] = line.split('='); - status.settings[key] = { + state.settings[key] = { key, description: settingsDescription[key], value: Number(value) }; } - function parseParameters(line, status) { + const keyMappings = { + HLP: 'Help', + MSG: 'Message', + GC: 'GCode', + VER: 'Version', + OPT: 'Option', + echo: 'Echo' + }; + + /** + * + * @param {string} line + * @param {State} [state={}] + * @returns + */ + function parseSquareBracket(line) { + let state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const [key, value] = line.replace(/\[(.*)\]/, '$1').split(':'); - status.parameters[key] = { - key, - description: parametersDescription[key], - value: value.split(',').map(field => Number(field)) - }; + const description = line.replace(/\[(.*)\]/, '$1').split(':').slice(1).join(':'); + switch (key) { + case 'echo': + case 'VER': + case 'OPT': + case 'HLP': + case 'GC': + case 'MSG': + appendMessage({ + kind: keyMappings[key], + description + }, state); + return; + default: + state.parameters[key] = { + key, + description: parametersDescription[key], + value: value.split(',').map(field => Number(field)) + }; + } } - function parseQuestionMark(line, status) { + + /** + * + * @param {string} line + * @param {State} [state] + * @returns + */ + function parseQuestionMark(line) { + let state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // const parts = line.replace(/<(.*)>/, '$1').split('|'); - const message = parts[0]; - const info = {}; + const status = { + value: parts[0] + }; + status.Pn = [false, false, false]; for (let i = 1; i < parts.length; i++) { const [key, value] = parts[i].split(':'); - info[key] = value.split(',').map(v => Number(v)); + if (key === 'Pn') { + status[key] = [value.includes('X'), value.includes('Y'), value.includes('Z')]; + } else { + status[key] = value.split(',').map(v => Number(v)); + } } - status.message = message; - status.info = { - ...status.info, - ...info + state.status = { + ...state.status, + ...status }; } + function appendMessage(message, state) { + state.messages.push({ + epoch: Date.now(), + ...message + }); + if (state.messages.length > MAX_ERRORS_MESSAGES) { + state.messages.splice(0, state.messages.length - MAX_ERRORS_MESSAGES); + } + console.log(state.messages); + } + function getEmptyState() { + return { + messages: [], + status: {}, + settings: {}, + parameters: {}, + version: '', + gcode: { + currentLine: 0, + sentLine: 1 + } + }; + } const GRBL = { - updateStatus + updateState, + getEmptyState }; exports.DevicesManager = DevicesManager; diff --git a/dist/legoino-navigator-serial.js.map b/dist/legoino-navigator-serial.js.map index 6740aa3..ff2a73d 100644 --- a/dist/legoino-navigator-serial.js.map +++ b/dist/legoino-navigator-serial.js.map @@ -1 +1 @@ -{"version":3,"file":"legoino-navigator-serial.js","sources":["../node_modules/delay/index.js","../src/Action.js","../src/Device.js","../src/util/EventEmitter.js","../src/util/checkSerial.js","../src/DevicesManager.js","../node_modules/@lukeed/uuid/dist/index.mjs","../src/terminal/Terminal.js","../src/grbl/errorsDescription.js","../src/grbl/parametersDescription.js","../src/grbl/settingsDescription.js","../src/grbl/updateStatus.js","../src/grbl/grbl.js"],"sourcesContent":["'use strict';\n\n// From https://github.com/sindresorhus/random-int/blob/c37741b56f76b9160b0b63dae4e9c64875128146/index.js#L13-L15\nconst randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum);\n\nconst createAbortError = () => {\n\tconst error = new Error('Delay aborted');\n\terror.name = 'AbortError';\n\treturn error;\n};\n\nconst createDelay = ({clearTimeout: defaultClear, setTimeout: set, willResolve}) => (ms, {value, signal} = {}) => {\n\tif (signal && signal.aborted) {\n\t\treturn Promise.reject(createAbortError());\n\t}\n\n\tlet timeoutId;\n\tlet settle;\n\tlet rejectFn;\n\tconst clear = defaultClear || clearTimeout;\n\n\tconst signalListener = () => {\n\t\tclear(timeoutId);\n\t\trejectFn(createAbortError());\n\t};\n\n\tconst cleanup = () => {\n\t\tif (signal) {\n\t\t\tsignal.removeEventListener('abort', signalListener);\n\t\t}\n\t};\n\n\tconst delayPromise = new Promise((resolve, reject) => {\n\t\tsettle = () => {\n\t\t\tcleanup();\n\t\t\tif (willResolve) {\n\t\t\t\tresolve(value);\n\t\t\t} else {\n\t\t\t\treject(value);\n\t\t\t}\n\t\t};\n\n\t\trejectFn = reject;\n\t\ttimeoutId = (set || setTimeout)(settle, ms);\n\t});\n\n\tif (signal) {\n\t\tsignal.addEventListener('abort', signalListener, {once: true});\n\t}\n\n\tdelayPromise.clear = () => {\n\t\tclear(timeoutId);\n\t\ttimeoutId = null;\n\t\tsettle();\n\t};\n\n\treturn delayPromise;\n};\n\nconst createWithTimers = clearAndSet => {\n\tconst delay = createDelay({...clearAndSet, willResolve: true});\n\tdelay.reject = createDelay({...clearAndSet, willResolve: false});\n\tdelay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options);\n\treturn delay;\n};\n\nconst delay = createWithTimers();\ndelay.createWithTimers = createWithTimers;\n\nmodule.exports = delay;\n// TODO: Remove this for the next major release\nmodule.exports.default = delay;\n","import delay from 'delay';\n\nconst STATUS_CREATED = 0;\nconst STATUS_COMMAND_SENT = 10;\nconst STATUS_WAITING_RECEIVING = 20;\nconst STATUS_ANSWER_PARTIALLY_RECEIVED = 30;\nconst STATUS_ANSWER_RECEIVED = 40;\nconst STATUS_RESOLVED = 50;\nconst STATUS_ERROR = 60;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nexport class Action {\n constructor(command, device, options = {}) {\n this.device = device;\n this.currentTimeout = undefined;\n this.command = command;\n this.timeout = options.timeout ?? 100;\n this.timeoutResolve = options.timeoutResolve ?? false;\n this.kind = options.kind ?? 'writeRead';\n this.answer = '';\n this.partialAnswer = '';\n this.logger = options.logger;\n this.status = STATUS_CREATED;\n this.creationTimestamp = Date.now();\n this.promise = new Promise((resolve, reject) => {\n this.reject = reject;\n this.resolve = resolve;\n });\n this.isEndCommandAnswer =\n options.isEndCommandAnswer ??\n (() => {\n throw new Error('isEndCommandAnswer is not defined');\n });\n this.endCommandAnswerCallback =\n options.endCommandAnswerCallback ??\n (() => {\n throw new Error('endCommandAnswerCallback is not defined');\n });\n this.logger?.info('Action created');\n }\n\n isFinished() {\n return this.status === STATUS_RESOLVED || this.status === STATUS_ERROR;\n }\n\n setTimeout() {\n if (this.currentTimeout) {\n clearTimeout(this.currentTimeout);\n }\n this.currentTimeout = setTimeout(() => {\n if (this.status === STATUS_RESOLVED || this.status === STATUS_ERROR) {\n return;\n }\n if (this.timeoutResolve) {\n this.status = STATUS_RESOLVED;\n this.resolve(this.partialAnswer);\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.info(`Timeout resolved after ${this.timeout}ms`);\n } else {\n this.status = STATUS_ERROR;\n this.reject(this.partialAnswer);\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.error(`Timeout reject after ${this.timeout}ms`);\n }\n }, this.timeout);\n }\n\n async writeRead() {\n this.startTimestamp = Date.now();\n this.status = STATUS_COMMAND_SENT;\n await this.setTimeout();\n this.writeText(this.command)\n .then(async () => {\n await this.readText();\n this.status = STATUS_ANSWER_RECEIVED;\n this.answer = this.endCommandAnswerCallback(\n this.command,\n this.partialAnswer,\n );\n })\n .then(() => {\n this.status = STATUS_RESOLVED;\n this.resolve(this.answer);\n });\n return this.promise;\n }\n\n async writeText(command) {\n if (!command) return;\n const dataArrayBuffer = encoder.encode(`${command}\\n`);\n this.device.terminal?.send(command);\n return this.device.writer.write(dataArrayBuffer);\n }\n\n async readText() {\n this.status = STATUS_ANSWER_PARTIALLY_RECEIVED;\n while (this.status === STATUS_ANSWER_PARTIALLY_RECEIVED) {\n const chunk = await this.device.reader.read();\n if (chunk.value.length > 0) {\n // as long as we receive, we delay the timeout\n this.setTimeout();\n }\n this.partialAnswer += decoder.decode(chunk.value);\n if (this.isEndCommandAnswer(this.command, this.partialAnswer)) break;\n await delay(1);\n }\n this.device.terminal?.receive(this.partialAnswer);\n }\n}\n","import delay from 'delay';\n\nimport { Action } from './Action';\n\nexport const STATUS_OPENING = 1;\nexport const STATUS_OPENED = 2;\nexport const STATUS_CLOSED = 3;\nexport const STATUS_MISSING = 9;\nexport const STATUS_ERROR = 10;\nconst statusLabels = {\n [STATUS_OPENING]: 'opening',\n [STATUS_OPENED]: 'opened',\n [STATUS_CLOSED]: 'closed',\n [STATUS_MISSING]: 'missing',\n [STATUS_ERROR]: 'error',\n};\n\nexport class Device {\n constructor(serialPort, options = {}) {\n const { commandOptions = {}, deviceOptions = {} } = options;\n this.logger = options.logger;\n this.terminal = options.terminal;\n this.setStatus(STATUS_OPENING);\n this.id = undefined;\n this.serialPort = serialPort;\n this.baudRate = deviceOptions.baudRate || 115200;\n this.interCommandDelay = deviceOptions.interCommandDelay || 10;\n this.getID =\n deviceOptions.getID ??\n (async (device) => {\n return `${device.usbVendorId}-${device.usbProductId}`;\n });\n this.timeout = deviceOptions.timeout || 100;\n this.commandOptions = commandOptions;\n\n this.queue = [];\n this.action = undefined;\n\n this.usbVendorId = options.usbVendorId;\n this.usbProductId = options.usbProductId;\n this.logger?.info(`Device created`);\n }\n\n setStatus(status) {\n this.status = status;\n this.statusLabel = statusLabels[status];\n }\n\n isReady() {\n return this.status === STATUS_OPENED;\n }\n\n /** restart process queue if the previous one was finished */\n async ensureProcessQueue() {\n this.logger?.info('ensureProcessQueue');\n if (!this.currentProcessQueue) {\n this.currentProcessQueue = this.runProcessQueue();\n }\n return this.currentProcessQueue;\n }\n\n async runProcessQueue() {\n while (this.queue.length > 0) {\n this.action = this.queue.shift();\n if (this.action) {\n await this.action\n .writeRead()\n .then((value) => {\n this.logger?.info(\n { command: this.action.command, answer: this.action.answer },\n 'Resolve writeRead command',\n );\n })\n .catch((error) => {\n this.logger?.error(\n {\n command: this.action.command,\n answer: this.action.partialAnswer,\n },\n error.toString(),\n );\n });\n\n this.action = undefined;\n await delay(this.interCommandDelay);\n }\n }\n this.currentProcessQueue = undefined;\n }\n\n async getStatus() {\n return {\n value: this.status,\n };\n }\n\n async ensureOpen() {\n this.logger?.trace(`Ensure open`);\n let counter = 0;\n // we wait for the serial port to be opened for max 1s\n while (this.status === STATUS_OPENING && counter++ < 100) {\n await delay(10);\n }\n\n if (this.status !== STATUS_OPENED) {\n return this.open();\n }\n }\n\n async open() {\n this.logger?.info(`Opening`);\n await this.serialPort\n .open({\n baudRate: this.baudRate,\n })\n .catch((error) => {\n this.error(error);\n this.close();\n })\n .then(() => {\n this.ensureOpen();\n });\n this.reader = this.serialPort.readable.getReader();\n this.writer = this.serialPort.writable.getWriter();\n this.logger?.info(`Getting id`);\n\n this.id = await this.getID(this);\n\n this.logger?.info(`Id: ${this.id}`);\n this.setStatus(STATUS_OPENED);\n }\n\n /*\n We need to add this command in the queue and wait it resolves or rejects\n */\n async get(command, options = {}) {\n const { timeout = this.timeout, timeoutResolve = false } = options;\n\n const action = new Action(command, this, {\n ...this.commandOptions,\n timeout,\n timeoutResolve,\n logger: this.logger.child({ kind: 'Command', command }),\n });\n\n this.queue.push(action);\n this.ensureProcessQueue();\n return action.promise;\n }\n\n error(error) {\n this.logger?.error(error, `Error ${this.serialPort?.path}`);\n this.setStatus(STATUS_ERROR);\n /**\n this.emit('adapter', {\n event: 'Error',\n value: error,\n });\n **/\n }\n\n close() {\n this.logger?.info(`Close`);\n this.setStatus(STATUS_CLOSED);\n }\n}\n","export default class EventEmitter {\n constructor() {\n this.callbacks = {};\n }\n\n on(event, cb) {\n if (!this.callbacks[event]) this.callbacks[event] = [];\n this.callbacks[event].push(cb);\n }\n\n emit(event, data) {\n let cbs = this.callbacks[event];\n if (cbs) {\n cbs.forEach((cb) => cb(data));\n }\n }\n}\n","/* eslint-disable no-console */\nexport default function checkSerial(serial) {\n if (!serial) {\n console.error(\n \"Web serial doesn't seem to be enabled in your browser. Try enabling it by visiting:\",\n );\n console.error('chrome://flags/#enable-experimental-web-platform-features');\n console.error('opera://flags/#enable-experimental-web-platform-features');\n console.error('edge://flags/#enable-experimental-web-platform-features');\n }\n}\n","import delay from 'delay';\n\nimport { Device, STATUS_MISSING, STATUS_OPENED, STATUS_CLOSED } from './Device';\nimport EventEmitter from './util/EventEmitter';\nimport checkSerial from './util/checkSerial';\n\n/**\n * Class creating a new serial bridge to manage serial ports.\n * @param {object} [options={}]\n * @param {Array} [options.portFilter] Filter the serial ports to address.\n * @param {object} [options.command={}]\n * @param {number} [options.command.timeout=100] Time to wait for answer before timeout\n * @param {Function} [options.command.isEndCommandAnswer]\n * @param {Function} [options.command.endCommandAnswerCallback]\n * @param {object} [options.device={}]\n * @param {AsyncFunction} [options.device.getID=(device)=>()] Time to wait between commands in [ms]\n * @param {number} [options.device.baudRate=115200] Baud rate\n * @param {number} [options.device.interCommandDelay=100] Time to wait between commands in [ms]\n */\nexport class DevicesManager extends EventEmitter {\n constructor(serial, options = {}) {\n super();\n checkSerial(serial);\n this.serial = serial;\n this.terminal = options.terminal;\n this.logger = options.logger;\n this.devices = [];\n this.portFilter = options.portFilter;\n this.commandOptions = options.command ?? {};\n this.deviceOptions = options.device ?? {};\n }\n\n /**\n * By calling this method from a click you give users the possibility to allow access to some devices\n */\n async requestDevices() {\n await this.serial.requestPort({\n filters: this.portFilter,\n });\n return this.updateDevices();\n }\n\n /**\n * Update this.devices\n */\n async updateDevices() {\n const serialPorts = await this.serial.getPorts();\n\n this.logger?.trace('start updateDevices');\n\n const missingDevicesSerialPort = this.devices.filter(\n (device) => !serialPorts.includes(device.serialPort),\n );\n for (let device of missingDevicesSerialPort) {\n if (device.status !== STATUS_MISSING && device.status !== STATUS_CLOSED) {\n device.close();\n }\n device.status = STATUS_MISSING;\n }\n for (let serialPort of serialPorts) {\n let device = this.devices.find(\n (device) => device.serialPort === serialPort,\n );\n if (device) {\n await device.ensureOpen();\n } else {\n const serialPortInfo = serialPort.getInfo();\n let newDevice = new Device(serialPort, {\n baudRate: this.baudRate,\n terminal: this.terminal,\n ...serialPortInfo,\n commandOptions: this.commandOptions,\n deviceOptions: this.deviceOptions,\n logger: this.logger.child({\n kind: 'Device',\n ...serialPort.getInfo(),\n }),\n });\n this.devices.push(newDevice);\n await newDevice.open();\n }\n }\n\n this.logger?.trace('finish updateDevices');\n }\n\n /**\n * Update this.devices every `scanInterval` [ms].\n * @param {object} [options={}]\n * @param {number} [options.scanInterval=1000] Delay between `updateDevices()` calls\n * @param {number} [options.callback] Callback to execute on each update\n */\n async continuousUpdateDevices(options = {}) {\n const { scanInterval = 1000, callback } = options;\n while (true) {\n await this.updateDevices();\n if (callback) {\n callback(this.devices);\n }\n await delay(scanInterval);\n }\n }\n\n /**\n * Returns this.devices\n * @param {object} [options={}]\n * @param {bool} [options.ready=false] If `true` returns only currently connected device. If `false` returns all devices ever connected.\n * @returns {Array}\n */\n getDevicesList(options = {}) {\n let { ready = false } = options;\n return this.devices\n .filter((device) => !ready || device.isReady())\n .map((device) => ({\n status: device.status,\n id: device.id,\n queueLength: device.queue.length,\n }));\n }\n\n // private function\n findDevice(id) {\n if (id === undefined) return undefined;\n let devices = this.devices.filter(\n (device) => device.id === id && device.status === STATUS_OPENED,\n );\n if (devices.length === 0) return undefined;\n if (devices.length > 1) {\n throw new Error(`Many devices have the same id: ${id}`);\n }\n return devices[0];\n }\n\n /**\n * Send a serial command to a device.\n * @param {number} id ID of the device\n * @param {string} command Command to send\n * @param {object} [options={}] options\n * @param {number} [options.timeout] Timeout in [ms]\n * @param {number} [options.timeoutResolve=false] If `true` the promise will resolve even if the command timed out\n */\n async sendCommand(id, command, options = {}) {\n const device = this.findDevice(id);\n if (!device) {\n throw Error(`Device ${id} not found`);\n }\n if (device && device.isReady()) {\n return device.get(command, options);\n }\n throw Error(`Device ${id} not ready: ${device.port.path}`);\n }\n}\n","var IDX=256, HEX=[], BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function v4() {\n\tvar i=0, num, out='';\n\n\tif (!BUFFER || ((IDX + 16) > 256)) {\n\t\tBUFFER = Array(i=256);\n\t\twhile (i--) BUFFER[i] = 256 * Math.random() | 0;\n\t\ti = IDX = 0;\n\t}\n\n\tfor (; i < 16; i++) {\n\t\tnum = BUFFER[IDX + i];\n\t\tif (i==6) out += HEX[num & 15 | 64];\n\t\telse if (i==8) out += HEX[num & 63 | 128];\n\t\telse out += HEX[num];\n\n\t\tif (i & 1 && i > 1 && i < 11) out += '-';\n\t}\n\n\tIDX++;\n\treturn out;\n}\n","import { v4 } from '@lukeed/uuid';\n\nexport class Terminal {\n constructor(options = {}) {\n this.lineNumber = 0;\n this.eventNumber = 0;\n this.limit = options.limit || 1000;\n this.onChange = options.onChange;\n this.ignoreSend = options.ignoreSend ?? [];\n this.ignoreReceive = options.ignoreReceive ?? [];\n this.showSpecial = options.showSpecial || true;\n this.sendColor = options.sendColor || '#41c5d1';\n this.receiveColor = options.receiveColor || '#2ea600';\n this.events = [];\n }\n\n send(text) {\n this.append(text, 'send');\n }\n\n receive(text) {\n this.append(text, 'receive');\n }\n\n shouldIgnore(line, kind) {\n const ignores = kind === 'send' ? this.ignoreSend : this.ignoreReceive;\n for (let ignore of ignores) {\n if (ignore.test(line)) {\n return true;\n }\n }\n return false;\n }\n\n append(text, kind) {\n const lines = splitInLines(text, this.showSpecial);\n this.eventNumber++;\n const newEvents = [];\n for (let line of lines) {\n this.lineNumber++;\n const event = {\n uuid: v4(),\n lineNumber: this.lineNumber,\n eventNumber: this.eventNumber,\n kind,\n line,\n };\n if (!this.shouldIgnore(line, kind)) {\n newEvents.push(event);\n this.events.push(event);\n }\n }\n\n if (this.events.length > this.limit) {\n this.events.splice(0, this.events.length - this.limit);\n }\n\n this.onChange?.(newEvents, this.events);\n }\n\n toHtml() {\n let html = [];\n html.push('
');\n for (let event of this.events) {\n html.push(\n `
${htmlEscape(event.line)}
`,\n );\n }\n html.push('
');\n return html.join('\\n');\n }\n}\n\nfunction splitInLines(text, showSpecial) {\n if (showSpecial) {\n text = text\n .replace(/\\r/g, '')\n .replace(/\\n/g, '\\n')\n .replace(/\\t/g, '\\t');\n }\n return text.split(/\\r?\\n/);\n}\n\nfunction htmlEscape(str) {\n return str.replace(/&/g, '&').replace(/>/g, '>').replace(/ Number(field)),\n };\n}\n\nfunction parseQuestionMark(line, status) {\n // \n const parts = line.replace(/<(.*)>/, '$1').split('|');\n const message = parts[0];\n const info = {};\n for (let i = 1; i < parts.length; i++) {\n const [key, value] = parts[i].split(':');\n info[key] = value.split(',').map((v) => Number(v));\n }\n status.message = message;\n status.info = { ...status.info, ...info };\n}\n","import { updateStatus } from './updateStatus.js';\n\nexport const GRBL = {\n updateStatus,\n};\n"],"names":["randomInteger","minimum","maximum","Math","floor","random","createAbortError","error","Error","name","createDelay","_ref","clearTimeout","defaultClear","setTimeout","set","willResolve","ms","value","signal","arguments","length","undefined","aborted","Promise","reject","timeoutId","settle","rejectFn","clear","signalListener","cleanup","removeEventListener","delayPromise","resolve","addEventListener","once","createWithTimers","clearAndSet","delay","range","options","delayModule","exports","delay_1","default","STATUS_CREATED","STATUS_COMMAND_SENT","STATUS_ANSWER_PARTIALLY_RECEIVED","STATUS_ANSWER_RECEIVED","STATUS_RESOLVED","STATUS_ERROR","encoder","TextEncoder","decoder","TextDecoder","Action","constructor","command","device","currentTimeout","timeout","timeoutResolve","kind","answer","partialAnswer","logger","status","creationTimestamp","Date","now","promise","isEndCommandAnswer","endCommandAnswerCallback","info","isFinished","terminal","receive","writeRead","startTimestamp","writeText","then","readText","dataArrayBuffer","encode","send","writer","write","chunk","reader","read","decode","STATUS_OPENING","STATUS_OPENED","STATUS_CLOSED","STATUS_MISSING","statusLabels","Device","serialPort","commandOptions","deviceOptions","setStatus","id","baudRate","interCommandDelay","getID","usbVendorId","usbProductId","queue","action","statusLabel","isReady","ensureProcessQueue","currentProcessQueue","runProcessQueue","shift","catch","toString","getStatus","ensureOpen","trace","counter","open","close","readable","getReader","writable","getWriter","get","child","push","path","EventEmitter","callbacks","on","event","cb","emit","data","cbs","forEach","checkSerial","serial","console","DevicesManager","devices","portFilter","requestDevices","requestPort","filters","updateDevices","serialPorts","getPorts","missingDevicesSerialPort","filter","includes","find","serialPortInfo","getInfo","newDevice","continuousUpdateDevices","scanInterval","callback","getDevicesList","ready","map","queueLength","findDevice","sendCommand","port","IDX","HEX","BUFFER","substring","v4","i","num","out","Array","Terminal","lineNumber","eventNumber","limit","onChange","ignoreSend","ignoreReceive","showSpecial","sendColor","receiveColor","events","text","append","shouldIgnore","line","ignores","ignore","test","lines","splitInLines","newEvents","uuid","splice","toHtml","html","htmlEscape","join","replace","split","str","errorsDescription","parametersDescription","settingsDescription","$0","$1","$2","$3","$4","$5","$6","$10","$11","$12","$13","$20","$21","$22","$23","$24","$25","$26","$27","$30","$31","$32","$100","$101","$102","$110","$111","$112","$120","$121","$122","$130","$131","$132","updateStatus","input","startsWith","parseQuestionMark","parseParameters","parseSettings","version","parseErrors","code","description","key","settings","Number","parameters","field","parts","message","v","GRBL"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"legoino-navigator-serial.js","sources":["../node_modules/delay/index.js","../src/Action.js","../src/Device.js","../src/util/EventEmitter.js","../src/util/checkSerial.js","../src/DevicesManager.js","../node_modules/@lukeed/uuid/dist/index.mjs","../src/terminal/Terminal.js","../src/grbl/alarmsDescription.js","../src/grbl/errorsDescription.js","../src/grbl/parametersDescription.js","../src/grbl/settingsDescription.js","../src/grbl/updateState.js","../src/grbl/grbl.js"],"sourcesContent":["'use strict';\n\n// From https://github.com/sindresorhus/random-int/blob/c37741b56f76b9160b0b63dae4e9c64875128146/index.js#L13-L15\nconst randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum);\n\nconst createAbortError = () => {\n\tconst error = new Error('Delay aborted');\n\terror.name = 'AbortError';\n\treturn error;\n};\n\nconst createDelay = ({clearTimeout: defaultClear, setTimeout: set, willResolve}) => (ms, {value, signal} = {}) => {\n\tif (signal && signal.aborted) {\n\t\treturn Promise.reject(createAbortError());\n\t}\n\n\tlet timeoutId;\n\tlet settle;\n\tlet rejectFn;\n\tconst clear = defaultClear || clearTimeout;\n\n\tconst signalListener = () => {\n\t\tclear(timeoutId);\n\t\trejectFn(createAbortError());\n\t};\n\n\tconst cleanup = () => {\n\t\tif (signal) {\n\t\t\tsignal.removeEventListener('abort', signalListener);\n\t\t}\n\t};\n\n\tconst delayPromise = new Promise((resolve, reject) => {\n\t\tsettle = () => {\n\t\t\tcleanup();\n\t\t\tif (willResolve) {\n\t\t\t\tresolve(value);\n\t\t\t} else {\n\t\t\t\treject(value);\n\t\t\t}\n\t\t};\n\n\t\trejectFn = reject;\n\t\ttimeoutId = (set || setTimeout)(settle, ms);\n\t});\n\n\tif (signal) {\n\t\tsignal.addEventListener('abort', signalListener, {once: true});\n\t}\n\n\tdelayPromise.clear = () => {\n\t\tclear(timeoutId);\n\t\ttimeoutId = null;\n\t\tsettle();\n\t};\n\n\treturn delayPromise;\n};\n\nconst createWithTimers = clearAndSet => {\n\tconst delay = createDelay({...clearAndSet, willResolve: true});\n\tdelay.reject = createDelay({...clearAndSet, willResolve: false});\n\tdelay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options);\n\treturn delay;\n};\n\nconst delay = createWithTimers();\ndelay.createWithTimers = createWithTimers;\n\nmodule.exports = delay;\n// TODO: Remove this for the next major release\nmodule.exports.default = delay;\n","import delay from 'delay';\n\nconst STATUS_CREATED = 0;\nconst STATUS_COMMAND_SENT = 10;\nconst STATUS_WAITING_RECEIVING = 20;\nconst STATUS_ANSWER_PARTIALLY_RECEIVED = 30;\nconst STATUS_ANSWER_RECEIVED = 40;\nconst STATUS_RESOLVED = 50;\nconst STATUS_ERROR = 60;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nexport class Action {\n constructor(command, device, options = {}) {\n this.device = device;\n this.currentTimeout = undefined;\n this.command = command;\n this.timeout = options.timeout ?? 200;\n this.timeoutResolve = options.timeoutResolve ?? false;\n this.disableTerminal = options.disableTerminal ?? false;\n this.kind = options.kind ?? 'writeRead';\n this.answer = '';\n this.partialAnswer = '';\n this.logger = options.logger;\n this.status = STATUS_CREATED;\n this.creationTimestamp = Date.now();\n this.promise = new Promise((resolve, reject) => {\n this.reject = reject;\n this.resolve = resolve;\n });\n this.isEndCommandAnswer =\n options.isEndCommandAnswer ??\n (() => {\n throw new Error('isEndCommandAnswer is not defined');\n });\n this.endCommandAnswerCallback =\n options.endCommandAnswerCallback ??\n (() => {\n throw new Error('endCommandAnswerCallback is not defined');\n });\n this.logger?.info('Action created');\n }\n\n isFinished() {\n return this.status === STATUS_RESOLVED || this.status === STATUS_ERROR;\n }\n\n setTimeout() {\n if (this.currentTimeout) {\n clearTimeout(this.currentTimeout);\n }\n this.currentTimeout = setTimeout(() => {\n if (this.status === STATUS_RESOLVED || this.status === STATUS_ERROR) {\n return;\n }\n if (this.timeoutResolve) {\n this.status = STATUS_RESOLVED;\n this.resolve(this.partialAnswer);\n !this.disableTerminal &&\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.info(`Timeout resolved after ${this.timeout}ms`);\n } else {\n this.status = STATUS_ERROR;\n this.reject(this.partialAnswer);\n !this.disableTerminal &&\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.error(`Timeout reject after ${this.timeout}ms`);\n }\n }, this.timeout);\n }\n\n async writeRead() {\n this.startTimestamp = Date.now();\n this.status = STATUS_COMMAND_SENT;\n await this.setTimeout();\n this.writeText(this.command)\n .then(async () => {\n await this.readText();\n this.status = STATUS_ANSWER_RECEIVED;\n this.answer = this.endCommandAnswerCallback(\n this.command,\n this.partialAnswer,\n );\n })\n .then(() => {\n this.status = STATUS_RESOLVED;\n this.resolve(this.answer);\n });\n return this.promise;\n }\n\n async writeText(command) {\n if (!command) return;\n const dataArrayBuffer = encoder.encode(`${command}\\n`);\n !this.disableTerminal && this.device.terminal?.send(command);\n return this.device.writer.write(dataArrayBuffer);\n }\n\n async readText() {\n this.status = STATUS_ANSWER_PARTIALLY_RECEIVED;\n while (this.status === STATUS_ANSWER_PARTIALLY_RECEIVED) {\n const chunk = await this.device.reader.read();\n if (chunk.value.length > 0) {\n // as long as we receive, we delay the timeout\n this.setTimeout();\n }\n this.partialAnswer += decoder.decode(chunk.value);\n if (this.isEndCommandAnswer(this.command, this.partialAnswer)) break;\n await delay(5);\n }\n !this.disableTerminal && this.device.terminal?.receive(this.partialAnswer);\n }\n}\n","import delay from 'delay';\n\nimport { Action } from './Action';\n\nexport const STATUS_OPENING = 1;\nexport const STATUS_OPENED = 2;\nexport const STATUS_CLOSED = 3;\nexport const STATUS_MISSING = 9;\nexport const STATUS_ERROR = 10;\nconst statusLabels = {\n [STATUS_OPENING]: 'opening',\n [STATUS_OPENED]: 'opened',\n [STATUS_CLOSED]: 'closed',\n [STATUS_MISSING]: 'missing',\n [STATUS_ERROR]: 'error',\n};\n\nexport class Device {\n constructor(serialPort, options = {}) {\n const { commandOptions = {}, deviceOptions = {} } = options;\n this.logger = options.logger;\n this.terminal = options.terminal;\n this.setStatus(STATUS_OPENING);\n this.id = undefined;\n this.serialPort = serialPort;\n this.baudRate = deviceOptions.baudRate || 115200;\n this.interCommandDelay = deviceOptions.interCommandDelay || 10;\n this.getID =\n deviceOptions.getID ??\n (async (device) => {\n return `${device.usbVendorId}-${device.usbProductId}`;\n });\n this.timeout = deviceOptions.timeout || 100;\n this.commandOptions = commandOptions;\n\n this.queue = [];\n this.action = undefined;\n\n this.usbVendorId = options.usbVendorId;\n this.usbProductId = options.usbProductId;\n this.logger?.info(`Device created`);\n }\n\n setStatus(status) {\n this.status = status;\n this.statusLabel = statusLabels[status];\n }\n\n isReady() {\n return this.status === STATUS_OPENED;\n }\n\n /** restart process queue if the previous one was finished */\n async ensureProcessQueue() {\n this.logger?.info('ensureProcessQueue');\n if (!this.currentProcessQueue) {\n this.currentProcessQueue = this.runProcessQueue();\n }\n return this.currentProcessQueue;\n }\n\n async runProcessQueue() {\n while (this.queue.length > 0) {\n this.action = this.queue.shift();\n if (this.action) {\n await this.action\n .writeRead()\n .then((value) => {\n this.logger?.info(\n { command: this.action.command, answer: this.action.answer },\n 'Resolve writeRead command',\n );\n })\n .catch((error) => {\n this.logger?.error(\n {\n command: this.action.command,\n answer: this.action.partialAnswer,\n },\n error.toString(),\n );\n });\n\n this.action = undefined;\n await delay(this.interCommandDelay);\n }\n }\n this.currentProcessQueue = undefined;\n }\n\n async getStatus() {\n return {\n value: this.status,\n };\n }\n\n async ensureOpen() {\n this.logger?.trace(`Ensure open`);\n let counter = 0;\n // we wait for the serial port to be opened for max 1s\n while (this.status === STATUS_OPENING && counter++ < 100) {\n await delay(10);\n }\n\n if (this.status !== STATUS_OPENED) {\n return this.open();\n }\n }\n\n async open() {\n this.logger?.info(`Opening`);\n await this.serialPort\n .open({\n baudRate: this.baudRate,\n })\n .catch((error) => {\n this.error(error);\n this.close();\n })\n .then(() => {\n this.ensureOpen();\n });\n this.reader = this.serialPort.readable.getReader();\n this.writer = this.serialPort.writable.getWriter();\n this.logger?.info(`Getting id`);\n\n this.id = await this.getID(this);\n\n this.logger?.info(`Id: ${this.id}`);\n this.setStatus(STATUS_OPENED);\n }\n\n /*\n We need to add this command in the queue and wait it resolves or rejects\n */\n async get(command, options = {}) {\n const {\n timeout = this.timeout,\n timeoutResolve = false,\n disableTerminal = false,\n } = options;\n\n const action = new Action(command, this, {\n ...this.commandOptions,\n timeout,\n timeoutResolve,\n disableTerminal,\n logger: this.logger.child({ kind: 'Command', command }),\n });\n\n this.queue.push(action);\n this.ensureProcessQueue();\n return action.promise;\n }\n\n error(error) {\n this.logger?.error(error, `Error ${this.serialPort?.path}`);\n this.setStatus(STATUS_ERROR);\n /**\n this.emit('adapter', {\n event: 'Error',\n value: error,\n });\n **/\n }\n\n close() {\n this.logger?.info(`Close`);\n this.setStatus(STATUS_CLOSED);\n }\n}\n","export default class EventEmitter {\n constructor() {\n this.callbacks = {};\n }\n\n on(event, cb) {\n if (!this.callbacks[event]) this.callbacks[event] = [];\n this.callbacks[event].push(cb);\n }\n\n emit(event, data) {\n let cbs = this.callbacks[event];\n if (cbs) {\n cbs.forEach((cb) => cb(data));\n }\n }\n}\n","/* eslint-disable no-console */\nexport default function checkSerial(serial) {\n if (!serial) {\n console.error(\n \"Web serial doesn't seem to be enabled in your browser. Try enabling it by visiting:\",\n );\n console.error('chrome://flags/#enable-experimental-web-platform-features');\n console.error('opera://flags/#enable-experimental-web-platform-features');\n console.error('edge://flags/#enable-experimental-web-platform-features');\n }\n}\n","import delay from 'delay';\n\nimport { Device, STATUS_MISSING, STATUS_OPENED, STATUS_CLOSED } from './Device';\nimport EventEmitter from './util/EventEmitter';\nimport checkSerial from './util/checkSerial';\n\n/**\n * Class creating a new serial bridge to manage serial ports.\n * @param {object} [options={}]\n * @param {Array} [options.portFilter] Filter the serial ports to address.\n * @param {object} [options.command={}]\n * @param {number} [options.command.timeout=100] Time to wait for answer before timeout\n * @param {Function} [options.command.isEndCommandAnswer]\n * @param {Function} [options.command.endCommandAnswerCallback]\n * @param {object} [options.device={}]\n * @param {AsyncFunction} [options.device.getID=(device)=>()] Time to wait between commands in [ms]\n * @param {number} [options.device.baudRate=115200] Baud rate\n * @param {number} [options.device.interCommandDelay=100] Time to wait between commands in [ms]\n */\nexport class DevicesManager extends EventEmitter {\n constructor(serial, options = {}) {\n super();\n checkSerial(serial);\n this.serial = serial;\n this.terminal = options.terminal;\n this.logger = options.logger;\n this.devices = [];\n this.portFilter = options.portFilter;\n this.commandOptions = options.command ?? {};\n this.deviceOptions = options.device ?? {};\n }\n\n /**\n * By calling this method from a click you give users the possibility to allow access to some devices\n */\n async requestDevices() {\n await this.serial.requestPort({\n filters: this.portFilter,\n });\n return this.updateDevices();\n }\n\n /**\n * Update this.devices\n */\n async updateDevices() {\n const serialPorts = await this.serial.getPorts();\n\n this.logger?.trace('start updateDevices');\n\n const missingDevicesSerialPort = this.devices.filter(\n (device) => !serialPorts.includes(device.serialPort),\n );\n for (let device of missingDevicesSerialPort) {\n if (device.status !== STATUS_MISSING && device.status !== STATUS_CLOSED) {\n device.close();\n }\n device.status = STATUS_MISSING;\n }\n for (let serialPort of serialPorts) {\n let device = this.devices.find(\n (device) => device.serialPort === serialPort,\n );\n if (device) {\n await device.ensureOpen();\n } else {\n const serialPortInfo = serialPort.getInfo();\n let newDevice = new Device(serialPort, {\n baudRate: this.baudRate,\n terminal: this.terminal,\n ...serialPortInfo,\n commandOptions: this.commandOptions,\n deviceOptions: this.deviceOptions,\n logger: this.logger.child({\n kind: 'Device',\n ...serialPort.getInfo(),\n }),\n });\n this.devices.push(newDevice);\n await newDevice.open();\n }\n }\n\n this.logger?.trace('finish updateDevices');\n }\n\n /**\n * Update this.devices every `scanInterval` [ms].\n * @param {object} [options={}]\n * @param {number} [options.scanInterval=1000] Delay between `updateDevices()` calls\n * @param {number} [options.callback] Callback to execute on each update\n */\n async continuousUpdateDevices(options = {}) {\n const { scanInterval = 1000, callback } = options;\n while (true) {\n await this.updateDevices();\n if (callback) {\n callback(this.devices);\n }\n await delay(scanInterval);\n }\n }\n\n /**\n * Returns this.devices\n * @param {object} [options={}]\n * @param {bool} [options.ready=false] If `true` returns only currently connected device. If `false` returns all devices ever connected.\n * @returns {Array}\n */\n getDevicesList(options = {}) {\n let { ready = false } = options;\n return this.devices\n .filter((device) => !ready || device.isReady())\n .map((device) => ({\n status: device.status,\n id: device.id,\n queueLength: device.queue.length,\n }));\n }\n\n // private function\n findDevice(id) {\n if (id === undefined) return undefined;\n let devices = this.devices.filter(\n (device) => device.id === id && device.status === STATUS_OPENED,\n );\n if (devices.length === 0) return undefined;\n if (devices.length > 1) {\n throw new Error(`Many devices have the same id: ${id}`);\n }\n return devices[0];\n }\n\n /**\n * Send a serial command to a device.\n * @param {number} id ID of the device\n * @param {string} command Command to send\n * @param {object} [options={}] options\n * @param {number} [options.timeout] Timeout in [ms]\n * @param {boolean} [options.timeoutResolve=false] If `true` the promise will resolve even if the command timed out\n * @param {boolean} [options.disableTerminal=false]\n */\n async sendCommand(id, command, options = {}) {\n const device = this.findDevice(id);\n if (!device) {\n throw Error(`Device ${id} not found`);\n }\n if (device && device.isReady()) {\n return device.get(command, options);\n }\n throw Error(`Device ${id} not ready: ${device.port.path}`);\n }\n}\n","var IDX=256, HEX=[], BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function v4() {\n\tvar i=0, num, out='';\n\n\tif (!BUFFER || ((IDX + 16) > 256)) {\n\t\tBUFFER = Array(i=256);\n\t\twhile (i--) BUFFER[i] = 256 * Math.random() | 0;\n\t\ti = IDX = 0;\n\t}\n\n\tfor (; i < 16; i++) {\n\t\tnum = BUFFER[IDX + i];\n\t\tif (i==6) out += HEX[num & 15 | 64];\n\t\telse if (i==8) out += HEX[num & 63 | 128];\n\t\telse out += HEX[num];\n\n\t\tif (i & 1 && i > 1 && i < 11) out += '-';\n\t}\n\n\tIDX++;\n\treturn out;\n}\n","import { v4 } from '@lukeed/uuid';\n\nexport class Terminal {\n constructor(options = {}) {\n this.start = Date.now();\n this.lineNumber = 0;\n this.eventNumber = 0;\n this.limit = options.limit ?? 1000;\n this.onChange = options.onChange;\n this.ignoreSend = options.ignoreSend ?? [];\n this.ignoreReceive = options.ignoreReceive ?? [];\n this.showSpecial = options.showSpecial ?? true;\n this.sendColor = options.sendColor ?? '#efcef2';\n this.receiveColor = options.receiveColor ?? '#bbeeb7';\n this.events = [];\n }\n\n send(text) {\n this.append(text, 'send');\n }\n\n receive(text) {\n this.append(text, 'receive');\n }\n\n shouldIgnore(line, kind) {\n const ignores = kind === 'send' ? this.ignoreSend : this.ignoreReceive;\n for (let ignore of ignores) {\n if (ignore.test(line)) {\n return true;\n }\n }\n return false;\n }\n\n append(text, kind) {\n const lines = splitInLines(text, this.showSpecial);\n this.eventNumber++;\n const newEvents = [];\n for (let line of lines) {\n this.lineNumber++;\n const event = {\n uuid: v4(),\n time: Math.round(Date.now() - this.start),\n lineNumber: this.lineNumber,\n eventNumber: this.eventNumber,\n kind,\n line,\n };\n if (!this.shouldIgnore(line, kind)) {\n newEvents.push(event);\n this.events.push(event);\n }\n }\n\n if (this.events.length > this.limit) {\n this.events.splice(0, this.events.length - this.limit);\n }\n\n this.onChange?.(newEvents, this.events);\n }\n\n toHtml() {\n let html = [];\n html.push('
');\n for (let event of this.events) {\n html.push(\n `
${(event.time / 1000).toFixed(3)}: ${htmlEscape(event.line)}
`,\n );\n }\n html.push('
');\n return html.join('\\n');\n }\n}\n\nfunction splitInLines(text, showSpecial) {\n if (showSpecial) {\n text = text\n .replace(/\\r/g, '')\n .replace(/\\n/g, '\\n')\n .replace(/\\t/g, '\\t');\n }\n return text.replace(/[\\r\\n]+$/, '').split(/\\r?\\n/);\n}\n\nfunction htmlEscape(str) {\n return str.replace(/&/g, '&').replace(/>/g, '>').replace(/ Number(field)),\n };\n }\n}\n\n/**\n *\n * @param {string} line\n * @param {State} [state]\n * @returns\n */\nfunction parseQuestionMark(line, state = {}) {\n // \n const parts = line.replace(/<(.*)>/, '$1').split('|');\n const status = { value: parts[0] };\n status.Pn = [false, false, false];\n for (let i = 1; i < parts.length; i++) {\n const [key, value] = parts[i].split(':');\n\n if (key === 'Pn') {\n status[key] = [\n value.includes('X'),\n value.includes('Y'),\n value.includes('Z'),\n ];\n } else {\n status[key] = value.split(',').map((v) => Number(v));\n }\n }\n state.status = { ...state.status, ...status };\n}\n\nfunction appendMessage(message, state) {\n state.messages.push({\n epoch: Date.now(),\n ...message,\n });\n if (state.messages.length > MAX_ERRORS_MESSAGES) {\n state.messages.splice(0, state.messages.length - MAX_ERRORS_MESSAGES);\n }\n console.log(state.messages);\n}\n","import { updateState } from './updateState.js';\n\nfunction getEmptyState() {\n return {\n messages: [],\n status: {},\n settings: {},\n parameters: {},\n version: '',\n gcode: {\n currentLine: 0,\n sentLine: 1,\n },\n };\n}\n\nexport const GRBL = {\n updateState,\n getEmptyState,\n};\n"],"names":["randomInteger","minimum","maximum","Math","floor","random","createAbortError","error","Error","name","createDelay","_ref","clearTimeout","defaultClear","setTimeout","set","willResolve","ms","value","signal","arguments","length","undefined","aborted","Promise","reject","timeoutId","settle","rejectFn","clear","signalListener","cleanup","removeEventListener","delayPromise","resolve","addEventListener","once","createWithTimers","clearAndSet","delay","range","options","delayModule","exports","delay_1","default","STATUS_CREATED","STATUS_COMMAND_SENT","STATUS_ANSWER_PARTIALLY_RECEIVED","STATUS_ANSWER_RECEIVED","STATUS_RESOLVED","STATUS_ERROR","encoder","TextEncoder","decoder","TextDecoder","Action","constructor","command","device","currentTimeout","timeout","timeoutResolve","disableTerminal","kind","answer","partialAnswer","logger","status","creationTimestamp","Date","now","promise","isEndCommandAnswer","endCommandAnswerCallback","info","isFinished","terminal","receive","writeRead","startTimestamp","writeText","then","readText","dataArrayBuffer","encode","send","writer","write","chunk","reader","read","decode","STATUS_OPENING","STATUS_OPENED","STATUS_CLOSED","STATUS_MISSING","statusLabels","Device","serialPort","commandOptions","deviceOptions","setStatus","id","baudRate","interCommandDelay","getID","usbVendorId","usbProductId","queue","action","statusLabel","isReady","ensureProcessQueue","currentProcessQueue","runProcessQueue","shift","catch","toString","getStatus","ensureOpen","trace","counter","open","close","readable","getReader","writable","getWriter","get","child","push","path","EventEmitter","callbacks","on","event","cb","emit","data","cbs","forEach","checkSerial","serial","console","DevicesManager","devices","portFilter","requestDevices","requestPort","filters","updateDevices","serialPorts","getPorts","missingDevicesSerialPort","filter","includes","find","serialPortInfo","getInfo","newDevice","continuousUpdateDevices","scanInterval","callback","getDevicesList","ready","map","queueLength","findDevice","sendCommand","port","IDX","HEX","BUFFER","substring","v4","i","num","out","Array","Terminal","start","lineNumber","eventNumber","limit","onChange","ignoreSend","ignoreReceive","showSpecial","sendColor","receiveColor","events","text","append","shouldIgnore","line","ignores","ignore","test","lines","splitInLines","newEvents","uuid","time","round","splice","toHtml","html","toFixed","htmlEscape","join","replace","split","str","alarmsDescription","errorsDescription","parametersDescription","settingsDescription","$0","$1","$2","$3","$4","$5","$6","$10","$11","$12","$13","$20","$21","$22","$23","$24","$25","$26","$27","$30","$31","$32","$100","$101","$102","$110","$111","$112","$120","$121","$122","$130","$131","$132","MAX_ERRORS_MESSAGES","updateState","input","state","startsWith","parseQuestionMark","parseSquareBracket","parseSettings","version","parseErrors","parseAlarms","appendMessage","code","description","alarm","key","settings","Number","keyMappings","HLP","MSG","GC","VER","OPT","echo","slice","parameters","field","parts","Pn","v","message","messages","epoch","log","getEmptyState","gcode","currentLine","sentLine","GRBL"],"mappings":"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"} \ No newline at end of file diff --git a/dist/legoino-navigator-serial.min.js b/dist/legoino-navigator-serial.min.js index ae3fb6e..87ce49f 100644 --- a/dist/legoino-navigator-serial.min.js +++ b/dist/legoino-navigator-serial.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LegoinoSerial={})}(this,(function(e){"use strict";var t={exports:{}};const i=()=>{const e=new Error("Delay aborted");return e.name="AbortError",e},s=e=>{let{clearTimeout:t,setTimeout:s,willResolve:r}=e;return function(e){let o,n,a,{value:l,signal:c}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(c&&c.aborted)return Promise.reject(i());const d=t||clearTimeout,h=()=>{d(o),a(i())},m=()=>{c&&c.removeEventListener("abort",h)},u=new Promise(((t,i)=>{n=()=>{m(),r?t(l):i(l)},a=i,o=(s||setTimeout)(n,e)}));return c&&c.addEventListener("abort",h,{once:!0}),u.clear=()=>{d(o),o=null,n()},u}},r=e=>{const t=s({...e,willResolve:!0});return t.reject=s({...e,willResolve:!1}),t.range=(e,i,s)=>t(((e,t)=>Math.floor(Math.random()*(t-e+1)+e))(e,i),s),t},o=r();o.createWithTimers=r,t.exports=o,t.exports.default=o;var n=t.exports;const a=new TextEncoder,l=new TextDecoder;class c{constructor(e,t){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};this.device=t,this.currentTimeout=void 0,this.command=e,this.timeout=i.timeout??100,this.timeoutResolve=i.timeoutResolve??!1,this.kind=i.kind??"writeRead",this.answer="",this.partialAnswer="",this.logger=i.logger,this.status=0,this.creationTimestamp=Date.now(),this.promise=new Promise(((e,t)=>{this.reject=t,this.resolve=e})),this.isEndCommandAnswer=i.isEndCommandAnswer??(()=>{throw new Error("isEndCommandAnswer is not defined")}),this.endCommandAnswerCallback=i.endCommandAnswerCallback??(()=>{throw new Error("endCommandAnswerCallback is not defined")}),this.logger?.info("Action created")}isFinished(){return 50===this.status||60===this.status}setTimeout(){this.currentTimeout&&clearTimeout(this.currentTimeout),this.currentTimeout=setTimeout((()=>{50!==this.status&&60!==this.status&&(this.timeoutResolve?(this.status=50,this.resolve(this.partialAnswer),this.device.terminal?.receive(this.partialAnswer),this.logger?.info(`Timeout resolved after ${this.timeout}ms`)):(this.status=60,this.reject(this.partialAnswer),this.device.terminal?.receive(this.partialAnswer),this.logger?.error(`Timeout reject after ${this.timeout}ms`)))}),this.timeout)}async writeRead(){return this.startTimestamp=Date.now(),this.status=10,await this.setTimeout(),this.writeText(this.command).then((async()=>{await this.readText(),this.status=40,this.answer=this.endCommandAnswerCallback(this.command,this.partialAnswer)})).then((()=>{this.status=50,this.resolve(this.answer)})),this.promise}async writeText(e){if(!e)return;const t=a.encode(`${e}\n`);return this.device.terminal?.send(e),this.device.writer.write(t)}async readText(){for(this.status=30;30===this.status;){const e=await this.device.reader.read();if(e.value.length>0&&this.setTimeout(),this.partialAnswer+=l.decode(e.value),this.isEndCommandAnswer(this.command,this.partialAnswer))break;await n(1)}this.device.terminal?.receive(this.partialAnswer)}}const d={1:"opening",2:"opened",3:"closed",9:"missing",10:"error"};class h{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{commandOptions:i={},deviceOptions:s={}}=t;this.logger=t.logger,this.terminal=t.terminal,this.setStatus(1),this.id=void 0,this.serialPort=e,this.baudRate=s.baudRate||115200,this.interCommandDelay=s.interCommandDelay||10,this.getID=s.getID??(async e=>`${e.usbVendorId}-${e.usbProductId}`),this.timeout=s.timeout||100,this.commandOptions=i,this.queue=[],this.action=void 0,this.usbVendorId=t.usbVendorId,this.usbProductId=t.usbProductId,this.logger?.info("Device created")}setStatus(e){this.status=e,this.statusLabel=d[e]}isReady(){return 2===this.status}async ensureProcessQueue(){return this.logger?.info("ensureProcessQueue"),this.currentProcessQueue||(this.currentProcessQueue=this.runProcessQueue()),this.currentProcessQueue}async runProcessQueue(){for(;this.queue.length>0;)this.action=this.queue.shift(),this.action&&(await this.action.writeRead().then((e=>{this.logger?.info({command:this.action.command,answer:this.action.answer},"Resolve writeRead command")})).catch((e=>{this.logger?.error({command:this.action.command,answer:this.action.partialAnswer},e.toString())})),this.action=void 0,await n(this.interCommandDelay));this.currentProcessQueue=void 0}async getStatus(){return{value:this.status}}async ensureOpen(){this.logger?.trace("Ensure open");let e=0;for(;1===this.status&&e++<100;)await n(10);if(2!==this.status)return this.open()}async open(){this.logger?.info("Opening"),await this.serialPort.open({baudRate:this.baudRate}).catch((e=>{this.error(e),this.close()})).then((()=>{this.ensureOpen()})),this.reader=this.serialPort.readable.getReader(),this.writer=this.serialPort.writable.getWriter(),this.logger?.info("Getting id"),this.id=await this.getID(this),this.logger?.info(`Id: ${this.id}`),this.setStatus(2)}async get(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{timeout:i=this.timeout,timeoutResolve:s=!1}=t,r=new c(e,this,{...this.commandOptions,timeout:i,timeoutResolve:s,logger:this.logger.child({kind:"Command",command:e})});return this.queue.push(r),this.ensureProcessQueue(),r.promise}error(e){this.logger?.error(e,`Error ${this.serialPort?.path}`),this.setStatus(10)}close(){this.logger?.info("Close"),this.setStatus(3)}}class m{constructor(){this.callbacks={}}on(e,t){this.callbacks[e]||(this.callbacks[e]=[]),this.callbacks[e].push(t)}emit(e,t){let i=this.callbacks[e];i&&i.forEach((e=>e(t)))}}for(var u,p=256,g=[];p--;)g[p]=(p+256).toString(16).substring(1);function v(){var e,t=0,i="";if(!u||p+16>256){for(u=Array(t=256);t--;)u[t]=256*Math.random()|0;t=p=0}for(;t<16;t++)e=u[p+t],i+=6==t?g[15&e|64]:8==t?g[63&e|128]:g[e],1&t&&t>1&&t<11&&(i+="-");return p++,i}const f={1:"G-code words consist of a letter and a value. Letter was not found.",2:"Numeric value format is not valid or missing an expected value.",3:"Grbl `$` system command was not recognized or supported.",4:"Negative value received for an expected positive value.",5:"Homing cycle is not enabled via settings.",6:"Minimum step pulse time must be greater than 3usec",7:"EEPROM read failed. Reset and restored to default values.",8:"Grbl `$` command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job.",9:"G-code locked out during alarm or jog state",10:"Soft limits cannot be enabled without homing also enabled.",11:"Max characters per line exceeded. Line was not processed and executed.",12:"(Compile Option) Grbl `$` setting value exceeds the maximum step rate supported.",13:"Safety door detected as opened and door state initiated.",14:"(Grbl-Mega Only) Build info or startup line exceeded EEPROM line length limit.",15:"Jog target exceeds machine travel. Command ignored.",16:"Jog command with no `=` or contains prohibited g-code.",17:"Laser mode disabled. Requires PWM output.",20:"Unsupported or invalid g-code command found in block.",21:"More than one g-code command from same modal group found in block.",22:"Feed rate has not yet been set or is undefined.",23:"G-code command in block requires an integer value.",24:"Two G-code commands that both require the use of the `XYZ` axis words were detected in the block.",25:"A G-code word was repeated in the block.",26:"A G-code command implicitly or explicitly requires `XYZ` axis words in the block, but none were detected.",27:"`N` line number value is not within the valid range of `1` - `9,999,999`.",28:"A G-code command was sent, but is missing some required `P` or `L` value words in the line.",29:"Grbl supports six work coordinate systems `G54-G59`. `G59.1`, `G59.2`, and `G59.3` are not supported.",30:"The `G53` G-code command requires either a `G0` seek or `G1` feed motion mode to be active. A different motion was active.",31:"There are unused axis words in the block and `G80` motion mode cancel is active.",32:"A `G2` or `G3` arc was commanded but there are no `XYZ` axis words in the selected plane to trace the arc.",33:"The motion command has an invalid target. `G2`, `G3`, and `G38.2` generates this error, if the arc is impossible to generate or if the probe target is the current position.",34:"A `G2` or `G3` arc, traced with the radius definition, had a mathematical error when computing the arc geometry. Try either breaking up the arc into semi-circles or quadrants, or redefine them with the arc offset definition.",35:"A `G2` or `G3` arc, traced with the offset definition, is missing the `IJK` offset word in the selected plane to trace the arc.",36:"There are unused, leftover G-code words that aren't used by any command in the block.",37:"The `G43.1` dynamic tool length offset command cannot apply an offset to an axis other than its configured axis. The Grbl default axis is the Z-axis.",38:"Tool number greater than max supported value."},b={},w={$0:"Step pulse time, microseconds",$1:"Step idle delay, milliseconds",$2:"Step pulse invert, mask",$3:"Step direction invert, mask",$4:"Invert step enable pin, boolean",$5:"Invert limit pins, boolean",$6:"Invert probe pin, boolean",$10:"Status report options, mask",$11:"Junction deviation, millimeters",$12:"Arc tolerance, millimeters",$13:"Report in inches, boolean",$20:"Soft limits enable, boolean",$21:"Hard limits enable, boolean",$22:"Homing cycle enable, boolean",$23:"Homing direction invert, mask",$24:"Homing locate feed rate, mm/min",$25:"Homing search seek rate, mm/min ",$26:"Homing switch debounce delay, milliseconds",$27:"Homing switch pull-off distance, millimeters",$30:"Maximum spindle speed, RPM",$31:"Minimum spindle speed, RPM",$32:"Laser-mode enable, boolean",$100:"X-axis steps per millimeter",$101:"Y-axis steps per millimeter",$102:"Z-axis steps per millimeter",$110:"X-axis maximum rate, mm/min",$111:"Y-axis maximum rate, mm/min",$112:"Z-axis maximum rate, mm/min",$120:"X-axis acceleration, mm/sec^2",$121:"Y-axis acceleration, mm/sec^2",$122:"Z-axis acceleration, mm/sec^2",$130:"X-axis maximum travel, millimeters",$131:"Y-axis maximum travel, millimeters",$132:"Z-axis maximum travel, millimeters"};function x(e,t){const[,i]=e.split(":");t.error={code:i,description:f[i]}}function y(e,t){const[i,s]=e.split("=");t.settings[i]={key:i,description:w[i],value:Number(s)}}function $(e,t){const[i,s]=e.replace(/\[(.*)\]/,"$1").split(":");t.parameters[i]={key:i,description:b[i],value:s.split(",").map((e=>Number(e)))}}function G(e,t){const i=e.replace(/<(.*)>/,"$1").split("|"),s=i[0],r={};for(let e=1;eNumber(e)))}t.message=s,t.info={...t.info,...r}}const k={updateStatus:function(e,t){const i=e.split(/\r?\n/);for(let e of i)e.startsWith("<")&&G(e,t),e.startsWith("[")&&$(e,t),e.startsWith("$")&&y(e,t),e.startsWith("Grbl")&&(t.version=e.replace("Grbl ","")),e.startsWith("error")&&x(e,t)}};e.DevicesManager=class extends m{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),function(e){e||(console.error("Web serial doesn't seem to be enabled in your browser. Try enabling it by visiting:"),console.error("chrome://flags/#enable-experimental-web-platform-features"),console.error("opera://flags/#enable-experimental-web-platform-features"),console.error("edge://flags/#enable-experimental-web-platform-features"))}(e),this.serial=e,this.terminal=t.terminal,this.logger=t.logger,this.devices=[],this.portFilter=t.portFilter,this.commandOptions=t.command??{},this.deviceOptions=t.device??{}}async requestDevices(){return await this.serial.requestPort({filters:this.portFilter}),this.updateDevices()}async updateDevices(){const e=await this.serial.getPorts();this.logger?.trace("start updateDevices");const t=this.devices.filter((t=>!e.includes(t.serialPort)));for(let e of t)9!==e.status&&3!==e.status&&e.close(),e.status=9;for(let t of e){let e=this.devices.find((e=>e.serialPort===t));if(e)await e.ensureOpen();else{const e=t.getInfo();let i=new h(t,{baudRate:this.baudRate,terminal:this.terminal,...e,commandOptions:this.commandOptions,deviceOptions:this.deviceOptions,logger:this.logger.child({kind:"Device",...t.getInfo()})});this.devices.push(i),await i.open()}}this.logger?.trace("finish updateDevices")}async continuousUpdateDevices(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{scanInterval:t=1e3,callback:i}=e;for(;;)await this.updateDevices(),i&&i(this.devices),await n(t)}getDevicesList(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{ready:t=!1}=e;return this.devices.filter((e=>!t||e.isReady())).map((e=>({status:e.status,id:e.id,queueLength:e.queue.length})))}findDevice(e){if(void 0===e)return;let t=this.devices.filter((t=>t.id===e&&2===t.status));if(0!==t.length){if(t.length>1)throw new Error(`Many devices have the same id: ${e}`);return t[0]}}async sendCommand(e,t){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const s=this.findDevice(e);if(!s)throw Error(`Device ${e} not found`);if(s&&s.isReady())return s.get(t,i);throw Error(`Device ${e} not ready: ${s.port.path}`)}},e.GRBL=k,e.Terminal=class{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.lineNumber=0,this.eventNumber=0,this.limit=e.limit||1e3,this.onChange=e.onChange,this.ignoreSend=e.ignoreSend??[],this.ignoreReceive=e.ignoreReceive??[],this.showSpecial=e.showSpecial||!0,this.sendColor=e.sendColor||"#41c5d1",this.receiveColor=e.receiveColor||"#2ea600",this.events=[]}send(e){this.append(e,"send")}receive(e){this.append(e,"receive")}shouldIgnore(e,t){const i="send"===t?this.ignoreSend:this.ignoreReceive;for(let t of i)if(t.test(e))return!0;return!1}append(e,t){const i=function(e,t){t&&(e=e.replace(/\r/g,"").replace(/\n/g,"\n").replace(/\t/g,"\t"));return e.split(/\r?\n/)}(e,this.showSpecial);this.eventNumber++;const s=[];for(let e of i){this.lineNumber++;const i={uuid:v(),lineNumber:this.lineNumber,eventNumber:this.eventNumber,kind:t,line:e};this.shouldIgnore(e,t)||(s.push(i),this.events.push(i))}this.events.length>this.limit&&this.events.splice(0,this.events.length-this.limit),this.onChange?.(s,this.events)}toHtml(){let e=[];e.push('
');for(let i of this.events)e.push(`
${t=i.line,t.replace(/&/g,"&").replace(/>/g,">").replace(/`);var t;return e.push("
"),e.join("\n")}},Object.defineProperty(e,"__esModule",{value:!0})})); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LegoinoSerial={})}(this,(function(e){"use strict";var t={exports:{}};const i=()=>{const e=new Error("Delay aborted");return e.name="AbortError",e},s=e=>{let{clearTimeout:t,setTimeout:s,willResolve:r}=e;return function(e){let n,o,a,{value:l,signal:c}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(c&&c.aborted)return Promise.reject(i());const d=t||clearTimeout,h=()=>{d(n),a(i())},m=()=>{c&&c.removeEventListener("abort",h)},u=new Promise(((t,i)=>{o=()=>{m(),r?t(l):i(l)},a=i,n=(s||setTimeout)(o,e)}));return c&&c.addEventListener("abort",h,{once:!0}),u.clear=()=>{d(n),n=null,o()},u}},r=e=>{const t=s({...e,willResolve:!0});return t.reject=s({...e,willResolve:!1}),t.range=(e,i,s)=>t(((e,t)=>Math.floor(Math.random()*(t-e+1)+e))(e,i),s),t},n=r();n.createWithTimers=r,t.exports=n,t.exports.default=n;var o=t.exports;const a=new TextEncoder,l=new TextDecoder;class c{constructor(e,t){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};this.device=t,this.currentTimeout=void 0,this.command=e,this.timeout=i.timeout??200,this.timeoutResolve=i.timeoutResolve??!1,this.disableTerminal=i.disableTerminal??!1,this.kind=i.kind??"writeRead",this.answer="",this.partialAnswer="",this.logger=i.logger,this.status=0,this.creationTimestamp=Date.now(),this.promise=new Promise(((e,t)=>{this.reject=t,this.resolve=e})),this.isEndCommandAnswer=i.isEndCommandAnswer??(()=>{throw new Error("isEndCommandAnswer is not defined")}),this.endCommandAnswerCallback=i.endCommandAnswerCallback??(()=>{throw new Error("endCommandAnswerCallback is not defined")}),this.logger?.info("Action created")}isFinished(){return 50===this.status||60===this.status}setTimeout(){this.currentTimeout&&clearTimeout(this.currentTimeout),this.currentTimeout=setTimeout((()=>{50!==this.status&&60!==this.status&&(this.timeoutResolve?(this.status=50,this.resolve(this.partialAnswer),!this.disableTerminal&&this.device.terminal?.receive(this.partialAnswer),this.logger?.info(`Timeout resolved after ${this.timeout}ms`)):(this.status=60,this.reject(this.partialAnswer),!this.disableTerminal&&this.device.terminal?.receive(this.partialAnswer),this.logger?.error(`Timeout reject after ${this.timeout}ms`)))}),this.timeout)}async writeRead(){return this.startTimestamp=Date.now(),this.status=10,await this.setTimeout(),this.writeText(this.command).then((async()=>{await this.readText(),this.status=40,this.answer=this.endCommandAnswerCallback(this.command,this.partialAnswer)})).then((()=>{this.status=50,this.resolve(this.answer)})),this.promise}async writeText(e){if(!e)return;const t=a.encode(`${e}\n`);return!this.disableTerminal&&this.device.terminal?.send(e),this.device.writer.write(t)}async readText(){for(this.status=30;30===this.status;){const e=await this.device.reader.read();if(e.value.length>0&&this.setTimeout(),this.partialAnswer+=l.decode(e.value),this.isEndCommandAnswer(this.command,this.partialAnswer))break;await o(5)}!this.disableTerminal&&this.device.terminal?.receive(this.partialAnswer)}}const d={1:"opening",2:"opened",3:"closed",9:"missing",10:"error"};class h{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{commandOptions:i={},deviceOptions:s={}}=t;this.logger=t.logger,this.terminal=t.terminal,this.setStatus(1),this.id=void 0,this.serialPort=e,this.baudRate=s.baudRate||115200,this.interCommandDelay=s.interCommandDelay||10,this.getID=s.getID??(async e=>`${e.usbVendorId}-${e.usbProductId}`),this.timeout=s.timeout||100,this.commandOptions=i,this.queue=[],this.action=void 0,this.usbVendorId=t.usbVendorId,this.usbProductId=t.usbProductId,this.logger?.info("Device created")}setStatus(e){this.status=e,this.statusLabel=d[e]}isReady(){return 2===this.status}async ensureProcessQueue(){return this.logger?.info("ensureProcessQueue"),this.currentProcessQueue||(this.currentProcessQueue=this.runProcessQueue()),this.currentProcessQueue}async runProcessQueue(){for(;this.queue.length>0;)this.action=this.queue.shift(),this.action&&(await this.action.writeRead().then((e=>{this.logger?.info({command:this.action.command,answer:this.action.answer},"Resolve writeRead command")})).catch((e=>{this.logger?.error({command:this.action.command,answer:this.action.partialAnswer},e.toString())})),this.action=void 0,await o(this.interCommandDelay));this.currentProcessQueue=void 0}async getStatus(){return{value:this.status}}async ensureOpen(){this.logger?.trace("Ensure open");let e=0;for(;1===this.status&&e++<100;)await o(10);if(2!==this.status)return this.open()}async open(){this.logger?.info("Opening"),await this.serialPort.open({baudRate:this.baudRate}).catch((e=>{this.error(e),this.close()})).then((()=>{this.ensureOpen()})),this.reader=this.serialPort.readable.getReader(),this.writer=this.serialPort.writable.getWriter(),this.logger?.info("Getting id"),this.id=await this.getID(this),this.logger?.info(`Id: ${this.id}`),this.setStatus(2)}async get(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{timeout:i=this.timeout,timeoutResolve:s=!1,disableTerminal:r=!1}=t,n=new c(e,this,{...this.commandOptions,timeout:i,timeoutResolve:s,disableTerminal:r,logger:this.logger.child({kind:"Command",command:e})});return this.queue.push(n),this.ensureProcessQueue(),n.promise}error(e){this.logger?.error(e,`Error ${this.serialPort?.path}`),this.setStatus(10)}close(){this.logger?.info("Close"),this.setStatus(3)}}class m{constructor(){this.callbacks={}}on(e,t){this.callbacks[e]||(this.callbacks[e]=[]),this.callbacks[e].push(t)}emit(e,t){let i=this.callbacks[e];i&&i.forEach((e=>e(t)))}}for(var u,p=256,g=[];p--;)g[p]=(p+256).toString(16).substring(1);function f(){var e,t=0,i="";if(!u||p+16>256){for(u=Array(t=256);t--;)u[t]=256*Math.random()|0;t=p=0}for(;t<16;t++)e=u[p+t],i+=6==t?g[15&e|64]:8==t?g[63&e|128]:g[e],1&t&&t>1&&t<11&&(i+="-");return p++,i}const v={1:"Hard limit triggered. Machine position is likely lost due to sudden and immediate halt. Re-homing is highly recommended.",2:"G-code motion target exceeds machine travel. Machine position safely retained. Alarm may be unlocked.",3:"Reset while in motion. Grbl cannot guarantee position. Lost steps are likely. Re-homing is highly recommended.",4:"Probe fail. The probe is not in the expected initial state before starting probe cycle, where G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered.",5:"Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4.",6:"Homing fail. Reset during active homing cycle.",7:"Homing fail. Safety door was opened during active homing cycle.",8:"Homing fail. Cycle failed to clear limit switch when pulling off. Try increasing pull-off setting or check wiring.",9:"Homing fail. Could not find limit switch within search distance. Defined as `1.5 * max_travel` on search and `5 * pulloff` on locate phases."},b={1:"G-code words consist of a letter and a value. Letter was not found.",2:"Numeric value format is not valid or missing an expected value.",3:"Grbl `$` system command was not recognized or supported.",4:"Negative value received for an expected positive value.",5:"Homing cycle is not enabled via settings.",6:"Minimum step pulse time must be greater than 3usec",7:"EEPROM read failed. Reset and restored to default values.",8:"Grbl `$` command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job.",9:"G-code locked out during alarm or jog state",10:"Soft limits cannot be enabled without homing also enabled.",11:"Max characters per line exceeded. Line was not processed and executed.",12:"(Compile Option) Grbl `$` setting value exceeds the maximum step rate supported.",13:"Safety door detected as opened and door state initiated.",14:"(Grbl-Mega Only) Build info or startup line exceeded EEPROM line length limit.",15:"Jog target exceeds machine travel. Command ignored.",16:"Jog command with no `=` or contains prohibited g-code.",17:"Laser mode disabled. Requires PWM output.",20:"Unsupported or invalid g-code command found in block.",21:"More than one g-code command from same modal group found in block.",22:"Feed rate has not yet been set or is undefined.",23:"G-code command in block requires an integer value.",24:"Two G-code commands that both require the use of the `XYZ` axis words were detected in the block.",25:"A G-code word was repeated in the block.",26:"A G-code command implicitly or explicitly requires `XYZ` axis words in the block, but none were detected.",27:"`N` line number value is not within the valid range of `1` - `9,999,999`.",28:"A G-code command was sent, but is missing some required `P` or `L` value words in the line.",29:"Grbl supports six work coordinate systems `G54-G59`. `G59.1`, `G59.2`, and `G59.3` are not supported.",30:"The `G53` G-code command requires either a `G0` seek or `G1` feed motion mode to be active. A different motion was active.",31:"There are unused axis words in the block and `G80` motion mode cancel is active.",32:"A `G2` or `G3` arc was commanded but there are no `XYZ` axis words in the selected plane to trace the arc.",33:"The motion command has an invalid target. `G2`, `G3`, and `G38.2` generates this error, if the arc is impossible to generate or if the probe target is the current position.",34:"A `G2` or `G3` arc, traced with the radius definition, had a mathematical error when computing the arc geometry. Try either breaking up the arc into semi-circles or quadrants, or redefine them with the arc offset definition.",35:"A `G2` or `G3` arc, traced with the offset definition, is missing the `IJK` offset word in the selected plane to trace the arc.",36:"There are unused, leftover G-code words that aren't used by any command in the block.",37:"The `G43.1` dynamic tool length offset command cannot apply an offset to an axis other than its configured axis. The Grbl default axis is the Z-axis.",38:"Tool number greater than max supported value."},w={},y={$0:"Step pulse time, microseconds",$1:"Step idle delay, milliseconds",$2:"Step pulse invert, mask",$3:"Step direction invert, mask",$4:"Invert step enable pin, boolean",$5:"Invert limit pins, boolean",$6:"Invert probe pin, boolean",$10:"Status report options, mask",$11:"Junction deviation, millimeters",$12:"Arc tolerance, millimeters",$13:"Report in inches, boolean",$20:"Soft limits enable, boolean",$21:"Hard limits enable, boolean",$22:"Homing cycle enable, boolean",$23:"Homing direction invert, mask",$24:"Homing locate feed rate, mm/min",$25:"Homing search seek rate, mm/min ",$26:"Homing switch debounce delay, milliseconds",$27:"Homing switch pull-off distance, millimeters",$30:"Maximum spindle speed, RPM",$31:"Minimum spindle speed, RPM",$32:"Laser-mode enable, boolean",$100:"X-axis steps per millimeter",$101:"Y-axis steps per millimeter",$102:"Z-axis steps per millimeter",$110:"X-axis maximum rate, mm/min",$111:"Y-axis maximum rate, mm/min",$112:"Z-axis maximum rate, mm/min",$120:"X-axis acceleration, mm/sec^2",$121:"Y-axis acceleration, mm/sec^2",$122:"Z-axis acceleration, mm/sec^2",$130:"X-axis maximum travel, millimeters",$131:"Y-axis maximum travel, millimeters",$132:"Z-axis maximum travel, millimeters"};function x(e,t){const[,i]=e.split(":");P({kind:"ERROR",code:i,description:b[i]},t)}function $(e,t){const[,i]=e.split(":");P({kind:"ALARM",code:i,description:v[i]},t)}function G(e,t){const[i,s]=e.split("=");t.settings[i]={key:i,description:y[i],value:Number(s)}}const T={HLP:"Help",MSG:"Message",GC:"GCode",VER:"Version",OPT:"Option",echo:"Echo"};function k(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const[i,s]=e.replace(/\[(.*)\]/,"$1").split(":"),r=e.replace(/\[(.*)\]/,"$1").split(":").slice(1).join(":");switch(i){case"echo":case"VER":case"OPT":case"HLP":case"GC":case"MSG":return void P({kind:T[i],description:r},t);default:t.parameters[i]={key:i,description:w[i],value:s.split(",").map((e=>Number(e)))}}}function R(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const i=e.replace(/<(.*)>/,"$1").split("|"),s={value:i[0],Pn:[!1,!1,!1]};for(let e=1;eNumber(e)))}t.status={...t.status,...s}}function P(e,t){t.messages.push({epoch:Date.now(),...e}),t.messages.length>20&&t.messages.splice(0,t.messages.length-20),console.log(t.messages)}const A={updateState:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!e)return;const i=e.split(/\r?\n/);for(let e of i)e.startsWith("<")&&R(e,t),e.startsWith("[")&&k(e,t),e.startsWith("$")&&G(e,t),e.startsWith("Grbl")&&(t.version=e.replace("Grbl ","")),e.startsWith("error")&&x(e,t),e.includes("ALARM")&&$(e,t)},getEmptyState:function(){return{messages:[],status:{},settings:{},parameters:{},version:"",gcode:{currentLine:0,sentLine:1}}}};e.DevicesManager=class extends m{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),function(e){e||(console.error("Web serial doesn't seem to be enabled in your browser. Try enabling it by visiting:"),console.error("chrome://flags/#enable-experimental-web-platform-features"),console.error("opera://flags/#enable-experimental-web-platform-features"),console.error("edge://flags/#enable-experimental-web-platform-features"))}(e),this.serial=e,this.terminal=t.terminal,this.logger=t.logger,this.devices=[],this.portFilter=t.portFilter,this.commandOptions=t.command??{},this.deviceOptions=t.device??{}}async requestDevices(){return await this.serial.requestPort({filters:this.portFilter}),this.updateDevices()}async updateDevices(){const e=await this.serial.getPorts();this.logger?.trace("start updateDevices");const t=this.devices.filter((t=>!e.includes(t.serialPort)));for(let e of t)9!==e.status&&3!==e.status&&e.close(),e.status=9;for(let t of e){let e=this.devices.find((e=>e.serialPort===t));if(e)await e.ensureOpen();else{const e=t.getInfo();let i=new h(t,{baudRate:this.baudRate,terminal:this.terminal,...e,commandOptions:this.commandOptions,deviceOptions:this.deviceOptions,logger:this.logger.child({kind:"Device",...t.getInfo()})});this.devices.push(i),await i.open()}}this.logger?.trace("finish updateDevices")}async continuousUpdateDevices(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{scanInterval:t=1e3,callback:i}=e;for(;;)await this.updateDevices(),i&&i(this.devices),await o(t)}getDevicesList(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{ready:t=!1}=e;return this.devices.filter((e=>!t||e.isReady())).map((e=>({status:e.status,id:e.id,queueLength:e.queue.length})))}findDevice(e){if(void 0===e)return;let t=this.devices.filter((t=>t.id===e&&2===t.status));if(0!==t.length){if(t.length>1)throw new Error(`Many devices have the same id: ${e}`);return t[0]}}async sendCommand(e,t){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const s=this.findDevice(e);if(!s)throw Error(`Device ${e} not found`);if(s&&s.isReady())return s.get(t,i);throw Error(`Device ${e} not ready: ${s.port.path}`)}},e.GRBL=A,e.Terminal=class{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.start=Date.now(),this.lineNumber=0,this.eventNumber=0,this.limit=e.limit??1e3,this.onChange=e.onChange,this.ignoreSend=e.ignoreSend??[],this.ignoreReceive=e.ignoreReceive??[],this.showSpecial=e.showSpecial??!0,this.sendColor=e.sendColor??"#efcef2",this.receiveColor=e.receiveColor??"#bbeeb7",this.events=[]}send(e){this.append(e,"send")}receive(e){this.append(e,"receive")}shouldIgnore(e,t){const i="send"===t?this.ignoreSend:this.ignoreReceive;for(let t of i)if(t.test(e))return!0;return!1}append(e,t){const i=function(e,t){t&&(e=e.replace(/\r/g,"").replace(/\n/g,"\n").replace(/\t/g,"\t"));return e.replace(/[\r\n]+$/,"").split(/\r?\n/)}(e,this.showSpecial);this.eventNumber++;const s=[];for(let e of i){this.lineNumber++;const i={uuid:f(),time:Math.round(Date.now()-this.start),lineNumber:this.lineNumber,eventNumber:this.eventNumber,kind:t,line:e};this.shouldIgnore(e,t)||(s.push(i),this.events.push(i))}this.events.length>this.limit&&this.events.splice(0,this.events.length-this.limit),this.onChange?.(s,this.events)}toHtml(){let e=[];e.push('
');for(let i of this.events)e.push(`
${(i.time/1e3).toFixed(3)}: ${t=i.line,t.replace(/&/g,"&").replace(/>/g,">").replace(/`);var t;return e.push("
"),e.join("\n")}},Object.defineProperty(e,"__esModule",{value:!0})})); //# sourceMappingURL=legoino-navigator-serial.min.js.map diff --git a/dist/legoino-navigator-serial.min.js.map b/dist/legoino-navigator-serial.min.js.map index 92d17fc..0181b2b 100644 --- a/dist/legoino-navigator-serial.min.js.map +++ b/dist/legoino-navigator-serial.min.js.map @@ -1 +1 @@ -{"version":3,"file":"legoino-navigator-serial.min.js","sources":["../node_modules/delay/index.js","../src/Action.js","../src/Device.js","../src/util/EventEmitter.js","../node_modules/@lukeed/uuid/dist/index.mjs","../src/grbl/errorsDescription.js","../src/grbl/parametersDescription.js","../src/grbl/settingsDescription.js","../src/grbl/updateStatus.js","../src/grbl/grbl.js","../src/DevicesManager.js","../src/util/checkSerial.js","../src/terminal/Terminal.js"],"sourcesContent":["'use strict';\n\n// From https://github.com/sindresorhus/random-int/blob/c37741b56f76b9160b0b63dae4e9c64875128146/index.js#L13-L15\nconst randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum);\n\nconst createAbortError = () => {\n\tconst error = new Error('Delay aborted');\n\terror.name = 'AbortError';\n\treturn error;\n};\n\nconst createDelay = ({clearTimeout: defaultClear, setTimeout: set, willResolve}) => (ms, {value, signal} = {}) => {\n\tif (signal && signal.aborted) {\n\t\treturn Promise.reject(createAbortError());\n\t}\n\n\tlet timeoutId;\n\tlet settle;\n\tlet rejectFn;\n\tconst clear = defaultClear || clearTimeout;\n\n\tconst signalListener = () => {\n\t\tclear(timeoutId);\n\t\trejectFn(createAbortError());\n\t};\n\n\tconst cleanup = () => {\n\t\tif (signal) {\n\t\t\tsignal.removeEventListener('abort', signalListener);\n\t\t}\n\t};\n\n\tconst delayPromise = new Promise((resolve, reject) => {\n\t\tsettle = () => {\n\t\t\tcleanup();\n\t\t\tif (willResolve) {\n\t\t\t\tresolve(value);\n\t\t\t} else {\n\t\t\t\treject(value);\n\t\t\t}\n\t\t};\n\n\t\trejectFn = reject;\n\t\ttimeoutId = (set || setTimeout)(settle, ms);\n\t});\n\n\tif (signal) {\n\t\tsignal.addEventListener('abort', signalListener, {once: true});\n\t}\n\n\tdelayPromise.clear = () => {\n\t\tclear(timeoutId);\n\t\ttimeoutId = null;\n\t\tsettle();\n\t};\n\n\treturn delayPromise;\n};\n\nconst createWithTimers = clearAndSet => {\n\tconst delay = createDelay({...clearAndSet, willResolve: true});\n\tdelay.reject = createDelay({...clearAndSet, willResolve: false});\n\tdelay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options);\n\treturn delay;\n};\n\nconst delay = createWithTimers();\ndelay.createWithTimers = createWithTimers;\n\nmodule.exports = delay;\n// TODO: Remove this for the next major release\nmodule.exports.default = delay;\n","import delay from 'delay';\n\nconst STATUS_CREATED = 0;\nconst STATUS_COMMAND_SENT = 10;\nconst STATUS_WAITING_RECEIVING = 20;\nconst STATUS_ANSWER_PARTIALLY_RECEIVED = 30;\nconst STATUS_ANSWER_RECEIVED = 40;\nconst STATUS_RESOLVED = 50;\nconst STATUS_ERROR = 60;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nexport class Action {\n constructor(command, device, options = {}) {\n this.device = device;\n this.currentTimeout = undefined;\n this.command = command;\n this.timeout = options.timeout ?? 100;\n this.timeoutResolve = options.timeoutResolve ?? false;\n this.kind = options.kind ?? 'writeRead';\n this.answer = '';\n this.partialAnswer = '';\n this.logger = options.logger;\n this.status = STATUS_CREATED;\n this.creationTimestamp = Date.now();\n this.promise = new Promise((resolve, reject) => {\n this.reject = reject;\n this.resolve = resolve;\n });\n this.isEndCommandAnswer =\n options.isEndCommandAnswer ??\n (() => {\n throw new Error('isEndCommandAnswer is not defined');\n });\n this.endCommandAnswerCallback =\n options.endCommandAnswerCallback ??\n (() => {\n throw new Error('endCommandAnswerCallback is not defined');\n });\n this.logger?.info('Action created');\n }\n\n isFinished() {\n return this.status === STATUS_RESOLVED || this.status === STATUS_ERROR;\n }\n\n setTimeout() {\n if (this.currentTimeout) {\n clearTimeout(this.currentTimeout);\n }\n this.currentTimeout = setTimeout(() => {\n if (this.status === STATUS_RESOLVED || this.status === STATUS_ERROR) {\n return;\n }\n if (this.timeoutResolve) {\n this.status = STATUS_RESOLVED;\n this.resolve(this.partialAnswer);\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.info(`Timeout resolved after ${this.timeout}ms`);\n } else {\n this.status = STATUS_ERROR;\n this.reject(this.partialAnswer);\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.error(`Timeout reject after ${this.timeout}ms`);\n }\n }, this.timeout);\n }\n\n async writeRead() {\n this.startTimestamp = Date.now();\n this.status = STATUS_COMMAND_SENT;\n await this.setTimeout();\n this.writeText(this.command)\n .then(async () => {\n await this.readText();\n this.status = STATUS_ANSWER_RECEIVED;\n this.answer = this.endCommandAnswerCallback(\n this.command,\n this.partialAnswer,\n );\n })\n .then(() => {\n this.status = STATUS_RESOLVED;\n this.resolve(this.answer);\n });\n return this.promise;\n }\n\n async writeText(command) {\n if (!command) return;\n const dataArrayBuffer = encoder.encode(`${command}\\n`);\n this.device.terminal?.send(command);\n return this.device.writer.write(dataArrayBuffer);\n }\n\n async readText() {\n this.status = STATUS_ANSWER_PARTIALLY_RECEIVED;\n while (this.status === STATUS_ANSWER_PARTIALLY_RECEIVED) {\n const chunk = await this.device.reader.read();\n if (chunk.value.length > 0) {\n // as long as we receive, we delay the timeout\n this.setTimeout();\n }\n this.partialAnswer += decoder.decode(chunk.value);\n if (this.isEndCommandAnswer(this.command, this.partialAnswer)) break;\n await delay(1);\n }\n this.device.terminal?.receive(this.partialAnswer);\n }\n}\n","import delay from 'delay';\n\nimport { Action } from './Action';\n\nexport const STATUS_OPENING = 1;\nexport const STATUS_OPENED = 2;\nexport const STATUS_CLOSED = 3;\nexport const STATUS_MISSING = 9;\nexport const STATUS_ERROR = 10;\nconst statusLabels = {\n [STATUS_OPENING]: 'opening',\n [STATUS_OPENED]: 'opened',\n [STATUS_CLOSED]: 'closed',\n [STATUS_MISSING]: 'missing',\n [STATUS_ERROR]: 'error',\n};\n\nexport class Device {\n constructor(serialPort, options = {}) {\n const { commandOptions = {}, deviceOptions = {} } = options;\n this.logger = options.logger;\n this.terminal = options.terminal;\n this.setStatus(STATUS_OPENING);\n this.id = undefined;\n this.serialPort = serialPort;\n this.baudRate = deviceOptions.baudRate || 115200;\n this.interCommandDelay = deviceOptions.interCommandDelay || 10;\n this.getID =\n deviceOptions.getID ??\n (async (device) => {\n return `${device.usbVendorId}-${device.usbProductId}`;\n });\n this.timeout = deviceOptions.timeout || 100;\n this.commandOptions = commandOptions;\n\n this.queue = [];\n this.action = undefined;\n\n this.usbVendorId = options.usbVendorId;\n this.usbProductId = options.usbProductId;\n this.logger?.info(`Device created`);\n }\n\n setStatus(status) {\n this.status = status;\n this.statusLabel = statusLabels[status];\n }\n\n isReady() {\n return this.status === STATUS_OPENED;\n }\n\n /** restart process queue if the previous one was finished */\n async ensureProcessQueue() {\n this.logger?.info('ensureProcessQueue');\n if (!this.currentProcessQueue) {\n this.currentProcessQueue = this.runProcessQueue();\n }\n return this.currentProcessQueue;\n }\n\n async runProcessQueue() {\n while (this.queue.length > 0) {\n this.action = this.queue.shift();\n if (this.action) {\n await this.action\n .writeRead()\n .then((value) => {\n this.logger?.info(\n { command: this.action.command, answer: this.action.answer },\n 'Resolve writeRead command',\n );\n })\n .catch((error) => {\n this.logger?.error(\n {\n command: this.action.command,\n answer: this.action.partialAnswer,\n },\n error.toString(),\n );\n });\n\n this.action = undefined;\n await delay(this.interCommandDelay);\n }\n }\n this.currentProcessQueue = undefined;\n }\n\n async getStatus() {\n return {\n value: this.status,\n };\n }\n\n async ensureOpen() {\n this.logger?.trace(`Ensure open`);\n let counter = 0;\n // we wait for the serial port to be opened for max 1s\n while (this.status === STATUS_OPENING && counter++ < 100) {\n await delay(10);\n }\n\n if (this.status !== STATUS_OPENED) {\n return this.open();\n }\n }\n\n async open() {\n this.logger?.info(`Opening`);\n await this.serialPort\n .open({\n baudRate: this.baudRate,\n })\n .catch((error) => {\n this.error(error);\n this.close();\n })\n .then(() => {\n this.ensureOpen();\n });\n this.reader = this.serialPort.readable.getReader();\n this.writer = this.serialPort.writable.getWriter();\n this.logger?.info(`Getting id`);\n\n this.id = await this.getID(this);\n\n this.logger?.info(`Id: ${this.id}`);\n this.setStatus(STATUS_OPENED);\n }\n\n /*\n We need to add this command in the queue and wait it resolves or rejects\n */\n async get(command, options = {}) {\n const { timeout = this.timeout, timeoutResolve = false } = options;\n\n const action = new Action(command, this, {\n ...this.commandOptions,\n timeout,\n timeoutResolve,\n logger: this.logger.child({ kind: 'Command', command }),\n });\n\n this.queue.push(action);\n this.ensureProcessQueue();\n return action.promise;\n }\n\n error(error) {\n this.logger?.error(error, `Error ${this.serialPort?.path}`);\n this.setStatus(STATUS_ERROR);\n /**\n this.emit('adapter', {\n event: 'Error',\n value: error,\n });\n **/\n }\n\n close() {\n this.logger?.info(`Close`);\n this.setStatus(STATUS_CLOSED);\n }\n}\n","export default class EventEmitter {\n constructor() {\n this.callbacks = {};\n }\n\n on(event, cb) {\n if (!this.callbacks[event]) this.callbacks[event] = [];\n this.callbacks[event].push(cb);\n }\n\n emit(event, data) {\n let cbs = this.callbacks[event];\n if (cbs) {\n cbs.forEach((cb) => cb(data));\n }\n }\n}\n","var IDX=256, HEX=[], BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function v4() {\n\tvar i=0, num, out='';\n\n\tif (!BUFFER || ((IDX + 16) > 256)) {\n\t\tBUFFER = Array(i=256);\n\t\twhile (i--) BUFFER[i] = 256 * Math.random() | 0;\n\t\ti = IDX = 0;\n\t}\n\n\tfor (; i < 16; i++) {\n\t\tnum = BUFFER[IDX + i];\n\t\tif (i==6) out += HEX[num & 15 | 64];\n\t\telse if (i==8) out += HEX[num & 63 | 128];\n\t\telse out += HEX[num];\n\n\t\tif (i & 1 && i > 1 && i < 11) out += '-';\n\t}\n\n\tIDX++;\n\treturn out;\n}\n","export const errorsDescription = {\n 1: 'G-code words consist of a letter and a value. Letter was not found.',\n 2: 'Numeric value format is not valid or missing an expected value.',\n 3: 'Grbl `$` system command was not recognized or supported.',\n 4: 'Negative value received for an expected positive value.',\n 5: 'Homing cycle is not enabled via settings.',\n 6: 'Minimum step pulse time must be greater than 3usec',\n 7: 'EEPROM read failed. Reset and restored to default values.',\n 8: 'Grbl `$` command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job.',\n 9: 'G-code locked out during alarm or jog state',\n 10: 'Soft limits cannot be enabled without homing also enabled.',\n 11: 'Max characters per line exceeded. Line was not processed and executed.',\n 12: '(Compile Option) Grbl `$` setting value exceeds the maximum step rate supported.',\n 13: 'Safety door detected as opened and door state initiated.',\n 14: '(Grbl-Mega Only) Build info or startup line exceeded EEPROM line length limit.',\n 15: 'Jog target exceeds machine travel. Command ignored.',\n 16: 'Jog command with no `=` or contains prohibited g-code.',\n 17: 'Laser mode disabled. Requires PWM output.',\n 20: 'Unsupported or invalid g-code command found in block.',\n 21: 'More than one g-code command from same modal group found in block.',\n 22: 'Feed rate has not yet been set or is undefined.',\n 23: 'G-code command in block requires an integer value.',\n 24: 'Two G-code commands that both require the use of the `XYZ` axis words were detected in the block.',\n 25: 'A G-code word was repeated in the block.',\n 26: 'A G-code command implicitly or explicitly requires `XYZ` axis words in the block, but none were detected.',\n 27: '`N` line number value is not within the valid range of `1` - `9,999,999`.',\n 28: 'A G-code command was sent, but is missing some required `P` or `L` value words in the line.',\n 29: 'Grbl supports six work coordinate systems `G54-G59`. `G59.1`, `G59.2`, and `G59.3` are not supported.',\n 30: 'The `G53` G-code command requires either a `G0` seek or `G1` feed motion mode to be active. A different motion was active.',\n 31: 'There are unused axis words in the block and `G80` motion mode cancel is active.',\n 32: 'A `G2` or `G3` arc was commanded but there are no `XYZ` axis words in the selected plane to trace the arc.',\n 33: 'The motion command has an invalid target. `G2`, `G3`, and `G38.2` generates this error, if the arc is impossible to generate or if the probe target is the current position.',\n 34: 'A `G2` or `G3` arc, traced with the radius definition, had a mathematical error when computing the arc geometry. Try either breaking up the arc into semi-circles or quadrants, or redefine them with the arc offset definition.',\n 35: 'A `G2` or `G3` arc, traced with the offset definition, is missing the `IJK` offset word in the selected plane to trace the arc.',\n 36: \"There are unused, leftover G-code words that aren't used by any command in the block.\",\n 37: 'The `G43.1` dynamic tool length offset command cannot apply an offset to an axis other than its configured axis. The Grbl default axis is the Z-axis.',\n 38: 'Tool number greater than max supported value.',\n};\n","export const parametersDescription = {};\n","export const settingsDescription = {\n $0: 'Step pulse time, microseconds',\n $1: 'Step idle delay, milliseconds',\n $2: 'Step pulse invert, mask',\n $3: 'Step direction invert, mask',\n $4: 'Invert step enable pin, boolean',\n $5: 'Invert limit pins, boolean',\n $6: 'Invert probe pin, boolean',\n $10: 'Status report options, mask',\n $11: 'Junction deviation, millimeters',\n $12: 'Arc tolerance, millimeters',\n $13: 'Report in inches, boolean',\n $20: 'Soft limits enable, boolean',\n $21: 'Hard limits enable, boolean',\n $22: 'Homing cycle enable, boolean',\n $23: 'Homing direction invert, mask',\n $24: 'Homing locate feed rate, mm/min',\n $25: 'Homing search seek rate, mm/min ',\n $26: 'Homing switch debounce delay, milliseconds',\n $27: 'Homing switch pull-off distance, millimeters',\n $30: 'Maximum spindle speed, RPM',\n $31: 'Minimum spindle speed, RPM',\n $32: 'Laser-mode enable, boolean',\n $100: 'X-axis steps per millimeter',\n $101: 'Y-axis steps per millimeter',\n $102: 'Z-axis steps per millimeter',\n $110: 'X-axis maximum rate, mm/min',\n $111: 'Y-axis maximum rate, mm/min',\n $112: 'Z-axis maximum rate, mm/min',\n $120: 'X-axis acceleration, mm/sec^2',\n $121: 'Y-axis acceleration, mm/sec^2',\n $122: 'Z-axis acceleration, mm/sec^2',\n $130: 'X-axis maximum travel, millimeters',\n $131: 'Y-axis maximum travel, millimeters',\n $132: 'Z-axis maximum travel, millimeters',\n};\n","import { errorsDescription } from './errorsDescription.js';\nimport { parametersDescription } from './parametersDescription.js';\nimport { settingsDescription } from './settingsDescription.js';\n\nexport function updateStatus(input, status) {\n const lines = input.split(/\\r?\\n/);\n\n for (let line of lines) {\n if (line.startsWith('<')) {\n parseQuestionMark(line, status);\n }\n if (line.startsWith('[')) {\n parseParameters(line, status);\n }\n if (line.startsWith('$')) {\n parseSettings(line, status);\n }\n if (line.startsWith('Grbl')) {\n status.version = line.replace('Grbl ', '');\n }\n if (line.startsWith('error')) {\n parseErrors(line, status);\n }\n }\n}\n\nfunction parseErrors(line, status) {\n const [, error] = line.split(':');\n status.error = {\n code: error,\n description: errorsDescription[error],\n };\n}\n\nfunction parseSettings(line, status) {\n const [key, value] = line.split('=');\n status.settings[key] = {\n key,\n description: settingsDescription[key],\n value: Number(value),\n };\n}\n\nfunction parseParameters(line, status) {\n const [key, value] = line.replace(/\\[(.*)\\]/, '$1').split(':');\n status.parameters[key] = {\n key,\n description: parametersDescription[key],\n value: value.split(',').map((field) => Number(field)),\n };\n}\n\nfunction parseQuestionMark(line, status) {\n // \n const parts = line.replace(/<(.*)>/, '$1').split('|');\n const message = parts[0];\n const info = {};\n for (let i = 1; i < parts.length; i++) {\n const [key, value] = parts[i].split(':');\n info[key] = value.split(',').map((v) => Number(v));\n }\n status.message = message;\n status.info = { ...status.info, ...info };\n}\n","import { updateStatus } from './updateStatus.js';\n\nexport const GRBL = {\n updateStatus,\n};\n","import delay from 'delay';\n\nimport { Device, STATUS_MISSING, STATUS_OPENED, STATUS_CLOSED } from './Device';\nimport EventEmitter from './util/EventEmitter';\nimport checkSerial from './util/checkSerial';\n\n/**\n * Class creating a new serial bridge to manage serial ports.\n * @param {object} [options={}]\n * @param {Array} [options.portFilter] Filter the serial ports to address.\n * @param {object} [options.command={}]\n * @param {number} [options.command.timeout=100] Time to wait for answer before timeout\n * @param {Function} [options.command.isEndCommandAnswer]\n * @param {Function} [options.command.endCommandAnswerCallback]\n * @param {object} [options.device={}]\n * @param {AsyncFunction} [options.device.getID=(device)=>()] Time to wait between commands in [ms]\n * @param {number} [options.device.baudRate=115200] Baud rate\n * @param {number} [options.device.interCommandDelay=100] Time to wait between commands in [ms]\n */\nexport class DevicesManager extends EventEmitter {\n constructor(serial, options = {}) {\n super();\n checkSerial(serial);\n this.serial = serial;\n this.terminal = options.terminal;\n this.logger = options.logger;\n this.devices = [];\n this.portFilter = options.portFilter;\n this.commandOptions = options.command ?? {};\n this.deviceOptions = options.device ?? {};\n }\n\n /**\n * By calling this method from a click you give users the possibility to allow access to some devices\n */\n async requestDevices() {\n await this.serial.requestPort({\n filters: this.portFilter,\n });\n return this.updateDevices();\n }\n\n /**\n * Update this.devices\n */\n async updateDevices() {\n const serialPorts = await this.serial.getPorts();\n\n this.logger?.trace('start updateDevices');\n\n const missingDevicesSerialPort = this.devices.filter(\n (device) => !serialPorts.includes(device.serialPort),\n );\n for (let device of missingDevicesSerialPort) {\n if (device.status !== STATUS_MISSING && device.status !== STATUS_CLOSED) {\n device.close();\n }\n device.status = STATUS_MISSING;\n }\n for (let serialPort of serialPorts) {\n let device = this.devices.find(\n (device) => device.serialPort === serialPort,\n );\n if (device) {\n await device.ensureOpen();\n } else {\n const serialPortInfo = serialPort.getInfo();\n let newDevice = new Device(serialPort, {\n baudRate: this.baudRate,\n terminal: this.terminal,\n ...serialPortInfo,\n commandOptions: this.commandOptions,\n deviceOptions: this.deviceOptions,\n logger: this.logger.child({\n kind: 'Device',\n ...serialPort.getInfo(),\n }),\n });\n this.devices.push(newDevice);\n await newDevice.open();\n }\n }\n\n this.logger?.trace('finish updateDevices');\n }\n\n /**\n * Update this.devices every `scanInterval` [ms].\n * @param {object} [options={}]\n * @param {number} [options.scanInterval=1000] Delay between `updateDevices()` calls\n * @param {number} [options.callback] Callback to execute on each update\n */\n async continuousUpdateDevices(options = {}) {\n const { scanInterval = 1000, callback } = options;\n while (true) {\n await this.updateDevices();\n if (callback) {\n callback(this.devices);\n }\n await delay(scanInterval);\n }\n }\n\n /**\n * Returns this.devices\n * @param {object} [options={}]\n * @param {bool} [options.ready=false] If `true` returns only currently connected device. If `false` returns all devices ever connected.\n * @returns {Array}\n */\n getDevicesList(options = {}) {\n let { ready = false } = options;\n return this.devices\n .filter((device) => !ready || device.isReady())\n .map((device) => ({\n status: device.status,\n id: device.id,\n queueLength: device.queue.length,\n }));\n }\n\n // private function\n findDevice(id) {\n if (id === undefined) return undefined;\n let devices = this.devices.filter(\n (device) => device.id === id && device.status === STATUS_OPENED,\n );\n if (devices.length === 0) return undefined;\n if (devices.length > 1) {\n throw new Error(`Many devices have the same id: ${id}`);\n }\n return devices[0];\n }\n\n /**\n * Send a serial command to a device.\n * @param {number} id ID of the device\n * @param {string} command Command to send\n * @param {object} [options={}] options\n * @param {number} [options.timeout] Timeout in [ms]\n * @param {number} [options.timeoutResolve=false] If `true` the promise will resolve even if the command timed out\n */\n async sendCommand(id, command, options = {}) {\n const device = this.findDevice(id);\n if (!device) {\n throw Error(`Device ${id} not found`);\n }\n if (device && device.isReady()) {\n return device.get(command, options);\n }\n throw Error(`Device ${id} not ready: ${device.port.path}`);\n }\n}\n","/* eslint-disable no-console */\nexport default function checkSerial(serial) {\n if (!serial) {\n console.error(\n \"Web serial doesn't seem to be enabled in your browser. Try enabling it by visiting:\",\n );\n console.error('chrome://flags/#enable-experimental-web-platform-features');\n console.error('opera://flags/#enable-experimental-web-platform-features');\n console.error('edge://flags/#enable-experimental-web-platform-features');\n }\n}\n","import { v4 } from '@lukeed/uuid';\n\nexport class Terminal {\n constructor(options = {}) {\n this.lineNumber = 0;\n this.eventNumber = 0;\n this.limit = options.limit || 1000;\n this.onChange = options.onChange;\n this.ignoreSend = options.ignoreSend ?? [];\n this.ignoreReceive = options.ignoreReceive ?? [];\n this.showSpecial = options.showSpecial || true;\n this.sendColor = options.sendColor || '#41c5d1';\n this.receiveColor = options.receiveColor || '#2ea600';\n this.events = [];\n }\n\n send(text) {\n this.append(text, 'send');\n }\n\n receive(text) {\n this.append(text, 'receive');\n }\n\n shouldIgnore(line, kind) {\n const ignores = kind === 'send' ? this.ignoreSend : this.ignoreReceive;\n for (let ignore of ignores) {\n if (ignore.test(line)) {\n return true;\n }\n }\n return false;\n }\n\n append(text, kind) {\n const lines = splitInLines(text, this.showSpecial);\n this.eventNumber++;\n const newEvents = [];\n for (let line of lines) {\n this.lineNumber++;\n const event = {\n uuid: v4(),\n lineNumber: this.lineNumber,\n eventNumber: this.eventNumber,\n kind,\n line,\n };\n if (!this.shouldIgnore(line, kind)) {\n newEvents.push(event);\n this.events.push(event);\n }\n }\n\n if (this.events.length > this.limit) {\n this.events.splice(0, this.events.length - this.limit);\n }\n\n this.onChange?.(newEvents, this.events);\n }\n\n toHtml() {\n let html = [];\n html.push('
');\n for (let event of this.events) {\n html.push(\n `
${htmlEscape(event.line)}
`,\n );\n }\n html.push('
');\n return html.join('\\n');\n }\n}\n\nfunction splitInLines(text, showSpecial) {\n if (showSpecial) {\n text = text\n .replace(/\\r/g, '')\n .replace(/\\n/g, '\\n')\n .replace(/\\t/g, '\\t');\n }\n return text.split(/\\r?\\n/);\n}\n\nfunction htmlEscape(str) {\n return str.replace(/&/g, '&').replace(/>/g, '>').replace(/ Math.floor((Math.random() * (maximum - minimum + 1)) + minimum);\n\nconst createAbortError = () => {\n\tconst error = new Error('Delay aborted');\n\terror.name = 'AbortError';\n\treturn error;\n};\n\nconst createDelay = ({clearTimeout: defaultClear, setTimeout: set, willResolve}) => (ms, {value, signal} = {}) => {\n\tif (signal && signal.aborted) {\n\t\treturn Promise.reject(createAbortError());\n\t}\n\n\tlet timeoutId;\n\tlet settle;\n\tlet rejectFn;\n\tconst clear = defaultClear || clearTimeout;\n\n\tconst signalListener = () => {\n\t\tclear(timeoutId);\n\t\trejectFn(createAbortError());\n\t};\n\n\tconst cleanup = () => {\n\t\tif (signal) {\n\t\t\tsignal.removeEventListener('abort', signalListener);\n\t\t}\n\t};\n\n\tconst delayPromise = new Promise((resolve, reject) => {\n\t\tsettle = () => {\n\t\t\tcleanup();\n\t\t\tif (willResolve) {\n\t\t\t\tresolve(value);\n\t\t\t} else {\n\t\t\t\treject(value);\n\t\t\t}\n\t\t};\n\n\t\trejectFn = reject;\n\t\ttimeoutId = (set || setTimeout)(settle, ms);\n\t});\n\n\tif (signal) {\n\t\tsignal.addEventListener('abort', signalListener, {once: true});\n\t}\n\n\tdelayPromise.clear = () => {\n\t\tclear(timeoutId);\n\t\ttimeoutId = null;\n\t\tsettle();\n\t};\n\n\treturn delayPromise;\n};\n\nconst createWithTimers = clearAndSet => {\n\tconst delay = createDelay({...clearAndSet, willResolve: true});\n\tdelay.reject = createDelay({...clearAndSet, willResolve: false});\n\tdelay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options);\n\treturn delay;\n};\n\nconst delay = createWithTimers();\ndelay.createWithTimers = createWithTimers;\n\nmodule.exports = delay;\n// TODO: Remove this for the next major release\nmodule.exports.default = delay;\n","import delay from 'delay';\n\nconst STATUS_CREATED = 0;\nconst STATUS_COMMAND_SENT = 10;\nconst STATUS_WAITING_RECEIVING = 20;\nconst STATUS_ANSWER_PARTIALLY_RECEIVED = 30;\nconst STATUS_ANSWER_RECEIVED = 40;\nconst STATUS_RESOLVED = 50;\nconst STATUS_ERROR = 60;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nexport class Action {\n constructor(command, device, options = {}) {\n this.device = device;\n this.currentTimeout = undefined;\n this.command = command;\n this.timeout = options.timeout ?? 200;\n this.timeoutResolve = options.timeoutResolve ?? false;\n this.disableTerminal = options.disableTerminal ?? false;\n this.kind = options.kind ?? 'writeRead';\n this.answer = '';\n this.partialAnswer = '';\n this.logger = options.logger;\n this.status = STATUS_CREATED;\n this.creationTimestamp = Date.now();\n this.promise = new Promise((resolve, reject) => {\n this.reject = reject;\n this.resolve = resolve;\n });\n this.isEndCommandAnswer =\n options.isEndCommandAnswer ??\n (() => {\n throw new Error('isEndCommandAnswer is not defined');\n });\n this.endCommandAnswerCallback =\n options.endCommandAnswerCallback ??\n (() => {\n throw new Error('endCommandAnswerCallback is not defined');\n });\n this.logger?.info('Action created');\n }\n\n isFinished() {\n return this.status === STATUS_RESOLVED || this.status === STATUS_ERROR;\n }\n\n setTimeout() {\n if (this.currentTimeout) {\n clearTimeout(this.currentTimeout);\n }\n this.currentTimeout = setTimeout(() => {\n if (this.status === STATUS_RESOLVED || this.status === STATUS_ERROR) {\n return;\n }\n if (this.timeoutResolve) {\n this.status = STATUS_RESOLVED;\n this.resolve(this.partialAnswer);\n !this.disableTerminal &&\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.info(`Timeout resolved after ${this.timeout}ms`);\n } else {\n this.status = STATUS_ERROR;\n this.reject(this.partialAnswer);\n !this.disableTerminal &&\n this.device.terminal?.receive(this.partialAnswer);\n this.logger?.error(`Timeout reject after ${this.timeout}ms`);\n }\n }, this.timeout);\n }\n\n async writeRead() {\n this.startTimestamp = Date.now();\n this.status = STATUS_COMMAND_SENT;\n await this.setTimeout();\n this.writeText(this.command)\n .then(async () => {\n await this.readText();\n this.status = STATUS_ANSWER_RECEIVED;\n this.answer = this.endCommandAnswerCallback(\n this.command,\n this.partialAnswer,\n );\n })\n .then(() => {\n this.status = STATUS_RESOLVED;\n this.resolve(this.answer);\n });\n return this.promise;\n }\n\n async writeText(command) {\n if (!command) return;\n const dataArrayBuffer = encoder.encode(`${command}\\n`);\n !this.disableTerminal && this.device.terminal?.send(command);\n return this.device.writer.write(dataArrayBuffer);\n }\n\n async readText() {\n this.status = STATUS_ANSWER_PARTIALLY_RECEIVED;\n while (this.status === STATUS_ANSWER_PARTIALLY_RECEIVED) {\n const chunk = await this.device.reader.read();\n if (chunk.value.length > 0) {\n // as long as we receive, we delay the timeout\n this.setTimeout();\n }\n this.partialAnswer += decoder.decode(chunk.value);\n if (this.isEndCommandAnswer(this.command, this.partialAnswer)) break;\n await delay(5);\n }\n !this.disableTerminal && this.device.terminal?.receive(this.partialAnswer);\n }\n}\n","import delay from 'delay';\n\nimport { Action } from './Action';\n\nexport const STATUS_OPENING = 1;\nexport const STATUS_OPENED = 2;\nexport const STATUS_CLOSED = 3;\nexport const STATUS_MISSING = 9;\nexport const STATUS_ERROR = 10;\nconst statusLabels = {\n [STATUS_OPENING]: 'opening',\n [STATUS_OPENED]: 'opened',\n [STATUS_CLOSED]: 'closed',\n [STATUS_MISSING]: 'missing',\n [STATUS_ERROR]: 'error',\n};\n\nexport class Device {\n constructor(serialPort, options = {}) {\n const { commandOptions = {}, deviceOptions = {} } = options;\n this.logger = options.logger;\n this.terminal = options.terminal;\n this.setStatus(STATUS_OPENING);\n this.id = undefined;\n this.serialPort = serialPort;\n this.baudRate = deviceOptions.baudRate || 115200;\n this.interCommandDelay = deviceOptions.interCommandDelay || 10;\n this.getID =\n deviceOptions.getID ??\n (async (device) => {\n return `${device.usbVendorId}-${device.usbProductId}`;\n });\n this.timeout = deviceOptions.timeout || 100;\n this.commandOptions = commandOptions;\n\n this.queue = [];\n this.action = undefined;\n\n this.usbVendorId = options.usbVendorId;\n this.usbProductId = options.usbProductId;\n this.logger?.info(`Device created`);\n }\n\n setStatus(status) {\n this.status = status;\n this.statusLabel = statusLabels[status];\n }\n\n isReady() {\n return this.status === STATUS_OPENED;\n }\n\n /** restart process queue if the previous one was finished */\n async ensureProcessQueue() {\n this.logger?.info('ensureProcessQueue');\n if (!this.currentProcessQueue) {\n this.currentProcessQueue = this.runProcessQueue();\n }\n return this.currentProcessQueue;\n }\n\n async runProcessQueue() {\n while (this.queue.length > 0) {\n this.action = this.queue.shift();\n if (this.action) {\n await this.action\n .writeRead()\n .then((value) => {\n this.logger?.info(\n { command: this.action.command, answer: this.action.answer },\n 'Resolve writeRead command',\n );\n })\n .catch((error) => {\n this.logger?.error(\n {\n command: this.action.command,\n answer: this.action.partialAnswer,\n },\n error.toString(),\n );\n });\n\n this.action = undefined;\n await delay(this.interCommandDelay);\n }\n }\n this.currentProcessQueue = undefined;\n }\n\n async getStatus() {\n return {\n value: this.status,\n };\n }\n\n async ensureOpen() {\n this.logger?.trace(`Ensure open`);\n let counter = 0;\n // we wait for the serial port to be opened for max 1s\n while (this.status === STATUS_OPENING && counter++ < 100) {\n await delay(10);\n }\n\n if (this.status !== STATUS_OPENED) {\n return this.open();\n }\n }\n\n async open() {\n this.logger?.info(`Opening`);\n await this.serialPort\n .open({\n baudRate: this.baudRate,\n })\n .catch((error) => {\n this.error(error);\n this.close();\n })\n .then(() => {\n this.ensureOpen();\n });\n this.reader = this.serialPort.readable.getReader();\n this.writer = this.serialPort.writable.getWriter();\n this.logger?.info(`Getting id`);\n\n this.id = await this.getID(this);\n\n this.logger?.info(`Id: ${this.id}`);\n this.setStatus(STATUS_OPENED);\n }\n\n /*\n We need to add this command in the queue and wait it resolves or rejects\n */\n async get(command, options = {}) {\n const {\n timeout = this.timeout,\n timeoutResolve = false,\n disableTerminal = false,\n } = options;\n\n const action = new Action(command, this, {\n ...this.commandOptions,\n timeout,\n timeoutResolve,\n disableTerminal,\n logger: this.logger.child({ kind: 'Command', command }),\n });\n\n this.queue.push(action);\n this.ensureProcessQueue();\n return action.promise;\n }\n\n error(error) {\n this.logger?.error(error, `Error ${this.serialPort?.path}`);\n this.setStatus(STATUS_ERROR);\n /**\n this.emit('adapter', {\n event: 'Error',\n value: error,\n });\n **/\n }\n\n close() {\n this.logger?.info(`Close`);\n this.setStatus(STATUS_CLOSED);\n }\n}\n","export default class EventEmitter {\n constructor() {\n this.callbacks = {};\n }\n\n on(event, cb) {\n if (!this.callbacks[event]) this.callbacks[event] = [];\n this.callbacks[event].push(cb);\n }\n\n emit(event, data) {\n let cbs = this.callbacks[event];\n if (cbs) {\n cbs.forEach((cb) => cb(data));\n }\n }\n}\n","var IDX=256, HEX=[], BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function v4() {\n\tvar i=0, num, out='';\n\n\tif (!BUFFER || ((IDX + 16) > 256)) {\n\t\tBUFFER = Array(i=256);\n\t\twhile (i--) BUFFER[i] = 256 * Math.random() | 0;\n\t\ti = IDX = 0;\n\t}\n\n\tfor (; i < 16; i++) {\n\t\tnum = BUFFER[IDX + i];\n\t\tif (i==6) out += HEX[num & 15 | 64];\n\t\telse if (i==8) out += HEX[num & 63 | 128];\n\t\telse out += HEX[num];\n\n\t\tif (i & 1 && i > 1 && i < 11) out += '-';\n\t}\n\n\tIDX++;\n\treturn out;\n}\n","export const alarmsDescription = {\n 1: 'Hard limit triggered. Machine position is likely lost due to sudden and immediate halt. Re-homing is highly recommended.',\n 2: 'G-code motion target exceeds machine travel. Machine position safely retained. Alarm may be unlocked.',\n 3: 'Reset while in motion. Grbl cannot guarantee position. Lost steps are likely. Re-homing is highly recommended.',\n 4: 'Probe fail. The probe is not in the expected initial state before starting probe cycle, where G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered.',\n 5: 'Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4.',\n 6: 'Homing fail. Reset during active homing cycle.',\n 7: 'Homing fail. Safety door was opened during active homing cycle.',\n 8: 'Homing fail. Cycle failed to clear limit switch when pulling off. Try increasing pull-off setting or check wiring.',\n 9: 'Homing fail. Could not find limit switch within search distance. Defined as `1.5 * max_travel` on search and `5 * pulloff` on locate phases.',\n};\n","export const errorsDescription = {\n 1: 'G-code words consist of a letter and a value. Letter was not found.',\n 2: 'Numeric value format is not valid or missing an expected value.',\n 3: 'Grbl `$` system command was not recognized or supported.',\n 4: 'Negative value received for an expected positive value.',\n 5: 'Homing cycle is not enabled via settings.',\n 6: 'Minimum step pulse time must be greater than 3usec',\n 7: 'EEPROM read failed. Reset and restored to default values.',\n 8: 'Grbl `$` command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job.',\n 9: 'G-code locked out during alarm or jog state',\n 10: 'Soft limits cannot be enabled without homing also enabled.',\n 11: 'Max characters per line exceeded. Line was not processed and executed.',\n 12: '(Compile Option) Grbl `$` setting value exceeds the maximum step rate supported.',\n 13: 'Safety door detected as opened and door state initiated.',\n 14: '(Grbl-Mega Only) Build info or startup line exceeded EEPROM line length limit.',\n 15: 'Jog target exceeds machine travel. Command ignored.',\n 16: 'Jog command with no `=` or contains prohibited g-code.',\n 17: 'Laser mode disabled. Requires PWM output.',\n 20: 'Unsupported or invalid g-code command found in block.',\n 21: 'More than one g-code command from same modal group found in block.',\n 22: 'Feed rate has not yet been set or is undefined.',\n 23: 'G-code command in block requires an integer value.',\n 24: 'Two G-code commands that both require the use of the `XYZ` axis words were detected in the block.',\n 25: 'A G-code word was repeated in the block.',\n 26: 'A G-code command implicitly or explicitly requires `XYZ` axis words in the block, but none were detected.',\n 27: '`N` line number value is not within the valid range of `1` - `9,999,999`.',\n 28: 'A G-code command was sent, but is missing some required `P` or `L` value words in the line.',\n 29: 'Grbl supports six work coordinate systems `G54-G59`. `G59.1`, `G59.2`, and `G59.3` are not supported.',\n 30: 'The `G53` G-code command requires either a `G0` seek or `G1` feed motion mode to be active. A different motion was active.',\n 31: 'There are unused axis words in the block and `G80` motion mode cancel is active.',\n 32: 'A `G2` or `G3` arc was commanded but there are no `XYZ` axis words in the selected plane to trace the arc.',\n 33: 'The motion command has an invalid target. `G2`, `G3`, and `G38.2` generates this error, if the arc is impossible to generate or if the probe target is the current position.',\n 34: 'A `G2` or `G3` arc, traced with the radius definition, had a mathematical error when computing the arc geometry. Try either breaking up the arc into semi-circles or quadrants, or redefine them with the arc offset definition.',\n 35: 'A `G2` or `G3` arc, traced with the offset definition, is missing the `IJK` offset word in the selected plane to trace the arc.',\n 36: \"There are unused, leftover G-code words that aren't used by any command in the block.\",\n 37: 'The `G43.1` dynamic tool length offset command cannot apply an offset to an axis other than its configured axis. The Grbl default axis is the Z-axis.',\n 38: 'Tool number greater than max supported value.',\n};\n","export const parametersDescription = {};\n","export const settingsDescription = {\n $0: 'Step pulse time, microseconds',\n $1: 'Step idle delay, milliseconds',\n $2: 'Step pulse invert, mask',\n $3: 'Step direction invert, mask',\n $4: 'Invert step enable pin, boolean',\n $5: 'Invert limit pins, boolean',\n $6: 'Invert probe pin, boolean',\n $10: 'Status report options, mask',\n $11: 'Junction deviation, millimeters',\n $12: 'Arc tolerance, millimeters',\n $13: 'Report in inches, boolean',\n $20: 'Soft limits enable, boolean',\n $21: 'Hard limits enable, boolean',\n $22: 'Homing cycle enable, boolean',\n $23: 'Homing direction invert, mask',\n $24: 'Homing locate feed rate, mm/min',\n $25: 'Homing search seek rate, mm/min ',\n $26: 'Homing switch debounce delay, milliseconds',\n $27: 'Homing switch pull-off distance, millimeters',\n $30: 'Maximum spindle speed, RPM',\n $31: 'Minimum spindle speed, RPM',\n $32: 'Laser-mode enable, boolean',\n $100: 'X-axis steps per millimeter',\n $101: 'Y-axis steps per millimeter',\n $102: 'Z-axis steps per millimeter',\n $110: 'X-axis maximum rate, mm/min',\n $111: 'Y-axis maximum rate, mm/min',\n $112: 'Z-axis maximum rate, mm/min',\n $120: 'X-axis acceleration, mm/sec^2',\n $121: 'Y-axis acceleration, mm/sec^2',\n $122: 'Z-axis acceleration, mm/sec^2',\n $130: 'X-axis maximum travel, millimeters',\n $131: 'Y-axis maximum travel, millimeters',\n $132: 'Z-axis maximum travel, millimeters',\n};\n","import { alarmsDescription } from './alarmsDescription.js';\nimport { errorsDescription } from './errorsDescription.js';\nimport { parametersDescription } from './parametersDescription.js';\nimport { settingsDescription } from './settingsDescription.js';\n\n// format description: https://github.com/gnea/grbl/edit/master/doc/markdown/interface.md\nconst MAX_ERRORS_MESSAGES = 20;\n\n/**\n * @typedef {Object} State\n * @property {object[]} [state.messages=[]]\n * @property {object} [state.status={}]\n * @property {object} [state.settings={}]\n * @property {object} [state.parameters={}]\n * @property {string} [state.version='']\n */\n\n/**\n *\n * @param {string} input\n * @param {State} [state={}]\n * @returns\n */\nexport function updateState(input, state = {}) {\n if (!input) return;\n const lines = input.split(/\\r?\\n/);\n\n for (let line of lines) {\n if (line.startsWith('<')) {\n parseQuestionMark(line, state);\n }\n if (line.startsWith('[')) {\n parseSquareBracket(line, state);\n }\n if (line.startsWith('$')) {\n parseSettings(line, state);\n }\n if (line.startsWith('Grbl')) {\n state.version = line.replace('Grbl ', '');\n }\n if (line.startsWith('error')) {\n parseErrors(line, state);\n }\n if (line.includes('ALARM')) {\n parseAlarms(line, state);\n }\n }\n}\n\n/**\n *\n * @param {string} line\n * @param {State} [state={}]\n * @returns\n */\nfunction parseErrors(line, state) {\n const [, error] = line.split(':');\n appendMessage(\n {\n kind: 'ERROR',\n code: error,\n description: errorsDescription[error],\n },\n state,\n );\n}\n\n/**\n *\n * @param {string} line\n * @param {State} [state={}]\n * @returns\n */\nfunction parseAlarms(line, state) {\n const [, alarm] = line.split(':');\n appendMessage(\n {\n kind: 'ALARM',\n code: alarm,\n description: alarmsDescription[alarm],\n },\n state,\n );\n}\n\n/**\n *\n * @param {string} line\n * @param {State} [state]\n * @return\n */\nfunction parseSettings(line, state) {\n const [key, value] = line.split('=');\n state.settings[key] = {\n key,\n description: settingsDescription[key],\n value: Number(value),\n };\n}\n\nconst keyMappings = {\n HLP: 'Help',\n MSG: 'Message',\n GC: 'GCode',\n VER: 'Version',\n OPT: 'Option',\n echo: 'Echo',\n};\n\n/**\n *\n * @param {string} line\n * @param {State} [state={}]\n * @returns\n */\nfunction parseSquareBracket(line, state = {}) {\n const [key, value] = line.replace(/\\[(.*)\\]/, '$1').split(':');\n const description = line\n .replace(/\\[(.*)\\]/, '$1')\n .split(':')\n .slice(1)\n .join(':');\n switch (key) {\n case 'echo':\n case 'VER':\n case 'OPT':\n case 'HLP':\n case 'GC':\n case 'MSG':\n appendMessage({ kind: keyMappings[key], description }, state);\n return;\n default:\n state.parameters[key] = {\n key,\n description: parametersDescription[key],\n value: value.split(',').map((field) => Number(field)),\n };\n }\n}\n\n/**\n *\n * @param {string} line\n * @param {State} [state]\n * @returns\n */\nfunction parseQuestionMark(line, state = {}) {\n // \n const parts = line.replace(/<(.*)>/, '$1').split('|');\n const status = { value: parts[0] };\n status.Pn = [false, false, false];\n for (let i = 1; i < parts.length; i++) {\n const [key, value] = parts[i].split(':');\n\n if (key === 'Pn') {\n status[key] = [\n value.includes('X'),\n value.includes('Y'),\n value.includes('Z'),\n ];\n } else {\n status[key] = value.split(',').map((v) => Number(v));\n }\n }\n state.status = { ...state.status, ...status };\n}\n\nfunction appendMessage(message, state) {\n state.messages.push({\n epoch: Date.now(),\n ...message,\n });\n if (state.messages.length > MAX_ERRORS_MESSAGES) {\n state.messages.splice(0, state.messages.length - MAX_ERRORS_MESSAGES);\n }\n console.log(state.messages);\n}\n","import { updateState } from './updateState.js';\n\nfunction getEmptyState() {\n return {\n messages: [],\n status: {},\n settings: {},\n parameters: {},\n version: '',\n gcode: {\n currentLine: 0,\n sentLine: 1,\n },\n };\n}\n\nexport const GRBL = {\n updateState,\n getEmptyState,\n};\n","import delay from 'delay';\n\nimport { Device, STATUS_MISSING, STATUS_OPENED, STATUS_CLOSED } from './Device';\nimport EventEmitter from './util/EventEmitter';\nimport checkSerial from './util/checkSerial';\n\n/**\n * Class creating a new serial bridge to manage serial ports.\n * @param {object} [options={}]\n * @param {Array} [options.portFilter] Filter the serial ports to address.\n * @param {object} [options.command={}]\n * @param {number} [options.command.timeout=100] Time to wait for answer before timeout\n * @param {Function} [options.command.isEndCommandAnswer]\n * @param {Function} [options.command.endCommandAnswerCallback]\n * @param {object} [options.device={}]\n * @param {AsyncFunction} [options.device.getID=(device)=>()] Time to wait between commands in [ms]\n * @param {number} [options.device.baudRate=115200] Baud rate\n * @param {number} [options.device.interCommandDelay=100] Time to wait between commands in [ms]\n */\nexport class DevicesManager extends EventEmitter {\n constructor(serial, options = {}) {\n super();\n checkSerial(serial);\n this.serial = serial;\n this.terminal = options.terminal;\n this.logger = options.logger;\n this.devices = [];\n this.portFilter = options.portFilter;\n this.commandOptions = options.command ?? {};\n this.deviceOptions = options.device ?? {};\n }\n\n /**\n * By calling this method from a click you give users the possibility to allow access to some devices\n */\n async requestDevices() {\n await this.serial.requestPort({\n filters: this.portFilter,\n });\n return this.updateDevices();\n }\n\n /**\n * Update this.devices\n */\n async updateDevices() {\n const serialPorts = await this.serial.getPorts();\n\n this.logger?.trace('start updateDevices');\n\n const missingDevicesSerialPort = this.devices.filter(\n (device) => !serialPorts.includes(device.serialPort),\n );\n for (let device of missingDevicesSerialPort) {\n if (device.status !== STATUS_MISSING && device.status !== STATUS_CLOSED) {\n device.close();\n }\n device.status = STATUS_MISSING;\n }\n for (let serialPort of serialPorts) {\n let device = this.devices.find(\n (device) => device.serialPort === serialPort,\n );\n if (device) {\n await device.ensureOpen();\n } else {\n const serialPortInfo = serialPort.getInfo();\n let newDevice = new Device(serialPort, {\n baudRate: this.baudRate,\n terminal: this.terminal,\n ...serialPortInfo,\n commandOptions: this.commandOptions,\n deviceOptions: this.deviceOptions,\n logger: this.logger.child({\n kind: 'Device',\n ...serialPort.getInfo(),\n }),\n });\n this.devices.push(newDevice);\n await newDevice.open();\n }\n }\n\n this.logger?.trace('finish updateDevices');\n }\n\n /**\n * Update this.devices every `scanInterval` [ms].\n * @param {object} [options={}]\n * @param {number} [options.scanInterval=1000] Delay between `updateDevices()` calls\n * @param {number} [options.callback] Callback to execute on each update\n */\n async continuousUpdateDevices(options = {}) {\n const { scanInterval = 1000, callback } = options;\n while (true) {\n await this.updateDevices();\n if (callback) {\n callback(this.devices);\n }\n await delay(scanInterval);\n }\n }\n\n /**\n * Returns this.devices\n * @param {object} [options={}]\n * @param {bool} [options.ready=false] If `true` returns only currently connected device. If `false` returns all devices ever connected.\n * @returns {Array}\n */\n getDevicesList(options = {}) {\n let { ready = false } = options;\n return this.devices\n .filter((device) => !ready || device.isReady())\n .map((device) => ({\n status: device.status,\n id: device.id,\n queueLength: device.queue.length,\n }));\n }\n\n // private function\n findDevice(id) {\n if (id === undefined) return undefined;\n let devices = this.devices.filter(\n (device) => device.id === id && device.status === STATUS_OPENED,\n );\n if (devices.length === 0) return undefined;\n if (devices.length > 1) {\n throw new Error(`Many devices have the same id: ${id}`);\n }\n return devices[0];\n }\n\n /**\n * Send a serial command to a device.\n * @param {number} id ID of the device\n * @param {string} command Command to send\n * @param {object} [options={}] options\n * @param {number} [options.timeout] Timeout in [ms]\n * @param {boolean} [options.timeoutResolve=false] If `true` the promise will resolve even if the command timed out\n * @param {boolean} [options.disableTerminal=false]\n */\n async sendCommand(id, command, options = {}) {\n const device = this.findDevice(id);\n if (!device) {\n throw Error(`Device ${id} not found`);\n }\n if (device && device.isReady()) {\n return device.get(command, options);\n }\n throw Error(`Device ${id} not ready: ${device.port.path}`);\n }\n}\n","/* eslint-disable no-console */\nexport default function checkSerial(serial) {\n if (!serial) {\n console.error(\n \"Web serial doesn't seem to be enabled in your browser. Try enabling it by visiting:\",\n );\n console.error('chrome://flags/#enable-experimental-web-platform-features');\n console.error('opera://flags/#enable-experimental-web-platform-features');\n console.error('edge://flags/#enable-experimental-web-platform-features');\n }\n}\n","import { v4 } from '@lukeed/uuid';\n\nexport class Terminal {\n constructor(options = {}) {\n this.start = Date.now();\n this.lineNumber = 0;\n this.eventNumber = 0;\n this.limit = options.limit ?? 1000;\n this.onChange = options.onChange;\n this.ignoreSend = options.ignoreSend ?? [];\n this.ignoreReceive = options.ignoreReceive ?? [];\n this.showSpecial = options.showSpecial ?? true;\n this.sendColor = options.sendColor ?? '#efcef2';\n this.receiveColor = options.receiveColor ?? '#bbeeb7';\n this.events = [];\n }\n\n send(text) {\n this.append(text, 'send');\n }\n\n receive(text) {\n this.append(text, 'receive');\n }\n\n shouldIgnore(line, kind) {\n const ignores = kind === 'send' ? this.ignoreSend : this.ignoreReceive;\n for (let ignore of ignores) {\n if (ignore.test(line)) {\n return true;\n }\n }\n return false;\n }\n\n append(text, kind) {\n const lines = splitInLines(text, this.showSpecial);\n this.eventNumber++;\n const newEvents = [];\n for (let line of lines) {\n this.lineNumber++;\n const event = {\n uuid: v4(),\n time: Math.round(Date.now() - this.start),\n lineNumber: this.lineNumber,\n eventNumber: this.eventNumber,\n kind,\n line,\n };\n if (!this.shouldIgnore(line, kind)) {\n newEvents.push(event);\n this.events.push(event);\n }\n }\n\n if (this.events.length > this.limit) {\n this.events.splice(0, this.events.length - this.limit);\n }\n\n this.onChange?.(newEvents, this.events);\n }\n\n toHtml() {\n let html = [];\n html.push('
');\n for (let event of this.events) {\n html.push(\n `
${(event.time / 1000).toFixed(3)}: ${htmlEscape(event.line)}
`,\n );\n }\n html.push('
');\n return html.join('\\n');\n }\n}\n\nfunction splitInLines(text, showSpecial) {\n if (showSpecial) {\n text = text\n .replace(/\\r/g, '')\n .replace(/\\n/g, '\\n')\n .replace(/\\t/g, '\\t');\n }\n return text.replace(/[\\r\\n]+$/, '').split(/\\r?\\n/);\n}\n\nfunction htmlEscape(str) {\n return str.replace(/&/g, '&').replace(/>/g, '>').replace(/ Number(field)), + }; + } +} + +/** + * + * @param {string} line + * @param {State} [state] + * @returns + */ +function parseQuestionMark(line, state = {}) { + // + const parts = line.replace(/<(.*)>/, '$1').split('|'); + const status = { value: parts[0] }; + status.Pn = [false, false, false]; + for (let i = 1; i < parts.length; i++) { + const [key, value] = parts[i].split(':'); + + if (key === 'Pn') { + status[key] = [ + value.includes('X'), + value.includes('Y'), + value.includes('Z'), + ]; + } else { + status[key] = value.split(',').map((v) => Number(v)); + } + } + state.status = { ...state.status, ...status }; +} + +function appendMessage(message, state) { + state.messages.push({ + epoch: Date.now(), + ...message, + }); + if (state.messages.length > MAX_ERRORS_MESSAGES) { + state.messages.splice(0, state.messages.length - MAX_ERRORS_MESSAGES); + } + console.log(state.messages); +} diff --git a/src/grbl/updateStatus.js b/src/grbl/updateStatus.js deleted file mode 100644 index 40b3f74..0000000 --- a/src/grbl/updateStatus.js +++ /dev/null @@ -1,64 +0,0 @@ -import { errorsDescription } from './errorsDescription.js'; -import { parametersDescription } from './parametersDescription.js'; -import { settingsDescription } from './settingsDescription.js'; - -export function updateStatus(input, status) { - const lines = input.split(/\r?\n/); - - for (let line of lines) { - if (line.startsWith('<')) { - parseQuestionMark(line, status); - } - if (line.startsWith('[')) { - parseParameters(line, status); - } - if (line.startsWith('$')) { - parseSettings(line, status); - } - if (line.startsWith('Grbl')) { - status.version = line.replace('Grbl ', ''); - } - if (line.startsWith('error')) { - parseErrors(line, status); - } - } -} - -function parseErrors(line, status) { - const [, error] = line.split(':'); - status.error = { - code: error, - description: errorsDescription[error], - }; -} - -function parseSettings(line, status) { - const [key, value] = line.split('='); - status.settings[key] = { - key, - description: settingsDescription[key], - value: Number(value), - }; -} - -function parseParameters(line, status) { - const [key, value] = line.replace(/\[(.*)\]/, '$1').split(':'); - status.parameters[key] = { - key, - description: parametersDescription[key], - value: value.split(',').map((field) => Number(field)), - }; -} - -function parseQuestionMark(line, status) { - // - const parts = line.replace(/<(.*)>/, '$1').split('|'); - const message = parts[0]; - const info = {}; - for (let i = 1; i < parts.length; i++) { - const [key, value] = parts[i].split(':'); - info[key] = value.split(',').map((v) => Number(v)); - } - status.message = message; - status.info = { ...status.info, ...info }; -} diff --git a/src/terminal/Terminal.js b/src/terminal/Terminal.js index ec360c6..1242614 100644 --- a/src/terminal/Terminal.js +++ b/src/terminal/Terminal.js @@ -2,15 +2,16 @@ import { v4 } from '@lukeed/uuid'; export class Terminal { constructor(options = {}) { + this.start = Date.now(); this.lineNumber = 0; this.eventNumber = 0; - this.limit = options.limit || 1000; + this.limit = options.limit ?? 1000; this.onChange = options.onChange; this.ignoreSend = options.ignoreSend ?? []; this.ignoreReceive = options.ignoreReceive ?? []; - this.showSpecial = options.showSpecial || true; - this.sendColor = options.sendColor || '#41c5d1'; - this.receiveColor = options.receiveColor || '#2ea600'; + this.showSpecial = options.showSpecial ?? true; + this.sendColor = options.sendColor ?? '#efcef2'; + this.receiveColor = options.receiveColor ?? '#bbeeb7'; this.events = []; } @@ -40,6 +41,7 @@ export class Terminal { this.lineNumber++; const event = { uuid: v4(), + time: Math.round(Date.now() - this.start), lineNumber: this.lineNumber, eventNumber: this.eventNumber, kind, @@ -65,7 +67,7 @@ export class Terminal { html.push( `
${htmlEscape(event.line)}
`, + }">${(event.time / 1000).toFixed(3)}: ${htmlEscape(event.line)}`, ); } html.push(''); @@ -80,7 +82,7 @@ function splitInLines(text, showSpecial) { .replace(/\n/g, '\n') .replace(/\t/g, '\t'); } - return text.split(/\r?\n/); + return text.replace(/[\r\n]+$/, '').split(/\r?\n/); } function htmlEscape(str) {