icom-wlan-node 0.2.0 → 0.2.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
@@ -111,15 +111,16 @@ await rig.setPtt(false);
111
111
  - `reconnectAttempting(ReconnectAttemptInfo)` — reconnect attempt started
112
112
  - `reconnectFailed(ReconnectFailedInfo)` — reconnect attempt failed
113
113
  - Methods
114
- - `connect()` / `disconnect()` — connects control + CIV + audio sub‑sessions; resolves when all ready
115
- - `sendCiv(buf: Buffer)` — send a raw CI‑V frame
116
- - `setPtt(on: boolean)` — key/unkey; also manages TX meter polling and audio tailing
117
- - `sendAudioFloat32(samples: Float32Array, addLeadingBuffer?: boolean)` / `sendAudioPcm16(samples: Int16Array)`
118
- - `getConnectionPhase()` returns current ConnectionPhase (IDLE, CONNECTING, CONNECTED, DISCONNECTING, RECONNECTING)
119
- - `getConnectionMetrics()` returns detailed ConnectionMetrics (phase, uptime, session states, etc.)
120
- - `getConnectionState()` returns per‑session ConnectionState (control, civ, audio)
121
- - `isAnySessionDisconnected()` — returns true if any session is disconnected
122
- - `configureMonitoring(config)` — configure connection monitoring and auto‑reconnect behavior
114
+ - **Connection**: `connect()` / `disconnect()` — connects control + CIV + audio sub‑sessions; resolves when all ready
115
+ - **Raw CI‑V**: `sendCiv(buf: Buffer)` — send a raw CI‑V frame
116
+ - **Audio TX**: `setPtt(on: boolean)`, `sendAudioFloat32()`, `sendAudioPcm16()`
117
+ - **Rig Control**: `setFrequency()`, `setMode()`, `setConnectorDataMode()`, `setConnectorWLanLevel()`
118
+ - **Rig Query**: `readOperatingFrequency()`, `readOperatingMode()`, `readTransmitFrequency()`, `readTransceiverState()`, `readBandEdges()`
119
+ - **Meters (RX)**: `readSquelchStatus()`, `readAudioSquelch()`, `readOvfStatus()`, `getLevelMeter()`
120
+ - **Meters (TX)**: `readSWR()`, `readALC()`, `readPowerLevel()`, `readCompLevel()`
121
+ - **Power Supply**: `readVoltage()`, `readCurrent()`
122
+ - **Audio Config**: `getConnectorWLanLevel()`
123
+ - **Connection Monitoring**: `getConnectionPhase()`, `getConnectionMetrics()`, `getConnectionState()`, `isAnySessionDisconnected()`, `configureMonitoring()`
123
124
 
124
125
  ### Connection Management & Auto-Reconnect
125
126
 
@@ -250,10 +251,24 @@ The library exposes common CI‑V operations as friendly methods. Addresses are
250
251
 
251
252
  #### Meters & Levels
252
253
 
253
- - `readSWR(options?: QueryOptions) => Promise<{ raw: number; swr: number; alert: boolean } | null>`
254
- - `readALC(options?: QueryOptions) => Promise<{ raw: number; percent: number; alert: boolean } | null>`
255
- - `getConnectorWLanLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>`
256
- - `getLevelMeter(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>`
254
+ **Reception Meters** (available anytime):
255
+ - `readSquelchStatus(options?: QueryOptions) => Promise<{ raw: number; isOpen: boolean } | null>` — Squelch gate state (CI-V 0x15/0x01)
256
+ - `readAudioSquelch(options?: QueryOptions) => Promise<{ raw: number; isOpen: boolean } | null>` — Audio squelch state (CI-V 0x15/0x05)
257
+ - `readOvfStatus(options?: QueryOptions) => Promise<{ raw: number; isOverload: boolean } | null>` — ADC overload detection (CI-V 0x15/0x07)
258
+ - `getLevelMeter(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` — S-meter level (CI-V 0x15/0x02)
259
+
260
+ **Transmission Meters** (require PTT on):
261
+ - `readSWR(options?: QueryOptions) => Promise<{ raw: number; swr: number; alert: boolean } | null>` — SWR meter (CI-V 0x15/0x12)
262
+ - `readALC(options?: QueryOptions) => Promise<{ raw: number; percent: number; alert: boolean } | null>` — ALC meter (CI-V 0x15/0x13)
263
+ - `readPowerLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` — Output power level (CI-V 0x15/0x11)
264
+ - `readCompLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` — Voice compression level (CI-V 0x15/0x14)
265
+
266
+ **Power Supply Monitoring**:
267
+ - `readVoltage(options?: QueryOptions) => Promise<{ raw: number; volts: number } | null>` — Supply voltage (CI-V 0x15/0x15)
268
+ - `readCurrent(options?: QueryOptions) => Promise<{ raw: number; amps: number } | null>` — Supply current draw (CI-V 0x15/0x16)
269
+
270
+ **Audio Configuration**:
271
+ - `getConnectorWLanLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` — Get WLAN audio level (CI-V 0x1A/0x05/0x01/0x17)
257
272
  - `setConnectorWLanLevel(level: number)` — Set WLAN audio level (0-255)
258
273
 
259
274
  #### Connector Settings
@@ -290,20 +305,75 @@ for (let n = 0; n < 10; n++) {
290
305
  }
291
306
  await rig.setPtt(false);
292
307
 
293
- // Read meters and connector settings
308
+ // Read reception meters (available anytime)
309
+ const squelch = await rig.readSquelchStatus({ timeout: 2000 });
310
+ if (squelch) {
311
+ console.log(`Squelch: ${squelch.isOpen ? 'OPEN' : 'CLOSED'}`);
312
+ }
313
+
314
+ const audioSq = await rig.readAudioSquelch({ timeout: 2000 });
315
+ if (audioSq) {
316
+ console.log(`Audio Squelch: ${audioSq.isOpen ? 'OPEN' : 'CLOSED'}`);
317
+ }
318
+
319
+ const ovf = await rig.readOvfStatus({ timeout: 2000 });
320
+ if (ovf) {
321
+ console.log(`ADC: ${ovf.isOverload ? '⚠️ OVERLOAD' : '✓ OK'}`);
322
+ }
323
+
324
+ const sMeter = await rig.getLevelMeter({ timeout: 2000 });
325
+ if (sMeter) {
326
+ console.log(`S-Meter: ${sMeter.percent.toFixed(1)}%`);
327
+ }
328
+
329
+ // Read power supply monitoring
330
+ const voltage = await rig.readVoltage({ timeout: 2000 });
331
+ if (voltage) {
332
+ console.log(`Voltage: ${voltage.volts.toFixed(2)}V`);
333
+ }
334
+
335
+ const current = await rig.readCurrent({ timeout: 2000 });
336
+ if (current) {
337
+ console.log(`Current: ${current.amps.toFixed(2)}A`);
338
+ }
339
+
340
+ // Read transmission meters (requires PTT on)
341
+ await rig.setPtt(true);
342
+ await new Promise(r => setTimeout(r, 200)); // Wait for meters to stabilize
343
+
294
344
  const swr = await rig.readSWR({ timeout: 2000 });
345
+ if (swr) {
346
+ console.log(`SWR: ${swr.swr.toFixed(2)} ${swr.alert ? '⚠️ HIGH' : '✓'}`);
347
+ }
348
+
295
349
  const alc = await rig.readALC({ timeout: 2000 });
350
+ if (alc) {
351
+ console.log(`ALC: ${alc.percent.toFixed(1)}% ${alc.alert ? '⚠️ HIGH' : '✓'}`);
352
+ }
353
+
354
+ const power = await rig.readPowerLevel({ timeout: 2000 });
355
+ if (power) {
356
+ console.log(`Power: ${power.percent.toFixed(1)}%`);
357
+ }
358
+
359
+ const comp = await rig.readCompLevel({ timeout: 2000 });
360
+ if (comp) {
361
+ console.log(`COMP: ${comp.percent.toFixed(1)}%`);
362
+ }
363
+
364
+ await rig.setPtt(false);
365
+
366
+ // Configure WLAN connector
296
367
  const wlanLevel = await rig.getConnectorWLanLevel({ timeout: 2000 });
368
+ if (wlanLevel) {
369
+ console.log(`WLAN Level: ${wlanLevel.percent.toFixed(1)}%`);
370
+ }
297
371
 
298
372
  // Set connector to WLAN mode using string constant
299
373
  await rig.setConnectorDataMode('WLAN');
300
374
  // Or numeric: await rig.setConnectorDataMode(0x03);
301
375
 
302
376
  await rig.setConnectorWLanLevel(120); // Set WLAN audio level
303
-
304
- if (wlanLevel) {
305
- console.log(`WLAN Level: ${wlanLevel.percent.toFixed(1)}%`);
306
- }
307
377
  ```
308
378
 
309
379
  ## Design Notes
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './types';
2
2
  export { IcomControl } from './rig/IcomControl';
3
- export { MODE_MAP, CONNECTOR_MODE_MAP, DEFAULT_CONTROLLER_ADDR, METER_THRESHOLDS, getModeCode, getConnectorModeCode, getModeString, getConnectorModeString, getFilterString } from './rig/IcomConstants';
3
+ export { MODE_MAP, CONNECTOR_MODE_MAP, DEFAULT_CONTROLLER_ADDR, METER_THRESHOLDS, METER_CALIBRATION, getModeCode, getConnectorModeCode, getModeString, getConnectorModeString, getFilterString, rawToPowerPercent, rawToVoltage, rawToCurrent } from './rig/IcomConstants';
4
4
  export { parseTwoByteBcd, intToTwoByteBcd } from './utils/bcd';
5
5
  export { IcomRigCommands } from './rig/IcomRigCommands';
6
6
  export { AUDIO_RATE } from './rig/IcomAudio';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.AUDIO_RATE = exports.IcomRigCommands = exports.intToTwoByteBcd = exports.parseTwoByteBcd = exports.getFilterString = exports.getConnectorModeString = exports.getModeString = exports.getConnectorModeCode = exports.getModeCode = exports.METER_THRESHOLDS = exports.DEFAULT_CONTROLLER_ADDR = exports.CONNECTOR_MODE_MAP = exports.MODE_MAP = exports.IcomControl = void 0;
17
+ exports.AUDIO_RATE = exports.IcomRigCommands = exports.intToTwoByteBcd = exports.parseTwoByteBcd = exports.rawToCurrent = exports.rawToVoltage = exports.rawToPowerPercent = exports.getFilterString = exports.getConnectorModeString = exports.getModeString = exports.getConnectorModeCode = exports.getModeCode = exports.METER_CALIBRATION = exports.METER_THRESHOLDS = exports.DEFAULT_CONTROLLER_ADDR = exports.CONNECTOR_MODE_MAP = exports.MODE_MAP = exports.IcomControl = void 0;
18
18
  // Export types (includes ConnectionPhase, ConnectionMetrics, etc.)
19
19
  __exportStar(require("./types"), exports);
20
20
  // Export main class
@@ -26,11 +26,15 @@ Object.defineProperty(exports, "MODE_MAP", { enumerable: true, get: function ()
26
26
  Object.defineProperty(exports, "CONNECTOR_MODE_MAP", { enumerable: true, get: function () { return IcomConstants_1.CONNECTOR_MODE_MAP; } });
27
27
  Object.defineProperty(exports, "DEFAULT_CONTROLLER_ADDR", { enumerable: true, get: function () { return IcomConstants_1.DEFAULT_CONTROLLER_ADDR; } });
28
28
  Object.defineProperty(exports, "METER_THRESHOLDS", { enumerable: true, get: function () { return IcomConstants_1.METER_THRESHOLDS; } });
29
+ Object.defineProperty(exports, "METER_CALIBRATION", { enumerable: true, get: function () { return IcomConstants_1.METER_CALIBRATION; } });
29
30
  Object.defineProperty(exports, "getModeCode", { enumerable: true, get: function () { return IcomConstants_1.getModeCode; } });
30
31
  Object.defineProperty(exports, "getConnectorModeCode", { enumerable: true, get: function () { return IcomConstants_1.getConnectorModeCode; } });
31
32
  Object.defineProperty(exports, "getModeString", { enumerable: true, get: function () { return IcomConstants_1.getModeString; } });
32
33
  Object.defineProperty(exports, "getConnectorModeString", { enumerable: true, get: function () { return IcomConstants_1.getConnectorModeString; } });
33
34
  Object.defineProperty(exports, "getFilterString", { enumerable: true, get: function () { return IcomConstants_1.getFilterString; } });
35
+ Object.defineProperty(exports, "rawToPowerPercent", { enumerable: true, get: function () { return IcomConstants_1.rawToPowerPercent; } });
36
+ Object.defineProperty(exports, "rawToVoltage", { enumerable: true, get: function () { return IcomConstants_1.rawToVoltage; } });
37
+ Object.defineProperty(exports, "rawToCurrent", { enumerable: true, get: function () { return IcomConstants_1.rawToCurrent; } });
34
38
  // Export BCD utilities
35
39
  var bcd_1 = require("./utils/bcd");
36
40
  Object.defineProperty(exports, "parseTwoByteBcd", { enumerable: true, get: function () { return bcd_1.parseTwoByteBcd; } });
@@ -82,3 +82,75 @@ export declare const METER_THRESHOLDS: {
82
82
  * Matches FT8CN's IComPacketTypes.METER_TIMER_PERIOD_MS
83
83
  */
84
84
  export declare const METER_TIMER_PERIOD_MS = 500;
85
+ /**
86
+ * Meter calibration constants for physical unit conversion
87
+ * Based on IC-705 official CI-V reference manual
88
+ */
89
+ export declare const METER_CALIBRATION: {
90
+ /**
91
+ * Power level (CI-V 0x15/0x11) calibration points
92
+ * Used for converting raw BCD to percentage
93
+ */
94
+ readonly POWER: {
95
+ /** 50% power reference point */
96
+ readonly HALF: {
97
+ readonly raw: 323;
98
+ readonly percent: 50;
99
+ };
100
+ /** 100% power reference point */
101
+ readonly FULL: {
102
+ readonly raw: 531;
103
+ readonly percent: 100;
104
+ };
105
+ };
106
+ /**
107
+ * Voltage (CI-V 0x15/0x15) calibration points
108
+ * Used for converting raw BCD to volts
109
+ */
110
+ readonly VOLTAGE: {
111
+ /** Low voltage reference: 5V */
112
+ readonly LOW: {
113
+ readonly raw: 117;
114
+ readonly volts: 5;
115
+ };
116
+ /** High voltage reference: 16V */
117
+ readonly HIGH: {
118
+ readonly raw: 577;
119
+ readonly volts: 16;
120
+ };
121
+ };
122
+ /**
123
+ * Current (CI-V 0x15/0x16) calibration points
124
+ * Used for converting raw BCD to amperes
125
+ */
126
+ readonly CURRENT: {
127
+ /** Low current reference: 2A */
128
+ readonly LOW: {
129
+ readonly raw: 289;
130
+ readonly amps: 2;
131
+ };
132
+ /** High current reference: 4A */
133
+ readonly HIGH: {
134
+ readonly raw: 577;
135
+ readonly amps: 4;
136
+ };
137
+ };
138
+ };
139
+ /**
140
+ * Convert raw power level to percentage
141
+ * @param raw - Raw BCD value (0-255)
142
+ * @returns Power percentage (0-100%)
143
+ */
144
+ export declare function rawToPowerPercent(raw: number): number;
145
+ /**
146
+ * Convert raw voltage reading to volts
147
+ * @param raw - Raw BCD value (0-255)
148
+ * @returns Voltage in volts
149
+ */
150
+ export declare function rawToVoltage(raw: number): number;
151
+ /**
152
+ * Convert raw current reading to amperes
153
+ * @param raw - Raw BCD value (0-255)
154
+ * @returns Current in amperes
155
+ */
156
+ export declare function rawToCurrent(raw: number): number;
@@ -4,12 +4,15 @@
4
4
  * Based on FT8CN's IcomRigConstant.java
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.METER_TIMER_PERIOD_MS = exports.METER_THRESHOLDS = exports.DEFAULT_CONTROLLER_ADDR = exports.CONNECTOR_MODE_MAP = exports.MODE_MAP = void 0;
7
+ exports.METER_CALIBRATION = exports.METER_TIMER_PERIOD_MS = exports.METER_THRESHOLDS = exports.DEFAULT_CONTROLLER_ADDR = exports.CONNECTOR_MODE_MAP = exports.MODE_MAP = void 0;
8
8
  exports.getModeCode = getModeCode;
9
9
  exports.getConnectorModeCode = getConnectorModeCode;
10
10
  exports.getModeString = getModeString;
11
11
  exports.getConnectorModeString = getConnectorModeString;
12
12
  exports.getFilterString = getFilterString;
13
+ exports.rawToPowerPercent = rawToPowerPercent;
14
+ exports.rawToVoltage = rawToVoltage;
15
+ exports.rawToCurrent = rawToCurrent;
13
16
  /**
14
17
  * Operating modes supported by ICOM radios
15
18
  * LSB:0, USB:1, AM:2, CW:3, RTTY:4, FM:5, WFM:6, CW_R:7, RTTY_R:8, DV:17
@@ -110,3 +113,81 @@ exports.METER_THRESHOLDS = {
110
113
  * Matches FT8CN's IComPacketTypes.METER_TIMER_PERIOD_MS
111
114
  */
112
115
  exports.METER_TIMER_PERIOD_MS = 500;
116
+ /**
117
+ * Meter calibration constants for physical unit conversion
118
+ * Based on IC-705 official CI-V reference manual
119
+ */
120
+ exports.METER_CALIBRATION = {
121
+ /**
122
+ * Power level (CI-V 0x15/0x11) calibration points
123
+ * Used for converting raw BCD to percentage
124
+ */
125
+ POWER: {
126
+ /** 50% power reference point */
127
+ HALF: { raw: 0x0143, percent: 50 },
128
+ /** 100% power reference point */
129
+ FULL: { raw: 0x0213, percent: 100 }
130
+ },
131
+ /**
132
+ * Voltage (CI-V 0x15/0x15) calibration points
133
+ * Used for converting raw BCD to volts
134
+ */
135
+ VOLTAGE: {
136
+ /** Low voltage reference: 5V */
137
+ LOW: { raw: 0x0075, volts: 5.0 },
138
+ /** High voltage reference: 16V */
139
+ HIGH: { raw: 0x0241, volts: 16.0 }
140
+ },
141
+ /**
142
+ * Current (CI-V 0x15/0x16) calibration points
143
+ * Used for converting raw BCD to amperes
144
+ */
145
+ CURRENT: {
146
+ /** Low current reference: 2A */
147
+ LOW: { raw: 0x0121, amps: 2.0 },
148
+ /** High current reference: 4A */
149
+ HIGH: { raw: 0x0241, amps: 4.0 }
150
+ }
151
+ };
152
+ /**
153
+ * Linear interpolation helper for meter value conversion
154
+ * @param raw - Raw BCD value
155
+ * @param x1 - Lower calibration point (raw value)
156
+ * @param y1 - Lower calibration point (physical value)
157
+ * @param x2 - Upper calibration point (raw value)
158
+ * @param y2 - Upper calibration point (physical value)
159
+ * @returns Interpolated physical value
160
+ */
161
+ function linearInterpolate(raw, x1, y1, x2, y2) {
162
+ // Clamp to range
163
+ if (raw <= x1)
164
+ return y1;
165
+ if (raw >= x2)
166
+ return y2;
167
+ // Linear interpolation: y = y1 + (raw - x1) * (y2 - y1) / (x2 - x1)
168
+ return y1 + ((raw - x1) * (y2 - y1)) / (x2 - x1);
169
+ }
170
+ /**
171
+ * Convert raw power level to percentage
172
+ * @param raw - Raw BCD value (0-255)
173
+ * @returns Power percentage (0-100%)
174
+ */
175
+ function rawToPowerPercent(raw) {
176
+ return linearInterpolate(raw, exports.METER_CALIBRATION.POWER.HALF.raw, exports.METER_CALIBRATION.POWER.HALF.percent, exports.METER_CALIBRATION.POWER.FULL.raw, exports.METER_CALIBRATION.POWER.FULL.percent);
177
+ }
178
+ /**
179
+ * Convert raw voltage reading to volts
180
+ * @param raw - Raw BCD value (0-255)
181
+ * @returns Voltage in volts
182
+ */
183
+ function rawToVoltage(raw) {
184
+ return linearInterpolate(raw, exports.METER_CALIBRATION.VOLTAGE.LOW.raw, exports.METER_CALIBRATION.VOLTAGE.LOW.volts, exports.METER_CALIBRATION.VOLTAGE.HIGH.raw, exports.METER_CALIBRATION.VOLTAGE.HIGH.volts);
185
+ }
186
+ /**
187
+ * Convert raw current reading to amperes
188
+ * @param raw - Raw BCD value (0-255)
189
+ * @returns Current in amperes
190
+ */
191
+ function rawToCurrent(raw) {
192
+ return linearInterpolate(raw, exports.METER_CALIBRATION.CURRENT.LOW.raw, exports.METER_CALIBRATION.CURRENT.LOW.amps, exports.METER_CALIBRATION.CURRENT.HIGH.raw, exports.METER_CALIBRATION.CURRENT.HIGH.amps);
193
+ }
@@ -1,4 +1,4 @@
1
- import { IcomRigOptions, RigEventEmitter, IcomMode, ConnectorDataMode, SetModeOptions, QueryOptions, SwrReading, AlcReading, WlanLevelReading, LevelMeterReading, ConnectionState, ConnectionMonitorConfig, ConnectionPhase, ConnectionMetrics } from '../types';
1
+ import { IcomRigOptions, RigEventEmitter, IcomMode, ConnectorDataMode, SetModeOptions, QueryOptions, SwrReading, AlcReading, WlanLevelReading, LevelMeterReading, SquelchStatusReading, AudioSquelchReading, OvfStatusReading, PowerLevelReading, CompLevelReading, VoltageReading, CurrentReading, ConnectionState, ConnectionMonitorConfig, ConnectionPhase, ConnectionMetrics } from '../types';
2
2
  import { IcomCiv } from './IcomCiv';
3
3
  import { IcomAudio } from './IcomAudio';
4
4
  export declare class IcomControl {
@@ -172,6 +172,83 @@ export declare class IcomControl {
172
172
  * await rig.setConnectorDataMode('WLAN');
173
173
  */
174
174
  setConnectorDataMode(mode: ConnectorDataMode | number): Promise<void>;
175
+ /**
176
+ * Read squelch status (noise/signal gate state)
177
+ * @param options - Query options (timeout in ms, default 3000)
178
+ * @returns Squelch status with raw value and boolean state
179
+ * @example
180
+ * const status = await rig.readSquelchStatus({ timeout: 2000 });
181
+ * if (status) {
182
+ * console.log(`Squelch: ${status.isOpen ? 'OPEN' : 'CLOSED'}`);
183
+ * }
184
+ */
185
+ readSquelchStatus(options?: QueryOptions): Promise<SquelchStatusReading | null>;
186
+ /**
187
+ * Read audio squelch state
188
+ * @param options - Query options (timeout in ms, default 3000)
189
+ * @returns Audio squelch status with raw value and boolean state
190
+ * @example
191
+ * const squelch = await rig.readAudioSquelch({ timeout: 2000 });
192
+ * if (squelch) {
193
+ * console.log(`Audio Squelch: ${squelch.isOpen ? 'OPEN' : 'CLOSED'}`);
194
+ * }
195
+ */
196
+ readAudioSquelch(options?: QueryOptions): Promise<AudioSquelchReading | null>;
197
+ /**
198
+ * Read OVF (ADC overload) status
199
+ * @param options - Query options (timeout in ms, default 3000)
200
+ * @returns OVF status with raw value and boolean overload flag
201
+ * @example
202
+ * const ovf = await rig.readOvfStatus({ timeout: 2000 });
203
+ * if (ovf) {
204
+ * console.log(`ADC: ${ovf.isOverload ? '⚠️ OVERLOAD' : '✓ OK'}`);
205
+ * }
206
+ */
207
+ readOvfStatus(options?: QueryOptions): Promise<OvfStatusReading | null>;
208
+ /**
209
+ * Read power output level during transmission
210
+ * @param options - Query options (timeout in ms, default 3000)
211
+ * @returns Power level with raw value and percentage
212
+ * @example
213
+ * const power = await rig.readPowerLevel({ timeout: 2000 });
214
+ * if (power) {
215
+ * console.log(`Power: ${power.percent.toFixed(1)}%`);
216
+ * }
217
+ */
218
+ readPowerLevel(options?: QueryOptions): Promise<PowerLevelReading | null>;
219
+ /**
220
+ * Read COMP (voice compression) level during transmission
221
+ * @param options - Query options (timeout in ms, default 3000)
222
+ * @returns Compression level with raw value and percentage
223
+ * @example
224
+ * const comp = await rig.readCompLevel({ timeout: 2000 });
225
+ * if (comp) {
226
+ * console.log(`COMP: ${comp.percent.toFixed(1)}%`);
227
+ * }
228
+ */
229
+ readCompLevel(options?: QueryOptions): Promise<CompLevelReading | null>;
230
+ /**
231
+ * Read power supply voltage
232
+ * @param options - Query options (timeout in ms, default 3000)
233
+ * @returns Voltage reading with raw value and volts
234
+ * @example
235
+ * const voltage = await rig.readVoltage({ timeout: 2000 });
236
+ * if (voltage) {
237
+ * console.log(`Voltage: ${voltage.volts.toFixed(2)}V`);
238
+ * }
239
+ */
240
+ readVoltage(options?: QueryOptions): Promise<VoltageReading | null>;
241
+ /**
242
+ * Read power supply current draw
243
+ * @param options - Query options (timeout in ms, default 3000)
244
+ * @returns Current reading with raw value and amperes
245
+ * @example
246
+ * const current = await rig.readCurrent({ timeout: 2000 });
247
+ * if (current) {
248
+ * console.log(`Current: ${current.amps.toFixed(2)}A`);
249
+ * }
250
+ */
251
+ readCurrent(options?: QueryOptions): Promise<CurrentReading | null>;
175
252
  private static isReplyOf;
176
253
  /**
177
254
  * Extract meter data from CI-V response frame
@@ -732,6 +732,174 @@ class IcomControl {
732
732
  const modeCode = typeof mode === 'string' ? (0, IcomConstants_1.getConnectorModeCode)(mode) : mode;
733
733
  this.sendCiv(IcomRigCommands_1.IcomRigCommands.setConnectorDataMode(ctrAddr, rigAddr, modeCode));
734
734
  }
735
+ /**
736
+ * Read squelch status (noise/signal gate state)
737
+ * @param options - Query options (timeout in ms, default 3000)
738
+ * @returns Squelch status with raw value and boolean state
739
+ * @example
740
+ * const status = await rig.readSquelchStatus({ timeout: 2000 });
741
+ * if (status) {
742
+ * console.log(`Squelch: ${status.isOpen ? 'OPEN' : 'CLOSED'}`);
743
+ * }
744
+ */
745
+ async readSquelchStatus(options) {
746
+ const timeoutMs = options?.timeout ?? 3000;
747
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
748
+ const rigAddr = this.civ.civAddress & 0xff;
749
+ const req = IcomRigCommands_1.IcomRigCommands.getSquelchStatus(ctrAddr, rigAddr);
750
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x01, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
751
+ const raw = IcomControl.extractMeterData(resp);
752
+ if (raw === null)
753
+ return null;
754
+ return {
755
+ raw,
756
+ isOpen: raw === 0x0001
757
+ };
758
+ }
759
+ /**
760
+ * Read audio squelch state
761
+ * @param options - Query options (timeout in ms, default 3000)
762
+ * @returns Audio squelch status with raw value and boolean state
763
+ * @example
764
+ * const squelch = await rig.readAudioSquelch({ timeout: 2000 });
765
+ * if (squelch) {
766
+ * console.log(`Audio Squelch: ${squelch.isOpen ? 'OPEN' : 'CLOSED'}`);
767
+ * }
768
+ */
769
+ async readAudioSquelch(options) {
770
+ const timeoutMs = options?.timeout ?? 3000;
771
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
772
+ const rigAddr = this.civ.civAddress & 0xff;
773
+ const req = IcomRigCommands_1.IcomRigCommands.getAudioSquelch(ctrAddr, rigAddr);
774
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x05, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
775
+ const raw = IcomControl.extractMeterData(resp);
776
+ if (raw === null)
777
+ return null;
778
+ return {
779
+ raw,
780
+ isOpen: raw === 0x0001
781
+ };
782
+ }
783
+ /**
784
+ * Read OVF (ADC overload) status
785
+ * @param options - Query options (timeout in ms, default 3000)
786
+ * @returns OVF status with raw value and boolean overload flag
787
+ * @example
788
+ * const ovf = await rig.readOvfStatus({ timeout: 2000 });
789
+ * if (ovf) {
790
+ * console.log(`ADC: ${ovf.isOverload ? '⚠️ OVERLOAD' : '✓ OK'}`);
791
+ * }
792
+ */
793
+ async readOvfStatus(options) {
794
+ const timeoutMs = options?.timeout ?? 3000;
795
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
796
+ const rigAddr = this.civ.civAddress & 0xff;
797
+ const req = IcomRigCommands_1.IcomRigCommands.getOvfStatus(ctrAddr, rigAddr);
798
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x07, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
799
+ const raw = IcomControl.extractMeterData(resp);
800
+ if (raw === null)
801
+ return null;
802
+ return {
803
+ raw,
804
+ isOverload: raw === 0x0001
805
+ };
806
+ }
807
+ /**
808
+ * Read power output level during transmission
809
+ * @param options - Query options (timeout in ms, default 3000)
810
+ * @returns Power level with raw value and percentage
811
+ * @example
812
+ * const power = await rig.readPowerLevel({ timeout: 2000 });
813
+ * if (power) {
814
+ * console.log(`Power: ${power.percent.toFixed(1)}%`);
815
+ * }
816
+ */
817
+ async readPowerLevel(options) {
818
+ const timeoutMs = options?.timeout ?? 3000;
819
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
820
+ const rigAddr = this.civ.civAddress & 0xff;
821
+ const req = IcomRigCommands_1.IcomRigCommands.getPowerLevel(ctrAddr, rigAddr);
822
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x11, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
823
+ const raw = IcomControl.extractMeterData(resp);
824
+ if (raw === null)
825
+ return null;
826
+ return {
827
+ raw,
828
+ percent: (0, IcomConstants_1.rawToPowerPercent)(raw)
829
+ };
830
+ }
831
+ /**
832
+ * Read COMP (voice compression) level during transmission
833
+ * @param options - Query options (timeout in ms, default 3000)
834
+ * @returns Compression level with raw value and percentage
835
+ * @example
836
+ * const comp = await rig.readCompLevel({ timeout: 2000 });
837
+ * if (comp) {
838
+ * console.log(`COMP: ${comp.percent.toFixed(1)}%`);
839
+ * }
840
+ */
841
+ async readCompLevel(options) {
842
+ const timeoutMs = options?.timeout ?? 3000;
843
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
844
+ const rigAddr = this.civ.civAddress & 0xff;
845
+ const req = IcomRigCommands_1.IcomRigCommands.getCompLevel(ctrAddr, rigAddr);
846
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x14, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
847
+ const raw = IcomControl.extractMeterData(resp);
848
+ if (raw === null)
849
+ return null;
850
+ return {
851
+ raw,
852
+ percent: (raw / 255) * 100
853
+ };
854
+ }
855
+ /**
856
+ * Read power supply voltage
857
+ * @param options - Query options (timeout in ms, default 3000)
858
+ * @returns Voltage reading with raw value and volts
859
+ * @example
860
+ * const voltage = await rig.readVoltage({ timeout: 2000 });
861
+ * if (voltage) {
862
+ * console.log(`Voltage: ${voltage.volts.toFixed(2)}V`);
863
+ * }
864
+ */
865
+ async readVoltage(options) {
866
+ const timeoutMs = options?.timeout ?? 3000;
867
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
868
+ const rigAddr = this.civ.civAddress & 0xff;
869
+ const req = IcomRigCommands_1.IcomRigCommands.getVoltage(ctrAddr, rigAddr);
870
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x15, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
871
+ const raw = IcomControl.extractMeterData(resp);
872
+ if (raw === null)
873
+ return null;
874
+ return {
875
+ raw,
876
+ volts: (0, IcomConstants_1.rawToVoltage)(raw)
877
+ };
878
+ }
879
+ /**
880
+ * Read power supply current draw
881
+ * @param options - Query options (timeout in ms, default 3000)
882
+ * @returns Current reading with raw value and amperes
883
+ * @example
884
+ * const current = await rig.readCurrent({ timeout: 2000 });
885
+ * if (current) {
886
+ * console.log(`Current: ${current.amps.toFixed(2)}A`);
887
+ * }
888
+ */
889
+ async readCurrent(options) {
890
+ const timeoutMs = options?.timeout ?? 3000;
891
+ const ctrAddr = IcomConstants_1.DEFAULT_CONTROLLER_ADDR;
892
+ const rigAddr = this.civ.civAddress & 0xff;
893
+ const req = IcomRigCommands_1.IcomRigCommands.getCurrent(ctrAddr, rigAddr);
894
+ const resp = await this.waitForCivFrame((frame) => IcomControl.isMeterReply(frame, 0x16, ctrAddr, rigAddr), timeoutMs, () => this.sendCiv(req));
895
+ const raw = IcomControl.extractMeterData(resp);
896
+ if (raw === null)
897
+ return null;
898
+ return {
899
+ raw,
900
+ amps: (0, IcomConstants_1.rawToCurrent)(raw)
901
+ };
902
+ }
735
903
  static isReplyOf(frame, cmd, ctrAddr, rigAddr) {
736
904
  // typical reply FE FE [ctr] [rig] cmd ... FD
737
905
  return frame.length >= 7 && frame[0] === 0xfe && frame[1] === 0xfe && frame[4] === (cmd & 0xff);
@@ -14,4 +14,11 @@ export declare const IcomRigCommands: {
14
14
  getConnectorWLanLevel(ctrAddr: number, rigAddr: number): Buffer;
15
15
  setConnectorWLanLevel(ctrAddr: number, rigAddr: number, level: number): Buffer;
16
16
  setConnectorDataMode(ctrAddr: number, rigAddr: number, mode: number): Buffer;
17
+ getSquelchStatus(ctrAddr: number, rigAddr: number): Buffer;
18
+ getAudioSquelch(ctrAddr: number, rigAddr: number): Buffer;
19
+ getOvfStatus(ctrAddr: number, rigAddr: number): Buffer;
20
+ getPowerLevel(ctrAddr: number, rigAddr: number): Buffer;
21
+ getCompLevel(ctrAddr: number, rigAddr: number): Buffer;
22
+ getVoltage(ctrAddr: number, rigAddr: number): Buffer;
23
+ getCurrent(ctrAddr: number, rigAddr: number): Buffer;
17
24
  };
@@ -69,5 +69,33 @@ exports.IcomRigCommands = {
69
69
  setConnectorDataMode(ctrAddr, rigAddr, mode) {
70
70
  // FE FE [rig] [ctr] 0x1A 0x05 0x01 0x19 [mode] FD
71
71
  return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x1a, 0x05, 0x01, 0x19, mode & 0xff, 0xfd]);
72
+ },
73
+ getSquelchStatus(ctrAddr, rigAddr) {
74
+ // FE FE [rig] [ctr] 0x15 0x01 FD
75
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x01, 0xfd]);
76
+ },
77
+ getAudioSquelch(ctrAddr, rigAddr) {
78
+ // FE FE [rig] [ctr] 0x15 0x05 FD
79
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x05, 0xfd]);
80
+ },
81
+ getOvfStatus(ctrAddr, rigAddr) {
82
+ // FE FE [rig] [ctr] 0x15 0x07 FD
83
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x07, 0xfd]);
84
+ },
85
+ getPowerLevel(ctrAddr, rigAddr) {
86
+ // FE FE [rig] [ctr] 0x15 0x11 FD
87
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x11, 0xfd]);
88
+ },
89
+ getCompLevel(ctrAddr, rigAddr) {
90
+ // FE FE [rig] [ctr] 0x15 0x14 FD
91
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x14, 0xfd]);
92
+ },
93
+ getVoltage(ctrAddr, rigAddr) {
94
+ // FE FE [rig] [ctr] 0x15 0x15 FD
95
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x15, 0xfd]);
96
+ },
97
+ getCurrent(ctrAddr, rigAddr) {
98
+ // FE FE [rig] [ctr] 0x15 0x16 FD
99
+ return Buffer.from([0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x15, 0x16, 0xfd]);
72
100
  }
73
101
  };
package/dist/types.d.ts CHANGED
@@ -162,6 +162,85 @@ export interface LevelMeterReading {
162
162
  /** Percentage (0-100%) */
163
163
  percent: number;
164
164
  }
165
+ /**
166
+ * Squelch status reading (CI-V 0x15/0x01)
167
+ * Indicates whether noise/signal squelch gate is open or closed
168
+ */
169
+ export interface SquelchStatusReading {
170
+ /** Raw BCD value (0 or 1) */
171
+ raw: number;
172
+ /** True if squelch is open (signal present), false if closed (no signal) */
173
+ isOpen: boolean;
174
+ }
175
+ /**
176
+ * Audio squelch reading (CI-V 0x15/0x05)
177
+ * Indicates audio squelch state
178
+ */
179
+ export interface AudioSquelchReading {
180
+ /** Raw BCD value (0 or 1) */
181
+ raw: number;
182
+ /** True if audio squelch is open, false if closed */
183
+ isOpen: boolean;
184
+ }
185
+ /**
186
+ * OVF (ADC overload) status reading (CI-V 0x15/0x07)
187
+ * Indicates whether the ADC (analog-to-digital converter) is overloading
188
+ */
189
+ export interface OvfStatusReading {
190
+ /** Raw BCD value (0 or 1) */
191
+ raw: number;
192
+ /** True if ADC is overloading, false if normal */
193
+ isOverload: boolean;
194
+ }
195
+ /**
196
+ * Power output level reading (CI-V 0x15/0x11)
197
+ * Represents transmitter output power level
198
+ */
199
+ export interface PowerLevelReading {
200
+ /**
201
+ * Raw BCD value (0-255)
202
+ * Calibration: 0143≈50%, 0213≈100%
203
+ */
204
+ raw: number;
205
+ /** Percentage of maximum power (0-100%) */
206
+ percent: number;
207
+ }
208
+ /**
209
+ * COMP (voice compression) level reading (CI-V 0x15/0x14)
210
+ * Represents speech compressor level during transmission
211
+ */
212
+ export interface CompLevelReading {
213
+ /** Raw BCD value (0-255) */
214
+ raw: number;
215
+ /** Percentage of maximum compression (0-100%) */
216
+ percent: number;
217
+ }
218
+ /**
219
+ * Voltage reading (CI-V 0x15/0x15)
220
+ * Represents power supply voltage
221
+ */
222
+ export interface VoltageReading {
223
+ /**
224
+ * Raw BCD value (0-255)
225
+ * Calibration: 0075≈5V, 0241≈16V
226
+ */
227
+ raw: number;
228
+ /** Voltage in volts */
229
+ volts: number;
230
+ }
231
+ /**
232
+ * Current reading (CI-V 0x15/0x16)
233
+ * Represents power supply current draw
234
+ */
235
+ export interface CurrentReading {
236
+ /**
237
+ * Raw BCD value (0-255)
238
+ * Calibration: 0121≈2A, 0241≈4A
239
+ */
240
+ raw: number;
241
+ /** Current in amperes */
242
+ amps: number;
243
+ }
165
244
  /**
166
245
  * Connection state enumeration
167
246
  * Represents the current state of a UDP session
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icom-wlan-node",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
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",