bt_parse.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. import {
  2. BtCmd,
  3. CmdBase,
  4. CmdEarPhone,
  5. CmdRtc,
  6. // CmdRgb,
  7. CmdKwh,
  8. CmdKey,
  9. CmdVoice,
  10. CmdWeek
  11. } from './bt_cmd';
  12. class BtParse {
  13. // 型号名称
  14. // static mateX2 = "MW-Mate X(4G_WIFI)";
  15. // static matePVX = "猫王音响·Mate_PVX";
  16. // static matePVXL = "猫王音响·Mate_PVXL";
  17. // 防止收到另外的消息
  18. static isReceiveCmd = false;
  19. // 如果10ms内获取两个一模一样的就删除一个
  20. static lastCmd = null;
  21. static lastTime = null;
  22. constructor() { }
  23. // 解析命令
  24. static parseTLV(cmd) {
  25. BtCmd.printTLV(cmd, false);
  26. // todo 在线
  27. // if (!PlayDevice.isOnline) {
  28. // return;
  29. // }
  30. // if (!BtParse.isReceiveCmd) {
  31. // return;
  32. // }
  33. if (cmd.length > 5) {
  34. // 指令类别
  35. const type = cmd[6];
  36. if (cmd.length < 9) {
  37. // 杰里、领芯的语音控制指令
  38. BtParse._voiceCmd(cmd);
  39. } else {
  40. // cmd[7]为命令长度
  41. // 命令类型
  42. const value = cmd[8];
  43. // 第二部分走杰理
  44. if (type === CmdVoice.jlReceiveVoiceData) {
  45. BtParse._receiveRecordData(cmd);
  46. }
  47. // 查询版本号后校验设备
  48. else if (type === CmdBase.queryVersion) {
  49. const version = CmdBase.parseVersion(value);
  50. //EventManager.fire(CmdEvent.version(version));
  51. //EventManager.fire(CmdEvent.getDeviceInfo());
  52. } else if (BtParse._getDataHeader(cmd)) {
  53. // 控制指令
  54. BtParse._controlCmd(cmd);
  55. } else {
  56. const manufacturer = "";
  57. // DeviceManager.instance.device?.manufacturer ?? "";
  58. // 山景的语音判断
  59. if (manufacturer === EnumSupplier.shanJing) {
  60. const sjCmd = cmd[4];
  61. if (sjCmd === CmdVoice.sjStartVoice) {
  62. BtParse._startRecord(EnumSupplier.shanJing);
  63. } else if (sjCmd === CmdVoice.sjStopVoice) {
  64. BtParse._stopRecord(EnumSupplier.shanJing);
  65. }
  66. // 山景的都要走接收数据
  67. BtParse._receiveRecordData(cmd);
  68. } else {
  69. // b1耳机、领芯、杰里p2第二部分语音数据直接走这里
  70. BtParse._receiveRecordData(cmd);
  71. }
  72. }
  73. }
  74. }
  75. }
  76. static _send(cmdEvent) {
  77. // todo
  78. // EventManager.fire(CmdEvent[cmdEvent]);
  79. }
  80. static _getDataHeader(cmd) {
  81. if (cmd.length < 4) {
  82. return false;
  83. }
  84. const header = [0x54, 0x44, 0x44, 0x48];
  85. return cmd[0] === header[0] && cmd[1] === header[1] && cmd[2] === header[2] && cmd[3] === header[3];
  86. }
  87. // todo 暂时不要
  88. static _voiceCmd(cmd) {
  89. const type = cmd[6];
  90. console.log("收到语音指令:", cmd);
  91. // switch (type) {
  92. // // 杰理语音开始
  93. // case CmdVoice.jlStartVoice:
  94. // BtParse._startRecord(EnumSupplier.jieLi);
  95. // break;
  96. // // 杰理结束
  97. // case CmdVoice.jlStopVoice:
  98. // BtParse._stopRecord(EnumSupplier.jieLi);
  99. // break;
  100. // // 发给插件
  101. // case CmdVoice.jlReceiveVoiceData:
  102. // console.log("发送杰里的p1语音:没有进来过,不走这里的,直接判断0x70 && jieLi");
  103. // BtParse._receiveRecordData(cmd);
  104. // break;
  105. // // 领心语音开始
  106. // case CmdVoice.lxStartVoice:
  107. // BtParse._startRecord(EnumSupplier.lingXin);
  108. // break;
  109. // // 领心语音结束
  110. // case CmdVoice.lxStopVoice:
  111. // BtParse._stopRecord(EnumSupplier.lingXin);
  112. // break;
  113. // default:
  114. // console.log("发送语音:默认发送,不走这里", cmd);
  115. // break;
  116. // }
  117. }
  118. static async _startRecord(supplier) {
  119. console.log("StartVoice======语音开始", supplier);
  120. }
  121. static async _stopRecord(supplier) {
  122. console.log("stopRecord======语音结束", supplier);
  123. }
  124. // 杰理接收设备第二部分 发送给插件
  125. static _receiveRecordData(cmd) {
  126. // todo 暂时不要
  127. // RecordVoiceManager.sendDataToPlugin(cmd);
  128. }
  129. static async _controlCmd(cmd) {
  130. const type = cmd[6];
  131. const value = cmd[8];
  132. // mqttAddDebugCmd("收到蓝牙指令:" + cmd);
  133. console.log("收到控制指令:", cmd, type)
  134. switch (type) {
  135. // 校验设备
  136. case CmdBase.checkDeviceSuccess:
  137. // 设置100ms间隔,同时发会丢失指令
  138. // DeviceManager.instance.setLowKwhWarningTone();
  139. // DeviceManager.instance.queryLowKwhWarningTone();
  140. // DeviceManager.instance.getAutoPlay();
  141. // DeviceManager.instance.setTime();
  142. // DeviceManager.instance.getDeviceInfo();
  143. break;
  144. // 按键 短按、长按等
  145. case CmdKey.type:
  146. // IOS的不要了
  147. // if (DeviceUtil.isIOS) {
  148. // if (BtParse.lastCmd && JSON.stringify(BtParse.lastCmd) === JSON.stringify(cmd)) {
  149. // if (BtParse.lastTime) {
  150. // const curTime = TimeUtil.getCurrentMillis();
  151. // if (curTime - BtParse.lastTime < 5) {
  152. // return;
  153. // }
  154. // }
  155. // }
  156. // BtParse.lastCmd = cmd;
  157. // BtParse.lastTime = TimeUtil.getCurrentMillis();
  158. // }
  159. let t = 0;
  160. if (cmd.length > 9) {
  161. t = cmd[9];
  162. }
  163. switch (t) {
  164. // 0x54 44 44 48 01 0a 21 02 01 02
  165. // 54, 44, 44, 48, 1, a, 21, 2, 1(value), 2(type)
  166. // 上一曲
  167. case CmdKey.previousSong:
  168. BtParse._send(EnumCmdEvent.previousSong);
  169. break;
  170. // 下一曲
  171. case CmdKey.nextSong:
  172. BtParse._send(EnumCmdEvent.nextSong);
  173. break;
  174. // 上一频道
  175. case CmdKey.previousChannel:
  176. BtParse._send(EnumCmdEvent.previousChannel);
  177. break;
  178. // 下一频道
  179. case CmdKey.nextChannel:
  180. BtParse._send(EnumCmdEvent.nextChannel);
  181. break;
  182. // 0x02 2
  183. case CmdKey.pressShort:
  184. // 1 下一个频道
  185. if (value === CmdKey.next) {
  186. BtParse._send(EnumCmdEvent.nextChannel);
  187. }
  188. // 2 上一个频道
  189. else if (value === CmdKey.previous) {
  190. BtParse._send(EnumCmdEvent.previousChannel);
  191. }
  192. // 3 单击下一个专辑 或者下一曲
  193. else if (value === CmdKey.changeProgram) {
  194. if (ProviderUtil.device.mDevice?.clientType === BtParse.mateX2) {
  195. BtParse._send(EnumCmdEvent.nextAlbum);
  196. } else {
  197. BtParse._send(EnumCmdEvent.nextSong);
  198. }
  199. }
  200. break;
  201. // 0x09 9
  202. case CmdKey.pressDouble:
  203. // 1 双击下一曲
  204. if (value === CmdKey.next) {
  205. BtParse._send(EnumCmdEvent.nextSong);
  206. }
  207. // 2 双击上一曲
  208. else if (value === CmdKey.previous) {
  209. BtParse._send(EnumCmdEvent.previousSong);
  210. }
  211. // 3 单击上一专辑或者上一曲
  212. else if (value === CmdKey.changeProgram) {
  213. if (ProviderUtil.device.mDevice?.clientType === BtParse.mateX2) {
  214. BtParse._send(EnumCmdEvent.previousAlbum);
  215. } else {
  216. BtParse._send(EnumCmdEvent.previousSong);
  217. }
  218. }
  219. break;
  220. // 0x08 8
  221. case CmdKey.pressLong:
  222. if (value === CmdKey.previous) {
  223. console.log("快退");
  224. BtParse._send(EnumCmdEvent.fastback);
  225. } else if (value === CmdKey.next) {
  226. console.log("快进");
  227. BtParse._send(EnumCmdEvent.speed);
  228. }
  229. break;
  230. // 0x04 4
  231. case CmdKey.pressLongUp:
  232. if (value === CmdKey.previous) {
  233. console.log("停止快退");
  234. BtParse._send(EnumCmdEvent.stopFastback);
  235. } else if (value === CmdKey.next) {
  236. console.log("停止快进");
  237. BtParse._send(EnumCmdEvent.stopSpeed);
  238. } else if (value === CmdKey.pressLongUp) {
  239. // [54, 44, 44, 48, 1, a, 21, 2, 4, 4]
  240. console.log("录音结束");
  241. BtParse._send(EnumCmdEvent.stopRecord);
  242. }
  243. break;
  244. }
  245. BtHelper.instance.changeChannelCallBack();
  246. break;
  247. // 音量 54 44 44 48 1 a 32 2 b 0
  248. case CmdBase.queryVolume:
  249. // 手机最大音量 需要获取
  250. const phoneMax = 15;
  251. // todo 音量
  252. //await VolumeUtil.getMaxVolume();
  253. const max = CmdBase.volumeMax;
  254. const d = phoneMax / max;
  255. const result = (d * value).toFixed(2);
  256. const trueVolume = parseFloat(result);
  257. console.log("trueVolume=====", max, "===", d, ",,,,", value, ",,,,", result, ",,,,", trueVolume);
  258. if (trueVolume > phoneMax) {
  259. trueVolume = phoneMax;
  260. }
  261. // 仅用于记录设备音量,播控页面显示用
  262. //EventManager.fire(CmdEvent.volume({ volume: trueVolume }));
  263. // if (DeviceUtil.isAndroid) {
  264. // const name = "";
  265. // // DeviceManager.instance.name;
  266. // if (name === "猫王·霹雳唱机") {
  267. // // VolumeUtil.setVolume(trueVolume);
  268. // }
  269. // }
  270. break;
  271. // 查询电量
  272. case CmdKwh.queryKwh:
  273. //EventManager.fire(CmdEvent.battery({ kwh: value }));
  274. break;
  275. // 自动播放 54, 44, 44, 48, 1, 9, 24, 1, 1
  276. case CmdBase.getAutoPlay:
  277. case CmdBase.setAutoPlay:
  278. // setTimeout(() => {
  279. // EventManager.fire(CmdEvent.playStatus({
  280. // playStatus: value === EnumOpen.open ? EnumPlayStatus.play : EnumPlayStatus.pause,
  281. // }));
  282. // }, 300);
  283. break;
  284. // 查询低电量设置
  285. case CmdKwh.queryLowKwhWarningTone:
  286. //EventManager.fire(CmdEvent.queryLowKwn({ kwh: value }));
  287. break;
  288. // 耳机电量 index0 :左耳机, index1:左耳机 ,index2: 充电盒。value: 0-9代表10-100% 获取不到用-1
  289. // [54, 44, 44, 48, 1, b, b1, 3, 8, 8, 2]
  290. case CmdEarPhone.queryEarPhoneKwh:
  291. const rightKwh = cmd[9];
  292. const boxKwh = cmd[10];
  293. let kwh = 0;
  294. if (value > 0 && rightKwh > 0) {
  295. kwh = Math.min(value, rightKwh);
  296. } else {
  297. kwh = Math.max(value, rightKwh);
  298. }
  299. // EventManager.fire(CmdEvent.batteryEarphone({
  300. // kwhLeft: value,
  301. // kwhBox: boxKwh,
  302. // kwhRight: rightKwh,
  303. // kwh: kwh,
  304. // }));
  305. break;
  306. // EQ [84, 68, 68, 72, 1, 18, 180, 10, 0, 0, 240, 237, 236, 0, 236, 0, 0, 0]
  307. // B5耳机获取EQ
  308. case CmdEarPhone.queryEQ:
  309. if (cmd.length > 15) {
  310. const result = cmd.slice(8, cmd.length);
  311. const list = result.map(element => parseInt(element, 16));
  312. console.log("eq==============", list);
  313. // EventManager.fire(CmdEvent.eqs({ eqs: list }));
  314. }
  315. break;
  316. // 低延迟 [54, 44, 44, 48, 1, a, b2, 2, 0, 2]
  317. case CmdEarPhone.queryLowDelayMode:
  318. const lowDelayMode = cmd[9];
  319. // EventManager.fire(CmdEvent.lowDelayMode({ lowDelayMode, lowDelayModeOpen: value }));
  320. break;
  321. // 耳机低电量
  322. case CmdEarPhone.queryLowPower:
  323. const lowPowerOpen = cmd[8];
  324. EventManager.fire(CmdEvent.lowPowerOpen({ lowPowerOpen }));
  325. break;
  326. // 查询唤醒闹钟
  327. case CmdRtc.queryAlarm:
  328. const wakeSwitch = cmd[8];
  329. if (cmd.length > 9) {
  330. const week = cmd[9];
  331. const hour = cmd[10];
  332. const minutes = cmd[11];
  333. const wakeCycle = CmdWeek.cmd2Week(week);
  334. console.log("queryAlarm=====", wakeSwitch, "=", wakeCycle);
  335. // EventManager.fire(CmdEvent.wake({
  336. // wakeSwitch,
  337. // wakeCycle,
  338. // wakeHour: hour,
  339. // wakeMinutes: minutes,
  340. // }));
  341. }
  342. break;
  343. // 查询自动休眠状态
  344. case CmdRtc.querySleepAfterPlayPause:
  345. case CmdRtc.setSleepAfterPlayPause:
  346. //EventManager.fire(CmdEvent.pauseSleep({ pauseSleep: value }));
  347. break;
  348. // 查询休眠
  349. case CmdRtc.querySleep:
  350. const sleepSwitch = cmd[8];
  351. const hour = cmd[9];
  352. const minutes = cmd[10];
  353. const leftHour = cmd[11];
  354. const leftMinutes = cmd[12];
  355. // EventManager.fire(CmdEvent.sleep({
  356. // sleepSwitch,
  357. // sleepHour: hour,
  358. // sleepMinutes: minutes,
  359. // }));
  360. break;
  361. // 开始录音
  362. case CmdVoice.startVoice:
  363. console.log("没有意义的开始录音");
  364. // _send(EnumCmdEvent.startRecord);
  365. break;
  366. // 查询 耳机手势
  367. case CmdEarPhone.queryCtrlStatus:
  368. const singleC = cmd[8];
  369. const doubleC = cmd[9];
  370. const longC = cmd[10];
  371. //EventManager.fire(CmdEvent.ctrlStatus({ ctrlStatus: [singleC, doubleC, longC] }));
  372. break;
  373. default:
  374. console.log("发送语音:默认发送2", cmd);
  375. // _receiveRecordData(cmd);
  376. break;
  377. }
  378. }
  379. }
  380. // 导出类
  381. module.exports = BtParse;