icom-wlan-node 0.6.0 → 0.6.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/README.md
CHANGED
|
@@ -126,6 +126,27 @@ console.log({ tuner, swr, watts: power?.watts, powerPercent: power?.percent });
|
|
|
126
126
|
|
|
127
127
|
Profile-specific behavior includes IC-905 6-byte frequency BCD above 5.85 GHz, model-specific scope fixed-edge ranges, and calibrated SWR/ALC/RF power/COMP/voltage/current meters. Private connector commands such as WLAN level or connector data mode are only enabled when the active profile declares the vendor extension; unsupported writes throw `UnsupportedCommandError`.
|
|
128
128
|
|
|
129
|
+
### CI-V Query Concurrency
|
|
130
|
+
|
|
131
|
+
Standard CI-V frames do not include a transaction/request ID, so the library does not add custom bytes to the CI-V payload. Instead, read/query helpers are internally deduplicated by response signature:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// Same response key: one real CI-V request, shared result
|
|
135
|
+
const [a, b] = await Promise.all([
|
|
136
|
+
rig.readOperatingFrequency(),
|
|
137
|
+
rig.readOperatingFrequency()
|
|
138
|
+
]);
|
|
139
|
+
|
|
140
|
+
// Different response keys: concurrent requests are allowed
|
|
141
|
+
const [freq, mode, ptt] = await Promise.all([
|
|
142
|
+
rig.readOperatingFrequency(),
|
|
143
|
+
rig.readOperatingMode(),
|
|
144
|
+
rig.readPtt()
|
|
145
|
+
]);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Raw `sendCiv()` is not managed by this query layer. Write methods such as `setFrequency()`, `setMode()`, and `setPtt()` remain fire-and-forget; if your application needs write-after-read consistency, send the write first and then issue the read sequentially.
|
|
149
|
+
|
|
129
150
|
### PTT and Audio TX
|
|
130
151
|
|
|
131
152
|
```ts
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RigEventEmitter } from '../types';
|
|
2
|
+
export interface CivQueryOptions {
|
|
3
|
+
key: string;
|
|
4
|
+
predicate: (frame: Buffer) => boolean;
|
|
5
|
+
timeoutMs: number;
|
|
6
|
+
send: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Deduplicates identical CI-V read queries while allowing different reply
|
|
10
|
+
* signatures to wait concurrently on the shared civFrame stream.
|
|
11
|
+
*/
|
|
12
|
+
export declare class IcomCivRequestManager {
|
|
13
|
+
private readonly events;
|
|
14
|
+
private pending;
|
|
15
|
+
private readonly onFrameBound;
|
|
16
|
+
constructor(events: RigEventEmitter);
|
|
17
|
+
query(options: CivQueryOptions): Promise<Buffer | null>;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
getPendingCount(): number;
|
|
20
|
+
private onFrame;
|
|
21
|
+
private finish;
|
|
22
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IcomCivRequestManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Deduplicates identical CI-V read queries while allowing different reply
|
|
6
|
+
* signatures to wait concurrently on the shared civFrame stream.
|
|
7
|
+
*/
|
|
8
|
+
class IcomCivRequestManager {
|
|
9
|
+
constructor(events) {
|
|
10
|
+
this.events = events;
|
|
11
|
+
this.pending = new Map();
|
|
12
|
+
this.onFrameBound = (frame) => this.onFrame(frame);
|
|
13
|
+
this.events.on('civFrame', this.onFrameBound);
|
|
14
|
+
}
|
|
15
|
+
query(options) {
|
|
16
|
+
const existing = this.pending.get(options.key);
|
|
17
|
+
if (existing) {
|
|
18
|
+
return existing.promise;
|
|
19
|
+
}
|
|
20
|
+
let entry;
|
|
21
|
+
const promise = new Promise((resolve, reject) => {
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
if (this.pending.get(options.key) === entry) {
|
|
24
|
+
this.pending.delete(options.key);
|
|
25
|
+
}
|
|
26
|
+
resolve(null);
|
|
27
|
+
}, options.timeoutMs);
|
|
28
|
+
entry = {
|
|
29
|
+
promise: undefined,
|
|
30
|
+
predicate: options.predicate,
|
|
31
|
+
resolve,
|
|
32
|
+
reject,
|
|
33
|
+
timer,
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
entry.promise = promise;
|
|
37
|
+
this.pending.set(options.key, entry);
|
|
38
|
+
try {
|
|
39
|
+
options.send();
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
this.finish(options.key, entry, null, err);
|
|
43
|
+
}
|
|
44
|
+
return promise;
|
|
45
|
+
}
|
|
46
|
+
dispose() {
|
|
47
|
+
this.events.off('civFrame', this.onFrameBound);
|
|
48
|
+
for (const [key, entry] of this.pending) {
|
|
49
|
+
this.finish(key, entry, null);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
getPendingCount() {
|
|
53
|
+
return this.pending.size;
|
|
54
|
+
}
|
|
55
|
+
onFrame(frame) {
|
|
56
|
+
for (const [key, entry] of Array.from(this.pending.entries())) {
|
|
57
|
+
if (entry.predicate(frame)) {
|
|
58
|
+
this.finish(key, entry, frame);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
finish(key, entry, frame, err) {
|
|
63
|
+
if (this.pending.get(key) === entry) {
|
|
64
|
+
this.pending.delete(key);
|
|
65
|
+
}
|
|
66
|
+
clearTimeout(entry.timer);
|
|
67
|
+
if (err !== undefined) {
|
|
68
|
+
entry.reject(err);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
entry.resolve(frame);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.IcomCivRequestManager = IcomCivRequestManager;
|
package/dist/rig/IcomControl.js
CHANGED
|
@@ -52,6 +52,7 @@ const IcomScopeService_1 = require("../scope/IcomScopeService");
|
|
|
52
52
|
const IcomCivFrame_1 = require("./IcomCivFrame");
|
|
53
53
|
const IcomCivSpec_1 = require("./IcomCivSpec");
|
|
54
54
|
const IcomProfiles_1 = require("./IcomProfiles");
|
|
55
|
+
const IcomCivRequestManager_1 = require("./IcomCivRequestManager");
|
|
55
56
|
const DEFAULT_SCOPE_SPANS_HZ = [25000000, 10000000, 5000000, 2500000, 1000000, 500000, 250000, 100000, 50000, 25000, 10000, 5000, 2500];
|
|
56
57
|
function modeCodeToName(mode) {
|
|
57
58
|
switch (mode) {
|
|
@@ -119,6 +120,7 @@ class IcomControl {
|
|
|
119
120
|
this.civ = new IcomCiv_1.IcomCiv(this.civSess);
|
|
120
121
|
this.audio = new IcomAudio_1.IcomAudio(this.audioSess);
|
|
121
122
|
this.scope = new IcomScopeService_1.IcomScopeService();
|
|
123
|
+
this.civRequestManager = new IcomCivRequestManager_1.IcomCivRequestManager(this.ev);
|
|
122
124
|
this.scope.on('scopeSegment', (segment) => this.ev.emit('scopeSegment', segment));
|
|
123
125
|
this.scope.on('scopeFrame', (frame) => this.ev.emit('scopeFrame', frame));
|
|
124
126
|
}
|
|
@@ -576,7 +578,7 @@ class IcomControl {
|
|
|
576
578
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
577
579
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
578
580
|
const req = IcomScopeCommands_1.IcomScopeCommands.readScopeSpan(ctrAddr, rigAddr, receiver);
|
|
579
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x15, receiver], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
581
|
+
const resp = await this.waitForCivFrame(`scope:0x27:0x15:${receiver}`, (frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x15, receiver], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
580
582
|
if (!resp || resp.length < 13) {
|
|
581
583
|
return null;
|
|
582
584
|
}
|
|
@@ -598,7 +600,7 @@ class IcomControl {
|
|
|
598
600
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
599
601
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
600
602
|
const req = IcomScopeCommands_1.IcomScopeCommands.readScopeMode(ctrAddr, rigAddr, receiver);
|
|
601
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x14, receiver], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
603
|
+
const resp = await this.waitForCivFrame(`scope:0x27:0x14:${receiver}`, (frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x14, receiver], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
602
604
|
if (!resp || resp.length < 9) {
|
|
603
605
|
return null;
|
|
604
606
|
}
|
|
@@ -622,7 +624,7 @@ class IcomControl {
|
|
|
622
624
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
623
625
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
624
626
|
const req = IcomScopeCommands_1.IcomScopeCommands.readScopeEdge(ctrAddr, rigAddr, receiver);
|
|
625
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x16, receiver], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
627
|
+
const resp = await this.waitForCivFrame(`scope:0x27:0x16:${receiver}`, (frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x16, receiver], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
626
628
|
if (!resp || resp.length < 9) {
|
|
627
629
|
return null;
|
|
628
630
|
}
|
|
@@ -645,7 +647,7 @@ class IcomControl {
|
|
|
645
647
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
646
648
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
647
649
|
const req = IcomScopeCommands_1.IcomScopeCommands.readScopeFixedEdge(ctrAddr, rigAddr, rangeId, edgeSlot);
|
|
648
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x1e, rangeId, edgeSlot], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
650
|
+
const resp = await this.waitForCivFrame(`scope:0x27:0x1e:${rangeId}:${edgeSlot}`, (frame) => IcomControl.matchCommandFrame(frame, 0x27, [0x1e, rangeId, edgeSlot], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
649
651
|
if (!resp || resp.length < 18) {
|
|
650
652
|
return null;
|
|
651
653
|
}
|
|
@@ -855,7 +857,7 @@ class IcomControl {
|
|
|
855
857
|
const req = useX25
|
|
856
858
|
? IcomRigCommands_1.IcomRigCommands.readSelectedFrequency(ctrAddr, rigAddr, 0)
|
|
857
859
|
: IcomRigCommands_1.IcomRigCommands.readOperatingFrequency(ctrAddr, rigAddr);
|
|
858
|
-
const resp = await this.waitForCivFrame((frame) => useX25
|
|
860
|
+
const resp = await this.waitForCivFrame(useX25 ? 'freq:0x25:0' : 'freq:0x03', (frame) => useX25
|
|
859
861
|
? IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_SEND_SEL_FREQ, [0x00], ctrAddr, rigAddr)
|
|
860
862
|
: IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_RD_FREQ, [], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
861
863
|
if (!resp)
|
|
@@ -872,7 +874,7 @@ class IcomControl {
|
|
|
872
874
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
873
875
|
const useX26 = this.activeProfile.supportsX25X26 && this.activeProfile.modeWithFilter;
|
|
874
876
|
const req = useX26 ? IcomRigCommands_1.IcomRigCommands.readSelectedMode(ctrAddr, rigAddr, 0) : IcomRigCommands_1.IcomRigCommands.readOperatingMode(ctrAddr, rigAddr);
|
|
875
|
-
const resp = await this.waitForCivFrame((frame) => useX26
|
|
877
|
+
const resp = await this.waitForCivFrame(useX26 ? 'mode:0x26:0' : 'mode:0x04', (frame) => useX26
|
|
876
878
|
? IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_SEND_SEL_MODE, [0x00], ctrAddr, rigAddr)
|
|
877
879
|
: IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_RD_MODE, [], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
878
880
|
if (!resp)
|
|
@@ -899,7 +901,7 @@ class IcomControl {
|
|
|
899
901
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
900
902
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
901
903
|
const req = IcomRigCommands_1.IcomRigCommands.readTransmitFrequency(ctrAddr, rigAddr);
|
|
902
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_CTL_PTT, [IcomCivSpec_1.CIV.S_RD_TX_FREQ], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
904
|
+
const resp = await this.waitForCivFrame('freq:0x1c:0x03', (frame) => IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_CTL_PTT, [IcomCivSpec_1.CIV.S_RD_TX_FREQ], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
903
905
|
if (!resp)
|
|
904
906
|
return null;
|
|
905
907
|
return IcomControl.parseFrequencyReply(resp, 1);
|
|
@@ -909,7 +911,7 @@ class IcomControl {
|
|
|
909
911
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
910
912
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
911
913
|
const req = IcomRigCommands_1.IcomRigCommands.readPTT(ctrAddr, rigAddr);
|
|
912
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_CTL_PTT, [IcomCivSpec_1.CIV.S_PTT], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
914
|
+
const resp = await this.waitForCivFrame('ptt:0x1c:0x00', (frame) => IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_CTL_PTT, [IcomCivSpec_1.CIV.S_PTT], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
913
915
|
if (!resp || resp.length < 7)
|
|
914
916
|
return null;
|
|
915
917
|
return resp[6] !== 0x00;
|
|
@@ -929,7 +931,7 @@ class IcomControl {
|
|
|
929
931
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
930
932
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
931
933
|
const req = IcomRigCommands_1.IcomRigCommands.readBandEdges(ctrAddr, rigAddr);
|
|
932
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, 0x02, [], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
934
|
+
const resp = await this.waitForCivFrame('band:0x02', (frame) => IcomControl.matchCommandFrame(frame, 0x02, [], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
933
935
|
if (!resp)
|
|
934
936
|
return null;
|
|
935
937
|
// Return raw payload bytes after command
|
|
@@ -950,7 +952,7 @@ class IcomControl {
|
|
|
950
952
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
951
953
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
952
954
|
const req = IcomRigCommands_1.IcomRigCommands.getSWRState(ctrAddr, rigAddr);
|
|
953
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x12, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
955
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x12', (frame) => IcomControl.isMeterReply(frame, 0x12, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
954
956
|
const raw = IcomControl.extractMeterData(resp);
|
|
955
957
|
if (raw === null)
|
|
956
958
|
return null;
|
|
@@ -975,7 +977,7 @@ class IcomControl {
|
|
|
975
977
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
976
978
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
977
979
|
const req = IcomRigCommands_1.IcomRigCommands.getALCState(ctrAddr, rigAddr);
|
|
978
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x13, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
980
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x13', (frame) => IcomControl.isMeterReply(frame, 0x13, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
979
981
|
const raw = IcomControl.extractMeterData(resp);
|
|
980
982
|
if (raw === null)
|
|
981
983
|
return null;
|
|
@@ -1003,7 +1005,7 @@ class IcomControl {
|
|
|
1003
1005
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1004
1006
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1005
1007
|
const req = IcomRigCommands_1.IcomRigCommands.getConnectorWLanLevel(ctrAddr, rigAddr, ext.subext);
|
|
1006
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, ext.command, [ext.subcmd, ...ext.subext], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1008
|
+
const resp = await this.waitForCivFrame(`ext:0x${ext.command.toString(16)}:0x${ext.subcmd.toString(16)}:${ext.subext.join('.')}`, (frame) => IcomControl.matchCommandFrame(frame, ext.command, [ext.subcmd, ...ext.subext], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1007
1009
|
const raw = IcomControl.extractTrailingBcd(resp, ext.dataBytes);
|
|
1008
1010
|
if (raw === null)
|
|
1009
1011
|
return null;
|
|
@@ -1034,7 +1036,7 @@ class IcomControl {
|
|
|
1034
1036
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1035
1037
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1036
1038
|
const req = IcomRigCommands_1.IcomRigCommands.getLevelMeter(ctrAddr, rigAddr);
|
|
1037
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x02, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1039
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x02', (frame) => IcomControl.isMeterReply(frame, 0x02, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1038
1040
|
if (!resp)
|
|
1039
1041
|
return null;
|
|
1040
1042
|
const data = resp.subarray(6, resp.length - 1);
|
|
@@ -1064,7 +1066,7 @@ class IcomControl {
|
|
|
1064
1066
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1065
1067
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1066
1068
|
const req = IcomRigCommands_1.IcomRigCommands.getUsbAfLevel(ctrAddr, rigAddr, ext.subext);
|
|
1067
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, ext.command, [ext.subcmd, ...ext.subext], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1069
|
+
const resp = await this.waitForCivFrame(`ext:0x${ext.command.toString(16)}:0x${ext.subcmd.toString(16)}:${ext.subext.join('.')}`, (frame) => IcomControl.matchCommandFrame(frame, ext.command, [ext.subcmd, ...ext.subext], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1068
1070
|
const raw = IcomControl.extractTrailingBcd(resp, ext.dataBytes);
|
|
1069
1071
|
if (raw === null)
|
|
1070
1072
|
return null;
|
|
@@ -1111,7 +1113,7 @@ class IcomControl {
|
|
|
1111
1113
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1112
1114
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1113
1115
|
const req = IcomRigCommands_1.IcomRigCommands.getTunerStatus(ctrAddr, rigAddr);
|
|
1114
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_CTL_PTT, [IcomCivSpec_1.CIV.S_ANT_TUN], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1116
|
+
const resp = await this.waitForCivFrame('tuner:0x1c:0x01', (frame) => IcomControl.matchCommandFrame(frame, IcomCivSpec_1.CIV.C_CTL_PTT, [IcomCivSpec_1.CIV.S_ANT_TUN], ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1115
1117
|
if (!resp)
|
|
1116
1118
|
return null;
|
|
1117
1119
|
// Expect FE FE [ctr] [rig] 0x1C 0x01 [status] FD
|
|
@@ -1233,7 +1235,7 @@ class IcomControl {
|
|
|
1233
1235
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1234
1236
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1235
1237
|
const req = IcomRigCommands_1.IcomRigCommands.getSquelchStatus(ctrAddr, rigAddr);
|
|
1236
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x01, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1238
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x01', (frame) => IcomControl.isMeterReply(frame, 0x01, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1237
1239
|
const raw = IcomControl.extractMeterData(resp);
|
|
1238
1240
|
if (raw === null)
|
|
1239
1241
|
return null;
|
|
@@ -1257,7 +1259,7 @@ class IcomControl {
|
|
|
1257
1259
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1258
1260
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1259
1261
|
const req = IcomRigCommands_1.IcomRigCommands.getAudioSquelch(ctrAddr, rigAddr);
|
|
1260
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x05, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1262
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x05', (frame) => IcomControl.isMeterReply(frame, 0x05, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1261
1263
|
const raw = IcomControl.extractMeterData(resp);
|
|
1262
1264
|
if (raw === null)
|
|
1263
1265
|
return null;
|
|
@@ -1281,7 +1283,7 @@ class IcomControl {
|
|
|
1281
1283
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1282
1284
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1283
1285
|
const req = IcomRigCommands_1.IcomRigCommands.getOvfStatus(ctrAddr, rigAddr);
|
|
1284
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x07, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1286
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x07', (frame) => IcomControl.isMeterReply(frame, 0x07, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1285
1287
|
const raw = IcomControl.extractMeterData(resp);
|
|
1286
1288
|
if (raw === null)
|
|
1287
1289
|
return null;
|
|
@@ -1305,7 +1307,7 @@ class IcomControl {
|
|
|
1305
1307
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1306
1308
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1307
1309
|
const req = IcomRigCommands_1.IcomRigCommands.getPowerLevel(ctrAddr, rigAddr);
|
|
1308
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x11, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1310
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x11', (frame) => IcomControl.isMeterReply(frame, 0x11, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1309
1311
|
const raw = IcomControl.extractMeterData(resp);
|
|
1310
1312
|
if (raw === null)
|
|
1311
1313
|
return null;
|
|
@@ -1332,7 +1334,7 @@ class IcomControl {
|
|
|
1332
1334
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1333
1335
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1334
1336
|
const req = IcomRigCommands_1.IcomRigCommands.getCompLevel(ctrAddr, rigAddr);
|
|
1335
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x14, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1337
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x14', (frame) => IcomControl.isMeterReply(frame, 0x14, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1336
1338
|
const raw = IcomControl.extractMeterData(resp);
|
|
1337
1339
|
if (raw === null)
|
|
1338
1340
|
return null;
|
|
@@ -1358,7 +1360,7 @@ class IcomControl {
|
|
|
1358
1360
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1359
1361
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1360
1362
|
const req = IcomRigCommands_1.IcomRigCommands.getVoltage(ctrAddr, rigAddr);
|
|
1361
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x15, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1363
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x15', (frame) => IcomControl.isMeterReply(frame, 0x15, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1362
1364
|
const raw = IcomControl.extractMeterData(resp);
|
|
1363
1365
|
if (raw === null)
|
|
1364
1366
|
return null;
|
|
@@ -1382,7 +1384,7 @@ class IcomControl {
|
|
|
1382
1384
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1383
1385
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1384
1386
|
const req = IcomRigCommands_1.IcomRigCommands.getCurrent(ctrAddr, rigAddr);
|
|
1385
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x16, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1387
|
+
const resp = await this.waitForCivFrame('meter:0x15:0x16', (frame) => IcomControl.isMeterReply(frame, 0x16, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1386
1388
|
const raw = IcomControl.extractMeterData(resp);
|
|
1387
1389
|
if (raw === null)
|
|
1388
1390
|
return null;
|
|
@@ -1822,26 +1824,14 @@ class IcomControl {
|
|
|
1822
1824
|
// Continue loop in case multiple frames are in buffer
|
|
1823
1825
|
}
|
|
1824
1826
|
}
|
|
1825
|
-
// Wait for
|
|
1826
|
-
async waitForCivFrame(predicate, timeoutMs, onSend) {
|
|
1827
|
-
return
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
resolve(frame);
|
|
1834
|
-
}
|
|
1835
|
-
};
|
|
1836
|
-
this.ev.on('civFrame', onFrame);
|
|
1837
|
-
if (onSend)
|
|
1838
|
-
onSend();
|
|
1839
|
-
setTimeout(() => {
|
|
1840
|
-
if (!done) {
|
|
1841
|
-
this.ev.off('civFrame', onFrame);
|
|
1842
|
-
resolve(null);
|
|
1843
|
-
}
|
|
1844
|
-
}, timeoutMs);
|
|
1827
|
+
// Wait for a CI-V reply by response key. Same-key queries are deduplicated.
|
|
1828
|
+
async waitForCivFrame(key, predicate, timeoutMs, onSend) {
|
|
1829
|
+
return this.civRequestManager.query({
|
|
1830
|
+
key,
|
|
1831
|
+
predicate,
|
|
1832
|
+
timeoutMs,
|
|
1833
|
+
send: () => { if (onSend)
|
|
1834
|
+
onSend(); },
|
|
1845
1835
|
});
|
|
1846
1836
|
}
|
|
1847
1837
|
// Strict meter reply matcher: FE FE [ctr|00] [rig] 0x15 [sub] ... FD
|
|
@@ -1889,7 +1879,7 @@ class IcomControl {
|
|
|
1889
1879
|
const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
|
|
1890
1880
|
const rigAddr = this.civ.civAddress & 0xff;
|
|
1891
1881
|
const req = IcomRigCommands_1.IcomRigCommands.get0x14Level(ctrAddr, rigAddr, subcmd);
|
|
1892
|
-
const resp = await this.waitForCivFrame((frame) => IcomControl.is0x14DataReply(frame, subcmd, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1882
|
+
const resp = await this.waitForCivFrame(`level:0x14:0x${subcmd.toString(16)}`, (frame) => IcomControl.is0x14DataReply(frame, subcmd, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
|
|
1893
1883
|
if (!resp || resp.length < 9)
|
|
1894
1884
|
return null;
|
|
1895
1885
|
const raw = (0, bcd_1.parseTwoByteBcd)(resp.subarray(6, 8));
|