@evops/lightwaverf
v1.0.5
Published
Lightwave RF client library
Downloads
44
Readme
@evops/lightwaverf
A modern TypeScript client library for controlling LightwaveRF home automation devices
Control your LightwaveRF smart lights, switches, and dimmers from Node.js with a clean, type-safe API. This library communicates with LightwaveRF Link Plus devices over your local network and integrates with the LightwaveRF cloud API for device configuration.
Features
- 🎯 Type-Safe - Full TypeScript support with strict type checking
- 🔌 Event-Driven - Real-time device state change notifications
- 🔄 Automatic Device Discovery - Finds LightwaveRF Link devices on your network
- 🔐 Registration Management - Handles device pairing automatically
- ⚡ Command Queueing - Built-in queue prevents command collisions
- 🔁 Retry Logic - Automatic retry with exponential backoff on errors
- 🐛 Debug Logging - Comprehensive debug output via
debugmodule - ☁️ Cloud Integration - Fetches device configuration from LightwaveRF cloud
- ✅ Well Tested - Comprehensive test suite with Vitest
Installation
npm install @evops/lightwaverfQuick Start
import LightwaveRF from '@evops/lightwaverf';
// Initialize the client
const lw = new LightwaveRF({
email: '[email protected]',
pin: '1234',
ip: '192.168.1.100' // Optional: Link IP (auto-discovered if omitted)
});
// Connect and ensure registration
await lw.connect();
await lw.ensureRegistration();
// Get all your devices
const devices = await lw.getDevices();
console.log('Found devices:', devices);
// Control a device
const myLight = devices.find(d => d.deviceName === 'Living Room Light');
await lw.turnOn(myLight);
await lw.dim(myLight, 50); // Set to 50% brightness
await lw.turnOff(myLight);API Reference
Constructor
new LightwaveRF(config: LightwaveRFConfiguration)Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| email | string | - | Your LightwaveRF account email |
| pin | string | - | Your LightwaveRF account PIN |
| ip | string | 255.255.255.255 | Link device IP (defaults to broadcast for auto-discovery) |
| timeout | number | 1000 | Command timeout in milliseconds |
Methods
Device Control
turnOn(device: ILightwaveDevice): Promise<void>
Turns a device on.
await lw.turnOn({ roomId: 1, deviceId: 1, roomName: 'Living Room', deviceName: 'Light' });turnOff(device: ILightwaveDevice): Promise<void>
Turns a device off.
await lw.turnOff(myLight);dim(device: ILightwaveDevice, percentage: number): Promise<void>
Dims a device to the specified percentage (0-100).
await lw.dim(myLight, 75); // Set to 75% brightnessDevice Management
getDevices(): Promise<LightwaveDevice[]>
Retrieves all devices from your LightwaveRF cloud account.
const devices = await lw.getDevices();
devices.forEach(device => {
console.log(`${device.roomName} - ${device.deviceName} (${device.deviceType})`);
});Connection & Registration
connect(): Promise<void>
Connects to the LightwaveRF Link device on your local network.
await lw.connect();isRegistered(): Promise<boolean>
Checks if the client is registered with the Link device.
const registered = await lw.isRegistered();
if (!registered) {
console.log('Please press the button on your Link device to register');
}ensureRegistration(): Promise<void>
Ensures the client is registered with the Link. If not registered, enters pairing mode. You'll need to press the pairing button on your Link device.
await lw.ensureRegistration();Device Information (Read-only Properties)
console.log('Serial:', lw.serial);
console.log('MAC Address:', lw.mac);
console.log('Uptime:', lw.uptime);
console.log('Model:', lw.model);
console.log('Firmware Version:', lw.version);Events
The client extends EventEmitter and emits the following events:
deviceTurnedOn
Emitted when a device is turned on (including via physical switches or other apps).
lw.on('deviceTurnedOn', (roomId: number, deviceId: number) => {
console.log(`Device ${deviceId} in room ${roomId} was turned on`);
});deviceTurnedOff
Emitted when a device is turned off.
lw.on('deviceTurnedOff', (roomId: number, deviceId: number) => {
console.log(`Device ${deviceId} in room ${roomId} was turned off`);
});deviceDimmed
Emitted when a device is dimmed to a specific level.
lw.on('deviceDimmed', (roomId: number, deviceId: number, percentage: number) => {
console.log(`Device ${deviceId} in room ${roomId} dimmed to ${percentage}%`);
});Types
ILightwaveDevice
interface ILightwaveDevice {
roomId: number;
deviceId: number;
roomName: string;
deviceName: string;
deviceType: string;
}LightwaveDeviceType
enum LightwaveDeviceType {
Dimmer = "D",
OnOff = "O"
}LightwaveDevice
A class representing a physical LightwaveRF device. Returned by getDevices().
class LightwaveDevice {
roomId: number;
deviceId: number;
roomName: string;
deviceName: string;
deviceType: LightwaveDeviceType;
}Examples
Basic Device Control
import LightwaveRF from '@evops/lightwaverf';
const lw = new LightwaveRF({
email: '[email protected]',
pin: '1234'
});
await lw.connect();
await lw.ensureRegistration();
// Turn on all devices
const devices = await lw.getDevices();
for (const device of devices) {
await lw.turnOn(device);
}Scene Control with Dimming
// Create a movie night scene
async function movieNightScene(lw, devices) {
const ceilingLight = devices.find(d => d.deviceName === 'Ceiling Light');
const lampLeft = devices.find(d => d.deviceName === 'Lamp Left');
const lampRight = devices.find(d => d.deviceName === 'Lamp Right');
await lw.turnOff(ceilingLight);
await lw.dim(lampLeft, 30);
await lw.dim(lampRight, 30);
}
await movieNightScene(lw, await lw.getDevices());Event Monitoring
// Monitor all device state changes
lw.on('deviceTurnedOn', (roomId, deviceId) => {
console.log(`[ON] Room ${roomId}, Device ${deviceId}`);
});
lw.on('deviceTurnedOff', (roomId, deviceId) => {
console.log(`[OFF] Room ${roomId}, Device ${deviceId}`);
});
lw.on('deviceDimmed', (roomId, deviceId, percentage) => {
console.log(`[DIM] Room ${roomId}, Device ${deviceId} -> ${percentage}%`);
});Control by Room and Device ID
If you already know your room and device IDs, you can control devices directly without fetching from the cloud:
await lw.turnOn({
roomId: 1,
deviceId: 2,
roomName: 'Living Room',
deviceName: 'Light'
});Error Handling
try {
await lw.connect();
await lw.ensureRegistration();
const devices = await lw.getDevices();
await lw.turnOn(devices[0]);
} catch (error) {
console.error('Error controlling devices:', error);
}Enable Debug Logging
Use the debug module to see detailed logging:
DEBUG=lightwave* node your-script.jsThis will show all UDP communication, command queue operations, and API calls.
How It Works
Architecture
- LightwaveRF Client (Main API) - High-level interface for device control and management
- LightwaveRFClient - Low-level UDP client handling communication with Link devices
- LightwaveAccount - Cloud API integration for device configuration
- Message Processors - Parse JSON and text protocol responses
- Queue System - Manages command transactions and prevents conflicts
Communication Protocol
The library communicates with LightwaveRF Link devices using:
- Protocol: UDP
- Ports: Sends on 9760, receives on 9761
- Rate Limiting: 125ms delay between commands
- Transaction-Based: Each command gets a unique transaction ID
- Response Timeout: 5 seconds (configurable)
- Format: Supports both JSON (
*!{...}) and text responses
Device Discovery
When no IP is specified (or 255.255.255.255 is used), the library broadcasts on the local network to automatically discover LightwaveRF Link devices.
Requirements
- Node.js 14 or higher
- LightwaveRF Link or Link Plus device
- LightwaveRF account (for device configuration)
- Local network access to the Link device
Troubleshooting
Connection Issues
Problem: Cannot connect to Link device
Solution:
- Ensure your Link device is powered on and connected to the same network
- Try specifying the Link IP address explicitly in the config
- Check your firewall allows UDP traffic on ports 9760/9761
Registration Issues
Problem: ensureRegistration() hangs or fails
Solution:
- Press and release the pairing button on your Link device when prompted
- The Link button should flash during pairing mode
- Registration is usually required only once per client
Device Control Not Working
Problem: Commands don't affect devices
Solution:
- Verify you're registered with
await lw.isRegistered() - Check device IDs match your actual device configuration
- Enable debug logging to see command/response details
- Ensure devices are paired with your Link in the LightwaveRF app
Cloud API Issues
Problem: getDevices() fails
Solution:
- Verify your email and PIN are correct
- Check your internet connection (cloud API requires internet)
- Ensure you have devices configured in your LightwaveRF account
Migration from 0.x to 1.0
Version 1.0 is a complete TypeScript rewrite with breaking changes. See CHANGELOG.md for details.
Key Changes
- ✅ Public API remains compatible
- ⚠️ Output directory changed from
distto.dist - ⚠️ Internal files renamed (only affects direct imports)
- ⚠️ CLI removed (use library API directly)
- ⚠️ Modern ES2024 output with strict TypeScript
Development
# Install dependencies
npm install
# Run tests
npm test
# Build TypeScript
npm run prepublishTesting
The library includes comprehensive tests using Vitest with HTTP request recording/replay:
npm testTests use fetch-vcr to record API interactions, making them fast and reliable.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE file for details
Credits
Originally based on node-lightwaverf by Ollie Parsley.
Rewritten and maintained by Stanislaw Wozniak.
Related Projects
Support
- Issues: GitHub Issues
- Email: Contact via GitHub
Made with ⚡ by the community
