import {md5} from 'js-md5' import crc from 'crc' // 周数组转换 export function convertWeekdaysToNumber(weekDay) { let weekStr = '00000000' // eslint-disable-next-line no-restricted-syntax for (const day of weekDay) { const index = day % 7 weekStr = weekStr.substring(0, index) + '1' + weekStr.substring(index + 1) } // 倒序 weekStr weekStr = weekStr.split('').reverse().join('') return parseInt(weekStr, 2) } // 时间戳转二进制 export function timestampToArray(timestamp) { const array = new Uint8Array(4) array[0] = (timestamp & 0xff000000) >> 24 array[1] = (timestamp & 0xff0000) >> 16 array[2] = (timestamp & 0xff00) >> 8 array[3] = timestamp & 0xff return array } // 时分字符串转二进制 export function parseTimeToList(timeString) { let timeList = [0, 0, 0, 0] if (timeString.includes(':')) { let timeParts = timeString.split(':') timeList[2] = parseInt(timeParts[0], 10) timeList[3] = parseInt(timeParts[1], 10) } return new Uint8Array(timeList) } // md5加密 export function md5Encrypt(text, token, key) { const length = text.length + 4 + 16 const md5Array = new Uint8Array(length) for (let i = 0; i < text.length; i++) { md5Array[i] = text.charCodeAt(i) } md5Array.set(token, text.length) md5Array.set(key, text.length + 4) const md5Text = md5(md5Array) return new Uint8Array(md5Text.match(/.{1,2}/g).map(byte => parseInt(byte, 16))) } // 生成包尾 头部数据+内容数据 export function createPackageEnd(headArray, contentArray) { // 拼接头部和内容 let mergerArray = new Uint8Array(headArray.length + contentArray.length) mergerArray.set(headArray) mergerArray.set(contentArray, headArray.length) // crc加密 const crcResult = crc.crc16kermit(mergerArray) // 拼接crc let newArray = new Uint8Array(mergerArray.length + 2) newArray.set(mergerArray) newArray.set([crcResult / 256, crcResult % 256], mergerArray.length) return newArray } // 二进制转时间戳 export function arrayToTimestamp(array) { const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3] return timestamp >>> 0 } // 二进制转字符串 export function uint8ArrayToString(uint8Array) { let str = '' for (let i = 0; i < uint8Array.length; i++) { if (uint8Array[i] !== 0) { str += String.fromCharCode(uint8Array[i]) } } return str } // 去除特征值尾部0 export function removeTrailingZeros(data) { const featureCount = data[0] let currentIndex = 1 for (let i = 0; i < featureCount; i++) { const length = data[currentIndex + 1] currentIndex += 2 + length } return data.slice(0, currentIndex) } /** * 将分钟时间转换为两个字节的数组 * @param minutes * @returns {(number|number)[]} */ export function convertTimeToBytes(minutes) { return [ Math.floor(minutes / 256), // 高字节 minutes % 256 // 低字节 ]; } /** * 二进制字符串转换为十进制数字数组 * 例如 '0111110' 会被转换为 [1, 2, 3, 4, 5](表示周一到周五) * @param weekdayBit * @returns {*[]} */ export function convertWeekdayBitToArray(weekdayBit) { const weekdays = []; const bits = weekdayBit.split(''); bits.forEach((bit, index) => { if (bit === '1') { weekdays.push(index); } }); return weekdays; } /** * 十进制数字数组转为二进制字符串 * 例如 将 [1,2,3,4,5] 转换回 '0111110'(表示周一到周五) * @param {number[]} weekdays - 周几数组,1-7 分别代表周一到周日 * @returns {string} - 7位二进制字符串,从右到左分别代表周一到周日 */ export function convertWeekdayArrayToBit(weekdays) { const bits = new Array(7).fill('0'); weekdays.forEach(day => { if (day >= 1 && day <= 7) { // 将1-7转换为0-6的数组索引 const index = day === 7 ? 0 : day - 1; bits[index] = '1'; } }); return bits.join(''); } /** * 用于判断时间戳是否是秒级别的,如果是的话则补充到毫秒级别 * @param timestamp 时间戳 * @returns {number|*} * @private */ export function _convertToMilliseconds(timestamp) { if (!timestamp) return timestamp; return timestamp.toString().length === 10 ? timestamp * 1000 : timestamp; } /** * 检查并返回具体哪个参数为空 * @param {Object} params - 参数对象 * @param {Array} requiredFields - 必填字段列表 * @returns {string | null} - 如果有字段为空,则返回错误消息;否则返回null */ export function checkRequiredFields(params, requiredFields) { for (let field of requiredFields) { if (params[field] === undefined || params[field] === null) { return `${field} 不能为空`; } } return null; } /** * 转换解析wifi列表数据 * @param data * @returns {{status: *, numberOfSsid: *, wifiList: *[]}} */ export function parseWifiList(data) { // data: Array or Uint8Array // 跳过前两位命令码 const status = data[2]; const numberOfSsid = data[3]; const wifiList = []; let offset = 4; for (let i = 0; i < numberOfSsid; i++) { // 取32字节SSID const ssidBytes = data.slice(offset, offset + 32); // 用自定义函数转字符串并去除末尾0 const ssid = _bytesToString(ssidBytes).trim(); offset += 32; // 取rssi let rssi = data[offset]; // 通常rssi是无符号byte,需转为有符号 if (rssi > 127) rssi = rssi - 256; offset += 1; // 过滤空名 if (ssid) { wifiList.push({ssid, rssi}); } } return {status, numberOfSsid, wifiList}; } function _bytesToString(bytes) { // 只适用于ASCII和UTF-8无多字节字符的场景 let str = ''; for (let i = 0; i < bytes.length; i++) { if (bytes[i] === 0) break; // 截断0 str += String.fromCharCode(bytes[i]); } return str; } // 解析decrypted中的json数据,返回对象 export function parseNetworkJsonFromDecrypted(decrypted) { let peerId, wifiName, secretKey, deviceMac, networkMac; try { const secretKeyJsonLength = (decrypted[4] << 8) + decrypted[3]; const secretKeyList = decrypted.slice(5, 5 + secretKeyJsonLength); let result; if (typeof TextDecoder !== 'undefined') { result = new TextDecoder('utf-8').decode(secretKeyList); } else { // 兼容性处理 result = uint8ArrayToString(secretKeyList); } const jsonMap = JSON.parse(result); peerId = jsonMap.peerId; wifiName = jsonMap.wifiName; secretKey = jsonMap.secretKey; deviceMac = jsonMap.deviceMac; networkMac = jsonMap.networkMac; console.log('解析配网信息:', jsonMap); } catch (e) { console.error('解析配网信息失败:', e); } return { peerId, wifiName, secretKey, deviceMac, networkMac }; } /** * 生成随机长度字符串 * @param length * @returns {string} */ export function generateRandomString(length) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars[Math.floor(Math.random() * chars.length)]; } return result; }