Use SEN from Node.js without native bindings or a local SEN installation.
Connect to existing SEN sessions, read live objects, react to changes and events, call methods, or publish JavaScript objects as regular SEN participants.
Pure JavaScript · ESM · Multi-session · STL and HLA FOM support · Automatic reconnect
Install the package:
npm install sen-ether-clientThen connect and create an interest:
import { Sen } from 'sen-ether-client';
const sen = await Sen.connect();
try {
const board = await sen.interest('SELECT * FROM chess.board');
const knight = await board.waitFor('white-knight-b1');
console.log(knight.snapshot);
knight.on('change:square', ({ value }) => {
console.log('New square:', value);
});
} finally {
await sen.close();
}In chess.board, chess is the SEN session and board is the bus. Discovery
uses SEN multicast by default and continues while the client is running.
Once an object has been returned by waitFor() or objects(), the usual
operations are:
console.log(object.name, object.className, object.snapshot);
object.on('change', change => console.log(change));
object.on('change:altitude', ({ value }) => console.log(value));
object.on('warningRaised', ({ args }) => console.log(args));
await object.set('selected', true); // Writable STL property
const result = await object.call('reset', []); // SEN method| Need | API |
|---|---|
| Current properties | object.snapshot |
| Property changes | object.on('change:<name>', handler) |
| SEN events | object.on('<eventName>', handler) |
| Writable property | object.set(name, value) |
| Method call | object.call(name, args) |
Values and arguments are decoded from the object's SEN type information.
Load your STL definitions and give the client a session. publish() returns a
handle that remains usable after an automatic reconnect.
import { Sen } from 'sen-ether-client';
const types = await Sen.loadStl('./stl');
const sen = await Sen.connect({
session: 'chess',
announceDiscovery: true,
types
});
try {
let knight;
knight = await sen.publish('board', {
name: 'white-knight-b1',
className: 'chess.Piece',
properties: {
color: 'white',
kind: 'knight',
square: 'b1'
},
methods: {
async move(square) {
await knight.update({ square });
return true;
}
}
});
await knight.update({ square: 'c3' });
await knight.emit('moved', ['b1', 'c3']);
} finally {
await sen.close();
}To native applications, the JavaScript publisher behaves like any other SEN participant.
For buses in different sessions, use a qualified name such as chess.board.
The default connection is enough when multicast discovery works:
const sen = await Sen.connect();To use one known session and network interface:
const sen = await Sen.connect({
session: 'chess',
interfaceAddress: '192.0.2.10'
});To use a TCP discovery hub:
const sen = await Sen.connect({
session: 'chess',
tcpHub: '127.0.0.1:65222'
});Useful navigation methods are:
console.log(sen.listSessions());
console.log(sen.listBuses());
console.log(await sen.discoverBuses());Sen.connect() waits until discovery is operational, not until a particular
producer exists. An interest can therefore be created before its producer
starts. See connection and discovery options for timeouts,
fixed targets, multicast settings and reconnect behaviour.
For consumers, type information is normally requested from the SEN publisher. For publishers, load the STL used by the application:
const types = await Sen.loadStl('./stl', {
includePaths: ['./shared-stl']
});
const sen = await Sen.connect({ types });A module-relative URL also works:
const types = await Sen.loadStl(new URL('./stl', import.meta.url));STL classes, inheritance, properties, methods, events and value types are
resolved automatically. HLA FOM XML layouts can be loaded with Sen.loadFom()
or imported from STL. This imports the FOM as SEN type information; it does not
join an HLA federation.
See STL loading and HLA FOM loading for supported layouts and mapping options.
For tracks or telemetry, select only the properties you need and receive batched changes:
const tracks = await sen.interest('SELECT * FROM tactical.tracks', {
properties: ['latitude', 'longitude', 'altitude'],
changeMode: 'batch',
coalesce: true
});
tracks.on('changes', ({ changes, dropped }) => {
// Update the UI or forward one compact batch.
});Queue limits, batch intervals and backpressure policies are described in the
SenInterest reference.
Inspect the SEN environment without writing an application:
npx sen-ether-scan --timeout 3000
npx sen-ether-probe
npx sen-ether-probe --bus chess.boardGenerate typed JavaScript helpers from an STL layout:
npx sen-stl-types ./stl --output ./stl.mjsThe generated module provides publish<Class>() and waitFor<Class>()
helpers with JSDoc typing. The examples/ directory includes a
consumer, publisher, methods, events and a generated STL module.
Check these first:
- Use a session-qualified query:
SELECT * FROM session.bus. - Confirm discovery with
npx sen-ether-scan. - On a multi-interface machine, set
interfaceAddressto the SEN interface. - Confirm the publisher uses the same STL revision as the consumer.
- Use a TCP discovery hub if multicast is unavailable between hosts.
For a protocol-routing trace, start the application with
SEN_TRACE_ROUTING=1. The client writes one compact JSON record per routing
decision to stderr; object values and application payloads are not included.
This option is intended for temporary diagnostics.
| sen-ether-client | Node.js | SEN kernel | Ether |
|---|---|---|---|
| 0.7.x | >= 22 | 9 | 2 |
The protocol versions are checked during the handshake. The library has no runtime dependencies.
- Complete API reference
- Runnable examples
- Advanced browser-safe type inspection is available from
sen-ether-client/types.