icom-wlan-node 0.5.0 → 0.6.0

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.
@@ -1,37 +1,56 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.IcomScopeCommands = void 0;
4
+ const IcomCivFrame_1 = require("../rig/IcomCivFrame");
5
+ const IcomCivSpec_1 = require("../rig/IcomCivSpec");
4
6
  exports.IcomScopeCommands = {
5
7
  setScopeDataOutput(ctrAddr, rigAddr, enabled) {
6
- return Buffer.from([
7
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x11, enabled ? 0x01 : 0x00, 0xfd
8
- ]);
8
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_DOP, payload: [enabled ? 0x01 : 0x00] });
9
9
  },
10
10
  setScopeDisplay(ctrAddr, rigAddr, enabled) {
11
- return Buffer.from([
12
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x10, enabled ? 0x01 : 0x00, 0xfd
13
- ]);
11
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_STS, payload: [enabled ? 0x01 : 0x00] });
14
12
  },
15
13
  readScopeSpan(ctrAddr, rigAddr, receiver = 0) {
16
- return Buffer.from([
17
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x15, receiver & 0xff, 0xfd
18
- ]);
14
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_SPN, payload: [receiver & 0xff] });
19
15
  },
20
16
  setScopeSpan(ctrAddr, rigAddr, spanHz, receiver = 0) {
21
- const bytes = exports.IcomScopeCommands.encodeScopeSpanHz(spanHz);
22
- return Buffer.from([
23
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x15, receiver & 0xff, ...bytes, 0xfd
24
- ]);
17
+ // Hamlib maps public span to ICOM's +/- span value.
18
+ const bytes = exports.IcomScopeCommands.encodeScopeSpanHz(Math.round(spanHz / 2));
19
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_SPN, payload: [receiver & 0xff, ...bytes] });
20
+ },
21
+ readScopeMode(ctrAddr, rigAddr, receiver = 0) {
22
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_MOD, payload: [receiver & 0xff] });
23
+ },
24
+ setScopeMode(ctrAddr, rigAddr, mode, receiver = 0) {
25
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_MOD, payload: [receiver & 0xff, mode & 0xff] });
26
+ },
27
+ readScopeEdge(ctrAddr, rigAddr, receiver = 0) {
28
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_EDG, payload: [receiver & 0xff] });
29
+ },
30
+ setScopeEdge(ctrAddr, rigAddr, edgeSlot, receiver = 0) {
31
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_EDG, payload: [receiver & 0xff, edgeSlot & 0xff] });
32
+ },
33
+ readScopeFixedEdge(ctrAddr, rigAddr, rangeId, edgeSlot) {
34
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_FEF, payload: [rangeId & 0xff, edgeSlot & 0xff] });
35
+ },
36
+ setScopeFixedEdge(ctrAddr, rigAddr, rangeId, edgeSlot, lowHz, highHz) {
37
+ return (0, IcomCivFrame_1.buildCivFrame)({
38
+ rigAddr,
39
+ ctrlAddr: ctrAddr,
40
+ cmd: IcomCivSpec_1.CIV.C_CTL_SCP,
41
+ subcmd: IcomCivSpec_1.CIV.S_SCP_FEF,
42
+ payload: [
43
+ rangeId & 0xff,
44
+ edgeSlot & 0xff,
45
+ ...exports.IcomScopeCommands.encodeScopeFreqHz(lowHz),
46
+ ...exports.IcomScopeCommands.encodeScopeFreqHz(highHz),
47
+ ],
48
+ });
25
49
  },
26
50
  encodeScopeSpanHz(spanHz) {
27
- const safeSpanHz = Math.max(0, Math.round(spanHz));
28
- const out = Buffer.alloc(5);
29
- let remaining = safeSpanHz;
30
- for (let i = 0; i < out.length; i++) {
31
- const twoDigits = remaining % 100;
32
- out[i] = ((((twoDigits / 10) | 0) & 0x0f) << 4) | (twoDigits % 10);
33
- remaining = Math.floor(remaining / 100);
34
- }
35
- return out;
51
+ return (0, IcomCivFrame_1.encodeFrequencyBcdLE)(Math.max(0, Math.round(spanHz)), 5);
52
+ },
53
+ encodeScopeFreqHz(freqHz) {
54
+ return (0, IcomCivFrame_1.encodeFrequencyBcdLE)(Math.max(0, Math.round(freqHz)), 5);
36
55
  }
37
56
  };
package/dist/types.d.ts CHANGED
@@ -8,8 +8,11 @@ export interface IcomCredentials {
8
8
  userName: string;
9
9
  password: string;
10
10
  }
11
+ export type IcomModelId = 'IC-705' | 'IC-905' | 'IC-7300' | 'IC-9700' | 'IC-7610' | 'IC-7760' | 'generic-modern-icom';
11
12
  export interface IcomRigOptions extends IcomCredentials {
12
13
  control: UdpAddress;
14
+ /** Radio model profile. Defaults to auto-detection from rig name or CI-V address. */
15
+ model?: IcomModelId | 'auto';
13
16
  }
14
17
  export interface CivCommand {
15
18
  bytes: Buffer;
@@ -32,6 +35,8 @@ export interface CapabilitiesInfo {
32
35
  civAddress?: number;
33
36
  audioName?: string;
34
37
  supportTX?: boolean;
38
+ modelId?: IcomModelId;
39
+ profileName?: string;
35
40
  }
36
41
  export interface IcomRigEvents {
37
42
  login: (res: LoginResult) => void;
@@ -71,9 +76,11 @@ export type ConnectorDataMode = keyof typeof CONNECTOR_MODE_MAP;
71
76
  export interface SetModeOptions {
72
77
  /**
73
78
  * Enable data mode (e.g., USB-D for digital modes)
74
- * Uses CI-V command 0x26 instead of 0x06
79
+ * Uses CI-V command 0x26 on modern targetable ICOM profiles.
75
80
  */
76
81
  dataMode?: boolean;
82
+ /** Optional IF filter preset. Modern DSP rigs commonly support 1, 2, or 3. */
83
+ filter?: 1 | 2 | 3;
77
84
  }
78
85
  /**
79
86
  * Options for query operations (frequency, meters, etc.)
@@ -114,6 +121,44 @@ export interface IcomScopeSpanInfo {
114
121
  receiver: 0 | 1;
115
122
  spanHz: number;
116
123
  }
124
+ export type IcomScopeMode = 'center' | 'fixed' | 'scroll-center' | 'scroll-fixed';
125
+ export interface IcomScopeModeInfo {
126
+ receiver: 0 | 1;
127
+ mode: 0 | 1 | 2 | 3;
128
+ modeName: IcomScopeMode;
129
+ }
130
+ export interface IcomScopeEdgeInfo {
131
+ receiver: 0 | 1;
132
+ edgeSlot: number;
133
+ }
134
+ export interface IcomScopeFixedEdgeInfo {
135
+ rangeId: number;
136
+ edgeSlot: number;
137
+ lowHz: number;
138
+ highHz: number;
139
+ }
140
+ export interface IcomSpectrumDisplayState {
141
+ mode: IcomScopeMode | null;
142
+ modeCode: 0 | 1 | 2 | 3 | null;
143
+ spanHz: number | null;
144
+ edgeSlot: number | null;
145
+ edgeLowHz: number | null;
146
+ edgeHighHz: number | null;
147
+ supportedModes: IcomScopeMode[];
148
+ supportedSpans: number[];
149
+ supportedEdgeSlots: number[];
150
+ supportsFixedEdges: boolean;
151
+ supportsEdgeSlotSelection: boolean;
152
+ }
153
+ export interface IcomSpectrumDisplayConfig {
154
+ receiver?: 0 | 1;
155
+ mode?: IcomScopeMode;
156
+ spanHz?: number;
157
+ edgeSlot?: number;
158
+ rangeId?: number;
159
+ edgeLowHz?: number;
160
+ edgeHighHz?: number;
161
+ }
117
162
  /**
118
163
  * Result of a meter reading operation (SWR, ALC, etc.)
119
164
  * @deprecated Use specific types like SwrReading, AlcReading instead
@@ -145,8 +190,8 @@ export interface LevelReading {
145
190
  export interface SwrReading {
146
191
  /**
147
192
  * Raw BCD value (0-300+)
148
- * Actual SWR = raw / 100
149
- * Example: 120 = SWR 1.2, 250 = SWR 2.5
193
+ * Conversion is profile-calibrated from Hamlib curves.
194
+ * Example: raw 48 SWR 1.5, raw 120 SWR 3.0 on modern ICOM profiles.
150
195
  */
151
196
  raw: number;
152
197
  /**
@@ -155,7 +200,7 @@ export interface SwrReading {
155
200
  */
156
201
  swr: number;
157
202
  /**
158
- * Alert flag when SWR is too high (≥1.2)
203
+ * Alert flag when SWR is too high (≥3.0)
159
204
  * High SWR can damage transmitter
160
205
  */
161
206
  alert: boolean;
@@ -254,11 +299,13 @@ export interface OvfStatusReading {
254
299
  export interface PowerLevelReading {
255
300
  /**
256
301
  * Raw BCD value (0-255)
257
- * Calibration: 0143≈50%, 0213≈100%
302
+ * Calibration is model-specific.
258
303
  */
259
304
  raw: number;
260
- /** Percentage of maximum power (0-100%) */
305
+ /** Percentage of profile maximum power (0-100%) */
261
306
  percent: number;
307
+ /** Estimated RF output in watts when profile calibration is available */
308
+ watts?: number;
262
309
  }
263
310
  /**
264
311
  * COMP (voice compression) level reading (CI-V 0x15/0x14)
@@ -267,8 +314,10 @@ export interface PowerLevelReading {
267
314
  export interface CompLevelReading {
268
315
  /** Raw BCD value (0-255) */
269
316
  raw: number;
270
- /** Percentage of maximum compression (0-100%) */
317
+ /** Percentage of 30 dB compression scale (0-100%) */
271
318
  percent: number;
319
+ /** Estimated compression level in dB */
320
+ db?: number;
272
321
  }
273
322
  /**
274
323
  * Voltage reading (CI-V 0x15/0x15)
@@ -297,7 +346,7 @@ export interface CurrentReading {
297
346
  amps: number;
298
347
  }
299
348
  /**
300
- * Antenna tuner state (IC-705 CI-V 0x1A/0x00)
349
+ * Antenna tuner state (standard CI-V 0x1C/0x01)
301
350
  * 00=OFF, 01=ON, 02=TUNING
302
351
  */
303
352
  export type TunerState = 'OFF' | 'ON' | 'TUNING';
@@ -31,3 +31,16 @@ export declare class ConnectionAbortedError extends Error {
31
31
  context: Record<string, any> | undefined;
32
32
  };
33
33
  }
34
+ export interface UnsupportedCommandContext {
35
+ modelId?: string;
36
+ commandName: string;
37
+ civCommand?: number | string;
38
+ reason?: string;
39
+ }
40
+ export declare class UnsupportedCommandError extends Error {
41
+ readonly modelId?: string;
42
+ readonly commandName: string;
43
+ readonly civCommand?: number | string;
44
+ readonly reason?: string;
45
+ constructor(context: UnsupportedCommandContext);
46
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConnectionAbortedError = void 0;
3
+ exports.UnsupportedCommandError = exports.ConnectionAbortedError = void 0;
4
4
  exports.getDisconnectMessage = getDisconnectMessage;
5
5
  const types_1 = require("../types");
6
6
  /**
@@ -62,3 +62,19 @@ class ConnectionAbortedError extends Error {
62
62
  }
63
63
  }
64
64
  exports.ConnectionAbortedError = ConnectionAbortedError;
65
+ class UnsupportedCommandError extends Error {
66
+ constructor(context) {
67
+ const details = [
68
+ context.modelId ? `model=${context.modelId}` : undefined,
69
+ context.civCommand !== undefined ? `civ=${context.civCommand}` : undefined,
70
+ context.reason,
71
+ ].filter(Boolean).join(', ');
72
+ super(`Unsupported ICOM CI-V command '${context.commandName}'${details ? ` (${details})` : ''}`);
73
+ this.name = 'UnsupportedCommandError';
74
+ this.modelId = context.modelId;
75
+ this.commandName = context.commandName;
76
+ this.civCommand = context.civCommand;
77
+ this.reason = context.reason;
78
+ }
79
+ }
80
+ exports.UnsupportedCommandError = UnsupportedCommandError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icom-wlan-node",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Icom WLAN (CI‑V, audio) protocol implementation for Node.js/TypeScript.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "license": "MIT",
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "https://github.com/boybook/icom-wlan-node.git"
29
+ "url": "git+https://github.com/boybook/icom-wlan-node.git"
30
30
  },
31
31
  "files": [
32
32
  "dist"