ll_device_flutter_sdk 1.0.4 copy "ll_device_flutter_sdk: ^1.0.4" to clipboard
ll_device_flutter_sdk: ^1.0.4 copied to clipboard

discontinued

LinknLink Device Flutter SDK for controlling LinknLink devices via UDP. Provides APIs for smart home app integration with auto-pairing and device management.

LinkLink Device Flutter SDK #

A comprehensive Flutter SDK for controlling Broadlink devices via UDP. Designed specifically for smart home app integration with clean, simple APIs.

License: MIT

✨ Features #

  • 🔍 Smart Device Discovery:

    • Auto-pairing: Devices are automatically authenticated during discovery
    • Real-time streaming: Device responses pushed instantly
    • Multi-network support: Automatic network adaptation
    • Intelligent deduplication: Based on unique device identifiers
  • 🔐 Secure Authentication:

    • Python-compatible: Fully compatible with python-broadlink authentication
    • Auto-retry mechanism: >95% success rate in unstable networks
    • Dynamic key management: Secure AES-128-CBC encryption and session management
    • Complete error checking: Checksum validation + device error code detection
  • 📡 RM Device Control: IR/RF learning and sending with device-specific optimization

  • 🔌 SP Device Control: Power control, nightlight, energy monitoring

  • 📊 Real-time Events: Device status and discovery event streams

  • 🛡️ Error Handling: Comprehensive exception handling

  • 📱 Cross Platform: Android and iOS support

🏗️ Architecture #

This SDK provides a clean, event-driven API for smart home applications:

Your Smart Home App
       ↓
LinkLink Device SDK
       ↓
  Broadlink Devices

🚀 Quick Start #

Installation #

Add to your pubspec.yaml:

dependencies:
  flutter_sdk: ^1.0.0

Basic Usage #

import 'package:flutter_sdk/ll_device_flutter_sdk.dart';

// Get SDK instance
final sdk = LLDeviceFlutterSDK.getInstance();

// Listen to events
sdk.deviceEvents.listen((event) {
  print('Device event: $event');
});

sdk.discoveryEvents.listen((event) {
  print('Discovery event: $event');
});

// Discover devices with auto-pairing
final devices = await sdk.discoverDevices(
  autoAuthenticate: true  // Devices are automatically paired
);

for (final device in devices) {
  if (device.aesKey != null) {
    print('✅ ${device.name} - Already authenticated!');
  }
}

// Control devices directly
if (devices.isNotEmpty) {
  final device = devices.first;
  
  // Control smart plug
  if (device.capabilities.supportsPower) {
    await sdk.setSPPower(device.id, true);
  }
  
  // Learn IR code
  if (device.capabilities.supportsIR) {
    print('Point remote at device and press button...');
    final code = await sdk.learnIRCode(device.id);
    if (code != null) {
      await sdk.sendIRCode(device.id, code);
    }
  }
}

// Or use periodic probe for continuous monitoring
sdk.startProbe(
  interval: 10,
  autoAuthenticate: true,
);

Advanced Usage - Continuous Device Monitoring #

// Start continuous device discovery
sdk.startProbe(
  interval: 10,           // Check every 10 seconds
  timeout: 3,
  autoAuthenticate: true, // Auto-authenticate new devices
);

// Listen for new devices
sdk.discoveryEvents.listen((event) {
  if (event is DeviceDiscoveredEvent) {
    final device = event.device;
    print('🎯 New device: ${device.name}');
    
    // Device is automatically added and can be used immediately
    if (device.aesKey != null && device.capabilities.supportsPower) {
      sdk.setSPPower(device.id, true);
    }
  }
});

// Stop when done
// sdk.stopProbe();

📖 API Reference #

Core SDK Class #

LLDeviceFlutterSDK

Main SDK class providing all functionality.

// Singleton instance
LLDeviceFlutterSDK sdk = LLDeviceFlutterSDK.getInstance();

// Event streams
Stream<DeviceEvent> deviceEvents;
Stream<DiscoveryEvent> discoveryEvents;

Device Discovery #

discoverDevices() with Auto-Pairing

Discover Broadlink devices on the network with automatic authentication.

Future<List<LLDNADeviceInfo>> discoverDevices({
  int timeout = 10,                    // Discovery timeout in seconds
  String? localIpAddress,              // Local IP binding
  String discoverIpAddress = '255.255.255.255',
  int discoverPort = 80,
  bool autoAuthenticate = true,        // Auto-pair discovered devices
})

// Basic usage
final devices = await sdk.discoverDevices();

// Advanced usage
final devices = await sdk.discoverDevices(
  timeout: 15,
  autoAuthenticate: true,  // Devices will be ready to use immediately
);

// Check authentication status
for (final device in devices) {
  if (device.aesKey != null && device.deviceId != null) {
    print('✅ ${device.name} is authenticated and ready');
  }
}

discoverDevicesStream() - Real-time Discovery Stream

Provides real-time device discovery with optional auto-pairing:

Stream<LLDNADeviceInfo> discoverDevicesStream({
  int timeout = 10,
  String? localIpAddress,
  String discoverIpAddress = '255.255.255.255',
  int discoverPort = 80,
  bool autoAuthenticate = true,  // Auto-pair as devices are discovered
})

// Real-time device processing
await for (final device in sdk.discoverDevicesStream(
  timeout: 10,
  autoAuthenticate: true
)) {
  print('🎯 Discovered: ${device.name} (${device.host})');
  
  if (device.aesKey != null) {
    print('  → Authenticated and ready to use!');
    // Can use device immediately without manual authentication
  }
}

hello() - Direct Device Contact

Contact a device at a known IP address:

Future<LLDNADeviceInfo?> hello(
  String ipAddress,
  {int port = 80, int timeout = 3}
)

// Check if device is online
final device = await sdk.hello('192.168.1.100');
if (device != null) {
  print('✅ Device online: ${device.name}');
}

Device Management #

initializeDevices() - Initialize Known Devices

Initialize the SDK with a list of known devices (e.g., loaded from storage):

void initializeDevices(List<LLDNADeviceInfo> devices)

// Example: Load devices from storage
final savedDevices = await loadDevicesFromStorage();
sdk.initializeDevices(savedDevices);

// Devices can now be controlled without re-discovery
for (final device in savedDevices) {
  if (device.capabilities.supportsPower) {
    await sdk.setSPPower(device.id, true);
  }
}

connectDevice() - Manual Device Authentication

Manually authenticate a device (if not using auto-authentication):

Future<bool> connectDevice(String deviceId)

// Example
final success = await sdk.connectDevice(deviceId);
if (success) {
  print('Device authenticated successfully');
}

getConnectedDevices()

Get list of devices with authentication keys:

List<LLDNADeviceInfo> getConnectedDevices()

// Example
final connectedDevices = sdk.getConnectedDevices();
print('Connected devices: ${connectedDevices.length}');

getDeviceStatus()

Get device status information:

Future<DeviceStatus> getDeviceStatus(String deviceId)

// Example
final status = await sdk.getDeviceStatus(deviceId);
print('Power: ${status.powerState}');

startProbe() & stopProbe() - Periodic Device Discovery

Start and stop periodic device discovery (probe) to continuously monitor for new devices:

void startProbe({
  int interval = 10,           // Probe interval in seconds
  int timeout = 3,             // Discovery timeout per probe
  String? localIpAddress,      // Local IP binding
  String discoverIpAddress = '255.255.255.255',
  int discoverPort = 80,
  bool autoAuthenticate = false,  // Auto-authenticate new devices
})

void stopProbe()

// Example: Start periodic discovery every 10 seconds
sdk.startProbe(
  interval: 10,
  timeout: 3,
  autoAuthenticate: true,  // Auto-authenticate newly discovered devices
);

// Listen to discovery events
sdk.discoveryEvents.listen((event) {
  if (event is DeviceDiscoveredEvent) {
    print('New device found: ${event.device.name}');
    // Device is automatically added to device manager
  }
});

// Stop probing when done
sdk.stopProbe();

Use Cases:

  • Monitor for new devices joining the network
  • Maintain real-time device availability status
  • Auto-discover and configure new smart home devices
  • Build dynamic device management dashboards

RM Device Control #

learnIRCode()

Learn IR/RF code from remote control:

Future<String?> learnIRCode(
  String deviceId,
  {int timeout = 30}
)

// Example
print('Point remote at device and press button...');
final code = await sdk.learnIRCode(deviceId, timeout: 30);
if (code != null) {
  print('Learned code: $code');
  // Save code for later use
}

sendIRCode()

Send IR/RF code to device:

Future<bool> sendIRCode(String deviceId, String code)

// Example
final success = await sdk.sendIRCode(deviceId, savedCode);
if (success) {
  print('Code sent successfully');
}

getRMTemperature() & getRMHumidity()

Get sensor data from RM4 devices:

Future<double?> getRMTemperature(String deviceId)
Future<double?> getRMHumidity(String deviceId)

// Example
final temperature = await sdk.getRMTemperature(deviceId);
final humidity = await sdk.getRMHumidity(deviceId);
print('Temperature: ${temperature}°C, Humidity: ${humidity}%');

SP Device Control #

setSPPower() & getSPPower()

Control and check power state:

Future<bool> setSPPower(String deviceId, bool on)
Future<bool?> getSPPower(String deviceId)

// Example
await sdk.setSPPower(deviceId, true);   // Turn on
await sdk.setSPPower(deviceId, false);  // Turn off

final isOn = await sdk.getSPPower(deviceId);
print('Device is ${isOn ? 'ON' : 'OFF'}');

setSPNightlight()

Set nightlight (SP3 devices):

Future<bool> setSPNightlight(String deviceId, bool on)

// Example
await sdk.setSPNightlight(deviceId, true);

getSPEnergyConsumption()

Get energy consumption (SP2S devices):

Future<double?> getSPEnergyConsumption(String deviceId)

// Example
final watts = await sdk.getSPEnergyConsumption(deviceId);
print('Power consumption: ${watts}W');

📊 Data Models #

LLDNADeviceInfo #

Contains device information and authentication state:

class LLDNADeviceInfo {
  final String id;              // Unique device identifier
  final String name;            // Device name
  final String typeName;        // Device type name (e.g., "RM2 Pro")
  final int typeId;             // Device type ID (hex value)
  final String host;            // IP address
  final int port;               // Port number
  final String macAddress;      // MAC address
  final bool isLocked;          // Whether device is locked
  final DeviceCapabilities capabilities;
  final DateTime lastSeen;      // Last seen timestamp
  
  // Authentication fields (populated after authentication)
  Uint8List? aesKey;           // AES encryption key
  Uint8List? deviceId;         // Device ID for commands
}

DeviceCapabilities #

Describes what the device supports:

class DeviceCapabilities {
  final bool supportsIR;            // IR control
  final bool supportsRF;            // RF control
  final bool supportsPower;         // Power control
  final bool supportsNightlight;    // Nightlight control
  final bool supportsEnergyMonitoring;
  final bool supportsSensors;       // Temperature/humidity sensors
  final bool supportsTemperature;
  final bool supportsHumidity;
}

DeviceStatus #

Current device status information:

class DeviceStatus {
  final String deviceId;
  final bool isOnline;
  final bool isConnected;
  final int? firmwareVersion;
  final bool? powerState;
  final bool? nightlightState;
  final double? energyConsumption;
  final double? temperature;
  final double? humidity;
  final DateTime lastUpdate;
}

🎯 Events #

The SDK provides real-time events for device and discovery activities.

Device Events #

sdk.deviceEvents.listen((event) {
  if (event is DeviceConnectedEvent) {
    print('Device connected: ${event.deviceId}');
  } else if (event is DeviceStateChangedEvent) {
    print('Device state changed: ${event.changes}');
  } else if (event is CodeLearnedEvent) {
    print('IR code learned: ${event.code}');
  }
});

Discovery Events #

sdk.discoveryEvents.listen((event) {
  if (event is DiscoveryCompletedEvent) {
    print('Discovery completed: ${event.devices.length} devices found');
  } else if (event is DeviceDiscoveredEvent) {
    print('Device discovered: ${event.device.name}');
  }
});

🔧 Advanced Usage #

Save and Restore Devices #

// After discovery with auto-authentication
final devices = await sdk.discoverDevices(autoAuthenticate: true);

// Save authenticated devices
await saveDevicesToStorage(devices.map((d) => d.toJson()).toList());

// Later, restore devices
final savedData = await loadDevicesFromStorage();
final restoredDevices = savedData
    .map((json) => LLDNADeviceInfo.fromJson(json))
    .toList();

sdk.initializeDevices(restoredDevices);

// Use devices without re-authentication
for (final device in restoredDevices) {
  if (device.aesKey != null) {
    await sdk.setSPPower(device.id, true);
  }
}

Error Handling #

try {
  final devices = await sdk.discoverDevices();
} on BroadlinkDiscoveryException catch (e) {
  print('Discovery failed: $e');
} on BroadlinkNetworkException catch (e) {
  print('Network error: $e');
} catch (e) {
  print('Unexpected error: $e');
}

📱 Supported Devices #

RM Series (Remote Controllers) #

  • RM2 (0x2712): IR learning and sending
  • RM Mini (0x2737): IR learning and sending
  • RM Pro (0x273d): IR/RF learning and sending
  • RM4 Pro/Mini (0x51DA, 0x5209, etc.): IR/RF + temperature/humidity sensors

SP Series (Smart Plugs) #

  • SP2 (0x2711): Basic power control
  • SP3 (0x753e): Power control + nightlight
  • SP2S (0x7918): Power control + energy monitoring
  • SP4/SP4B: Advanced JSON-based control

🔒 Permissions #

Android #

Add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

iOS #

Add to ios/Runner/Info.plist:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to discover devices on your WiFi network.</string>

🐛 Troubleshooting #

Common Issues #

Device Discovery Fails:

  • Ensure devices and phone are on same WiFi network
  • Check router firewall settings
  • Try manual discovery with IP address

Authentication Issues:

  • If auto-authentication fails, the device may be locked by another app
  • Try power cycling the device
  • Use connectDevice() to manually authenticate

Devices Not Responding:

  • Verify device has valid aesKey and deviceId
  • Check device is online with hello()
  • Ensure correct device capabilities

Debug Logging #

All discovery operations include detailed logging with [LinkLinkSDK][DeviceDiscoveryService] prefix:

// Enable logging to see discovery details
[LinkLinkSDK][DeviceDiscoveryService] 开始设备发现
[LinkLinkSDK][DeviceDiscoveryService] 发现设备 - RM4 Pro (192.168.1.100:80)
[LinkLinkSDK][DeviceDiscoveryService] ✅ 设备配对成功: RM4 Pro

📄 License #

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments #

This SDK is based on the reverse-engineered Broadlink protocol and is compatible with the python-broadlink library.


Made with ❤️ for the Flutter and smart home communities.

0
likes
0
points
348
downloads

Publisher

unverified uploader

Weekly Downloads

LinknLink Device Flutter SDK for controlling LinknLink devices via UDP. Provides APIs for smart home app integration with auto-pairing and device management.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

convert, crypto, flutter, logger, network_info_plus, pointycastle

More

Packages that depend on ll_device_flutter_sdk