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
|
|
|
|
|
2025-03-07 11:15:19 +08:00
|
|
|
|
// 时分字符串转二进制
|
|
|
|
|
|
export function parseTimeToList(timeString) {
|
2025-06-11 17:29:21 +08:00
|
|
|
|
let timeList = [0, 0, 0, 0]
|
2025-03-07 11:15:19 +08:00
|
|
|
|
|
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-03-07 11:15:19 +08:00
|
|
|
|
|
2025-06-11 17:29:21 +08:00
|
|
|
|
return new Uint8Array(timeList)
|
2025-03-07 11:15:19 +08:00
|
|
|
|
}
|
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
|
|
|
|
}
|
2025-04-15 15:21:17 +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 // 低字节
|
|
|
|
|
|
];
|
2025-04-15 15:21:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 二进制字符串转换为十进制数字数组
|
|
|
|
|
|
* 例如 '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;
|
2025-04-15 15:21:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 十进制数字数组转为二进制字符串
|
2025-04-18 09:23:00 +08:00
|
|
|
|
* 例如 将 [1,2,3,4,5] 转换回 '0111110'(表示周一到周五)
|
|
|
|
|
|
* @param {number[]} weekdays - 周几数组,1-7 分别代表周一到周日
|
|
|
|
|
|
* @returns {string} - 7位二进制字符串,从右到左分别代表周一到周日
|
2025-04-15 15:21:17 +08:00
|
|
|
|
*/
|
|
|
|
|
|
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('');
|
2025-04-15 15:21:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 用于判断时间戳是否是秒级别的,如果是的话则补充到毫秒级别
|
|
|
|
|
|
* @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;
|
2025-04-15 15:21:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查并返回具体哪个参数为空
|
|
|
|
|
|
* @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-04-15 15:21:17 +08:00
|
|
|
|
}
|
2025-06-11 17:29:21 +08:00
|
|
|
|
return null;
|
2025-04-15 15:21:17 +08:00
|
|
|
|
}
|
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;
|
|
|
|
|
|
}
|