diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b87100..7ba3659 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,19 +1,19 @@ -name: Build Precompiled Binaries +name: Build and Publish on: push: - branches: [ main, develop ] - tags: [ 'v*' ] + branches: [main, develop] + tags: ['v*'] pull_request: - branches: [ main ] + branches: [main] jobs: build: env: HAMLIB_VERSION: '4.6.5' - PTHREADS_SOURCEWARE_DIR: 'prebuilt-dll-2-9-1-release' strategy: + fail-fast: false matrix: include: - os: ubuntu-latest @@ -38,6 +38,9 @@ jobs: node-version: '18' cache: 'npm' + - name: Install Python setuptools (for node-gyp) + run: pip3 install setuptools --break-system-packages || pip3 install setuptools || true + - name: Install system dependencies (Linux) if: startsWith(matrix.os, 'ubuntu') run: | @@ -76,20 +79,13 @@ jobs: Write-Host "HAMLIB root: $root" "HAMLIB_ROOT=$root" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Setup Windows pthread + - name: Setup MSYS2 MinGW (Windows) if: matrix.os == 'windows-latest' - shell: pwsh - run: | - $dir = $env:PTHREADS_SOURCEWARE_DIR - $base = "https://sourceware.org/pub/pthreads-win32/$dir" - $root = Join-Path $env:RUNNER_TEMP 'pthreads-root' - New-Item -ItemType Directory -Path (Join-Path $root 'lib/x64') -Force | Out-Null - - foreach ($f in @('pthread.h','sched.h','semaphore.h')) { - Invoke-WebRequest -Uri "$base/include/$f" -OutFile (Join-Path $root $f) - } - Invoke-WebRequest -Uri "$base/lib/x64/pthreadVC2.lib" -OutFile (Join-Path $root 'lib/x64/pthreadVC2.lib') - "PTHREAD_ROOT=$root" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + location: D:\msys2 + install: mingw-w64-x86_64-gcc mingw-w64-x86_64-binutils - name: Setup MSVC (Windows) if: matrix.os == 'windows-latest' @@ -97,156 +93,86 @@ jobs: with: arch: x64 - - name: Fix Hamlib import library (Windows) + - name: Install Node.js dependencies + run: npm ci --ignore-scripts + + - name: Build shim DLL (Windows) if: matrix.os == 'windows-latest' shell: pwsh + env: + MINGW_CC: D:\msys2\msys64\mingw64\bin\gcc.exe run: | - $dllPath = Get-ChildItem -Path (Join-Path $env:HAMLIB_ROOT 'bin') -Filter 'libhamlib-*.dll' | Select-Object -First 1 - $defPath = Join-Path $env:RUNNER_TEMP 'libhamlib-4.def' - $libPath = Join-Path $env:HAMLIB_ROOT 'lib/libhamlib-4.lib' - - $exports = dumpbin /exports $dllPath.FullName - $defContent = "LIBRARY libhamlib-4.dll`nEXPORTS`n" - $inExports = $false - foreach ($line in $exports -split "`n") { - if ($line -match '^\s+ordinal\s+hint\s+RVA\s+name') { $inExports = $true; continue } - if ($inExports -and $line -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { - $defContent += " $($matches[1])`n" - } - } - - Set-Content -Path $defPath -Value $defContent -Encoding ASCII - $libDir = Join-Path $env:HAMLIB_ROOT 'lib' - if (-not (Test-Path $libDir)) { New-Item -ItemType Directory -Path $libDir -Force | Out-Null } - lib /def:$defPath /out:$libPath /machine:x64 + $env:Path = "D:\msys2\msys64\mingw64\bin;$env:Path" + node scripts/build-shim.js --verbose - - name: Install Node.js dependencies - run: npm ci --ignore-scripts + - name: Build (Windows) + if: matrix.os == 'windows-latest' + run: npm run build:all -- --skip-hamlib --skip-shim --minimal - - name: Build (Linux/macOS - unified) + - name: Build (Unix) if: matrix.os != 'windows-latest' - run: | - npm run build:all -- --minimal - npm run verify + run: npm run build:all -- --minimal - - name: Build (Windows - staged) - if: matrix.os == 'windows-latest' + - name: Run tests run: | - node scripts/run-prebuildify.js - npm run bundle - npm run verify + node test/test_loader.js + node test/test_ci_functional.js - - name: Upload prebuilds artifact + - name: Upload prebuilds uses: actions/upload-artifact@v4 with: - name: prebuilds-${{ matrix.target }} - path: prebuilds/** - retention-days: 1 + name: prebuilt-${{ matrix.target }} + path: prebuilds/ + retention-days: 7 - package: + publish: + name: Publish needs: build runs-on: ubuntu-latest - + if: startsWith(github.ref, 'refs/tags/v') + permissions: + contents: write steps: - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/setup-node@v4 with: node-version: '18' + registry-url: 'https://registry.npmjs.org' - - name: Download all prebuilds - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v4 with: - path: prebuilds-temp + path: all-artifacts - name: Organize prebuilds run: | mkdir -p prebuilds - for platform_dir in prebuilds-temp/prebuilds-*/; do - if [ -d "$platform_dir/prebuilds" ]; then - mv "$platform_dir/prebuilds"/* prebuilds/ 2>/dev/null || true - else - mv "$platform_dir"/* prebuilds/ 2>/dev/null || true - fi + for dir in all-artifacts/prebuilt-*/; do + [ -d "$dir" ] && cp -r "$dir"/* prebuilds/ done - - name: Install dependencies - run: npm ci --ignore-scripts - - - name: Verify build - run: npm run verify:all - - - name: Create build info + - name: Validate prebuilds run: | - cat > prebuilds/BUILD_INFO.txt << EOF - Node-HamLib Precompiled Binaries - ================================ - Build Time: $(date -u) - Git Commit: ${{ github.sha }} - Git Ref: ${{ github.ref }} - - Supported Platforms: - EOF - - for dir in prebuilds/*/; do - if [ -d "$dir" ]; then - echo "- $(basename "$dir")" >> prebuilds/BUILD_INFO.txt - fi + for p in linux-x64 linux-arm64 darwin-arm64 darwin-x64 win32-x64; do + test -f "prebuilds/$p/node.napi.node" || { echo "Missing: $p"; exit 1; } done + echo "All 5 platform prebuilds verified." + find prebuilds -name "*.node" -exec ls -la {} \; - echo "" >> prebuilds/BUILD_INFO.txt - echo "Installation: Extract to your project's prebuilds/ directory" >> prebuilds/BUILD_INFO.txt + - run: npm ci --ignore-scripts - cd prebuilds - zip -r ../node-hamlib-prebuilds.zip . -x "*.DS_Store" - cd .. - - - name: Upload unified package - uses: actions/upload-artifact@v4 - with: - name: node-hamlib-prebuilds - path: node-hamlib-prebuilds.zip - retention-days: 90 + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Create GitHub Release - if: startsWith(github.ref, 'refs/tags/v') - uses: ncipollo/release-action@v1 - with: - tag: ${{ github.ref_name }} - name: "Node-HamLib ${{ github.ref_name }}" - artifacts: node-hamlib-prebuilds.zip - body: | - # Node-HamLib ${{ github.ref_name }} - - ## Precompiled Binaries - - Includes precompiled binaries for: - - Linux x64/ARM64 - - macOS ARM64 (Apple Silicon) & x64 (Intel) - - Windows x64 - - ### Installation - - ```bash - npm install node-hamlib - ``` - - Binaries are automatically detected and used when available. - - cleanup: - needs: [build, package] - runs-on: ubuntu-latest - if: always() - - steps: - - name: Delete temporary artifacts - uses: geekyeggo/delete-artifact@v5 - with: - name: | - prebuilds-linux-x64 - prebuilds-linux-arm64 - prebuilds-darwin-arm64 - prebuilds-darwin-x64 - prebuilds-win32-x64 - failOnError: false + env: + GH_TOKEN: ${{ github.token }} + run: | + VERSION=${GITHUB_REF#refs/tags/} + for dir in prebuilds/*/; do + platform=$(basename "$dir") + tar -czf "node-hamlib-${VERSION}-${platform}.tar.gz" -C prebuilds "$platform" + done + gh release create "$VERSION" --title "Node-HamLib $VERSION" --generate-notes \ + node-hamlib-${VERSION}-*.tar.gz diff --git a/.gitignore b/.gitignore index 099aa57..6392877 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Build outputs build/ +shim-build/ *.node prebuilds/ @@ -50,4 +51,5 @@ temp/ build.sh Dockerfile -Hamlib/ \ No newline at end of file +Hamlib/ +hamlib/ \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 51bb51f..fff1396 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,329 +4,128 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -node-hamlib是一个Node.js绑定,用于Hamlib业余无线电收发器控制库。它通过Node.js Addon API (NAPI)将C++代码与JavaScript接口连接,提供了完整的异步Promise-based API来控制业余无线电设备。 +node-hamlib 是 Hamlib 业余无线电控制库的 Node.js 绑定。通过纯 C shim 层 + N-API C++ addon,提供异步 Promise-based API 控制业余无线电设备。支持 5 个平台的预编译二进制分发。 -项目目录下提供了原始Hamlib仓库的C++实现(只读),你可以进行参考。 +## Architecture -## Development Commands - -### Building and Compilation -- `npm run build` - 配置并构建项目(node-gyp configure && node-gyp build) -- `npm run rebuild` - 重新构建项目(node-gyp rebuild) -- `npm run clean` - 清理构建文件(node-gyp clean) - -### Testing -- `npm test` - 运行基础加载器测试(test/test_loader.js) -- `npm run test:network` - 运行网络连接测试(test/test_network.js) - -### Installation -- `npm install` - 安装依赖(不在安装阶段编译) -- 预编译二进制通过 prebuildify 生成并随包分发;运行时由 node-gyp-build 自动加载 - -## Architecture Overview - -### Core Components - -**Native C++ Layer (src/):** -- `hamlib.cpp` - 主要的C++实现,包含所有Hamlib操作的异步封装器 -- `hamlib.h` - C++头文件,定义NodeHamLib类和AsyncWorker基类 -- `decoder.cpp/decoder.h` - 数据解码功能 -- `addon.cpp` - Node.js addon入口点 - -**JavaScript Layer:** -- `index.js` - CommonJS主入口,使用 node-gyp-build 自动加载本地或预编译二进制 -- `lib/index.mjs` - ES模块入口 - -**TypeScript Definitions:** -- `index.d.ts` - 完整的TypeScript类型定义,包含所有API接口和类型 - -### Promise-Based Async Architecture - -所有无线电控制操作都通过AsyncWorker类实现为异步Promise: -- 基类:`HamLibAsyncWorker` 提供Promise支持 -- 每个操作都有专门的AsyncWorker子类(如OpenAsyncWorker, SetFrequencyAsyncWorker等) -- 所有API方法返回Promise,支持async/await和.then()/.catch() - -### Binary Distribution Strategy - -项目支持多平台预编译二进制: -- **支持平台**: darwin-arm64, linux-x64, linux-arm64(Windows 可选) -- **产物布局**: `prebuilds/-[+libc]/node.napi*.node` -- **加载逻辑**: 由 `node-gyp-build` 自动查找 `build/Release` 与 `prebuilds/**` - -### Cross-Platform Build Configuration (binding.gyp) - -复杂的构建配置支持多个平台和环境: -- **Linux**: 使用系统libhamlib(/usr/include, /usr/local/include) -- **macOS**: 支持Homebrew路径(/opt/homebrew/include) -- **Windows**: 支持MSVC和MinGW环境,包含复杂的路径检测逻辑 - -## Key API Patterns - -### Connection Management -```javascript -const rig = new HamLib(modelNumber, portPath); -await rig.open(); // 异步连接 -// ... operations -await rig.close(); // 异步断开 +``` +JavaScript (lib/index.js) + ↓ async wrapper +C++ N-API addon (src/hamlib.cpp, MSVC on Windows) + ↓ shim_rig_*() calls +Pure C shim (src/shim/hamlib_shim.c, MinGW DLL on Windows / static .a on Unix) + ↓ rig_*() calls +libhamlib ``` -### Network vs Serial Connection Detection -代码自动检测连接类型: -- 包含冒号的地址被识别为网络连接(localhost:4532) -- 其他路径被视为串口连接(/dev/ttyUSB0, COM3) +### Shim Layer(关键架构) -### Error Handling Pattern -所有异步操作遵循相同的错误处理模式: -- 成功:Promise resolve with result code -- 失败:Promise reject with error message from rigerror() +shim 层解决 Windows 上 MSVC addon 与 MinGW Hamlib DLL 的跨编译器 ABI 不兼容问题(struct 内存布局差异导致崩溃)。所有平台统一使用 shim,保持代码一致性。 -## Testing Strategy +- `src/shim/hamlib_shim.h` — 纯 C 头文件,定义 `hamlib_shim_handle_t`(不透明 `void*` 句柄)和 ~95 个 `shim_rig_*` 函数 +- `src/shim/hamlib_shim.c` — 实现,内部 cast 回 `RIG*` 并调用 Hamlib API +- `scripts/build-shim.js` — 编译脚本。Linux/macOS: `gcc → .a`(静态链入 addon);Windows: `MinGW gcc → .dll`(addon 通过 MSVC import lib 动态加载) +- shim 输出到 `shim-build/` 目录(避免被 node-gyp rebuild 清除 `build/`) -### 优化后的测试结构 (8个核心测试) -项目测试已优化,从15个文件减少到8个,消除重复并提升质量: +**hamlib.cpp 中无条件编译**,统一通过 `shim_rig_*()` 调用 Hamlib,不直接 `#include `,不直接访问 `RIG` 结构体。 -**核心测试 (无需硬件)**: -- `test_loader.js` - 基础模块加载、实例化、方法存在性和API完整性测试 -- `test_api_integrity.js` - API完整性和一致性统一测试 (替代了之前的多个重复测试) -- `test_async_operations.js` - 异步操作和Promise支持测试 -- `test_complete.js` - 完整的端到端使用示例测试 +### Key Files -**功能测试 (需要特定环境)**: -- `test_network.js` - 网络连接测试 (需rigctld) -- `test_serial_config.js` - 串口配置测试 (需硬件) -- `test_new_features.js` - 新功能综合测试 (需硬件) +| 文件 | 说明 | +|------|------| +| `src/shim/hamlib_shim.h/.c` | 纯 C shim 层(~95 个函数) | +| `src/hamlib.cpp` | C++ N-API addon 主实现(~5300 行) | +| `src/hamlib.h` | C++ 头文件,使用 `void*` 不透明句柄 | +| `src/addon.cpp` | addon 入口 | +| `lib/index.js` | JavaScript 包装层 | +| `index.d.ts` | TypeScript 类型定义 | +| `binding.gyp` | 构建配置,链接 `shim-build/` 中的 shim 库 | +| `scripts/build-shim.js` | shim 编译脚本 | +| `scripts/build-all.js` | 统一构建脚本 | +| `scripts/bundle-deps.js` | 运行时依赖打包 | -**测试工具**: -- `run_all_tests.js` - 统一测试运行器,生成详细报告 +## Commands -### Test Execution ```bash -# 运行所有测试 (推荐) -node test/run_all_tests.js - -# 运行核心测试 (API验证) -node test/test_loader.js -node test/test_api_integrity.js - -# 运行单个功能测试 -node test/test_network.js -node test/test_async_operations.js -``` - -核心测试不需要实际硬件连接,主要验证模块加载、API完整性和接口一致性。功能测试需要相应的硬件或网络环境。 - -## Important Implementation Details - -### Hamlib Token Type Compatibility -项目包含跨平台兼容性处理: -```cpp -#ifndef HAMLIB_TOKEN_T -#ifdef __linux__ -#define HAMLIB_TOKEN_T token_t -#else -#define HAMLIB_TOKEN_T hamlib_token_t -#endif -#endif +npm run build:all # 完整构建(shim + addon + prebuild + bundle) +npm run build:all -- --minimal # 最小化 Hamlib 构建 +npm test # test_loader.js +node test/test_ci_functional.js # 功能测试(Dummy 设备,无需硬件) +node test/test_loader.js # API 存在性测试 ``` -### Memory Management -使用智能指针和RAII模式管理资源,确保RIG对象正确初始化和清理。 +## Adding a New API Method -### Callback Integration -支持Hamlib回调机制: -- 频率变化回调:`rig_set_freq_callback` -- PTT变化回调:`rig_set_ptt_callback` +四层必须同步修改。以添加 `setNewFeature(param)` 为例: -## API维护要求 (CRITICAL) +### Step 1: Shim 层 -**重要提醒**: 本项目采用三层API架构,任何API变更必须严格遵循以下流程,否则将导致运行时API缺失问题。 - -### API架构层级 +`src/shim/hamlib_shim.h`: +```c +SHIM_API int shim_rig_set_new_feature(hamlib_shim_handle_t h, int param); ``` -TypeScript定义 (index.d.ts) - ↓ -JavaScript包装器 (lib/index.js) - ↓ -C++原生实现 (src/hamlib.cpp) + +`src/shim/hamlib_shim.c`: +```c +int shim_rig_set_new_feature(hamlib_shim_handle_t h, int param) { + RIG *rig = (RIG *)h; + if (!rig) return -RIG_EINVAL; + return rig_set_new_feature(rig, param); +} ``` -### 🚨 强制性API维护流程 +### Step 2: C++ addon -#### 1. 添加新API方法时 (按顺序执行) +`src/hamlib.cpp`: +1. 创建 `SetNewFeatureAsyncWorker` 类 +2. 实现 `SetNewFeature` 方法,调用 `shim_rig_set_new_feature()` +3. 在 `DefineClass` 中注册: `InstanceMethod("setNewFeature", &NodeHamLib::SetNewFeature)` -**第一步: C++层实现** -- 在 `src/hamlib.h` 中添加方法声明 -- 在 `src/hamlib.cpp` 中实现AsyncWorker类和方法 -- 在 `src/hamlib.cpp` 的 `DefineClass` 中注册方法 -- 确认方法在 `NodeHamLib::InstanceMethod()` 中正确注册 +### Step 3: JavaScript 包装 -**第二步: JavaScript包装器实现 (必需)** -- **必须** 在 `lib/index.js` 中添加对应的JavaScript包装方法 -- 保持与C++方法相同的方法名和参数 -- 使用统一的async/Promise模式包装C++调用 -- 包装格式示例: +`lib/index.js`: ```javascript -async methodName(param1, param2) { - if (param2) { - return this._nativeInstance.methodName(param1, param2); - } else { - return this._nativeInstance.methodName(param1); - } +async setNewFeature(param) { + return this._nativeInstance.setNewFeature(param); } ``` -**第三步: TypeScript定义更新** -- 在 `index.d.ts` 中添加方法的类型定义 -- 保持参数类型和返回值类型的准确性 -- 添加完整的JSDoc文档和使用示例 - -**第四步: 验证API一致性** -- 运行 `node test/test_api_integrity.js` 验证API完整性 -- 确保所有三个层级的API数量一致 -- 验证新方法在运行时可用 - -#### 2. ⚠️ 常见错误和问题 +### Step 4: TypeScript 定义 -**JavaScript包装器缺失问题** -- **症状**: C++方法已实现并注册,但运行时显示"方法不存在" -- **原因**: `lib/index.js` 中缺少JavaScript包装方法 -- **解决**: 在 `lib/index.js` 中添加对应的包装方法 - -**API数量不匹配问题** -- **症状**: `test_api_integrity.js` 报告API数量不一致 -- **原因**: 三个层级中的某一层缺少方法定义 -- **解决**: 按照维护流程逐层检查和补充 - -**Promise模式不一致** -- **症状**: 某些方法不是async函数或不返回Promise -- **原因**: JavaScript包装器中未使用正确的async/Promise模式 -- **解决**: 统一使用 `async methodName() { return this._nativeInstance.methodName(); }` - -#### 3. 验证检查清单 - -在提交任何API变更前,必须确认: -- [ ] C++方法已在 `hamlib.h` 中声明 -- [ ] C++方法已在 `hamlib.cpp` 中实现 -- [ ] C++方法已在 `DefineClass` 中注册 -- [ ] **JavaScript包装方法已在 `lib/index.js` 中实现** -- [ ] TypeScript定义已在 `index.d.ts` 中更新 -- [ ] 运行 `node test/test_api_integrity.js` 通过 -- [ ] 运行 `node test/test_loader.js` 通过 -- [ ] API总数匹配预期 (当前应为55个方法) - -#### 4. API维护自动化检查 - -**API完整性测试** -```bash -# 运行API完整性检查 -node test/test_api_integrity.js - -# 预期结果:所有测试通过,API数量一致 +`index.d.ts`: +```typescript +setNewFeature(param: number): Promise; ``` -**基础功能测试** -```bash -# 运行基础加载测试 -node test/test_loader.js +### 验证 -# 预期结果:所有方法存在性检查通过 +```bash +node test/test_loader.js # 方法存在性 +node test/test_ci_functional.js # 功能验证 ``` -## 🚨 重要历史问题记录和经验教训 - -### Split API参数顺序混乱问题 (已修复,但需永久警示) - -**⚠️ 严重警告**: 这是一个典型的"注释与实现不一致"导致的系统性问题,曾导致AI反复修改却始终无法对齐的困扰。 - -#### 问题根源分析 - -**发现时间**: 2024年8月 -**问题性质**: C++实现逻辑错误 + 注释错误的双重问题 -**影响范围**: Split相关所有API (setSplit, getSplit, setSplitMode等) +## Testing -#### 具体问题内容 +CI 运行两个测试,均不需要硬件: +- `test_loader.js` — 模块加载 + 84 个方法存在性检查 +- `test_ci_functional.js` — Dummy 设备核心 API 功能验证(31 项) -1. **注释错误** (`src/hamlib.cpp:2957`) - ```cpp - // 错误注释: setSplit(enable, txVfo, rxVfo) - txVfo and RX VFO - // 正确注释: setSplit(enable, rxVfo, txVfo) - RX VFO and TX VFO - ``` +其他测试: +- `test_serial_config.js` — 串口配置(Dummy 设备,无需硬件) +- `test_dummy_complete.js` — 完整 API 测试(需 `rigctld -m 1 -t 4532`) +- `test_network.js` — 网络连接测试(需 rigctld + 硬件) -2. **实现逻辑错误** (`src/hamlib.cpp:2969-2970`) - ```cpp - // 错误实现: - std::string txVfoStr = info[1].As().Utf8Value(); // 将参数1赋给txVfo! - std::string rxVfoStr = info[2].As().Utf8Value(); // 将参数2赋给rxVfo! - - // 正确实现: - std::string rxVfoStr = info[1].As().Utf8Value(); // 参数1应该是rxVfo - std::string txVfoStr = info[2].As().Utf8Value(); // 参数2应该是txVfo - ``` +## Publishing -3. **三层API定义不一致** - - JavaScript: `setSplit(enable, rxVfo, txVfo)` ✅ 正确 - - C++实现: 按 `setSplit(enable, txVfo, rxVfo)` 处理 ❌ 错误 - - TypeScript: `setSplit(enable, rxVfo?, txVfo?)` ✅ 正确 - -#### 为什么AI反复修改失败 - -**根本原因**: AI每次只看到表面的注释问题,没有深入检查实现逻辑 -- 第1次修改: 只改注释,没有检查实现 -- 第2次修改: 发现注释还是不对,又改注释,还是没检查实现 -- 第N次修改: 陷入"注释修改循环",始终没有发现真正的实现逻辑错误 - -#### 修正措施 (已完成) - -1. **修正注释**: 统一所有注释为 `setSplit(enable, rxVfo, txVfo)` -2. **修正实现**: 确保参数1是rxVfo,参数2是txVfo -3. **修正变量赋值**: 调整参数解析的变量赋值顺序 -4. **添加专门测试**: `test_split_api_fix.js` 验证修正的正确性 - -#### 关键经验教训 - -**🔥 对AI的重要提醒**: - -1. **不要只看注释,必须检查实现逻辑** - - 注释可能是错误的或过时的 - - 实际的参数处理代码才是真相 - -2. **参数顺序问题的完整检查流程** - ``` - 步骤1: 检查JavaScript/TypeScript定义的参数顺序 - 步骤2: 检查C++方法签名和注释 - 步骤3: 检查C++实现中参数的实际处理逻辑 (关键!) - 步骤4: 检查原生Hamlib API的参数顺序 - 步骤5: 确保所有层级完全一致 - ``` - -3. **三层API架构一致性验证** - - JavaScript定义 ↔ C++实现 ↔ TypeScript定义 - - 任何一层不一致都会导致运行时错误 - -4. **避免"修改循环陷阱"** - - 如果多次修改同一个API还是有问题,说明可能存在更深层的逻辑错误 - - 必须从实现层面重新检查,而不是继续在表面修改 - -#### 验证方法 - -**每当修改涉及参数顺序的API时,必须**: -1. 运行专门的参数测试: `node test/test_split_api_fix.js` -2. 确认所有相关测试通过: `node test/test_api_integrity.js` -3. 手动验证参数处理逻辑与注释一致 +```bash +npm version patch && git push && git push --tags +``` -**警示标识**: 在 `src/hamlib.cpp` 的Split相关代码附近已添加特殊注释标记,提醒未来的维护者注意这个历史问题。 +Tag push 触发 CI 自动:构建 5 平台 → 测试 → 验证 → npm publish → GitHub Release。 +需要 GitHub Secret: `NPM_TOKEN`。详见 `PUBLISHING.md`。 -## Development Notes +## Historical Lessons -当修改API时,除了遵循上述API维护流程外,还需确保: -1. 保持Promise模式一致性 -2. 处理跨平台兼容性 -3. 更新相关测试文件 -4. 验证异步操作的正确性 -5. **特别注意参数顺序问题** (参考上述Split API的历史教训) +### Split API 参数顺序(已修复) -构建问题排查: -1. 检查Hamlib库是否正确安装在系统中 -2. 验证node-gyp和Python环境配置 -3. 查看binding.gyp中的路径配置是否适合当前系统 +曾因注释与实现不一致导致 `setSplit(enable, rxVfo, txVfo)` 的参数被错误交换。教训:**修改涉及参数顺序的 API 时,必须检查 C++ 实现中参数的实际处理逻辑**,不能只看注释。三层 API(JS/C++/TS)参数顺序必须完全一致。 diff --git a/PUBLISHING.md b/PUBLISHING.md new file mode 100644 index 0000000..34fca5f --- /dev/null +++ b/PUBLISHING.md @@ -0,0 +1,60 @@ +# Node-HamLib 发布指南 + +## 发布流程 + +```bash +# 1. 确保代码在 main 分支且 CI 通过 +# 2. bump 版本(自动创建 commit + v* tag) +npm version patch # bug 修复 +npm version minor # 新功能 +npm version major # 破坏性更改 + +# 3. 推送代码和 tag +git push && git push --tags +``` + +推送 tag 后 CI 自动完成: +1. 5 平台构建 + 测试(linux-x64, linux-arm64, darwin-arm64, darwin-x64, win32-x64) +2. 汇总 prebuilds +3. 验证全部平台二进制完整 +4. `npm publish` 发布到 npm registry +5. 创建 GitHub Release 并上传各平台预构建压缩包 + +## 前置条件 + +在 GitHub repo settings > Secrets and variables > Actions 中添加: +- `NPM_TOKEN`:npm access token(`npm token create` 生成) + +## 预构建包结构 + +``` +prebuilds/ +├── linux-x64/ +│ ├── node.napi.node +│ ├── libhamlib.so.5 +│ └── ... +├── linux-arm64/ +│ └── ... +├── darwin-arm64/ +│ ├── node.napi.node +│ ├── libhamlib.4.dylib +│ └── ... +├── darwin-x64/ +│ └── ... +└── win32-x64/ + ├── node.napi.node + ├── hamlib_shim.dll + ├── libhamlib-4.dll + └── ... +``` + +运行时通过 `node-gyp-build` 自动加载对应平台的预构建二进制。 + +## 用户安装 + +```bash +npm install hamlib +# 预构建二进制随包安装,无需编译 +``` + +无对应预构建的平台需从源码构建(需要 Hamlib 开发库、node-gyp、C++ 编译器)。 diff --git a/binding.gyp b/binding.gyp index a9babcc..576bd36 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,19 +2,20 @@ "targets": [ { "target_name": "hamlib", - "sources": [ + "sources": [ "src/hamlib.cpp", "src/decoder.cpp", "src/addon.cpp" ], "include_dirs": [ "include", + "src/shim", " /^libhamlib\.so\.\d+$/.test(f)) + .sort() + .reverse(); + if (versioned.length > 0) { + return path.join(dir, versioned[0]); + } + if (files.includes('libhamlib.so')) { + return path.join(dir, 'libhamlib.so'); + } + } catch { + // Directory doesn't exist or not readable + } + return null; + } + isSystemLib(libname) { const systemPatterns = [ 'linux-vdso', @@ -413,10 +444,29 @@ class LinuxBundler { logger.log(`Found libhamlib: ${path.basename(hamlibLib)}`, 'success'); - // Copy libhamlib.so - const hamlibDest = path.join(this.targetDir, path.basename(hamlibLib)); - fs.copyFileSync(hamlibLib, hamlibDest); - logger.log(`Copied ${path.basename(hamlibLib)}`, 'success'); + // Copy all libhamlib.so* files (soname variants) from the same directory + const hamlibDir = path.dirname(hamlibLib); + try { + const allFiles = fs.readdirSync(hamlibDir); + const hamlibFiles = allFiles.filter(f => /^libhamlib\.so/.test(f)); + for (const hf of hamlibFiles) { + const src = path.join(hamlibDir, hf); + const dest = path.join(this.targetDir, hf); + try { + // Resolve symlinks to copy actual file content + const realSrc = fs.realpathSync(src); + fs.copyFileSync(realSrc, dest); + logger.log(`Copied ${hf}`, 'success'); + } catch (e) { + logger.log(`Failed to copy ${hf}: ${e.message}`, 'warning'); + } + } + } catch { + // Fallback: just copy the found file + const hamlibDest = path.join(this.targetDir, path.basename(hamlibLib)); + fs.copyFileSync(hamlibLib, hamlibDest); + logger.log(`Copied ${path.basename(hamlibLib)}`, 'success'); + } // Get dependencies try { diff --git a/src/addon.cpp b/src/addon.cpp index bc79798..501e958 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -1,12 +1,12 @@ #include #include "hamlib.h" #include "decoder.h" -#include +#include "shim/hamlib_shim.h" Napi::Object Init(Napi::Env env, Napi::Object exports) { // Set Hamlib debug level to NONE by default to prevent unwanted output // Users can change this using HamLib.setDebugLevel() if needed - rig_set_debug(RIG_DEBUG_NONE); + shim_rig_set_debug(0); // 0 = RIG_DEBUG_NONE Napi::String name = Napi::String::New(env, "HamLib"); exports.Set(name, NodeHamLib::GetClass(env)); diff --git a/src/hamlib.cpp b/src/hamlib.cpp index 7432f06..595fe4c 100644 --- a/src/hamlib.cpp +++ b/src/hamlib.cpp @@ -1,25 +1,15 @@ #include "hamlib.h" -#include "hamlib_compat.h" +#include "shim/hamlib_shim.h" #include #include #include #include -// Cross-platform compatibility for hamlib token types -// Linux versions use token_t, some others use hamlib_token_t -#ifndef HAMLIB_TOKEN_T -#ifdef __linux__ -#define HAMLIB_TOKEN_T token_t -#else -#define HAMLIB_TOKEN_T hamlib_token_t -#endif -#endif - // 安全宏 - 检查RIG指针有效性,防止空指针解引用和已销毁对象访问 #define CHECK_RIG_VALID() \ do { \ if (!hamlib_instance_ || !hamlib_instance_->my_rig) { \ - result_code_ = -RIG_EINVAL; \ + result_code_ = SHIM_RIG_EINVAL; \ error_message_ = "RIG is not initialized or has been destroyed"; \ return; \ } \ @@ -49,24 +39,24 @@ class OpenAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_open(hamlib_instance_->my_rig); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_open(hamlib_instance_->my_rig); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } else { - rig_set_freq_callback(hamlib_instance_->my_rig, NodeHamLib::freq_change_cb, hamlib_instance_); - auto ppt_cb = +[](RIG *rig, vfo_t vfo, ptt_t ptt, rig_ptr_t arg) { + shim_rig_set_freq_callback(hamlib_instance_->my_rig, NodeHamLib::freq_change_cb, hamlib_instance_); + auto ppt_cb = +[](void* handle, int vfo, int ptt, void* arg) -> int { printf("PPT pushed!"); return 0; }; - int cb_result = rig_set_ptt_callback(hamlib_instance_->my_rig, ppt_cb, NULL); - rig_set_trn(hamlib_instance_->my_rig, RIG_TRN_POLL); + int cb_result = shim_rig_set_ptt_callback(hamlib_instance_->my_rig, ppt_cb, NULL); + shim_rig_set_trn(hamlib_instance_->my_rig, SHIM_RIG_TRN_POLL); hamlib_instance_->rig_is_open = true; } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -81,21 +71,21 @@ class OpenAsyncWorker : public HamLibAsyncWorker { class SetFrequencyAsyncWorker : public HamLibAsyncWorker { public: - SetFrequencyAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, freq_t freq, vfo_t vfo) + SetFrequencyAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, double freq, int vfo) : HamLibAsyncWorker(env, hamlib_instance), freq_(freq), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_freq(hamlib_instance_->my_rig, vfo_, freq_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_freq(hamlib_instance_->my_rig, vfo_, freq_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -108,27 +98,27 @@ class SetFrequencyAsyncWorker : public HamLibAsyncWorker { } private: - freq_t freq_; - vfo_t vfo_; + double freq_; + int vfo_; }; class GetFrequencyAsyncWorker : public HamLibAsyncWorker { public: - GetFrequencyAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetFrequencyAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), freq_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_freq(hamlib_instance_->my_rig, vfo_, &freq_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_freq(hamlib_instance_->my_rig, vfo_, &freq_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, freq_)); @@ -141,27 +131,27 @@ class GetFrequencyAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - freq_t freq_; + int vfo_; + double freq_; }; class SetModeAsyncWorker : public HamLibAsyncWorker { public: - SetModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, rmode_t mode, pbwidth_t width, vfo_t vfo = RIG_VFO_CURR) + SetModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int mode, int width, int vfo = SHIM_RIG_VFO_CURR) : HamLibAsyncWorker(env, hamlib_instance), mode_(mode), width_(width), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_mode(hamlib_instance_->my_rig, vfo_, mode_, width_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_mode(hamlib_instance_->my_rig, vfo_, mode_, width_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -174,9 +164,9 @@ class SetModeAsyncWorker : public HamLibAsyncWorker { } private: - rmode_t mode_; - pbwidth_t width_; - vfo_t vfo_; + int mode_; + int width_; + int vfo_; }; class GetModeAsyncWorker : public HamLibAsyncWorker { @@ -187,20 +177,20 @@ class GetModeAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_mode(hamlib_instance_->my_rig, RIG_VFO_CURR, &mode_, &width_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_mode(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, &mode_, &width_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { Napi::Object obj = Napi::Object::New(env); // Convert mode to string using rig_strrmode - const char* mode_str = rig_strrmode(mode_); + const char* mode_str = shim_rig_strrmode(mode_); obj.Set(Napi::String::New(env, "mode"), Napi::String::New(env, mode_str)); obj.Set(Napi::String::New(env, "bandwidth"), width_); deferred_.Resolve(obj); @@ -213,27 +203,27 @@ class GetModeAsyncWorker : public HamLibAsyncWorker { } private: - rmode_t mode_; - pbwidth_t width_; + int mode_; + int width_; }; class SetPttAsyncWorker : public HamLibAsyncWorker { public: - SetPttAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, ptt_t ptt) + SetPttAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int ptt) : HamLibAsyncWorker(env, hamlib_instance), ptt_(ptt) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_ptt(hamlib_instance_->my_rig, RIG_VFO_CURR, ptt_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_ptt(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, ptt_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -246,26 +236,26 @@ class SetPttAsyncWorker : public HamLibAsyncWorker { } private: - ptt_t ptt_; + int ptt_; }; class GetStrengthAsyncWorker : public HamLibAsyncWorker { public: - GetStrengthAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetStrengthAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), strength_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_strength(hamlib_instance_->my_rig, vfo_, &strength_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_strength(hamlib_instance_->my_rig, vfo_, &strength_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, strength_)); @@ -278,95 +268,93 @@ class GetStrengthAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; int strength_; }; class SetLevelAsyncWorker : public HamLibAsyncWorker { public: - SetLevelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, setting_t level_type, value_t value) + SetLevelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t level_type, float value) : HamLibAsyncWorker(env, hamlib_instance), level_type_(level_type), value_(value) {} - + void Execute() override { CHECK_RIG_VALID(); - - result_code_ = rig_set_level(hamlib_instance_->my_rig, RIG_VFO_CURR, level_type_, value_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + + result_code_ = shim_rig_set_level_f(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, level_type_, value_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); } } - + void OnError(const Napi::Error& e) override { Napi::Env env = Env(); deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } - + private: - setting_t level_type_; - value_t value_; + uint64_t level_type_; + float value_; }; class GetLevelAsyncWorker : public HamLibAsyncWorker { public: - GetLevelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, setting_t level_type) - : HamLibAsyncWorker(env, hamlib_instance), level_type_(level_type) { - value_.f = 0.0; - } - + GetLevelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t level_type) + : HamLibAsyncWorker(env, hamlib_instance), level_type_(level_type), value_(0.0f) {} + void Execute() override { CHECK_RIG_VALID(); - - result_code_ = rig_get_level(hamlib_instance_->my_rig, RIG_VFO_CURR, level_type_, &value_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + + result_code_ = shim_rig_get_level_f(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, level_type_, &value_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { - deferred_.Resolve(Napi::Number::New(env, value_.f)); + deferred_.Resolve(Napi::Number::New(env, value_)); } } - + void OnError(const Napi::Error& e) override { Napi::Env env = Env(); deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } - + private: - setting_t level_type_; - value_t value_; + uint64_t level_type_; + float value_; }; class SetFunctionAsyncWorker : public HamLibAsyncWorker { public: - SetFunctionAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, setting_t func_type, int enable) + SetFunctionAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t func_type, int enable) : HamLibAsyncWorker(env, hamlib_instance), func_type_(func_type), enable_(enable) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_func(hamlib_instance_->my_rig, RIG_VFO_CURR, func_type_, enable_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_func(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, func_type_, enable_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -379,27 +367,27 @@ class SetFunctionAsyncWorker : public HamLibAsyncWorker { } private: - setting_t func_type_; + uint64_t func_type_; int enable_; }; class GetFunctionAsyncWorker : public HamLibAsyncWorker { public: - GetFunctionAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, setting_t func_type) + GetFunctionAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t func_type) : HamLibAsyncWorker(env, hamlib_instance), func_type_(func_type), state_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_func(hamlib_instance_->my_rig, RIG_VFO_CURR, func_type_, &state_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_func(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, func_type_, &state_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Boolean::New(env, state_ != 0)); @@ -412,27 +400,27 @@ class GetFunctionAsyncWorker : public HamLibAsyncWorker { } private: - setting_t func_type_; + uint64_t func_type_; int state_; }; class SetMemoryChannelAsyncWorker : public HamLibAsyncWorker { public: - SetMemoryChannelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, const channel_t& chan) + SetMemoryChannelAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, const shim_channel_t& chan) : HamLibAsyncWorker(env, hamlib_instance), chan_(chan) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_channel(hamlib_instance_->my_rig, RIG_VFO_MEM, &chan_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_channel(hamlib_instance_->my_rig, SHIM_RIG_VFO_MEM, &chan_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -445,7 +433,7 @@ class SetMemoryChannelAsyncWorker : public HamLibAsyncWorker { } private: - channel_t chan_; + shim_channel_t chan_; }; class GetMemoryChannelAsyncWorker : public HamLibAsyncWorker { @@ -459,10 +447,10 @@ class GetMemoryChannelAsyncWorker : public HamLibAsyncWorker { CHECK_RIG_VALID(); chan_.channel_num = channel_num_; - chan_.vfo = RIG_VFO_MEM; - result_code_ = rig_get_channel(hamlib_instance_->my_rig, RIG_VFO_MEM, &chan_, read_only_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + chan_.vfo = SHIM_RIG_VFO_MEM; + result_code_ = shim_rig_get_channel(hamlib_instance_->my_rig, SHIM_RIG_VFO_MEM, &chan_, read_only_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } @@ -473,8 +461,8 @@ class GetMemoryChannelAsyncWorker : public HamLibAsyncWorker { obj.Set(Napi::String::New(env, "channelNumber"), chan_.channel_num); obj.Set(Napi::String::New(env, "frequency"), chan_.freq); - if (chan_.mode != RIG_MODE_NONE) { - const char* mode_str = rig_strrmode(chan_.mode); + if (chan_.mode != SHIM_RIG_MODE_NONE) { + const char* mode_str = shim_rig_strrmode(chan_.mode); obj.Set(Napi::String::New(env, "mode"), Napi::String::New(env, mode_str)); } @@ -484,7 +472,7 @@ class GetMemoryChannelAsyncWorker : public HamLibAsyncWorker { obj.Set(Napi::String::New(env, "description"), Napi::String::New(env, chan_.channel_desc)); } - if (chan_.split == RIG_SPLIT_ON) { + if (chan_.split == SHIM_RIG_SPLIT_ON) { obj.Set(Napi::String::New(env, "txFrequency"), chan_.tx_freq); } @@ -503,7 +491,7 @@ class GetMemoryChannelAsyncWorker : public HamLibAsyncWorker { private: int channel_num_; bool read_only_; - channel_t chan_; + shim_channel_t chan_; }; class SelectMemoryChannelAsyncWorker : public HamLibAsyncWorker { @@ -514,15 +502,15 @@ class SelectMemoryChannelAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_mem(hamlib_instance_->my_rig, RIG_VFO_CURR, channel_num_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_mem(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, channel_num_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -540,21 +528,21 @@ class SelectMemoryChannelAsyncWorker : public HamLibAsyncWorker { class SetRitAsyncWorker : public HamLibAsyncWorker { public: - SetRitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, shortfreq_t rit_offset) + SetRitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int rit_offset) : HamLibAsyncWorker(env, hamlib_instance), rit_offset_(rit_offset) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_rit(hamlib_instance_->my_rig, RIG_VFO_CURR, rit_offset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_rit(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, rit_offset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -567,7 +555,7 @@ class SetRitAsyncWorker : public HamLibAsyncWorker { } private: - shortfreq_t rit_offset_; + int rit_offset_; }; class GetRitAsyncWorker : public HamLibAsyncWorker { @@ -578,15 +566,15 @@ class GetRitAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_rit(hamlib_instance_->my_rig, RIG_VFO_CURR, &rit_offset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_rit(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, &rit_offset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, rit_offset_)); @@ -599,26 +587,26 @@ class GetRitAsyncWorker : public HamLibAsyncWorker { } private: - shortfreq_t rit_offset_; + int rit_offset_; }; class SetXitAsyncWorker : public HamLibAsyncWorker { public: - SetXitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, shortfreq_t xit_offset) + SetXitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int xit_offset) : HamLibAsyncWorker(env, hamlib_instance), xit_offset_(xit_offset) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_xit(hamlib_instance_->my_rig, RIG_VFO_CURR, xit_offset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_xit(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, xit_offset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -631,7 +619,7 @@ class SetXitAsyncWorker : public HamLibAsyncWorker { } private: - shortfreq_t xit_offset_; + int xit_offset_; }; class GetXitAsyncWorker : public HamLibAsyncWorker { @@ -642,15 +630,15 @@ class GetXitAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_xit(hamlib_instance_->my_rig, RIG_VFO_CURR, &xit_offset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_xit(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, &xit_offset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, xit_offset_)); @@ -663,7 +651,7 @@ class GetXitAsyncWorker : public HamLibAsyncWorker { } private: - shortfreq_t xit_offset_; + int xit_offset_; }; class ClearRitXitAsyncWorker : public HamLibAsyncWorker { @@ -674,23 +662,23 @@ class ClearRitXitAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - int ritCode = rig_set_rit(hamlib_instance_->my_rig, RIG_VFO_CURR, 0); - int xitCode = rig_set_xit(hamlib_instance_->my_rig, RIG_VFO_CURR, 0); + int ritCode = shim_rig_set_rit(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, 0); + int xitCode = shim_rig_set_xit(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, 0); - if (ritCode != RIG_OK) { + if (ritCode != SHIM_RIG_OK) { result_code_ = ritCode; - error_message_ = rigerror(ritCode); - } else if (xitCode != RIG_OK) { + error_message_ = shim_rigerror(ritCode); + } else if (xitCode != SHIM_RIG_OK) { result_code_ = xitCode; - error_message_ = rigerror(xitCode); + error_message_ = shim_rigerror(xitCode); } else { - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -705,21 +693,21 @@ class ClearRitXitAsyncWorker : public HamLibAsyncWorker { class SetSplitFreqAsyncWorker : public HamLibAsyncWorker { public: - SetSplitFreqAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, freq_t tx_freq, vfo_t vfo = RIG_VFO_CURR) + SetSplitFreqAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, double tx_freq, int vfo = SHIM_RIG_VFO_CURR) : HamLibAsyncWorker(env, hamlib_instance), tx_freq_(tx_freq), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_split_freq(hamlib_instance_->my_rig, vfo_, tx_freq_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_split_freq(hamlib_instance_->my_rig, vfo_, tx_freq_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -732,27 +720,27 @@ class SetSplitFreqAsyncWorker : public HamLibAsyncWorker { } private: - freq_t tx_freq_; - vfo_t vfo_; + double tx_freq_; + int vfo_; }; class GetSplitFreqAsyncWorker : public HamLibAsyncWorker { public: - GetSplitFreqAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo = RIG_VFO_CURR) + GetSplitFreqAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo = SHIM_RIG_VFO_CURR) : HamLibAsyncWorker(env, hamlib_instance), tx_freq_(0), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_split_freq(hamlib_instance_->my_rig, vfo_, &tx_freq_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_split_freq(hamlib_instance_->my_rig, vfo_, &tx_freq_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, tx_freq_)); @@ -765,27 +753,27 @@ class GetSplitFreqAsyncWorker : public HamLibAsyncWorker { } private: - freq_t tx_freq_; - vfo_t vfo_; + double tx_freq_; + int vfo_; }; class SetSplitAsyncWorker : public HamLibAsyncWorker { public: - SetSplitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t rx_vfo, split_t split, vfo_t tx_vfo) + SetSplitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int rx_vfo, int split, int tx_vfo) : HamLibAsyncWorker(env, hamlib_instance), rx_vfo_(rx_vfo), split_(split), tx_vfo_(tx_vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_split_vfo(hamlib_instance_->my_rig, rx_vfo_, split_, tx_vfo_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_split_vfo(hamlib_instance_->my_rig, rx_vfo_, split_, tx_vfo_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -798,35 +786,35 @@ class SetSplitAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t rx_vfo_; - split_t split_; - vfo_t tx_vfo_; + int rx_vfo_; + int split_; + int tx_vfo_; }; class GetSplitAsyncWorker : public HamLibAsyncWorker { public: - GetSplitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo = RIG_VFO_CURR) - : HamLibAsyncWorker(env, hamlib_instance), split_(RIG_SPLIT_OFF), tx_vfo_(RIG_VFO_B), vfo_(vfo) {} + GetSplitAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo = SHIM_RIG_VFO_CURR) + : HamLibAsyncWorker(env, hamlib_instance), split_(SHIM_RIG_SPLIT_OFF), tx_vfo_(SHIM_RIG_VFO_B), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_split_vfo(hamlib_instance_->my_rig, vfo_, &split_, &tx_vfo_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_split_vfo(hamlib_instance_->my_rig, vfo_, &split_, &tx_vfo_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { Napi::Object obj = Napi::Object::New(env); - obj.Set(Napi::String::New(env, "enabled"), Napi::Boolean::New(env, split_ == RIG_SPLIT_ON)); + obj.Set(Napi::String::New(env, "enabled"), Napi::Boolean::New(env, split_ == SHIM_RIG_SPLIT_ON)); const char* vfo_str = "VFO-B"; - if (tx_vfo_ == RIG_VFO_A) { + if (tx_vfo_ == SHIM_RIG_VFO_A) { vfo_str = "VFO-A"; } obj.Set(Napi::String::New(env, "txVfo"), Napi::String::New(env, vfo_str)); @@ -841,28 +829,28 @@ class GetSplitAsyncWorker : public HamLibAsyncWorker { } private: - split_t split_; - vfo_t tx_vfo_; - vfo_t vfo_; + int split_; + int tx_vfo_; + int vfo_; }; class SetVfoAsyncWorker : public HamLibAsyncWorker { public: - SetVfoAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + SetVfoAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_vfo(hamlib_instance_->my_rig, vfo_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_vfo(hamlib_instance_->my_rig, vfo_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -875,7 +863,7 @@ class SetVfoAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; }; class GetVfoAsyncWorker : public HamLibAsyncWorker { @@ -886,21 +874,20 @@ class GetVfoAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_vfo(hamlib_instance_->my_rig, &vfo_); - if (result_code_ != RIG_OK) { + result_code_ = shim_rig_get_vfo(hamlib_instance_->my_rig, &vfo_); + if (result_code_ != SHIM_RIG_OK) { // 提供更清晰的错误信息 switch (result_code_) { - case RIG_ENAVAIL: - case -11: // Feature not available + case SHIM_RIG_ENAVAIL: error_message_ = "VFO query not supported by this radio"; break; - case RIG_EIO: + case SHIM_RIG_EIO: error_message_ = "I/O error during VFO query"; break; - case RIG_ETIMEOUT: + case SHIM_RIG_ETIMEOUT: error_message_ = "Timeout during VFO query"; break; - case RIG_EPROTO: + case SHIM_RIG_EPROTO: error_message_ = "Protocol error during VFO query"; break; default: @@ -914,19 +901,19 @@ class GetVfoAsyncWorker : public HamLibAsyncWorker { Napi::Env env = Env(); // 如果API调用失败,reject Promise - if (result_code_ != RIG_OK) { + if (result_code_ != SHIM_RIG_OK) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); return; } const char* vfo_str = "VFO-CURR"; // 默认值 - if (vfo_ == RIG_VFO_A) { + if (vfo_ == SHIM_RIG_VFO_A) { vfo_str = "VFO-A"; - } else if (vfo_ == RIG_VFO_B) { + } else if (vfo_ == SHIM_RIG_VFO_B) { vfo_str = "VFO-B"; - } else if (vfo_ == RIG_VFO_CURR) { + } else if (vfo_ == SHIM_RIG_VFO_CURR) { vfo_str = "VFO-CURR"; - } else if (vfo_ == RIG_VFO_MEM) { + } else if (vfo_ == SHIM_RIG_VFO_MEM) { vfo_str = "VFO-MEM"; } deferred_.Resolve(Napi::String::New(env, vfo_str)); @@ -938,7 +925,7 @@ class GetVfoAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; }; class CloseAsyncWorker : public HamLibAsyncWorker { @@ -951,13 +938,13 @@ class CloseAsyncWorker : public HamLibAsyncWorker { // 检查rig是否已经关闭 if (!hamlib_instance_->rig_is_open) { - result_code_ = RIG_OK; // 已经关闭,返回成功 + result_code_ = SHIM_RIG_OK; // 已经关闭,返回成功 return; } - result_code_ = rig_close(hamlib_instance_->my_rig); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_close(hamlib_instance_->my_rig); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } else { hamlib_instance_->rig_is_open = false; } @@ -965,7 +952,7 @@ class CloseAsyncWorker : public HamLibAsyncWorker { void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -987,9 +974,9 @@ class DestroyAsyncWorker : public HamLibAsyncWorker { CHECK_RIG_VALID(); // rig_cleanup会自动调用rig_close,所以我们不需要重复调用 - result_code_ = rig_cleanup(hamlib_instance_->my_rig); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_cleanup(hamlib_instance_->my_rig); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } else { hamlib_instance_->rig_is_open = false; hamlib_instance_->my_rig = nullptr; // 重要:清空指针防止重复释放 @@ -998,7 +985,7 @@ class DestroyAsyncWorker : public HamLibAsyncWorker { void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1014,21 +1001,21 @@ class DestroyAsyncWorker : public HamLibAsyncWorker { // Start Scan AsyncWorker class StartScanAsyncWorker : public HamLibAsyncWorker { public: - StartScanAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, scan_t scan_type, int channel) - : HamLibAsyncWorker(env, hamlib_instance), scan_type_(scan_type), channel_(channel) {} + StartScanAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int intype, int channel) + : HamLibAsyncWorker(env, hamlib_instance), intype_(intype), channel_(channel) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_scan(hamlib_instance_->my_rig, RIG_VFO_CURR, scan_type_, channel_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_scan(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, intype_, channel_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1041,7 +1028,7 @@ class StartScanAsyncWorker : public HamLibAsyncWorker { } private: - scan_t scan_type_; + int intype_; int channel_; }; @@ -1054,15 +1041,15 @@ class StopScanAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_scan(hamlib_instance_->my_rig, RIG_VFO_CURR, RIG_SCAN_STOP, 0); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_scan(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, SHIM_RIG_SCAN_STOP, 0); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1078,21 +1065,21 @@ class StopScanAsyncWorker : public HamLibAsyncWorker { // VFO Operation AsyncWorker class VfoOperationAsyncWorker : public HamLibAsyncWorker { public: - VfoOperationAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_op_t vfo_op) + VfoOperationAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo_op) : HamLibAsyncWorker(env, hamlib_instance), vfo_op_(vfo_op) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_vfo_op(hamlib_instance_->my_rig, RIG_VFO_CURR, vfo_op_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_vfo_op(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, vfo_op_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1105,109 +1092,109 @@ class VfoOperationAsyncWorker : public HamLibAsyncWorker { } private: - vfo_op_t vfo_op_; + int vfo_op_; }; // Set Antenna AsyncWorker class SetAntennaAsyncWorker : public HamLibAsyncWorker { public: - SetAntennaAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, ant_t antenna, vfo_t vfo, value_t option) + SetAntennaAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int antenna, int vfo, float option) : HamLibAsyncWorker(env, hamlib_instance), antenna_(antenna), vfo_(vfo), option_(option) {} - + void Execute() override { CHECK_RIG_VALID(); - - result_code_ = rig_set_ant(hamlib_instance_->my_rig, vfo_, antenna_, option_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + + result_code_ = shim_rig_set_ant(hamlib_instance_->my_rig, vfo_, antenna_, option_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); } } - + void OnError(const Napi::Error& e) override { Napi::Env env = Env(); deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } - + private: - ant_t antenna_; - vfo_t vfo_; - value_t option_; + int antenna_; + int vfo_; + float option_; }; // Get Antenna AsyncWorker class GetAntennaAsyncWorker : public HamLibAsyncWorker { public: - GetAntennaAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, ant_t antenna) + GetAntennaAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int antenna) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), antenna_(antenna), antenna_curr_(0), antenna_tx_(0), antenna_rx_(0) {} void Execute() override { CHECK_RIG_VALID(); - option_ = {0}; - - result_code_ = rig_get_ant(hamlib_instance_->my_rig, vfo_, antenna_, &option_, &antenna_curr_, &antenna_tx_, &antenna_rx_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + option_ = 0.0f; + + result_code_ = shim_rig_get_ant(hamlib_instance_->my_rig, vfo_, antenna_, &option_, &antenna_curr_, &antenna_tx_, &antenna_rx_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { Napi::Object result = Napi::Object::New(env); - + result.Set("currentAntenna", Napi::Number::New(env, antenna_curr_)); result.Set("txAntenna", Napi::Number::New(env, antenna_tx_)); result.Set("rxAntenna", Napi::Number::New(env, antenna_rx_)); - result.Set("option", Napi::Number::New(env, option_.f)); - + result.Set("option", Napi::Number::New(env, option_)); + deferred_.Resolve(result); } } - + void OnError(const Napi::Error& e) override { Napi::Env env = Env(); deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } - + private: - vfo_t vfo_; - ant_t antenna_; - ant_t antenna_curr_; - ant_t antenna_tx_; - ant_t antenna_rx_; - value_t option_; + int vfo_; + int antenna_; + int antenna_curr_; + int antenna_tx_; + int antenna_rx_; + float option_; }; // Power to mW Conversion AsyncWorker class Power2mWAsyncWorker : public HamLibAsyncWorker { public: - Power2mWAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, float power, freq_t freq, rmode_t mode) + Power2mWAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, float power, double freq, int mode) : HamLibAsyncWorker(env, hamlib_instance), power_(power), freq_(freq), mode_(mode), mwpower_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_power2mW(hamlib_instance_->my_rig, &mwpower_, power_, freq_, mode_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_power2mW(hamlib_instance_->my_rig, &mwpower_, power_, freq_, mode_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, mwpower_)); @@ -1221,29 +1208,29 @@ class Power2mWAsyncWorker : public HamLibAsyncWorker { private: float power_; - freq_t freq_; - rmode_t mode_; + double freq_; + int mode_; unsigned int mwpower_; }; // mW to Power Conversion AsyncWorker class MW2PowerAsyncWorker : public HamLibAsyncWorker { public: - MW2PowerAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, unsigned int mwpower, freq_t freq, rmode_t mode) + MW2PowerAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, unsigned int mwpower, double freq, int mode) : HamLibAsyncWorker(env, hamlib_instance), mwpower_(mwpower), freq_(freq), mode_(mode), power_(0.0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_mW2power(hamlib_instance_->my_rig, &power_, mwpower_, freq_, mode_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_mW2power(hamlib_instance_->my_rig, &power_, mwpower_, freq_, mode_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, power_)); @@ -1257,29 +1244,29 @@ class MW2PowerAsyncWorker : public HamLibAsyncWorker { private: unsigned int mwpower_; - freq_t freq_; - rmode_t mode_; + double freq_; + int mode_; float power_; }; // Set Split Mode AsyncWorker class SetSplitModeAsyncWorker : public HamLibAsyncWorker { public: - SetSplitModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, rmode_t tx_mode, pbwidth_t tx_width, vfo_t vfo = RIG_VFO_CURR) + SetSplitModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int tx_mode, int tx_width, int vfo = SHIM_RIG_VFO_CURR) : HamLibAsyncWorker(env, hamlib_instance), tx_mode_(tx_mode), tx_width_(tx_width), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_split_mode(hamlib_instance_->my_rig, vfo_, tx_mode_, tx_width_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_split_mode(hamlib_instance_->my_rig, vfo_, tx_mode_, tx_width_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1292,34 +1279,34 @@ class SetSplitModeAsyncWorker : public HamLibAsyncWorker { } private: - rmode_t tx_mode_; - pbwidth_t tx_width_; - vfo_t vfo_; + int tx_mode_; + int tx_width_; + int vfo_; }; // Get Split Mode AsyncWorker class GetSplitModeAsyncWorker : public HamLibAsyncWorker { public: - GetSplitModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo = RIG_VFO_CURR) + GetSplitModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo = SHIM_RIG_VFO_CURR) : HamLibAsyncWorker(env, hamlib_instance), tx_mode_(0), tx_width_(0), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_split_mode(hamlib_instance_->my_rig, vfo_, &tx_mode_, &tx_width_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_split_mode(hamlib_instance_->my_rig, vfo_, &tx_mode_, &tx_width_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { Napi::Object obj = Napi::Object::New(env); // Convert mode to string using rig_strrmode - const char* mode_str = rig_strrmode(tx_mode_); + const char* mode_str = shim_rig_strrmode(tx_mode_); obj.Set(Napi::String::New(env, "mode"), Napi::String::New(env, mode_str)); obj.Set(Napi::String::New(env, "width"), tx_width_); deferred_.Resolve(obj); @@ -1332,9 +1319,9 @@ class GetSplitModeAsyncWorker : public HamLibAsyncWorker { } private: - rmode_t tx_mode_; - pbwidth_t tx_width_; - vfo_t vfo_; + int tx_mode_; + int tx_width_; + int vfo_; }; // Set Serial Config AsyncWorker @@ -1349,137 +1336,137 @@ class SetSerialConfigAsyncWorker : public HamLibAsyncWorker { // Apply serial configuration parameter if (param_name_ == "data_bits") { int data_bits = std::stoi(param_value_); - hamlib_instance_->my_rig->state.rigport.parm.serial.data_bits = data_bits; - result_code_ = RIG_OK; + shim_rig_set_serial_data_bits(hamlib_instance_->my_rig, data_bits); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "stop_bits") { int stop_bits = std::stoi(param_value_); - hamlib_instance_->my_rig->state.rigport.parm.serial.stop_bits = stop_bits; - result_code_ = RIG_OK; + shim_rig_set_serial_stop_bits(hamlib_instance_->my_rig, stop_bits); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "serial_parity") { - enum serial_parity_e parity; + int parity; if (param_value_ == "None") { - parity = RIG_PARITY_NONE; + parity = SHIM_RIG_PARITY_NONE; } else if (param_value_ == "Even") { - parity = RIG_PARITY_EVEN; + parity = SHIM_RIG_PARITY_EVEN; } else if (param_value_ == "Odd") { - parity = RIG_PARITY_ODD; + parity = SHIM_RIG_PARITY_ODD; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid parity value"; return; } - hamlib_instance_->my_rig->state.rigport.parm.serial.parity = parity; - result_code_ = RIG_OK; + shim_rig_set_serial_parity(hamlib_instance_->my_rig, parity); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "serial_handshake") { - enum serial_handshake_e handshake; + int handshake; if (param_value_ == "None") { - handshake = RIG_HANDSHAKE_NONE; + handshake = SHIM_RIG_HANDSHAKE_NONE; } else if (param_value_ == "Hardware") { - handshake = RIG_HANDSHAKE_HARDWARE; + handshake = SHIM_RIG_HANDSHAKE_HARDWARE; } else if (param_value_ == "Software") { - handshake = RIG_HANDSHAKE_XONXOFF; + handshake = SHIM_RIG_HANDSHAKE_XONXOFF; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid handshake value"; return; } - hamlib_instance_->my_rig->state.rigport.parm.serial.handshake = handshake; - result_code_ = RIG_OK; + shim_rig_set_serial_handshake(hamlib_instance_->my_rig, handshake); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "rts_state") { - enum serial_control_state_e state; + int state; if (param_value_ == "ON") { - state = RIG_SIGNAL_ON; + state = SHIM_RIG_SIGNAL_ON; } else if (param_value_ == "OFF") { - state = RIG_SIGNAL_OFF; + state = SHIM_RIG_SIGNAL_OFF; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid RTS state value"; return; } - hamlib_instance_->my_rig->state.rigport.parm.serial.rts_state = state; - result_code_ = RIG_OK; + shim_rig_set_serial_rts_state(hamlib_instance_->my_rig, state); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "dtr_state") { - enum serial_control_state_e state; + int state; if (param_value_ == "ON") { - state = RIG_SIGNAL_ON; + state = SHIM_RIG_SIGNAL_ON; } else if (param_value_ == "OFF") { - state = RIG_SIGNAL_OFF; + state = SHIM_RIG_SIGNAL_OFF; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid DTR state value"; return; } - hamlib_instance_->my_rig->state.rigport.parm.serial.dtr_state = state; - result_code_ = RIG_OK; + shim_rig_set_serial_dtr_state(hamlib_instance_->my_rig, state); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "rate") { int rate = std::stoi(param_value_); // Validate supported baud rates based on common values in Hamlib - std::vector valid_rates = {150, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, - 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, + std::vector valid_rates = {150, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, + 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000}; if (std::find(valid_rates.begin(), valid_rates.end(), rate) != valid_rates.end()) { - hamlib_instance_->my_rig->state.rigport.parm.serial.rate = rate; - result_code_ = RIG_OK; + shim_rig_set_serial_rate(hamlib_instance_->my_rig, rate); + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid baud rate value"; } } else if (param_name_ == "timeout") { int timeout_val = std::stoi(param_value_); if (timeout_val >= 0) { - hamlib_instance_->my_rig->state.rigport.timeout = timeout_val; - result_code_ = RIG_OK; + shim_rig_set_port_timeout(hamlib_instance_->my_rig, timeout_val); + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Timeout must be non-negative"; } } else if (param_name_ == "retry") { int retry_val = std::stoi(param_value_); if (retry_val >= 0) { - hamlib_instance_->my_rig->state.rigport.retry = (short)retry_val; - result_code_ = RIG_OK; + shim_rig_set_port_retry(hamlib_instance_->my_rig, retry_val); + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Retry count must be non-negative"; } } else if (param_name_ == "write_delay") { int delay = std::stoi(param_value_); if (delay >= 0) { - hamlib_instance_->my_rig->state.rigport.write_delay = delay; - result_code_ = RIG_OK; + shim_rig_set_port_write_delay(hamlib_instance_->my_rig, delay); + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Write delay must be non-negative"; } } else if (param_name_ == "post_write_delay") { int delay = std::stoi(param_value_); if (delay >= 0) { - hamlib_instance_->my_rig->state.rigport.post_write_delay = delay; - result_code_ = RIG_OK; + shim_rig_set_port_post_write_delay(hamlib_instance_->my_rig, delay); + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Post write delay must be non-negative"; } } else if (param_name_ == "flushx") { if (param_value_ == "true" || param_value_ == "1") { - hamlib_instance_->my_rig->state.rigport.flushx = 1; - result_code_ = RIG_OK; + shim_rig_set_port_flushx(hamlib_instance_->my_rig, 1); + result_code_ = SHIM_RIG_OK; } else if (param_value_ == "false" || param_value_ == "0") { - hamlib_instance_->my_rig->state.rigport.flushx = 0; - result_code_ = RIG_OK; + shim_rig_set_port_flushx(hamlib_instance_->my_rig, 0); + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Flushx must be true/false or 1/0"; } } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Unknown serial configuration parameter"; } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1507,96 +1494,96 @@ class GetSerialConfigAsyncWorker : public HamLibAsyncWorker { // Get serial configuration parameter if (param_name_ == "data_bits") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.parm.serial.data_bits); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_serial_data_bits(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "stop_bits") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.parm.serial.stop_bits); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_serial_stop_bits(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "serial_parity") { - switch (hamlib_instance_->my_rig->state.rigport.parm.serial.parity) { - case RIG_PARITY_NONE: + switch (shim_rig_get_serial_parity(hamlib_instance_->my_rig)) { + case SHIM_RIG_PARITY_NONE: param_value_ = "None"; break; - case RIG_PARITY_EVEN: + case SHIM_RIG_PARITY_EVEN: param_value_ = "Even"; break; - case RIG_PARITY_ODD: + case SHIM_RIG_PARITY_ODD: param_value_ = "Odd"; break; default: param_value_ = "Unknown"; break; } - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "serial_handshake") { - switch (hamlib_instance_->my_rig->state.rigport.parm.serial.handshake) { - case RIG_HANDSHAKE_NONE: + switch (shim_rig_get_serial_handshake(hamlib_instance_->my_rig)) { + case SHIM_RIG_HANDSHAKE_NONE: param_value_ = "None"; break; - case RIG_HANDSHAKE_HARDWARE: + case SHIM_RIG_HANDSHAKE_HARDWARE: param_value_ = "Hardware"; break; - case RIG_HANDSHAKE_XONXOFF: + case SHIM_RIG_HANDSHAKE_XONXOFF: param_value_ = "Software"; break; default: param_value_ = "Unknown"; break; } - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "rts_state") { - switch (hamlib_instance_->my_rig->state.rigport.parm.serial.rts_state) { - case RIG_SIGNAL_ON: + switch (shim_rig_get_serial_rts_state(hamlib_instance_->my_rig)) { + case SHIM_RIG_SIGNAL_ON: param_value_ = "ON"; break; - case RIG_SIGNAL_OFF: + case SHIM_RIG_SIGNAL_OFF: param_value_ = "OFF"; break; default: param_value_ = "Unknown"; break; } - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "dtr_state") { - switch (hamlib_instance_->my_rig->state.rigport.parm.serial.dtr_state) { - case RIG_SIGNAL_ON: + switch (shim_rig_get_serial_dtr_state(hamlib_instance_->my_rig)) { + case SHIM_RIG_SIGNAL_ON: param_value_ = "ON"; break; - case RIG_SIGNAL_OFF: + case SHIM_RIG_SIGNAL_OFF: param_value_ = "OFF"; break; default: param_value_ = "Unknown"; break; } - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "rate") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.parm.serial.rate); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_serial_rate(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "timeout") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.timeout); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_port_timeout(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "retry") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.retry); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_port_retry(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "write_delay") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.write_delay); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_port_write_delay(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "post_write_delay") { - param_value_ = std::to_string(hamlib_instance_->my_rig->state.rigport.post_write_delay); - result_code_ = RIG_OK; + param_value_ = std::to_string(shim_rig_get_port_post_write_delay(hamlib_instance_->my_rig)); + result_code_ = SHIM_RIG_OK; } else if (param_name_ == "flushx") { - param_value_ = hamlib_instance_->my_rig->state.rigport.flushx ? "true" : "false"; - result_code_ = RIG_OK; + param_value_ = shim_rig_get_port_flushx(hamlib_instance_->my_rig) ? "true" : "false"; + result_code_ = SHIM_RIG_OK; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Unknown serial configuration parameter"; } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::String::New(env, param_value_)); @@ -1616,42 +1603,42 @@ class GetSerialConfigAsyncWorker : public HamLibAsyncWorker { // Set PTT Type AsyncWorker class SetPttTypeAsyncWorker : public HamLibAsyncWorker { public: - SetPttTypeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, const std::string& ptt_type) - : HamLibAsyncWorker(env, hamlib_instance), ptt_type_(ptt_type) {} + SetPttTypeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, const std::string& intype) + : HamLibAsyncWorker(env, hamlib_instance), intype_(intype) {} void Execute() override { CHECK_RIG_VALID(); - ptt_type_t ptt_type; - if (ptt_type_ == "RIG") { - ptt_type = RIG_PTT_RIG; - } else if (ptt_type_ == "DTR") { - ptt_type = RIG_PTT_SERIAL_DTR; - } else if (ptt_type_ == "RTS") { - ptt_type = RIG_PTT_SERIAL_RTS; - } else if (ptt_type_ == "PARALLEL") { - ptt_type = RIG_PTT_PARALLEL; - } else if (ptt_type_ == "CM108") { - ptt_type = RIG_PTT_CM108; - } else if (ptt_type_ == "GPIO") { - ptt_type = RIG_PTT_GPIO; - } else if (ptt_type_ == "GPION") { - ptt_type = RIG_PTT_GPION; - } else if (ptt_type_ == "NONE") { - ptt_type = RIG_PTT_NONE; + int intype; + if (intype_ == "RIG") { + intype = SHIM_RIG_PTT_RIG; + } else if (intype_ == "DTR") { + intype = SHIM_RIG_PTT_SERIAL_DTR; + } else if (intype_ == "RTS") { + intype = SHIM_RIG_PTT_SERIAL_RTS; + } else if (intype_ == "PARALLEL") { + intype = SHIM_RIG_PTT_PARALLEL; + } else if (intype_ == "CM108") { + intype = SHIM_RIG_PTT_CM108; + } else if (intype_ == "GPIO") { + intype = SHIM_RIG_PTT_GPIO; + } else if (intype_ == "GPION") { + intype = SHIM_RIG_PTT_GPION; + } else if (intype_ == "NONE") { + intype = SHIM_RIG_PTT_NONE; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid PTT type"; return; } - hamlib_instance_->my_rig->state.pttport.type.ptt = ptt_type; - result_code_ = RIG_OK; + shim_rig_set_ptt_type(hamlib_instance_->my_rig, intype); + result_code_ = SHIM_RIG_OK; } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1664,7 +1651,7 @@ class SetPttTypeAsyncWorker : public HamLibAsyncWorker { } private: - std::string ptt_type_; + std::string intype_; }; // Get PTT Type AsyncWorker @@ -1676,46 +1663,46 @@ class GetPttTypeAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - ptt_type_t ptt_type = hamlib_instance_->my_rig->state.pttport.type.ptt; + int intype = shim_rig_get_ptt_type(hamlib_instance_->my_rig); - switch (ptt_type) { - case RIG_PTT_RIG: - ptt_type_str_ = "RIG"; + switch (intype) { + case SHIM_RIG_PTT_RIG: + intype_str_ = "RIG"; break; - case RIG_PTT_SERIAL_DTR: - ptt_type_str_ = "DTR"; + case SHIM_RIG_PTT_SERIAL_DTR: + intype_str_ = "DTR"; break; - case RIG_PTT_SERIAL_RTS: - ptt_type_str_ = "RTS"; + case SHIM_RIG_PTT_SERIAL_RTS: + intype_str_ = "RTS"; break; - case RIG_PTT_PARALLEL: - ptt_type_str_ = "PARALLEL"; + case SHIM_RIG_PTT_PARALLEL: + intype_str_ = "PARALLEL"; break; - case RIG_PTT_CM108: - ptt_type_str_ = "CM108"; + case SHIM_RIG_PTT_CM108: + intype_str_ = "CM108"; break; - case RIG_PTT_GPIO: - ptt_type_str_ = "GPIO"; + case SHIM_RIG_PTT_GPIO: + intype_str_ = "GPIO"; break; - case RIG_PTT_GPION: - ptt_type_str_ = "GPION"; + case SHIM_RIG_PTT_GPION: + intype_str_ = "GPION"; break; - case RIG_PTT_NONE: - ptt_type_str_ = "NONE"; + case SHIM_RIG_PTT_NONE: + intype_str_ = "NONE"; break; default: - ptt_type_str_ = "Unknown"; + intype_str_ = "Unknown"; break; } - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { - deferred_.Resolve(Napi::String::New(env, ptt_type_str_)); + deferred_.Resolve(Napi::String::New(env, intype_str_)); } } @@ -1725,50 +1712,50 @@ class GetPttTypeAsyncWorker : public HamLibAsyncWorker { } private: - std::string ptt_type_str_; + std::string intype_str_; }; // Set DCD Type AsyncWorker class SetDcdTypeAsyncWorker : public HamLibAsyncWorker { public: - SetDcdTypeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, const std::string& dcd_type) - : HamLibAsyncWorker(env, hamlib_instance), dcd_type_(dcd_type) {} + SetDcdTypeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, const std::string& intype) + : HamLibAsyncWorker(env, hamlib_instance), intype_(intype) {} void Execute() override { CHECK_RIG_VALID(); - dcd_type_t dcd_type; - if (dcd_type_ == "RIG") { - dcd_type = RIG_DCD_RIG; - } else if (dcd_type_ == "DSR") { - dcd_type = RIG_DCD_SERIAL_DSR; - } else if (dcd_type_ == "CTS") { - dcd_type = RIG_DCD_SERIAL_CTS; - } else if (dcd_type_ == "CD") { - dcd_type = RIG_DCD_SERIAL_CAR; - } else if (dcd_type_ == "PARALLEL") { - dcd_type = RIG_DCD_PARALLEL; - } else if (dcd_type_ == "CM108") { - dcd_type = RIG_DCD_CM108; - } else if (dcd_type_ == "GPIO") { - dcd_type = RIG_DCD_GPIO; - } else if (dcd_type_ == "GPION") { - dcd_type = RIG_DCD_GPION; - } else if (dcd_type_ == "NONE") { - dcd_type = RIG_DCD_NONE; + int intype; + if (intype_ == "RIG") { + intype = SHIM_RIG_DCD_RIG; + } else if (intype_ == "DSR") { + intype = SHIM_RIG_DCD_SERIAL_DSR; + } else if (intype_ == "CTS") { + intype = SHIM_RIG_DCD_SERIAL_CTS; + } else if (intype_ == "CD") { + intype = SHIM_RIG_DCD_SERIAL_CAR; + } else if (intype_ == "PARALLEL") { + intype = SHIM_RIG_DCD_PARALLEL; + } else if (intype_ == "CM108") { + intype = SHIM_RIG_DCD_CM108; + } else if (intype_ == "GPIO") { + intype = SHIM_RIG_DCD_GPIO; + } else if (intype_ == "GPION") { + intype = SHIM_RIG_DCD_GPION; + } else if (intype_ == "NONE") { + intype = SHIM_RIG_DCD_NONE; } else { - result_code_ = -RIG_EINVAL; + result_code_ = SHIM_RIG_EINVAL; error_message_ = "Invalid DCD type"; return; } - hamlib_instance_->my_rig->state.dcdport.type.dcd = dcd_type; - result_code_ = RIG_OK; + shim_rig_set_dcd_type(hamlib_instance_->my_rig, intype); + result_code_ = SHIM_RIG_OK; } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1781,7 +1768,7 @@ class SetDcdTypeAsyncWorker : public HamLibAsyncWorker { } private: - std::string dcd_type_; + std::string intype_; }; // Get DCD Type AsyncWorker @@ -1793,49 +1780,49 @@ class GetDcdTypeAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - dcd_type_t dcd_type = hamlib_instance_->my_rig->state.dcdport.type.dcd; + int intype = shim_rig_get_dcd_type(hamlib_instance_->my_rig); - switch (dcd_type) { - case RIG_DCD_RIG: - dcd_type_str_ = "RIG"; + switch (intype) { + case SHIM_RIG_DCD_RIG: + intype_str_ = "RIG"; break; - case RIG_DCD_SERIAL_DSR: - dcd_type_str_ = "DSR"; + case SHIM_RIG_DCD_SERIAL_DSR: + intype_str_ = "DSR"; break; - case RIG_DCD_SERIAL_CTS: - dcd_type_str_ = "CTS"; + case SHIM_RIG_DCD_SERIAL_CTS: + intype_str_ = "CTS"; break; - case RIG_DCD_SERIAL_CAR: - dcd_type_str_ = "CD"; + case SHIM_RIG_DCD_SERIAL_CAR: + intype_str_ = "CD"; break; - case RIG_DCD_PARALLEL: - dcd_type_str_ = "PARALLEL"; + case SHIM_RIG_DCD_PARALLEL: + intype_str_ = "PARALLEL"; break; - case RIG_DCD_CM108: - dcd_type_str_ = "CM108"; + case SHIM_RIG_DCD_CM108: + intype_str_ = "CM108"; break; - case RIG_DCD_GPIO: - dcd_type_str_ = "GPIO"; + case SHIM_RIG_DCD_GPIO: + intype_str_ = "GPIO"; break; - case RIG_DCD_GPION: - dcd_type_str_ = "GPION"; + case SHIM_RIG_DCD_GPION: + intype_str_ = "GPION"; break; - case RIG_DCD_NONE: - dcd_type_str_ = "NONE"; + case SHIM_RIG_DCD_NONE: + intype_str_ = "NONE"; break; default: - dcd_type_str_ = "Unknown"; + intype_str_ = "Unknown"; break; } - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { - deferred_.Resolve(Napi::String::New(env, dcd_type_str_)); + deferred_.Resolve(Napi::String::New(env, intype_str_)); } } @@ -1845,27 +1832,27 @@ class GetDcdTypeAsyncWorker : public HamLibAsyncWorker { } private: - std::string dcd_type_str_; + std::string intype_str_; }; // Power Control AsyncWorker classes class SetPowerstatAsyncWorker : public HamLibAsyncWorker { public: - SetPowerstatAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, powerstat_t status) + SetPowerstatAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int status) : HamLibAsyncWorker(env, hamlib_instance), status_(status) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_powerstat(hamlib_instance_->my_rig, status_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_powerstat(hamlib_instance_->my_rig, status_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -1878,26 +1865,26 @@ class SetPowerstatAsyncWorker : public HamLibAsyncWorker { } private: - powerstat_t status_; + int status_; }; class GetPowerstatAsyncWorker : public HamLibAsyncWorker { public: GetPowerstatAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance) - : HamLibAsyncWorker(env, hamlib_instance), status_(RIG_POWER_UNKNOWN) {} + : HamLibAsyncWorker(env, hamlib_instance), status_(SHIM_RIG_POWER_UNKNOWN) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_powerstat(hamlib_instance_->my_rig, &status_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_powerstat(hamlib_instance_->my_rig, &status_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, static_cast(status_))); @@ -1910,30 +1897,30 @@ class GetPowerstatAsyncWorker : public HamLibAsyncWorker { } private: - powerstat_t status_; + int status_; }; // PTT Status Detection AsyncWorker class GetPttAsyncWorker : public HamLibAsyncWorker { public: - GetPttAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) - : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), ptt_(RIG_PTT_OFF) {} + GetPttAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) + : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), ptt_(SHIM_RIG_PTT_OFF) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_ptt(hamlib_instance_->my_rig, vfo_, &ptt_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_ptt(hamlib_instance_->my_rig, vfo_, &ptt_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { - deferred_.Resolve(Napi::Boolean::New(env, ptt_ == RIG_PTT_ON)); + deferred_.Resolve(Napi::Boolean::New(env, ptt_ == SHIM_RIG_PTT_ON)); } } @@ -1943,31 +1930,31 @@ class GetPttAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - ptt_t ptt_; + int vfo_; + int ptt_; }; // Data Carrier Detect AsyncWorker class GetDcdAsyncWorker : public HamLibAsyncWorker { public: - GetDcdAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) - : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), dcd_(RIG_DCD_OFF) {} + GetDcdAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) + : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), dcd_(SHIM_RIG_DCD_OFF) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_dcd(hamlib_instance_->my_rig, vfo_, &dcd_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_dcd(hamlib_instance_->my_rig, vfo_, &dcd_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { - deferred_.Resolve(Napi::Boolean::New(env, dcd_ == RIG_DCD_ON)); + deferred_.Resolve(Napi::Boolean::New(env, dcd_ == SHIM_RIG_DCD_ON)); } } @@ -1977,28 +1964,28 @@ class GetDcdAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - dcd_t dcd_; + int vfo_; + int dcd_; }; // Tuning Step Control AsyncWorker classes class SetTuningStepAsyncWorker : public HamLibAsyncWorker { public: - SetTuningStepAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, shortfreq_t ts) + SetTuningStepAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int ts) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), ts_(ts) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_ts(hamlib_instance_->my_rig, vfo_, ts_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_ts(hamlib_instance_->my_rig, vfo_, ts_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -2011,27 +1998,27 @@ class SetTuningStepAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - shortfreq_t ts_; + int vfo_; + int ts_; }; class GetTuningStepAsyncWorker : public HamLibAsyncWorker { public: - GetTuningStepAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetTuningStepAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), ts_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_ts(hamlib_instance_->my_rig, vfo_, &ts_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_ts(hamlib_instance_->my_rig, vfo_, &ts_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, ts_)); @@ -2044,28 +2031,28 @@ class GetTuningStepAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - shortfreq_t ts_; + int vfo_; + int ts_; }; // Repeater Control AsyncWorker classes class SetRepeaterShiftAsyncWorker : public HamLibAsyncWorker { public: - SetRepeaterShiftAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, rptr_shift_t shift) + SetRepeaterShiftAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int shift) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), shift_(shift) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_rptr_shift(hamlib_instance_->my_rig, vfo_, shift_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_rptr_shift(hamlib_instance_->my_rig, vfo_, shift_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -2078,27 +2065,27 @@ class SetRepeaterShiftAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - rptr_shift_t shift_; + int vfo_; + int shift_; }; class GetRepeaterShiftAsyncWorker : public HamLibAsyncWorker { public: - GetRepeaterShiftAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) - : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), shift_(RIG_RPT_SHIFT_NONE) {} + GetRepeaterShiftAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) + : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), shift_(SHIM_RIG_RPT_SHIFT_NONE) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_rptr_shift(hamlib_instance_->my_rig, vfo_, &shift_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_rptr_shift(hamlib_instance_->my_rig, vfo_, &shift_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - const char* shift_str = rig_strptrshift(shift_); + const char* shift_str = shim_rig_strptrshift(shift_); deferred_.Resolve(Napi::String::New(env, shift_str)); } @@ -2108,27 +2095,27 @@ class GetRepeaterShiftAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - rptr_shift_t shift_; + int vfo_; + int shift_; }; class SetRepeaterOffsetAsyncWorker : public HamLibAsyncWorker { public: - SetRepeaterOffsetAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, shortfreq_t offset) + SetRepeaterOffsetAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int offset) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), offset_(offset) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_rptr_offs(hamlib_instance_->my_rig, vfo_, offset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_rptr_offs(hamlib_instance_->my_rig, vfo_, offset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -2141,27 +2128,27 @@ class SetRepeaterOffsetAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - shortfreq_t offset_; + int vfo_; + int offset_; }; class GetRepeaterOffsetAsyncWorker : public HamLibAsyncWorker { public: - GetRepeaterOffsetAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetRepeaterOffsetAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), offset_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_rptr_offs(hamlib_instance_->my_rig, vfo_, &offset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_rptr_offs(hamlib_instance_->my_rig, vfo_, &offset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, offset_)); @@ -2174,18 +2161,18 @@ class GetRepeaterOffsetAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - shortfreq_t offset_; + int vfo_; + int offset_; }; // Helper function to parse VFO parameter from JavaScript -vfo_t parseVfoParameter(const Napi::CallbackInfo& info, int index, vfo_t defaultVfo = RIG_VFO_CURR) { +int parseVfoParameter(const Napi::CallbackInfo& info, int index, int defaultVfo = SHIM_RIG_VFO_CURR) { if (info.Length() > index && info[index].IsString()) { std::string vfoStr = info[index].As().Utf8Value(); if (vfoStr == "VFO-A") { - return RIG_VFO_A; + return SHIM_RIG_VFO_A; } else if (vfoStr == "VFO-B") { - return RIG_VFO_B; + return SHIM_RIG_VFO_B; } } return defaultVfo; @@ -2205,35 +2192,35 @@ NodeHamLib::NodeHamLib(const Napi::CallbackInfo & info): ObjectWrap(info) { } // Set default port path if not provided - strncpy(port_path, "/dev/ttyUSB0", HAMLIB_FILPATHLEN - 1); - port_path[HAMLIB_FILPATHLEN - 1] = '\0'; + strncpy(port_path, "/dev/ttyUSB0", SHIM_HAMLIB_FILPATHLEN - 1); + port_path[SHIM_HAMLIB_FILPATHLEN - 1] = '\0'; // Check if port path is provided as second argument if (info.Length() >= 2) { if (info[1].IsString()) { std::string portStr = info[1].As().Utf8Value(); - strncpy(port_path, portStr.c_str(), HAMLIB_FILPATHLEN - 1); - port_path[HAMLIB_FILPATHLEN - 1] = '\0'; + strncpy(port_path, portStr.c_str(), SHIM_HAMLIB_FILPATHLEN - 1); + port_path[SHIM_HAMLIB_FILPATHLEN - 1] = '\0'; } // Note: Debug level is now controlled globally via HamLib.setDebugLevel() // and set to RIG_DEBUG_NONE by default in addon initialization } - //rig_model_t myrig_model; + //unsigned int myrig_model; // hamlib_port_t myport; // /* may be overriden by backend probe */ // myport.type.rig = RIG_PORT_SERIAL; // myport.parm.serial.rate = 38400; // myport.parm.serial.data_bits = 8; // myport.parm.serial.stop_bits = 2; - // myport.parm.serial.parity = RIG_PARITY_NONE; - // myport.parm.serial.handshake = RIG_HANDSHAKE_HARDWARE; - // strncpy(myport.pathname, "/dev/ttyUSB0", HAMLIB_FILPATHLEN - 1); + // myport.parm.serial.parity = SHIM_RIG_PARITY_NONE; + // myport.parm.serial.handshake = SHIM_RIG_HANDSHAKE_HARDWARE; + // strncpy(myport.pathname, "/dev/ttyUSB0", SHIM_HAMLIB_FILPATHLEN - 1); - // rig_load_all_backends(); + // shim_rig_load_all_backends(); // myrig_model = rig_probe(&myport); // fprintf(stderr, "Got Rig Model %d \n", myrig_model); - rig_model_t myrig_model = info[0].As < Napi::Number > ().DoubleValue(); + unsigned int myrig_model = info[0].As < Napi::Number > ().DoubleValue(); original_model = myrig_model; // Check if port_path is a network address (contains colon) @@ -2245,7 +2232,7 @@ NodeHamLib::NodeHamLib(const Napi::CallbackInfo & info): ObjectWrap(info) { // Network connection will be established on open() } - my_rig = rig_init(myrig_model); + my_rig = shim_rig_init(myrig_model); //int retcode = 0; if (!my_rig) { // Create detailed error message @@ -2256,15 +2243,15 @@ NodeHamLib::NodeHamLib(const Napi::CallbackInfo & info): ObjectWrap(info) { } // Set port path and type based on connection type - strncpy(my_rig -> state.rigport.pathname, port_path, HAMLIB_FILPATHLEN - 1); - + shim_rig_set_port_path(my_rig, port_path); + if (is_network_rig) { - my_rig -> state.rigport.type.rig = RIG_PORT_NETWORK; + shim_rig_set_port_type(my_rig, SHIM_RIG_PORT_NETWORK); } else { - my_rig -> state.rigport.type.rig = RIG_PORT_SERIAL; + shim_rig_set_port_type(my_rig, SHIM_RIG_PORT_SERIAL); } - // this->freq_emit_cb = [info](freq_t freq) { + // this->freq_emit_cb = [info](double freq) { // Napi::Env env = info.Env(); // Napi::Function emit = info.This().As().Get("emit").As(); // emit.Call( @@ -2281,16 +2268,16 @@ NodeHamLib::~NodeHamLib() { if (my_rig) { // 如果rig是打开状态,先关闭 if (rig_is_open) { - rig_close(my_rig); + shim_rig_close(my_rig); rig_is_open = false; } // 清理rig资源 - rig_cleanup(my_rig); + shim_rig_cleanup(my_rig); my_rig = nullptr; } } -int NodeHamLib::freq_change_cb(RIG *rig, vfo_t vfo, freq_t freq, void* arg) { +int NodeHamLib::freq_change_cb(void *handle, int vfo, double freq, void* arg) { auto instance = static_cast(arg); printf("Rig changed freq to %0.7f Hz\n", freq); Napi::Env env = instance->m_currentInfo->Env(); @@ -2336,12 +2323,12 @@ Napi::Value NodeHamLib::SetVFO(const Napi::CallbackInfo & info) { } std::string name = info[0].As().Utf8Value(); - vfo_t vfo; + int vfo; if (name == "VFO-A") { - vfo = RIG_VFO_A; + vfo = SHIM_RIG_VFO_A; } else if (name == "VFO-B") { - vfo = RIG_VFO_B; + vfo = SHIM_RIG_VFO_B; } else { Napi::TypeError::New(env, "Invalid VFO name") .ThrowAsJavaScriptException(); @@ -2375,7 +2362,7 @@ Napi::Value NodeHamLib::SetFrequency(const Napi::CallbackInfo & info) { return env.Null(); } - freq_t freq = info[0].As().DoubleValue(); + double freq = info[0].As().DoubleValue(); // Basic frequency range validation if (freq < 1000 || freq > 10000000000) { // 1 kHz to 10 GHz reasonable range @@ -2384,14 +2371,14 @@ Napi::Value NodeHamLib::SetFrequency(const Napi::CallbackInfo & info) { } // Support optional VFO parameter - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 2 && info[1].IsString()) { std::string vfostr = info[1].As().Utf8Value(); if (vfostr == "VFO-A") { - vfo = RIG_VFO_A; + vfo = SHIM_RIG_VFO_A; } else if (vfostr == "VFO-B") { - vfo = RIG_VFO_B; + vfo = SHIM_RIG_VFO_B; } } @@ -2423,32 +2410,32 @@ Napi::Value NodeHamLib::SetMode(const Napi::CallbackInfo & info) { } std::string modestr = info[0].As().Utf8Value(); - rmode_t mode = rig_parse_mode(modestr.c_str()); + int mode = shim_rig_parse_mode(modestr.c_str()); - if (mode == RIG_MODE_NONE) { + if (mode == SHIM_RIG_MODE_NONE) { Napi::Error::New(env, "Invalid mode: " + modestr).ThrowAsJavaScriptException(); return env.Null(); } - pbwidth_t bandwidth = RIG_PASSBAND_NORMAL; - vfo_t vfo = RIG_VFO_CURR; + int bandwidth = SHIM_RIG_PASSBAND_NORMAL; + int vfo = SHIM_RIG_VFO_CURR; // Parse parameters: setMode(mode) or setMode(mode, bandwidth) or setMode(mode, bandwidth, vfo) if (info.Length() >= 2 && info[1].IsString()) { std::string bandstr = info[1].As().Utf8Value(); if (bandstr == "narrow") { - bandwidth = rig_passband_narrow(my_rig, mode); + bandwidth = shim_rig_passband_narrow(my_rig, mode); } else if (bandstr == "wide") { - bandwidth = rig_passband_wide(my_rig, mode); + bandwidth = shim_rig_passband_wide(my_rig, mode); } else { // If second parameter is not "narrow" or "wide", might be VFO - vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); } } // Check for third parameter (VFO) if bandwidth was specified if (info.Length() >= 3) { - vfo = parseVfoParameter(info, 2, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 2, SHIM_RIG_VFO_CURR); } SetModeAsyncWorker* worker = new SetModeAsyncWorker(env, this, mode, bandwidth, vfo); @@ -2480,7 +2467,7 @@ Napi::Value NodeHamLib::SetPtt(const Napi::CallbackInfo & info) { bool ptt_state = info[0].As(); - ptt_t ptt = ptt_state ? RIG_PTT_ON : RIG_PTT_OFF; + int ptt = ptt_state ? SHIM_RIG_PTT_ON : SHIM_RIG_PTT_OFF; SetPttAsyncWorker* worker = new SetPttAsyncWorker(env, this, ptt); worker->Queue(); @@ -2512,14 +2499,14 @@ Napi::Value NodeHamLib::GetFrequency(const Napi::CallbackInfo & info) { } // Support optional VFO parameter - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 1 && info[0].IsString()) { std::string vfostr = info[0].As().Utf8Value(); if (vfostr == "VFO-A") { - vfo = RIG_VFO_A; + vfo = SHIM_RIG_VFO_A; } else if (vfostr == "VFO-B") { - vfo = RIG_VFO_B; + vfo = SHIM_RIG_VFO_B; } } @@ -2554,10 +2541,10 @@ Napi::Value NodeHamLib::GetStrength(const Napi::CallbackInfo & info) { } // Support optional VFO parameter: getStrength() or getStrength(vfo) - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 1 && info[0].IsString()) { - vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); } GetStrengthAsyncWorker* worker = new GetStrengthAsyncWorker(env, this, vfo); @@ -2626,11 +2613,11 @@ Napi::Value NodeHamLib::SetMemoryChannel(const Napi::CallbackInfo & info) { Napi::Object chanObj = info[1].As(); // Create channel structure - channel_t chan; + shim_channel_t chan; memset(&chan, 0, sizeof(chan)); chan.channel_num = channel_num; - chan.vfo = RIG_VFO_MEM; + chan.vfo = SHIM_RIG_VFO_MEM; // Extract frequency if (chanObj.Has("frequency")) { @@ -2640,14 +2627,14 @@ Napi::Value NodeHamLib::SetMemoryChannel(const Napi::CallbackInfo & info) { // Extract mode if (chanObj.Has("mode")) { std::string modeStr = chanObj.Get("mode").As().Utf8Value(); - chan.mode = rig_parse_mode(modeStr.c_str()); + chan.mode = shim_rig_parse_mode(modeStr.c_str()); } // Extract bandwidth if (chanObj.Has("bandwidth")) { chan.width = chanObj.Get("bandwidth").As().Int32Value(); } else { - chan.width = RIG_PASSBAND_NORMAL; + chan.width = SHIM_RIG_PASSBAND_NORMAL; } // Extract channel description @@ -2660,7 +2647,7 @@ Napi::Value NodeHamLib::SetMemoryChannel(const Napi::CallbackInfo & info) { // Extract TX frequency for split operation if (chanObj.Has("txFrequency")) { chan.tx_freq = chanObj.Get("txFrequency").As().DoubleValue(); - chan.split = RIG_SPLIT_ON; + chan.split = SHIM_RIG_SPLIT_ON; } // Extract CTCSS tone @@ -2736,7 +2723,7 @@ Napi::Value NodeHamLib::SetRit(const Napi::CallbackInfo & info) { return env.Null(); } - shortfreq_t rit_offset = info[0].As().Int32Value(); + int rit_offset = info[0].As().Int32Value(); SetRitAsyncWorker* worker = new SetRitAsyncWorker(env, this, rit_offset); worker->Queue(); @@ -2771,7 +2758,7 @@ Napi::Value NodeHamLib::SetXit(const Napi::CallbackInfo & info) { return env.Null(); } - shortfreq_t xit_offset = info[0].As().Int32Value(); + int xit_offset = info[0].As().Int32Value(); SetXitAsyncWorker* worker = new SetXitAsyncWorker(env, this, xit_offset); worker->Queue(); @@ -2822,18 +2809,18 @@ Napi::Value NodeHamLib::StartScan(const Napi::CallbackInfo & info) { } std::string scanTypeStr = info[0].As().Utf8Value(); - scan_t scanType; + int scanType; if (scanTypeStr == "VFO") { - scanType = RIG_SCAN_VFO; + scanType = SHIM_RIG_SCAN_VFO; } else if (scanTypeStr == "MEM") { - scanType = RIG_SCAN_MEM; + scanType = SHIM_RIG_SCAN_MEM; } else if (scanTypeStr == "PROG") { - scanType = RIG_SCAN_PROG; + scanType = SHIM_RIG_SCAN_PROG; } else if (scanTypeStr == "DELTA") { - scanType = RIG_SCAN_DELTA; + scanType = SHIM_RIG_SCAN_DELTA; } else if (scanTypeStr == "PRIO") { - scanType = RIG_SCAN_PRIO; + scanType = SHIM_RIG_SCAN_PRIO; } else { Napi::TypeError::New(env, "Invalid scan type").ThrowAsJavaScriptException(); return env.Null(); @@ -2880,56 +2867,54 @@ Napi::Value NodeHamLib::SetLevel(const Napi::CallbackInfo & info) { double levelValue = info[1].As().DoubleValue(); // Map level type strings to hamlib constants - setting_t levelType; + uint64_t levelType; if (levelTypeStr == "AF") { - levelType = RIG_LEVEL_AF; + levelType = SHIM_RIG_LEVEL_AF; } else if (levelTypeStr == "RF") { - levelType = RIG_LEVEL_RF; + levelType = SHIM_RIG_LEVEL_RF; } else if (levelTypeStr == "SQL") { - levelType = RIG_LEVEL_SQL; + levelType = SHIM_RIG_LEVEL_SQL; } else if (levelTypeStr == "RFPOWER") { - levelType = RIG_LEVEL_RFPOWER; + levelType = SHIM_RIG_LEVEL_RFPOWER; } else if (levelTypeStr == "MICGAIN") { - levelType = RIG_LEVEL_MICGAIN; + levelType = SHIM_RIG_LEVEL_MICGAIN; } else if (levelTypeStr == "IF") { - levelType = RIG_LEVEL_IF; + levelType = SHIM_RIG_LEVEL_IF; } else if (levelTypeStr == "APF") { - levelType = RIG_LEVEL_APF; + levelType = SHIM_RIG_LEVEL_APF; } else if (levelTypeStr == "NR") { - levelType = RIG_LEVEL_NR; + levelType = SHIM_RIG_LEVEL_NR; } else if (levelTypeStr == "PBT_IN") { - levelType = RIG_LEVEL_PBT_IN; + levelType = SHIM_RIG_LEVEL_PBT_IN; } else if (levelTypeStr == "PBT_OUT") { - levelType = RIG_LEVEL_PBT_OUT; + levelType = SHIM_RIG_LEVEL_PBT_OUT; } else if (levelTypeStr == "CWPITCH") { - levelType = RIG_LEVEL_CWPITCH; + levelType = SHIM_RIG_LEVEL_CWPITCH; } else if (levelTypeStr == "KEYSPD") { - levelType = RIG_LEVEL_KEYSPD; + levelType = SHIM_RIG_LEVEL_KEYSPD; } else if (levelTypeStr == "NOTCHF") { - levelType = RIG_LEVEL_NOTCHF; + levelType = SHIM_RIG_LEVEL_NOTCHF; } else if (levelTypeStr == "COMP") { - levelType = RIG_LEVEL_COMP; + levelType = SHIM_RIG_LEVEL_COMP; } else if (levelTypeStr == "AGC") { - levelType = RIG_LEVEL_AGC; + levelType = SHIM_RIG_LEVEL_AGC; } else if (levelTypeStr == "BKINDL") { - levelType = RIG_LEVEL_BKINDL; + levelType = SHIM_RIG_LEVEL_BKINDL; } else if (levelTypeStr == "BALANCE") { - levelType = RIG_LEVEL_BALANCE; + levelType = SHIM_RIG_LEVEL_BALANCE; } else if (levelTypeStr == "VOXGAIN") { - levelType = RIG_LEVEL_VOXGAIN; + levelType = SHIM_RIG_LEVEL_VOXGAIN; } else if (levelTypeStr == "VOXDELAY") { - levelType = RIG_LEVEL_VOXDELAY; + levelType = SHIM_RIG_LEVEL_VOXDELAY; } else if (levelTypeStr == "ANTIVOX") { - levelType = RIG_LEVEL_ANTIVOX; + levelType = SHIM_RIG_LEVEL_ANTIVOX; } else { Napi::TypeError::New(env, "Invalid level type").ThrowAsJavaScriptException(); return env.Null(); } - // Create value union - value_t val; - val.f = levelValue; - + float val = static_cast(levelValue); + SetLevelAsyncWorker* worker = new SetLevelAsyncWorker(env, this, levelType, val); worker->Queue(); @@ -2952,35 +2937,35 @@ Napi::Value NodeHamLib::GetLevel(const Napi::CallbackInfo & info) { std::string levelTypeStr = info[0].As().Utf8Value(); // Map level type strings to hamlib constants - setting_t levelType; + uint64_t levelType; if (levelTypeStr == "AF") { - levelType = RIG_LEVEL_AF; + levelType = SHIM_RIG_LEVEL_AF; } else if (levelTypeStr == "RF") { - levelType = RIG_LEVEL_RF; + levelType = SHIM_RIG_LEVEL_RF; } else if (levelTypeStr == "SQL") { - levelType = RIG_LEVEL_SQL; + levelType = SHIM_RIG_LEVEL_SQL; } else if (levelTypeStr == "RFPOWER") { - levelType = RIG_LEVEL_RFPOWER; + levelType = SHIM_RIG_LEVEL_RFPOWER; } else if (levelTypeStr == "MICGAIN") { - levelType = RIG_LEVEL_MICGAIN; + levelType = SHIM_RIG_LEVEL_MICGAIN; } else if (levelTypeStr == "SWR") { - levelType = RIG_LEVEL_SWR; + levelType = SHIM_RIG_LEVEL_SWR; } else if (levelTypeStr == "ALC") { - levelType = RIG_LEVEL_ALC; + levelType = SHIM_RIG_LEVEL_ALC; } else if (levelTypeStr == "STRENGTH") { - levelType = RIG_LEVEL_STRENGTH; + levelType = SHIM_RIG_LEVEL_STRENGTH; } else if (levelTypeStr == "RAWSTR") { - levelType = RIG_LEVEL_RAWSTR; + levelType = SHIM_RIG_LEVEL_RAWSTR; } else if (levelTypeStr == "RFPOWER_METER") { - levelType = RIG_LEVEL_RFPOWER_METER; + levelType = SHIM_RIG_LEVEL_RFPOWER_METER; } else if (levelTypeStr == "COMP_METER") { - levelType = RIG_LEVEL_COMP_METER; + levelType = SHIM_RIG_LEVEL_COMP_METER; } else if (levelTypeStr == "VD_METER") { - levelType = RIG_LEVEL_VD_METER; + levelType = SHIM_RIG_LEVEL_VD_METER; } else if (levelTypeStr == "ID_METER") { - levelType = RIG_LEVEL_ID_METER; + levelType = SHIM_RIG_LEVEL_ID_METER; } else if (levelTypeStr == "TEMP_METER") { - levelType = RIG_LEVEL_TEMP_METER; + levelType = SHIM_RIG_LEVEL_TEMP_METER; } else { Napi::TypeError::New(env, "Invalid level type").ThrowAsJavaScriptException(); return env.Null(); @@ -2996,40 +2981,40 @@ Napi::Value NodeHamLib::GetSupportedLevels(const Napi::CallbackInfo & info) { Napi::Env env = info.Env(); // Get capabilities from rig caps instead of state (doesn't require rig to be open) - setting_t levels = my_rig->caps->has_get_level | my_rig->caps->has_set_level; + uint64_t levels = shim_rig_get_caps_has_get_level(my_rig) | shim_rig_get_caps_has_set_level(my_rig); Napi::Array levelArray = Napi::Array::New(env); uint32_t index = 0; // Check each level type - if (levels & RIG_LEVEL_AF) levelArray[index++] = Napi::String::New(env, "AF"); - if (levels & RIG_LEVEL_RF) levelArray[index++] = Napi::String::New(env, "RF"); - if (levels & RIG_LEVEL_SQL) levelArray[index++] = Napi::String::New(env, "SQL"); - if (levels & RIG_LEVEL_RFPOWER) levelArray[index++] = Napi::String::New(env, "RFPOWER"); - if (levels & RIG_LEVEL_MICGAIN) levelArray[index++] = Napi::String::New(env, "MICGAIN"); - if (levels & RIG_LEVEL_IF) levelArray[index++] = Napi::String::New(env, "IF"); - if (levels & RIG_LEVEL_APF) levelArray[index++] = Napi::String::New(env, "APF"); - if (levels & RIG_LEVEL_NR) levelArray[index++] = Napi::String::New(env, "NR"); - if (levels & RIG_LEVEL_PBT_IN) levelArray[index++] = Napi::String::New(env, "PBT_IN"); - if (levels & RIG_LEVEL_PBT_OUT) levelArray[index++] = Napi::String::New(env, "PBT_OUT"); - if (levels & RIG_LEVEL_CWPITCH) levelArray[index++] = Napi::String::New(env, "CWPITCH"); - if (levels & RIG_LEVEL_KEYSPD) levelArray[index++] = Napi::String::New(env, "KEYSPD"); - if (levels & RIG_LEVEL_NOTCHF) levelArray[index++] = Napi::String::New(env, "NOTCHF"); - if (levels & RIG_LEVEL_COMP) levelArray[index++] = Napi::String::New(env, "COMP"); - if (levels & RIG_LEVEL_AGC) levelArray[index++] = Napi::String::New(env, "AGC"); - if (levels & RIG_LEVEL_BKINDL) levelArray[index++] = Napi::String::New(env, "BKINDL"); - if (levels & RIG_LEVEL_BALANCE) levelArray[index++] = Napi::String::New(env, "BALANCE"); - if (levels & RIG_LEVEL_VOXGAIN) levelArray[index++] = Napi::String::New(env, "VOXGAIN"); - if (levels & RIG_LEVEL_VOXDELAY) levelArray[index++] = Napi::String::New(env, "VOXDELAY"); - if (levels & RIG_LEVEL_ANTIVOX) levelArray[index++] = Napi::String::New(env, "ANTIVOX"); - if (levels & RIG_LEVEL_STRENGTH) levelArray[index++] = Napi::String::New(env, "STRENGTH"); - if (levels & RIG_LEVEL_RAWSTR) levelArray[index++] = Napi::String::New(env, "RAWSTR"); - if (levels & RIG_LEVEL_SWR) levelArray[index++] = Napi::String::New(env, "SWR"); - if (levels & RIG_LEVEL_ALC) levelArray[index++] = Napi::String::New(env, "ALC"); - if (levels & RIG_LEVEL_RFPOWER_METER) levelArray[index++] = Napi::String::New(env, "RFPOWER_METER"); - if (levels & RIG_LEVEL_COMP_METER) levelArray[index++] = Napi::String::New(env, "COMP_METER"); - if (levels & RIG_LEVEL_VD_METER) levelArray[index++] = Napi::String::New(env, "VD_METER"); - if (levels & RIG_LEVEL_ID_METER) levelArray[index++] = Napi::String::New(env, "ID_METER"); - if (levels & RIG_LEVEL_TEMP_METER) levelArray[index++] = Napi::String::New(env, "TEMP_METER"); + if (levels & SHIM_RIG_LEVEL_AF) levelArray[index++] = Napi::String::New(env, "AF"); + if (levels & SHIM_RIG_LEVEL_RF) levelArray[index++] = Napi::String::New(env, "RF"); + if (levels & SHIM_RIG_LEVEL_SQL) levelArray[index++] = Napi::String::New(env, "SQL"); + if (levels & SHIM_RIG_LEVEL_RFPOWER) levelArray[index++] = Napi::String::New(env, "RFPOWER"); + if (levels & SHIM_RIG_LEVEL_MICGAIN) levelArray[index++] = Napi::String::New(env, "MICGAIN"); + if (levels & SHIM_RIG_LEVEL_IF) levelArray[index++] = Napi::String::New(env, "IF"); + if (levels & SHIM_RIG_LEVEL_APF) levelArray[index++] = Napi::String::New(env, "APF"); + if (levels & SHIM_RIG_LEVEL_NR) levelArray[index++] = Napi::String::New(env, "NR"); + if (levels & SHIM_RIG_LEVEL_PBT_IN) levelArray[index++] = Napi::String::New(env, "PBT_IN"); + if (levels & SHIM_RIG_LEVEL_PBT_OUT) levelArray[index++] = Napi::String::New(env, "PBT_OUT"); + if (levels & SHIM_RIG_LEVEL_CWPITCH) levelArray[index++] = Napi::String::New(env, "CWPITCH"); + if (levels & SHIM_RIG_LEVEL_KEYSPD) levelArray[index++] = Napi::String::New(env, "KEYSPD"); + if (levels & SHIM_RIG_LEVEL_NOTCHF) levelArray[index++] = Napi::String::New(env, "NOTCHF"); + if (levels & SHIM_RIG_LEVEL_COMP) levelArray[index++] = Napi::String::New(env, "COMP"); + if (levels & SHIM_RIG_LEVEL_AGC) levelArray[index++] = Napi::String::New(env, "AGC"); + if (levels & SHIM_RIG_LEVEL_BKINDL) levelArray[index++] = Napi::String::New(env, "BKINDL"); + if (levels & SHIM_RIG_LEVEL_BALANCE) levelArray[index++] = Napi::String::New(env, "BALANCE"); + if (levels & SHIM_RIG_LEVEL_VOXGAIN) levelArray[index++] = Napi::String::New(env, "VOXGAIN"); + if (levels & SHIM_RIG_LEVEL_VOXDELAY) levelArray[index++] = Napi::String::New(env, "VOXDELAY"); + if (levels & SHIM_RIG_LEVEL_ANTIVOX) levelArray[index++] = Napi::String::New(env, "ANTIVOX"); + if (levels & SHIM_RIG_LEVEL_STRENGTH) levelArray[index++] = Napi::String::New(env, "STRENGTH"); + if (levels & SHIM_RIG_LEVEL_RAWSTR) levelArray[index++] = Napi::String::New(env, "RAWSTR"); + if (levels & SHIM_RIG_LEVEL_SWR) levelArray[index++] = Napi::String::New(env, "SWR"); + if (levels & SHIM_RIG_LEVEL_ALC) levelArray[index++] = Napi::String::New(env, "ALC"); + if (levels & SHIM_RIG_LEVEL_RFPOWER_METER) levelArray[index++] = Napi::String::New(env, "RFPOWER_METER"); + if (levels & SHIM_RIG_LEVEL_COMP_METER) levelArray[index++] = Napi::String::New(env, "COMP_METER"); + if (levels & SHIM_RIG_LEVEL_VD_METER) levelArray[index++] = Napi::String::New(env, "VD_METER"); + if (levels & SHIM_RIG_LEVEL_ID_METER) levelArray[index++] = Napi::String::New(env, "ID_METER"); + if (levels & SHIM_RIG_LEVEL_TEMP_METER) levelArray[index++] = Napi::String::New(env, "TEMP_METER"); return levelArray; } @@ -3052,63 +3037,63 @@ Napi::Value NodeHamLib::SetFunction(const Napi::CallbackInfo & info) { bool enable = info[1].As().Value(); // Map function type strings to hamlib constants - setting_t funcType; + uint64_t funcType; if (funcTypeStr == "FAGC") { - funcType = RIG_FUNC_FAGC; + funcType = SHIM_RIG_FUNC_FAGC; } else if (funcTypeStr == "NB") { - funcType = RIG_FUNC_NB; + funcType = SHIM_RIG_FUNC_NB; } else if (funcTypeStr == "COMP") { - funcType = RIG_FUNC_COMP; + funcType = SHIM_RIG_FUNC_COMP; } else if (funcTypeStr == "VOX") { - funcType = RIG_FUNC_VOX; + funcType = SHIM_RIG_FUNC_VOX; } else if (funcTypeStr == "TONE") { - funcType = RIG_FUNC_TONE; + funcType = SHIM_RIG_FUNC_TONE; } else if (funcTypeStr == "TSQL") { - funcType = RIG_FUNC_TSQL; + funcType = SHIM_RIG_FUNC_TSQL; } else if (funcTypeStr == "SBKIN") { - funcType = RIG_FUNC_SBKIN; + funcType = SHIM_RIG_FUNC_SBKIN; } else if (funcTypeStr == "FBKIN") { - funcType = RIG_FUNC_FBKIN; + funcType = SHIM_RIG_FUNC_FBKIN; } else if (funcTypeStr == "ANF") { - funcType = RIG_FUNC_ANF; + funcType = SHIM_RIG_FUNC_ANF; } else if (funcTypeStr == "NR") { - funcType = RIG_FUNC_NR; + funcType = SHIM_RIG_FUNC_NR; } else if (funcTypeStr == "AIP") { - funcType = RIG_FUNC_AIP; + funcType = SHIM_RIG_FUNC_AIP; } else if (funcTypeStr == "APF") { - funcType = RIG_FUNC_APF; + funcType = SHIM_RIG_FUNC_APF; } else if (funcTypeStr == "TUNER") { - funcType = RIG_FUNC_TUNER; + funcType = SHIM_RIG_FUNC_TUNER; } else if (funcTypeStr == "XIT") { - funcType = RIG_FUNC_XIT; + funcType = SHIM_RIG_FUNC_XIT; } else if (funcTypeStr == "RIT") { - funcType = RIG_FUNC_RIT; + funcType = SHIM_RIG_FUNC_RIT; } else if (funcTypeStr == "LOCK") { - funcType = RIG_FUNC_LOCK; + funcType = SHIM_RIG_FUNC_LOCK; } else if (funcTypeStr == "MUTE") { - funcType = RIG_FUNC_MUTE; + funcType = SHIM_RIG_FUNC_MUTE; } else if (funcTypeStr == "VSC") { - funcType = RIG_FUNC_VSC; + funcType = SHIM_RIG_FUNC_VSC; } else if (funcTypeStr == "REV") { - funcType = RIG_FUNC_REV; + funcType = SHIM_RIG_FUNC_REV; } else if (funcTypeStr == "SQL") { - funcType = RIG_FUNC_SQL; + funcType = SHIM_RIG_FUNC_SQL; } else if (funcTypeStr == "ABM") { - funcType = RIG_FUNC_ABM; + funcType = SHIM_RIG_FUNC_ABM; } else if (funcTypeStr == "BC") { - funcType = RIG_FUNC_BC; + funcType = SHIM_RIG_FUNC_BC; } else if (funcTypeStr == "MBC") { - funcType = RIG_FUNC_MBC; + funcType = SHIM_RIG_FUNC_MBC; } else if (funcTypeStr == "AFC") { - funcType = RIG_FUNC_AFC; + funcType = SHIM_RIG_FUNC_AFC; } else if (funcTypeStr == "SATMODE") { - funcType = RIG_FUNC_SATMODE; + funcType = SHIM_RIG_FUNC_SATMODE; } else if (funcTypeStr == "SCOPE") { - funcType = RIG_FUNC_SCOPE; + funcType = SHIM_RIG_FUNC_SCOPE; } else if (funcTypeStr == "RESUME") { - funcType = RIG_FUNC_RESUME; + funcType = SHIM_RIG_FUNC_RESUME; } else if (funcTypeStr == "TBURST") { - funcType = RIG_FUNC_TBURST; + funcType = SHIM_RIG_FUNC_TBURST; } else { Napi::TypeError::New(env, "Invalid function type").ThrowAsJavaScriptException(); return env.Null(); @@ -3136,63 +3121,63 @@ Napi::Value NodeHamLib::GetFunction(const Napi::CallbackInfo & info) { std::string funcTypeStr = info[0].As().Utf8Value(); // Map function type strings to hamlib constants (same as SetFunction) - setting_t funcType; + uint64_t funcType; if (funcTypeStr == "FAGC") { - funcType = RIG_FUNC_FAGC; + funcType = SHIM_RIG_FUNC_FAGC; } else if (funcTypeStr == "NB") { - funcType = RIG_FUNC_NB; + funcType = SHIM_RIG_FUNC_NB; } else if (funcTypeStr == "COMP") { - funcType = RIG_FUNC_COMP; + funcType = SHIM_RIG_FUNC_COMP; } else if (funcTypeStr == "VOX") { - funcType = RIG_FUNC_VOX; + funcType = SHIM_RIG_FUNC_VOX; } else if (funcTypeStr == "TONE") { - funcType = RIG_FUNC_TONE; + funcType = SHIM_RIG_FUNC_TONE; } else if (funcTypeStr == "TSQL") { - funcType = RIG_FUNC_TSQL; + funcType = SHIM_RIG_FUNC_TSQL; } else if (funcTypeStr == "SBKIN") { - funcType = RIG_FUNC_SBKIN; + funcType = SHIM_RIG_FUNC_SBKIN; } else if (funcTypeStr == "FBKIN") { - funcType = RIG_FUNC_FBKIN; + funcType = SHIM_RIG_FUNC_FBKIN; } else if (funcTypeStr == "ANF") { - funcType = RIG_FUNC_ANF; + funcType = SHIM_RIG_FUNC_ANF; } else if (funcTypeStr == "NR") { - funcType = RIG_FUNC_NR; + funcType = SHIM_RIG_FUNC_NR; } else if (funcTypeStr == "AIP") { - funcType = RIG_FUNC_AIP; + funcType = SHIM_RIG_FUNC_AIP; } else if (funcTypeStr == "APF") { - funcType = RIG_FUNC_APF; + funcType = SHIM_RIG_FUNC_APF; } else if (funcTypeStr == "TUNER") { - funcType = RIG_FUNC_TUNER; + funcType = SHIM_RIG_FUNC_TUNER; } else if (funcTypeStr == "XIT") { - funcType = RIG_FUNC_XIT; + funcType = SHIM_RIG_FUNC_XIT; } else if (funcTypeStr == "RIT") { - funcType = RIG_FUNC_RIT; + funcType = SHIM_RIG_FUNC_RIT; } else if (funcTypeStr == "LOCK") { - funcType = RIG_FUNC_LOCK; + funcType = SHIM_RIG_FUNC_LOCK; } else if (funcTypeStr == "MUTE") { - funcType = RIG_FUNC_MUTE; + funcType = SHIM_RIG_FUNC_MUTE; } else if (funcTypeStr == "VSC") { - funcType = RIG_FUNC_VSC; + funcType = SHIM_RIG_FUNC_VSC; } else if (funcTypeStr == "REV") { - funcType = RIG_FUNC_REV; + funcType = SHIM_RIG_FUNC_REV; } else if (funcTypeStr == "SQL") { - funcType = RIG_FUNC_SQL; + funcType = SHIM_RIG_FUNC_SQL; } else if (funcTypeStr == "ABM") { - funcType = RIG_FUNC_ABM; + funcType = SHIM_RIG_FUNC_ABM; } else if (funcTypeStr == "BC") { - funcType = RIG_FUNC_BC; + funcType = SHIM_RIG_FUNC_BC; } else if (funcTypeStr == "MBC") { - funcType = RIG_FUNC_MBC; + funcType = SHIM_RIG_FUNC_MBC; } else if (funcTypeStr == "AFC") { - funcType = RIG_FUNC_AFC; + funcType = SHIM_RIG_FUNC_AFC; } else if (funcTypeStr == "SATMODE") { - funcType = RIG_FUNC_SATMODE; + funcType = SHIM_RIG_FUNC_SATMODE; } else if (funcTypeStr == "SCOPE") { - funcType = RIG_FUNC_SCOPE; + funcType = SHIM_RIG_FUNC_SCOPE; } else if (funcTypeStr == "RESUME") { - funcType = RIG_FUNC_RESUME; + funcType = SHIM_RIG_FUNC_RESUME; } else if (funcTypeStr == "TBURST") { - funcType = RIG_FUNC_TBURST; + funcType = SHIM_RIG_FUNC_TBURST; } else { Napi::TypeError::New(env, "Invalid function type").ThrowAsJavaScriptException(); return env.Null(); @@ -3208,39 +3193,39 @@ Napi::Value NodeHamLib::GetSupportedFunctions(const Napi::CallbackInfo & info) { Napi::Env env = info.Env(); // Get capabilities from rig caps instead of state (doesn't require rig to be open) - setting_t functions = my_rig->caps->has_get_func | my_rig->caps->has_set_func; + uint64_t functions = shim_rig_get_caps_has_get_func(my_rig) | shim_rig_get_caps_has_set_func(my_rig); Napi::Array funcArray = Napi::Array::New(env); uint32_t index = 0; // Check each function type - if (functions & RIG_FUNC_FAGC) funcArray[index++] = Napi::String::New(env, "FAGC"); - if (functions & RIG_FUNC_NB) funcArray[index++] = Napi::String::New(env, "NB"); - if (functions & RIG_FUNC_COMP) funcArray[index++] = Napi::String::New(env, "COMP"); - if (functions & RIG_FUNC_VOX) funcArray[index++] = Napi::String::New(env, "VOX"); - if (functions & RIG_FUNC_TONE) funcArray[index++] = Napi::String::New(env, "TONE"); - if (functions & RIG_FUNC_TSQL) funcArray[index++] = Napi::String::New(env, "TSQL"); - if (functions & RIG_FUNC_SBKIN) funcArray[index++] = Napi::String::New(env, "SBKIN"); - if (functions & RIG_FUNC_FBKIN) funcArray[index++] = Napi::String::New(env, "FBKIN"); - if (functions & RIG_FUNC_ANF) funcArray[index++] = Napi::String::New(env, "ANF"); - if (functions & RIG_FUNC_NR) funcArray[index++] = Napi::String::New(env, "NR"); - if (functions & RIG_FUNC_AIP) funcArray[index++] = Napi::String::New(env, "AIP"); - if (functions & RIG_FUNC_APF) funcArray[index++] = Napi::String::New(env, "APF"); - if (functions & RIG_FUNC_TUNER) funcArray[index++] = Napi::String::New(env, "TUNER"); - if (functions & RIG_FUNC_XIT) funcArray[index++] = Napi::String::New(env, "XIT"); - if (functions & RIG_FUNC_RIT) funcArray[index++] = Napi::String::New(env, "RIT"); - if (functions & RIG_FUNC_LOCK) funcArray[index++] = Napi::String::New(env, "LOCK"); - if (functions & RIG_FUNC_MUTE) funcArray[index++] = Napi::String::New(env, "MUTE"); - if (functions & RIG_FUNC_VSC) funcArray[index++] = Napi::String::New(env, "VSC"); - if (functions & RIG_FUNC_REV) funcArray[index++] = Napi::String::New(env, "REV"); - if (functions & RIG_FUNC_SQL) funcArray[index++] = Napi::String::New(env, "SQL"); - if (functions & RIG_FUNC_ABM) funcArray[index++] = Napi::String::New(env, "ABM"); - if (functions & RIG_FUNC_BC) funcArray[index++] = Napi::String::New(env, "BC"); - if (functions & RIG_FUNC_MBC) funcArray[index++] = Napi::String::New(env, "MBC"); - if (functions & RIG_FUNC_AFC) funcArray[index++] = Napi::String::New(env, "AFC"); - if (functions & RIG_FUNC_SATMODE) funcArray[index++] = Napi::String::New(env, "SATMODE"); - if (functions & RIG_FUNC_SCOPE) funcArray[index++] = Napi::String::New(env, "SCOPE"); - if (functions & RIG_FUNC_RESUME) funcArray[index++] = Napi::String::New(env, "RESUME"); - if (functions & RIG_FUNC_TBURST) funcArray[index++] = Napi::String::New(env, "TBURST"); + if (functions & SHIM_RIG_FUNC_FAGC) funcArray[index++] = Napi::String::New(env, "FAGC"); + if (functions & SHIM_RIG_FUNC_NB) funcArray[index++] = Napi::String::New(env, "NB"); + if (functions & SHIM_RIG_FUNC_COMP) funcArray[index++] = Napi::String::New(env, "COMP"); + if (functions & SHIM_RIG_FUNC_VOX) funcArray[index++] = Napi::String::New(env, "VOX"); + if (functions & SHIM_RIG_FUNC_TONE) funcArray[index++] = Napi::String::New(env, "TONE"); + if (functions & SHIM_RIG_FUNC_TSQL) funcArray[index++] = Napi::String::New(env, "TSQL"); + if (functions & SHIM_RIG_FUNC_SBKIN) funcArray[index++] = Napi::String::New(env, "SBKIN"); + if (functions & SHIM_RIG_FUNC_FBKIN) funcArray[index++] = Napi::String::New(env, "FBKIN"); + if (functions & SHIM_RIG_FUNC_ANF) funcArray[index++] = Napi::String::New(env, "ANF"); + if (functions & SHIM_RIG_FUNC_NR) funcArray[index++] = Napi::String::New(env, "NR"); + if (functions & SHIM_RIG_FUNC_AIP) funcArray[index++] = Napi::String::New(env, "AIP"); + if (functions & SHIM_RIG_FUNC_APF) funcArray[index++] = Napi::String::New(env, "APF"); + if (functions & SHIM_RIG_FUNC_TUNER) funcArray[index++] = Napi::String::New(env, "TUNER"); + if (functions & SHIM_RIG_FUNC_XIT) funcArray[index++] = Napi::String::New(env, "XIT"); + if (functions & SHIM_RIG_FUNC_RIT) funcArray[index++] = Napi::String::New(env, "RIT"); + if (functions & SHIM_RIG_FUNC_LOCK) funcArray[index++] = Napi::String::New(env, "LOCK"); + if (functions & SHIM_RIG_FUNC_MUTE) funcArray[index++] = Napi::String::New(env, "MUTE"); + if (functions & SHIM_RIG_FUNC_VSC) funcArray[index++] = Napi::String::New(env, "VSC"); + if (functions & SHIM_RIG_FUNC_REV) funcArray[index++] = Napi::String::New(env, "REV"); + if (functions & SHIM_RIG_FUNC_SQL) funcArray[index++] = Napi::String::New(env, "SQL"); + if (functions & SHIM_RIG_FUNC_ABM) funcArray[index++] = Napi::String::New(env, "ABM"); + if (functions & SHIM_RIG_FUNC_BC) funcArray[index++] = Napi::String::New(env, "BC"); + if (functions & SHIM_RIG_FUNC_MBC) funcArray[index++] = Napi::String::New(env, "MBC"); + if (functions & SHIM_RIG_FUNC_AFC) funcArray[index++] = Napi::String::New(env, "AFC"); + if (functions & SHIM_RIG_FUNC_SATMODE) funcArray[index++] = Napi::String::New(env, "SATMODE"); + if (functions & SHIM_RIG_FUNC_SCOPE) funcArray[index++] = Napi::String::New(env, "SCOPE"); + if (functions & SHIM_RIG_FUNC_RESUME) funcArray[index++] = Napi::String::New(env, "RESUME"); + if (functions & SHIM_RIG_FUNC_TBURST) funcArray[index++] = Napi::String::New(env, "TBURST"); return funcArray; } @@ -3250,16 +3235,16 @@ Napi::Value NodeHamLib::GetSupportedModes(const Napi::CallbackInfo & info) { Napi::Env env = info.Env(); // Get mode list from rig state (populated during rig_open from rx/tx range lists) - rmode_t modes = my_rig->state.mode_list; + uint64_t modes = shim_rig_get_mode_list(my_rig); Napi::Array modeArray = Napi::Array::New(env); uint32_t index = 0; // Iterate through all possible mode bits (similar to rig_sprintf_mode) - for (unsigned int i = 0; i < HAMLIB_MAX_MODES; i++) { - rmode_t mode_bit = modes & (1ULL << i); + for (unsigned int i = 0; i < SHIM_HAMLIB_MAX_MODES; i++) { + uint64_t mode_bit = modes & (1ULL << i); if (mode_bit) { - const char* mode_str = rig_strrmode(mode_bit); + const char* mode_str = shim_rig_strrmode(mode_bit); // Skip empty or unknown modes if (mode_str && mode_str[0] != '\0') { @@ -3285,7 +3270,7 @@ Napi::Value NodeHamLib::SetSplitFreq(const Napi::CallbackInfo & info) { return env.Null(); } - freq_t tx_freq = info[0].As().DoubleValue(); + double tx_freq = info[0].As().DoubleValue(); // Basic frequency range validation if (tx_freq < 1000 || tx_freq > 10000000000) { // 1 kHz to 10 GHz reasonable range @@ -3293,11 +3278,11 @@ Napi::Value NodeHamLib::SetSplitFreq(const Napi::CallbackInfo & info) { return env.Null(); } - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 2 && info[1].IsString()) { // setSplitFreq(freq, vfo) - vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); } SetSplitFreqAsyncWorker* asyncWorker = new SetSplitFreqAsyncWorker(env, this, tx_freq, vfo); @@ -3313,13 +3298,13 @@ Napi::Value NodeHamLib::GetSplitFreq(const Napi::CallbackInfo & info) { return env.Null(); } - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 1 && info[0].IsString()) { // getSplitFreq(vfo) - vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); } - // Otherwise use default RIG_VFO_CURR for getSplitFreq() + // Otherwise use default SHIM_RIG_VFO_CURR for getSplitFreq() GetSplitFreqAsyncWorker* asyncWorker = new GetSplitFreqAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -3340,21 +3325,21 @@ Napi::Value NodeHamLib::SetSplitMode(const Napi::CallbackInfo & info) { } std::string modeStr = info[0].As().Utf8Value(); - rmode_t tx_mode = rig_parse_mode(modeStr.c_str()); + int tx_mode = shim_rig_parse_mode(modeStr.c_str()); - if (tx_mode == RIG_MODE_NONE) { + if (tx_mode == SHIM_RIG_MODE_NONE) { Napi::Error::New(env, "Invalid mode: " + modeStr).ThrowAsJavaScriptException(); return env.Null(); } - pbwidth_t tx_width = RIG_PASSBAND_NORMAL; - vfo_t vfo = RIG_VFO_CURR; + int tx_width = SHIM_RIG_PASSBAND_NORMAL; + int vfo = SHIM_RIG_VFO_CURR; // Parse parameters: setSplitMode(mode) | setSplitMode(mode, vfo) | setSplitMode(mode, width) | setSplitMode(mode, width, vfo) if (info.Length() == 2) { if (info[1].IsString()) { // setSplitMode(mode, vfo) - vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); } else if (info[1].IsNumber()) { // setSplitMode(mode, width) tx_width = info[1].As().Int32Value(); @@ -3362,7 +3347,7 @@ Napi::Value NodeHamLib::SetSplitMode(const Napi::CallbackInfo & info) { } else if (info.Length() == 3 && info[1].IsNumber() && info[2].IsString()) { // setSplitMode(mode, width, vfo) tx_width = info[1].As().Int32Value(); - vfo = parseVfoParameter(info, 2, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 2, SHIM_RIG_VFO_CURR); } SetSplitModeAsyncWorker* asyncWorker = new SetSplitModeAsyncWorker(env, this, tx_mode, tx_width, vfo); @@ -3378,13 +3363,13 @@ Napi::Value NodeHamLib::GetSplitMode(const Napi::CallbackInfo & info) { return env.Null(); } - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 1 && info[0].IsString()) { // getSplitMode(vfo) - vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); } - // Otherwise use default RIG_VFO_CURR for getSplitMode() + // Otherwise use default SHIM_RIG_VFO_CURR for getSplitMode() GetSplitModeAsyncWorker* asyncWorker = new GetSplitModeAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -3405,11 +3390,11 @@ Napi::Value NodeHamLib::SetSplit(const Napi::CallbackInfo & info) { } bool split_enabled = info[0].As().Value(); - split_t split = split_enabled ? RIG_SPLIT_ON : RIG_SPLIT_OFF; + int split = split_enabled ? SHIM_RIG_SPLIT_ON : SHIM_RIG_SPLIT_OFF; // Default values - vfo_t rx_vfo = RIG_VFO_CURR; - vfo_t tx_vfo = RIG_VFO_B; // Default TX VFO + int rx_vfo = SHIM_RIG_VFO_CURR; + int tx_vfo = SHIM_RIG_VFO_B; // Default TX VFO // ⚠️ CRITICAL HISTORICAL ISSUE WARNING ⚠️ // This Split API had a severe parameter order bug that caused AI to repeatedly @@ -3430,9 +3415,9 @@ Napi::Value NodeHamLib::SetSplit(const Napi::CallbackInfo & info) { // setSplit(enable, rxVfo) - treating vfo as RX VFO for current VFO operation std::string vfoStr = info[1].As().Utf8Value(); if (vfoStr == "VFO-A") { - rx_vfo = RIG_VFO_A; + rx_vfo = SHIM_RIG_VFO_A; } else if (vfoStr == "VFO-B") { - rx_vfo = RIG_VFO_B; + rx_vfo = SHIM_RIG_VFO_B; } } else if (info.Length() == 3 && info[1].IsString() && info[2].IsString()) { // setSplit(enable, rxVfo, txVfo) @@ -3443,15 +3428,15 @@ Napi::Value NodeHamLib::SetSplit(const Napi::CallbackInfo & info) { std::string txVfoStr = info[2].As().Utf8Value(); // ✅ CORRECT: info[2] is txVfo if (rxVfoStr == "VFO-A") { - rx_vfo = RIG_VFO_A; + rx_vfo = SHIM_RIG_VFO_A; } else if (rxVfoStr == "VFO-B") { - rx_vfo = RIG_VFO_B; + rx_vfo = SHIM_RIG_VFO_B; } if (txVfoStr == "VFO-A") { - tx_vfo = RIG_VFO_A; + tx_vfo = SHIM_RIG_VFO_A; } else if (txVfoStr == "VFO-B") { - tx_vfo = RIG_VFO_B; + tx_vfo = SHIM_RIG_VFO_B; } } @@ -3468,13 +3453,13 @@ Napi::Value NodeHamLib::GetSplit(const Napi::CallbackInfo & info) { return env.Null(); } - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 1 && info[0].IsString()) { // getSplit(vfo) - vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); } - // Otherwise use default RIG_VFO_CURR for getSplit() + // Otherwise use default SHIM_RIG_VFO_CURR for getSplit() GetSplitAsyncWorker* asyncWorker = new GetSplitAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -3497,33 +3482,33 @@ Napi::Value NodeHamLib::VfoOperation(const Napi::CallbackInfo & info) { std::string vfoOpStr = info[0].As().Utf8Value(); - vfo_op_t vfo_op; + int vfo_op; if (vfoOpStr == "CPY") { - vfo_op = RIG_OP_CPY; + vfo_op = SHIM_RIG_OP_CPY; } else if (vfoOpStr == "XCHG") { - vfo_op = RIG_OP_XCHG; + vfo_op = SHIM_RIG_OP_XCHG; } else if (vfoOpStr == "FROM_VFO") { - vfo_op = RIG_OP_FROM_VFO; + vfo_op = SHIM_RIG_OP_FROM_VFO; } else if (vfoOpStr == "TO_VFO") { - vfo_op = RIG_OP_TO_VFO; + vfo_op = SHIM_RIG_OP_TO_VFO; } else if (vfoOpStr == "MCL") { - vfo_op = RIG_OP_MCL; + vfo_op = SHIM_RIG_OP_MCL; } else if (vfoOpStr == "UP") { - vfo_op = RIG_OP_UP; + vfo_op = SHIM_RIG_OP_UP; } else if (vfoOpStr == "DOWN") { - vfo_op = RIG_OP_DOWN; + vfo_op = SHIM_RIG_OP_DOWN; } else if (vfoOpStr == "BAND_UP") { - vfo_op = RIG_OP_BAND_UP; + vfo_op = SHIM_RIG_OP_BAND_UP; } else if (vfoOpStr == "BAND_DOWN") { - vfo_op = RIG_OP_BAND_DOWN; + vfo_op = SHIM_RIG_OP_BAND_DOWN; } else if (vfoOpStr == "LEFT") { - vfo_op = RIG_OP_LEFT; + vfo_op = SHIM_RIG_OP_LEFT; } else if (vfoOpStr == "RIGHT") { - vfo_op = RIG_OP_RIGHT; + vfo_op = SHIM_RIG_OP_RIGHT; } else if (vfoOpStr == "TUNE") { - vfo_op = RIG_OP_TUNE; + vfo_op = SHIM_RIG_OP_TUNE; } else if (vfoOpStr == "TOGGLE") { - vfo_op = RIG_OP_TOGGLE; + vfo_op = SHIM_RIG_OP_TOGGLE; } else { Napi::TypeError::New(env, "Invalid VFO operation").ThrowAsJavaScriptException(); return env.Null(); @@ -3548,17 +3533,17 @@ Napi::Value NodeHamLib::SetAntenna(const Napi::CallbackInfo & info) { return env.Null(); } - ant_t antenna = info[0].As().Int32Value(); + int antenna = info[0].As().Int32Value(); // Support optional VFO parameter: setAntenna(antenna) or setAntenna(antenna, vfo) - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 2 && info[1].IsString()) { - vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); } // Default option value (can be extended later if needed) - value_t option = {0}; - + float option = 0.0f; + SetAntennaAsyncWorker* asyncWorker = new SetAntennaAsyncWorker(env, this, antenna, vfo, option); asyncWorker->Queue(); return asyncWorker->GetPromise(); @@ -3573,13 +3558,13 @@ Napi::Value NodeHamLib::GetAntenna(const Napi::CallbackInfo & info) { } // Support optional VFO parameter: getAntenna() or getAntenna(vfo) - vfo_t vfo = RIG_VFO_CURR; + int vfo = SHIM_RIG_VFO_CURR; if (info.Length() >= 1 && info[0].IsString()) { - vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); } - // Default antenna query (RIG_ANT_CURR gets all antenna info) - ant_t antenna = RIG_ANT_CURR; + // Default antenna query (SHIM_RIG_ANT_CURR gets all antenna info) + int antenna = SHIM_RIG_ANT_CURR; GetAntennaAsyncWorker* asyncWorker = new GetAntennaAsyncWorker(env, this, vfo, antenna); asyncWorker->Queue(); @@ -3750,60 +3735,31 @@ bool NodeHamLib::isNetworkAddress(const char* path) { } // Static callback function for rig_list_foreach -int NodeHamLib::rig_list_callback(const struct rig_caps *caps, void *data) { +int NodeHamLib::rig_list_callback(const shim_rig_info_t *info, void *data) { RigListData *rig_data = static_cast(data); - + // Create rig info object Napi::Object rigInfo = Napi::Object::New(rig_data->env); - rigInfo.Set(Napi::String::New(rig_data->env, "rigModel"), - Napi::Number::New(rig_data->env, caps->rig_model)); - rigInfo.Set(Napi::String::New(rig_data->env, "modelName"), - Napi::String::New(rig_data->env, caps->model_name ? caps->model_name : "")); - rigInfo.Set(Napi::String::New(rig_data->env, "mfgName"), - Napi::String::New(rig_data->env, caps->mfg_name ? caps->mfg_name : "")); - rigInfo.Set(Napi::String::New(rig_data->env, "version"), - Napi::String::New(rig_data->env, caps->version ? caps->version : "")); - rigInfo.Set(Napi::String::New(rig_data->env, "status"), - Napi::String::New(rig_data->env, rig_strstatus(caps->status))); - - // Determine rig type string - const char* rigType = "Unknown"; - switch (caps->rig_type & RIG_TYPE_MASK) { - case RIG_TYPE_TRANSCEIVER: - rigType = "Transceiver"; - break; - case RIG_TYPE_HANDHELD: - rigType = "Handheld"; - break; - case RIG_TYPE_MOBILE: - rigType = "Mobile"; - break; - case RIG_TYPE_RECEIVER: - rigType = "Receiver"; - break; - case RIG_TYPE_PCRECEIVER: - rigType = "PC Receiver"; - break; - case RIG_TYPE_SCANNER: - rigType = "Scanner"; - break; - case RIG_TYPE_TRUNKSCANNER: - rigType = "Trunk Scanner"; - break; - case RIG_TYPE_COMPUTER: - rigType = "Computer"; - break; - case RIG_TYPE_OTHER: - rigType = "Other"; - break; - } - - rigInfo.Set(Napi::String::New(rig_data->env, "rigType"), + rigInfo.Set(Napi::String::New(rig_data->env, "rigModel"), + Napi::Number::New(rig_data->env, info->rig_model)); + rigInfo.Set(Napi::String::New(rig_data->env, "modelName"), + Napi::String::New(rig_data->env, info->model_name ? info->model_name : "")); + rigInfo.Set(Napi::String::New(rig_data->env, "mfgName"), + Napi::String::New(rig_data->env, info->mfg_name ? info->mfg_name : "")); + rigInfo.Set(Napi::String::New(rig_data->env, "version"), + Napi::String::New(rig_data->env, info->version ? info->version : "")); + rigInfo.Set(Napi::String::New(rig_data->env, "status"), + Napi::String::New(rig_data->env, shim_rig_strstatus(info->status))); + + // Determine rig type string using shim helper + const char* rigType = shim_rig_type_str(info->rig_type); + + rigInfo.Set(Napi::String::New(rig_data->env, "rigType"), Napi::String::New(rig_data->env, rigType)); - + // Add to list rig_data->rigList.push_back(rigInfo); - + return 1; // Continue iteration (returning 0 would stop) } @@ -3812,15 +3768,15 @@ Napi::Value NodeHamLib::GetSupportedRigs(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); // Load all backends to ensure we get the complete list - rig_load_all_backends(); + shim_rig_load_all_backends(); // Prepare data structure for callback with proper initialization RigListData rigData{std::vector(), env}; // Call hamlib function to iterate through all supported rigs - int result = rig_list_foreach(rig_list_callback, &rigData); + int result = shim_rig_list_foreach(rig_list_callback, &rigData); - if (result != RIG_OK) { + if (result != SHIM_RIG_OK) { Napi::Error::New(env, "Failed to retrieve supported rig list").ThrowAsJavaScriptException(); return env.Null(); } @@ -3838,10 +3794,7 @@ Napi::Value NodeHamLib::GetSupportedRigs(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetHamlibVersion(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - // Reference to external hamlib_version2 variable - extern const char* hamlib_version2; - - return Napi::String::New(env, hamlib_version2); + return Napi::String::New(env, shim_rig_get_version()); } // Set Hamlib debug level @@ -3862,7 +3815,7 @@ Napi::Value NodeHamLib::SetDebugLevel(const Napi::CallbackInfo& info) { return env.Undefined(); } - rig_set_debug((enum rig_debug_level_e)level); + shim_rig_set_debug(level); return env.Undefined(); } @@ -4027,7 +3980,7 @@ Napi::Value NodeHamLib::GetSupportedSerialConfigs(const Napi::CallbackInfo& info pttTypeOptions[5u] = Napi::String::New(env, "GPIO"); pttTypeOptions[6u] = Napi::String::New(env, "GPION"); pttTypeOptions[7u] = Napi::String::New(env, "NONE"); - configs.Set("ptt_type", pttTypeOptions); + configs.Set("intype", pttTypeOptions); // DCD type options Napi::Array dcdTypeOptions = Napi::Array::New(env, 9); @@ -4040,7 +3993,7 @@ Napi::Value NodeHamLib::GetSupportedSerialConfigs(const Napi::CallbackInfo& info dcdTypeOptions[6u] = Napi::String::New(env, "GPIO"); dcdTypeOptions[7u] = Napi::String::New(env, "GPION"); dcdTypeOptions[8u] = Napi::String::New(env, "NONE"); - configs.Set("dcd_type", dcdTypeOptions); + configs.Set("intype", dcdTypeOptions); return configs; } @@ -4055,7 +4008,7 @@ Napi::Value NodeHamLib::SetPowerstat(const Napi::CallbackInfo& info) { } int powerStatus = info[0].As().Int32Value(); - powerstat_t status = static_cast(powerStatus); + int status = static_cast(powerStatus); SetPowerstatAsyncWorker* asyncWorker = new SetPowerstatAsyncWorker(env, this, status); asyncWorker->Queue(); @@ -4074,7 +4027,7 @@ Napi::Value NodeHamLib::GetPowerstat(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetPtt(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetPttAsyncWorker* asyncWorker = new GetPttAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -4085,7 +4038,7 @@ Napi::Value NodeHamLib::GetPtt(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetDcd(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetDcdAsyncWorker* asyncWorker = new GetDcdAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -4101,8 +4054,8 @@ Napi::Value NodeHamLib::SetTuningStep(const Napi::CallbackInfo& info) { return env.Null(); } - shortfreq_t ts = info[0].As().Int32Value(); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int ts = info[0].As().Int32Value(); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetTuningStepAsyncWorker* asyncWorker = new SetTuningStepAsyncWorker(env, this, vfo, ts); asyncWorker->Queue(); @@ -4112,7 +4065,7 @@ Napi::Value NodeHamLib::SetTuningStep(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetTuningStep(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetTuningStepAsyncWorker* asyncWorker = new GetTuningStepAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -4129,20 +4082,20 @@ Napi::Value NodeHamLib::SetRepeaterShift(const Napi::CallbackInfo& info) { } std::string shiftStr = info[0].As().Utf8Value(); - rptr_shift_t shift = RIG_RPT_SHIFT_NONE; + int shift = SHIM_RIG_RPT_SHIFT_NONE; if (shiftStr == "NONE" || shiftStr == "none") { - shift = RIG_RPT_SHIFT_NONE; + shift = SHIM_RIG_RPT_SHIFT_NONE; } else if (shiftStr == "MINUS" || shiftStr == "minus" || shiftStr == "-") { - shift = RIG_RPT_SHIFT_MINUS; + shift = SHIM_RIG_RPT_SHIFT_MINUS; } else if (shiftStr == "PLUS" || shiftStr == "plus" || shiftStr == "+") { - shift = RIG_RPT_SHIFT_PLUS; + shift = SHIM_RIG_RPT_SHIFT_PLUS; } else { Napi::TypeError::New(env, "Invalid repeater shift (must be 'NONE', 'MINUS', or 'PLUS')").ThrowAsJavaScriptException(); return env.Null(); } - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetRepeaterShiftAsyncWorker* asyncWorker = new SetRepeaterShiftAsyncWorker(env, this, vfo, shift); asyncWorker->Queue(); @@ -4152,7 +4105,7 @@ Napi::Value NodeHamLib::SetRepeaterShift(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetRepeaterShift(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetRepeaterShiftAsyncWorker* asyncWorker = new GetRepeaterShiftAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -4167,8 +4120,8 @@ Napi::Value NodeHamLib::SetRepeaterOffset(const Napi::CallbackInfo& info) { return env.Null(); } - shortfreq_t offset = info[0].As().Int32Value(); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int offset = info[0].As().Int32Value(); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetRepeaterOffsetAsyncWorker* asyncWorker = new SetRepeaterOffsetAsyncWorker(env, this, vfo, offset); asyncWorker->Queue(); @@ -4178,7 +4131,7 @@ Napi::Value NodeHamLib::SetRepeaterOffset(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetRepeaterOffset(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetRepeaterOffsetAsyncWorker* asyncWorker = new GetRepeaterOffsetAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -4188,21 +4141,21 @@ Napi::Value NodeHamLib::GetRepeaterOffset(const Napi::CallbackInfo& info) { // CTCSS/DCS Tone Control AsyncWorker classes class SetCtcssToneAsyncWorker : public HamLibAsyncWorker { public: - SetCtcssToneAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, tone_t tone) + SetCtcssToneAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, unsigned int tone) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tone_(tone) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_ctcss_tone(hamlib_instance_->my_rig, vfo_, tone_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_ctcss_tone(hamlib_instance_->my_rig, vfo_, tone_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4215,27 +4168,27 @@ class SetCtcssToneAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t tone_; + int vfo_; + unsigned int tone_; }; class GetCtcssToneAsyncWorker : public HamLibAsyncWorker { public: - GetCtcssToneAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetCtcssToneAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tone_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_ctcss_tone(hamlib_instance_->my_rig, vfo_, &tone_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_ctcss_tone(hamlib_instance_->my_rig, vfo_, &tone_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, tone_)); @@ -4248,27 +4201,27 @@ class GetCtcssToneAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t tone_; + int vfo_; + unsigned int tone_; }; class SetDcsCodeAsyncWorker : public HamLibAsyncWorker { public: - SetDcsCodeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, tone_t code) + SetDcsCodeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, unsigned int code) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), code_(code) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_dcs_code(hamlib_instance_->my_rig, vfo_, code_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_dcs_code(hamlib_instance_->my_rig, vfo_, code_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4281,27 +4234,27 @@ class SetDcsCodeAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t code_; + int vfo_; + unsigned int code_; }; class GetDcsCodeAsyncWorker : public HamLibAsyncWorker { public: - GetDcsCodeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetDcsCodeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), code_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_dcs_code(hamlib_instance_->my_rig, vfo_, &code_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_dcs_code(hamlib_instance_->my_rig, vfo_, &code_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, code_)); @@ -4314,27 +4267,27 @@ class GetDcsCodeAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t code_; + int vfo_; + unsigned int code_; }; class SetCtcssSqlAsyncWorker : public HamLibAsyncWorker { public: - SetCtcssSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, tone_t tone) + SetCtcssSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, unsigned int tone) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tone_(tone) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_ctcss_sql(hamlib_instance_->my_rig, vfo_, tone_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_ctcss_sql(hamlib_instance_->my_rig, vfo_, tone_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4347,27 +4300,27 @@ class SetCtcssSqlAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t tone_; + int vfo_; + unsigned int tone_; }; class GetCtcssSqlAsyncWorker : public HamLibAsyncWorker { public: - GetCtcssSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetCtcssSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tone_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_ctcss_sql(hamlib_instance_->my_rig, vfo_, &tone_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_ctcss_sql(hamlib_instance_->my_rig, vfo_, &tone_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, tone_)); @@ -4380,27 +4333,27 @@ class GetCtcssSqlAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t tone_; + int vfo_; + unsigned int tone_; }; class SetDcsSqlAsyncWorker : public HamLibAsyncWorker { public: - SetDcsSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, tone_t code) + SetDcsSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, unsigned int code) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), code_(code) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_dcs_sql(hamlib_instance_->my_rig, vfo_, code_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_dcs_sql(hamlib_instance_->my_rig, vfo_, code_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4413,27 +4366,27 @@ class SetDcsSqlAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t code_; + int vfo_; + unsigned int code_; }; class GetDcsSqlAsyncWorker : public HamLibAsyncWorker { public: - GetDcsSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetDcsSqlAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), code_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_dcs_sql(hamlib_instance_->my_rig, vfo_, &code_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_dcs_sql(hamlib_instance_->my_rig, vfo_, &code_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, code_)); @@ -4446,97 +4399,95 @@ class GetDcsSqlAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - tone_t code_; + int vfo_; + unsigned int code_; }; // Parameter Control AsyncWorker classes class SetParmAsyncWorker : public HamLibAsyncWorker { public: - SetParmAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, setting_t parm, value_t value) + SetParmAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t parm, float value) : HamLibAsyncWorker(env, hamlib_instance), parm_(parm), value_(value) {} - + void Execute() override { CHECK_RIG_VALID(); - - result_code_ = rig_set_parm(hamlib_instance_->my_rig, parm_, value_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + + result_code_ = shim_rig_set_parm_f(hamlib_instance_->my_rig, parm_, value_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); } } - + void OnError(const Napi::Error& e) override { Napi::Env env = Env(); deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } - + private: - setting_t parm_; - value_t value_; + uint64_t parm_; + float value_; }; class GetParmAsyncWorker : public HamLibAsyncWorker { public: - GetParmAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, setting_t parm) - : HamLibAsyncWorker(env, hamlib_instance), parm_(parm) { - value_.f = 0.0; - } - + GetParmAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, uint64_t parm) + : HamLibAsyncWorker(env, hamlib_instance), parm_(parm), value_(0.0f) {} + void Execute() override { CHECK_RIG_VALID(); - - result_code_ = rig_get_parm(hamlib_instance_->my_rig, parm_, &value_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + + result_code_ = shim_rig_get_parm_f(hamlib_instance_->my_rig, parm_, &value_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } - + void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { - deferred_.Resolve(Napi::Number::New(env, value_.f)); + deferred_.Resolve(Napi::Number::New(env, value_)); } } - + void OnError(const Napi::Error& e) override { Napi::Env env = Env(); deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } - + private: - setting_t parm_; - value_t value_; + uint64_t parm_; + float value_; }; // DTMF Support AsyncWorker classes class SendDtmfAsyncWorker : public HamLibAsyncWorker { public: - SendDtmfAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, const std::string& digits) + SendDtmfAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, const std::string& digits) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), digits_(digits) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_send_dtmf(hamlib_instance_->my_rig, vfo_, digits_.c_str()); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_send_dtmf(hamlib_instance_->my_rig, vfo_, digits_.c_str()); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4549,13 +4500,13 @@ class SendDtmfAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; std::string digits_; }; class RecvDtmfAsyncWorker : public HamLibAsyncWorker { public: - RecvDtmfAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, int maxLength) + RecvDtmfAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int maxLength) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), max_length_(maxLength), length_(0) { digits_.resize(maxLength + 1, '\0'); } @@ -4565,15 +4516,15 @@ class RecvDtmfAsyncWorker : public HamLibAsyncWorker { length_ = max_length_; // rig_recv_dtmf expects a mutable buffer (char*). Ensure non-const pointer. - result_code_ = rig_recv_dtmf(hamlib_instance_->my_rig, vfo_, &digits_[0], &length_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_recv_dtmf(hamlib_instance_->my_rig, vfo_, &digits_[0], &length_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { Napi::Object obj = Napi::Object::New(env); @@ -4589,7 +4540,7 @@ class RecvDtmfAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; int max_length_; int length_; std::string digits_; @@ -4598,21 +4549,21 @@ class RecvDtmfAsyncWorker : public HamLibAsyncWorker { // Memory Channel Advanced Operations AsyncWorker classes class GetMemAsyncWorker : public HamLibAsyncWorker { public: - GetMemAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + GetMemAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), ch_(0) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_get_mem(hamlib_instance_->my_rig, vfo_, &ch_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_mem(hamlib_instance_->my_rig, vfo_, &ch_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, ch_)); @@ -4625,27 +4576,27 @@ class GetMemAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; int ch_; }; class SetBankAsyncWorker : public HamLibAsyncWorker { public: - SetBankAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, int bank) + SetBankAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int bank) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), bank_(bank) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_set_bank(hamlib_instance_->my_rig, vfo_, bank_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_bank(hamlib_instance_->my_rig, vfo_, bank_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4658,7 +4609,7 @@ class SetBankAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; int bank_; }; @@ -4670,18 +4621,18 @@ class MemCountAsyncWorker : public HamLibAsyncWorker { void Execute() override { CHECK_RIG_VALID(); - count_ = rig_mem_count(hamlib_instance_->my_rig); + count_ = shim_rig_mem_count(hamlib_instance_->my_rig); if (count_ < 0) { result_code_ = count_; - error_message_ = rigerror(result_code_); + error_message_ = shim_rigerror(result_code_); } else { - result_code_ = RIG_OK; + result_code_ = SHIM_RIG_OK; } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, count_)); @@ -4700,21 +4651,21 @@ class MemCountAsyncWorker : public HamLibAsyncWorker { // Morse Code Support AsyncWorker classes class SendMorseAsyncWorker : public HamLibAsyncWorker { public: - SendMorseAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, const std::string& msg) + SendMorseAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, const std::string& msg) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), msg_(msg) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_send_morse(hamlib_instance_->my_rig, vfo_, msg_.c_str()); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_send_morse(hamlib_instance_->my_rig, vfo_, msg_.c_str()); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4727,27 +4678,27 @@ class SendMorseAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; std::string msg_; }; class StopMorseAsyncWorker : public HamLibAsyncWorker { public: - StopMorseAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + StopMorseAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_stop_morse(hamlib_instance_->my_rig, vfo_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_stop_morse(hamlib_instance_->my_rig, vfo_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4760,26 +4711,26 @@ class StopMorseAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; }; class WaitMorseAsyncWorker : public HamLibAsyncWorker { public: - WaitMorseAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + WaitMorseAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_wait_morse(hamlib_instance_->my_rig, vfo_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_wait_morse(hamlib_instance_->my_rig, vfo_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4792,27 +4743,27 @@ class WaitMorseAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; }; // Voice Memory Support AsyncWorker classes class SendVoiceMemAsyncWorker : public HamLibAsyncWorker { public: - SendVoiceMemAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, int ch) + SendVoiceMemAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, int ch) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), ch_(ch) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_send_voice_mem(hamlib_instance_->my_rig, vfo_, ch_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_send_voice_mem(hamlib_instance_->my_rig, vfo_, ch_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4825,34 +4776,27 @@ class SendVoiceMemAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; int ch_; }; class StopVoiceMemAsyncWorker : public HamLibAsyncWorker { public: - StopVoiceMemAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) + StopVoiceMemAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo) {} void Execute() override { CHECK_RIG_VALID(); - #if HAVE_RIG_STOP_VOICE_MEM - result_code_ = rig_stop_voice_mem(hamlib_instance_->my_rig, vfo_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_stop_voice_mem(hamlib_instance_->my_rig, vfo_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } - #else - // rig_stop_voice_mem function is not available in this hamlib version - // Return not implemented for compatibility with older hamlib versions - result_code_ = -RIG_ENIMPL; - error_message_ = "rig_stop_voice_mem not available in this hamlib version"; - #endif } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4865,36 +4809,29 @@ class StopVoiceMemAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; + int vfo_; }; // Complex Split Frequency/Mode Operations AsyncWorker classes class SetSplitFreqModeAsyncWorker : public HamLibAsyncWorker { public: - SetSplitFreqModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo, - freq_t tx_freq, rmode_t tx_mode, pbwidth_t tx_width) + SetSplitFreqModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo, + double tx_freq, int tx_mode, int tx_width) : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tx_freq_(tx_freq), tx_mode_(tx_mode), tx_width_(tx_width) {} void Execute() override { CHECK_RIG_VALID(); - #if HAVE_RIG_SPLIT_FREQ_MODE - result_code_ = rig_set_split_freq_mode(hamlib_instance_->my_rig, vfo_, tx_freq_, tx_mode_, tx_width_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_set_split_freq_mode(hamlib_instance_->my_rig, vfo_, tx_freq_, tx_mode_, tx_width_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } - #else - // rig_set_split_freq_mode function is not available in this hamlib version - // Fall back to using separate calls - result_code_ = -RIG_ENIMPL; - error_message_ = "rig_set_split_freq_mode not available - use setSplitFreq and setSplitMode separately"; - #endif } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4907,41 +4844,34 @@ class SetSplitFreqModeAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - freq_t tx_freq_; - rmode_t tx_mode_; - pbwidth_t tx_width_; + int vfo_; + double tx_freq_; + int tx_mode_; + int tx_width_; }; class GetSplitFreqModeAsyncWorker : public HamLibAsyncWorker { public: - GetSplitFreqModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, vfo_t vfo) - : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tx_freq_(0), tx_mode_(RIG_MODE_NONE), tx_width_(0) {} + GetSplitFreqModeAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int vfo) + : HamLibAsyncWorker(env, hamlib_instance), vfo_(vfo), tx_freq_(0), tx_mode_(SHIM_RIG_MODE_NONE), tx_width_(0) {} void Execute() override { CHECK_RIG_VALID(); - #if HAVE_RIG_SPLIT_FREQ_MODE - result_code_ = rig_get_split_freq_mode(hamlib_instance_->my_rig, vfo_, &tx_freq_, &tx_mode_, &tx_width_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_get_split_freq_mode(hamlib_instance_->my_rig, vfo_, &tx_freq_, &tx_mode_, &tx_width_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } - #else - // rig_get_split_freq_mode function is not available in this hamlib version - // Fall back to using separate calls - result_code_ = -RIG_ENIMPL; - error_message_ = "rig_get_split_freq_mode not available - use getSplitFreq and getSplitMode separately"; - #endif } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { Napi::Object obj = Napi::Object::New(env); obj.Set(Napi::String::New(env, "txFrequency"), Napi::Number::New(env, static_cast(tx_freq_))); - obj.Set(Napi::String::New(env, "txMode"), Napi::String::New(env, rig_strrmode(tx_mode_))); + obj.Set(Napi::String::New(env, "txMode"), Napi::String::New(env, shim_rig_strrmode(tx_mode_))); obj.Set(Napi::String::New(env, "txWidth"), Napi::Number::New(env, static_cast(tx_width_))); deferred_.Resolve(obj); } @@ -4953,30 +4883,30 @@ class GetSplitFreqModeAsyncWorker : public HamLibAsyncWorker { } private: - vfo_t vfo_; - freq_t tx_freq_; - rmode_t tx_mode_; - pbwidth_t tx_width_; + int vfo_; + double tx_freq_; + int tx_mode_; + int tx_width_; }; // Reset Function AsyncWorker class class ResetAsyncWorker : public HamLibAsyncWorker { public: - ResetAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, reset_t reset) + ResetAsyncWorker(Napi::Env env, NodeHamLib* hamlib_instance, int reset) : HamLibAsyncWorker(env, hamlib_instance), reset_(reset) {} void Execute() override { CHECK_RIG_VALID(); - result_code_ = rig_reset(hamlib_instance_->my_rig, reset_); - if (result_code_ != RIG_OK) { - error_message_ = rigerror(result_code_); + result_code_ = shim_rig_reset(hamlib_instance_->my_rig, reset_); + if (result_code_ != SHIM_RIG_OK) { + error_message_ = shim_rigerror(result_code_); } } void OnOK() override { Napi::Env env = Env(); - if (result_code_ != RIG_OK && !error_message_.empty()) { + if (result_code_ != SHIM_RIG_OK && !error_message_.empty()) { deferred_.Reject(Napi::Error::New(env, error_message_).Value()); } else { deferred_.Resolve(Napi::Number::New(env, result_code_)); @@ -4989,7 +4919,7 @@ class ResetAsyncWorker : public HamLibAsyncWorker { } private: - reset_t reset_; + int reset_; }; // CTCSS/DCS Tone Control Methods Implementation @@ -5001,8 +4931,8 @@ Napi::Value NodeHamLib::SetCtcssTone(const Napi::CallbackInfo& info) { return env.Null(); } - tone_t tone = static_cast(info[0].As().Uint32Value()); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + unsigned int tone = static_cast(info[0].As().Uint32Value()); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetCtcssToneAsyncWorker* asyncWorker = new SetCtcssToneAsyncWorker(env, this, vfo, tone); asyncWorker->Queue(); @@ -5012,7 +4942,7 @@ Napi::Value NodeHamLib::SetCtcssTone(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetCtcssTone(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetCtcssToneAsyncWorker* asyncWorker = new GetCtcssToneAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5027,8 +4957,8 @@ Napi::Value NodeHamLib::SetDcsCode(const Napi::CallbackInfo& info) { return env.Null(); } - tone_t code = static_cast(info[0].As().Uint32Value()); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + unsigned int code = static_cast(info[0].As().Uint32Value()); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetDcsCodeAsyncWorker* asyncWorker = new SetDcsCodeAsyncWorker(env, this, vfo, code); asyncWorker->Queue(); @@ -5038,7 +4968,7 @@ Napi::Value NodeHamLib::SetDcsCode(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetDcsCode(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetDcsCodeAsyncWorker* asyncWorker = new GetDcsCodeAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5053,8 +4983,8 @@ Napi::Value NodeHamLib::SetCtcssSql(const Napi::CallbackInfo& info) { return env.Null(); } - tone_t tone = static_cast(info[0].As().Uint32Value()); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + unsigned int tone = static_cast(info[0].As().Uint32Value()); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetCtcssSqlAsyncWorker* asyncWorker = new SetCtcssSqlAsyncWorker(env, this, vfo, tone); asyncWorker->Queue(); @@ -5064,7 +4994,7 @@ Napi::Value NodeHamLib::SetCtcssSql(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetCtcssSql(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetCtcssSqlAsyncWorker* asyncWorker = new GetCtcssSqlAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5079,8 +5009,8 @@ Napi::Value NodeHamLib::SetDcsSql(const Napi::CallbackInfo& info) { return env.Null(); } - tone_t code = static_cast(info[0].As().Uint32Value()); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + unsigned int code = static_cast(info[0].As().Uint32Value()); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetDcsSqlAsyncWorker* asyncWorker = new SetDcsSqlAsyncWorker(env, this, vfo, code); asyncWorker->Queue(); @@ -5090,7 +5020,7 @@ Napi::Value NodeHamLib::SetDcsSql(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetDcsSql(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetDcsSqlAsyncWorker* asyncWorker = new GetDcsSqlAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5107,16 +5037,15 @@ Napi::Value NodeHamLib::SetParm(const Napi::CallbackInfo& info) { } std::string parm_str = info[0].As().Utf8Value(); - setting_t parm = rig_parse_parm(parm_str.c_str()); + uint64_t parm = shim_rig_parse_parm(parm_str.c_str()); if (parm == 0) { Napi::Error::New(env, "Invalid parameter name: " + parm_str).ThrowAsJavaScriptException(); return env.Null(); } - value_t value; - value.f = info[1].As().FloatValue(); - + float value = info[1].As().FloatValue(); + SetParmAsyncWorker* asyncWorker = new SetParmAsyncWorker(env, this, parm, value); asyncWorker->Queue(); return asyncWorker->GetPromise(); @@ -5131,7 +5060,7 @@ Napi::Value NodeHamLib::GetParm(const Napi::CallbackInfo& info) { } std::string parm_str = info[0].As().Utf8Value(); - setting_t parm = rig_parse_parm(parm_str.c_str()); + uint64_t parm = shim_rig_parse_parm(parm_str.c_str()); if (parm == 0) { Napi::Error::New(env, "Invalid parameter name: " + parm_str).ThrowAsJavaScriptException(); @@ -5153,7 +5082,7 @@ Napi::Value NodeHamLib::SendDtmf(const Napi::CallbackInfo& info) { } std::string digits = info[0].As().Utf8Value(); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SendDtmfAsyncWorker* asyncWorker = new SendDtmfAsyncWorker(env, this, vfo, digits); asyncWorker->Queue(); @@ -5168,7 +5097,7 @@ Napi::Value NodeHamLib::RecvDtmf(const Napi::CallbackInfo& info) { maxLength = info[0].As().Int32Value(); } - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); RecvDtmfAsyncWorker* asyncWorker = new RecvDtmfAsyncWorker(env, this, vfo, maxLength); asyncWorker->Queue(); @@ -5179,7 +5108,7 @@ Napi::Value NodeHamLib::RecvDtmf(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetMem(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetMemAsyncWorker* asyncWorker = new GetMemAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5195,7 +5124,7 @@ Napi::Value NodeHamLib::SetBank(const Napi::CallbackInfo& info) { } int bank = info[0].As().Int32Value(); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SetBankAsyncWorker* asyncWorker = new SetBankAsyncWorker(env, this, vfo, bank); asyncWorker->Queue(); @@ -5220,7 +5149,7 @@ Napi::Value NodeHamLib::SendMorse(const Napi::CallbackInfo& info) { } std::string msg = info[0].As().Utf8Value(); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SendMorseAsyncWorker* asyncWorker = new SendMorseAsyncWorker(env, this, vfo, msg); asyncWorker->Queue(); @@ -5230,7 +5159,7 @@ Napi::Value NodeHamLib::SendMorse(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::StopMorse(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); StopMorseAsyncWorker* asyncWorker = new StopMorseAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5240,7 +5169,7 @@ Napi::Value NodeHamLib::StopMorse(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::WaitMorse(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); WaitMorseAsyncWorker* asyncWorker = new WaitMorseAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5257,7 +5186,7 @@ Napi::Value NodeHamLib::SendVoiceMem(const Napi::CallbackInfo& info) { } int ch = info[0].As().Int32Value(); - vfo_t vfo = parseVfoParameter(info, 1, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 1, SHIM_RIG_VFO_CURR); SendVoiceMemAsyncWorker* asyncWorker = new SendVoiceMemAsyncWorker(env, this, vfo, ch); asyncWorker->Queue(); @@ -5267,7 +5196,7 @@ Napi::Value NodeHamLib::SendVoiceMem(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::StopVoiceMem(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); StopVoiceMemAsyncWorker* asyncWorker = new StopVoiceMemAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5283,7 +5212,7 @@ Napi::Value NodeHamLib::SetSplitFreqMode(const Napi::CallbackInfo& info) { return env.Null(); } - freq_t tx_freq = static_cast(info[0].As().DoubleValue()); + double tx_freq = static_cast(info[0].As().DoubleValue()); // Basic frequency range validation if (tx_freq < 1000 || tx_freq > 10000000000) { // 1 kHz to 10 GHz reasonable range @@ -5292,11 +5221,11 @@ Napi::Value NodeHamLib::SetSplitFreqMode(const Napi::CallbackInfo& info) { } std::string mode_str = info[1].As().Utf8Value(); - pbwidth_t tx_width = static_cast(info[2].As().DoubleValue()); - vfo_t vfo = parseVfoParameter(info, 3, RIG_VFO_CURR); + int tx_width = static_cast(info[2].As().DoubleValue()); + int vfo = parseVfoParameter(info, 3, SHIM_RIG_VFO_CURR); - rmode_t tx_mode = rig_parse_mode(mode_str.c_str()); - if (tx_mode == RIG_MODE_NONE) { + int tx_mode = shim_rig_parse_mode(mode_str.c_str()); + if (tx_mode == SHIM_RIG_MODE_NONE) { Napi::Error::New(env, "Invalid mode: " + mode_str).ThrowAsJavaScriptException(); return env.Null(); } @@ -5309,7 +5238,7 @@ Napi::Value NodeHamLib::SetSplitFreqMode(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::GetSplitFreqMode(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - vfo_t vfo = parseVfoParameter(info, 0, RIG_VFO_CURR); + int vfo = parseVfoParameter(info, 0, SHIM_RIG_VFO_CURR); GetSplitFreqModeAsyncWorker* asyncWorker = new GetSplitFreqModeAsyncWorker(env, this, vfo); asyncWorker->Queue(); @@ -5331,7 +5260,7 @@ Napi::Value NodeHamLib::Power2mW(const Napi::CallbackInfo& info) { } float power = info[0].As().FloatValue(); - freq_t freq = info[1].As().DoubleValue(); + double freq = info[1].As().DoubleValue(); std::string mode_str = info[2].As().Utf8Value(); // Validate power (0.0 to 1.0) @@ -5347,8 +5276,8 @@ Napi::Value NodeHamLib::Power2mW(const Napi::CallbackInfo& info) { } // Parse mode string - rmode_t mode = rig_parse_mode(mode_str.c_str()); - if (mode == RIG_MODE_NONE) { + int mode = shim_rig_parse_mode(mode_str.c_str()); + if (mode == SHIM_RIG_MODE_NONE) { Napi::Error::New(env, "Invalid mode: " + mode_str).ThrowAsJavaScriptException(); return env.Null(); } @@ -5373,7 +5302,7 @@ Napi::Value NodeHamLib::MW2Power(const Napi::CallbackInfo& info) { } unsigned int mwpower = info[0].As().Uint32Value(); - freq_t freq = info[1].As().DoubleValue(); + double freq = info[1].As().DoubleValue(); std::string mode_str = info[2].As().Utf8Value(); // Validate milliwatts (reasonable range) @@ -5389,8 +5318,8 @@ Napi::Value NodeHamLib::MW2Power(const Napi::CallbackInfo& info) { } // Parse mode string - rmode_t mode = rig_parse_mode(mode_str.c_str()); - if (mode == RIG_MODE_NONE) { + int mode = shim_rig_parse_mode(mode_str.c_str()); + if (mode == SHIM_RIG_MODE_NONE) { Napi::Error::New(env, "Invalid mode: " + mode_str).ThrowAsJavaScriptException(); return env.Null(); } @@ -5404,20 +5333,20 @@ Napi::Value NodeHamLib::MW2Power(const Napi::CallbackInfo& info) { Napi::Value NodeHamLib::Reset(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); - reset_t reset = RIG_RESET_SOFT; // Default to soft reset + int reset = SHIM_RIG_RESET_SOFT; // Default to soft reset if (info.Length() > 0 && info[0].IsString()) { std::string reset_str = info[0].As().Utf8Value(); if (reset_str == "NONE") { - reset = RIG_RESET_NONE; + reset = SHIM_RIG_RESET_NONE; } else if (reset_str == "SOFT") { - reset = RIG_RESET_SOFT; + reset = SHIM_RIG_RESET_SOFT; } else if (reset_str == "MCALL") { - reset = RIG_RESET_MCALL; + reset = SHIM_RIG_RESET_MCALL; } else if (reset_str == "MASTER") { - reset = RIG_RESET_MASTER; + reset = SHIM_RIG_RESET_MASTER; } else if (reset_str == "VFO") { - reset = RIG_RESET_VFO; + reset = SHIM_RIG_RESET_VFO; } else { Napi::Error::New(env, "Invalid reset type: " + reset_str + " (valid: NONE, SOFT, VFO, MCALL, MASTER)").ThrowAsJavaScriptException(); diff --git a/src/hamlib.h b/src/hamlib.h index 0714f69..a1d13c2 100644 --- a/src/hamlib.h +++ b/src/hamlib.h @@ -1,12 +1,9 @@ #pragma once #include -#include +#include "shim/hamlib_shim.h" #include -//forward declarations -//typedef struct s_rig RIG; -//typedef unsigned int vfo_t; -//typedef double freq_t; +#include // Forward declaration class NodeHamLib; @@ -45,28 +42,28 @@ class NodeHamLib : public Napi::ObjectWrap { Napi::Value Close(const Napi::CallbackInfo&); Napi::Value Destroy(const Napi::CallbackInfo&); Napi::Value GetConnectionInfo(const Napi::CallbackInfo&); - + // Memory Channel Management Napi::Value SetMemoryChannel(const Napi::CallbackInfo&); Napi::Value GetMemoryChannel(const Napi::CallbackInfo&); Napi::Value SelectMemoryChannel(const Napi::CallbackInfo&); - + // RIT/XIT Control Napi::Value SetRit(const Napi::CallbackInfo&); Napi::Value GetRit(const Napi::CallbackInfo&); Napi::Value SetXit(const Napi::CallbackInfo&); Napi::Value GetXit(const Napi::CallbackInfo&); Napi::Value ClearRitXit(const Napi::CallbackInfo&); - + // Scanning Operations Napi::Value StartScan(const Napi::CallbackInfo&); Napi::Value StopScan(const Napi::CallbackInfo&); - + // Level Controls Napi::Value SetLevel(const Napi::CallbackInfo&); Napi::Value GetLevel(const Napi::CallbackInfo&); Napi::Value GetSupportedLevels(const Napi::CallbackInfo&); - + // Function Controls Napi::Value SetFunction(const Napi::CallbackInfo&); Napi::Value GetFunction(const Napi::CallbackInfo&); @@ -82,14 +79,14 @@ class NodeHamLib : public Napi::ObjectWrap { Napi::Value GetSplitMode(const Napi::CallbackInfo&); Napi::Value SetSplit(const Napi::CallbackInfo&); Napi::Value GetSplit(const Napi::CallbackInfo&); - + // VFO Operations Napi::Value VfoOperation(const Napi::CallbackInfo&); - + // Antenna Selection Napi::Value SetAntenna(const Napi::CallbackInfo&); Napi::Value GetAntenna(const Napi::CallbackInfo&); - + // Serial Port Configuration Napi::Value SetSerialConfig(const Napi::CallbackInfo&); Napi::Value GetSerialConfig(const Napi::CallbackInfo&); @@ -98,27 +95,27 @@ class NodeHamLib : public Napi::ObjectWrap { Napi::Value SetDcdType(const Napi::CallbackInfo&); Napi::Value GetDcdType(const Napi::CallbackInfo&); Napi::Value GetSupportedSerialConfigs(const Napi::CallbackInfo&); - + // Power Control Napi::Value SetPowerstat(const Napi::CallbackInfo&); Napi::Value GetPowerstat(const Napi::CallbackInfo&); - + // PTT Status Detection Napi::Value GetPtt(const Napi::CallbackInfo&); - + // Data Carrier Detect Napi::Value GetDcd(const Napi::CallbackInfo&); - + // Tuning Step Control Napi::Value SetTuningStep(const Napi::CallbackInfo&); Napi::Value GetTuningStep(const Napi::CallbackInfo&); - + // Repeater Control Napi::Value SetRepeaterShift(const Napi::CallbackInfo&); Napi::Value GetRepeaterShift(const Napi::CallbackInfo&); Napi::Value SetRepeaterOffset(const Napi::CallbackInfo&); Napi::Value GetRepeaterOffset(const Napi::CallbackInfo&); - + // CTCSS/DCS Tone Control Napi::Value SetCtcssTone(const Napi::CallbackInfo&); Napi::Value GetCtcssTone(const Napi::CallbackInfo&); @@ -128,40 +125,40 @@ class NodeHamLib : public Napi::ObjectWrap { Napi::Value GetCtcssSql(const Napi::CallbackInfo&); Napi::Value SetDcsSql(const Napi::CallbackInfo&); Napi::Value GetDcsSql(const Napi::CallbackInfo&); - + // Parameter Control Napi::Value SetParm(const Napi::CallbackInfo&); Napi::Value GetParm(const Napi::CallbackInfo&); - + // DTMF Support Napi::Value SendDtmf(const Napi::CallbackInfo&); Napi::Value RecvDtmf(const Napi::CallbackInfo&); - + // Memory Channel Advanced Operations Napi::Value GetMem(const Napi::CallbackInfo&); Napi::Value SetBank(const Napi::CallbackInfo&); Napi::Value MemCount(const Napi::CallbackInfo&); - + // Morse Code Support Napi::Value SendMorse(const Napi::CallbackInfo&); Napi::Value StopMorse(const Napi::CallbackInfo&); Napi::Value WaitMorse(const Napi::CallbackInfo&); - + // Voice Memory Support Napi::Value SendVoiceMem(const Napi::CallbackInfo&); Napi::Value StopVoiceMem(const Napi::CallbackInfo&); - + // Complex Split Frequency/Mode Operations Napi::Value SetSplitFreqMode(const Napi::CallbackInfo&); Napi::Value GetSplitFreqMode(const Napi::CallbackInfo&); - + // Power Conversion Functions Napi::Value Power2mW(const Napi::CallbackInfo&); Napi::Value MW2Power(const Napi::CallbackInfo&); - + // Reset Function Napi::Value Reset(const Napi::CallbackInfo&); - + // Static method to get supported rig models static Napi::Value GetSupportedRigs(const Napi::CallbackInfo&); @@ -174,22 +171,23 @@ class NodeHamLib : public Napi::ObjectWrap { static Napi::Function GetClass(Napi::Env); - static int freq_change_cb(RIG*, vfo_t, freq_t, void*); + // Frequency change callback (uses basic C types via shim) + static int freq_change_cb(void* handle, int vfo, double freq, void* arg); public: - RIG *my_rig; + hamlib_shim_handle_t my_rig; // Opaque handle instead of RIG* bool rig_is_open = false; bool is_network_rig = false; // Flag to indicate if using network connection - rig_model_t original_model = 0; // Store original model when using network + unsigned int original_model = 0; // Store original model when using network int count = 0; void* freq_emit_cb; - char port_path[HAMLIB_FILPATHLEN]; // Store the port path + char port_path[SHIM_HAMLIB_FILPATHLEN]; // Store the port path static Napi::FunctionReference constructor; Napi::CallbackInfo * m_currentInfo; - + // Helper method to detect network address format bool isNetworkAddress(const char* path); - - // Static callback helper for rig_list_foreach - static int rig_list_callback(const struct rig_caps *caps, void *data); -}; \ No newline at end of file + + // Static callback helper for shim_rig_list_foreach + static int rig_list_callback(const shim_rig_info_t* info, void* data); +}; diff --git a/src/hamlib_compat.h b/src/hamlib_compat.h deleted file mode 100644 index 7ae12f8..0000000 --- a/src/hamlib_compat.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -/** - * hamlib_compat.h - Hamlib compatibility layer for different versions - * - * This header handles compatibility issues between different versions of hamlib - * Some functions are only available in newer versions and may not be present - * in older Linux distribution packages. - */ - -#include - -// Check for hamlib version if available -#ifdef HAMLIB_VERSION - // Version-specific feature detection - #if HAMLIB_VERSION >= 0x040500 // Version 4.5.0 and later - #define HAVE_RIG_STOP_VOICE_MEM 1 - #define HAVE_RIG_SPLIT_FREQ_MODE 1 - #endif -#else - // If version is not available, assume older version - // We'll disable newer functions for maximum compatibility - #undef HAVE_RIG_STOP_VOICE_MEM - #undef HAVE_RIG_SPLIT_FREQ_MODE -#endif - -// Manual feature detection based on typical availability -// These functions were added in recent hamlib versions -// Comment out these lines if your hamlib version doesn't have them - -// Uncomment if you have a newer hamlib version with these functions: -// #define HAVE_RIG_STOP_VOICE_MEM 1 -// #define HAVE_RIG_SPLIT_FREQ_MODE 1 - -// For maximum compatibility with older distributions, keep these disabled -// Users with newer hamlib can enable them manually - -#ifndef HAVE_RIG_STOP_VOICE_MEM -#define HAVE_RIG_STOP_VOICE_MEM 0 -#endif - -#ifndef HAVE_RIG_SPLIT_FREQ_MODE -#define HAVE_RIG_SPLIT_FREQ_MODE 0 -#endif \ No newline at end of file diff --git a/src/shim/hamlib_shim.c b/src/shim/hamlib_shim.c new file mode 100644 index 0000000..e76f250 --- /dev/null +++ b/src/shim/hamlib_shim.c @@ -0,0 +1,865 @@ +/** + * hamlib_shim.c - Pure C implementation of the Hamlib shim layer + * + * This file wraps all Hamlib C API calls and struct accesses, providing + * a clean C ABI boundary. It must be compiled with the same compiler + * as Hamlib (MinGW on Windows, gcc/clang on Unix). + */ + +#ifndef HAMLIB_SHIM_BUILD +#define HAMLIB_SHIM_BUILD +#endif +#include "hamlib_shim.h" +#include +#include +#include + +/* ===== Lifecycle ===== */ + +SHIM_API hamlib_shim_handle_t shim_rig_init(unsigned int model) { + return (hamlib_shim_handle_t)rig_init((rig_model_t)model); +} + +SHIM_API int shim_rig_open(hamlib_shim_handle_t h) { + return rig_open((RIG*)h); +} + +SHIM_API int shim_rig_close(hamlib_shim_handle_t h) { + return rig_close((RIG*)h); +} + +SHIM_API int shim_rig_cleanup(hamlib_shim_handle_t h) { + return rig_cleanup((RIG*)h); +} + +SHIM_API const char* shim_rigerror(int errcode) { + return rigerror(errcode); +} + +/* ===== Debug / Utility ===== */ + +SHIM_API void shim_rig_set_debug(int level) { + rig_set_debug((enum rig_debug_level_e)level); +} + +SHIM_API int shim_rig_get_debug(void) { + /* Hamlib doesn't have rig_get_debug in all versions, + but we use the global variable if available */ +#ifdef HAVE_RIG_GET_DEBUG + return (int)rig_get_debug(); +#else + return -1; /* Not available */ +#endif +} + +SHIM_API const char* shim_rig_get_version(void) { + return hamlib_version; +} + +SHIM_API int shim_rig_load_all_backends(void) { + return rig_load_all_backends(); +} + +/* Internal callback adapter for rig_list_foreach */ +struct shim_list_adapter { + shim_rig_list_cb_t user_cb; + void* user_data; +}; + +static int shim_list_foreach_adapter(const struct rig_caps *caps, void *data) { + struct shim_list_adapter *adapter = (struct shim_list_adapter*)data; + shim_rig_info_t info; + info.rig_model = caps->rig_model; + info.model_name = caps->model_name ? caps->model_name : ""; + info.mfg_name = caps->mfg_name ? caps->mfg_name : ""; + info.version = caps->version ? caps->version : ""; + info.status = (int)caps->status; + info.rig_type = (int)(caps->rig_type & RIG_TYPE_MASK); + return adapter->user_cb(&info, adapter->user_data); +} + +SHIM_API int shim_rig_list_foreach(shim_rig_list_cb_t cb, void* data) { + struct shim_list_adapter adapter; + adapter.user_cb = cb; + adapter.user_data = data; + return rig_list_foreach(shim_list_foreach_adapter, &adapter); +} + +SHIM_API const char* shim_rig_strstatus(int status) { + return rig_strstatus((enum rig_status_e)status); +} + +/* ===== Port configuration ===== */ + +SHIM_API void shim_rig_set_port_path(hamlib_shim_handle_t h, const char* path) { + RIG* rig = (RIG*)h; + strncpy(rig->state.rigport.pathname, path, HAMLIB_FILPATHLEN - 1); + rig->state.rigport.pathname[HAMLIB_FILPATHLEN - 1] = '\0'; +} + +SHIM_API void shim_rig_set_port_type(hamlib_shim_handle_t h, int type) { + RIG* rig = (RIG*)h; + rig->state.rigport.type.rig = (enum rig_port_e)type; +} + +/* Serial config */ +SHIM_API void shim_rig_set_serial_rate(hamlib_shim_handle_t h, int rate) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.rate = rate; +} + +SHIM_API int shim_rig_get_serial_rate(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.parm.serial.rate; +} + +SHIM_API void shim_rig_set_serial_data_bits(hamlib_shim_handle_t h, int bits) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.data_bits = bits; +} + +SHIM_API int shim_rig_get_serial_data_bits(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.parm.serial.data_bits; +} + +SHIM_API void shim_rig_set_serial_stop_bits(hamlib_shim_handle_t h, int bits) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.stop_bits = bits; +} + +SHIM_API int shim_rig_get_serial_stop_bits(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.parm.serial.stop_bits; +} + +SHIM_API void shim_rig_set_serial_parity(hamlib_shim_handle_t h, int parity) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.parity = (enum serial_parity_e)parity; +} + +SHIM_API int shim_rig_get_serial_parity(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.rigport.parm.serial.parity; +} + +SHIM_API void shim_rig_set_serial_handshake(hamlib_shim_handle_t h, int handshake) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.handshake = (enum serial_handshake_e)handshake; +} + +SHIM_API int shim_rig_get_serial_handshake(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.rigport.parm.serial.handshake; +} + +SHIM_API void shim_rig_set_serial_rts_state(hamlib_shim_handle_t h, int state) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.rts_state = (enum serial_control_state_e)state; +} + +SHIM_API int shim_rig_get_serial_rts_state(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.rigport.parm.serial.rts_state; +} + +SHIM_API void shim_rig_set_serial_dtr_state(hamlib_shim_handle_t h, int state) { + RIG* rig = (RIG*)h; + rig->state.rigport.parm.serial.dtr_state = (enum serial_control_state_e)state; +} + +SHIM_API int shim_rig_get_serial_dtr_state(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.rigport.parm.serial.dtr_state; +} + +/* Port timing */ +SHIM_API void shim_rig_set_port_timeout(hamlib_shim_handle_t h, int ms) { + RIG* rig = (RIG*)h; + rig->state.rigport.timeout = ms; +} + +SHIM_API int shim_rig_get_port_timeout(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.timeout; +} + +SHIM_API void shim_rig_set_port_retry(hamlib_shim_handle_t h, int count) { + RIG* rig = (RIG*)h; + rig->state.rigport.retry = (short)count; +} + +SHIM_API int shim_rig_get_port_retry(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.rigport.retry; +} + +SHIM_API void shim_rig_set_port_write_delay(hamlib_shim_handle_t h, int ms) { + RIG* rig = (RIG*)h; + rig->state.rigport.write_delay = ms; +} + +SHIM_API int shim_rig_get_port_write_delay(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.write_delay; +} + +SHIM_API void shim_rig_set_port_post_write_delay(hamlib_shim_handle_t h, int ms) { + RIG* rig = (RIG*)h; + rig->state.rigport.post_write_delay = ms; +} + +SHIM_API int shim_rig_get_port_post_write_delay(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.post_write_delay; +} + +SHIM_API void shim_rig_set_port_flushx(hamlib_shim_handle_t h, int enable) { + RIG* rig = (RIG*)h; + rig->state.rigport.flushx = enable; +} + +SHIM_API int shim_rig_get_port_flushx(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return rig->state.rigport.flushx; +} + +/* PTT/DCD port type */ +SHIM_API void shim_rig_set_ptt_type(hamlib_shim_handle_t h, int type) { + RIG* rig = (RIG*)h; + rig->state.pttport.type.ptt = (ptt_type_t)type; +} + +SHIM_API int shim_rig_get_ptt_type(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.pttport.type.ptt; +} + +SHIM_API void shim_rig_set_dcd_type(hamlib_shim_handle_t h, int type) { + RIG* rig = (RIG*)h; + rig->state.dcdport.type.dcd = (dcd_type_t)type; +} + +SHIM_API int shim_rig_get_dcd_type(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (int)rig->state.dcdport.type.dcd; +} + +/* ===== Frequency control ===== */ + +SHIM_API int shim_rig_set_freq(hamlib_shim_handle_t h, int vfo, double freq) { + return rig_set_freq((RIG*)h, (vfo_t)vfo, (freq_t)freq); +} + +SHIM_API int shim_rig_get_freq(hamlib_shim_handle_t h, int vfo, double* freq) { + freq_t f = 0; + int ret = rig_get_freq((RIG*)h, (vfo_t)vfo, &f); + if (freq) *freq = (double)f; + return ret; +} + +/* ===== VFO control ===== */ + +SHIM_API int shim_rig_set_vfo(hamlib_shim_handle_t h, int vfo) { + return rig_set_vfo((RIG*)h, (vfo_t)vfo); +} + +SHIM_API int shim_rig_get_vfo(hamlib_shim_handle_t h, int* vfo) { + vfo_t v = 0; + int ret = rig_get_vfo((RIG*)h, &v); + if (vfo) *vfo = (int)v; + return ret; +} + +/* ===== Mode control ===== */ + +SHIM_API int shim_rig_set_mode(hamlib_shim_handle_t h, int vfo, int mode, int width) { + return rig_set_mode((RIG*)h, (vfo_t)vfo, (rmode_t)mode, (pbwidth_t)width); +} + +SHIM_API int shim_rig_get_mode(hamlib_shim_handle_t h, int vfo, int* mode, int* width) { + rmode_t m = 0; + pbwidth_t w = 0; + int ret = rig_get_mode((RIG*)h, (vfo_t)vfo, &m, &w); + if (mode) *mode = (int)m; + if (width) *width = (int)w; + return ret; +} + +SHIM_API int shim_rig_parse_mode(const char* mode_str) { + return (int)rig_parse_mode(mode_str); +} + +SHIM_API const char* shim_rig_strrmode(int mode) { + return rig_strrmode((rmode_t)mode); +} + +SHIM_API int shim_rig_passband_narrow(hamlib_shim_handle_t h, int mode) { + return (int)rig_passband_narrow((RIG*)h, (rmode_t)mode); +} + +SHIM_API int shim_rig_passband_wide(hamlib_shim_handle_t h, int mode) { + return (int)rig_passband_wide((RIG*)h, (rmode_t)mode); +} + +/* ===== PTT control ===== */ + +SHIM_API int shim_rig_set_ptt(hamlib_shim_handle_t h, int vfo, int ptt) { + return rig_set_ptt((RIG*)h, (vfo_t)vfo, (ptt_t)ptt); +} + +SHIM_API int shim_rig_get_ptt(hamlib_shim_handle_t h, int vfo, int* ptt) { + ptt_t p = 0; + int ret = rig_get_ptt((RIG*)h, (vfo_t)vfo, &p); + if (ptt) *ptt = (int)p; + return ret; +} + +SHIM_API int shim_rig_get_dcd(hamlib_shim_handle_t h, int vfo, int* dcd) { + dcd_t d = 0; + int ret = rig_get_dcd((RIG*)h, (vfo_t)vfo, &d); + if (dcd) *dcd = (int)d; + return ret; +} + +/* ===== Signal strength ===== */ + +SHIM_API int shim_rig_get_strength(hamlib_shim_handle_t h, int vfo, int* strength) { + int s = 0; + int ret = rig_get_strength((RIG*)h, (vfo_t)vfo, &s); + if (strength) *strength = s; + return ret; +} + +/* ===== Level control ===== */ + +SHIM_API int shim_rig_set_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float value) { + value_t val; + val.f = value; + return rig_set_level((RIG*)h, (vfo_t)vfo, (setting_t)level, val); +} + +SHIM_API int shim_rig_set_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int value) { + value_t val; + val.i = value; + return rig_set_level((RIG*)h, (vfo_t)vfo, (setting_t)level, val); +} + +SHIM_API int shim_rig_get_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float* value) { + value_t val; + val.f = 0.0f; + int ret = rig_get_level((RIG*)h, (vfo_t)vfo, (setting_t)level, &val); + if (value) *value = val.f; + return ret; +} + +SHIM_API int shim_rig_get_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int* value) { + value_t val; + val.i = 0; + int ret = rig_get_level((RIG*)h, (vfo_t)vfo, (setting_t)level, &val); + if (value) *value = val.i; + return ret; +} + +/* ===== Function control ===== */ + +SHIM_API int shim_rig_set_func(hamlib_shim_handle_t h, int vfo, uint64_t func, int enable) { + return rig_set_func((RIG*)h, (vfo_t)vfo, (setting_t)func, enable); +} + +SHIM_API int shim_rig_get_func(hamlib_shim_handle_t h, int vfo, uint64_t func, int* state) { + int s = 0; + int ret = rig_get_func((RIG*)h, (vfo_t)vfo, (setting_t)func, &s); + if (state) *state = s; + return ret; +} + +/* ===== Parameter control ===== */ + +SHIM_API int shim_rig_set_parm_f(hamlib_shim_handle_t h, uint64_t parm, float value) { + value_t val; + val.f = value; + return rig_set_parm((RIG*)h, (setting_t)parm, val); +} + +SHIM_API int shim_rig_set_parm_i(hamlib_shim_handle_t h, uint64_t parm, int value) { + value_t val; + val.i = value; + return rig_set_parm((RIG*)h, (setting_t)parm, val); +} + +SHIM_API int shim_rig_get_parm_f(hamlib_shim_handle_t h, uint64_t parm, float* value) { + value_t val; + val.f = 0.0f; + int ret = rig_get_parm((RIG*)h, (setting_t)parm, &val); + if (value) *value = val.f; + return ret; +} + +SHIM_API int shim_rig_get_parm_i(hamlib_shim_handle_t h, uint64_t parm, int* value) { + value_t val; + val.i = 0; + int ret = rig_get_parm((RIG*)h, (setting_t)parm, &val); + if (value) *value = val.i; + return ret; +} + +SHIM_API uint64_t shim_rig_parse_parm(const char* parm_str) { + return (uint64_t)rig_parse_parm(parm_str); +} + +/* ===== Split operations ===== */ + +SHIM_API int shim_rig_set_split_freq(hamlib_shim_handle_t h, int vfo, double freq) { + return rig_set_split_freq((RIG*)h, (vfo_t)vfo, (freq_t)freq); +} + +SHIM_API int shim_rig_get_split_freq(hamlib_shim_handle_t h, int vfo, double* freq) { + freq_t f = 0; + int ret = rig_get_split_freq((RIG*)h, (vfo_t)vfo, &f); + if (freq) *freq = (double)f; + return ret; +} + +SHIM_API int shim_rig_set_split_vfo(hamlib_shim_handle_t h, int rx_vfo, int split, int tx_vfo) { + return rig_set_split_vfo((RIG*)h, (vfo_t)rx_vfo, (split_t)split, (vfo_t)tx_vfo); +} + +SHIM_API int shim_rig_get_split_vfo(hamlib_shim_handle_t h, int vfo, int* split, int* tx_vfo) { + split_t s = 0; + vfo_t tv = 0; + int ret = rig_get_split_vfo((RIG*)h, (vfo_t)vfo, &s, &tv); + if (split) *split = (int)s; + if (tx_vfo) *tx_vfo = (int)tv; + return ret; +} + +SHIM_API int shim_rig_set_split_mode(hamlib_shim_handle_t h, int vfo, int mode, int width) { + return rig_set_split_mode((RIG*)h, (vfo_t)vfo, (rmode_t)mode, (pbwidth_t)width); +} + +SHIM_API int shim_rig_get_split_mode(hamlib_shim_handle_t h, int vfo, int* mode, int* width) { + rmode_t m = 0; + pbwidth_t w = 0; + int ret = rig_get_split_mode((RIG*)h, (vfo_t)vfo, &m, &w); + if (mode) *mode = (int)m; + if (width) *width = (int)w; + return ret; +} + +SHIM_API int shim_rig_set_split_freq_mode(hamlib_shim_handle_t h, int vfo, double freq, int mode, int width) { +#if HAVE_RIG_SPLIT_FREQ_MODE + return rig_set_split_freq_mode((RIG*)h, (vfo_t)vfo, (freq_t)freq, (rmode_t)mode, (pbwidth_t)width); +#else + /* Fallback: set freq and mode separately */ + int ret = rig_set_split_freq((RIG*)h, (vfo_t)vfo, (freq_t)freq); + if (ret != RIG_OK) return ret; + return rig_set_split_mode((RIG*)h, (vfo_t)vfo, (rmode_t)mode, (pbwidth_t)width); +#endif +} + +SHIM_API int shim_rig_get_split_freq_mode(hamlib_shim_handle_t h, int vfo, double* freq, int* mode, int* width) { +#if HAVE_RIG_SPLIT_FREQ_MODE + freq_t f = 0; + rmode_t m = 0; + pbwidth_t w = 0; + int ret = rig_get_split_freq_mode((RIG*)h, (vfo_t)vfo, &f, &m, &w); + if (freq) *freq = (double)f; + if (mode) *mode = (int)m; + if (width) *width = (int)w; + return ret; +#else + /* Fallback: get freq and mode separately */ + freq_t f = 0; + int ret = rig_get_split_freq((RIG*)h, (vfo_t)vfo, &f); + if (freq) *freq = (double)f; + if (ret != RIG_OK) return ret; + rmode_t m = 0; + pbwidth_t w = 0; + ret = rig_get_split_mode((RIG*)h, (vfo_t)vfo, &m, &w); + if (mode) *mode = (int)m; + if (width) *width = (int)w; + return ret; +#endif +} + +/* ===== RIT/XIT control ===== */ + +SHIM_API int shim_rig_set_rit(hamlib_shim_handle_t h, int vfo, int offset) { + return rig_set_rit((RIG*)h, (vfo_t)vfo, (shortfreq_t)offset); +} + +SHIM_API int shim_rig_get_rit(hamlib_shim_handle_t h, int vfo, int* offset) { + shortfreq_t o = 0; + int ret = rig_get_rit((RIG*)h, (vfo_t)vfo, &o); + if (offset) *offset = (int)o; + return ret; +} + +SHIM_API int shim_rig_set_xit(hamlib_shim_handle_t h, int vfo, int offset) { + return rig_set_xit((RIG*)h, (vfo_t)vfo, (shortfreq_t)offset); +} + +SHIM_API int shim_rig_get_xit(hamlib_shim_handle_t h, int vfo, int* offset) { + shortfreq_t o = 0; + int ret = rig_get_xit((RIG*)h, (vfo_t)vfo, &o); + if (offset) *offset = (int)o; + return ret; +} + +/* ===== Memory channel operations ===== */ + +SHIM_API int shim_rig_set_channel(hamlib_shim_handle_t h, int vfo, const shim_channel_t* schan) { + channel_t chan; + memset(&chan, 0, sizeof(chan)); + chan.channel_num = schan->channel_num; + chan.freq = (freq_t)schan->freq; + chan.tx_freq = (freq_t)schan->tx_freq; + chan.mode = (rmode_t)schan->mode; + chan.width = (pbwidth_t)schan->width; + chan.split = (split_t)schan->split; + chan.ctcss_tone = (tone_t)schan->ctcss_tone; + chan.vfo = (vfo_t)schan->vfo; + strncpy(chan.channel_desc, schan->channel_desc, sizeof(chan.channel_desc) - 1); + chan.channel_desc[sizeof(chan.channel_desc) - 1] = '\0'; + return rig_set_channel((RIG*)h, (vfo_t)vfo, &chan); +} + +SHIM_API int shim_rig_get_channel(hamlib_shim_handle_t h, int vfo, shim_channel_t* schan, int read_only) { + channel_t chan; + memset(&chan, 0, sizeof(chan)); + chan.channel_num = schan->channel_num; + chan.vfo = (vfo_t)schan->vfo; + int ret = rig_get_channel((RIG*)h, (vfo_t)vfo, &chan, read_only); + if (ret == RIG_OK) { + schan->channel_num = chan.channel_num; + schan->freq = (double)chan.freq; + schan->tx_freq = (double)chan.tx_freq; + schan->mode = (int)chan.mode; + schan->width = (int)chan.width; + schan->split = (int)chan.split; + schan->ctcss_tone = (int)chan.ctcss_tone; + schan->vfo = (int)chan.vfo; + strncpy(schan->channel_desc, chan.channel_desc, sizeof(schan->channel_desc) - 1); + schan->channel_desc[sizeof(schan->channel_desc) - 1] = '\0'; + } + return ret; +} + +SHIM_API int shim_rig_set_mem(hamlib_shim_handle_t h, int vfo, int ch) { + return rig_set_mem((RIG*)h, (vfo_t)vfo, ch); +} + +SHIM_API int shim_rig_get_mem(hamlib_shim_handle_t h, int vfo, int* ch) { + return rig_get_mem((RIG*)h, (vfo_t)vfo, ch); +} + +SHIM_API int shim_rig_set_bank(hamlib_shim_handle_t h, int vfo, int bank) { + return rig_set_bank((RIG*)h, (vfo_t)vfo, bank); +} + +SHIM_API int shim_rig_mem_count(hamlib_shim_handle_t h) { + return rig_mem_count((RIG*)h); +} + +/* ===== Scanning ===== */ + +SHIM_API int shim_rig_scan(hamlib_shim_handle_t h, int vfo, int scan_type, int channel) { + return rig_scan((RIG*)h, (vfo_t)vfo, (scan_t)scan_type, channel); +} + +/* ===== VFO operations ===== */ + +SHIM_API int shim_rig_vfo_op(hamlib_shim_handle_t h, int vfo, int op) { + return rig_vfo_op((RIG*)h, (vfo_t)vfo, (vfo_op_t)op); +} + +/* ===== Antenna control ===== */ + +SHIM_API int shim_rig_set_ant(hamlib_shim_handle_t h, int vfo, int ant, float option) { + value_t opt; + opt.f = option; + return rig_set_ant((RIG*)h, (vfo_t)vfo, (ant_t)ant, opt); +} + +SHIM_API int shim_rig_get_ant(hamlib_shim_handle_t h, int vfo, int ant, float* option, + int* ant_curr, int* ant_tx, int* ant_rx) { + value_t opt = {0}; + ant_t ac = 0, atx = 0, arx = 0; + int ret = rig_get_ant((RIG*)h, (vfo_t)vfo, (ant_t)ant, &opt, &ac, &atx, &arx); + if (option) *option = opt.f; + if (ant_curr) *ant_curr = (int)ac; + if (ant_tx) *ant_tx = (int)atx; + if (ant_rx) *ant_rx = (int)arx; + return ret; +} + +/* ===== Tuning step ===== */ + +SHIM_API int shim_rig_set_ts(hamlib_shim_handle_t h, int vfo, int ts) { + return rig_set_ts((RIG*)h, (vfo_t)vfo, (shortfreq_t)ts); +} + +SHIM_API int shim_rig_get_ts(hamlib_shim_handle_t h, int vfo, int* ts) { + shortfreq_t t = 0; + int ret = rig_get_ts((RIG*)h, (vfo_t)vfo, &t); + if (ts) *ts = (int)t; + return ret; +} + +/* ===== Repeater control ===== */ + +SHIM_API int shim_rig_set_rptr_shift(hamlib_shim_handle_t h, int vfo, int shift) { + return rig_set_rptr_shift((RIG*)h, (vfo_t)vfo, (rptr_shift_t)shift); +} + +SHIM_API int shim_rig_get_rptr_shift(hamlib_shim_handle_t h, int vfo, int* shift) { + rptr_shift_t s = 0; + int ret = rig_get_rptr_shift((RIG*)h, (vfo_t)vfo, &s); + if (shift) *shift = (int)s; + return ret; +} + +SHIM_API const char* shim_rig_strptrshift(int shift) { + return rig_strptrshift((rptr_shift_t)shift); +} + +SHIM_API int shim_rig_set_rptr_offs(hamlib_shim_handle_t h, int vfo, int offset) { + return rig_set_rptr_offs((RIG*)h, (vfo_t)vfo, (shortfreq_t)offset); +} + +SHIM_API int shim_rig_get_rptr_offs(hamlib_shim_handle_t h, int vfo, int* offset) { + shortfreq_t o = 0; + int ret = rig_get_rptr_offs((RIG*)h, (vfo_t)vfo, &o); + if (offset) *offset = (int)o; + return ret; +} + +/* ===== CTCSS/DCS tone control ===== */ + +SHIM_API int shim_rig_set_ctcss_tone(hamlib_shim_handle_t h, int vfo, unsigned int tone) { + return rig_set_ctcss_tone((RIG*)h, (vfo_t)vfo, (tone_t)tone); +} + +SHIM_API int shim_rig_get_ctcss_tone(hamlib_shim_handle_t h, int vfo, unsigned int* tone) { + tone_t t = 0; + int ret = rig_get_ctcss_tone((RIG*)h, (vfo_t)vfo, &t); + if (tone) *tone = (unsigned int)t; + return ret; +} + +SHIM_API int shim_rig_set_dcs_code(hamlib_shim_handle_t h, int vfo, unsigned int code) { + return rig_set_dcs_code((RIG*)h, (vfo_t)vfo, (tone_t)code); +} + +SHIM_API int shim_rig_get_dcs_code(hamlib_shim_handle_t h, int vfo, unsigned int* code) { + tone_t c = 0; + int ret = rig_get_dcs_code((RIG*)h, (vfo_t)vfo, &c); + if (code) *code = (unsigned int)c; + return ret; +} + +SHIM_API int shim_rig_set_ctcss_sql(hamlib_shim_handle_t h, int vfo, unsigned int tone) { + return rig_set_ctcss_sql((RIG*)h, (vfo_t)vfo, (tone_t)tone); +} + +SHIM_API int shim_rig_get_ctcss_sql(hamlib_shim_handle_t h, int vfo, unsigned int* tone) { + tone_t t = 0; + int ret = rig_get_ctcss_sql((RIG*)h, (vfo_t)vfo, &t); + if (tone) *tone = (unsigned int)t; + return ret; +} + +SHIM_API int shim_rig_set_dcs_sql(hamlib_shim_handle_t h, int vfo, unsigned int code) { + return rig_set_dcs_sql((RIG*)h, (vfo_t)vfo, (tone_t)code); +} + +SHIM_API int shim_rig_get_dcs_sql(hamlib_shim_handle_t h, int vfo, unsigned int* code) { + tone_t c = 0; + int ret = rig_get_dcs_sql((RIG*)h, (vfo_t)vfo, &c); + if (code) *code = (unsigned int)c; + return ret; +} + +/* ===== DTMF ===== */ + +SHIM_API int shim_rig_send_dtmf(hamlib_shim_handle_t h, int vfo, const char* digits) { + return rig_send_dtmf((RIG*)h, (vfo_t)vfo, digits); +} + +SHIM_API int shim_rig_recv_dtmf(hamlib_shim_handle_t h, int vfo, char* digits, int* length) { + return rig_recv_dtmf((RIG*)h, (vfo_t)vfo, digits, length); +} + +/* ===== Morse code ===== */ + +SHIM_API int shim_rig_send_morse(hamlib_shim_handle_t h, int vfo, const char* msg) { + return rig_send_morse((RIG*)h, (vfo_t)vfo, msg); +} + +SHIM_API int shim_rig_stop_morse(hamlib_shim_handle_t h, int vfo) { + return rig_stop_morse((RIG*)h, (vfo_t)vfo); +} + +SHIM_API int shim_rig_wait_morse(hamlib_shim_handle_t h, int vfo) { + return rig_wait_morse((RIG*)h, (vfo_t)vfo); +} + +/* ===== Voice memory ===== */ + +SHIM_API int shim_rig_send_voice_mem(hamlib_shim_handle_t h, int vfo, int ch) { + return rig_send_voice_mem((RIG*)h, (vfo_t)vfo, ch); +} + +SHIM_API int shim_rig_stop_voice_mem(hamlib_shim_handle_t h, int vfo) { +#if HAVE_RIG_STOP_VOICE_MEM + return rig_stop_voice_mem((RIG*)h, (vfo_t)vfo); +#else + (void)h; (void)vfo; + return -RIG_ENIMPL; +#endif +} + +/* ===== Power control ===== */ + +SHIM_API int shim_rig_set_powerstat(hamlib_shim_handle_t h, int status) { + return rig_set_powerstat((RIG*)h, (powerstat_t)status); +} + +SHIM_API int shim_rig_get_powerstat(hamlib_shim_handle_t h, int* status) { + powerstat_t s = 0; + int ret = rig_get_powerstat((RIG*)h, &s); + if (status) *status = (int)s; + return ret; +} + +/* ===== Power conversion ===== */ + +SHIM_API int shim_rig_power2mW(hamlib_shim_handle_t h, unsigned int* mwpower, float power, double freq, int mode) { + return rig_power2mW((RIG*)h, mwpower, power, (freq_t)freq, (rmode_t)mode); +} + +SHIM_API int shim_rig_mW2power(hamlib_shim_handle_t h, float* power, unsigned int mwpower, double freq, int mode) { + return rig_mW2power((RIG*)h, power, mwpower, (freq_t)freq, (rmode_t)mode); +} + +/* ===== Reset ===== */ + +SHIM_API int shim_rig_reset(hamlib_shim_handle_t h, int reset_type) { + return rig_reset((RIG*)h, (reset_t)reset_type); +} + +/* ===== Callbacks ===== */ + +/* Internal adapter structs for callback forwarding */ +struct shim_freq_cb_adapter { + shim_freq_cb_t user_cb; + void* user_arg; +}; + +struct shim_ptt_cb_adapter { + shim_ptt_cb_t user_cb; + void* user_arg; +}; + +/* We store adapters statically (one per rig handle - simplified) */ +static struct shim_freq_cb_adapter freq_cb_adapter = {NULL, NULL}; +static struct shim_ptt_cb_adapter ptt_cb_adapter = {NULL, NULL}; + +static int shim_freq_cb_thunk(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg) { + struct shim_freq_cb_adapter *adapter = (struct shim_freq_cb_adapter*)arg; + if (adapter && adapter->user_cb) { + return adapter->user_cb((void*)rig, (int)vfo, (double)freq, adapter->user_arg); + } + return 0; +} + +static int shim_ptt_cb_thunk(RIG *rig, vfo_t vfo, ptt_t ptt, rig_ptr_t arg) { + struct shim_ptt_cb_adapter *adapter = (struct shim_ptt_cb_adapter*)arg; + if (adapter && adapter->user_cb) { + return adapter->user_cb((void*)rig, (int)vfo, (int)ptt, adapter->user_arg); + } + return 0; +} + +SHIM_API int shim_rig_set_freq_callback(hamlib_shim_handle_t h, shim_freq_cb_t cb, void* arg) { + freq_cb_adapter.user_cb = cb; + freq_cb_adapter.user_arg = arg; + return rig_set_freq_callback((RIG*)h, shim_freq_cb_thunk, &freq_cb_adapter); +} + +SHIM_API int shim_rig_set_ptt_callback(hamlib_shim_handle_t h, shim_ptt_cb_t cb, void* arg) { + ptt_cb_adapter.user_cb = cb; + ptt_cb_adapter.user_arg = arg; + return rig_set_ptt_callback((RIG*)h, shim_ptt_cb_thunk, &ptt_cb_adapter); +} + +SHIM_API int shim_rig_set_trn(hamlib_shim_handle_t h, int trn) { + return rig_set_trn((RIG*)h, trn); +} + +/* ===== Capability queries ===== */ + +SHIM_API uint64_t shim_rig_get_mode_list(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (uint64_t)(rig->state.mode_list); +} + +SHIM_API uint64_t shim_rig_get_caps_has_get_level(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (uint64_t)(rig->caps->has_get_level); +} + +SHIM_API uint64_t shim_rig_get_caps_has_set_level(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (uint64_t)(rig->caps->has_set_level); +} + +SHIM_API uint64_t shim_rig_get_caps_has_get_func(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (uint64_t)(rig->caps->has_get_func); +} + +SHIM_API uint64_t shim_rig_get_caps_has_set_func(hamlib_shim_handle_t h) { + RIG* rig = (RIG*)h; + return (uint64_t)(rig->caps->has_set_func); +} + +SHIM_API int shim_rig_sprintf_mode(uint64_t modes, char* buf, int buflen) { + if (!buf || buflen <= 0) return 0; + buf[0] = '\0'; + int pos = 0; + uint64_t mode; + for (mode = 1; mode != 0 && pos < buflen - 1; mode <<= 1) { + if (modes & mode) { + const char* name = rig_strrmode((rmode_t)mode); + if (name && name[0] != '?') { + int len = (int)strlen(name); + if (pos + len + 1 < buflen) { + if (pos > 0) buf[pos++] = ' '; + memcpy(buf + pos, name, len); + pos += len; + } + } + } + } + buf[pos] = '\0'; + return pos; +} + +/* ===== Rig type to string ===== */ + +SHIM_API const char* shim_rig_type_str(int rig_type) { + switch (rig_type & RIG_TYPE_MASK) { + case RIG_TYPE_TRANSCEIVER: return "Transceiver"; + case RIG_TYPE_HANDHELD: return "Handheld"; + case RIG_TYPE_MOBILE: return "Mobile"; + case RIG_TYPE_RECEIVER: return "Receiver"; + case RIG_TYPE_PCRECEIVER: return "PC Receiver"; + case RIG_TYPE_SCANNER: return "Scanner"; + case RIG_TYPE_TRUNKSCANNER: return "Trunk Scanner"; + case RIG_TYPE_COMPUTER: return "Computer"; + case RIG_TYPE_OTHER: return "Other"; + default: return "Unknown"; + } +} diff --git a/src/shim/hamlib_shim.h b/src/shim/hamlib_shim.h new file mode 100644 index 0000000..63005fe --- /dev/null +++ b/src/shim/hamlib_shim.h @@ -0,0 +1,511 @@ +/** + * hamlib_shim.h - Pure C interface layer for Hamlib + * + * This shim provides a compiler-safe C ABI boundary between the Node.js + * native addon (compiled with MSVC on Windows) and the Hamlib library + * (compiled with MinGW on Windows). + * + * On Linux/macOS: compiled as static library (.a), linked into addon + * On Windows: compiled as DLL (MinGW), loaded by addon (MSVC) + * + * All Hamlib struct access is encapsulated here to avoid cross-compiler + * struct layout differences. + */ + +#ifndef HAMLIB_SHIM_H +#define HAMLIB_SHIM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* DLL export/import macros */ +#ifdef _WIN32 + #ifdef HAMLIB_SHIM_BUILD + #define SHIM_API __declspec(dllexport) + #else + #define SHIM_API __declspec(dllimport) + #endif +#else + #define SHIM_API +#endif + +/* Opaque handle type - hides RIG* from the addon */ +typedef void* hamlib_shim_handle_t; + +/* ===== Constants (mirror Hamlib values) ===== */ + +/* Return codes */ +#define SHIM_RIG_OK 0 +#define SHIM_RIG_EINVAL -1 +#define SHIM_RIG_EIO -2 +#define SHIM_RIG_ENIMPL -3 +#define SHIM_RIG_ETIMEOUT -4 +#define SHIM_RIG_ENAVAIL -11 +#define SHIM_RIG_EPROTO -8 + +/* VFO constants */ +#define SHIM_RIG_VFO_NONE 0 +#define SHIM_RIG_VFO_CURR ((int)0x40000000) /* RIG_VFO_CURR */ +#define SHIM_RIG_VFO_MEM ((int)0x10000000) /* RIG_VFO_MEM */ +#define SHIM_RIG_VFO_A ((int)(1<<0)) /* RIG_VFO_A */ +#define SHIM_RIG_VFO_B ((int)(1<<1)) /* RIG_VFO_B */ + +/* Mode constants */ +#define SHIM_RIG_MODE_NONE 0 + +/* Split constants */ +#define SHIM_RIG_SPLIT_OFF 0 +#define SHIM_RIG_SPLIT_ON 1 + +/* PTT constants */ +#define SHIM_RIG_PTT_OFF 0 +#define SHIM_RIG_PTT_ON 1 + +/* DCD constants */ +#define SHIM_RIG_DCD_OFF 0 +#define SHIM_RIG_DCD_ON 1 + +/* Passband constants */ +#define SHIM_RIG_PASSBAND_NORMAL 0 + +/* Port types */ +#define SHIM_RIG_PORT_SERIAL 0 +#define SHIM_RIG_PORT_NETWORK 4 + +/* Scan types */ +#define SHIM_RIG_SCAN_STOP 0 +#define SHIM_RIG_SCAN_MEM 1 +#define SHIM_RIG_SCAN_VFO (1<<1) +#define SHIM_RIG_SCAN_PROG (1<<2) +#define SHIM_RIG_SCAN_DELTA (1<<3) +#define SHIM_RIG_SCAN_PRIO (1<<4) + +/* Transceive mode */ +#define SHIM_RIG_TRN_POLL 1 + +/* Power status */ +#define SHIM_RIG_POWER_UNKNOWN -1 + +/* PTT types (for port config) */ +#define SHIM_RIG_PTT_NONE 0 +#define SHIM_RIG_PTT_RIG 1 +#define SHIM_RIG_PTT_SERIAL_DTR 2 +#define SHIM_RIG_PTT_SERIAL_RTS 3 +#define SHIM_RIG_PTT_PARALLEL 4 +#define SHIM_RIG_PTT_CM108 8 +#define SHIM_RIG_PTT_GPIO 16 +#define SHIM_RIG_PTT_GPION 32 + +/* DCD types (for port config) */ +#define SHIM_RIG_DCD_NONE 0 +#define SHIM_RIG_DCD_RIG 1 +#define SHIM_RIG_DCD_SERIAL_DSR 2 +#define SHIM_RIG_DCD_SERIAL_CTS 3 +#define SHIM_RIG_DCD_SERIAL_CAR 4 +#define SHIM_RIG_DCD_PARALLEL 5 +#define SHIM_RIG_DCD_CM108 8 +#define SHIM_RIG_DCD_GPIO 16 +#define SHIM_RIG_DCD_GPION 32 + +/* Serial parity */ +#define SHIM_RIG_PARITY_NONE 0 +#define SHIM_RIG_PARITY_ODD 1 +#define SHIM_RIG_PARITY_EVEN 2 + +/* Serial handshake */ +#define SHIM_RIG_HANDSHAKE_NONE 0 +#define SHIM_RIG_HANDSHAKE_XONXOFF 1 +#define SHIM_RIG_HANDSHAKE_HARDWARE 2 + +/* Serial control state */ +#define SHIM_RIG_SIGNAL_UNSET 0 +#define SHIM_RIG_SIGNAL_ON 1 +#define SHIM_RIG_SIGNAL_OFF 2 + +/* Repeater shift */ +#define SHIM_RIG_RPT_SHIFT_NONE 0 + +/* Reset types */ +#define SHIM_RIG_RESET_NONE 0 +#define SHIM_RIG_RESET_SOFT 1 +#define SHIM_RIG_RESET_VFO 2 +#define SHIM_RIG_RESET_MCALL 4 +#define SHIM_RIG_RESET_MASTER 8 + +/* Antenna */ +#define SHIM_RIG_ANT_CURR 0 + +/* Rig type mask and types */ +#define SHIM_RIG_TYPE_MASK 0x7F000000 + +/* Max path length */ +#define SHIM_HAMLIB_FILPATHLEN 512 + +/* Max modes for iteration */ +#define SHIM_HAMLIB_MAX_MODES 64 + +/* ===== Level constants (bit positions for setting_t / uint64_t) ===== */ +#define SHIM_RIG_LEVEL_PREAMP (1ULL << 0) +#define SHIM_RIG_LEVEL_ATT (1ULL << 1) +#define SHIM_RIG_LEVEL_VOXDELAY (1ULL << 2) +#define SHIM_RIG_LEVEL_AF (1ULL << 3) +#define SHIM_RIG_LEVEL_RF (1ULL << 4) +#define SHIM_RIG_LEVEL_SQL (1ULL << 5) +#define SHIM_RIG_LEVEL_IF (1ULL << 6) +#define SHIM_RIG_LEVEL_APF (1ULL << 7) +#define SHIM_RIG_LEVEL_NR (1ULL << 8) +#define SHIM_RIG_LEVEL_PBT_IN (1ULL << 9) +#define SHIM_RIG_LEVEL_PBT_OUT (1ULL << 10) +#define SHIM_RIG_LEVEL_CWPITCH (1ULL << 11) +#define SHIM_RIG_LEVEL_RFPOWER (1ULL << 12) +#define SHIM_RIG_LEVEL_MICGAIN (1ULL << 13) +#define SHIM_RIG_LEVEL_KEYSPD (1ULL << 14) +#define SHIM_RIG_LEVEL_NOTCHF (1ULL << 15) +#define SHIM_RIG_LEVEL_COMP (1ULL << 16) +#define SHIM_RIG_LEVEL_AGC (1ULL << 17) +#define SHIM_RIG_LEVEL_BKINDL (1ULL << 18) +#define SHIM_RIG_LEVEL_BALANCE (1ULL << 19) +#define SHIM_RIG_LEVEL_METER (1ULL << 20) +#define SHIM_RIG_LEVEL_VOXGAIN (1ULL << 21) +#define SHIM_RIG_LEVEL_ANTIVOX (1ULL << 22) +#define SHIM_RIG_LEVEL_STRENGTH (1ULL << 26) +#define SHIM_RIG_LEVEL_RAWSTR (1ULL << 28) +#define SHIM_RIG_LEVEL_SWR (1ULL << 29) +#define SHIM_RIG_LEVEL_ALC (1ULL << 30) +#define SHIM_RIG_LEVEL_RFPOWER_METER (1ULL << 33) +#define SHIM_RIG_LEVEL_COMP_METER (1ULL << 34) +#define SHIM_RIG_LEVEL_VD_METER (1ULL << 35) +#define SHIM_RIG_LEVEL_ID_METER (1ULL << 36) +#define SHIM_RIG_LEVEL_TEMP_METER (1ULL << 42) + +/* ===== Function constants (bit positions for setting_t / uint64_t) ===== */ +#define SHIM_RIG_FUNC_FAGC (1ULL << 0) +#define SHIM_RIG_FUNC_NB (1ULL << 1) +#define SHIM_RIG_FUNC_COMP (1ULL << 2) +#define SHIM_RIG_FUNC_VOX (1ULL << 3) +#define SHIM_RIG_FUNC_TONE (1ULL << 4) +#define SHIM_RIG_FUNC_TSQL (1ULL << 5) +#define SHIM_RIG_FUNC_SBKIN (1ULL << 6) +#define SHIM_RIG_FUNC_FBKIN (1ULL << 7) +#define SHIM_RIG_FUNC_ANF (1ULL << 8) +#define SHIM_RIG_FUNC_NR (1ULL << 9) +#define SHIM_RIG_FUNC_AIP (1ULL << 10) +#define SHIM_RIG_FUNC_APF (1ULL << 11) +#define SHIM_RIG_FUNC_MON (1ULL << 12) +#define SHIM_RIG_FUNC_MN (1ULL << 13) +#define SHIM_RIG_FUNC_RF (1ULL << 14) +#define SHIM_RIG_FUNC_ARO (1ULL << 15) +#define SHIM_RIG_FUNC_LOCK (1ULL << 16) +#define SHIM_RIG_FUNC_MUTE (1ULL << 17) +#define SHIM_RIG_FUNC_VSC (1ULL << 18) +#define SHIM_RIG_FUNC_REV (1ULL << 19) +#define SHIM_RIG_FUNC_SQL (1ULL << 20) +#define SHIM_RIG_FUNC_ABM (1ULL << 21) +#define SHIM_RIG_FUNC_BC (1ULL << 22) +#define SHIM_RIG_FUNC_MBC (1ULL << 23) +#define SHIM_RIG_FUNC_RIT (1ULL << 24) +#define SHIM_RIG_FUNC_AFC (1ULL << 25) +#define SHIM_RIG_FUNC_SATMODE (1ULL << 26) +#define SHIM_RIG_FUNC_SCOPE (1ULL << 27) +#define SHIM_RIG_FUNC_RESUME (1ULL << 28) +#define SHIM_RIG_FUNC_TBURST (1ULL << 29) +#define SHIM_RIG_FUNC_TUNER (1ULL << 30) +#define SHIM_RIG_FUNC_XIT (1ULL << 31) + +/* ===== VFO operation constants ===== */ +#define SHIM_RIG_OP_CPY (1<<0) +#define SHIM_RIG_OP_XCHG (1<<1) +#define SHIM_RIG_OP_FROM_VFO (1<<2) +#define SHIM_RIG_OP_TO_VFO (1<<3) +#define SHIM_RIG_OP_MCL (1<<4) +#define SHIM_RIG_OP_UP (1<<5) +#define SHIM_RIG_OP_DOWN (1<<6) +#define SHIM_RIG_OP_BAND_UP (1<<7) +#define SHIM_RIG_OP_BAND_DOWN (1<<8) +#define SHIM_RIG_OP_LEFT (1<<9) +#define SHIM_RIG_OP_RIGHT (1<<10) +#define SHIM_RIG_OP_TUNE (1<<11) +#define SHIM_RIG_OP_TOGGLE (1<<12) + +/* ===== Repeater shift constants ===== */ +#define SHIM_RIG_RPT_SHIFT_MINUS 1 +#define SHIM_RIG_RPT_SHIFT_PLUS 2 + +/* ===== Simplified structs for cross-compiler safety ===== */ + +/* Simplified channel data for set/get memory channel */ +typedef struct { + int channel_num; + double freq; + double tx_freq; + int mode; /* rmode_t as int */ + int width; /* pbwidth_t as int */ + int split; /* split_t as int */ + int ctcss_tone; + int vfo; + char channel_desc[64]; +} shim_channel_t; + +/* Rig info for rig list enumeration */ +typedef struct { + unsigned int rig_model; + const char* model_name; + const char* mfg_name; + const char* version; + int status; + int rig_type; +} shim_rig_info_t; + +/* ===== Callback types ===== */ + +/* Frequency change callback: (handle, vfo, freq, arg) -> int */ +typedef int (*shim_freq_cb_t)(void* handle, int vfo, double freq, void* arg); + +/* PTT change callback: (handle, vfo, ptt, arg) -> int */ +typedef int (*shim_ptt_cb_t)(void* handle, int vfo, int ptt, void* arg); + +/* Rig list callback: (info, data) -> int */ +typedef int (*shim_rig_list_cb_t)(const shim_rig_info_t* info, void* data); + +/* ===== Lifecycle functions ===== */ + +SHIM_API hamlib_shim_handle_t shim_rig_init(unsigned int model); +SHIM_API int shim_rig_open(hamlib_shim_handle_t h); +SHIM_API int shim_rig_close(hamlib_shim_handle_t h); +SHIM_API int shim_rig_cleanup(hamlib_shim_handle_t h); +SHIM_API const char* shim_rigerror(int errcode); + +/* ===== Debug / Utility ===== */ + +SHIM_API void shim_rig_set_debug(int level); +SHIM_API int shim_rig_get_debug(void); +SHIM_API const char* shim_rig_get_version(void); +SHIM_API int shim_rig_load_all_backends(void); +SHIM_API int shim_rig_list_foreach(shim_rig_list_cb_t cb, void* data); +SHIM_API const char* shim_rig_strstatus(int status); + +/* ===== Port configuration (before open) ===== */ + +SHIM_API void shim_rig_set_port_path(hamlib_shim_handle_t h, const char* path); +SHIM_API void shim_rig_set_port_type(hamlib_shim_handle_t h, int type); + +/* Serial port configuration */ +SHIM_API void shim_rig_set_serial_rate(hamlib_shim_handle_t h, int rate); +SHIM_API int shim_rig_get_serial_rate(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_serial_data_bits(hamlib_shim_handle_t h, int bits); +SHIM_API int shim_rig_get_serial_data_bits(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_serial_stop_bits(hamlib_shim_handle_t h, int bits); +SHIM_API int shim_rig_get_serial_stop_bits(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_serial_parity(hamlib_shim_handle_t h, int parity); +SHIM_API int shim_rig_get_serial_parity(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_serial_handshake(hamlib_shim_handle_t h, int handshake); +SHIM_API int shim_rig_get_serial_handshake(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_serial_rts_state(hamlib_shim_handle_t h, int state); +SHIM_API int shim_rig_get_serial_rts_state(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_serial_dtr_state(hamlib_shim_handle_t h, int state); +SHIM_API int shim_rig_get_serial_dtr_state(hamlib_shim_handle_t h); + +/* Port timing configuration */ +SHIM_API void shim_rig_set_port_timeout(hamlib_shim_handle_t h, int ms); +SHIM_API int shim_rig_get_port_timeout(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_port_retry(hamlib_shim_handle_t h, int count); +SHIM_API int shim_rig_get_port_retry(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_port_write_delay(hamlib_shim_handle_t h, int ms); +SHIM_API int shim_rig_get_port_write_delay(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_port_post_write_delay(hamlib_shim_handle_t h, int ms); +SHIM_API int shim_rig_get_port_post_write_delay(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_port_flushx(hamlib_shim_handle_t h, int enable); +SHIM_API int shim_rig_get_port_flushx(hamlib_shim_handle_t h); + +/* PTT/DCD port type configuration */ +SHIM_API void shim_rig_set_ptt_type(hamlib_shim_handle_t h, int type); +SHIM_API int shim_rig_get_ptt_type(hamlib_shim_handle_t h); + +SHIM_API void shim_rig_set_dcd_type(hamlib_shim_handle_t h, int type); +SHIM_API int shim_rig_get_dcd_type(hamlib_shim_handle_t h); + +/* ===== Frequency control ===== */ + +SHIM_API int shim_rig_set_freq(hamlib_shim_handle_t h, int vfo, double freq); +SHIM_API int shim_rig_get_freq(hamlib_shim_handle_t h, int vfo, double* freq); + +/* ===== VFO control ===== */ + +SHIM_API int shim_rig_set_vfo(hamlib_shim_handle_t h, int vfo); +SHIM_API int shim_rig_get_vfo(hamlib_shim_handle_t h, int* vfo); + +/* ===== Mode control ===== */ + +SHIM_API int shim_rig_set_mode(hamlib_shim_handle_t h, int vfo, int mode, int width); +SHIM_API int shim_rig_get_mode(hamlib_shim_handle_t h, int vfo, int* mode, int* width); +SHIM_API int shim_rig_parse_mode(const char* mode_str); +SHIM_API const char* shim_rig_strrmode(int mode); +SHIM_API int shim_rig_passband_narrow(hamlib_shim_handle_t h, int mode); +SHIM_API int shim_rig_passband_wide(hamlib_shim_handle_t h, int mode); + +/* ===== PTT control ===== */ + +SHIM_API int shim_rig_set_ptt(hamlib_shim_handle_t h, int vfo, int ptt); +SHIM_API int shim_rig_get_ptt(hamlib_shim_handle_t h, int vfo, int* ptt); +SHIM_API int shim_rig_get_dcd(hamlib_shim_handle_t h, int vfo, int* dcd); + +/* ===== Signal strength ===== */ + +SHIM_API int shim_rig_get_strength(hamlib_shim_handle_t h, int vfo, int* strength); + +/* ===== Level control ===== */ + +SHIM_API int shim_rig_set_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float value); +SHIM_API int shim_rig_set_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int value); +SHIM_API int shim_rig_get_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float* value); +SHIM_API int shim_rig_get_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int* value); + +/* ===== Function control ===== */ + +SHIM_API int shim_rig_set_func(hamlib_shim_handle_t h, int vfo, uint64_t func, int enable); +SHIM_API int shim_rig_get_func(hamlib_shim_handle_t h, int vfo, uint64_t func, int* state); + +/* ===== Parameter control ===== */ + +SHIM_API int shim_rig_set_parm_f(hamlib_shim_handle_t h, uint64_t parm, float value); +SHIM_API int shim_rig_set_parm_i(hamlib_shim_handle_t h, uint64_t parm, int value); +SHIM_API int shim_rig_get_parm_f(hamlib_shim_handle_t h, uint64_t parm, float* value); +SHIM_API int shim_rig_get_parm_i(hamlib_shim_handle_t h, uint64_t parm, int* value); +SHIM_API uint64_t shim_rig_parse_parm(const char* parm_str); + +/* ===== Split operations ===== */ + +SHIM_API int shim_rig_set_split_freq(hamlib_shim_handle_t h, int vfo, double freq); +SHIM_API int shim_rig_get_split_freq(hamlib_shim_handle_t h, int vfo, double* freq); + +SHIM_API int shim_rig_set_split_vfo(hamlib_shim_handle_t h, int rx_vfo, int split, int tx_vfo); +SHIM_API int shim_rig_get_split_vfo(hamlib_shim_handle_t h, int vfo, int* split, int* tx_vfo); + +SHIM_API int shim_rig_set_split_mode(hamlib_shim_handle_t h, int vfo, int mode, int width); +SHIM_API int shim_rig_get_split_mode(hamlib_shim_handle_t h, int vfo, int* mode, int* width); + +SHIM_API int shim_rig_set_split_freq_mode(hamlib_shim_handle_t h, int vfo, double freq, int mode, int width); +SHIM_API int shim_rig_get_split_freq_mode(hamlib_shim_handle_t h, int vfo, double* freq, int* mode, int* width); + +/* ===== RIT/XIT control ===== */ + +SHIM_API int shim_rig_set_rit(hamlib_shim_handle_t h, int vfo, int offset); +SHIM_API int shim_rig_get_rit(hamlib_shim_handle_t h, int vfo, int* offset); +SHIM_API int shim_rig_set_xit(hamlib_shim_handle_t h, int vfo, int offset); +SHIM_API int shim_rig_get_xit(hamlib_shim_handle_t h, int vfo, int* offset); + +/* ===== Memory channel operations ===== */ + +SHIM_API int shim_rig_set_channel(hamlib_shim_handle_t h, int vfo, const shim_channel_t* chan); +SHIM_API int shim_rig_get_channel(hamlib_shim_handle_t h, int vfo, shim_channel_t* chan, int read_only); +SHIM_API int shim_rig_set_mem(hamlib_shim_handle_t h, int vfo, int ch); +SHIM_API int shim_rig_get_mem(hamlib_shim_handle_t h, int vfo, int* ch); +SHIM_API int shim_rig_set_bank(hamlib_shim_handle_t h, int vfo, int bank); +SHIM_API int shim_rig_mem_count(hamlib_shim_handle_t h); + +/* ===== Scanning ===== */ + +SHIM_API int shim_rig_scan(hamlib_shim_handle_t h, int vfo, int scan_type, int channel); + +/* ===== VFO operations ===== */ + +SHIM_API int shim_rig_vfo_op(hamlib_shim_handle_t h, int vfo, int op); + +/* ===== Antenna control ===== */ + +SHIM_API int shim_rig_set_ant(hamlib_shim_handle_t h, int vfo, int ant, float option); +SHIM_API int shim_rig_get_ant(hamlib_shim_handle_t h, int vfo, int ant, float* option, + int* ant_curr, int* ant_tx, int* ant_rx); + +/* ===== Tuning step ===== */ + +SHIM_API int shim_rig_set_ts(hamlib_shim_handle_t h, int vfo, int ts); +SHIM_API int shim_rig_get_ts(hamlib_shim_handle_t h, int vfo, int* ts); + +/* ===== Repeater control ===== */ + +SHIM_API int shim_rig_set_rptr_shift(hamlib_shim_handle_t h, int vfo, int shift); +SHIM_API int shim_rig_get_rptr_shift(hamlib_shim_handle_t h, int vfo, int* shift); +SHIM_API const char* shim_rig_strptrshift(int shift); +SHIM_API int shim_rig_set_rptr_offs(hamlib_shim_handle_t h, int vfo, int offset); +SHIM_API int shim_rig_get_rptr_offs(hamlib_shim_handle_t h, int vfo, int* offset); + +/* ===== CTCSS/DCS tone control ===== */ + +SHIM_API int shim_rig_set_ctcss_tone(hamlib_shim_handle_t h, int vfo, unsigned int tone); +SHIM_API int shim_rig_get_ctcss_tone(hamlib_shim_handle_t h, int vfo, unsigned int* tone); +SHIM_API int shim_rig_set_dcs_code(hamlib_shim_handle_t h, int vfo, unsigned int code); +SHIM_API int shim_rig_get_dcs_code(hamlib_shim_handle_t h, int vfo, unsigned int* code); +SHIM_API int shim_rig_set_ctcss_sql(hamlib_shim_handle_t h, int vfo, unsigned int tone); +SHIM_API int shim_rig_get_ctcss_sql(hamlib_shim_handle_t h, int vfo, unsigned int* tone); +SHIM_API int shim_rig_set_dcs_sql(hamlib_shim_handle_t h, int vfo, unsigned int code); +SHIM_API int shim_rig_get_dcs_sql(hamlib_shim_handle_t h, int vfo, unsigned int* code); + +/* ===== DTMF ===== */ + +SHIM_API int shim_rig_send_dtmf(hamlib_shim_handle_t h, int vfo, const char* digits); +SHIM_API int shim_rig_recv_dtmf(hamlib_shim_handle_t h, int vfo, char* digits, int* length); + +/* ===== Morse code ===== */ + +SHIM_API int shim_rig_send_morse(hamlib_shim_handle_t h, int vfo, const char* msg); +SHIM_API int shim_rig_stop_morse(hamlib_shim_handle_t h, int vfo); +SHIM_API int shim_rig_wait_morse(hamlib_shim_handle_t h, int vfo); + +/* ===== Voice memory ===== */ + +SHIM_API int shim_rig_send_voice_mem(hamlib_shim_handle_t h, int vfo, int ch); +SHIM_API int shim_rig_stop_voice_mem(hamlib_shim_handle_t h, int vfo); + +/* ===== Power control ===== */ + +SHIM_API int shim_rig_set_powerstat(hamlib_shim_handle_t h, int status); +SHIM_API int shim_rig_get_powerstat(hamlib_shim_handle_t h, int* status); + +/* ===== Power conversion ===== */ + +SHIM_API int shim_rig_power2mW(hamlib_shim_handle_t h, unsigned int* mwpower, float power, double freq, int mode); +SHIM_API int shim_rig_mW2power(hamlib_shim_handle_t h, float* power, unsigned int mwpower, double freq, int mode); + +/* ===== Reset ===== */ + +SHIM_API int shim_rig_reset(hamlib_shim_handle_t h, int reset_type); + +/* ===== Callbacks ===== */ + +SHIM_API int shim_rig_set_freq_callback(hamlib_shim_handle_t h, shim_freq_cb_t cb, void* arg); +SHIM_API int shim_rig_set_ptt_callback(hamlib_shim_handle_t h, shim_ptt_cb_t cb, void* arg); +SHIM_API int shim_rig_set_trn(hamlib_shim_handle_t h, int trn); + +/* ===== Capability queries (replaces direct caps-> access) ===== */ + +SHIM_API uint64_t shim_rig_get_mode_list(hamlib_shim_handle_t h); +SHIM_API uint64_t shim_rig_get_caps_has_get_level(hamlib_shim_handle_t h); +SHIM_API uint64_t shim_rig_get_caps_has_set_level(hamlib_shim_handle_t h); +SHIM_API uint64_t shim_rig_get_caps_has_get_func(hamlib_shim_handle_t h); +SHIM_API uint64_t shim_rig_get_caps_has_set_func(hamlib_shim_handle_t h); + +/* Format mode bitmask to string list */ +SHIM_API int shim_rig_sprintf_mode(uint64_t modes, char* buf, int buflen); + +/* Rig type to string conversion */ +SHIM_API const char* shim_rig_type_str(int rig_type); + +#ifdef __cplusplus +} +#endif + +#endif /* HAMLIB_SHIM_H */ diff --git a/test/test_ci_functional.js b/test/test_ci_functional.js new file mode 100644 index 0000000..e2bc105 --- /dev/null +++ b/test/test_ci_functional.js @@ -0,0 +1,225 @@ +#!/usr/bin/env node + +/** + * CI Functional Test - validates compiled binary works correctly + * Uses Hamlib Dummy device (Model 1) directly, no rigctld needed. + * Tests core API operations to ensure the native addon is functional. + */ + +const { HamLib } = require('../index.js'); + +let passed = 0; +let failed = 0; + +function ok(desc) { + passed++; + console.log(` PASS: ${desc}`); +} + +function fail(desc, err) { + failed++; + console.log(` FAIL: ${desc} - ${err}`); +} + +async function test(desc, fn) { + try { + await fn(); + ok(desc); + } catch (e) { + fail(desc, e.message.split('\n')[0]); + } +} + +function assert(condition, msg) { + if (!condition) throw new Error(msg || 'Assertion failed'); +} + +async function run() { + console.log('=== CI Functional Test ===\n'); + + // --- Static methods --- + console.log('[Static Methods]'); + + await test('getHamlibVersion returns string', () => { + const ver = HamLib.getHamlibVersion(); + assert(typeof ver === 'string' && ver.length > 0, `got: ${ver}`); + }); + + await test('getSupportedRigs returns non-empty array', () => { + const rigs = HamLib.getSupportedRigs(); + assert(Array.isArray(rigs) && rigs.length > 100, `got ${rigs.length} rigs`); + assert(rigs[0].rigModel !== undefined, 'rig entry missing rigModel'); + assert(rigs[0].modelName !== undefined, 'rig entry missing modelName'); + }); + + // --- Instance lifecycle --- + console.log('\n[Instance Lifecycle]'); + + const rig = new HamLib(1); + + await test('constructor creates instance', () => { + assert(rig !== null && rig !== undefined); + }); + + await test('getConnectionInfo before open', () => { + const info = rig.getConnectionInfo(); + assert(info.isOpen === false, 'should not be open yet'); + assert(info.originalModel === 1, `model should be 1, got ${info.originalModel}`); + }); + + await test('open() succeeds', async () => { + const result = await rig.open(); + assert(result === 0, `expected 0, got ${result}`); + }); + + await test('getConnectionInfo after open', () => { + const info = rig.getConnectionInfo(); + assert(info.isOpen === true, 'should be open'); + }); + + // --- VFO operations --- + console.log('\n[VFO Operations]'); + + await test('setVfo VFO-A', async () => { + await rig.setVfo('VFO-A'); + }); + + await test('getVfo returns VFO-A', async () => { + const vfo = await rig.getVfo(); + assert(vfo === 'VFO-A', `expected VFO-A, got ${vfo}`); + }); + + await test('setVfo VFO-B', async () => { + await rig.setVfo('VFO-B'); + }); + + await test('getVfo returns VFO-B', async () => { + const vfo = await rig.getVfo(); + assert(vfo === 'VFO-B', `expected VFO-B, got ${vfo}`); + }); + + // --- Frequency operations --- + console.log('\n[Frequency Operations]'); + + await test('setFrequency 144.39MHz on VFO-A', async () => { + await rig.setFrequency(144390000, 'VFO-A'); + }); + + await test('getFrequency returns 144.39MHz', async () => { + const freq = await rig.getFrequency('VFO-A'); + assert(freq === 144390000, `expected 144390000, got ${freq}`); + }); + + await test('setFrequency 432.1MHz on VFO-B', async () => { + await rig.setFrequency(432100000, 'VFO-B'); + }); + + await test('getFrequency VFO-B returns 432.1MHz', async () => { + const freq = await rig.getFrequency('VFO-B'); + assert(freq === 432100000, `expected 432100000, got ${freq}`); + }); + + // --- PTT operations --- + console.log('\n[PTT Operations]'); + + await test('setPtt on', async () => { + await rig.setPtt(true); + }); + + await test('getPtt returns true', async () => { + const ptt = await rig.getPtt(); + assert(ptt === true, `expected true, got ${ptt}`); + }); + + await test('setPtt off', async () => { + await rig.setPtt(false); + }); + + await test('getPtt returns false', async () => { + const ptt = await rig.getPtt(); + assert(ptt === false, `expected false, got ${ptt}`); + }); + + // --- Serial config --- + console.log('\n[Serial Configuration]'); + + await test('setSerialConfig rate', async () => { + await rig.setSerialConfig('rate', '115200'); + }); + + await test('getSerialConfig rate', async () => { + const rate = await rig.getSerialConfig('rate'); + assert(rate === '115200', `expected 115200, got ${rate}`); + }); + + await test('setSerialConfig data_bits', async () => { + await rig.setSerialConfig('data_bits', '8'); + }); + + await test('getSerialConfig data_bits', async () => { + const bits = await rig.getSerialConfig('data_bits'); + assert(bits === '8', `expected 8, got ${bits}`); + }); + + await test('getSupportedSerialConfigs returns config object', () => { + const configs = rig.getSupportedSerialConfigs(); + assert(configs.serial && configs.serial.data_bits, 'missing serial.data_bits'); + }); + + // --- PTT/DCD type --- + console.log('\n[PTT/DCD Type]'); + + await test('setPttType RIG', async () => { + await rig.setPttType('RIG'); + }); + + await test('getPttType returns RIG', async () => { + const type = await rig.getPttType(); + assert(type === 'RIG', `expected RIG, got ${type}`); + }); + + await test('setDcdType RIG', async () => { + await rig.setDcdType('RIG'); + }); + + await test('getDcdType returns RIG', async () => { + const type = await rig.getDcdType(); + assert(type === 'RIG', `expected RIG, got ${type}`); + }); + + // --- Powerstat --- + console.log('\n[Power Control]'); + + await test('setPowerstat on', async () => { + await rig.setPowerstat(1); + }); + + await test('getPowerstat returns 1', async () => { + const ps = await rig.getPowerstat(); + assert(ps === 1, `expected 1, got ${ps}`); + }); + + // --- Cleanup --- + console.log('\n[Cleanup]'); + + await test('close() succeeds', async () => { + await rig.close(); + }); + + await test('destroy() succeeds', async () => { + await rig.destroy(); + }); + + // --- Summary --- + const total = passed + failed; + console.log(`\n=== Results: ${passed}/${total} passed, ${failed} failed ===`); + + if (failed > 0) { + process.exit(1); + } +} + +run().catch(err => { + console.error('Fatal error:', err); + process.exit(1); +});