123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- // 设备命令
- // TLV格式(16进制)
- // 二进制协议使用 TLV (Type-Length-Value)编码格式。
- // - Type:固定长度, 一字节。
- // - Length:可变长度。 0 或 1 个字节。
- // - Value:二进制数据。 长度由 Length 字段决定。 数据本身可以上数字或者字符串。
- const EnumOpen = {
- close: 0,
- open: 1
- };
- const EnumConnectType = {
- bt: 0,
- ble: 1,
- upnp: 2,
- mqtt: 3
- }
- class BtCmd {
- // BtCmd._();
- constructor() { }
- // 获取版本号
- static queryVersion() {
- return this._build(CmdBase.queryVersion, [0x00]);
- }
- // 查询电量 电量值 0-9,0对应10%,9对应100%,10充电
- static queryKwh() {
- return this._build(CmdKwh.queryKwh, [0x00]);
- }
- // 查询耳机电量
- static queryKwhEarPhone() {
- return this._build(CmdEarPhone.queryEarPhoneKwh, [0x00]);
- }
- // 查询EQ音效
- static queryEQ() {
- return this._build(CmdEarPhone.queryEQ, [0x00]);
- }
- // 设置EQ音效
- static setEQ(list) {
- return this._build(CmdEarPhone.setEQ, list);
- }
- // B5耳机-低电耗模式
- static queryLowPower() {
- return this._build(CmdEarPhone.queryLowPower, [0x00]);
- }
- static setLowPowerMode(isOpen) {
- return this._build(CmdEarPhone.setLowPowerMode, [isOpen]);
- }
- // B5耳机-自定义操作手势
- static queryCtrlStatus() {
- return this._build(CmdEarPhone.queryCtrlStatus, [0x00]);
- }
- static setCtrlStatus(singleClick, doubleClick, longClick) {
- return this._build(CmdEarPhone.setCtrlStatus, [singleClick, doubleClick, longClick]);
- }
- // 查询低延时模式
- static queryLowDelayMode() {
- return this._build(CmdEarPhone.queryLowDelayMode, [0x00]);
- }
- // 低延时模式
- static setLowDelayMode(open, mode) {
- return this._build(CmdEarPhone.setLowDelayMode, [open, mode]);
- }
- // 低电量提示音
- static queryLowKwhWarningTone() {
- return this._build(CmdKwh.queryLowKwhWarningTone, [0x00]);
- }
- static setLowKwhWarningTone(isNotify) {
- return this._build(CmdKwh.setLowKwhWarningTone, isNotify ? [0x01] : [0x00]);
- }
- // 蓝牙自动播放
- static setAutoPlay(switchStatus) {
- return this._build(CmdBase.setAutoPlay, [switchStatus]);
- }
- static AutoPlay() {
- return this._build(CmdBase.getAutoPlay, [0x00]);
- }
- // 查询音量
- static queryVolume() {
- return this._build(CmdBase.queryVolume, [0x00]);
- }
- static setVolume(volume) {
- return this._build(CmdBase.setVolume, [volume]);
- }
- // 查询闹钟
- static queryAlarm() {
- return this._build(CmdRtc.queryAlarm, [0x00]);
- }
- // 设置闹钟
- static setAlarm(switchStatus, weekCycle, hour, minutes, channel = 1) {
- console.log("setAlarm=====", switchStatus, "=", weekCycle, "=", hour, "=", minutes);
- const weeks = CmdWeek.week2Cmd(weekCycle);
- return this._build(CmdRtc.setAlarm, [switchStatus, weeks, hour, minutes, channel]);
- }
- // 查询休眠
- static querySleep() {
- return this._build(CmdRtc.querySleep, [0x00]);
- }
- static querySleepAfterPlayPause() {
- return this._build(CmdRtc.querySleepAfterPlayPause, [0x00]);
- }
- static setSleepAfterPlayPause(time) {
- if (time > 0) {
- // let day = (60 * 60)
- // let hour = 60
- // const hours = time / day;
- // const minutes = (time % day) / hour;
- // const seconds = (time % day % hour);
- // 将小时、分钟和秒转换为16进制字符串并转为大写
- // console.log(`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`);
- // console.log("休眠:", hour, minutes, seconds)
- // 跟app一样错误的处理方式
- return this._build(CmdRtc.setSleepAfterPlayPause, [time]);
- } else {
- return this._build(CmdRtc.setSleepAfterPlayPause, [0]);
- }
- }
- // 设置休眠
- static setSleep(switchStatus, hour, minutes) {
- return this._build(CmdRtc.setSleep, [switchStatus, hour, minutes]);
- }
- // 设置时间
- static setDevTime() {
- const now = new Date();
- const y = now.getFullYear();
- const year = Math.floor(y / 100);
- const _year = y % 100;
- const month = now.getMonth() + 1; // getMonth() 返回 0-11,所以需要加 1
- const day = now.getDate();
- const hour = now.getHours();
- const minutes = now.getMinutes();
- const seconds = now.getSeconds();
- console.log(`setTime========${year},${_year},${month},${day},${hour},${minutes},${seconds}`);
- // console.log(`setTime======== 2, ${CmdRtc.setTime}`);
- let cmd = this._build(0x50, [year, _year, month, day, hour, minutes, seconds]);
- console.log(`setTime========${cmd}`);
- return cmd;
- }
- // 查询时间
- static queryTime() {
- return this._build(CmdRtc.queryTime, [0x00]);
- }
- // 设置RGB
- static setRGB(r, g, b) {
- return this._build(CmdRgb.set, [r, g, b]);
- }
- // 查询RGB
- static queryRGB() {
- return this._build(CmdRgb.query, [0x00]);
- }
- static stringToUint8Array(text) {
- // return [0x73, 0x6d, 0x61, 0x72, 0x74, 0x5f, 0x41, 0x32, 0x46]
- // return [115, 109, 97, 114, 116, 95, 65, 50, 70]
- // return [115, 109, 97, 114, 116, 95, 65, 50, 70]
- // 73 6D 61 72 74 5F 41 32 46
- if (!text) {
- return []
- }
- console.log("stringToUint8Array", text)
- let code = Array.from(text).map(char => char.charCodeAt(0));
- console.log("stringToUint8Array", code)
- return code
- }
- static listInt2String(data) {
- return String.fromCharCode(...data);
- }
- static intToHex(num) {
- let value = num ?? 0;
- let hexStr = value.toString(16).toUpperCase();
- hexStr = hexStr.padStart(2, '0');
- let hexNum = parseInt(hexStr, 16);
- return hexNum;
- }
- // 校验设备
- static checkDevice() {
- let secretKey = this.stringToUint8Array(CmdBase.secretKey)
- // console.log(`checkDevice========${secretKey}`);
- return this._build(CmdBase.checkDevice, secretKey);
- }
- // 杰理语音开始回应
- static jlStartVoiceResponse() {
- return this._build(CmdVoice.jlStartVoiceResponse);
- }
- // 杰理语音结束回应
- static jlStopVoiceResponse() {
- return this._build(CmdVoice.jlStopVoiceResponse);
- }
- // 领芯语音
- static lxStartVoiceResponse() {
- return this._build(CmdVoice.lxStartVoiceResponse);
- }
- // 杰理语音结束回应
- static lxStopVoiceResponse() {
- return this._build(CmdVoice.lxStopVoiceResponse);
- }
- // b1开始语音回调
- static b1StartVoiceResponse() {
- const data = [0x04, 0x80, 0x01, 0x00, 0x02];
- return new Uint8Array(data);
- }
- // b1结束语音回调
- static b1StopVoiceResponse() {
- const data = [0x05, 0x80, 0x01, 0x00, 0x02];
- return new Uint8Array(data);
- }
- // 固定头部
- static get _header() {
- return [0x54, 0x44, 0x44, 0x48];
- }
- // 版本号
- static get _version() {
- return 0x01;
- }
- // wifi ,md5都用这个
- static sendWiFiInfo(wifiName, pwd) {
- // [0x22, (wifiList.length + pwdList.length + 6), 0x33, (wifiList.length), (wifiList), 0x44, (pwdList)];
- if (!wifiName) {
- return;
- }
- let result = [];
- // 字母*6 +
- let wifiList = BtCmd.stringToUint8Array(wifiName);
- // 数字*3 +
- var pwdList = [];
- if (pwd) {
- pwdList = BtCmd.stringToUint8Array(pwd);
- }
- console.log("wifiList", wifiList, "pwdList", pwdList)
- // 16进制
- result.push(0x22);
- result.push(BtCmd.intToHex(wifiList.length + pwdList.length + 6));
- // 账号
- result.push(0x33);
- result.push(BtCmd.intToHex(wifiList.length));
- let p = result[3] + 4;
- let j = 0;
- for (let i = 4; i < p; i++) {
- result.splice(i, 0, wifiList[j++]);
- }
- result.splice(p, 0, 0x44);
- // 有密码
- if (pwdList.length > 0) {
- result.splice(++p, 0, BtCmd.intToHex(pwdList.length));
- p++;
- j = 0;
- for (let i = p; i < p + pwdList.length; i++) {
- result.splice(i, 0, pwdList[j++]);
- }
- } else {
- result.splice(++p, 0, BtCmd.intToHex(pwdList.length));
- }
- console.log("发送转换拼接数据:", result.toString());
- return result;
- }
- /* 黑胶音箱的指令 */
- // 壁纸指令 1开始, 0结束
- static wallPaper(value) {
- let cmd = this._build(CmdBase.wallPaper, [value]);
- console.log("图片上传:", cmd);
- return cmd;
- }
- static wallPaperMD5(value) {
- let cmd = this._build(CmdBase.wallPaperMD5, value, true, false);
- console.log("图片上传MD5:", cmd);
- return cmd;
- }
- // 壁纸指令
- static wallPaperData(value) {
- let uint8Array = new Uint8Array(value);
- let cmd = this._build(CmdBase.wallPaperData, uint8Array, true, false);
- return cmd;
- }
- // 设置wifi
- static otaSetWifi(value) {
- return this._build(CmdBase.heijiaoBackImg, value, true, false);
- } // 背景图指令
- static backgroudImgData(value) {
- return this._build(CmdBase.heijiaoBackImgData, [value]);
- }
- // OTA指令 1开始, 0结束
- static otaCmd(value) {
- return this._build(CmdBase.heiJiaoOta, [value]);
- }
- // 发送OTA的URL
- static otaUrl(value) {
- return this._build(CmdBase.heiJiaoOtaData, value, true, false);
- }
- //暂时没用了
- static otaData(value) {
- return this._build(CmdBase.heiJiaoOta, [value], true, false);
- }
- /// 获取设备型号指令
- static getClientType() {
- return this._build(0x31, [0x00]);
- } ///获取设备mac地址
- static getMac() {
- return this._build(0x35, [0x00]);
- }
- ///获取手机是否连接了设备
- static getIsConnect() {
- return this._build(0x36, [0x00]);
- }
- // 生成命令(固定头部+版本号+命令总长度+命令类型+)
- static _build(cmdType, otherCmd = [], isWriteChildCmdLength = true, isChangeHex = true) {
- const cmd = [];
- // 固定头部
- cmd.push(...this._header);
- // 版本号
- cmd.push(this._version);
- // 命令类型
- cmd.push(cmdType);
- if (isWriteChildCmdLength) {
- // 子命令长度
- const childLength = this._int2Hex(otherCmd.length);
- cmd.push(childLength);
- }
- // 其他命令
- if (otherCmd.length > 0) {
- if (isChangeHex) {
- for (const element of otherCmd) {
- cmd.push(this._int2Hex(element));
- }
- } else {
- cmd.push(...otherCmd);
- }
- }
- // 命令长度(位置在版本号之后)
- const length = cmd.length + 1;
- const l = this._int2Hex(length);
- cmd.splice(5, 0, l);
- // console.log(`打印cmd:${cmd}`);
- return cmd;
- }
- // 打印cmd
- static printTLV(cmd, isSend = false) {
- let result = "";
- const key = isSend ? "发送" : "接收";
- if (isSend) {
- // console.log(`${key}原始-${cmd.toString()}`);
- }
- for (let i = 0; i < cmd.length; i++) {
- result += (`${this._int2HexString(cmd[i])}`.padStart(2, "0") + ":");
- }
- if (isSend) {
- mqttAddDebugCmd(`发送蓝牙指令:${cmd} \n ${result}`);
- }
- console.log(`${key}解析- [${result}],原始数据:${cmd}`);
- }
- static _int2Hex(num) {
- let value = num ?? 0;
- let hexStr = value.toString(16).toUpperCase();
- hexStr = hexStr.padStart(2, '0');
- let hexNum = parseInt(hexStr, 16);
- return hexNum;
- }
- static _int2HexString(value) {
- return value.toString(16).toUpperCase();
- }
- }
- // 设备命令类型
- const CmdBase = {
- secretKey: "smart_A2F",
- queryVersion: 0x30,
- checkDevice: 0x28,
- checkDeviceSuccess: 0x27,
- setAutoPlay: 0x24,
- getAutoPlay: 0x23,
- queryChannelAngle: 0x38,
- switchLed: 0x39,
- queryVolume: 0x32,
- setVolume: 0x33,
- wallPaper: 0x78,
- wallPaperMD5: 0x80,
- wallPaperData: 0x79,
- heiJiaoOta: 0x074,
- heiJiaoOtaData: 0x75,
- heijiaoBackImg: 0x76,
- heijiaoBackImgData: 0x77,
- // 获取设备型号指令
- getClientType: 0x31,
- ///获取设备mac地址
- getMac: 0x35,
- ///获取手机是否连接了设备
- getIsConnect: 0x36,
- newFlag: "MW-Mate X\\(4G_WIFI\\)|MW-2AX\\(WIFI-N\\)|MW-SR1\\(4G_WIFI\\)|MW-SR1\\(4G_WIFI_MEIZU01\\)",
- // volumeMax: (new RegExp(`^(${CmdBase.newFlag})$`, 'i').test(DeviceManager.instance.clientType || "")) ? 0x20 : 0xF,
- volumeMax: 15,
- parseVersion(version) {
- let ver;
- if (version <= 0) {
- ver = "1.0.0";
- } else {
- const split = version.toString().split("");
- if (split.length === 1) {
- split.unshift("0", "0");
- } else if (split.length === 2) {
- split.unshift("0");
- }
- ver = split.join(".");
- }
- console.log(`parseVersion======${version},,,,,,,${ver.toString()}`);
- return ver;
- }
- };
- // 耳机相关指令
- const CmdEarPhone = {
- queryLowDelayMode: 0xb2,
- setLowDelayMode: 0xb3,
- queryEQ: 0xb4,
- setEQ: 0xb5,
- queryEarPhoneKwh: 0xb1,
- queryCtrlStatus: 0xB6,
- setCtrlStatus: 0xB7,
- queryLowPower: 0xB8,
- setLowPowerMode: 0xB9
- };
- // 时间相关
- const CmdRtc = {
- setTime: 0x50,
- queryTime: 0x51,
- setAlarm: 0x52,
- queryAlarm: 0x54,
- setSleep: 0x56,
- querySleep: 0x57,
- setSleepAfterPlayPause: 0x5a,
- querySleepAfterPlayPause: 0x5b
- };
- // 设置设备颜色
- const CmdRgb = {
- query: 0x80,
- set: 0x81
- };
- // 电量相关命令
- const CmdKwh = {
- queryKwh: 0x22,
- setLowKwhWarningTone: 0x26,
- queryLowKwhWarningTone: 0x25
- };
- // 按键
- const CmdKey = {
- previousSong: 0x0a,
- nextSong: 0x0b,
- previousChannel: 0x0c,
- nextChannel: 0x0d,
- type: 0x21,
- pressShort: 0x02,
- pressLongUp: 0x04,
- pressLong: 0x08,
- pressDouble: 0x09,
- next: 0x01,
- previous: 0x02,
- changeProgram: 0x03
- };
- // 语音
- const CmdVoice = {
- startVoice: 0x01,
- jlStartVoice: 0x66,
- jlStopVoice: 0x68,
- jlStartVoiceResponse: 0x67,
- jlStopVoiceResponse: 0x69,
- jlReceiveVoiceData: 0x70,
- lxStartVoice: 0x71,
- lxStopVoice: 0x72,
- lxStartVoiceResponse: 0x40,
- lxStopVoiceResponse: 0x41,
- sjStartVoice: 0x23,
- sjStopVoice: 0x24
- };
- // 一周
- const CmdWeek = {
- sunday: 0x01,
- monday: 0x02,
- tuesday: 0x04,
- wednesday: 0x08,
- thursday: 0x10,
- friday: 0x20,
- saturday: 0x40,
- weeks: [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40],
- week2Cmd(weekCycle) {
- let result = 0;
- for (let i = 0; i < weekCycle.length; i++) {
- const item = weekCycle[i];
- if (item === EnumOpen.open) {
- result += this.weeks[i];
- }
- }
- return result;
- },
- cmd2Week(cmd) {
- const w = [0, 0, 0, 0, 0, 0, 0];
- for (let i = this.weeks.length - 1; i >= 0; i--) {
- const week = this.weeks[i];
- if (week <= cmd) {
- w[i] = EnumOpen.open;
- cmd -= week;
- }
- }
- return w;
- }
- };
- module.exports = {
- BtCmd,
- CmdBase,
- CmdEarPhone,
- CmdRtc,
- CmdRgb,
- CmdKwh,
- CmdKey,
- CmdVoice,
- CmdWeek
- };
|