小程序蓝牙BLE链接设备读取数据

本文提供了用于微信小程序蓝牙连接的一系列函数,包括初始化、连接、断开、读写特征值、监听变化等操作,以及搜索和管理蓝牙设备的方法。代码示例展示了如何连接特定设备并与其进行数据交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一丶封装小程序蓝牙连接

// wx_ble_api.js
/**
 * @description
 * 连接蓝牙低功耗设备。
 * 若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,
 * 可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需再次进行搜索操作。
 * @param {
 *  deviceId  蓝牙设备 id
 *  timeout 超时时间,单位 ms,不填表示不会超时
 * }
 * @returns {Promise<any>}
 */
export function createBLEConnection({
	deviceId,
	timeout
}) {
	return new Promise((resolve, reject) =>
		wx.createBLEConnection({
			deviceId,
			timeout,
			success: resolve,
			fail: reject,
		})
	);
}

/**
 * @description
 * 断开与蓝牙低功耗设备的连接。
 * @param {
 *  deviceId  蓝牙设备 id
 * }
 * @returns {Promise<any>}
 */
export function closeBLEConnection() {
	return new Promise((resolve, reject) =>
		wx.closeBLEConnection({
			deviceId: wx.getStorageSync('wx_ble_deviceId'),
			success: resolve,
			fail: reject
		})
	);
}

/**
 * @description
 * 向蓝牙低功耗设备特征值中写入二进制数据。注意:必须设备的特征支持 write 才可以成功调用。
 * @param {
 *  deviceId  蓝牙设备 id
 *  serviceId  蓝牙特征对应服务的 UUID
 *  characteristicId 蓝牙特征的 UUID
 *  value 蓝牙设备特征对应的二进制值
 * }
 * @returns {Promise<any>}
 */
export function writeBLECharacteristicValue({
	deviceId,
	serviceId,
	characteristicId,
	value,
}) {
	return new Promise((resolve, reject) =>
		wx.writeBLECharacteristicValue({
			...arguments[0],
			success: resolve,
			fail: reject,
		})
	);
}

/**
 * @description
 * 读取蓝牙低功耗设备特征值的二进制数据。注意:必须设备的特征支持 read 才可以成功调用
 * @param {
 *  deviceId  蓝牙设备 id
 *  serviceId  蓝牙特征对应服务的 UUID
 *  characteristicId 蓝牙特征的 UUID
 * }
 * @returns {Promise<any>}
 */
export function readBLECharacteristicValue({
	deviceId,
	serviceId,
	characteristicId,
}) {
	return new Promise((resolve, reject) =>
		wx.readBLECharacteristicValue({
			serviceId,
			deviceId,
			characteristicId,
			success: resolve,
			fail: reject,
		})
	);
}

/**
 * @description
 * 获取蓝牙低功耗设备所有服务 (service)
 * @param {
 *  deviceId  蓝牙设备 id
 * }
 * @returns {Promise<any>}
 */
export function getBLEDeviceServices({
	deviceId
}) {
	return new Promise((resolve, reject) =>
		wx.getBLEDeviceServices({
			deviceId,
			success: (res) => {
				const {
					services
				} = res;
				console.log("device services:", services);
				resolve({
					services
				});
			},
			fail: reject,
		})
	);
}

/**
 * @description
 * 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)
 * @param {
 *  deviceId  蓝牙设备 id
 *  serviceId  蓝牙特征对应服务的 UUID
 * }
 * @returns {Promise<any>}
 */
export function getBLEDeviceCharacteristics({
	deviceId,
	serviceId
}) {
	return new Promise((resolve, reject) =>
		wx.getBLEDeviceCharacteristics({
			deviceId,
			serviceId,
			success: (res) => {
				const {
					characteristics
				} = res;
				console.log("device getBLEDeviceCharacteristics:", characteristics);
				resolve({
					characteristics,
					serviceId
				});
			},
			fail: reject,
		})
	);
}

/**
 * @description
 * 开始搜寻附近的蓝牙外围设备。
 * @param {
 *  serviceId  蓝牙特征对应服务的 UUID
 * }
 * @returns {Promise<any>}
 */
export function startBlueToothDevicesDiscovery() {
	return new Promise((resolve, reject) =>
		wx.startBluetoothDevicesDiscovery({
			...arguments[0],
			success: resolve,
			fail: reject,
		})
	);
}

/**
 * @description
 * 停止搜索附近的蓝牙外围设备。
 * @param {}
 * @returns {Promise<any>}
 */
export function stopBlueToothDevicesDiscovery() {
	return new Promise((resolve, reject) =>
		wx.stopBluetoothDevicesDiscovery({
			success: resolve,
			fail: reject
		})
	);
}

/**
 * @description
 * 初始化蓝牙模块。iOS 上开启主机/从机(外围设备)模式时需分别调用一次,并指定对应的 mode
 * @param {}
 * @returns {Promise<any>}
 */
export function openBlueToothAdapter() {
	let isBugPhone = false;
	try {
		const {
			model
		} = wx.getSystemInfoSync();
		isBugPhone =
			model.indexOf("iPhone 6") !== -1 || model.indexOf("iPhone 7") !== -1;
	} catch (e) {
		console.error("wx.getSystemInfoSync() error", e);
	}
	return (openBlueToothAdapter = function() {
		return new Promise((resolve, reject) => {
			if (!isBugPhone) {
				wx.openBluetoothAdapter({
					success: resolve,
					fail: reject
				});
			} else {
				setTimeout(() => {
					wx.openBluetoothAdapter({
						success: resolve,
						fail: reject
					});
				}, 150);
			}
		});
	})();
}

/**
 * @description
 * 关闭蓝牙模块。调用该方法将断开所有已建立的连接并释放系统资源。建议在使用蓝牙流程后,与 wx.openBluetoothAdapter 成对调用。
 * @param {}
 * @returns {Promise<any>}
 */
export function closeBlueToothAdapter() {
	return new Promise((resolve, reject) =>
		wx.closeBluetoothAdapter({
			success: resolve,
			fail: reject
		})
	);
}

/**
 * @description
 * 根据主服务 UUID 获取已连接的蓝牙设备。
 * @param {
 *  serviceId  蓝牙特征对应服务的 UUID
 * }
 * @returns {Promise<any>}
 */
export function getConnectedBlueToothDevices({
	services
}) {
	return new Promise((resolve, reject) =>
		wx.getConnectedBluetoothDevices({
			services,
			success: resolve,
			fail: reject,
		})
	);
}

/**
 * @description
 * 监听蓝牙低功耗设备的特征值变化事件。
 * @param {
 *  function listener  蓝牙低功耗设备的特征值变化事件的监听函数
 * }
 * @returns
 */
export function onBLECharacteristicValueChange(cb) {
	wx.onBLECharacteristicValueChange(cb);
}

/**
 * @description
 * 监听蓝牙适配器状态变化事件
 * @param {
 *  function listener  蓝牙适配器状态变化事件的监听函数
 * }
 * @returns
 */
export function onBluetoothAdapterStateChange(cb) {
	wx.onBluetoothAdapterStateChange(cb);
}

/**
 * @description
 * 监听蓝牙低功耗连接状态改变事件。包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
 * @param {
 *  function listener  蓝牙低功耗连接状态改变事件的监听函数
 * }
 * @returns
 */
export function onBLEConnectionStateChange(cb) {
	wx.onBLEConnectionStateChange(cb);
}

/**
 * @description
 * 监听搜索到新设备的事件
 * @param {
 *  function listener  搜索到新设备的事件的监听函数
 * }
 * @returns
 */
export function onBlueToothDeviceFound(cb) {
	wx.onBluetoothDeviceFound(cb);
}

/**
 * @description
 * 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征。注意:必须设备的特征支持 notify 或者 indicate 才可以成功调用
 * @param {
 *  deviceId  蓝牙设备 id
 *  serviceId  蓝牙特征对应服务的 UUID
 *  characteristicId 蓝牙特征的 UUID
 *  state 是否启用 notify
 * }
 * @returns {Promise<any>}
 */
export function notifyBLECharacteristicValueChange({
	deviceId,
	serviceId,
	characteristicId,
	state,
}) {
	return new Promise((resolve, reject) =>
		wx.notifyBLECharacteristicValueChange({
			deviceId,
			serviceId,
			characteristicId,
			state,
			success: resolve,
			fail: reject,
		})
	);
}

/**
 * @description
 * 获取在蓝牙模块生效期间所有搜索到的蓝牙设备。包括已经和本机处于连接状态的设备
 * @param {}
 * @returns {Promise<any>}
 */
export function getBlueToothDevices() {
	return new Promise((resolve, reject) =>
		wx.getBluetoothDevices({
			success: resolve,
			fail: reject
		})
	);
}

/**
 * @description
 * 获取本机蓝牙适配器状态
 * @param {}
 * @returns {Promise<any>}
 */
export function getBlueToothAdapterState() {
	return new Promise((resolve, reject) =>
		wx.getBluetoothAdapterState({
			success: resolve,
			fail: reject
		})
	);
}

/**
 * 注册读写notify监听,该事件要发生在连接上设备之后
 * @param deviceId 已连接的设备id
 * @param targetServiceUUID 目标蓝牙服务UUID
 * @param targetCharacteristics 目标蓝牙服务对应的特征值,包括writeCharacteristicId, notifyCharacteristicId, readCharacteristicId
 * @returns {Promise<{serviceId, characteristicId: *, deviceId: *}>}
 */
export async function notifyBLE({
	deviceId,
	targetServiceUUID,
	targetCharacteristics,
}) {
	const {
		characteristics,
		serviceId
	} = await findTargetServiceByUUID({
		deviceId,
		targetServiceUUID,
	});
	const {
		writeCharacteristicId,
		notifyCharacteristicId,
		readCharacteristicId,
	} = targetCharacteristics;
	let characteristicId = "";
	const notifyItem = characteristics.find(
		({
			uuid
		}) => uuid === notifyCharacteristicId
	);
	if (notifyItem) {
		await notifyBLECharacteristicValueChange({
			deviceId,
			serviceId,
			characteristicId: notifyCharacteristicId,
			state: true,
		});
		console.warn("已注册notify事件 characteristicId:", notifyCharacteristicId);
	}
	const readItem = characteristics.find(
		({
			uuid
		}) => uuid === readCharacteristicId
	);
	if (readItem) {
		await readBLECharacteristicValue({
			deviceId,
			serviceId,
			characteristicId: readCharacteristicId,
		});
		console.warn("本次读特征值是 characteristicId:", readCharacteristicId);
	}
	const writeItem = characteristics.find(
		({
			uuid
		}) => uuid === writeCharacteristicId
	);
	if (writeItem) {
		characteristicId = writeCharacteristicId;
		console.warn("本次写特征值是 characteristicId:", writeCharacteristicId);
	}
	return {
		serviceId,
		characteristicId
	};
}

/**
 * @description
 * 获取本机蓝牙适配器状态
 * @param {
 *  deviceId 已连接的设备id
 *  targetServiceUUID 目标蓝牙服务UUID
 * }
 * @returns {Promise<any>}
 */
async function findTargetServiceByUUID({
	deviceId,
	targetServiceUUID
}) {
	const {
		services
	} = await getBLEDeviceServices({
		deviceId
	});
	for (const {
			isPrimary,
			uuid
		} of services) {
		if (isPrimary && uuid.toUpperCase() === targetServiceUUID) {
			console.log('即将建立通信的服务uuid:', uuid);
			return await getBLEDeviceCharacteristics({
				deviceId,
				serviceId: uuid
			});
		}
	}
}

二丶连接蓝牙

// 连接的设备ID
const deviceId = "xx:xx:xx";
// 表端服务ID
const servicesId = "xxx-xxx-xx";
// notify数据的特征值
const notifyCharacteristicId = "xxx-xxx-xx";
// 写入数据的特征值
const writeCharacteristicId = "xxx-xxx-xx";
async function bleConnect() {
  await openBlueToothAdapter();
  // 扫描设备
  findDevices();
}

async function findDevices() {
  await startBlueToothDevicesDiscovery();
  // 定时关闭什么时候停止扫描
  setTimeout(async () => {
    await stopBlueToothDevicesDiscovery();
    const { devices } = await getBlueToothDevices();
    // devices 就是扫描出来的所有设备
    // ios已连接的设备没有展示,安卓可以展示已连接的。
    // 设备列表展示后点击后连接
  }, 3000);
}

async function connectDevice() {
  await createBLEConnection({
    deviceId: deviceId,
  });

  // 连接这个设备的服务,该服务ID由表端开发提供
  connectServices();
}

async function connectServices() {
  // 获取蓝牙设备所有服务(service)。
  await getBLEDeviceServices({
    deviceId: deviceId,
  });
  //获取对应服务的所有特征值
  await getBLEDeviceCharacteristics({
    deviceId: deviceId,
    serviceId: servicesId,
  });
  // 启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。
  // 注意:必须设备的特征值支持 notify 或者 indicate 才可以成功调用。 另外,必须先启用 notifyBLECharacteristicValueChange 才能监听到设备 characteristicValueChange 事件
  await notifyBLECharacteristicValueChange({
    deviceId: deviceId,
    serviceId: servicesId,
    characteristicId: notifyCharacteristicId,
    state: true,
  });

  // 这步做完就连接成功,可以监听对应特征值的数据了
  watchNotify();
}

function watchNotify() {
  onBLECharacteristicValueChange((res) => {
    // 监听数据返回转成二进制
    let hex = arrayBufferToHex(res.value).toUpperCase();
    console.log(hex);
  });
}

// ArrayBuffer转16进制字符串示例
function arrayBufferToHex(buffer) {
  let hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
    return ("00" + bit.toString(16)).slice(-2);
  });
  return hexArr.join("");
}

// 写入数据给表端writeCharacteristicId
function writeInstruct(data) {
  // data = [0x01,0x02....]
  let buffer = new ArrayBuffer(data.length);
  let dataViewLast = new DataView(buffer);
  for (let i = 0; i < data.length; i++) {
    dataViewLast.setUint8(i, data[i]);
  }
  const value = dataViewLast.buffer;
  writeBLECharacteristicValue({
    // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
    deviceId: deviceId,
    // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
    serviceId: servicesId,
    // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
    characteristicId: writeCharacteristicId,
    // 这里的value是ArrayBuffer类型
    value: value,
  });
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值