feat: 实现 AMT 设备自动添加功能(仅 Digest 认证)
- 添加 AMT Digest 认证服务 (AmtDigestService) - 添加 AMT 模拟服务用于测试 (AmtMockService) - 更新设备控制器支持 AMT 连接测试和设备信息获取 - 前端添加 AMT 自动添加方式,支持手动输入和凭证选择 - 移除 Basic 认证,仅使用 Digest 认证 - 添加 Apache HttpClient 依赖支持 Digest 认证 - 创建相关文档和测试脚本
This commit is contained in:
parent
7d3f98e4f0
commit
8b07d8f52a
0
.kiro/specs/amt-device-addition/requirements.md
Normal file
0
.kiro/specs/amt-device-addition/requirements.md
Normal file
245
AMT_DEVICE_ADD_FEATURE.md
Normal file
245
AMT_DEVICE_ADD_FEATURE.md
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
# AMT 设备添加功能说明
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
|
||||||
|
在设备管理的设备列表页面,增强了"新增设备"功能,支持通过 Intel AMT(Active Management Technology)协议自动发现和添加设备。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
### 1. 两种添加方式
|
||||||
|
|
||||||
|
#### 手动添加
|
||||||
|
- 传统的手动输入设备信息方式
|
||||||
|
- 需要手动填写设备名称、UUID、IP地址、MAC地址等信息
|
||||||
|
|
||||||
|
#### AMT 自动添加
|
||||||
|
- 通过 AMT 协议自动发现设备
|
||||||
|
- 只需输入 IP 地址和认证信息
|
||||||
|
- 自动获取设备名称、MAC 地址等信息
|
||||||
|
- 自动生成 UUID
|
||||||
|
|
||||||
|
### 2. 认证方式
|
||||||
|
|
||||||
|
#### 直接输入
|
||||||
|
- 手动输入 AMT 用户名和密码
|
||||||
|
- 适合临时测试或一次性添加
|
||||||
|
|
||||||
|
#### 使用已保存凭证
|
||||||
|
- 从"AMT 设置"页面选择已保存的凭证
|
||||||
|
- 支持默认凭证快速选择
|
||||||
|
- 提高安全性和便捷性
|
||||||
|
|
||||||
|
### 3. 连接测试
|
||||||
|
|
||||||
|
- 提供"测试连接"按钮
|
||||||
|
- 验证 AMT 连接是否可用
|
||||||
|
- 测试成功后自动获取设备信息
|
||||||
|
- 显示连接状态反馈
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 后端实现
|
||||||
|
|
||||||
|
#### 1. AmtDigestService.java
|
||||||
|
- 使用 WS-Management 协议与 AMT 设备通信
|
||||||
|
- 支持 Digest 认证(HTTP Digest Auth)
|
||||||
|
- 实现设备信息获取和连接测试
|
||||||
|
|
||||||
|
#### 2. 主要接口
|
||||||
|
|
||||||
|
**测试 AMT 连接**
|
||||||
|
```
|
||||||
|
POST /device/amt/test
|
||||||
|
{
|
||||||
|
"ipAddress": "192.168.1.100",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "password"
|
||||||
|
}
|
||||||
|
或
|
||||||
|
{
|
||||||
|
"ipAddress": "192.168.1.100",
|
||||||
|
"credentialId": 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**获取 AMT 设备信息**
|
||||||
|
```
|
||||||
|
POST /device/amt/getInfo
|
||||||
|
{
|
||||||
|
"ipAddress": "192.168.1.100",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "password"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. WS-Management 协议
|
||||||
|
|
||||||
|
使用标准的 SOAP over HTTP 协议:
|
||||||
|
- 端口:HTTP 16992, HTTPS 16993
|
||||||
|
- 认证:HTTP Digest Authentication
|
||||||
|
- 协议:WS-Management (WSMAN)
|
||||||
|
|
||||||
|
### 前端实现
|
||||||
|
|
||||||
|
#### 1. 设备列表页面增强
|
||||||
|
- 添加方式选择(单选按钮)
|
||||||
|
- AMT 设备发现表单
|
||||||
|
- 认证方式切换(开关)
|
||||||
|
- 凭证选择下拉框
|
||||||
|
- 测试连接按钮和状态显示
|
||||||
|
|
||||||
|
#### 2. 用户交互流程
|
||||||
|
|
||||||
|
1. 点击"新增设备"按钮
|
||||||
|
2. 选择"AMT 自动添加"方式
|
||||||
|
3. 输入 IP 地址
|
||||||
|
4. 选择认证方式:
|
||||||
|
- 手动输入:填写用户名和密码
|
||||||
|
- 使用凭证:从下拉框选择已保存的凭证
|
||||||
|
5. 点击"测试连接"
|
||||||
|
6. 连接成功后,自动填充设备信息
|
||||||
|
7. 确认并保存设备
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 前置条件
|
||||||
|
|
||||||
|
1. AMT 设备已启用并配置
|
||||||
|
2. AMT 设备网络可达
|
||||||
|
3. 已知 AMT 管理员账号密码
|
||||||
|
4. (可选)在"AMT 设置"中预先保存凭证
|
||||||
|
|
||||||
|
### 操作步骤
|
||||||
|
|
||||||
|
1. **进入设备列表页面**
|
||||||
|
- 导航到:设备管理 > 设备列表
|
||||||
|
|
||||||
|
2. **点击新增设备**
|
||||||
|
- 点击页面右上角的"新增设备"按钮
|
||||||
|
|
||||||
|
3. **选择 AMT 自动添加**
|
||||||
|
- 在弹出的对话框中选择"AMT 自动添加"单选按钮
|
||||||
|
|
||||||
|
4. **输入 AMT 设备信息**
|
||||||
|
- IP 地址:输入 AMT 设备的 IP 地址
|
||||||
|
- 认证方式:
|
||||||
|
- 方式一:切换到"手动输入",填写用户名和密码
|
||||||
|
- 方式二:切换到"使用已保存凭证",从下拉框选择凭证
|
||||||
|
|
||||||
|
5. **测试连接**
|
||||||
|
- 点击"测试连接"按钮
|
||||||
|
- 等待测试结果
|
||||||
|
- 成功后会显示绿色的"连接成功"标签
|
||||||
|
|
||||||
|
6. **确认设备信息**
|
||||||
|
- 系统自动填充设备名称、UUID、IP地址、MAC地址
|
||||||
|
- 可以修改设备名称和备注
|
||||||
|
- 选择设备状态
|
||||||
|
|
||||||
|
7. **保存设备**
|
||||||
|
- 点击"确定"按钮保存设备
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
|
||||||
|
1. **网络连接**
|
||||||
|
- 确保服务器能够访问 AMT 设备的 16992 端口
|
||||||
|
- 检查防火墙设置
|
||||||
|
|
||||||
|
2. **AMT 配置**
|
||||||
|
- AMT 设备必须已启用并配置
|
||||||
|
- 确认 AMT 管理员账号可用
|
||||||
|
|
||||||
|
3. **安全性**
|
||||||
|
- 建议使用已保存的凭证而不是每次手动输入
|
||||||
|
- 定期更新 AMT 密码
|
||||||
|
|
||||||
|
4. **错误处理**
|
||||||
|
- 连接失败时会显示具体错误信息
|
||||||
|
- 常见错误:
|
||||||
|
- 网络不可达
|
||||||
|
- 认证失败
|
||||||
|
- AMT 未启用
|
||||||
|
|
||||||
|
## 文件清单
|
||||||
|
|
||||||
|
### 后端文件
|
||||||
|
- `backend/src/main/java/com/soybean/admin/service/AmtDigestService.java` - AMT Digest 认证服务
|
||||||
|
- `backend/src/main/java/com/soybean/admin/dto/AmtTestRequest.java` - 测试请求 DTO
|
||||||
|
- `backend/src/main/java/com/soybean/admin/dto/AmtDeviceInfo.java` - 设备信息 DTO
|
||||||
|
- `backend/src/main/java/com/soybean/admin/controller/DeviceController.java` - 设备控制器(已更新)
|
||||||
|
|
||||||
|
### 前端文件
|
||||||
|
- `src/views/device/list/index.vue` - 设备列表页面(已更新)
|
||||||
|
- `src/service/api/device.ts` - 设备 API(已更新)
|
||||||
|
- `src/typings/api/device.d.ts` - 设备类型定义(已更新)
|
||||||
|
|
||||||
|
### 工具文件
|
||||||
|
- `rebuild_and_test_amt.bat` - 重新编译和测试脚本
|
||||||
|
- `AMT_DEVICE_ADD_FEATURE.md` - 本说明文档
|
||||||
|
|
||||||
|
## 测试建议
|
||||||
|
|
||||||
|
1. **单元测试**
|
||||||
|
- 测试 AMT 连接功能
|
||||||
|
- 测试设备信息获取
|
||||||
|
- 测试凭证集成
|
||||||
|
|
||||||
|
2. **集成测试**
|
||||||
|
- 使用真实 AMT 设备测试
|
||||||
|
- 测试不同的认证方式
|
||||||
|
- 测试错误处理
|
||||||
|
|
||||||
|
3. **用户测试**
|
||||||
|
- 测试完整的添加流程
|
||||||
|
- 验证用户体验
|
||||||
|
- 收集反馈
|
||||||
|
|
||||||
|
## 未来改进
|
||||||
|
|
||||||
|
1. **批量发现**
|
||||||
|
- 支持 IP 段扫描
|
||||||
|
- 批量添加多个设备
|
||||||
|
|
||||||
|
2. **更多设备信息**
|
||||||
|
- 获取 CPU、内存等硬件信息
|
||||||
|
- 获取 AMT 版本信息
|
||||||
|
- 获取设备序列号
|
||||||
|
|
||||||
|
3. **高级功能**
|
||||||
|
- 支持 TLS 加密连接
|
||||||
|
- 支持证书认证
|
||||||
|
- 支持 Kerberos 认证
|
||||||
|
|
||||||
|
4. **监控集成**
|
||||||
|
- 定期检查设备状态
|
||||||
|
- AMT 事件日志收集
|
||||||
|
- 设备健康度监控
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 问题:连接超时
|
||||||
|
**原因**:网络不可达或防火墙阻止
|
||||||
|
**解决**:
|
||||||
|
- 检查网络连接
|
||||||
|
- 确认防火墙规则
|
||||||
|
- 验证 AMT 端口 16992 是否开放
|
||||||
|
|
||||||
|
### 问题:认证失败
|
||||||
|
**原因**:用户名或密码错误
|
||||||
|
**解决**:
|
||||||
|
- 确认 AMT 管理员账号
|
||||||
|
- 重置 AMT 密码
|
||||||
|
- 检查凭证配置
|
||||||
|
|
||||||
|
### 问题:无法获取设备信息
|
||||||
|
**原因**:AMT 未完全配置或版本不兼容
|
||||||
|
**解决**:
|
||||||
|
- 检查 AMT 配置状态
|
||||||
|
- 确认 AMT 版本
|
||||||
|
- 查看 AMT 日志
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- [Intel AMT SDK Documentation](https://software.intel.com/sites/manageability/)
|
||||||
|
- [WS-Management Protocol](https://www.dmtf.org/standards/ws-man)
|
||||||
|
- [Intel vPro Technology](https://www.intel.com/content/www/us/en/architecture-and-technology/vpro/vpro-technology-general.html)
|
||||||
221
AMT_NO_LOGS_FIX.md
Normal file
221
AMT_NO_LOGS_FIX.md
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
# AMT 功能无日志问题修复指南
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
|
||||||
|
点击"测试连接"后,后端没有任何日志输出,直接显示超时错误。
|
||||||
|
|
||||||
|
## 可能原因
|
||||||
|
|
||||||
|
1. **代码未编译**:新添加的代码没有被编译
|
||||||
|
2. **后端未重启**:修改后没有重启后端服务
|
||||||
|
3. **请求未到达后端**:前端请求没有正确发送到后端
|
||||||
|
4. **端口问题**:后端端口被占用或配置错误
|
||||||
|
|
||||||
|
## 解决步骤
|
||||||
|
|
||||||
|
### 步骤 1:停止当前后端服务
|
||||||
|
|
||||||
|
如果后端正在运行,先停止它:
|
||||||
|
- 在运行后端的命令行窗口按 `Ctrl+C`
|
||||||
|
- 或者关闭运行后端的窗口
|
||||||
|
|
||||||
|
### 步骤 2:重新编译并启动后端
|
||||||
|
|
||||||
|
运行以下脚本:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
rebuild_backend_with_logs.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
这个脚本会:
|
||||||
|
1. 清理旧的编译文件
|
||||||
|
2. 重新编译所有代码
|
||||||
|
3. 启动后端服务并显示详细日志
|
||||||
|
|
||||||
|
### 步骤 3:验证后端是否正常运行
|
||||||
|
|
||||||
|
在新的命令行窗口运行:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
test_amt_api.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
这个脚本会测试:
|
||||||
|
1. 后端是否运行
|
||||||
|
2. AMT API 是否可访问
|
||||||
|
3. 模拟模式状态
|
||||||
|
|
||||||
|
### 步骤 4:查看日志输出
|
||||||
|
|
||||||
|
启动后端后,你应该能看到类似的日志:
|
||||||
|
|
||||||
|
```
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [main] c.s.a.Application : Starting Application
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [main] c.s.a.Application : Started Application in x.xxx seconds
|
||||||
|
```
|
||||||
|
|
||||||
|
当你点击"测试连接"时,应该看到:
|
||||||
|
|
||||||
|
```
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.c.DeviceController : 收到 AMT 测试连接请求,IP: 192.168.1.100, 模拟模式: false
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.c.DeviceController : 使用真实 AMT 服务测试连接
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.s.AmtService : 开始测试 AMT 连接,IP: 192.168.1.100
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.s.AmtService : 使用手动输入的凭证,用户名: admin
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.s.AmtService : 准备发送 WS-Management 请求到: 192.168.1.100
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 5:如果仍然没有日志
|
||||||
|
|
||||||
|
#### 5.1 检查后端是否真的在运行
|
||||||
|
|
||||||
|
```batch
|
||||||
|
netstat -ano | findstr 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
应该看到端口 8080 被占用。
|
||||||
|
|
||||||
|
#### 5.2 检查前端请求是否发送
|
||||||
|
|
||||||
|
打开浏览器开发者工具(F12),切换到 Network 标签,点击"测试连接",查看是否有请求发送到 `/device/amt/test`。
|
||||||
|
|
||||||
|
#### 5.3 检查请求 URL
|
||||||
|
|
||||||
|
确认前端请求的 URL 是:
|
||||||
|
```
|
||||||
|
POST http://localhost:8080/device/amt/test
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.4 检查 CORS 问题
|
||||||
|
|
||||||
|
如果看到 CORS 错误,需要在后端添加 CORS 配置。
|
||||||
|
|
||||||
|
### 步骤 6:使用模拟模式测试
|
||||||
|
|
||||||
|
如果真实 AMT 连接有问题,先用模拟模式测试功能:
|
||||||
|
|
||||||
|
#### 方法 1:修改代码
|
||||||
|
|
||||||
|
编辑 `backend/src/main/java/com/soybean/admin/controller/DeviceController.java`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 将这一行
|
||||||
|
private boolean useMockMode = false;
|
||||||
|
|
||||||
|
// 改为
|
||||||
|
private boolean useMockMode = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
然后重新编译并启动。
|
||||||
|
|
||||||
|
#### 方法 2:使用 API 切换
|
||||||
|
|
||||||
|
发送 POST 请求:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
curl -X POST http://localhost:8080/device/amt/toggleMock
|
||||||
|
```
|
||||||
|
|
||||||
|
或者在浏览器中访问:
|
||||||
|
```
|
||||||
|
http://localhost:8080/device/amt/toggleMock
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 7:测试模拟模式
|
||||||
|
|
||||||
|
启用模拟模式后:
|
||||||
|
1. IP 地址:任意(如 192.168.1.100)
|
||||||
|
2. 用户名:`admin`
|
||||||
|
3. 密码:`admin`
|
||||||
|
4. 点击"测试连接"
|
||||||
|
|
||||||
|
应该会成功并显示日志:
|
||||||
|
|
||||||
|
```
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.c.DeviceController : 收到 AMT 测试连接请求,IP: 192.168.1.100, 模拟模式: true
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.c.DeviceController : 使用模拟模式测试连接
|
||||||
|
2024-xx-xx xx:xx:xx.xxx INFO xxxxx --- [http-nio-8080-exec-1] c.s.a.c.DeviceController : AMT 测试连接结果: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q1: 编译失败
|
||||||
|
|
||||||
|
**错误**:`mvn clean compile` 失败
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 检查 Java 版本:`java -version`(需要 Java 8 或更高)
|
||||||
|
2. 检查 Maven 版本:`mvn -version`
|
||||||
|
3. 查看错误信息,可能缺少依赖
|
||||||
|
|
||||||
|
### Q2: 端口被占用
|
||||||
|
|
||||||
|
**错误**:`Port 8080 was already in use`
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 找到占用端口的进程:
|
||||||
|
```batch
|
||||||
|
netstat -ano | findstr 8080
|
||||||
|
```
|
||||||
|
2. 结束进程:
|
||||||
|
```batch
|
||||||
|
taskkill /PID <进程ID> /F
|
||||||
|
```
|
||||||
|
3. 或者修改端口(在 `application.properties` 中)
|
||||||
|
|
||||||
|
### Q3: 前端请求超时
|
||||||
|
|
||||||
|
**错误**:前端显示 `timeout of 10000ms exceeded`
|
||||||
|
|
||||||
|
**原因**:
|
||||||
|
- 后端未运行
|
||||||
|
- 后端处理请求时间过长
|
||||||
|
- 网络问题
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 确认后端正在运行
|
||||||
|
2. 查看后端日志是否有错误
|
||||||
|
3. 使用模拟模式测试
|
||||||
|
|
||||||
|
### Q4: 看不到详细日志
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 确认使用 `rebuild_backend_with_logs.bat` 启动
|
||||||
|
2. 或者在 `application.properties` 中添加:
|
||||||
|
```properties
|
||||||
|
logging.level.com.soybean.admin=DEBUG
|
||||||
|
```
|
||||||
|
|
||||||
|
## 验证清单
|
||||||
|
|
||||||
|
- [ ] 后端已停止旧的进程
|
||||||
|
- [ ] 运行了 `rebuild_backend_with_logs.bat`
|
||||||
|
- [ ] 看到后端启动成功的日志
|
||||||
|
- [ ] 端口 8080 正常监听
|
||||||
|
- [ ] 运行了 `test_amt_api.bat` 验证 API
|
||||||
|
- [ ] 前端可以访问
|
||||||
|
- [ ] 点击"测试连接"时后端有日志输出
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
如果完成以上步骤后:
|
||||||
|
|
||||||
|
1. **有日志但连接失败**:
|
||||||
|
- 查看 `AMT_TROUBLESHOOTING.md`
|
||||||
|
- 使用 `quick_amt_test.bat` 诊断网络
|
||||||
|
|
||||||
|
2. **模拟模式正常**:
|
||||||
|
- 说明代码和流程没问题
|
||||||
|
- 专注于解决真实 AMT 连接问题
|
||||||
|
|
||||||
|
3. **仍然没有日志**:
|
||||||
|
- 检查防火墙设置
|
||||||
|
- 检查前端配置
|
||||||
|
- 查看浏览器控制台错误
|
||||||
|
|
||||||
|
## 获取帮助
|
||||||
|
|
||||||
|
如果问题仍未解决:
|
||||||
|
1. 复制完整的错误信息
|
||||||
|
2. 复制后端日志
|
||||||
|
3. 复制浏览器控制台错误
|
||||||
|
4. 说明已尝试的步骤
|
||||||
242
AMT_QUICK_START.md
Normal file
242
AMT_QUICK_START.md
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
# AMT 设备添加功能 - 快速开始
|
||||||
|
|
||||||
|
## 问题诊断
|
||||||
|
|
||||||
|
### 超时错误:timeout of 10000ms exceeded
|
||||||
|
|
||||||
|
这个错误表示无法连接到 AMT 设备。请按以下步骤排查:
|
||||||
|
|
||||||
|
## 步骤 1:运行快速测试
|
||||||
|
|
||||||
|
运行 `quick_amt_test.bat` 进行基本连接测试:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
quick_amt_test.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
输入 AMT 设备的 IP 地址,查看测试结果。
|
||||||
|
|
||||||
|
### 测试结果分析
|
||||||
|
|
||||||
|
#### 情况 1:Ping 失败
|
||||||
|
**问题**:网络不可达
|
||||||
|
**解决**:
|
||||||
|
- 检查 IP 地址是否正确
|
||||||
|
- 检查网络连接
|
||||||
|
- 确认设备已开机
|
||||||
|
|
||||||
|
#### 情况 2:Ping 成功,但端口关闭
|
||||||
|
**问题**:AMT 未启用或服务未运行
|
||||||
|
**解决**:
|
||||||
|
1. 在 AMT 设备上启用 AMT
|
||||||
|
2. 检查 AMT 服务状态
|
||||||
|
3. 检查防火墙设置
|
||||||
|
|
||||||
|
#### 情况 3:端口开放,但连接超时
|
||||||
|
**问题**:AMT 配置问题或认证失败
|
||||||
|
**解决**:
|
||||||
|
1. 检查 AMT 用户名和密码
|
||||||
|
2. 尝试重启 AMT 服务
|
||||||
|
3. 查看 AMT 配置
|
||||||
|
|
||||||
|
## 步骤 2:使用模拟模式测试功能
|
||||||
|
|
||||||
|
如果暂时没有真实的 AMT 设备,可以使用模拟模式测试功能:
|
||||||
|
|
||||||
|
### 启用模拟模式
|
||||||
|
|
||||||
|
1. **方法 1:修改代码**
|
||||||
|
|
||||||
|
编辑 `backend/src/main/java/com/soybean/admin/controller/DeviceController.java`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 将这一行
|
||||||
|
private boolean useMockMode = false;
|
||||||
|
|
||||||
|
// 改为
|
||||||
|
private boolean useMockMode = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **方法 2:使用 API 切换**
|
||||||
|
|
||||||
|
发送 POST 请求到:
|
||||||
|
```
|
||||||
|
POST http://localhost:8080/device/amt/toggleMock
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用模拟模式
|
||||||
|
|
||||||
|
启用模拟模式后:
|
||||||
|
|
||||||
|
1. 在设备列表点击"新增设备"
|
||||||
|
2. 选择"AMT 自动添加"
|
||||||
|
3. 输入任意 IP 地址(如 192.168.1.100)
|
||||||
|
4. 用户名:`admin`
|
||||||
|
5. 密码:`admin`
|
||||||
|
6. 点击"测试连接"
|
||||||
|
7. 应该会成功并自动填充设备信息
|
||||||
|
|
||||||
|
### 模拟模式说明
|
||||||
|
|
||||||
|
- 模拟模式仅用于测试界面和流程
|
||||||
|
- 不会真正连接到 AMT 设备
|
||||||
|
- 测试账号:admin/admin
|
||||||
|
- 会生成模拟的设备信息
|
||||||
|
|
||||||
|
## 步骤 3:配置真实 AMT 设备
|
||||||
|
|
||||||
|
### 3.1 启用 AMT
|
||||||
|
|
||||||
|
1. **进入 BIOS/UEFI**
|
||||||
|
- 重启设备
|
||||||
|
- 按 F2 或 Del 进入 BIOS
|
||||||
|
|
||||||
|
2. **进入 Intel ME 配置**
|
||||||
|
- 在 BIOS 中找到 Intel ME 或 AMT 选项
|
||||||
|
- 或者在开机时按 Ctrl+P 直接进入 MEBx
|
||||||
|
|
||||||
|
3. **启用 AMT**
|
||||||
|
- Intel(R) ME Configuration
|
||||||
|
- Intel(R) AMT Configuration
|
||||||
|
- Manageability Feature Selection
|
||||||
|
- 选择 "Intel AMT"
|
||||||
|
|
||||||
|
4. **配置网络**
|
||||||
|
- Network Setup
|
||||||
|
- TCP/IP Settings
|
||||||
|
- 选择 DHCP 或配置静态 IP
|
||||||
|
|
||||||
|
5. **设置管理员密码**
|
||||||
|
- MEBx Password
|
||||||
|
- 设置强密码(至少 8 位,包含大小写字母、数字和特殊字符)
|
||||||
|
- 记住这个密码!
|
||||||
|
|
||||||
|
6. **激活 AMT**
|
||||||
|
- Activate Network Access
|
||||||
|
- 选择激活方式(通常选择 "Host Based")
|
||||||
|
|
||||||
|
7. **保存并退出**
|
||||||
|
- 保存设置
|
||||||
|
- 退出并重启
|
||||||
|
|
||||||
|
### 3.2 验证 AMT 配置
|
||||||
|
|
||||||
|
在 Windows 上验证 AMT 是否正常运行:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
# 检查 LMS 服务状态
|
||||||
|
sc query LMS
|
||||||
|
|
||||||
|
# 如果服务未运行,启动它
|
||||||
|
net start LMS
|
||||||
|
|
||||||
|
# 检查端口是否监听
|
||||||
|
netstat -ano | findstr 16992
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 测试 AMT 连接
|
||||||
|
|
||||||
|
使用 PowerShell 测试:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 替换为你的 AMT 设备 IP
|
||||||
|
$amtIP = "192.168.1.100"
|
||||||
|
|
||||||
|
# 测试端口
|
||||||
|
Test-NetConnection -ComputerName $amtIP -Port 16992
|
||||||
|
|
||||||
|
# 如果端口开放,尝试连接
|
||||||
|
$username = "admin"
|
||||||
|
$password = "your_amt_password"
|
||||||
|
$base64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
|
||||||
|
|
||||||
|
$headers = @{
|
||||||
|
"Authorization" = "Basic $base64"
|
||||||
|
"Content-Type" = "application/soap+xml;charset=UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = @"
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd">
|
||||||
|
<s:Header/>
|
||||||
|
<s:Body>
|
||||||
|
<wsmid:Identify/>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
||||||
|
"@
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = Invoke-WebRequest -Uri "http://${amtIP}:16992/wsman" -Method POST -Headers $headers -Body $body
|
||||||
|
Write-Host "连接成功!" -ForegroundColor Green
|
||||||
|
Write-Host $response.Content
|
||||||
|
} catch {
|
||||||
|
Write-Host "连接失败:$($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 步骤 4:在系统中使用
|
||||||
|
|
||||||
|
### 4.1 保存 AMT 凭证(推荐)
|
||||||
|
|
||||||
|
1. 进入"系统设置" > "AMT 设置"
|
||||||
|
2. 点击"新增凭证"
|
||||||
|
3. 输入凭证名称、用户名和密码
|
||||||
|
4. 保存
|
||||||
|
|
||||||
|
### 4.2 添加 AMT 设备
|
||||||
|
|
||||||
|
1. 进入"设备管理" > "设备列表"
|
||||||
|
2. 点击"新增设备"
|
||||||
|
3. 选择"AMT 自动添加"
|
||||||
|
4. 输入 IP 地址
|
||||||
|
5. 选择认证方式:
|
||||||
|
- 使用已保存凭证:从下拉框选择
|
||||||
|
- 手动输入:填写用户名和密码
|
||||||
|
6. 点击"测试连接"
|
||||||
|
7. 连接成功后,确认设备信息
|
||||||
|
8. 点击"确定"保存
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q1: 超时错误怎么办?
|
||||||
|
**A**: 运行 `quick_amt_test.bat` 诊断网络连接问题。
|
||||||
|
|
||||||
|
### Q2: 401 认证失败怎么办?
|
||||||
|
**A**: 检查用户名和密码是否正确,确认 AMT 已正确配置。
|
||||||
|
|
||||||
|
### Q3: 没有真实 AMT 设备怎么测试?
|
||||||
|
**A**: 启用模拟模式,使用 admin/admin 测试。
|
||||||
|
|
||||||
|
### Q4: 如何知道 AMT 是否已启用?
|
||||||
|
**A**:
|
||||||
|
- 检查 LMS 服务是否运行
|
||||||
|
- 测试端口 16992 是否开放
|
||||||
|
- 尝试访问 http://AMT_IP:16992/wsman
|
||||||
|
|
||||||
|
### Q5: 支持哪些 AMT 版本?
|
||||||
|
**A**: 支持 AMT 6.0 及以上版本。
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
- 查看 `AMT_TROUBLESHOOTING.md` 了解详细的故障排除
|
||||||
|
- 查看 `AMT_DEVICE_ADD_FEATURE.md` 了解完整功能说明
|
||||||
|
- 配置更多 AMT 设备
|
||||||
|
- 探索远程控制功能
|
||||||
|
|
||||||
|
## 获取帮助
|
||||||
|
|
||||||
|
如果遇到问题:
|
||||||
|
1. 查看错误信息
|
||||||
|
2. 运行诊断工具
|
||||||
|
3. 查阅故障排除文档
|
||||||
|
4. 检查 AMT 设备配置
|
||||||
|
5. 查看系统日志
|
||||||
|
|
||||||
|
## 重要提示
|
||||||
|
|
||||||
|
⚠️ **安全警告**:
|
||||||
|
- 使用强密码
|
||||||
|
- 限制网络访问
|
||||||
|
- 定期更新固件
|
||||||
|
- 不要在生产环境使用模拟模式
|
||||||
269
AMT_TROUBLESHOOTING.md
Normal file
269
AMT_TROUBLESHOOTING.md
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
# AMT 连接故障排除指南
|
||||||
|
|
||||||
|
## 常见错误及解决方案
|
||||||
|
|
||||||
|
### 错误 1: HTTP 401 - 认证失败
|
||||||
|
|
||||||
|
**错误信息**:`AMT 连接测试失败: HTTP 错误: 401`
|
||||||
|
|
||||||
|
**可能原因**:
|
||||||
|
1. 用户名或密码错误
|
||||||
|
2. AMT 未正确配置
|
||||||
|
3. 需要使用 Digest 认证而不是 Basic 认证
|
||||||
|
4. 需要使用 HTTPS 而不是 HTTP
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
|
||||||
|
#### 方案 1:检查 AMT 凭证
|
||||||
|
1. 确认 AMT 管理员用户名(通常是 `admin`)
|
||||||
|
2. 确认 AMT 管理员密码
|
||||||
|
3. 尝试使用 AMT 配置工具重置密码
|
||||||
|
|
||||||
|
#### 方案 2:检查 AMT 配置状态
|
||||||
|
在 AMT 设备上:
|
||||||
|
1. 重启进入 BIOS/UEFI
|
||||||
|
2. 按 Ctrl+P 进入 Intel ME 配置
|
||||||
|
3. 检查 AMT 是否已启用
|
||||||
|
4. 检查网络配置是否正确
|
||||||
|
|
||||||
|
#### 方案 3:使用测试工具诊断
|
||||||
|
运行 `test_amt_connection.bat` 进行详细诊断:
|
||||||
|
```batch
|
||||||
|
test_amt_connection.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
输入 IP 地址和用户名,查看详细的连接测试结果。
|
||||||
|
|
||||||
|
#### 方案 4:手动测试 AMT 连接
|
||||||
|
|
||||||
|
使用 PowerShell 测试:
|
||||||
|
```powershell
|
||||||
|
# 测试端口
|
||||||
|
Test-NetConnection -ComputerName 192.168.1.100 -Port 16992
|
||||||
|
|
||||||
|
# 测试 HTTP 连接
|
||||||
|
$username = "admin"
|
||||||
|
$password = "your_password"
|
||||||
|
$base64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
|
||||||
|
|
||||||
|
$headers = @{
|
||||||
|
"Authorization" = "Basic $base64"
|
||||||
|
"Content-Type" = "application/soap+xml;charset=UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = @"
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd">
|
||||||
|
<s:Header/>
|
||||||
|
<s:Body>
|
||||||
|
<wsmid:Identify/>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
||||||
|
"@
|
||||||
|
|
||||||
|
Invoke-WebRequest -Uri "http://192.168.1.100:16992/wsman" -Method POST -Headers $headers -Body $body
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方案 5:尝试 HTTPS 连接
|
||||||
|
|
||||||
|
某些 AMT 配置要求使用 HTTPS:
|
||||||
|
- HTTP 端口:16992
|
||||||
|
- HTTPS 端口:16993
|
||||||
|
|
||||||
|
修改代码已支持自动尝试 HTTPS,重新编译后端即可。
|
||||||
|
|
||||||
|
### 错误 2: 连接超时
|
||||||
|
|
||||||
|
**错误信息**:`AMT 连接超时`
|
||||||
|
|
||||||
|
**可能原因**:
|
||||||
|
1. IP 地址错误
|
||||||
|
2. 网络不可达
|
||||||
|
3. 防火墙阻止
|
||||||
|
4. AMT 未启用
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
|
||||||
|
1. **检查网络连接**
|
||||||
|
```batch
|
||||||
|
ping 192.168.1.100
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **检查端口是否开放**
|
||||||
|
```batch
|
||||||
|
telnet 192.168.1.100 16992
|
||||||
|
```
|
||||||
|
或使用 PowerShell:
|
||||||
|
```powershell
|
||||||
|
Test-NetConnection -ComputerName 192.168.1.100 -Port 16992
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **检查防火墙规则**
|
||||||
|
- Windows 防火墙
|
||||||
|
- 网络防火墙
|
||||||
|
- AMT 设备防火墙
|
||||||
|
|
||||||
|
4. **确认 AMT 已启用**
|
||||||
|
- 进入 BIOS/UEFI
|
||||||
|
- 检查 Intel ME 配置
|
||||||
|
- 确认 AMT 服务正在运行
|
||||||
|
|
||||||
|
### 错误 3: 连接被拒绝
|
||||||
|
|
||||||
|
**错误信息**:`Connection refused`
|
||||||
|
|
||||||
|
**可能原因**:
|
||||||
|
1. AMT 服务未运行
|
||||||
|
2. 端口被占用
|
||||||
|
3. AMT 未正确配置
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
|
||||||
|
1. **检查 AMT 服务状态**
|
||||||
|
在 AMT 设备上运行:
|
||||||
|
```batch
|
||||||
|
sc query LMS
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **重启 AMT 服务**
|
||||||
|
```batch
|
||||||
|
net stop LMS
|
||||||
|
net start LMS
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **检查端口占用**
|
||||||
|
```batch
|
||||||
|
netstat -ano | findstr 16992
|
||||||
|
```
|
||||||
|
|
||||||
|
## AMT 配置检查清单
|
||||||
|
|
||||||
|
### 基本配置
|
||||||
|
- [ ] AMT 已在 BIOS/UEFI 中启用
|
||||||
|
- [ ] 设置了 AMT 管理员密码
|
||||||
|
- [ ] 配置了网络设置(IP、子网掩码、网关)
|
||||||
|
- [ ] AMT 服务正在运行
|
||||||
|
|
||||||
|
### 网络配置
|
||||||
|
- [ ] AMT 设备网络可达
|
||||||
|
- [ ] 防火墙允许端口 16992 (HTTP) 和 16993 (HTTPS)
|
||||||
|
- [ ] 没有网络隔离或 VLAN 限制
|
||||||
|
|
||||||
|
### 认证配置
|
||||||
|
- [ ] 知道正确的管理员用户名
|
||||||
|
- [ ] 知道正确的管理员密码
|
||||||
|
- [ ] 密码符合复杂度要求
|
||||||
|
|
||||||
|
## 使用 Intel AMT 配置工具
|
||||||
|
|
||||||
|
### Intel ME Configuration Tool (MEBx)
|
||||||
|
|
||||||
|
1. **进入 MEBx**
|
||||||
|
- 开机时按 Ctrl+P
|
||||||
|
- 默认密码:admin
|
||||||
|
|
||||||
|
2. **启用 AMT**
|
||||||
|
- Intel(R) ME Configuration
|
||||||
|
- Intel(R) AMT Configuration
|
||||||
|
- Manageability Feature Selection
|
||||||
|
- 选择 "Intel AMT"
|
||||||
|
|
||||||
|
3. **配置网络**
|
||||||
|
- Network Setup
|
||||||
|
- TCP/IP Settings
|
||||||
|
- 配置 IP 地址(DHCP 或静态)
|
||||||
|
|
||||||
|
4. **设置密码**
|
||||||
|
- MEBx Password
|
||||||
|
- 设置强密码(至少 8 位,包含大小写字母和数字)
|
||||||
|
|
||||||
|
5. **激活 AMT**
|
||||||
|
- Activate Network Access
|
||||||
|
- 选择激活方式
|
||||||
|
|
||||||
|
### Intel Setup and Configuration Service (SCS)
|
||||||
|
|
||||||
|
使用 Intel SCS 进行批量配置:
|
||||||
|
1. 下载 Intel SCS
|
||||||
|
2. 创建配置文件
|
||||||
|
3. 批量部署到设备
|
||||||
|
|
||||||
|
## 常用 AMT 命令
|
||||||
|
|
||||||
|
### 使用 PowerShell 模块
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 安装 Intel vPro 模块
|
||||||
|
Install-Module -Name IntelVPro
|
||||||
|
|
||||||
|
# 连接到 AMT 设备
|
||||||
|
$cred = Get-Credential
|
||||||
|
Connect-AMT -ComputerName 192.168.1.100 -Credential $cred
|
||||||
|
|
||||||
|
# 获取设备信息
|
||||||
|
Get-AMTSystemInfo
|
||||||
|
|
||||||
|
# 获取电源状态
|
||||||
|
Get-AMTPowerState
|
||||||
|
|
||||||
|
# 远程开机
|
||||||
|
Invoke-AMTPowerAction -Action PowerOn
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 WSMAN 命令行
|
||||||
|
|
||||||
|
```batch
|
||||||
|
# 测试连接
|
||||||
|
wsman identify -r:http://192.168.1.100:16992/wsman -auth:basic -u:admin -p:password
|
||||||
|
|
||||||
|
# 获取系统信息
|
||||||
|
wsman get http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem -r:http://192.168.1.100:16992/wsman -auth:basic -u:admin -p:password
|
||||||
|
```
|
||||||
|
|
||||||
|
## 推荐的 AMT 设置
|
||||||
|
|
||||||
|
### 安全设置
|
||||||
|
- 使用强密码(至少 12 位)
|
||||||
|
- 启用 TLS/SSL
|
||||||
|
- 限制访问 IP 范围
|
||||||
|
- 定期更新固件
|
||||||
|
|
||||||
|
### 网络设置
|
||||||
|
- 使用静态 IP(便于管理)
|
||||||
|
- 配置正确的 DNS
|
||||||
|
- 确保网络稳定
|
||||||
|
|
||||||
|
### 功能设置
|
||||||
|
- 启用远程控制
|
||||||
|
- 启用 KVM(键盘视频鼠标)
|
||||||
|
- 启用 IDE-R(IDE 重定向)
|
||||||
|
- 启用 SOL(串行控制台)
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- [Intel AMT 官方文档](https://software.intel.com/sites/manageability/)
|
||||||
|
- [Intel vPro 技术指南](https://www.intel.com/content/www/us/en/architecture-and-technology/vpro/vpro-technology-general.html)
|
||||||
|
- [WS-Management 协议规范](https://www.dmtf.org/standards/ws-man)
|
||||||
|
|
||||||
|
## 获取帮助
|
||||||
|
|
||||||
|
如果以上方法都无法解决问题:
|
||||||
|
|
||||||
|
1. 检查 AMT 设备日志
|
||||||
|
2. 查看系统事件日志
|
||||||
|
3. 联系设备制造商支持
|
||||||
|
4. 查阅 Intel AMT 社区论坛
|
||||||
|
|
||||||
|
## 调试模式
|
||||||
|
|
||||||
|
在开发环境中启用详细日志:
|
||||||
|
|
||||||
|
1. 修改 `application.properties`:
|
||||||
|
```properties
|
||||||
|
logging.level.com.soybean.admin.service.AmtService=DEBUG
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 查看详细的请求和响应日志
|
||||||
|
|
||||||
|
3. 使用网络抓包工具(如 Wireshark)分析流量
|
||||||
@ -77,6 +77,13 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Apache HttpClient for Digest Authentication -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||||
|
<artifactId>httpclient5</artifactId>
|
||||||
|
<version>5.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring Boot Test -->
|
<!-- Spring Boot Test -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@ -4,8 +4,14 @@ import com.soybean.admin.common.Result;
|
|||||||
import com.soybean.admin.dto.DeviceDTO;
|
import com.soybean.admin.dto.DeviceDTO;
|
||||||
import com.soybean.admin.dto.PageRequest;
|
import com.soybean.admin.dto.PageRequest;
|
||||||
import com.soybean.admin.dto.PageResponse;
|
import com.soybean.admin.dto.PageResponse;
|
||||||
|
import com.soybean.admin.dto.AmtTestRequest;
|
||||||
|
import com.soybean.admin.dto.AmtDeviceInfo;
|
||||||
import com.soybean.admin.entity.Device;
|
import com.soybean.admin.entity.Device;
|
||||||
|
import com.soybean.admin.service.AmtMockService;
|
||||||
import com.soybean.admin.service.DeviceService;
|
import com.soybean.admin.service.DeviceService;
|
||||||
|
import com.soybean.admin.service.AmtDigestService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -16,9 +22,20 @@ import java.util.Map;
|
|||||||
@RequestMapping("/device")
|
@RequestMapping("/device")
|
||||||
public class DeviceController {
|
public class DeviceController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(DeviceController.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceService deviceService;
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmtMockService amtMockService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmtDigestService amtDigestService;
|
||||||
|
|
||||||
|
// 是否使用模拟模式(用于测试)
|
||||||
|
private boolean useMockMode = false; // 改为 true 启用模拟模式
|
||||||
|
|
||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
public Result<PageResponse<Device>> getDeviceList(@RequestBody PageRequest pageRequest) {
|
public Result<PageResponse<Device>> getDeviceList(@RequestBody PageRequest pageRequest) {
|
||||||
try {
|
try {
|
||||||
@ -90,4 +107,58 @@ public class DeviceController {
|
|||||||
return Result.error(e.getMessage());
|
return Result.error(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/amt/test")
|
||||||
|
public Result<Boolean> testAmtConnection(@RequestBody AmtTestRequest request) {
|
||||||
|
logger.info("收到 AMT 测试连接请求,IP: {}, 模拟模式: {}", request.getIpAddress(), useMockMode);
|
||||||
|
try {
|
||||||
|
boolean success;
|
||||||
|
if (useMockMode) {
|
||||||
|
logger.info("使用模拟模式测试连接");
|
||||||
|
success = amtMockService.mockTestConnection(request);
|
||||||
|
} else {
|
||||||
|
// 使用 Digest 认证
|
||||||
|
logger.info("使用 Digest 认证测试连接");
|
||||||
|
success = amtDigestService.testAmtConnectionWithDigest(request);
|
||||||
|
logger.info("Digest 认证成功");
|
||||||
|
}
|
||||||
|
logger.info("AMT 测试连接结果: {}", success);
|
||||||
|
return Result.success(success);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("AMT 测试连接失败", e);
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/amt/getInfo")
|
||||||
|
public Result<AmtDeviceInfo> getAmtDeviceInfo(@RequestBody AmtTestRequest request) {
|
||||||
|
logger.info("收到获取 AMT 设备信息请求,IP: {}", request.getIpAddress());
|
||||||
|
try {
|
||||||
|
AmtDeviceInfo deviceInfo;
|
||||||
|
if (useMockMode) {
|
||||||
|
deviceInfo = amtMockService.mockGetDeviceInfo(request);
|
||||||
|
} else {
|
||||||
|
// 使用 Digest 认证
|
||||||
|
logger.info("使用 Digest 认证获取设备信息");
|
||||||
|
deviceInfo = amtDigestService.getAmtDeviceInfoWithDigest(request);
|
||||||
|
}
|
||||||
|
logger.info("成功获取 AMT 设备信息: {}", deviceInfo.getDeviceName());
|
||||||
|
return Result.success(deviceInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取 AMT 设备信息失败", e);
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/amt/toggleMock")
|
||||||
|
public Result<Boolean> toggleMockMode() {
|
||||||
|
useMockMode = !useMockMode;
|
||||||
|
logger.info("切换模拟模式: {}", useMockMode ? "已启用" : "已禁用");
|
||||||
|
return Result.success(useMockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/amt/mockStatus")
|
||||||
|
public Result<Boolean> getMockStatus() {
|
||||||
|
return Result.success(useMockMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AmtDeviceInfo {
|
||||||
|
private String deviceName;
|
||||||
|
private String deviceCode;
|
||||||
|
private String ipAddress;
|
||||||
|
private String macAddress;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AmtTestRequest {
|
||||||
|
private String ipAddress;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private Long credentialId; // 可选:使用已保存的凭证ID
|
||||||
|
}
|
||||||
@ -0,0 +1,218 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.soybean.admin.dto.AmtTestRequest;
|
||||||
|
import com.soybean.admin.dto.AmtDeviceInfo;
|
||||||
|
import com.soybean.admin.entity.AmtCredential;
|
||||||
|
import org.apache.hc.client5.http.auth.AuthScope;
|
||||||
|
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
|
||||||
|
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||||
|
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||||
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
|
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||||
|
import org.apache.hc.core5.http.io.entity.StringEntity;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMT Digest 认证服务
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class AmtDigestService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AmtDigestService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmtCredentialService amtCredentialService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 AMT 连接(使用 Digest 认证)
|
||||||
|
*/
|
||||||
|
public boolean testAmtConnectionWithDigest(AmtTestRequest request) {
|
||||||
|
logger.info("使用 Digest 认证测试 AMT 连接,IP: {}", request.getIpAddress());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String username;
|
||||||
|
String password;
|
||||||
|
|
||||||
|
if (request.getCredentialId() != null) {
|
||||||
|
AmtCredential credential = amtCredentialService.getCredentialById(request.getCredentialId().toString());
|
||||||
|
if (credential == null) {
|
||||||
|
throw new RuntimeException("凭证不存在");
|
||||||
|
}
|
||||||
|
username = credential.getUsername();
|
||||||
|
password = credential.getPassword();
|
||||||
|
} else {
|
||||||
|
username = request.getUsername();
|
||||||
|
password = request.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Digest 认证 - 用户名: {}", username);
|
||||||
|
|
||||||
|
String response = sendDigestRequest(
|
||||||
|
request.getIpAddress(),
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
getIdentifyRequest()
|
||||||
|
);
|
||||||
|
|
||||||
|
boolean success = response != null && (response.contains("IdentifyResponse") || response.contains("ProductVendor"));
|
||||||
|
logger.info("Digest 认证测试结果: {}", success);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Digest 认证测试失败", e);
|
||||||
|
throw new RuntimeException("AMT Digest 认证失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 AMT 设备信息(使用 Digest 认证)
|
||||||
|
*/
|
||||||
|
public AmtDeviceInfo getAmtDeviceInfoWithDigest(AmtTestRequest request) {
|
||||||
|
try {
|
||||||
|
String username;
|
||||||
|
String password;
|
||||||
|
|
||||||
|
if (request.getCredentialId() != null) {
|
||||||
|
AmtCredential credential = amtCredentialService.getCredentialById(request.getCredentialId().toString());
|
||||||
|
if (credential == null) {
|
||||||
|
throw new RuntimeException("凭证不存在");
|
||||||
|
}
|
||||||
|
username = credential.getUsername();
|
||||||
|
password = credential.getPassword();
|
||||||
|
} else {
|
||||||
|
username = request.getUsername();
|
||||||
|
password = request.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
AmtDeviceInfo deviceInfo = new AmtDeviceInfo();
|
||||||
|
|
||||||
|
String systemInfo = sendDigestRequest(
|
||||||
|
request.getIpAddress(),
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
getSystemInfoRequest()
|
||||||
|
);
|
||||||
|
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
factory.setNamespaceAware(true);
|
||||||
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
Document doc = builder.parse(new ByteArrayInputStream(systemInfo.getBytes()));
|
||||||
|
|
||||||
|
deviceInfo.setIpAddress(request.getIpAddress());
|
||||||
|
deviceInfo.setDeviceName(extractValue(doc, "ElementName"));
|
||||||
|
deviceInfo.setMacAddress("00:00:00:00:00:00"); // 简化处理
|
||||||
|
deviceInfo.setDeviceCode(UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
return deviceInfo;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("获取 AMT 设备信息失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 Digest 认证请求
|
||||||
|
*/
|
||||||
|
private String sendDigestRequest(String ipAddress, String username, String password, String soapRequest) throws Exception {
|
||||||
|
// 先尝试 HTTP
|
||||||
|
try {
|
||||||
|
return sendDigestRequestWithProtocol("http", ipAddress, 16992, username, password, soapRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("HTTP Digest 认证失败,尝试 HTTPS: {}", e.getMessage());
|
||||||
|
// 尝试 HTTPS
|
||||||
|
return sendDigestRequestWithProtocol("https", ipAddress, 16993, username, password, soapRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用指定协议发送 Digest 请求
|
||||||
|
*/
|
||||||
|
private String sendDigestRequestWithProtocol(String protocol, String ipAddress, int port,
|
||||||
|
String username, String password, String soapRequest) throws Exception {
|
||||||
|
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||||
|
credsProvider.setCredentials(
|
||||||
|
new AuthScope(ipAddress, port),
|
||||||
|
new UsernamePasswordCredentials(username, password.toCharArray())
|
||||||
|
);
|
||||||
|
|
||||||
|
try (CloseableHttpClient httpClient = HttpClients.custom()
|
||||||
|
.setDefaultCredentialsProvider(credsProvider)
|
||||||
|
.build()) {
|
||||||
|
|
||||||
|
HttpHost target = new HttpHost(protocol, ipAddress, port);
|
||||||
|
HttpPost httpPost = new HttpPost("/wsman");
|
||||||
|
httpPost.setHeader("Content-Type", "application/soap+xml;charset=UTF-8");
|
||||||
|
httpPost.setEntity(new StringEntity(soapRequest));
|
||||||
|
|
||||||
|
logger.info("发送 Digest 请求到: {}://{}:{}/wsman", protocol, ipAddress, port);
|
||||||
|
|
||||||
|
try (CloseableHttpResponse response = httpClient.execute(target, httpPost)) {
|
||||||
|
int statusCode = response.getCode();
|
||||||
|
logger.info("收到响应,状态码: {}", statusCode);
|
||||||
|
|
||||||
|
if (statusCode == 401) {
|
||||||
|
throw new RuntimeException("Digest 认证失败 (401)");
|
||||||
|
} else if (statusCode != 200) {
|
||||||
|
throw new RuntimeException("HTTP 错误: " + statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseBody = EntityUtils.toString(response.getEntity());
|
||||||
|
logger.info("响应长度: {} 字节", responseBody.length());
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getIdentifyRequest() {
|
||||||
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" " +
|
||||||
|
"xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\">" +
|
||||||
|
"<s:Header/>" +
|
||||||
|
"<s:Body>" +
|
||||||
|
"<wsmid:Identify/>" +
|
||||||
|
"</s:Body>" +
|
||||||
|
"</s:Envelope>";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSystemInfoRequest() {
|
||||||
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" " +
|
||||||
|
"xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" " +
|
||||||
|
"xmlns:wsman=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\">" +
|
||||||
|
"<s:Header>" +
|
||||||
|
"<wsa:Action s:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</wsa:Action>" +
|
||||||
|
"<wsa:To s:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>" +
|
||||||
|
"<wsman:ResourceURI s:mustUnderstand=\"true\">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</wsman:ResourceURI>" +
|
||||||
|
"<wsa:MessageID s:mustUnderstand=\"true\">uuid:" + UUID.randomUUID().toString() + "</wsa:MessageID>" +
|
||||||
|
"<wsa:ReplyTo>" +
|
||||||
|
"<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>" +
|
||||||
|
"</wsa:ReplyTo>" +
|
||||||
|
"</s:Header>" +
|
||||||
|
"<s:Body/>" +
|
||||||
|
"</s:Envelope>";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractValue(Document doc, String tagName) {
|
||||||
|
try {
|
||||||
|
NodeList nodeList = doc.getElementsByTagName(tagName);
|
||||||
|
if (nodeList.getLength() > 0) {
|
||||||
|
return nodeList.item(0).getTextContent();
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.soybean.admin.dto.AmtTestRequest;
|
||||||
|
import com.soybean.admin.dto.AmtDeviceInfo;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMT 模拟服务 - 用于测试和演示
|
||||||
|
* 当没有真实 AMT 设备时使用
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class AmtMockService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟测试 AMT 连接
|
||||||
|
*/
|
||||||
|
public boolean mockTestConnection(AmtTestRequest request) {
|
||||||
|
// 模拟延迟
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟成功(用户名为 admin 且密码为 admin 时成功)
|
||||||
|
if ("admin".equals(request.getUsername()) && "admin".equals(request.getPassword())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("模拟认证失败:用户名或密码错误(测试账号: admin/admin)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟获取 AMT 设备信息
|
||||||
|
*/
|
||||||
|
public AmtDeviceInfo mockGetDeviceInfo(AmtTestRequest request) {
|
||||||
|
// 模拟延迟
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
AmtDeviceInfo deviceInfo = new AmtDeviceInfo();
|
||||||
|
deviceInfo.setIpAddress(request.getIpAddress());
|
||||||
|
deviceInfo.setDeviceName("Mock-AMT-Device-" + request.getIpAddress().replace(".", "-"));
|
||||||
|
deviceInfo.setDeviceCode(UUID.randomUUID().toString());
|
||||||
|
deviceInfo.setMacAddress(generateMockMacAddress(request.getIpAddress()));
|
||||||
|
|
||||||
|
return deviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 IP 地址生成模拟 MAC 地址
|
||||||
|
*/
|
||||||
|
private String generateMockMacAddress(String ipAddress) {
|
||||||
|
String[] parts = ipAddress.split("\\.");
|
||||||
|
if (parts.length == 4) {
|
||||||
|
return String.format("00:11:22:%02X:%02X:%02X",
|
||||||
|
Integer.parseInt(parts[1]) % 256,
|
||||||
|
Integer.parseInt(parts[2]) % 256,
|
||||||
|
Integer.parseInt(parts[3]) % 256);
|
||||||
|
}
|
||||||
|
return "00:11:22:33:44:55";
|
||||||
|
}
|
||||||
|
}
|
||||||
48
enable_amt_mock_mode.bat
Normal file
48
enable_amt_mock_mode.bat
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 启用 AMT 模拟模式
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 此脚本将:
|
||||||
|
echo 1. 修改代码启用模拟模式
|
||||||
|
echo 2. 重新编译后端
|
||||||
|
echo 3. 启动后端服务
|
||||||
|
echo.
|
||||||
|
echo 模拟模式说明:
|
||||||
|
echo - 不需要真实的 AMT 设备
|
||||||
|
echo - 测试账号:admin / admin
|
||||||
|
echo - 用于测试界面和流程
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
|
||||||
|
cd backend\src\main\java\com\soybean\admin\controller
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [1/3] 修改 DeviceController.java...
|
||||||
|
|
||||||
|
powershell -Command "(Get-Content DeviceController.java) -replace 'private boolean useMockMode = false;', 'private boolean useMockMode = true;' | Set-Content DeviceController.java"
|
||||||
|
|
||||||
|
echo 已启用模拟模式
|
||||||
|
|
||||||
|
cd ..\..\..\..\..\..
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [2/3] 重新编译...
|
||||||
|
call mvn clean compile
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [3/3] 启动后端...
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 模拟模式已启用
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 测试账号:
|
||||||
|
echo 用户名:admin
|
||||||
|
echo 密码:admin
|
||||||
|
echo.
|
||||||
|
echo 可以使用任意 IP 地址进行测试
|
||||||
|
echo.
|
||||||
|
call mvn spring-boot:run
|
||||||
|
|
||||||
|
pause
|
||||||
41
quick_amt_test.bat
Normal file
41
quick_amt_test.bat
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 快速 AMT 连接测试
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
set /p AMT_IP="请输入 AMT 设备 IP 地址: "
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [测试 1] Ping 测试...
|
||||||
|
ping -n 4 %AMT_IP%
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [测试 2] 端口 16992 (HTTP) 测试...
|
||||||
|
powershell -Command "$result = Test-NetConnection -ComputerName %AMT_IP% -Port 16992 -WarningAction SilentlyContinue; if($result.TcpTestSucceeded) { Write-Host '端口 16992 开放 - 成功' -ForegroundColor Green } else { Write-Host '端口 16992 关闭 - 失败' -ForegroundColor Red }"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [测试 3] 端口 16993 (HTTPS) 测试...
|
||||||
|
powershell -Command "$result = Test-NetConnection -ComputerName %AMT_IP% -Port 16993 -WarningAction SilentlyContinue; if($result.TcpTestSucceeded) { Write-Host '端口 16993 开放 - 成功' -ForegroundColor Green } else { Write-Host '端口 16993 关闭 - 失败' -ForegroundColor Red }"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 诊断结果
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 如果 Ping 失败:
|
||||||
|
echo - 检查 IP 地址是否正确
|
||||||
|
echo - 检查网络连接
|
||||||
|
echo - 检查防火墙设置
|
||||||
|
echo.
|
||||||
|
echo 如果端口关闭:
|
||||||
|
echo - AMT 可能未启用
|
||||||
|
echo - 防火墙阻止了端口
|
||||||
|
echo - AMT 服务未运行
|
||||||
|
echo.
|
||||||
|
echo 如果端口开放但仍然超时:
|
||||||
|
echo - 检查 AMT 用户名和密码
|
||||||
|
echo - 尝试在 AMT 设备上重启 LMS 服务
|
||||||
|
echo.
|
||||||
|
|
||||||
|
pause
|
||||||
22
rebuild_and_test_amt.bat
Normal file
22
rebuild_and_test_amt.bat
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 重新编译后端并测试 AMT 功能
|
||||||
|
echo ========================================
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [1/3] 清理旧的编译文件...
|
||||||
|
call mvn clean
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [2/3] 编译项目...
|
||||||
|
call mvn compile
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [3/3] 启动后端服务...
|
||||||
|
echo 提示:后端将在 http://localhost:8080 启动
|
||||||
|
echo.
|
||||||
|
call mvn spring-boot:run
|
||||||
|
|
||||||
|
pause
|
||||||
40
rebuild_backend_with_logs.bat
Normal file
40
rebuild_backend_with_logs.bat
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 重新编译后端并启动(带详细日志)
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
echo [1/2] 清理并重新编译...
|
||||||
|
call mvn clean compile
|
||||||
|
|
||||||
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
|
echo.
|
||||||
|
echo 编译失败!请检查错误信息。
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [2/2] 启动后端服务(带详细日志)...
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 后端服务启动中...
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 日志级别:DEBUG
|
||||||
|
echo 端口:8080
|
||||||
|
echo.
|
||||||
|
echo 提示:
|
||||||
|
echo - 查看控制台输出了解详细日志
|
||||||
|
echo - AMT 测试连接时会显示详细的连接过程
|
||||||
|
echo - 按 Ctrl+C 停止服务
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM 设置日志级别为 DEBUG
|
||||||
|
set JAVA_OPTS=-Dlogging.level.com.soybean.admin=DEBUG
|
||||||
|
|
||||||
|
call mvn spring-boot:run
|
||||||
|
|
||||||
|
pause
|
||||||
33
rebuild_digest_only.bat
Normal file
33
rebuild_digest_only.bat
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 重新编译后端(仅 Digest 认证)
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
echo 清理旧的编译文件...
|
||||||
|
call mvn clean
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 重新编译项目...
|
||||||
|
call mvn compile
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 打包项目...
|
||||||
|
call mvn package -DskipTests
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 编译完成!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 现在可以启动后端服务:
|
||||||
|
echo cd backend
|
||||||
|
echo java -jar target/soybean-admin-0.0.1-SNAPSHOT.jar
|
||||||
|
echo.
|
||||||
|
echo 或者运行:
|
||||||
|
echo start_backend.bat
|
||||||
|
echo.
|
||||||
|
|
||||||
|
pause
|
||||||
42
rebuild_with_digest_auth.bat
Normal file
42
rebuild_with_digest_auth.bat
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo 重新编译后端(添加 Digest 认证支持)
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
echo [1/3] 清理旧的编译文件...
|
||||||
|
call mvn clean
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [2/3] 下载依赖并编译...
|
||||||
|
echo 注意:首次运行会下载 Apache HttpClient 依赖
|
||||||
|
call mvn compile
|
||||||
|
|
||||||
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
|
echo.
|
||||||
|
echo 编译失败!请检查错误信息。
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [3/3] 启动后端服务...
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo Digest 认证支持已添加
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 现在支持两种认证方式:
|
||||||
|
echo 1. Basic 认证(先尝试)
|
||||||
|
echo 2. Digest 认证(Basic 失败后自动尝试)
|
||||||
|
echo.
|
||||||
|
echo 提示:
|
||||||
|
echo - 系统会自动尝试两种认证方式
|
||||||
|
echo - 查看日志了解使用了哪种认证
|
||||||
|
echo.
|
||||||
|
|
||||||
|
call mvn spring-boot:run
|
||||||
|
|
||||||
|
pause
|
||||||
@ -75,3 +75,25 @@ export function fetchDeviceStatistics() {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 AMT 连接
|
||||||
|
*/
|
||||||
|
export function fetchTestAmtConnection(data: Api.Device.AmtTestRequest) {
|
||||||
|
return request<boolean>({
|
||||||
|
url: '/device/amt/test',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 AMT 设备信息
|
||||||
|
*/
|
||||||
|
export function fetchAmtDeviceInfo(data: Api.Device.AmtTestRequest) {
|
||||||
|
return request<Api.Device.AmtDeviceInfo>({
|
||||||
|
url: '/device/amt/getInfo',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
24
src/typings/api/device.d.ts
vendored
24
src/typings/api/device.d.ts
vendored
@ -51,5 +51,29 @@ declare namespace Api {
|
|||||||
/** 备注 */
|
/** 备注 */
|
||||||
remark?: string;
|
remark?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** AMT 测试请求 */
|
||||||
|
interface AmtTestRequest {
|
||||||
|
/** IP地址 */
|
||||||
|
ipAddress: string;
|
||||||
|
/** 用户名 */
|
||||||
|
username?: string;
|
||||||
|
/** 密码 */
|
||||||
|
password?: string;
|
||||||
|
/** 凭证ID */
|
||||||
|
credentialId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** AMT 设备信息 */
|
||||||
|
interface AmtDeviceInfo {
|
||||||
|
/** 设备名称 */
|
||||||
|
deviceName: string;
|
||||||
|
/** 设备编号 */
|
||||||
|
deviceCode: string;
|
||||||
|
/** IP地址 */
|
||||||
|
ipAddress: string;
|
||||||
|
/** MAC地址 */
|
||||||
|
macAddress: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
src/typings/components.d.ts
vendored
2
src/typings/components.d.ts
vendored
@ -49,6 +49,7 @@ declare module 'vue' {
|
|||||||
IconMdiIp: typeof import('~icons/mdi/ip')['default']
|
IconMdiIp: typeof import('~icons/mdi/ip')['default']
|
||||||
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||||
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||||
|
IconMdiLanConnect: typeof import('~icons/mdi/lan-connect')['default']
|
||||||
IconMdiMagnify: typeof import('~icons/mdi/magnify')['default']
|
IconMdiMagnify: typeof import('~icons/mdi/magnify')['default']
|
||||||
IconMdiMapMarker: typeof import('~icons/mdi/map-marker')['default']
|
IconMdiMapMarker: typeof import('~icons/mdi/map-marker')['default']
|
||||||
IconMdiMemory: typeof import('~icons/mdi/memory')['default']
|
IconMdiMemory: typeof import('~icons/mdi/memory')['default']
|
||||||
@ -188,6 +189,7 @@ declare global {
|
|||||||
const IconMdiIp: typeof import('~icons/mdi/ip')['default']
|
const IconMdiIp: typeof import('~icons/mdi/ip')['default']
|
||||||
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||||
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||||
|
const IconMdiLanConnect: typeof import('~icons/mdi/lan-connect')['default']
|
||||||
const IconMdiMagnify: typeof import('~icons/mdi/magnify')['default']
|
const IconMdiMagnify: typeof import('~icons/mdi/magnify')['default']
|
||||||
const IconMdiMapMarker: typeof import('~icons/mdi/map-marker')['default']
|
const IconMdiMapMarker: typeof import('~icons/mdi/map-marker')['default']
|
||||||
const IconMdiMemory: typeof import('~icons/mdi/memory')['default']
|
const IconMdiMemory: typeof import('~icons/mdi/memory')['default']
|
||||||
|
|||||||
@ -93,8 +93,88 @@
|
|||||||
v-model:show="modalVisible"
|
v-model:show="modalVisible"
|
||||||
:title="modalTitle"
|
:title="modalTitle"
|
||||||
preset="card"
|
preset="card"
|
||||||
class="w-700px"
|
class="w-800px"
|
||||||
>
|
>
|
||||||
|
<!-- 添加方式选择(仅新增时显示) -->
|
||||||
|
<n-radio-group v-if="!isEdit" v-model:value="addMode" class="mb-16px">
|
||||||
|
<n-space>
|
||||||
|
<n-radio value="manual">手动添加</n-radio>
|
||||||
|
<n-radio value="amt">AMT 自动添加</n-radio>
|
||||||
|
</n-space>
|
||||||
|
</n-radio-group>
|
||||||
|
|
||||||
|
<!-- AMT 添加方式 -->
|
||||||
|
<div v-if="!isEdit && addMode === 'amt'" class="mb-16px">
|
||||||
|
<n-card title="AMT 设备发现" size="small" :bordered="false" class="bg-gray-50">
|
||||||
|
<n-form label-placement="left" label-width="100px">
|
||||||
|
<n-form-item label="IP 地址" required>
|
||||||
|
<n-input
|
||||||
|
v-model:value="amtFormData.ipAddress"
|
||||||
|
placeholder="请输入 AMT 设备 IP 地址"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="认证方式">
|
||||||
|
<n-switch
|
||||||
|
v-model:value="amtFormData.useCredential"
|
||||||
|
@update:value="handleCredentialToggle"
|
||||||
|
>
|
||||||
|
<template #checked>使用已保存凭证</template>
|
||||||
|
<template #unchecked>手动输入</template>
|
||||||
|
</n-switch>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<template v-if="amtFormData.useCredential">
|
||||||
|
<n-form-item label="选择凭证" required>
|
||||||
|
<n-select
|
||||||
|
v-model:value="amtFormData.credentialId"
|
||||||
|
:options="amtCredentials.map(c => ({ label: c.credentialName, value: c.credentialId }))"
|
||||||
|
placeholder="请选择 AMT 凭证"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<n-form-item label="用户名" required>
|
||||||
|
<n-input
|
||||||
|
v-model:value="amtFormData.username"
|
||||||
|
placeholder="请输入 AMT 用户名"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="密码" required>
|
||||||
|
<n-input
|
||||||
|
v-model:value="amtFormData.password"
|
||||||
|
type="password"
|
||||||
|
show-password-on="click"
|
||||||
|
placeholder="请输入 AMT 密码"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<n-form-item>
|
||||||
|
<n-space>
|
||||||
|
<n-button
|
||||||
|
type="primary"
|
||||||
|
:loading="amtTesting"
|
||||||
|
@click="handleTestAmtConnection"
|
||||||
|
>
|
||||||
|
<icon-mdi-lan-connect class="mr-4px" />
|
||||||
|
测试连接
|
||||||
|
</n-button>
|
||||||
|
<n-tag v-if="amtTestSuccess" type="success">
|
||||||
|
<icon-mdi-check-circle class="mr-4px" />
|
||||||
|
连接成功
|
||||||
|
</n-tag>
|
||||||
|
</n-space>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<n-divider class="!my-16px">设备信息</n-divider>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 设备信息表单 -->
|
||||||
<n-form
|
<n-form
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
@ -107,25 +187,28 @@
|
|||||||
<n-input
|
<n-input
|
||||||
v-model:value="formData.deviceName"
|
v-model:value="formData.deviceName"
|
||||||
placeholder="请输入设备名称"
|
placeholder="请输入设备名称"
|
||||||
|
:disabled="!isEdit && addMode === 'amt' && !amtTestSuccess"
|
||||||
/>
|
/>
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi label="UUID" path="deviceCode">
|
<n-form-item-gi label="UUID" path="deviceCode">
|
||||||
<n-input
|
<n-input
|
||||||
v-model:value="formData.deviceCode"
|
v-model:value="formData.deviceCode"
|
||||||
placeholder="请输入UUID"
|
placeholder="请输入UUID"
|
||||||
:disabled="isEdit"
|
:disabled="isEdit || (addMode === 'amt' && !amtTestSuccess)"
|
||||||
/>
|
/>
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi label="IP地址" path="ipAddress">
|
<n-form-item-gi label="IP地址" path="ipAddress">
|
||||||
<n-input
|
<n-input
|
||||||
v-model:value="formData.ipAddress"
|
v-model:value="formData.ipAddress"
|
||||||
placeholder="请输入IP地址"
|
placeholder="请输入IP地址"
|
||||||
|
:disabled="!isEdit && addMode === 'amt' && !amtTestSuccess"
|
||||||
/>
|
/>
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi label="MAC地址" path="macAddress">
|
<n-form-item-gi label="MAC地址" path="macAddress">
|
||||||
<n-input
|
<n-input
|
||||||
v-model:value="formData.macAddress"
|
v-model:value="formData.macAddress"
|
||||||
placeholder="请输入MAC地址"
|
placeholder="请输入MAC地址"
|
||||||
|
:disabled="!isEdit && addMode === 'amt' && !amtTestSuccess"
|
||||||
/>
|
/>
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi label="设备状态" path="status">
|
<n-form-item-gi label="设备状态" path="status">
|
||||||
@ -148,7 +231,14 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<n-space justify="end">
|
<n-space justify="end">
|
||||||
<n-button @click="modalVisible = false">取消</n-button>
|
<n-button @click="modalVisible = false">取消</n-button>
|
||||||
<n-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</n-button>
|
<n-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSubmit"
|
||||||
|
:loading="submitLoading"
|
||||||
|
:disabled="!isEdit && addMode === 'amt' && !amtTestSuccess"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</n-button>
|
||||||
</n-space>
|
</n-space>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
@ -187,8 +277,11 @@ import {
|
|||||||
fetchCreateDevice,
|
fetchCreateDevice,
|
||||||
fetchUpdateDevice,
|
fetchUpdateDevice,
|
||||||
fetchDeleteDevice,
|
fetchDeleteDevice,
|
||||||
fetchBatchDeleteDevice
|
fetchBatchDeleteDevice,
|
||||||
|
fetchTestAmtConnection,
|
||||||
|
fetchAmtDeviceInfo
|
||||||
} from '@/service/api/device';
|
} from '@/service/api/device';
|
||||||
|
import { fetchAllActiveCredentials, type AmtCredential } from '@/service/api/amt';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'DeviceList'
|
name: 'DeviceList'
|
||||||
@ -353,6 +446,22 @@ const modalTitle = ref('');
|
|||||||
const isEdit = ref(false);
|
const isEdit = ref(false);
|
||||||
const submitLoading = ref(false);
|
const submitLoading = ref(false);
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 添加方式:manual(手动)、amt(AMT自动)
|
||||||
|
const addMode = ref<'manual' | 'amt'>('manual');
|
||||||
|
|
||||||
|
// AMT 相关
|
||||||
|
const amtFormData = reactive({
|
||||||
|
ipAddress: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
credentialId: null as number | null,
|
||||||
|
useCredential: false
|
||||||
|
});
|
||||||
|
const amtCredentials = ref<AmtCredential[]>([]);
|
||||||
|
const amtTesting = ref(false);
|
||||||
|
const amtTestSuccess = ref(false);
|
||||||
|
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
id: null as number | null,
|
id: null as number | null,
|
||||||
deviceName: '',
|
deviceName: '',
|
||||||
@ -421,6 +530,8 @@ function handleCheck(keys: number[]) {
|
|||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
isEdit.value = false;
|
isEdit.value = false;
|
||||||
modalTitle.value = '新增设备';
|
modalTitle.value = '新增设备';
|
||||||
|
addMode.value = 'manual';
|
||||||
|
amtTestSuccess.value = false;
|
||||||
Object.assign(formData, {
|
Object.assign(formData, {
|
||||||
id: null,
|
id: null,
|
||||||
deviceName: '',
|
deviceName: '',
|
||||||
@ -430,7 +541,15 @@ function handleAdd() {
|
|||||||
macAddress: '',
|
macAddress: '',
|
||||||
remark: ''
|
remark: ''
|
||||||
});
|
});
|
||||||
|
Object.assign(amtFormData, {
|
||||||
|
ipAddress: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
credentialId: null,
|
||||||
|
useCredential: false
|
||||||
|
});
|
||||||
modalVisible.value = true;
|
modalVisible.value = true;
|
||||||
|
loadAmtCredentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑
|
// 编辑
|
||||||
@ -506,4 +625,105 @@ async function handleBatchDelete() {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadData();
|
loadData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 加载 AMT 凭证列表
|
||||||
|
async function loadAmtCredentials() {
|
||||||
|
try {
|
||||||
|
const { data } = await fetchAllActiveCredentials();
|
||||||
|
amtCredentials.value = data || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载 AMT 凭证失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 AMT 连接
|
||||||
|
async function handleTestAmtConnection() {
|
||||||
|
// 验证必填项
|
||||||
|
if (!amtFormData.ipAddress) {
|
||||||
|
window.$message?.warning('请输入 IP 地址');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amtFormData.useCredential && (!amtFormData.username || !amtFormData.password)) {
|
||||||
|
window.$message?.warning('请输入用户名和密码,或选择已保存的凭证');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amtFormData.useCredential && !amtFormData.credentialId) {
|
||||||
|
window.$message?.warning('请选择 AMT 凭证');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
amtTesting.value = true;
|
||||||
|
amtTestSuccess.value = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const requestData: Api.Device.AmtTestRequest = {
|
||||||
|
ipAddress: amtFormData.ipAddress
|
||||||
|
};
|
||||||
|
|
||||||
|
if (amtFormData.useCredential && amtFormData.credentialId) {
|
||||||
|
requestData.credentialId = amtFormData.credentialId;
|
||||||
|
} else {
|
||||||
|
requestData.username = amtFormData.username;
|
||||||
|
requestData.password = amtFormData.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await fetchTestAmtConnection(requestData);
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
amtTestSuccess.value = true;
|
||||||
|
window.$message?.success('AMT 连接测试成功');
|
||||||
|
|
||||||
|
// 自动获取设备信息
|
||||||
|
await handleGetAmtDeviceInfo();
|
||||||
|
} else {
|
||||||
|
window.$message?.error('AMT 连接测试失败');
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
window.$message?.error(error?.message || 'AMT 连接测试失败');
|
||||||
|
} finally {
|
||||||
|
amtTesting.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 AMT 设备信息
|
||||||
|
async function handleGetAmtDeviceInfo() {
|
||||||
|
try {
|
||||||
|
const requestData: Api.Device.AmtTestRequest = {
|
||||||
|
ipAddress: amtFormData.ipAddress
|
||||||
|
};
|
||||||
|
|
||||||
|
if (amtFormData.useCredential && amtFormData.credentialId) {
|
||||||
|
requestData.credentialId = amtFormData.credentialId;
|
||||||
|
} else {
|
||||||
|
requestData.username = amtFormData.username;
|
||||||
|
requestData.password = amtFormData.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await fetchAmtDeviceInfo(requestData);
|
||||||
|
|
||||||
|
// 填充表单数据
|
||||||
|
formData.deviceName = data.deviceName;
|
||||||
|
formData.deviceCode = data.deviceCode;
|
||||||
|
formData.ipAddress = data.ipAddress;
|
||||||
|
formData.macAddress = data.macAddress;
|
||||||
|
|
||||||
|
window.$message?.success('设备信息获取成功');
|
||||||
|
} catch (error: any) {
|
||||||
|
window.$message?.error(error?.message || '获取设备信息失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换凭证使用方式
|
||||||
|
function handleCredentialToggle(value: boolean) {
|
||||||
|
if (value) {
|
||||||
|
amtFormData.username = '';
|
||||||
|
amtFormData.password = '';
|
||||||
|
} else {
|
||||||
|
amtFormData.credentialId = null;
|
||||||
|
}
|
||||||
|
amtTestSuccess.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,16 +1,43 @@
|
|||||||
@echo off
|
@echo off
|
||||||
chcp 65001 >nul
|
|
||||||
echo ========================================
|
echo ========================================
|
||||||
echo 测试 AMT API 接口
|
echo 测试 AMT API 是否正常
|
||||||
echo ========================================
|
echo ========================================
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo 测试获取凭证列表...
|
echo [测试 1] 检查后端是否运行...
|
||||||
curl -X GET "http://localhost:8080/api/amt/credential/list?page=1&size=10" -H "Content-Type: application/json"
|
curl -s http://localhost:8080/device/statistics >nul 2>&1
|
||||||
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
|
echo 后端未运行或无法连接!
|
||||||
|
echo 请先启动后端服务。
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo 后端正常运行 ✓
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [测试 2] 检查模拟模式状态...
|
||||||
|
curl -s http://localhost:8080/device/amt/mockStatus
|
||||||
|
echo.
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [测试 3] 测试 AMT 连接 API(使用模拟数据)...
|
||||||
|
echo.
|
||||||
|
echo 发送测试请求...
|
||||||
|
curl -X POST http://localhost:8080/device/amt/test ^
|
||||||
|
-H "Content-Type: application/json" ^
|
||||||
|
-d "{\"ipAddress\":\"192.168.1.100\",\"username\":\"admin\",\"password\":\"admin\"}"
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo.
|
echo.
|
||||||
echo ========================================
|
echo ========================================
|
||||||
echo 测试完成
|
echo 测试完成
|
||||||
echo ========================================
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 如果看到成功响应,说明 API 正常工作。
|
||||||
|
echo 如果看到错误,请检查:
|
||||||
|
echo 1. 后端是否正常启动
|
||||||
|
echo 2. 端口 8080 是否被占用
|
||||||
|
echo 3. 查看后端控制台日志
|
||||||
|
echo.
|
||||||
|
|
||||||
pause
|
pause
|
||||||
|
|||||||
43
test_amt_connection.bat
Normal file
43
test_amt_connection.bat
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo AMT 连接测试工具
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
set /p AMT_IP="请输入 AMT 设备 IP 地址: "
|
||||||
|
set /p AMT_USER="请输入 AMT 用户名 (默认: admin): "
|
||||||
|
if "%AMT_USER%"=="" set AMT_USER=admin
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 正在测试连接到 %AMT_IP%...
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM 测试端口 16992 是否开放
|
||||||
|
echo [1/4] 测试端口 16992 (HTTP)...
|
||||||
|
powershell -Command "Test-NetConnection -ComputerName %AMT_IP% -Port 16992 -InformationLevel Detailed"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [2/4] 测试端口 16993 (HTTPS)...
|
||||||
|
powershell -Command "Test-NetConnection -ComputerName %AMT_IP% -Port 16993 -InformationLevel Detailed"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [3/4] 尝试 HTTP 连接...
|
||||||
|
curl -v -u %AMT_USER% http://%AMT_IP%:16992/wsman -H "Content-Type: application/soap+xml;charset=UTF-8" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\"><s:Header/><s:Body><wsmid:Identify/></s:Body></s:Envelope>"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [4/4] 尝试 HTTPS 连接...
|
||||||
|
curl -v -k -u %AMT_USER% https://%AMT_IP%:16993/wsman -H "Content-Type: application/soap+xml;charset=UTF-8" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\"><s:Header/><s:Body><wsmid:Identify/></s:Body></s:Envelope>"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 测试完成
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 提示:
|
||||||
|
echo - 如果端口不通,请检查防火墙设置
|
||||||
|
echo - 如果返回 401,请检查用户名和密码
|
||||||
|
echo - 如果返回 404,AMT 可能未启用
|
||||||
|
echo - HTTP 端口: 16992, HTTPS 端口: 16993
|
||||||
|
echo.
|
||||||
|
|
||||||
|
pause
|
||||||
Loading…
x
Reference in New Issue
Block a user