@eventmsg/core
v0.2.0
Published
EventMsgV3 TypeScript library - Core protocol implementation with transport abstraction
Maintainers
Readme
@eventmsg/core
Type-safe, transport-agnostic messaging library with EventMsgV3 binary protocol for reliable device communication.
Installation
npm install @eventmsg/coreBrowser CDN Usage
Use directly in browser via CDN without npm:
<script type="importmap">
{
"imports": {
"@eventmsg/core": "https://cdn.jsdelivr.net/npm/@eventmsg/core@latest"
}
}
</script>
<script type="module">
import { EventMsg } from '@eventmsg/core';
// Use same API as npm version
</script>Usage
Quick Start
import { EventMsg } from '@eventmsg/core';
import { WebBLETransport, createNordicUARTConfig } from '@eventmsg/transport-webble';
// Create transport and EventMsg instance
const transport = new WebBLETransport(createNordicUARTConfig(0, 0));
const eventMsg = new EventMsg({ transport });
// Connect and send messages
await eventMsg.connect();
await eventMsg.send('hello', 'Hello device!', { receiverId: 1 });
// Listen for messages with type safety
eventMsg.onMessage('sensor_data', (data, metadata) => {
console.log(`Data from device ${metadata.senderId}:`, data);
});Core API
Connection Management
await eventMsg.connect() // Connect to transport
await eventMsg.disconnect() // Disconnect gracefully
eventMsg.isConnected() // Check connection status
eventMsg.getLocalAddress() // Get device address
eventMsg.getStats() // Get connection statisticsSending Messages
// Send to specific device
await eventMsg.send('command', { action: 'led_on' }, {
receiverId: 5
});
// Broadcast to all devices
await eventMsg.send('announcement', 'System update', {
receiverId: 255, // Broadcast
receiverGroupId: 255 // All groups
});
// Send with custom flags
await eventMsg.send('urgent', { alert: 'emergency' }, {
receiverId: 1,
flags: 0x80 // Priority flag
});Receiving Messages
// Listen for all messages
eventMsg.onMessage((eventName, data, metadata) => {
console.log(`Received ${eventName} from device ${metadata.senderId}`);
});
// Listen for specific events with type safety
eventMsg.onMessage<SensorData>('sensor_data', (data, metadata) => {
console.log(`Temperature: ${data.temperature}°C`);
});
// Remove listeners
eventMsg.offMessage('sensor_data'); // Remove specific
eventMsg.offMessage(); // Remove allRequest/Response Pattern
// Send request and wait for response
const response = await eventMsg.waitFor('status_response', {
timeout: 5000,
filter: (meta) => meta.senderId === 1
});
// Ping/pong example — arm the wait before sending so a fast
// response can't arrive before the listener is registered
const startTime = Date.now();
const [pong] = await Promise.all([
eventMsg.waitFor('pong'),
eventMsg.send('ping', { timestamp: startTime }, { receiverId: 1 })
]);
console.log(`RTT: ${Date.now() - startTime}ms`);TypeScript Support
// Define your message types
interface SensorReading {
temperature: number;
humidity: number;
timestamp: number;
}
interface DeviceCommand {
action: 'led' | 'relay' | 'motor';
state: 'on' | 'off';
intensity?: number;
}
// Type-safe messaging
await eventMsg.send<DeviceCommand>('control', {
action: 'led',
state: 'on',
intensity: 75
}, { receiverId: 1 });
// Type-safe receiving
eventMsg.onMessage<SensorReading>('sensor_data', (data, metadata) => {
// TypeScript knows the exact structure
console.log(`${data.temperature}°C, ${data.humidity}%`);
});Configuration
interface EventMsgConfig {
transport: Transport; // Transport implementation (required)
maxMessageSize?: number; // Default: unlimited
messageTimeout?: number; // Default: 5000ms
debug?: boolean; // Default: false
protocol?: ProtocolOptions; // Protocol configuration
}
// Example with custom configuration
const eventMsg = new EventMsg({
transport,
maxMessageSize: 2048,
messageTimeout: 10000,
debug: true
});Event Handling
// Lifecycle events
eventMsg.on('connect', () => console.log('Connected'));
eventMsg.on('disconnect', () => console.log('Disconnected'));
eventMsg.on('error', (error) => console.error('Error:', error));
// Debug events (when debug: true)
eventMsg.on('send', (info) => console.log('Message sent:', info.event));Troubleshooting
Common Issues
"Not connected to transport"
- Call
await eventMsg.connect()before sending messages - Check if transport is properly configured
"Invalid address" errors
- Addresses must be 0-255
- receiverId is required in send options
- Use 255 for broadcast addressing
"Message too large" errors
- No artificial size limit is applied by default
- Check whether your app config sets maxMessageSize
- Check whether your app config sets protocol maxEventNameLength or maxEventDataLength
- For BLE transports, large payloads are still constrained by MTU, transfer time, memory, and device firmware behavior
"Timeout" errors
- Increase timeout in waitFor options
- Check if target device is responding
- Verify device addressing is correct
Error Types
import {
EventMsgError, // Base error
ValidationError, // Input validation
ConnectionError, // Connection issues
SendError, // Message sending
WaitForTimeoutError, // Response timeout
AddressValidationError // Invalid addressing
} from '@eventmsg/core';
try {
await eventMsg.send('test', {}, { receiverId: 999 });
} catch (error) {
if (error instanceof AddressValidationError) {
console.error(`Invalid address: ${error.value}`);
}
}Debug Tips
// Enable debug logging
const eventMsg = new EventMsg({ transport, debug: true });
// Monitor all events
eventMsg.on('connect', () => console.log('Connected'));
eventMsg.on('disconnect', () => console.log('Disconnected'));
eventMsg.on('error', (error) => console.error('Error:', error));
// Log all messages
eventMsg.onMessage((eventName, data, metadata) => {
console.log(`📨 ${eventName}:`, data, 'from', metadata.senderId);
});
// Check connection stats
console.log(eventMsg.getStats());Protocol Information
EventMsgV3 uses a binary protocol with:
- 7-byte header with device/group addressing
- JSON serialization for event data
- Byte stuffing for reliable framing
- Message size limits for transport compatibility
