@hla4ts/hla-api 0.1.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/README.md +436 -0
- package/package.json +48 -0
- package/src/callback-dispatcher.ts +673 -0
- package/src/converters.ts +449 -0
- package/src/encoding.ts +52 -0
- package/src/exceptions.ts +971 -0
- package/src/federate-ambassador.ts +874 -0
- package/src/index.ts +378 -0
- package/src/rti-ambassador.ts +1441 -0
- package/src/types.ts +440 -0
|
@@ -0,0 +1,1441 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RTI Ambassador
|
|
3
|
+
*
|
|
4
|
+
* This module provides the high-level HLA 4 RTI Ambassador API for TypeScript.
|
|
5
|
+
* The RTI Ambassador is the main interface for federates to interact with the RTI.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Session, type HlaCallbackRequestListener } from "@hla4ts/session";
|
|
9
|
+
import { type Transport, TlsTransport, TcpTransport } from "@hla4ts/transport";
|
|
10
|
+
import {
|
|
11
|
+
CallRequestCodec,
|
|
12
|
+
CallResponseCodec,
|
|
13
|
+
type CallRequest,
|
|
14
|
+
type CallResponse,
|
|
15
|
+
ResignAction,
|
|
16
|
+
} from "@hla4ts/proto";
|
|
17
|
+
|
|
18
|
+
import type { FederateAmbassador } from "./federate-ambassador.ts";
|
|
19
|
+
import { CallbackDispatcher } from "./callback-dispatcher.ts";
|
|
20
|
+
import {
|
|
21
|
+
NotConnected,
|
|
22
|
+
AlreadyConnected,
|
|
23
|
+
createExceptionFromProto,
|
|
24
|
+
CallNotAllowedFromWithinCallback,
|
|
25
|
+
} from "./exceptions.ts";
|
|
26
|
+
import {
|
|
27
|
+
convertJoinResult,
|
|
28
|
+
convertObjectInstanceHandle,
|
|
29
|
+
convertConfigurationResult,
|
|
30
|
+
convertLogicalTime,
|
|
31
|
+
convertLogicalTimeInterval,
|
|
32
|
+
convertTimeQueryReturn,
|
|
33
|
+
toProtoObjectClassHandle,
|
|
34
|
+
toProtoAttributeHandleSet,
|
|
35
|
+
toProtoInteractionClassHandle,
|
|
36
|
+
toProtoObjectInstanceHandle,
|
|
37
|
+
toProtoAttributeHandleValueMap,
|
|
38
|
+
toProtoParameterHandleValueMap,
|
|
39
|
+
toProtoLogicalTime,
|
|
40
|
+
toProtoLogicalTimeInterval,
|
|
41
|
+
toProtoFederateHandleSet,
|
|
42
|
+
toProtoRtiConfiguration,
|
|
43
|
+
toProtoCredentials,
|
|
44
|
+
toProtoFomModule,
|
|
45
|
+
toProtoFomModuleSet,
|
|
46
|
+
} from "./converters.ts";
|
|
47
|
+
import type {
|
|
48
|
+
ObjectClassHandle,
|
|
49
|
+
AttributeHandleSet,
|
|
50
|
+
InteractionClassHandle,
|
|
51
|
+
ObjectInstanceHandle,
|
|
52
|
+
AttributeHandleValueMap,
|
|
53
|
+
ParameterHandleValueMap,
|
|
54
|
+
UserSuppliedTag,
|
|
55
|
+
LogicalTime,
|
|
56
|
+
LogicalTimeInterval,
|
|
57
|
+
MessageRetractionReturn,
|
|
58
|
+
TimeQueryReturn,
|
|
59
|
+
JoinResult,
|
|
60
|
+
FederateHandleSet,
|
|
61
|
+
FomModule,
|
|
62
|
+
FomModuleSet,
|
|
63
|
+
ConfigurationResult,
|
|
64
|
+
ConnectionOptions,
|
|
65
|
+
} from "./types.ts";
|
|
66
|
+
|
|
67
|
+
// =============================================================================
|
|
68
|
+
// RTI Ambassador Options
|
|
69
|
+
// =============================================================================
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Options for creating an RTI Ambassador.
|
|
73
|
+
*/
|
|
74
|
+
export interface RTIAmbassadorOptions {
|
|
75
|
+
/** RTI host address */
|
|
76
|
+
host: string;
|
|
77
|
+
|
|
78
|
+
/** RTI port (default: 15165 for TLS, 15164 for TCP) */
|
|
79
|
+
port?: number;
|
|
80
|
+
|
|
81
|
+
/** Use TLS (default: true) */
|
|
82
|
+
useTls?: boolean;
|
|
83
|
+
|
|
84
|
+
/** Connection timeout in milliseconds (default: 30000) */
|
|
85
|
+
connectionTimeout?: number;
|
|
86
|
+
|
|
87
|
+
/** Response timeout in milliseconds (default: 180000) */
|
|
88
|
+
responseTimeout?: number;
|
|
89
|
+
|
|
90
|
+
/** TLS options (certificate paths, etc.) */
|
|
91
|
+
tlsOptions?: {
|
|
92
|
+
/** Path to CA certificate file */
|
|
93
|
+
ca?: string;
|
|
94
|
+
/** Path to client certificate file */
|
|
95
|
+
cert?: string;
|
|
96
|
+
/** Path to client private key file */
|
|
97
|
+
key?: string;
|
|
98
|
+
/** Skip server verification (INSECURE) */
|
|
99
|
+
rejectUnauthorized?: boolean;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// =============================================================================
|
|
104
|
+
// RTI Ambassador
|
|
105
|
+
// =============================================================================
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* RTI Ambassador - Main interface for federate-to-RTI communication.
|
|
109
|
+
*
|
|
110
|
+
* The RTI Ambassador provides methods for all HLA services:
|
|
111
|
+
* - Federation Management (create, join, resign, destroy)
|
|
112
|
+
* - Declaration Management (publish, subscribe)
|
|
113
|
+
* - Object Management (register, update, delete, interactions)
|
|
114
|
+
* - Time Management (constrained, regulation, advance)
|
|
115
|
+
* - Ownership Management (acquire, divest)
|
|
116
|
+
* - Support Services (handle/name lookups)
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* import { RTIAmbassador, BaseFederateAmbassador, CallbackModel } from '@hla4ts/hla-api';
|
|
121
|
+
*
|
|
122
|
+
* // Create federate ambassador
|
|
123
|
+
* class MyFederateAmbassador extends BaseFederateAmbassador {
|
|
124
|
+
* discoverObjectInstance(objectInstance, objectClass, name) {
|
|
125
|
+
* console.log(`Discovered: ${name}`);
|
|
126
|
+
* }
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* // Create RTI ambassador
|
|
130
|
+
* const rtiAmbassador = new RTIAmbassador({ host: 'rti.example.com' });
|
|
131
|
+
*
|
|
132
|
+
* // Connect and join
|
|
133
|
+
* const federateAmbassador = new MyFederateAmbassador();
|
|
134
|
+
* await rtiAmbassador.connect(federateAmbassador, { callbackModel: CallbackModel.EVOKED });
|
|
135
|
+
* const joinResult = await rtiAmbassador.joinFederationExecution('MyFederate', 'FederateType', 'TestFederation');
|
|
136
|
+
*
|
|
137
|
+
* // ... do HLA operations ...
|
|
138
|
+
*
|
|
139
|
+
* // Clean up
|
|
140
|
+
* await rtiAmbassador.resignFederationExecution(ResignAction.DELETE_OBJECTS_THEN_DIVEST);
|
|
141
|
+
* await rtiAmbassador.disconnect();
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export class RTIAmbassador {
|
|
145
|
+
private readonly _options: Required<RTIAmbassadorOptions>;
|
|
146
|
+
private _transport: Transport | null = null;
|
|
147
|
+
private _session: Session | null = null;
|
|
148
|
+
private _callbackDispatcher: CallbackDispatcher | null = null;
|
|
149
|
+
private _inCallback = false;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Create a new RTI Ambassador.
|
|
153
|
+
*
|
|
154
|
+
* @param options - Connection options
|
|
155
|
+
*/
|
|
156
|
+
constructor(options: RTIAmbassadorOptions) {
|
|
157
|
+
this._options = {
|
|
158
|
+
host: options.host,
|
|
159
|
+
port: options.port ?? (options.useTls !== false ? 15165 : 15164),
|
|
160
|
+
useTls: options.useTls ?? true,
|
|
161
|
+
connectionTimeout: options.connectionTimeout ?? 30000,
|
|
162
|
+
responseTimeout: options.responseTimeout ?? 180000,
|
|
163
|
+
tlsOptions: options.tlsOptions ?? {},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ===========================================================================
|
|
168
|
+
// Connection Management
|
|
169
|
+
// ===========================================================================
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Check if connected to the RTI.
|
|
173
|
+
*/
|
|
174
|
+
get isConnected(): boolean {
|
|
175
|
+
return this._session?.isOperational ?? false;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Connect to the RTI.
|
|
180
|
+
*
|
|
181
|
+
* @param federateAmbassador - The federate ambassador to receive callbacks
|
|
182
|
+
* @param options - Connection options
|
|
183
|
+
* @returns Configuration result
|
|
184
|
+
*/
|
|
185
|
+
async connect(
|
|
186
|
+
federateAmbassador: FederateAmbassador,
|
|
187
|
+
options: ConnectionOptions
|
|
188
|
+
): Promise<ConfigurationResult> {
|
|
189
|
+
if (this._session) {
|
|
190
|
+
throw new AlreadyConnected("Already connected to RTI");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this._callbackDispatcher = new CallbackDispatcher(federateAmbassador);
|
|
194
|
+
|
|
195
|
+
// Create transport
|
|
196
|
+
if (this._options.useTls) {
|
|
197
|
+
this._transport = new TlsTransport({
|
|
198
|
+
host: this._options.host,
|
|
199
|
+
port: this._options.port,
|
|
200
|
+
...this._options.tlsOptions,
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
this._transport = new TcpTransport({
|
|
204
|
+
host: this._options.host,
|
|
205
|
+
port: this._options.port,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Create session
|
|
210
|
+
this._session = new Session(this._transport, {
|
|
211
|
+
connectionTimeout: this._options.connectionTimeout,
|
|
212
|
+
responseTimeout: this._options.responseTimeout,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Create callback listener
|
|
216
|
+
const callbackListener: HlaCallbackRequestListener = {
|
|
217
|
+
onHlaCallbackRequest: (seqNum: number, callbackData: Uint8Array) => {
|
|
218
|
+
this._handleCallback(seqNum, callbackData);
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
// Start session
|
|
224
|
+
await this._session.start(callbackListener);
|
|
225
|
+
|
|
226
|
+
// Send Connect request
|
|
227
|
+
let callRequest: CallRequest;
|
|
228
|
+
|
|
229
|
+
if (options.credentials && options.rtiConfiguration) {
|
|
230
|
+
callRequest = {
|
|
231
|
+
connectWithConfigurationAndCredentialsRequest: {
|
|
232
|
+
rtiConfiguration: toProtoRtiConfiguration(options.rtiConfiguration),
|
|
233
|
+
credentials: toProtoCredentials(options.credentials),
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
} else if (options.credentials) {
|
|
237
|
+
callRequest = {
|
|
238
|
+
connectWithCredentialsRequest: {
|
|
239
|
+
credentials: toProtoCredentials(options.credentials),
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
} else if (options.rtiConfiguration) {
|
|
243
|
+
callRequest = {
|
|
244
|
+
connectWithConfigurationRequest: {
|
|
245
|
+
rtiConfiguration: toProtoRtiConfiguration(options.rtiConfiguration),
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
} else {
|
|
249
|
+
callRequest = {
|
|
250
|
+
connectRequest: {},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const response = await this._doHlaCall(callRequest);
|
|
255
|
+
|
|
256
|
+
// Extract configuration result
|
|
257
|
+
if (response.connectResponse) {
|
|
258
|
+
return convertConfigurationResult(response.connectResponse.configurationResult);
|
|
259
|
+
}
|
|
260
|
+
if (response.connectWithCredentialsResponse) {
|
|
261
|
+
return convertConfigurationResult(response.connectWithCredentialsResponse.configurationResult);
|
|
262
|
+
}
|
|
263
|
+
if (response.connectWithConfigurationResponse) {
|
|
264
|
+
return convertConfigurationResult(response.connectWithConfigurationResponse.configurationResult);
|
|
265
|
+
}
|
|
266
|
+
if (response.connectWithConfigurationAndCredentialsResponse) {
|
|
267
|
+
return convertConfigurationResult(response.connectWithConfigurationAndCredentialsResponse.configurationResult);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return { configurationUsed: false };
|
|
271
|
+
} catch (error) {
|
|
272
|
+
// Clean up on failure
|
|
273
|
+
this._cleanup();
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Disconnect from the RTI.
|
|
280
|
+
*/
|
|
281
|
+
async disconnect(): Promise<void> {
|
|
282
|
+
if (!this._session) {
|
|
283
|
+
return; // Already disconnected
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
// Send Disconnect request
|
|
288
|
+
await this._doHlaCall({ disconnectRequest: {} });
|
|
289
|
+
} finally {
|
|
290
|
+
// Terminate session
|
|
291
|
+
await this._session.terminate().catch(() => {});
|
|
292
|
+
this._cleanup();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Disconnect immediately without waiting for RTI responses.
|
|
298
|
+
*/
|
|
299
|
+
async disconnectNow(): Promise<void> {
|
|
300
|
+
if (!this._session) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
await this._session.terminate(0);
|
|
305
|
+
} catch {
|
|
306
|
+
// Best effort; fall through to cleanup.
|
|
307
|
+
} finally {
|
|
308
|
+
this._cleanup();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ===========================================================================
|
|
313
|
+
// Federation Management
|
|
314
|
+
// ===========================================================================
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Create a federation execution.
|
|
318
|
+
*
|
|
319
|
+
* @param federationName - Name of the federation
|
|
320
|
+
* @param fomModule - FOM module
|
|
321
|
+
*/
|
|
322
|
+
async createFederationExecution(federationName: string, fomModule: FomModule): Promise<void> {
|
|
323
|
+
await this._doHlaCall({
|
|
324
|
+
createFederationExecutionRequest: {
|
|
325
|
+
federationName,
|
|
326
|
+
fomModule: toProtoFomModule(fomModule),
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Create a federation execution with time representation.
|
|
333
|
+
*
|
|
334
|
+
* @param federationName - Name of the federation
|
|
335
|
+
* @param fomModule - FOM module
|
|
336
|
+
* @param logicalTimeImplementationName - Name of the logical time factory
|
|
337
|
+
*/
|
|
338
|
+
async createFederationExecutionWithTime(
|
|
339
|
+
federationName: string,
|
|
340
|
+
fomModule: FomModule,
|
|
341
|
+
logicalTimeImplementationName: string
|
|
342
|
+
): Promise<void> {
|
|
343
|
+
await this._doHlaCall({
|
|
344
|
+
createFederationExecutionWithTimeRequest: {
|
|
345
|
+
federationName,
|
|
346
|
+
fomModule: toProtoFomModule(fomModule),
|
|
347
|
+
logicalTimeImplementationName,
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Create a federation execution with multiple FOM modules.
|
|
354
|
+
*
|
|
355
|
+
* @param federationName - Name of the federation
|
|
356
|
+
* @param fomModules - FOM modules
|
|
357
|
+
*/
|
|
358
|
+
async createFederationExecutionWithModules(
|
|
359
|
+
federationName: string,
|
|
360
|
+
fomModules: FomModuleSet
|
|
361
|
+
): Promise<void> {
|
|
362
|
+
await this._doHlaCall({
|
|
363
|
+
createFederationExecutionWithModulesRequest: {
|
|
364
|
+
federationName,
|
|
365
|
+
fomModules: toProtoFomModuleSet(fomModules),
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Create a federation execution with multiple FOM modules and time.
|
|
372
|
+
*
|
|
373
|
+
* @param federationName - Name of the federation
|
|
374
|
+
* @param fomModules - FOM modules
|
|
375
|
+
* @param logicalTimeImplementationName - Name of the logical time factory
|
|
376
|
+
*/
|
|
377
|
+
async createFederationExecutionWithModulesAndTime(
|
|
378
|
+
federationName: string,
|
|
379
|
+
fomModules: FomModuleSet,
|
|
380
|
+
logicalTimeImplementationName: string
|
|
381
|
+
): Promise<void> {
|
|
382
|
+
await this._doHlaCall({
|
|
383
|
+
createFederationExecutionWithModulesAndTimeRequest: {
|
|
384
|
+
federationName,
|
|
385
|
+
fomModules: toProtoFomModuleSet(fomModules),
|
|
386
|
+
logicalTimeImplementationName,
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Destroy a federation execution.
|
|
393
|
+
*
|
|
394
|
+
* @param federationName - Name of the federation to destroy
|
|
395
|
+
*/
|
|
396
|
+
async destroyFederationExecution(federationName: string): Promise<void> {
|
|
397
|
+
await this._doHlaCall({
|
|
398
|
+
destroyFederationExecutionRequest: { federationName },
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* List federation executions (async - results come via callback).
|
|
404
|
+
*/
|
|
405
|
+
async listFederationExecutions(): Promise<void> {
|
|
406
|
+
await this._doHlaCall({ listFederationExecutionsRequest: {} });
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* List federation execution members (async - results come via callback).
|
|
411
|
+
*
|
|
412
|
+
* @param federationName - Name of the federation
|
|
413
|
+
*/
|
|
414
|
+
async listFederationExecutionMembers(federationName: string): Promise<void> {
|
|
415
|
+
await this._doHlaCall({
|
|
416
|
+
listFederationExecutionMembersRequest: { federationName },
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Join a federation execution.
|
|
422
|
+
*
|
|
423
|
+
* @param federateType - Type of the federate
|
|
424
|
+
* @param federationName - Name of the federation to join
|
|
425
|
+
* @returns Join result with federate handle and time implementation
|
|
426
|
+
*/
|
|
427
|
+
async joinFederationExecution(
|
|
428
|
+
federateType: string,
|
|
429
|
+
federationName: string
|
|
430
|
+
): Promise<JoinResult> {
|
|
431
|
+
this._throwIfInCallback("joinFederationExecution");
|
|
432
|
+
const response = await this._doHlaCall({
|
|
433
|
+
joinFederationExecutionRequest: { federateType, federationName },
|
|
434
|
+
});
|
|
435
|
+
return convertJoinResult(response.joinFederationExecutionResponse?.result);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Join a federation execution with a specific name.
|
|
440
|
+
*
|
|
441
|
+
* @param federateName - Name for this federate
|
|
442
|
+
* @param federateType - Type of the federate
|
|
443
|
+
* @param federationName - Name of the federation to join
|
|
444
|
+
* @returns Join result
|
|
445
|
+
*/
|
|
446
|
+
async joinFederationExecutionWithName(
|
|
447
|
+
federateName: string,
|
|
448
|
+
federateType: string,
|
|
449
|
+
federationName: string
|
|
450
|
+
): Promise<JoinResult> {
|
|
451
|
+
this._throwIfInCallback("joinFederationExecution");
|
|
452
|
+
const response = await this._doHlaCall({
|
|
453
|
+
joinFederationExecutionWithNameRequest: { federateName, federateType, federationName },
|
|
454
|
+
});
|
|
455
|
+
return convertJoinResult(response.joinFederationExecutionWithNameResponse?.result);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Join a federation execution with additional FOM modules.
|
|
460
|
+
*
|
|
461
|
+
* @param federateType - Type of the federate
|
|
462
|
+
* @param federationName - Name of the federation to join
|
|
463
|
+
* @param additionalFomModules - Additional FOM modules
|
|
464
|
+
* @returns Join result
|
|
465
|
+
*/
|
|
466
|
+
async joinFederationExecutionWithModules(
|
|
467
|
+
federateType: string,
|
|
468
|
+
federationName: string,
|
|
469
|
+
additionalFomModules: FomModuleSet
|
|
470
|
+
): Promise<JoinResult> {
|
|
471
|
+
this._throwIfInCallback("joinFederationExecution");
|
|
472
|
+
const response = await this._doHlaCall({
|
|
473
|
+
joinFederationExecutionWithModulesRequest: {
|
|
474
|
+
federateType,
|
|
475
|
+
federationName,
|
|
476
|
+
additionalFomModules: toProtoFomModuleSet(additionalFomModules),
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
return convertJoinResult(response.joinFederationExecutionWithModulesResponse?.result);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Join a federation execution with name and additional FOM modules.
|
|
484
|
+
*
|
|
485
|
+
* @param federateName - Name for this federate
|
|
486
|
+
* @param federateType - Type of the federate
|
|
487
|
+
* @param federationName - Name of the federation to join
|
|
488
|
+
* @param additionalFomModules - Additional FOM modules
|
|
489
|
+
* @returns Join result
|
|
490
|
+
*/
|
|
491
|
+
async joinFederationExecutionWithNameAndModules(
|
|
492
|
+
federateName: string,
|
|
493
|
+
federateType: string,
|
|
494
|
+
federationName: string,
|
|
495
|
+
additionalFomModules: FomModuleSet
|
|
496
|
+
): Promise<JoinResult> {
|
|
497
|
+
this._throwIfInCallback("joinFederationExecution");
|
|
498
|
+
const response = await this._doHlaCall({
|
|
499
|
+
joinFederationExecutionWithNameAndModulesRequest: {
|
|
500
|
+
federateName,
|
|
501
|
+
federateType,
|
|
502
|
+
federationName,
|
|
503
|
+
additionalFomModules: toProtoFomModuleSet(additionalFomModules),
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
return convertJoinResult(response.joinFederationExecutionWithNameAndModulesResponse?.result);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Resign from a federation execution.
|
|
511
|
+
*
|
|
512
|
+
* @param resignAction - Action to take when resigning
|
|
513
|
+
*/
|
|
514
|
+
async resignFederationExecution(resignAction: ResignAction): Promise<void> {
|
|
515
|
+
this._throwIfInCallback("resignFederationExecution");
|
|
516
|
+
await this._doHlaCall({
|
|
517
|
+
resignFederationExecutionRequest: { resignAction },
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// ===========================================================================
|
|
522
|
+
// Synchronization Point Services
|
|
523
|
+
// ===========================================================================
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Register a federation synchronization point.
|
|
527
|
+
*
|
|
528
|
+
* @param label - Synchronization point label
|
|
529
|
+
* @param userSuppliedTag - User-supplied tag
|
|
530
|
+
*/
|
|
531
|
+
async registerFederationSynchronizationPoint(
|
|
532
|
+
label: string,
|
|
533
|
+
userSuppliedTag: UserSuppliedTag
|
|
534
|
+
): Promise<void> {
|
|
535
|
+
await this._doHlaCall({
|
|
536
|
+
registerFederationSynchronizationPointRequest: {
|
|
537
|
+
synchronizationPointLabel: label,
|
|
538
|
+
userSuppliedTag,
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Register a federation synchronization point with a specific set of federates.
|
|
545
|
+
*
|
|
546
|
+
* @param label - Synchronization point label
|
|
547
|
+
* @param userSuppliedTag - User-supplied tag
|
|
548
|
+
* @param synchronizationSet - Set of federates to synchronize
|
|
549
|
+
*/
|
|
550
|
+
async registerFederationSynchronizationPointWithSet(
|
|
551
|
+
label: string,
|
|
552
|
+
userSuppliedTag: UserSuppliedTag,
|
|
553
|
+
synchronizationSet: FederateHandleSet
|
|
554
|
+
): Promise<void> {
|
|
555
|
+
await this._doHlaCall({
|
|
556
|
+
registerFederationSynchronizationPointWithSetRequest: {
|
|
557
|
+
synchronizationPointLabel: label,
|
|
558
|
+
userSuppliedTag,
|
|
559
|
+
synchronizationSet: toProtoFederateHandleSet(synchronizationSet),
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Indicate that this federate has achieved a synchronization point.
|
|
566
|
+
*
|
|
567
|
+
* @param label - Synchronization point label
|
|
568
|
+
* @param successfully - Whether the synchronization was successful
|
|
569
|
+
*/
|
|
570
|
+
async synchronizationPointAchieved(label: string, successfully: boolean = true): Promise<void> {
|
|
571
|
+
await this._doHlaCall({
|
|
572
|
+
synchronizationPointAchievedRequest: {
|
|
573
|
+
synchronizationPointLabel: label,
|
|
574
|
+
successfully,
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// ===========================================================================
|
|
580
|
+
// Declaration Management
|
|
581
|
+
// ===========================================================================
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Publish object class attributes.
|
|
585
|
+
*
|
|
586
|
+
* @param objectClass - Object class handle
|
|
587
|
+
* @param attributes - Set of attribute handles to publish
|
|
588
|
+
*/
|
|
589
|
+
async publishObjectClassAttributes(
|
|
590
|
+
objectClass: ObjectClassHandle,
|
|
591
|
+
attributes: AttributeHandleSet
|
|
592
|
+
): Promise<void> {
|
|
593
|
+
await this._doHlaCall({
|
|
594
|
+
publishObjectClassAttributesRequest: {
|
|
595
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
596
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
597
|
+
},
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Unpublish all attributes of an object class.
|
|
603
|
+
*
|
|
604
|
+
* @param objectClass - Object class handle
|
|
605
|
+
*/
|
|
606
|
+
async unpublishObjectClass(objectClass: ObjectClassHandle): Promise<void> {
|
|
607
|
+
await this._doHlaCall({
|
|
608
|
+
unpublishObjectClassRequest: {
|
|
609
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Unpublish specific attributes of an object class.
|
|
616
|
+
*
|
|
617
|
+
* @param objectClass - Object class handle
|
|
618
|
+
* @param attributes - Set of attribute handles to unpublish
|
|
619
|
+
*/
|
|
620
|
+
async unpublishObjectClassAttributes(
|
|
621
|
+
objectClass: ObjectClassHandle,
|
|
622
|
+
attributes: AttributeHandleSet
|
|
623
|
+
): Promise<void> {
|
|
624
|
+
await this._doHlaCall({
|
|
625
|
+
unpublishObjectClassAttributesRequest: {
|
|
626
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
627
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
628
|
+
},
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Publish an interaction class.
|
|
634
|
+
*
|
|
635
|
+
* @param interactionClass - Interaction class handle
|
|
636
|
+
*/
|
|
637
|
+
async publishInteractionClass(interactionClass: InteractionClassHandle): Promise<void> {
|
|
638
|
+
await this._doHlaCall({
|
|
639
|
+
publishInteractionClassRequest: {
|
|
640
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
641
|
+
},
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Unpublish an interaction class.
|
|
647
|
+
*
|
|
648
|
+
* @param interactionClass - Interaction class handle
|
|
649
|
+
*/
|
|
650
|
+
async unpublishInteractionClass(interactionClass: InteractionClassHandle): Promise<void> {
|
|
651
|
+
await this._doHlaCall({
|
|
652
|
+
unpublishInteractionClassRequest: {
|
|
653
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
654
|
+
},
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Subscribe to object class attributes.
|
|
660
|
+
*
|
|
661
|
+
* @param objectClass - Object class handle
|
|
662
|
+
* @param attributes - Set of attribute handles to subscribe to
|
|
663
|
+
*/
|
|
664
|
+
async subscribeObjectClassAttributes(
|
|
665
|
+
objectClass: ObjectClassHandle,
|
|
666
|
+
attributes: AttributeHandleSet
|
|
667
|
+
): Promise<void> {
|
|
668
|
+
await this._doHlaCall({
|
|
669
|
+
subscribeObjectClassAttributesRequest: {
|
|
670
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
671
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
672
|
+
},
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Subscribe to object class attributes passively.
|
|
678
|
+
*
|
|
679
|
+
* @param objectClass - Object class handle
|
|
680
|
+
* @param attributes - Set of attribute handles
|
|
681
|
+
*/
|
|
682
|
+
async subscribeObjectClassAttributesPassively(
|
|
683
|
+
objectClass: ObjectClassHandle,
|
|
684
|
+
attributes: AttributeHandleSet
|
|
685
|
+
): Promise<void> {
|
|
686
|
+
await this._doHlaCall({
|
|
687
|
+
subscribeObjectClassAttributesPassivelyRequest: {
|
|
688
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
689
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
690
|
+
},
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Unsubscribe from all attributes of an object class.
|
|
696
|
+
*
|
|
697
|
+
* @param objectClass - Object class handle
|
|
698
|
+
*/
|
|
699
|
+
async unsubscribeObjectClass(objectClass: ObjectClassHandle): Promise<void> {
|
|
700
|
+
await this._doHlaCall({
|
|
701
|
+
unsubscribeObjectClassRequest: {
|
|
702
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
703
|
+
},
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Unsubscribe from specific attributes of an object class.
|
|
709
|
+
*
|
|
710
|
+
* @param objectClass - Object class handle
|
|
711
|
+
* @param attributes - Set of attribute handles
|
|
712
|
+
*/
|
|
713
|
+
async unsubscribeObjectClassAttributes(
|
|
714
|
+
objectClass: ObjectClassHandle,
|
|
715
|
+
attributes: AttributeHandleSet
|
|
716
|
+
): Promise<void> {
|
|
717
|
+
await this._doHlaCall({
|
|
718
|
+
unsubscribeObjectClassAttributesRequest: {
|
|
719
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
720
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
721
|
+
},
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Subscribe to an interaction class.
|
|
727
|
+
*
|
|
728
|
+
* @param interactionClass - Interaction class handle
|
|
729
|
+
*/
|
|
730
|
+
async subscribeInteractionClass(interactionClass: InteractionClassHandle): Promise<void> {
|
|
731
|
+
await this._doHlaCall({
|
|
732
|
+
subscribeInteractionClassRequest: {
|
|
733
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
734
|
+
},
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Subscribe to an interaction class passively.
|
|
740
|
+
*
|
|
741
|
+
* @param interactionClass - Interaction class handle
|
|
742
|
+
*/
|
|
743
|
+
async subscribeInteractionClassPassively(interactionClass: InteractionClassHandle): Promise<void> {
|
|
744
|
+
await this._doHlaCall({
|
|
745
|
+
subscribeInteractionClassPassivelyRequest: {
|
|
746
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
747
|
+
},
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Unsubscribe from an interaction class.
|
|
753
|
+
*
|
|
754
|
+
* @param interactionClass - Interaction class handle
|
|
755
|
+
*/
|
|
756
|
+
async unsubscribeInteractionClass(interactionClass: InteractionClassHandle): Promise<void> {
|
|
757
|
+
await this._doHlaCall({
|
|
758
|
+
unsubscribeInteractionClassRequest: {
|
|
759
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
760
|
+
},
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// ===========================================================================
|
|
765
|
+
// Object Management
|
|
766
|
+
// ===========================================================================
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Reserve an object instance name.
|
|
770
|
+
*
|
|
771
|
+
* @param objectInstanceName - Name to reserve
|
|
772
|
+
*/
|
|
773
|
+
async reserveObjectInstanceName(objectInstanceName: string): Promise<void> {
|
|
774
|
+
await this._doHlaCall({
|
|
775
|
+
reserveObjectInstanceNameRequest: { objectInstanceName },
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Release a reserved object instance name.
|
|
781
|
+
*
|
|
782
|
+
* @param objectInstanceName - Name to release
|
|
783
|
+
*/
|
|
784
|
+
async releaseObjectInstanceName(objectInstanceName: string): Promise<void> {
|
|
785
|
+
await this._doHlaCall({
|
|
786
|
+
releaseObjectInstanceNameRequest: { objectInstanceName },
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Register a new object instance.
|
|
792
|
+
*
|
|
793
|
+
* @param objectClass - Object class handle
|
|
794
|
+
* @returns Handle of the registered object instance
|
|
795
|
+
*/
|
|
796
|
+
async registerObjectInstance(objectClass: ObjectClassHandle): Promise<ObjectInstanceHandle> {
|
|
797
|
+
const response = await this._doHlaCall({
|
|
798
|
+
registerObjectInstanceRequest: {
|
|
799
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
800
|
+
},
|
|
801
|
+
});
|
|
802
|
+
return convertObjectInstanceHandle(response.registerObjectInstanceResponse?.result);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* Register a new object instance with a specific name.
|
|
807
|
+
*
|
|
808
|
+
* @param objectClass - Object class handle
|
|
809
|
+
* @param objectInstanceName - Name for the object instance
|
|
810
|
+
* @returns Handle of the registered object instance
|
|
811
|
+
*/
|
|
812
|
+
async registerObjectInstanceWithName(
|
|
813
|
+
objectClass: ObjectClassHandle,
|
|
814
|
+
objectInstanceName: string
|
|
815
|
+
): Promise<ObjectInstanceHandle> {
|
|
816
|
+
const response = await this._doHlaCall({
|
|
817
|
+
registerObjectInstanceWithNameRequest: {
|
|
818
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
819
|
+
objectInstanceName,
|
|
820
|
+
},
|
|
821
|
+
});
|
|
822
|
+
return convertObjectInstanceHandle(response.registerObjectInstanceWithNameResponse?.result);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Update attribute values of an object instance.
|
|
827
|
+
*
|
|
828
|
+
* @param objectInstance - Object instance handle
|
|
829
|
+
* @param attributeValues - Map of attribute handles to values
|
|
830
|
+
* @param userSuppliedTag - User-supplied tag
|
|
831
|
+
*/
|
|
832
|
+
async updateAttributeValues(
|
|
833
|
+
objectInstance: ObjectInstanceHandle,
|
|
834
|
+
attributeValues: AttributeHandleValueMap,
|
|
835
|
+
userSuppliedTag: UserSuppliedTag
|
|
836
|
+
): Promise<void> {
|
|
837
|
+
await this._doHlaCall({
|
|
838
|
+
updateAttributeValuesRequest: {
|
|
839
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
840
|
+
attributeValues: toProtoAttributeHandleValueMap(attributeValues),
|
|
841
|
+
userSuppliedTag,
|
|
842
|
+
},
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Update attribute values with a timestamp.
|
|
848
|
+
*
|
|
849
|
+
* @param objectInstance - Object instance handle
|
|
850
|
+
* @param attributeValues - Map of attribute handles to values
|
|
851
|
+
* @param userSuppliedTag - User-supplied tag
|
|
852
|
+
* @param time - Logical time
|
|
853
|
+
* @returns Message retraction info
|
|
854
|
+
*/
|
|
855
|
+
async updateAttributeValuesWithTime(
|
|
856
|
+
objectInstance: ObjectInstanceHandle,
|
|
857
|
+
attributeValues: AttributeHandleValueMap,
|
|
858
|
+
userSuppliedTag: UserSuppliedTag,
|
|
859
|
+
time: LogicalTime
|
|
860
|
+
): Promise<MessageRetractionReturn> {
|
|
861
|
+
const response = await this._doHlaCall({
|
|
862
|
+
updateAttributeValuesWithTimeRequest: {
|
|
863
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
864
|
+
attributeValues: toProtoAttributeHandleValueMap(attributeValues),
|
|
865
|
+
userSuppliedTag,
|
|
866
|
+
time: toProtoLogicalTime(time),
|
|
867
|
+
},
|
|
868
|
+
});
|
|
869
|
+
const result = response.updateAttributeValuesWithTimeResponse?.result;
|
|
870
|
+
return {
|
|
871
|
+
retractionHandleIsValid: result?.retractionHandleIsValid ?? false,
|
|
872
|
+
retractionHandle: result?.messageRetractionHandle?.data,
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Send an interaction.
|
|
878
|
+
*
|
|
879
|
+
* @param interactionClass - Interaction class handle
|
|
880
|
+
* @param parameterValues - Map of parameter handles to values
|
|
881
|
+
* @param userSuppliedTag - User-supplied tag
|
|
882
|
+
*/
|
|
883
|
+
async sendInteraction(
|
|
884
|
+
interactionClass: InteractionClassHandle,
|
|
885
|
+
parameterValues: ParameterHandleValueMap,
|
|
886
|
+
userSuppliedTag: UserSuppliedTag
|
|
887
|
+
): Promise<void> {
|
|
888
|
+
await this._doHlaCall({
|
|
889
|
+
sendInteractionRequest: {
|
|
890
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
891
|
+
parameterValues: toProtoParameterHandleValueMap(parameterValues),
|
|
892
|
+
userSuppliedTag,
|
|
893
|
+
},
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Send an interaction with a timestamp.
|
|
899
|
+
*
|
|
900
|
+
* @param interactionClass - Interaction class handle
|
|
901
|
+
* @param parameterValues - Map of parameter handles to values
|
|
902
|
+
* @param userSuppliedTag - User-supplied tag
|
|
903
|
+
* @param time - Logical time
|
|
904
|
+
* @returns Message retraction info
|
|
905
|
+
*/
|
|
906
|
+
async sendInteractionWithTime(
|
|
907
|
+
interactionClass: InteractionClassHandle,
|
|
908
|
+
parameterValues: ParameterHandleValueMap,
|
|
909
|
+
userSuppliedTag: UserSuppliedTag,
|
|
910
|
+
time: LogicalTime
|
|
911
|
+
): Promise<MessageRetractionReturn> {
|
|
912
|
+
const response = await this._doHlaCall({
|
|
913
|
+
sendInteractionWithTimeRequest: {
|
|
914
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
915
|
+
parameterValues: toProtoParameterHandleValueMap(parameterValues),
|
|
916
|
+
userSuppliedTag,
|
|
917
|
+
time: toProtoLogicalTime(time),
|
|
918
|
+
},
|
|
919
|
+
});
|
|
920
|
+
const result = response.sendInteractionWithTimeResponse?.result;
|
|
921
|
+
return {
|
|
922
|
+
retractionHandleIsValid: result?.retractionHandleIsValid ?? false,
|
|
923
|
+
retractionHandle: result?.messageRetractionHandle?.data,
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Delete an object instance.
|
|
929
|
+
*
|
|
930
|
+
* @param objectInstance - Object instance handle
|
|
931
|
+
* @param userSuppliedTag - User-supplied tag
|
|
932
|
+
*/
|
|
933
|
+
async deleteObjectInstance(
|
|
934
|
+
objectInstance: ObjectInstanceHandle,
|
|
935
|
+
userSuppliedTag: UserSuppliedTag
|
|
936
|
+
): Promise<void> {
|
|
937
|
+
await this._doHlaCall({
|
|
938
|
+
deleteObjectInstanceRequest: {
|
|
939
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
940
|
+
userSuppliedTag,
|
|
941
|
+
},
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Delete an object instance with a timestamp.
|
|
947
|
+
*
|
|
948
|
+
* @param objectInstance - Object instance handle
|
|
949
|
+
* @param userSuppliedTag - User-supplied tag
|
|
950
|
+
* @param time - Logical time
|
|
951
|
+
* @returns Message retraction info
|
|
952
|
+
*/
|
|
953
|
+
async deleteObjectInstanceWithTime(
|
|
954
|
+
objectInstance: ObjectInstanceHandle,
|
|
955
|
+
userSuppliedTag: UserSuppliedTag,
|
|
956
|
+
time: LogicalTime
|
|
957
|
+
): Promise<MessageRetractionReturn> {
|
|
958
|
+
const response = await this._doHlaCall({
|
|
959
|
+
deleteObjectInstanceWithTimeRequest: {
|
|
960
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
961
|
+
userSuppliedTag,
|
|
962
|
+
time: toProtoLogicalTime(time),
|
|
963
|
+
},
|
|
964
|
+
});
|
|
965
|
+
const result = response.deleteObjectInstanceWithTimeResponse?.result;
|
|
966
|
+
return {
|
|
967
|
+
retractionHandleIsValid: result?.retractionHandleIsValid ?? false,
|
|
968
|
+
retractionHandle: result?.messageRetractionHandle?.data,
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Locally delete an object instance (remove from local object model without notifying others).
|
|
974
|
+
*
|
|
975
|
+
* @param objectInstance - Object instance handle
|
|
976
|
+
*/
|
|
977
|
+
async localDeleteObjectInstance(objectInstance: ObjectInstanceHandle): Promise<void> {
|
|
978
|
+
await this._doHlaCall({
|
|
979
|
+
localDeleteObjectInstanceRequest: {
|
|
980
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
981
|
+
},
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Request attribute value update for a specific object instance.
|
|
987
|
+
*
|
|
988
|
+
* @param objectInstance - Object instance handle
|
|
989
|
+
* @param attributes - Set of attributes to request
|
|
990
|
+
* @param userSuppliedTag - User-supplied tag
|
|
991
|
+
*/
|
|
992
|
+
async requestInstanceAttributeValueUpdate(
|
|
993
|
+
objectInstance: ObjectInstanceHandle,
|
|
994
|
+
attributes: AttributeHandleSet,
|
|
995
|
+
userSuppliedTag: UserSuppliedTag
|
|
996
|
+
): Promise<void> {
|
|
997
|
+
await this._doHlaCall({
|
|
998
|
+
requestInstanceAttributeValueUpdateRequest: {
|
|
999
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
1000
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
1001
|
+
userSuppliedTag,
|
|
1002
|
+
},
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Request attribute value update for all objects of a class.
|
|
1008
|
+
*
|
|
1009
|
+
* @param objectClass - Object class handle
|
|
1010
|
+
* @param attributes - Set of attributes to request
|
|
1011
|
+
* @param userSuppliedTag - User-supplied tag
|
|
1012
|
+
*/
|
|
1013
|
+
async requestClassAttributeValueUpdate(
|
|
1014
|
+
objectClass: ObjectClassHandle,
|
|
1015
|
+
attributes: AttributeHandleSet,
|
|
1016
|
+
userSuppliedTag: UserSuppliedTag
|
|
1017
|
+
): Promise<void> {
|
|
1018
|
+
await this._doHlaCall({
|
|
1019
|
+
requestClassAttributeValueUpdateRequest: {
|
|
1020
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
1021
|
+
attributes: toProtoAttributeHandleSet(attributes),
|
|
1022
|
+
userSuppliedTag,
|
|
1023
|
+
},
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// ===========================================================================
|
|
1028
|
+
// Time Management
|
|
1029
|
+
// ===========================================================================
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Enable time regulation.
|
|
1033
|
+
*
|
|
1034
|
+
* @param lookahead - Lookahead interval
|
|
1035
|
+
*/
|
|
1036
|
+
async enableTimeRegulation(lookahead: LogicalTimeInterval): Promise<void> {
|
|
1037
|
+
await this._doHlaCall({
|
|
1038
|
+
enableTimeRegulationRequest: {
|
|
1039
|
+
lookahead: toProtoLogicalTimeInterval(lookahead),
|
|
1040
|
+
},
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Disable time regulation.
|
|
1046
|
+
*/
|
|
1047
|
+
async disableTimeRegulation(): Promise<void> {
|
|
1048
|
+
await this._doHlaCall({ disableTimeRegulationRequest: {} });
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Enable time constrained mode.
|
|
1053
|
+
*/
|
|
1054
|
+
async enableTimeConstrained(): Promise<void> {
|
|
1055
|
+
await this._doHlaCall({ enableTimeConstrainedRequest: {} });
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* Disable time constrained mode.
|
|
1060
|
+
*/
|
|
1061
|
+
async disableTimeConstrained(): Promise<void> {
|
|
1062
|
+
await this._doHlaCall({ disableTimeConstrainedRequest: {} });
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* Request a time advance.
|
|
1067
|
+
*
|
|
1068
|
+
* @param time - Target logical time
|
|
1069
|
+
*/
|
|
1070
|
+
async timeAdvanceRequest(time: LogicalTime): Promise<void> {
|
|
1071
|
+
await this._doHlaCall({
|
|
1072
|
+
timeAdvanceRequestRequest: {
|
|
1073
|
+
time: toProtoLogicalTime(time),
|
|
1074
|
+
},
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* Request a time advance available.
|
|
1080
|
+
*
|
|
1081
|
+
* @param time - Target logical time
|
|
1082
|
+
*/
|
|
1083
|
+
async timeAdvanceRequestAvailable(time: LogicalTime): Promise<void> {
|
|
1084
|
+
await this._doHlaCall({
|
|
1085
|
+
timeAdvanceRequestAvailableRequest: {
|
|
1086
|
+
time: toProtoLogicalTime(time),
|
|
1087
|
+
},
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Request next message.
|
|
1093
|
+
*
|
|
1094
|
+
* @param time - Target logical time
|
|
1095
|
+
*/
|
|
1096
|
+
async nextMessageRequest(time: LogicalTime): Promise<void> {
|
|
1097
|
+
await this._doHlaCall({
|
|
1098
|
+
nextMessageRequestRequest: {
|
|
1099
|
+
time: toProtoLogicalTime(time),
|
|
1100
|
+
},
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Request next message available.
|
|
1106
|
+
*
|
|
1107
|
+
* @param time - Target logical time
|
|
1108
|
+
*/
|
|
1109
|
+
async nextMessageRequestAvailable(time: LogicalTime): Promise<void> {
|
|
1110
|
+
await this._doHlaCall({
|
|
1111
|
+
nextMessageRequestAvailableRequest: {
|
|
1112
|
+
time: toProtoLogicalTime(time),
|
|
1113
|
+
},
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Flush the message queue.
|
|
1119
|
+
*
|
|
1120
|
+
* @param time - Target logical time
|
|
1121
|
+
*/
|
|
1122
|
+
async flushQueueRequest(time: LogicalTime): Promise<void> {
|
|
1123
|
+
await this._doHlaCall({
|
|
1124
|
+
flushQueueRequestRequest: {
|
|
1125
|
+
time: toProtoLogicalTime(time),
|
|
1126
|
+
},
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Modify the lookahead interval.
|
|
1132
|
+
*
|
|
1133
|
+
* @param lookahead - New lookahead interval
|
|
1134
|
+
*/
|
|
1135
|
+
async modifyLookahead(lookahead: LogicalTimeInterval): Promise<void> {
|
|
1136
|
+
await this._doHlaCall({
|
|
1137
|
+
modifyLookaheadRequest: {
|
|
1138
|
+
lookahead: toProtoLogicalTimeInterval(lookahead),
|
|
1139
|
+
},
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Query the Greatest Available Logical Time (GALT).
|
|
1145
|
+
*/
|
|
1146
|
+
async queryGALT(): Promise<TimeQueryReturn> {
|
|
1147
|
+
const response = await this._doHlaCall({ queryGALTRequest: {} });
|
|
1148
|
+
return convertTimeQueryReturn(response.queryGALTResponse?.result);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Query the current logical time.
|
|
1153
|
+
*/
|
|
1154
|
+
async queryLogicalTime(): Promise<LogicalTime> {
|
|
1155
|
+
const response = await this._doHlaCall({ queryLogicalTimeRequest: {} });
|
|
1156
|
+
return convertLogicalTime(response.queryLogicalTimeResponse?.result);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* Query the Least Incoming Time Stamp (LITS).
|
|
1161
|
+
*/
|
|
1162
|
+
async queryLITS(): Promise<TimeQueryReturn> {
|
|
1163
|
+
const response = await this._doHlaCall({ queryLITSRequest: {} });
|
|
1164
|
+
return convertTimeQueryReturn(response.queryLITSResponse?.result);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Query the current lookahead interval.
|
|
1169
|
+
*/
|
|
1170
|
+
async queryLookahead(): Promise<LogicalTimeInterval> {
|
|
1171
|
+
const response = await this._doHlaCall({ queryLookaheadRequest: {} });
|
|
1172
|
+
return convertLogicalTimeInterval(response.queryLookaheadResponse?.result);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// ===========================================================================
|
|
1176
|
+
// Support Services
|
|
1177
|
+
// ===========================================================================
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Get the handle for an object class by name.
|
|
1181
|
+
*
|
|
1182
|
+
* @param objectClassName - Name of the object class
|
|
1183
|
+
* @returns Object class handle
|
|
1184
|
+
*/
|
|
1185
|
+
async getObjectClassHandle(objectClassName: string): Promise<ObjectClassHandle> {
|
|
1186
|
+
const response = await this._doHlaCall({
|
|
1187
|
+
getObjectClassHandleRequest: { objectClassName },
|
|
1188
|
+
});
|
|
1189
|
+
return response.getObjectClassHandleResponse?.result?.data ?? new Uint8Array(0);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Get the name of an object class by handle.
|
|
1194
|
+
*
|
|
1195
|
+
* @param objectClass - Object class handle
|
|
1196
|
+
* @returns Object class name
|
|
1197
|
+
*/
|
|
1198
|
+
async getObjectClassName(objectClass: ObjectClassHandle): Promise<string> {
|
|
1199
|
+
const response = await this._doHlaCall({
|
|
1200
|
+
getObjectClassNameRequest: {
|
|
1201
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
1202
|
+
},
|
|
1203
|
+
});
|
|
1204
|
+
return response.getObjectClassNameResponse?.result ?? "";
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Get the handle for an attribute by name.
|
|
1209
|
+
*
|
|
1210
|
+
* @param objectClass - Object class handle
|
|
1211
|
+
* @param attributeName - Name of the attribute
|
|
1212
|
+
* @returns Attribute handle
|
|
1213
|
+
*/
|
|
1214
|
+
async getAttributeHandle(
|
|
1215
|
+
objectClass: ObjectClassHandle,
|
|
1216
|
+
attributeName: string
|
|
1217
|
+
): Promise<Uint8Array> {
|
|
1218
|
+
const response = await this._doHlaCall({
|
|
1219
|
+
getAttributeHandleRequest: {
|
|
1220
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
1221
|
+
attributeName,
|
|
1222
|
+
},
|
|
1223
|
+
});
|
|
1224
|
+
return response.getAttributeHandleResponse?.result?.data ?? new Uint8Array(0);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
* Get the name of an attribute by handle.
|
|
1229
|
+
*
|
|
1230
|
+
* @param objectClass - Object class handle
|
|
1231
|
+
* @param attribute - Attribute handle
|
|
1232
|
+
* @returns Attribute name
|
|
1233
|
+
*/
|
|
1234
|
+
async getAttributeName(
|
|
1235
|
+
objectClass: ObjectClassHandle,
|
|
1236
|
+
attribute: Uint8Array
|
|
1237
|
+
): Promise<string> {
|
|
1238
|
+
const response = await this._doHlaCall({
|
|
1239
|
+
getAttributeNameRequest: {
|
|
1240
|
+
objectClass: toProtoObjectClassHandle(objectClass),
|
|
1241
|
+
attribute: { data: attribute },
|
|
1242
|
+
},
|
|
1243
|
+
});
|
|
1244
|
+
return response.getAttributeNameResponse?.result ?? "";
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* Get the handle for an interaction class by name.
|
|
1249
|
+
*
|
|
1250
|
+
* @param interactionClassName - Name of the interaction class
|
|
1251
|
+
* @returns Interaction class handle
|
|
1252
|
+
*/
|
|
1253
|
+
async getInteractionClassHandle(interactionClassName: string): Promise<InteractionClassHandle> {
|
|
1254
|
+
const response = await this._doHlaCall({
|
|
1255
|
+
getInteractionClassHandleRequest: { interactionClassName },
|
|
1256
|
+
});
|
|
1257
|
+
return response.getInteractionClassHandleResponse?.result?.data ?? new Uint8Array(0);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Get the name of an interaction class by handle.
|
|
1262
|
+
*
|
|
1263
|
+
* @param interactionClass - Interaction class handle
|
|
1264
|
+
* @returns Interaction class name
|
|
1265
|
+
*/
|
|
1266
|
+
async getInteractionClassName(interactionClass: InteractionClassHandle): Promise<string> {
|
|
1267
|
+
const response = await this._doHlaCall({
|
|
1268
|
+
getInteractionClassNameRequest: {
|
|
1269
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
1270
|
+
},
|
|
1271
|
+
});
|
|
1272
|
+
return response.getInteractionClassNameResponse?.result ?? "";
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* Get the handle for a parameter by name.
|
|
1277
|
+
*
|
|
1278
|
+
* @param interactionClass - Interaction class handle
|
|
1279
|
+
* @param parameterName - Name of the parameter
|
|
1280
|
+
* @returns Parameter handle
|
|
1281
|
+
*/
|
|
1282
|
+
async getParameterHandle(
|
|
1283
|
+
interactionClass: InteractionClassHandle,
|
|
1284
|
+
parameterName: string
|
|
1285
|
+
): Promise<Uint8Array> {
|
|
1286
|
+
const response = await this._doHlaCall({
|
|
1287
|
+
getParameterHandleRequest: {
|
|
1288
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
1289
|
+
parameterName,
|
|
1290
|
+
},
|
|
1291
|
+
});
|
|
1292
|
+
return response.getParameterHandleResponse?.result?.data ?? new Uint8Array(0);
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
/**
|
|
1296
|
+
* Get the name of a parameter by handle.
|
|
1297
|
+
*
|
|
1298
|
+
* @param interactionClass - Interaction class handle
|
|
1299
|
+
* @param parameter - Parameter handle
|
|
1300
|
+
* @returns Parameter name
|
|
1301
|
+
*/
|
|
1302
|
+
async getParameterName(
|
|
1303
|
+
interactionClass: InteractionClassHandle,
|
|
1304
|
+
parameter: Uint8Array
|
|
1305
|
+
): Promise<string> {
|
|
1306
|
+
const response = await this._doHlaCall({
|
|
1307
|
+
getParameterNameRequest: {
|
|
1308
|
+
interactionClass: toProtoInteractionClassHandle(interactionClass),
|
|
1309
|
+
parameter: { data: parameter },
|
|
1310
|
+
},
|
|
1311
|
+
});
|
|
1312
|
+
return response.getParameterNameResponse?.result ?? "";
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Get the handle for an object instance by name.
|
|
1317
|
+
*
|
|
1318
|
+
* @param objectInstanceName - Name of the object instance
|
|
1319
|
+
* @returns Object instance handle
|
|
1320
|
+
*/
|
|
1321
|
+
async getObjectInstanceHandle(objectInstanceName: string): Promise<ObjectInstanceHandle> {
|
|
1322
|
+
const response = await this._doHlaCall({
|
|
1323
|
+
getObjectInstanceHandleRequest: { objectInstanceName },
|
|
1324
|
+
});
|
|
1325
|
+
return response.getObjectInstanceHandleResponse?.result?.data ?? new Uint8Array(0);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
/**
|
|
1329
|
+
* Get the name of an object instance by handle.
|
|
1330
|
+
*
|
|
1331
|
+
* @param objectInstance - Object instance handle
|
|
1332
|
+
* @returns Object instance name
|
|
1333
|
+
*/
|
|
1334
|
+
async getObjectInstanceName(objectInstance: ObjectInstanceHandle): Promise<string> {
|
|
1335
|
+
const response = await this._doHlaCall({
|
|
1336
|
+
getObjectInstanceNameRequest: {
|
|
1337
|
+
objectInstance: toProtoObjectInstanceHandle(objectInstance),
|
|
1338
|
+
},
|
|
1339
|
+
});
|
|
1340
|
+
return response.getObjectInstanceNameResponse?.result ?? "";
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// ===========================================================================
|
|
1344
|
+
// Callback Handling
|
|
1345
|
+
// ===========================================================================
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Evoke a single callback.
|
|
1349
|
+
*
|
|
1350
|
+
* @param _approximateMinimumTimeInSeconds - Minimum time to wait for a callback
|
|
1351
|
+
* @returns true if a callback was processed
|
|
1352
|
+
*/
|
|
1353
|
+
async evokeCallback(_approximateMinimumTimeInSeconds: number): Promise<boolean> {
|
|
1354
|
+
this._throwIfInCallback("evokeCallback");
|
|
1355
|
+
// In this implementation, callbacks are handled immediately by the session layer
|
|
1356
|
+
// This method is provided for API compatibility but may need enhancement
|
|
1357
|
+
// for full evoked callback model support
|
|
1358
|
+
return false;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/**
|
|
1362
|
+
* Evoke multiple callbacks.
|
|
1363
|
+
*
|
|
1364
|
+
* @param _minimumTime - Minimum time to wait
|
|
1365
|
+
* @param _maximumTime - Maximum time to wait
|
|
1366
|
+
* @returns true if callbacks were processed
|
|
1367
|
+
*/
|
|
1368
|
+
async evokeMultipleCallbacks(_minimumTime: number, _maximumTime: number): Promise<boolean> {
|
|
1369
|
+
this._throwIfInCallback("evokeMultipleCallbacks");
|
|
1370
|
+
// In this implementation, callbacks are handled immediately by the session layer
|
|
1371
|
+
return false;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// ===========================================================================
|
|
1375
|
+
// Private Methods
|
|
1376
|
+
// ===========================================================================
|
|
1377
|
+
|
|
1378
|
+
/**
|
|
1379
|
+
* Handle an incoming callback from the RTI.
|
|
1380
|
+
*/
|
|
1381
|
+
private _handleCallback(seqNum: number, callbackData: Uint8Array): void {
|
|
1382
|
+
if (!this._callbackDispatcher || !this._session) {
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
this._inCallback = true;
|
|
1387
|
+
try {
|
|
1388
|
+
const responseData = this._callbackDispatcher.processCallback(callbackData);
|
|
1389
|
+
this._session.sendHlaCallbackResponse(seqNum, responseData).catch((err) => {
|
|
1390
|
+
console.error("[RTIAmbassador] Failed to send callback response:", err);
|
|
1391
|
+
});
|
|
1392
|
+
} finally {
|
|
1393
|
+
this._inCallback = false;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
/**
|
|
1398
|
+
* Execute an HLA call and return the response.
|
|
1399
|
+
*/
|
|
1400
|
+
private async _doHlaCall(callRequest: CallRequest): Promise<CallResponse> {
|
|
1401
|
+
if (!this._session) {
|
|
1402
|
+
throw new NotConnected("Not connected to RTI");
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// Encode the request
|
|
1406
|
+
const encodedRequest = CallRequestCodec.encode(callRequest).finish();
|
|
1407
|
+
|
|
1408
|
+
// Send and wait for response
|
|
1409
|
+
const encodedResponse = await this._session.sendHlaCallRequest(encodedRequest);
|
|
1410
|
+
|
|
1411
|
+
// Decode response
|
|
1412
|
+
const response = CallResponseCodec.decode(encodedResponse);
|
|
1413
|
+
|
|
1414
|
+
// Check for exception
|
|
1415
|
+
if (response.exceptionData) {
|
|
1416
|
+
throw createExceptionFromProto(response.exceptionData);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
return response;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
/**
|
|
1423
|
+
* Throw if we're currently in a callback.
|
|
1424
|
+
*/
|
|
1425
|
+
private _throwIfInCallback(methodName: string): void {
|
|
1426
|
+
if (this._inCallback) {
|
|
1427
|
+
throw new CallNotAllowedFromWithinCallback(
|
|
1428
|
+
`Call to ${methodName} not allowed from within callback`
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
/**
|
|
1434
|
+
* Clean up resources.
|
|
1435
|
+
*/
|
|
1436
|
+
private _cleanup(): void {
|
|
1437
|
+
this._session = null;
|
|
1438
|
+
this._transport = null;
|
|
1439
|
+
this._callbackDispatcher = null;
|
|
1440
|
+
}
|
|
1441
|
+
}
|