Files
APP/utils/BleReceive.js
2026-03-30 14:01:07 +08:00

956 lines
24 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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

import Common from '@/utils/Common.js'
import { parseBleData } from '@/api/100J/HBY100-J.js'
class BleReceive {
constructor() {
this.StorageKey = "linkedDevices";
this.HandlerMap = {
'/pages/6155/deviceDetail': this.Receive_6155.bind(this),
'/pages/6155/BJQ6155': this.Receive_6155_XH.bind(this),
'/pages/7305/BJQ7305': this.Receive_6155.bind(this),
'/pages/650/HBY650': this.Receive_650.bind(this),
'/pages/670/HBY670': this.Receive_670.bind(this),
'/pages/4877/BJQ4877': this.Receive_4877.bind(this),
'/pages/100/HBY100': this.Receive_100.bind(this),
'/pages/102/HBY102': this.Receive_102.bind(this),
'/pages/6170/deviceControl/index':this.Receive_6170.bind(this),
'/pages/100J/HBY100-J': this.Receive_100J.bind(this),
'/pages/6075J/BJQ6075J':this.Receive_6075.bind(this)
};
}
setBleFormData(data, f) {
if (data) {
let linkedList = uni.getStorageSync(this.StorageKey);
if (!linkedList) {
return;
}
linkedList.find((v) => {
if (f.deviceId == v.deviceId) {
let keys = Object.keys(data);
keys.forEach((key) => {
if (!v.formData) {
v.formData = {};
}
if (!f.formData) {
f.formData = {};
}
v.formData[key] = data[key];
f.formData[key] = data[key];
});
uni.setStorageSync(this.StorageKey, linkedList);
return true;
}
});
}
}
ReceiveData(receive, f, path, recArr) {
// 100J首页等场景 LinkedList 项可能未带齐 mac/device但语音分片上传依赖 parseBleData 消费 FB 05
const sid = receive && receive.serviceId ? String(receive.serviceId) : '';
const is100JAe30 = /ae30/i.test(sid);
const fReady = f && f.macAddress && f.device && f.device.id;
if (is100JAe30 && receive && receive.bytes && receive.bytes.length >= 3 && !fReady) {
try {
parseBleData(new Uint8Array(receive.bytes));
} catch (e) {
console.warn('[100J] ReceiveData 兜底解析失败', e);
}
return receive;
}
if (f && f.macAddress && f.device && f.device.id) {
let handler = null;
let keys = Object.keys(this.HandlerMap);
let devKey = f.device.detailPageUrl ? f.device.detailPageUrl.replace(/\//g, '').toLowerCase() : '';
for (let index = 0; index < keys.length; index++) {
let devKey = f.device.detailPageUrl ? f.device.detailPageUrl.replace(/\//g, "").toLowerCase() : '';
let key = keys[index].replace(/\//g, '').toLowerCase();
if (key == devKey) {
handler = this.HandlerMap[keys[index]];
break;
}
}
if (handler) {
let data = handler(receive, f, path, recArr);
this.setBleFormData(data, f);
return data;
} else {
console.error("已收到消息,但无指定处理程序, deviceUrl:", f.device.detailPageUrl, "可用handlers:", keys);
}
} else {
// 100J AE30 二进制帧在 f 不完整时已在上方 parseBleData此处不再误报「无法处理」
if (!is100JAe30) {
console.log("已收到该消息,但无法处理", receive, "f:", f);
}
}
return receive;
}
Receive_650(receive, f, path, recArr) {
console.log("通用程序正在处理650的数据", receive);
var parseData = () => {
let bytes = receive.bytes;
if (bytes[0] == 0x55) {
try {
let staticLevelByte = bytes[1];
let staticLevelText = '未知';
let modeCurr = "";
switch (staticLevelByte) {
case 0x65:
staticLevelText = '高档';
modeCurr = "hight";
break;
case 0x66:
staticLevelText = '中档';
modeCurr = "center";
break;
case 0x67:
staticLevelText = '低档';
modeCurr = "low";
break;
case 0x68:
staticLevelText = '前置';
modeCurr = "smalllow";
break;
case 0x64:
staticLevelText = '关闭';
modeCurr = "close";
break;
}
// 解析照明档位
let lightingLevelByte = bytes[2];
let lightingLevelText = lightingLevelByte === 0x6e ? '开启' : '关闭';
// 解析剩余照明时间(第三和第四字节,大端序)
let lightingTime = (bytes[3] << 8) | bytes[4];
let hours = Math.floor(lightingTime / 60);
let remainingMinutes = lightingTime % 60;
let xuhang = '0分';
// 处理不同情况的显示
if (hours === 0) {
xuhang = `${remainingMinutes}`;
} else if (remainingMinutes === 0) {
xuhang = `${hours}小时`;
} else {
xuhang = `${hours}小时${remainingMinutes}`;
}
// 解析剩余电量
let batteryLevelByte = bytes[5];
// 电量百分比范围检查
let batteryLevel = Math.max(0, Math.min(100, batteryLevelByte));
let iswarn = false;
let warn = bytes[6];
if (warn == 0x00) {
warn = '无预警';
} else if (warn == 0x01) {
warn = '弱预警';
} else if (warn == 0x02) {
iswarn = true;
warn = '中预警';
} else if (warn == 0x03) {
iswarn = true;
warn = '强预警';
} else if (warn == 0x04) {
iswarn = true;
warn = '非常强预警';
}
let formData = {};
formData.battary = batteryLevel;
formData.xuhang = xuhang;
formData.cMode = lightingLevelByte === 0x6e;
formData.modeCurr = modeCurr;
formData.warnLevel = warn;
formData.iswarn = iswarn;
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
if (iswarn) {
uni.showModal({
content: "'" + f.device.deviceName + "'环境存在漏电电源",
title: "警告",
success(res) {
if (res.confirm) {
if (f) {
uni.navigateTo({
url: f.detailPageUrl,
events: {
ack: function(data) {}
},
success: (res) => {
res.eventChannel.emit('detailData', {
data: f,
deviceType: '',
apiType: 'listA'
});
}
});
}
}
}
})
}
}
return formData;
} catch (error) {
return null;
}
}
if (receive.str) {
try {
let str = receive.str;
if (str.indexOf('mac address:') == 0) {
let formData = {};
formData.macAddress = str.split(':')[1];
return formData;
} else {
let receiveData = {
a: 1
};
try {
let json = JSON.parse(str);
if ("staBlue_picture" in json) {
//重发图片
console.log("收到重新发送图片的命令");
receiveData = json;
} else if ("staBlue_text" in json) {
//重发文本
console.log("收到重新发送文本的命令");
receiveData = json;
} else if ("staBlue_vidio" in json) {
//重发视频
console.log("收到重新发送视频的命令");
receiveData = json;
} else if ("staBlue" in json) {
if (json.staBlue == "finish") {
console.log("收到设备回复,全部传输完成");
receiveData = json;
}
} else {
receiveData = {};
console.log("无法解析该文本");
}
} catch (error) {
receiveData = {};
console.log("文本解析失败")
}
return receiveData;
}
return null;
} catch (ex) {
return null;
}
}
}
let data = parseData(receive.bytes);
console.log("data=", data);
return data;
}
Receive_670(receive, f, path, recArr) {
// console.log("pagh=", path);
var todo = (bytes) => {
console.log("todo", receive);
let receiveData = {};
if (bytes[0] == 0x55) {
try {
// console.log("todo");
// 跳过帧头(第一个字节),从第二个字节开始解析
let staticLevelByte = bytes[1];
let staticLevelText = '';
switch (staticLevelByte) {
case 0x65:
staticLevelText = 'hight';
break
case 0x66:
staticLevelText = 'center';
break
case 0x67:
staticLevelText = 'low';
break
case 0x64:
staticLevelText = 'close';
break
}
// console.log("todo");
// 解析照明档位
let lightingLevelByte = bytes[2];
let lightingLevelText = lightingLevelByte === 0x6d ? 'qiang' : lightingLevelByte === 0x6e ?
'ruo' : 'close';
// 解析剩余照明时间(第三和第四字节,小端序)
let lightingTime = (bytes[3] << 8) | bytes[4];
// 解析剩余电量 // 电量百分比范围检查
let batteryLevelByte = bytes[5];
let batteryLevel = Math.max(0, Math.min(100, batteryLevelByte));
// console.log("todo");
let warn = bytes[6];
if (warn == 0x00) {
warn = 'none';
} else if (warn == 0x01) {
warn = 'ruo';
} else if (warn == 0x02) {
warn = 'center';
} else if (warn == 0x03) {
warn = 'hight';
} else if (warn == 0x04) {
warn = 'veryhight';
}
let staticWarn = bytes[7] == 0x01; //静止报警
let fourGStrenth = bytes[8]; //4g信号强度
let sosTxt = bytes[9] == 0x00 ? 'close' : bytes[9] == 0x01 ? 'sg' : 'rb';
// console.log("todo");
receiveData.modeCurr = staticLevelText;
receiveData.lightCurr = lightingLevelText;
receiveData.xuhang = lightingTime;
receiveData.battary = batteryLevel;
receiveData.warnLevel = warn;
receiveData.staticWarn = staticWarn;
receiveData.fourGStrenth = fourGStrenth;
receiveData.SOS = sosTxt;
receiveData.qzwarn = sosTxt === 'sg';
console.log("recArr=", recArr);
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
let msgs = [];
if (receiveData.qzwarn) {
msgs.push("声光报警中");
}
if (staticWarn) { //有静止报警
msgs.push("静止报警中");
}
if (msgs.length > 0) {
msgs = "设备'" + f.device.deviceName + msgs.join(";");
uni.showModal({
title: "警告",
content: msgs,
showCancel: false
});
}
}
} catch (error) {
console.error('数据解析错误:', error);
}
// console.log("todo");
} else {
try {
let uint8Array = new Uint8Array(receive.value);
let str = '';
for (let i = 0; i < uint8Array.length; i++) {
// 将每个字节转换为对应的字符
str += String.fromCharCode(uint8Array[i]);
}
if (str.indexOf('mac address:') == 0) {
receiveData.macAddress = str.split(':').slice(1).join(":");
console.log('收到mac地址:', +this.receiveData.macAddress);
} else if (str.indexOf('imei:') == 0) {
receiveData.imei = str.split(':')[1];
console.log('收到IEMI:', +this.receiveData.macAddress);
} else if (str.indexOf('longitude:') == 0) {
receiveData.Lon = str.split(':')[1];
console.log('收到经度:', +this.receiveData.macAddress);
} else if (str.indexOf('latitude:') == 0) {
receiveData.Lat = str.split(':')[1];
console.log('收到纬度:', +this.receiveData.macAddress);
} else {
try {
// console.log("str=",str);
let json = JSON.parse(str);
if ("staBlue_picture" in json) {
//重发图片
console.log("收到重新发送图片的命令");
receiveData = json;
} else if ("staBlue_text" in json) {
//重发文本
console.log("收到重新发送文本的命令");
receiveData = json;
} else if ("staBlue_vidio" in json) {
//重发视频
console.log("收到重新发送视频的命令");
receiveData = json;
} else if ("staBlue" in json) {
if (json.staBlue == "finish") {
console.log("收到设备回复,全部传输完成");
receiveData = json;
}
} else {
receiveData = {};
console.log("无法解析该文本");
}
} catch (error) {
receiveData = {};
// console.log("文本解析失败",error)
}
}
} catch (ex) {
receiveData = {};
console.log('将数据转文本失败', ex);
}
}
return receiveData;
}
let data = todo(receive.bytes);
return data;
}
Receive_6155_XH(receive, f, path, recArr) {
let bytes = receive.bytes;
if (bytes[0] == 0xFB && bytes[1] == 0x64 && bytes.length >= 8) {
try {
let light = null;
let mode = null;
if (bytes[2] === 0x01 && bytes[3] === 0x00) {
light = 0;
mode = 'main';
} else if (bytes[2] === 0x02 && bytes[3] === 0x00) {
light = 1;
mode = 'main';
} else if (bytes[2] === 0x00 && bytes[3] === 0x01) {
light = 2;
mode = 'main';
} else if (bytes[2] === 0x03 && bytes[3] === 0x00) {
light = 0;
mode = 'fu';
} else if (bytes[2] === 0x04 && bytes[3] === 0x00) {
light = 1;
mode = 'fu';
}
if (bytes[2] === 0x05 && bytes[3] === 0x00) {
light = 3;
}
// 解析剩余电量
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 + "分钟";
let formData = {};
formData.mode = mode;
formData.light = light;
formData.battary = batteryLevel;
formData.statu = warn;
formData.xuhang = lightingTime;
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() === f.device.detailPageUrl.replace(/\//g,
'').toLowerCase();
});
if (!recCnt) {
if (batteryLevel <= 20) {
// 会弹出两个框,暂且注释掉这段代码
uni.showModal({
content: "设备'" + f.device.deviceName + "'电量低",
title: "提示"
});
}
}
return formData;
} catch (error) {
console.log('7305数据解析错误:', error);
return null;
}
}
return null;
}
Receive_6155(receive, f, path, recArr) {
let bytes = receive.bytes;
if (bytes[0] == 0xFB && bytes[1] == 0x64 && bytes.length >= 8) {
try {
let getName = function(type, ) {
let name = "";
switch (type) {
case 0x01:
// name = '强光';
name = 0;
break;
case 0x02:
// name = '弱光';
name = 1;
break;
case 0x03:
// name = '爆闪';
name = 2;
break;
case 0x04:
name = 0; //泛光
break;
case 0x0A:
name = 1; //强光&泛光
break;
default:
// name = '关闭';
name = null;
break;
}
return name;
}
let staticLevelText = getName(bytes[2]);
// 解析照明档位
let lightingLevelText = getName(bytes[3]);
// 解析剩余电量
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 + "分钟";
let formData = {};
formData.mode = (bytes[2] === 0x00 || bytes[2] === 0x0B) ? 'fu' : 'main';
formData.light = formData.mode == 'fu' ? lightingLevelText : staticLevelText;
formData.battary = batteryLevel;
formData.statu = warn;
formData.xuhang = lightingTime;
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() === f.device.detailPageUrl.replace(/\//g,
'').toLowerCase();
});
if (!recCnt) {
if (batteryLevel <= 20) {
// 会弹出两个框,暂且注释掉这段代码
uni.showModal({
content: "设备'" + f.device.deviceName + "'电量低",
title: "提示"
});
}
}
return formData;
} catch (error) {
console.log('7305数据解析错误:', error);
return null;
}
}
return null;
}
Receive_4877(receive, f, path, recArr) {
let receiveData = {};
try {
// console.log("str=",receive.str);
receiveData = JSON.parse(receive.str);
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
if (receiveData.sta_PowerPercent <= 20) {
uni.showModal({
title: "提示",
content: "设备'" + f.device.deviceName + "'电量低",
showCancel: false
});
}
}
} catch (error) {
receiveData = {};
console.log("文本解析失败", error)
}
return receiveData;
}
Receive_100(receive, f, path, recArr) {
let receiveData = {};
try {
// console.log("str=",receive.str);
receiveData = JSON.parse(receive.str);
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
if (receiveData.sta_battery <= 20) {
uni.showModal({
title: "提示",
content: "设备'" + f.device.deviceName + "'电量低",
showCancel: false
});
}
}
} catch (error) {
receiveData = {};
console.log("文本解析失败", error)
}
return receiveData;
}
Receive_100J(receive, f, path, recArr) {
let receiveData = {};
try {
if (!receive.bytes || receive.bytes.length < 3) return receiveData;
const parsed = parseBleData(receive.bytes);
if (!parsed) return receiveData;
if (parsed.longitude !== undefined) receiveData.longitude = parsed.longitude;
if (parsed.latitude !== undefined) receiveData.latitude = parsed.latitude;
if (parsed.batteryPercentage !== undefined) receiveData.batteryPercentage = parsed.batteryPercentage;
if (parsed.batteryRemainingTime !== undefined) receiveData.batteryRemainingTime = parsed.batteryRemainingTime;
} catch (e) {
console.log('[100J] BleReceive 解析失败', e);
}
return receiveData;
}
Receive_6170(receive, f, path, recArr) {
let receiveData = {};
try {
console.log("订阅消息者:", path);
console.log("设备收到消息:", f);
console.log("消息内容:", receive);
receiveData = JSON.parse(receive.str);
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
if (receiveData.sta_PowerPercent <= 20) {
uni.showModal({
title: "提示",
content: "设备'" + f.device.deviceName + "'电量低",
showCancel: false
});
}
}
} catch (error) {
receiveData = {};
console.error("文本解析失败", error)
}
return receiveData;
}
Receive_102(receive, f, path, recArr) {
let receiveData = {};
try {
console.log("订阅消息者:", path);
console.log("设备收到消息:", f);
console.log("消息内容:", receive);
receiveData = JSON.parse(receive.str);
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
if (receiveData.sta_PowerPercent <= 20) {
uni.showModal({
title: "提示",
content: "设备'" + f.device.deviceName + "'电量低",
showCancel: false
});
}
if (receiveData.sta_Intrusion === 1) {
uni.showModal({
title: "提示",
content: "闯入报警中",
showCancel: false
});
}
}
if (f.device && path === "pages/common/index") { //仅在首页订阅此操作
console.error("1111111111");
let linkKey = "102_" + f.device.id + "_linked";
let warnKey = "102_" + f.device.id + "_warning";
let time = new Date(); //Common.DateFormat(new Date(),'yyyy-MM-dd HH:mmss');
if (receiveData.sta_tomac) { //某个设备上线了
if (receiveData.sta_tomac.indexOf(':') == -1) {
receiveData.sta_tomac = receiveData.sta_tomac.replace(/(.{2})/g, '$1:').slice(0, -
1); //mac地址自动补:
}
uni.getStorageInfo({
success: function(res) {
let arr = [];
let linked = {
linkId: f.linkId,
read: false,
linkEqs: [{
linkTime: time,
linkMac: f.macAddress
}, {
linkTime: time,
linkMac: receiveData.sta_tomac
}]
};
if (res.keys.includes(linkKey)) {
arr = uni.getStorageSync(linkKey);
}
if (arr.length == 0) {
arr.unshift(linked);
} else {
let dev = arr.find(v => {
if (v.linkId == f.linkId) {
let vl = v.linkEqs.find(cvl => {
if(cvl.linkMac === receiveData.sta_tomac){
v.read=false;
cvl.linkTime=time;
return true;
}
return false;
});
if (!vl) {
v.linkEqs.push({
linkTime: time,
linkMac: receiveData.sta_tomac
});
}
return vl;
}
return false;
});
if (!dev) {
arr.unshift(linked);
}
}
console.error("某个设备上线了", arr)
uni.setStorage({
key: linkKey,
data: arr
});
}
});
}
let warnArrs = [];
let guid = Common.guid();
if (receiveData.sta_sosadd) { //某个设备闯入报警
console.error("某个设备闯入报警");
if (receiveData.sta_sosadd.indexOf(':') == -1) {
receiveData.sta_sosadd = receiveData.sta_sosadd.replace(/(.{2})/g, '$1:').slice(0, -
1); //mac地址自动补:
}
warnArrs.push({
linkId: f.linkId,
read: false,
key: guid,
warnType: "闯入报警",
warnMac: receiveData.sta_sosadd,
warnTime: time,
warnName: ""
});
}
if (receiveData.sta_LedType === 'led_alarm' || receiveData.ins_LedType === 'led_alarm') { //强制报警
console.error("强制报警了", f);
warnArrs.push({
linkId: f.linkId,
read: false,
key: guid,
warnType: "强制报警",
warnMac: f.macAddress,
warnTime: time,
warnName: ""
});
}
if (warnArrs.length > 0) {
uni.getStorageInfo({
success: function(res) {
let arr = [];
if (res.keys.includes(warnKey)) {
arr = uni.getStorageSync(warnKey);
arr = warnArrs.concat(arr);
} else {
arr = warnArrs
}
uni.setStorage({
key: warnKey,
data: arr
});
}
});
}
}
} catch (error) {
receiveData = {};
console.log("文本解析失败", error)
}
return receiveData;
}
Receive_6075(receive,f,path,recArr){
let receiveData = {};
try {
receiveData = JSON.parse(receive.str);
let recCnt = recArr.find(v => {
return v.key.replace(/\//g, "").toLowerCase() == f.device.detailPageUrl
.replace(/\//g, "").toLowerCase();
});
if (!recCnt) {
// if (receiveData.sta_PowerPercent <= 20) {
// uni.showModal({
// title: "提示",
// content: "设备'" + f.device.deviceName + "'电量低",
// showCancel: false
// });
// }
}
} catch (error) {
receiveData = {};
console.log("文本解析失败", error)
}
return receiveData;
}
}
let receiveInstance = null;
export default {
getBleReceive: function(found, receive) {
if (!receiveInstance) {
receiveInstance = new BleReceive();
}
return receiveInstance;
}
}