From 50080b0dea446d07c574cd25c21ed05c7dee00d6 Mon Sep 17 00:00:00 2001 From: mhrsntrk Date: Mon, 21 Sep 2026 12:17:37 +0200 Subject: [PATCH] docs: improve public onboarding and contributor guidance --- .github/ISSUE_TEMPLATE/config.yml | 8 ++ .github/ISSUE_TEMPLATE/hardware.yml | 27 +++++++ CONTRIBUTING.md | 28 ++++++- README.md | 110 ++++++++++++++++++++++------ SECURITY.md | 6 +- docs/API.md | 84 +++++++++++++++++++++ docs/TROUBLESHOOTING.md | 35 +++++++++ 7 files changed, 273 insertions(+), 25 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/hardware.yml create mode 100644 docs/API.md create mode 100644 docs/TROUBLESHOOTING.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8e3124b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Troubleshooting and setup + url: https://github.com/su-engineering/react-native-nearby-interaction/blob/main/docs/TROUBLESHOOTING.md + about: Check common discovery, configuration, and measurement problems. + - name: Report a security vulnerability privately + url: https://github.com/su-engineering/react-native-nearby-interaction/security/advisories/new + about: Use private reporting instead of a public issue for vulnerabilities. diff --git a/.github/ISSUE_TEMPLATE/hardware.yml b/.github/ISSUE_TEMPLATE/hardware.yml new file mode 100644 index 0000000..380593f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/hardware.yml @@ -0,0 +1,27 @@ +name: Hardware validation +description: Share reproducible results for an iPhone and UWB accessory combination +body: + - type: markdown + attributes: + value: "Report observed results, including failures and unavailable readings. Remove device identifiers and raw accessory configuration tokens." + - type: textarea + id: environment + attributes: + label: Hardware and software + description: Package version or commit, iPhone model, iOS, React Native/Expo, accessory model, and firmware revision (or unknown). + validations: + required: true + - type: textarea + id: setup + attributes: + label: Setup and reproduction + description: Example app or minimal reproduction, transport/profile changes, and relevant public protocol documentation. + validations: + required: true + - type: textarea + id: results + attributes: + label: Observed results + description: Report distance, angle/direction availability, Stop/Start, foreground resume, tag power-cycle, stale-reading cleanup, and any untested checks. Include approximate distances and conditions without claiming calibrated accuracy. + validations: + required: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 55be9a7..7810d93 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,16 @@ Open an issue before substantial API changes. Bug reports should include package React Native/Expo, iOS and Xcode versions, tag model/firmware, lifecycle state and a minimal reproduction. Remove credentials and private accessory tokens. +Use Node.js 22 for parity with CI. Native checks require macOS and Xcode; CI uses +Xcode 26.2. Start with the fast checks, then run consumer checks for integration changes. + +```sh +npm ci +npm run check +``` + +Before changing packaging or native integration: + ```sh npm ci npm run release:check @@ -17,8 +27,24 @@ On macOS, also run `swift test` and compile generated consumers as CI does. Add tests for changed behavior, update the changelog and document API changes. Changes to NI lifecycle, BLE negotiation or framing require physical test results -with hardware/firmware versions. The first beta's physical validation is pending. +with hardware/firmware versions. See the [first hardware report](docs/validation/2026-09-21.md) for the validated +configuration and remaining coverage. Report additional hardware using the +hardware validation issue form. Preserve explicit session ownership/stop, nullable measurements, main-queue native isolation and bounded recovery. Keep application-specific behavior out of the library. Contributions must be yours to submit and distributable under MIT. + +## Pull requests + +Keep each PR focused on one problem. Explain the observed behavior, the resulting +behavior, and the checks you ran. Link the relevant issue when there is one. +For hardware-dependent changes, distinguish measurements observed on a device +from simulator or mocked tests; record any checks you could not run. + +Documentation-only changes need accurate examples and working links. Changes to +public behavior need appropriate regression coverage. Do not include signing +profiles, device identifiers, raw nearby-device scans, or private accessory data. + +Use respectful, constructive discussion. For vulnerabilities, follow +[SECURITY.md](SECURITY.md) instead of filing a public bug. diff --git a/README.md b/README.md index b237303..d635466 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,34 @@ # React Native Nearby Interaction -iPhone → UWB accessory ranging through Apple's Nearby Interaction framework. -This standalone MVP has a configurable Truesense T-TAG BLE profile, an external -transport API for other accessories, a typed event API, and a React hook. +**Measure the distance from an iPhone to a UWB accessory in React Native and Expo.** -Current release: **0.1.0**, published under the `latest` npm tag. Initial physical distance ranging, stop/restart, foreground resume and -tag reconnection passed on an iPhone 16 Pro with a Truesense T-TAG. See -[validation](docs/VALIDATION.md) for the evidence and remaining acceptance tests. +[![CI](https://github.com/su-engineering/react-native-nearby-interaction/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/su-engineering/react-native-nearby-interaction/actions/workflows/ci.yml) +[![npm](https://img.shields.io/npm/v/@su-engineering/react-native-nearby-interaction)](https://www.npmjs.com/package/@su-engineering/react-native-nearby-interaction) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +Apple's Nearby Interaction framework provides the measurements. This library +handles the native session, Truesense T-TAG Bluetooth negotiation, and recovery, +and exposes a typed event API and a React hook. + +- **T-TAG support:** configurable BLE services, characteristics, and command bytes. +- **React state:** distance, session state, accessory details, and errors through one hook. +- **Session recovery:** bounded retries, foreground resume, and stale-reading cleanup. +- **Other accessories:** bring your own transport for an Apple-compatible NI protocol. +- **Native integration:** React Native New Architecture and an Expo config plugin. + +Current release: **[0.1.0](https://github.com/su-engineering/react-native-nearby-interaction/releases/tag/v0.1.0)**. +Distance ranging, stop/restart, foreground resume, and tag reconnection passed on +an iPhone 16 Pro with a Truesense T-TAG. Direction and angle were unavailable in +those sessions. See the [hardware report](docs/validation/2026-09-21.md) for the +exact test scope; other accessories remain unverified. + +[Quick start](#installation) · [API reference](docs/API.md) · +[Troubleshooting](docs/TROUBLESHOOTING.md) · [Validation](docs/VALIDATION.md) · +[Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) ## Scope -| Capability | MVP | +| Capability | Support in 0.1.0 | | --- | --- | | iOS UWB accessory sessions | Implemented | | Truesense demo firmware handshake | Device-tested with a T-TAG; firmware revision not recorded | @@ -20,8 +38,8 @@ tag reconnection passed on an iPhone 16 Pro with a Truesense T-TAG. See | Bounded retries, deadlines, write acknowledgements, stale reading cleanup | Implemented | | React Native New Architecture | TurboModule + generated event bindings | | Expo | Info.plist config plugin; native development build required | -| Android, iPhone-to-iPhone, multiple simultaneous tags | Outside this MVP | -| Background ranging | Outside this MVP; disconnects and resumes in foreground | +| Android, iPhone-to-iPhone, multiple simultaneous tags | Outside this release | +| Background ranging | Outside this release; disconnects and resumes in foreground | Compatibility target: React Native 0.83.x (baseline 0.83.1), React 19.2.x, Expo SDK 55 (baseline 55.0.0), iOS 15.1+, Xcode 26.2+ for Expo builds. Other versions are not claimed by this @@ -36,15 +54,16 @@ Install from npm: npm install @su-engineering/react-native-nearby-interaction ``` -Before release, install the tarball produced by `npm run pack:check`, or clone -the repository and install locally: +For a bare React Native app, install the iOS pods after adding the package: ```sh -npm install /absolute/path/to/react-native-nearby-interaction cd ios bundle exec pod install ``` +You need a UWB-capable iPhone and an Apple-compatible UWB accessory for physical +ranging. A simulator can validate UI and unsupported-device handling only. + Add nonempty `NSNearbyInteractionUsageDescription` and `NSBluetoothAlwaysUsageDescription` strings to your app's Info.plist. The library checks their presence before starting a built-in BLE session. @@ -68,22 +87,54 @@ not add background modes. Expo Go cannot load this native module. ## Basic usage ```tsx -import {Text} from 'react-native'; +import {useEffect, useState} from 'react'; +import {Button, Text, View} from 'react-native'; import {nearbyInteraction, useNearbyInteraction} from '@su-engineering/react-native-nearby-interaction'; -function Distance() { +// This screen owns the shared session. Mount only one session owner at a time. +export function DistanceScreen() { const {state, measurement, error} = useNearbyInteraction(); - return {error?.message ?? `${state}: ${measurement?.distance ?? '—'} m`}; -} + const [busy, setBusy] = useState(false); + const [message, setMessage] = useState(null); + + useEffect(() => () => { + void nearbyInteraction.stop().catch(console.error); + }, []); + + async function run(action: 'start' | 'stop') { + setBusy(true); + setMessage(null); + try { + if (action === 'start') { + const capabilities = await nearbyInteraction.getCapabilities(); + if (!capabilities.supported) { + setMessage('This device does not support accessory UWB ranging.'); + return; + } + await nearbyInteraction.start(); + } else { + await nearbyInteraction.stop(); + } + } catch (cause) { + setMessage(cause instanceof Error ? cause.message : String(cause)); + } finally { + setBusy(false); + } + } -const capabilities = await nearbyInteraction.getCapabilities(); -if (capabilities.supported) { - await nearbyInteraction.start({namePrefix: 'T-TAG', maxRetries: 3}); + return ( + + {state} + {measurement?.distance == null ? '—' : `${measurement.distance.toFixed(2)} m`} + {message ?? error?.message} +