import { BtCmd, CmdBase, CmdEarPhone, CmdRtc, // CmdRgb, CmdKwh, CmdKey, CmdVoice, CmdWeek } from './bt_cmd'; import { CmdEvent, EnumCmdEvent, EnumPlayStatus, EnumSupplier } from '../cmd_key_event'; import eventBus from '../../utils/eventBus' class BtParse { // 型号名称 // static mateX2 = "MW-Mate X(4G_WIFI)"; // static matePVX = "猫王音响·Mate_PVX"; // static matePVXL = "猫王音响·Mate_PVXL"; // 防止收到另外的消息 static isReceiveCmd = false; // 如果10ms内获取两个一模一样的就删除一个 static lastCmd = null; static lastTime = null; constructor() {} // 解析命令 static parseTLV(cmd) { BtCmd.printTLV(cmd, false); // todo 在线 // if (!PlayDevice.isOnline) { // return; // } // if (!BtParse.isReceiveCmd) { // return; // } if (cmd.length > 5) { // 指令类别 const type = cmd[6]; if (cmd.length < 9) { // 杰里、领芯的语音控制指令 BtParse._voiceCmd(cmd); } else { // cmd[7]为命令长度 // 命令类型 const value = cmd[8]; // 第二部分走杰理 if (type === CmdVoice.jlReceiveVoiceData) { BtParse._receiveRecordData(cmd); } // 查询版本号后校验设备 else if (type === CmdBase.queryVersion) { const version = CmdBase.parseVersion(value); eventBus.fire(CmdEvent.version({ version })); eventBus.fire(CmdEvent.getDeviceInfo()); } else if (BtParse._getDataHeader(cmd)) { // 控制指令 BtParse._controlCmd(cmd); } else { // console.log("收到不明指令:", cmd); const manufacturer = ""; // DeviceManager.instance.device?.manufacturer ?? ""; // 山景的语音判断 // if (manufacturer === EnumSupplier.shanJing) { // const sjCmd = cmd[4]; // if (sjCmd === CmdVoice.sjStartVoice) { // BtParse._startRecord(EnumSupplier.shanJing); // } else if (sjCmd === CmdVoice.sjStopVoice) { // BtParse._stopRecord(EnumSupplier.shanJing); // } // // 山景的都要走接收数据 // BtParse._receiveRecordData(cmd); // } else { // // b1耳机、领芯、杰里p2第二部分语音数据直接走这里 // BtParse._receiveRecordData(cmd); // } } } } } static _send(cmdEvent) { eventBus.fire(CmdEvent[cmdEvent]); } static _getDataHeader(cmd) { if (cmd.length < 4) { return false; } ["54", "44", "44", "48", "1", "9", "22", "1", "4"] const header = [0x54, 0x44, 0x44, 0x48]; let isCmd = cmd[0] === header[0] && cmd[1] === header[1] && cmd[2] === header[2] && cmd[3] === header[3]; // console.log("收到数据头:", cmd[0], header[0], cmd[1], header[1], cmd[2], header[2], cmd[3], header[3],); return isCmd; } // todo 暂时不要 static _voiceCmd(cmd) { const type = cmd[6]; console.log("收到语音指令:", cmd); // switch (type) { // // 杰理语音开始 // case CmdVoice.jlStartVoice: // BtParse._startRecord(EnumSupplier.jieLi); // break; // // 杰理结束 // case CmdVoice.jlStopVoice: // BtParse._stopRecord(EnumSupplier.jieLi); // break; // // 发给插件 // case CmdVoice.jlReceiveVoiceData: // console.log("发送杰里的p1语音:没有进来过,不走这里的,直接判断0x70 && jieLi"); // BtParse._receiveRecordData(cmd); // break; // // 领心语音开始 // case CmdVoice.lxStartVoice: // BtParse._startRecord(EnumSupplier.lingXin); // break; // // 领心语音结束 // case CmdVoice.lxStopVoice: // BtParse._stopRecord(EnumSupplier.lingXin); // break; // default: // console.log("发送语音:默认发送,不走这里", cmd); // break; // } } static async _startRecord(supplier) { console.log("StartVoice======语音开始", supplier); } static async _stopRecord(supplier) { console.log("stopRecord======语音结束", supplier); } // 杰理接收设备第二部分 发送给插件 static _receiveRecordData(cmd) { // todo 暂时不要 // RecordVoiceManager.sendDataToPlugin(cmd); } static async _controlCmd(cmd) { const type = cmd[6]; const value = cmd[8]; // mqttAddDebugCmd("收到蓝牙指令:" + cmd); // console.log("收到控制指令:", cmd, type) switch (type) { // 校验设备 case CmdBase.checkDeviceSuccess: case CmdBase.checkDevice: // [84, 68, 68, 72, 1, 17, 40, 9, 115, 109, 97, 114, 116, 95, 65, 50, 70] break; // 按键 短按、长按等 case CmdKey.type: // IOS的不要了 // if (DeviceUtil.isIOS) { // if (BtParse.lastCmd && JSON.stringify(BtParse.lastCmd) === JSON.stringify(cmd)) { // if (BtParse.lastTime) { // const curTime = TimeUtil.getCurrentMillis(); // if (curTime - BtParse.lastTime < 5) { // return; // } // } // } // BtParse.lastCmd = cmd; // BtParse.lastTime = TimeUtil.getCurrentMillis(); // } let t = 0; if (cmd.length > 9) { t = cmd[9]; } switch (t) { // 0x54 44 44 48 01 0a 21 02 01 02 // 54, 44, 44, 48, 1, a, 21, 2, 1(value), 2(type) // 上一曲 case CmdKey.previousSong: BtParse._send(EnumCmdEvent.previousSong); break; // 下一曲 case CmdKey.nextSong: BtParse._send(EnumCmdEvent.nextSong); break; // 上一频道 case CmdKey.previousChannel: BtParse._send(EnumCmdEvent.previousChannel); break; // 下一频道 case CmdKey.nextChannel: BtParse._send(EnumCmdEvent.nextChannel); break; // 0x02 2 case CmdKey.pressShort: // 1 下一个频道 if (value === CmdKey.next) { BtParse._send(EnumCmdEvent.nextChannel); } // 2 上一个频道 else if (value === CmdKey.previous) { BtParse._send(EnumCmdEvent.previousChannel); } // 3 单击下一个专辑 或者下一曲 else if (value === CmdKey.changeProgram) { // if (ProviderUtil.device.mDevice?.clientType === BtParse.mateX2) { // BtParse._send(EnumCmdEvent.nextAlbum); // } else { // BtParse._send(EnumCmdEvent.nextSong); // } } break; // 0x09 9 case CmdKey.pressDouble: // 1 双击下一曲 if (value === CmdKey.next) { BtParse._send(EnumCmdEvent.nextSong); } // 2 双击上一曲 else if (value === CmdKey.previous) { BtParse._send(EnumCmdEvent.previousSong); } // 3 单击上一专辑或者上一曲 else if (value === CmdKey.changeProgram) { // todo // if (ProviderUtil.device.mDevice?.clientType === BtParse.mateX2) { // BtParse._send(EnumCmdEvent.previousAlbum); // } else { // BtParse._send(EnumCmdEvent.previousSong); // } } break; // 0x08 8 case CmdKey.pressLong: if (value === CmdKey.previous) { console.log("快退"); BtParse._send(EnumCmdEvent.fastback); } else if (value === CmdKey.next) { console.log("快进"); BtParse._send(EnumCmdEvent.speed); } break; // 0x04 4 case CmdKey.pressLongUp: if (value === CmdKey.previous) { console.log("停止快退"); BtParse._send(EnumCmdEvent.stopFastback); } else if (value === CmdKey.next) { console.log("停止快进"); BtParse._send(EnumCmdEvent.stopSpeed); } else if (value === CmdKey.pressLongUp) { // [54, 44, 44, 48, 1, a, 21, 2, 4, 4] console.log("录音结束"); BtParse._send(EnumCmdEvent.stopRecord); } break; } BtHelper.instance.changeChannelCallBack(); break; // 音量 54 44 44 48 1 a 32 2 b 0 case CmdBase.queryVolume: // 手机最大音量 需要获取 const phoneMax = 15; // todo 音量 //await VolumeUtil.getMaxVolume(); const max = CmdBase.volumeMax; const d = phoneMax / max; const result = (d * value).toFixed(2); var trueVolume = parseFloat(result) ?? 0; console.log("trueVolume=====", max, "===", d, ",,,,", value, ",,,,", result, ",,,,", trueVolume); if (trueVolume > phoneMax) { trueVolume = phoneMax; } // 仅用于记录设备音量,播控页面显示用 eventBus.fire(CmdEvent.volume({ volume: trueVolume })); // if (DeviceUtil.isAndroid) { // const name = ""; // // todo // // DeviceManager.instance.name; // if (name === "猫王·霹雳唱机") { // // VolumeUtil.setVolume(trueVolume); // } // } break; // 查询电量 case CmdKwh.queryKwh: eventBus.fire(CmdEvent.battery({ kwh: value })); break; // 自动播放 54, 44, 44, 48, 1, 9, 24, 1, 1 case CmdBase.getAutoPlay: case CmdBase.setAutoPlay: setTimeout(() => { eventBus.fire(CmdEvent.playStatus({ playStatus: value === EnumOpen.open ? EnumPlayStatus.play : EnumPlayStatus.pause, })); }, 300); break; // 查询低电量设置 case CmdKwh.queryLowKwhWarningTone: eventBus.fire(CmdEvent.queryLowKwn({ kwh: value })); break; // 耳机电量 index0 :左耳机, index1:左耳机 ,index2: 充电盒。value: 0-9代表10-100% 获取不到用-1 // [54, 44, 44, 48, 1, b, b1, 3, 8, 8, 2] case CmdEarPhone.queryEarPhoneKwh: const rightKwh = cmd[9]; const boxKwh = cmd[10]; let kwh = 0; if (value > 0 && rightKwh > 0) { kwh = Math.min(value, rightKwh); } else { kwh = Math.max(value, rightKwh); } eventBus.fire(CmdEvent.batteryEarphone({ kwhLeft: value, kwhBox: boxKwh, kwhRight: rightKwh, kwh: kwh, })); break; // EQ [84, 68, 68, 72, 1, 18, 180, 10, 0, 0, 240, 237, 236, 0, 236, 0, 0, 0] // B5耳机获取EQ case CmdEarPhone.queryEQ: if (cmd.length > 15) { const result = cmd.slice(8, cmd.length); const list = result.map(element => parseInt(element, 16)); console.log("eq==============", list); eventBus.fire(CmdEvent.eqs({ eqs: list })); } break; // 低延迟 [54, 44, 44, 48, 1, a, b2, 2, 0, 2] case CmdEarPhone.queryLowDelayMode: const lowDelayMode = cmd[9]; eventBus.fire(CmdEvent.lowDelayMode({ lowDelayMode, lowDelayModeOpen: value })); break; // 耳机低电量 case CmdEarPhone.queryLowPower: const lowPowerOpen = cmd[8]; eventBus.fire(CmdEvent.lowPowerOpen({ lowPowerOpen })); break; // 查询唤醒闹钟 case CmdRtc.queryAlarm: const wakeSwitch = cmd[8]; if (cmd.length > 9) { const week = cmd[9]; const hour = cmd[10]; const minutes = cmd[11]; const wakeCycle = CmdWeek.cmd2Week(week); console.log("queryAlarm=====", wakeSwitch, "=", wakeCycle); eventBus.fire(CmdEvent.wake({ wakeSwitch, wakeCycle, wakeHour: hour, wakeMinutes: minutes, })); } break; // 查询自动休眠状态 case CmdRtc.querySleepAfterPlayPause: case CmdRtc.setSleepAfterPlayPause: { let hour = cmd[8] ?? 0; let minutes = cmd[9] ?? 0; var seconds = cmd[10] ?? 0; console.log("hour=====", hour, "minutes=====", minutes, "seconds=====", seconds) hour = hour > 24 ? 0 : hour; minutes = minutes > 60 ? 0 : minutes; seconds = seconds > 60 ? 0 : seconds; let allSeconds = hour * 3600 + minutes * 60 + seconds; // [84, 68, 68, 72, 1, 12, 90, 4, 0, 14, 0, 72] eventBus.fire(CmdEvent.pauseSleep({ pauseSleep: allSeconds })); } break; // 查询休眠 case CmdRtc.querySleep: const sleepSwitch = cmd[8]; const hour = cmd[9]; const minutes = cmd[10]; const leftHour = cmd[11]; const leftMinutes = cmd[12]; eventBus.fire(CmdEvent.sleep({ sleepSwitch, sleepHour: hour, sleepMinutes: minutes, })); break; // 开始录音 case CmdVoice.startVoice: console.log("没有意义的开始录音"); // _send(EnumCmdEvent.startRecord); break; // 查询 耳机手势 case CmdEarPhone.queryCtrlStatus: const singleC = cmd[8]; const doubleC = cmd[9]; const longC = cmd[10]; eventBus.fire(CmdEvent.ctrlStatus({ ctrlStatus: [singleC, doubleC, longC] })); break; case CmdBase.getMac: { var values = "" // [54:44:44:48:01:0D:35:90:9D:99:CF:34:5B:] for (let i = 7; i < cmd.length; i++) { values += cmd[i].toString(16); if (i != cmd.length - 1) { values += ":"; } } // let str = this.hexArrayToString(values); // getMac===== ?MV-SR1(4G_WIFI) // let device = getApp().globalData.mDeviceList[0] ?? {}; // device["mac"] = values; console.log("getMac=====", values) eventBus.fire(CmdEvent.btMac({ "btMac": values })); } // [84, 68, 68, 72, 1, 23, 53, 16, 77, 86, 45, 83, 82, 49, 40, 52, 71, 95, 87, 73, 70, 73, 41] break; case CmdBase.getClientType: { var values = [] for (let i = 8; i < cmd.length; i++) { values.push(cmd[i]); } let str = this.hexArrayToString(values); let device = getApp().globalData.mDeviceList[0] ?? {}; device["trueClientType"] = str; console.log("getClientType=====", device) eventBus.fire(CmdEvent.clientType(str)); } //  [84, 68, 68, 72, 1, 14, 49, 7, 228, 159, 128, 9, 224, 236] break; case CmdBase.getIsConnect: // [84, 68, 68, 72, 1, 10, 54, 2, 0, 1] let device = getApp().globalData.mDeviceList[0] ?? {}; device["isConnectMac"] = value; console.log("getIsConnect=====", device) break; case CmdBase.heiJiaoOta: // [54:44:44:48:01:0A:74:01:01:00] { let kind = cmd[9] eventBus.fire(CmdEvent.otaCmd({ value: value, kind: kind })); } break; case CmdBase.heijiaoBackImg: // 0x76 { let kind = cmd[9] eventBus.fire(CmdEvent.otaWifi({ value: value, kind: kind })); } break; case CmdBase.wallPaper: // [54:44:44:48:01:0A:78:01:01:00] { let kind = cmd[9] eventBus.fire(CmdEvent.wallpaper({ value: value, kind: kind })); } break; case CmdBase.wallPaperData: // [54:44:44:48:01:0A:78:01:01:00] { let kind = cmd[9] eventBus.fire(CmdEvent.wallPaperData({ value: value, kind: kind })); } break; case CmdBase.heiJiaoOtaData: //0x75 { let kind = cmd[9] eventBus.fire(CmdEvent.otaUrl({ value: value, kind: kind })); } break; case CmdBase.wallPaperMD5: //0x80 { let kind = cmd[9] eventBus.fire(CmdEvent.wallPaperMD5({ value: value, kind: kind })); } break; default: console.log("接收到语音:", cmd); // _receiveRecordData(cmd); break; } } static hexArrayToString(hexArray) { let str = ''; for (let i = 0; i < hexArray.length; i++) { const charCode = hexArray[i]; if (charCode >= 32 && charCode <= 126) { // 可打印的ASCII字符范围 str += String.fromCharCode(charCode); } else { str += '?'; // 替换为问号或其他符号 } } return str; } static ab2hex(buffer) { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(':'); } } // 导出类 module.exports = BtParse;