|
|
|
|
|
# STOMP 服务使用指南
|
|
|
|
|
|
|
|
|
|
|
|
## 简介
|
|
|
|
|
|
|
|
|
|
|
|
这是一个基于 `@stomp/stompjs` 库封装的 STOMP 服务,提供了完整的连接、订阅、发布和消息处理功能。
|
|
|
|
|
|
|
|
|
|
|
|
**注意:** 您的项目使用的是 **STOMP over WebSocket** 协议,而不是 MQTT。
|
|
|
|
|
|
|
|
|
|
|
|
## 主要功能
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ 自动连接和重连
|
|
|
|
|
|
- ✅ 服务注册机制
|
|
|
|
|
|
- ✅ 消息自动分发
|
|
|
|
|
|
- ✅ TypeScript 类型支持
|
|
|
|
|
|
- ✅ 错误处理和日志记录
|
|
|
|
|
|
|
|
|
|
|
|
## 使用方法
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 在 main.ts 中初始化
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { stompService } from './utils/stompService';
|
|
|
|
|
|
|
|
|
|
|
|
// 应用启动时连接 STOMP
|
|
|
|
|
|
const app = createApp(App);
|
|
|
|
|
|
|
|
|
|
|
|
// 连接 STOMP 服务器
|
|
|
|
|
|
stompService.connect({
|
|
|
|
|
|
// brokerUrl: 'ws://your-server:8080/stomp-endpoint', // 可选,默认使用当前域名
|
|
|
|
|
|
// username: 'your-username', // 可选
|
|
|
|
|
|
// password: 'your-password', // 可选
|
|
|
|
|
|
reconnectDelay: 5000 // 重连间隔,默认 5000ms
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
app.mount('#app');
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 注册服务
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 在您的组件或 store 中
|
|
|
|
|
|
import { stompService } from '@/utils/stompService';
|
|
|
|
|
|
|
|
|
|
|
|
// 注册您的服务
|
|
|
|
|
|
stompService.registerService('node', {
|
|
|
|
|
|
// 当 STOMP 连接成功时会调用此方法
|
|
|
|
|
|
mqttReady() {
|
|
|
|
|
|
console.log('Node 服务已就绪');
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 处理 Node 初始化消息
|
|
|
|
|
|
msgNodeInit(data: any) {
|
|
|
|
|
|
console.log('收到 Node 初始化数据:', data);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 处理 Node 更新消息
|
|
|
|
|
|
msgNode(data: any) {
|
|
|
|
|
|
console.log('收到 Node 更新:', data);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 运行时的数据
|
|
|
|
|
|
runtimes: {}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 注册其他服务
|
|
|
|
|
|
stompService.registerService('channel', {
|
|
|
|
|
|
online(cid: string, isOnline: boolean) {
|
|
|
|
|
|
console.log(`通道 ${cid} 状态:`, isOnline);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
stompService.registerService('video', {
|
|
|
|
|
|
initVideo(data: any) {
|
|
|
|
|
|
console.log('初始化视频:', data);
|
|
|
|
|
|
},
|
|
|
|
|
|
playVideo(data: any) {
|
|
|
|
|
|
console.log('播放视频:', data);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 发送消息
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { stompService, MqttCmd } from '@/utils/stompService';
|
|
|
|
|
|
|
|
|
|
|
|
// 发送控制命令
|
|
|
|
|
|
stompService.send('/app/web/write', MqttCmd.Control, {
|
|
|
|
|
|
nodeId: 'node-001',
|
|
|
|
|
|
action: 'turnOn'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 发送 Node 更新
|
|
|
|
|
|
stompService.send('/app/web/write', MqttCmd.Node, {
|
|
|
|
|
|
node: {
|
|
|
|
|
|
id: 'node-001',
|
|
|
|
|
|
status: 'active'
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 订阅主题
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { stompService } from '@/utils/stompService';
|
|
|
|
|
|
|
|
|
|
|
|
// 订阅自定义主题
|
|
|
|
|
|
stompService.subscribe('/topic/custom', (message) => {
|
|
|
|
|
|
console.log('收到自定义消息:', message);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 取消订阅
|
|
|
|
|
|
stompService.unsubscribe('/topic/custom');
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 在 Vue 组件中使用
|
|
|
|
|
|
|
|
|
|
|
|
```vue
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<el-button @click="sendCommand">发送命令</el-button>
|
|
|
|
|
|
<div>连接状态:{{ isConnected ? '已连接' : '未连接' }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
|
import { ref, onMounted, onUnmounted } from 'vue';
|
|
|
|
|
|
import { stompService, MqttCmd } from '@/utils/stompService';
|
|
|
|
|
|
|
|
|
|
|
|
const isConnected = ref(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 注册服务
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
stompService.registerService('myComponent', {
|
|
|
|
|
|
mqttReady() {
|
|
|
|
|
|
console.log('组件服务已就绪');
|
|
|
|
|
|
isConnected.value = true;
|
|
|
|
|
|
},
|
|
|
|
|
|
onConnectionLost() {
|
|
|
|
|
|
isConnected.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 发送命令
|
|
|
|
|
|
function sendCommand() {
|
|
|
|
|
|
stompService.send('/app/web/write', MqttCmd.Control, {
|
|
|
|
|
|
command: 'test'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 组件卸载时清理
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
// 如果需要,可以在这里断开连接
|
|
|
|
|
|
// stompService.disconnect();
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 消息命令类型
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
export const MqttCmd = {
|
|
|
|
|
|
Channel: 'channel', // 通道状态
|
|
|
|
|
|
NodeInit: 'nodeInit', // Node 初始化
|
|
|
|
|
|
Node: 'node', // Node 更新
|
|
|
|
|
|
User: 'user', // 用户登录
|
|
|
|
|
|
Control: 'control', // 控制命令
|
|
|
|
|
|
VideoInit: 'videoInit', // 视频初始化
|
|
|
|
|
|
VideoCtl: 'videoCtl', // 视频控制
|
|
|
|
|
|
Lock: 'lock', // 锁控
|
|
|
|
|
|
Alarm: 'alarm', // 告警
|
|
|
|
|
|
Info: 'info', // 通知提示
|
|
|
|
|
|
SocketDebugger: 'socketDebugger' // 调试
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## API 文档
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.connect(config?)
|
|
|
|
|
|
|
|
|
|
|
|
连接 STOMP 服务器
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
|
|
- `config?: StompServiceConfig` - 连接配置
|
|
|
|
|
|
- `brokerUrl?: string` - STOMP 服务器地址
|
|
|
|
|
|
- `username?: string` - 用户名
|
|
|
|
|
|
- `password?: string` - 密码
|
|
|
|
|
|
- `reconnectDelay?: number` - 重连间隔(毫秒)
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.disconnect()
|
|
|
|
|
|
|
|
|
|
|
|
断开 STOMP 连接
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.send(destination, cmd, value)
|
|
|
|
|
|
|
|
|
|
|
|
发送消息
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
|
|
- `destination: string` - STOMP 目标地址
|
|
|
|
|
|
- `cmd: string` - 命令类型
|
|
|
|
|
|
- `value: any` - 消息内容
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.subscribe(destination, callback?)
|
|
|
|
|
|
|
|
|
|
|
|
订阅主题
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
|
|
- `destination: string` - 目标地址
|
|
|
|
|
|
- `callback?: (message: StompMessage) => void` - 消息回调
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.unsubscribe(destination)
|
|
|
|
|
|
|
|
|
|
|
|
取消订阅
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
|
|
- `destination: string` - 目标地址
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.registerService(name, service)
|
|
|
|
|
|
|
|
|
|
|
|
注册服务
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
|
|
- `name: string` - 服务名称
|
|
|
|
|
|
- `service: any` - 服务对象
|
|
|
|
|
|
|
|
|
|
|
|
### stompService.getClientStatus()
|
|
|
|
|
|
|
|
|
|
|
|
获取客户端状态
|
|
|
|
|
|
|
|
|
|
|
|
**返回:** `{ connected: boolean; client: Client | null }`
|
|
|
|
|
|
|
|
|
|
|
|
## 注意事项
|
|
|
|
|
|
|
|
|
|
|
|
1. **连接时机**: 建议在应用启动时(main.ts)连接 STOMP
|
|
|
|
|
|
2. **服务注册**: 在组件的 `onMounted` 生命周期注册服务
|
|
|
|
|
|
3. **清理资源**: 组件卸载时根据需要断开连接或取消订阅
|
|
|
|
|
|
4. **错误处理**: 服务已内置重连机制,无需手动处理
|
|
|
|
|
|
5. **类型安全**: 所有方法都有 TypeScript 类型支持
|
|
|
|
|
|
|
|
|
|
|
|
## 迁移指南
|
|
|
|
|
|
|
|
|
|
|
|
从旧的 ExtJS 版本迁移:
|
|
|
|
|
|
|
|
|
|
|
|
### 旧代码
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
Rec.mqtt.connect();
|
|
|
|
|
|
Rec.service.node = { ... };
|
|
|
|
|
|
Rec.mqtt.send(cmd, value);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 新代码
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { stompService } from '@/utils/stompService';
|
|
|
|
|
|
|
|
|
|
|
|
stompService.connect();
|
|
|
|
|
|
stompService.registerService('node', { ... });
|
|
|
|
|
|
stompService.send('/app/web/write', cmd, value);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 示例项目结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
src/
|
|
|
|
|
|
├── utils/
|
|
|
|
|
|
│ └── stompService.ts # STOMP 服务
|
|
|
|
|
|
├── services/
|
|
|
|
|
|
│ ├── nodeService.ts # Node 服务
|
|
|
|
|
|
│ ├── channelService.ts # 通道服务
|
|
|
|
|
|
│ └── videoService.ts # 视频服务
|
|
|
|
|
|
└── views/
|
|
|
|
|
|
└── YourComponent.vue # 使用 STOMP 的组件
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 故障排除
|
|
|
|
|
|
|
|
|
|
|
|
### 连接失败
|
|
|
|
|
|
|
|
|
|
|
|
- 检查 STOMP 服务器地址是否正确
|
|
|
|
|
|
- 检查 WebSocket 是否可用(某些浏览器需要 HTTPS)
|
|
|
|
|
|
- 查看浏览器控制台日志
|
|
|
|
|
|
|
|
|
|
|
|
### 消息未收到
|
|
|
|
|
|
|
|
|
|
|
|
- 确认服务已注册
|
|
|
|
|
|
- 检查主题订阅是否正确
|
|
|
|
|
|
- 查看消息格式是否符合预期
|
|
|
|
|
|
|
|
|
|
|
|
### 重连问题
|
|
|
|
|
|
|
|
|
|
|
|
- 检查 `reconnectDelay` 设置
|
|
|
|
|
|
- 查看服务器是否在线
|
|
|
|
|
|
- 检查认证信息是否正确
|
|
|
|
|
|
|
|
|
|
|
|
## 与 MQTT 的区别
|
|
|
|
|
|
|
|
|
|
|
|
STOMP 是一个简单的文本协议,基于 WebSocket:
|
|
|
|
|
|
|
|
|
|
|
|
- 使用 `destination` 而不是 `topic`
|
|
|
|
|
|
- 使用 `send/publish` 发送消息
|
|
|
|
|
|
- 使用 `subscribe` 订阅消息
|
|
|
|
|
|
- 连接地址格式:`ws://host/stomp-endpoint`
|