Device Entrypoints
Understanding device entrypoint lifecycle and methods
What is an Entrypoint?
An entrypoint is the main handler for device connections. It:
- Receives messages from devices
- Sends commands to devices
- Manages device lifecycle
- Processes events in real-time
Class Structure
Every entrypoint extends DeviceEntrypoint:
import { DeviceEntrypoint } from '@devicesdk/core';
export default class MyDevice extends DeviceEntrypoint {
// Lifecycle methods
async onDeviceConnect() { }
async onMessage(message: DeviceMessage) { }
async onDeviceDisconnect() { }
}
Lifecycle Methods
onDeviceConnect
Called when a device establishes a WebSocket connection.
async onDeviceConnect() {
// Initialize device
await this.env.logger.info(`Device connected`);
}
Use cases:
- Initialize device state
- Setup monitoring
- Log connection event
onMessage
Called when a device sends a message.
async onMessage(message: DeviceMessage) {
// Handle different message types
switch (message.type) {
case 'sensor_data':
await this.handleSensorData(message);
break;
case 'alert':
await this.handleAlert(message);
break;
}
}
Use cases:
- Process sensor readings
- Handle device events
- Store data
- Trigger actions
onDeviceDisconnect
Called when a device disconnects.
async onDeviceDisconnect() {
// Cleanup
await this.env.logger.info(`Device disconnected`);
// Update status
await this.env.DEVICE.kv.put(`status`, 'offline');
}
Use cases:
- Update connection status
- Cleanup resources
- Log disconnect event
- Trigger alerts
Environment Bindings
Your entrypoint has access to these bindings:
this.env.DEVICE
Send messages and manage devices:
// Send message to device
await this.env.DEVICE.send({
type: 'command',
action: 'restart'
});
// Access KV storage
await this.env.DEVICE.kv.put('key', 'value');
const value = await this.env.DEVICE.kv.get('key');
this.env.logger
Structured logging:
await this.env.logger.info('Device connected', { });
await this.env.logger.error('Sensor reading failed', { error });
await this.env.logger.warn('Temperature threshold exceeded', { temp: 85 });
Message Handling Patterns
Event Broadcasting
Device sends event, script processes asynchronously:
async onMessage(message: DeviceMessage) {
if (message.type === 'alert') {
// Don't wait for external calls
this.sendEmailAlert(message).catch(err =>
this.env.logger.error('Email failed', { err })
);
}
}
State Management
Maintain device state in KV:
async onMessage(message: DeviceMessage) {
// Load current state
const state = await this.env.DEVICE.kv.get(`state`);
// Update state
const newState = { ...JSON.parse(state), ...message.data };
// Save state
await this.env.DEVICE.kv.put(`state`, JSON.stringify(newState));
}
Multiple Device Support
Handle multiple device types in one project:
// devicesdk.ts
export default {
devices: {
'temperature-sensor': './src/devices/temp-sensor.ts',
'motion-detector': './src/devices/motion.ts',
'led-controller': './src/devices/led.ts'
}
}
Each device type has its own entrypoint class.
Error Handling
Handle errors gracefully:
async onMessage(message: DeviceMessage) {
try {
await this.processMessage(message);
} catch (error) {
await this.env.logger.error('Message processing failed', {
error: error.message
});
}
}
Performance Considerations
Keep Methods Fast
Entrypoint methods should complete quickly:
- Typical execution: < 10ms
- Maximum: 50ms recommended
- CPU time limited
Minimize State
- Store only necessary data in KV
- Clean up old data
Best Practices
- Validate messages - Check message structure before processing
- Log important events - Use structured logging
- Handle errors - Don’t let exceptions crash the script
- Keep state minimal - Only store what’s needed
- Be idempotent - Handle duplicate messages gracefully
Next Steps
- Your First Device - Build a complete example
- Platform Architecture - System overview