@thejrsoft/subway-protocol 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ACK_MESSAGES_IMPLEMENTATION_SUMMARY.md +128 -0
- package/ACK_MESSAGE_DESIGN.md +457 -0
- package/CHANGELOG.md +58 -0
- package/COMMAND_VALIDATION_RULES.md +178 -0
- package/DOCUMENTATION_REORGANIZATION_SUMMARY.md +81 -0
- package/DOCUMENTATION_STRUCTURE.md +106 -0
- package/GATEWAY_MIGRATION_GUIDE.md +130 -0
- package/GATEWAY_PROTOCOL_COMPARISON.md +216 -0
- package/INTEGRATION_GUIDE.md +190 -0
- package/OPTIONAL_FIELDS_WITHOUT_DEFAULTS.md +97 -0
- package/PROTOCOL_UTILS_USAGE.md +278 -0
- package/README.md +237 -0
- package/TYPE_FIXES_SUMMARY.md +210 -0
- package/UPDATE_ENUM_VALUES.md +139 -0
- package/dist/asyncapi-sync.d.ts +47 -0
- package/dist/asyncapi-sync.d.ts.map +1 -0
- package/dist/asyncapi-sync.js +85 -0
- package/dist/asyncapi-sync.js.map +1 -0
- package/dist/command-factory.d.ts +62 -0
- package/dist/command-factory.d.ts.map +1 -0
- package/dist/command-factory.js +137 -0
- package/dist/command-factory.js.map +1 -0
- package/dist/command-types.d.ts +27 -0
- package/dist/command-types.d.ts.map +1 -0
- package/dist/command-types.js +31 -0
- package/dist/command-types.js.map +1 -0
- package/dist/index.d.ts +403 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +413 -0
- package/dist/index.js.map +1 -0
- package/dist/message-validator.d.ts +102 -0
- package/dist/message-validator.d.ts.map +1 -0
- package/dist/message-validator.js +640 -0
- package/dist/message-validator.js.map +1 -0
- package/dist/protocol-utils.d.ts +108 -0
- package/dist/protocol-utils.d.ts.map +1 -0
- package/dist/protocol-utils.js +293 -0
- package/dist/protocol-utils.js.map +1 -0
- package/docs/01-protocol/README.md +45 -0
- package/docs/01-protocol/design-rationale.md +198 -0
- package/docs/01-protocol/message-types.md +669 -0
- package/docs/01-protocol/specification.md +1466 -0
- package/docs/02-commands/README.md +56 -0
- package/docs/02-commands/batch-command.md +435 -0
- package/docs/02-commands/complex-command.md +537 -0
- package/docs/02-commands/simple-command.md +332 -0
- package/docs/02-commands/typed-commands.md +362 -0
- package/docs/03-architecture/README.md +66 -0
- package/docs/03-architecture/device-protocol.md +430 -0
- package/docs/03-architecture/edge-proxy.md +727 -0
- package/docs/03-architecture/routing-flow.md +893 -0
- package/docs/04-integration/README.md +144 -0
- package/docs/04-integration/backend-guide.md +551 -0
- package/docs/04-integration/edge-guide.md +684 -0
- package/docs/04-integration/gateway-guide.md +180 -0
- package/docs/04-integration/migration-guide.md +226 -0
- package/docs/05-examples/README.md +141 -0
- package/docs/05-examples/progress-update-examples.md +757 -0
- package/docs/06-reference/README.md +67 -0
- package/docs/06-reference/api.md +572 -0
- package/docs/06-reference/faq.md +302 -0
- package/docs/06-reference/glossary.md +232 -0
- package/examples/backend-upgrade.ts +279 -0
- package/examples/edge-multi-device.ts +513 -0
- package/examples/gateway-upgrade.ts +150 -0
- package/examples/protocol-implementation.ts +715 -0
- package/package.json +48 -0
- package/scripts/validate-asyncapi.ts +78 -0
- package/src/__tests__/protocol.test.ts +297 -0
- package/src/asyncapi-sync.ts +84 -0
- package/src/command-factory.ts +183 -0
- package/src/command-types.ts +72 -0
- package/src/edge-proxy.ts +494 -0
- package/src/gateway-extensions.ts +278 -0
- package/src/index.ts +792 -0
- package/src/message-validator.ts +726 -0
- package/src/protocol-utils.ts +355 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Gateway vs Protocol 类型定义比较
|
|
2
|
+
|
|
3
|
+
## BaseMessage 比较
|
|
4
|
+
|
|
5
|
+
### Gateway 定义
|
|
6
|
+
```typescript
|
|
7
|
+
export interface BaseMessage {
|
|
8
|
+
type: MessageType;
|
|
9
|
+
targetClientId?: string;
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Protocol 定义
|
|
14
|
+
```typescript
|
|
15
|
+
export interface BaseMessage {
|
|
16
|
+
type: MessageType;
|
|
17
|
+
timestamp: string; // ISO 8601 格式
|
|
18
|
+
version: string; // 协议版本 "1.0"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 差异分析
|
|
23
|
+
| 字段 | Gateway | Protocol | 说明 |
|
|
24
|
+
|------|---------|----------|------|
|
|
25
|
+
| type | ✓ | ✓ | 都有,类型一致 |
|
|
26
|
+
| targetClientId | ✓ (可选) | ✗ | Gateway 特有,但应该只在特定消息中使用 |
|
|
27
|
+
| timestamp | ✗ | ✓ (必需) | Protocol 要求所有消息都有时间戳 |
|
|
28
|
+
| version | ✗ | ✓ (必需) | Protocol 要求协议版本号 |
|
|
29
|
+
|
|
30
|
+
## CommandMessage 比较
|
|
31
|
+
|
|
32
|
+
### Gateway 定义
|
|
33
|
+
```typescript
|
|
34
|
+
export interface CommandMessage extends BaseMessage {
|
|
35
|
+
type: typeof WS_MESSAGE_TYPES.COMMAND;
|
|
36
|
+
requestRef: string;
|
|
37
|
+
targetClientId: string;
|
|
38
|
+
command: {
|
|
39
|
+
commandType?: 'SIMPLE' | 'BATCH' | 'COMPLEX';
|
|
40
|
+
commandCode: string;
|
|
41
|
+
deviceType: string;
|
|
42
|
+
deviceId?: number;
|
|
43
|
+
operationType: string;
|
|
44
|
+
parameters: Record<string, unknown>;
|
|
45
|
+
};
|
|
46
|
+
priority: string;
|
|
47
|
+
timeout: number;
|
|
48
|
+
timestamp: string;
|
|
49
|
+
callback?: string;
|
|
50
|
+
version?: string;
|
|
51
|
+
metadata?: Record<string, any>;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Protocol 定义
|
|
56
|
+
```typescript
|
|
57
|
+
export interface CommandMessage extends BaseMessage {
|
|
58
|
+
type: MessageType.COMMAND;
|
|
59
|
+
requestRef: string;
|
|
60
|
+
targetClientId: string;
|
|
61
|
+
command: Command; // 支持多种命令类型
|
|
62
|
+
priority: Priority; // 枚举类型
|
|
63
|
+
timeout: number;
|
|
64
|
+
retryCount?: number;
|
|
65
|
+
callback: string;
|
|
66
|
+
metadata?: Record<string, any>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Command 可以是:
|
|
70
|
+
// - SpecificCommand (从 C# 生成)
|
|
71
|
+
// - SimpleCommand
|
|
72
|
+
// - BatchCommand
|
|
73
|
+
// - ComplexCommand
|
|
74
|
+
// - GenericCommand
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 详细差异分析
|
|
78
|
+
|
|
79
|
+
#### 1. 继承的差异
|
|
80
|
+
- **Gateway**: 继承的 BaseMessage 有 `targetClientId?`
|
|
81
|
+
- **Protocol**: 继承的 BaseMessage 有 `timestamp` 和 `version`
|
|
82
|
+
|
|
83
|
+
#### 2. 字段级别差异
|
|
84
|
+
|
|
85
|
+
| 字段 | Gateway | Protocol | 差异说明 |
|
|
86
|
+
|------|---------|----------|----------|
|
|
87
|
+
| requestRef | ✓ string | ✓ string | ✅ 一致 |
|
|
88
|
+
| targetClientId | ✓ string | ✓ string | ✅ 一致 |
|
|
89
|
+
| command | 内联对象 | Command 类型 | ⚠️ Protocol 使用强类型 |
|
|
90
|
+
| priority | string | Priority 枚举 | ⚠️ Protocol 使用枚举 |
|
|
91
|
+
| timeout | ✓ number | ✓ number | ✅ 一致 |
|
|
92
|
+
| timestamp | ✓ string | 继承自 BaseMessage | ⚠️ Gateway 直接定义,Protocol 继承 |
|
|
93
|
+
| callback | ✓ 可选 | ✓ 必需 | ❌ **重要差异** |
|
|
94
|
+
| version | ✓ 可选 | 继承自 BaseMessage | ⚠️ Gateway 直接定义,Protocol 继承 |
|
|
95
|
+
| retryCount | ✗ | ✓ 可选 | ⚠️ Protocol 特有 |
|
|
96
|
+
| metadata | ✓ 可选 | ✓ 可选 | ✅ 一致 |
|
|
97
|
+
|
|
98
|
+
#### 3. Command 结构差异
|
|
99
|
+
|
|
100
|
+
**Gateway 的 command**:
|
|
101
|
+
```typescript
|
|
102
|
+
command: {
|
|
103
|
+
commandType?: 'SIMPLE' | 'BATCH' | 'COMPLEX';
|
|
104
|
+
commandCode: string;
|
|
105
|
+
deviceType: string;
|
|
106
|
+
deviceId?: number;
|
|
107
|
+
operationType: string;
|
|
108
|
+
parameters: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Protocol 的 command**:
|
|
113
|
+
- 支持多种类型(SimpleCommand, BatchCommand, ComplexCommand, GenericCommand)
|
|
114
|
+
- deviceId 支持 `number | number[] | string`
|
|
115
|
+
- 有严格的类型定义和验证
|
|
116
|
+
|
|
117
|
+
## 其他消息类型差异
|
|
118
|
+
|
|
119
|
+
### RegisterMessage
|
|
120
|
+
**主要差异**:
|
|
121
|
+
- Gateway: `clientType: 'device' | 'edge' | 'backend'`
|
|
122
|
+
- Protocol: `clientType: ClientType` (枚举)
|
|
123
|
+
- Gateway: 没有 timestamp 和 version
|
|
124
|
+
- Protocol: 继承自 BaseMessage,有 timestamp 和 version
|
|
125
|
+
|
|
126
|
+
### RegisterAckMessage
|
|
127
|
+
**主要差异**:
|
|
128
|
+
- Gateway: `message?: string`
|
|
129
|
+
- Protocol: `error?: { code: string; message: string }`
|
|
130
|
+
- Protocol 有更详细的 serverInfo
|
|
131
|
+
|
|
132
|
+
## 字段一致性总结
|
|
133
|
+
|
|
134
|
+
### CommandMessage 完全一致的字段:
|
|
135
|
+
- `requestRef: string` ✅
|
|
136
|
+
- `targetClientId: string` ✅
|
|
137
|
+
- `timeout: number` ✅
|
|
138
|
+
- `metadata?: Record<string, any>` ✅
|
|
139
|
+
|
|
140
|
+
### 主要差异字段:
|
|
141
|
+
1. **callback**: Gateway 可选 vs Protocol 必需 ❌
|
|
142
|
+
2. **priority**: Gateway 字符串 vs Protocol 枚举 ⚠️
|
|
143
|
+
3. **command**: Gateway 内联对象 vs Protocol 强类型 ⚠️
|
|
144
|
+
4. **retryCount**: 只在 Protocol 中存在 ⚠️
|
|
145
|
+
|
|
146
|
+
## 统一建议
|
|
147
|
+
|
|
148
|
+
### 1. BaseMessage 统一
|
|
149
|
+
```typescript
|
|
150
|
+
// 建议的统一定义
|
|
151
|
+
export interface BaseMessage {
|
|
152
|
+
type: MessageType;
|
|
153
|
+
timestamp: string; // 必需,便于追踪
|
|
154
|
+
version: string; // 必需,便于版本管理
|
|
155
|
+
// targetClientId 不应该在这里,只在需要的消息中定义
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. CommandMessage 统一
|
|
160
|
+
需要决定:
|
|
161
|
+
- **callback**: 是否必需?
|
|
162
|
+
- **priority**: 使用枚举还是字符串?
|
|
163
|
+
- **command**: 使用强类型还是松散对象?
|
|
164
|
+
|
|
165
|
+
### 3. 迁移步骤
|
|
166
|
+
1. Gateway 先迁移到使用协议包
|
|
167
|
+
2. 处理字段差异(添加 timestamp, version)
|
|
168
|
+
3. 统一类型定义(枚举 vs 字符串)
|
|
169
|
+
4. 更新验证逻辑
|
|
170
|
+
|
|
171
|
+
## 影响评估
|
|
172
|
+
|
|
173
|
+
### 如果采用 Protocol 的严格定义
|
|
174
|
+
**需要修改 Gateway**:
|
|
175
|
+
1. 所有消息添加 timestamp 和 version
|
|
176
|
+
2. callback 改为必需(或修改协议使其可选)
|
|
177
|
+
3. priority 使用 Priority 枚举
|
|
178
|
+
4. 移除 BaseMessage 中的 targetClientId
|
|
179
|
+
|
|
180
|
+
### 如果放松 Protocol 的定义
|
|
181
|
+
**需要修改 Protocol**:
|
|
182
|
+
1. callback 改为可选
|
|
183
|
+
2. priority 改为可选并提供默认值
|
|
184
|
+
3. 可能需要调整验证逻辑
|
|
185
|
+
|
|
186
|
+
## 推荐方案
|
|
187
|
+
|
|
188
|
+
1. **保持 Protocol 的严格定义**(推荐)
|
|
189
|
+
- 更好的类型安全
|
|
190
|
+
- 清晰的 API 契约
|
|
191
|
+
- Gateway 迁移到使用协议包
|
|
192
|
+
|
|
193
|
+
2. **创建适配层**
|
|
194
|
+
- Gateway 保持现有定义
|
|
195
|
+
- 创建转换函数在 Gateway 和 Protocol 之间转换
|
|
196
|
+
- 逐步迁移
|
|
197
|
+
|
|
198
|
+
3. **放松 Protocol 定义**
|
|
199
|
+
- 使某些字段可选
|
|
200
|
+
- 降低迁移成本
|
|
201
|
+
- 但可能导致运行时错误
|
|
202
|
+
|
|
203
|
+
## 更新说明
|
|
204
|
+
|
|
205
|
+
### 关于 timeout 字段
|
|
206
|
+
经过检查,`timeout` 字段在 Gateway 和 Protocol 的 CommandMessage 定义中都存在,都是必需的 `number` 类型。这不是差异点。
|
|
207
|
+
|
|
208
|
+
### Backend 使用情况
|
|
209
|
+
- Backend 已经完全迁移到使用 `@jrsoft/subway-protocol`
|
|
210
|
+
- Backend 的 `gateway.client.ts` 和 `command.dispatcher.ts` 都使用了协议包的类型定义
|
|
211
|
+
- Backend 中的 callback 使用 `appConfig.gateway.callbackUrl` 作为值
|
|
212
|
+
|
|
213
|
+
### Gateway 使用情况
|
|
214
|
+
- Gateway 仍在使用自己的类型定义文件 (`src/types/common.types.ts`)
|
|
215
|
+
- Gateway 尚未迁移到协议包
|
|
216
|
+
- Gateway 的 callback 字段是可选的,这是主要差异之一
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# JRSoft Subway Protocol - C# 模型集成指南
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
本协议包设计为与 `jrsoft-subway-csharp-model` 生成的 TypeScript 类型配合使用。当前包含的命令类型(`ExampleCommand`)仅为示例,实际使用时应从 C# 模型包导入真实的命令类型。
|
|
6
|
+
|
|
7
|
+
## 集成步骤
|
|
8
|
+
|
|
9
|
+
### 1. 安装 C# 模型包
|
|
10
|
+
|
|
11
|
+
首先,需要将 C# 模型包添加为依赖:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 如果 C# 模型包已发布到 npm
|
|
15
|
+
npm install @jrsoft/csharp-model
|
|
16
|
+
|
|
17
|
+
# 或者使用本地链接(开发时)
|
|
18
|
+
cd ../jrsoft-subway-csharp-model
|
|
19
|
+
npm link
|
|
20
|
+
cd ../jrsoft-subway-protocol
|
|
21
|
+
npm link @jrsoft/csharp-model
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. 更新 package.json
|
|
25
|
+
|
|
26
|
+
在 `package.json` 中添加依赖:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@jrsoft/csharp-model": "^1.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
或者对于本地开发:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@jrsoft/csharp-model": "file:../jrsoft-subway-csharp-model"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. 更新 command-types.ts
|
|
47
|
+
|
|
48
|
+
将示例命令替换为真实的 C# 生成的命令:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// src/command-types.ts
|
|
52
|
+
|
|
53
|
+
import { OperationType, CommandType } from './index';
|
|
54
|
+
|
|
55
|
+
// 导入 C# 生成的命令类型
|
|
56
|
+
import {
|
|
57
|
+
LedSwitchCommand as CSharpLedSwitchCommand,
|
|
58
|
+
LedSwitchParameters,
|
|
59
|
+
BlockPlayCommand as CSharpBlockPlayCommand,
|
|
60
|
+
BlockPlayParameters,
|
|
61
|
+
// ... 更多命令
|
|
62
|
+
} from '@jrsoft/csharp-model/typescript-schemas';
|
|
63
|
+
|
|
64
|
+
// 适配命令接口(处理字段名差异,如 deviceID -> deviceId)
|
|
65
|
+
export interface LedSwitchCommand extends Omit<CSharpLedSwitchCommand, 'deviceID'> {
|
|
66
|
+
commandType: CommandType;
|
|
67
|
+
deviceId: number | number[] | string; // 重命名并支持批量
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface BlockPlayCommand extends Omit<CSharpBlockPlayCommand, 'deviceID'> {
|
|
71
|
+
commandType: CommandType;
|
|
72
|
+
deviceId: number | number[] | string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 导出所有命令的联合类型
|
|
76
|
+
export type SpecificCommand =
|
|
77
|
+
| LedSwitchCommand
|
|
78
|
+
| BlockPlayCommand
|
|
79
|
+
// ... 更多命令
|
|
80
|
+
;
|
|
81
|
+
|
|
82
|
+
// 命令映射
|
|
83
|
+
export interface CommandTypeMap {
|
|
84
|
+
'LedSwitch': LedSwitchCommand;
|
|
85
|
+
'BlockPlay': BlockPlayCommand;
|
|
86
|
+
// ... 更多映射
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. 更新 command-factory.ts
|
|
91
|
+
|
|
92
|
+
为每个真实命令添加工厂方法:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// src/command-factory.ts
|
|
96
|
+
|
|
97
|
+
export class TypedCommandFactory {
|
|
98
|
+
static createLedSwitchCommand(
|
|
99
|
+
requestRef: string,
|
|
100
|
+
targetClientId: string,
|
|
101
|
+
deviceId: number | number[] | string,
|
|
102
|
+
switchState: 'ON' | 'OFF',
|
|
103
|
+
operationType: OperationType = OperationType.WRITE,
|
|
104
|
+
options?: CommandOptions
|
|
105
|
+
): CommandMessage {
|
|
106
|
+
return this.createTypedCommandMessage(
|
|
107
|
+
requestRef,
|
|
108
|
+
targetClientId,
|
|
109
|
+
'LedSwitch',
|
|
110
|
+
{
|
|
111
|
+
commandType: CommandType.SIMPLE,
|
|
112
|
+
deviceType: 'pillar',
|
|
113
|
+
deviceId,
|
|
114
|
+
operationType,
|
|
115
|
+
parameters: { switch: switchState }
|
|
116
|
+
},
|
|
117
|
+
options
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ... 更多命令工厂方法
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 字段映射说明
|
|
126
|
+
|
|
127
|
+
C# 生成的类型和协议要求的类型之间存在一些差异:
|
|
128
|
+
|
|
129
|
+
1. **字段名称差异**
|
|
130
|
+
- C# 使用 `deviceID`(大写 ID)
|
|
131
|
+
- 协议使用 `deviceId`(小写 id)
|
|
132
|
+
|
|
133
|
+
2. **额外字段**
|
|
134
|
+
- 协议需要 `commandType` 字段(SIMPLE/BATCH/COMPLEX)
|
|
135
|
+
- C# 生成的类型可能不包含此字段
|
|
136
|
+
|
|
137
|
+
3. **批量操作支持**
|
|
138
|
+
- 协议的 `deviceId` 支持 `number | number[] | string`
|
|
139
|
+
- C# 可能只定义了 `number`
|
|
140
|
+
|
|
141
|
+
## 开发建议
|
|
142
|
+
|
|
143
|
+
1. **使用 TypeScript 接口扩展**
|
|
144
|
+
```typescript
|
|
145
|
+
interface ProtocolCommand extends CSharpCommand {
|
|
146
|
+
commandType: CommandType;
|
|
147
|
+
// 其他协议特定字段
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
2. **创建适配器函数**
|
|
152
|
+
```typescript
|
|
153
|
+
function adaptCSharpCommand(cmd: CSharpCommand): ProtocolCommand {
|
|
154
|
+
return {
|
|
155
|
+
...cmd,
|
|
156
|
+
commandType: CommandType.SIMPLE,
|
|
157
|
+
deviceId: cmd.deviceID, // 字段重命名
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
3. **验证器更新**
|
|
163
|
+
- 确保验证器能处理 C# 生成的命令结构
|
|
164
|
+
- 添加特定命令的验证逻辑
|
|
165
|
+
|
|
166
|
+
## 注意事项
|
|
167
|
+
|
|
168
|
+
1. **版本同步**:确保 C# 模型包和协议包版本兼容
|
|
169
|
+
2. **类型安全**:使用 TypeScript 的严格模式确保类型正确
|
|
170
|
+
3. **测试覆盖**:为每个集成的命令添加单元测试
|
|
171
|
+
4. **文档更新**:集成新命令时更新相关文档
|
|
172
|
+
|
|
173
|
+
## 示例项目结构
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
jrsoft-subway/
|
|
177
|
+
├── jrsoft-subway-protocol/ # 协议定义
|
|
178
|
+
│ ├── src/
|
|
179
|
+
│ │ ├── index.ts # 核心协议
|
|
180
|
+
│ │ ├── command-types.ts # 命令类型(导入 C# 类型)
|
|
181
|
+
│ │ └── command-factory.ts # 命令工厂
|
|
182
|
+
│ └── package.json
|
|
183
|
+
├── jrsoft-subway-csharp-model/ # C# 模型
|
|
184
|
+
│ ├── typescript-schemas/ # 生成的 TS 类型
|
|
185
|
+
│ │ ├── LedSwitchCommand.generated.ts
|
|
186
|
+
│ │ └── ...
|
|
187
|
+
│ └── package.json
|
|
188
|
+
└── jrsoft-subway-gateway/ # 使用协议的服务
|
|
189
|
+
└── package.json # 依赖 protocol 包
|
|
190
|
+
```
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Protocol 中没有默认值的可选字段
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
这些可选字段在 MessageFactory 中没有提供默认值,使用时需要显式传递或留空。
|
|
5
|
+
|
|
6
|
+
## 1. RegisterMessage
|
|
7
|
+
- `clientInfo?: ClientInfo` - 没有默认值
|
|
8
|
+
- `name?: string`
|
|
9
|
+
- `version?: string`
|
|
10
|
+
- `platform?: string`
|
|
11
|
+
- `capabilities?: string[]`
|
|
12
|
+
- `deviceType?: string`
|
|
13
|
+
- `description?: string`
|
|
14
|
+
- `metadata?: Record<string, any>`
|
|
15
|
+
- `edgeInfo?: EdgeInfo` - 没有默认值
|
|
16
|
+
- `edgeVersion?: string`
|
|
17
|
+
- `connectionTime?: string`
|
|
18
|
+
|
|
19
|
+
## 2. RegisterAckMessage
|
|
20
|
+
- `sessionId?: string` - 没有默认值
|
|
21
|
+
- `error?: { code: string; message: string }` - 根据 success 条件生成
|
|
22
|
+
- `serverInfo?: { ... }` - 没有默认值
|
|
23
|
+
- `currentLoad?: number`
|
|
24
|
+
- `maxClients?: number`
|
|
25
|
+
|
|
26
|
+
## 3. UnregisterMessage
|
|
27
|
+
- `reason?: string` - 没有默认值
|
|
28
|
+
|
|
29
|
+
## 4. UnregisterAckMessage
|
|
30
|
+
- `cleanupInfo?: { ... }` - 没有默认值
|
|
31
|
+
|
|
32
|
+
## 5. CommandMessage
|
|
33
|
+
- `retryCount?: number` - 没有默认值
|
|
34
|
+
- `metadata?: Record<string, any>` - 没有默认值
|
|
35
|
+
|
|
36
|
+
## 6. Command 相关
|
|
37
|
+
- `parameters?: Record<string, any>` - 没有默认值(所有 Command 类型)
|
|
38
|
+
- ComplexCommand 中的可选字段:
|
|
39
|
+
- `deviceId?: number | number[] | string`
|
|
40
|
+
- `deviceType?: string`
|
|
41
|
+
- `operationType?: OperationType`
|
|
42
|
+
- GenericCommand 中的可选字段(无默认值,但验证器会检查):
|
|
43
|
+
- `commandType?: CommandType`
|
|
44
|
+
- `deviceId?: number | number[] | string`
|
|
45
|
+
- `deviceType?: string`
|
|
46
|
+
- `operationType?: OperationType`
|
|
47
|
+
|
|
48
|
+
## 7. CommandResponseMessage
|
|
49
|
+
- `result?: CommandResult` - 没有默认值
|
|
50
|
+
- `report?: ReportMessage` - 根据 message 参数条件生成
|
|
51
|
+
- `executionTime?: number` - 没有默认值
|
|
52
|
+
|
|
53
|
+
## 8. HeartbeatAckMessage
|
|
54
|
+
- `latency?: number` - 没有默认值
|
|
55
|
+
- `serverStatus?: { ... }` - 没有默认值
|
|
56
|
+
- `cpuUsage?: number`
|
|
57
|
+
- `memoryUsage?: number`
|
|
58
|
+
|
|
59
|
+
## 9. ErrorMessage
|
|
60
|
+
- `category?: string` - 没有默认值
|
|
61
|
+
- `context?: any` - 根据参数构建,但内部字段可能为空
|
|
62
|
+
- `retryable?: boolean` - 没有默认值
|
|
63
|
+
|
|
64
|
+
## 10. ProgramResponseMessage
|
|
65
|
+
- `context?: ProgramContext` - 没有默认值(使用 result 参数)
|
|
66
|
+
- `report?: ReportMessage` - 根据 message 参数条件生成
|
|
67
|
+
- `executionTime?: number` - 没有默认值
|
|
68
|
+
|
|
69
|
+
## 11. ProgressUpdateMessage
|
|
70
|
+
- `context?: ProgramContext` - 没有默认值
|
|
71
|
+
- `command?: DeviceOperationRecord` - 没有默认值
|
|
72
|
+
- `report?: ReportMessage` - 根据 message 参数条件生成
|
|
73
|
+
- `code?: string` - 没有默认值
|
|
74
|
+
- `data?: Record<string, any>` - 没有默认值
|
|
75
|
+
|
|
76
|
+
## 12. DeviceOperationRecord
|
|
77
|
+
- `result?: Record<string, any>` - 没有默认值
|
|
78
|
+
|
|
79
|
+
## 建议
|
|
80
|
+
|
|
81
|
+
### 可以考虑添加默认值的字段:
|
|
82
|
+
1. **retryCount** - 可以默认为 0
|
|
83
|
+
2. **metadata** - 可以默认为空对象 {}
|
|
84
|
+
3. **latency** - 可以根据时间戳计算
|
|
85
|
+
4. **executionTime** - 可以根据开始和结束时间计算
|
|
86
|
+
|
|
87
|
+
### 不应该有默认值的字段:
|
|
88
|
+
1. **sessionId** - 必须由服务器生成
|
|
89
|
+
2. **result** - 必须是实际执行结果
|
|
90
|
+
3. **error** - 只在错误时存在
|
|
91
|
+
4. **serverInfo/serverStatus** - 必须是实际服务器状态
|
|
92
|
+
5. **context** - 必须是实际上下文信息
|
|
93
|
+
|
|
94
|
+
### Gateway 迁移注意事项:
|
|
95
|
+
- 这些没有默认值的可选字段,Gateway 可以根据实际情况选择性提供
|
|
96
|
+
- 不提供时,字段会被省略(undefined),这符合 Protocol 的设计
|
|
97
|
+
- 某些字段(如 metadata)虽然没有默认值,但 Gateway 可以在自己的代码中设置默认空对象
|