소스 검색

增加 蓝牙协议下发demo

feat-bluetooth
chenJinxu 9 달 전
부모
커밋
7244c22690
7개의 변경된 파일743개의 추가작업 그리고 837개의 파일을 삭제
  1. +20
    -0
      miniprogram/blue-sdk/blue-sdk.js
  2. +51
    -1
      miniprogram/model/index.js
  3. +191
    -128
      miniprogram/pages/bluetooth/bluetooth.js
  4. +8
    -5
      miniprogram/pages/bluetooth/bluetooth.wxml
  5. +318
    -529
      miniprogram/pages/devicedetail/index.js
  6. +33
    -94
      miniprogram/pages/devicedetail/index.wxml
  7. +122
    -80
      miniprogram/pages/devicedetail/index.wxss

+ 20
- 0
miniprogram/blue-sdk/blue-sdk.js 파일 보기

@@ -0,0 +1,20 @@
"use strict";
// 塑性仪蓝牙连接封装sdk
// 1.初始话蓝牙设备,根据蓝牙设备指定的服务ID过滤并且获取周边可用的蓝牙设备列表

/**
*
*
*/
function _initBlue() {
console.log("初始化蓝牙::");
wx.openBluetoothAdapter({
mode: 'peripheral',
success: (res) => {
console.error('蓝牙初始化成功', res)
},
fail: function (err) {
console.error('蓝牙初始化失败', err)
}
})
}

+ 51
- 1
miniprogram/model/index.js 파일 보기

@@ -1 +1,51 @@
export const VersionModel = '2.0.4F';
export const VersionModel = '2.0.4F';

export const CommandButtonList = {
// 下发
send: [
// 2.2.1.读取工作强度映射表(0x0101)
{name:'读取工作强度映射表', enName: 'readWorkIntensityMapping', defaultSendData: 'FE0007010100FF'},
// 2.2.2.设置设备工作强度映射表(0x0102)
{name:'设置工作强度映射表', enName: 'sendWorkIntensityMapping', defaultSendData: 'FE000701027FF'},

// 2.2.3.读取设备工作强度(0x0103)
{name:'读取设备工作强度', enName: 'readWorkIntensity', defaultSendData: 'FE0007010300FF'},

// 2.2.4.设置设备工作强度(0x0104)
{name:'设置设备工作强度', enName: 'sendWorkIntensity', defaultSendData: 'FE000E01040102FF'},

// 2.2.5.读取设备工作流程(0x0105)
{name:'读取设备工作流程', enName: 'readWorkProcess', defaultSendData: 'FE0007010500FF'},

// 2.2.6.设置设备工作流程(0x0106)
// {name:'设置设备工作流程', enName: 'sendWorkProcess', defaultSendData: 'FE00XX0016FF'},
// 2.2.7.设备启动工作(0x0107)
{name:'设备启动工作', enName: 'deviceStartWork', defaultSendData: 'FE00070107000000010060FF'},

// 2.2.8设备停止工作(0x0108)
{name:'设备停止工作', enName: 'deviceStopWork', defaultSendData: 'FE0007010800000001FF'},

// 2.2.9设备暂停工作(0x0109)
{name:'设备暂停工作', enName: 'devicePauseWork', defaultSendData: 'FE0007010900000001FF'},
//2.2.10设备恢复工作(0x010A)
{name:'设备恢复工作', enName: 'deviceResumeWork', defaultSendData: 'FE0007010A00000001FF'},



//2.2.11设置设备时钟(0x010B)
{name:'设置设备时钟', enName: 'sendDeviceClock', defaultSendData: ''},

//2.2.12设备恢复出厂设置(0x010C)
{name:'设备恢复出厂设置', enName: 'deviceReset', defaultSendData: 'FE0007010C00FF'},



],
// 上报,解析
report: [

]
};

+ 191
- 128
miniprogram/pages/bluetooth/bluetooth.js 파일 보기

@@ -2,139 +2,202 @@
const plugin = requirePlugin('ppScale-plugin')
var app = getApp();
Page({
data: {
deviceslist:[
],
param: {
appKey:"lefu7afd0a504245139b"
}
},
onLoad() {
},
onUnload() {
// 业务结束后需要调用此方法
plugin.Blue.stop()
},
// 选择设备
selItem: function(res) {
var that = this;
var devItem = res.currentTarget.dataset.item;
var device = this.data.deviceslist.find(item => item.deviceId === devItem.deviceId)
app.globalData.selmac = device;
console.log("this.globalData",app.globalData.selmac)
that.setData({
selmac: device
data: {
deviceslist: [{
name: "LFSmart Scale",

deviceId: "CF:E6:16:22:82:28"
}],

},
onHide() {
},
onLoad() {
let that = this;
//监听蓝牙打开状态
wx.onBluetoothAdapterStateChange(function (res) {
console.log('蓝牙适配器打开状态变化', res)
// 如果蓝牙从关闭到打开并且 deviceslist 为空,则重新初始化蓝牙
if (res.available && !that.data.deviceslist) {
that.initBlue();
}
})
//监听蓝牙连接状态
wx.onBLEConnectionStateChange(function (res) {
// 该方法回调中可以用于处理连接意外断开等异常情况
console.log(`设备蓝牙连接状态`, res);
// 如果蓝牙断开
if (!res.connected) {
// 关闭蓝牙连接事件,再重新初始化连接?
// that.closeBlue();
wx.showToast({
title: '蓝牙已断开',
icon: 'error'
})
},
refresh: function(res) {
// plugin.Blue.startBluetoothDevicesDiscovery();
plugin.Blue.start([]);
console.log("刷新", plugin);
},
doback: function(res) {
if(app.globalData.selmac){
wx.navigateTo({
url: '/pages/devicedetail/index'
})
} else if(this.data.deviceslist.length <= 0) {
wx.showModal({
title: '温馨提示',
content: `请打开手机蓝牙并且双脚站上蓝牙称扫描设备`,
showCancel: false,
/* setTimeout(() => {
that.initBlue();
}, 1500) */

} else {
wx.showToast({
title: '蓝牙已连接',
icon: 'success'
})
}else {
wx.showModal({
title: '温馨提示',
content: `请选择上面要连接的设备`,
showCancel: false,
}
})
},
onShow() {
// 初始化蓝牙
this.initBlue()
},
onUnload() {
// 业务结束后需要停止蓝牙
this.closeBlue();

},
closeBlue() {
wx.closeBluetoothAdapter();
wx.offBluetoothAdapterStateChange()
},
initBlue() {
let that = this;
/* that.setData({
deviceslist: ''
}) */
console.log("初始化蓝牙");
wx.openBluetoothAdapter({
mode: 'peripheral',
success: (res) => {
console.log('openBluetoothAdapter', res)
// 初始化成功后开始搜索周边蓝牙列表
wx.showLoading({
title: '搜索中',
})
console.log('请选择设备')
}
},
doback2: function(res) {
if(app.globalData.selmac){
wx.navigateTo({
url: '/pages/devicedetailfood/index'
wx.startBluetoothDevicesDiscovery({
services: [], // 可指定服务UUID筛选要搜索的设备
success: function (res) {
if (res.errno === 0) {
console.log('蓝牙设备搜索成功');

setTimeout(() => {

wx.getBluetoothDevices({
success: (resu) => {
console.log('getBluetoothDevices', resu)
// resu.device 为蓝牙列表
wx.hideLoading();
if (resu.devices.length > 0) {
wx.showToast({
title: '搜索成功',
icon: 'success'
})
that.setData({
deviceslist: resu.devices
});
// 此时再监听搜索到新设备的事件
wx.onBluetoothDeviceFound(function(res) {
var devices = res.devices;
console.log('找到一个新设备', devices)
that.data.deviceslist.push(devices[0]);
that.setData({
deviceslist: that.data.deviceslist
});
})
} else {

wx.showModal({
title: '温馨提示',
content: `暂无搜索到可用设备`,
showCancel: false,
})
}

}
})
// // 搜索到设备后停止搜索
// wx.stopBluetoothDevicesDiscovery({
// success: () => {
// console.log("搜索到设备,停止搜索");
// }
// });

}, 1500)
}

},
fail: function (err) {
wx.hideLoading();
wx.showModal({
title: '温馨提示',
content: `蓝牙设备搜索失败`,
showCancel: false,
})
}else {
wx.showModal({
title: '温馨提示',
content: `请选择上面要连接的设备`,
showCancel: false,
console.error('蓝牙设备搜索失败', err)
}
})
console.log('请选择设备')
}
},

/**
* 刷新token
* @param {function} fn 获取token后执行函数
* @param {boolean} flag 请求刷新token
*/
async refreshToken(fn, flag) {
let bodyToken = wx.getStorageSync('bodyToken');
let bodyTokenTime = wx.getStorageSync('bodyTokenTime');
if (!bodyToken || bodyTokenTime * 1000 < +new Date() || flag) {
let res = await plugin.refreshToken({
url: 'https://uniquehealth.lefuenergy.com',
data: {
"appSecret":"AlgH7XDNWG1nABz3LSKdhaYTFUdETSBmKL4pRmD5mS4=",
"appKey": "lefu7afd0a504245139b"
}
});
console.log("res", res);
if (res.data.code == 200) {
wx.setStorageSync('bodyToken', res.data.data.token);
wx.setStorageSync('bodyTokenTime', res.data.data.expireTime);
fn();
}
} else {
fn();
}
},
getDeviceSettingList(param) {
let bodyToken = wx.getStorageSync('bodyToken');
console.log("获取最新设备列表");
console.log("param",param)
plugin.getDeviceSettingList({
url: 'https://uniquehealth.lefuenergy.com',
data: param,
header: {
"token": bodyToken,
"Accept-Language": wx.getStorageSync("lang") || 'zh'
}
}).then(this.handleResponse);
},
handleResponse(res) {
if (res.data.code == 200) {
// 配置蓝牙设备列表
console.log("res.data.data",res.data.data)
plugin.Blue.setDeviceSetting(res.data.data)
} else if (res.data.code == 401) {
// token过期 重新请求token解析数据
this.refreshToken(() => {
this.getDeviceSettingList(this.data.param)
}, true);
},
fail: (fail) => {
wx.showModal({
title: '温馨提示',
content: `请打开蓝牙`,
showCancel: false,
})
}
});

},
// 选择设备
selItem(res) {
var that = this;
var devItem = res.currentTarget.dataset.item;
var device = this.data.deviceslist.find(item => item.deviceId === devItem.deviceId)
app.globalData.selmac = device;
that.data.selmac = device;
that.setData({
selmac: device
})
// 本地缓存连接的蓝牙设备信息
console.log("this.globalData", app.globalData.selmac)

},
refresh: function (res) {
this.initBlue();
console.log("刷新", );
},
doback(res) {
if (app.globalData.selmac) {
// 进入详情前先停止搜索设备,
wx.stopBluetoothDevicesDiscovery({
success: () => {
console.log("开始连接到设备,停止搜索");
}
},

onShow() {
// 高于1.0.5版本 如无法扫描设备 需请求获取并设置最新设备配置列表
console.log("开始扫描周边设备");
/* this.getDeviceSettingList(this.data.param) */
plugin.Blue.setDeviceSetting([ { "createBy": null, "createTime": "2023-10-11 16:57:08", "updateBy": null, "updateTime": "2023-10-20 14:05:03", "remark": null, "id": 39, "deviceName": "LFSmart Scale", "sign": "CE4004", "advLength": 20, "macAddressStart": 7, "deviceConnectType": 2, "deviceType": 1, "deviceProtocolType": 2, "deviceCalcuteType": 3, "devicePowerType": 1, "deviceFuncType": 67, "deviceAccuracyType": 2, "deviceUnitType": "0,1,11", "calorieStatus": 1, "uhStatus": 1, "status": 0, "imgUrl": null },
])
console.log("plugin.Blue",plugin)
plugin.Blue.start([],false)
// 获取扫描设备列表
plugin.bus.subscribe("devicesList", (res) => {
console.log("devicesList'", JSON.parse(JSON.stringify(res)))
this.setData({
deviceslist: res
});
});
},
});
wx.navigateTo({
url: '/pages/devicedetail/index'
})
} else if (this.data.deviceslist.length <= 0) {
wx.showModal({
title: '温馨提示',
content: `搜索不到设备,请重试获取打开蓝牙`,
showCancel: false,
})
} else {
wx.showModal({
title: '温馨提示',
content: `请选择上面要连接的设备`,
showCancel: false,
})
console.log('请选择设备')
}
},







})

+ 8
- 5
miniprogram/pages/bluetooth/bluetooth.wxml 파일 보기

@@ -1,12 +1,12 @@
<view style="width:100vw;height:3vw"></view>
<view bindtap='selItem' data-item='{{item}}' class="item_class flex_column flex_space" wx:for="{{deviceslist}}" wx:key="lkeys">
<view class="flex_row flex_space flex_vcenter">
<view bindtap='selItem' data-item='{{item}}' class="item_class flex_column flex_space" wx:for="{{deviceslist}}" wx:key="lkeys">
<view class="flex_row flex_space flex_vcenter" >
<view class="flex_row flex_vcenter">
<text class="item_name_text">设备名:{{item.name || "未知设备"}}</text>
</view>
</view>
<view class="flex_row flex_space flex_vcenter flex_wrap" style="margin-top:3vw;display: flex;justify-content: space-between;">
<text class="item_name_text">设备MAC:{{item.deviceId}} &nbsp;信号值:{{item.RSSI || "0"}}</text>
<text class="item_name_text">设备MAC:{{item.deviceId}};信号值:{{item.RSSI || "0"}}</text>
<text hidden="{{selmac.deviceId != item.deviceId}}" mode="aspectFit" class="item_sel_img-active" ></text>
<text hidden="{{selmac.deviceId == item.deviceId}}" mode="aspectFit" class="item_sel_img" ></text>
</view>
@@ -16,7 +16,10 @@
<view>
<text bindtap='refresh' class='bottom_text'>刷新</text>
<button hidden="{{selmac.deviceId != ''}}" class="btn_disable">选择设备</button>
<button bindtap='doback' hidden="{{selmac.deviceId == ''}}" class="btn_normal" style="margin:0">选择设备</button>
<button bindtap='doback' hidden="{{selmac.deviceId == ''}}" class="btn_normal" style="margin:0">
选择设备</button>
</view>

<view style="width:100vw;height:20vh;"></view>
<view style="width:100vw;height:20vh;">

</view>

+ 318
- 529
miniprogram/pages/devicedetail/index.js 파일 보기

@@ -1,552 +1,341 @@
// 示例demo
const plugin = requirePlugin('ppScale-plugin')
var app = getApp();
const plugin = requirePlugin('ppScale-plugin');
import { CommandButtonList } from '../../model/index'
let app = getApp();
Page({
data: {
// 选择的设备对象
selmac: null,
// 是否在测量中
scaleing: false,
// 测量心率测量状态
state: 0,
// 体重数据
weight: '00.0',
// 测量单位
unit: 'kg',
// 蓝牙连接状态
devLink: false,
// 体重数据
currentWeight: 0,
// 阻抗数据
currentImpedance: 0,
// 扫描筛选出的设备
selectDev: null,
// 设备模型
deviceModel: null,
// 锁定数据
lastData: null,
// 域名值
domainValue: '',
// wifi名
wifiValue: '',
// 密码值
pwValue: '',
// 单位数组
deviceUnitArray: Object.keys(plugin.PPBluetoothDefine.PPDeviceUnit),
// 单位数组下标
deviceUnitIndex: 0,
// 网络dialog
netWorkFlag: false,
// 域名dialog
domainFlag: false,
// 单位dialog
unitFlag: false,
// 调试log列表
consoleList: [],
// 获取设备数据传参
param: {
appKey:"lefu7afd0a504245139b"
}
},
data: {
// 选择的设备对象
selmac: null,
// 是否在测量中
scaleing: false,

/**
* 页面卸载时调用
*/
onUnload() {
// 业务结束后需要调用此方法
plugin.Blue.stop()
},

/**
* 页面隐藏时调用
*/
onHide() {
// 业务结束后需要调用此方法
this.seeConsole('销毁蓝牙插件')
plugin.Blue.stop()
},
onShow() {
// 高于1.0.5版本 如无法扫描设备 需请求获取并设置最新设备配置列表
this.getDeviceSettingList(this.data.param)
// 高于1.0.5版本 如无法扫描设备 直接设置最新设备列表
// plugin.Blue.setDeviceSetting([{"createBy":null,"createTime":"2023-09-14 11:38:56","updateBy":null,"updateTime":"2023-10-18 16:08:39","remark":null,"id":12,"deviceName":"LFSmart Scale","sign":"CF4303","advLength":20,"macAddressStart":7,"deviceConnectType":2,"deviceType":1,"deviceProtocolType":2,"deviceCalcuteType":3,"devicePowerType":2,"deviceFuncType":75,"deviceAccuracyType":2,"deviceUnitType":"0,3","calorieStatus":1,"uhStatus":1,"status":0,"imgUrl":"https://unique.lefuenergy.com/dev/2023/09/28/4dianji_border_20230928102849A007.png"}])
// 使用节流函数包装测重事件处理函数
let throttledScroll = this.throttle(this.handleProgress, 1500);
// 记录设备对象
this.setData({
selmac: app.globalData.selmac
})
// 蓝牙状态监听
wx.onBluetoothAdapterStateChange((res) => {
if (!res.available) {
this.seeConsole('蓝牙设备断开')
}
})
// 是否开启插件日志
// plugin.Blue.visibleLog()
this.seeConsole('开启蓝牙开始扫描设备')
// 获取扫描设备列表
plugin.bus.subscribe("devicesList", (devList) => {
// 根据deviceId查找匹配设备
let selectDev = devList.find(item => {
return item.deviceId == this.data.selmac.deviceId
})
// 记录选择出设备
this.setData({
selectDev: selectDev
})
if (!this.data.deviceModel && this.data.selectDev) {
//获取与保存秤类型
this.seeConsole('获取秤端设备模型')
// 获取与记录设备模型
this.setData({
deviceModel: plugin.Blue.getDeviceModel(selectDev)
})
}
// 匹配广播秤
if (this.data.deviceModel && this.data.deviceModel.deviceConnectType == plugin.PPBluetoothDefine.PPDeviceConnectType
.PPDeviceConnectTypeBleAdv) {
this.seeConsole('设备连接广播秤')
// 广播秤 匹配与数据监听
plugin.Blue.setbroadcastDev(selectDev)
}
// 匹配连接秤
if (this.data.deviceModel && this.data.deviceModel.deviceConnectType == plugin.PPBluetoothDefine.PPDeviceConnectType
.PPDeviceConnectTypeBleConnect) {
// 停止扫描
this.seeConsole('停止扫描')
plugin.Blue.stopBluetoothDevicesDiscovery()
// 连接设备
this.seeConsole('开始连接设备')
plugin.Blue.createBLEConnection(selectDev)
}
});
// 设备链接回调
plugin.bus.subscribe("deviceConnect", (res) => {
this.seeConsole('成功连接设备')
// 开启监听蓝牙秤数据 必填
plugin.ScaleAction.startDataProgress()
setTimeout(()=>{
plugin.ScaleAction.syncDeviceSetting({
unit: +this.data.deviceUnitIndex,
})
},800)
});

// 设备链接回调
plugin.bus.subscribe("devicesModel", (res) => {
// console.log("res",res)
});
// 蓝牙连接状态
devLink: false,

// 监听秤端数据回调
plugin.bus.subscribe("progressData", (res) => {
throttledScroll()
// console.log("selectDev",this.data.selectDev)
// console.log("selectDev",plugin.Blue.getDeviceModel(this.data.selectDev))
if (this.data.selectDev) {
// 广播秤类型连接
if (this.data.deviceModel && this.data.deviceModel.deviceConnectType == plugin.PPBluetoothDefine.PPDeviceConnectType
.PPDeviceConnectTypeBleAdv) {
this.setData({
devLink: true
})
}
if (res.weight > 0) {
// 有数据显示为测量中
this.setData({
scaleing: true
})
// 记录体重数据
this.setData({
weight: (res.weight / 100).toFixed(2)
})
// 获取测量过程秤显示单位
this.setData({
unit: this.getKeyByUnit(res.unit)
})
} else {
// 无数据显示为未测量
this.setData({
state: 0
})
// 无数据显示为未测量
this.setData({
scaleing: false
})
}
if (res.isHeartRating) {
// 心率测量中状态设置
this.setData({
state: 1
})
}
}
});

// 设备自动断开监听
plugin.bus.subscribe("deviceWillDisconnect", (res) => {
this.seeConsole('设备自动断开连接')
// 设备自动断连后重连
this.setData({
devLink: false
})
// 重新连接方法
this.reconnectDevice()
})
// 扫描筛选出的设备
selectDev: null,
// 设备模型
deviceModel: null,
// 通讯结果
contnectResult: null,
// 发送指令内容
sendData: null,
// 蓝牙设备返回的结果
callBack: null,
// 蓝牙设备下发指令按钮数据
sendBtnList: CommandButtonList.send, //版本号
// 手动输入文本域的值
inputValue: '',

// 锁定数据
plugin.bus.subscribe("lockData", (res) => {
this.seeConsole('锁定测量数据:' + JSON.stringify(res))
// 测量结束
this.setData({
currentWeight: (res.weight / 100).toFixed(2)
})
// 记录阻抗值
this.setData({
currentImpedance: res.resistance
})
// 记录测量结果数据
this.setData({
lastData: JSON.stringify(res)
})
// 状态还原
this.setData({
state: 0
})
this.setData({
scaleing: false
})

});
// 蓝牙连接状态监听
plugin.bus.subscribe("connectState", (res) => {
// 连接状态
if (this.data.selectDev) {
if (res == plugin.BLUE_STATE.TRANSMITDATA || res == plugin.BLUE_STATE.LOCKDATA || res == plugin.BLUE_STATE
.HEARTRATING || res ==
plugin.BLUE_STATE.CONNECTSUCCESS || res == plugin.BLUE_STATE.WIFISUCCESS) {
this.setData({
devLink: true
})
} else {
this.setData({
devLink: false
})
}
// 连接失败则重新连接
if (res == plugin.BLUE_STATE.CONNECTFAILED) {
this.reconnectDevice()
}
}
});
// 秤端操作回调
plugin.bus.subscribe("syncDeviceSetting", (res) => {
this.seeConsole('成功配置设备')
})
plugin.bus.subscribe("snData", () => {
this.seeConsole('成功配置wifi网络')
})
plugin.bus.subscribe("domainChange", () => {
this.seeConsole('成功更新秤端请求服务器域名')
})
plugin.bus.subscribe("syncDeviceTimeSuccess", () => {
this.seeConsole('成功同步时间')
})
plugin.bus.subscribe("syncDeviceHistorySuccess", (e) => {
console.log("历史列表",e)
this.seeConsole('成功同步历史')
})
plugin.bus.subscribe("deviceInfo", (res) => {
console.log("deviceInfo", res)
this.seeConsole('设备信息')
})
},

plugin.bus.subscribe("deleteDeviceHistoryDataSuccess", () => {
this.seeConsole('成功删除同步历史')
})
// 开始扫描
plugin.Blue.start([], false)
/**
* 页面卸载时调用
*/
onUnload() {
// 业务结束后需要调用此方法

},
connect() {
this.seeConsole('开始连接设备')
if (this.data.deviceModel && this.data.deviceModel.deviceConnectType == plugin.PPBluetoothDefine.PPDeviceConnectType
.PPDeviceConnectTypeBleConnect) {
// 连接设备
plugin.Blue.createBLEConnection(this.data.selectDev)
}
},
disconnect() {
this.seeConsole('断开连接')
plugin.Blue.disconnect()
},
switchUnit() {
this.setData({
unitFlag: true
},

/**
* 页面隐藏时调用
*/
onHide() {

},
onLoad() {
let that = this;
//监听蓝牙连接状态
wx.onBLEConnectionStateChange(function (res) {
// 该方法回调中可以用于处理连接意外断开等异常情况
console.log(`设备蓝牙连接状态`, res);
// 如果蓝牙断开
if (!res.connected) {
// 关闭蓝牙连接事件,再重新初始化连接?
that.setData({
devLink: false,
})
},
setUserMes() {
this.seeConsole('下发用户信息')
if (this.data.devLink) {
// 根据设备已有单位切换
plugin.ScaleAction.syncDeviceSetting({
age: 28,
height: 167,
gender: 1,
})
} else {
this.seeConsole('停止下发用户信息')
wx.showToast({
title: '需要连接蓝牙秤',
icon: 'error',
duration: 1000,
mask: true
})
}
},
syncHistory() {
this.seeConsole('同步历史')
if (this.data.devLink) {
// 根据设备已有单位切换
plugin.ScaleAction.fetchDeviceHistoryData()
} else {
this.seeConsole('停止同步历史')
wx.showToast({
title: '需要连接蓝牙秤',
icon: 'error',
duration: 1000,
mask: true
})
}
},
deleteSyncHistory() {
this.seeConsole('删除同步历史')
if (this.data.devLink) {
// 根据设备已有单位切换
plugin.ScaleAction.deleteDeviceHistoryData()
} else {
this.seeConsole('停止删除同步历史')
wx.showToast({
title: '需要连接蓝牙秤',
icon: 'error',
duration: 1000,
mask: true
})
}
},
syncTime() {
this.seeConsole('同步时间')
if (this.data.devLink) {
// 根据设备已有单位切换
plugin.ScaleAction.startDataProgress()
} else {
this.seeConsole('停止同步时间')
wx.showToast({
title: '需要连接蓝牙秤',
icon: 'error',
duration: 1000,
mask: true
})
}
},
configureNetwork() {
this.setData({
netWorkFlag: true
wx.showToast({
title: '蓝牙已断开',
})
},
modifyDNS() {
this.setData({
domainFlag: true
/* setTimeout(() => {
that.initBlue();
}, 1500) */

} else {
that.setData({
devLink: true,
})
},
/**
* 重新连接设备
*/
reconnectDevice() {
this.seeConsole('尝试重新连接')
// 设备断开连接后重新连接
plugin.Blue.disconnect((disres) => {
if (disres.errCode == 0) {
this.seeConsole('开始扫描设备')
plugin.Blue.startBluetoothDevicesDiscovery()
} else {
this.reconnectDevice()
}
}
})
},
onShow() {
let that = this;
// 记录设备对象
this.setData({
selmac: app.globalData.selmac
})
console.log("selmac", that.data.selmac);
// 连接设备
wx.createBLEConnection({
deviceId: app.globalData.selmac.deviceId,
success: (res) => {
console.log("连接成功", res);
that.setData({
devLink: true
})
},
},
fail: (e) => {
console.log("连接失败", e);
}
})


/**
* 根据单位值获取设备单位描述
* @param {number} unit 单位值
* @return {string} 单位描述
*/
getKeyByUnit(unit) {
for (const key in plugin.PPBluetoothDefine.PPDeviceUnit) {
if (plugin.PPBluetoothDefine.PPDeviceUnit[key] === unit) {
return key;

setTimeout(() => {
// 获取蓝牙低功耗设备所有服务 (service)
wx.getBLEDeviceServices({
deviceId: app.globalData.selmac.deviceId,
success: (res) => {
console.log("获取蓝牙低功耗设备所有服务成功", res);
let serviceId = res.services[0].uuid;
// 缓存数据 serviceId
app.globalData.serviceId = serviceId;
//获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。
wx.getBLEDeviceCharacteristics({
deviceId: app.globalData.selmac.deviceId,
serviceId: serviceId,
success: (res) => {
console.log("获取蓝牙低功耗设备某个服务中所有特征", res);
let characteristicId = res.characteristics[0].uuid;
// 缓存数据 characteristicId
app.globalData.characteristicId = characteristicId;
},
fail: (e) => {
console.log("获取蓝牙低功耗设备某个服务中所有特征", e);
}
})
},
fail: (e) => {
console.log("获取蓝牙低功耗设备所有服务失败", e);
}
return null;
},
bindKeyInput: function (e) {
this.setData({
inputValue: e.detail.value
})
},
bindDomainInput: function (e) {
this.setData({
domainValue: e.detail.value
})
},
bindWifiInput: function (e) {
this.setData({
wifiValue: e.detail.value
})
},
bindPasswdInput: function (e) {
this.setData({
pwValue: e.detail.value
})
},
bindPickerChange: function (e) {
this.setData({
deviceUnitIndex: e.detail.value
});
},
changeUnit() {
this.seeConsole('切换单位')
if (this.data.devLink) {
// 根据设备已有单位切换
plugin.ScaleAction.syncDeviceSetting({
unit: +this.data.deviceUnitIndex,
})
})

} else {
this.seeConsole('停止切换单位')
wx.showToast({
title: '需要连接蓝牙秤',
icon: 'error',
duration: 1000,
mask: true
})
}
this.setData({
unitFlag: false
})
},
configWifi() {
this.seeConsole('开始配置wifi')
// 配置wifi
if (this.data.devLink && this.data.wifiValue && this.data.pwValue) {
console.log("this.data.wifiValue && this.data.pwValue",this.data.wifiValue , this.data.pwValue)
plugin.ScaleAction.configWifi(this.data.wifiValue, this.data.pwValue)
} else {
this.seeConsole('停止配置wifi')
wx.showToast({
title: '需要连接蓝牙秤或wifi名称或密码',
duration: 1000,
mask: true
})



}, 1500)

},
connect() {
let that = this;
if (this.data.selmac.deviceId) {
console.log("可以初始化");
wx.openBluetoothAdapter({
mode: 'peripheral',
})
// 连接设备
wx.createBLEConnection({
deviceId: that.data.selmac.deviceId,
success: (res) => {
console.log("建立连接成功", res);
},
fail: (e) => {
console.log("建立连接失败", e);
wx.showToast({
title: '重新连接失败',
icon: 'error'
})
}
this.setData({
netWorkFlag: false
})
},
changeDomain() {
this.seeConsole('开始配置域名')
// 配置域名
if (this.data.domainValue != '' && this.data.devLink) {
plugin.ScaleAction.configDomain(this.data.domainValue.replace(/^(https?:\/\/)/, ""))
} else {
this.seeConsole('停止配置域名')
wx.showToast({
title: '需要连接蓝牙秤或输入域名',
duration: 1000,
mask: true
})
})
}
},
disconnect() {
let that = this;
if (this.data.selmac.deviceId) {
// 连接设备
wx.closeBLEConnection({
deviceId: that.data.selmac.deviceId,
success: (res) => {
console.log("断开连接成功", res);
},
fail: (e) => {
console.log("断开连接失败", e);
}
this.setData({
domainFlag: false
})
},
// 节流函数
throttle: function (func, delay) {
let timer = null;
let lastTime = 0;
return function () {
const now = Date.now();
if (now - lastTime >= delay) {
func();
lastTime = now;
} else {
clearTimeout(timer);
timer = setTimeout(func, delay);
}
};
},
// 测量中体重记录
handleProgress: function () {
this.seeConsole('正在测量体重:' + this.data.weight)
},
seeConsole(string) {
this.setData({
consoleList: [string].concat(this.data.consoleList)
})
},
/**
* 清除控制台
*/
clear() {
this.setData({
consoleList: []
})
}
},
onClearInput() {
this.setData({
callBack: '',
sendData: '',
});

},
startwrite() {
// 下发指令
let text = this.cleanHexString('hello');
let buffer = this.stringToCmdBuffer(text);
let hexData = this.ab2hex(buffer);
let string = this.hexCharCodeToStr(hexData);
console.log("十六进制字符串转buffer", buffer);
console.log("buffer转hexData", hexData);
console.log("hexData转string", string);
this.sendMessage(text);

},
bindTextAreaBlur(e) {
this.data.inputValue = e.detail.value;
console.log(e.detail.value)
},
// 手动输入文本域的值
onInputSend() {
console.log("this.data.inputValue", this.data.inputValue);
if(this.data.inputValue) {
this.sendMessage(this.data.inputValue, true);
} else {
wx.showToast({
title: '指令不能为空',
icon: 'error'
})
}
},
// 发送数据
sendMessage(event,type) {
let that = this;
let sendData = '';
if(type) {
console.log("手动输出方式");
sendData = event
} else {
console.log("按钮点击输出方式");
console.log("event", event.target.dataset);
sendData = event.target.dataset.command.defaultSendData;
}
if(!that.data.devLink) {
wx.showToast({
title: '蓝牙已断开',
icon: 'error'
})
return
}
if(!sendData) {
wx.showToast({
title: '指令不存在',
icon: 'error'
})
return
}
this.setData({
sendData: sendData
})
let buffer = this.stringToCmdBuffer(sendData);
console.log("发送的指令",buffer);
wx.writeBLECharacteristicValue({
deviceId: app.globalData.selmac.deviceId, // 设备ID
serviceId: app.globalData.selmac.serviceId, // 服务UUID
characteristicId: app.globalData.selmac.characteristicId, // 特征值
value: buffer,
success(res) {
console.log("write指令发送成功", res)
that.notify();
},
fail(err) {
console.log("write指令发送失败", err);
that.setData({
callBack: err.errMsg
});
wx.showToast({
title: '指令发送失败',
icon: 'error'
})
},
/**
* 刷新token
* @param {function} fn 获取token后执行函数
* @param {boolean} flag 请求刷新token
*/
async refreshToken(fn, flag) {
let bodyToken = wx.getStorageSync('bodyToken');
let bodyTokenTime = wx.getStorageSync('bodyTokenTime');
if (!bodyToken || bodyTokenTime * 1000 < +new Date() || flag) {
let res = await plugin.refreshToken({
url: 'https://uniquehealth.lefuenergy.com',
data: {
"appSecret":"AlgH7XDNWG1nABz3LSKdhaYTFUdETSBmKL4pRmD5mS4=",
"appKey": "lefu7afd0a504245139b"
}
});
console.log("res", res);
if (res.data.code == 200) {
wx.setStorageSync('bodyToken', res.data.data.token);
wx.setStorageSync('bodyTokenTime', res.data.data.expireTime);
fn();
}
} else {
fn();
}
},
getDeviceSettingList(param) {
let bodyToken = wx.getStorageSync('bodyToken');
plugin.getDeviceSettingList({
url: 'https://uniquehealth.lefuenergy.com',
data: param,
header: {
"token": bodyToken,
"Accept-Language": wx.getStorageSync("lang") || 'zh'
}
}).then(this.handleResponse);
},
handleResponse(res) {
if (res.data.code == 200) {
// 配置蓝牙设备列表
plugin.Blue.setDeviceSetting(res.data.data)
} else if (res.data.code == 401) {
// token过期 重新请求token解析数据
this.refreshToken(() => {
this.getDeviceSettingList(this.data.param)
}, true);
}
},
}
})
},
cleanHexString(hexStr) {
// 使用正则表达式匹配并移除多余的'0x',并拼接剩下的部分
let cleanedHex = hexStr.replace(/0x/g, '').replace(/\b0+/g, ''); // 第二个正则表达式用于移除前导零
return cleanedHex;
},
// 开启消息监听
notify() {
let that = this;
wx.notifyBLECharacteristicValueChange({
deviceId: app.globalData.selmac.deviceId, // 设备ID,
serviceId: app.globalData.selmac.serviceId, // 服务UUID
characteristicId: app.globalData.selmac.characteristicId, // 特征值
success(res) {
console.log(res)
// 监听消息变化的方法
that.listenValueChange()
},
fail(err) {
console.error(err)
}
})
},
// 消息变化
listenValueChange() {
let that = this;
wx.onBLECharacteristicValueChange(res => {
console.log(res)
let resHex = that.ab2hex(res.value)
console.log("resHex", resHex)
let result = that.hexCharCodeToStr(resHex)
console.log("消息变化", String(result))
that.setData({
callBack: String(result)
});
})
},
// 将16进制的内容转成我们看得懂的字符串内容
hexCharCodeToStr(hexCharCodeStr) {
let trimedStr = hexCharCodeStr.trim();
let rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
let len = rawStr.length;
if (len % 2 !== 0) {
alert("存在非法字符!");
return "";
}
let curCharCode;
let resultStr = [];
for (let i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
},
/*字符串转换16进制buffer*/
stringToCmdBuffer(msg) {
const buffer = new ArrayBuffer(msg.length)
const dataView = new DataView(buffer)
//dataView.setUint8(0, 0)
for (let i = 0; i < msg.length; i++) {
dataView.setUint8(i, msg.charAt(i).charCodeAt())
};
return buffer

},
// ArrayBuffer转16进度字符串示例
ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}

})

+ 33
- 94
miniprogram/pages/devicedetail/index.wxml 파일 보기

@@ -1,103 +1,42 @@
<!--pages/selble/selble.wxml-->
<view class="command">
<view class="device-item">
<view>连接状态:</view>
<view>{{devLink?'已连接':'未连接'}}</view>
</view>
<view class="device-item">
<view>设备名:</view>
<view>{{selmac.name}}</view>
</view>
<view class="device-item">
<view>设备mac:</view>
<view>{{selmac.deviceId}}</view>
</view>
<view class="device-item">
<view>体重:</view>
<view>{{weight}}</view>
</view>
<view class="device-item">
<view>当前单位:</view>
<view>{{unit}}</view>
</view>
<view class="device-item">
<view>心率测量状态:</view>
<view>{{state==0?'未测量心率':'正在测量心率'}}</view>
</view>
<view class="device-item">
<view>体重状态:</view>
<view>{{scaleing?'有体重数据':'无体重数据'}}</view>
</view>
<!-- <view class="device-item">
<view>结果数据:</view>
<view class="device-result">{"isPlus": true, "isOverload": false, "weight": 1405, "resistance": 43181, "isEnd": true, "isHeartRating": false, "heartRate": 0, "unit": 0, "dateStr": "2023-08-01 09:48:52"}</view>
</view> -->
<view class="device-item">
<view>连接状态:</view>
<view>{{devLink?'已连接':'未连接'}}</view>
</view>
<view class="device-item">
<view>设备名:</view>
<view>{{selmac.name}}</view>
</view>
<view class="device-item">
<view>设备mac:</view>
<view>{{selmac.deviceId}}</view>
</view>
<view class="device-item">
<view>发送内容:</view>
<view>{{sendData || '暂无指令'}}</view>
</view>
<view class="command-result">
<view>返回结果:</view>
<view>{{callBack || '暂无结果'}}</view>
</view>

<view class="command-line">
<view wx:for="{{consoleList}}">{{item}}</view>
</view>
<view style="width:100vw;height:3vw"></view>
<view class="event-bar">
<button type="default" bindtap="connect">连接</button>
<button type="default" bindtap="disconnect">断开连接</button>
<button type="default" bindtap="syncHistory">同步历史</button>
<button type="default" bindtap="deleteSyncHistory">删除同步历史</button>
<button type="default" bindtap="syncTime">同步时间</button>
<button type="default" bindtap="switchUnit">切换单位</button>
<button type="default" bindtap="configureNetwork">配置网络</button>
<button type="default" bindtap="modifyDNS">修改服务器域名</button>
<button type="default" bindtap="setUserMes">下发用户信息</button>
</view>
<view>

</view>




<view class="dialog" wx:if="{{unitFlag}}">
<view class="dialog-content">
<view class="dialog-title">切换单位</view>
<view>
<picker mode="selector" range="{{deviceUnitArray}}" bindchange="bindPickerChange">
<view class="picker">
点击选择单位:{{deviceUnitArray[deviceUnitIndex]}}
</view>
</picker>
</view>
<button type="default" bindtap="changeUnit">切换最新单位</button>
</view>
</view>
<view class="dialog" wx:if="{{domainFlag}}">
<view class="dialog-content">
<view>
<view class="dialog-title">域名配置</view>
<view>域名:{{domainValue}}</view>
<view>
<view>
<input class="weui-input" bindinput="bindDomainInput" placeholder="输入域名" />
</view>
</view>
</view>
<button type="default" bindtap="changeDomain">更新服务器域名</button>

</view>
<view style="width:100vw;height:3vw"></view>
<view class="event-bar">
<view class="btn-con">
<button type="default" bindtap="connect">重新连接</button>
<!-- <button type="default" bindtap="startwrite">发送指令</button> -->
<button type="default" wx:for="{{sendBtnList}}" wx:key="lkeys" bindtap="sendMessage" data-command="{{item}}">{{item.name}}</button>
</view>
<view class="dialog" wx:if="{{netWorkFlag}}">
<view class="dialog-content">
<view class="dialog-title">wifi网络配置</view>
<view>
<!-- <view >wifi和密码:{{wifiValue}}-{{pwValue}}</view> -->
<view>
<view>wifi名称<input class="weui-input" bindinput="bindWifiInput" placeholder="输入wifi名称" />
</view>
<view>密码: <input class="weui-input" bindinput="bindPasswdInput" placeholder="输入wifi密码" />
</view>
</view>
</view>
<button class="dialog-button" bindtap="configWifi">配置网络</button>
</view>

<view class="command-input">
<textarea bindblur="bindTextAreaBlur" auto-height
placeholder="请输入十六进制的数据格式,例如:FE0007010100FF" />
<button type="primary" bindtap="onInputSend">手动输入发送</button>
<button type="primary" bindtap="onClearInput" >清空输出内容</button>
</view>
</view>

<button class="clear-btn" bindtap="clear">清除控制台</button>

+ 122
- 80
miniprogram/pages/devicedetail/index.wxss 파일 보기

@@ -1,90 +1,132 @@
.device-item {
display: flex;
justify-content: space-between;
display: flex;
justify-content: space-between;
}

.device-result {
flex:1;
text-align: center;
flex: 1;
text-align: center;
}

.command {
background-color: black;
color: white;
margin: 24rpx;
padding: 10rpx;
margin-bottom: 0;
}

.command{
background-color: black;
color: white;
margin: 24rpx;
padding: 10rpx;
margin-bottom: 0;
.command-result {
background-color: black;
color: white;
/* margin: 0 24rpx 24rpx 24rpx; */
margin-top: 24rpx;
overflow: auto;
height: 350rpx;
word-wrap: break-word;
word-break: normal;
}

.command-line {
background-color: black;
color: white;
font-family: monospace;
padding: 20rpx;
border: 1rpx solid white;
padding: 10rpx;
overflow: auto;
height: 350rpx;
margin: 24rpx;
margin-top: 0;
overflow-y: scroll;
text-align: right;
}
.command-line view {
word-wrap: break-word;
word-break: normal;
}
background-color: black;
color: white;
font-family: monospace;
padding: 20rpx;
border: 1rpx solid white;
padding: 10rpx;
overflow: auto;
height: 350rpx;
margin: 24rpx;
margin-top: 0;
overflow-y: scroll;
text-align: right;
}

.command-line view {
word-wrap: break-word;
word-break: normal;
}

.event-bar {
display: flex;
justify-content: space-between;
padding: 24rpx;
flex-wrap: wrap;
}
.event-bar button {
width: 45%;
background-color: #f8f8f8;
color: #000;
text-align: center;
padding: 10rpx;
border:1rpx #ccc solid;
margin-bottom: 10rpx;
display: flex;
justify-content: space-between;
/* padding: 24rpx; */
flex-wrap: wrap;
}
.dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
}
.dialog-content {
background-color: #fff;
padding: 20rpx;
border-radius: 10rpx;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
width: 80%;
}
.dialog-title {
font-size: 35rpx;
font-weight: bold;
margin-bottom: 10rpx;
text-align: center;
}
.dialog-message {
font-size: 30rpx;
margin-bottom: 20rpx;
}
.btn-con {
padding: 0 20rpx;
display: flex;
justify-content: flex-start;
padding: 24rpx;
flex-wrap: wrap;
}
.btn-con button {
width: 200rpx;
background-color: #f8f8f8;
color: #000;
text-align: center;
padding: 5rpx;
border: 1rpx #ccc solid;
margin-bottom: 15rpx;
font-size: 20rpx;
}
.command-input {
width: 100vw;
padding: 24rpx;
.dialog-button {
padding: 10rpx 20rpx;
border-radius: 5rpx;
font-size: 30rpx;
}
.clear-btn {
margin: 24rpx;
}
}
.command-input button {
margin-bottom: 10rpx;
}
textarea {
height: 30rpx;
width: auto;
position: relative;
padding: 30rpx 24rpx;
margin-bottom: 20rpx;
border: 1rpx solid #c2bebe;
border-radius: 30rpx;
}

.dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
}

.dialog-content {
background-color: #fff;
padding: 20rpx;
border-radius: 10rpx;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
width: 80%;
}

.dialog-title {
font-size: 35rpx;
font-weight: bold;
margin-bottom: 10rpx;
text-align: center;
}

.dialog-message {
font-size: 30rpx;
margin-bottom: 20rpx;
}

.dialog-button {
padding: 10rpx 20rpx;
border-radius: 5rpx;
font-size: 30rpx;
}

.clear-btn {
margin: 24rpx;
}

Loading…
취소
저장