hamlib 0.4.2 → 0.4.4

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/src/hamlib.cpp CHANGED
@@ -106,6 +106,27 @@ static int parseVfoString(Napi::Env env, const std::string& vfoToken) {
106
106
  return vfo;
107
107
  }
108
108
 
109
+ static int antennaOrdinalToMask(Napi::Env env, int antennaOrdinal) {
110
+ if (antennaOrdinal < 1 || antennaOrdinal > 30) {
111
+ Napi::RangeError::New(env, "Antenna number must be between 1 and 30").ThrowAsJavaScriptException();
112
+ return 0;
113
+ }
114
+ return static_cast<int>(1u << (antennaOrdinal - 1));
115
+ }
116
+
117
+ static int antennaMaskToOrdinal(int antennaMask) {
118
+ const uint32_t mask = static_cast<uint32_t>(antennaMask);
119
+ if (mask == 0 || (mask & (mask - 1)) != 0) {
120
+ return 0;
121
+ }
122
+ for (int bit = 0; bit < 30; ++bit) {
123
+ if (mask == (1u << bit)) {
124
+ return bit + 1;
125
+ }
126
+ }
127
+ return 0;
128
+ }
129
+
109
130
  // Base AsyncWorker implementation with Promise support
110
131
  HamLibAsyncWorker::HamLibAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance)
111
132
  : AsyncWorker(env), hamlib_instance_(hamlib_instance), result_code_(0), error_message_(""), deferred_(Napi::Promise::Deferred::New(env)) {}
@@ -1230,9 +1251,9 @@ public:
1230
1251
  } else {
1231
1252
  Napi::Object result = Napi::Object::New(env);
1232
1253
 
1233
- result.Set("currentAntenna", Napi::Number::New(env, antenna_curr_));
1234
- result.Set("txAntenna", Napi::Number::New(env, antenna_tx_));
1235
- result.Set("rxAntenna", Napi::Number::New(env, antenna_rx_));
1254
+ result.Set("currentAntenna", Napi::Number::New(env, antennaMaskToOrdinal(antenna_curr_)));
1255
+ result.Set("txAntenna", Napi::Number::New(env, antennaMaskToOrdinal(antenna_tx_)));
1256
+ result.Set("rxAntenna", Napi::Number::New(env, antennaMaskToOrdinal(antenna_rx_)));
1236
1257
  result.Set("option", Napi::Number::New(env, option_));
1237
1258
 
1238
1259
  deferred_.Resolve(result);
@@ -2546,16 +2567,28 @@ Napi::Value NodeHamLib::SetMode(const Napi::CallbackInfo & info) {
2546
2567
  int vfo = SHIM_RIG_VFO_CURR;
2547
2568
 
2548
2569
  // Parse parameters: setMode(mode) or setMode(mode, bandwidth) or setMode(mode, bandwidth, vfo)
2549
- if (info.Length() >= 2 && info[1].IsString()) {
2550
- std::string bandstr = info[1].As<Napi::String>().Utf8Value();
2551
- if (bandstr == "narrow") {
2552
- bandwidth = shim_rig_passband_narrow(my_rig, mode);
2553
- } else if (bandstr == "wide") {
2554
- bandwidth = shim_rig_passband_wide(my_rig, mode);
2570
+ if (info.Length() >= 2) {
2571
+ if (info[1].IsNumber()) {
2572
+ bandwidth = info[1].As<Napi::Number>().Int32Value();
2573
+ } else if (info[1].IsString()) {
2574
+ std::string bandstr = info[1].As<Napi::String>().Utf8Value();
2575
+ if (bandstr == "narrow") {
2576
+ bandwidth = shim_rig_passband_narrow(my_rig, mode);
2577
+ } else if (bandstr == "wide") {
2578
+ bandwidth = shim_rig_passband_wide(my_rig, mode);
2579
+ } else if (bandstr == "normal") {
2580
+ bandwidth = SHIM_RIG_PASSBAND_NORMAL;
2581
+ } else if (bandstr == "nochange") {
2582
+ bandwidth = SHIM_RIG_PASSBAND_NOCHANGE;
2583
+ } else {
2584
+ // If second parameter is not a known passband selector, treat it as VFO
2585
+ vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR);
2586
+ RETURN_NULL_IF_INVALID_VFO(vfo);
2587
+ }
2555
2588
  } else {
2556
- // If second parameter is not "narrow" or "wide", might be VFO
2557
- vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR);
2558
- RETURN_NULL_IF_INVALID_VFO(vfo);
2589
+ Napi::TypeError::New(env, "Bandwidth must be a string selector or numeric passband width")
2590
+ .ThrowAsJavaScriptException();
2591
+ return env.Null();
2559
2592
  }
2560
2593
  }
2561
2594
 
@@ -3768,18 +3801,39 @@ Napi::Value NodeHamLib::SetAntenna(const Napi::CallbackInfo & info) {
3768
3801
  return env.Null();
3769
3802
  }
3770
3803
 
3771
- int antenna = info[0].As<Napi::Number>().Int32Value();
3772
-
3773
- // Support optional VFO parameter: setAntenna(antenna) or setAntenna(antenna, vfo)
3774
- int vfo = SHIM_RIG_VFO_CURR;
3775
- if (info.Length() >= 2 && info[1].IsString()) {
3776
- vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR);
3777
- RETURN_NULL_IF_INVALID_VFO(vfo);
3804
+ const int antennaOrdinal = info[0].As<Napi::Number>().Int32Value();
3805
+ const int antenna = antennaOrdinalToMask(env, antennaOrdinal);
3806
+ if (antenna == 0) {
3807
+ return env.Null();
3778
3808
  }
3779
-
3780
- // Default option value (can be extended later if needed)
3809
+
3810
+ int vfo = SHIM_RIG_VFO_CURR;
3781
3811
  float option = 0.0f;
3782
3812
 
3813
+ if (info.Length() >= 2) {
3814
+ if (info[1].IsNumber()) {
3815
+ option = info[1].As<Napi::Number>().FloatValue();
3816
+ if (info.Length() >= 3 && info[2].IsString()) {
3817
+ vfo = parseVfoParameter(info, 2, SHIM_RIG_VFO_CURR);
3818
+ RETURN_NULL_IF_INVALID_VFO(vfo);
3819
+ } else if (info.Length() >= 3 && !info[2].IsUndefined()) {
3820
+ Napi::TypeError::New(env, "Expected VFO token as third argument").ThrowAsJavaScriptException();
3821
+ return env.Null();
3822
+ }
3823
+ } else if (info[1].IsString()) {
3824
+ vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR);
3825
+ RETURN_NULL_IF_INVALID_VFO(vfo);
3826
+ } else if (!info[1].IsUndefined()) {
3827
+ Napi::TypeError::New(env, "Expected antenna option as number or VFO token as string").ThrowAsJavaScriptException();
3828
+ return env.Null();
3829
+ }
3830
+ }
3831
+
3832
+ if (info.Length() >= 3 && info[1].IsString()) {
3833
+ Napi::TypeError::New(env, "Antenna option must come before VFO").ThrowAsJavaScriptException();
3834
+ return env.Null();
3835
+ }
3836
+
3783
3837
  SetAntennaAsyncWorker* asyncWorker = new SetAntennaAsyncWorker(env, this, antenna, vfo, option);
3784
3838
  asyncWorker->Queue();
3785
3839
  return asyncWorker->GetPromise();