262 lines
7.4 KiB
JavaScript
Raw Permalink Normal View History

2025-06-11 17:29:21 +08:00
import {md5} from 'js-md5'
2024-10-12 14:35:58 +08:00
import crc from 'crc'
// 周数组转换
export function convertWeekdaysToNumber(weekDay) {
2025-06-11 17:29:21 +08:00
let weekStr = '00000000'
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
// 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)
}
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
// 倒序 weekStr
weekStr = weekStr.split('').reverse().join('')
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
return parseInt(weekStr, 2)
2024-10-12 14:35:58 +08:00
}
// 时间戳转二进制
export function timestampToArray(timestamp) {
2025-06-11 17:29:21 +08:00
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
2024-10-12 14:35:58 +08:00
}
2025-06-11 17:29:21 +08:00
// 时分字符串转二进制
export function parseTimeToList(timeString) {
2025-06-11 17:29:21 +08:00
let timeList = [0, 0, 0, 0]
2025-06-11 17:29:21 +08:00
if (timeString.includes(':')) {
let timeParts = timeString.split(':')
timeList[2] = parseInt(timeParts[0], 10)
timeList[3] = parseInt(timeParts[1], 10)
}
2025-06-11 17:29:21 +08:00
return new Uint8Array(timeList)
}
2024-10-12 14:35:58 +08:00
// md5加密
export function md5Encrypt(text, token, key) {
2025-06-11 17:29:21 +08:00
const length = text.length + 4 + 16
const md5Array = new Uint8Array(length)
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
for (let i = 0; i < text.length; i++) {
md5Array[i] = text.charCodeAt(i)
}
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
md5Array.set(token, text.length)
md5Array.set(key, text.length + 4)
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
const md5Text = md5(md5Array)
return new Uint8Array(md5Text.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))
2024-10-12 14:35:58 +08:00
}
// 生成包尾 头部数据+内容数据
export function createPackageEnd(headArray, contentArray) {
2025-06-11 17:29:21 +08:00
// 拼接头部和内容
let mergerArray = new Uint8Array(headArray.length + contentArray.length)
mergerArray.set(headArray)
mergerArray.set(contentArray, headArray.length)
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
// crc加密
const crcResult = crc.crc16kermit(mergerArray)
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
// 拼接crc
let newArray = new Uint8Array(mergerArray.length + 2)
newArray.set(mergerArray)
newArray.set([crcResult / 256, crcResult % 256], mergerArray.length)
2024-10-12 14:35:58 +08:00
2025-06-11 17:29:21 +08:00
return newArray
2024-10-12 14:35:58 +08:00
}
// 二进制转时间戳
export function arrayToTimestamp(array) {
2025-06-11 17:29:21 +08:00
const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]
return timestamp >>> 0
2024-10-12 14:35:58 +08:00
}
// 二进制转字符串
export function uint8ArrayToString(uint8Array) {
2025-06-11 17:29:21 +08:00
let str = ''
for (let i = 0; i < uint8Array.length; i++) {
if (uint8Array[i] !== 0) {
str += String.fromCharCode(uint8Array[i])
}
2024-10-12 14:35:58 +08:00
}
2025-06-11 17:29:21 +08:00
return str
2024-10-12 14:35:58 +08:00
}
2025-01-07 18:11:07 +08:00
// 去除特征值尾部0
export function removeTrailingZeros(data) {
2025-06-11 17:29:21 +08:00
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)
2025-01-07 18:11:07 +08:00
}
/**
* 将分钟时间转换为两个字节的数组
* @param minutes
* @returns {(number|number)[]}
*/
export function convertTimeToBytes(minutes) {
2025-06-11 17:29:21 +08:00
return [
Math.floor(minutes / 256), // 高字节
minutes % 256 // 低字节
];
}
/**
* 二进制字符串转换为十进制数字数组
* 例如 '0111110' 会被转换为 [1, 2, 3, 4, 5]表示周一到周五
* @param weekdayBit
* @returns {*[]}
*/
export function convertWeekdayBitToArray(weekdayBit) {
2025-06-11 17:29:21 +08:00
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) {
2025-06-11 17:29:21 +08:00
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) {
2025-06-11 17:29:21 +08:00
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) {
2025-06-11 17:29:21 +08:00
for (let field of requiredFields) {
if (params[field] === undefined || params[field] === null) {
return `${field} 不能为空`;
}
}
2025-06-11 17:29:21 +08:00
return null;
}
2025-06-11 17:29:21 +08:00
/**
* 转换解析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;
2025-06-11 17:29:21 +08:00
}