{"version":3,"file":"index.mjs","names":["#timeouts","debug","debug","Buffer"],"sources":["../src/Packet.ts","../src/Request.ts","../src/Session.ts","../src/ConnectionClosedError.ts","../src/NovastarDecoder.ts","../src/NovastarEncoder.ts","../src/ResponseError.ts","../src/TimeoutError.ts","../src/helper.ts","../src/Connection.ts","../src/index.ts"],"sourcesContent":["// noinspection JSUnusedGlobalSymbols\n\nimport { ExtractType, Struct, typed } from 'typed-struct';\n\n/**\n * Destination device type\n */\nexport enum DeviceType {\n  /**\n   * Devices connected to the COM/USB port\n   */\n  SendingCard,\n  ReceivingCard,\n  FunctionCard,\n}\n\n/**\n * I/O operation type\n */\nexport enum IO {\n  Read,\n  Write,\n}\n\n/**\n * Operation result code\n */\nexport enum ErrorType {\n  Succeeded,\n  Timeout,\n  RequestCRCError,\n  ResponseCRCError,\n  UnknownCommand,\n  Invalid = 255,\n}\n\n/*\nexport enum DisplayMode {\n  Video,\n  Red = 2,\n  Green,\n  Blue,\n  White,\n  HorizonLine,\n  VerticalLine,\n  InclineLine,\n  Grayscale,\n  Loop,\n}\n\nexport enum Calibration {\n  Color,\n  Brightness,\n}\n*/\n\n/**\n * Request header\n */\nexport const REQUEST = 0xaa55;\n\n/**\n * Response header\n */\nexport const RESPONSE = 0x55aa;\n\n/**\n * For a request, this is the source (sender) address; for a response, the destination address\n */\nexport const COMPUTER = 0xfe;\n\n/**\n * Constructor for creating and processing binary packages used when communicating with novastar devices\n * @see {@link Packet}\n * @see {@link https://sarakusha.github.io/typed-struct/interfaces/StructConstructor.html}\n */\nexport const Packet = new Struct('Packet')\n  .UInt16LE('head', typed<typeof REQUEST | typeof RESPONSE>())\n  .UInt8('ack', typed<ErrorType>())\n  .UInt8('serno')\n  .UInt8('source')\n  .UInt8('destination')\n  .UInt8('deviceType')\n  .UInt8('port')\n  .UInt16LE('rcvIndex')\n  .UInt8('io', typed<IO>())\n  .seek(1)\n  .UInt32LE('address')\n  .UInt16LE('length')\n  .Buffer('data')\n  .CRC16LE('crc', {\n    calc: (raw) => raw.reduce((crc, val) => (crc + val) % 0x10000, 0x5555),\n    start: 2,\n  })\n  .compile();\n\n/**\n * @typedef Packet\n * @property head - [REQUEST](#REQUEST) - for requests and [RESPONSE](#RESPONSE) for responses\n * @property ack - always `0` for request and result code for response\n * @property serno - sequential number of the request, and the corresponding response (set automatically)\n * @property source - source address, always [COMPUTER](#COMPUTER) for request\n * @property destination - destination address, usually `0` for request\n * @property deviceType - target device type\n * @property port - port number\n * @property rcvIndex - receiving card index\n * @property io - I/O operation type\n * @property address - register unit address\n * @property length - length of data requested when reading or length of data sent when writing\n * @property data - data sent on write or empty buffer on read\n * @property crc - cyclic redundancy check\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface Packet extends ExtractType<typeof Packet, false> {}\n\n/**\n * [[Packet]] type guard\n * @param packet\n */\nexport function isPacket(packet: unknown): packet is Packet {\n  return packet instanceof Packet;\n}\n","import { COMPUTER, IO, isPacket, Packet, REQUEST } from './Packet';\n\nconst isLikeNumberArray = (value: unknown): value is ReadonlyArray<number> | Buffer =>\n  Buffer.isBuffer(value) ||\n  (Array.isArray(value) && (value.length === 0 || typeof value[0] === 'number'));\n\nconst createArgs = (\n  param: Packet | Buffer | ReadonlyArray<number> | number,\n): [Buffer, true | undefined] => {\n  if (isPacket(param)) return [Packet.raw(param), true];\n  const raw = Buffer.alloc(Packet.baseSize + (isLikeNumberArray(param) ? param.length : 0));\n  return [raw, undefined];\n};\n\nconst dataOffset = Packet.getOffsetOf('data');\n\n/**\n * Custom request prepared for sending to Novastar devices\n */\nexport default class Request<Broadcast extends boolean = false> extends Packet {\n  private static counter = 0;\n\n  /**\n   * If this is true, then do not wait for a response from the device\n   */\n  readonly broadcast?: Broadcast;\n\n  /**\n   * Overriding the timeout for this request\n   */\n  timeout?: number;\n\n  /**\n   * Overriding the maximum data length for this request\n   */\n  maxLength?: number;\n\n  /**\n   * Preserves the size of the original request if it exceeds 65535.\n   */\n  readonly originalLength?: number;\n\n  /**\n   * For debugging and describing exceptions\n   */\n  readonly tag?: string;\n\n  /**\n   * @internal\n   * Copy constructor\n   * @param other\n   * @param broadcast\n   * @param tag\n   */\n  constructor(other: Packet, broadcast?: Broadcast, tag?: string);\n\n  /**\n   * Create a read request\n   * @param readLength - requested data length\n   * @param tag - description\n   */\n  constructor(readLength: number, tag?: string);\n\n  /**\n   * Create a write request. If `broadcast` is true, then do not wait for a response from the device\n   * @param writeData - data to send\n   * @param broadcast\n   * @param tag description\n   */\n  constructor(writeData: Buffer | ReadonlyArray<number>, broadcast?: Broadcast, tag?: string);\n\n  constructor(writeData: Buffer | ReadonlyArray<number>, tag: string);\n\n  constructor(\n    param: Packet | Buffer | ReadonlyArray<number> | number,\n    param2?: Broadcast | string,\n    param3?: string,\n  ) {\n    super(...createArgs(param));\n    const broadcast = typeof param2 === 'boolean' ? param2 : undefined;\n    this.tag = typeof param2 === 'string' ? param2 : param3;\n    if (!isPacket(param)) {\n      this.head = REQUEST;\n      this.source = COMPUTER;\n      this.broadcast = broadcast;\n\n      if (isLikeNumberArray(param)) {\n        this.io = IO.Write;\n        Buffer.from(param).copy(this.data);\n        this.length = param.length;\n        this.originalLength = param.length;\n      } else {\n        this.io = IO.Read;\n        this.length = param;\n        this.originalLength = param;\n      }\n    } else if (param instanceof Request) {\n      this.broadcast = param.broadcast;\n      this.timeout = param.timeout;\n      this.maxLength = param.maxLength;\n      this.originalLength = param.originalLength;\n      this.tag = param.tag;\n    }\n    this.serno = Request.next();\n  }\n\n  /**\n   * Split the original request into chunks with the specified maximum data length\n   * @param req - original request\n   * @param maxLength - maximum data length\n   * @returns - chunks\n   */\n  static makeChunks<Broadcast extends boolean = false>(\n    req: Request<Broadcast>,\n    maxLength = 256,\n  ): Request<Broadcast>[] {\n    if (maxLength <= 0) throw new TypeError(`Invalid maxLength: ${maxLength}`);\n    const total = req.originalLength ?? req.length; // req.data.length;\n    const count = Math.ceil(total / maxLength) || 1;\n    if (count === 1) return [req];\n    const raw = Packet.raw(req);\n    return [...new Array(count)].map((_, i) => {\n      const start = i * maxLength;\n      const length = Math.min(total - start, maxLength);\n      const bufSize = Packet.baseSize + (req.io === IO.Write ? length : 0);\n      const buffer = Buffer.alloc(bufSize);\n      raw.copy(buffer, 0, 0, dataOffset);\n      if (req.io === IO.Write) {\n        req.data.copy(buffer, dataOffset, start, start + length);\n      }\n      const chunk = new Request(\n        new Packet(buffer),\n        req.broadcast,\n        req.tag && `${req.tag}:${i}`,\n      ) as Request<Broadcast>;\n      chunk.timeout = req.timeout;\n      chunk.maxLength = maxLength;\n      chunk.address += start;\n      chunk.length = length;\n      return chunk;\n    });\n  }\n\n  private static next(): number {\n    Request.counter = (Request.counter + 1) % 256;\n    return Request.counter;\n  }\n}\n\nexport const isNotBroadcast = (req: Request<boolean>): req is Request => !req.broadcast;\n","import { Duplex } from 'stream';\n\nimport Connection from './Connection';\n\n/**\n * Base implementation of the extensible `Session` class\n */\nexport interface Session<S extends Duplex = Duplex> {\n  /**\n   * Current connection to interact with the device\n   */\n  readonly connection: Connection<S>;\n\n  /**\n   * Is current [connection]{@link Session.connection} active\n   */\n  readonly isConnected: boolean;\n\n  /**\n   * Change the current timeout keeping the previous value\n   * @param timeout\n   */\n  pushTimeout(timeout: number): void;\n\n  /**\n   * Restore previous timeout value\n   */\n  popTimeout(): number;\n\n  /**\n   * Close current connection\n   */\n  close(): boolean;\n}\n\n/**\n * API extensible via plugins from @novastar/gen.\n * @remarks Original API contains more than a thousand methods, and you won't need all of\n * them, so you just include the methods you need, and they will be embedded into your `Session`\n * instance\n */\nexport interface API {\n  readonly version: '2.0';\n}\n\nexport interface SessionStatic {\n  new <S extends Duplex>(connection: Connection<S>): Session<S> & API;\n}\n\nclass SessionImpl<S extends Duplex> implements Session<S> {\n  // eslint-disable-next-line no-empty-function\n  constructor(readonly connection: Connection<S>) {}\n\n  get isConnected(): boolean {\n    return this.connection.isConnected;\n  }\n\n  readonly version = '2.0';\n\n  close(): boolean {\n    if (!this.connection.isConnected) return false;\n    this.connection.close();\n    return true;\n  }\n\n  pushTimeout(timeout: number): void {\n    if (timeout <= 0) throw new TypeError('Invalid timeout');\n    this.#timeouts.push(this.connection.timeout);\n    this.connection.timeout = timeout;\n  }\n\n  popTimeout(): number {\n    const timeout = this.#timeouts.pop();\n    if (timeout) {\n      this.connection.timeout = timeout;\n    }\n    return timeout ?? this.connection.timeout;\n  }\n\n  #timeouts: number[] = [];\n}\n\n/**\n * Session\n */\nexport const Session: SessionStatic = SessionImpl;\n","export default class ConnectionClosedError extends Error {\n  constructor() {\n    super('Connection closed');\n  }\n}\n","/* eslint-disable no-underscore-dangle,no-bitwise */\nimport { Transform, TransformCallback, TransformOptions } from 'stream';\n\nimport debugFactory from 'debug';\n\nimport { COMPUTER, Packet, RESPONSE } from './Packet';\n\nconst debug = debugFactory('novastar:decoder');\n\nconst empty = Buffer.alloc(0);\n\nconst preamble = Buffer.from([RESPONSE % 256, RESPONSE >>> 8]);\n\nconst lengthOffset = Packet.getOffsetOf('length');\n\nexport default class NovastarDecoder extends Transform {\n  private buf: Buffer = empty;\n\n  private last: Packet[] = [];\n\n  constructor(options?: TransformOptions) {\n    super({\n      ...options,\n      readableObjectMode: true,\n    });\n  }\n\n  public _transform(chunk: unknown, encoding: BufferEncoding, callback: TransformCallback) {\n    if (Buffer.isBuffer(chunk)) {\n      const data = Buffer.concat([this.buf, chunk]);\n      if (data.length >= preamble.length) {\n        this.buf = this.recognize(data);\n      }\n\n      if (this.last.length > 0) debug(`>>> [${this.last.map((pkg) => pkg.serno).join(', ')}]`);\n      this.last.length = 0;\n    }\n    callback();\n  }\n\n  _flush(callback: TransformCallback) {\n    this.buf = empty;\n    callback();\n  }\n\n  private recognize(data: Buffer): Buffer {\n    for (let offset = 0; ; ) {\n      const rest = data.length - offset;\n      if (rest <= 0) return empty;\n      const start = data.indexOf(\n        rest < preamble.length ? preamble.slice(0, rest) : preamble,\n        offset,\n      );\n      if (start === -1) return empty;\n      const frame = data.slice(start);\n      if (frame.length < Packet.baseSize) return frame;\n      const length = frame.readUInt16LE(lengthOffset);\n      const total = length + Packet.baseSize;\n      if (frame.length < total) return frame;\n      const pkg = new Packet(frame.slice(0, total));\n      if (Packet.crc(pkg) === pkg.crc) {\n        if (pkg.destination === COMPUTER) {\n          this.push(pkg);\n          this.last.push(pkg);\n        }\n        offset = start + total;\n      }\n      if (offset <= start) {\n        offset = start + 1;\n      }\n    }\n  }\n}\n","/* eslint-disable no-underscore-dangle */\nimport { Transform, TransformCallback, TransformOptions } from 'stream';\n\nimport debugFactory from 'debug';\n\nimport Request from './Request';\n\nconst debug = debugFactory('novastar:encoder');\n\nexport default class NovastarEncoder extends Transform {\n  constructor(options?: TransformOptions) {\n    super({\n      ...options,\n      writableObjectMode: true,\n    });\n  }\n\n  public _transform(chunk: unknown, encoding: BufferEncoding, callback: TransformCallback): void {\n    const chunks = Array.isArray(chunk) ? chunk : [chunk];\n    chunks.forEach((pkg) => {\n      if (pkg instanceof Request) {\n        Request.crc(pkg, true);\n        const raw = Request.raw(pkg);\n        debug(`<<< [${pkg.serno}:${pkg.tag ?? ''}]`);\n        this.push(raw);\n      }\n    });\n    callback();\n  }\n}\n","import { ErrorType, Packet } from './Packet';\n\n/**\n * Response error\n */\nexport default class ResponseError extends Error {\n  /**\n   * Constructor\n   * @param res - response\n   * @param tag - description\n   */\n  constructor(\n    readonly res: Readonly<Packet>,\n    readonly tag?: string,\n  ) {\n    super(\n      `Request #${res.serno}${tag ? ` [${tag}:${res.source}.${res.port}.${res.rcvIndex}]` : ''} failed with <${ErrorType[res.ack]}>`,\n    );\n  }\n}\n","import { Packet } from './Packet';\n\nexport default class TimeoutError extends Error {\n  constructor(\n    readonly req: Packet,\n    readonly tag?: string,\n  ) {\n    super(\n      `No response was received for the #${req.serno}${tag ? ` [${tag}:${req.destination}.${req.port}.${req.rcvIndex}]` : ''} request.`,\n    );\n  }\n}\n","export type ArrayLike = unknown[] | Buffer | string;\n\n/**\n * Split array/buffer/string into chunks\n * @param array - source array\n * @param len - chunk size\n */\nfunction chunkArray<T extends ArrayLike>(array: T, len: number): T[] {\n  const ret: T[] = [];\n  const size = Math.ceil(array.length / len);\n  ret.length = size;\n  let offset;\n\n  for (let i = 0; i < size; i += 1) {\n    offset = i * len;\n    ret[i] = array.slice(offset, offset + len) as T;\n  }\n\n  return ret;\n}\n\n/**\n * Buffer formatting\n * @param buffer\n */\nexport function printBuffer(buffer: Buffer): string {\n  return chunkArray(chunkArray(buffer.toString('hex'), 2), 16)\n    .map((chunk) => chunk.join('-'))\n    .join('=');\n}\n\n/**\n * Create a promise which resolves after the specified milliseconds.\n * @param ms\n */\nexport const delay = (ms: number): Promise<void> =>\n  new Promise<void>((resolve) => {\n    setTimeout(resolve, ms);\n  });\n\n/**\n * Performs an asynchronous operation sequentially on all elements of an array\n * @param array\n * @param action\n */\nexport function series<T, R>(\n  array: ReadonlyArray<T>,\n  action: (item: T, index: number, arr: ReadonlyArray<T>, results: ReadonlyArray<R>) => Promise<R>,\n): Promise<R[]> {\n  return array.reduce<Promise<R[]>>(\n    (acc, item, index) =>\n      acc.then(async (items) => {\n        const result = await action(item, index, array, items);\n        return [...items, result];\n      }),\n    Promise.resolve<R[]>([]),\n  );\n}\n\n/**\n * 'Not Empty' type guard\n * @param value\n */\nexport function notEmpty<TValue>(value: TValue | null | undefined | void): value is TValue {\n  return (\n    value !== undefined && value !== null && (typeof value !== 'number' || !Number.isNaN(value))\n  );\n}\n","import { Duplex } from 'stream';\n\nimport debugFactory from 'debug';\nimport pump from 'pump';\nimport { TypedEmitter } from 'tiny-typed-emitter';\n\nimport ConnectionClosedError from './ConnectionClosedError';\nimport NovastarDecoder from './NovastarDecoder';\nimport NovastarEncoder from './NovastarEncoder';\nimport { ErrorType, Packet } from './Packet';\nimport Request, { isNotBroadcast } from './Request';\nimport ResponseError from './ResponseError';\nimport TimeoutError from './TimeoutError';\nimport { delay, notEmpty, series } from './helper';\n\ntype ResolveResponse = (res: Packet) => void;\n\ntype WaitingRequest = [req: Request, resolve: ResolveResponse];\n\nexport interface ConnectionEvents {\n  /**\n   * The open event happens when the connection is opened and ready for writing\n   */\n  open(): void;\n  /**\n   * The close event is emitted when the connection is closed.\n   */\n  close(): void;\n}\n\nconst debug = debugFactory('novastar:connection');\n\ntype Result<SkipErrors extends boolean = false> = SkipErrors extends false ? Packet : Packet | null;\n\ntype Response<Broadcast extends boolean, SkipErrors extends boolean = false> = Promise<\n  Broadcast extends false ? Result<SkipErrors> : void\n>;\n\ntype ConnectionParams = {\n  /**\n   * automatically opens this connection, see {@link Connection.open}\n   * @default true\n   */\n  open?: boolean;\n  /**\n   * Default timeout for this connection\n   * @default 1000\n   */\n  timeout?: number;\n  /**\n   * Maximum default data length in single {@link Request} for this connection\n   * @default 256\n   */\n  maxLength?: number;\n  /**\n   * Whether to process requests serially\n   * @default false\n   */\n  serial?: boolean;\n};\n\n/**\n * Wrapper for I/O stream using {@link Request} for out and {@link Packet} to in\n */\nexport default class Connection<S extends Duplex> extends TypedEmitter<ConnectionEvents> {\n  /**\n   * Default timeout for this connection\n   */\n  public timeout = 1000;\n\n  /**\n   * Maximum default data length in single {@link Request} for this connection\n   */\n  public maxLength = 256;\n\n  protected ready = Promise.resolve();\n\n  protected queue: WaitingRequest[] = [];\n\n  private encoder: NovastarEncoder | undefined;\n\n  private decoder: NovastarDecoder | undefined;\n\n  private connected = false;\n\n  protected serial = false;\n\n  /**\n   * Constructor\n   * @param stream - wrapped I/O stream\n   */\n  constructor(\n    readonly stream: S,\n    { open = true, timeout = 1000, maxLength = 256, serial = false }: ConnectionParams = {},\n  ) {\n    super();\n    this.timeout = timeout;\n    this.maxLength = maxLength;\n    this.serial = serial;\n    if (open) this.open();\n  }\n\n  /**\n   * Returns true if the connection is ready for writing.\n   */\n  get isConnected(): boolean {\n    return this.connected;\n  }\n\n  /**\n   * Pipes streams (encoder->stream->decoder) together.\n   * Emits {@link ConnectionEvents.open}\n   */\n  public open(): void {\n    if (this.connected) return;\n    this.decoder = new NovastarDecoder();\n    this.encoder = new NovastarEncoder();\n    this.decoder.on('data', this.listener);\n    pump(this.encoder, this.stream, this.decoder, (err) => {\n      if (err && this.connected) debug(`Error while pump: ${err.message}`);\n      this.close();\n    });\n    this.connected = true;\n    debug('open');\n    this.emit('open');\n  }\n\n  /**\n   * Detaches streams. Emits {@link ConnectionEvents.close}\n   */\n  public close(): void {\n    if (!this.connected) return;\n    this.connected = false;\n    this.decoder?.off('data', this.listener);\n    this.stream.unpipe(this.decoder);\n    this.encoder?.unpipe(this.stream);\n    this.decoder?.destroy();\n    this.decoder = undefined;\n    this.encoder?.destroy();\n    this.encoder = undefined;\n    debug('close');\n    this.emit('close');\n  }\n\n  /**\n   * Decodes the request and sends the raw data to the stream after the previous operation\n   * completes, If the request `length` exceeds the `maxLength`, the request will be split into\n   * multiple requests and responses will be composed.\n   * @param req - request\n   * @returns If the request is not broadcast, then a successful response to the request is\n   * returned. If the response status is not successful or a timeout occurs, an exception is thrown.\n   * @see TimeoutError\n   * @see ResponseError\n   */\n  public send<Broadcast extends boolean>(req: Request<Broadcast>): Response<Broadcast>;\n\n  public send(req: Request<boolean>): Promise<Packet | void> {\n    return new Promise<Packet | void>((resolve, reject) => {\n      // this.ready = this.ready.finally().then(() => {\n      const executeSend = () => {\n        const chunks = Request.makeChunks(req, this.getMaxLength(req));\n        series(chunks, (chunk) => this.sendImpl(chunk))\n          .then((results) => {\n            const responses = results.filter(notEmpty);\n            if (responses.length === 0) return resolve();\n            const [first] = responses;\n            if (responses.length === 1) return resolve(first);\n            const srcRaw = Packet.raw(first);\n            const total = Buffer.concat(responses.map((res) => res.data));\n            const result = new Packet(total.length + Packet.baseSize);\n            srcRaw.copy(Packet.raw(result));\n            // Object.entries(first.toJSON()).forEach(([name, value]) => {\n            //   if (name !== 'data') {\n            //     (result as Record<string, unknown>)[name] = value;\n            //   }\n            // });\n            result.length = total.length;\n            total.copy(result.data);\n            Packet.crc(result, true);\n            return resolve(result);\n          })\n          .catch(reject);\n      };\n      if (this.serial) this.ready = this.ready.finally().then(executeSend);\n      else executeSend();\n      // });\n    });\n  }\n\n  /**\n   * Sends a request, `length` of which does not exceed `maxLength`.\n   * @param req\n   * @returns In case of no response by timeout, returns null. Don't forget to check the `ack`\n   * status of a response packet.\n   */\n  public trySend(req: Request): Promise<Packet | null> {\n    return new Promise<Packet | null>((resolve, reject) => {\n      this.ready = this.ready.finally().then(() => this.sendImpl(req, true).then(resolve, reject));\n    });\n  }\n\n  protected sendImpl<Broadcast extends boolean, SkipErrors extends boolean = false>(\n    req: Request<Broadcast>,\n    skipError?: SkipErrors,\n  ): Response<Broadcast, SkipErrors>;\n\n  protected async sendImpl(\n    req: Request<boolean>,\n    skipErrors?: boolean,\n  ): Promise<Packet | null | void> {\n    const { connected, encoder } = this;\n    if (!connected || !encoder) throw new ConnectionClosedError();\n    const maxLength = this.getMaxLength(req);\n    if (req.length > maxLength)\n      throw new TypeError(\n        `The request size is too large. Use \"send\" instead of \"trySend\", maxLength: ${maxLength}`,\n      );\n    if (!encoder.write(req)) {\n      await new Promise<void>((resolve) => {\n        encoder.once('drain', resolve);\n      });\n    }\n    if (isNotBroadcast(req)) {\n      const res = await this.wait(req, skipErrors);\n      if (!skipErrors && res && res.ack !== ErrorType.Succeeded) {\n        const err = new ResponseError(res, req.tag);\n        debug(err.message);\n        throw err;\n      }\n      return res;\n    }\n    return delay(50);\n  }\n\n  protected wait<SkipErrors extends boolean = false>(\n    req: Request,\n    skipErrors?: SkipErrors,\n  ): Promise<Result<SkipErrors>>;\n\n  protected wait(req: Request, skipErrors?: boolean): Promise<Packet | null> {\n    return new Promise<Packet | null>((resolve, reject) => {\n      let timer: NodeJS.Timeout;\n      const complete = (): void => {\n        clearTimeout(timer);\n        this.queue = this.queue.filter(([request]) => req !== request);\n      };\n      const rejectTimeout = (): void => {\n        complete();\n        if (skipErrors) return resolve(null);\n        const err = new TimeoutError(req, req.tag);\n        debug(err.message);\n        return reject(err);\n      };\n      const resolveResponse: ResolveResponse = (res) => {\n        complete();\n        resolve(res);\n      };\n      timer = global.setTimeout(rejectTimeout, req.timeout ?? this.timeout);\n      this.queue.push([req, resolveResponse]);\n    });\n  }\n\n  protected listener = (res: Packet): void => {\n    const [, resolve] = this.queue.find(([req]) => req.serno === res.serno) ?? [];\n    if (resolve) resolve(res);\n    else if (res.source !== 255 && res.ack !== ErrorType.Timeout) {\n      debug(`Unknown package ${JSON.stringify(res)}`);\n    }\n  };\n\n  protected getMaxLength(req: Request<boolean>): number {\n    return req.maxLength || this.maxLength || 256;\n  }\n}\n","import { Buffer } from 'buffer';\nimport { Packet } from './Packet';\n\nexport * from './Packet';\nexport { default as Request } from './Request';\nexport * from './Session';\nexport { default as Connection } from './Connection';\nexport type { ConnectionEvents } from './Connection';\nexport { default as ResponseError } from './ResponseError';\nexport { default as TimeoutError } from './TimeoutError';\nexport { default as ConnectionClosedError } from './ConnectionClosedError';\nexport * from './helper';\n\n/**\n * Converts a `data` property of type `Buffer` of length 1, 2, or 4 bytes to an unsigned integer.\n * @param data - Buffer 1, 2 or 4 bytes long to convert\n */\nexport const decodeUIntLE = ({ data }: Packet): number => {\n  switch (data.length) {\n    case 1:\n      return data.readUInt8();\n    case 2:\n      return data.readUInt16LE();\n    case 4:\n      return data.readUInt32LE();\n    default:\n      throw new TypeError(`Invalid buffer length: ${data.length}`);\n  }\n};\n\n/**\n * Stores a non-negative number in a buffer of the specified length\n * @param value - Non-negative integer\n * @param size - Buffer size (1, 2, 4 bytes)\n */\nexport const encodeUIntLE = (value: number, size: number): Buffer => {\n  const buffer = Buffer.alloc(size);\n  switch (size) {\n    case 1:\n      buffer.writeUInt8(value);\n      break;\n    case 2:\n      buffer.writeUInt16LE(value);\n      break;\n    case 4:\n      buffer.writeUInt32LE(value);\n      break;\n    default:\n      throw new TypeError(`Invalid buffer size: ${size}`);\n  }\n  return buffer;\n};\n"],"mappings":"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"}