1
0
forked from dyf/APP

merge upstream

This commit is contained in:
2026-04-01 08:45:34 +08:00
4 changed files with 92 additions and 56 deletions

View File

@ -163,7 +163,12 @@ class HBY100JProtocol {
this.onNotifyCallback = callback;
}
parseBleData(buffer) {
/**
* @param {Uint8Array|ArrayBuffer} buffer
* @param {{ skipSideEffects?: boolean }} [options] skipSideEffects=true仅解析字段不打日志、不触发 onNotify/文件回调(供 BleReceive 与设备页 bleValueNotify 双订阅时避免重复)
*/
parseBleData(buffer, options = {}) {
const skipSideEffects = !!options.skipSideEffects;
const view = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
if (view.length < 3) return null;
@ -175,8 +180,10 @@ class HBY100JProtocol {
const macBytes = view.slice(1, 7);
const macAddress = Array.from(macBytes).map(b => b.toString(16).padStart(2, '0').toUpperCase()).join(':');
const result = { type: 'mac', macAddress };
console.log('[100J-蓝牙] 设备上报MAC:', macAddress, '原始:', Array.from(view).map(b => b.toString(16).padStart(2, '0').toUpperCase()).join(' '));
if (this.onNotifyCallback) this.onNotifyCallback(result);
if (!skipSideEffects) {
console.log('[100J-蓝牙] 设备上报MAC:', macAddress, '原始:', Array.from(view).map(b => b.toString(16).padStart(2, '0').toUpperCase()).join(' '));
if (this.onNotifyCallback) this.onNotifyCallback(result);
}
return result;
}
@ -206,15 +213,19 @@ class HBY100JProtocol {
// 05: 文件更新响应 FB 05 [fileType] [status] FFstatus: 1=成功 2=失败
if (data.length >= 1) result.fileType = data[0];
if (data.length >= 2) result.fileStatus = data[1]; // 1=Success, 2=Failure
if (this._fileResponseResolve) this._fileResponseResolve(result);
if (!skipSideEffects && this._fileResponseResolve) this._fileResponseResolve(result);
break;
case 0x04:
// 5.5 获取设备电源状态: 电池容量8B + 电压8B + 百分比1B + 车载电源1B + 续航时间2B(分钟)
// 5.5 获取设备电源状态: 容量8B + 电压8B + 百分比1B + 车载1B + 续航2B(分钟) + [充电状态1B] + FF
// 充电状态为固件新增,在续航之后;旧固件仅 20 字节 payload不影响 [16..19] 字段
if (data.length >= 20) {
result.batteryPercentage = data[16];
result.vehiclePower = data[17];
result.batteryRemainingTime = data[18] | (data[19] << 8); // 小端序,单位分钟
}
if (data.length >= 21) {
result.chargingStatus = data[20]; // 0未充电 1充电中 2已充满
}
break;
case 0x06:
// 06: 语音播报响应
@ -261,10 +272,11 @@ class HBY100JProtocol {
const funcNames = { 0x01: '复位', 0x02: '基础信息', 0x03: '位置', 0x04: '电源状态', 0x05: '文件更新', 0x06: '语音播报', 0x09: '音量', 0x0A: '爆闪模式', 0x0B: '爆闪频率', 0x0C: '强制报警', 0x0D: 'LED亮度', 0x0E: '工作方式' };
const name = funcNames[funcCode] || ('0x' + funcCode.toString(16));
console.log('[100J-蓝牙] 设备响应 FB:', name, '解析:', JSON.stringify(result), '原始:', hexStr);
if (this.onNotifyCallback) {
this.onNotifyCallback(result);
if (!skipSideEffects) {
console.log('[100J-蓝牙] 设备响应 FB:', name, '解析:', JSON.stringify(result), '原始:', hexStr);
if (this.onNotifyCallback) {
this.onNotifyCallback(result);
}
}
return result;
}
@ -879,9 +891,9 @@ export function cache100JVoiceFileForBle(deviceId, voiceListId, filePath) {
});
}
// 暴露给页面:解析蓝牙接收到的数据
export function parseBleData(buffer) {
return protocolInstance.parseBleData(buffer);
// 暴露给页面:解析蓝牙接收到的数据options 见类上 parseBleData 注释)
export function parseBleData(buffer, options) {
return protocolInstance.parseBleData(buffer, options);
}
// 暴露给页面:蓝牙连接后主动拉取电源状态(电量、续航)
@ -1121,37 +1133,47 @@ function execWithBleFirst(bleExec, httpExec, logName, onWaiting, opts = {}) {
} catch (e) {}
};
// 协议层认为已连:仍可能被系统蓝牙关闭/底层已断而滞后,先校验适配器,避免先发蓝牙卡超时再回退
if (protocolInstance.isBleConnected && protocolInstance.bleDeviceId) {
console.log('[100J] 语音上传:协议层已连接,执行蓝牙传文件');
return doBle().catch(onBleSendFail);
return getBleAdapterAvailable().then((adapterOk) => {
if (!adapterOk) {
protocolInstance.setBleConnectionStatus(false, '');
return go4GOrReject('系统蓝牙已关闭走4G');
}
console.log('[100J]', logName || '指令', '协议层已连接,走蓝牙');
return doBle().catch(onBleSendFail);
});
}
console.log('[100J] 语音上传:协议层未就绪,将等待重连或走 4G', { isBleConnected: protocolInstance.isBleConnected, hasBleDeviceId: !!protocolInstance.bleDeviceId });
// 无 bleDeviceId系统蓝牙关闭则立即 4G开启则短时等页面扫描连上不再白等 12s
console.log('[100J]', logName || '指令', '协议层未就绪', { isBleConnected: protocolInstance.isBleConnected, hasBleDeviceId: !!protocolInstance.bleDeviceId });
// 无 bleDeviceId本地仅蓝牙场景仍弹「请稍候」并等扫描;可走 4G 时不弹 loading、不白等 5s直接 4G
if (!protocolInstance.bleDeviceId) {
return getBleAdapterAvailable().then((adapterOk) => {
if (!adapterOk) {
protocolInstance.setBleConnectionStatus(false, '');
return go4GOrReject('系统蓝牙未开启走4G');
}
if (typeof onWaiting === 'function') onWaiting();
else showWaitUi('请稍候…');
return waitForBleConnection()
.then((connected) => {
return connected ? doBle().catch(onBleSendFail) : go4GOrReject('蓝牙未连接');
})
.finally(hideWaitUi);
if (no4G) {
if (typeof onWaiting === 'function') onWaiting();
else showWaitUi('请稍候…');
return waitForBleConnection()
.then((connected) => {
return connected ? doBle().catch(onBleSendFail) : go4GOrReject('蓝牙未连接');
})
.finally(hideWaitUi);
}
return waitForBleConnection(0, BLE_POLL_INTERVAL_MS).then((connected) =>
connected ? doBle().catch(onBleSendFail) : go4GOrReject('无蓝牙连接走4G')
);
});
}
// 有 bleDeviceId 但未连:系统蓝牙关则直接 4G否则短时重连
// 有 bleDeviceId 但未连:用户刚关蓝牙/超出范围时,不再弹「请稍候」等重连 ~2s双通道在线时直接 4G
return getBleAdapterAvailable().then((adapterOk) => {
if (!adapterOk) {
protocolInstance.setBleConnectionStatus(false, '');
return go4GOrReject('系统蓝牙未开启走4G');
}
if (typeof onWaiting !== 'function') showWaitUi('请稍候…');
return tryReconnectBle()
.then((reconnected) => {
return reconnected ? doBle().catch(onBleSendFail) : go4GOrReject('蓝牙未连接');
})
.finally(hideWaitUi);
console.log('[100J]', logName || '指令', '蓝牙已断开直接走4G不阻塞重连');
return go4GOrReject(null);
});
}

View File

@ -173,10 +173,10 @@
<view class="line"></view>
<view class="header paddingTop0">
<text class="sliderTxt">频率</text>
<text class="sliderVal">{{ formData.strobeFrequency }}HZ</text>
<text class="sliderVal">{{ strobeFrequencySlider }}HZ</text>
</view>
<view class="slider-container">
<slider min="1" max="10" step="1" :disabled="false" :value="formData.strobeFrequency"
<slider min="1" max="10" step="1" :disabled="false" :value="strobeFrequencySlider"
activeColor="#bbe600" backgroundColor="#686767" block-size="20" block-color="#ffffffde"
@change="onFreqChanging" @changing="onFreqChanging" class="custom-slider" />
</view>
@ -331,7 +331,7 @@
sta_VoiceType: '0',
volume: 10,
sta_LightType: '',
strobeFrequency: 0.5,
strobeFrequency: 1,
lightBrightness: 10,
sta_system: '',
warnTime: 0,
@ -552,8 +552,9 @@
// 设备按键, app同步
} else if (funcType == '14') {
// 调节亮度,音量,频率相关字段
these.formData.strobeFrequency = led_strobe.frequency ||
0.5; //频率
these.formData.strobeFrequency = these.normalizeStrobeFreq(
led_strobe.frequency != null ? led_strobe.frequency : 1
);
these.formData.volume = volume || 10; //音量
these.formData.lightBrightness = brightness.red ||
10; //亮度值
@ -693,6 +694,10 @@
this.$nextTick(() => this.sync100JBleUiFromHelper());
},
computed: {
/** 与 slider min/max(1~10) 对齐;离线未拉到详情时避免 0.5 等非法值导致滑块渲染飞出 */
strobeFrequencySlider() {
return this.normalizeStrobeFreq(this.formData.strobeFrequency);
},
getbleStatu() {
if (this.formData.bleStatu === true) {
return '已连接';
@ -711,6 +716,15 @@
},
methods: {
/** 警示灯频率 UIslider 为 1~10与协议 0~12 取交集 */
normalizeStrobeFreq(v) {
const n = Number(v);
if (!Number.isFinite(n)) return 1;
const r = Math.round(n);
if (r < 1) return 1;
if (r > 10) return 10;
return r;
},
/** 与 BleHelper 实际连接状态对齐(系统关蓝牙再开、从后台回前台等) */
sync100JBleUiFromHelper() {
const mac = (this.device && this.device.deviceMac) || (this.deviceInfo && this.deviceInfo.deviceMac);
@ -796,6 +810,7 @@
})
);
Object.assign(this.formData, validData);
that.formData.strobeFrequency = that.normalizeStrobeFreq(that.formData.strobeFrequency);
that.deviceInfo = res.data;
that.$nextTick(() => that.sync100JBleUiFromHelper && that.sync100JBleUiFromHelper());
const strobeEnable = res.data.strobeEnable ?? 0; // 0=关闭1=开启
@ -1368,6 +1383,9 @@
if (parsedData.batteryRemainingTime !== undefined) {
this.$set(this.deviceInfo, 'batteryRemainingTime', parsedData.batteryRemainingTime);
}
if (parsedData.chargingStatus !== undefined) {
this.$set(this.deviceInfo, 'chargingStatus', parsedData.chargingStatus);
}
@ -1417,15 +1435,17 @@
else if (this.formData.sta_VoiceType === '7') this.formData.sta_VoiceType = '-1';
}
if (parsedData.volume !== undefined) this.formData.volume = parsedData.volume;
if (parsedData.strobeFrequency !== undefined) this.formData.strobeFrequency = parsedData
.strobeFrequency;
if (parsedData.strobeFrequency !== undefined) {
this.formData.strobeFrequency = this.normalizeStrobeFreq(parsedData.strobeFrequency);
}
if (parsedData.redBrightness !== undefined) this.formData.lightBrightness = parsedData
.redBrightness;
}
// 0x09 音量、0x0D 亮度:单独响应时同步
if (fc === 0x09 && parsedData.volume !== undefined) this.formData.volume = parsedData.volume;
if (fc === 0x0B && parsedData.strobeFrequency !== undefined) this.formData.strobeFrequency = parsedData
.strobeFrequency;
if (fc === 0x0B && parsedData.strobeFrequency !== undefined) {
this.formData.strobeFrequency = this.normalizeStrobeFreq(parsedData.strobeFrequency);
}
if (fc === 0x0D && parsedData.redBrightness !== undefined) this.formData.lightBrightness = parsedData
.redBrightness;
},
@ -1932,6 +1952,9 @@
.slider-container {
padding: 0px;
width: 100%;
overflow: hidden;
box-sizing: border-box;
}
.addIco {

View File

@ -1728,28 +1728,18 @@ class BleHelper {
return linkDevice(deviceId);
}).then((res) => {
if (res) { //新连接
if (res) { //新连接(含 createBLEConnection 刚成功)
// console.log("11111111");
if (fIndex == -1) {
// console.log("开始获取服务", targetServiceId)
return this.getService(deviceId, targetServiceId, writeCharId,
notifyCharId); //获取服务
} else {
if (f.wirteCharactId && f.notifyCharactId) {
if (!f.notifyState) {
// console.log("开始订阅特征");
this.subScribe(deviceId, true);
} else {
console.log("不订阅消息");
}
return Promise.resolve(true);
} else {
console.log("开始获取服务", targetServiceId)
return this.getService(deviceId, targetServiceId, writeCharId,
notifyCharId);
}
// 设备已在 LinkedList例如缓存/重连):不能仅用缓存的 write/notify UUID 直接订阅。
// 重连后须先 getBLEDeviceServices否则部分机型 notifyBLECharacteristicValueChange 报 no service(10004)notify 收不到任何数据。
console.log("已缓存设备重新连接,重新发现服务并订阅", deviceId);
return this.getService(deviceId, targetServiceId, writeCharId,
notifyCharId);
}
} else { //已连接过,直接订阅消息
// console.log("11111111");

View File

@ -694,7 +694,8 @@ class BleReceive {
let receiveData = {};
try {
if (!receive.bytes || receive.bytes.length < 3) return receiveData;
const parsed = parseBleData(receive.bytes);
// 与 HBY100-J 页 bleValueNotify 共用 notify避免 parseBleData 执行两次重复日志、FB05 双次 resolve、onNotify 双次
const parsed = parseBleData(receive.bytes, { skipSideEffects: true });
if (!parsed) return receiveData;
if (parsed.longitude !== undefined) receiveData.longitude = parsed.longitude;
if (parsed.latitude !== undefined) receiveData.latitude = parsed.latitude;