179 lines
4.0 KiB
JavaScript
179 lines
4.0 KiB
JavaScript
/**
|
||
* 命令管理服务
|
||
*/
|
||
const { bleService } = require('./ble.js');
|
||
const cmdStorage = require('../utils/command-storage.js');
|
||
const { LIMITS } = require('../utils/constants.js');
|
||
|
||
class CommandManager {
|
||
constructor() {
|
||
this._lastSendTime = 0;
|
||
this._minSendInterval = 500; // 最小发送间隔(毫秒)
|
||
}
|
||
|
||
/**
|
||
* 发送命令(固定使用BLE)
|
||
* @param {string} hex - 十六进制命令
|
||
* @param {string} method - 发送方式:'BLE'(保留参数兼容性)
|
||
* @param {Object} device - 设备信息
|
||
* @param {Object} options - 可选参数
|
||
* @returns {Promise}
|
||
*/
|
||
async sendCommand(hex, method, device, options = {}) {
|
||
// 1. 验证命令格式
|
||
if (!this._validateHex(hex)) {
|
||
throw new Error('命令格式错误:必须是有效的十六进制字符串');
|
||
}
|
||
|
||
// 2. 发送频率限制
|
||
const now = Date.now();
|
||
if (now - this._lastSendTime < this._minSendInterval) {
|
||
throw new Error('发送频率过快,请稍后再试');
|
||
}
|
||
this._lastSendTime = now;
|
||
|
||
// 3. 使用BLE发送
|
||
let result;
|
||
try {
|
||
result = await this._sendViaBle(hex, device);
|
||
|
||
// 4. 记录发送历史
|
||
this._recordHistory(hex, 'BLE', device, 'success', options.name);
|
||
|
||
return result;
|
||
} catch (err) {
|
||
// 记录失败历史
|
||
this._recordHistory(hex, 'BLE', device, 'failed', options.name, err.message);
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 通过 BLE 发送
|
||
* @param {string} hex
|
||
* @param {Object} device
|
||
* @returns {Promise}
|
||
*/
|
||
async _sendViaBle(hex, device) {
|
||
// 检查 BLE 连接状态
|
||
if (!bleService.isReady()) {
|
||
throw new Error('BLE 未连接,请先连接设备');
|
||
}
|
||
|
||
// 检查是否连接的是目标设备
|
||
if (bleService.deviceId !== device.deviceId) {
|
||
throw new Error('BLE 连接的设备不匹配');
|
||
}
|
||
|
||
// 发送命令
|
||
await bleService.writeCommand(hex);
|
||
return {
|
||
success: true,
|
||
method: 'BLE',
|
||
message: 'BLE 发送成功',
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 验证十六进制格式
|
||
* @param {string} hex
|
||
* @returns {boolean}
|
||
*/
|
||
_validateHex(hex) {
|
||
if (!hex || typeof hex !== 'string') {
|
||
return false;
|
||
}
|
||
// 移除空格
|
||
hex = hex.replace(/\s+/g, '');
|
||
// 检查是否只包含 0-9, A-F, a-f
|
||
return /^[0-9A-Fa-f]+$/.test(hex) && hex.length % 2 === 0;
|
||
}
|
||
|
||
/**
|
||
* 记录发送历史
|
||
*/
|
||
_recordHistory(hex, method, device, status, name, error) {
|
||
cmdStorage.addHistory({
|
||
hex,
|
||
method,
|
||
deviceId: device.serialNumber,
|
||
deviceName: device.name,
|
||
name: name || '自定义命令',
|
||
status,
|
||
error: error || null,
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 获取预设命令列表
|
||
* @param {string} deviceId
|
||
* @returns {Array}
|
||
*/
|
||
getCommands(deviceId) {
|
||
return cmdStorage.getCommands(deviceId);
|
||
}
|
||
|
||
/**
|
||
* 添加预设命令
|
||
* @param {Object} command
|
||
* @returns {boolean}
|
||
*/
|
||
addCommand(command) {
|
||
return cmdStorage.addCommand(command);
|
||
}
|
||
|
||
/**
|
||
* 更新预设命令
|
||
* @param {Object} command
|
||
* @returns {boolean}
|
||
*/
|
||
updateCommand(command) {
|
||
return cmdStorage.updateCommand(command);
|
||
}
|
||
|
||
/**
|
||
* 删除预设命令
|
||
* @param {string} id
|
||
*/
|
||
removeCommand(id) {
|
||
cmdStorage.removeCommand(id);
|
||
}
|
||
|
||
/**
|
||
* 获取发送历史(只返回当天的)
|
||
* @param {string} deviceId
|
||
* @returns {Array}
|
||
*/
|
||
getHistory(deviceId) {
|
||
return cmdStorage.getHistory(deviceId);
|
||
}
|
||
|
||
/**
|
||
* 清空发送历史
|
||
*/
|
||
clearHistory() {
|
||
cmdStorage.clearHistory();
|
||
}
|
||
|
||
/**
|
||
* 更新命令使用次数
|
||
* @param {string} id
|
||
*/
|
||
incrementUseCount(id) {
|
||
const commands = cmdStorage.getCommands();
|
||
const command = commands.find(c => c.id === id);
|
||
if (command) {
|
||
command.useCount = (command.useCount || 0) + 1;
|
||
command.lastUsedTime = Date.now();
|
||
cmdStorage.saveCommands(commands);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 导出单例
|
||
const commandManager = new CommandManager();
|
||
|
||
module.exports = {
|
||
CommandManager,
|
||
commandManager,
|
||
}; |