Skip to content

Commit ee0c4bf

Browse files
boybookclaude
andcommitted
fix: correct level constants, add auto int/float detection and targetable level bypass
- Fix SHIM_RIG_LEVEL_* bit positions to match Hamlib headers (STRENGTH was bit 26 instead of 30, ALC was bit 30 instead of 29, etc.) - Add shim_rig_get_level_auto() that auto-detects int/float level type using RIG_LEVEL_IS_FLOAT, avoiding type mismatch bugs (e.g. STRENGTH read as float returns 0 instead of correct dB value) - Set RIG_TARGETABLE_LEVEL flag to bypass VFO switching in rig_get_level while preserving calibration and locking - Add optional VFO parameter to getLevel() JS API Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e48a87d commit ee0c4bf

4 files changed

Lines changed: 64 additions & 26 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hamlib",
3-
"version": "0.2.4",
3+
"version": "0.2.5",
44
"description": "Node.js wrapper for hamlib radio control library",
55
"main": "index.js",
66
"module": "lib/index.mjs",

src/hamlib.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,14 @@ class SetLevelAsyncWorker : public HamLibAsyncWorker {
308308
class GetLevelAsyncWorker : public HamLibAsyncWorker {
309309
public:
310310
GetLevelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t level_type, int vfo = SHIM_RIG_VFO_CURR)
311-
: HamLibAsyncWorker(env, hamlib_instance), level_type_(level_type), vfo_(vfo), value_(0.0f) {}
311+
: HamLibAsyncWorker(env, hamlib_instance), level_type_(level_type), vfo_(vfo), value_(0.0) {}
312312

313313
void Execute() override {
314314
CHECK_RIG_VALID();
315315

316-
result_code_ = shim_rig_get_level_f(hamlib_instance_->my_rig, vfo_, level_type_, &value_);
316+
// Use auto-detect to handle int levels (STRENGTH, RAWSTR) and
317+
// float levels (SWR, ALC, RFPOWER_METER, etc.) correctly
318+
result_code_ = shim_rig_get_level_auto(hamlib_instance_->my_rig, vfo_, level_type_, &value_);
317319
if (result_code_ != SHIM_RIG_OK) {
318320
error_message_ = shim_rigerror(result_code_);
319321
}
@@ -336,7 +338,7 @@ class GetLevelAsyncWorker : public HamLibAsyncWorker {
336338
private:
337339
uint64_t level_type_;
338340
int vfo_;
339-
float value_;
341+
double value_;
340342
};
341343

342344
class SetFunctionAsyncWorker : public HamLibAsyncWorker {

src/shim/hamlib_shim.c

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -346,38 +346,63 @@ SHIM_API int shim_rig_set_level_i(hamlib_shim_handle_t h, int vfo, uint64_t leve
346346
}
347347

348348
/*
349-
* get_level with automatic fallback:
350-
* 1. Try standard rig_get_level() (with VFO handling, locking, caching)
351-
* 2. If it fails with RIG_EINVAL (-1), fall back to direct backend call
352-
* to bypass VFO switching issues (e.g. ICOM serial rigs where
353-
* icom_set_vfo fails with "unsupported VFO")
349+
* Ensure RIG_TARGETABLE_LEVEL is set so rig_get_level() skips VFO
350+
* switching but still performs calibration and type conversion.
351+
* This fixes ICOM serial rigs where icom_set_vfo fails with
352+
* "unsupported VFO" during get_level calls.
353+
*
354+
* RIG_TARGETABLE_LEVEL = (1<<5) tells Hamlib: "this rig can read
355+
* levels without needing to switch VFO first".
354356
*/
355-
static int shim_get_level_with_fallback(hamlib_shim_handle_t h, int vfo, uint64_t level, value_t* val) {
357+
#ifndef RIG_TARGETABLE_LEVEL
358+
#define RIG_TARGETABLE_LEVEL (1<<5)
359+
#endif
360+
361+
static void shim_ensure_targetable_level(hamlib_shim_handle_t h) {
356362
RIG* rig = (RIG*)h;
357-
int ret = rig_get_level(rig, (vfo_t)vfo, (setting_t)level, val);
358-
if (ret == -1 && rig->caps->get_level) {
359-
/* RIG_EINVAL: VFO switching failed, try direct backend call */
360-
ret = rig->caps->get_level(rig, (vfo_t)vfo, (setting_t)level, val);
363+
if (rig && rig->caps && !(rig->caps->targetable_vfo & RIG_TARGETABLE_LEVEL)) {
364+
rig->caps->targetable_vfo |= RIG_TARGETABLE_LEVEL;
361365
}
362-
return ret;
363366
}
364367

365368
SHIM_API int shim_rig_get_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float* value) {
369+
shim_ensure_targetable_level(h);
366370
value_t val;
367371
val.f = 0.0f;
368-
int ret = shim_get_level_with_fallback(h, vfo, level, &val);
372+
int ret = rig_get_level((RIG*)h, (vfo_t)vfo, (setting_t)level, &val);
369373
if (value) *value = val.f;
370374
return ret;
371375
}
372376

373377
SHIM_API int shim_rig_get_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int* value) {
378+
shim_ensure_targetable_level(h);
374379
value_t val;
375380
val.i = 0;
376-
int ret = shim_get_level_with_fallback(h, vfo, level, &val);
381+
int ret = rig_get_level((RIG*)h, (vfo_t)vfo, (setting_t)level, &val);
377382
if (value) *value = val.i;
378383
return ret;
379384
}
380385

386+
/*
387+
* Auto-detect int/float level type using RIG_LEVEL_IS_FLOAT macro.
388+
* Returns the value as double regardless of the underlying type.
389+
* This avoids the common bug where STRENGTH (int) is read as float.
390+
*/
391+
SHIM_API int shim_rig_get_level_auto(hamlib_shim_handle_t h, int vfo, uint64_t level, double* value) {
392+
shim_ensure_targetable_level(h);
393+
value_t val;
394+
memset(&val, 0, sizeof(val));
395+
int ret = rig_get_level((RIG*)h, (vfo_t)vfo, (setting_t)level, &val);
396+
if (value) {
397+
if (RIG_LEVEL_IS_FLOAT((setting_t)level)) {
398+
*value = (double)val.f;
399+
} else {
400+
*value = (double)val.i;
401+
}
402+
}
403+
return ret;
404+
}
405+
381406
/* ===== Function control ===== */
382407

383408
SHIM_API int shim_rig_set_func(hamlib_shim_handle_t h, int vfo, uint64_t func, int enable) {

src/shim/hamlib_shim.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,24 @@ typedef void* hamlib_shim_handle_t;
182182
#define SHIM_RIG_LEVEL_METER (1ULL << 20)
183183
#define SHIM_RIG_LEVEL_VOXGAIN (1ULL << 21)
184184
#define SHIM_RIG_LEVEL_ANTIVOX (1ULL << 22)
185-
#define SHIM_RIG_LEVEL_STRENGTH (1ULL << 26)
186-
#define SHIM_RIG_LEVEL_RAWSTR (1ULL << 28)
187-
#define SHIM_RIG_LEVEL_SWR (1ULL << 29)
188-
#define SHIM_RIG_LEVEL_ALC (1ULL << 30)
189-
#define SHIM_RIG_LEVEL_RFPOWER_METER (1ULL << 33)
190-
#define SHIM_RIG_LEVEL_COMP_METER (1ULL << 34)
191-
#define SHIM_RIG_LEVEL_VD_METER (1ULL << 35)
192-
#define SHIM_RIG_LEVEL_ID_METER (1ULL << 36)
193-
#define SHIM_RIG_LEVEL_TEMP_METER (1ULL << 42)
185+
#define SHIM_RIG_LEVEL_SLOPE_LOW (1ULL << 23)
186+
#define SHIM_RIG_LEVEL_SLOPE_HIGH (1ULL << 24)
187+
#define SHIM_RIG_LEVEL_BKIN_DLYMS (1ULL << 25)
188+
#define SHIM_RIG_LEVEL_RAWSTR (1ULL << 26)
189+
/* bit 27 reserved (was SQLSTAT, deprecated) */
190+
#define SHIM_RIG_LEVEL_SWR (1ULL << 28)
191+
#define SHIM_RIG_LEVEL_ALC (1ULL << 29)
192+
#define SHIM_RIG_LEVEL_STRENGTH (1ULL << 30)
193+
/* bit 31 reserved */
194+
#define SHIM_RIG_LEVEL_RFPOWER_METER (1ULL << 32)
195+
#define SHIM_RIG_LEVEL_COMP_METER (1ULL << 33)
196+
#define SHIM_RIG_LEVEL_VD_METER (1ULL << 34)
197+
#define SHIM_RIG_LEVEL_ID_METER (1ULL << 35)
198+
#define SHIM_RIG_LEVEL_NOTCHF_RAW (1ULL << 36)
199+
#define SHIM_RIG_LEVEL_MONITOR_GAIN (1ULL << 37)
200+
#define SHIM_RIG_LEVEL_NB (1ULL << 38)
201+
#define SHIM_RIG_LEVEL_RFPOWER_METER_WATTS (1ULL << 39)
202+
#define SHIM_RIG_LEVEL_TEMP_METER (1ULL << 48)
194203

195204
/* ===== Function constants (bit positions for setting_t / uint64_t) ===== */
196205
#define SHIM_RIG_FUNC_FAGC (1ULL << 0)
@@ -383,6 +392,8 @@ SHIM_API int shim_rig_set_level_f(hamlib_shim_handle_t h, int vfo, uint64_t leve
383392
SHIM_API int shim_rig_set_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int value);
384393
SHIM_API int shim_rig_get_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float* value);
385394
SHIM_API int shim_rig_get_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int* value);
395+
/* Auto-detect int/float level type, returns value as double */
396+
SHIM_API int shim_rig_get_level_auto(hamlib_shim_handle_t h, int vfo, uint64_t level, double* value);
386397

387398
/* ===== Function control ===== */
388399

0 commit comments

Comments
 (0)