kitchendDevice/components/bluetooth_food - copy.vue

618 lines
18 KiB
Vue
Raw Permalink Normal View History

2025-11-08 16:50:26 +08:00
<template>
<view class="weightPages">
<view class="table" v-if="isConnection == 0">测量中请将食物放到秤上</view>
<view class="table" v-if="isConnection == 1" @click="openBluetoothAdapter">连接失败点击重新连接</view>
<view class="image" v-if="isConnection != 3">
<image src="../static/cheng.png"></image>
</view>
<view v-if="isConnection == 3">
<view class="weight-wrap">
<view class="weight">
<text class="val">{{weight == '' ? '--':weight}}</text>
<text class="unit">{{unitConversion(dw)}}</text>
</view>
<view class="kcal">
<text class="val">{{kcal == '' ? 0 : kcal}}</text>
<text class="unit">千卡</text>
</view>
</view>
<view class="tips">
重新测量可更新当前数据
</view>
<view class="groupbtn" v-if="weightType!=2">
<view class="btn" @click="handleDetailSub">完成</view>
<view class="btn" @click="handleDetailNext" v-if="!stopblue">下一位</view>
</view>
<view class="btn" @click="handlesub" v-if="weightType==2">确认添加</view>
</view>
<view class="tips" v-if="isConnection == 1">
<uni-icons type="info-filled" color="#dd524d" size="20"></uni-icons>
请确定设备是开机状态手机蓝牙权限已打开
</view>
</view>
</template>
<script>
import {
mapState
} from "vuex";
let myTime
let nextCnt = 0
export default {
data() {
return {
dw: "g",
kcal: 0,
weight: "",
weightALL: "",
unit: '',
weight0: 0,
stopblue: false,
isConnection: 0, //是否连接成功
units: ['kg', '斤', 'st:lb', 'lb', 'g', 'ml', 'Waterml',
'milkml', 'oz', 'floz', 'lboz'
]
}
},
props: {
weightKcal: {
type: Number,
default: 0 //当前测量食物每100g含的kcal
},
weightType: {
type: Number,
default: -1 //0分类测量,1累计测量,2购物车测量
},
isLast: {
type: Boolean,
default: false
}
},
computed: {
...mapState(["user", 'isConnected', "isBluetoothTyle"]),
},
mounted() {
let that = this
console.log("mounted_new", that.weightType)
that.openBluetoothAdapter()
that.onBLEConnectionStateChange()
uni.onBluetoothAdapterStateChange(function(res) {
that.$store.commit("changeBluetooth", res.available);
})
},
destroyed() {
this.isConnection = 1
this.closeBLEConnection()
this.closeBluetoothAdapter()
},
watch: {
// weightType: function() {
// let that = this
// that.openBluetoothAdapter()
// },
isBluetoothTyle: function() {
let that = this
if (!that.isBluetoothTyle) {
that.handleBack()
}
},
isLast: function() {
let that = this
that.stopblue = that.isLast
console.log("最后", this.isLast)
}
},
methods: {
// 初始化蓝牙
openBluetoothAdapter() {
let that = this
that.weight = ""
that.kcal = ""
uni.openBluetoothAdapter({
success: e => {
that.isConnection = 0
that.startBluetoothDeviceDiscovery()
},
fail: e => {
that.isConnection = 1
console.log('openBluetoothAdapter', e)
that.$tools.msg("请确定设备是开机状态、手机蓝牙权限已打开!")
}
});
},
// 开始搜寻附近的蓝牙外围设备
startBluetoothDeviceDiscovery() {
let that = this
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
services: [
// "F0A0",
// "A5FE"
],
success: res => {
that.isConnection = 0
that.onBluetoothDeviceFound();
},
fail: res => {
that.isConnection = 1
console.log('startBluetoothDeviceDiscovery', res)
that.$tools.msg("请确定设备是开机状态、手机蓝牙权限已打开!")
}
});
},
// 监听蓝牙连接状态
onBLEConnectionStateChange() {
let that = this
uni.onBLEConnectionStateChange(function(res) {
console.log("监听蓝牙连接状态", res.connected)
if (!res.connected) {
that.isConnection = 1
that.closeBLEConnection()
that.closeBluetoothAdapter()
}
that.$store.commit("changeConnected", res.connected);
})
},
/**
* 停止搜索蓝牙设备
*/
stopBluetoothDevicesDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success: e => {
console.log("停止搜索蓝牙设备", e)
},
});
},
/**
* 发现外围设备
*/
onBluetoothDeviceFound() {
var that = this;
that.isConnection = 0
uni.onBluetoothDeviceFound(res => {
res.devices.forEach(device => {
device.advertisData = device.advertisData ? device.advertisData : ''
device.advertisServiceUUIDs = device.advertisServiceUUIDs ? device.advertisServiceUUIDs : ""
let value = that.$tools.ab2hex(device.advertisData, "")
let id = value.substring(0, 4)
if (!device.name && !device.localName) {
return
}
if (device.name.indexOf("EL") !== -1 && device.advertisServiceUUIDs != '') {
that.isConnection = 3
let value = that.$tools.ab2hex(device.advertisData)
let parseDataRes = plugin.parseBroadcastData(device.advertisData)
let analyzeData = plugin.analyzeBroadcastScaleData(parseDataRes)
let analyzeDataText = analyzeData.text
let data = analyzeData.data
if (parseDataRes.status == 1) {
let data0 = parseDataRes.payload
let data = parseInt(data0[3]).toString(16)
console.log('data' + data)
let data1 = parseInt(data0[4]).toString(16)
let data2 = parseInt((data + data1), 16) //重量
//
let unit0 = parseInt(data0[5]).toString(16) //单位小数点
let unit = unit0.length > 1 ? unit0.substring(1, 2) : unit0 //单位
let num = parseInt(unit0.substring(0, 1), 16).toString(8)
let dot = num.toString().substring(0, 1) //小数点
let zfz = 0 //正负值
if (num.toString().length > 1) {
dot = num.toString().substring(1, 2)
zfz = num.toString().substring(0, 1)
}
if(unit == '0') {
that.dw = 'g'
}
if (unit == "7") {
that.dw = "ml"
}
if (unit == "3") {
that.dw = "oz"
}
if (unit == "2") {
that.dw = "lb'oz"
}
if (dot == "1") {
data2 = data2 / 10
}
if (dot == "2") {
data2 = data2 / 100
}
if (zfz == "0") {
data2 = data2
}
if (zfz == "1") {
data2 = "-" + data2
}
that.weight = data2
that.kcal = (Number(that.weightKcal) / 100 * data2).toFixed(2)
that.$emit('realTimeWeight',data2,that.dw)
}
}else if(device.name.indexOf('Chipsea-BLE') != -1 || device.localName.indexOf('Chipsea-BLE') != -1 || id == 'a5fe') {
that.stopBluetoothDevicesDiscovery()
that.connectDevice(device.deviceId)
}
})
});
},
//连接设备
async connectDevice(device_id) {
let that = this;
uni.createBLEConnection({
deviceId: device_id,
success: res => {
setTimeout(function() {
that.getBLEDeviceServices(device_id)
}, 200)
},
fail: res => {
console.log("设备连接失败,请重新连接", res);
}
});
},
/**
* 获取设备的UUID
*/
getBLEDeviceServices(device_id) {
let serviceList = [];
let that = this;
uni.getBLEDeviceServices({
deviceId: device_id,
success: res => {
console.log("获取设备的UUID成功", res)
serviceList = res.services;
for (let i = 0; i < serviceList.length; i++) {
let service = serviceList[i];
if (service.uuid.indexOf("FFF0") != -1) {
that.getBLEDeviceCharacteristics(device_id, service.uuid);
break;
}
}
},
fail: res => {
console.log('获取设备的UUID失败:', res)
}
});
},
/**
* 获取指定服务的特征值
*/
getBLEDeviceCharacteristics(deviceId, serviceId) {
let characteristicsList = [];
let that = this;
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: res => {
console.log("服务的特征值成功", 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
}
}
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: notify,
state: true,
success: () => {
that.isConnection = 3
that.$emit('connect_success')
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:
that.parseWeightData(dataView)
break
case 0x03:
break
}
}
})
},
fail: res => {
console.log('获取特征值失败:', JSON.stringify(res))
}
})
},
fail: res => {
console.log('获取特征值失败:', JSON.stringify(res))
}
})
},
parseWeightData(dataView) {
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)
if (isNegative) finalWeight = -finalWeight
// 更新状态
this.weight = finalWeight
this.dw = this.units[unitIndex] || 'g'
this.kcal = (Number(this.weightKcal) / 100 * finalWeight).toFixed(2)
// console.log('重量:' + finalWeight)
// console.log('单位:' + this.unit)
this.$emit('realTimeWeight',finalWeight,this.dw)
// 状态处理
// if (statusType === 0x02) {
// this.$emit('handleBle', finalWeight,this.unit,0)
// }
},
// 保存测量结果
handlesub() {
let that = this
console.log("weight", that.weight)
if (Number(that.weight) > 0) {
that.$emit("handleBle", that.weight, that.dw, that.kcal)
// that.stopBluetoothDevicesDiscovery() //取消蓝牙搜索
// that.closeBLEConnection()
// that.closeBluetoothAdapter()
} else {
that.$tools.msg("数据异常,请清零后重新测量!")
}
},
// 备料完成
handleDetailSub() {
let that = this
if (that.weightType == 1) { //累计测量
// that.weight0 = Number(that.weight) - Number(that.weightALL)
that.weight0 = Number((Number(that.weight) - Number(that.weightALL)).toFixed(2))
if(that.weight0 > 0) {
that.weightALL = that.weight
}else {
that.$tools.msg("数据异常,请清零后重新测量!")
}
} else {
that.weight0 = that.weight
}
if (Number(that.weight0) > 0) {
that.$emit("handleDetailSub", that.weight0, that.dw, that.kcal)
// that.stopBluetoothDevicesDiscovery() //取消蓝牙搜索
// that.closeBLEConnection()
// that.closeBluetoothAdapter()
that.weight = 0
that.weight0 = 0
} else {
that.$tools.msg("数据异常,请重新测量!")
}
},
//备料下一个
handleDetailNext() {
let that = this
if (that.weightType == 1) {
console.log('weight' + that.weight)
console.log('weight0' + that.weight0)
console.log('weightALL' + that.weightALL)
// that.weight0 = Number(that.weight) - Number(that.weightALL)
that.weight0 = Number((Number(that.weight) - Number(that.weightALL)).toFixed(2))
if(that.weight0 > 0) {
that.weightALL = that.weight
}else {
that.$tools.msg("数据异常,请清零后重新测量!")
}
} else {
that.weight0 = that.weight
}
if (Number(that.weight0) > 0) {
that.$emit("handleDetailNext", that.weight0, that.dw, that.kcal)
that.weight = 0
that.weight0 = 0
} else {
that.$tools.msg("数据异常,请清零后重新测量!")
}
},
handlechongzhi(weight) {
let that = this
console.log('当前总重:' + that.weightALL)
console.log('重置重量:' + weight)
if (that.weightType == 1) {
that.weightALL = Number((Number(that.weightALL) - Number(weight)).toFixed(2))
console.log('剩余重量:' + that.weightALL)
}
},
handleBack() {
let that = this
that.isConnection = 1
that.stopBluetoothDevicesDiscovery() //取消蓝牙搜索
that.closeBLEConnection()
that.closeBluetoothAdapter()
},
/**
* 断开蓝牙模块
*/
closeBluetoothAdapter() {
let that = this;
uni.closeBluetoothAdapter({
success: res => {
console.log('蓝牙模块关闭成功');
}
})
},
/**
* 断开蓝牙连接
*/
closeBLEConnection() {
var that = this;
uni.closeBLEConnection({
deviceId: that.deviceId,
success: res => {
console.log('断开蓝牙连接成功');
}
});
},
unitConversion(unit) {
if(unit == 'kcal') {
return '千卡'
}else if(unit == 'g') {
return '克'
}else if(unit == 'lb') {
return '磅'
}else if(unit =='oz') {
return '盎司'
}
return unit
}
// isNutritionScale(advertisData) {
// const buffer = this.base64ToArrayBuffer(advertisData)
// const dataView = new DataView(buffer)
// // 检查厂商自定义数据头
// if (dataView.getUint16(0) !== 0xA5FE) return false
// // 检查产品类型 (营养秤:0x0001)
// const typeId = dataView.getUint16(2)
// if (typeId !== 0x0001) return false
// // 检查厂商ID (通用方案:0x0001)
// const vendorId = dataView.getUint16(4)
// return vendorId === 0x0001
// },
// base64ToArrayBuffer(base64) {
// const str = atob(base64)
// const buffer = new ArrayBuffer(str.length)
// const view = new Uint8Array(buffer)
// for (let i = 0; i < str.length; i++) {
// view[i] = str.charCodeAt(i)
// }
// return buffer
// }
},
}
</script>
<style scoped lang="scss">
.weightPages {
display: flex;
flex-wrap: wrap;
flex-direction: column;
position: relative;
justify-content: space-around;
.weight-wrap {
display: flex;
flex-direction: column;
align-items: center;
background: #fff;
color: #666;
font-size: 16px;
flex-wrap: wrap;
text-align: center;
.weight, .kcal {
display: flex;
justify-content: center;
align-items: center;
width: 70%;
padding: 40rpx 0;
border-radius: 20rpx;
background-color: #F8F8F8;
}
.weight {
margin-bottom: 30rpx;
.val {
font-size: 40rpx;
color: #F0AE43;
margin: 0 !important;
}
.unit {
padding: 10rpx;
margin-left: 30rpx;
font-size: 28rpx;
color: #fff;
border-radius: 8rpx;
background-color: #F0AE43;
}
}
.kcal {
font-size: 32rpx;
.val {
font-size: 40rpx;
color: #F0AE43;
margin: 0 !important;
}
.unit {
margin-left: 20rpx;
}
}
}
.tips {
2025-11-25 14:21:22 +08:00
font-size: 24rpx;
2025-11-08 16:50:26 +08:00
text-align: center;
}
.btn {
color: #fff;
width: 80%;
margin-left: 10%
}
.groupbtn {
.btn {
color: #000 !important;
}
}
.table {
width: 100%;
font-size: 16px;
font-weight: bold;
text-align: center;
2025-11-25 14:21:22 +08:00
margin: 30rpx 0;
2025-11-08 16:50:26 +08:00
}
.image {
2025-11-25 14:21:22 +08:00
width: 1120rpx;
height: 1120rpx;
2025-11-08 16:50:26 +08:00
margin: auto;
image {
width: 100%;
height: 100%;
}
}
.tips {
margin-top: 40rpx;
2025-11-25 14:21:22 +08:00
margin-left: 30rpx;
2025-11-08 16:50:26 +08:00
display: flex;
color: #999;
}
}
</style>