@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.
Files changed (78) hide show
  1. package/ACK_MESSAGES_IMPLEMENTATION_SUMMARY.md +128 -0
  2. package/ACK_MESSAGE_DESIGN.md +457 -0
  3. package/CHANGELOG.md +58 -0
  4. package/COMMAND_VALIDATION_RULES.md +178 -0
  5. package/DOCUMENTATION_REORGANIZATION_SUMMARY.md +81 -0
  6. package/DOCUMENTATION_STRUCTURE.md +106 -0
  7. package/GATEWAY_MIGRATION_GUIDE.md +130 -0
  8. package/GATEWAY_PROTOCOL_COMPARISON.md +216 -0
  9. package/INTEGRATION_GUIDE.md +190 -0
  10. package/OPTIONAL_FIELDS_WITHOUT_DEFAULTS.md +97 -0
  11. package/PROTOCOL_UTILS_USAGE.md +278 -0
  12. package/README.md +237 -0
  13. package/TYPE_FIXES_SUMMARY.md +210 -0
  14. package/UPDATE_ENUM_VALUES.md +139 -0
  15. package/dist/asyncapi-sync.d.ts +47 -0
  16. package/dist/asyncapi-sync.d.ts.map +1 -0
  17. package/dist/asyncapi-sync.js +85 -0
  18. package/dist/asyncapi-sync.js.map +1 -0
  19. package/dist/command-factory.d.ts +62 -0
  20. package/dist/command-factory.d.ts.map +1 -0
  21. package/dist/command-factory.js +137 -0
  22. package/dist/command-factory.js.map +1 -0
  23. package/dist/command-types.d.ts +27 -0
  24. package/dist/command-types.d.ts.map +1 -0
  25. package/dist/command-types.js +31 -0
  26. package/dist/command-types.js.map +1 -0
  27. package/dist/index.d.ts +403 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +413 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/message-validator.d.ts +102 -0
  32. package/dist/message-validator.d.ts.map +1 -0
  33. package/dist/message-validator.js +640 -0
  34. package/dist/message-validator.js.map +1 -0
  35. package/dist/protocol-utils.d.ts +108 -0
  36. package/dist/protocol-utils.d.ts.map +1 -0
  37. package/dist/protocol-utils.js +293 -0
  38. package/dist/protocol-utils.js.map +1 -0
  39. package/docs/01-protocol/README.md +45 -0
  40. package/docs/01-protocol/design-rationale.md +198 -0
  41. package/docs/01-protocol/message-types.md +669 -0
  42. package/docs/01-protocol/specification.md +1466 -0
  43. package/docs/02-commands/README.md +56 -0
  44. package/docs/02-commands/batch-command.md +435 -0
  45. package/docs/02-commands/complex-command.md +537 -0
  46. package/docs/02-commands/simple-command.md +332 -0
  47. package/docs/02-commands/typed-commands.md +362 -0
  48. package/docs/03-architecture/README.md +66 -0
  49. package/docs/03-architecture/device-protocol.md +430 -0
  50. package/docs/03-architecture/edge-proxy.md +727 -0
  51. package/docs/03-architecture/routing-flow.md +893 -0
  52. package/docs/04-integration/README.md +144 -0
  53. package/docs/04-integration/backend-guide.md +551 -0
  54. package/docs/04-integration/edge-guide.md +684 -0
  55. package/docs/04-integration/gateway-guide.md +180 -0
  56. package/docs/04-integration/migration-guide.md +226 -0
  57. package/docs/05-examples/README.md +141 -0
  58. package/docs/05-examples/progress-update-examples.md +757 -0
  59. package/docs/06-reference/README.md +67 -0
  60. package/docs/06-reference/api.md +572 -0
  61. package/docs/06-reference/faq.md +302 -0
  62. package/docs/06-reference/glossary.md +232 -0
  63. package/examples/backend-upgrade.ts +279 -0
  64. package/examples/edge-multi-device.ts +513 -0
  65. package/examples/gateway-upgrade.ts +150 -0
  66. package/examples/protocol-implementation.ts +715 -0
  67. package/package.json +48 -0
  68. package/scripts/validate-asyncapi.ts +78 -0
  69. package/src/__tests__/protocol.test.ts +297 -0
  70. package/src/asyncapi-sync.ts +84 -0
  71. package/src/command-factory.ts +183 -0
  72. package/src/command-types.ts +72 -0
  73. package/src/edge-proxy.ts +494 -0
  74. package/src/gateway-extensions.ts +278 -0
  75. package/src/index.ts +792 -0
  76. package/src/message-validator.ts +726 -0
  77. package/src/protocol-utils.ts +355 -0
  78. package/tsconfig.json +24 -0
package/src/index.ts ADDED
@@ -0,0 +1,792 @@
1
+ /**
2
+ * JRSoft Subway 统一WebSocket协议定义
3
+ * 版本: 1.0
4
+ *
5
+ * 功能特性:
6
+ * 1. 统一消息格式定义
7
+ * 2. 支持设备注册、命令执行、心跳等核心功能
8
+ * 3. 支持 Edge 代理模式
9
+ */
10
+
11
+ // 消息类型枚举
12
+ export enum MessageType {
13
+ // 连接管理
14
+ REGISTER = 'REGISTER',
15
+ REGISTER_ACK = 'REGISTER_ACK',
16
+ UNREGISTER = 'UNREGISTER',
17
+ UNREGISTER_ACK = 'UNREGISTER_ACK',
18
+
19
+ // 心跳
20
+ HEARTBEAT = 'HEARTBEAT',
21
+ HEARTBEAT_ACK = 'HEARTBEAT_ACK',
22
+
23
+ // 命令执行
24
+ COMMAND = 'COMMAND',
25
+ COMMAND_RESPONSE = 'COMMAND_RESPONSE',
26
+
27
+ // 程序管理
28
+ PROGRAM = 'PROGRAM',
29
+ PROGRAM_RESPONSE = 'PROGRAM_RESPONSE',
30
+
31
+ // 进度更新
32
+ PROGRESS_UPDATE = 'PROGRESS_UPDATE',
33
+
34
+ // 错误
35
+ ERROR = 'ERROR'
36
+ }
37
+
38
+ // 客户端类型
39
+ export enum ClientType {
40
+ DEVICE = 'DEVICE',
41
+ BACKEND = 'BACKEND',
42
+ EDGE = 'EDGE',
43
+ GATEWAY = 'GATEWAY' // 添加缺失的 GATEWAY 类型
44
+ }
45
+
46
+ // 操作类型
47
+ export enum OperationType {
48
+ READ = 'READ',
49
+ WRITE = 'WRITE',
50
+ QUERY = 'QUERY',
51
+ UPDATE = 'UPDATE',
52
+ CONTROL = 'CONTROL'
53
+ }
54
+
55
+ // 优先级
56
+ export enum Priority {
57
+ LOW = 'LOW',
58
+ NORMAL = 'NORMAL',
59
+ HIGH = 'HIGH',
60
+ CRITICAL = 'CRITICAL',
61
+ EMERGENCY = 'EMERGENCY'
62
+ }
63
+
64
+ // 命令状态
65
+ export enum CommandStatus {
66
+ COMPLETED = 'COMPLETED',
67
+ FAILED = 'FAILED',
68
+ TIMEOUT = 'TIMEOUT',
69
+ CANCELLED = 'CANCELLED',
70
+ IN_PROGRESS = 'IN_PROGRESS' // Gateway特有
71
+ }
72
+
73
+ // 基础消息接口
74
+ export interface BaseMessage {
75
+ type: MessageType;
76
+ timestamp: string; // ISO 8601 格式
77
+ version: string; // 协议版本 "1.0"
78
+ }
79
+
80
+ // 客户端信息(可选,用于扩展信息)
81
+ export interface ClientInfo {
82
+ name?: string;
83
+ version?: string;
84
+ platform?: string;
85
+ capabilities?: string[];
86
+ deviceType?: string; // 设备类型,用于设备端
87
+ description?: string;
88
+ metadata?: Record<string, any>;
89
+ }
90
+
91
+ // Edge 信息(设备端通过 Edge 注册时包含)
92
+ export interface EdgeInfo {
93
+ edgeId: string;
94
+ edgeVersion?: string;
95
+ connectionTime?: string;
96
+ }
97
+
98
+ // 注册消息
99
+ export interface RegisterMessage extends BaseMessage {
100
+ type: MessageType.REGISTER;
101
+ clientId: string; // 客户端唯一标识符
102
+ clientType: ClientType;
103
+ clientInfo?: ClientInfo;
104
+ edgeInfo?: EdgeInfo; // 当设备通过 Edge 注册时包含
105
+ }
106
+
107
+ // 注册确认消息
108
+ export interface RegisterAckMessage extends BaseMessage {
109
+ type: MessageType.REGISTER_ACK;
110
+ clientId: string; // 确认的客户端ID
111
+ success: boolean; // 注册是否成功
112
+ sessionId?: string; // 成功时分配的会话ID
113
+ error?: { // 失败时的错误信息
114
+ code: string;
115
+ message: string;
116
+ };
117
+ serverInfo?: { // 服务器信息
118
+ version: string;
119
+ capabilities: string[];
120
+ currentLoad?: number; // 当前负载
121
+ maxClients?: number; // 最大客户端数
122
+ };
123
+ }
124
+
125
+ // 注销消息
126
+ export interface UnregisterMessage extends BaseMessage {
127
+ type: MessageType.UNREGISTER;
128
+ clientId: string; // 客户端唯一标识符
129
+ reason?: string; // 注销原因
130
+ }
131
+
132
+ // 注销确认消息
133
+ export interface UnregisterAckMessage extends BaseMessage {
134
+ type: MessageType.UNREGISTER_ACK;
135
+ clientId: string; // 客户端唯一标识符
136
+ success: boolean; // 注销是否成功
137
+ cleanupInfo?: { // 清理信息
138
+ messagesProcessed: number; // 已处理的消息数
139
+ pendingMessages: number; // 待处理的消息数
140
+ connectionDuration: number; // 连接持续时间(秒)
141
+ };
142
+ }
143
+
144
+ // 引用生成的强类型命令
145
+ import type { SpecificCommand as ImportedSpecificCommand, CommandTypeMap as ImportedCommandTypeMap } from './command-types';
146
+ export type SpecificCommand = ImportedSpecificCommand;
147
+ export type CommandTypeMap = ImportedCommandTypeMap;
148
+
149
+ // 基础命令接口
150
+ export interface BaseCommand {
151
+ commandCode: string;
152
+ parameters?: Record<string, any>;
153
+ }
154
+
155
+ // 简单命令接口(点对点)
156
+ export interface SimpleCommand extends BaseCommand {
157
+ commandType: CommandType.SIMPLE;
158
+ deviceId: number | string; // 必需:单个设备
159
+ deviceType: string; // 必需
160
+ operationType: OperationType; // 必需
161
+ }
162
+
163
+ // 批量命令接口(多设备)
164
+ export interface BatchCommand extends BaseCommand {
165
+ commandType: CommandType.BATCH;
166
+ deviceId: number[] | string; // 必需:设备数组或范围表达式
167
+ deviceType: string; // 必需
168
+ operationType: OperationType; // 必需
169
+ }
170
+
171
+ // 复杂命令接口(持续响应)
172
+ export interface ComplexCommand extends BaseCommand {
173
+ commandType: CommandType.COMPLEX;
174
+ deviceId?: number | number[] | string; // 可选
175
+ deviceType?: string; // 可选
176
+ operationType?: OperationType; // 可选
177
+ }
178
+
179
+ // 通用命令接口(用于运行时动态命令)
180
+ // 注意:字段是否必需由 MessageValidator 根据 commandType 在运行时验证
181
+ export interface GenericCommand extends BaseCommand {
182
+ commandType?: CommandType; // 可选,默认为 SIMPLE
183
+ deviceId?: number | number[] | string; // 可选,验证器会检查
184
+ deviceType?: string; // 可选,验证器会检查
185
+ operationType?: OperationType; // 可选,验证器会检查
186
+ }
187
+
188
+ // 命令详情 - 支持强类型和通用类型
189
+ export type Command = SpecificCommand | SimpleCommand | BatchCommand | ComplexCommand | GenericCommand;
190
+
191
+ // 命令类型
192
+ export enum CommandType {
193
+ SIMPLE = 'SIMPLE', // 点对点命令
194
+ BATCH = 'BATCH', // 多设备命令
195
+ COMPLEX = 'COMPLEX' // 持续响应命令
196
+ }
197
+
198
+ // 命令消息
199
+ export interface CommandMessage extends BaseMessage {
200
+ type: MessageType.COMMAND;
201
+ requestRef: string;
202
+ targetClientId: string; // 目标客户端 ID (所有类型必需)
203
+ command: Command; // 所有类型都使用command字段
204
+ priority: Priority;
205
+ timeout: number;
206
+ retryCount?: number;
207
+ callback: string; // 回调地址,用于接收命令响应
208
+ metadata?: Record<string, any>;
209
+ }
210
+
211
+ // 命令执行结果
212
+ export interface CommandResult {
213
+ deviceType: string;
214
+ deviceId: number | string;
215
+ commandCode: string;
216
+ operationType: OperationType;
217
+ data: Record<string, any>;
218
+ }
219
+
220
+ // 命令响应消息
221
+ export interface CommandResponseMessage extends BaseMessage {
222
+ type: MessageType.COMMAND_RESPONSE;
223
+ requestRef: string;
224
+ status: CommandStatus;
225
+ result?: CommandResult; // 命令执行结果
226
+ report?: ReportMessage;
227
+ executionTime?: number;
228
+ }
229
+ // 注意:批量命令和复杂命令通过 progress_update 报告执行进度,最终返回简单的 command_response
230
+
231
+ // 心跳消息
232
+ export interface HeartbeatMessage extends BaseMessage {
233
+ type: MessageType.HEARTBEAT;
234
+ clientId: string; // 客户端唯一标识符
235
+ sequence: number; // 序列号,用于匹配请求和响应
236
+ clientTime: string; // 客户端时间戳
237
+ }
238
+
239
+ // 心跳确认消息
240
+ export interface HeartbeatAckMessage extends BaseMessage {
241
+ type: MessageType.HEARTBEAT_ACK;
242
+ clientId: string; // 客户端唯一标识符
243
+ sequence: number; // 原始序列号
244
+ clientTime: string; // 原始客户端时间
245
+ serverTime: string; // 服务器时间
246
+ latency?: number; // 服务器处理延迟(毫秒)
247
+ serverStatus?: { // 服务器状态
248
+ healthy: boolean;
249
+ activeConnections: number;
250
+ messageQueueSize: number;
251
+ cpuUsage?: number;
252
+ memoryUsage?: number;
253
+ };
254
+ }
255
+
256
+ // 错误消息
257
+ export interface ErrorMessage extends BaseMessage {
258
+ type: MessageType.ERROR;
259
+ code: string;
260
+ message: string;
261
+ severity?: string;
262
+ category?: string;
263
+ context?: any;
264
+ retryable?: boolean;
265
+ }
266
+
267
+ // 程序类型
268
+ export enum ProgramType {
269
+ DYNAMIC = 'DYNAMIC',
270
+ STATIC = 'STATIC'
271
+ }
272
+
273
+ // 程序方向
274
+ export enum ProgramDirection {
275
+ LEFT_TO_RIGHT = 'LEFT_TO_RIGHT',
276
+ RIGHT_TO_LEFT = 'RIGHT_TO_LEFT'
277
+ }
278
+
279
+ // 程序上传参数
280
+ export interface ProgramParameters {
281
+ deviceId: string;
282
+ taskId: string; // Snowflake ID
283
+ programId: string; // Snowflake ID
284
+ programName: string;
285
+ programNumber: number; // 1-10
286
+ programType: ProgramType;
287
+ width: number;
288
+ height: number;
289
+ direction: ProgramDirection;
290
+ publishTime: string; // 上刊时间
291
+ unpublishTime: string; // 下刊时间
292
+ downloadUrl: string;
293
+ checksum: string;
294
+ hashAlgorithm: 'SHA256';
295
+ fileSize: number;
296
+ }
297
+
298
+ // 程序消息
299
+ export interface ProgramMessage extends BaseMessage {
300
+ type: MessageType.PROGRAM;
301
+ requestRef: string;
302
+ targetClientId: string; // 目标客户端 ID
303
+ command: {
304
+ commandCode: 'UPLOAD_PROGRAM';
305
+ parameters: ProgramParameters;
306
+ };
307
+ priority: Priority;
308
+ timeout: number;
309
+ callback: string; // 回调地址,用于接收程序上传进度和结果
310
+ }
311
+
312
+ // 程序响应消息
313
+ export interface ProgramResponseMessage extends BaseMessage {
314
+ type: MessageType.PROGRAM_RESPONSE;
315
+ requestRef: string;
316
+ status: CommandStatus; // 使用相同的状态枚举
317
+ context?: ProgramContext; // 上下文信息(可选)
318
+ report?: ReportMessage; // 日志信息(可选)
319
+ executionTime?: number; // 总执行时间(毫秒)
320
+ }
321
+
322
+ // 进度阶段
323
+ export enum ProgressPhase {
324
+ DOWNLOAD = 'DOWNLOAD', // 下载文件
325
+ DECOMPRESS = 'DECOMPRESS', // 解压文件
326
+ PREPROCESS = 'PREPROCESS', // 预处理
327
+ FRAMES = 'FRAMES', // 创建帧
328
+ UPLOAD = 'UPLOAD', // 上传到设备
329
+ STATS = 'STATS' // 统计信息
330
+ }
331
+
332
+ // 设备操作记录
333
+ export interface DeviceOperationRecord {
334
+ commandType: CommandType; // 命令类型
335
+ commandCode: string; // 命令代码
336
+ deviceType: string; // 设备类型
337
+ deviceId: number | string; // 设备ID
338
+ operationType: OperationType; // 读写类型
339
+ result?: Record<string, any>; // 命令执行结果对象
340
+ }
341
+
342
+ // 进度状态
343
+ export enum ProgressStatus {
344
+ PENDING = 'PENDING',
345
+ IN_PROGRESS = 'IN_PROGRESS',
346
+ PAUSED = 'PAUSED',
347
+ COMPLETED = 'COMPLETED',
348
+ FAILED = 'FAILED',
349
+ CANCELLED = 'CANCELLED'
350
+ }
351
+
352
+ // 程序上下文信息
353
+ export interface ProgramContext {
354
+ taskId: string; // Snowflake ID
355
+ programId: string; // Snowflake ID
356
+ programName: string; // 程序名称
357
+ programNumber: number; // 1-10
358
+ programType: ProgramType; // dynamic | static
359
+ }
360
+
361
+ // 报告级别
362
+ export enum ReportLevel {
363
+ DEBUG = 'DEBUG',
364
+ INFO = 'INFO',
365
+ WARNING = 'WARNING',
366
+ ERROR = 'ERROR',
367
+ CRITICAL = 'CRITICAL'
368
+ }
369
+
370
+ // 报告信息
371
+ export interface ReportMessage {
372
+ level: ReportLevel;
373
+ message: string; // 报告消息
374
+ code?: string; // 标准化的消息代码
375
+ data?: Record<string, any>; // 额外的数据对象
376
+ }
377
+
378
+ // 进度更新消息
379
+ export interface ProgressUpdateMessage extends BaseMessage {
380
+ type: MessageType.PROGRESS_UPDATE;
381
+ requestRef: string;
382
+ status: ProgressStatus; // 状态
383
+ phase: ProgressPhase | string; // 当前阶段(支持自定义阶段)
384
+ progress: number; // 0-100 进度百分比
385
+ sourceType: 'COMMAND' | 'SYSTEM'; // 来源类型:命令操作结果 或 系统类型结果
386
+ context?: ProgramContext; // 上下文信息(用于程序上传相关的进度更新)
387
+ command?: DeviceOperationRecord; // 设备操作记录(当涉及设备读写时)
388
+ report?: ReportMessage; // 日志信息(可选)
389
+ timestamp: string; // ISO 8601 时间戳
390
+ version: string; // 协议版本
391
+ }
392
+
393
+ // 类型守卫函数
394
+ export function isRegisterMessage(msg: any): msg is RegisterMessage {
395
+ return msg && msg.type === MessageType.REGISTER;
396
+ }
397
+
398
+ export function isRegisterAckMessage(msg: any): msg is RegisterAckMessage {
399
+ return msg && msg.type === MessageType.REGISTER_ACK;
400
+ }
401
+
402
+ export function isUnregisterMessage(msg: any): msg is UnregisterMessage {
403
+ return msg && msg.type === MessageType.UNREGISTER;
404
+ }
405
+
406
+ export function isUnregisterAckMessage(msg: any): msg is UnregisterAckMessage {
407
+ return msg && msg.type === MessageType.UNREGISTER_ACK;
408
+ }
409
+
410
+ export function isHeartbeatMessage(msg: any): msg is HeartbeatMessage {
411
+ return msg && msg.type === MessageType.HEARTBEAT;
412
+ }
413
+
414
+ export function isHeartbeatAckMessage(msg: any): msg is HeartbeatAckMessage {
415
+ return msg && msg.type === MessageType.HEARTBEAT_ACK;
416
+ }
417
+
418
+ export function isCommandMessage(msg: any): msg is CommandMessage {
419
+ return msg && msg.type === MessageType.COMMAND;
420
+ }
421
+
422
+ export function isCommandResponseMessage(msg: any): msg is CommandResponseMessage {
423
+ return msg && msg.type === MessageType.COMMAND_RESPONSE;
424
+ }
425
+
426
+ export function isProgramMessage(msg: any): msg is ProgramMessage {
427
+ return msg && msg.type === MessageType.PROGRAM;
428
+ }
429
+
430
+ export function isProgramResponseMessage(msg: any): msg is ProgramResponseMessage {
431
+ return msg && msg.type === MessageType.PROGRAM_RESPONSE;
432
+ }
433
+
434
+ export function isProgressUpdateMessage(msg: any): msg is ProgressUpdateMessage {
435
+ return msg && msg.type === MessageType.PROGRESS_UPDATE;
436
+ }
437
+
438
+ export function isErrorMessage(msg: any): msg is ErrorMessage {
439
+ return msg && msg.type === MessageType.ERROR;
440
+ }
441
+
442
+
443
+ // 消息工厂类 - 创建符合新协议的消息
444
+ export class MessageFactory {
445
+
446
+ /**
447
+ * 创建注册消息
448
+ */
449
+ static createRegisterMessage(
450
+ clientId: string,
451
+ clientType: ClientType,
452
+ clientInfo?: ClientInfo
453
+ ): RegisterMessage {
454
+ return {
455
+ type: MessageType.REGISTER,
456
+ clientId,
457
+ clientType,
458
+ clientInfo,
459
+ timestamp: new Date().toISOString(),
460
+ version: '1.0'
461
+ };
462
+ }
463
+
464
+ /**
465
+ * 创建命令消息
466
+ */
467
+ static createCommandMessage(
468
+ requestRef: string,
469
+ targetClientId: string,
470
+ command: Command,
471
+ callback: string,
472
+ options?: {
473
+ priority?: Priority;
474
+ timeout?: number;
475
+ retryCount?: number;
476
+ }
477
+ ): CommandMessage {
478
+ return {
479
+ type: MessageType.COMMAND,
480
+ requestRef,
481
+ targetClientId,
482
+ command: {
483
+ ...command,
484
+ commandType: command.commandType || CommandType.SIMPLE
485
+ },
486
+ priority: options?.priority || Priority.NORMAL,
487
+ timeout: options?.timeout || DEFAULT_TIMEOUT,
488
+ retryCount: options?.retryCount || 0, // 默认值 0
489
+ callback,
490
+ timestamp: new Date().toISOString(),
491
+ version: PROTOCOL_VERSION
492
+ };
493
+ }
494
+
495
+ /**
496
+ * 创建心跳消息
497
+ */
498
+ static createHeartbeatMessage(clientId: string, sequence: number): HeartbeatMessage {
499
+ const now = new Date().toISOString();
500
+ return {
501
+ type: MessageType.HEARTBEAT,
502
+ clientId,
503
+ sequence,
504
+ clientTime: now,
505
+ timestamp: now,
506
+ version: PROTOCOL_VERSION
507
+ };
508
+ }
509
+
510
+ /**
511
+ * 创建注销消息
512
+ */
513
+ static createUnregisterMessage(clientId: string, reason?: string): UnregisterMessage {
514
+ return {
515
+ type: MessageType.UNREGISTER,
516
+ clientId,
517
+ reason,
518
+ timestamp: new Date().toISOString(),
519
+ version: PROTOCOL_VERSION
520
+ };
521
+ }
522
+
523
+ /**
524
+ * 创建程序上传消息
525
+ */
526
+ static createProgramMessage(
527
+ requestRef: string,
528
+ targetClientId: string,
529
+ parameters: ProgramParameters,
530
+ callback: string,
531
+ options?: {
532
+ priority?: Priority;
533
+ timeout?: number;
534
+ }
535
+ ): ProgramMessage {
536
+ return {
537
+ type: MessageType.PROGRAM,
538
+ requestRef,
539
+ targetClientId,
540
+ command: {
541
+ commandCode: 'UPLOAD_PROGRAM',
542
+ parameters
543
+ },
544
+ priority: options?.priority || Priority.NORMAL,
545
+ timeout: options?.timeout || 1800000, // 30分钟
546
+ callback,
547
+ timestamp: new Date().toISOString(),
548
+ version: PROTOCOL_VERSION
549
+ };
550
+ }
551
+
552
+ /**
553
+ * 创建进度更新消息
554
+ */
555
+ static createProgressUpdateMessage(
556
+ requestRef: string,
557
+ phase: ProgressPhase | string,
558
+ progress: number,
559
+ message?: string,
560
+ status: ProgressStatus = ProgressStatus.IN_PROGRESS,
561
+ options?: {
562
+ level?: ReportLevel;
563
+ code?: string;
564
+ data?: Record<string, any>;
565
+ context?: ProgramContext;
566
+ command?: DeviceOperationRecord;
567
+ }
568
+ ): ProgressUpdateMessage {
569
+ return {
570
+ type: MessageType.PROGRESS_UPDATE,
571
+ requestRef,
572
+ status,
573
+ phase,
574
+ progress,
575
+ sourceType: options?.command ? 'COMMAND' : 'SYSTEM', // 根据是否有command自动判断
576
+ context: options?.context,
577
+ command: options?.command,
578
+ report: message ? {
579
+ level: options?.level || ReportLevel.INFO,
580
+ message,
581
+ code: options?.code,
582
+ data: options?.data
583
+ } : undefined,
584
+ timestamp: new Date().toISOString(),
585
+ version: PROTOCOL_VERSION
586
+ };
587
+ }
588
+
589
+ /**
590
+ * 创建命令响应消息 (Backend 急需)
591
+ */
592
+ static createCommandResponseMessage(
593
+ requestRef: string,
594
+ status: CommandStatus,
595
+ result: any,
596
+ message?: string,
597
+ options?: {
598
+ executionTime?: number;
599
+ report?: ReportMessage;
600
+ version?: string;
601
+ commandStartTime?: number; // 命令开始时间戳(毫秒)
602
+ }
603
+ ): CommandResponseMessage {
604
+ // 如果提供了开始时间但没有 executionTime,自动计算
605
+ const executionTime = options?.executionTime ||
606
+ (options?.commandStartTime ? Date.now() - options.commandStartTime : undefined);
607
+
608
+ return {
609
+ type: MessageType.COMMAND_RESPONSE,
610
+ requestRef,
611
+ status,
612
+ result,
613
+ report: options?.report || (message ? {
614
+ level: ReportLevel.INFO,
615
+ message
616
+ } : undefined),
617
+ executionTime,
618
+ timestamp: new Date().toISOString(),
619
+ version: options?.version || PROTOCOL_VERSION
620
+ };
621
+ }
622
+
623
+ /**
624
+ * 创建程序响应消息
625
+ */
626
+ static createProgramResponseMessage(
627
+ requestRef: string,
628
+ status: CommandStatus,
629
+ result: any,
630
+ message?: string,
631
+ options?: {
632
+ executionTime?: number;
633
+ programStartTime?: number; // 程序开始时间戳(毫秒)
634
+ }
635
+ ): ProgramResponseMessage {
636
+ // 如果提供了开始时间但没有 executionTime,自动计算
637
+ const executionTime = options?.executionTime ||
638
+ (options?.programStartTime ? Date.now() - options.programStartTime : undefined);
639
+
640
+ return {
641
+ type: MessageType.PROGRAM_RESPONSE,
642
+ requestRef,
643
+ status,
644
+ context: result,
645
+ report: message ? {
646
+ level: ReportLevel.INFO,
647
+ message
648
+ } : undefined,
649
+ executionTime,
650
+ timestamp: new Date().toISOString(),
651
+ version: PROTOCOL_VERSION
652
+ };
653
+ }
654
+
655
+ /**
656
+ * 创建错误消息 (Gateway & Backend 都需要)
657
+ */
658
+ static createErrorMessage(
659
+ code: string,
660
+ message: string,
661
+ requestRef?: string,
662
+ options?: {
663
+ level?: ReportLevel;
664
+ data?: Record<string, any>;
665
+ severity?: string;
666
+ category?: string;
667
+ retryable?: boolean;
668
+ }
669
+ ): ErrorMessage {
670
+ return {
671
+ type: MessageType.ERROR,
672
+ code,
673
+ message,
674
+ severity: options?.severity || 'ERROR',
675
+ category: options?.category,
676
+ context: {
677
+ requestRef,
678
+ data: options?.data
679
+ },
680
+ retryable: options?.retryable,
681
+ timestamp: new Date().toISOString(),
682
+ version: PROTOCOL_VERSION
683
+ };
684
+ }
685
+
686
+ /**
687
+ * 创建心跳确认消息 (Gateway 急需)
688
+ */
689
+ static createHeartbeatAckMessage(
690
+ sequence: number,
691
+ clientId?: string,
692
+ clientTime?: string,
693
+ options?: {
694
+ latency?: number;
695
+ heartbeatReceivedTime?: number; // 收到心跳的时间戳(毫秒)
696
+ }
697
+ ): HeartbeatAckMessage {
698
+ const now = new Date().toISOString();
699
+ const nowMs = Date.now();
700
+
701
+ // 如果提供了接收时间但没有 latency,自动计算处理延迟
702
+ const latency = options?.latency ||
703
+ (options?.heartbeatReceivedTime ? nowMs - options.heartbeatReceivedTime : undefined);
704
+
705
+ return {
706
+ type: MessageType.HEARTBEAT_ACK,
707
+ clientId: clientId || '',
708
+ sequence,
709
+ clientTime: clientTime || now, // 使用传入的客户端时间或当前时间
710
+ serverTime: now,
711
+ latency,
712
+ timestamp: now,
713
+ version: PROTOCOL_VERSION
714
+ };
715
+ }
716
+
717
+ /**
718
+ * 创建注册确认消息 (Gateway 需要)
719
+ */
720
+ static createRegisterAckMessage(
721
+ clientId: string,
722
+ success: boolean,
723
+ message?: string,
724
+ sessionId?: string
725
+ ): RegisterAckMessage {
726
+ return {
727
+ type: MessageType.REGISTER_ACK,
728
+ clientId,
729
+ success,
730
+ sessionId,
731
+ error: !success && message ? {
732
+ code: 'REGISTRATION_FAILED',
733
+ message
734
+ } : undefined,
735
+ timestamp: new Date().toISOString(),
736
+ version: PROTOCOL_VERSION
737
+ };
738
+ }
739
+
740
+ /**
741
+ * 创建注销确认消息
742
+ */
743
+ static createUnregisterAckMessage(
744
+ clientId: string,
745
+ success: boolean
746
+ ): UnregisterAckMessage {
747
+ return {
748
+ type: MessageType.UNREGISTER_ACK,
749
+ clientId,
750
+ success,
751
+ timestamp: new Date().toISOString(),
752
+ version: PROTOCOL_VERSION
753
+ };
754
+ }
755
+ }
756
+
757
+
758
+ // 导出所有类型
759
+ export type AnyMessage =
760
+ | RegisterMessage
761
+ | RegisterAckMessage
762
+ | UnregisterMessage
763
+ | UnregisterAckMessage
764
+ | CommandMessage
765
+ | CommandResponseMessage
766
+ | ProgramMessage
767
+ | ProgramResponseMessage
768
+ | HeartbeatMessage
769
+ | HeartbeatAckMessage
770
+ | ProgressUpdateMessage
771
+ | ErrorMessage;
772
+
773
+ // 导出常量
774
+ export const PROTOCOL_VERSION = '1.0';
775
+ export const DEFAULT_TIMEOUT = 10000;
776
+ export const DEFAULT_PRIORITY = Priority.NORMAL;
777
+
778
+ // 导出强类型命令系统
779
+ export * from './command-types';
780
+ export * from './command-factory';
781
+
782
+ // 导出消息验证器
783
+ export { MessageValidator, ValidationResult } from './message-validator';
784
+
785
+ // 导出协议工具类
786
+ export { ProtocolUtils } from './protocol-utils';
787
+
788
+ // 导出 Gateway 扩展 (暂时禁用,有编译错误)
789
+ // export * from './gateway-extensions';
790
+
791
+ // 导出 Edge 代理模式 (暂时禁用,有编译错误)
792
+ // export * from './edge-proxy';