|
@@ -0,0 +1,417 @@
|
|
|
+import { BtCmd } from './bt_cmd.js';
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+ // 解析命令
|
|
|
+ static async 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);
|
|
|
+ EventManager.fire(CmdEvent.version(version));
|
|
|
+ EventManager.fire(CmdEvent.getDeviceInfo());
|
|
|
+ } else if (BtParse._getDataHeader(cmd)) {
|
|
|
+ // 控制指令
|
|
|
+ BtParse._controlCmd(cmd);
|
|
|
+ } else {
|
|
|
+ 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) {
|
|
|
+ // todo
|
|
|
+ // EventManager.fire(CmdEvent[cmdEvent]);
|
|
|
+ }
|
|
|
+
|
|
|
+ static _getDataHeader(cmd) {
|
|
|
+ if (cmd.length < 4) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const header = [0x54, 0x44, 0x44, 0x48];
|
|
|
+ return cmd[0] === header[0] && cmd[1] === header[1] && cmd[2] === header[2] && cmd[3] === header[3];
|
|
|
+ }
|
|
|
+
|
|
|
+ // todo 暂时不要
|
|
|
+ // static _voiceCmd(cmd) {
|
|
|
+ // const type = cmd[6];
|
|
|
+
|
|
|
+ // 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);
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ // 校验设备
|
|
|
+ case CmdBase.checkDeviceSuccess:
|
|
|
+ // 设置100ms间隔,同时发会丢失指令
|
|
|
+ // DeviceManager.instance.setLowKwhWarningTone();
|
|
|
+ // DeviceManager.instance.queryLowKwhWarningTone();
|
|
|
+ // DeviceManager.instance.getAutoPlay();
|
|
|
+ // DeviceManager.instance.setTime();
|
|
|
+ // DeviceManager.instance.getDeviceInfo();
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 按键 短按、长按等
|
|
|
+ case CmdKey.type:
|
|
|
+ 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) {
|
|
|
+ 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 = await VolumeUtil.getMaxVolume();
|
|
|
+ const max = CmdBase.volumeMax;
|
|
|
+ const d = phoneMax / max;
|
|
|
+
|
|
|
+ const result = (d * value).toFixed(2);
|
|
|
+ const trueVolume = parseFloat(result);
|
|
|
+
|
|
|
+ console.log("trueVolume=====", max, "===", d, ",,,,", value, ",,,,", result, ",,,,", trueVolume);
|
|
|
+ if (trueVolume > phoneMax) {
|
|
|
+ trueVolume = phoneMax;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 仅用于记录设备音量,播控页面显示用
|
|
|
+ EventManager.fire(CmdEvent.volume({ volume: trueVolume }));
|
|
|
+ if (DeviceUtil.isAndroid) {
|
|
|
+ const name = DeviceManager.instance.name;
|
|
|
+ if (name === "猫王·霹雳唱机") {
|
|
|
+ VolumeUtil.setVolume(trueVolume);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 查询电量
|
|
|
+ case CmdKwh.queryKwh:
|
|
|
+ EventManager.fire(CmdEvent.battery({ kwh: value }));
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 自动播放 54, 44, 44, 48, 1, 9, 24, 1, 1
|
|
|
+ case CmdBase.getAutoPlay:
|
|
|
+ case CmdBase.setAutoPlay:
|
|
|
+ setTimeout(() => {
|
|
|
+ EventManager.fire(CmdEvent.playStatus({
|
|
|
+ playStatus: value === EnumOpen.open ? EnumPlayStatus.play : EnumPlayStatus.pause,
|
|
|
+ }));
|
|
|
+ }, 300);
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 查询低电量设置
|
|
|
+ case CmdKwh.queryLowKwhWarningTone:
|
|
|
+ EventManager.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);
|
|
|
+ }
|
|
|
+
|
|
|
+ EventManager.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);
|
|
|
+ EventManager.fire(CmdEvent.eqs({ eqs: list }));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 低延迟 [54, 44, 44, 48, 1, a, b2, 2, 0, 2]
|
|
|
+ case CmdEarPhone.queryLowDelayMode:
|
|
|
+ const lowDelayMode = cmd[9];
|
|
|
+ EventManager.fire(CmdEvent.lowDelayMode({ lowDelayMode, lowDelayModeOpen: value }));
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 耳机低电量
|
|
|
+ case CmdEarPhone.queryLowPower:
|
|
|
+ const lowPowerOpen = cmd[8];
|
|
|
+ EventManager.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);
|
|
|
+ EventManager.fire(CmdEvent.wake({
|
|
|
+ wakeSwitch,
|
|
|
+ wakeCycle,
|
|
|
+ wakeHour: hour,
|
|
|
+ wakeMinutes: minutes,
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 查询自动休眠状态
|
|
|
+ case CmdRtc.querySleepAfterPlayPause:
|
|
|
+ case CmdRtc.setSleepAfterPlayPause:
|
|
|
+ EventManager.fire(CmdEvent.pauseSleep({ pauseSleep: value }));
|
|
|
+ break;
|
|
|
+
|
|
|
+ // 查询休眠
|
|
|
+ case CmdRtc.querySleep:
|
|
|
+ const sleepSwitch = cmd[8];
|
|
|
+ const hour = cmd[9];
|
|
|
+ const minutes = cmd[10];
|
|
|
+ const leftHour = cmd[11];
|
|
|
+ const leftMinutes = cmd[12];
|
|
|
+ EventManager.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];
|
|
|
+ EventManager.fire(CmdEvent.ctrlStatus({ ctrlStatus: [singleC, doubleC, longC] }));
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ console.log("发送语音:默认发送2", cmd);
|
|
|
+ // _receiveRecordData(cmd);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export { BtParse };
|