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

@leir0ng/uniapp-ble-sdk

v1.0.4

Published

A comprehensive BLE (Bluetooth Low Energy) SDK for uniapp with connection management, device discovery, and data handling

Downloads

9

Readme

uniapp-ble-sdk

一个功能完整的 UniApp 蓝牙低功耗 (BLE) SDK,提供设备搜索、连接管理、数据传输等完整功能。 如果你想用测试可以参考https://gitee.com/lei_rong/uniapp-ble-sdk-test-v这里是uniapp测试工程[直接下载运行就行]

特性

  • 🔄 自动重连: 支持连接断开后自动重连
  • 🔍 设备搜索: 支持过滤条件的设备搜索
  • 📡 连接管理: 完整的连接状态管理和监听
  • 📊 数据传输: 支持特征值读写和通知
  • 🛡️ 错误处理: 完善的错误处理和事件回调
  • 📱 跨平台: 支持 App、微信小程序等平台
  • 🎯 TypeScript: 完整的 TypeScript 支持

安装

npm install uniapp-ble-sdk

快速开始

基础使用

import { BLEManager, BLEEventType, ConnectionState } from 'uniapp-ble-sdk';

// 创建BLE管理器实例
const bleManager = new BLEManager({
  autoReconnect: true,
  reconnectInterval: 3000,
  maxReconnectAttempts: 5
});

// 初始化
await bleManager.initialize();

// 监听事件
bleManager.on(BLEEventType.DEVICE_FOUND, (device) => {
  console.log('发现设备:', device);
});

bleManager.on(BLEEventType.CONNECTION_STATE_CHANGE, (event) => {
  console.log('连接状态变化:', event);
});

// 开始搜索设备
await bleManager.startDeviceDiscovery({
  nameKeyword: 'MyDevice',
  minRSSI: -80
});

// 连接设备
await bleManager.connect('device-id');

// 获取服务和特征值
const services = await bleManager.getDeviceServices();
const characteristics = await bleManager.getDeviceCharacteristics(serviceId);

// 启用通知
await bleManager.notifyCharacteristicValueChange(serviceId, characteristicId);

// 监听数据
bleManager.on(BLEEventType.CHARACTERISTIC_VALUE_CHANGE, (data) => {
  console.log('收到数据:', data);
});

// 写入数据
const buffer = new ArrayBuffer(4);
await bleManager.writeCharacteristicValue(serviceId, characteristicId, buffer);

// 断开连接
await bleManager.disconnect();

// 销毁管理器
await bleManager.destroy();

API 文档

BLEManager

主要的 BLE 管理类。

构造函数

constructor(options?: BLEOptions)

参数:

  • options - 可选配置项
interface BLEOptions {
  allowDuplicatesKey?: boolean;     // 是否允许重复上报同一设备,默认 false
  interval?: number;                // 上报设备间隔(ms),默认 0
  autoReconnect?: boolean;          // 是否启用自动重连,默认 true
  reconnectInterval?: number;       // 重连间隔(ms),默认 3000
  maxReconnectAttempts?: number;    // 最大重连次数,默认 5
  connectionTimeout?: number;       // 连接超时时间(ms),默认 10000
}

方法

initialize(): Promise

初始化蓝牙适配器。

await bleManager.initialize();
destroy(): Promise

销毁管理器,关闭所有连接和监听。

await bleManager.destroy();
getAdapterState(): Promise

获取蓝牙适配器状态。

const state = await bleManager.getAdapterState();
console.log('蓝牙可用:', state.available);
console.log('正在搜索:', state.discovering);
startDeviceDiscovery(filter?: DeviceFilter): Promise

开始搜索蓝牙设备。

// 搜索所有设备
await bleManager.startDeviceDiscovery();

// 使用过滤器搜索
await bleManager.startDeviceDiscovery({
  nameKeyword: 'sensor',
  minRSSI: -70,
  services: ['180F'] // 电池服务
});
stopDeviceDiscovery(): Promise

停止搜索蓝牙设备。

await bleManager.stopDeviceDiscovery();
getDiscoveredDevices(): BLEDevice[]

获取已发现的设备列表。

const devices = bleManager.getDiscoveredDevices();
connect(deviceId: string): Promise

连接到指定设备。

await bleManager.connect('device-id-123');
disconnect(): Promise

断开当前连接。

await bleManager.disconnect();
getDeviceServices(deviceId?: string): Promise<BLEService[]>

获取设备服务列表。

const services = await bleManager.getDeviceServices();
getDeviceCharacteristics(serviceId: string, deviceId?: string): Promise<BLECharacteristic[]>

获取设备特征值列表。

const characteristics = await bleManager.getDeviceCharacteristics('180F');
getDeviceRSSI(deviceId?: string): Promise

获取设备信号强度。

const rssi = await bleManager.getDeviceRSSI();
notifyCharacteristicValueChange(serviceId: string, characteristicId: string, state?: boolean, deviceId?: string): Promise

启用或禁用特征值变化通知。

// 启用通知
await bleManager.notifyCharacteristicValueChange(serviceId, characteristicId, true);

// 禁用通知
await bleManager.notifyCharacteristicValueChange(serviceId, characteristicId, false);
readCharacteristicValue(serviceId: string, characteristicId: string, deviceId?: string): Promise

读取特征值。

const data = await bleManager.readCharacteristicValue(serviceId, characteristicId);
writeCharacteristicValue(serviceId: string, characteristicId: string, value: ArrayBuffer, writeType?: WriteType, deviceId?: string): Promise

写入特征值。

const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setUint32(0, 1234, true);

await bleManager.writeCharacteristicValue(
  serviceId, 
  characteristicId, 
  buffer, 
  WriteType.WRITE
);
setMTU(mtu: number, deviceId?: string): Promise

设置最大传输单元 (22-512)。

await bleManager.setMTU(247);
getConnectionState(): ConnectionState

获取当前连接状态。

const state = bleManager.getConnectionState();
getConnectedDevice(): BLEDevice | null

获取当前连接的设备信息。

const device = bleManager.getConnectedDevice();

事件监听

on(event: string, callback: EventCallback): void

添加事件监听器。

bleManager.on(BLEEventType.DEVICE_FOUND, (device) => {
  console.log('发现设备:', device);
});
off(event: string, callback?: EventCallback): void

移除事件监听器。

bleManager.off(BLEEventType.DEVICE_FOUND, callback);
// 或移除所有监听器
bleManager.off(BLEEventType.DEVICE_FOUND);

事件类型

enum BLEEventType {
  ADAPTER_STATE_CHANGE = 'adapterStateChange',           // 适配器状态变化
  DEVICE_FOUND = 'deviceFound',                          // 发现新设备
  CONNECTION_STATE_CHANGE = 'connectionStateChange',     // 连接状态变化
  CHARACTERISTIC_VALUE_CHANGE = 'characteristicValueChange', // 特征值变化
  ERROR = 'error'                                        // 错误事件
}

连接状态

enum ConnectionState {
  DISCONNECTED = 'disconnected',       // 未连接
  CONNECTING = 'connecting',           // 连接中
  CONNECTED = 'connected',             // 已连接
  DISCONNECTING = 'disconnecting'      // 断开连接中
}

写入类型

enum WriteType {
  WRITE = 'write',                     // 需要回复
  WRITE_NO_RESPONSE = 'writeNoResponse' // 不需要回复
}

完整示例

Vue 3 组件示例

<template>
  <view class="ble-demo">
    <button @click="initBLE">初始化蓝牙</button>
    <button @click="startScan" :disabled="!isInitialized">开始扫描</button>
    <button @click="stopScan">停止扫描</button>
    
    <view class="device-list">
      <view 
        v-for="device in devices" 
        :key="device.deviceId"
        class="device-item"
        @click="connectDevice(device.deviceId)"
      >
        <text>{{ device.name || device.localName || '未知设备' }}</text>
        <text>{{ device.RSSI }}dBm</text>
      </view>
    </view>
    
    <view v-if="connectedDevice" class="connected-info">
      <text>已连接: {{ connectedDevice.name }}</text>
      <button @click="sendData">发送数据</button>
      <button @click="disconnect">断开连接</button>
    </view>
    
    <view class="logs">
      <text v-for="log in logs" :key="log.id">{{ log.message }}</text>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, onUnmounted } from 'vue';
import { BLEManager, BLEEventType, ConnectionState, type BLEDevice } from 'uniapp-ble-sdk';

const bleManager = new BLEManager({
  autoReconnect: true,
  reconnectInterval: 3000,
  maxReconnectAttempts: 3
});

const isInitialized = ref(false);
const devices = ref<BLEDevice[]>([]);
const connectedDevice = ref<BLEDevice | null>(null);
const logs = ref<Array<{ id: number, message: string }>>([]);
let logId = 0;

// 添加日志
const addLog = (message: string) => {
  logs.value.push({
    id: logId++,
    message: `${new Date().toLocaleTimeString()}: ${message}`
  });
  if (logs.value.length > 100) {
    logs.value.shift();
  }
};

// 初始化蓝牙
const initBLE = async () => {
  try {
    await bleManager.initialize();
    isInitialized.value = true;
    addLog('蓝牙初始化成功');
    
    // 设置事件监听
    setupEventListeners();
  } catch (error) {
    addLog(`蓝牙初始化失败: ${error.message}`);
  }
};

// 设置事件监听
const setupEventListeners = () => {
  bleManager.on(BLEEventType.DEVICE_FOUND, (device: BLEDevice) => {
    const existingIndex = devices.value.findIndex(d => d.deviceId === device.deviceId);
    if (existingIndex >= 0) {
      devices.value[existingIndex] = device;
    } else {
      devices.value.push(device);
    }
    addLog(`发现设备: ${device.name || device.localName || device.deviceId}`);
  });
  
  bleManager.on(BLEEventType.CONNECTION_STATE_CHANGE, (event) => {
    addLog(`连接状态: ${event.deviceId} - ${event.state}`);
    if (event.state === ConnectionState.CONNECTED) {
      connectedDevice.value = bleManager.getConnectedDevice();
    } else if (event.state === ConnectionState.DISCONNECTED) {
      connectedDevice.value = null;
    }
  });
  
  bleManager.on(BLEEventType.CHARACTERISTIC_VALUE_CHANGE, (data) => {
    const view = new DataView(data.value);
    addLog(`收到数据: ${Array.from(new Uint8Array(data.value)).map(b => b.toString(16).padStart(2, '0')).join(' ')}`);
  });
  
  bleManager.on(BLEEventType.ERROR, (error) => {
    addLog(`错误: ${error.errMsg}`);
  });
};

// 开始扫描
const startScan = async () => {
  try {
    devices.value = [];
    await bleManager.startDeviceDiscovery({
      minRSSI: -80
    });
    addLog('开始扫描设备');
  } catch (error) {
    addLog(`开始扫描失败: ${error.message}`);
  }
};

// 停止扫描
const stopScan = async () => {
  try {
    await bleManager.stopDeviceDiscovery();
    addLog('停止扫描');
  } catch (error) {
    addLog(`停止扫描失败: ${error.message}`);
  }
};

// 连接设备
const connectDevice = async (deviceId: string) => {
  try {
    await bleManager.connect(deviceId);
    addLog(`连接设备: ${deviceId}`);
    
    // 获取服务和特征值
    const services = await bleManager.getDeviceServices();
    addLog(`发现 ${services.length} 个服务`);
    
    // 这里可以根据具体需求处理服务和特征值
    // 例如启用某个特征值的通知
    if (services.length > 0) {
      const characteristics = await bleManager.getDeviceCharacteristics(services[0].uuid);
      addLog(`服务 ${services[0].uuid} 有 ${characteristics.length} 个特征值`);
      
      // 查找可通知的特征值
      const notifyChar = characteristics.find(c => c.properties.notify);
      if (notifyChar) {
        await bleManager.notifyCharacteristicValueChange(services[0].uuid, notifyChar.uuid);
        addLog(`启用特征值通知: ${notifyChar.uuid}`);
      }
    }
  } catch (error) {
    addLog(`连接失败: ${error.message}`);
  }
};

// 发送数据
const sendData = async () => {
  try {
    const device = bleManager.getConnectedDevice();
    if (!device) return;
    
    const services = await bleManager.getDeviceServices();
    if (services.length === 0) return;
    
    const characteristics = await bleManager.getDeviceCharacteristics(services[0].uuid);
    const writeChar = characteristics.find(c => c.properties.write || c.properties.writeNoResponse);
    
    if (writeChar) {
      const buffer = new ArrayBuffer(4);
      const view = new DataView(buffer);
      view.setUint32(0, Date.now() % 10000, true);
      
      await bleManager.writeCharacteristicValue(services[0].uuid, writeChar.uuid, buffer);
      addLog('数据发送成功');
    } else {
      addLog('未找到可写特征值');
    }
  } catch (error) {
    addLog(`发送数据失败: ${error.message}`);
  }
};

// 断开连接
const disconnect = async () => {
  try {
    await bleManager.disconnect();
    addLog('主动断开连接');
  } catch (error) {
    addLog(`断开连接失败: ${error.message}`);
  }
};

// 组件销毁时清理
onUnmounted(async () => {
  await bleManager.destroy();
});
</script>

<style scoped>
.ble-demo {
  padding: 20px;
}

.device-list {
  margin: 20px 0;
}

.device-item {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  border: 1px solid #eee;
  margin-bottom: 5px;
  border-radius: 5px;
}

.connected-info {
  background-color: #e8f5e8;
  padding: 10px;
  border-radius: 5px;
  margin: 10px 0;
}

.logs {
  max-height: 300px;
  overflow-y: auto;
  background-color: #f5f5f5;
  padding: 10px;
  border-radius: 5px;
  font-family: monospace;
  font-size: 12px;
}
</style>

注意事项

  1. 权限配置: 确保在 manifest.json 中配置了蓝牙权限:
{
  "mp-weixin": {
    "permission": {
      "scope.bluetooth": {
        "desc": "用于连接蓝牙设备"
      }
    }
  },
  "app-plus": {
    "modules": {
      "Bluetooth": {}
    }
  }
}
  1. 平台差异: 不同平台对BLE支持可能有差异,建议在目标平台上充分测试。

  2. 连接管理: 建议在应用退出或页面销毁时主动断开连接和销毁管理器。

  3. 错误处理: 蓝牙操作可能因为各种原因失败,建议完善错误处理逻辑。

  4. 性能优化: 大量数据传输时注意控制频率,避免造成性能问题。

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!

更新日志

1.0.0

  • 初始版本发布
  • 支持基础的BLE功能
  • 自动重连机制
  • 完整的事件系统
  • TypeScript 支持