tci-client-node 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +130 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -4
- package/dist/index.d.ts +22 -4
- package/dist/index.js +130 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -624,7 +624,11 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
624
624
|
trx: options.trx ?? 0,
|
|
625
625
|
vfo: options.vfo ?? 0,
|
|
626
626
|
connectTimeoutMs: options.connectTimeoutMs ?? 5e3,
|
|
627
|
-
commandTimeoutMs: options.commandTimeoutMs ?? 1e3
|
|
627
|
+
commandTimeoutMs: options.commandTimeoutMs ?? 1e3,
|
|
628
|
+
writeAckMode: options.writeAckMode ?? "state",
|
|
629
|
+
writeTimeoutMs: options.writeTimeoutMs ?? 3e3,
|
|
630
|
+
writeSettleMs: options.writeSettleMs ?? 0,
|
|
631
|
+
frequencyWriteSettleMs: options.frequencyWriteSettleMs ?? 250
|
|
628
632
|
};
|
|
629
633
|
this.WebSocketImpl = options.WebSocketImpl ?? import_ws.default;
|
|
630
634
|
this.queue = new TciCommandQueue({
|
|
@@ -710,15 +714,55 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
710
714
|
}
|
|
711
715
|
return reply;
|
|
712
716
|
}
|
|
713
|
-
async
|
|
714
|
-
|
|
717
|
+
async sendStateWrite(name, args, isApplied, description = formatTciCommand(name, args).replace(/;$/, ""), options = {}) {
|
|
718
|
+
const ackMode = options.ackMode ?? this.options.writeAckMode;
|
|
719
|
+
if (ackMode === "reply") {
|
|
720
|
+
await this.sendCommand(name, args, { timeoutMs: options.timeoutMs });
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
if (isApplied(this.getState())) {
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
if (ackMode === "optimistic") {
|
|
727
|
+
await this.sendCommand(name, args, { waitForReply: false });
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const timeoutMs = options.timeoutMs ?? this.options.writeTimeoutMs;
|
|
731
|
+
const settleMs = options.settleMs ?? this.options.writeSettleMs;
|
|
732
|
+
const waiter = this.waitForState(isApplied, timeoutMs, settleMs, description);
|
|
733
|
+
try {
|
|
734
|
+
await this.sendCommand(name, args, { waitForReply: false });
|
|
735
|
+
await waiter.promise;
|
|
736
|
+
} catch (error) {
|
|
737
|
+
waiter.cancel();
|
|
738
|
+
throw error;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
async setFrequency(frequencyHz, receiver = this.options.receiver, vfo = this.options.vfo, options = {}) {
|
|
742
|
+
const frequency = Math.round(frequencyHz);
|
|
743
|
+
const key = rxVfoKey(receiver, vfo);
|
|
744
|
+
await this.sendStateWrite(
|
|
745
|
+
"VFO",
|
|
746
|
+
[receiver, vfo, frequency],
|
|
747
|
+
(state) => state.frequencies[key] === frequency,
|
|
748
|
+
`VFO:${receiver},${vfo},${frequency}`,
|
|
749
|
+
{ settleMs: this.options.frequencyWriteSettleMs, ...options }
|
|
750
|
+
);
|
|
715
751
|
}
|
|
716
752
|
async getFrequency(receiver = this.options.receiver, vfo = this.options.vfo) {
|
|
717
753
|
const reply = await this.request("VFO", [receiver, vfo]);
|
|
718
754
|
return parseNumber(reply.args[2]) ?? this.state.frequencies[rxVfoKey(receiver, vfo)];
|
|
719
755
|
}
|
|
720
|
-
async setMode(mode, receiver = this.options.receiver) {
|
|
721
|
-
|
|
756
|
+
async setMode(mode, receiver = this.options.receiver, options = {}) {
|
|
757
|
+
const normalizedMode = mode.toUpperCase();
|
|
758
|
+
const key = rxVfoKey(receiver, this.options.vfo);
|
|
759
|
+
await this.sendStateWrite(
|
|
760
|
+
"MODULATION",
|
|
761
|
+
[receiver, normalizedMode],
|
|
762
|
+
(state) => state.modes[key]?.toLowerCase() === normalizedMode.toLowerCase(),
|
|
763
|
+
`MODULATION:${receiver},${normalizedMode}`,
|
|
764
|
+
options
|
|
765
|
+
);
|
|
722
766
|
}
|
|
723
767
|
async getMode(receiver = this.options.receiver) {
|
|
724
768
|
const reply = await this.request("MODULATION", [receiver]);
|
|
@@ -728,7 +772,13 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
728
772
|
async setPtt(enabled, options = {}) {
|
|
729
773
|
const trx = options.trx ?? this.options.trx;
|
|
730
774
|
const args = options.source ? [trx, enabled, options.source] : [trx, enabled];
|
|
731
|
-
await this.
|
|
775
|
+
await this.sendStateWrite(
|
|
776
|
+
"TRX",
|
|
777
|
+
args,
|
|
778
|
+
(state) => state.ptt[String(trx)] === enabled,
|
|
779
|
+
`TRX:${trx},${enabled}`,
|
|
780
|
+
options
|
|
781
|
+
);
|
|
732
782
|
}
|
|
733
783
|
async getPtt(trx = this.options.trx) {
|
|
734
784
|
const reply = await this.request("TRX", [trx]);
|
|
@@ -797,6 +847,75 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
797
847
|
async stopCw() {
|
|
798
848
|
await this.sendCommand("CW_MACROS_STOP");
|
|
799
849
|
}
|
|
850
|
+
waitForState(predicate, timeoutMs, settleMs, description) {
|
|
851
|
+
let timeout;
|
|
852
|
+
let settleTimeout;
|
|
853
|
+
let resolved = false;
|
|
854
|
+
let resolvePromise;
|
|
855
|
+
let rejectPromise;
|
|
856
|
+
const cleanup = () => {
|
|
857
|
+
if (timeout) {
|
|
858
|
+
clearTimeout(timeout);
|
|
859
|
+
timeout = void 0;
|
|
860
|
+
}
|
|
861
|
+
if (settleTimeout) {
|
|
862
|
+
clearTimeout(settleTimeout);
|
|
863
|
+
settleTimeout = void 0;
|
|
864
|
+
}
|
|
865
|
+
this.off("state", onState);
|
|
866
|
+
this.off("disconnected", onDisconnected);
|
|
867
|
+
};
|
|
868
|
+
const resolveNow = () => {
|
|
869
|
+
resolved = true;
|
|
870
|
+
cleanup();
|
|
871
|
+
resolvePromise();
|
|
872
|
+
};
|
|
873
|
+
const check = () => {
|
|
874
|
+
if (!predicate(this.getState())) {
|
|
875
|
+
if (settleTimeout) {
|
|
876
|
+
clearTimeout(settleTimeout);
|
|
877
|
+
settleTimeout = void 0;
|
|
878
|
+
}
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (settleMs <= 0) {
|
|
882
|
+
resolveNow();
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
if (settleTimeout) {
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
settleTimeout = setTimeout(() => {
|
|
889
|
+
settleTimeout = void 0;
|
|
890
|
+
if (predicate(this.getState())) {
|
|
891
|
+
resolveNow();
|
|
892
|
+
}
|
|
893
|
+
}, settleMs);
|
|
894
|
+
};
|
|
895
|
+
const onState = () => check();
|
|
896
|
+
const onDisconnected = () => {
|
|
897
|
+
if (resolved) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
cleanup();
|
|
901
|
+
rejectPromise(new TciError("disconnected", `Disconnected while waiting for TCI state ${description}`));
|
|
902
|
+
};
|
|
903
|
+
const promise = new Promise((resolve, reject) => {
|
|
904
|
+
resolvePromise = resolve;
|
|
905
|
+
rejectPromise = reject;
|
|
906
|
+
timeout = setTimeout(() => {
|
|
907
|
+
cleanup();
|
|
908
|
+
reject(new TciError("command-timeout", `Timed out waiting for TCI state ${description}`));
|
|
909
|
+
}, timeoutMs);
|
|
910
|
+
this.on("state", onState);
|
|
911
|
+
this.on("disconnected", onDisconnected);
|
|
912
|
+
check();
|
|
913
|
+
});
|
|
914
|
+
return {
|
|
915
|
+
promise,
|
|
916
|
+
cancel: cleanup
|
|
917
|
+
};
|
|
918
|
+
}
|
|
800
919
|
waitForOpen(ws) {
|
|
801
920
|
return new Promise((resolve, reject) => {
|
|
802
921
|
const timer = setTimeout(() => {
|
|
@@ -847,6 +966,7 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
847
966
|
if (!ws || ws.readyState !== import_ws.default.OPEN) {
|
|
848
967
|
throw new TciError("not-connected", "TCI socket is not connected");
|
|
849
968
|
}
|
|
969
|
+
this.emit("tci:tx", raw);
|
|
850
970
|
await new Promise((resolve, reject) => {
|
|
851
971
|
ws.send(raw, (error) => error ? reject(error) : resolve());
|
|
852
972
|
});
|
|
@@ -864,7 +984,9 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
864
984
|
this.handleBinary(data);
|
|
865
985
|
return;
|
|
866
986
|
}
|
|
867
|
-
const
|
|
987
|
+
const raw = dataToBuffer(data).toString("utf8");
|
|
988
|
+
const commands = parseTciText(raw);
|
|
989
|
+
this.emit("tci:rx", raw, commands);
|
|
868
990
|
for (const command of commands) {
|
|
869
991
|
this.queue.handleCommand(command);
|
|
870
992
|
this.applyCommand(command);
|
|
@@ -876,6 +998,7 @@ var TciClient = class extends import_eventemitter3.EventEmitter {
|
|
|
876
998
|
}
|
|
877
999
|
handleBinary(data) {
|
|
878
1000
|
const frame = parseStreamFrame(dataToBuffer(data));
|
|
1001
|
+
this.emit("tci:binary", frame);
|
|
879
1002
|
this.emit("binary", frame);
|
|
880
1003
|
switch (frame.streamType) {
|
|
881
1004
|
case 1 /* RX_AUDIO_STREAM */:
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client/TciClient.ts","../src/audio/streamFrame.ts","../src/protocol/text.ts","../src/protocol/commandQueue.ts"],"sourcesContent":["export * from './errors.js';\nexport * from './client/TciClient.js';\nexport * from './protocol/index.js';\nexport * from './audio/index.js';\n","export type TciErrorCode =\n | 'connect-timeout'\n | 'command-timeout'\n | 'not-connected'\n | 'disconnected'\n | 'protocol-error'\n | 'invalid-frame'\n | 'cancelled';\n\nexport class TciError extends Error {\n readonly code: TciErrorCode;\n readonly details?: unknown;\n\n constructor(code: TciErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TciError';\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toTciError(error: unknown, fallbackCode: TciErrorCode = 'protocol-error'): TciError {\n if (error instanceof TciError) {\n return error;\n }\n if (error instanceof Error) {\n return new TciError(fallbackCode, error.message, error);\n }\n return new TciError(fallbackCode, String(error), error);\n}\n","import { EventEmitter } from 'eventemitter3';\nimport WebSocket from 'ws';\nimport { TciError, toTciError } from '../errors.js';\nimport {\n buildTxAudioFrame,\n normalizeSampleType,\n parseStreamFrame,\n sampleTypeName,\n TciSampleType,\n TciStreamType,\n type BuildTxAudioFrameOptions,\n type TciSampleTypeName,\n type TciStreamFrame,\n} from '../audio/streamFrame.js';\nimport {\n formatTciCommand,\n parseTciText,\n TciCommandQueue,\n type QueueCommandOptions,\n type TciCommand,\n} from '../protocol/index.js';\n\nexport interface TciClientOptions {\n url: string;\n receiver?: number;\n trx?: number;\n vfo?: number;\n connectTimeoutMs?: number;\n commandTimeoutMs?: number;\n WebSocketImpl?: typeof WebSocket;\n}\n\nexport interface TciAudioConfig {\n sampleRate: 8_000 | 12_000 | 24_000 | 48_000 | number;\n sampleType?: TciSampleType | TciSampleTypeName;\n channels?: 1 | 2 | number;\n samplesPerFrame?: number;\n txBufferingMs?: number;\n}\n\nexport interface TciPttOptions {\n source?: 'tci' | 'mic1' | 'mic2' | 'micpc' | 'ecoder2' | string;\n trx?: number;\n}\n\nexport interface TciTxChronoRequest {\n frame: TciStreamFrame;\n receiver: number;\n sampleRate: number;\n channels: number;\n sampleType: TciSampleType;\n sampleCount: number;\n}\n\nexport interface TciClientState {\n connected: boolean;\n ready: boolean;\n protocol?: string;\n device?: string;\n receiveOnly?: boolean;\n trxCount?: number;\n channelCount?: number;\n vfoLimits?: [number, number];\n ifLimits?: [number, number];\n modulations: string[];\n frequencies: Record<string, number>;\n modes: Record<string, string>;\n ptt: Record<string, boolean>;\n pttSource: Record<string, string | undefined>;\n tune: Record<string, boolean>;\n drive: Record<string, number>;\n split: Record<string, boolean>;\n rxSensors: Record<string, Record<string, number | string | boolean>>;\n txSensors: Record<string, Record<string, number | string | boolean>>;\n audio?: Required<Pick<TciAudioConfig, 'sampleRate' | 'channels' | 'sampleType' | 'samplesPerFrame'>> & {\n txBufferingMs?: number;\n running: boolean;\n };\n}\n\nexport interface TciClientEvents {\n connected: () => void;\n disconnected: (reason?: unknown) => void;\n ready: (state: TciClientState) => void;\n state: (state: TciClientState) => void;\n command: (command: TciCommand) => void;\n binary: (frame: TciStreamFrame) => void;\n rxAudioFrame: (frame: TciStreamFrame) => void;\n lineoutAudioFrame: (frame: TciStreamFrame) => void;\n txChrono: (request: TciTxChronoRequest) => void;\n error: (error: TciError) => void;\n}\n\nexport interface SendCommandOptions extends QueueCommandOptions {\n waitForReply?: boolean;\n}\n\nexport class TciClient extends EventEmitter<TciClientEvents> {\n readonly options: Required<Pick<TciClientOptions, 'receiver' | 'trx' | 'vfo' | 'connectTimeoutMs' | 'commandTimeoutMs'>> &\n Pick<TciClientOptions, 'url'>;\n\n private readonly WebSocketImpl: typeof WebSocket;\n private ws?: WebSocket;\n private readonly queue: TciCommandQueue;\n private readonly state: TciClientState;\n\n constructor(options: TciClientOptions) {\n super();\n this.options = {\n url: options.url,\n receiver: options.receiver ?? 0,\n trx: options.trx ?? 0,\n vfo: options.vfo ?? 0,\n connectTimeoutMs: options.connectTimeoutMs ?? 5_000,\n commandTimeoutMs: options.commandTimeoutMs ?? 1_000,\n };\n this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;\n this.queue = new TciCommandQueue({\n timeoutMs: this.options.commandTimeoutMs,\n send: (raw) => this.sendRaw(raw),\n });\n this.queue.setConnected(false);\n this.state = {\n connected: false,\n ready: false,\n modulations: [],\n frequencies: {},\n modes: {},\n ptt: {},\n pttSource: {},\n tune: {},\n drive: {},\n split: {},\n rxSensors: {},\n txSensors: {},\n };\n }\n\n async connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {\n await this.waitForOpen(this.ws);\n return;\n }\n\n const ws = new this.WebSocketImpl(this.options.url);\n this.ws = ws;\n await this.waitForOpen(ws);\n }\n\n async disconnect(code = 1000, reason = 'client disconnect'): Promise<void> {\n const ws = this.ws;\n if (!ws) {\n return;\n }\n if (ws.readyState === WebSocket.CLOSED) {\n this.handleClose();\n return;\n }\n await new Promise<void>((resolve) => {\n const cleanup = () => {\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onClose = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n resolve();\n };\n ws.once('close', onClose);\n ws.once('error', onError);\n ws.close(code, reason);\n setTimeout(() => resolve(), 1_000).unref?.();\n });\n this.handleClose();\n }\n\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n getState(): TciClientState {\n return cloneState(this.state);\n }\n\n async sendCommand(name: string, args: readonly unknown[] = [], options: SendCommandOptions = {}): Promise<TciCommand | undefined> {\n const raw = formatTciCommand(name, args);\n if (options.waitForReply === false) {\n await this.sendRaw(raw);\n return undefined;\n }\n const result = await this.queue.enqueue(raw, options);\n return result.reply;\n }\n\n async request(name: string, args: readonly unknown[] = [], options: QueueCommandOptions = {}): Promise<TciCommand> {\n const reply = await this.sendCommand(name, args, { ...options, waitForReply: true });\n if (!reply) {\n throw new TciError('protocol-error', `No reply for ${name}`);\n }\n return reply;\n }\n\n async setFrequency(frequencyHz: number, receiver = this.options.receiver, vfo = this.options.vfo): Promise<void> {\n await this.sendCommand('VFO', [receiver, vfo, Math.round(frequencyHz)]);\n }\n\n async getFrequency(receiver = this.options.receiver, vfo = this.options.vfo): Promise<number | undefined> {\n const reply = await this.request('VFO', [receiver, vfo]);\n return parseNumber(reply.args[2]) ?? this.state.frequencies[rxVfoKey(receiver, vfo)];\n }\n\n async setMode(mode: string, receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('MODULATION', [receiver, mode.toUpperCase()]);\n }\n\n async getMode(receiver = this.options.receiver): Promise<string | undefined> {\n const reply = await this.request('MODULATION', [receiver]);\n const mode = reply.args.length >= 3 ? reply.args[2] : reply.args[1];\n return (mode ?? this.state.modes[rxVfoKey(receiver, this.options.vfo)])?.toLowerCase();\n }\n\n async setPtt(enabled: boolean, options: TciPttOptions = {}): Promise<void> {\n const trx = options.trx ?? this.options.trx;\n const args = options.source ? [trx, enabled, options.source] : [trx, enabled];\n await this.sendCommand('TRX', args);\n }\n\n async getPtt(trx = this.options.trx): Promise<boolean | undefined> {\n const reply = await this.request('TRX', [trx]);\n return parseBoolean(reply.args[1]) ?? this.state.ptt[String(trx)];\n }\n\n async setTune(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('TUNE', [trx, enabled]);\n }\n\n async setDrive(value: number, trx = this.options.trx): Promise<void> {\n await this.sendCommand('DRIVE', [trx, value]);\n }\n\n async setSplit(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('SPLIT_ENABLE', [trx, enabled]);\n }\n\n async configureAudio(config: TciAudioConfig): Promise<void> {\n const audio = {\n sampleRate: config.sampleRate,\n sampleType: normalizeSampleType(config.sampleType ?? TciSampleType.FLOAT32),\n channels: config.channels ?? 1,\n samplesPerFrame: config.samplesPerFrame ?? 512,\n txBufferingMs: config.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n this.state.audio = audio;\n\n await this.sendCommand('AUDIO_SAMPLERATE', [audio.sampleRate], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLE_TYPE', [sampleTypeName(audio.sampleType)], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_CHANNELS', [audio.channels], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLES', [audio.samplesPerFrame], { waitForReply: false });\n if (audio.txBufferingMs !== undefined) {\n await this.sendCommand('TX_STREAM_AUDIO_BUFFERING', [audio.txBufferingMs], { waitForReply: false });\n }\n this.emitState();\n }\n\n async startAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_START', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = true;\n this.emitState();\n }\n }\n\n async stopAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_STOP', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = false;\n this.emitState();\n }\n }\n\n sendTxAudio(options: BuildTxAudioFrameOptions): void {\n const frame = buildTxAudioFrame({ receiver: this.options.receiver, ...options });\n this.sendRawBinary(frame);\n }\n\n async setRxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('RX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async setTxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('TX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async sendCwMacro(index: number): Promise<void> {\n await this.sendCommand('CW_MACROS', [index]);\n }\n\n async sendCwMessage(message: string): Promise<void> {\n await this.sendCommand('CW_MSG', [message]);\n }\n\n async stopCw(): Promise<void> {\n await this.sendCommand('CW_MACROS_STOP');\n }\n\n private waitForOpen(ws: WebSocket): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n try {\n ws.terminate();\n } catch {\n // ignore termination races\n }\n reject(new TciError('connect-timeout', `Timed out connecting to ${this.options.url}`));\n }, this.options.connectTimeoutMs);\n\n const cleanup = () => {\n clearTimeout(timer);\n ws.off('open', onOpen);\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onOpen = () => {\n cleanup();\n this.attachSocket(ws);\n this.state.connected = true;\n this.queue.setConnected(true);\n this.emit('connected');\n this.emitState();\n resolve();\n };\n const onClose = () => {\n cleanup();\n this.handleClose();\n reject(new TciError('disconnected', `Disconnected while connecting to ${this.options.url}`));\n };\n const onError = (error: Error) => {\n cleanup();\n this.handleError(error);\n reject(toTciError(error, 'disconnected'));\n };\n ws.once('open', onOpen);\n ws.once('close', onClose);\n ws.once('error', onError);\n });\n }\n\n private attachSocket(ws: WebSocket): void {\n ws.on('message', (data, isBinary) => this.handleMessage(data, isBinary));\n ws.on('close', () => this.handleClose());\n ws.on('error', (error) => this.handleError(error));\n }\n\n private async sendRaw(raw: string): Promise<void> {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n await new Promise<void>((resolve, reject) => {\n ws.send(raw, (error) => (error ? reject(error) : resolve()));\n });\n }\n\n private sendRawBinary(raw: Buffer): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n ws.send(raw, { binary: true });\n }\n\n private handleMessage(data: WebSocket.RawData, isBinary: boolean): void {\n try {\n if (isBinary) {\n this.handleBinary(data);\n return;\n }\n const commands = parseTciText(dataToBuffer(data));\n for (const command of commands) {\n this.queue.handleCommand(command);\n this.applyCommand(command);\n this.emit('command', command);\n }\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private handleBinary(data: WebSocket.RawData): void {\n const frame = parseStreamFrame(dataToBuffer(data));\n this.emit('binary', frame);\n switch (frame.streamType) {\n case TciStreamType.RX_AUDIO_STREAM:\n this.emit('rxAudioFrame', frame);\n break;\n case TciStreamType.TX_CHRONO:\n this.emit('txChrono', {\n frame,\n receiver: frame.receiver,\n sampleRate: frame.sampleRate,\n channels: frame.channels,\n sampleType: frame.sampleType,\n sampleCount: frame.sampleCount,\n });\n break;\n case TciStreamType.LINEOUT_STREAM:\n this.emit('lineoutAudioFrame', frame);\n break;\n default:\n break;\n }\n }\n\n private applyCommand(command: TciCommand): void {\n const readyBefore = this.state.ready;\n switch (command.name) {\n case 'ready':\n this.state.ready = command.args.length === 0 ? true : (parseBoolean(command.args[0]) ?? true);\n break;\n case 'protocol':\n this.state.protocol = command.args[0];\n break;\n case 'device':\n this.state.device = command.args.join(',');\n break;\n case 'receive_only':\n this.state.receiveOnly = parseBoolean(command.args[0]);\n break;\n case 'trx_count':\n this.state.trxCount = parseNumber(command.args[0]);\n break;\n case 'channels_count':\n case 'channel_count':\n this.state.channelCount = parseNumber(command.args[0]);\n break;\n case 'vfo_limits':\n this.state.vfoLimits = parseNumberPair(command.args);\n break;\n case 'if_limits':\n this.state.ifLimits = parseNumberPair(command.args);\n break;\n case 'modulations_list':\n this.state.modulations = command.args.map((mode) => mode.toLowerCase());\n break;\n case 'vfo':\n this.applyVfo(command.args);\n break;\n case 'modulation':\n this.applyModulation(command.args);\n break;\n case 'trx':\n this.applyTrx(command.args);\n break;\n case 'tune':\n this.applyBooleanByFirstArg(this.state.tune, command.args);\n break;\n case 'drive':\n this.applyDrive(command.args);\n break;\n case 'split_enable':\n this.applyBooleanByFirstArg(this.state.split, command.args);\n break;\n case 'rx_channel_sensors':\n this.applyRxChannelSensors(command.args);\n break;\n case 'rx_sensors':\n this.applyRxSensors(command.args);\n break;\n case 'tx_sensors':\n this.applyTxSensors(command.args);\n break;\n case 'audio_samplerate':\n this.state.audio = {\n sampleRate: parseNumber(command.args[0]) ?? this.state.audio?.sampleRate ?? 12_000,\n sampleType: this.state.audio?.sampleType ?? TciSampleType.FLOAT32,\n channels: this.state.audio?.channels ?? 1,\n samplesPerFrame: this.state.audio?.samplesPerFrame ?? 512,\n txBufferingMs: this.state.audio?.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n break;\n default:\n break;\n }\n\n if (!readyBefore && this.state.ready) {\n this.emit('ready', this.getState());\n }\n this.emitState();\n }\n\n private applyVfo(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const receiver = parseNumber(args[0]);\n const vfo = parseNumber(args[1]);\n const frequency = parseNumber(args[2]);\n if (receiver === undefined || vfo === undefined || frequency === undefined || frequency < 0) {\n return;\n }\n this.state.frequencies[rxVfoKey(receiver, vfo)] = frequency;\n }\n\n private applyModulation(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const receiver = parseNumber(args[0]);\n if (receiver === undefined) {\n return;\n }\n const vfo = args.length >= 3 ? parseNumber(args[1]) ?? this.options.vfo : this.options.vfo;\n const mode = args.length >= 3 ? args[2] : args[1];\n if (!mode) {\n return;\n }\n this.state.modes[rxVfoKey(receiver, vfo)] = mode.toLowerCase();\n }\n\n private applyTrx(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n this.state.ptt[trx] = parseBoolean(args[1]) ?? false;\n this.state.pttSource[trx] = args[2]?.toLowerCase();\n }\n\n private applyBooleanByFirstArg(target: Record<string, boolean>, args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const key = args[0] ?? '0';\n const value = parseBoolean(args[1]);\n if (value !== undefined) {\n target[key] = value;\n }\n }\n\n private applyDrive(args: string[]): void {\n if (args.length === 1) {\n const value = parseNumber(args[0]);\n if (value !== undefined) {\n this.state.drive[String(this.options.trx)] = value;\n }\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n const value = parseNumber(args[1]);\n if (value !== undefined) {\n this.state.drive[trx] = value;\n }\n }\n\n private applyRxChannelSensors(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const key = rxVfoKey(args[0], args[1]);\n this.state.rxSensors[key] = {\n receiver: args[0],\n channel: args[1],\n levelDbm: parseNumber(args[2]) ?? args[2],\n };\n }\n\n private applyRxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.rxSensors[String(args[0])] = {\n receiver: args[0],\n levelDbm: parseNumber(args[1]) ?? args[1],\n deprecated: true,\n };\n }\n\n private applyTxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.txSensors[String(args[0])] = {\n trx: args[0],\n micDbm: parseNumber(args[1]) ?? args[1],\n rmsPowerW: parseNumber(args[2]) ?? args[2],\n peakPowerW: parseNumber(args[3]) ?? args[3],\n swr: parseNumber(args[4]) ?? args[4],\n };\n }\n\n private handleClose(reason?: unknown): void {\n this.ws = undefined;\n const wasConnected = this.state.connected;\n this.state.connected = false;\n this.state.ready = false;\n this.queue.setConnected(false);\n if (wasConnected) {\n this.emit('disconnected', reason);\n this.emitState();\n }\n }\n\n private handleError(error: unknown): void {\n const tciError = toTciError(error);\n this.emit('error', tciError);\n }\n\n private emitState(): void {\n this.emit('state', this.getState());\n }\n}\n\nexport function createTciClient(options: TciClientOptions): TciClient {\n return new TciClient(options);\n}\n\nfunction dataToBuffer(data: WebSocket.RawData): Buffer {\n if (Buffer.isBuffer(data)) {\n return data;\n }\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data);\n }\n if (Array.isArray(data)) {\n return Buffer.concat(data.map((item) => dataToBuffer(item)));\n }\n throw new TciError('protocol-error', 'Unsupported WebSocket data type');\n}\n\nfunction rxVfoKey(receiver: string | number, vfo: string | number): string {\n return `${receiver}:${vfo}`;\n}\n\nfunction parseNumber(value: string | undefined): number | undefined {\n if (value === undefined || value === '') {\n return undefined;\n }\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) {\n return undefined;\n }\n const normalized = value.toLowerCase();\n if (normalized === 'true' || normalized === '1' || normalized === 'on') {\n return true;\n }\n if (normalized === 'false' || normalized === '0' || normalized === 'off') {\n return false;\n }\n return undefined;\n}\n\nfunction parseNumberPair(args: string[]): [number, number] | undefined {\n const first = parseNumber(args[0]);\n const second = parseNumber(args[1]);\n return first === undefined || second === undefined ? undefined : [first, second];\n}\n\nfunction cloneState(state: TciClientState): TciClientState {\n return {\n ...state,\n modulations: [...state.modulations],\n frequencies: { ...state.frequencies },\n modes: { ...state.modes },\n ptt: { ...state.ptt },\n pttSource: { ...state.pttSource },\n tune: { ...state.tune },\n drive: { ...state.drive },\n split: { ...state.split },\n rxSensors: cloneNested(state.rxSensors),\n txSensors: cloneNested(state.txSensors),\n audio: state.audio ? { ...state.audio } : undefined,\n };\n}\n\nfunction cloneNested<T>(value: Record<string, T>): Record<string, T> {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, { ...(item as Record<string, unknown>) } as T]));\n}\n","import { TciError } from '../errors.js';\n\nexport const TCI_STREAM_HEADER_BYTES = 16 * 4;\n\nexport enum TciStreamType {\n IQ_STREAM = 0,\n RX_AUDIO_STREAM = 1,\n TX_AUDIO_STREAM = 2,\n TX_CHRONO = 3,\n LINEOUT_STREAM = 4,\n}\n\nexport enum TciSampleType {\n INT16 = 0,\n INT24 = 1,\n INT32 = 2,\n FLOAT32 = 3,\n}\n\nexport type TciSampleTypeName = 'int16' | 'int24' | 'int32' | 'float32';\n\nexport interface TciStreamFrame {\n receiver: number;\n sampleRate: number;\n sampleType: TciSampleType;\n codec: number;\n crc: number;\n /** Byte length of the payload following the 64-byte TCI stream header. */\n payloadLength: number;\n streamType: TciStreamType;\n channels: number;\n reserved: number[];\n payload: Buffer;\n /** Official Stream.length value: number of samples per channel in the payload. */\n sampleCount: number;\n}\n\nexport interface BuildStreamFrameOptions {\n receiver?: number;\n sampleRate: number;\n sampleType: TciSampleType | TciSampleTypeName;\n streamType: TciStreamType;\n channels: number;\n payload?: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView;\n samples?: Float32Array | readonly number[];\n codec?: number;\n crc?: number;\n reserved?: readonly number[];\n}\n\nexport interface BuildTxAudioFrameOptions extends Omit<BuildStreamFrameOptions, 'streamType'> {\n receiver?: number;\n}\n\nexport function parseStreamFrame(input: Buffer | ArrayBuffer | ArrayBufferView): TciStreamFrame {\n const buffer = toBuffer(input);\n if (buffer.byteLength < TCI_STREAM_HEADER_BYTES) {\n throw new TciError('invalid-frame', `TCI stream frame is shorter than ${TCI_STREAM_HEADER_BYTES} bytes`);\n }\n\n const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n const header = Array.from({ length: 16 }, (_, index) => view.getUint32(index * 4, true));\n const sampleType = normalizeSampleType(header[2]);\n let channels = header[7];\n const bytesPerSample = sampleTypeBytes(sampleType);\n const sampleCount = header[5];\n const actualPayloadLength = buffer.byteLength - TCI_STREAM_HEADER_BYTES;\n if (channels <= 0) {\n const inferredChannels = sampleCount > 0 ? actualPayloadLength / sampleCount / bytesPerSample : 1;\n if (!Number.isInteger(inferredChannels) || inferredChannels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n channels = inferredChannels;\n }\n const payloadLength = sampleCount * bytesPerSample * channels;\n const expectedLength = TCI_STREAM_HEADER_BYTES + payloadLength;\n if (buffer.byteLength !== expectedLength) {\n throw new TciError(\n 'invalid-frame',\n `TCI stream frame length mismatch: header says ${sampleCount} samples (${payloadLength} payload bytes), got ${buffer.byteLength - TCI_STREAM_HEADER_BYTES}`,\n );\n }\n if (payloadLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n\n return {\n receiver: header[0],\n sampleRate: header[1],\n sampleType,\n codec: header[3],\n crc: header[4],\n payloadLength,\n streamType: normalizeStreamType(header[6]),\n channels,\n reserved: header.slice(8),\n payload: buffer.subarray(TCI_STREAM_HEADER_BYTES),\n sampleCount,\n };\n}\n\nexport function buildStreamFrame(options: BuildStreamFrameOptions): Buffer {\n const sampleType = normalizeSampleType(options.sampleType);\n const payload = options.payload ? toBuffer(options.payload) : samplesToPayload(options.samples ?? [], sampleType);\n const channels = options.channels;\n if (channels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n const bytesPerSample = sampleTypeBytes(sampleType);\n if (payload.byteLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n const sampleCount = payload.byteLength / bytesPerSample / channels;\n\n const frame = Buffer.alloc(TCI_STREAM_HEADER_BYTES + payload.byteLength);\n const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);\n const reserved = options.reserved ?? [];\n const header = [\n options.receiver ?? 0,\n options.sampleRate,\n sampleType,\n options.codec ?? 0,\n options.crc ?? 0,\n sampleCount,\n options.streamType,\n channels,\n ...Array.from({ length: 8 }, (_, index) => reserved[index] ?? 0),\n ];\n header.forEach((value, index) => view.setUint32(index * 4, value >>> 0, true));\n payload.copy(frame, TCI_STREAM_HEADER_BYTES);\n return frame;\n}\n\nexport function buildTxAudioFrame(options: BuildTxAudioFrameOptions): Buffer {\n return buildStreamFrame({ ...options, streamType: TciStreamType.TX_AUDIO_STREAM });\n}\n\nexport function sampleTypeBytes(sampleType: TciSampleType | TciSampleTypeName): number {\n switch (normalizeSampleType(sampleType)) {\n case TciSampleType.INT16:\n return 2;\n case TciSampleType.INT24:\n return 3;\n case TciSampleType.INT32:\n case TciSampleType.FLOAT32:\n return 4;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function sampleTypeName(sampleType: TciSampleType): TciSampleTypeName {\n switch (sampleType) {\n case TciSampleType.INT16:\n return 'int16';\n case TciSampleType.INT24:\n return 'int24';\n case TciSampleType.INT32:\n return 'int32';\n case TciSampleType.FLOAT32:\n return 'float32';\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function normalizeSampleType(sampleType: TciSampleType | TciSampleTypeName | number): TciSampleType {\n if (typeof sampleType === 'string') {\n switch (sampleType.toLowerCase()) {\n case 'int16':\n return TciSampleType.INT16;\n case 'int24':\n return TciSampleType.INT24;\n case 'int32':\n return TciSampleType.INT32;\n case 'float32':\n return TciSampleType.FLOAT32;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n }\n if (sampleType >= TciSampleType.INT16 && sampleType <= TciSampleType.FLOAT32) {\n return sampleType as TciSampleType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n}\n\nexport function normalizeStreamType(streamType: TciStreamType | number): TciStreamType {\n if (streamType >= TciStreamType.IQ_STREAM && streamType <= TciStreamType.LINEOUT_STREAM) {\n return streamType as TciStreamType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI stream type: ${streamType}`);\n}\n\nexport function payloadToFloat32(frameOrPayload: TciStreamFrame | Buffer | Uint8Array, sampleType?: TciSampleType | TciSampleTypeName): Float32Array {\n const payload = isFrame(frameOrPayload) ? frameOrPayload.payload : toBuffer(frameOrPayload);\n const type = isFrame(frameOrPayload) ? frameOrPayload.sampleType : normalizeSampleType(sampleType ?? TciSampleType.FLOAT32);\n const bytes = sampleTypeBytes(type);\n if (payload.byteLength % bytes !== 0) {\n throw new TciError('invalid-frame', 'Payload length is not aligned to sample type');\n }\n\n const output = new Float32Array(payload.byteLength / bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < output.length; i += 1) {\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n output[i] = view.getInt16(offset, true) / 32768;\n break;\n case TciSampleType.INT24:\n output[i] = readInt24(view, offset) / 8388608;\n break;\n case TciSampleType.INT32:\n output[i] = view.getInt32(offset, true) / 2147483648;\n break;\n case TciSampleType.FLOAT32:\n output[i] = view.getFloat32(offset, true);\n break;\n }\n }\n return output;\n}\n\nexport function samplesToPayload(samples: Float32Array | readonly number[], sampleType: TciSampleType | TciSampleTypeName): Buffer {\n const type = normalizeSampleType(sampleType);\n const bytes = sampleTypeBytes(type);\n const payload = Buffer.alloc(samples.length * bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < samples.length; i += 1) {\n const value = clampSample(samples[i] ?? 0);\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n view.setInt16(offset, Math.round(value * 32767), true);\n break;\n case TciSampleType.INT24:\n writeInt24(view, offset, Math.round(value * 8388607));\n break;\n case TciSampleType.INT32:\n view.setInt32(offset, Math.round(value * 2147483647), true);\n break;\n case TciSampleType.FLOAT32:\n view.setFloat32(offset, value, true);\n break;\n }\n }\n return payload;\n}\n\nexport function pcm16ToFloat32(input: Buffer | Uint8Array | Int16Array): Float32Array {\n if (input instanceof Int16Array) {\n const output = new Float32Array(input.length);\n for (let i = 0; i < input.length; i += 1) {\n output[i] = input[i] / 32768;\n }\n return output;\n }\n return payloadToFloat32(toBuffer(input), TciSampleType.INT16);\n}\n\nexport function float32ToPcm16(samples: Float32Array | readonly number[]): Buffer {\n return samplesToPayload(samples, TciSampleType.INT16);\n}\n\nexport function deinterleaveChannels(samples: Float32Array, channels: number): Float32Array[] {\n if (channels <= 0 || samples.length % channels !== 0) {\n throw new TciError('invalid-frame', 'Cannot deinterleave samples with invalid channel count');\n }\n const frames = samples.length / channels;\n const outputs = Array.from({ length: channels }, () => new Float32Array(frames));\n for (let frame = 0; frame < frames; frame += 1) {\n for (let channel = 0; channel < channels; channel += 1) {\n outputs[channel][frame] = samples[frame * channels + channel];\n }\n }\n return outputs;\n}\n\nexport function mixToMono(samples: Float32Array, channels: number): Float32Array {\n if (channels === 1) {\n return samples;\n }\n const separated = deinterleaveChannels(samples, channels);\n const mono = new Float32Array(separated[0]?.length ?? 0);\n for (const channel of separated) {\n for (let i = 0; i < mono.length; i += 1) {\n mono[i] += channel[i] / channels;\n }\n }\n return mono;\n}\n\nfunction toBuffer(input: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView): Buffer {\n if (Buffer.isBuffer(input)) {\n return input;\n }\n if (input instanceof ArrayBuffer) {\n return Buffer.from(input);\n }\n if (ArrayBuffer.isView(input)) {\n return Buffer.from(input.buffer, input.byteOffset, input.byteLength);\n }\n return Buffer.from(input);\n}\n\nfunction isFrame(value: unknown): value is TciStreamFrame {\n return Boolean(value && typeof value === 'object' && 'payload' in value && 'sampleType' in value);\n}\n\nfunction clampSample(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n return Math.max(-1, Math.min(1, value));\n}\n\nfunction readInt24(view: DataView, offset: number): number {\n const value = view.getUint8(offset) | (view.getUint8(offset + 1) << 8) | (view.getUint8(offset + 2) << 16);\n return value & 0x800000 ? value | 0xff000000 : value;\n}\n\nfunction writeInt24(view: DataView, offset: number, value: number): void {\n const clamped = Math.max(-8388608, Math.min(8388607, value));\n view.setUint8(offset, clamped & 0xff);\n view.setUint8(offset + 1, (clamped >> 8) & 0xff);\n view.setUint8(offset + 2, (clamped >> 16) & 0xff);\n}\n","export interface TciCommand {\n /** Lower-case command name for case-insensitive matching. */\n name: string;\n /** Original command name as received, without surrounding whitespace. */\n originalName: string;\n /** Unescaped argument list. Empty commands have an empty array. */\n args: string[];\n /** Raw command fragment without the trailing semicolon. */\n raw: string;\n}\n\nexport type TciCommandInput = string | TciCommand;\n\nconst ESCAPE_TO_CHAR: Record<string, string> = {\n '^': ':',\n '~': ',',\n '*': ';',\n};\n\nconst CHAR_TO_ESCAPE: Record<string, string> = {\n ':': '^',\n ',': '~',\n ';': '*',\n};\n\nexport function escapeTciText(value: unknown): string {\n return String(value).replace(/[:;,]/g, (char) => CHAR_TO_ESCAPE[char] ?? char);\n}\n\nexport function unescapeTciText(value: string): string {\n return value.replace(/[\\^~*]/g, (char) => ESCAPE_TO_CHAR[char] ?? char);\n}\n\nexport function parseTciText(text: string | Buffer | ArrayBuffer | ArrayBufferView): TciCommand[] {\n const source = normalizeTextInput(text);\n const commands: TciCommand[] = [];\n\n for (const fragment of source.split(';')) {\n const raw = fragment.trim();\n if (!raw) {\n continue;\n }\n\n const colonIndex = raw.indexOf(':');\n const originalName = (colonIndex >= 0 ? raw.slice(0, colonIndex) : raw).trim();\n if (!originalName) {\n continue;\n }\n\n const argsText = colonIndex >= 0 ? raw.slice(colonIndex + 1) : undefined;\n commands.push({\n name: originalName.toLowerCase(),\n originalName,\n args: argsText === undefined ? [] : splitArgs(argsText),\n raw,\n });\n }\n\n return commands;\n}\n\nexport function parseTciCommand(input: TciCommandInput): TciCommand {\n if (typeof input !== 'string') {\n return input;\n }\n const [command] = parseTciText(input);\n if (!command) {\n throw new Error(`Invalid TCI command: ${input}`);\n }\n return command;\n}\n\nexport function formatTciCommand(name: string, args: readonly unknown[] = []): string {\n const commandName = name.trim().toUpperCase();\n if (!commandName) {\n throw new Error('TCI command name cannot be empty');\n }\n if (args.length === 0) {\n return `${commandName};`;\n }\n return `${commandName}:${args.map(escapeTciText).join(',')};`;\n}\n\nexport function normalizeCommandName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nexport function isCommandReplyTo(replyInput: TciCommandInput, requestInput: TciCommandInput): boolean {\n const reply = parseTciCommand(replyInput);\n const request = parseTciCommand(requestInput);\n if (reply.name !== request.name) {\n return false;\n }\n\n if (request.args.length === 0) {\n return true;\n }\n\n if (argsHavePrefix(reply.args, request.args)) {\n return true;\n }\n\n return isKnownVariantReply(reply, request);\n}\n\nexport function commandKey(command: TciCommandInput): string {\n const parsed = parseTciCommand(command);\n return `${parsed.name}:${parsed.args.join(',')}`;\n}\n\nfunction normalizeTextInput(text: string | Buffer | ArrayBuffer | ArrayBufferView): string {\n if (typeof text === 'string') {\n return text;\n }\n if (Buffer.isBuffer(text)) {\n return text.toString('utf8');\n }\n if (text instanceof ArrayBuffer) {\n return Buffer.from(text).toString('utf8');\n }\n return Buffer.from(text.buffer, text.byteOffset, text.byteLength).toString('utf8');\n}\n\nfunction splitArgs(argsText: string): string[] {\n return argsText.split(',').map((arg) => unescapeTciText(arg.trim()));\n}\n\nfunction argsHavePrefix(args: readonly string[], prefix: readonly string[]): boolean {\n if (args.length < prefix.length) {\n return false;\n }\n return prefix.every((arg, index) => args[index]?.toLowerCase() === arg.toLowerCase());\n}\n\nfunction isKnownVariantReply(reply: TciCommand, request: TciCommand): boolean {\n if (reply.name === 'modulation') {\n // ExpertSDR/WSJT-X variants can use MODULATION:rx,mode and MODULATION:rx,vfo,mode.\n if (request.args.length === 2 && reply.args.length >= 3) {\n return reply.args[0] === request.args[0] && reply.args[2]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n if (request.args.length === 3 && reply.args.length === 2) {\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[2]?.toLowerCase();\n }\n }\n\n if (reply.name === 'protocol') {\n return request.args.length <= 1;\n }\n\n if (reply.name === 'trx' && request.args.length >= 3 && reply.args.length >= 2) {\n // Official TRX writes may include an audio source as arg3, while replies only echo trx+state.\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n\n return false;\n}\n","import { TciError } from '../errors.js';\nimport {\n formatTciCommand,\n isCommandReplyTo,\n parseTciCommand,\n type TciCommand,\n type TciCommandInput,\n} from './text.js';\n\nexport type TciCommandMatcher = (reply: TciCommand, request: TciCommand) => boolean;\n\nexport interface QueueCommandOptions {\n timeoutMs?: number;\n matcher?: TciCommandMatcher;\n signal?: AbortSignal;\n}\n\nexport interface QueuedCommandResult {\n request: TciCommand;\n reply: TciCommand;\n}\n\ninterface PendingCommand {\n raw: string;\n request: TciCommand;\n timeoutMs: number;\n matcher: TciCommandMatcher;\n resolve: (result: QueuedCommandResult) => void;\n reject: (error: TciError) => void;\n timer?: NodeJS.Timeout;\n abortCleanup?: () => void;\n}\n\nexport interface TciCommandQueueOptions {\n send: (raw: string) => void | Promise<void>;\n timeoutMs?: number;\n}\n\nexport class TciCommandQueue {\n private readonly send: (raw: string) => void | Promise<void>;\n private readonly defaultTimeoutMs: number;\n private queue: PendingCommand[] = [];\n private active?: PendingCommand;\n private connected = true;\n\n constructor(options: TciCommandQueueOptions) {\n this.send = options.send;\n this.defaultTimeoutMs = options.timeoutMs ?? 1_000;\n }\n\n setConnected(connected: boolean): void {\n this.connected = connected;\n if (!connected) {\n this.cancelAll(new TciError('disconnected', 'TCI connection closed'));\n }\n }\n\n enqueue(command: TciCommandInput, options: QueueCommandOptions = {}): Promise<QueuedCommandResult> {\n const request = parseTciCommand(command);\n const raw = typeof command === 'string' ? ensureSemicolon(command) : formatTciCommand(command.originalName, command.args);\n\n if (!this.connected) {\n return Promise.reject(new TciError('not-connected', 'TCI socket is not connected'));\n }\n\n return new Promise<QueuedCommandResult>((resolve, reject) => {\n const pending: PendingCommand = {\n raw,\n request,\n timeoutMs: options.timeoutMs ?? this.defaultTimeoutMs,\n matcher: options.matcher ?? ((reply, req) => isCommandReplyTo(reply, req)),\n resolve,\n reject,\n };\n\n if (options.signal) {\n if (options.signal.aborted) {\n reject(new TciError('cancelled', 'TCI command was cancelled'));\n return;\n }\n const onAbort = () => this.rejectPending(pending, new TciError('cancelled', 'TCI command was cancelled'));\n options.signal.addEventListener('abort', onAbort, { once: true });\n pending.abortCleanup = () => options.signal?.removeEventListener('abort', onAbort);\n }\n\n this.queue.push(pending);\n void this.pump();\n });\n }\n\n handleCommand(commandInput: TciCommandInput): boolean {\n const active = this.active;\n if (!active) {\n return false;\n }\n const reply = parseTciCommand(commandInput);\n if (!active.matcher(reply, active.request)) {\n return false;\n }\n this.finishActive(reply);\n return true;\n }\n\n cancelAll(error = new TciError('cancelled', 'TCI command queue cancelled')): void {\n const pending = [...this.queue];\n this.queue = [];\n if (this.active) {\n pending.unshift(this.active);\n this.active = undefined;\n }\n for (const item of pending) {\n this.rejectPending(item, error);\n }\n }\n\n get size(): number {\n return this.queue.length + (this.active ? 1 : 0);\n }\n\n private async pump(): Promise<void> {\n if (this.active || !this.connected) {\n return;\n }\n const next = this.queue.shift();\n if (!next) {\n return;\n }\n\n this.active = next;\n next.timer = setTimeout(() => {\n this.rejectPending(next, new TciError('command-timeout', `Timed out waiting for TCI reply to ${next.raw}`));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }, next.timeoutMs);\n\n try {\n await this.send(next.raw);\n } catch (error) {\n this.rejectPending(next, new TciError('disconnected', error instanceof Error ? error.message : String(error), error));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }\n }\n\n private finishActive(reply: TciCommand): void {\n const active = this.active;\n if (!active) {\n return;\n }\n this.active = undefined;\n if (active.timer) {\n clearTimeout(active.timer);\n }\n active.abortCleanup?.();\n active.resolve({ request: active.request, reply });\n void this.pump();\n }\n\n private rejectPending(pending: PendingCommand, error: TciError): void {\n if (pending.timer) {\n clearTimeout(pending.timer);\n }\n pending.abortCleanup?.();\n const wasActive = this.active === pending;\n if (wasActive) {\n this.active = undefined;\n } else {\n this.queue = this.queue.filter((item) => item !== pending);\n }\n pending.reject(error);\n if (wasActive && this.connected) {\n void this.pump();\n }\n }\n}\n\nfunction ensureSemicolon(command: string): string {\n return command.trim().endsWith(';') ? command.trim() : `${command.trim()};`;\n}\n"],"mappings":"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","names":["TciStreamType","TciSampleType","WebSocket","value"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client/TciClient.ts","../src/audio/streamFrame.ts","../src/protocol/text.ts","../src/protocol/commandQueue.ts"],"sourcesContent":["export * from './errors.js';\nexport * from './client/TciClient.js';\nexport * from './protocol/index.js';\nexport * from './audio/index.js';\n","export type TciErrorCode =\n | 'connect-timeout'\n | 'command-timeout'\n | 'not-connected'\n | 'disconnected'\n | 'protocol-error'\n | 'invalid-frame'\n | 'cancelled';\n\nexport class TciError extends Error {\n readonly code: TciErrorCode;\n readonly details?: unknown;\n\n constructor(code: TciErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TciError';\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toTciError(error: unknown, fallbackCode: TciErrorCode = 'protocol-error'): TciError {\n if (error instanceof TciError) {\n return error;\n }\n if (error instanceof Error) {\n return new TciError(fallbackCode, error.message, error);\n }\n return new TciError(fallbackCode, String(error), error);\n}\n","import { EventEmitter } from 'eventemitter3';\nimport WebSocket from 'ws';\nimport { TciError, toTciError } from '../errors.js';\nimport {\n buildTxAudioFrame,\n normalizeSampleType,\n parseStreamFrame,\n sampleTypeName,\n TciSampleType,\n TciStreamType,\n type BuildTxAudioFrameOptions,\n type TciSampleTypeName,\n type TciStreamFrame,\n} from '../audio/streamFrame.js';\nimport {\n formatTciCommand,\n parseTciText,\n TciCommandQueue,\n type QueueCommandOptions,\n type TciCommand,\n} from '../protocol/index.js';\n\nexport interface TciClientOptions {\n url: string;\n receiver?: number;\n trx?: number;\n vfo?: number;\n connectTimeoutMs?: number;\n commandTimeoutMs?: number;\n writeAckMode?: TciWriteAckMode;\n writeTimeoutMs?: number;\n writeSettleMs?: number;\n frequencyWriteSettleMs?: number;\n WebSocketImpl?: typeof WebSocket;\n}\n\nexport interface TciAudioConfig {\n sampleRate: 8_000 | 12_000 | 24_000 | 48_000 | number;\n sampleType?: TciSampleType | TciSampleTypeName;\n channels?: 1 | 2 | number;\n samplesPerFrame?: number;\n txBufferingMs?: number;\n}\n\nexport interface TciPttOptions {\n source?: 'tci' | 'mic1' | 'mic2' | 'micpc' | 'ecoder2' | string;\n trx?: number;\n ackMode?: TciWriteAckMode;\n timeoutMs?: number;\n settleMs?: number;\n}\n\nexport type TciWriteAckMode = 'state' | 'reply' | 'optimistic';\n\nexport interface TciWriteOptions {\n ackMode?: TciWriteAckMode;\n timeoutMs?: number;\n settleMs?: number;\n}\n\nexport interface TciTxChronoRequest {\n frame: TciStreamFrame;\n receiver: number;\n sampleRate: number;\n channels: number;\n sampleType: TciSampleType;\n sampleCount: number;\n}\n\nexport interface TciClientState {\n connected: boolean;\n ready: boolean;\n protocol?: string;\n device?: string;\n receiveOnly?: boolean;\n trxCount?: number;\n channelCount?: number;\n vfoLimits?: [number, number];\n ifLimits?: [number, number];\n modulations: string[];\n frequencies: Record<string, number>;\n modes: Record<string, string>;\n ptt: Record<string, boolean>;\n pttSource: Record<string, string | undefined>;\n tune: Record<string, boolean>;\n drive: Record<string, number>;\n split: Record<string, boolean>;\n rxSensors: Record<string, Record<string, number | string | boolean>>;\n txSensors: Record<string, Record<string, number | string | boolean>>;\n audio?: Required<Pick<TciAudioConfig, 'sampleRate' | 'channels' | 'sampleType' | 'samplesPerFrame'>> & {\n txBufferingMs?: number;\n running: boolean;\n };\n}\n\nexport interface TciClientEvents {\n connected: () => void;\n disconnected: (reason?: unknown) => void;\n ready: (state: TciClientState) => void;\n state: (state: TciClientState) => void;\n command: (command: TciCommand) => void;\n binary: (frame: TciStreamFrame) => void;\n 'tci:tx': (raw: string) => void;\n 'tci:rx': (raw: string, commands: TciCommand[]) => void;\n 'tci:binary': (frame: TciStreamFrame) => void;\n rxAudioFrame: (frame: TciStreamFrame) => void;\n lineoutAudioFrame: (frame: TciStreamFrame) => void;\n txChrono: (request: TciTxChronoRequest) => void;\n error: (error: TciError) => void;\n}\n\nexport interface SendCommandOptions extends QueueCommandOptions {\n waitForReply?: boolean;\n}\n\nexport class TciClient extends EventEmitter<TciClientEvents> {\n readonly options: Required<Pick<\n TciClientOptions,\n | 'receiver'\n | 'trx'\n | 'vfo'\n | 'connectTimeoutMs'\n | 'commandTimeoutMs'\n | 'writeAckMode'\n | 'writeTimeoutMs'\n | 'writeSettleMs'\n | 'frequencyWriteSettleMs'\n >> &\n Pick<TciClientOptions, 'url'>;\n\n private readonly WebSocketImpl: typeof WebSocket;\n private ws?: WebSocket;\n private readonly queue: TciCommandQueue;\n private readonly state: TciClientState;\n\n constructor(options: TciClientOptions) {\n super();\n this.options = {\n url: options.url,\n receiver: options.receiver ?? 0,\n trx: options.trx ?? 0,\n vfo: options.vfo ?? 0,\n connectTimeoutMs: options.connectTimeoutMs ?? 5_000,\n commandTimeoutMs: options.commandTimeoutMs ?? 1_000,\n writeAckMode: options.writeAckMode ?? 'state',\n writeTimeoutMs: options.writeTimeoutMs ?? 3_000,\n writeSettleMs: options.writeSettleMs ?? 0,\n frequencyWriteSettleMs: options.frequencyWriteSettleMs ?? 250,\n };\n this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;\n this.queue = new TciCommandQueue({\n timeoutMs: this.options.commandTimeoutMs,\n send: (raw) => this.sendRaw(raw),\n });\n this.queue.setConnected(false);\n this.state = {\n connected: false,\n ready: false,\n modulations: [],\n frequencies: {},\n modes: {},\n ptt: {},\n pttSource: {},\n tune: {},\n drive: {},\n split: {},\n rxSensors: {},\n txSensors: {},\n };\n }\n\n async connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {\n await this.waitForOpen(this.ws);\n return;\n }\n\n const ws = new this.WebSocketImpl(this.options.url);\n this.ws = ws;\n await this.waitForOpen(ws);\n }\n\n async disconnect(code = 1000, reason = 'client disconnect'): Promise<void> {\n const ws = this.ws;\n if (!ws) {\n return;\n }\n if (ws.readyState === WebSocket.CLOSED) {\n this.handleClose();\n return;\n }\n await new Promise<void>((resolve) => {\n const cleanup = () => {\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onClose = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n resolve();\n };\n ws.once('close', onClose);\n ws.once('error', onError);\n ws.close(code, reason);\n setTimeout(() => resolve(), 1_000).unref?.();\n });\n this.handleClose();\n }\n\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n getState(): TciClientState {\n return cloneState(this.state);\n }\n\n async sendCommand(name: string, args: readonly unknown[] = [], options: SendCommandOptions = {}): Promise<TciCommand | undefined> {\n const raw = formatTciCommand(name, args);\n if (options.waitForReply === false) {\n await this.sendRaw(raw);\n return undefined;\n }\n const result = await this.queue.enqueue(raw, options);\n return result.reply;\n }\n\n async request(name: string, args: readonly unknown[] = [], options: QueueCommandOptions = {}): Promise<TciCommand> {\n const reply = await this.sendCommand(name, args, { ...options, waitForReply: true });\n if (!reply) {\n throw new TciError('protocol-error', `No reply for ${name}`);\n }\n return reply;\n }\n\n async sendStateWrite(\n name: string,\n args: readonly unknown[],\n isApplied: (state: TciClientState) => boolean,\n description = formatTciCommand(name, args).replace(/;$/, ''),\n options: TciWriteOptions = {},\n ): Promise<void> {\n const ackMode = options.ackMode ?? this.options.writeAckMode;\n if (ackMode === 'reply') {\n await this.sendCommand(name, args, { timeoutMs: options.timeoutMs });\n return;\n }\n\n if (isApplied(this.getState())) {\n return;\n }\n\n if (ackMode === 'optimistic') {\n await this.sendCommand(name, args, { waitForReply: false });\n return;\n }\n\n const timeoutMs = options.timeoutMs ?? this.options.writeTimeoutMs;\n const settleMs = options.settleMs ?? this.options.writeSettleMs;\n const waiter = this.waitForState(isApplied, timeoutMs, settleMs, description);\n try {\n await this.sendCommand(name, args, { waitForReply: false });\n await waiter.promise;\n } catch (error) {\n waiter.cancel();\n throw error;\n }\n }\n\n async setFrequency(\n frequencyHz: number,\n receiver = this.options.receiver,\n vfo = this.options.vfo,\n options: TciWriteOptions = {},\n ): Promise<void> {\n const frequency = Math.round(frequencyHz);\n const key = rxVfoKey(receiver, vfo);\n await this.sendStateWrite(\n 'VFO',\n [receiver, vfo, frequency],\n (state) => state.frequencies[key] === frequency,\n `VFO:${receiver},${vfo},${frequency}`,\n { settleMs: this.options.frequencyWriteSettleMs, ...options },\n );\n }\n\n async getFrequency(receiver = this.options.receiver, vfo = this.options.vfo): Promise<number | undefined> {\n const reply = await this.request('VFO', [receiver, vfo]);\n return parseNumber(reply.args[2]) ?? this.state.frequencies[rxVfoKey(receiver, vfo)];\n }\n\n async setMode(mode: string, receiver = this.options.receiver, options: TciWriteOptions = {}): Promise<void> {\n const normalizedMode = mode.toUpperCase();\n const key = rxVfoKey(receiver, this.options.vfo);\n await this.sendStateWrite(\n 'MODULATION',\n [receiver, normalizedMode],\n (state) => state.modes[key]?.toLowerCase() === normalizedMode.toLowerCase(),\n `MODULATION:${receiver},${normalizedMode}`,\n options,\n );\n }\n\n async getMode(receiver = this.options.receiver): Promise<string | undefined> {\n const reply = await this.request('MODULATION', [receiver]);\n const mode = reply.args.length >= 3 ? reply.args[2] : reply.args[1];\n return (mode ?? this.state.modes[rxVfoKey(receiver, this.options.vfo)])?.toLowerCase();\n }\n\n async setPtt(enabled: boolean, options: TciPttOptions = {}): Promise<void> {\n const trx = options.trx ?? this.options.trx;\n const args = options.source ? [trx, enabled, options.source] : [trx, enabled];\n await this.sendStateWrite(\n 'TRX',\n args,\n (state) => state.ptt[String(trx)] === enabled,\n `TRX:${trx},${enabled}`,\n options,\n );\n }\n\n async getPtt(trx = this.options.trx): Promise<boolean | undefined> {\n const reply = await this.request('TRX', [trx]);\n return parseBoolean(reply.args[1]) ?? this.state.ptt[String(trx)];\n }\n\n async setTune(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('TUNE', [trx, enabled]);\n }\n\n async setDrive(value: number, trx = this.options.trx): Promise<void> {\n await this.sendCommand('DRIVE', [trx, value]);\n }\n\n async setSplit(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('SPLIT_ENABLE', [trx, enabled]);\n }\n\n async configureAudio(config: TciAudioConfig): Promise<void> {\n const audio = {\n sampleRate: config.sampleRate,\n sampleType: normalizeSampleType(config.sampleType ?? TciSampleType.FLOAT32),\n channels: config.channels ?? 1,\n samplesPerFrame: config.samplesPerFrame ?? 512,\n txBufferingMs: config.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n this.state.audio = audio;\n\n await this.sendCommand('AUDIO_SAMPLERATE', [audio.sampleRate], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLE_TYPE', [sampleTypeName(audio.sampleType)], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_CHANNELS', [audio.channels], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLES', [audio.samplesPerFrame], { waitForReply: false });\n if (audio.txBufferingMs !== undefined) {\n await this.sendCommand('TX_STREAM_AUDIO_BUFFERING', [audio.txBufferingMs], { waitForReply: false });\n }\n this.emitState();\n }\n\n async startAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_START', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = true;\n this.emitState();\n }\n }\n\n async stopAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_STOP', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = false;\n this.emitState();\n }\n }\n\n sendTxAudio(options: BuildTxAudioFrameOptions): void {\n const frame = buildTxAudioFrame({ receiver: this.options.receiver, ...options });\n this.sendRawBinary(frame);\n }\n\n async setRxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('RX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async setTxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('TX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async sendCwMacro(index: number): Promise<void> {\n await this.sendCommand('CW_MACROS', [index]);\n }\n\n async sendCwMessage(message: string): Promise<void> {\n await this.sendCommand('CW_MSG', [message]);\n }\n\n async stopCw(): Promise<void> {\n await this.sendCommand('CW_MACROS_STOP');\n }\n\n private waitForState(\n predicate: (state: TciClientState) => boolean,\n timeoutMs: number,\n settleMs: number,\n description: string,\n ): { promise: Promise<void>; cancel: () => void } {\n let timeout: NodeJS.Timeout | undefined;\n let settleTimeout: NodeJS.Timeout | undefined;\n let resolved = false;\n let resolvePromise!: () => void;\n let rejectPromise!: (error: TciError) => void;\n\n const cleanup = () => {\n if (timeout) {\n clearTimeout(timeout);\n timeout = undefined;\n }\n if (settleTimeout) {\n clearTimeout(settleTimeout);\n settleTimeout = undefined;\n }\n this.off('state', onState);\n this.off('disconnected', onDisconnected);\n };\n\n const resolveNow = () => {\n resolved = true;\n cleanup();\n resolvePromise();\n };\n\n const check = () => {\n if (!predicate(this.getState())) {\n if (settleTimeout) {\n clearTimeout(settleTimeout);\n settleTimeout = undefined;\n }\n return;\n }\n\n if (settleMs <= 0) {\n resolveNow();\n return;\n }\n\n if (settleTimeout) {\n return;\n }\n\n settleTimeout = setTimeout(() => {\n settleTimeout = undefined;\n if (predicate(this.getState())) {\n resolveNow();\n }\n }, settleMs);\n };\n\n const onState = () => check();\n const onDisconnected = () => {\n if (resolved) {\n return;\n }\n cleanup();\n rejectPromise(new TciError('disconnected', `Disconnected while waiting for TCI state ${description}`));\n };\n\n const promise = new Promise<void>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n timeout = setTimeout(() => {\n cleanup();\n reject(new TciError('command-timeout', `Timed out waiting for TCI state ${description}`));\n }, timeoutMs);\n this.on('state', onState);\n this.on('disconnected', onDisconnected);\n check();\n });\n\n return {\n promise,\n cancel: cleanup,\n };\n }\n\n private waitForOpen(ws: WebSocket): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n try {\n ws.terminate();\n } catch {\n // ignore termination races\n }\n reject(new TciError('connect-timeout', `Timed out connecting to ${this.options.url}`));\n }, this.options.connectTimeoutMs);\n\n const cleanup = () => {\n clearTimeout(timer);\n ws.off('open', onOpen);\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onOpen = () => {\n cleanup();\n this.attachSocket(ws);\n this.state.connected = true;\n this.queue.setConnected(true);\n this.emit('connected');\n this.emitState();\n resolve();\n };\n const onClose = () => {\n cleanup();\n this.handleClose();\n reject(new TciError('disconnected', `Disconnected while connecting to ${this.options.url}`));\n };\n const onError = (error: Error) => {\n cleanup();\n this.handleError(error);\n reject(toTciError(error, 'disconnected'));\n };\n ws.once('open', onOpen);\n ws.once('close', onClose);\n ws.once('error', onError);\n });\n }\n\n private attachSocket(ws: WebSocket): void {\n ws.on('message', (data, isBinary) => this.handleMessage(data, isBinary));\n ws.on('close', () => this.handleClose());\n ws.on('error', (error) => this.handleError(error));\n }\n\n private async sendRaw(raw: string): Promise<void> {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n this.emit('tci:tx', raw);\n await new Promise<void>((resolve, reject) => {\n ws.send(raw, (error) => (error ? reject(error) : resolve()));\n });\n }\n\n private sendRawBinary(raw: Buffer): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n ws.send(raw, { binary: true });\n }\n\n private handleMessage(data: WebSocket.RawData, isBinary: boolean): void {\n try {\n if (isBinary) {\n this.handleBinary(data);\n return;\n }\n const raw = dataToBuffer(data).toString('utf8');\n const commands = parseTciText(raw);\n this.emit('tci:rx', raw, commands);\n for (const command of commands) {\n this.queue.handleCommand(command);\n this.applyCommand(command);\n this.emit('command', command);\n }\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private handleBinary(data: WebSocket.RawData): void {\n const frame = parseStreamFrame(dataToBuffer(data));\n this.emit('tci:binary', frame);\n this.emit('binary', frame);\n switch (frame.streamType) {\n case TciStreamType.RX_AUDIO_STREAM:\n this.emit('rxAudioFrame', frame);\n break;\n case TciStreamType.TX_CHRONO:\n this.emit('txChrono', {\n frame,\n receiver: frame.receiver,\n sampleRate: frame.sampleRate,\n channels: frame.channels,\n sampleType: frame.sampleType,\n sampleCount: frame.sampleCount,\n });\n break;\n case TciStreamType.LINEOUT_STREAM:\n this.emit('lineoutAudioFrame', frame);\n break;\n default:\n break;\n }\n }\n\n private applyCommand(command: TciCommand): void {\n const readyBefore = this.state.ready;\n switch (command.name) {\n case 'ready':\n this.state.ready = command.args.length === 0 ? true : (parseBoolean(command.args[0]) ?? true);\n break;\n case 'protocol':\n this.state.protocol = command.args[0];\n break;\n case 'device':\n this.state.device = command.args.join(',');\n break;\n case 'receive_only':\n this.state.receiveOnly = parseBoolean(command.args[0]);\n break;\n case 'trx_count':\n this.state.trxCount = parseNumber(command.args[0]);\n break;\n case 'channels_count':\n case 'channel_count':\n this.state.channelCount = parseNumber(command.args[0]);\n break;\n case 'vfo_limits':\n this.state.vfoLimits = parseNumberPair(command.args);\n break;\n case 'if_limits':\n this.state.ifLimits = parseNumberPair(command.args);\n break;\n case 'modulations_list':\n this.state.modulations = command.args.map((mode) => mode.toLowerCase());\n break;\n case 'vfo':\n this.applyVfo(command.args);\n break;\n case 'modulation':\n this.applyModulation(command.args);\n break;\n case 'trx':\n this.applyTrx(command.args);\n break;\n case 'tune':\n this.applyBooleanByFirstArg(this.state.tune, command.args);\n break;\n case 'drive':\n this.applyDrive(command.args);\n break;\n case 'split_enable':\n this.applyBooleanByFirstArg(this.state.split, command.args);\n break;\n case 'rx_channel_sensors':\n this.applyRxChannelSensors(command.args);\n break;\n case 'rx_sensors':\n this.applyRxSensors(command.args);\n break;\n case 'tx_sensors':\n this.applyTxSensors(command.args);\n break;\n case 'audio_samplerate':\n this.state.audio = {\n sampleRate: parseNumber(command.args[0]) ?? this.state.audio?.sampleRate ?? 12_000,\n sampleType: this.state.audio?.sampleType ?? TciSampleType.FLOAT32,\n channels: this.state.audio?.channels ?? 1,\n samplesPerFrame: this.state.audio?.samplesPerFrame ?? 512,\n txBufferingMs: this.state.audio?.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n break;\n default:\n break;\n }\n\n if (!readyBefore && this.state.ready) {\n this.emit('ready', this.getState());\n }\n this.emitState();\n }\n\n private applyVfo(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const receiver = parseNumber(args[0]);\n const vfo = parseNumber(args[1]);\n const frequency = parseNumber(args[2]);\n if (receiver === undefined || vfo === undefined || frequency === undefined || frequency < 0) {\n return;\n }\n this.state.frequencies[rxVfoKey(receiver, vfo)] = frequency;\n }\n\n private applyModulation(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const receiver = parseNumber(args[0]);\n if (receiver === undefined) {\n return;\n }\n const vfo = args.length >= 3 ? parseNumber(args[1]) ?? this.options.vfo : this.options.vfo;\n const mode = args.length >= 3 ? args[2] : args[1];\n if (!mode) {\n return;\n }\n this.state.modes[rxVfoKey(receiver, vfo)] = mode.toLowerCase();\n }\n\n private applyTrx(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n this.state.ptt[trx] = parseBoolean(args[1]) ?? false;\n this.state.pttSource[trx] = args[2]?.toLowerCase();\n }\n\n private applyBooleanByFirstArg(target: Record<string, boolean>, args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const key = args[0] ?? '0';\n const value = parseBoolean(args[1]);\n if (value !== undefined) {\n target[key] = value;\n }\n }\n\n private applyDrive(args: string[]): void {\n if (args.length === 1) {\n const value = parseNumber(args[0]);\n if (value !== undefined) {\n this.state.drive[String(this.options.trx)] = value;\n }\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n const value = parseNumber(args[1]);\n if (value !== undefined) {\n this.state.drive[trx] = value;\n }\n }\n\n private applyRxChannelSensors(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const key = rxVfoKey(args[0], args[1]);\n this.state.rxSensors[key] = {\n receiver: args[0],\n channel: args[1],\n levelDbm: parseNumber(args[2]) ?? args[2],\n };\n }\n\n private applyRxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.rxSensors[String(args[0])] = {\n receiver: args[0],\n levelDbm: parseNumber(args[1]) ?? args[1],\n deprecated: true,\n };\n }\n\n private applyTxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.txSensors[String(args[0])] = {\n trx: args[0],\n micDbm: parseNumber(args[1]) ?? args[1],\n rmsPowerW: parseNumber(args[2]) ?? args[2],\n peakPowerW: parseNumber(args[3]) ?? args[3],\n swr: parseNumber(args[4]) ?? args[4],\n };\n }\n\n private handleClose(reason?: unknown): void {\n this.ws = undefined;\n const wasConnected = this.state.connected;\n this.state.connected = false;\n this.state.ready = false;\n this.queue.setConnected(false);\n if (wasConnected) {\n this.emit('disconnected', reason);\n this.emitState();\n }\n }\n\n private handleError(error: unknown): void {\n const tciError = toTciError(error);\n this.emit('error', tciError);\n }\n\n private emitState(): void {\n this.emit('state', this.getState());\n }\n}\n\nexport function createTciClient(options: TciClientOptions): TciClient {\n return new TciClient(options);\n}\n\nfunction dataToBuffer(data: WebSocket.RawData): Buffer {\n if (Buffer.isBuffer(data)) {\n return data;\n }\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data);\n }\n if (Array.isArray(data)) {\n return Buffer.concat(data.map((item) => dataToBuffer(item)));\n }\n throw new TciError('protocol-error', 'Unsupported WebSocket data type');\n}\n\nfunction rxVfoKey(receiver: string | number, vfo: string | number): string {\n return `${receiver}:${vfo}`;\n}\n\nfunction parseNumber(value: string | undefined): number | undefined {\n if (value === undefined || value === '') {\n return undefined;\n }\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) {\n return undefined;\n }\n const normalized = value.toLowerCase();\n if (normalized === 'true' || normalized === '1' || normalized === 'on') {\n return true;\n }\n if (normalized === 'false' || normalized === '0' || normalized === 'off') {\n return false;\n }\n return undefined;\n}\n\nfunction parseNumberPair(args: string[]): [number, number] | undefined {\n const first = parseNumber(args[0]);\n const second = parseNumber(args[1]);\n return first === undefined || second === undefined ? undefined : [first, second];\n}\n\nfunction cloneState(state: TciClientState): TciClientState {\n return {\n ...state,\n modulations: [...state.modulations],\n frequencies: { ...state.frequencies },\n modes: { ...state.modes },\n ptt: { ...state.ptt },\n pttSource: { ...state.pttSource },\n tune: { ...state.tune },\n drive: { ...state.drive },\n split: { ...state.split },\n rxSensors: cloneNested(state.rxSensors),\n txSensors: cloneNested(state.txSensors),\n audio: state.audio ? { ...state.audio } : undefined,\n };\n}\n\nfunction cloneNested<T>(value: Record<string, T>): Record<string, T> {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, { ...(item as Record<string, unknown>) } as T]));\n}\n","import { TciError } from '../errors.js';\n\nexport const TCI_STREAM_HEADER_BYTES = 16 * 4;\n\nexport enum TciStreamType {\n IQ_STREAM = 0,\n RX_AUDIO_STREAM = 1,\n TX_AUDIO_STREAM = 2,\n TX_CHRONO = 3,\n LINEOUT_STREAM = 4,\n}\n\nexport enum TciSampleType {\n INT16 = 0,\n INT24 = 1,\n INT32 = 2,\n FLOAT32 = 3,\n}\n\nexport type TciSampleTypeName = 'int16' | 'int24' | 'int32' | 'float32';\n\nexport interface TciStreamFrame {\n receiver: number;\n sampleRate: number;\n sampleType: TciSampleType;\n codec: number;\n crc: number;\n /** Byte length of the payload following the 64-byte TCI stream header. */\n payloadLength: number;\n streamType: TciStreamType;\n channels: number;\n reserved: number[];\n payload: Buffer;\n /** Official Stream.length value: number of samples per channel in the payload. */\n sampleCount: number;\n}\n\nexport interface BuildStreamFrameOptions {\n receiver?: number;\n sampleRate: number;\n sampleType: TciSampleType | TciSampleTypeName;\n streamType: TciStreamType;\n channels: number;\n payload?: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView;\n samples?: Float32Array | readonly number[];\n codec?: number;\n crc?: number;\n reserved?: readonly number[];\n}\n\nexport interface BuildTxAudioFrameOptions extends Omit<BuildStreamFrameOptions, 'streamType'> {\n receiver?: number;\n}\n\nexport function parseStreamFrame(input: Buffer | ArrayBuffer | ArrayBufferView): TciStreamFrame {\n const buffer = toBuffer(input);\n if (buffer.byteLength < TCI_STREAM_HEADER_BYTES) {\n throw new TciError('invalid-frame', `TCI stream frame is shorter than ${TCI_STREAM_HEADER_BYTES} bytes`);\n }\n\n const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n const header = Array.from({ length: 16 }, (_, index) => view.getUint32(index * 4, true));\n const sampleType = normalizeSampleType(header[2]);\n let channels = header[7];\n const bytesPerSample = sampleTypeBytes(sampleType);\n const sampleCount = header[5];\n const actualPayloadLength = buffer.byteLength - TCI_STREAM_HEADER_BYTES;\n if (channels <= 0) {\n const inferredChannels = sampleCount > 0 ? actualPayloadLength / sampleCount / bytesPerSample : 1;\n if (!Number.isInteger(inferredChannels) || inferredChannels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n channels = inferredChannels;\n }\n const payloadLength = sampleCount * bytesPerSample * channels;\n const expectedLength = TCI_STREAM_HEADER_BYTES + payloadLength;\n if (buffer.byteLength !== expectedLength) {\n throw new TciError(\n 'invalid-frame',\n `TCI stream frame length mismatch: header says ${sampleCount} samples (${payloadLength} payload bytes), got ${buffer.byteLength - TCI_STREAM_HEADER_BYTES}`,\n );\n }\n if (payloadLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n\n return {\n receiver: header[0],\n sampleRate: header[1],\n sampleType,\n codec: header[3],\n crc: header[4],\n payloadLength,\n streamType: normalizeStreamType(header[6]),\n channels,\n reserved: header.slice(8),\n payload: buffer.subarray(TCI_STREAM_HEADER_BYTES),\n sampleCount,\n };\n}\n\nexport function buildStreamFrame(options: BuildStreamFrameOptions): Buffer {\n const sampleType = normalizeSampleType(options.sampleType);\n const payload = options.payload ? toBuffer(options.payload) : samplesToPayload(options.samples ?? [], sampleType);\n const channels = options.channels;\n if (channels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n const bytesPerSample = sampleTypeBytes(sampleType);\n if (payload.byteLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n const sampleCount = payload.byteLength / bytesPerSample / channels;\n\n const frame = Buffer.alloc(TCI_STREAM_HEADER_BYTES + payload.byteLength);\n const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);\n const reserved = options.reserved ?? [];\n const header = [\n options.receiver ?? 0,\n options.sampleRate,\n sampleType,\n options.codec ?? 0,\n options.crc ?? 0,\n sampleCount,\n options.streamType,\n channels,\n ...Array.from({ length: 8 }, (_, index) => reserved[index] ?? 0),\n ];\n header.forEach((value, index) => view.setUint32(index * 4, value >>> 0, true));\n payload.copy(frame, TCI_STREAM_HEADER_BYTES);\n return frame;\n}\n\nexport function buildTxAudioFrame(options: BuildTxAudioFrameOptions): Buffer {\n return buildStreamFrame({ ...options, streamType: TciStreamType.TX_AUDIO_STREAM });\n}\n\nexport function sampleTypeBytes(sampleType: TciSampleType | TciSampleTypeName): number {\n switch (normalizeSampleType(sampleType)) {\n case TciSampleType.INT16:\n return 2;\n case TciSampleType.INT24:\n return 3;\n case TciSampleType.INT32:\n case TciSampleType.FLOAT32:\n return 4;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function sampleTypeName(sampleType: TciSampleType): TciSampleTypeName {\n switch (sampleType) {\n case TciSampleType.INT16:\n return 'int16';\n case TciSampleType.INT24:\n return 'int24';\n case TciSampleType.INT32:\n return 'int32';\n case TciSampleType.FLOAT32:\n return 'float32';\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function normalizeSampleType(sampleType: TciSampleType | TciSampleTypeName | number): TciSampleType {\n if (typeof sampleType === 'string') {\n switch (sampleType.toLowerCase()) {\n case 'int16':\n return TciSampleType.INT16;\n case 'int24':\n return TciSampleType.INT24;\n case 'int32':\n return TciSampleType.INT32;\n case 'float32':\n return TciSampleType.FLOAT32;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n }\n if (sampleType >= TciSampleType.INT16 && sampleType <= TciSampleType.FLOAT32) {\n return sampleType as TciSampleType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n}\n\nexport function normalizeStreamType(streamType: TciStreamType | number): TciStreamType {\n if (streamType >= TciStreamType.IQ_STREAM && streamType <= TciStreamType.LINEOUT_STREAM) {\n return streamType as TciStreamType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI stream type: ${streamType}`);\n}\n\nexport function payloadToFloat32(frameOrPayload: TciStreamFrame | Buffer | Uint8Array, sampleType?: TciSampleType | TciSampleTypeName): Float32Array {\n const payload = isFrame(frameOrPayload) ? frameOrPayload.payload : toBuffer(frameOrPayload);\n const type = isFrame(frameOrPayload) ? frameOrPayload.sampleType : normalizeSampleType(sampleType ?? TciSampleType.FLOAT32);\n const bytes = sampleTypeBytes(type);\n if (payload.byteLength % bytes !== 0) {\n throw new TciError('invalid-frame', 'Payload length is not aligned to sample type');\n }\n\n const output = new Float32Array(payload.byteLength / bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < output.length; i += 1) {\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n output[i] = view.getInt16(offset, true) / 32768;\n break;\n case TciSampleType.INT24:\n output[i] = readInt24(view, offset) / 8388608;\n break;\n case TciSampleType.INT32:\n output[i] = view.getInt32(offset, true) / 2147483648;\n break;\n case TciSampleType.FLOAT32:\n output[i] = view.getFloat32(offset, true);\n break;\n }\n }\n return output;\n}\n\nexport function samplesToPayload(samples: Float32Array | readonly number[], sampleType: TciSampleType | TciSampleTypeName): Buffer {\n const type = normalizeSampleType(sampleType);\n const bytes = sampleTypeBytes(type);\n const payload = Buffer.alloc(samples.length * bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < samples.length; i += 1) {\n const value = clampSample(samples[i] ?? 0);\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n view.setInt16(offset, Math.round(value * 32767), true);\n break;\n case TciSampleType.INT24:\n writeInt24(view, offset, Math.round(value * 8388607));\n break;\n case TciSampleType.INT32:\n view.setInt32(offset, Math.round(value * 2147483647), true);\n break;\n case TciSampleType.FLOAT32:\n view.setFloat32(offset, value, true);\n break;\n }\n }\n return payload;\n}\n\nexport function pcm16ToFloat32(input: Buffer | Uint8Array | Int16Array): Float32Array {\n if (input instanceof Int16Array) {\n const output = new Float32Array(input.length);\n for (let i = 0; i < input.length; i += 1) {\n output[i] = input[i] / 32768;\n }\n return output;\n }\n return payloadToFloat32(toBuffer(input), TciSampleType.INT16);\n}\n\nexport function float32ToPcm16(samples: Float32Array | readonly number[]): Buffer {\n return samplesToPayload(samples, TciSampleType.INT16);\n}\n\nexport function deinterleaveChannels(samples: Float32Array, channels: number): Float32Array[] {\n if (channels <= 0 || samples.length % channels !== 0) {\n throw new TciError('invalid-frame', 'Cannot deinterleave samples with invalid channel count');\n }\n const frames = samples.length / channels;\n const outputs = Array.from({ length: channels }, () => new Float32Array(frames));\n for (let frame = 0; frame < frames; frame += 1) {\n for (let channel = 0; channel < channels; channel += 1) {\n outputs[channel][frame] = samples[frame * channels + channel];\n }\n }\n return outputs;\n}\n\nexport function mixToMono(samples: Float32Array, channels: number): Float32Array {\n if (channels === 1) {\n return samples;\n }\n const separated = deinterleaveChannels(samples, channels);\n const mono = new Float32Array(separated[0]?.length ?? 0);\n for (const channel of separated) {\n for (let i = 0; i < mono.length; i += 1) {\n mono[i] += channel[i] / channels;\n }\n }\n return mono;\n}\n\nfunction toBuffer(input: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView): Buffer {\n if (Buffer.isBuffer(input)) {\n return input;\n }\n if (input instanceof ArrayBuffer) {\n return Buffer.from(input);\n }\n if (ArrayBuffer.isView(input)) {\n return Buffer.from(input.buffer, input.byteOffset, input.byteLength);\n }\n return Buffer.from(input);\n}\n\nfunction isFrame(value: unknown): value is TciStreamFrame {\n return Boolean(value && typeof value === 'object' && 'payload' in value && 'sampleType' in value);\n}\n\nfunction clampSample(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n return Math.max(-1, Math.min(1, value));\n}\n\nfunction readInt24(view: DataView, offset: number): number {\n const value = view.getUint8(offset) | (view.getUint8(offset + 1) << 8) | (view.getUint8(offset + 2) << 16);\n return value & 0x800000 ? value | 0xff000000 : value;\n}\n\nfunction writeInt24(view: DataView, offset: number, value: number): void {\n const clamped = Math.max(-8388608, Math.min(8388607, value));\n view.setUint8(offset, clamped & 0xff);\n view.setUint8(offset + 1, (clamped >> 8) & 0xff);\n view.setUint8(offset + 2, (clamped >> 16) & 0xff);\n}\n","export interface TciCommand {\n /** Lower-case command name for case-insensitive matching. */\n name: string;\n /** Original command name as received, without surrounding whitespace. */\n originalName: string;\n /** Unescaped argument list. Empty commands have an empty array. */\n args: string[];\n /** Raw command fragment without the trailing semicolon. */\n raw: string;\n}\n\nexport type TciCommandInput = string | TciCommand;\n\nconst ESCAPE_TO_CHAR: Record<string, string> = {\n '^': ':',\n '~': ',',\n '*': ';',\n};\n\nconst CHAR_TO_ESCAPE: Record<string, string> = {\n ':': '^',\n ',': '~',\n ';': '*',\n};\n\nexport function escapeTciText(value: unknown): string {\n return String(value).replace(/[:;,]/g, (char) => CHAR_TO_ESCAPE[char] ?? char);\n}\n\nexport function unescapeTciText(value: string): string {\n return value.replace(/[\\^~*]/g, (char) => ESCAPE_TO_CHAR[char] ?? char);\n}\n\nexport function parseTciText(text: string | Buffer | ArrayBuffer | ArrayBufferView): TciCommand[] {\n const source = normalizeTextInput(text);\n const commands: TciCommand[] = [];\n\n for (const fragment of source.split(';')) {\n const raw = fragment.trim();\n if (!raw) {\n continue;\n }\n\n const colonIndex = raw.indexOf(':');\n const originalName = (colonIndex >= 0 ? raw.slice(0, colonIndex) : raw).trim();\n if (!originalName) {\n continue;\n }\n\n const argsText = colonIndex >= 0 ? raw.slice(colonIndex + 1) : undefined;\n commands.push({\n name: originalName.toLowerCase(),\n originalName,\n args: argsText === undefined ? [] : splitArgs(argsText),\n raw,\n });\n }\n\n return commands;\n}\n\nexport function parseTciCommand(input: TciCommandInput): TciCommand {\n if (typeof input !== 'string') {\n return input;\n }\n const [command] = parseTciText(input);\n if (!command) {\n throw new Error(`Invalid TCI command: ${input}`);\n }\n return command;\n}\n\nexport function formatTciCommand(name: string, args: readonly unknown[] = []): string {\n const commandName = name.trim().toUpperCase();\n if (!commandName) {\n throw new Error('TCI command name cannot be empty');\n }\n if (args.length === 0) {\n return `${commandName};`;\n }\n return `${commandName}:${args.map(escapeTciText).join(',')};`;\n}\n\nexport function normalizeCommandName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nexport function isCommandReplyTo(replyInput: TciCommandInput, requestInput: TciCommandInput): boolean {\n const reply = parseTciCommand(replyInput);\n const request = parseTciCommand(requestInput);\n if (reply.name !== request.name) {\n return false;\n }\n\n if (request.args.length === 0) {\n return true;\n }\n\n if (argsHavePrefix(reply.args, request.args)) {\n return true;\n }\n\n return isKnownVariantReply(reply, request);\n}\n\nexport function commandKey(command: TciCommandInput): string {\n const parsed = parseTciCommand(command);\n return `${parsed.name}:${parsed.args.join(',')}`;\n}\n\nfunction normalizeTextInput(text: string | Buffer | ArrayBuffer | ArrayBufferView): string {\n if (typeof text === 'string') {\n return text;\n }\n if (Buffer.isBuffer(text)) {\n return text.toString('utf8');\n }\n if (text instanceof ArrayBuffer) {\n return Buffer.from(text).toString('utf8');\n }\n return Buffer.from(text.buffer, text.byteOffset, text.byteLength).toString('utf8');\n}\n\nfunction splitArgs(argsText: string): string[] {\n return argsText.split(',').map((arg) => unescapeTciText(arg.trim()));\n}\n\nfunction argsHavePrefix(args: readonly string[], prefix: readonly string[]): boolean {\n if (args.length < prefix.length) {\n return false;\n }\n return prefix.every((arg, index) => args[index]?.toLowerCase() === arg.toLowerCase());\n}\n\nfunction isKnownVariantReply(reply: TciCommand, request: TciCommand): boolean {\n if (reply.name === 'modulation') {\n // ExpertSDR/WSJT-X variants can use MODULATION:rx,mode and MODULATION:rx,vfo,mode.\n if (request.args.length === 2 && reply.args.length >= 3) {\n return reply.args[0] === request.args[0] && reply.args[2]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n if (request.args.length === 3 && reply.args.length === 2) {\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[2]?.toLowerCase();\n }\n }\n\n if (reply.name === 'protocol') {\n return request.args.length <= 1;\n }\n\n if (reply.name === 'trx' && request.args.length >= 3 && reply.args.length >= 2) {\n // Official TRX writes may include an audio source as arg3, while replies only echo trx+state.\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n\n return false;\n}\n","import { TciError } from '../errors.js';\nimport {\n formatTciCommand,\n isCommandReplyTo,\n parseTciCommand,\n type TciCommand,\n type TciCommandInput,\n} from './text.js';\n\nexport type TciCommandMatcher = (reply: TciCommand, request: TciCommand) => boolean;\n\nexport interface QueueCommandOptions {\n timeoutMs?: number;\n matcher?: TciCommandMatcher;\n signal?: AbortSignal;\n}\n\nexport interface QueuedCommandResult {\n request: TciCommand;\n reply: TciCommand;\n}\n\ninterface PendingCommand {\n raw: string;\n request: TciCommand;\n timeoutMs: number;\n matcher: TciCommandMatcher;\n resolve: (result: QueuedCommandResult) => void;\n reject: (error: TciError) => void;\n timer?: NodeJS.Timeout;\n abortCleanup?: () => void;\n}\n\nexport interface TciCommandQueueOptions {\n send: (raw: string) => void | Promise<void>;\n timeoutMs?: number;\n}\n\nexport class TciCommandQueue {\n private readonly send: (raw: string) => void | Promise<void>;\n private readonly defaultTimeoutMs: number;\n private queue: PendingCommand[] = [];\n private active?: PendingCommand;\n private connected = true;\n\n constructor(options: TciCommandQueueOptions) {\n this.send = options.send;\n this.defaultTimeoutMs = options.timeoutMs ?? 1_000;\n }\n\n setConnected(connected: boolean): void {\n this.connected = connected;\n if (!connected) {\n this.cancelAll(new TciError('disconnected', 'TCI connection closed'));\n }\n }\n\n enqueue(command: TciCommandInput, options: QueueCommandOptions = {}): Promise<QueuedCommandResult> {\n const request = parseTciCommand(command);\n const raw = typeof command === 'string' ? ensureSemicolon(command) : formatTciCommand(command.originalName, command.args);\n\n if (!this.connected) {\n return Promise.reject(new TciError('not-connected', 'TCI socket is not connected'));\n }\n\n return new Promise<QueuedCommandResult>((resolve, reject) => {\n const pending: PendingCommand = {\n raw,\n request,\n timeoutMs: options.timeoutMs ?? this.defaultTimeoutMs,\n matcher: options.matcher ?? ((reply, req) => isCommandReplyTo(reply, req)),\n resolve,\n reject,\n };\n\n if (options.signal) {\n if (options.signal.aborted) {\n reject(new TciError('cancelled', 'TCI command was cancelled'));\n return;\n }\n const onAbort = () => this.rejectPending(pending, new TciError('cancelled', 'TCI command was cancelled'));\n options.signal.addEventListener('abort', onAbort, { once: true });\n pending.abortCleanup = () => options.signal?.removeEventListener('abort', onAbort);\n }\n\n this.queue.push(pending);\n void this.pump();\n });\n }\n\n handleCommand(commandInput: TciCommandInput): boolean {\n const active = this.active;\n if (!active) {\n return false;\n }\n const reply = parseTciCommand(commandInput);\n if (!active.matcher(reply, active.request)) {\n return false;\n }\n this.finishActive(reply);\n return true;\n }\n\n cancelAll(error = new TciError('cancelled', 'TCI command queue cancelled')): void {\n const pending = [...this.queue];\n this.queue = [];\n if (this.active) {\n pending.unshift(this.active);\n this.active = undefined;\n }\n for (const item of pending) {\n this.rejectPending(item, error);\n }\n }\n\n get size(): number {\n return this.queue.length + (this.active ? 1 : 0);\n }\n\n private async pump(): Promise<void> {\n if (this.active || !this.connected) {\n return;\n }\n const next = this.queue.shift();\n if (!next) {\n return;\n }\n\n this.active = next;\n next.timer = setTimeout(() => {\n this.rejectPending(next, new TciError('command-timeout', `Timed out waiting for TCI reply to ${next.raw}`));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }, next.timeoutMs);\n\n try {\n await this.send(next.raw);\n } catch (error) {\n this.rejectPending(next, new TciError('disconnected', error instanceof Error ? error.message : String(error), error));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }\n }\n\n private finishActive(reply: TciCommand): void {\n const active = this.active;\n if (!active) {\n return;\n }\n this.active = undefined;\n if (active.timer) {\n clearTimeout(active.timer);\n }\n active.abortCleanup?.();\n active.resolve({ request: active.request, reply });\n void this.pump();\n }\n\n private rejectPending(pending: PendingCommand, error: TciError): void {\n if (pending.timer) {\n clearTimeout(pending.timer);\n }\n pending.abortCleanup?.();\n const wasActive = this.active === pending;\n if (wasActive) {\n this.active = undefined;\n } else {\n this.queue = this.queue.filter((item) => item !== pending);\n }\n pending.reject(error);\n if (wasActive && this.connected) {\n void this.pump();\n }\n }\n}\n\nfunction ensureSemicolon(command: string): string {\n return command.trim().endsWith(';') ? command.trim() : `${command.trim()};`;\n}\n"],"mappings":"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","names":["TciStreamType","TciSampleType","WebSocket","value"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -14,6 +14,10 @@ interface TciClientOptions {
|
|
|
14
14
|
vfo?: number;
|
|
15
15
|
connectTimeoutMs?: number;
|
|
16
16
|
commandTimeoutMs?: number;
|
|
17
|
+
writeAckMode?: TciWriteAckMode;
|
|
18
|
+
writeTimeoutMs?: number;
|
|
19
|
+
writeSettleMs?: number;
|
|
20
|
+
frequencyWriteSettleMs?: number;
|
|
17
21
|
WebSocketImpl?: typeof WebSocket;
|
|
18
22
|
}
|
|
19
23
|
interface TciAudioConfig {
|
|
@@ -26,6 +30,15 @@ interface TciAudioConfig {
|
|
|
26
30
|
interface TciPttOptions {
|
|
27
31
|
source?: 'tci' | 'mic1' | 'mic2' | 'micpc' | 'ecoder2' | string;
|
|
28
32
|
trx?: number;
|
|
33
|
+
ackMode?: TciWriteAckMode;
|
|
34
|
+
timeoutMs?: number;
|
|
35
|
+
settleMs?: number;
|
|
36
|
+
}
|
|
37
|
+
type TciWriteAckMode = 'state' | 'reply' | 'optimistic';
|
|
38
|
+
interface TciWriteOptions {
|
|
39
|
+
ackMode?: TciWriteAckMode;
|
|
40
|
+
timeoutMs?: number;
|
|
41
|
+
settleMs?: number;
|
|
29
42
|
}
|
|
30
43
|
interface TciTxChronoRequest {
|
|
31
44
|
frame: TciStreamFrame;
|
|
@@ -67,6 +80,9 @@ interface TciClientEvents {
|
|
|
67
80
|
state: (state: TciClientState) => void;
|
|
68
81
|
command: (command: TciCommand) => void;
|
|
69
82
|
binary: (frame: TciStreamFrame) => void;
|
|
83
|
+
'tci:tx': (raw: string) => void;
|
|
84
|
+
'tci:rx': (raw: string, commands: TciCommand[]) => void;
|
|
85
|
+
'tci:binary': (frame: TciStreamFrame) => void;
|
|
70
86
|
rxAudioFrame: (frame: TciStreamFrame) => void;
|
|
71
87
|
lineoutAudioFrame: (frame: TciStreamFrame) => void;
|
|
72
88
|
txChrono: (request: TciTxChronoRequest) => void;
|
|
@@ -76,7 +92,7 @@ interface SendCommandOptions extends QueueCommandOptions {
|
|
|
76
92
|
waitForReply?: boolean;
|
|
77
93
|
}
|
|
78
94
|
declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
79
|
-
readonly options: Required<Pick<TciClientOptions, 'receiver' | 'trx' | 'vfo' | 'connectTimeoutMs' | 'commandTimeoutMs'>> & Pick<TciClientOptions, 'url'>;
|
|
95
|
+
readonly options: Required<Pick<TciClientOptions, 'receiver' | 'trx' | 'vfo' | 'connectTimeoutMs' | 'commandTimeoutMs' | 'writeAckMode' | 'writeTimeoutMs' | 'writeSettleMs' | 'frequencyWriteSettleMs'>> & Pick<TciClientOptions, 'url'>;
|
|
80
96
|
private readonly WebSocketImpl;
|
|
81
97
|
private ws?;
|
|
82
98
|
private readonly queue;
|
|
@@ -88,9 +104,10 @@ declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
|
88
104
|
getState(): TciClientState;
|
|
89
105
|
sendCommand(name: string, args?: readonly unknown[], options?: SendCommandOptions): Promise<TciCommand | undefined>;
|
|
90
106
|
request(name: string, args?: readonly unknown[], options?: QueueCommandOptions): Promise<TciCommand>;
|
|
91
|
-
|
|
107
|
+
sendStateWrite(name: string, args: readonly unknown[], isApplied: (state: TciClientState) => boolean, description?: string, options?: TciWriteOptions): Promise<void>;
|
|
108
|
+
setFrequency(frequencyHz: number, receiver?: number, vfo?: number, options?: TciWriteOptions): Promise<void>;
|
|
92
109
|
getFrequency(receiver?: number, vfo?: number): Promise<number | undefined>;
|
|
93
|
-
setMode(mode: string, receiver?: number): Promise<void>;
|
|
110
|
+
setMode(mode: string, receiver?: number, options?: TciWriteOptions): Promise<void>;
|
|
94
111
|
getMode(receiver?: number): Promise<string | undefined>;
|
|
95
112
|
setPtt(enabled: boolean, options?: TciPttOptions): Promise<void>;
|
|
96
113
|
getPtt(trx?: number): Promise<boolean | undefined>;
|
|
@@ -106,6 +123,7 @@ declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
|
106
123
|
sendCwMacro(index: number): Promise<void>;
|
|
107
124
|
sendCwMessage(message: string): Promise<void>;
|
|
108
125
|
stopCw(): Promise<void>;
|
|
126
|
+
private waitForState;
|
|
109
127
|
private waitForOpen;
|
|
110
128
|
private attachSocket;
|
|
111
129
|
private sendRaw;
|
|
@@ -127,4 +145,4 @@ declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
|
127
145
|
}
|
|
128
146
|
declare function createTciClient(options: TciClientOptions): TciClient;
|
|
129
147
|
|
|
130
|
-
export { BuildTxAudioFrameOptions, QueueCommandOptions, type SendCommandOptions, type TciAudioConfig, TciClient, type TciClientEvents, type TciClientOptions, type TciClientState, TciCommand, TciError, type TciPttOptions, TciSampleType, TciSampleTypeName, TciStreamFrame, type TciTxChronoRequest, createTciClient };
|
|
148
|
+
export { BuildTxAudioFrameOptions, QueueCommandOptions, type SendCommandOptions, type TciAudioConfig, TciClient, type TciClientEvents, type TciClientOptions, type TciClientState, TciCommand, TciError, type TciPttOptions, TciSampleType, TciSampleTypeName, TciStreamFrame, type TciTxChronoRequest, type TciWriteAckMode, type TciWriteOptions, createTciClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ interface TciClientOptions {
|
|
|
14
14
|
vfo?: number;
|
|
15
15
|
connectTimeoutMs?: number;
|
|
16
16
|
commandTimeoutMs?: number;
|
|
17
|
+
writeAckMode?: TciWriteAckMode;
|
|
18
|
+
writeTimeoutMs?: number;
|
|
19
|
+
writeSettleMs?: number;
|
|
20
|
+
frequencyWriteSettleMs?: number;
|
|
17
21
|
WebSocketImpl?: typeof WebSocket;
|
|
18
22
|
}
|
|
19
23
|
interface TciAudioConfig {
|
|
@@ -26,6 +30,15 @@ interface TciAudioConfig {
|
|
|
26
30
|
interface TciPttOptions {
|
|
27
31
|
source?: 'tci' | 'mic1' | 'mic2' | 'micpc' | 'ecoder2' | string;
|
|
28
32
|
trx?: number;
|
|
33
|
+
ackMode?: TciWriteAckMode;
|
|
34
|
+
timeoutMs?: number;
|
|
35
|
+
settleMs?: number;
|
|
36
|
+
}
|
|
37
|
+
type TciWriteAckMode = 'state' | 'reply' | 'optimistic';
|
|
38
|
+
interface TciWriteOptions {
|
|
39
|
+
ackMode?: TciWriteAckMode;
|
|
40
|
+
timeoutMs?: number;
|
|
41
|
+
settleMs?: number;
|
|
29
42
|
}
|
|
30
43
|
interface TciTxChronoRequest {
|
|
31
44
|
frame: TciStreamFrame;
|
|
@@ -67,6 +80,9 @@ interface TciClientEvents {
|
|
|
67
80
|
state: (state: TciClientState) => void;
|
|
68
81
|
command: (command: TciCommand) => void;
|
|
69
82
|
binary: (frame: TciStreamFrame) => void;
|
|
83
|
+
'tci:tx': (raw: string) => void;
|
|
84
|
+
'tci:rx': (raw: string, commands: TciCommand[]) => void;
|
|
85
|
+
'tci:binary': (frame: TciStreamFrame) => void;
|
|
70
86
|
rxAudioFrame: (frame: TciStreamFrame) => void;
|
|
71
87
|
lineoutAudioFrame: (frame: TciStreamFrame) => void;
|
|
72
88
|
txChrono: (request: TciTxChronoRequest) => void;
|
|
@@ -76,7 +92,7 @@ interface SendCommandOptions extends QueueCommandOptions {
|
|
|
76
92
|
waitForReply?: boolean;
|
|
77
93
|
}
|
|
78
94
|
declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
79
|
-
readonly options: Required<Pick<TciClientOptions, 'receiver' | 'trx' | 'vfo' | 'connectTimeoutMs' | 'commandTimeoutMs'>> & Pick<TciClientOptions, 'url'>;
|
|
95
|
+
readonly options: Required<Pick<TciClientOptions, 'receiver' | 'trx' | 'vfo' | 'connectTimeoutMs' | 'commandTimeoutMs' | 'writeAckMode' | 'writeTimeoutMs' | 'writeSettleMs' | 'frequencyWriteSettleMs'>> & Pick<TciClientOptions, 'url'>;
|
|
80
96
|
private readonly WebSocketImpl;
|
|
81
97
|
private ws?;
|
|
82
98
|
private readonly queue;
|
|
@@ -88,9 +104,10 @@ declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
|
88
104
|
getState(): TciClientState;
|
|
89
105
|
sendCommand(name: string, args?: readonly unknown[], options?: SendCommandOptions): Promise<TciCommand | undefined>;
|
|
90
106
|
request(name: string, args?: readonly unknown[], options?: QueueCommandOptions): Promise<TciCommand>;
|
|
91
|
-
|
|
107
|
+
sendStateWrite(name: string, args: readonly unknown[], isApplied: (state: TciClientState) => boolean, description?: string, options?: TciWriteOptions): Promise<void>;
|
|
108
|
+
setFrequency(frequencyHz: number, receiver?: number, vfo?: number, options?: TciWriteOptions): Promise<void>;
|
|
92
109
|
getFrequency(receiver?: number, vfo?: number): Promise<number | undefined>;
|
|
93
|
-
setMode(mode: string, receiver?: number): Promise<void>;
|
|
110
|
+
setMode(mode: string, receiver?: number, options?: TciWriteOptions): Promise<void>;
|
|
94
111
|
getMode(receiver?: number): Promise<string | undefined>;
|
|
95
112
|
setPtt(enabled: boolean, options?: TciPttOptions): Promise<void>;
|
|
96
113
|
getPtt(trx?: number): Promise<boolean | undefined>;
|
|
@@ -106,6 +123,7 @@ declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
|
106
123
|
sendCwMacro(index: number): Promise<void>;
|
|
107
124
|
sendCwMessage(message: string): Promise<void>;
|
|
108
125
|
stopCw(): Promise<void>;
|
|
126
|
+
private waitForState;
|
|
109
127
|
private waitForOpen;
|
|
110
128
|
private attachSocket;
|
|
111
129
|
private sendRaw;
|
|
@@ -127,4 +145,4 @@ declare class TciClient extends EventEmitter<TciClientEvents> {
|
|
|
127
145
|
}
|
|
128
146
|
declare function createTciClient(options: TciClientOptions): TciClient;
|
|
129
147
|
|
|
130
|
-
export { BuildTxAudioFrameOptions, QueueCommandOptions, type SendCommandOptions, type TciAudioConfig, TciClient, type TciClientEvents, type TciClientOptions, type TciClientState, TciCommand, TciError, type TciPttOptions, TciSampleType, TciSampleTypeName, TciStreamFrame, type TciTxChronoRequest, createTciClient };
|
|
148
|
+
export { BuildTxAudioFrameOptions, QueueCommandOptions, type SendCommandOptions, type TciAudioConfig, TciClient, type TciClientEvents, type TciClientOptions, type TciClientState, TciCommand, TciError, type TciPttOptions, TciSampleType, TciSampleTypeName, TciStreamFrame, type TciTxChronoRequest, type TciWriteAckMode, type TciWriteOptions, createTciClient };
|
package/dist/index.js
CHANGED
|
@@ -560,7 +560,11 @@ var TciClient = class extends EventEmitter {
|
|
|
560
560
|
trx: options.trx ?? 0,
|
|
561
561
|
vfo: options.vfo ?? 0,
|
|
562
562
|
connectTimeoutMs: options.connectTimeoutMs ?? 5e3,
|
|
563
|
-
commandTimeoutMs: options.commandTimeoutMs ?? 1e3
|
|
563
|
+
commandTimeoutMs: options.commandTimeoutMs ?? 1e3,
|
|
564
|
+
writeAckMode: options.writeAckMode ?? "state",
|
|
565
|
+
writeTimeoutMs: options.writeTimeoutMs ?? 3e3,
|
|
566
|
+
writeSettleMs: options.writeSettleMs ?? 0,
|
|
567
|
+
frequencyWriteSettleMs: options.frequencyWriteSettleMs ?? 250
|
|
564
568
|
};
|
|
565
569
|
this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;
|
|
566
570
|
this.queue = new TciCommandQueue({
|
|
@@ -646,15 +650,55 @@ var TciClient = class extends EventEmitter {
|
|
|
646
650
|
}
|
|
647
651
|
return reply;
|
|
648
652
|
}
|
|
649
|
-
async
|
|
650
|
-
|
|
653
|
+
async sendStateWrite(name, args, isApplied, description = formatTciCommand(name, args).replace(/;$/, ""), options = {}) {
|
|
654
|
+
const ackMode = options.ackMode ?? this.options.writeAckMode;
|
|
655
|
+
if (ackMode === "reply") {
|
|
656
|
+
await this.sendCommand(name, args, { timeoutMs: options.timeoutMs });
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (isApplied(this.getState())) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
if (ackMode === "optimistic") {
|
|
663
|
+
await this.sendCommand(name, args, { waitForReply: false });
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
const timeoutMs = options.timeoutMs ?? this.options.writeTimeoutMs;
|
|
667
|
+
const settleMs = options.settleMs ?? this.options.writeSettleMs;
|
|
668
|
+
const waiter = this.waitForState(isApplied, timeoutMs, settleMs, description);
|
|
669
|
+
try {
|
|
670
|
+
await this.sendCommand(name, args, { waitForReply: false });
|
|
671
|
+
await waiter.promise;
|
|
672
|
+
} catch (error) {
|
|
673
|
+
waiter.cancel();
|
|
674
|
+
throw error;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
async setFrequency(frequencyHz, receiver = this.options.receiver, vfo = this.options.vfo, options = {}) {
|
|
678
|
+
const frequency = Math.round(frequencyHz);
|
|
679
|
+
const key = rxVfoKey(receiver, vfo);
|
|
680
|
+
await this.sendStateWrite(
|
|
681
|
+
"VFO",
|
|
682
|
+
[receiver, vfo, frequency],
|
|
683
|
+
(state) => state.frequencies[key] === frequency,
|
|
684
|
+
`VFO:${receiver},${vfo},${frequency}`,
|
|
685
|
+
{ settleMs: this.options.frequencyWriteSettleMs, ...options }
|
|
686
|
+
);
|
|
651
687
|
}
|
|
652
688
|
async getFrequency(receiver = this.options.receiver, vfo = this.options.vfo) {
|
|
653
689
|
const reply = await this.request("VFO", [receiver, vfo]);
|
|
654
690
|
return parseNumber(reply.args[2]) ?? this.state.frequencies[rxVfoKey(receiver, vfo)];
|
|
655
691
|
}
|
|
656
|
-
async setMode(mode, receiver = this.options.receiver) {
|
|
657
|
-
|
|
692
|
+
async setMode(mode, receiver = this.options.receiver, options = {}) {
|
|
693
|
+
const normalizedMode = mode.toUpperCase();
|
|
694
|
+
const key = rxVfoKey(receiver, this.options.vfo);
|
|
695
|
+
await this.sendStateWrite(
|
|
696
|
+
"MODULATION",
|
|
697
|
+
[receiver, normalizedMode],
|
|
698
|
+
(state) => state.modes[key]?.toLowerCase() === normalizedMode.toLowerCase(),
|
|
699
|
+
`MODULATION:${receiver},${normalizedMode}`,
|
|
700
|
+
options
|
|
701
|
+
);
|
|
658
702
|
}
|
|
659
703
|
async getMode(receiver = this.options.receiver) {
|
|
660
704
|
const reply = await this.request("MODULATION", [receiver]);
|
|
@@ -664,7 +708,13 @@ var TciClient = class extends EventEmitter {
|
|
|
664
708
|
async setPtt(enabled, options = {}) {
|
|
665
709
|
const trx = options.trx ?? this.options.trx;
|
|
666
710
|
const args = options.source ? [trx, enabled, options.source] : [trx, enabled];
|
|
667
|
-
await this.
|
|
711
|
+
await this.sendStateWrite(
|
|
712
|
+
"TRX",
|
|
713
|
+
args,
|
|
714
|
+
(state) => state.ptt[String(trx)] === enabled,
|
|
715
|
+
`TRX:${trx},${enabled}`,
|
|
716
|
+
options
|
|
717
|
+
);
|
|
668
718
|
}
|
|
669
719
|
async getPtt(trx = this.options.trx) {
|
|
670
720
|
const reply = await this.request("TRX", [trx]);
|
|
@@ -733,6 +783,75 @@ var TciClient = class extends EventEmitter {
|
|
|
733
783
|
async stopCw() {
|
|
734
784
|
await this.sendCommand("CW_MACROS_STOP");
|
|
735
785
|
}
|
|
786
|
+
waitForState(predicate, timeoutMs, settleMs, description) {
|
|
787
|
+
let timeout;
|
|
788
|
+
let settleTimeout;
|
|
789
|
+
let resolved = false;
|
|
790
|
+
let resolvePromise;
|
|
791
|
+
let rejectPromise;
|
|
792
|
+
const cleanup = () => {
|
|
793
|
+
if (timeout) {
|
|
794
|
+
clearTimeout(timeout);
|
|
795
|
+
timeout = void 0;
|
|
796
|
+
}
|
|
797
|
+
if (settleTimeout) {
|
|
798
|
+
clearTimeout(settleTimeout);
|
|
799
|
+
settleTimeout = void 0;
|
|
800
|
+
}
|
|
801
|
+
this.off("state", onState);
|
|
802
|
+
this.off("disconnected", onDisconnected);
|
|
803
|
+
};
|
|
804
|
+
const resolveNow = () => {
|
|
805
|
+
resolved = true;
|
|
806
|
+
cleanup();
|
|
807
|
+
resolvePromise();
|
|
808
|
+
};
|
|
809
|
+
const check = () => {
|
|
810
|
+
if (!predicate(this.getState())) {
|
|
811
|
+
if (settleTimeout) {
|
|
812
|
+
clearTimeout(settleTimeout);
|
|
813
|
+
settleTimeout = void 0;
|
|
814
|
+
}
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (settleMs <= 0) {
|
|
818
|
+
resolveNow();
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
if (settleTimeout) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
settleTimeout = setTimeout(() => {
|
|
825
|
+
settleTimeout = void 0;
|
|
826
|
+
if (predicate(this.getState())) {
|
|
827
|
+
resolveNow();
|
|
828
|
+
}
|
|
829
|
+
}, settleMs);
|
|
830
|
+
};
|
|
831
|
+
const onState = () => check();
|
|
832
|
+
const onDisconnected = () => {
|
|
833
|
+
if (resolved) {
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
cleanup();
|
|
837
|
+
rejectPromise(new TciError("disconnected", `Disconnected while waiting for TCI state ${description}`));
|
|
838
|
+
};
|
|
839
|
+
const promise = new Promise((resolve, reject) => {
|
|
840
|
+
resolvePromise = resolve;
|
|
841
|
+
rejectPromise = reject;
|
|
842
|
+
timeout = setTimeout(() => {
|
|
843
|
+
cleanup();
|
|
844
|
+
reject(new TciError("command-timeout", `Timed out waiting for TCI state ${description}`));
|
|
845
|
+
}, timeoutMs);
|
|
846
|
+
this.on("state", onState);
|
|
847
|
+
this.on("disconnected", onDisconnected);
|
|
848
|
+
check();
|
|
849
|
+
});
|
|
850
|
+
return {
|
|
851
|
+
promise,
|
|
852
|
+
cancel: cleanup
|
|
853
|
+
};
|
|
854
|
+
}
|
|
736
855
|
waitForOpen(ws) {
|
|
737
856
|
return new Promise((resolve, reject) => {
|
|
738
857
|
const timer = setTimeout(() => {
|
|
@@ -783,6 +902,7 @@ var TciClient = class extends EventEmitter {
|
|
|
783
902
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
784
903
|
throw new TciError("not-connected", "TCI socket is not connected");
|
|
785
904
|
}
|
|
905
|
+
this.emit("tci:tx", raw);
|
|
786
906
|
await new Promise((resolve, reject) => {
|
|
787
907
|
ws.send(raw, (error) => error ? reject(error) : resolve());
|
|
788
908
|
});
|
|
@@ -800,7 +920,9 @@ var TciClient = class extends EventEmitter {
|
|
|
800
920
|
this.handleBinary(data);
|
|
801
921
|
return;
|
|
802
922
|
}
|
|
803
|
-
const
|
|
923
|
+
const raw = dataToBuffer(data).toString("utf8");
|
|
924
|
+
const commands = parseTciText(raw);
|
|
925
|
+
this.emit("tci:rx", raw, commands);
|
|
804
926
|
for (const command of commands) {
|
|
805
927
|
this.queue.handleCommand(command);
|
|
806
928
|
this.applyCommand(command);
|
|
@@ -812,6 +934,7 @@ var TciClient = class extends EventEmitter {
|
|
|
812
934
|
}
|
|
813
935
|
handleBinary(data) {
|
|
814
936
|
const frame = parseStreamFrame(dataToBuffer(data));
|
|
937
|
+
this.emit("tci:binary", frame);
|
|
815
938
|
this.emit("binary", frame);
|
|
816
939
|
switch (frame.streamType) {
|
|
817
940
|
case 1 /* RX_AUDIO_STREAM */:
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/client/TciClient.ts","../src/audio/streamFrame.ts","../src/protocol/text.ts","../src/protocol/commandQueue.ts"],"sourcesContent":["export type TciErrorCode =\n | 'connect-timeout'\n | 'command-timeout'\n | 'not-connected'\n | 'disconnected'\n | 'protocol-error'\n | 'invalid-frame'\n | 'cancelled';\n\nexport class TciError extends Error {\n readonly code: TciErrorCode;\n readonly details?: unknown;\n\n constructor(code: TciErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TciError';\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toTciError(error: unknown, fallbackCode: TciErrorCode = 'protocol-error'): TciError {\n if (error instanceof TciError) {\n return error;\n }\n if (error instanceof Error) {\n return new TciError(fallbackCode, error.message, error);\n }\n return new TciError(fallbackCode, String(error), error);\n}\n","import { EventEmitter } from 'eventemitter3';\nimport WebSocket from 'ws';\nimport { TciError, toTciError } from '../errors.js';\nimport {\n buildTxAudioFrame,\n normalizeSampleType,\n parseStreamFrame,\n sampleTypeName,\n TciSampleType,\n TciStreamType,\n type BuildTxAudioFrameOptions,\n type TciSampleTypeName,\n type TciStreamFrame,\n} from '../audio/streamFrame.js';\nimport {\n formatTciCommand,\n parseTciText,\n TciCommandQueue,\n type QueueCommandOptions,\n type TciCommand,\n} from '../protocol/index.js';\n\nexport interface TciClientOptions {\n url: string;\n receiver?: number;\n trx?: number;\n vfo?: number;\n connectTimeoutMs?: number;\n commandTimeoutMs?: number;\n WebSocketImpl?: typeof WebSocket;\n}\n\nexport interface TciAudioConfig {\n sampleRate: 8_000 | 12_000 | 24_000 | 48_000 | number;\n sampleType?: TciSampleType | TciSampleTypeName;\n channels?: 1 | 2 | number;\n samplesPerFrame?: number;\n txBufferingMs?: number;\n}\n\nexport interface TciPttOptions {\n source?: 'tci' | 'mic1' | 'mic2' | 'micpc' | 'ecoder2' | string;\n trx?: number;\n}\n\nexport interface TciTxChronoRequest {\n frame: TciStreamFrame;\n receiver: number;\n sampleRate: number;\n channels: number;\n sampleType: TciSampleType;\n sampleCount: number;\n}\n\nexport interface TciClientState {\n connected: boolean;\n ready: boolean;\n protocol?: string;\n device?: string;\n receiveOnly?: boolean;\n trxCount?: number;\n channelCount?: number;\n vfoLimits?: [number, number];\n ifLimits?: [number, number];\n modulations: string[];\n frequencies: Record<string, number>;\n modes: Record<string, string>;\n ptt: Record<string, boolean>;\n pttSource: Record<string, string | undefined>;\n tune: Record<string, boolean>;\n drive: Record<string, number>;\n split: Record<string, boolean>;\n rxSensors: Record<string, Record<string, number | string | boolean>>;\n txSensors: Record<string, Record<string, number | string | boolean>>;\n audio?: Required<Pick<TciAudioConfig, 'sampleRate' | 'channels' | 'sampleType' | 'samplesPerFrame'>> & {\n txBufferingMs?: number;\n running: boolean;\n };\n}\n\nexport interface TciClientEvents {\n connected: () => void;\n disconnected: (reason?: unknown) => void;\n ready: (state: TciClientState) => void;\n state: (state: TciClientState) => void;\n command: (command: TciCommand) => void;\n binary: (frame: TciStreamFrame) => void;\n rxAudioFrame: (frame: TciStreamFrame) => void;\n lineoutAudioFrame: (frame: TciStreamFrame) => void;\n txChrono: (request: TciTxChronoRequest) => void;\n error: (error: TciError) => void;\n}\n\nexport interface SendCommandOptions extends QueueCommandOptions {\n waitForReply?: boolean;\n}\n\nexport class TciClient extends EventEmitter<TciClientEvents> {\n readonly options: Required<Pick<TciClientOptions, 'receiver' | 'trx' | 'vfo' | 'connectTimeoutMs' | 'commandTimeoutMs'>> &\n Pick<TciClientOptions, 'url'>;\n\n private readonly WebSocketImpl: typeof WebSocket;\n private ws?: WebSocket;\n private readonly queue: TciCommandQueue;\n private readonly state: TciClientState;\n\n constructor(options: TciClientOptions) {\n super();\n this.options = {\n url: options.url,\n receiver: options.receiver ?? 0,\n trx: options.trx ?? 0,\n vfo: options.vfo ?? 0,\n connectTimeoutMs: options.connectTimeoutMs ?? 5_000,\n commandTimeoutMs: options.commandTimeoutMs ?? 1_000,\n };\n this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;\n this.queue = new TciCommandQueue({\n timeoutMs: this.options.commandTimeoutMs,\n send: (raw) => this.sendRaw(raw),\n });\n this.queue.setConnected(false);\n this.state = {\n connected: false,\n ready: false,\n modulations: [],\n frequencies: {},\n modes: {},\n ptt: {},\n pttSource: {},\n tune: {},\n drive: {},\n split: {},\n rxSensors: {},\n txSensors: {},\n };\n }\n\n async connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {\n await this.waitForOpen(this.ws);\n return;\n }\n\n const ws = new this.WebSocketImpl(this.options.url);\n this.ws = ws;\n await this.waitForOpen(ws);\n }\n\n async disconnect(code = 1000, reason = 'client disconnect'): Promise<void> {\n const ws = this.ws;\n if (!ws) {\n return;\n }\n if (ws.readyState === WebSocket.CLOSED) {\n this.handleClose();\n return;\n }\n await new Promise<void>((resolve) => {\n const cleanup = () => {\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onClose = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n resolve();\n };\n ws.once('close', onClose);\n ws.once('error', onError);\n ws.close(code, reason);\n setTimeout(() => resolve(), 1_000).unref?.();\n });\n this.handleClose();\n }\n\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n getState(): TciClientState {\n return cloneState(this.state);\n }\n\n async sendCommand(name: string, args: readonly unknown[] = [], options: SendCommandOptions = {}): Promise<TciCommand | undefined> {\n const raw = formatTciCommand(name, args);\n if (options.waitForReply === false) {\n await this.sendRaw(raw);\n return undefined;\n }\n const result = await this.queue.enqueue(raw, options);\n return result.reply;\n }\n\n async request(name: string, args: readonly unknown[] = [], options: QueueCommandOptions = {}): Promise<TciCommand> {\n const reply = await this.sendCommand(name, args, { ...options, waitForReply: true });\n if (!reply) {\n throw new TciError('protocol-error', `No reply for ${name}`);\n }\n return reply;\n }\n\n async setFrequency(frequencyHz: number, receiver = this.options.receiver, vfo = this.options.vfo): Promise<void> {\n await this.sendCommand('VFO', [receiver, vfo, Math.round(frequencyHz)]);\n }\n\n async getFrequency(receiver = this.options.receiver, vfo = this.options.vfo): Promise<number | undefined> {\n const reply = await this.request('VFO', [receiver, vfo]);\n return parseNumber(reply.args[2]) ?? this.state.frequencies[rxVfoKey(receiver, vfo)];\n }\n\n async setMode(mode: string, receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('MODULATION', [receiver, mode.toUpperCase()]);\n }\n\n async getMode(receiver = this.options.receiver): Promise<string | undefined> {\n const reply = await this.request('MODULATION', [receiver]);\n const mode = reply.args.length >= 3 ? reply.args[2] : reply.args[1];\n return (mode ?? this.state.modes[rxVfoKey(receiver, this.options.vfo)])?.toLowerCase();\n }\n\n async setPtt(enabled: boolean, options: TciPttOptions = {}): Promise<void> {\n const trx = options.trx ?? this.options.trx;\n const args = options.source ? [trx, enabled, options.source] : [trx, enabled];\n await this.sendCommand('TRX', args);\n }\n\n async getPtt(trx = this.options.trx): Promise<boolean | undefined> {\n const reply = await this.request('TRX', [trx]);\n return parseBoolean(reply.args[1]) ?? this.state.ptt[String(trx)];\n }\n\n async setTune(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('TUNE', [trx, enabled]);\n }\n\n async setDrive(value: number, trx = this.options.trx): Promise<void> {\n await this.sendCommand('DRIVE', [trx, value]);\n }\n\n async setSplit(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('SPLIT_ENABLE', [trx, enabled]);\n }\n\n async configureAudio(config: TciAudioConfig): Promise<void> {\n const audio = {\n sampleRate: config.sampleRate,\n sampleType: normalizeSampleType(config.sampleType ?? TciSampleType.FLOAT32),\n channels: config.channels ?? 1,\n samplesPerFrame: config.samplesPerFrame ?? 512,\n txBufferingMs: config.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n this.state.audio = audio;\n\n await this.sendCommand('AUDIO_SAMPLERATE', [audio.sampleRate], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLE_TYPE', [sampleTypeName(audio.sampleType)], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_CHANNELS', [audio.channels], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLES', [audio.samplesPerFrame], { waitForReply: false });\n if (audio.txBufferingMs !== undefined) {\n await this.sendCommand('TX_STREAM_AUDIO_BUFFERING', [audio.txBufferingMs], { waitForReply: false });\n }\n this.emitState();\n }\n\n async startAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_START', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = true;\n this.emitState();\n }\n }\n\n async stopAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_STOP', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = false;\n this.emitState();\n }\n }\n\n sendTxAudio(options: BuildTxAudioFrameOptions): void {\n const frame = buildTxAudioFrame({ receiver: this.options.receiver, ...options });\n this.sendRawBinary(frame);\n }\n\n async setRxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('RX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async setTxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('TX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async sendCwMacro(index: number): Promise<void> {\n await this.sendCommand('CW_MACROS', [index]);\n }\n\n async sendCwMessage(message: string): Promise<void> {\n await this.sendCommand('CW_MSG', [message]);\n }\n\n async stopCw(): Promise<void> {\n await this.sendCommand('CW_MACROS_STOP');\n }\n\n private waitForOpen(ws: WebSocket): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n try {\n ws.terminate();\n } catch {\n // ignore termination races\n }\n reject(new TciError('connect-timeout', `Timed out connecting to ${this.options.url}`));\n }, this.options.connectTimeoutMs);\n\n const cleanup = () => {\n clearTimeout(timer);\n ws.off('open', onOpen);\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onOpen = () => {\n cleanup();\n this.attachSocket(ws);\n this.state.connected = true;\n this.queue.setConnected(true);\n this.emit('connected');\n this.emitState();\n resolve();\n };\n const onClose = () => {\n cleanup();\n this.handleClose();\n reject(new TciError('disconnected', `Disconnected while connecting to ${this.options.url}`));\n };\n const onError = (error: Error) => {\n cleanup();\n this.handleError(error);\n reject(toTciError(error, 'disconnected'));\n };\n ws.once('open', onOpen);\n ws.once('close', onClose);\n ws.once('error', onError);\n });\n }\n\n private attachSocket(ws: WebSocket): void {\n ws.on('message', (data, isBinary) => this.handleMessage(data, isBinary));\n ws.on('close', () => this.handleClose());\n ws.on('error', (error) => this.handleError(error));\n }\n\n private async sendRaw(raw: string): Promise<void> {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n await new Promise<void>((resolve, reject) => {\n ws.send(raw, (error) => (error ? reject(error) : resolve()));\n });\n }\n\n private sendRawBinary(raw: Buffer): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n ws.send(raw, { binary: true });\n }\n\n private handleMessage(data: WebSocket.RawData, isBinary: boolean): void {\n try {\n if (isBinary) {\n this.handleBinary(data);\n return;\n }\n const commands = parseTciText(dataToBuffer(data));\n for (const command of commands) {\n this.queue.handleCommand(command);\n this.applyCommand(command);\n this.emit('command', command);\n }\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private handleBinary(data: WebSocket.RawData): void {\n const frame = parseStreamFrame(dataToBuffer(data));\n this.emit('binary', frame);\n switch (frame.streamType) {\n case TciStreamType.RX_AUDIO_STREAM:\n this.emit('rxAudioFrame', frame);\n break;\n case TciStreamType.TX_CHRONO:\n this.emit('txChrono', {\n frame,\n receiver: frame.receiver,\n sampleRate: frame.sampleRate,\n channels: frame.channels,\n sampleType: frame.sampleType,\n sampleCount: frame.sampleCount,\n });\n break;\n case TciStreamType.LINEOUT_STREAM:\n this.emit('lineoutAudioFrame', frame);\n break;\n default:\n break;\n }\n }\n\n private applyCommand(command: TciCommand): void {\n const readyBefore = this.state.ready;\n switch (command.name) {\n case 'ready':\n this.state.ready = command.args.length === 0 ? true : (parseBoolean(command.args[0]) ?? true);\n break;\n case 'protocol':\n this.state.protocol = command.args[0];\n break;\n case 'device':\n this.state.device = command.args.join(',');\n break;\n case 'receive_only':\n this.state.receiveOnly = parseBoolean(command.args[0]);\n break;\n case 'trx_count':\n this.state.trxCount = parseNumber(command.args[0]);\n break;\n case 'channels_count':\n case 'channel_count':\n this.state.channelCount = parseNumber(command.args[0]);\n break;\n case 'vfo_limits':\n this.state.vfoLimits = parseNumberPair(command.args);\n break;\n case 'if_limits':\n this.state.ifLimits = parseNumberPair(command.args);\n break;\n case 'modulations_list':\n this.state.modulations = command.args.map((mode) => mode.toLowerCase());\n break;\n case 'vfo':\n this.applyVfo(command.args);\n break;\n case 'modulation':\n this.applyModulation(command.args);\n break;\n case 'trx':\n this.applyTrx(command.args);\n break;\n case 'tune':\n this.applyBooleanByFirstArg(this.state.tune, command.args);\n break;\n case 'drive':\n this.applyDrive(command.args);\n break;\n case 'split_enable':\n this.applyBooleanByFirstArg(this.state.split, command.args);\n break;\n case 'rx_channel_sensors':\n this.applyRxChannelSensors(command.args);\n break;\n case 'rx_sensors':\n this.applyRxSensors(command.args);\n break;\n case 'tx_sensors':\n this.applyTxSensors(command.args);\n break;\n case 'audio_samplerate':\n this.state.audio = {\n sampleRate: parseNumber(command.args[0]) ?? this.state.audio?.sampleRate ?? 12_000,\n sampleType: this.state.audio?.sampleType ?? TciSampleType.FLOAT32,\n channels: this.state.audio?.channels ?? 1,\n samplesPerFrame: this.state.audio?.samplesPerFrame ?? 512,\n txBufferingMs: this.state.audio?.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n break;\n default:\n break;\n }\n\n if (!readyBefore && this.state.ready) {\n this.emit('ready', this.getState());\n }\n this.emitState();\n }\n\n private applyVfo(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const receiver = parseNumber(args[0]);\n const vfo = parseNumber(args[1]);\n const frequency = parseNumber(args[2]);\n if (receiver === undefined || vfo === undefined || frequency === undefined || frequency < 0) {\n return;\n }\n this.state.frequencies[rxVfoKey(receiver, vfo)] = frequency;\n }\n\n private applyModulation(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const receiver = parseNumber(args[0]);\n if (receiver === undefined) {\n return;\n }\n const vfo = args.length >= 3 ? parseNumber(args[1]) ?? this.options.vfo : this.options.vfo;\n const mode = args.length >= 3 ? args[2] : args[1];\n if (!mode) {\n return;\n }\n this.state.modes[rxVfoKey(receiver, vfo)] = mode.toLowerCase();\n }\n\n private applyTrx(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n this.state.ptt[trx] = parseBoolean(args[1]) ?? false;\n this.state.pttSource[trx] = args[2]?.toLowerCase();\n }\n\n private applyBooleanByFirstArg(target: Record<string, boolean>, args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const key = args[0] ?? '0';\n const value = parseBoolean(args[1]);\n if (value !== undefined) {\n target[key] = value;\n }\n }\n\n private applyDrive(args: string[]): void {\n if (args.length === 1) {\n const value = parseNumber(args[0]);\n if (value !== undefined) {\n this.state.drive[String(this.options.trx)] = value;\n }\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n const value = parseNumber(args[1]);\n if (value !== undefined) {\n this.state.drive[trx] = value;\n }\n }\n\n private applyRxChannelSensors(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const key = rxVfoKey(args[0], args[1]);\n this.state.rxSensors[key] = {\n receiver: args[0],\n channel: args[1],\n levelDbm: parseNumber(args[2]) ?? args[2],\n };\n }\n\n private applyRxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.rxSensors[String(args[0])] = {\n receiver: args[0],\n levelDbm: parseNumber(args[1]) ?? args[1],\n deprecated: true,\n };\n }\n\n private applyTxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.txSensors[String(args[0])] = {\n trx: args[0],\n micDbm: parseNumber(args[1]) ?? args[1],\n rmsPowerW: parseNumber(args[2]) ?? args[2],\n peakPowerW: parseNumber(args[3]) ?? args[3],\n swr: parseNumber(args[4]) ?? args[4],\n };\n }\n\n private handleClose(reason?: unknown): void {\n this.ws = undefined;\n const wasConnected = this.state.connected;\n this.state.connected = false;\n this.state.ready = false;\n this.queue.setConnected(false);\n if (wasConnected) {\n this.emit('disconnected', reason);\n this.emitState();\n }\n }\n\n private handleError(error: unknown): void {\n const tciError = toTciError(error);\n this.emit('error', tciError);\n }\n\n private emitState(): void {\n this.emit('state', this.getState());\n }\n}\n\nexport function createTciClient(options: TciClientOptions): TciClient {\n return new TciClient(options);\n}\n\nfunction dataToBuffer(data: WebSocket.RawData): Buffer {\n if (Buffer.isBuffer(data)) {\n return data;\n }\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data);\n }\n if (Array.isArray(data)) {\n return Buffer.concat(data.map((item) => dataToBuffer(item)));\n }\n throw new TciError('protocol-error', 'Unsupported WebSocket data type');\n}\n\nfunction rxVfoKey(receiver: string | number, vfo: string | number): string {\n return `${receiver}:${vfo}`;\n}\n\nfunction parseNumber(value: string | undefined): number | undefined {\n if (value === undefined || value === '') {\n return undefined;\n }\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) {\n return undefined;\n }\n const normalized = value.toLowerCase();\n if (normalized === 'true' || normalized === '1' || normalized === 'on') {\n return true;\n }\n if (normalized === 'false' || normalized === '0' || normalized === 'off') {\n return false;\n }\n return undefined;\n}\n\nfunction parseNumberPair(args: string[]): [number, number] | undefined {\n const first = parseNumber(args[0]);\n const second = parseNumber(args[1]);\n return first === undefined || second === undefined ? undefined : [first, second];\n}\n\nfunction cloneState(state: TciClientState): TciClientState {\n return {\n ...state,\n modulations: [...state.modulations],\n frequencies: { ...state.frequencies },\n modes: { ...state.modes },\n ptt: { ...state.ptt },\n pttSource: { ...state.pttSource },\n tune: { ...state.tune },\n drive: { ...state.drive },\n split: { ...state.split },\n rxSensors: cloneNested(state.rxSensors),\n txSensors: cloneNested(state.txSensors),\n audio: state.audio ? { ...state.audio } : undefined,\n };\n}\n\nfunction cloneNested<T>(value: Record<string, T>): Record<string, T> {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, { ...(item as Record<string, unknown>) } as T]));\n}\n","import { TciError } from '../errors.js';\n\nexport const TCI_STREAM_HEADER_BYTES = 16 * 4;\n\nexport enum TciStreamType {\n IQ_STREAM = 0,\n RX_AUDIO_STREAM = 1,\n TX_AUDIO_STREAM = 2,\n TX_CHRONO = 3,\n LINEOUT_STREAM = 4,\n}\n\nexport enum TciSampleType {\n INT16 = 0,\n INT24 = 1,\n INT32 = 2,\n FLOAT32 = 3,\n}\n\nexport type TciSampleTypeName = 'int16' | 'int24' | 'int32' | 'float32';\n\nexport interface TciStreamFrame {\n receiver: number;\n sampleRate: number;\n sampleType: TciSampleType;\n codec: number;\n crc: number;\n /** Byte length of the payload following the 64-byte TCI stream header. */\n payloadLength: number;\n streamType: TciStreamType;\n channels: number;\n reserved: number[];\n payload: Buffer;\n /** Official Stream.length value: number of samples per channel in the payload. */\n sampleCount: number;\n}\n\nexport interface BuildStreamFrameOptions {\n receiver?: number;\n sampleRate: number;\n sampleType: TciSampleType | TciSampleTypeName;\n streamType: TciStreamType;\n channels: number;\n payload?: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView;\n samples?: Float32Array | readonly number[];\n codec?: number;\n crc?: number;\n reserved?: readonly number[];\n}\n\nexport interface BuildTxAudioFrameOptions extends Omit<BuildStreamFrameOptions, 'streamType'> {\n receiver?: number;\n}\n\nexport function parseStreamFrame(input: Buffer | ArrayBuffer | ArrayBufferView): TciStreamFrame {\n const buffer = toBuffer(input);\n if (buffer.byteLength < TCI_STREAM_HEADER_BYTES) {\n throw new TciError('invalid-frame', `TCI stream frame is shorter than ${TCI_STREAM_HEADER_BYTES} bytes`);\n }\n\n const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n const header = Array.from({ length: 16 }, (_, index) => view.getUint32(index * 4, true));\n const sampleType = normalizeSampleType(header[2]);\n let channels = header[7];\n const bytesPerSample = sampleTypeBytes(sampleType);\n const sampleCount = header[5];\n const actualPayloadLength = buffer.byteLength - TCI_STREAM_HEADER_BYTES;\n if (channels <= 0) {\n const inferredChannels = sampleCount > 0 ? actualPayloadLength / sampleCount / bytesPerSample : 1;\n if (!Number.isInteger(inferredChannels) || inferredChannels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n channels = inferredChannels;\n }\n const payloadLength = sampleCount * bytesPerSample * channels;\n const expectedLength = TCI_STREAM_HEADER_BYTES + payloadLength;\n if (buffer.byteLength !== expectedLength) {\n throw new TciError(\n 'invalid-frame',\n `TCI stream frame length mismatch: header says ${sampleCount} samples (${payloadLength} payload bytes), got ${buffer.byteLength - TCI_STREAM_HEADER_BYTES}`,\n );\n }\n if (payloadLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n\n return {\n receiver: header[0],\n sampleRate: header[1],\n sampleType,\n codec: header[3],\n crc: header[4],\n payloadLength,\n streamType: normalizeStreamType(header[6]),\n channels,\n reserved: header.slice(8),\n payload: buffer.subarray(TCI_STREAM_HEADER_BYTES),\n sampleCount,\n };\n}\n\nexport function buildStreamFrame(options: BuildStreamFrameOptions): Buffer {\n const sampleType = normalizeSampleType(options.sampleType);\n const payload = options.payload ? toBuffer(options.payload) : samplesToPayload(options.samples ?? [], sampleType);\n const channels = options.channels;\n if (channels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n const bytesPerSample = sampleTypeBytes(sampleType);\n if (payload.byteLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n const sampleCount = payload.byteLength / bytesPerSample / channels;\n\n const frame = Buffer.alloc(TCI_STREAM_HEADER_BYTES + payload.byteLength);\n const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);\n const reserved = options.reserved ?? [];\n const header = [\n options.receiver ?? 0,\n options.sampleRate,\n sampleType,\n options.codec ?? 0,\n options.crc ?? 0,\n sampleCount,\n options.streamType,\n channels,\n ...Array.from({ length: 8 }, (_, index) => reserved[index] ?? 0),\n ];\n header.forEach((value, index) => view.setUint32(index * 4, value >>> 0, true));\n payload.copy(frame, TCI_STREAM_HEADER_BYTES);\n return frame;\n}\n\nexport function buildTxAudioFrame(options: BuildTxAudioFrameOptions): Buffer {\n return buildStreamFrame({ ...options, streamType: TciStreamType.TX_AUDIO_STREAM });\n}\n\nexport function sampleTypeBytes(sampleType: TciSampleType | TciSampleTypeName): number {\n switch (normalizeSampleType(sampleType)) {\n case TciSampleType.INT16:\n return 2;\n case TciSampleType.INT24:\n return 3;\n case TciSampleType.INT32:\n case TciSampleType.FLOAT32:\n return 4;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function sampleTypeName(sampleType: TciSampleType): TciSampleTypeName {\n switch (sampleType) {\n case TciSampleType.INT16:\n return 'int16';\n case TciSampleType.INT24:\n return 'int24';\n case TciSampleType.INT32:\n return 'int32';\n case TciSampleType.FLOAT32:\n return 'float32';\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function normalizeSampleType(sampleType: TciSampleType | TciSampleTypeName | number): TciSampleType {\n if (typeof sampleType === 'string') {\n switch (sampleType.toLowerCase()) {\n case 'int16':\n return TciSampleType.INT16;\n case 'int24':\n return TciSampleType.INT24;\n case 'int32':\n return TciSampleType.INT32;\n case 'float32':\n return TciSampleType.FLOAT32;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n }\n if (sampleType >= TciSampleType.INT16 && sampleType <= TciSampleType.FLOAT32) {\n return sampleType as TciSampleType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n}\n\nexport function normalizeStreamType(streamType: TciStreamType | number): TciStreamType {\n if (streamType >= TciStreamType.IQ_STREAM && streamType <= TciStreamType.LINEOUT_STREAM) {\n return streamType as TciStreamType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI stream type: ${streamType}`);\n}\n\nexport function payloadToFloat32(frameOrPayload: TciStreamFrame | Buffer | Uint8Array, sampleType?: TciSampleType | TciSampleTypeName): Float32Array {\n const payload = isFrame(frameOrPayload) ? frameOrPayload.payload : toBuffer(frameOrPayload);\n const type = isFrame(frameOrPayload) ? frameOrPayload.sampleType : normalizeSampleType(sampleType ?? TciSampleType.FLOAT32);\n const bytes = sampleTypeBytes(type);\n if (payload.byteLength % bytes !== 0) {\n throw new TciError('invalid-frame', 'Payload length is not aligned to sample type');\n }\n\n const output = new Float32Array(payload.byteLength / bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < output.length; i += 1) {\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n output[i] = view.getInt16(offset, true) / 32768;\n break;\n case TciSampleType.INT24:\n output[i] = readInt24(view, offset) / 8388608;\n break;\n case TciSampleType.INT32:\n output[i] = view.getInt32(offset, true) / 2147483648;\n break;\n case TciSampleType.FLOAT32:\n output[i] = view.getFloat32(offset, true);\n break;\n }\n }\n return output;\n}\n\nexport function samplesToPayload(samples: Float32Array | readonly number[], sampleType: TciSampleType | TciSampleTypeName): Buffer {\n const type = normalizeSampleType(sampleType);\n const bytes = sampleTypeBytes(type);\n const payload = Buffer.alloc(samples.length * bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < samples.length; i += 1) {\n const value = clampSample(samples[i] ?? 0);\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n view.setInt16(offset, Math.round(value * 32767), true);\n break;\n case TciSampleType.INT24:\n writeInt24(view, offset, Math.round(value * 8388607));\n break;\n case TciSampleType.INT32:\n view.setInt32(offset, Math.round(value * 2147483647), true);\n break;\n case TciSampleType.FLOAT32:\n view.setFloat32(offset, value, true);\n break;\n }\n }\n return payload;\n}\n\nexport function pcm16ToFloat32(input: Buffer | Uint8Array | Int16Array): Float32Array {\n if (input instanceof Int16Array) {\n const output = new Float32Array(input.length);\n for (let i = 0; i < input.length; i += 1) {\n output[i] = input[i] / 32768;\n }\n return output;\n }\n return payloadToFloat32(toBuffer(input), TciSampleType.INT16);\n}\n\nexport function float32ToPcm16(samples: Float32Array | readonly number[]): Buffer {\n return samplesToPayload(samples, TciSampleType.INT16);\n}\n\nexport function deinterleaveChannels(samples: Float32Array, channels: number): Float32Array[] {\n if (channels <= 0 || samples.length % channels !== 0) {\n throw new TciError('invalid-frame', 'Cannot deinterleave samples with invalid channel count');\n }\n const frames = samples.length / channels;\n const outputs = Array.from({ length: channels }, () => new Float32Array(frames));\n for (let frame = 0; frame < frames; frame += 1) {\n for (let channel = 0; channel < channels; channel += 1) {\n outputs[channel][frame] = samples[frame * channels + channel];\n }\n }\n return outputs;\n}\n\nexport function mixToMono(samples: Float32Array, channels: number): Float32Array {\n if (channels === 1) {\n return samples;\n }\n const separated = deinterleaveChannels(samples, channels);\n const mono = new Float32Array(separated[0]?.length ?? 0);\n for (const channel of separated) {\n for (let i = 0; i < mono.length; i += 1) {\n mono[i] += channel[i] / channels;\n }\n }\n return mono;\n}\n\nfunction toBuffer(input: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView): Buffer {\n if (Buffer.isBuffer(input)) {\n return input;\n }\n if (input instanceof ArrayBuffer) {\n return Buffer.from(input);\n }\n if (ArrayBuffer.isView(input)) {\n return Buffer.from(input.buffer, input.byteOffset, input.byteLength);\n }\n return Buffer.from(input);\n}\n\nfunction isFrame(value: unknown): value is TciStreamFrame {\n return Boolean(value && typeof value === 'object' && 'payload' in value && 'sampleType' in value);\n}\n\nfunction clampSample(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n return Math.max(-1, Math.min(1, value));\n}\n\nfunction readInt24(view: DataView, offset: number): number {\n const value = view.getUint8(offset) | (view.getUint8(offset + 1) << 8) | (view.getUint8(offset + 2) << 16);\n return value & 0x800000 ? value | 0xff000000 : value;\n}\n\nfunction writeInt24(view: DataView, offset: number, value: number): void {\n const clamped = Math.max(-8388608, Math.min(8388607, value));\n view.setUint8(offset, clamped & 0xff);\n view.setUint8(offset + 1, (clamped >> 8) & 0xff);\n view.setUint8(offset + 2, (clamped >> 16) & 0xff);\n}\n","export interface TciCommand {\n /** Lower-case command name for case-insensitive matching. */\n name: string;\n /** Original command name as received, without surrounding whitespace. */\n originalName: string;\n /** Unescaped argument list. Empty commands have an empty array. */\n args: string[];\n /** Raw command fragment without the trailing semicolon. */\n raw: string;\n}\n\nexport type TciCommandInput = string | TciCommand;\n\nconst ESCAPE_TO_CHAR: Record<string, string> = {\n '^': ':',\n '~': ',',\n '*': ';',\n};\n\nconst CHAR_TO_ESCAPE: Record<string, string> = {\n ':': '^',\n ',': '~',\n ';': '*',\n};\n\nexport function escapeTciText(value: unknown): string {\n return String(value).replace(/[:;,]/g, (char) => CHAR_TO_ESCAPE[char] ?? char);\n}\n\nexport function unescapeTciText(value: string): string {\n return value.replace(/[\\^~*]/g, (char) => ESCAPE_TO_CHAR[char] ?? char);\n}\n\nexport function parseTciText(text: string | Buffer | ArrayBuffer | ArrayBufferView): TciCommand[] {\n const source = normalizeTextInput(text);\n const commands: TciCommand[] = [];\n\n for (const fragment of source.split(';')) {\n const raw = fragment.trim();\n if (!raw) {\n continue;\n }\n\n const colonIndex = raw.indexOf(':');\n const originalName = (colonIndex >= 0 ? raw.slice(0, colonIndex) : raw).trim();\n if (!originalName) {\n continue;\n }\n\n const argsText = colonIndex >= 0 ? raw.slice(colonIndex + 1) : undefined;\n commands.push({\n name: originalName.toLowerCase(),\n originalName,\n args: argsText === undefined ? [] : splitArgs(argsText),\n raw,\n });\n }\n\n return commands;\n}\n\nexport function parseTciCommand(input: TciCommandInput): TciCommand {\n if (typeof input !== 'string') {\n return input;\n }\n const [command] = parseTciText(input);\n if (!command) {\n throw new Error(`Invalid TCI command: ${input}`);\n }\n return command;\n}\n\nexport function formatTciCommand(name: string, args: readonly unknown[] = []): string {\n const commandName = name.trim().toUpperCase();\n if (!commandName) {\n throw new Error('TCI command name cannot be empty');\n }\n if (args.length === 0) {\n return `${commandName};`;\n }\n return `${commandName}:${args.map(escapeTciText).join(',')};`;\n}\n\nexport function normalizeCommandName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nexport function isCommandReplyTo(replyInput: TciCommandInput, requestInput: TciCommandInput): boolean {\n const reply = parseTciCommand(replyInput);\n const request = parseTciCommand(requestInput);\n if (reply.name !== request.name) {\n return false;\n }\n\n if (request.args.length === 0) {\n return true;\n }\n\n if (argsHavePrefix(reply.args, request.args)) {\n return true;\n }\n\n return isKnownVariantReply(reply, request);\n}\n\nexport function commandKey(command: TciCommandInput): string {\n const parsed = parseTciCommand(command);\n return `${parsed.name}:${parsed.args.join(',')}`;\n}\n\nfunction normalizeTextInput(text: string | Buffer | ArrayBuffer | ArrayBufferView): string {\n if (typeof text === 'string') {\n return text;\n }\n if (Buffer.isBuffer(text)) {\n return text.toString('utf8');\n }\n if (text instanceof ArrayBuffer) {\n return Buffer.from(text).toString('utf8');\n }\n return Buffer.from(text.buffer, text.byteOffset, text.byteLength).toString('utf8');\n}\n\nfunction splitArgs(argsText: string): string[] {\n return argsText.split(',').map((arg) => unescapeTciText(arg.trim()));\n}\n\nfunction argsHavePrefix(args: readonly string[], prefix: readonly string[]): boolean {\n if (args.length < prefix.length) {\n return false;\n }\n return prefix.every((arg, index) => args[index]?.toLowerCase() === arg.toLowerCase());\n}\n\nfunction isKnownVariantReply(reply: TciCommand, request: TciCommand): boolean {\n if (reply.name === 'modulation') {\n // ExpertSDR/WSJT-X variants can use MODULATION:rx,mode and MODULATION:rx,vfo,mode.\n if (request.args.length === 2 && reply.args.length >= 3) {\n return reply.args[0] === request.args[0] && reply.args[2]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n if (request.args.length === 3 && reply.args.length === 2) {\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[2]?.toLowerCase();\n }\n }\n\n if (reply.name === 'protocol') {\n return request.args.length <= 1;\n }\n\n if (reply.name === 'trx' && request.args.length >= 3 && reply.args.length >= 2) {\n // Official TRX writes may include an audio source as arg3, while replies only echo trx+state.\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n\n return false;\n}\n","import { TciError } from '../errors.js';\nimport {\n formatTciCommand,\n isCommandReplyTo,\n parseTciCommand,\n type TciCommand,\n type TciCommandInput,\n} from './text.js';\n\nexport type TciCommandMatcher = (reply: TciCommand, request: TciCommand) => boolean;\n\nexport interface QueueCommandOptions {\n timeoutMs?: number;\n matcher?: TciCommandMatcher;\n signal?: AbortSignal;\n}\n\nexport interface QueuedCommandResult {\n request: TciCommand;\n reply: TciCommand;\n}\n\ninterface PendingCommand {\n raw: string;\n request: TciCommand;\n timeoutMs: number;\n matcher: TciCommandMatcher;\n resolve: (result: QueuedCommandResult) => void;\n reject: (error: TciError) => void;\n timer?: NodeJS.Timeout;\n abortCleanup?: () => void;\n}\n\nexport interface TciCommandQueueOptions {\n send: (raw: string) => void | Promise<void>;\n timeoutMs?: number;\n}\n\nexport class TciCommandQueue {\n private readonly send: (raw: string) => void | Promise<void>;\n private readonly defaultTimeoutMs: number;\n private queue: PendingCommand[] = [];\n private active?: PendingCommand;\n private connected = true;\n\n constructor(options: TciCommandQueueOptions) {\n this.send = options.send;\n this.defaultTimeoutMs = options.timeoutMs ?? 1_000;\n }\n\n setConnected(connected: boolean): void {\n this.connected = connected;\n if (!connected) {\n this.cancelAll(new TciError('disconnected', 'TCI connection closed'));\n }\n }\n\n enqueue(command: TciCommandInput, options: QueueCommandOptions = {}): Promise<QueuedCommandResult> {\n const request = parseTciCommand(command);\n const raw = typeof command === 'string' ? ensureSemicolon(command) : formatTciCommand(command.originalName, command.args);\n\n if (!this.connected) {\n return Promise.reject(new TciError('not-connected', 'TCI socket is not connected'));\n }\n\n return new Promise<QueuedCommandResult>((resolve, reject) => {\n const pending: PendingCommand = {\n raw,\n request,\n timeoutMs: options.timeoutMs ?? this.defaultTimeoutMs,\n matcher: options.matcher ?? ((reply, req) => isCommandReplyTo(reply, req)),\n resolve,\n reject,\n };\n\n if (options.signal) {\n if (options.signal.aborted) {\n reject(new TciError('cancelled', 'TCI command was cancelled'));\n return;\n }\n const onAbort = () => this.rejectPending(pending, new TciError('cancelled', 'TCI command was cancelled'));\n options.signal.addEventListener('abort', onAbort, { once: true });\n pending.abortCleanup = () => options.signal?.removeEventListener('abort', onAbort);\n }\n\n this.queue.push(pending);\n void this.pump();\n });\n }\n\n handleCommand(commandInput: TciCommandInput): boolean {\n const active = this.active;\n if (!active) {\n return false;\n }\n const reply = parseTciCommand(commandInput);\n if (!active.matcher(reply, active.request)) {\n return false;\n }\n this.finishActive(reply);\n return true;\n }\n\n cancelAll(error = new TciError('cancelled', 'TCI command queue cancelled')): void {\n const pending = [...this.queue];\n this.queue = [];\n if (this.active) {\n pending.unshift(this.active);\n this.active = undefined;\n }\n for (const item of pending) {\n this.rejectPending(item, error);\n }\n }\n\n get size(): number {\n return this.queue.length + (this.active ? 1 : 0);\n }\n\n private async pump(): Promise<void> {\n if (this.active || !this.connected) {\n return;\n }\n const next = this.queue.shift();\n if (!next) {\n return;\n }\n\n this.active = next;\n next.timer = setTimeout(() => {\n this.rejectPending(next, new TciError('command-timeout', `Timed out waiting for TCI reply to ${next.raw}`));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }, next.timeoutMs);\n\n try {\n await this.send(next.raw);\n } catch (error) {\n this.rejectPending(next, new TciError('disconnected', error instanceof Error ? error.message : String(error), error));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }\n }\n\n private finishActive(reply: TciCommand): void {\n const active = this.active;\n if (!active) {\n return;\n }\n this.active = undefined;\n if (active.timer) {\n clearTimeout(active.timer);\n }\n active.abortCleanup?.();\n active.resolve({ request: active.request, reply });\n void this.pump();\n }\n\n private rejectPending(pending: PendingCommand, error: TciError): void {\n if (pending.timer) {\n clearTimeout(pending.timer);\n }\n pending.abortCleanup?.();\n const wasActive = this.active === pending;\n if (wasActive) {\n this.active = undefined;\n } else {\n this.queue = this.queue.filter((item) => item !== pending);\n }\n pending.reject(error);\n if (wasActive && this.connected) {\n void this.pump();\n }\n }\n}\n\nfunction ensureSemicolon(command: string): string {\n return command.trim().endsWith(';') ? command.trim() : `${command.trim()};`;\n}\n"],"mappings":"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","names":["TciStreamType","TciSampleType","value"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client/TciClient.ts","../src/audio/streamFrame.ts","../src/protocol/text.ts","../src/protocol/commandQueue.ts"],"sourcesContent":["export type TciErrorCode =\n | 'connect-timeout'\n | 'command-timeout'\n | 'not-connected'\n | 'disconnected'\n | 'protocol-error'\n | 'invalid-frame'\n | 'cancelled';\n\nexport class TciError extends Error {\n readonly code: TciErrorCode;\n readonly details?: unknown;\n\n constructor(code: TciErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TciError';\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toTciError(error: unknown, fallbackCode: TciErrorCode = 'protocol-error'): TciError {\n if (error instanceof TciError) {\n return error;\n }\n if (error instanceof Error) {\n return new TciError(fallbackCode, error.message, error);\n }\n return new TciError(fallbackCode, String(error), error);\n}\n","import { EventEmitter } from 'eventemitter3';\nimport WebSocket from 'ws';\nimport { TciError, toTciError } from '../errors.js';\nimport {\n buildTxAudioFrame,\n normalizeSampleType,\n parseStreamFrame,\n sampleTypeName,\n TciSampleType,\n TciStreamType,\n type BuildTxAudioFrameOptions,\n type TciSampleTypeName,\n type TciStreamFrame,\n} from '../audio/streamFrame.js';\nimport {\n formatTciCommand,\n parseTciText,\n TciCommandQueue,\n type QueueCommandOptions,\n type TciCommand,\n} from '../protocol/index.js';\n\nexport interface TciClientOptions {\n url: string;\n receiver?: number;\n trx?: number;\n vfo?: number;\n connectTimeoutMs?: number;\n commandTimeoutMs?: number;\n writeAckMode?: TciWriteAckMode;\n writeTimeoutMs?: number;\n writeSettleMs?: number;\n frequencyWriteSettleMs?: number;\n WebSocketImpl?: typeof WebSocket;\n}\n\nexport interface TciAudioConfig {\n sampleRate: 8_000 | 12_000 | 24_000 | 48_000 | number;\n sampleType?: TciSampleType | TciSampleTypeName;\n channels?: 1 | 2 | number;\n samplesPerFrame?: number;\n txBufferingMs?: number;\n}\n\nexport interface TciPttOptions {\n source?: 'tci' | 'mic1' | 'mic2' | 'micpc' | 'ecoder2' | string;\n trx?: number;\n ackMode?: TciWriteAckMode;\n timeoutMs?: number;\n settleMs?: number;\n}\n\nexport type TciWriteAckMode = 'state' | 'reply' | 'optimistic';\n\nexport interface TciWriteOptions {\n ackMode?: TciWriteAckMode;\n timeoutMs?: number;\n settleMs?: number;\n}\n\nexport interface TciTxChronoRequest {\n frame: TciStreamFrame;\n receiver: number;\n sampleRate: number;\n channels: number;\n sampleType: TciSampleType;\n sampleCount: number;\n}\n\nexport interface TciClientState {\n connected: boolean;\n ready: boolean;\n protocol?: string;\n device?: string;\n receiveOnly?: boolean;\n trxCount?: number;\n channelCount?: number;\n vfoLimits?: [number, number];\n ifLimits?: [number, number];\n modulations: string[];\n frequencies: Record<string, number>;\n modes: Record<string, string>;\n ptt: Record<string, boolean>;\n pttSource: Record<string, string | undefined>;\n tune: Record<string, boolean>;\n drive: Record<string, number>;\n split: Record<string, boolean>;\n rxSensors: Record<string, Record<string, number | string | boolean>>;\n txSensors: Record<string, Record<string, number | string | boolean>>;\n audio?: Required<Pick<TciAudioConfig, 'sampleRate' | 'channels' | 'sampleType' | 'samplesPerFrame'>> & {\n txBufferingMs?: number;\n running: boolean;\n };\n}\n\nexport interface TciClientEvents {\n connected: () => void;\n disconnected: (reason?: unknown) => void;\n ready: (state: TciClientState) => void;\n state: (state: TciClientState) => void;\n command: (command: TciCommand) => void;\n binary: (frame: TciStreamFrame) => void;\n 'tci:tx': (raw: string) => void;\n 'tci:rx': (raw: string, commands: TciCommand[]) => void;\n 'tci:binary': (frame: TciStreamFrame) => void;\n rxAudioFrame: (frame: TciStreamFrame) => void;\n lineoutAudioFrame: (frame: TciStreamFrame) => void;\n txChrono: (request: TciTxChronoRequest) => void;\n error: (error: TciError) => void;\n}\n\nexport interface SendCommandOptions extends QueueCommandOptions {\n waitForReply?: boolean;\n}\n\nexport class TciClient extends EventEmitter<TciClientEvents> {\n readonly options: Required<Pick<\n TciClientOptions,\n | 'receiver'\n | 'trx'\n | 'vfo'\n | 'connectTimeoutMs'\n | 'commandTimeoutMs'\n | 'writeAckMode'\n | 'writeTimeoutMs'\n | 'writeSettleMs'\n | 'frequencyWriteSettleMs'\n >> &\n Pick<TciClientOptions, 'url'>;\n\n private readonly WebSocketImpl: typeof WebSocket;\n private ws?: WebSocket;\n private readonly queue: TciCommandQueue;\n private readonly state: TciClientState;\n\n constructor(options: TciClientOptions) {\n super();\n this.options = {\n url: options.url,\n receiver: options.receiver ?? 0,\n trx: options.trx ?? 0,\n vfo: options.vfo ?? 0,\n connectTimeoutMs: options.connectTimeoutMs ?? 5_000,\n commandTimeoutMs: options.commandTimeoutMs ?? 1_000,\n writeAckMode: options.writeAckMode ?? 'state',\n writeTimeoutMs: options.writeTimeoutMs ?? 3_000,\n writeSettleMs: options.writeSettleMs ?? 0,\n frequencyWriteSettleMs: options.frequencyWriteSettleMs ?? 250,\n };\n this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;\n this.queue = new TciCommandQueue({\n timeoutMs: this.options.commandTimeoutMs,\n send: (raw) => this.sendRaw(raw),\n });\n this.queue.setConnected(false);\n this.state = {\n connected: false,\n ready: false,\n modulations: [],\n frequencies: {},\n modes: {},\n ptt: {},\n pttSource: {},\n tune: {},\n drive: {},\n split: {},\n rxSensors: {},\n txSensors: {},\n };\n }\n\n async connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {\n await this.waitForOpen(this.ws);\n return;\n }\n\n const ws = new this.WebSocketImpl(this.options.url);\n this.ws = ws;\n await this.waitForOpen(ws);\n }\n\n async disconnect(code = 1000, reason = 'client disconnect'): Promise<void> {\n const ws = this.ws;\n if (!ws) {\n return;\n }\n if (ws.readyState === WebSocket.CLOSED) {\n this.handleClose();\n return;\n }\n await new Promise<void>((resolve) => {\n const cleanup = () => {\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onClose = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n resolve();\n };\n ws.once('close', onClose);\n ws.once('error', onError);\n ws.close(code, reason);\n setTimeout(() => resolve(), 1_000).unref?.();\n });\n this.handleClose();\n }\n\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n getState(): TciClientState {\n return cloneState(this.state);\n }\n\n async sendCommand(name: string, args: readonly unknown[] = [], options: SendCommandOptions = {}): Promise<TciCommand | undefined> {\n const raw = formatTciCommand(name, args);\n if (options.waitForReply === false) {\n await this.sendRaw(raw);\n return undefined;\n }\n const result = await this.queue.enqueue(raw, options);\n return result.reply;\n }\n\n async request(name: string, args: readonly unknown[] = [], options: QueueCommandOptions = {}): Promise<TciCommand> {\n const reply = await this.sendCommand(name, args, { ...options, waitForReply: true });\n if (!reply) {\n throw new TciError('protocol-error', `No reply for ${name}`);\n }\n return reply;\n }\n\n async sendStateWrite(\n name: string,\n args: readonly unknown[],\n isApplied: (state: TciClientState) => boolean,\n description = formatTciCommand(name, args).replace(/;$/, ''),\n options: TciWriteOptions = {},\n ): Promise<void> {\n const ackMode = options.ackMode ?? this.options.writeAckMode;\n if (ackMode === 'reply') {\n await this.sendCommand(name, args, { timeoutMs: options.timeoutMs });\n return;\n }\n\n if (isApplied(this.getState())) {\n return;\n }\n\n if (ackMode === 'optimistic') {\n await this.sendCommand(name, args, { waitForReply: false });\n return;\n }\n\n const timeoutMs = options.timeoutMs ?? this.options.writeTimeoutMs;\n const settleMs = options.settleMs ?? this.options.writeSettleMs;\n const waiter = this.waitForState(isApplied, timeoutMs, settleMs, description);\n try {\n await this.sendCommand(name, args, { waitForReply: false });\n await waiter.promise;\n } catch (error) {\n waiter.cancel();\n throw error;\n }\n }\n\n async setFrequency(\n frequencyHz: number,\n receiver = this.options.receiver,\n vfo = this.options.vfo,\n options: TciWriteOptions = {},\n ): Promise<void> {\n const frequency = Math.round(frequencyHz);\n const key = rxVfoKey(receiver, vfo);\n await this.sendStateWrite(\n 'VFO',\n [receiver, vfo, frequency],\n (state) => state.frequencies[key] === frequency,\n `VFO:${receiver},${vfo},${frequency}`,\n { settleMs: this.options.frequencyWriteSettleMs, ...options },\n );\n }\n\n async getFrequency(receiver = this.options.receiver, vfo = this.options.vfo): Promise<number | undefined> {\n const reply = await this.request('VFO', [receiver, vfo]);\n return parseNumber(reply.args[2]) ?? this.state.frequencies[rxVfoKey(receiver, vfo)];\n }\n\n async setMode(mode: string, receiver = this.options.receiver, options: TciWriteOptions = {}): Promise<void> {\n const normalizedMode = mode.toUpperCase();\n const key = rxVfoKey(receiver, this.options.vfo);\n await this.sendStateWrite(\n 'MODULATION',\n [receiver, normalizedMode],\n (state) => state.modes[key]?.toLowerCase() === normalizedMode.toLowerCase(),\n `MODULATION:${receiver},${normalizedMode}`,\n options,\n );\n }\n\n async getMode(receiver = this.options.receiver): Promise<string | undefined> {\n const reply = await this.request('MODULATION', [receiver]);\n const mode = reply.args.length >= 3 ? reply.args[2] : reply.args[1];\n return (mode ?? this.state.modes[rxVfoKey(receiver, this.options.vfo)])?.toLowerCase();\n }\n\n async setPtt(enabled: boolean, options: TciPttOptions = {}): Promise<void> {\n const trx = options.trx ?? this.options.trx;\n const args = options.source ? [trx, enabled, options.source] : [trx, enabled];\n await this.sendStateWrite(\n 'TRX',\n args,\n (state) => state.ptt[String(trx)] === enabled,\n `TRX:${trx},${enabled}`,\n options,\n );\n }\n\n async getPtt(trx = this.options.trx): Promise<boolean | undefined> {\n const reply = await this.request('TRX', [trx]);\n return parseBoolean(reply.args[1]) ?? this.state.ptt[String(trx)];\n }\n\n async setTune(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('TUNE', [trx, enabled]);\n }\n\n async setDrive(value: number, trx = this.options.trx): Promise<void> {\n await this.sendCommand('DRIVE', [trx, value]);\n }\n\n async setSplit(enabled: boolean, trx = this.options.trx): Promise<void> {\n await this.sendCommand('SPLIT_ENABLE', [trx, enabled]);\n }\n\n async configureAudio(config: TciAudioConfig): Promise<void> {\n const audio = {\n sampleRate: config.sampleRate,\n sampleType: normalizeSampleType(config.sampleType ?? TciSampleType.FLOAT32),\n channels: config.channels ?? 1,\n samplesPerFrame: config.samplesPerFrame ?? 512,\n txBufferingMs: config.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n this.state.audio = audio;\n\n await this.sendCommand('AUDIO_SAMPLERATE', [audio.sampleRate], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLE_TYPE', [sampleTypeName(audio.sampleType)], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_CHANNELS', [audio.channels], { waitForReply: false });\n await this.sendCommand('AUDIO_STREAM_SAMPLES', [audio.samplesPerFrame], { waitForReply: false });\n if (audio.txBufferingMs !== undefined) {\n await this.sendCommand('TX_STREAM_AUDIO_BUFFERING', [audio.txBufferingMs], { waitForReply: false });\n }\n this.emitState();\n }\n\n async startAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_START', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = true;\n this.emitState();\n }\n }\n\n async stopAudio(receiver = this.options.receiver): Promise<void> {\n await this.sendCommand('AUDIO_STOP', [receiver], { waitForReply: false });\n if (this.state.audio) {\n this.state.audio.running = false;\n this.emitState();\n }\n }\n\n sendTxAudio(options: BuildTxAudioFrameOptions): void {\n const frame = buildTxAudioFrame({ receiver: this.options.receiver, ...options });\n this.sendRawBinary(frame);\n }\n\n async setRxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('RX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async setTxSensorsEnabled(enabled: boolean, intervalMs?: number): Promise<void> {\n const args = intervalMs === undefined ? [enabled] : [enabled, intervalMs];\n await this.sendCommand('TX_SENSORS_ENABLE', args, { waitForReply: false });\n }\n\n async sendCwMacro(index: number): Promise<void> {\n await this.sendCommand('CW_MACROS', [index]);\n }\n\n async sendCwMessage(message: string): Promise<void> {\n await this.sendCommand('CW_MSG', [message]);\n }\n\n async stopCw(): Promise<void> {\n await this.sendCommand('CW_MACROS_STOP');\n }\n\n private waitForState(\n predicate: (state: TciClientState) => boolean,\n timeoutMs: number,\n settleMs: number,\n description: string,\n ): { promise: Promise<void>; cancel: () => void } {\n let timeout: NodeJS.Timeout | undefined;\n let settleTimeout: NodeJS.Timeout | undefined;\n let resolved = false;\n let resolvePromise!: () => void;\n let rejectPromise!: (error: TciError) => void;\n\n const cleanup = () => {\n if (timeout) {\n clearTimeout(timeout);\n timeout = undefined;\n }\n if (settleTimeout) {\n clearTimeout(settleTimeout);\n settleTimeout = undefined;\n }\n this.off('state', onState);\n this.off('disconnected', onDisconnected);\n };\n\n const resolveNow = () => {\n resolved = true;\n cleanup();\n resolvePromise();\n };\n\n const check = () => {\n if (!predicate(this.getState())) {\n if (settleTimeout) {\n clearTimeout(settleTimeout);\n settleTimeout = undefined;\n }\n return;\n }\n\n if (settleMs <= 0) {\n resolveNow();\n return;\n }\n\n if (settleTimeout) {\n return;\n }\n\n settleTimeout = setTimeout(() => {\n settleTimeout = undefined;\n if (predicate(this.getState())) {\n resolveNow();\n }\n }, settleMs);\n };\n\n const onState = () => check();\n const onDisconnected = () => {\n if (resolved) {\n return;\n }\n cleanup();\n rejectPromise(new TciError('disconnected', `Disconnected while waiting for TCI state ${description}`));\n };\n\n const promise = new Promise<void>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n timeout = setTimeout(() => {\n cleanup();\n reject(new TciError('command-timeout', `Timed out waiting for TCI state ${description}`));\n }, timeoutMs);\n this.on('state', onState);\n this.on('disconnected', onDisconnected);\n check();\n });\n\n return {\n promise,\n cancel: cleanup,\n };\n }\n\n private waitForOpen(ws: WebSocket): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n cleanup();\n try {\n ws.terminate();\n } catch {\n // ignore termination races\n }\n reject(new TciError('connect-timeout', `Timed out connecting to ${this.options.url}`));\n }, this.options.connectTimeoutMs);\n\n const cleanup = () => {\n clearTimeout(timer);\n ws.off('open', onOpen);\n ws.off('close', onClose);\n ws.off('error', onError);\n };\n const onOpen = () => {\n cleanup();\n this.attachSocket(ws);\n this.state.connected = true;\n this.queue.setConnected(true);\n this.emit('connected');\n this.emitState();\n resolve();\n };\n const onClose = () => {\n cleanup();\n this.handleClose();\n reject(new TciError('disconnected', `Disconnected while connecting to ${this.options.url}`));\n };\n const onError = (error: Error) => {\n cleanup();\n this.handleError(error);\n reject(toTciError(error, 'disconnected'));\n };\n ws.once('open', onOpen);\n ws.once('close', onClose);\n ws.once('error', onError);\n });\n }\n\n private attachSocket(ws: WebSocket): void {\n ws.on('message', (data, isBinary) => this.handleMessage(data, isBinary));\n ws.on('close', () => this.handleClose());\n ws.on('error', (error) => this.handleError(error));\n }\n\n private async sendRaw(raw: string): Promise<void> {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n this.emit('tci:tx', raw);\n await new Promise<void>((resolve, reject) => {\n ws.send(raw, (error) => (error ? reject(error) : resolve()));\n });\n }\n\n private sendRawBinary(raw: Buffer): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n throw new TciError('not-connected', 'TCI socket is not connected');\n }\n ws.send(raw, { binary: true });\n }\n\n private handleMessage(data: WebSocket.RawData, isBinary: boolean): void {\n try {\n if (isBinary) {\n this.handleBinary(data);\n return;\n }\n const raw = dataToBuffer(data).toString('utf8');\n const commands = parseTciText(raw);\n this.emit('tci:rx', raw, commands);\n for (const command of commands) {\n this.queue.handleCommand(command);\n this.applyCommand(command);\n this.emit('command', command);\n }\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private handleBinary(data: WebSocket.RawData): void {\n const frame = parseStreamFrame(dataToBuffer(data));\n this.emit('tci:binary', frame);\n this.emit('binary', frame);\n switch (frame.streamType) {\n case TciStreamType.RX_AUDIO_STREAM:\n this.emit('rxAudioFrame', frame);\n break;\n case TciStreamType.TX_CHRONO:\n this.emit('txChrono', {\n frame,\n receiver: frame.receiver,\n sampleRate: frame.sampleRate,\n channels: frame.channels,\n sampleType: frame.sampleType,\n sampleCount: frame.sampleCount,\n });\n break;\n case TciStreamType.LINEOUT_STREAM:\n this.emit('lineoutAudioFrame', frame);\n break;\n default:\n break;\n }\n }\n\n private applyCommand(command: TciCommand): void {\n const readyBefore = this.state.ready;\n switch (command.name) {\n case 'ready':\n this.state.ready = command.args.length === 0 ? true : (parseBoolean(command.args[0]) ?? true);\n break;\n case 'protocol':\n this.state.protocol = command.args[0];\n break;\n case 'device':\n this.state.device = command.args.join(',');\n break;\n case 'receive_only':\n this.state.receiveOnly = parseBoolean(command.args[0]);\n break;\n case 'trx_count':\n this.state.trxCount = parseNumber(command.args[0]);\n break;\n case 'channels_count':\n case 'channel_count':\n this.state.channelCount = parseNumber(command.args[0]);\n break;\n case 'vfo_limits':\n this.state.vfoLimits = parseNumberPair(command.args);\n break;\n case 'if_limits':\n this.state.ifLimits = parseNumberPair(command.args);\n break;\n case 'modulations_list':\n this.state.modulations = command.args.map((mode) => mode.toLowerCase());\n break;\n case 'vfo':\n this.applyVfo(command.args);\n break;\n case 'modulation':\n this.applyModulation(command.args);\n break;\n case 'trx':\n this.applyTrx(command.args);\n break;\n case 'tune':\n this.applyBooleanByFirstArg(this.state.tune, command.args);\n break;\n case 'drive':\n this.applyDrive(command.args);\n break;\n case 'split_enable':\n this.applyBooleanByFirstArg(this.state.split, command.args);\n break;\n case 'rx_channel_sensors':\n this.applyRxChannelSensors(command.args);\n break;\n case 'rx_sensors':\n this.applyRxSensors(command.args);\n break;\n case 'tx_sensors':\n this.applyTxSensors(command.args);\n break;\n case 'audio_samplerate':\n this.state.audio = {\n sampleRate: parseNumber(command.args[0]) ?? this.state.audio?.sampleRate ?? 12_000,\n sampleType: this.state.audio?.sampleType ?? TciSampleType.FLOAT32,\n channels: this.state.audio?.channels ?? 1,\n samplesPerFrame: this.state.audio?.samplesPerFrame ?? 512,\n txBufferingMs: this.state.audio?.txBufferingMs,\n running: this.state.audio?.running ?? false,\n };\n break;\n default:\n break;\n }\n\n if (!readyBefore && this.state.ready) {\n this.emit('ready', this.getState());\n }\n this.emitState();\n }\n\n private applyVfo(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const receiver = parseNumber(args[0]);\n const vfo = parseNumber(args[1]);\n const frequency = parseNumber(args[2]);\n if (receiver === undefined || vfo === undefined || frequency === undefined || frequency < 0) {\n return;\n }\n this.state.frequencies[rxVfoKey(receiver, vfo)] = frequency;\n }\n\n private applyModulation(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const receiver = parseNumber(args[0]);\n if (receiver === undefined) {\n return;\n }\n const vfo = args.length >= 3 ? parseNumber(args[1]) ?? this.options.vfo : this.options.vfo;\n const mode = args.length >= 3 ? args[2] : args[1];\n if (!mode) {\n return;\n }\n this.state.modes[rxVfoKey(receiver, vfo)] = mode.toLowerCase();\n }\n\n private applyTrx(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n this.state.ptt[trx] = parseBoolean(args[1]) ?? false;\n this.state.pttSource[trx] = args[2]?.toLowerCase();\n }\n\n private applyBooleanByFirstArg(target: Record<string, boolean>, args: string[]): void {\n if (args.length < 2) {\n return;\n }\n const key = args[0] ?? '0';\n const value = parseBoolean(args[1]);\n if (value !== undefined) {\n target[key] = value;\n }\n }\n\n private applyDrive(args: string[]): void {\n if (args.length === 1) {\n const value = parseNumber(args[0]);\n if (value !== undefined) {\n this.state.drive[String(this.options.trx)] = value;\n }\n return;\n }\n const trx = args[0] ?? String(this.options.trx);\n const value = parseNumber(args[1]);\n if (value !== undefined) {\n this.state.drive[trx] = value;\n }\n }\n\n private applyRxChannelSensors(args: string[]): void {\n if (args.length < 3) {\n return;\n }\n const key = rxVfoKey(args[0], args[1]);\n this.state.rxSensors[key] = {\n receiver: args[0],\n channel: args[1],\n levelDbm: parseNumber(args[2]) ?? args[2],\n };\n }\n\n private applyRxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.rxSensors[String(args[0])] = {\n receiver: args[0],\n levelDbm: parseNumber(args[1]) ?? args[1],\n deprecated: true,\n };\n }\n\n private applyTxSensors(args: string[]): void {\n if (args.length < 2) {\n return;\n }\n this.state.txSensors[String(args[0])] = {\n trx: args[0],\n micDbm: parseNumber(args[1]) ?? args[1],\n rmsPowerW: parseNumber(args[2]) ?? args[2],\n peakPowerW: parseNumber(args[3]) ?? args[3],\n swr: parseNumber(args[4]) ?? args[4],\n };\n }\n\n private handleClose(reason?: unknown): void {\n this.ws = undefined;\n const wasConnected = this.state.connected;\n this.state.connected = false;\n this.state.ready = false;\n this.queue.setConnected(false);\n if (wasConnected) {\n this.emit('disconnected', reason);\n this.emitState();\n }\n }\n\n private handleError(error: unknown): void {\n const tciError = toTciError(error);\n this.emit('error', tciError);\n }\n\n private emitState(): void {\n this.emit('state', this.getState());\n }\n}\n\nexport function createTciClient(options: TciClientOptions): TciClient {\n return new TciClient(options);\n}\n\nfunction dataToBuffer(data: WebSocket.RawData): Buffer {\n if (Buffer.isBuffer(data)) {\n return data;\n }\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data);\n }\n if (Array.isArray(data)) {\n return Buffer.concat(data.map((item) => dataToBuffer(item)));\n }\n throw new TciError('protocol-error', 'Unsupported WebSocket data type');\n}\n\nfunction rxVfoKey(receiver: string | number, vfo: string | number): string {\n return `${receiver}:${vfo}`;\n}\n\nfunction parseNumber(value: string | undefined): number | undefined {\n if (value === undefined || value === '') {\n return undefined;\n }\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) {\n return undefined;\n }\n const normalized = value.toLowerCase();\n if (normalized === 'true' || normalized === '1' || normalized === 'on') {\n return true;\n }\n if (normalized === 'false' || normalized === '0' || normalized === 'off') {\n return false;\n }\n return undefined;\n}\n\nfunction parseNumberPair(args: string[]): [number, number] | undefined {\n const first = parseNumber(args[0]);\n const second = parseNumber(args[1]);\n return first === undefined || second === undefined ? undefined : [first, second];\n}\n\nfunction cloneState(state: TciClientState): TciClientState {\n return {\n ...state,\n modulations: [...state.modulations],\n frequencies: { ...state.frequencies },\n modes: { ...state.modes },\n ptt: { ...state.ptt },\n pttSource: { ...state.pttSource },\n tune: { ...state.tune },\n drive: { ...state.drive },\n split: { ...state.split },\n rxSensors: cloneNested(state.rxSensors),\n txSensors: cloneNested(state.txSensors),\n audio: state.audio ? { ...state.audio } : undefined,\n };\n}\n\nfunction cloneNested<T>(value: Record<string, T>): Record<string, T> {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, { ...(item as Record<string, unknown>) } as T]));\n}\n","import { TciError } from '../errors.js';\n\nexport const TCI_STREAM_HEADER_BYTES = 16 * 4;\n\nexport enum TciStreamType {\n IQ_STREAM = 0,\n RX_AUDIO_STREAM = 1,\n TX_AUDIO_STREAM = 2,\n TX_CHRONO = 3,\n LINEOUT_STREAM = 4,\n}\n\nexport enum TciSampleType {\n INT16 = 0,\n INT24 = 1,\n INT32 = 2,\n FLOAT32 = 3,\n}\n\nexport type TciSampleTypeName = 'int16' | 'int24' | 'int32' | 'float32';\n\nexport interface TciStreamFrame {\n receiver: number;\n sampleRate: number;\n sampleType: TciSampleType;\n codec: number;\n crc: number;\n /** Byte length of the payload following the 64-byte TCI stream header. */\n payloadLength: number;\n streamType: TciStreamType;\n channels: number;\n reserved: number[];\n payload: Buffer;\n /** Official Stream.length value: number of samples per channel in the payload. */\n sampleCount: number;\n}\n\nexport interface BuildStreamFrameOptions {\n receiver?: number;\n sampleRate: number;\n sampleType: TciSampleType | TciSampleTypeName;\n streamType: TciStreamType;\n channels: number;\n payload?: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView;\n samples?: Float32Array | readonly number[];\n codec?: number;\n crc?: number;\n reserved?: readonly number[];\n}\n\nexport interface BuildTxAudioFrameOptions extends Omit<BuildStreamFrameOptions, 'streamType'> {\n receiver?: number;\n}\n\nexport function parseStreamFrame(input: Buffer | ArrayBuffer | ArrayBufferView): TciStreamFrame {\n const buffer = toBuffer(input);\n if (buffer.byteLength < TCI_STREAM_HEADER_BYTES) {\n throw new TciError('invalid-frame', `TCI stream frame is shorter than ${TCI_STREAM_HEADER_BYTES} bytes`);\n }\n\n const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n const header = Array.from({ length: 16 }, (_, index) => view.getUint32(index * 4, true));\n const sampleType = normalizeSampleType(header[2]);\n let channels = header[7];\n const bytesPerSample = sampleTypeBytes(sampleType);\n const sampleCount = header[5];\n const actualPayloadLength = buffer.byteLength - TCI_STREAM_HEADER_BYTES;\n if (channels <= 0) {\n const inferredChannels = sampleCount > 0 ? actualPayloadLength / sampleCount / bytesPerSample : 1;\n if (!Number.isInteger(inferredChannels) || inferredChannels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n channels = inferredChannels;\n }\n const payloadLength = sampleCount * bytesPerSample * channels;\n const expectedLength = TCI_STREAM_HEADER_BYTES + payloadLength;\n if (buffer.byteLength !== expectedLength) {\n throw new TciError(\n 'invalid-frame',\n `TCI stream frame length mismatch: header says ${sampleCount} samples (${payloadLength} payload bytes), got ${buffer.byteLength - TCI_STREAM_HEADER_BYTES}`,\n );\n }\n if (payloadLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n\n return {\n receiver: header[0],\n sampleRate: header[1],\n sampleType,\n codec: header[3],\n crc: header[4],\n payloadLength,\n streamType: normalizeStreamType(header[6]),\n channels,\n reserved: header.slice(8),\n payload: buffer.subarray(TCI_STREAM_HEADER_BYTES),\n sampleCount,\n };\n}\n\nexport function buildStreamFrame(options: BuildStreamFrameOptions): Buffer {\n const sampleType = normalizeSampleType(options.sampleType);\n const payload = options.payload ? toBuffer(options.payload) : samplesToPayload(options.samples ?? [], sampleType);\n const channels = options.channels;\n if (channels <= 0) {\n throw new TciError('invalid-frame', `Invalid TCI channel count: ${channels}`);\n }\n const bytesPerSample = sampleTypeBytes(sampleType);\n if (payload.byteLength % (bytesPerSample * channels) !== 0) {\n throw new TciError('invalid-frame', 'TCI payload length is not aligned to sample type and channel count');\n }\n const sampleCount = payload.byteLength / bytesPerSample / channels;\n\n const frame = Buffer.alloc(TCI_STREAM_HEADER_BYTES + payload.byteLength);\n const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);\n const reserved = options.reserved ?? [];\n const header = [\n options.receiver ?? 0,\n options.sampleRate,\n sampleType,\n options.codec ?? 0,\n options.crc ?? 0,\n sampleCount,\n options.streamType,\n channels,\n ...Array.from({ length: 8 }, (_, index) => reserved[index] ?? 0),\n ];\n header.forEach((value, index) => view.setUint32(index * 4, value >>> 0, true));\n payload.copy(frame, TCI_STREAM_HEADER_BYTES);\n return frame;\n}\n\nexport function buildTxAudioFrame(options: BuildTxAudioFrameOptions): Buffer {\n return buildStreamFrame({ ...options, streamType: TciStreamType.TX_AUDIO_STREAM });\n}\n\nexport function sampleTypeBytes(sampleType: TciSampleType | TciSampleTypeName): number {\n switch (normalizeSampleType(sampleType)) {\n case TciSampleType.INT16:\n return 2;\n case TciSampleType.INT24:\n return 3;\n case TciSampleType.INT32:\n case TciSampleType.FLOAT32:\n return 4;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function sampleTypeName(sampleType: TciSampleType): TciSampleTypeName {\n switch (sampleType) {\n case TciSampleType.INT16:\n return 'int16';\n case TciSampleType.INT24:\n return 'int24';\n case TciSampleType.INT32:\n return 'int32';\n case TciSampleType.FLOAT32:\n return 'float32';\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n}\n\nexport function normalizeSampleType(sampleType: TciSampleType | TciSampleTypeName | number): TciSampleType {\n if (typeof sampleType === 'string') {\n switch (sampleType.toLowerCase()) {\n case 'int16':\n return TciSampleType.INT16;\n case 'int24':\n return TciSampleType.INT24;\n case 'int32':\n return TciSampleType.INT32;\n case 'float32':\n return TciSampleType.FLOAT32;\n default:\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n }\n }\n if (sampleType >= TciSampleType.INT16 && sampleType <= TciSampleType.FLOAT32) {\n return sampleType as TciSampleType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI sample type: ${sampleType}`);\n}\n\nexport function normalizeStreamType(streamType: TciStreamType | number): TciStreamType {\n if (streamType >= TciStreamType.IQ_STREAM && streamType <= TciStreamType.LINEOUT_STREAM) {\n return streamType as TciStreamType;\n }\n throw new TciError('invalid-frame', `Unsupported TCI stream type: ${streamType}`);\n}\n\nexport function payloadToFloat32(frameOrPayload: TciStreamFrame | Buffer | Uint8Array, sampleType?: TciSampleType | TciSampleTypeName): Float32Array {\n const payload = isFrame(frameOrPayload) ? frameOrPayload.payload : toBuffer(frameOrPayload);\n const type = isFrame(frameOrPayload) ? frameOrPayload.sampleType : normalizeSampleType(sampleType ?? TciSampleType.FLOAT32);\n const bytes = sampleTypeBytes(type);\n if (payload.byteLength % bytes !== 0) {\n throw new TciError('invalid-frame', 'Payload length is not aligned to sample type');\n }\n\n const output = new Float32Array(payload.byteLength / bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < output.length; i += 1) {\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n output[i] = view.getInt16(offset, true) / 32768;\n break;\n case TciSampleType.INT24:\n output[i] = readInt24(view, offset) / 8388608;\n break;\n case TciSampleType.INT32:\n output[i] = view.getInt32(offset, true) / 2147483648;\n break;\n case TciSampleType.FLOAT32:\n output[i] = view.getFloat32(offset, true);\n break;\n }\n }\n return output;\n}\n\nexport function samplesToPayload(samples: Float32Array | readonly number[], sampleType: TciSampleType | TciSampleTypeName): Buffer {\n const type = normalizeSampleType(sampleType);\n const bytes = sampleTypeBytes(type);\n const payload = Buffer.alloc(samples.length * bytes);\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n for (let i = 0; i < samples.length; i += 1) {\n const value = clampSample(samples[i] ?? 0);\n const offset = i * bytes;\n switch (type) {\n case TciSampleType.INT16:\n view.setInt16(offset, Math.round(value * 32767), true);\n break;\n case TciSampleType.INT24:\n writeInt24(view, offset, Math.round(value * 8388607));\n break;\n case TciSampleType.INT32:\n view.setInt32(offset, Math.round(value * 2147483647), true);\n break;\n case TciSampleType.FLOAT32:\n view.setFloat32(offset, value, true);\n break;\n }\n }\n return payload;\n}\n\nexport function pcm16ToFloat32(input: Buffer | Uint8Array | Int16Array): Float32Array {\n if (input instanceof Int16Array) {\n const output = new Float32Array(input.length);\n for (let i = 0; i < input.length; i += 1) {\n output[i] = input[i] / 32768;\n }\n return output;\n }\n return payloadToFloat32(toBuffer(input), TciSampleType.INT16);\n}\n\nexport function float32ToPcm16(samples: Float32Array | readonly number[]): Buffer {\n return samplesToPayload(samples, TciSampleType.INT16);\n}\n\nexport function deinterleaveChannels(samples: Float32Array, channels: number): Float32Array[] {\n if (channels <= 0 || samples.length % channels !== 0) {\n throw new TciError('invalid-frame', 'Cannot deinterleave samples with invalid channel count');\n }\n const frames = samples.length / channels;\n const outputs = Array.from({ length: channels }, () => new Float32Array(frames));\n for (let frame = 0; frame < frames; frame += 1) {\n for (let channel = 0; channel < channels; channel += 1) {\n outputs[channel][frame] = samples[frame * channels + channel];\n }\n }\n return outputs;\n}\n\nexport function mixToMono(samples: Float32Array, channels: number): Float32Array {\n if (channels === 1) {\n return samples;\n }\n const separated = deinterleaveChannels(samples, channels);\n const mono = new Float32Array(separated[0]?.length ?? 0);\n for (const channel of separated) {\n for (let i = 0; i < mono.length; i += 1) {\n mono[i] += channel[i] / channels;\n }\n }\n return mono;\n}\n\nfunction toBuffer(input: Buffer | Uint8Array | ArrayBuffer | ArrayBufferView): Buffer {\n if (Buffer.isBuffer(input)) {\n return input;\n }\n if (input instanceof ArrayBuffer) {\n return Buffer.from(input);\n }\n if (ArrayBuffer.isView(input)) {\n return Buffer.from(input.buffer, input.byteOffset, input.byteLength);\n }\n return Buffer.from(input);\n}\n\nfunction isFrame(value: unknown): value is TciStreamFrame {\n return Boolean(value && typeof value === 'object' && 'payload' in value && 'sampleType' in value);\n}\n\nfunction clampSample(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n return Math.max(-1, Math.min(1, value));\n}\n\nfunction readInt24(view: DataView, offset: number): number {\n const value = view.getUint8(offset) | (view.getUint8(offset + 1) << 8) | (view.getUint8(offset + 2) << 16);\n return value & 0x800000 ? value | 0xff000000 : value;\n}\n\nfunction writeInt24(view: DataView, offset: number, value: number): void {\n const clamped = Math.max(-8388608, Math.min(8388607, value));\n view.setUint8(offset, clamped & 0xff);\n view.setUint8(offset + 1, (clamped >> 8) & 0xff);\n view.setUint8(offset + 2, (clamped >> 16) & 0xff);\n}\n","export interface TciCommand {\n /** Lower-case command name for case-insensitive matching. */\n name: string;\n /** Original command name as received, without surrounding whitespace. */\n originalName: string;\n /** Unescaped argument list. Empty commands have an empty array. */\n args: string[];\n /** Raw command fragment without the trailing semicolon. */\n raw: string;\n}\n\nexport type TciCommandInput = string | TciCommand;\n\nconst ESCAPE_TO_CHAR: Record<string, string> = {\n '^': ':',\n '~': ',',\n '*': ';',\n};\n\nconst CHAR_TO_ESCAPE: Record<string, string> = {\n ':': '^',\n ',': '~',\n ';': '*',\n};\n\nexport function escapeTciText(value: unknown): string {\n return String(value).replace(/[:;,]/g, (char) => CHAR_TO_ESCAPE[char] ?? char);\n}\n\nexport function unescapeTciText(value: string): string {\n return value.replace(/[\\^~*]/g, (char) => ESCAPE_TO_CHAR[char] ?? char);\n}\n\nexport function parseTciText(text: string | Buffer | ArrayBuffer | ArrayBufferView): TciCommand[] {\n const source = normalizeTextInput(text);\n const commands: TciCommand[] = [];\n\n for (const fragment of source.split(';')) {\n const raw = fragment.trim();\n if (!raw) {\n continue;\n }\n\n const colonIndex = raw.indexOf(':');\n const originalName = (colonIndex >= 0 ? raw.slice(0, colonIndex) : raw).trim();\n if (!originalName) {\n continue;\n }\n\n const argsText = colonIndex >= 0 ? raw.slice(colonIndex + 1) : undefined;\n commands.push({\n name: originalName.toLowerCase(),\n originalName,\n args: argsText === undefined ? [] : splitArgs(argsText),\n raw,\n });\n }\n\n return commands;\n}\n\nexport function parseTciCommand(input: TciCommandInput): TciCommand {\n if (typeof input !== 'string') {\n return input;\n }\n const [command] = parseTciText(input);\n if (!command) {\n throw new Error(`Invalid TCI command: ${input}`);\n }\n return command;\n}\n\nexport function formatTciCommand(name: string, args: readonly unknown[] = []): string {\n const commandName = name.trim().toUpperCase();\n if (!commandName) {\n throw new Error('TCI command name cannot be empty');\n }\n if (args.length === 0) {\n return `${commandName};`;\n }\n return `${commandName}:${args.map(escapeTciText).join(',')};`;\n}\n\nexport function normalizeCommandName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nexport function isCommandReplyTo(replyInput: TciCommandInput, requestInput: TciCommandInput): boolean {\n const reply = parseTciCommand(replyInput);\n const request = parseTciCommand(requestInput);\n if (reply.name !== request.name) {\n return false;\n }\n\n if (request.args.length === 0) {\n return true;\n }\n\n if (argsHavePrefix(reply.args, request.args)) {\n return true;\n }\n\n return isKnownVariantReply(reply, request);\n}\n\nexport function commandKey(command: TciCommandInput): string {\n const parsed = parseTciCommand(command);\n return `${parsed.name}:${parsed.args.join(',')}`;\n}\n\nfunction normalizeTextInput(text: string | Buffer | ArrayBuffer | ArrayBufferView): string {\n if (typeof text === 'string') {\n return text;\n }\n if (Buffer.isBuffer(text)) {\n return text.toString('utf8');\n }\n if (text instanceof ArrayBuffer) {\n return Buffer.from(text).toString('utf8');\n }\n return Buffer.from(text.buffer, text.byteOffset, text.byteLength).toString('utf8');\n}\n\nfunction splitArgs(argsText: string): string[] {\n return argsText.split(',').map((arg) => unescapeTciText(arg.trim()));\n}\n\nfunction argsHavePrefix(args: readonly string[], prefix: readonly string[]): boolean {\n if (args.length < prefix.length) {\n return false;\n }\n return prefix.every((arg, index) => args[index]?.toLowerCase() === arg.toLowerCase());\n}\n\nfunction isKnownVariantReply(reply: TciCommand, request: TciCommand): boolean {\n if (reply.name === 'modulation') {\n // ExpertSDR/WSJT-X variants can use MODULATION:rx,mode and MODULATION:rx,vfo,mode.\n if (request.args.length === 2 && reply.args.length >= 3) {\n return reply.args[0] === request.args[0] && reply.args[2]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n if (request.args.length === 3 && reply.args.length === 2) {\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[2]?.toLowerCase();\n }\n }\n\n if (reply.name === 'protocol') {\n return request.args.length <= 1;\n }\n\n if (reply.name === 'trx' && request.args.length >= 3 && reply.args.length >= 2) {\n // Official TRX writes may include an audio source as arg3, while replies only echo trx+state.\n return reply.args[0] === request.args[0] && reply.args[1]?.toLowerCase() === request.args[1]?.toLowerCase();\n }\n\n return false;\n}\n","import { TciError } from '../errors.js';\nimport {\n formatTciCommand,\n isCommandReplyTo,\n parseTciCommand,\n type TciCommand,\n type TciCommandInput,\n} from './text.js';\n\nexport type TciCommandMatcher = (reply: TciCommand, request: TciCommand) => boolean;\n\nexport interface QueueCommandOptions {\n timeoutMs?: number;\n matcher?: TciCommandMatcher;\n signal?: AbortSignal;\n}\n\nexport interface QueuedCommandResult {\n request: TciCommand;\n reply: TciCommand;\n}\n\ninterface PendingCommand {\n raw: string;\n request: TciCommand;\n timeoutMs: number;\n matcher: TciCommandMatcher;\n resolve: (result: QueuedCommandResult) => void;\n reject: (error: TciError) => void;\n timer?: NodeJS.Timeout;\n abortCleanup?: () => void;\n}\n\nexport interface TciCommandQueueOptions {\n send: (raw: string) => void | Promise<void>;\n timeoutMs?: number;\n}\n\nexport class TciCommandQueue {\n private readonly send: (raw: string) => void | Promise<void>;\n private readonly defaultTimeoutMs: number;\n private queue: PendingCommand[] = [];\n private active?: PendingCommand;\n private connected = true;\n\n constructor(options: TciCommandQueueOptions) {\n this.send = options.send;\n this.defaultTimeoutMs = options.timeoutMs ?? 1_000;\n }\n\n setConnected(connected: boolean): void {\n this.connected = connected;\n if (!connected) {\n this.cancelAll(new TciError('disconnected', 'TCI connection closed'));\n }\n }\n\n enqueue(command: TciCommandInput, options: QueueCommandOptions = {}): Promise<QueuedCommandResult> {\n const request = parseTciCommand(command);\n const raw = typeof command === 'string' ? ensureSemicolon(command) : formatTciCommand(command.originalName, command.args);\n\n if (!this.connected) {\n return Promise.reject(new TciError('not-connected', 'TCI socket is not connected'));\n }\n\n return new Promise<QueuedCommandResult>((resolve, reject) => {\n const pending: PendingCommand = {\n raw,\n request,\n timeoutMs: options.timeoutMs ?? this.defaultTimeoutMs,\n matcher: options.matcher ?? ((reply, req) => isCommandReplyTo(reply, req)),\n resolve,\n reject,\n };\n\n if (options.signal) {\n if (options.signal.aborted) {\n reject(new TciError('cancelled', 'TCI command was cancelled'));\n return;\n }\n const onAbort = () => this.rejectPending(pending, new TciError('cancelled', 'TCI command was cancelled'));\n options.signal.addEventListener('abort', onAbort, { once: true });\n pending.abortCleanup = () => options.signal?.removeEventListener('abort', onAbort);\n }\n\n this.queue.push(pending);\n void this.pump();\n });\n }\n\n handleCommand(commandInput: TciCommandInput): boolean {\n const active = this.active;\n if (!active) {\n return false;\n }\n const reply = parseTciCommand(commandInput);\n if (!active.matcher(reply, active.request)) {\n return false;\n }\n this.finishActive(reply);\n return true;\n }\n\n cancelAll(error = new TciError('cancelled', 'TCI command queue cancelled')): void {\n const pending = [...this.queue];\n this.queue = [];\n if (this.active) {\n pending.unshift(this.active);\n this.active = undefined;\n }\n for (const item of pending) {\n this.rejectPending(item, error);\n }\n }\n\n get size(): number {\n return this.queue.length + (this.active ? 1 : 0);\n }\n\n private async pump(): Promise<void> {\n if (this.active || !this.connected) {\n return;\n }\n const next = this.queue.shift();\n if (!next) {\n return;\n }\n\n this.active = next;\n next.timer = setTimeout(() => {\n this.rejectPending(next, new TciError('command-timeout', `Timed out waiting for TCI reply to ${next.raw}`));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }, next.timeoutMs);\n\n try {\n await this.send(next.raw);\n } catch (error) {\n this.rejectPending(next, new TciError('disconnected', error instanceof Error ? error.message : String(error), error));\n if (this.active === next) {\n this.active = undefined;\n }\n void this.pump();\n }\n }\n\n private finishActive(reply: TciCommand): void {\n const active = this.active;\n if (!active) {\n return;\n }\n this.active = undefined;\n if (active.timer) {\n clearTimeout(active.timer);\n }\n active.abortCleanup?.();\n active.resolve({ request: active.request, reply });\n void this.pump();\n }\n\n private rejectPending(pending: PendingCommand, error: TciError): void {\n if (pending.timer) {\n clearTimeout(pending.timer);\n }\n pending.abortCleanup?.();\n const wasActive = this.active === pending;\n if (wasActive) {\n this.active = undefined;\n } else {\n this.queue = this.queue.filter((item) => item !== pending);\n }\n pending.reject(error);\n if (wasActive && this.connected) {\n void this.pump();\n }\n }\n}\n\nfunction ensureSemicolon(command: string): string {\n return command.trim().endsWith(';') ? command.trim() : `${command.trim()};`;\n}\n"],"mappings":"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","names":["TciStreamType","TciSampleType","value"]}
|