From 7cdf02fdc0907c168bd46536b0e995ae59b33cd5 Mon Sep 17 00:00:00 2001
From: Brendan <2bndy5@gmail.com>
Date: Thu, 10 Oct 2024 03:31:58 -0700
Subject: [PATCH] add node binding
---
.github/workflows/node-packaging.yml | 217 +++++++++
.gitignore | 166 ++++++-
Cargo.toml | 6 +-
cspell.config.yml | 10 +
package.json | 16 +
rf24-node/.cargo/config.toml | 5 +
rf24-node/.gitignore | 197 ++++++++
rf24-node/.npmignore | 13 +
rf24-node/.yarnrc.yml | 1 +
rf24-node/Cargo.toml | 19 +
rf24-node/build.rs | 5 +
rf24-node/index.d.ts | 132 +++++
rf24-node/index.js | 319 ++++++++++++
rf24-node/npm/android-arm-eabi/README.md | 3 +
rf24-node/npm/android-arm-eabi/package.json | 18 +
rf24-node/npm/android-arm64/README.md | 3 +
rf24-node/npm/android-arm64/package.json | 18 +
rf24-node/npm/darwin-arm64/README.md | 3 +
rf24-node/npm/darwin-arm64/package.json | 18 +
rf24-node/npm/darwin-universal/README.md | 3 +
rf24-node/npm/darwin-universal/package.json | 15 +
rf24-node/npm/darwin-x64/README.md | 3 +
rf24-node/npm/darwin-x64/package.json | 18 +
rf24-node/npm/linux-arm-gnueabihf/README.md | 3 +
.../npm/linux-arm-gnueabihf/package.json | 18 +
rf24-node/npm/linux-arm-musleabihf/README.md | 3 +
.../npm/linux-arm-musleabihf/package.json | 18 +
rf24-node/npm/linux-arm64-gnu/README.md | 3 +
rf24-node/npm/linux-arm64-gnu/package.json | 21 +
rf24-node/npm/linux-arm64-musl/README.md | 3 +
rf24-node/npm/linux-arm64-musl/package.json | 21 +
rf24-node/npm/linux-riscv64-gnu/README.md | 3 +
rf24-node/npm/linux-riscv64-gnu/package.json | 21 +
rf24-node/npm/linux-x64-gnu/README.md | 3 +
rf24-node/npm/linux-x64-gnu/package.json | 21 +
rf24-node/npm/linux-x64-musl/README.md | 3 +
rf24-node/npm/linux-x64-musl/package.json | 21 +
rf24-node/npm/win32-arm64-msvc/README.md | 3 +
rf24-node/npm/win32-arm64-msvc/package.json | 18 +
rf24-node/npm/win32-ia32-msvc/README.md | 3 +
rf24-node/npm/win32-ia32-msvc/package.json | 18 +
rf24-node/npm/win32-x64-msvc/README.md | 3 +
rf24-node/npm/win32-x64-msvc/package.json | 18 +
rf24-node/package.json | 46 ++
rf24-node/src/enums.rs | 152 ++++++
rf24-node/src/lib.rs | 6 +
rf24-node/src/radio.rs | 454 ++++++++++++++++++
yarn.lock | 20 +
48 files changed, 2104 insertions(+), 7 deletions(-)
create mode 100644 .github/workflows/node-packaging.yml
create mode 100644 package.json
create mode 100644 rf24-node/.cargo/config.toml
create mode 100644 rf24-node/.gitignore
create mode 100644 rf24-node/.npmignore
create mode 100644 rf24-node/.yarnrc.yml
create mode 100644 rf24-node/Cargo.toml
create mode 100644 rf24-node/build.rs
create mode 100644 rf24-node/index.d.ts
create mode 100644 rf24-node/index.js
create mode 100644 rf24-node/npm/android-arm-eabi/README.md
create mode 100644 rf24-node/npm/android-arm-eabi/package.json
create mode 100644 rf24-node/npm/android-arm64/README.md
create mode 100644 rf24-node/npm/android-arm64/package.json
create mode 100644 rf24-node/npm/darwin-arm64/README.md
create mode 100644 rf24-node/npm/darwin-arm64/package.json
create mode 100644 rf24-node/npm/darwin-universal/README.md
create mode 100644 rf24-node/npm/darwin-universal/package.json
create mode 100644 rf24-node/npm/darwin-x64/README.md
create mode 100644 rf24-node/npm/darwin-x64/package.json
create mode 100644 rf24-node/npm/linux-arm-gnueabihf/README.md
create mode 100644 rf24-node/npm/linux-arm-gnueabihf/package.json
create mode 100644 rf24-node/npm/linux-arm-musleabihf/README.md
create mode 100644 rf24-node/npm/linux-arm-musleabihf/package.json
create mode 100644 rf24-node/npm/linux-arm64-gnu/README.md
create mode 100644 rf24-node/npm/linux-arm64-gnu/package.json
create mode 100644 rf24-node/npm/linux-arm64-musl/README.md
create mode 100644 rf24-node/npm/linux-arm64-musl/package.json
create mode 100644 rf24-node/npm/linux-riscv64-gnu/README.md
create mode 100644 rf24-node/npm/linux-riscv64-gnu/package.json
create mode 100644 rf24-node/npm/linux-x64-gnu/README.md
create mode 100644 rf24-node/npm/linux-x64-gnu/package.json
create mode 100644 rf24-node/npm/linux-x64-musl/README.md
create mode 100644 rf24-node/npm/linux-x64-musl/package.json
create mode 100644 rf24-node/npm/win32-arm64-msvc/README.md
create mode 100644 rf24-node/npm/win32-arm64-msvc/package.json
create mode 100644 rf24-node/npm/win32-ia32-msvc/README.md
create mode 100644 rf24-node/npm/win32-ia32-msvc/package.json
create mode 100644 rf24-node/npm/win32-x64-msvc/README.md
create mode 100644 rf24-node/npm/win32-x64-msvc/package.json
create mode 100644 rf24-node/package.json
create mode 100644 rf24-node/src/enums.rs
create mode 100644 rf24-node/src/lib.rs
create mode 100644 rf24-node/src/radio.rs
create mode 100644 yarn.lock
diff --git a/.github/workflows/node-packaging.yml b/.github/workflows/node-packaging.yml
new file mode 100644
index 0000000..f8b3ed4
--- /dev/null
+++ b/.github/workflows/node-packaging.yml
@@ -0,0 +1,217 @@
+name: Node.js Builds
+env:
+ DEBUG: napi:*
+ ARTIFACT_PATH: rf24-node/rf24.*.node
+ MACOSX_DEPLOYMENT_TARGET: '10.13'
+on:
+ push:
+ branches: [main]
+ tags: ['v*']
+ paths:
+ - 'lib/src/**'
+ - 'rf24-node/**'
+ - '!**/*.md'
+ pull_request:
+ branches: [main]
+jobs:
+ build:
+ strategy:
+ fail-fast: false
+ matrix:
+ settings:
+ - host: macos-latest
+ target: x86_64-apple-darwin
+ build: yarn build --target x86_64-apple-darwin
+ - host: windows-latest
+ build: yarn build --target x86_64-pc-windows-msvc
+ target: x86_64-pc-windows-msvc
+ - host: windows-latest
+ build: yarn build --target i686-pc-windows-msvc
+ target: i686-pc-windows-msvc
+ - host: ubuntu-latest
+ target: x86_64-unknown-linux-gnu
+ docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
+ build: yarn build --target x86_64-unknown-linux-gnu
+ - host: ubuntu-latest
+ target: x86_64-unknown-linux-musl
+ docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
+ build: yarn build --target x86_64-unknown-linux-musl
+ - host: macos-latest
+ target: aarch64-apple-darwin
+ build: yarn build --target aarch64-apple-darwin
+ - host: ubuntu-latest
+ target: aarch64-unknown-linux-gnu
+ docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
+ build: yarn build --target aarch64-unknown-linux-gnu
+ - host: ubuntu-latest
+ target: armv7-unknown-linux-gnueabihf
+ setup: |
+ sudo apt-get update
+ sudo apt-get install gcc-arm-linux-gnueabihf -y
+ build: yarn build --target armv7-unknown-linux-gnueabihf
+ - host: ubuntu-latest
+ target: armv7-unknown-linux-musleabihf
+ build: yarn build --target armv7-unknown-linux-musleabihf
+ - host: ubuntu-latest
+ target: aarch64-linux-android
+ build: yarn build --target aarch64-linux-android
+ - host: ubuntu-latest
+ target: armv7-linux-androideabi
+ build: yarn build --target armv7-linux-androideabi
+ - host: ubuntu-latest
+ target: aarch64-unknown-linux-musl
+ docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
+ build: |-
+ set -e &&
+ rustup target add aarch64-unknown-linux-musl &&
+ yarn build --target aarch64-unknown-linux-musl
+ - host: windows-latest
+ target: aarch64-pc-windows-msvc
+ build: yarn build --target aarch64-pc-windows-msvc
+ - host: ubuntu-latest
+ target: riscv64gc-unknown-linux-gnu
+ setup: |
+ sudo apt-get update
+ sudo apt-get install gcc-riscv64-linux-gnu -y
+ build: yarn build --target riscv64gc-unknown-linux-gnu
+ name: stable - ${{ matrix.settings.target }} - node@20
+ runs-on: ${{ matrix.settings.host }}
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup node
+ uses: actions/setup-node@v4
+ if: ${{ !matrix.settings.docker }}
+ with:
+ node-version: 20
+ cache: yarn
+ - name: Install
+ uses: dtolnay/rust-toolchain@stable
+ if: ${{ !matrix.settings.docker }}
+ with:
+ toolchain: stable
+ targets: ${{ matrix.settings.target }}
+ - name: Cache cargo
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ .cargo-cache
+ target/
+ key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}
+ - uses: goto-bus-stop/setup-zig@v2
+ if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' || matrix.settings.target == 'armv7-unknown-linux-musleabihf' }}
+ with:
+ version: 0.13.0
+ - name: Setup toolchain
+ run: ${{ matrix.settings.setup }}
+ if: ${{ matrix.settings.setup }}
+ shell: bash
+ - name: Setup node x86
+ if: matrix.settings.target == 'i686-pc-windows-msvc'
+ run: yarn config set supportedArchitectures.cpu "ia32"
+ shell: bash
+ - name: Install dependencies
+ run: yarn install
+ - name: Setup node x86
+ uses: actions/setup-node@v4
+ if: matrix.settings.target == 'i686-pc-windows-msvc'
+ with:
+ node-version: 20
+ cache: yarn
+ architecture: x86
+ - name: Build in docker
+ uses: addnab/docker-run-action@v3
+ if: ${{ matrix.settings.docker }}
+ with:
+ image: ${{ matrix.settings.docker }}
+ options: '--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build'
+ run: ${{ matrix.settings.build }}
+ - name: Build
+ run: ${{ matrix.settings.build }}
+ if: ${{ !matrix.settings.docker }}
+ shell: bash
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: bindings-${{ matrix.settings.target }}
+ path: ${{ env.ARTIFACT_PATH }}
+ if-no-files-found: error
+
+ universal-macOS:
+ name: Build universal macOS binary
+ needs:
+ - build
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: yarn
+ - name: Install dependencies
+ run: yarn install
+ - name: Download macOS x64 artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: bindings-x86_64-apple-darwin
+ path: rf24-node/artifacts
+ - name: Download macOS arm64 artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: bindings-aarch64-apple-darwin
+ path: rf24-node/artifacts
+ - name: Combine binaries
+ run: yarn universal
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: bindings-universal-apple-darwin
+ path: ${{ env.ARTIFACT_PATH }}
+ if-no-files-found: error
+ publish:
+ name: Publish
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ id-token: write
+ needs:
+ - build
+ - universal-macOS
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: yarn
+ - name: Install dependencies
+ run: yarn install
+ - name: Download all artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: rf24-node/artifacts
+ - name: Move artifacts
+ run: yarn artifacts
+ - name: List packages
+ run: ls -R ./rf24-node/npm
+ shell: bash
+ - name: Publish
+ run: |
+ npm config set provenance true
+ if git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+$";
+ then
+ echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
+ npm publish --access public
+ elif git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+";
+ then
+ echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
+ npm publish --tag next --access public
+ else
+ echo "Not a release, skipping publish"
+ fi
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 6b1af17..cd5f6fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,145 @@
-# Created by https://www.toptal.com/developers/gitignore/api/rust,python
-# Edit at https://www.toptal.com/developers/gitignore?templates=rust,python
+# Created by https://www.toptal.com/developers/gitignore/api/rust,python,node,yarn
+# Edit at https://www.toptal.com/developers/gitignore?templates=rust,python,node,yarn
+
+### Node ###
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+### Node Patch ###
+# Serverless Webpack directories
+.webpack/
+
+# Optional stylelint cache
+
+# SvelteKit build / generate output
+.svelte-kit
### Python ###
# Byte-compiled / optimized / DLL files
@@ -46,7 +186,6 @@ htmlcov/
.nox/
.coverage
.coverage.*
-.cache
nosetests.xml
coverage.xml
*.cover
@@ -60,7 +199,6 @@ cover/
*.pot
# Django stuff:
-*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
@@ -124,7 +262,6 @@ celerybeat.pid
*.sage.py
# Environments
-.env
.venv
env/
venv/
@@ -188,7 +325,24 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
-# End of https://www.toptal.com/developers/gitignore/api/rust,python
+### yarn ###
+# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
+
+.yarn/*
+!.yarn/releases
+!.yarn/patches
+!.yarn/plugins
+!.yarn/sdks
+!.yarn/versions
+
+# if you are NOT using Zero-installs, then:
+# comment the following lines
+# !.yarn/cache
+
+# and uncomment the following lines
+# .pnp.*
+
+# End of https://www.toptal.com/developers/gitignore/api/rust,python,node,yarn
# .vscode settings
.vscode/
diff --git a/Cargo.toml b/Cargo.toml
index c898417..10a6295 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
-members = ["lib", "examples", "rf24-py"]
+members = ["lib", "examples", "rf24-py", "rf24-node"]
default-members = ["lib"]
resolver = "2"
@@ -10,3 +10,7 @@ homepage = "https://nRF24.github.io/rf24-rs"
edition = "2021"
rust-version = "1.70"
license-file = "LICENSE"
+
+[profile.release]
+lto = true
+strip = "symbols"
diff --git a/cspell.config.yml b/cspell.config.yml
index 743c8fa..988829c 100644
--- a/cspell.config.yml
+++ b/cspell.config.yml
@@ -1,10 +1,16 @@
version: "0.2"
words:
+ - aarch
+ - androideabi
+ - armv
+ - bindgen
- bytearray
- Cdev
- Doherty
- DYNPD
+ - eabi
- fontawesome
+ - gnueabihf
- gpio
- gpiochip
- inlinehilite
@@ -13,11 +19,15 @@ words:
- Mbps
- milliwatts
- mkdocs
+ - msvc
+ - musleabihf
+ - napi
- pyclass
- pymdownx
- pymethods
- pymodule
- RETR
+ - riscv
- rustc
- RXADDR
- Spidev
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9567963
--- /dev/null
+++ b/package.json
@@ -0,0 +1,16 @@
+{
+ "private": true,
+ "workspaces": [
+ "rf24-node"
+ ],
+ "scripts": {
+ "artifacts": "cd rf24-node && yarn artifacts",
+ "build": "cd rf24-node && yarn build",
+ "build:debug": "cd rf24-node && yarn build:debug",
+ "prepublishOnly": "cd rf24-node && yarn prepublishOnly",
+ "universal": "cd rf24-node && yarn universal",
+ "version": "cd rf24-node && yarn version"
+ },
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
+ "version": "0.1.0"
+}
diff --git a/rf24-node/.cargo/config.toml b/rf24-node/.cargo/config.toml
new file mode 100644
index 0000000..0651654
--- /dev/null
+++ b/rf24-node/.cargo/config.toml
@@ -0,0 +1,5 @@
+[target.aarch64-unknown-linux-musl]
+linker = "aarch64-linux-musl-gcc"
+rustflags = ["-C", "target-feature=-crt-static"]
+[target.x86_64-pc-windows-msvc]
+rustflags = ["-C", "target-feature=+crt-static"]
\ No newline at end of file
diff --git a/rf24-node/.gitignore b/rf24-node/.gitignore
new file mode 100644
index 0000000..a2b5be1
--- /dev/null
+++ b/rf24-node/.gitignore
@@ -0,0 +1,197 @@
+# Created by https://www.toptal.com/developers/gitignore/api/node
+# Edit at https://www.toptal.com/developers/gitignore?templates=node
+
+### Node ###
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+.env.test
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+
+# Next.js build output
+.next
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# End of https://www.toptal.com/developers/gitignore/api/node
+
+# Created by https://www.toptal.com/developers/gitignore/api/macos
+# Edit at https://www.toptal.com/developers/gitignore?templates=macos
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### macOS Patch ###
+# iCloud generated files
+*.icloud
+
+# End of https://www.toptal.com/developers/gitignore/api/macos
+
+# Created by https://www.toptal.com/developers/gitignore/api/windows
+# Edit at https://www.toptal.com/developers/gitignore?templates=windows
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.toptal.com/developers/gitignore/api/windows
+
+#Added by cargo
+
+/target
+Cargo.lock
+
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
+
+*.node
diff --git a/rf24-node/.npmignore b/rf24-node/.npmignore
new file mode 100644
index 0000000..ec144db
--- /dev/null
+++ b/rf24-node/.npmignore
@@ -0,0 +1,13 @@
+target
+Cargo.lock
+.cargo
+.github
+npm
+.eslintrc
+.prettierignore
+rustfmt.toml
+yarn.lock
+*.node
+.yarn
+__test__
+renovate.json
diff --git a/rf24-node/.yarnrc.yml b/rf24-node/.yarnrc.yml
new file mode 100644
index 0000000..3186f3f
--- /dev/null
+++ b/rf24-node/.yarnrc.yml
@@ -0,0 +1 @@
+nodeLinker: node-modules
diff --git a/rf24-node/Cargo.toml b/rf24-node/Cargo.toml
new file mode 100644
index 0000000..a135875
--- /dev/null
+++ b/rf24-node/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+edition = "2021"
+name = "rf24_rf24"
+version = "0.0.0"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
+napi = { version = "2.12.2", default-features = false, features = ["napi4"] }
+napi-derive = "2.12.2"
+
+[build-dependencies]
+napi-build = "2.0.1"
+
+[target.'cfg(target_os = "linux")'.dependencies]
+linux-embedded-hal = "0.4.0"
+rf24-rs = { path = "../lib" }
diff --git a/rf24-node/build.rs b/rf24-node/build.rs
new file mode 100644
index 0000000..9fc2367
--- /dev/null
+++ b/rf24-node/build.rs
@@ -0,0 +1,5 @@
+extern crate napi_build;
+
+fn main() {
+ napi_build::setup();
+}
diff --git a/rf24-node/index.d.ts b/rf24-node/index.d.ts
new file mode 100644
index 0000000..343e5db
--- /dev/null
+++ b/rf24-node/index.d.ts
@@ -0,0 +1,132 @@
+/* tslint:disable */
+/* eslint-disable */
+
+/* auto-generated by NAPI-RS */
+
+/** The return type for `RF24.getStatusFlags()` */
+export interface StatusFlags {
+ rxDr: boolean
+ txDs: boolean
+ txDf: boolean
+}
+/** The return type for `RF24.availablePipe()` */
+export interface AvailablePipe {
+ available: boolean
+ pipe: number
+}
+/**
+ * Power Amplifier level. The units dBm (decibel-milliwatts or dBmW)
+ * represents a logarithmic signal loss.
+ */
+export const enum PaLevel {
+ /**
+ * | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ * | :-------:|:--------------------------:|:---------------------------:|
+ * | -18 dBm | -6 dBm | -12 dBm |
+ */
+ MIN = 0,
+ /**
+ * | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ * | :-------:|:--------------------------:|:---------------------------:|
+ * | -12 dBm | 0 dBm | -4 dBm |
+ */
+ LOW = 1,
+ /**
+ * | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ * | :-------:|:--------------------------:|:---------------------------:|
+ * | -6 dBm | 3 dBm | 1 dBm |
+ */
+ HIGH = 2,
+ /**
+ * | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ * | :-------:|:--------------------------:|:---------------------------:|
+ * | 0 dBm | 7 dBm | 4 dBm |
+ */
+ MAX = 3
+}
+/** How fast data moves through the air. Units are in bits per second (bps). */
+export const enum DataRate {
+ /** represents 1 Mbps */
+ Mbps1 = 0,
+ /** represents 2 Mbps */
+ Mbps2 = 1,
+ /** represents 250 Kbps */
+ Kbps250 = 2
+}
+/**
+ * The length of a CRC checksum that is used (if any).
+ *
+ * Cyclical Redundancy Checking (CRC) is commonly used to ensure data integrity.
+ */
+export const enum CrcLength {
+ /** represents no CRC checksum is used */
+ DISABLED = 0,
+ /** represents CRC 8 bit checksum is used */
+ BIT8 = 1,
+ /** represents CRC 16 bit checksum is used */
+ BIT16 = 2
+}
+/** The possible states of a FIFO. */
+export const enum FifoState {
+ /** Represent the state of a FIFO when it is full. */
+ Full = 0,
+ /** Represent the state of a FIFO when it is empty. */
+ Empty = 1,
+ /** Represent the state of a FIFO when it is not full but not empty either. */
+ Occupied = 2
+}
+export type NodeRF24 = RF24
+export declare class RF24 {
+ constructor(cePin: number, csPin: number, devGpioChip: number, devSpiBus: number, spiSpeed: number)
+ begin(): void
+ startListening(): void
+ stopListening(): void
+ send(buf: Uint8Array, askNoAck: boolean): boolean
+ write(buf: Uint8Array, askNoAck: boolean, startTx: boolean): boolean
+ read(len: number): Buffer
+ resend(): boolean
+ rewrite(): void
+ getLastArc(): number
+ isPlusVariant(): boolean
+ testRpd(): boolean
+ startCarrierWave(level: PaLevel, channel: number): void
+ stopCarrierWave(): void
+ setLna(enable: boolean): void
+ allowAckPayloads(enable: boolean): void
+ setAutoAck(enable: boolean): void
+ setAutoAckPipe(enable: boolean, pipe: number): void
+ allowAskNoAck(enable: boolean): void
+ writeAckPayload(pipe: number, buf: Uint8Array): boolean
+ setAutoRetries(delay: number, count: number): void
+ setChannel(channel: number): void
+ getChannel(): number
+ getCrcLength(): CrcLength
+ setCrcLength(crcLength: CrcLength): void
+ getDataRate(): DataRate
+ setDataRate(dataRate: DataRate): void
+ available(): boolean
+ availablePipe(): AvailablePipe
+ /** Use this to discard all 3 layers in the radio's RX FIFO. */
+ flushRx(): void
+ /** Use this to discard all 3 layers in the radio's TX FIFO. */
+ flushTx(): void
+ getFifoState(aboutTx: boolean): FifoState
+ getPaLevel(): PaLevel
+ setPaLevel(paLevel: PaLevel): void
+ setPayloadLength(length: number): void
+ getPayloadLength(): number
+ setDynamicPayloads(enable: boolean): void
+ getDynamicPayloadLength(): number
+ openRxPipe(pipe: number, address: Uint8Array): void
+ openTxPipe(address: Uint8Array): void
+ /** If the given `pipe` number is not in range [0, 5], then this function does nothing. */
+ closeRxPipe(pipe: number): void
+ setAddressLength(length: number): void
+ getAddressLength(): number
+ powerDown(): void
+ powerUp(delay?: number | undefined | null): void
+ setStatusFlags(rxDr: boolean, txDs: boolean, txDf: boolean): void
+ clearStatusFlags(rxDr: boolean, txDs: boolean, txDf: boolean): void
+ update(): void
+ getStatusFlags(): StatusFlags
+}
diff --git a/rf24-node/index.js b/rf24-node/index.js
new file mode 100644
index 0000000..88e2b44
--- /dev/null
+++ b/rf24-node/index.js
@@ -0,0 +1,319 @@
+/* tslint:disable */
+/* eslint-disable */
+/* prettier-ignore */
+
+/* auto-generated by NAPI-RS */
+
+const { existsSync, readFileSync } = require('fs')
+const { join } = require('path')
+
+const { platform, arch } = process
+
+let nativeBinding = null
+let localFileExisted = false
+let loadError = null
+
+function isMusl() {
+ // For Node 10
+ if (!process.report || typeof process.report.getReport !== 'function') {
+ try {
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
+ return readFileSync(lddPath, 'utf8').includes('musl')
+ } catch (e) {
+ return true
+ }
+ } else {
+ const { glibcVersionRuntime } = process.report.getReport().header
+ return !glibcVersionRuntime
+ }
+}
+
+switch (platform) {
+ case 'android':
+ switch (arch) {
+ case 'arm64':
+ localFileExisted = existsSync(join(__dirname, 'rf24.android-arm64.node'))
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.android-arm64.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-android-arm64')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ case 'arm':
+ localFileExisted = existsSync(join(__dirname, 'rf24.android-arm-eabi.node'))
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.android-arm-eabi.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-android-arm-eabi')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ default:
+ throw new Error(`Unsupported architecture on Android ${arch}`)
+ }
+ break
+ case 'win32':
+ switch (arch) {
+ case 'x64':
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.win32-x64-msvc.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.win32-x64-msvc.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-win32-x64-msvc')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ case 'ia32':
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.win32-ia32-msvc.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.win32-ia32-msvc.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-win32-ia32-msvc')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ case 'arm64':
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.win32-arm64-msvc.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.win32-arm64-msvc.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-win32-arm64-msvc')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ default:
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
+ }
+ break
+ case 'darwin':
+ localFileExisted = existsSync(join(__dirname, 'rf24.darwin-universal.node'))
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.darwin-universal.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-darwin-universal')
+ }
+ break
+ } catch {}
+ switch (arch) {
+ case 'x64':
+ localFileExisted = existsSync(join(__dirname, 'rf24.darwin-x64.node'))
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.darwin-x64.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-darwin-x64')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ case 'arm64':
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.darwin-arm64.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.darwin-arm64.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-darwin-arm64')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ default:
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
+ }
+ break
+ case 'freebsd':
+ if (arch !== 'x64') {
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
+ }
+ localFileExisted = existsSync(join(__dirname, 'rf24.freebsd-x64.node'))
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.freebsd-x64.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-freebsd-x64')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ case 'linux':
+ switch (arch) {
+ case 'x64':
+ if (isMusl()) {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-x64-musl.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-x64-musl.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-x64-musl')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ } else {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-x64-gnu.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-x64-gnu.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-x64-gnu')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ }
+ break
+ case 'arm64':
+ if (isMusl()) {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-arm64-musl.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-arm64-musl.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-arm64-musl')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ } else {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-arm64-gnu.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-arm64-gnu.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-arm64-gnu')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ }
+ break
+ case 'arm':
+ if (isMusl()) {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-arm-musleabihf.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-arm-musleabihf.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-arm-musleabihf')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ } else {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-arm-gnueabihf.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-arm-gnueabihf.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-arm-gnueabihf')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ }
+ break
+ case 'riscv64':
+ if (isMusl()) {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-riscv64-musl.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-riscv64-musl.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-riscv64-musl')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ } else {
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-riscv64-gnu.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-riscv64-gnu.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-riscv64-gnu')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ }
+ break
+ case 's390x':
+ localFileExisted = existsSync(
+ join(__dirname, 'rf24.linux-s390x-gnu.node')
+ )
+ try {
+ if (localFileExisted) {
+ nativeBinding = require('./rf24.linux-s390x-gnu.node')
+ } else {
+ nativeBinding = require('@rf24/rf24-linux-s390x-gnu')
+ }
+ } catch (e) {
+ loadError = e
+ }
+ break
+ default:
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
+ }
+ break
+ default:
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
+}
+
+if (!nativeBinding) {
+ if (loadError) {
+ throw loadError
+ }
+ throw new Error(`Failed to load native binding`)
+}
+
+const { PaLevel, DataRate, CrcLength, FifoState, RF24 } = nativeBinding
+
+module.exports.PaLevel = PaLevel
+module.exports.DataRate = DataRate
+module.exports.CrcLength = CrcLength
+module.exports.FifoState = FifoState
+module.exports.RF24 = RF24
diff --git a/rf24-node/npm/android-arm-eabi/README.md b/rf24-node/npm/android-arm-eabi/README.md
new file mode 100644
index 0000000..87134de
--- /dev/null
+++ b/rf24-node/npm/android-arm-eabi/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-android-arm-eabi`
+
+This is the **armv7-linux-androideabi** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/android-arm-eabi/package.json b/rf24-node/npm/android-arm-eabi/package.json
new file mode 100644
index 0000000..e3051e2
--- /dev/null
+++ b/rf24-node/npm/android-arm-eabi/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-android-arm-eabi",
+ "version": "0.1.0",
+ "os": [
+ "android"
+ ],
+ "cpu": [
+ "arm"
+ ],
+ "main": "rf24.android-arm-eabi.node",
+ "files": [
+ "rf24.android-arm-eabi.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/android-arm64/README.md b/rf24-node/npm/android-arm64/README.md
new file mode 100644
index 0000000..27eb5bb
--- /dev/null
+++ b/rf24-node/npm/android-arm64/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-android-arm64`
+
+This is the **aarch64-linux-android** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/android-arm64/package.json b/rf24-node/npm/android-arm64/package.json
new file mode 100644
index 0000000..1849106
--- /dev/null
+++ b/rf24-node/npm/android-arm64/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-android-arm64",
+ "version": "0.1.0",
+ "os": [
+ "android"
+ ],
+ "cpu": [
+ "arm64"
+ ],
+ "main": "rf24.android-arm64.node",
+ "files": [
+ "rf24.android-arm64.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/darwin-arm64/README.md b/rf24-node/npm/darwin-arm64/README.md
new file mode 100644
index 0000000..05d31cd
--- /dev/null
+++ b/rf24-node/npm/darwin-arm64/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-darwin-arm64`
+
+This is the **aarch64-apple-darwin** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/darwin-arm64/package.json b/rf24-node/npm/darwin-arm64/package.json
new file mode 100644
index 0000000..083932e
--- /dev/null
+++ b/rf24-node/npm/darwin-arm64/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-darwin-arm64",
+ "version": "0.1.0",
+ "os": [
+ "darwin"
+ ],
+ "cpu": [
+ "arm64"
+ ],
+ "main": "rf24.darwin-arm64.node",
+ "files": [
+ "rf24.darwin-arm64.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/darwin-universal/README.md b/rf24-node/npm/darwin-universal/README.md
new file mode 100644
index 0000000..a6a9f15
--- /dev/null
+++ b/rf24-node/npm/darwin-universal/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-darwin-universal`
+
+This is the **universal-apple-darwin** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/darwin-universal/package.json b/rf24-node/npm/darwin-universal/package.json
new file mode 100644
index 0000000..6a73fec
--- /dev/null
+++ b/rf24-node/npm/darwin-universal/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "@rf24/rf24-darwin-universal",
+ "version": "0.1.0",
+ "os": [
+ "darwin"
+ ],
+ "main": "rf24.darwin-universal.node",
+ "files": [
+ "rf24.darwin-universal.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/darwin-x64/README.md b/rf24-node/npm/darwin-x64/README.md
new file mode 100644
index 0000000..5c71d9f
--- /dev/null
+++ b/rf24-node/npm/darwin-x64/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-darwin-x64`
+
+This is the **x86_64-apple-darwin** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/darwin-x64/package.json b/rf24-node/npm/darwin-x64/package.json
new file mode 100644
index 0000000..ccfc9e9
--- /dev/null
+++ b/rf24-node/npm/darwin-x64/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-darwin-x64",
+ "version": "0.1.0",
+ "os": [
+ "darwin"
+ ],
+ "cpu": [
+ "x64"
+ ],
+ "main": "rf24.darwin-x64.node",
+ "files": [
+ "rf24.darwin-x64.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-arm-gnueabihf/README.md b/rf24-node/npm/linux-arm-gnueabihf/README.md
new file mode 100644
index 0000000..a47c6dd
--- /dev/null
+++ b/rf24-node/npm/linux-arm-gnueabihf/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-arm-gnueabihf`
+
+This is the **armv7-unknown-linux-gnueabihf** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-arm-gnueabihf/package.json b/rf24-node/npm/linux-arm-gnueabihf/package.json
new file mode 100644
index 0000000..09870c8
--- /dev/null
+++ b/rf24-node/npm/linux-arm-gnueabihf/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-linux-arm-gnueabihf",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "arm"
+ ],
+ "main": "rf24.linux-arm-gnueabihf.node",
+ "files": [
+ "rf24.linux-arm-gnueabihf.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-arm-musleabihf/README.md b/rf24-node/npm/linux-arm-musleabihf/README.md
new file mode 100644
index 0000000..bf6e814
--- /dev/null
+++ b/rf24-node/npm/linux-arm-musleabihf/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-arm-musleabihf`
+
+This is the **armv7-unknown-linux-musleabihf** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-arm-musleabihf/package.json b/rf24-node/npm/linux-arm-musleabihf/package.json
new file mode 100644
index 0000000..9fd4f1b
--- /dev/null
+++ b/rf24-node/npm/linux-arm-musleabihf/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-linux-arm-musleabihf",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "arm"
+ ],
+ "main": "rf24.linux-arm-musleabihf.node",
+ "files": [
+ "rf24.linux-arm-musleabihf.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-arm64-gnu/README.md b/rf24-node/npm/linux-arm64-gnu/README.md
new file mode 100644
index 0000000..b7bb154
--- /dev/null
+++ b/rf24-node/npm/linux-arm64-gnu/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-arm64-gnu`
+
+This is the **aarch64-unknown-linux-gnu** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-arm64-gnu/package.json b/rf24-node/npm/linux-arm64-gnu/package.json
new file mode 100644
index 0000000..9f044ce
--- /dev/null
+++ b/rf24-node/npm/linux-arm64-gnu/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@rf24/rf24-linux-arm64-gnu",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "arm64"
+ ],
+ "main": "rf24.linux-arm64-gnu.node",
+ "files": [
+ "rf24.linux-arm64-gnu.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "libc": [
+ "glibc"
+ ]
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-arm64-musl/README.md b/rf24-node/npm/linux-arm64-musl/README.md
new file mode 100644
index 0000000..68400d6
--- /dev/null
+++ b/rf24-node/npm/linux-arm64-musl/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-arm64-musl`
+
+This is the **aarch64-unknown-linux-musl** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-arm64-musl/package.json b/rf24-node/npm/linux-arm64-musl/package.json
new file mode 100644
index 0000000..c1f066a
--- /dev/null
+++ b/rf24-node/npm/linux-arm64-musl/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@rf24/rf24-linux-arm64-musl",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "arm64"
+ ],
+ "main": "rf24.linux-arm64-musl.node",
+ "files": [
+ "rf24.linux-arm64-musl.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "libc": [
+ "musl"
+ ]
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-riscv64-gnu/README.md b/rf24-node/npm/linux-riscv64-gnu/README.md
new file mode 100644
index 0000000..4c3a47d
--- /dev/null
+++ b/rf24-node/npm/linux-riscv64-gnu/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-riscv64-gnu`
+
+This is the **riscv64gc-unknown-linux-gnu** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-riscv64-gnu/package.json b/rf24-node/npm/linux-riscv64-gnu/package.json
new file mode 100644
index 0000000..cc87a60
--- /dev/null
+++ b/rf24-node/npm/linux-riscv64-gnu/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@rf24/rf24-linux-riscv64-gnu",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "riscv64"
+ ],
+ "main": "rf24.linux-riscv64-gnu.node",
+ "files": [
+ "rf24.linux-riscv64-gnu.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "libc": [
+ "glibc"
+ ]
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-x64-gnu/README.md b/rf24-node/npm/linux-x64-gnu/README.md
new file mode 100644
index 0000000..98d2d6d
--- /dev/null
+++ b/rf24-node/npm/linux-x64-gnu/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-x64-gnu`
+
+This is the **x86_64-unknown-linux-gnu** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-x64-gnu/package.json b/rf24-node/npm/linux-x64-gnu/package.json
new file mode 100644
index 0000000..5f49ddc
--- /dev/null
+++ b/rf24-node/npm/linux-x64-gnu/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@rf24/rf24-linux-x64-gnu",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "x64"
+ ],
+ "main": "rf24.linux-x64-gnu.node",
+ "files": [
+ "rf24.linux-x64-gnu.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "libc": [
+ "glibc"
+ ]
+}
\ No newline at end of file
diff --git a/rf24-node/npm/linux-x64-musl/README.md b/rf24-node/npm/linux-x64-musl/README.md
new file mode 100644
index 0000000..a8e0c9d
--- /dev/null
+++ b/rf24-node/npm/linux-x64-musl/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-linux-x64-musl`
+
+This is the **x86_64-unknown-linux-musl** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/linux-x64-musl/package.json b/rf24-node/npm/linux-x64-musl/package.json
new file mode 100644
index 0000000..b8fc6e6
--- /dev/null
+++ b/rf24-node/npm/linux-x64-musl/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@rf24/rf24-linux-x64-musl",
+ "version": "0.1.0",
+ "os": [
+ "linux"
+ ],
+ "cpu": [
+ "x64"
+ ],
+ "main": "rf24.linux-x64-musl.node",
+ "files": [
+ "rf24.linux-x64-musl.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "libc": [
+ "musl"
+ ]
+}
\ No newline at end of file
diff --git a/rf24-node/npm/win32-arm64-msvc/README.md b/rf24-node/npm/win32-arm64-msvc/README.md
new file mode 100644
index 0000000..a6252c5
--- /dev/null
+++ b/rf24-node/npm/win32-arm64-msvc/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-win32-arm64-msvc`
+
+This is the **aarch64-pc-windows-msvc** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/win32-arm64-msvc/package.json b/rf24-node/npm/win32-arm64-msvc/package.json
new file mode 100644
index 0000000..6dcc0ca
--- /dev/null
+++ b/rf24-node/npm/win32-arm64-msvc/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-win32-arm64-msvc",
+ "version": "0.1.0",
+ "os": [
+ "win32"
+ ],
+ "cpu": [
+ "arm64"
+ ],
+ "main": "rf24.win32-arm64-msvc.node",
+ "files": [
+ "rf24.win32-arm64-msvc.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/win32-ia32-msvc/README.md b/rf24-node/npm/win32-ia32-msvc/README.md
new file mode 100644
index 0000000..ed5b6b6
--- /dev/null
+++ b/rf24-node/npm/win32-ia32-msvc/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-win32-ia32-msvc`
+
+This is the **i686-pc-windows-msvc** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/win32-ia32-msvc/package.json b/rf24-node/npm/win32-ia32-msvc/package.json
new file mode 100644
index 0000000..0c0da04
--- /dev/null
+++ b/rf24-node/npm/win32-ia32-msvc/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-win32-ia32-msvc",
+ "version": "0.1.0",
+ "os": [
+ "win32"
+ ],
+ "cpu": [
+ "ia32"
+ ],
+ "main": "rf24.win32-ia32-msvc.node",
+ "files": [
+ "rf24.win32-ia32-msvc.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/npm/win32-x64-msvc/README.md b/rf24-node/npm/win32-x64-msvc/README.md
new file mode 100644
index 0000000..1b6768f
--- /dev/null
+++ b/rf24-node/npm/win32-x64-msvc/README.md
@@ -0,0 +1,3 @@
+# `@rf24/rf24-win32-x64-msvc`
+
+This is the **x86_64-pc-windows-msvc** binary for `@rf24/rf24`
diff --git a/rf24-node/npm/win32-x64-msvc/package.json b/rf24-node/npm/win32-x64-msvc/package.json
new file mode 100644
index 0000000..5bcea6a
--- /dev/null
+++ b/rf24-node/npm/win32-x64-msvc/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@rf24/rf24-win32-x64-msvc",
+ "version": "0.1.0",
+ "os": [
+ "win32"
+ ],
+ "cpu": [
+ "x64"
+ ],
+ "main": "rf24.win32-x64-msvc.node",
+ "files": [
+ "rf24.win32-x64-msvc.node"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+}
\ No newline at end of file
diff --git a/rf24-node/package.json b/rf24-node/package.json
new file mode 100644
index 0000000..069c5f2
--- /dev/null
+++ b/rf24-node/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "@rf24/rf24",
+ "version": "0.1.0",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "napi": {
+ "name": "rf24",
+ "triples": {
+ "additional": [
+ "aarch64-apple-darwin",
+ "aarch64-linux-android",
+ "aarch64-unknown-linux-gnu",
+ "aarch64-unknown-linux-musl",
+ "aarch64-pc-windows-msvc",
+ "armv7-unknown-linux-gnueabihf",
+ "armv7-unknown-linux-musleabihf",
+ "x86_64-unknown-linux-musl",
+ "x86_64-unknown-freebsd",
+ "i686-pc-windows-msvc",
+ "armv7-linux-androideabi",
+ "universal-apple-darwin",
+ "riscv64gc-unknown-linux-gnu"
+ ]
+ }
+ },
+ "license": "MIT",
+ "devDependencies": {
+ "@napi-rs/cli": "^2.18.4",
+ "@types/node": "^22.7.5"
+ },
+ "ava": {
+ "timeout": "3m"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "scripts": {
+ "artifacts": "napi artifacts",
+ "build": "napi build --platform --release",
+ "build:debug": "napi build --platform",
+ "prepublishOnly": "napi prepublish -t npm",
+ "universal": "napi universal",
+ "version": "napi version"
+ },
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
+}
diff --git a/rf24-node/src/enums.rs b/rf24-node/src/enums.rs
new file mode 100644
index 0000000..a9e3522
--- /dev/null
+++ b/rf24-node/src/enums.rs
@@ -0,0 +1,152 @@
+#[cfg(target_os = "linux")]
+use rf24_rs::{CrcLength, DataRate, FifoState, PaLevel};
+
+/// The return type for `RF24.getStatusFlags()`
+#[napi(object)]
+pub struct StatusFlags {
+ pub rx_dr: bool,
+ pub tx_ds: bool,
+ pub tx_df: bool,
+}
+
+/// The return type for `RF24.availablePipe()`
+#[napi(object)]
+pub struct AvailablePipe {
+ pub available: bool,
+ pub pipe: u8,
+}
+
+/// Power Amplifier level. The units dBm (decibel-milliwatts or dBmW)
+/// represents a logarithmic signal loss.
+#[napi(js_name = "PaLevel")]
+#[derive(Debug, PartialEq)]
+pub enum NodePaLevel {
+ /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ /// | :-------:|:--------------------------:|:---------------------------:|
+ /// | -18 dBm | -6 dBm | -12 dBm |
+ MIN,
+ /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ /// | :-------:|:--------------------------:|:---------------------------:|
+ /// | -12 dBm | 0 dBm | -4 dBm |
+ LOW,
+ /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ /// | :-------:|:--------------------------:|:---------------------------:|
+ /// | -6 dBm | 3 dBm | 1 dBm |
+ HIGH,
+ /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled |
+ /// | :-------:|:--------------------------:|:---------------------------:|
+ /// | 0 dBm | 7 dBm | 4 dBm |
+ MAX,
+}
+
+#[cfg(target_os = "linux")]
+impl NodePaLevel {
+ pub fn into_inner(self) -> PaLevel {
+ match self {
+ NodePaLevel::MIN => PaLevel::MIN,
+ NodePaLevel::LOW => PaLevel::LOW,
+ NodePaLevel::HIGH => PaLevel::HIGH,
+ NodePaLevel::MAX => PaLevel::MAX,
+ }
+ }
+ pub fn from_inner(other: PaLevel) -> NodePaLevel {
+ match other {
+ PaLevel::MIN => NodePaLevel::MIN,
+ PaLevel::LOW => NodePaLevel::LOW,
+ PaLevel::HIGH => NodePaLevel::HIGH,
+ PaLevel::MAX => NodePaLevel::MAX,
+ }
+ }
+}
+
+/// How fast data moves through the air. Units are in bits per second (bps).
+#[napi(js_name = "DataRate")]
+#[derive(Debug, PartialEq)]
+pub enum NodeDataRate {
+ /// represents 1 Mbps
+ Mbps1,
+ /// represents 2 Mbps
+ Mbps2,
+ /// represents 250 Kbps
+ Kbps250,
+}
+
+#[cfg(target_os = "linux")]
+impl NodeDataRate {
+ pub fn into_inner(self) -> DataRate {
+ match self {
+ NodeDataRate::Mbps1 => DataRate::Mbps1,
+ NodeDataRate::Mbps2 => DataRate::Mbps2,
+ NodeDataRate::Kbps250 => DataRate::Kbps250,
+ }
+ }
+ pub fn from_inner(other: DataRate) -> NodeDataRate {
+ match other {
+ DataRate::Mbps1 => NodeDataRate::Mbps1,
+ DataRate::Mbps2 => NodeDataRate::Mbps2,
+ DataRate::Kbps250 => NodeDataRate::Kbps250,
+ }
+ }
+}
+
+/// The length of a CRC checksum that is used (if any).
+///
+/// Cyclical Redundancy Checking (CRC) is commonly used to ensure data integrity.
+#[napi(js_name = "CrcLength")]
+#[derive(Debug, PartialEq)]
+pub enum NodeCrcLength {
+ /// represents no CRC checksum is used
+ DISABLED,
+ /// represents CRC 8 bit checksum is used
+ BIT8,
+ /// represents CRC 16 bit checksum is used
+ BIT16,
+}
+
+#[cfg(target_os = "linux")]
+impl NodeCrcLength {
+ pub fn into_inner(self) -> CrcLength {
+ match self {
+ NodeCrcLength::DISABLED => CrcLength::DISABLED,
+ NodeCrcLength::BIT8 => CrcLength::BIT8,
+ NodeCrcLength::BIT16 => CrcLength::BIT16,
+ }
+ }
+ pub fn from_inner(other: CrcLength) -> NodeCrcLength {
+ match other {
+ CrcLength::DISABLED => NodeCrcLength::DISABLED,
+ CrcLength::BIT8 => NodeCrcLength::BIT8,
+ CrcLength::BIT16 => NodeCrcLength::BIT16,
+ }
+ }
+}
+
+/// The possible states of a FIFO.
+#[napi(js_name = "FifoState")]
+#[derive(Debug, PartialEq)]
+pub enum NodeFifoState {
+ /// Represent the state of a FIFO when it is full.
+ Full,
+ /// Represent the state of a FIFO when it is empty.
+ Empty,
+ /// Represent the state of a FIFO when it is not full but not empty either.
+ Occupied,
+}
+
+#[cfg(target_os = "linux")]
+impl NodeFifoState {
+ pub fn into_inner(self) -> FifoState {
+ match self {
+ NodeFifoState::Full => FifoState::Full,
+ NodeFifoState::Empty => FifoState::Empty,
+ NodeFifoState::Occupied => FifoState::Occupied,
+ }
+ }
+ pub fn from_inner(other: FifoState) -> NodeFifoState {
+ match other {
+ FifoState::Full => NodeFifoState::Full,
+ FifoState::Empty => NodeFifoState::Empty,
+ FifoState::Occupied => NodeFifoState::Occupied,
+ }
+ }
+}
diff --git a/rf24-node/src/lib.rs b/rf24-node/src/lib.rs
new file mode 100644
index 0000000..1947909
--- /dev/null
+++ b/rf24-node/src/lib.rs
@@ -0,0 +1,6 @@
+mod enums;
+#[cfg(target_os = "linux")]
+mod radio;
+
+#[macro_use]
+extern crate napi_derive;
diff --git a/rf24-node/src/radio.rs b/rf24-node/src/radio.rs
new file mode 100644
index 0000000..122e1aa
--- /dev/null
+++ b/rf24-node/src/radio.rs
@@ -0,0 +1,454 @@
+#![cfg(target_os = "linux")]
+
+use crate::enums::{
+ AvailablePipe, NodeCrcLength, NodeDataRate, NodeFifoState, NodePaLevel, StatusFlags,
+};
+use linux_embedded_hal::{
+ gpio_cdev::{chips, LineRequestFlags},
+ spidev::{SpiModeFlags, SpidevOptions},
+ CdevPin, Delay, SpidevDevice,
+};
+use napi::{bindgen_prelude::Buffer, Error, Result, Status};
+
+use rf24_rs::radio::{prelude::*, RF24};
+
+#[napi(js_name = "RF24")]
+pub struct NodeRF24 {
+ inner: RF24,
+ read_buf: [u8; 32],
+}
+
+#[napi]
+impl NodeRF24 {
+ #[napi(constructor)]
+ pub fn new(
+ ce_pin: u32,
+ cs_pin: u8,
+ dev_gpio_chip: u8,
+ dev_spi_bus: u8,
+ spi_speed: u32,
+ ) -> Result {
+ // get the desired "/dev/gpiochip{dev_gpio_chip}"
+ let mut dev_gpio = chips()
+ .map_err(|_| {
+ Error::new(
+ Status::GenericFailure,
+ "Failed to get list of GPIO chips for the system",
+ )
+ })?
+ .find(|chip| {
+ if let Ok(chip) = chip {
+ if chip
+ .path()
+ .to_string_lossy()
+ .ends_with(&dev_gpio_chip.to_string())
+ {
+ return true;
+ }
+ }
+ false
+ })
+ .ok_or(Error::new(
+ Status::InvalidArg,
+ format!("Could not find specified dev/gpiochip{dev_gpio_chip} for this system."),
+ ))?
+ .map_err(|e| {
+ Error::new(
+ Status::InvalidArg,
+ format!("Could not open GPIO chip dev/gpiochip{dev_gpio_chip}: {e:?}"),
+ )
+ })?;
+ let ce_line = dev_gpio.get_line(ce_pin).map_err(|e| {
+ Error::new(
+ Status::InvalidArg,
+ format!("GPIO{ce_pin} is unavailable: {e:?}"),
+ )
+ })?;
+ let ce_line_handle = ce_line
+ .request(LineRequestFlags::OUTPUT, 0, "rf24-rs")
+ .map_err(|e| {
+ Error::new(
+ Status::InvalidArg,
+ format!("GPIO{ce_pin} is already in use: {e:?}"),
+ )
+ })?;
+ let ce_pin = CdevPin::new(ce_line_handle)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))?;
+
+ let mut spi =
+ SpidevDevice::open(format!("/dev/spidev{dev_spi_bus}.{cs_pin}")).map_err(|_| {
+ Error::new(Status::InvalidArg, format!(
+ "SPI bus {dev_spi_bus} with CS pin option {cs_pin} is not available in this system"
+ )
+ )
+ })?;
+ let config = SpidevOptions::new()
+ .max_speed_hz(spi_speed)
+ .mode(SpiModeFlags::SPI_MODE_0)
+ .bits_per_word(8)
+ .build();
+ spi.configure(&config)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))?;
+
+ Ok(Self {
+ inner: RF24::new(ce_pin, spi, Delay),
+ read_buf: [0u8; 32],
+ })
+ }
+
+ #[napi]
+ pub fn begin(&mut self) -> Result<()> {
+ self.inner
+ .init()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn start_listening(&mut self) -> Result<()> {
+ self.inner
+ .start_listening()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn stop_listening(&mut self) -> Result<()> {
+ self.inner
+ .stop_listening()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn send(&mut self, buf: &[u8], ask_no_ack: bool) -> Result {
+ self.inner
+ .send(buf, ask_no_ack)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn write(&mut self, buf: &[u8], ask_no_ack: bool, start_tx: bool) -> Result {
+ self.inner
+ .write(buf, ask_no_ack, start_tx)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn read(&mut self, len: u8) -> Result {
+ self.inner
+ .read(&mut self.read_buf, len)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))?;
+ Ok(Buffer::from(&self.read_buf[0..len as usize]))
+ }
+
+ #[napi]
+ pub fn resend(&mut self) -> Result {
+ self.inner
+ .resend()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn rewrite(&mut self) -> Result<()> {
+ self.inner
+ .rewrite()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_last_arc(&mut self) -> Result {
+ self.inner
+ .get_last_arc()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn is_plus_variant(&self) -> bool {
+ self.inner.is_plus_variant()
+ }
+
+ #[napi]
+ pub fn test_rpd(&mut self) -> Result {
+ self.inner
+ .test_rpd()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn start_carrier_wave(&mut self, level: NodePaLevel, channel: u8) -> Result<()> {
+ self.inner
+ .start_carrier_wave(level.into_inner(), channel)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn stop_carrier_wave(&mut self) -> Result<()> {
+ self.inner
+ .stop_carrier_wave()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_lna(&mut self, enable: bool) -> Result<()> {
+ self.inner
+ .set_lna(enable)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn allow_ack_payloads(&mut self, enable: bool) -> Result<()> {
+ self.inner
+ .allow_ack_payloads(enable)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_auto_ack(&mut self, enable: bool) -> Result<()> {
+ self.inner
+ .set_auto_ack(enable)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_auto_ack_pipe(&mut self, enable: bool, pipe: u8) -> Result<()> {
+ self.inner
+ .set_auto_ack_pipe(enable, pipe)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn allow_ask_no_ack(&mut self, enable: bool) -> Result<()> {
+ self.inner
+ .allow_ask_no_ack(enable)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn write_ack_payload(&mut self, pipe: u8, buf: &[u8]) -> Result {
+ self.inner
+ .write_ack_payload(pipe, buf)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_auto_retries(&mut self, delay: u8, count: u8) -> Result<()> {
+ self.inner
+ .set_auto_retries(delay, count)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_channel(&mut self, channel: u8) -> Result<()> {
+ self.inner
+ .set_channel(channel)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_channel(&mut self) -> Result {
+ self.inner
+ .get_channel()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_crc_length(&mut self) -> Result {
+ self.inner
+ .get_crc_length()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ .map(|e| NodeCrcLength::from_inner(e))
+ }
+
+ #[napi]
+ pub fn set_crc_length(&mut self, crc_length: NodeCrcLength) -> Result<()> {
+ self.inner
+ .set_crc_length(crc_length.into_inner())
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_data_rate(&mut self) -> Result {
+ self.inner
+ .get_data_rate()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ .map(|e| NodeDataRate::from_inner(e))
+ }
+
+ #[napi]
+ pub fn set_data_rate(&mut self, data_rate: NodeDataRate) -> Result<()> {
+ self.inner
+ .set_data_rate(data_rate.into_inner())
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn available(&mut self) -> Result {
+ self.inner
+ .available()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn available_pipe(&mut self) -> Result {
+ let mut pipe = Some(0u8);
+ let result = self
+ .inner
+ .available_pipe(&mut pipe)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))?;
+ Ok(AvailablePipe {
+ available: result,
+ pipe: pipe.expect("`pipe` should be a number"),
+ })
+ }
+
+ /// Use this to discard all 3 layers in the radio's RX FIFO.
+ #[napi]
+ pub fn flush_rx(&mut self) -> Result<()> {
+ self.inner
+ .flush_rx()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ /// Use this to discard all 3 layers in the radio's TX FIFO.
+ #[napi]
+ pub fn flush_tx(&mut self) -> Result<()> {
+ self.inner
+ .flush_tx()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_fifo_state(&mut self, about_tx: bool) -> Result {
+ self.inner
+ .get_fifo_state(about_tx)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ .map(|e| NodeFifoState::from_inner(e))
+ }
+
+ #[napi]
+ pub fn get_pa_level(&mut self) -> Result {
+ self.inner
+ .get_pa_level()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ .map(|e| NodePaLevel::from_inner(e))
+ }
+
+ #[napi]
+ pub fn set_pa_level(&mut self, pa_level: NodePaLevel) -> Result<()> {
+ self.inner
+ .set_pa_level(pa_level.into_inner())
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_payload_length(&mut self, length: u8) -> Result<()> {
+ self.inner
+ .set_payload_length(length)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_payload_length(&mut self) -> Result {
+ self.inner
+ .get_payload_length()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_dynamic_payloads(&mut self, enable: bool) -> Result<()> {
+ self.inner
+ .set_dynamic_payloads(enable)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_dynamic_payload_length(&mut self) -> Result {
+ self.inner
+ .get_dynamic_payload_length()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn open_rx_pipe(&mut self, pipe: u8, address: &[u8]) -> Result<()> {
+ self.inner
+ .open_rx_pipe(pipe, address)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn open_tx_pipe(&mut self, address: &[u8]) -> Result<()> {
+ self.inner
+ .open_tx_pipe(address)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ /// If the given `pipe` number is not in range [0, 5], then this function does nothing.
+ #[napi]
+ pub fn close_rx_pipe(&mut self, pipe: u8) -> Result<()> {
+ self.inner
+ .close_rx_pipe(pipe)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_address_length(&mut self, length: u8) -> Result<()> {
+ self.inner
+ .set_address_length(length)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_address_length(&mut self) -> Result {
+ self.inner
+ .get_address_length()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn power_down(&mut self) -> Result<()> {
+ self.inner
+ .power_down()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn power_up(&mut self, delay: Option) -> Result<()> {
+ self.inner
+ .power_up(delay)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn set_status_flags(&mut self, rx_dr: bool, tx_ds: bool, tx_df: bool) -> Result<()> {
+ self.inner
+ .set_status_flags(rx_dr, tx_ds, tx_df)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn clear_status_flags(&mut self, rx_dr: bool, tx_ds: bool, tx_df: bool) -> Result<()> {
+ self.inner
+ .clear_status_flags(rx_dr, tx_ds, tx_df)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn update(&mut self) -> Result<()> {
+ self.inner
+ .update()
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))
+ }
+
+ #[napi]
+ pub fn get_status_flags(&mut self) -> Result {
+ let mut rx_dr = Some(false);
+ let mut tx_ds = Some(false);
+ let mut tx_df = Some(false);
+ self.inner
+ .get_status_flags(&mut rx_dr, &mut tx_ds, &mut tx_df)
+ .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))?;
+ Ok(StatusFlags {
+ rx_dr: rx_dr.unwrap(),
+ tx_ds: tx_ds.unwrap(),
+ tx_df: tx_df.unwrap(),
+ })
+ }
+}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..881d869
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,20 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@napi-rs/cli@^2.18.4":
+ version "2.18.4"
+ resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.18.4.tgz#12bebfb7995902fa7ab43cc0b155a7f5a2caa873"
+ integrity sha512-SgJeA4df9DE2iAEpr3M2H0OKl/yjtg1BnRI5/JyowS71tUWhrfSu2LT0V3vlHET+g1hBVlrO60PmEXwUEKp8Mg==
+
+"@types/node@^22.7.5":
+ version "22.7.5"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b"
+ integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==
+ dependencies:
+ undici-types "~6.19.2"
+
+undici-types@~6.19.2:
+ version "6.19.8"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
+ integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==