248 lines
7.0 KiB
JavaScript
248 lines
7.0 KiB
JavaScript
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<string>} 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 };
|
||
} |