1
0
forked from dyf/APP

Compare commits

...

3 Commits

17 changed files with 3540 additions and 733 deletions

31
App.vue
View File

@ -29,17 +29,23 @@
// uni.clearStorageSync();
//以上代码仅在开发时使用,否则会出现不可预知的问题。
uni.getSystemInfo({success:function(res){
if(res.uniPlatform=='app'){
bleTool.getBleTool();
upgrade.checkAndUpdateWgt();
}
}});
},
onShow: function() {
console.log('App Show');
//将检查更新换到onshow,因为苹果用户喜欢一直挂着
uni.getSystemInfo({success:function(res){
if(res.uniPlatform=='app'){
let appid=plus.runtime.appid;
if(appid!=='HBuilder'){
console.log("appid=",appid);
bleTool.getBleTool();
upgrade.checkAndUpdateWgt();
}
}
}});
},
onHide: function() {
console.log('App Hide');
@ -92,6 +98,15 @@
background: rgba(42, 42, 42, 1);
}
.green{
color: #BBE600 !important;
}
.red{
color:#E03434 !important;
}
@font-face {
font-family: "PingFang SC";
src: url("~@/static/fonts/PingFangSC.ttf") format("opentype");

View File

@ -0,0 +1,231 @@
<template>
<view>
<canvas type="2d" canvas-id="reusableCanvas" :width="currentCanvasWidth" :height="currentCanvasHeight"
class="offscreen-canvas"></canvas>
</view>
</template>
<script>
export default {
name: "textToDotMatrix",
props: {
txts: {
type: Array,
default: () => [],
validator: (value) => value.every(item => typeof item === 'string')
},
fontSize: {
type: Number,
default: 16,
validator: (value) => value > 0 && value <= 100
},
bgColor: {
type: String,
default: "#ffffff"
},
color: {
type: String,
default: "#000000"
}
},
data() {
return {
// 当前Canvas的宽高动态调整
currentCanvasWidth: 0,
currentCanvasHeight: 0,
// Canvas上下文复用
ctx: null
};
},
computed: {
validTxts() {
return this.txts.filter(line => line.trim() !== '');
}
},
mounted() {
// 初始化Canvas上下文只创建一次
this.ctx = uni.createCanvasContext('reusableCanvas', this);
},
methods: {
/**
* 估算单行文本所需的Canvas宽度
*/
calcLineWidth(textLine) {
return textLine.length * 16;
},
/**
* 清除Canvas内容
*/
clearCanvas() {
this.ctx.setFillStyle(this.bgColor);
this.ctx.fillRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight);
},
/**
* 复用单个Canvas处理所有文本行
*/
async drawAndGetPixels() {
let binaryToHex = (binaryArray) => {
if (!Array.isArray(binaryArray) || binaryArray.length !== 8) {
throw new Error("输入必须是包含8个元素的二进制数组");
}
// 检查每个元素是否为0或1
if (!binaryArray.every(bit => bit === 0 || bit === 1)) {
throw new Error("数组元素必须只能是0或1");
}
// 将二进制数组转换为十进制数
let decimalValue = 0;
for (let i = 0; i < 8; i++) {
// 计算每个位的权重并累加
decimalValue += binaryArray[i] * Math.pow(2, 7 - i);
}
// 将十进制转换为十六进制字符串并添加0x前缀
const hexString = "0x" + decimalValue.toString(16).padStart(2, '0').toUpperCase();
return hexString;
}
let convertCharToMatrix = (imageData, item) => {
// console.log("imgOldData=", imageData)
let matrix = [];
let arr = [];
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
// 计算像素在imageData中的索引 (RGBA格式)
let index = (y * 16 + x) * 4;
let red = imageData[index];
// 黑色像素R值较低视为1白色视为0
let isBlack = red < 128 ? 1 : 0;
arr.push(isBlack);
}
}
let firstHalf = arr.slice(0, arr.length / 2); // [1, 2, ..., 128]
let secondHalf = arr.slice(arr.length / 2); // [129, 130, ..., 256]
for (let i = 0; i < 16; i++) {
let tmp = [];
for (let index = i; index < firstHalf.length; index += 16) {
tmp.push(firstHalf[index]);
}
tmp = tmp.reverse();
matrix.push(binaryToHex(tmp));
}
for (let i = 0; i < 16; i++) {
let tmp = [];
for (let index = i; index < secondHalf.length; index += 16) {
tmp.push(secondHalf[index]);
}
tmp = tmp.reverse();
matrix.push(binaryToHex(tmp));
}
console.log("matrix=", matrix);
return matrix;
}
let drawTxt = async (textLine) => {
let result = {};
let ctx = this.ctx;
// 1. 动态调整Canvas尺寸
this.currentCanvasWidth = this.calcLineWidth(textLine);
this.currentCanvasHeight = 16;
// 2. 清空Canvas绘制背景
this.clearCanvas();
// 3. 设置文字样式
ctx.setFillStyle(this.color);
ctx.setTextBaseline('middle');
// ctx.setTextAlign('center')
ctx.setFontSize(this.fontSize);
ctx.font = `${this.fontSize}px "PingFangBold", "PingFang SC", Arial, sans-serif`;
// 4. 绘制当前行文本
let currentX = 0;
let currentY = this.fontSize / 2;
for (let j = 0; j < textLine.length; j++) {
let char = textLine[j];
ctx.fillText(char, currentX, currentY);
// 按实际字符宽度计算间距
let charWidth = ctx.measureText(char).width;
currentX += charWidth;
}
// 5. 异步绘制并获取像素数据(串行处理避免冲突)
await new Promise((resolve, reject) => {
ctx.draw(false, () => {
uni.canvasGetImageData({
canvasId: 'reusableCanvas',
x: 0,
y: 0,
width: this.currentCanvasWidth,
height: this.currentCanvasHeight,
success: res => {
result = {
line: textLine,
pixelData: res.data,
width: this.currentCanvasWidth,
height: this.currentCanvasHeight
};
resolve();
},
fail: err => {
// console.error(`处理第${i+1}行失败:`, err);
reject(err)
}
});
});
});
return result;
}
let arr = [];
// 循环处理每行文本
for (let i = 0; i < this.validTxts.length; i++) {
let linePixls = [];
let item = this.validTxts[i];
console.log("item=", item);
for (var j = 0; j < item.length; j++) {
let result = await drawTxt(item[j]);
linePixls.push(convertCharToMatrix(result.pixelData, item));
}
console.log("hexs=", linePixls.join(","));
arr.push(linePixls);
}
return arr;
}
}
};
</script>
<style>
.offscreen-canvas {
position: fixed;
left: -9999px;
top: -9999px;
visibility: hidden;
}
</style>

View File

@ -2,7 +2,7 @@
const config = {
// 开发环境
development: {
BASE_URL: 'https://www.cnxhyc.com/jq',
BASE_URL: 'http://192.168.110.56:8000',
API_PREFIX: '',
// MQTT 配置
MQTT_HOST: 'www.cnxhyc.com',

View File

@ -2,7 +2,7 @@
"name" : "星汉物联",
"appid" : "__UNI__A21EF43",
"description" : "设备管控",
"versionName" : "1.0.4",
"versionName" : "1.0.3",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */

View File

@ -250,6 +250,13 @@
"style": {
"navigationBarTitleText": "BJQ7305"
}
},
{
"path" : "pages/6331/BJQ6331",
"style" :
{
"navigationBarTitleText" : "BJQ6331"
}
}

View File

@ -1,9 +1,9 @@
<template>
<view>
<canvas id="splashCanvas" canvas-id="splashCanvas" style="width: 160px; height: 80px; z-index: 9999;position: fixed; visibility: hidden;"></canvas>
<canvas id="splashCanvas" canvas-id="splashCanvas" :style="{'width':width+'px','height':height+'px'}" style=" z-index: 9999;position: fixed; visibility: hidden;"></canvas>
<qf-image-cropper :src="src" :showAngle="false" :width="1600" :height="800" fileType="jpg"
<qf-image-cropper :src="src" :showAngle="false" :width="cropWidth" :height="cropHeight" fileType="jpg"
@crop="handleCrop" :gpu="true">
</qf-image-cropper>
</view>
@ -18,17 +18,30 @@
data() {
return {
src: "",
Statu: false
Statu: false,
width:160,
height:80,
times:10
}
},
computed:{
cropWidth(){
return this.width*this.times;
}
,
cropHeight(){
return this.height*this.times;
}
},
onLoad: function(option) {
const eventChannel = this.getOpenerEventChannel();
var these = this;
eventChannel.on('checkImg', (data)=> {
console.log("我收到你的消息了,消息内容是:" + JSON.stringify(data));
this.src = data.data;
console.log("我收到你的消息了,消息内容是:",data);
eventChannel.on('checkImg', (rec)=> {
console.log("我收到你的消息了,消息内容是:" + JSON.stringify(rec));
this.src = rec.data;
this.width=rec.width?rec.width:160;
this.height=rec.height?rec.height:80;
this.times=rec.times?rec.times:10;
})
},
methods: {
@ -43,7 +56,7 @@
const ctx = uni.createCanvasContext('splashCanvas', this);
ctx.drawImage(
e.tempFilePath,
0,0,160,80
0,0,these.width,these.height
);
setTimeout(() => {
ctx.draw(false, ()=>{
@ -52,8 +65,8 @@
canvasId: 'splashCanvas',
x: 0,
y: 0,
width: 160,
height: 80,
width: these.width,
height: these.height,
success: (res) => {
// 处理像素数据并发送
@ -81,8 +94,7 @@
<style>
.canvas {
width: 1600px;
height: 800px;
border: 1px solid #ccc;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<view class="content contentBg">
<view class="eq">
<view class="leftImg">
<view class="leftImg" @click.stop="previewImg(formData.img)">
<image class="img" :src="formData.img" mode="aspectFit"></image>
</view>
<view class="rightTxt">
@ -34,6 +34,10 @@
<text class="lbl">充电状态</text>
<text class="value">{{formData.statu}}</text>
</view>
<view class="item">
<text class="lbl">蓝牙状态</text>
<text class="value" :class="formData.bleStatu?'green':'red'">{{formData.bleStatu?'已连接':'未连接'}}</text>
</view>
</view>
<view class="lamp">
<view class="title">
@ -124,8 +128,8 @@
:borderColor="Status.Pop.borderColor" :textColor="Status.Pop.textColor"
:buttonBgColor="Status.Pop.buttonBgColor" :buttonTextColor="Status.Pop.buttonTextColor"
:iconUrl="Status.Pop.iconUrl" :message="Status.Pop.message" :buttonText="Status.Pop.buttonText"
@buttonClick="HidePop" @closePop="closePop" :visiblePrompt="Status.Pop.visiblePrompt" :promptTitle="Status.Pop.promptTitle"
v-model="Status.Pop.modelValue" />
@buttonClick="HidePop" @closePop="closePop" :visiblePrompt="Status.Pop.visiblePrompt"
:promptTitle="Status.Pop.promptTitle" v-model="Status.Pop.modelValue" />
<!-- 下方菜单 -->
<BottomSlideMenuPlus :config="Status.BottomMenu" @close="closeMenu" @itemClick="handleItemClick"
@ -152,7 +156,7 @@
updateLoading
} from '@/utils/loading.js'
import BleReceive from '@/utils/BleReceive';
var pagePath = "pages/6155/HBY6155";
var ble = null;
var these = null;
@ -166,6 +170,7 @@
data() {
return {
Status: {
pageHide: false,
Pop: {
showPop: false, //是否显示弹窗
popType: 'custom',
@ -182,7 +187,7 @@
promptTitle: '设备名称',
modelValue: '',
visibleClose: false,
okCallback:null
okCallback: null
},
BottomMenu: {
show: false,
@ -232,7 +237,8 @@
id: '',
deviceId: '',
textLines: ['', '', ''],
mode: ''
mode: '',
bleStatu: ''
},
inteval: 200,
device: {
@ -258,7 +264,7 @@
}
},
onUnload() {
ble.removeReceiveCallback(this);
ble.removeAllCallback(pagePath);
},
onLoad: function() {
these = this;
@ -310,7 +316,12 @@
// link();
// }
console.log("6155");
ble.addReceiveCallback(these.bleValueNotify);
ble.addReceiveCallback(these.bleValueNotify, pagePath);
ble.addStateBreakCallback(these.bleStateBreak, pagePath);
ble.addStateRecoveryCallback(these.bleStateRecovry, pagePath);
ble.addDisposeCallback(these.deviceDispose, pagePath);
ble.addRecoveryCallback(these.deviceRecovry, pagePath);
let eventChannel = this.getOpenerEventChannel();
eventChannel.on('detailData', function(data) {
@ -346,7 +357,9 @@
these.formData.img = device.devicePic;
these.formData.id = device.id;
these.formData.deviceId = f.deviceId;
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId);
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId).then(res => {
these.formData.bleStatu = true;
});
these.setBleFormData();
these.getDetail();
@ -355,7 +368,10 @@
},
onHide: function() {
this.Status.pageHide = true;
},
onShow() {
this.Status.pageHide = false;
},
onBackPress(e) {
@ -410,6 +426,85 @@
}
},
methods: {
deviceRecovry(res) {
if (this.Status.pageHide) {
return;
}
if (res.deviceId == these.formData.deviceId) {
this.formData.bleStatu = true;
setTimeout(() => {
hideLoading(these, 1000);
});
uni.showToast({
icon: 'success',
title: '蓝牙连接成功'
});
}
},
deviceDispose(res) {
if (this.Status.pageHide) {
return;
}
if (res.deviceId == these.formData.deviceId) {
this.formData.bleStatu = false;
setTimeout(() => {
hideLoading(these, 1000);
});
uni.showToast({
icon: 'fail',
title: '蓝牙连接已断开'
});
}
},
bleStateBreak() {
if (this.Status.pageHide) {
return;
}
//蓝牙适配器不可用
this.formData.bleStatu = false;
uni.showToast({
icon: 'fail',
title: '蓝牙已不可用'
})
hideLoading(this);
},
bleStateRecovry() {
console.log("蓝牙可用");
if (this.Status.pageHide) {
return;
}
console.log("蓝牙可用");
//蓝牙适配器再次可用,尝试恢复连接
showLoading(this, {
text: "蓝牙恢复可用,正在连接设备"
});
ble.LinkBlue(these.formData.deviceId).then(() => {
these.formData.bleStatu = true;
updateLoading(these, {
text: '连接成功'
});
}).catch(ex => {
updateLoading(these, {
text: ex.msg
})
}).finally(() => {
setTimeout(() => {
hideLoading(these);
}, 1000);
});
},
previewImg(img) {
if (!img) {
return;
}
uni.previewImage({
urls: [img]
})
},
getDevice: function() {
// console.log("LinkedList=", ble.data.LinkedList);
// console.log("formData=", these.formData);
@ -420,89 +515,28 @@
return f;
},
bleValueNotify: function(receive, device, path) {
let str = recei.ReceiveData(receive, device, path);
console.log("处理接收到的数据:" + str);
return;
let data = recei.ReceiveData(receive, device, path);
let bytes = receive.bytes;
if (bytes[0] == 0xFB && bytes[1] == 0x64 && bytes.length >= 8) {
try {
let staticLevelByte = bytes[2];
let getName = function(type) {
let name = "";
switch (type) {
case 0x02:
name = '弱光';
break;
case 0x04:
name = '工作光';
break;
case 0x01:
name = '强光';
break;
case 0x03:
name = '爆闪';
break;
case 0x00:
name = '关闭';
break;
}
return name;
}
let staticLevelText = getName(staticLevelByte);
// 解析照明档位
let lightingLevelByte = bytes[3];
let lightingLevelText = getName(lightingLevelByte);
// 解析剩余电量
let batteryLevelByte = bytes[4];
// 电量百分比范围检查
let batteryLevel = Math.max(0, Math.min(100, batteryLevelByte));
//充电状态
let warn = bytes[5];
if (warn == 0x00) {
warn = '未充电';
} else if (warn == 0x01) {
warn = '充电中';
}
// 解析剩余照明时间(第三和第四字节,小端序)
let lightingTime = "";
let HH = Math.max(0, Math.min(100, bytes[6]));
let mm = Math.max(0, Math.min(100, bytes[7]));
lightingTime = HH + "小时" + mm + "分钟";
this.formData.mode = staticLevelText;
this.formData.fuMode = lightingLevelText;
this.formData.battary = batteryLevel;
this.formData.statu = warn;
this.formData.xuhang = lightingTime;
if (batteryLevel <= 20) {
this.showPop({
message: "设备电量低",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
});
}
this.setBleFormData();
} catch (error) {
console.log('数据解析错误:', error);
}
if (this.Status.pageHide) {
return;
}
let json = recei.ReceiveData(receive, device, path);
if (!json) {
return;
}
let keys = Object.keys(json);
keys.forEach((key) => {
if (key in these.formData) {
these.formData[key] = json[key];
}
});
if (this.formData.battary <= 20) {
this.showPop({
message: "设备电量低",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
});
}
},
proParam: function() {
@ -544,6 +578,7 @@
events: {
BindOver: function(data) {
console.log(data)
these.formData.bleStatu = true;
}
},
success: function(res) {
@ -975,12 +1010,12 @@
},
closePop: function() {
this.Status.Pop.showPop = false;
if (this.Status.Pop.cancelCallback) {
this.Status.Pop.cancelCallback();
}
},
this.Status.Pop.showPop = false;
if (this.Status.Pop.cancelCallback) {
this.Status.Pop.cancelCallback();
}
},
HidePop: function() {
// console.log("1111");
if (this.Status.Pop.clickEvt == 'SendUsr') {

2048
pages/6331/BJQ6331.vue Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<template>
<view class="content contentBg">
<view class="eq">
<view class="leftImg">
<view class="leftImg" @click.stop="previewImg(formData.img)">
<image class="img" :src="formData.img" mode="aspectFit"></image>
</view>
<view class="rightTxt">
@ -30,6 +30,10 @@
<text class="lbl">设备名称</text>
<text class="value">{{formData.deviceName}}</text>
</view>
<view class="item">
<text class="lbl">蓝牙状态</text>
<text class="value" :class="formData.bleStatu?'green':'red'">{{formData.bleStatu?'已连接':'未连接'}}</text>
</view>
<view class="item">
<text class="lbl">预警级别</text>
<text class="value">{{formData.warnLevel}}</text>
@ -180,6 +184,7 @@
import usrApi from '@/api/670/HBY670.js'
const pagePath = "pages/650/HBY650";
var ble = null;
var these = null;
var recei = null;
@ -263,7 +268,8 @@
name: '',
job: '',
id: '',
iswarn: false
iswarn: false,
bleStatu: false
},
rgb565Data: [],
videoHexArray: [],
@ -291,14 +297,21 @@
onUnload() {
console.log("页面卸载,释放资源");
ble.removeReceiveCallback(pagePath);
ble.removeAllCallback(pagePath);
},
onLoad: function() {
these = this;
recei = BleReceive.getBleReceive();
ble = BleTool.getBleTool();
console.log("650")
ble.addReceiveCallback(these.bleValueNotify);
ble.addReceiveCallback(these.bleValueNotify, pagePath);
ble.addStateBreakCallback(these.bleStateBreak, pagePath);
ble.addStateRecoveryCallback(these.bleStateRecovry, pagePath);
ble.addDisposeCallback(these.deviceDispose, pagePath);
ble.addRecoveryCallback(these.deviceRecovry, pagePath);
let eventChannel = this.getOpenerEventChannel();
eventChannel.on('detailData', function(data) {
@ -332,9 +345,11 @@
these.formData.blename = f.name ? f.name : "Unname";
these.formData.deviceName = device.deviceName;
these.formData.img = device.devicePic;
these.formData.id = device.id;
these.formData.deviceId = f.deviceId;
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId);
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId).then(res=>{
these.formData.bleStatu=true;
});
these.setBleFormData();
these.getDetail();
@ -343,10 +358,10 @@
},
onHide: function() {
this.Status.pageHide = true;
},
onBackPress(e) {
ble.removeReceiveCallback(pagePath);
onShow() {
this.Status.pageHide = false;
},
computed: {
RSSIRemark: function() {
@ -367,6 +382,85 @@
}
},
methods: {
deviceRecovry(res) {
if (this.Status.pageHide) {
return;
}
if (res.deviceId == these.formData.deviceId) {
this.formData.bleStatu = true;
setTimeout(() => {
hideLoading(these, 1000);
});
uni.showToast({
icon: 'success',
title: '蓝牙连接成功'
});
}
},
deviceDispose(res) {
if (this.Status.pageHide) {
return;
}
if (res.deviceId == these.formData.deviceId) {
this.formData.bleStatu = false;
setTimeout(() => {
hideLoading(these, 1000);
});
uni.showToast({
icon: 'fail',
title: '蓝牙连接已断开'
});
}
},
bleStateBreak() {
if (this.Status.pageHide) {
return;
}
//蓝牙适配器不可用
this.formData.bleStatu = false;
uni.showToast({
icon: 'fail',
title: '蓝牙已不可用'
})
hideLoading(this);
},
bleStateRecovry() {
console.log("蓝牙可用");
if (this.Status.pageHide) {
return;
}
console.log("蓝牙可用");
//蓝牙适配器再次可用,尝试恢复连接
showLoading(this, {
text: "蓝牙恢复可用,正在连接设备"
});
ble.LinkBlue(these.formData.deviceId).then(() => {
these.formData.bleStatu = true;
updateLoading(these, {
text: '连接成功'
});
}).catch(ex => {
updateLoading(these, {
text: ex.msg
})
}).finally(() => {
setTimeout(() => {
hideLoading(these);
}, 1000);
});
},
previewImg(img) {
if (!img) {
return;
}
uni.previewImage({
urls: [img]
})
},
getWarnStyle(index) {
let className = "";
switch (this.formData.warnLevel) {
@ -465,7 +559,7 @@
getDetail() {
var that = this;
usrApi.getDetail(this.device.id).then(res => {
console.log("res=",res);
if (res && res.code == 200) {
res = res.data;
let personnelInfo = res.personnelInfo;
@ -590,8 +684,9 @@
borderColor: "#e034344d",
buttonBgColor: "#E03434",
buttonText: '去连接',
buttonTextColor: '#FFFFFFde',
okCallback: function() {
uni.navigateTo({
url: "/pages/common/addBLE/addEquip",
events: {
@ -620,7 +715,7 @@
proParam: function() {
uni.navigateTo({
url: '/pages/common/productDes/index?id=' + this.formData.id,
url: '/pages/common/productDes/index?id=' + this.device.id,
success(ev) {
}
@ -628,7 +723,7 @@
},
handRemark: function() {
uni.navigateTo({
url: '/pages/common/operatingInstruct/index?id=' + this.formData.id,
url: '/pages/common/operatingInstruct/index?id=' + this.device.id,
success(ev) {
}
@ -636,7 +731,7 @@
},
handVideo: function() {
uni.navigateTo({
url: '/pages/common/operationVideo/index?id=' + this.formData.id,
url: '/pages/common/operationVideo/index?id=' + this.device.id,
success(ev) {
}

View File

@ -4,7 +4,7 @@
:rightIcons="Status.navbar.icons" @icon-click="handleRightClick"></custom-navbar>
<view class="eq" :style="{marginTop:Status.navbar.height+'px'}">
<view class="leftImg">
<view class="leftImg" @click.stop="previewImg(device['devicePic'])">
<image class="img" :src="device['devicePic']" mode="aspectFit"></image>
</view>
<view class="rightTxt">
@ -33,10 +33,15 @@
<text class="lbl">设备名称</text>
<text class="value valueFont">{{device.deviceName}}</text>
</view>
<view class="item">
<text class="lbl">蓝牙状态</text>
<text class="value" :class="formData.bleStatu?'green':'red'">{{formData.bleStatu?'已连接':'未连接'}}</text>
</view>
<view class="item">
<text class="lbl">设备状态</text>
<text class="value valueFont">{{formData.sta_system}}</text>
</view>
<view class="item">
<text class="lbl">定位信息</text>
<view class="multiValue" @click.stop="gotoMap()">
@ -293,6 +298,7 @@
data() {
return {
Status: {
pageHide: false,
apiType: "listA",
navbar: {
icons: [{
@ -369,7 +375,7 @@
showClose: false
},
usrToggle: true,
bleLinkCnt:0
bleLinkCnt: 0
},
formData: {
battary: "", //电量
@ -391,7 +397,8 @@
staticWarn: false, //静止报警
fourGStrenth: 0, //4G信号强度
deviceId: "",
sta_system: "" //设备状态0关机1仅充电2开机未充电,3开机且充电
sta_system: "", //设备状态0关机1仅充电2开机未充电,3开机且充电
bleStatu: false
},
device: {
id: "",
@ -446,7 +453,7 @@
onUnload() {
console.log("页面卸载,释放资源");
let statusTopic = `A/${this.formData.imei?this.formData.imei:this.device.deviceImei}`;
ble.removeReceiveCallback(pagePath);
ble.removeAllCallback(pagePath);
if (mqttClient) {
mqttClient.unsubscribe(statusTopic);
mqttClient.disconnect();
@ -460,8 +467,14 @@
these = this;
recei = BleReceive.getBleReceive();
ble = BleTool.getBleTool();
console.log("670")
ble.addReceiveCallback(these.bleValueNotify);
ble.addReceiveCallback(these.bleValueNotify, pagePath);
ble.addStateBreakCallback(these.bleStateBreak, pagePath);
ble.addStateRecoveryCallback(these.bleStateRecovry, pagePath);
ble.addDisposeCallback(these.deviceDispose, pagePath);
ble.addRecoveryCallback(these.deviceRecovry, pagePath);
let eventChannel = this.getOpenerEventChannel();
eventChannel.on('detailData', function(data) {
@ -510,12 +523,17 @@
these.formData['imei'] = these.device.deviceImei;
}
these.getDetail();
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId);
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId).then(res => {
these.formData.bleStatu = true;
});
});
},
onShow() {
this.Status.pageHide=false;
},
onHide: function() {
this.Status.pageHide=true;
},
onBackPress(e) {
ble.removeReceiveCallback(pagePath);
@ -524,20 +542,99 @@
},
methods: {
deviceRecovry(res) {
if (this.Status.pageHide) {
return;
}
if (res.deviceId == these.formData.deviceId) {
this.formData.bleStatu = true;
setTimeout(() => {
hideLoading(these, 1000);
});
uni.showToast({
icon: 'success',
title: '蓝牙连接成功'
});
}
},
deviceDispose(res) {
if (this.Status.pageHide) {
return;
}
if (res.deviceId == these.formData.deviceId) {
this.formData.bleStatu = false;
setTimeout(() => {
hideLoading(these, 1000);
});
uni.showToast({
icon: 'fail',
title: '蓝牙连接已断开'
});
}
},
bleStateBreak() {
if (this.Status.pageHide) {
return;
}
//蓝牙适配器不可用
this.formData.bleStatu = false;
uni.showToast({
icon: 'fail',
title: '蓝牙已不可用'
})
hideLoading(this);
},
bleStateRecovry() {
console.log("蓝牙可用");
if (this.Status.pageHide) {
return;
}
console.log("蓝牙可用");
//蓝牙适配器再次可用,尝试恢复连接
showLoading(this, {
text: "蓝牙恢复可用,正在连接设备"
});
ble.LinkBlue(these.formData.deviceId).then(() => {
these.formData.bleStatu = true;
updateLoading(these, {
text: '连接成功'
});
}).catch(ex => {
updateLoading(these, {
text: ex.msg
})
}).finally(() => {
setTimeout(() => {
hideLoading(these);
}, 1000);
});
},
previewImg(img) {
if (!img) {
return;
}
uni.previewImage({
urls: [img]
})
},
showBleUnConnect() {
this.Status.bleLinkCnt++;
if(this.Status.bleLinkCnt>3){
if (this.Status.bleLinkCnt > 3) {
return;
}
this.showPop({
message: "蓝牙未连接过该设备,请使用蓝牙重新添加该设备",
message: "蓝牙未连接过该设备,请使用蓝牙重新添加该设备,取消"+(4-this.Status.bleLinkCnt)+"次后不再提醒",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
buttonText: '去连接',
showCancel: true,
cancelCallback: () => {
this.closePop();
// this.closePop();
},
okCallback: function() {
console.log("1111");
@ -562,7 +659,7 @@
});
},
gotoMap() {
let lnglat=lnglatConvert.wgs84_to_gcj02(this.formData.Lon,this.formData.Lat);
let lnglat = lnglatConvert.wgs84_to_gcj02(this.formData.Lon, this.formData.Lat);
this.detailData.longitude = lnglat[0];
this.detailData.latitude = lnglat[1];
uni.navigateTo({
@ -1166,6 +1263,7 @@
}
if (this.formData.SOS == type) {
console.log("111111");
type = "close";
}
@ -1200,23 +1298,31 @@
message.deviceId = these.device.id;
message.deviceImei = these.device.deviceImei;
let requestSend = () => {
let requestSend = (callback) => {
debugger;
message.isBluetooth = false;
api.sendSos(message).then((res) => {
console.log("res=>", res);
if (res && res.code == 200) {
console.log("接口发送SOS指令成功");
if (callback) {
callback();
}
return Promise.resolve({
code: 200,
msg: '操作成功'
});
} else {
return this.sendMQ(json);
}
}).then((res) => {
console.log("res=", res);
if (callback) {
callback();
}
}).catch((ex) => {
console.log("ex=", ex);
these.showPop({
@ -1234,7 +1340,7 @@
}
let bleSendCmd = () => {
let bleSendCmd = (callback) => {
let f = this.getDevice();
let buffer = null;
if (f) {
@ -1247,75 +1353,87 @@
dataView.setUint8(3, 0x00); // 数据长度
dataView.setUint8(4, 0x01); // 数据长度
dataView.setUint8(5, dic.ble[type]); // 数据
console.log("type=", type);
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 10).then(
() => {
console.log("蓝牙发送成功了");
hideLoading(these);
these.setBleFormData();
message.isBluetooth = true;
api.sendSos(message);
// api.sendSos(message);
if (callback) {
callback();
}
}).catch((ex) => {
//使用4G发送
console.log("蓝牙发送失败,转4g发送", ex);
requestSend();
requestSend(callback);
});
} else {
console.log("找不到蓝牙设备");
requestSend();
requestSend(callback);
these.showBleUnConnect();
}
}
let OpenSOS = () => {
these.formData.qzwarn = true; //标记为强制报警了
let execSos = () => {
these.formData.qzwarn = true; //标记为强制报警了
these.Status.staticWarn.time = 180;
this.formData.SOS = type;
let loopFunc = () => {
if (these.Status.staticWarn.inteval === null) {
return;
}
if (these.Status.staticWarn.time === 0) {
clearInterval(these.Status.staticWarn.inteval);
these.Status.staticWarn.inteval = null;
these.formData.qzwarn = false;
if(this.Status.Pop.okCallback){
these.CloseWarn(false);
these.formData.SOS = 'close';
}
return;
}
these.Status.staticWarn.time = these.Status.staticWarn
.time - 1;
if (these.Status.Pop.clickEvt == 'time' && this.Status.Pop.showPop) {
console.log("111111");
this.showQzWarn(this.Status.Pop.okCallback);
}
these.Status.staticWarn.time = 180;
this.formData.SOS = type;
let loopFunc = () => {
if (these.Status.staticWarn.inteval === null) {
return;
}
if (these.Status.staticWarn.time === 0) {
clearInterval(these.Status.staticWarn.inteval);
these.Status.staticWarn.inteval = null;
these.formData.qzwarn = false;
these.formData.SOS = 'close';
these.CloseWarn(false);
return;
}
these.Status.staticWarn.time = these.Status.staticWarn
.time - 1;
if (these.Status.Pop.clickEvt == 'time' && this.Status.Pop.showPop) {
console.log("111111");
this.showQzWarn(this.Status.Pop.okCallback);
}
these.Status.staticWarn.inteval = setInterval(() => {
loopFunc();
}, 1000);
}
these.Status.staticWarn.inteval = setInterval(() => {
loopFunc();
}, 1000);
bleSendCmd();
bleSendCmd(execSos);
}
if (type == 'rb') { //红蓝报警
console.log("11111");
let sendRb = () => {
this.formData.SOS = type;
bleSendCmd();
these.formData.qzwarn = false;
this.Status.staticWarn.time = 0;
return;
}
if (these.formData.qzwarn && these.Status.staticWarn.inteval) {
if (these.formData.qzwarn && these.Status.staticWarn.inteval && these.Status.staticWarn.time) {
console.log("222222");
this.Status.Pop.okCallback=null;
these.showQzWarn(sendRb);
} else {
sendRb();
@ -2100,8 +2218,8 @@
}
let requestSend = () => {
let json = {
deviceId: this.device.id,
deviceImei: this.device.deviceImei ? this.device.deviceImei : this.formData.imei,
@ -2262,7 +2380,7 @@
setTimeout(sendNextPacket, 200);
}).catch(err => {
if (err.code == '10007') {
setTimeout(sendNextPacket,200);
setTimeout(sendNextPacket, 200);
} else {
requestSend();
}

View File

@ -1,7 +1,7 @@
<template>
<view class="content contentBg">
<view class="eq">
<view class="leftImg">
<view class="leftImg" @click.stop="previewImg(formData.img)">
<image class="img" :src="formData.img" mode="aspectFit"></image>
</view>
<view class="rightTxt">
@ -34,6 +34,10 @@
<text class="lbl">充电状态</text>
<text class="value">{{formData.statu}}</text>
</view>
<view class="item">
<text class="lbl">蓝牙状态</text>
<text class="value" :class="formData.bleStatu?'green':'red'">{{formData.bleStatu?'已连接':'未连接'}}</text>
</view>
</view>
<view class="lamp">
<view class="title">
@ -83,7 +87,7 @@
<text class="usrtitle fleft">人员信息登记</text>
<view class="btnSend fright" v-on:click.stop="sendUsr">发送</view>
<view class="clear"></view>
<TextToHexV1 class="TextToHex" ref="textToHex" :txts="formData.textLines" :bgColor="'#FFFFFF'"
<textToDotMatrix class="TextToHex" ref="textToHex" :txts="formData.textLines" :bgColor="'#FFFFFF'"
:color="'#000000'" :fontSize="14" />
</view>
@ -124,8 +128,8 @@
:borderColor="Status.Pop.borderColor" :textColor="Status.Pop.textColor"
:buttonBgColor="Status.Pop.buttonBgColor" :buttonTextColor="Status.Pop.buttonTextColor"
:iconUrl="Status.Pop.iconUrl" :message="Status.Pop.message" :buttonText="Status.Pop.buttonText"
@buttonClick="HidePop" @closePop="closePop" :visiblePrompt="Status.Pop.visiblePrompt" :promptTitle="Status.Pop.promptTitle"
v-model="Status.Pop.modelValue" />
@buttonClick="HidePop" @closePop="closePop" :visiblePrompt="Status.Pop.visiblePrompt"
:promptTitle="Status.Pop.promptTitle" v-model="Status.Pop.modelValue" />
<!-- 下方菜单 -->
<BottomSlideMenuPlus :config="Status.BottomMenu" @close="closeMenu" @itemClick="handleItemClick"
@ -143,7 +147,7 @@
</template>
<script>
import TextToHexV1 from '@/components/TextToHex/TextToHexV1.vue';
import textToDotMatrix from '@/components/TextToHex/textToDotMatrix.vue';
import bleTool from '@/utils/BleHelper.js';
import usrApi from '@/api/670/HBY670.js'
import {
@ -158,14 +162,15 @@
var these = null;
var BrighInteval = null;
var recei = null;
var pagePath = "pages/7305/BJQ7305";
export default {
components: {
TextToHexV1
textToDotMatrix
},
data() {
return {
Status: {
pageHide: false,
Pop: {
showPop: false, //是否显示弹窗
popType: 'custom',
@ -182,7 +187,7 @@
promptTitle: '设备名称',
modelValue: '',
visibleClose: false,
okCallback:null
okCallback: null
},
BottomMenu: {
show: false,
@ -232,7 +237,8 @@
id: '',
deviceId: '',
textLines: ['', '', ''],
mode: ''
mode: '',
bleStatu: ''
},
inteval: 200,
device: {
@ -258,59 +264,18 @@
}
},
onUnload() {
ble.removeReceiveCallback(this);
ble.removeAllCallback(pagePath);
},
onLoad: function() {
these = this;
recei = BleReceive.getBleReceive();
ble = bleTool.getBleTool();
// let bleName = 'FB_Site_UART'; //JQZM-EF4651 FB_Site_UART
// let f = ble.data.LinkedList.find((v) => {
// if (v.name == bleName) {
// console.log("找到设备了", v);
// these.formData.deviceId = v.deviceId;
// return true;
// }
// return false;
// });
// let link = () => {
// if (bleName == 'FB_Site_UART') {
// ble.LinkBlue(f.deviceId, '0000AE30-0000-1000-8000-00805F9B34FB',
// '0000AE03-0000-1000-8000-00805F9B34FB', '0000AE02-0000-1000-8000-00805F9B34FB');
// } else {
// ble.LinkBlue(f.deviceId, '0000FFE0-0000-1000-8000-00805F9B34FB',
// '0000FFE1-0000-1000-8000-00805F9B34FB', '0000FFE2-0000-1000-8000-00805F9B34FB');
// }
// }
// if (!f) {
// ble.addDeviceFound((res) => {
// // console.log("发现新设备", res);
// f = res.devices.find((v) => {
// return v.name == bleName;
// });
// if (f) {
// console.log("找到目标设备了", f);
// these.formData.deviceId = f.deviceId;
// link();
// ble.StopSearch();
// }
// });
// ble.StartSearch();
// } else {
// link();
// }
console.log("6155");
ble.addReceiveCallback(these.bleValueNotify);
ble.addReceiveCallback(these.bleValueNotify, pagePath);
ble.addStateBreakCallback(these.bleStateBreak, pagePath);
ble.addStateRecoveryCallback(these.bleStateRecovry,pagePath);
ble.addDisposeCallback(these.deviceDispose,pagePath);
ble.addRecoveryCallback(these.deviceRecovry,pagePath);
let eventChannel = this.getOpenerEventChannel();
eventChannel.on('detailData', function(data) {
@ -346,7 +311,10 @@
these.formData.img = device.devicePic;
these.formData.id = device.id;
these.formData.deviceId = f.deviceId;
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId);
ble.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId).then(res=>{
console.log("连接成功")
these.formData.bleStatu=true;
});
these.setBleFormData();
these.getDetail();
@ -355,12 +323,11 @@
},
onHide: function() {
this.Status.pageHide = true;
console.log("页面隐藏");
},
onBackPress(e) {
ble.removeReceiveCallback();
onShow: function() {
this.Status.pageHide = false;
},
computed: {
RSSIRemark: function() {
@ -410,6 +377,85 @@
}
},
methods: {
deviceRecovry(res){
if(this.Status.pageHide){
return;
}
if(res.deviceId==these.formData.deviceId){
this.formData.bleStatu=true;
setTimeout(()=>{
hideLoading(these,1000);
});
uni.showToast({
icon:'success',
title:'蓝牙连接成功'
});
}
},
deviceDispose(res){
if(this.Status.pageHide){
return;
}
if(res.deviceId==these.formData.deviceId){
this.formData.bleStatu=false;
setTimeout(()=>{
hideLoading(these,1000);
});
uni.showToast({
icon:'fail',
title:'蓝牙连接已断开'
});
}
},
bleStateBreak() {
if(this.Status.pageHide){
return;
}
//蓝牙适配器不可用
this.formData.bleStatu = false;
uni.showToast({
icon: 'fail',
title: '蓝牙已不可用'
})
hideLoading(this);
},
bleStateRecovry() {
console.log("蓝牙可用");
if(this.Status.pageHide){
return;
}
console.log("蓝牙可用");
//蓝牙适配器再次可用,尝试恢复连接
showLoading(this, {
text: "蓝牙恢复可用,正在连接设备"
});
ble.LinkBlue(these.formData.deviceId).then(() => {
these.formData.bleStatu = true;
updateLoading(these,{
text:'连接成功'
});
}).catch(ex => {
updateLoading(these, {
text: ex.msg
})
}).finally(() => {
setTimeout(() => {
hideLoading(these);
}, 1000);
});
},
previewImg(img) {
if (!img) {
return;
}
uni.previewImage({
urls: [img]
})
},
getDevice: function() {
// console.log("LinkedList=", ble.data.LinkedList);
// console.log("formData=", these.formData);
@ -420,87 +466,27 @@
return f;
},
bleValueNotify: function(receive, device, path) {
let str = recei.ReceiveData(receive, device, path);
console.log("处理接收到的数据:" + str);
return;
let data = recei.ReceiveData(receive, device, path);
let bytes = receive.bytes;
if (bytes[0] == 0xFB && bytes[1] == 0x64 && bytes.length >= 8) {
try {
let staticLevelByte = bytes[2];
let getName = function(type) {
let name = "";
switch (type) {
case 0x02:
name = '弱光';
break;
case 0x04:
name = '工作光';
break;
case 0x01:
name = '强光';
break;
case 0x03:
name = '爆闪';
break;
case 0x00:
name = '关闭';
break;
}
return name;
}
let staticLevelText = getName(staticLevelByte);
// 解析照明档位
let lightingLevelByte = bytes[3];
let lightingLevelText = getName(lightingLevelByte);
// 解析剩余电量
let batteryLevelByte = bytes[4];
// 电量百分比范围检查
let batteryLevel = Math.max(0, Math.min(100, batteryLevelByte));
//充电状态
let warn = bytes[5];
if (warn == 0x00) {
warn = '未充电';
} else if (warn == 0x01) {
warn = '充电中';
}
// 解析剩余照明时间(第三和第四字节,小端序)
let lightingTime = "";
let HH = Math.max(0, Math.min(100, bytes[6]));
let mm = Math.max(0, Math.min(100, bytes[7]));
lightingTime = HH + "小时" + mm + "分钟";
this.formData.mode = staticLevelText;
this.formData.fuMode = lightingLevelText;
this.formData.battary = batteryLevel;
this.formData.statu = warn;
this.formData.xuhang = lightingTime;
if (batteryLevel <= 20) {
this.showPop({
message: "设备电量低",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
});
}
this.setBleFormData();
} catch (error) {
console.log('数据解析错误:', error);
if (this.Status.pageHide) {
return;
}
let json = recei.ReceiveData(receive, device, path);
if (!json) {
return;
}
let keys = Object.keys(json);
keys.forEach((key) => {
if (key in these.formData) {
these.formData[key] = json[key];
}
});
if ('battary' in json && this.formData.battary <= 20) {
this.showPop({
message: "设备电量低",
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
});
}
},
@ -544,6 +530,7 @@
events: {
BindOver: function(data) {
console.log(data)
these.formData.bleStatu=true;
}
},
success: function(res) {
@ -567,72 +554,18 @@
return;
}
// 处理像素数据并发送
var processAndSendImageData = function(pixels) {
return new Promise((resolve, reject) => {
// 创建RGB565格式的像素数据
const arr = ble.convertToRGB565(pixels, 'bgr');
var list = [];
let index = 0; // 用于追踪arr的当前位置
let packetSize = 2048;
let cSize = 248;
// 外层循环7个主要元素i从1到7
for (let i = 1; i < 8; i++) {
let secondLevel = [];
let secondCnt = 0;
// 中层循环每个主要元素包含9个子数组j从1到9
for (let j = 1; j < 10; j++) {
// 确定当前子数组的长度前8个是254第9个是64
let thirdLevel = [];
// 从arr中提取相应数量的元素
for (let k = 0; k < cSize && index < arr.length; k++) {
if (secondCnt == packetSize) {
break;
}
thirdLevel.push(arr[index]);
secondCnt++;
index++;
}
secondLevel.push(thirdLevel);
}
list.push(secondLevel);
}
console.log("list=", list);
let length = 0;
for (let i = 0; i < list.length; i++) {
const item = list[i];
let clength = 0;
for (let j = 0; j < item.length; j++) {
const element = item[j];
// console.log("第" + i + "包,第" + j + "小包,长度:" + element.length)
length += element.length;
clength += element.length;
}
}
// 分包发送
sendImagePackets(list).then(resolve).catch(reject);
});
}
// 分包发送图片数据
var sendImagePackets = function(imageData) {
var sendImagePackets = function(packetData) {
return new Promise((resolve, reject) => {
// 总数据包数
const totalPackets = 7;
const totalPackets = 3;
let currentPacket = 1;
let childPacket = 1;
let totalChildPacket = 9;
// 发送单个数据包
@ -650,92 +583,49 @@
});
resolve();
}, 20000)
}, 0)
return;
}
var packetData = imageData[currentPacket - 1][childPacket - 1];
// if (packetData.length == 0) {
// hideLoading(these);
// these.Status.BottomMenu.show = false;
// these.showPop({
// message: "上传成功",
// iconUrl: "/static/images/6155/DeviceDetail/uploadSuccess.png"
// });
// resolve();
// return;
// }
let start = 0;
let bufferSize = packetData.length * 2;
if (currentPacket == 7) {
if (childPacket > 2 && childPacket < 9) {
bufferSize = 496;
} else if (childPacket == 9) {
bufferSize = 128;
}
}
if (childPacket == 1) {
bufferSize = bufferSize + 8
start = 8;
}
if (childPacket == 9) { //|| (currentPacket==7 && childPacket==3
bufferSize = bufferSize + 1
}
//FA 09 10 04 FC 09 [00] [01] + 4096字节+FF 数据格式
let bufferSize = 343; //总共1029字节3包正好每包343字节
//FA 09 04 00 1024字节 FF
var buffer = new ArrayBuffer(bufferSize);
var dataView = new DataView(buffer);
if (childPacket == 1) {
if (currentPacket == 1) {
dataView.setUint8(0, 0xFA); // 帧头
dataView.setUint8(1, 0x09); // 帧头
dataView.setUint8(2, 0x10); // 帧头
dataView.setUint8(3, 0x04); // 帧头
dataView.setUint8(4, 0xFC); // 帧头
dataView.setUint8(5, 0x09); // 帧头
dataView.setUint8(1, 0x09); // 帧头
dataView.setUint8(2, 0x04); // 帧头
dataView.setUint8(3, 0x00); // 帧头
dataView.setUint8(6, 0x00); // 图序号,图片固定0视频的话要写序号
dataView.setUint8(7, currentPacket); //子包序号
}
for (let i = 0; i < packetData.length; i++) {
dataView.setUint16(start + i * 2, packetData[i], false); //本包数据,大端字节序
for (let i = 0; i < packetData.length; i++) {
dataView.setUint8(4 + i, parseInt(packetData[i], 16));
}
}
console.log("packetData.length=", packetData.length);
console.log("bufferSize=", bufferSize)
if (childPacket == 9) { // || (currentPacket==7 && childPacket==3
if (currentPacket == totalPackets) {
dataView.setUint8(bufferSize - 1, 0xFF);
}
//发送数据包
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId,
1000)
30)
.then(() => {
let curr = childPacket + (currentPacket - 1) *
totalChildPacket;
console.log("第" + currentPacket + "大包,第" + childPacket +
"小包发送完成,总计:" + curr);
updateLoading(these, {
text: "正在发送" + curr + "/63"
text: "正在发送" + currentPacket + "/" + totalPackets
})
if (childPacket == 9) {
currentPacket++;
childPacket = 1;
} else {
childPacket++;
}
currentPacket++;
setTimeout(sendNextPacket, 1000);
setTimeout(sendNextPacket, 100);
}).catch(err => {
if (err.code == 10007) {
setTimeout(sendNextPacket, 1000);
setTimeout(sendNextPacket, 100);
return;
}
@ -756,6 +646,7 @@
// 开始发送数据
sendNextPacket();
});
}
@ -769,16 +660,115 @@
url: "/pages/6155/ImgCrop",
events: {
ImgCutOver: function(data) {
//将8位的二进制数组转换成16进制数据
let binaryToHex = (binaryArray) => {
if (!Array.isArray(binaryArray) || binaryArray
.length !== 8) {
throw new Error("输入必须是包含8个元素的二进制数组");
}
// 检查每个元素是否为0或1
if (!binaryArray.every(bit => bit === 0 || bit ===
1)) {
throw new Error("数组元素必须只能是0或1");
}
// 将二进制数组转换为十进制数
let decimalValue = 0;
for (let i = 0; i < 8; i++) {
// 计算每个位的权重并累加
decimalValue += binaryArray[i] * Math.pow(2,
7 - i);
}
// 将十进制转换为十六进制字符串并添加0x前缀
const hexString = "0x" + decimalValue.toString(16)
.padStart(2, '0').toUpperCase();
return hexString;
}
let imageData = data.piexls;
let arr = [];
for (let currIndex = 0; currIndex < imageData
.length; currIndex += 4) {
let R = imageData[currIndex];
let G = imageData[currIndex + 1];
let B = imageData[currIndex + 2];
let A = imageData[currIndex + 3];
let grayVal = Math.floor(R * 0.299 + G * 0.587 + B *
0.114);
arr.push(grayVal < 128 ? 1 : 0);
}
let f = arr.filter(v => {
return v === 1;
});
//如果有超过1/3的亮点,将进行反色处理
if (f.length > arr.length / 3) {
for (var r = 0; r < arr.length; r++) {
if (arr[r] === 0) {
arr[r] = 1;
} else {
arr[r] = 0;
}
}
}
// console.log("arr=", JSON.stringify(arr));
let matrix = [];
let size = 512;
let len = arr.length / size;
for (let j = 0; j < len; j++) {
let start = j * size;
let end = start + size;
let firstHalf = arr.slice(start, end);
let arr64 = [];
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 64; col++) {
let ind = col + row * 64;
if (col === 63) {
}
let val = firstHalf[ind];
if (arr64.length < col + 1) {
arr64.push([])
}
arr64[col].push(val);
if (arr64[col].length === 8) {
arr64[col] = arr64[col].reverse();
matrix.push(binaryToHex(arr64[col]));
}
}
}
}
console.log("matrix=", JSON.stringify(matrix));
showLoading(these, {
text: "正在发送0/52"
text: "正在发送0/3"
});
these.Status.BottomMenu.show = false;
setTimeout(function() {
processAndSendImageData(data.piexls).catch((
sendImagePackets(matrix).catch((
ex) => {
console.log("出现异常", ex);
hideLoading(these);
});
}, 0)
@ -786,7 +776,10 @@
},
success(ev) {
ev.eventChannel.emit('checkImg', {
data: res.tempFiles[0].path
data: res.tempFiles[0].path,
width: 64,
height: 32,
times: 10
})
},
fail(ex) {
@ -973,12 +966,12 @@
},
closePop: function() {
this.Status.Pop.showPop = false;
if (this.Status.Pop.cancelCallback) {
this.Status.Pop.cancelCallback();
}
},
this.Status.Pop.showPop = false;
if (this.Status.Pop.cancelCallback) {
this.Status.Pop.cancelCallback();
}
},
HidePop: function() {
console.log("1111");
if (this.Status.Pop.clickEvt == 'SendUsr') {
@ -1135,21 +1128,6 @@
return level1.flat(Infinity);
});
console.log("result=", result);
// var str1="FA 06 01 00 FF FF F7 9F EF 6F EC F7 EA 09 CF FF AF FB EF EB EF EB EC 6B EF EB EC 6B EF EB EF FB EE 63 FF FF FF FF F7 9F EF 6F EC F7 EA 09 CF FF AF FB EF EB EF EB EC 6B EF EB EC 6B EF EB EF FB EE 63 FF FF FF FF F7 FF 81 03 ED BB DD B7 CB CF F3 C7 CD 39 BE FF FE FF C0 03 FE FB FD FB F3 F7 8F 87 FF FF FF FF FE FF FE FF FE FF C0 03 FF FB FD FB FD FB FD FB FD FB FB FB FB FF F7 F7 EF F7 9F 8F FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF"
// var str2="FA 07 01 00 FF FF EE DD EE DF EF 5B AB DF AA 03 AE FF AE FF EE 03 EE FF EE FF EE 03 EE FF EE FF EE E3 FF FF FF FF EE DD EE DF EF 5B AB DF AA 03 AE FF AE FF EE 03 EE FF EE FF EE 03 EE FF EE FF EE E3 FF FF FF FF EF 77 EF 73 EF 7F 80 01 EF 7F EF 7F EF 03 E7 3B 8E BB EE D7 EE EF ED E7 ED 9B 8B 7D FF FF FF FF FF FF F7 EF F7 F7 EF F7 DF FB FF FF FF FF FE FF 80 01 FE 7F FD BF FB DF F7 E7 9F F9 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF"
// var str3="FA 08 01 00 FF FF EF DF EC 01 EF FF AB FF AA 03 AA FB AE FB EE 03 EF DF EF DF EE DB ED DF ED DD EF 1F FF FF FF FF EF BF EF 87 81 77 EE F7 EC 03 81 7F EF 7F EF 7F EF 03 81 7F EF 7F EF 7D EF 7D EF 03 FF FF FF FF F9 F1 CF BF DF FF DF FF C1 FF DD 81 DD F7 DD F7 C1 F7 DF 77 FF 77 BF 77 BF 77 FF F7 FF FF FF FF FD FF FD FF FB FF FB FF F0 07 E7 F7 EF F7 D8 07 BF F7 FF F7 F8 07 FF F7 FF F7 FF C7 FF FF FF FF FF FF FF FF FF FF FE FF FE 7F FE 7F FE FF FD BF FD FF FB DF F7 EF EF F7 DF FB BF FD FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF"
// let arr1=('0x'+(str1.split(' ').join(",0x"))).split(',');
// let arr2=('0x'+(str2.split(' ').join(",0x"))).split(',');
// let arr3=('0x'+(str3.split(' ').join(",0x"))).split(',');
// result=[arr1,arr2,arr3];
// console.log("result=",result);
let h3dic = [0x06, 0x07, 0x08];
let pros = [];
let flag = true;
@ -1259,7 +1237,14 @@
if (f) {
// 发送数据
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 100);
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 100).catch(ex=>{
these.showPop({
message: "发送失败," + ex.msg,
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
});
});
}
@ -1301,7 +1286,14 @@
if (f) {
// 发送数据
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 100);
ble.sendData(f.deviceId, buffer, f.writeServiceId, f.wirteCharactId, 100).catch(ex=>{
these.showPop({
message: "发送失败," + ex.msg,
iconUrl: "/static/images/6155/DeviceDetail/uploadErr.png",
borderColor: "#e034344d",
buttonBgColor: "#E03434",
});
});
}
@ -1489,6 +1481,7 @@
letter-spacing: 0.07px;
text-align: left;
}
.lamp {
margin-top: 24rpx;

View File

@ -46,14 +46,14 @@
var these = null;
var eventChannel = null;
var ble = null;
export default {
data() {
return {
Statu: {
bound: null,
timeInteval:null,
isSearch:false
timeInteval: null,
isSearch: false
},
device: {
"deviceId": "",
@ -64,12 +64,12 @@
"advertisServiceUUIDs": [
],
"linkStatu": false,
"linkStatu": true,
"macAddress": "",
"communicationMode":"",
"imei":""
"communicationMode": "",
"imei": ""
},
serverDevice:null
serverDevice: null
}
},
computed: {
@ -83,51 +83,84 @@
return "red";
}
},
deviceStatu:function(){
if(!this.device.name){
deviceStatu: function() {
if (!this.device.name) {
return "";
}
if(!this.device.macAddress){
if (!this.device.linkStatu) {
return "蓝牙未连接";
}
if (!this.device.macAddress) {
return '等待设备上报Mac地址';
}
if(!this.device.deviceName ){
if(this.Statu.isSearch){
if (!this.device.deviceName) {
if (this.Statu.isSearch) {
return "无效设备";
}else{
if(this.Statu.timeInteval===null){
} else {
if (this.Statu.timeInteval === null) {
return "等待查询设备"
}else{
} else {
return "正在查询设备";
}
}
}else{
} else {
return "找到有效设备"
}
return "";
}
},
onUnload() {
console.log("返回时断开蓝牙连接,取消订阅");
ble.removeReceiveCallback(pagePath);
console.log("返回取消订阅");
ble.removeAllCallback(pagePath);
},
onLoad(option) {
these = this;
ble = bleTool.getBleTool();
console.log("LinkBle")
ble.addStateBreakCallback(res => {
these.device.linkStatu = false;
hideLoading(these);
uni.showToast({
icon:'fail',
title:'蓝牙已不可用'
})
},pagePath);
ble.addStateRecoveryCallback(res => {
if (these.device.deviceId) {
showLoading(these, {
text: '蓝牙已恢复正在连接设备'
});
these.reLinkdevice();
}
},pagePath);
ble.addDisposeCallback(res => {
console.log("处理蓝牙断开连接");
these.device.linkStatu = false;
if (these.device.deviceId == res.deviceId) {
showLoading(these, {
text: '蓝牙已断开,正在重连'
});
these.reLinkdevice();
}
},pagePath);
ble.addReceiveCallback((receive, f, path) => {
console.log("收到设备消息,", receive);
if (these.device.deviceId == receive.deviceId) {
console.log("11111:",receive);
these.device.imei=f.imei;
console.log("11111:", receive);
these.device.imei = f.imei;
if (receive.bytes[0] == 0xFC || receive.str.indexOf('mac address:') == 0) {
if (f && f.macAddress) {
these.device.macAddress = f.macAddress;
console.log("222222");
these.Statu.isSearch=false;
console.log("222222");
these.Statu.isSearch = false;
these.initDevice();
}
}
@ -157,19 +190,41 @@
}
})
let inteval = setInterval(this.initDevice, 10000);
let inteval = setInterval(this.initDevice, 10000);
},
methods: {
reLinkdevice() {
ble.LinkBlue(these.device.deviceId).then(res => {
updateLoading(these, {
text: '连接成功'
});
these.device.linkStatu = true;
setTimeout(() => {
hideLoading(these);
}, 2000);
}).catch(ex => {
updateLoading(these, {
text: ex.msg
});
setTimeout(() => {
hideLoading(these);
}, 2000);
});
},
initDevice: function() {
if(!these.device.macAddress){
if (!these.device.macAddress) {
return;
}
//无效的设备回调
let deviceInvalid = () => {
these.$set(these.device, "deviceName", "");
}
clearTimeout(this.Statu.timeInteval);
this.Statu.timeInteval = setTimeout(() => {
this.Statu.isSearch=true;
this.Statu.isSearch = true;
showLoading(these, {
text: '正在获取设备信息'
});
@ -181,45 +236,34 @@
deviceMac: these.device.macAddress
}
}).then(res => {
console.log("获取设备信息", res);
if (res && res.code == 200) {
console.log("res=", res);
let data = res.data;
this.serverDevice=data;
this.serverDevice = data;
if (data) {
let keys = Object.keys(data);
ble.data.LinkedList.find((v) => {
if (v.deviceId == these.device.deviceId) {
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
// if(!v.device){
// v.device={};
// }
// v.device[key] = data[key];
// console.log("key="+key);
// console.log("value="+data[key]);
let key = keys[i];
these.$set(these.device, key, data[key]);
}
// ble.setBleData();
}
});
// console.log("device=", these.device);
// console.log("LinkedList=", ble.data.LinkedList);
} else {
deviceInvalid();
}
} else {
deviceInvalid();
}
}).catch((ex) => {
console.error("获取设备出现异常:", ex);
}).finally(() => {
this.Statu.timeInteval=null;
this.Statu.isSearch=false;
this.Statu.timeInteval = null;
this.Statu.isSearch = false;
hideLoading(these);
});
@ -242,7 +286,7 @@
these.Statu.boundRemark = "设备上报Mac地址异常";
return;
}
if(!this.device.deviceName){
if (!this.device.deviceName) {
these.Statu.bound = false;
these.Statu.boundRemark = "设备未入库";
return;
@ -267,26 +311,26 @@
if (res.code == 200) {
these.Statu.bound = true;
these.Statu.boundRemark = "设备绑定成功!";
let data=these.serverDevice;
let data = these.serverDevice;
let keys = Object.keys(data);
ble.data.LinkedList.find((v) => {
if (v.deviceId == these.device.deviceId) {
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
if(!v.device){
v.device={};
if (!v.device) {
v.device = {};
}
v.device[key] = data[key];
v.device[key] = data[key];
}
ble.updateCache();
ble.updateCache();
}
});
ble.removeReceiveCallback(pagePath);
clearTimeout(this.Statu.timeInteval);
this.device.macAddress=null;
this.Statu.timeInteval=null;
this.device.macAddress = null;
this.Statu.timeInteval = null;
uni.$emit("refreshDeviceList");
setTimeout(() => {
uni.switchTab({
@ -300,7 +344,7 @@
}).catch((ex) => {
these.Statu.bound = false;
these.Statu.boundRemark = '出现了未知的异常,操作失败';
console.log("ex=",ex);
console.log("ex=", ex);
}).finally(() => {
hideLoading(this);
});

View File

@ -32,7 +32,9 @@
</view>
<view class="centertxt ">
<view class="name" v-text="item.name"></view>
<view class="id" v-text="item.deviceId"></view>
<view class="id">
<text>信号:{{110+item.RSSI>100?100:110+item.RSSI}}%</text>
</view>
</view>
<view class="rightIco center">
<image src="/static/images/BLEAdd/linked.png" class="img" mode="aspectFit">
@ -63,7 +65,7 @@
</view>
<view class="id">
<text>信号强度:{{110+item.RSSI>100?100:110+item.RSSI}}%</text>
<text>信号:{{110+item.RSSI>100?100:110+item.RSSI}}%</text>
</view>
</view>
@ -116,6 +118,7 @@
data() {
return {
Status: {
isPageHidden: false,
intval: null,
time: null,
BottomMenu: {
@ -156,13 +159,14 @@
},
onHide: function() {
this.Status.isPageHidden = true;
ble.StopSearch();
},
onUnload() {
ble.StopSearch();
ble.removeDeviceFound(pagePath);
ble.removeReceiveCallback(pagePath);
ble.removeAllCallback(pagePath);
},
onLoad(option) {
let search = option.search;
@ -203,14 +207,86 @@
let StartSubsrib = () => {
these.EquipMents=[];
these.EquipMents = [];
ble = bleTool.getBleTool();
//蓝牙不可用的回调
ble.addStateBreakCallback(res=>{
if (these.Status.isPageHidden) {
return;
}
console.log("处理蓝牙不可用");
hideLoading(these);
these.PairEquip=[];
these.EquipMents=[];
uni.showToast({
icon:'fail',
title:'蓝牙已不可用'
});
these.showOpenSetting();
},pagePath);
//蓝牙再次可用的回调
ble.addStateRecoveryCallback(res=>{
if (these.Status.isPageHidden) {
return;
}
uni.showToast({
icon:'success',
title:'蓝牙恢复可用'
});
these.Status.BottomMenu.show = false;
these.EquipMents=[];
these.refreshBleList();
},pagePath);
//蓝牙断开连接的回调
ble.addDisposeCallback(res => {
if (these.Status.isPageHidden) {
return;
}
console.log("处理蓝牙断开连接");
hideLoading(these);
these.PairEquip.find(function(v, ind) {
these.PairEquip.splice(ind, 1);
return v.deviceId == res.deviceId;
});
}, pagePath);
//蓝牙连接已恢复的回调
ble.addRecoveryCallback(res => {
if (these.Status.isPageHidden) {
return;
}
// hideLoading(these);
these.EquipMents.find(function(v, ind) {
if (v.deviceId == res.deviceId) {
these.PairEquip.push(v);
return true;
}
return false;
});
if (these.device) {
clearInterval(this.Status.intval);
showLoading(these, {
text: '蓝牙连接已恢复,正在验证设备'
});
setTimeout(() => {
these.DeviceVerdict(res.deviceId);
}, 0);
} else {
hideLoading(these);
}
}, pagePath);
//搜索到新设备的回调
ble.addDeviceFound((arr) => {
if (these.Status.isPageHidden) {
return;
}
arr = arr.devices;
for (var i = 0; i < arr.length; i++) {
@ -246,8 +322,11 @@
}
console.log("EquipMents=", these.EquipMents)
}, pagePath);
//收到设备的消息回调
ble.addReceiveCallback((receivData, f, path, arr) => {
if (these.Status.isPageHidden) {
return;
}
if (f.macAddress && these.device) {
clearInterval(this.Status.intval);
this.Status.intval = null;
@ -265,6 +344,7 @@
}, pagePath);
}
if (search) {
@ -281,6 +361,7 @@
},
onShow: function() {
this.Status.isPageHidden = false;
this.refreshBleList();
},
methods: {
@ -288,26 +369,37 @@
if (!ble) {
return;
}
let promis = [];
for (let index = 0; index < this.PairEquip.length; index++) {
let item = this.PairEquip[index];
promis.push(ble.disconnectDevice(item.deviceId));
ble.StopSearch().then(res => {
// console.log("停止搜索成功");
this.EquipMents = [];
ble.StartSearch().then(result => {
// console.log("开始搜索成功");
}).catch(err => {
console.error("开始搜索失败,err=", err);
if(err.code===10001){
these.showOpenSetting();
}else{
uni.showModal({
title:'提示',
content:'出现异常:'+err.msg
});
}
}
Promise.allSettled(promis).finally(() => {
ble.StopSearch().then(res => {
// console.log("停止搜索成功");
these.EquipMents = [];
these.PairEquip = [];
ble.StartSearch().then(result => {
// console.log("开始搜索成功");
}).catch(err => {
console.error("开始搜索失败,err=", err);
if (err.code === 10001) {
these.showOpenSetting();
} else {
uni.showModal({
title: '提示',
content: '出现异常:' + err.msg
});
}
});
}).catch(ex => {
console.error("ex=", ex);
});
}).catch(ex => {
console.error("ex=", ex);
});
},
isItemLink: function(item, index) {
let src = '/static/images/BLEAdd/noLink.png';
@ -348,15 +440,16 @@
});
let removeLink = () => {
ble.subScribe(deviceId, false); //取消订阅消息
ble.DropDevice(deviceId); //从缓存中删除该设备
ble.disconnectDevice(deviceId); //断开与该设备的连接
ble.DropDevice(deviceId, null); //从缓存中删除该设备并断开连接
these.device.deviceMac = "";
let index = this.PairEquip.findIndex(function(v) {
let index = these.PairEquip.findIndex(function(v) {
return v.deviceId == deviceId;
});
if (index > -1) {
this.PairEquip.splice(index, 1);
}
}
console.log("f=", f);
@ -372,24 +465,30 @@
hideLoading(these);
}, 1000)
return;
}
} else {
}
hideLoading(these);
ble.updateCache();
uni.navigateBack();
return true;
} else {
this.Status.time = 30;
showLoading(these, {
text: "等待设备上报Mac地址," + these.Status.time + 's'
});
console.log("11111111", this.Status.time);
clearInterval(this.Status.intval);
this.Status.intval = null;
this.Status.intval = setInterval(() => {
this.Status.time = this.Status.time - 1;
if (this.Status.time < 0) {
console.log("停止倒计时", this.Status.time);
clearInterval(this.Status.intval)
this.Status.intval = null;
this.Status.time = null;
@ -408,15 +507,14 @@
setTimeout(() => {
hideLoading(these)
}, 1000);
}, 1500);
}
return;
}
updateLoading(these, {
updateLoading(these, {
text: "等待设备上报Mac地址," + these.Status.time + 's'
});
}, 1000);
return undefined;
}
@ -617,22 +715,24 @@
}
@keyframes expand {
0% {
width: 0;
height: 0;
opacity: 0.8;
}
80% {
width: 18.75rem;
height: 18.75rem;
opacity: 0.2;
}
100% {
width: 0.5rem;
height: 0.5rem;
opacity: 0.5;
}
0% {
width: 0;
height: 0;
opacity: 0.8;
}
80% {
width: 18.75rem;
height: 18.75rem;
opacity: 0.2;
}
100% {
width: 0.5rem;
height: 0.5rem;
opacity: 0.5;
}
}
.mainContent {

View File

@ -458,7 +458,7 @@
}
console.log("111111",this.deviceId);
console.log("ble==null,",ble)
ble && ble.DropDevice(this.deviceId.id);
ble && ble.DropDevice(null,this.deviceId.id);
} else {
uni.showToast({
title: res.msg,

View File

@ -84,6 +84,7 @@
}
},
onLoad() {
this.phone= uni.getStorageSync('phone');
if (uni.getStorageSync("token") && uni.getStorageSync("clientID")) { //免登陆
let time = uni.getStorageSync("tokenTime");
if (!time) {
@ -101,7 +102,7 @@
uni.removeStorageSync("token")
uni.removeStorageSync("clientID")
uni.removeStorageSync("tokenTime")
this.phone= uni.getStorageInfoSync('phone');
}
}

View File

@ -22,7 +22,7 @@
<text class="title">隐私协议</text>
<uni-icons type="right" size="25" color="rgba(255, 255, 255, 0.4)" class="uniIcon"></uni-icons>
</view>
<view class="menu-item" @click="gotoAppStore()">
<view class="menu-item" @click="gotoAppStore()" v-if="appVersion?true:false">
<image src="/static/images/common/ver.png" class="icon"></image>
<text class="title">版本更新 ({{appVersion}})</text>
<uni-icons type="right" size="25" color="rgba(255, 255, 255, 0.4)" class="uniIcon"></uni-icons>
@ -120,7 +120,7 @@
// 确定
handleAgree() {
// 退出登录
Logout().then((res) => {
Logout().finally((res) => {
this.showAgreement = false
uni.showTabBar()
// 1. 清除本地存储的 token

View File

@ -17,18 +17,18 @@ const serviceDic = [ //合作供应商的蓝牙主服务
class BleHelper {
constructor() {
this.StorageKey = "linkedDevices";
this.dropKey = "DeletedDevices";
recei = receivTool.getBleReceive();
this.init();
}
init() {
let key = this.StorageKey;
var store = uni.getStorageInfoSync();
var f = store.keys.includes(key);
var f = store.keys.includes(this.StorageKey);
var linkedDevices = [];
if (f) {
linkedDevices = uni.getStorageSync(key);
linkedDevices = uni.getStorageSync(this.StorageKey);
}
if (linkedDevices && linkedDevices.length && linkedDevices.length > 0) {
// console.log("111111", linkedDevices);
@ -39,11 +39,7 @@ class BleHelper {
});
}
var deletedEqs = [];
f = store.keys.includes(this.dropKey);
if (f) {
deletedEqs = uni.getStorageSync(this.dropKey);
}
setTimeout(() => {
this.OpenBlue().then(() => {
@ -57,12 +53,16 @@ class BleHelper {
discovering: false, //蓝牙是否正在搜索
searchList: [], //已搜索到的设备列表,
isSubscribe: false, //是否开启了订阅
LinkedList: linkedDevices, //已连接的设备列表
deletedEqs: deletedEqs
LinkedList: linkedDevices //已连接的设备列表
}
this.cfg = {
onDeviceFound: [], //发现新设备的事件
receivDataCallback: [] //接收到数据的事件
receivDataCallback: [], //接收到数据的事件
bleDisposeCallback: [], //蓝牙断开连接的事件
recoveryCallback: [], //蓝牙连接恢复的事件
stateRecoveryCallback: [], //蓝牙适配器恢复可用事件
stateBreakCallback: [] //蓝牙适配器不可用事件
}
// this.addReceiveCallback((a, b, c) => {
// recei.ReceiveData(a, b, c);
@ -131,45 +131,28 @@ class BleHelper {
DropDevice(bleId, deviceId) {
let flag = false;
let delItem=null;
if (!this.data.deletedEqs || !this.data.deletedEqs.length) {
this.data.deletedEqs = [];
}
for (var i = 0; i < this.data.LinkedList.length; i++) {
let item = this.data.LinkedList[i];
if (bleId && item.device) {
if (item.device.id == bleId) {
// console.log("找到要删除的设备", item);
if (deviceId && item.device) {
if (item.device.id == deviceId) {
console.log("找到要删除的设备", item);
this.data.LinkedList.splice(i, 1);
this.disconnectDevice(item.deviceId);
flag = true;
delItem=item;
break;
}
} else {
if (deviceId && item.deviceId == deviceId) {
// console.log("找到要删除的设备1,", item)
if (bleId && item.deviceId == bleId) {
console.log("找到要删除的设备1,", item)
this.data.LinkedList.splice(i, 1);
this.disconnectDevice(item.deviceId);
flag = true;
delItem=item;
break;
}
}
}
if (flag) {
this.data.deletedEqs=this.data.deletedEqs.filter(v => {
return v.deviceId != delItem.deviceId;
});
this.data.deletedEqs.push(delItem);
this.updateCache();
}
@ -177,11 +160,11 @@ class BleHelper {
//更新缓存
updateCache() {
// console.log("this.StorageKey=", this.StorageKey)
uni.setStorageSync(this.StorageKey, this.data.LinkedList);
uni.setStorageSync(this.dropKey, this.data.deletedEqs);
}
uni.setStorageSync(this.StorageKey, this.data.LinkedList);
}
//连接所有已连接过的设备
linkAllDevices() {
// console.log("模块启动时,自动连接已连接过的设备", this.data.LinkedList);
@ -205,7 +188,7 @@ class BleHelper {
this.updateCache();
}
}
//获取当前页面栈
getCurrentPagePath() {
const pages = getCurrentPages();
@ -218,93 +201,128 @@ class BleHelper {
// console.log("currentPage=", currentPage.route);
return currentPage.route;
}
//设置发现新设备的回调
addDeviceFound(callback, currKey) {
//添加事件回调
addCallback(callback, currKey, type) {
if (!type) {
return;
}
let key = currKey ? currKey : this.getCurrentPagePath();
if (!key) {
key = new Date().getTime();
}
if (key) {
// console.log("key=" + key);
let f = this.cfg.onDeviceFound.findIndex((v) => {
let f = this.cfg[type].findIndex((v) => {
return v.key == key;
});
if (f > -1) {
this.cfg.onDeviceFound[f].callback = callback;
this.cfg[type][f].callback = callback;
return;
}
this.cfg.onDeviceFound.push({
this.cfg[type].push({
key: key,
callback: callback
});
}
}
//移除事件回调
removeCallback(currKey, type) {
if (!type) {
return;
}
let key = currKey ? currKey : this.getCurrentPagePath();
if (key) {
// console.log("key=" + key);
let f = this.cfg[type].findIndex((v) => {
return v.key == key;
});
if (f > -1) {
this.cfg[type].splice(f, 1);
}
} else {
if (this.cfg[type].length > 0) {
this.cfg[type].splice(this.cfg[type].length - 1, 1);
}
}
}
//设置蓝牙恢复连接的回调
addRecoveryCallback(callback, currKey) {
this.addCallback(callback, currKey, 'recoveryCallback');
}
//移除蓝牙恢复连接的回调
removeRecoveryCallback(currKey) {
this.removeCallback(currKey, 'recoveryCallback');
}
//设置蓝牙断开连接的回调
addDisposeCallback(callback, currKey) {
this.addCallback(callback, currKey, 'bleDisposeCallback');
}
//移除蓝牙断开连接的回调
removeDisposeCallback(currKey) {
this.removeCallback(currKey, 'bleDisposeCallback');
}
//设置发现新设备的回调
addDeviceFound(callback, currKey) {
this.addCallback(callback, currKey, 'onDeviceFound');
}
//移除发现新设备的回调
removeDeviceFound(currKey) {
let key = currKey ? currKey : this.getCurrentPagePath();
if (key) {
// console.log("key=" + key);
let f = this.cfg.onDeviceFound.findIndex((v) => {
return v.key == key;
});
if (f > -1) {
this.cfg.onDeviceFound.splice(f, 1);
}
} else {
if (this.cfg.onDeviceFound.length > 0) {
this.cfg.onDeviceFound.splice(this.cfg.onDeviceFound.length - 1, 1);
}
}
this.removeCallback(currKey, 'onDeviceFound');
}
//添加接收到数据的回调
addReceiveCallback(callback, currKey) {
let key = currKey ? currKey : this.getCurrentPagePath();
if (!key) {
key = new Date().getTime();
}
if (key) {
// console.log("订阅消息回调,key=" + key);
let f = this.cfg.receivDataCallback.findIndex((v) => {
return v.key == key;
});
if (f > -1) {
this.cfg.receivDataCallback.callback = callback;
return;
}
this.cfg.receivDataCallback.push({
key: key,
callback: callback
});
}
this.addCallback(callback, currKey, 'receivDataCallback');
}
//设置接收到数据的回调
//移除接收到数据的回调
removeReceiveCallback(currKey) {
let key = currKey ? currKey : this.getCurrentPagePath();
if (key) {
// console.log("移除消息回调:" + key);
let f = this.cfg.receivDataCallback.findIndex((v) => {
return v.key == key;
});
if (f > -1) {
this.cfg.receivDataCallback.splice(f, 1);
}
} else {
if (this.cfg.receivDataCallback.length > 0) {
this.cfg.receivDataCallback.splice(this.cfg.receivDataCallback.length - 1, 1);
}
}
this.removeCallback(currKey, 'receivDataCallback');
}
//添加蓝牙不可用的回调
addStateBreakCallback(callback, currKey) {
this.addCallback(callback, currKey, 'stateBreakCallback');
}
//移除蓝牙不可用的回调
removeStateBreakCallback(currKey) {
this.removeCallback(currKey, 'stateBreakCallback');
}
//设置蓝牙适配器恢复可用的回调
addStateRecoveryCallback(callback, currKey) {
this.addCallback(callback, currKey, 'stateRecoveryCallback');
}
//移除蓝牙适配器恢复的回调
removeStateRecoveryCallback(currKey) {
this.removeCallback(currKey, 'stateRecoveryCallback');
}
//清除所有事件回调
removeAllCallback(currKey) {
this.removeDeviceFound(currKey)
this.removeDisposeCallback(currKey);
this.removeReceiveCallback(currKey);
this.removeRecoveryCallback(currKey);
this.removeStateRecoveryCallback(currKey);
this.removeStateBreakCallback(currKey);
}
getError(ex) {
@ -453,7 +471,7 @@ class BleHelper {
uni.openBluetoothAdapter({
success: (args) => {
// console.log("蓝牙初始化成功:" + JSON.stringify(args));
// console.log("蓝牙初始化成功:" + JSON.stringify(args));
this.data.isOpenBlue = true;
this.data.available = true;
resolve(true);
@ -461,9 +479,12 @@ class BleHelper {
if (this.data.isSubscribe) { //整个App生命周期只订阅一次
return;
}
console.log("开始订阅各类变化消息");
console.log("开始订阅各类变化消息");
this.data.isSubscribe = true;
// 保存每个设备的连接状态
let bleDeviceStates = {};
var bytesToHexString = (bytes) => {
return bytes.map(byte => byte.toString(16).padStart(2,
@ -471,77 +492,159 @@ class BleHelper {
}
uni.onBluetoothAdapterStateChange((state) => {
console.log('蓝牙状态发生变化:' + JSON.stringify(state));
// console.log('蓝牙状态发生变化:' + JSON.stringify(state));
if (this.data.available !== state.available) {
this.data.available = state.available;
this.data.discovering = state.discovering;
if (this.data.available && this.data
.isOpenBlue) { //蓝牙状态再次可用,重连所有设备
// this.linkAllDevices();
if (this.cfg.stateRecoveryCallback.length > 0) {
this.cfg.stateRecoveryCallback.forEach(
c => {
try {
c.callback();
} catch (error) {
console.error(
"蓝牙适配器已恢复,但回调函数发生错误",
error);
}
})
}
}
}
if (!state.available) { //蓝牙状态不可用了,将所有设备标记为断开连接
this.data.LinkedList.filter((v) => {
v.Linked = false;
v.notifyState = false;
return true;
});
let keys = Object.keys(bleDeviceStates)
keys.filter(v => {
bleDeviceStates[v] = false;
});
this.cfg.stateBreakCallback.forEach(f => {
try {
f.callback();
} catch (error) {
console.error("蓝牙状态不可用了,执行回调异常",
error)
}
})
this.updateCache();
}
});
uni.onBLEConnectionStateChange((res) => {
console.log("蓝牙连接状态变化了", res);
// 检查状态是否真的发生了变化
if (bleDeviceStates[res.deviceId] === res.connected) {
console.error('专业给Uniapp填坑,连接状态');
return;
}
if (!res.connected) {
// 更新状态记录
bleDeviceStates[res.deviceId] = res.connected;
console.error("蓝牙适配器已不可用", res);
let f = this.data.LinkedList.find((v) => {
if (v.deviceId == res.deviceId) {
v.Linked = false;
v.notifyState = false;
return true;
setTimeout(() => {
if (!res.connected) {
console.error("蓝牙已断开", res);
let f = this.data.LinkedList.find((
v) => {
if (v.deviceId == res
.deviceId) {
v.Linked = false;
v.notifyState = false;
return true;
}
return false;
});
this.updateCache();
if (f && f.device && f.device.id) {
console.log("尝试5次恢复连接,", f
.deviceId);
this.LinkBlue(res.deviceId, f
.writeServiceId, f
.wirteCharactId, f
.notifyCharactId, 5);
}
if (this.cfg.bleDisposeCallback.length >
0) {
this.cfg.bleDisposeCallback.forEach(
(c) => {
try {
c.callback(res);
} catch (error) {
console.error(
"执行蓝牙断开连接的回调出现异常,",
error)
}
});
}
} else {
console.log("蓝牙连接已恢复,", res);
if (this.cfg.recoveryCallback.length >
0) {
this.cfg.recoveryCallback.forEach((
c) => {
try {
c.callback(res);
} catch (error) {
console.error(
"执行蓝牙恢复连接的回调出现异常,",
error)
}
});
}
return false;
});
this.updateCache();
if (f.device && f.device.id) {
console.log("尝试5次恢复连接,", f.deviceId);
this.LinkBlue(res.deviceId, f.writeServiceId, f
.wirteCharactId, f.notifyCharactId, 5)
}
} else {
console.log("蓝牙适配器已恢复,", res);
}
}, 0);
});
uni.onBluetoothDeviceFound((res) => {
// console.log("发现新设备:" + JSON.stringify(devices));
let arr=[];
let arr = [];
for (var i = 0; i < res.devices.length; i++) {
let item = res.devices[i];
let f=serviceDic.find(v=>{
return item.advertisServiceUUIDs.includes(v.serviceId);
let f = serviceDic.find(v => {
return item.advertisServiceUUIDs
.includes(v.serviceId);
});
if(f){
if (f) {
console.log("发现新设备:", item);
arr.push(item);
}
}
if(arr.length===0){
if (arr.length === 0) {
// console.error("发现了设备,但不是想要的设备", res);
return;
}
res.devices=arr;
res.devices = arr;
this.data.searchList = this.data.searchList.concat(
res);
if (this.cfg.onDeviceFound) {
if (this.cfg.onDeviceFound.length > 0) {
this.cfg.onDeviceFound.forEach((found) => {
found.callback(res);
try {
found.callback(res);
} catch (error) {
console.error("处理发现设备的回调出现异常,",
error);
}
});
}
@ -717,12 +820,12 @@ class BleHelper {
uni.closeBluetoothAdapter({
success: () => {
// console.log("蓝牙模块已关闭");
this.data.isOpenBlue = false;
},
fail: (ex) => {
console.error('无法关闭蓝牙模块:',ex);
console.error('无法关闭蓝牙模块:', ex);
ex = this.getError(ex);
////console.log(msg);
},
complete: () => {
resolve();
@ -795,7 +898,7 @@ class BleHelper {
//停止搜索
StopSearch() {
let p1= new Promise((resolve, reject) => {
let p1 = new Promise((resolve, reject) => {
uni.stopBluetoothDevicesDiscovery({
success: (res) => {
// console.log("停止搜索蓝牙设备成功");
@ -808,27 +911,28 @@ class BleHelper {
}
});
});
let p2 = new Promise((succ, err) => {
setTimeout(() => {
err({
code: -1
});
}, 50);
}, 100);
});
return new Promise((resolve,reject)=>{
Promise.race([p1,p2]).then(resolve).catch(ex=>{
return new Promise((resolve, reject) => {
Promise.race([p1, p2]).then(resolve).catch(ex => {
if (ex.code == -1) {
console.error('专业给Uniapp填坑,停止搜索');
resolve();
return;
}
reject(ex);
});
});
}
//获取已连接的设备
@ -932,6 +1036,7 @@ class BleHelper {
Promise.race([p1, p2]).then(succ).catch(ex => {
// console.error("异常了:",ex);
if (ex.code == -1) {
console.error('专业给Uniapp填坑,订阅成功');
succ();
return;
}
@ -1313,7 +1418,8 @@ class BleHelper {
resolve(true);
},
fail: () => {
console.error("mtu设置失败");
console.error(
"mtu设置失败");
resolve(
true
); // MTU设置失败不影响连接成功
@ -1328,7 +1434,8 @@ class BleHelper {
},
fail: (ex) => {
ex = this.getError(ex);
console.error("蓝牙" + deviceId + "连接失败" + JSON.stringify(ex));
console.error("蓝牙" + deviceId + "连接失败" + JSON.stringify(
ex));
// 连接超时后自动重试
if (ex.code === 10012 && retryCount < maxRetries) {
@ -1411,12 +1518,12 @@ class BleHelper {
uni.closeBLEConnection({
deviceId: id,
success: (res) => {
console.log("蓝牙连接已断开:" + id);
console.log("用户主动断开了蓝牙:" + id);
this.subScribe(id, false);
resolve();
},
fail: (ex) => {
console.error("无法断开蓝牙连接", ex);
reject(this.getError(ex));
}
});
@ -1540,6 +1647,7 @@ class BleHelper {
Promise.race([timeOut(ms), promise]).then(resolve).catch((ex) => {
// console.error("ex=", ex);
if (ex.code == -1) {
console.error('专业给Uniapp填坑,发送成功');
resolve(ex);
} else {
reject(ex);