{"version":3,"file":"ngx-serial-console.mjs","sources":["../../../projects/ngx-serial-console/src/lib/ngx-serial-console.ts","../../../projects/ngx-serial-console/src/lib/ngx-serial-console.html","../../../projects/ngx-serial-console/src/public-api.ts","../../../projects/ngx-serial-console/src/ngx-serial-console.ts"],"sourcesContent":["import { Component, computed, ElementRef, Input, Signal, signal, ViewChild, WritableSignal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\ninterface SerialMonitorState {\n  serialAvailable: boolean;\n  maxLines: number;\n  outputLines: string[];\n  baudRate: number;\n  vendorId: string | undefined;\n  productId: string | undefined;\n  theme: \"CRT\" | \"Plain\";\n  prevInputs: string[];\n  currentInput: string;\n}\n\n// should not be shared across components or services\ninterface SerialConnectionState {\n  connected: boolean;\n  port: any;\n  textDecoder: TextDecoderStream | null;\n  textEncoder: TextEncoderStream | null;\n  readableStreamClosed: any;\n  writableStreamClosed: any;\n  reader: ReadableStreamDefaultReader<string> | null;\n  writer: WritableStreamDefaultWriter<string> | null; \n  keepConnectionAlive: boolean;\n}\n\n@Component({\n  selector: 'ngx-serial-console',\n  imports: [FormsModule],\n  templateUrl: './ngx-serial-console.html',\n  styleUrl: './ngx-serial-console.css'\n})\n\n// NgxSerialConsole\n// Works only on Chromium based browsers, allows users to select the usb port and baud rate\n// to connect with serial interface. The output of the serial interface can be monitored using this tool.\n// When debugging Arduino devices, ESP32, ESP8266 and other devices with a serial port.\nexport class NgxSerialConsole {\n\n  @ViewChild('scrollSerialContainer') private scrollContainer!: ElementRef;  \n\n  @Input() theme: \"CRT\" | \"Plain\" = \"Plain\";\n\n  // state as a signal, so the component to react to state changes immediately.\n  state: WritableSignal<SerialMonitorState> = signal({\n    serialAvailable: false,\n    connected: false,\n    maxLines: 500,\n    outputLines: [],\n    prevInputs: [],\n    currentInput: \"\",\n    baudRate: 115200,\n    vendorId: \"\",\n    productId: \"\",\n    theme: \"Plain\"\n  }); \n  \n  connState: SerialConnectionState = {\n    connected: false,\n    port: undefined,\n    reader: null,\n    writer: null,\n    textDecoder: null,\n    textEncoder: null,\n    readableStreamClosed: undefined,\n    writableStreamClosed: undefined,\n    keepConnectionAlive: false,\n  }\n  \n  // computed signal, which listens on state changes, and updates the consoleOutput\n  consoleOutput: Signal<string> = computed(() => this.state().outputLines.join(''));\n\n  serial: any;\n\n  themeStyles: string[] = [\"CRT\", \"Plain\"];\n  baudRates: number[] = [300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 1000000, 1500000];\n\n  isUserScrolling = false; // triggered when user scrolls using mouse or touch\n  autoScrollEnabled: boolean = true; // when user scrolls to any other position, auto scroll is disabled\n\n  constructor() {\n\n    let serialAvailable = false;\n    if ('serial' in navigator) {\n      this.serial = navigator.serial;\n      serialAvailable = true;\n      console.info(\"Serial device is available\");\n    } else {\n      this.serial = null;\n      console.info(\"Serial device not available, use google chrome browser\");\n    }\n\n    this.state.update(state => ({ \n      ...state, \n      serialAvailable: serialAvailable,\n      theme: this.theme, \n    }));\n\n  }\n\n  ngAfterViewChecked() {\n\n    if (!this.serial) return; // there will be no view to check the scroll\n\n    const element = this.scrollContainer.nativeElement;\n\n    element.addEventListener('scroll', () => {\n\n      // Ignore scroll events triggered by programmatic scroll\n      if (!this.isUserScrolling) return;\n      // adding a threshold of 100 to scroll bottom, so user does not have to go to the fag end bottom\n      const nearBottom = element.scrollHeight - element.scrollTop < (element.clientHeight + 100);\n      this.autoScrollEnabled = nearBottom;\n      \n      // console.log(\"Auto scroll enabled \", this.autoScrollEnabled);\n    });\n\n    // Enable this flag only on user interaction, for example with mouse or touch:\n    element.addEventListener('wheel', () => this.isUserScrolling = true);\n    element.addEventListener('touchmove', () => this.isUserScrolling = true);\n\n  }\n\n  // send the input to serial\n  async send() {\n    this._send(this.state().currentInput);\n  }\n\n  private async _send(text: string) {\n    if (this.connState.writer) {\n      // console.log(\"Can write to serial, sending \", this.state().currentInput);\n      await this.connState.writer.write(text);\n      this.state.update(state => {\n        const updatedInputs = [...state.prevInputs, text];\n        return {\n          ...state,\n          prevInputs: updatedInputs,\n          currentInput: \"\"\n        };\n      });\n    } else {\n      // console.log(\"Serial port not writable\");\n    }\n  }\n\n  // clear the output of the console window\n  clear() {\n    this.state.update(state => ({\n      ...state,\n      outputLines: []\n    }));\n  }\n\n  clearInput() {\n    this.state.update(state => ({\n      ...state,\n      currentInput: \"\"\n    }));\n  }\n\n  // binu - do not change flow\n  // close the reader\n  // close the writer\n  // close the port\n  // unset the states\n  async unsetConnection() {\n\n    // console.log(\"Closing all serial connections (unsetConnection)\");\n    // close the reader, write and cleanup states\n    // do not ever combine the exception try catches below...\n    try {\n      await this.connState.reader?.cancel();\n    } catch(err) {}\n\n    try {\n      // console.log(\"Serial writer closing (unsetConnection)\");\n      await this.connState.writer?.close();\n      // console.log(\"Serial writer closed (unsetConnection)\");\n\n    } catch(err) { }\n\n    await this.connState.readableStreamClosed.catch(() => { /* Ignore the error */ });\n    await this.connState.writableStreamClosed.catch(() => { /* Ignore errors here */ });\n\n    try {\n      // console.log(\"Closing serial port (unsetConnection)\");\n\n      await this.connState.port.close();\n      // console.log(\"Serial port closed (unsetConnection)\");\n    } catch(err) {}\n\n    // console.log(\"Serial port closed (unsetConnection)\");\n\n    this.state.update(state => ({\n      ...state,\n      connected: false,\n      vendorId: \"\",\n      productId: \"\",\n    }));\n\n    // unset all connection states\n    this.connState = {\n      connected: false,\n      port: undefined,\n      reader: null,\n      writer: null,\n      textDecoder: null,\n      textEncoder: null,\n      readableStreamClosed: undefined,\n      writableStreamClosed: undefined,\n      keepConnectionAlive: false,\n    }\n    // console.log(\"ConnState unset (unsetConnection)\");\n    this.appendOutput('\\nDisconnected from serial port\\n');\n\n  }\n\n  async disconnectSerialPort() {\n    // console.log(\"Triggering disconnectSerialPort\");\n    this._send(\"__disconnect\");\n    //this.connState.keepConnectionAlive = false;\n    this._send(\"__disconnected\");\n    this.unsetConnection();\n  }\n\n  // initiate the serial connection\n  // this will open a dialog, where the user has to select the console port\n  // because of security reasons, we cannot auto connect to a serial port from browser\n  connectSerialPort() {\n\n    if (this.serial) {\n      this.handleSerialEvents();\n      this.openSerialPort();\n    }\n  }\n\n  // handle events, so we know if the serial device disconnected\n  handleSerialEvents() {\n\n    this.serial?.addEventListener('disconnect', (event: any) => {\n      //console.log('Serial port disconnected:', event.target);\n      this.unsetConnection();\n      this.appendOutput('\\n\\nConnection lost, check device or cable. Please reconnect again using the \"Connect Button above\" \\n');\n    });\n    this.serial?.addEventListener('connect', (event: any) => {\n      //console.log('Serial port connected:', event.target);\n      this.appendOutput('\\n\\nConnection was reset, check device or cable. Please reconnect again using the \"Connect Button above\" \\n');\n    });\n\n  }\n\n  async openSerialPort() {\n    try {\n      if (this.serial) {\n        // Request the user to select a serial port.\n        \n        this.appendOutput(`Waiting for user input to connect to serial port\\n`);  \n        const port = await this.serial.requestPort();\n        await port.open({ baudRate: this.state().baudRate });\n\n        if (port) {\n          this.state.update(state => ({\n            ...state,\n            vendorId: port.getInfo().vendorId,\n            productId: port.getInfo().productId,\n          }));\n          this.connState.connected = true;\n\n          this.appendOutput(`Connected serial port with baud rate ${this.state().baudRate}\\n`);   \n          // Set up a text decoder stream to read from the serial port.\n          this.connState.port = port;\n          this.connState.textDecoder = new TextDecoderStream();\n          this.connState.readableStreamClosed = port.readable.pipeTo(this.connState.textDecoder.writable);\n          this.connState.reader = this.connState.textDecoder.readable.getReader();\n\n          this.connState.textEncoder = new TextEncoderStream();\n\n          this.connState.writableStreamClosed = this.connState.textEncoder.readable.pipeTo(port.writable);\n          this.connState.writer = this.connState.textEncoder.writable.getWriter();\n\n          this.readSerialPort(port);\n        }\n      }\n    } \n    catch (error: unknown) {\n      if (error instanceof Error) {\n        // this.unsetConnection(); // TODO, depending on  error we have to terminate connection\n        this.appendOutput(`Error received: ${error.message} \\n`);\n      } else {\n        this.unsetConnection();\n        this.appendOutput(`Unexpected error: ${String(error)}`);\n      }\n    }\n  }\n\n  // read stream from the serial port, till a user disconnects\n  // or the serial device disconnects\n  // handle disconnections gracefully\n  async  readSerialPort(port: any) {\n    \n    this.appendOutput('Connected and reading data:\\n');\n\n    // if we want to stop the read loop, set this var to false, in other functions\n    this.connState.keepConnectionAlive = true;\n    \n    // we are using zoneless, \n    // #TODO binu, revisit why PendingTasks is not needed here\n    while (this.connState.keepConnectionAlive && this.connState.reader) {\n      const { value, done } = await this.connState.reader.read();\n      if (done) {\n        console.log(\"Serial Reader closed\");\n        this.connState.reader.releaseLock();\n        this.connState.keepConnectionAlive = false;\n        break;\n      }\n      if (value) {\n        this.appendOutput(value);\n      }\n    }\n  \n    this.unsetConnection();\n\n  }\n  \n  // appends the new data from serial monitor to the output array\n  // if the number of lines exceed maxLines, we trim the array to maxLines length\n  appendOutput(newData: string) {\n\n    this.state.update(state => {\n      // Concatenate existing lines with new lines\n      const updatedLines = [...state.outputLines, newData];\n\n      // Trim the array if it exceeds maxLines\n      const trimmedLines =\n        updatedLines.length > state.maxLines\n          ? updatedLines.slice(updatedLines.length - state.maxLines)\n          : updatedLines;\n\n      return {\n        ...state,\n        outputLines: trimmedLines\n      };\n    });\n    this.scrollToBottomSerialOut();\n  }\n\n  private scrollToBottomSerialOut(): void {\n\n    if (!this.autoScrollEnabled) return;\n    this.isUserScrolling = false; // unset flag, till user feedback is present\n    try {\n      this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;\n    } catch (err) {\n      // Handle errors if any\n    }\n\n  }  \n\n}\n","@if (state().serialAvailable) {\n    <div class=\"card console-window\" [class]=\"state().theme\">\n        \n        <div class=\"input-group input-group-sm mb-3\">\n            <span class=\"input-group-text\">\n                Serial Monitor\n                @if (connState.connected) {\n                    <i class=\"fa-solid fa-link px-2\"></i>\n                } @else {\n                    <i class=\"fa-solid fa-link-slash px-2\"></i>\n                }\n            </span>\n            @if (connState.connected) {\n                <button id=\"serialDisConnectButton\" class=\"btn btn-outline-secondary\" (click)=\"disconnectSerialPort()\">Disconnect</button>\n            } @else {\n                <button id=\"serialConnectButton\" class=\"btn btn-outline-secondary\" (click)=\"connectSerialPort()\">Connect</button>\n            }\n            \n            <span class=\"input-group-text ps-4\">Theme</span>\n            <select class=\"form-select\" id=\"themeStyleSelect\" name=\"themeStyle\" [(ngModel)]=\"state().theme\">\n                @for (rate of themeStyles; track rate) {\n                    <option [value]=\"rate\">{{ rate }}</option>\n                }\n            </select>\n \n            <span class=\"input-group-text ps-4\">Baud Rate</span>\n            <select class=\"form-select\" id=\"baudRateSelect\" name=\"baudRate\" [(ngModel)]=\"state().baudRate\">\n                @for (rate of baudRates; track rate) {\n                    <option [value]=\"rate\">{{ rate }}</option>\n                }\n            </select>\n            <button class=\"btn btn-outline-secondary\"  (click)=\"clear()\" tooltip=\"Clear History\">\n                Clear\n            </button>\n        </div>\n\n        \n        <div class=\"card-body serial-out\" #scrollSerialContainer>\n            <pre class=\"serial-out-text\">{{ consoleOutput() }}</pre>\n        </div>\n \n        <div class=\"input-group input-group-sm mt-3\">\n            <input [(ngModel)]=\"state().currentInput\" (keyup.enter)=\"send()\" [disabled]=\"!this.connState.writer\"\n            type=\"text\" class=\"form-control\" placeholder=\"Send Text Message\" aria-label=\"Serial Input\">\n            <button class=\"btn btn-outline-secondary\" (click)=\"clearInput()\" tooltip=\"Clear Input\">\n                Clear\n            </button>\n            <button class=\"btn btn-outline-secondary\" (click)=\"send()\" tooltip=\"Send Input\">\n                Send\n            </button>\n        </div>\n\n        \n    </div>\n} @else {\n    <div class=\"alert alert-info\" role=\"alert\">\n        <i class=\"fa-solid fa-triangle-exclamation\"></i> Your browser does not support serial port access.<br/>\n        This feature is only available on chromium based browsers.<br/>\n        Please use one the below browsers to access this feature.<br/>\n        eg: Google Chrome, Opera, Edge<br/>\n        <a href=\"https://caniuse.com/?search=usb\" target=\"_blank\">Browser support</a>\n    </div>\n}\n\n","/*\n * Public API Surface of ngx-serial-console\n */\n\nexport * from './lib/ngx-serial-console';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}