rtl_ir_control 1.0.6 copy "rtl_ir_control: ^1.0.6" to clipboard
rtl_ir_control: ^1.0.6 copied to clipboard

A utility designed to simplify the setup and configuration of Remotec products using Bluetooth Low Energy (BLE).

rtl_ir_control #

A Flutter package for setup and controlling infrared (IR) devices via Bluetooth. This package leverages esp_blufi and flutter_blue_plus to set up and manage Bluetooth Low Energy (BLE) connections and download ir code from api call to device.

Features #

  • Device scanning and connection management using BLE.
  • Blufi setup for BW8459 devices.
  • Downloading IR code for device control.

Dependencies #

This package relies on the following external packages:

  • esp_blufi: For BLE communication with ESP-based devices.
  • flutter_blue_plus: For Bluetooth Low Energy operations on Android and iOS.

Setup #

Permission #

To use this package, you must configure Bluetooth permissions for your Flutter app. Below are the steps for Android and iOS.

Android #

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

<!-- Tell Google Play Store that your app uses Bluetooth LE
     Set android:required="true" if bluetooth is necessary -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />

    <!-- New Bluetooth permissions in Android 12
    https://developer.android.com/about/versions/12/features/bluetooth-permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" /><uses-permission
android:name="android.permission.BLUETOOTH_CONNECT" /><uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!-- legacy for Android 11 or lower -->
<uses-permission android:maxSdkVersion="30"
android:name="android.permission.BLUETOOTH" /><uses-permission android:maxSdkVersion="30"
android:name="android.permission.BLUETOOTH_ADMIN" />

    <!-- legacy for Android 9 or lower -->
<uses-permission android:maxSdkVersion="28"
android:name="android.permission.ACCESS_COARSE_LOCATION" />

iOS #

  • In the ios/Runner/Info.plist let’s add:

<dict>
    <!-- Required for Bluetooth usage on iOS 13 and later; explains why the app needs Bluetooth access -->
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>This app requires Bluetooth to scan and connect to devices.</string>

    <!-- Legacy key for Bluetooth usage on iOS 12 and earlier; included for backward compatibility -->
    <key>NSBluetoothPeripheralUsageDescription</key>
    <string>This app requires Bluetooth to scan and connect to devices.</string>
</dict>
  • To use BLE in app background, add the following to your Info.plist

<dict>
    <key>UIBackgroundModes</key>
    <array>
        <string>bluetooth-central</string>
    </array>
</dict>

Note: Ensure that Bluetooth and location permissions have been granted for the app.

How to use #

1. Scan Devices #

Scan for BW8459 devices using a name prefix filter.

  • Both BLUETOOTH_SCAN and ACCESS_FINE_LOCATION permissions are required for Bluetooth scanning on Android.
import 'package:rtl_ir_control/rtl_ir_control.dart';

void scanDevices() {
  RtlIrControl().startScan(nameFilter: ['BW8459', 'BLUFI', 'RM2']).listen((
      List<RTLBluetoothScanRecord> scanResults,) {
    print('Discovered devices (${scanResults.length}):');
    for (var result in scanResults) {
      print('Device Name: ${result.device.name} ${result.device.advName}');
    }
  });
}

2. Setup Device #

Checks the device's configuration status, prepares it for Wi-Fi setup by using enterSetupMode() function

Future<void> verifyAndSetup(String id) async {
  try {
    // Initialize the device using the provided ID
    final device = RtlIrControl().getDevice(id);

    // Establish connection to the device
    await device.connect();

    // Create handler for device operations
    final handler = BW8459DeviceHandler(device);

    // OPTIONAL - check device is already configured
    bool isConfigured = await handler.isConfigured();

    //  enter setup mode programmatically
    await handler.enterSetupMode();

    // IMPORTANT: release connection for blufi setup
    await device.disconnect();

    await setupDevice(id);
  } catch (e) {
    print("Setup failed: $e");
  }
}

Connect to a device, scan for Wi-Fi networks, and configure Wi-Fi credentials.

Note: Ensure the device is in pairing mode before starting the setup process. Otherwise, it may appear disconnected or result in a connection timeout.

import 'package:rtl_ir_control/rtl_ir_control.dart';

Future<void> setupDevice(String id) async {
  final blufi = RTLBlufiSetupUtils();

  try {
    // Set device ID form scan
    await blufi.setCurrentId(id);

    // Establish connection
    await blufi.connect();

    // Scan for Wi-Fi networks
    var wifiList = await blufi.scanWifiList();

    // Select Wi-Fi (replace with your UI logic)
    var ssid = await selectWifi(wifiList);

    // Get password (replace with your UI logic)
    var password = await inputPassword(ssid);

    // Provision Wi-Fi credentials
    await blufi.configProvision(ssid: ssid, password: password);

    print("Setup Completed");
  } catch (e) {
    print("Setup failed: $e");
  }
}

// Placeholder UI functions
Future<String> selectWifi(List<String> wifiList) async {
  return wifiList.first; // Replace with actual selection logic
}

Future<String> inputPassword(String ssid) async {
  return "your_password"; // Replace with actual input logic
}

3. Read Device Information #

Read the device information to get IR data from the API.

import 'package:rtl_ir_control/rtl_ir_control.dart';

Future<void> readDeviceInfo(String id) async {
  try {
    // Initialize the device using the provided ID
    final device = RtlIrControl().getDevice(id);

    // Establish connection to the device
    await device.connect();

    // Create handler for device operations
    final handler = BW8459DeviceHandler(device);

    var masterKey = await handler.readMasterKey();

    var macAddress = await handler.readMacAddress();

    var firmwareVersion = await handler.readFirmwareVersion();

    var hardwareVersion = await handler.readHardwareVersion();

    var modelNumber = await handler.readRemoteModel();

    // display device information
    print('''
      Master Key: $masterKey
      MAC Address: $macAddress
      Firmware Version: $firmwareVersion
      Hardware Version: $hardwareVersion
      Model Number: $modelNumber
    ''');

    // Disconnect after the action is completed
    await device.disconnect();
  } catch (e) {
    print("Read device info failed: $e");
  } finally {
    // Ensure device is properly disconnected
    await device.disconnect();
  }
}

4. Decoding API Response to IR Codeset #

Convert the API response to an IR codeset for downloading.

void decodeIrCodeset(String jsonResponse) {
  try {
    // Decode codeset from API response
    RTLIrCodeset codeset = RTLIrCodeset.fromApiJson(jsonResponse);
    print("Successfully decoded IR codeset: ${codeset.toString()}");
  } catch (e) {
    print("Failed to decode IR codeset: $e");
  }
}

5. Download IR Codeset #

Download an IR codeset to a device.

import 'package:rtl_ir_control/rtl_ir_control.dart';

Future<void> downloadCodes(String id, RTLIrCodeset codeset) async {
  try {
    // Get device instance
    var device = RtlIrControl().getDevice(id);

    // Connect to device
    await device.connect();

    // Initialize handler
    final handler = BW8459DeviceHandler(device);

    // Download codeset with progress updates
    handler.downloadCodeFromCodeset(
      channel: 1,
      brandName: "LG",
      codeNum: "81",
      codeset: codeset,
    ).listen((progress) => print("Download progress: $progress%"),
      onDone: () {
        print("Download completed");
        device.disconnect();
      },
      onError: (e) {
        print("Download failed: $e");
        device.disconnect();
      },
    );
  } catch (e) {
    print("Code download failed: $e");
  }
}

6. Delete IR Codeset #

Delete IR codes with channel.

import 'package:rtl_ir_control/rtl_ir_control.dart';

Future<void> deleteCodes(String id, int channel) async {
  try {
    // Get device instance
    var device = RtlIrControl().getDevice(id);

    // Connect to device
    await device.connect();

    // Initialize handler
    final handler = BW8459DeviceHandler(device);

    // Delete IR Codeset with channel
    await handler.deleteCode(channel);

    // Disconnect after the action is completed
    await device.disconnect();
  } catch (e) {
    print("Delete code failed: $e");
  }
}

Custom Device Handler #

Extend the functionality of rtl_ir_control by creating a custom DeviceHandler tailored to your Bluetooth device.

import 'package:rtl_ir_control/rtl_ir_control.dart';

class CustomDeviceHandler extends GeneralDeviceHandler {
  // Custom UUIDs for your device's BLE service and characteristic
  static final RTLBluetoothUuid customServiceUuid =
  RTLBluetoothUuid('00001800-0000-1000-8000-00805f9b34fb'); // Generic Access service
  static final RTLBluetoothUuid customCharacteristicUuid =
  RTLBluetoothUuid('00002a00-0000-1000-8000-00805f9b34fb'); // Device Name characteristic

  // Constructor takes an RTLBluetoothDevice instance
  CustomDeviceHandler(super.rtlBluetoothDevice);

  // Read raw data from the device as a byte list
  Future<List<int>> readCustomData() async {
    final value = await rtlBluetoothDevice.readData(
      customServiceUuid,
      customCharacteristicUuid,
    );
    return value; // Returns raw bytes (e.g., for further processing)
  }

  // Send a custom command to the device
  Future<void> sendCustomCommand(List<int> data) async {
    await rtlBluetoothDevice.sendCommand(
      customServiceUuid,
      customCharacteristicUuid,
      data, // Byte list representing your command
    );
  }

  // Stream progress for a custom operation (e.g., firmware update)
  Stream<int> performCustomOperation(int param) async* {
    for (var i = 0; i <= 100; i += 20) {
      await Future.delayed(Duration(milliseconds: 500)); // Simulate async work
      yield i; // Emit progress percentage
    }
    // Replace with your device's specific operation logic
  }
}

Once you've created your CustomDeviceHandler, use the following example to call its methods:

// Usage
Future<void> useCustomHandler(String deviceId) async {
  try {
    // Retrieve and connect to the device
    var device = RtlIrControl().getDevice(deviceId);
    await device.connect();

    // Instantiate your custom handler
    var handler = CustomDeviceHandler(device);

    // Read data (raw bytes)
    List<int> data = await handler.readCustomData();
    print("Custom data (bytes): $data");

    // Send a sample command
    await handler.sendCustomCommand([0x01, 0x02, 0x03]);
    print("Command sent successfully");

    // Monitor a custom operation's progress
    handler.performCustomOperation(42).listen(
          (progress) => print("Operation progress: $progress%"),
      onDone: () => print("Operation completed"),
    );
  } catch (e) {
    print("Error in custom handler usage: $e");
  }
}

Notes #

  • Handle exceptions (e.g., RTLBluetoothException) for errors like timeouts or permission issues.

  • The package is tailored for BW8459 devices; adapt for other devices as needed.

  • Use a real API response for apiJson in production.

0
likes
140
points
54
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A utility designed to simplify the setup and configuration of Remotec products using Bluetooth Low Energy (BLE).

Homepage

License

MIT (license)

Dependencies

esp_blufi, flutter, flutter_blue_plus, plugin_platform_interface

More

Packages that depend on rtl_ir_control