<template>
|
<view class="bg-white">
|
<!-- 顶部标题栏 -->
|
<view class="title_style">
|
<view
|
style="display: flex;height: 100%;width: 100%;justify-content: center;align-items: center;padding: 0rpx 25rpx;">
|
<!-- <text class="cuIcon-sort" style="font-size: 44rpx;width: 10%;" @tap="showLeftDrawer"
|
data-target="DrawerModalL"></text> -->
|
<view class="flex"
|
style="justify-content: center; align-items: center; flex-direction: column;width: 100%;">
|
<text style="font-size: 32rpx;font-family: none;">{{deviceName}}</text>
|
</view>
|
</view>
|
</view>
|
<!-- 配置内容部分 -->
|
<scroll-view scroll-y="true" style="height: calc(100vh - 220upx);">
|
<view v-for="(item,index) in settingTitle" :key="index">
|
<view class="cu-bar bg-white solid-bottom"
|
style="background-color: #8f8fbd;min-height: 80rpx;color: #ffffff;">
|
<view class="action">
|
<text style="font-size: 32upx;font-family: ui-monospace;">{{item.title}}</text>
|
</view>
|
</view>
|
<view class="cu-list menu">
|
<view class="cu-item" style="height: 90rpx;" v-for="(set_item,set_index) in settingItem"
|
:key="set_index">
|
<view class="content flex align-center justify-between" style="height: 100%;width: 100%;">
|
<view style="width: 40%;">
|
<text class="text-grey" style="font-size: 24upx;">{{set_item.name}}</text>
|
</view>
|
<view
|
style="width: 20%;display: flex;font-size: 24rpx;align-items: center;justify-content: center;">
|
<view class="flex justify-center align-center" style="width: 100upx;"><input
|
type="digit" style="text-align: center;" :value="set_item.value"
|
:data-index="set_index" :data-name="set_item.name" @input="handleValue" />
|
</view>
|
<view style="width:50upx;"><text>{{set_item.unit}}</text></view>
|
</view>
|
<view class="flex justify-center align-center" style="width: 30%;">
|
<button class="bg-grey cu-btn icon" @tap="reduce" :data-index='set_index'
|
:data-name="set_item.name"
|
style="font-size: 55rpx;opacity: 0.9;margin-right:20rpx;">
|
<text class="cuIcon-move"></text>
|
</button>
|
<button class="bg-grey cu-btn icon" style="font-size: 55rpx;opacity: 0.9;" @tap="add"
|
:data-index='set_index' :data-name="set_item.name">
|
<text class="cuIcon-add"></text>
|
</button>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</scroll-view>
|
<!-- 保存配置按钮 -->
|
<view class="padding flex flex-direction" @tap="saveSetOption">
|
<button class="cu-btn lg" style="background-color: #8f8fbd;color: #FFFFFF;">保存</button>
|
</view>
|
|
<!-- 左侧菜单抽屉 -->
|
<view class="cu-modal drawer-modal justify-start" style="z-index: 100;"
|
:class="leftDrawerStatus==true?'show':''" @tap="hideLeftDrawer">
|
<view class="cu-dialog basis-lg" style="max-width: 50%;background-color: #000;" @tap.stop="">
|
<view class="cu-list menu text-left">
|
<view class="cu-item arrow" @tap="deviceList(item.click)"
|
style="min-height: 100rpx;min-height: 55px;background: #000;color: #fff;"
|
v-for="(item,index) in leftDrawerList" :key="index">
|
<view style="width: 50rpx;height: 50rpx;">
|
<text :class="'iconfont ' + item.icon" style="font-size: 50rpx;"></text>
|
</view>
|
<view class="content">
|
<view style="padding-left: 20rpx;"><text>{{item.text}}</text></view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
const Constant = require('../../utils/constant.js');
|
let keepRead = null; //定时器
|
export default {
|
data() {
|
return {
|
deviceName: '', //设置的设备名称
|
deviceId: '', //设备id
|
serviceId: '', //设备服务id
|
characteristicId: '', //设备特征值id
|
hex: '', //读取指令
|
address: '', // 生成CRC的地址
|
func: '', // 生产CRC的能效码
|
leftDrawerStatus: false, //左侧菜单的显示状态
|
isAnalysisNotifyValue: true, //是否继续分析特征值 默认分析
|
isCache: false, //是否存入缓存 当配置修改成功的时候此变量未true
|
leftDrawerList: [{
|
text: '设备列表',
|
icon: 'icon-shebeiliebiao',
|
click: 'deviceList'
|
},
|
{
|
text: '诊断',
|
icon: 'icon-jiankangzhenduan'
|
},
|
{
|
text: '生产报告',
|
icon: 'icon-baogao'
|
},
|
{
|
text: 'FAQ',
|
icon: 'icon-FAQ'
|
},
|
{
|
text: '用户设置',
|
icon: 'icon-yonghu'
|
},
|
],
|
settingTitle: [{
|
title: '警告上 / 下限值'
|
}, ],
|
settingItem: [], //设置值的详情
|
productOption: [], //用于存入缓存中的设备配置
|
}
|
},
|
onLoad(option) {
|
let that = this
|
uni.showLoading({
|
title: '配置读取中...'
|
})
|
// console.log(option)
|
this.deviceName = option.name
|
//根据连接的设备名称获取缓存中对应名称的信息
|
let productListInfo = uni.getStorageSync('productListInfo')
|
for (let i = 0; i < productListInfo.length; i++) {
|
if (productListInfo[i].name.indexOf(this.deviceName) != -1) {
|
that.deviceId = productListInfo[i].deviceId
|
that.serviceId = productListInfo[i].serviceId
|
that.characteristicId = productListInfo[i].characteristicId
|
}
|
}
|
//根据连接的设备名称来自动匹配发送的指令
|
let instructionsList = Constant.instructionsList
|
for (let i = 0; i < instructionsList.length; i++) {
|
if (instructionsList[i].name.indexOf(this.deviceName) != -1) {
|
this.hex = instructionsList[i].readOptionHex
|
}
|
}
|
//关闭上一页的定时器发送
|
let pages = getCurrentPages(); //当前页
|
let beforePage = pages[pages.length - 2]; //上个页面
|
//开始上个页面的获取数据方法
|
// #ifdef H5
|
beforePage.closeWritting()
|
// #endif
|
// #ifndef H5
|
beforePage.$vm.closeWritting()
|
// #endif
|
|
setTimeout(function() {
|
uni.hideLoading()
|
that.writeing()
|
}, 1000);
|
},
|
// 页面周期与 onLoad 同级 监听返回事件,暂时无效
|
onBackPress(e) {
|
console.log(e);
|
if (e.from == 'backbutton') {
|
uni.showModal({
|
title: '提示',
|
content: '是否保存?',
|
success: function(res) {
|
if (res.confirm) {
|
uni.showToast({
|
title: '用户点击确定',
|
duration: 1000
|
})
|
} else if (res.cancel) {
|
uni.showToast({
|
title: '用户点击取消',
|
duration: 1000
|
})
|
}
|
uni.navigateBack({
|
delta: 1
|
});
|
}
|
});
|
return true; //阻止默认返回行为
|
}
|
},
|
onHide() {},
|
onUnload() {
|
clearInterval(keepRead)
|
let pages = getCurrentPages(); //当前页
|
let beforePage = pages[pages.length - 2]; //上个页面
|
//开始上个页面的获取数据方法
|
// #ifdef H5
|
beforePage.onBLECharacteristicValueChange()
|
beforePage.refreshDeviceDate()
|
// beforePage.initProductOption()
|
// #endif
|
// #ifndef H5
|
beforePage.$vm.onBLECharacteristicValueChange()
|
beforePage.$vm.refreshDeviceDate()
|
// beforePage.$vm.initProductOption()
|
// #endif
|
},
|
onShareAppMessage: function() {
|
return Constant.Share
|
},
|
methods: {
|
//写入数据
|
writeing: function() {
|
let that = this
|
// console.log(147, '我被调用了')
|
// this.notifyBLECharacteristicValueChange(this.writeUUID)
|
that.writeBLECharacteristicValue()
|
|
keepRead = setInterval(function() {
|
that.writeBLECharacteristicValue()
|
}, 10000) //执行一次后定时10s调用一次防止长时间不通讯与设备连接断开
|
},
|
//向低功耗蓝牙设备特征值中写入二进制数据
|
writeBLECharacteristicValue: function() {
|
console.log(181, '我被调用了')
|
let that = this
|
let deviceId = this.deviceId
|
let serviceId = this.serviceId
|
let characteristicId = this.characteristicId
|
//16进制字符串 转ArrayBuffer --- start
|
let hex = this.hex
|
let typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function(h) {
|
return parseInt(h, 16)
|
}))
|
let buffer = typedArray.buffer
|
//16进制字符串 转ArrayBuffer --- end
|
uni.writeBLECharacteristicValue({
|
deviceId: deviceId,
|
serviceId: serviceId,
|
characteristicId: characteristicId,
|
value: buffer,
|
success: (res) => {
|
console.log(171, '写入成功', res)
|
this.onBLECharacteristicValueChange()
|
if (this.isCache) { //将连接设备的配置信息存入缓存
|
uni.showToast({
|
title: '修改成功',
|
icon: 'success',
|
duration: 1000
|
})
|
console.log(252,this.settingItem)
|
//存入缓存的设备配置
|
let item = this.settingItem
|
let productOption = [{
|
type: 'X_zdjsd',
|
max: item[0].value == 0 ? '0.00' : item[0].value,
|
min: item[1].value ,
|
alermValue:'',
|
},
|
{
|
type: 'X_zdsd',
|
max: item[2].value == 0 ? '0.00' : item[2].value,
|
min: item[3].value,
|
alermValue:'',
|
},
|
{
|
type: 'Y_zdjsd',
|
max: item[4].value == 0 ? '0.00' : item[4].value,
|
min: item[5].value,
|
alermValue:'',
|
},
|
{
|
type: 'Y_zdsd',
|
max: item[6].value == 0 ? '0.00' : item[6].value,
|
min: item[7].value,
|
alermValue:'',
|
},
|
{
|
type: 'Z_zdjsd',
|
max: item[8].value == 0 ? '0.00' : item[8].value,
|
min: item[9].value,
|
alermValue:'',
|
},
|
{
|
type: 'Z_zdsd',
|
max: item[10].value == 0 ? '0.00' : item[10].value,
|
min: item[11].value,
|
alermValue:'',
|
},
|
{
|
type: 'temperature',
|
max: item[12].value == 0 ? '0.00' : item[12].value,
|
min: item[13].value,
|
alermValue:'',
|
},
|
]
|
uni.setStorageSync(this.deviceName + 'Option', productOption)
|
let pages = getCurrentPages(); //当前页
|
let beforePage = pages[pages.length - 2]; //上个页面
|
//开始上个页面的获取数据方法
|
// #ifdef H5
|
beforePage.initProductOption()
|
// #endif
|
// #ifndef H5
|
beforePage.$vm.initProductOption()
|
// #endif
|
// console.log(258,uni.getStorageSync(this.deviceName + 'Option'))
|
this.isCache = false
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: '修改失败',
|
icon: 'none',
|
duration: 1000
|
})
|
this.isCache = false
|
// console.log('写入失败', err)
|
}
|
})
|
},
|
//监听低功耗蓝牙设备的特征值变化事件
|
onBLECharacteristicValueChange: function() {
|
// console.log(182, '我被调用了')
|
let that = this
|
let writeUUID = that.characteristicId
|
uni.onBLECharacteristicValueChange(function(res) {
|
// console.log(195, res.characteristicId, writeUUID)
|
if (res.characteristicId == writeUUID) {
|
console.log(197, '成功获取写入后返回的数据')
|
//console.log(202,res)
|
that.resultWriteValue = that.ab2hex(res.value)
|
if (that.ab2hex(res.value).length >= 50 && that.isAnalysisNotifyValue == true) {
|
// console.log(200, '准备处理返回的订阅值')
|
that.notifyValueHandle(that.resultWriteValue)
|
that.isAnalysisNotifyValue = false
|
}
|
}
|
console.log(214, '打印监听到的特征值变化', "写入返回的数据:" + that
|
.resultWriteValue)
|
})
|
|
},
|
//设备返回的数据处理
|
notifyValueHandle: function(data) {
|
console.log(221, data)
|
let X_zdjsdMax = (this.hex2int(data.slice(6, 10))) / 100 //x轴振动加速度上限
|
let X_zdjsdMin = (this.hex2int(data.slice(10, 14))) / 100 //x轴振动加速度下限
|
|
let X_zdsdMax = (this.hex2int(data.slice(14, 18))) / 100 //x轴振动速度上限
|
let X_zdsdMin = (this.hex2int(data.slice(18, 22))) / 100 //x轴振动速度下限
|
|
let Y_zdjsdMax = (this.hex2int(data.slice(22, 26))) / 100 //y轴振动加速度上限
|
let Y_zdjsdMin = (this.hex2int(data.slice(26, 30))) / 100 //y轴振动加速度下限
|
|
let Y_zdsdMax = (this.hex2int(data.slice(30, 34))) / 100 //y轴振动速度上限
|
let Y_zdsdMin = (this.hex2int(data.slice(34, 38))) / 100 //y轴振动速度下限
|
|
let Z_zdjsdMax = (this.hex2int(data.slice(38, 42))) / 100 //z轴振动加速度上限
|
let Z_zdjsdMin = (this.hex2int(data.slice(42, 46))) / 100 //z轴振动加速度下限
|
|
let Z_zdsdMax = (this.hex2int(data.slice(46, 50))) / 100 //z轴振动速度上限
|
let Z_zdsdMin = (this.hex2int(data.slice(50, 54))) / 100 //z轴振动速度下限
|
|
let temperatureMax = (this.hex2int(data.slice(70, 74))) / 10 //温度上限
|
let temperatureMin = (this.hex2int(data.slice(74, 78))) / 10 //温度下限
|
|
let setValueDetail = [{
|
type: 'X_zdjsd',
|
name: 'x轴振动加速度上限值',
|
value: X_zdjsdMax,
|
unit: 'm/s²'
|
}, {
|
type: 'X_zdjsd',
|
name: 'x轴振动加速度下限值',
|
value: X_zdjsdMin == 0 ? '0.00' : X_zdjsdMin,
|
unit: 'm/s²'
|
}, {
|
type: 'X_zdsd',
|
name: 'x轴振动速度上限值',
|
value: X_zdsdMax,
|
unit: 'mm/s'
|
}, {
|
type: 'X_zdsd',
|
name: 'x轴振动速度下限值',
|
value: X_zdsdMin == 0 ? '0.00' : X_zdsdMin,
|
unit: 'mm/s'
|
},
|
{
|
type: 'Y_zdjsd',
|
name: 'y轴振动加速度上限值',
|
value: Y_zdjsdMax,
|
unit: 'm/s²'
|
}, {
|
type: 'Y_zdjsd',
|
name: 'y轴振动加速度下限值',
|
value: Y_zdjsdMin == 0 ? '0.00' : Y_zdjsdMin,
|
unit: 'm/s²'
|
}, {
|
type: 'Y_zdsd',
|
name: 'y轴振动速度上限值',
|
value: Y_zdsdMax,
|
unit: 'mm/s'
|
},
|
{
|
type: 'Y_zdsd',
|
name: 'y轴振动速度下限值',
|
value: Y_zdsdMin == 0 ? '0.00' : Y_zdsdMin,
|
unit: 'mm/s'
|
},
|
{
|
type: 'Z_zdjsd',
|
name: 'z轴振动加速度上限值',
|
value: Z_zdjsdMax,
|
unit: 'm/s²'
|
},
|
{
|
type: 'Z_zdjsd',
|
name: 'z轴振动加速度下限值',
|
value: Z_zdjsdMin == 0 ? '0.00' : Z_zdjsdMin,
|
unit: 'm/s²'
|
},
|
{
|
type: 'Z_zdsd',
|
name: 'z轴振动速度上限值',
|
value: Z_zdsdMax,
|
unit: 'mm/s'
|
},
|
{
|
type: 'Z_zdsd',
|
name: 'z轴振动速度下限值',
|
value: Z_zdsdMin == 0 ? '0.00' : Z_zdsdMin,
|
unit: 'mm/s'
|
},
|
{
|
type: 'temperature',
|
name: '温度上限值',
|
value: temperatureMax,
|
unit: '℃'
|
},
|
{
|
type: 'temperature',
|
name: '温度下限值',
|
value: temperatureMin == 0 ? '0.00' : temperatureMin,
|
unit: '℃'
|
}
|
]
|
|
this.settingItem = setValueDetail
|
this.address = data.slice(0, 2) //设备指令地址
|
// console.log(X_zdjsd, X_zdsu, Y_zdjsd, Y_zdsu, Z_zdjsd, Z_zdsu, temperature, voltage)
|
|
},
|
//显示左侧抽屉菜单
|
showLeftDrawer: function(e) {
|
this.leftDrawerStatus = true
|
},
|
//隐藏左侧抽屉菜单
|
hideLeftDrawer: function() {
|
this.leftDrawerStatus = false
|
},
|
//跳转到设备列表
|
deviceList: function(e) {
|
console.log(e)
|
if (e == 'deviceList') {
|
uni.closeBLEConnection({
|
deviceId: this.deviceId,
|
success: (res) => {
|
console.log(res)
|
},
|
fail: (err) => {
|
console.log(err)
|
}
|
})
|
uni.redirectTo({
|
url: '../Connect/mainIndex',
|
})
|
} else {
|
return;
|
}
|
},
|
// 增加警告上限
|
add: function(e) {
|
let index = e.currentTarget.dataset.index
|
let name = e.currentTarget.dataset.name
|
let value = ''
|
if (this.settingItem[index].name.search('下限') != -1 && this.settingItem[index].value > this
|
.settingItem[index - 1].value) {
|
uni.showToast({
|
title: '不能超过上限值',
|
icon: 'none',
|
duration: 1500
|
})
|
return;
|
}
|
if (name.search('温度') != -1) {
|
value = this.settingItem[index].value * 10
|
value = parseFloat((value + 1) / 10) == 0?parseFloat((value + 1) / 10).toFixed(2) : parseFloat((value + 1) / 10)
|
} else {
|
value = this.settingItem[index].value * 100
|
value = parseFloat((value + 1) / 100).toFixed(2)
|
}
|
this.settingItem[index].value = value
|
console.log(this.settingItem[index].value)
|
},
|
//减少警告下限
|
reduce: function(e) {
|
// console.log(e)
|
let index = e.currentTarget.dataset.index
|
let name = e.currentTarget.dataset.name
|
let value = ''
|
if (name.search('温度') != -1) {
|
value = this.settingItem[index].value * 10
|
value = parseFloat((value - 1) / 10) == 0?parseFloat((value + 1) / 10).toFixed(2) : parseFloat((value + 1) / 10)
|
} else {
|
value = parseFloat((value - 1) / 100).toFixed(2)
|
this.settingItem[index].value = value
|
}
|
|
if (value == 0 || value < 0) {
|
value = "0.00"
|
this.settingItem[index].value = value
|
return;
|
}
|
this.settingItem[index].value = value
|
console.log(this.settingItem[index].value)
|
},
|
//手动修改警告的值
|
handleValue: function(e) {
|
// console.log(e)
|
let index = e.target.dataset.index
|
let value = e.target.value
|
let itemName = e.target.name
|
if (this.settingItem[index].name.search('下限') != -1 && this.settingItem[index].value > this
|
.settingItem[index - 1].value) {
|
uni.showToast({
|
title: '不能超过上限值',
|
icon: 'none',
|
duration: 1500
|
})
|
return;
|
}
|
this.settingItem[index].value = value
|
console.log(481, this.settingItem[index].value)
|
},
|
//保存设置项
|
saveSetOption: function() {
|
let setItem = JSON.parse(JSON.stringify(this.settingItem))
|
let address = this.address //地址
|
let func = '10' //功能码
|
let startRegister = 'F500' //寄存器起始位置
|
let reviseRegister = '0014' //修改的寄存器的个数 默认20个
|
let registerLength = '28' //寄存器长度 默认40 长的等于寄存器修改的个数乘2
|
let writeHexHead = address + func + startRegister + reviseRegister + registerLength //指令头部
|
let writeHexItem = "" //拼接每个需要修改的寄存器的对应的十六进制项
|
let crc = '' //校验码
|
let reserve = {
|
name: '预留',
|
value: 0,
|
unit: ''
|
}
|
//将设备寄存器中预留的寄存器项加上 才能生成正确的CRC校验码
|
setItem.splice(12, 0, reserve)
|
setItem.splice(12, 0, reserve)
|
setItem.splice(12, 0, reserve)
|
setItem.splice(12, 0, reserve)
|
setItem.push(reserve)
|
setItem.push(reserve)
|
for (let i = 0; i < setItem.length; i++) {
|
if (i > setItem.length - 5) {
|
writeHexItem += this.str_pad((setItem[i].value * 10).toString(16))
|
// console.log(writeHexItem)
|
} else {
|
writeHexItem += this.str_pad((setItem[i].value * 100).toString(16))
|
}
|
}
|
console.log(519, '未生成校验码的指令:' + (writeHexHead + writeHexItem).toUpperCase())
|
crc = this.modbusCRC(new Buffer((writeHexHead + writeHexItem).toUpperCase(), "hex"))
|
console.log('检验码:' + crc)
|
|
|
let hex = (writeHexHead + writeHexItem + crc[0] + crc[1]).toUpperCase() //写入的指令
|
console.log(525, '指令:' + hex)
|
uni.showModal({
|
title: '提示',
|
content: '是否保存设置',
|
showCancel: true,
|
cancelText: '取消',
|
confirmText: '确定',
|
success: res => {
|
if (res.confirm) { //用户点击确定写入指令
|
this.hex = hex
|
this.isCache = true
|
this.writeBLECharacteristicValue()
|
clearInterval(keepRead) //清除定时器
|
} else if (res.cancel) {
|
this.isCache = false
|
return;
|
}
|
},
|
fail: () => {},
|
complete: () => {}
|
});
|
},
|
|
//获取modbusCRC校验码 返回的array 其中的array[0] + array[1]即为校验码
|
modbusCRC: function(data) {
|
let crcValue = 0xFFFF;
|
for (let i = 0; i < data.length; i++) {
|
crcValue ^= data[i] & 0xFFFF
|
for (let j = 0; j < 8; j++) {
|
if (crcValue & 0x0001) {
|
crcValue >>= 1
|
crcValue ^= 0xA001
|
} else {
|
crcValue >>= 1
|
}
|
}
|
}
|
|
crcValue = crcValue.toString(16)
|
let crcArr = new Array(2)
|
crcArr[0] = crcValue.substring(2, 4)
|
crcArr[1] = crcValue.substring(0, 2)
|
return crcArr
|
},
|
//转换成0000格式的十六进制字符串
|
str_pad: function(hex) {
|
var zero = '0000';
|
var tmp = 4 - hex.length;
|
return '' + zero.substr(0, tmp) + hex;
|
},
|
//十六进制字符串转十进制
|
hex2int: function(hex) {
|
var len = hex.length,
|
a = new Array(len),
|
code;
|
for (var i = 0; i < len; i++) {
|
code = hex.charCodeAt(i);
|
if (48 <= code && code < 58) {
|
code -= 48;
|
} else {
|
code = (code & 0xdf) - 65 + 10;
|
}
|
a[i] = code;
|
}
|
|
return a.reduce(function(acc, c) {
|
acc = 16 * acc + c;
|
return acc;
|
}, 0);
|
},
|
|
// ArrayBuffer转16进度字符串
|
ab2hex: function(buffer) {
|
const hexArr = Array.prototype.map.call(
|
new Uint8Array(buffer),
|
function(bit) {
|
return ('00' + bit.toString(16)).slice(-2)
|
}
|
)
|
return hexArr.join('')
|
},
|
}
|
}
|
</script>
|
|
<style>
|
@import url("/style/animation.css");
|
@import url("/style/main.css");
|
@import url("/style/icon.css");
|
@import url("/style/iconfont.css");
|
|
.title_style {
|
width: 100%;
|
height: 100rpx;
|
background-color: #16b5cb;
|
text-align: center;
|
display: flex;
|
justify-content: flex-end;
|
align-items: center;
|
color: #ffffff;
|
}
|
</style>
|