kitchendDevice/tools/bluetooth.js

425 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import $store from '@/store'
import $model from '@/tools/model.js'
import $tools from '@/tools/tools.js'
import $data from '@/content.json'
let unitList = []
let devicesList = []
let searchTimer = null
let UNIT_MAP = $data.units
// 初始化蓝牙
function openBluetoothAdapter() {
devicesList = []
unitList = []
clearTimeout(searchTimer);
uni.openBluetoothAdapter({
success: e => {
$store.commit("changeBluetoothValue", {
bleTipsText: "蓝牙搜索中",
isConnectStatus: 0,
unitList: $data.unitMinus,
})
startBluetoothDeviceDiscovery()
},
fail: e => {
$store.commit("changeBluetoothValue", {
bleTipsText: "连接超时,点击重新连接",
isConnectStatus: 1,
unitList: $data.unitMinus,
})
}
});
}
// 开始搜寻附近的蓝牙外围设备
function startBluetoothDeviceDiscovery() {
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
interval: 200,
success: res => {
onBluetoothDeviceFound();
searchTimer = setTimeout(() => {
uni.stopBluetoothDevicesDiscovery()
if (!devicesList.length) {
clearTimeout(searchTimer);
$store.commit("changeBluetoothValue", {
bleTipsText: "连接超时,点击重新连接",
isConnectStatus: 1
});
}
}, 30000); // 30秒超时
},
fail: res => {
$store.commit("changeBluetoothValue", {
bleTipsText: "连接超时,点击重新连接",
isConnectStatus: 1
})
}
});
}
/**
* 发现外围设备
*/
function onBluetoothDeviceFound() {
uni.onBluetoothDeviceFound(res => {
res.devices.forEach(device => {
device.advertisData = device.advertisData ? device.advertisData : ''
let value = ab2hex(device.advertisData, "")
let id = value.substring(0, 4)
if (!device.name && !device.localName) {
return
}
if (device.name.toLowerCase().indexOf('pc-c06pro') != -1 ||
device.name.toLowerCase().indexOf('pc-c02pro') != -1 ||
device.name.toLowerCase().indexOf('pc-c09pro') != -1 ||
device.name.toLowerCase().indexOf('pc-c10pro') != -1 ||
device.name.toLowerCase().indexOf('pc-c07pro') != -1 ||
(device.localName && device.localName.toLowerCase().indexOf('pc-c07pro') != -1) ||
(device.localName && device.localName.toLowerCase().indexOf('pc-c10pro') != -1) ||
(device.localName && device.localName.toLowerCase().indexOf('pc-c06pro') != -1) ||
(device.localName && device.localName.toLowerCase().indexOf('pc-c02pro') != -1) ||
(device.localName && device.localName.toLowerCase().indexOf('pc-c09pro') != -1)) {
clearTimeout(searchTimer);
const bytes = new Uint8Array(device.advertisData);
const macBytes = bytes.slice(6, 12);
device.macAddr = $tools.ab2hex(macBytes, ':').toUpperCase()
stopBluetoothDevicesDiscovery()
Bluetoothfilter(device)
return
}
})
});
}
// 过滤蓝牙
function Bluetoothfilter(device) {
const foundDevices = devicesList
const idx = inArray(foundDevices, "deviceId", device.deviceId)
if (idx === -1) {
devicesList.push(device);
// handleDevType(device)
connectDevice(device.deviceId)
}
}
// 排查设备
function handleDevType(device) {
$model.getCheckDevice({
mac: device.macAddr,
}).then(res => {
console.log("排查设备:", device, res)
if (res.code == 0) {
connectDevice(device.deviceId)
} else {
devicesList = []
$tools.msg('设备未登记,请联系出售方进行系统认证')
$store.commit("changeBluetoothValue", {
type: 1,
isConnectStatus: 1,
bleTipsText: "连接超时,点击重新连接",
})
}
})
}
//连接设备
function connectDevice(device_id) {
uni.createBLEConnection({
deviceId: device_id,
success: res => {
setTimeout(function() {
getBLEDeviceServices(device_id)
}, 200)
},
fail: res => {
$store.commit("changeBluetoothValue", {
type: 1,
isConnectStatus: 1,
bleTipsText: "连接超时,点击重新连接",
})
}
});
}
/**
* 获取设备的UUID
*/
function getBLEDeviceServices(device_id) {
let serviceList = [];
uni.getBLEDeviceServices({
deviceId: device_id,
success: res => {
console.log("获取设备的UUID成功", res)
stopBluetoothDevicesDiscovery();
serviceList = res.services;
for (let i = 0; i < serviceList.length; i++) {
let service = serviceList[i];
if (service.uuid.indexOf("FFF0") != -1) {
getBLEDeviceCharacteristics(device_id, service.uuid);
break;
}
}
},
fail: res => {
$store.commit("changeBluetoothValue", {
type: 1,
isConnectStatus: 1,
bleTipsText: "连接超时,点击重新连接",
})
console.log('获取设备的UUID失败:', res)
}
});
}
/**
* 获取指定服务的特征值
*/
function getBLEDeviceCharacteristics(deviceId, serviceId) {
let characteristicsList = [];
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: res => {
let write, notify
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i];
if (item.uuid.indexOf('0000FFF2') != -1) {
write = item.uuid
} else if (item.uuid.indexOf('0000FFF1') != -1) {
notify = item.uuid
}
}
getBLECharacteristicValueChange(deviceId, serviceId, notify, write)
},
fail: res => {
$store.commit("changeBluetoothValue", {
type: 1,
isConnectStatus: 1,
bleTipsText: "连接超时,点击重新连接",
})
console.log('获取特征值失败:', JSON.stringify(res))
}
})
}
function getBLECharacteristicValueChange(deviceId, serviceId, notify, write) {
let that = this
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: notify,
state: true,
success: () => {
$store.commit('changeBluetoothValue', {
deviceId: deviceId,
serviceId: serviceId,
notify: notify,
write: write,
unit: "g",
type: 1,
countWeight: 0,
oldCountWeight: 0,
bleTipsText: "测量中,请将食物放到秤上",
isConnectStatus: 2
})
uni.onBLECharacteristicValueChange(function(res) {
const value = res.value
const dataView = new DataView(value)
const header = dataView.getUint8(0)
// MCU主动上报数据
if (header === 0xC7) {
const cmd = dataView.getUint8(2)
switch (cmd) {
case 0x02:
const statusByte = dataView.getUint8(4)
const isNegative = !!(statusByte & 0x80) // 最高位表示正负
const statusType = statusByte & 0x0F // 状态类型
// 组合24位重量值 (大端序)
const weightValue =
(dataView.getUint8(5) << 16) |
(dataView.getUint8(6) << 8) |
dataView.getUint8(7)
// 精度和单位
const unitByte = dataView.getUint8(8)
const precision = (unitByte & 0xF0) >> 4 // 高4位精度
const unitIndex = unitByte & 0x0F // 低4位单位
// 计算实际重量
let finalWeight = weightValue / Math.pow(10, precision)
console.log("类型:", cmd, "重量",
finalWeight, "小数点", precision, "单位", UNIT_MAP[unitIndex])
if (isNegative) finalWeight = -finalWeight
$store.commit("changeBluetoothValue", {
countWeight: finalWeight,
unit: UNIT_MAP[unitIndex],
type: statusType
})
break
case 0x03:
break
case 0x08:
const start0 = []
const value2 = $tools.ab2hex(res.value, "");
const start = parseUnitMask(value2.substring(8, 10), UNIT_MAP.slice(0,
7))
const start1 = parseUnitMask(value2.substring(10, 12), UNIT_MAP.slice(8,
10))
start.push.apply(start, start1)
if (start.length) {
$data.unitMinus.forEach(item => {
start.forEach(item2 => {
if (item.unit == item2) {
start0.push(item)
}
})
})
}
$store.commit("changeBluetoothValue", {
unitList: start0.length ? start0 : $data.unitMinus
})
console.log("2222222", start, start0)
break
}
}
})
},
fail: res => {
console.log('获取特征值失败:', JSON.stringify(res))
}
})
}
function inArray(arr, key, val) {
if (!arr || !arr.length || typeof arr != 'object' || !Array.isArray(arr)) {
return -1
}
for (let i = 0; i < arr.length; i++) {
if (!key) {
if (arr[i] == val) {
return i
}
} else if (arr[i][key] === val) {
return i
}
}
return -1;
}
function ab2hex(buffer, split) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join(split);
}
/**
* 断开蓝牙模块
*/
function closeBluetoothAdapter() {
uni.closeBluetoothAdapter({
success: res => {
clearTimeout(searchTimer);
$store.commit("changeBluetoothValue", {
deviceId: "",
serviceId: "",
notify: "",
write: "",
unit: "g",
countWeight: 0,
oldCountWeight: 0,
type: 1,
unitList: $data.unitMinus,
isConnectStatus: 1,
bleTipsText: "连接超时,点击重新连接",
})
console.log('蓝牙模块关闭成功');
}
})
}
/**
* 断开蓝牙连接
*/
function closeBLEConnection(deviceId) {
uni.closeBLEConnection({
deviceId: deviceId,
success: res => {
console.log('断开蓝牙连接成功');
}
});
}
// 监听蓝牙连接状态
function onBLEConnectionStateChange() {
uni.onBLEConnectionStateChange(function(res) {
console.log("监听蓝牙连接状态", res.connected)
if (!res.connected) {
$store.commit("changeBluetoothValue", {
bleTipsText: "连接超时,点击重新连接",
unitList: $data.unitMinus,
isConnectStatus: 1,
type: 1,
})
closeBLEConnection()
closeBluetoothAdapter()
}
$store.commit("changeBluetooth", res.connected);
})
}
/**
* 停止搜索蓝牙设备
*/
function stopBluetoothDevicesDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success: e => {
console.log("停止搜索蓝牙设备", e)
},
});
}
//@param {number|string} hexValue - 16进制值如 0x19 或 '0x19'
// @returns {Array} 使用的单位列表
function parseUnitMask(hexValue, UNIT_MAP) {
// 转换为数字
const mask = typeof hexValue === 'string' ? parseInt(hexValue, 16) : hexValue;
// 验证输入
if (isNaN(mask) || mask < 0 || mask > 0xFF) {
console.error('无效的位掩码值');
return [];
}
// 存储结果
const usedUnits = [];
// 遍历每一位
for (let i = 0; i < 8; i++) {
// 使用位运算检查第 i 位是否为 1
if (mask & (1 << i)) {
usedUnits.push(UNIT_MAP[i]);
}
}
return usedUnits;
}
export default {
ab2hex,
inArray,
unitList,
openBluetoothAdapter,
startBluetoothDeviceDiscovery,
onBluetoothDeviceFound,
Bluetoothfilter,
connectDevice,
getBLEDeviceServices,
getBLEDeviceCharacteristics,
closeBluetoothAdapter,
closeBLEConnection,
getBLECharacteristicValueChange,
onBLEConnectionStateChange,
stopBluetoothDevicesDiscovery
}