updateFirmware method

  1. @override
Future<void> updateFirmware(
  1. BluetoothDevice device,
  2. int updateType,
  3. int firmwareType,
  4. BluetoothService service,
  5. BluetoothCharacteristic dataUUID,
  6. BluetoothCharacteristic controlUUID, {
  7. String? binFilePath,
  8. String? url,
})
override

sendPArt function ends here

Implementation

@override
Future<void> updateFirmware(
    BluetoothDevice device,
    int updateType,
    int firmwareType,
    BluetoothService service,
    BluetoothCharacteristic dataUUID,
    BluetoothCharacteristic controlUUID,
    {String? binFilePath,
    String? url}) async {
  if (updateType == 1) {
    final bleRepo = BleRepository();

    /// Get MTU size from the device
    int mtuSize = 200;

    print("MTU size of current device $mtuSize");

    /// Prepare a byte list to write MTU size to controlCharacteristic
    Uint8List byteList = Uint8List(2);
    byteList[0] = mtuSize & 0xFF;
    byteList[1] = (mtuSize >> 8) & 0xFF;

    List<Uint8List> binaryChunks;

    /// Choose firmware source based on firmwareType
    if (firmwareType == 1 && binFilePath != null && binFilePath.isNotEmpty) {
      binaryChunks = await _readBinaryFile(binFilePath, mtuSize);
    } else if (firmwareType == 2) {
      binaryChunks = await _getFirmwareFromPicker(mtuSize);
    } else if (firmwareType == 3 && url != null && url.isNotEmpty) {
      binaryChunks = await _getFirmwareFromUrl(url, mtuSize);
    } else {
      binaryChunks = [];
    }

    /// Write x01 to the controlCharacteristic and check if it returns value of 0x02
    await bleRepo.writeDataCharacteristic(writeCharacteristic, byteList);
    await bleRepo.writeDataCharacteristic(
        notifyCharacteristic, Uint8List.fromList([1]));

    /// Read value from controlCharacteristic
    List<int> value = await bleRepo
        .readCharacteristic(notifyCharacteristic)
        .timeout(Duration(seconds: 10));
    print('value returned is this ------- ${value[0]}');

    int packageNumber = 0;
    print('Before Progress');
    for (Uint8List chunk in binaryChunks) {
      /// Write firmware chunks to dataCharacteristic
      await bleRepo.writeDataCharacteristic(writeCharacteristic, chunk);
      packageNumber++;

      double progress = (packageNumber / binaryChunks.length) * 100;
      int roundedProgress = progress.round(); // Rounded off progress value
      print(
          'Writing package number $packageNumber of ${binaryChunks.length} to ESP32');
      print('Progress: $roundedProgress%');
      _percentageController.add(roundedProgress);
    }

    /// Write x04 to the controlCharacteristic to finish the update process
    await bleRepo.writeDataCharacteristic(
        notifyCharacteristic, Uint8List.fromList([4]));

    /// Check if controlCharacteristic reads 0x05, indicating OTA update finished
    value = await bleRepo
        .readCharacteristic(notifyCharacteristic)
        .timeout(Duration(seconds: 600));
    print('value returned is this ------- ${value[0]}');

    if (value[0] == 5) {
      print('OTA update finished');
      firmwareUpdate = true; // Firmware update was successful
    } else {
      print('OTA update failed');
      firmwareUpdate = false; // Firmware update failed
    }
  } else if (updateType == 2) {
    final bleRepo = BleRepository();

    /// Get MTU size from the device
    int mtuSize = await device.mtu.first;

    print("MTU size of current device $mtuSize");

    /// Prepare a byte list to write MTU size to controlCharacteristic
    Uint8List byteList = Uint8List(2);
    byteList[0] = 200 & 0xFF;
    byteList[1] = (200 >> 8) & 0xFF;

    List<Uint8List> binaryChunks;
    Uint8List? binFile;

    /// Choose firmware source based on firmwareType
    if (firmwareType == 1 && binFilePath != null) {
      ByteData fileData = await rootBundle.load(binFilePath);
      List<int> bytes = fileData.buffer.asUint8List();
      binFile = Uint8List.fromList(bytes);
      print("Bin file after conversion is $binFile");
      print("Bin file length after conversion is ${binFile.length}");
    } else if (firmwareType == 2) {
      binFile = await _getFirmwareFromPickerArduino(200);
      print("binFile is $binFile");
    } else if (firmwareType == 3 && url != null && url.isNotEmpty) {
      binaryChunks = await _getFirmwareFromUrl(url, mtuSize);
    } else {
      binaryChunks = [];
    }
    print('before printing file Length');
    int fileLen = binFile!.length;
    int fileParts = (fileLen / part).ceil();
    print("this is the fileParts :  $fileParts");

    ///1. Start stream which listens to the notification advertisement
    await notifyCharacteristic.setNotifyValue(true);
    subscription = notifyCharacteristic.onValueReceived.listen((value) async {
      print("received value is $value");
      double progress = (value[2] / fileParts) * 100;
      int roundedProgress = progress.round();

      /// Rounded off progress value
      print('Writing part number ${value[2]} of $fileParts to ESP32');
      print('Progress: $roundedProgress%');
      _percentageController.add(roundedProgress);
      if (value[0] == 0xF1)

      /// this basically is checking listener stream
      {
        Uint8List bytes = Uint8List.fromList([
          value[1],
          value[2],
        ]);
        ByteData byteData = ByteData.sublistView(bytes);
        int nxt = byteData.getUint16(0);

        /// Used getUint16 for a 2-byte integer
        print("--------- nxt -------- $nxt");
        sendPart(nxt, binFile!);
      }
      if (value[0] == 0x0F) {
        print("OTA Update complete");
      }
      if (value[0] == 0xF2) {
        print("New bin file installation begins on esp32");
      }
    });

    ///2. Send 0xFD first to start reading
    Uint8List byteListData = Uint8List(1);
    byteList[0] = 0xFD;
    await bleRepo.writeDataCharacteristic(writeCharacteristic, byteListData);

    ///3. Send 0xFE appended with other info
    ///--------> 2nd step create and then send file size
    Uint8List fileSize = Uint8List(5);
    fileSize[0] = 0xFE; // The fixed byte
    fileSize[1] = (fileLen >> 24) & 0xFF; // Most significant byte of fileLen
    fileSize[2] = (fileLen >> 16) & 0xFF; // Second most significant byte
    fileSize[3] = (fileLen >> 8) & 0xFF; // Third most significant byte
    fileSize[4] = fileLen & 0xFF; // Least significant byte
    print(
        "this is file size : $fileSize"); // this is where it is sent to esp32
    await bleRepo.writeDataCharacteristic(writeCharacteristic, fileSize);

    ///4. Send 0xFF appended with other info - see code below
    ///--------> 3rd step create and then send otaInfo
    Uint8List otaInfo = Uint8List(5);
    otaInfo[0] = 0xFF;
    otaInfo[1] = (fileParts ~/ 256);
    otaInfo[2] = (fileParts % 256);
    otaInfo[3] = (mtu ~/ 256);
    otaInfo[4] = (mtu % 256);
    print("this is otaInfo : $otaInfo"); // this is where it is sent to esp32
    await bleRepo.writeDataCharacteristic(writeCharacteristic, otaInfo);

    ///5. Divide bin file into parts
    int packageNumber = 0;
    sendPart(0, binFile);
    double progress = (packageNumber / fileParts) * 100;
    int roundedProgress = progress.round(); // Rounded off progress value
    print('Writing part number $packageNumber of $fileParts to ESP32');
    print('Progress: $roundedProgress%');
    _percentageController.add(roundedProgress);
  }
}