npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ble-ion-proxima

v0.0.1

Published

BLE Background Plugin

Readme

ble-ion-proxima

A high-performance Capacitor plugin for dual-role Bluetooth Low Energy (BLE) background proximity detection.

This plugin allows your Ionic/Capacitor app to act as both a BLE Broadcaster (Peripheral) and a BLE Scanner (Central) simultaneously, even when the app is completely killed or running in the background. It is specifically designed to bypass OS limitations and trigger Truecaller-style full-screen overlays (Android) or Local Notifications (iOS) when a specific proximity node is detected.

Features

  • Dual Role: Broadcast and Scan simultaneously.
  • True Background Execution: Android BroadcastReceiver wakes up your killed app using PendingIntent. iOS utilizes State Restoration and Local Notifications.
  • Custom Payloads: Transmit and receive custom device names directly via the ServiceData payload, bypassing hardware name limitations.
  • Proximity Distance Estimation: Built-in RSSI-to-distance mathematical conversion.

Install

npm install ble-ion-proxima
npx cap sync

Setup Configuration

Android

The plugin automatically injects the necessary permissions and receivers into your AndroidManifest.xml via Capacitor. However, to show popups when the app is in the background, you must explicitly request the Overlay permission from the user in your app:

import { BleDualRolePlugin } from 'ble-ion-proxima';
await BleDualRolePlugin.requestOverlayPermission();

iOS

Add the following keys to your ios/App/App/Info.plist file to allow background Bluetooth execution and explain your privacy usages:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app requires Bluetooth to detect nearby proximity nodes.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs to broadcast its presence to nearby devices.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location is required for Bluetooth scanning.</string>
<key>UIBackgroundModes</key>
<array>
  <string>bluetooth-central</string>
  <string>bluetooth-peripheral</string>
</array>

Usage Example

import { BleDualRolePlugin } from 'ble-ion-proxima';

// Request standard runtime permissions first
await BleDualRolePlugin.requestPermissions();

// Start Broadcasting your presence
await BleDualRolePlugin.startBroadcasting({
  serviceUuid: '0000180D-0000-1000-8000-00805f9b34fb',
  localName: 'Viroj Node'
});

// Start Scanning for other broadcasters in the background
await BleDualRolePlugin.startScanning({
  serviceUuid: '0000180D-0000-1000-8000-00805f9b34fb',
  notificationTitle: 'Node Found!', // Android Background Notification Title
  notificationText: 'A device is nearby.' // Android Background Notification Text
});

// Listen for foreground discoveries (App is open)
BleDualRolePlugin.addListener('onDeviceDiscovered', (result) => {
  console.log(`Found ${result.device.name} at ${result.device.distance} meters!`);
});

// Listen for background wakeups (App was killed but woke up due to BLE hit)
BleDualRolePlugin.addListener('onOverlayWakeup', (result) => {
  // Show a custom Ionic Alert or modal here!
  console.log(`Woke up by ${result.name} (UUID: ${result.uuid})`);
});

API

requestPermissions()

requestPermissions() => Promise<{ scan: string; advertise: string; }>

Request necessary Bluetooth and Location runtime permissions (Required for Android 12+).

Returns: Promise<{ scan: string; advertise: string; }>


startScanning(...)

startScanning(options: { serviceUuid: string; environmentalFactor?: number; notificationTitle?: string; notificationText?: string; }) => Promise<void>

Arm the native system to scan for peripherals matching a strict Service UUID.

| Param | Type | | ------------- | -------------------------------------------------------------------------------------------------------------------------- | | options | { serviceUuid: string; environmentalFactor?: number; notificationTitle?: string; notificationText?: string; } |


stopScanning()

stopScanning() => Promise<void>

startBroadcasting(...)

startBroadcasting(options: { serviceUuid: string; localName: string; }) => Promise<void>

Manually trigger the device to act as a Peripheral.

| Param | Type | | ------------- | -------------------------------------------------------- | | options | { serviceUuid: string; localName: string; } |


stopBroadcasting()

stopBroadcasting() => Promise<void>

addListener('onDeviceDiscovered', ...)

addListener(eventName: 'onDeviceDiscovered', listenerFunc: (result: { device: BleDevice; }) => void) => Promise<PluginListenerHandle>

Event listener fired when a device is found while the app is in the FOREGROUND.

| Param | Type | | ------------------ | --------------------------------------------------------------------------------- | | eventName | 'onDeviceDiscovered' | | listenerFunc | (result: { device: BleDevice; }) => void |

Returns: Promise<PluginListenerHandle>


addListener('onOverlayWakeup', ...)

addListener(eventName: 'onOverlayWakeup', listenerFunc: (result: { macAddress: string; name?: string; uuid?: string; }) => void) => Promise<PluginListenerHandle>

| Param | Type | | ------------------ | --------------------------------------------------------------------------------------- | | eventName | 'onOverlayWakeup' | | listenerFunc | (result: { macAddress: string; name?: string; uuid?: string; }) => void |

Returns: Promise<PluginListenerHandle>


requestOverlayPermission()

requestOverlayPermission() => Promise<void>

Interfaces

PluginListenerHandle

| Prop | Type | | ------------ | ----------------------------------------- | | remove | () => Promise<void> |

BleDevice

| Prop | Type | | ------------------ | ------------------- | | id | string | | uuid | string | | macAddress | string | | name | string | | rssi | number | | distance | number | | txPowerLevel | number | | timestamp | number |